Note-to-frequency algorithms

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

hello there, i have a fairly simple math question i guess, about note-to-frequency algorithms. I've done note-to-sample region algorithms several times in different environments and although i can recognize a note-to-frequency algorithm(prolly just good code documentation :lol:), I'm still not qute sure how it works.

I'm playing around with STK and have noticed this bit of code

Code: Select all

register StkFloat value1 = data->message.floatValues[0];
  register StkFloat value2 = data->message.floatValues[1];

....
StkFloat frequency = 220.0 * pow( 2.0, (value1 - 57.0) / 12.0 ); 
      data->instrument->noteOn( frequency, value2 * ONE_OVER_128 );
forgive me if i didn't post enough info about the code for a clear understanding of it. but the 3rd line of code is where my interest lies atm.
i'm guessing that 57.0 represents the note numbers? if that's the case, i would usualy test (value1 - 60.0), and if i remember correctly, i'd end up changing that value to 59.0 sinc note number 60 is middle C?

i hope this is making sense. just wondering if anyone recognizes and has an explaination for this?

thanks for your help :)

Post

57 is the note corresponding to 220hz. Basically, what you do is this:

basefreq * ( 2 ^ offset_in_octaves_from_basenote )

so, you could change their line to this:
StkFloat frequency = 440.0 * pow( 2.0, (value1 - 69.0) / 12.0 );

And get the same result

If you want to use middle C as the base note, you'll get a much "uglier" base frequency (not a integer number).

Post

stefancrs wrote:57 is the note corresponding to 220hz. Basically, what you do is this:

basefreq * ( 2 ^ offset_in_octaves_from_basenote )

so, you could change their line to this:
StkFloat frequency = 440.0 * pow( 2.0, (value1 - 69.0) / 12.0 );

And get the same result

If you want to use middle C as the base note, you'll get a much "uglier" base frequency (not a integer number).
good point. i always used middle C as the base note for my samplers. since i only used about 16 keys at the most for it.

thanks :)

Post

laserbeak wrote:
stefancrs wrote:57 is the note corresponding to 220hz. Basically, what you do is this:

basefreq * ( 2 ^ offset_in_octaves_from_basenote )

so, you could change their line to this:
StkFloat frequency = 440.0 * pow( 2.0, (value1 - 69.0) / 12.0 );

And get the same result

If you want to use middle C as the base note, you'll get a much "uglier" base frequency (not a integer number).
good point. i always used middle C as the base note for my samplers. since i only used about 16 keys at the most for it.

thanks :)
...and don't forget to learn from other's mistakes...(re readability)

const float middle_A_freq = 440.0;
const float middle_A_note_number = 69.0;
const float notes_per_octave = 12.0;

StkFloat frequency = middle_A_freq * pow( 2.0, (value1 - middle_A_note_number ) / notes_per_octave );

Self-documenting code is more readable for others (and yourself)

Jeff

Post

hey jeff! :)
thanks! that's the cleanest documentation i've seen in probably months! :lol:

Post

Jeff McClintock wrote: StkFloat frequency = middle_A_freq * pow( 2.0, (value1 - middle_A_note_number ) / notes_per_octave );
SYNTAX ERROR: Maximum number of characters per line (80) exceed.

edit:

Really, narrow lines are a lot easier to read to me. :)

Post

mystran wrote:
Jeff McClintock wrote: StkFloat frequency = middle_A_freq * pow( 2.0, (value1 - middle_A_note_number ) / notes_per_octave );
SYNTAX ERROR: Maximum number of characters per line (80) exceed.

edit:

Really, narrow lines are a lot easier to read to me. :)
never seen that error before!! :?:

Post

laserbeak wrote: never seen that error before!! :?:
You were born in the 90s, weren't you? You never understood what the "text-mode" on computers really is, and why they boot with such an ugly font (when not hidden by the mobos even uglier graphics logo), right?

Ok, obviously I'm joking, but there at least used to be a huge army of programmers that think a line is too long if it doesn't fit in 80 columns, and a function is too long if it doesn't fit on 80x24 VT100 screen.

Post

mystran wrote:
laserbeak wrote: never seen that error before!! :?:
You were born in the 90s, weren't you? You never understood what the "text-mode" on computers really is, and why they boot with such an ugly font (when not hidden by the mobos even uglier graphics logo), right?
i almost got offeneded :lol:
Ok, obviously I'm joking, but there at least used to be a huge army of programmers that think a line is too long if it doesn't fit in 80 columns, and a function is too long if it doesn't fit on 80x24 VT100 screen.
hmm, ok i can live with that...

