Please explain pitchRatio derived in SamplerVoiceExpert::startNote()

pitchRatio = pow (2.0, (midiNoteNumber - sound->midiRootNote) / 12.0) * sound->sourceSampleRate / getSampleRate();

I don’t understand the maths there, why is pow() used?

whilst searching the forum I found this which I do understand. Is the equation above a simplfied version maybe?

pitchRatio = (targetFreq * sound->sourceSampleRate) / (naturalFreq * getSampleRate());

The pow() calculation is used to transform the MIDI notes in equally tempered semitones to a playback speed ratio.

I understand this is the result, but what’s the science behind it? Why would deriving two to the power of ‘semi tone difference over semi tones in octave’ result in the desired pitch step for the render function?

When I feed values into a calculator I see it works out

e.g. root midi c2, current midi b1
2^(-1/12) = 0.94387431268
e.g. root midi c2, current midi c#2
2^(1/12) = 1.05946309436

This produces scalar, much like targetSamplerate/sourceSampleRate will produce a scalar. I just can’t visualise why it works.

I suppose 2^1 is two, that’s the same as root midi c2 target c3, and 2^0 is 1, that’s the same as root midi c2 and target c2 also. So I suppose it works out simply as a y= 2^x produces desired values.

The pitch is not a linear function but an exponential one. To get from one tone to it’s octave, you double the frequency. Not adding - multiplying.
That’s what pow() does.

yes, but that one works only for octaves.

To split that into 12 equal multiplications, that you can execute in series for instance, you divide the exponent by the number of steps (semitones).

pow (2, 1/12) * pow (2, 1/12) * pow (2, 1/12) * pow (2, 1/12) 
* pow (2, 1/12) * pow (2, 1/12) * pow (2, 1/12) * pow (2, 1/12) 
* pow (2, 1/12) * pow (2, 1/12) * pow (2, 1/12) * pow (2, 1/12) = 2

Or simpler: two numbers with the same base are multiplied by adding the exponent.
pow (2, 1/12) * pow (2, 1/12) = pow (2/12)
Do this 12 times, you end up with pow (2, 12/12) = 2

1 Like

a cool thing you can do with this formular, which also improves your understanding about it, is to exchange the “12.0” with an integer (non-integer are fine too but then there are no octaves) variable. call it xen. now you can convert midi notes to xenharmonic scales easily in your synth (or what it is that takes midi notes), because the 12 stands for amount of notes per octave

Thanks, I understand now. Very handy thing to have in the engine, I would never have worked that out.