pitch to frequency conversion

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

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

Post

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.

Post

>>I prefer to use powf() directly, at control rate, and linearly interpolate in between.

What is the ratio between your control rate and audiorate?

Post

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 = 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 10:16 am, edited 1 time in total.
/arwa02

Post

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.

Post

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.
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

Exponential modulations are nice for some purposes. :)

Post

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.
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

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.

Post

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.

Post Reply

Return to “DSP and Plugin Development”