pitch to frequency conversion

mystran
KVRAF

4927 posts since 11 Feb, 2006, from Helsinki, Finland
Ok, now that I've posted a few comments, I think I feel confident enough to start a topic that concerns fast ways to do pow(2.,x) for purposes of pitch to frequency and related conversions.

I've tried a lot of suggested functions here and elsewhere for the purpose, and it seems most of them are either

1. wildly inaccurate or only accurate near zero
2. not much faster (or even slower) than gcc's stock pow().

So I've used the trivial solution for now, namely converting pitch from float to a (say) 16-bit fixed point, then using the identity

a^(x+y) = a^x * a^y

to do separate table lookups for low and high bytes and multiply together (so 2 tables of 256 floats each, 2kB total). It needs one pre-multiply, float-to-int, two lookups, another float multiply, and some trivial integer bitsuffling.

Ofcourse with larger tables one gets more accuracy without extra operations, with more tables one needs less memory but with some extra operations.

Even if it isn't complicated at all, this took me a minute or two to figure out, so I'm just wondering why I haven't seen it mentioned anywhere? Did I just miss? Is it just considered too trivial? Or is there's some critical flaw?

I mean it seems to perform much better than most methods suggested, accuracy is more or less uniform on logarithmic scale, and the memory requirements aren't huge (YMMV).
Borogove
KVRAF

2456 posts since 3 Oct, 2002, from SF CA USA NA Earth
I prefer to use powf() directly, at control rate, and linearly interpolate in between.

Yours is a good trick, though. I recently saw a page on fast sin/cos that suggested something analogous, using the identity sincos(x+y)=sincos(x)*sincos(y) where sincos is a complex number. You pick sincos(x) from a table so as to leave y as small as possible, near zero where sin is nearly linear.

Don't do it my way.
mistertoast
KVRAF

3415 posts since 15 Sep, 2002
>>I prefer to use powf() directly, at control rate, and linearly interpolate in between.

What is the ratio between your control rate and audiorate?
arwa02
KVRist

42 posts since 1 Jun, 2006
There was a thread about this recently where I suggested this approach. You make one table with precalculated semitone frequencies, and you make another table with 100 elements of precalculated cents (cent_table[i] = pow(2, i/1200)). Then calculate cent precision frequency of any pitch with

Code: Select all
`freq = semitone_table[semitone_pitch]*cent_table[cents];`

So a pitch of 76.45 would give you

Code: Select all
`freq = semitone_table[76]*cent_table[45];`

You need two tables of 128/100 floats to do this. If you want better precision, just divide each semitone into something else than cents and make the second table larger. To get a precision of one tenth of a cent, just make the second table a 1000 position table and fill it with pow(2, i/(12*(1000))). You can get any precision you want simply by increasing/decreasing the size of the second table this way, but cent precision is probably accurate enough for most applications.
Last edited by arwa02 on Sun Dec 17, 2006 2:16 am, edited 1 time in total.
/arwa02
mystran
KVRAF

4927 posts since 11 Feb, 2006, from Helsinki, Finland
Yeah ok arwa. Must have missed the thread.

I actually thought of the semitone and cent tables as well, but decided against it. IMHO it buys nothing, and if modulations are summed as floats (or fixed points, doesn't matter really), having the table sizes be powers of two means getting the indexes is just shift and bitwise-and. For non-powers like 100 one needs an integer divide and remainder, which I admit might not be a huge loss.
Music Engineer
KVRAF

3759 posts since 8 Mar, 2004, from Berlin, Germany
i use that macro:
Code: Select all
`//conversion from a MIDI-Note Number to a frequency in Hz:#define PITCH2FREQ(pitch) (440*( pow(2, ((((double)pitch)-69)/12))))`

all the time. and why not? or is you frequency-calculation supposed to be called at audio-rate? i need that calculation typically only when a new note comes in.
mystran
KVRAF

4927 posts since 11 Feb, 2006, from Helsinki, Finland
Exponential modulations are nice for some purposes.
<- plugins | forum
Music Engineer
KVRAF

3759 posts since 8 Mar, 2004, from Berlin, Germany
mystran wrote:Exponential modulations are nice for some purposes.

that's right. in particular, when the modulator is an envelope. but in this case, there is RC-solution (as currently discussed once more in another thread). and when the modulator is some LFO - mmmhh...couldn't we just multiply the (raised) LFO's output with the average frequency like:

freq = averageFreq * (1.0 + depth*lfoOut);

something like that? i think, i do this in my flanger in the exponential LFO-mode - but i'm not quite sure a the moment.
Borogove
KVRAF

2456 posts since 3 Oct, 2002, from SF CA USA NA Earth
braindoc wrote:i use that macro:
Code: Select all
`//conversion from a MIDI-Note Number to a frequency in Hz:#define PITCH2FREQ(pitch) (440*( pow(2, ((((double)pitch)-69)/12))))`

all the time. and why not? or is you frequency-calculation supposed to be called at audio-rate? i need that calculation typically only when a new note comes in.

Pitch bend, pitch envelope, LFO...

Don't do it my way.
Borogove
KVRAF

2456 posts since 3 Oct, 2002, from SF CA USA NA Earth
mistertoast wrote:>>I prefer to use powf() directly, at control rate, and linearly interpolate in between.

What is the ratio between your control rate and audiorate?

32 or 64.

Don't do it my way.

Moderator: Moderators (Main)