Login / Register  0 items | $0.00 New#KVRDeals

pitch to frequency conversion

mystran
KVRAF
 
4611 posts since 11 Feb, 2006, from Helsinki, Finland

Postby mystran; Sat Dec 16, 2006 9:06 am pitch to frequency conversion

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

Postby Borogove; Sat Dec 16, 2006 10:08 am

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.
Image
Don't do it my way.
mistertoast
KVRAF
 
3415 posts since 15 Sep, 2002

Postby mistertoast; Sat Dec 16, 2006 10:43 am

>>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

Postby arwa02; Sat Dec 16, 2006 10:45 am

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
 
4611 posts since 11 Feb, 2006, from Helsinki, Finland

Postby mystran; Sat Dec 16, 2006 11:07 am

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
 
3721 posts since 8 Mar, 2004, from Berlin, Germany

Postby Music Engineer; Sat Dec 16, 2006 11:48 am

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.
Image
mystran
KVRAF
 
4611 posts since 11 Feb, 2006, from Helsinki, Finland

Postby mystran; Sat Dec 16, 2006 12:09 pm

Exponential modulations are nice for some purposes. :)
Image <- plugins | forum
Music Engineer
KVRAF
 
3721 posts since 8 Mar, 2004, from Berlin, Germany

Postby Music Engineer; Sat Dec 16, 2006 12:23 pm

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.
Image
Borogove
KVRAF
 
2456 posts since 3 Oct, 2002, from SF CA USA NA Earth

Postby Borogove; Sat Dec 16, 2006 12:29 pm

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...
Image
Don't do it my way.
Borogove
KVRAF
 
2456 posts since 3 Oct, 2002, from SF CA USA NA Earth

Postby Borogove; Sat Dec 16, 2006 12:33 pm

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.
Image
Don't do it my way.

Moderator: Moderators (Main)

Return to DSP and Plug-in Development