Post

mystran wrote: Ok, obviously I'm joking, but there at least used to be a huge army of programmers that think a line is too long if it doesn't fit in 80 columns, and a function is too long if it doesn't fit on 80x24 VT100 screen.
I still try to follow the 80 column rule of thumb whenever I can. Two things make it more difficult now than in times past. First, with a language like C#, the class implementation is nested inside the class declaration which is nested inside the namespace declaration. Each level of nesting carries with it (usually) four spaces of indention. By the time you've gotten to the meat of the code, you've already eaten up a good number of those 80 columns (this doesn't apply to C or C++).

The other thing that works against the 80 column practise is the trend towards using descriptive variable names (see Jeff's post :-)). The more descriptive the name, the more verbose it gets, and the more columns you eat up. Descriptive names are nice because it clues you in to what they represent more so than cryptic, abreviated names. On the other hand, fitting a line of code within 80 columns makes it easier to take in what the code is doing at a glance; there's a tension between these two practises. So as with just about everything else, you have to reach a compromise in which the code is descriptive enough to make it understandable without running on for 100s of columns.

Post

good point. i definately don't like to scroll left to right when i'm looking at code or comments

Post

The cure for most horizontal scrolling issues, are dual 24" monitors.

Am not particularly a spendthrift, but the dual 24" monitors have been a more rewarding investment than most, though it felt borderline-decadent when spending that money.

They have been so rewarding, would almost be tempted to consider dual 30" monitors a reasonable purchase. No longer insane decadence.

If code lines get too wide on big wide monitors, then agreed, the line is probably too long (grin).

Post

they're getting a lot cheaper :) i'd love to get a nice big one to have a vst and a mixer's full area on the screen at the same time :)

Post

JCJR wrote:The cure for most horizontal scrolling issues, are dual 24" monitors.
Yeah, well, honestly I don't usually care that much nowadays whether I fit in 80 characters (except for some types of system code, which I might end up actually viewing on a terminal screen) but really wide lines are annoying when you just have to fix something yesterday, and all you have is a laptop with some 1280 pixels (or less) in a row, and you don't even want to spend all of that by maximizing your editor, 'cos then you'd have to mess with the task-bar or alt-tab bouncing between 69 different open windows.

Or worse, maybe you just absolutely have to fix a critical bug from the bus with your PDAs PocketPuTTY.

That said, I'm just writing some code for work, and I just wrote several lines around 120 characters... and I'm not going to split em. :)

Oh and finally, I'd take word-wrap anyday before horizontal scrolling. If you keep line numbers visible, it's quite easy to see where there's wrapper lines, so it's not that bad.

As for descriptive names, IMHO the best variable names are as short as possible, while still staying informative. That is, I prefer to balance name length against descriptiveness. Short names are less reading, so while the number of syntax tokens stays the same, it's somewhat faster to read, and you need to type less characters so there's less chance of typos as well. On the other hand, using nothing but single character variables is obviously not that helpful, and in that case a typo could cause more trouble than a parse error (which is a quick fix) so it's a tradeoff.

If I wrote the above mentioned code, I'd probably make it look something like:

Code: Select all

static const float base_freq = 440.0; // middle A frequency
static const float base_note = 69.0;  // middle A MIDI note number

StkFloat note_freq = base_freq*pow(2.0, (note-base_note)/12.0);
IMHO the "notes per octave" isn't worth documenting, if we assume the exponent base of 2.0 is not either. Not naming the constants for middle A (which is arbitrary) is a win, if we later decide to change the base note, because then there's no need to go through the code renaming all the references.

Oh, and static const floats so that compiler isn't required to put a symbol into the object files just in case some other module happens to refer to them, so they behave like true constants.

But like said, I ain't entirely serious here. :P

Post

well i don't think that jeff writes his code like that, but it really does help with an explaination. :)

oh and dont tell me about laptops, :/ i'm stuck on one for a while now....
at least i have the option to change my working environment with a bit of ease if i wanted to though... and i have 17 monitor set up in each of the places i'd be most likely to move to. :)

Post Reply

Return to “DSP and Plugin Development”