mitxela.com forum
Welcome. Please log in or register.

Implementing pitch bending
DAVID Posted: 3 Aug 2020, 05:12 AM
Avatar
I love mcus

Member
Posts: 237
Joined: 10-September 17
I'm currently trying to make a new usb midi synth with the stm32 (bluepill) and so far it's been going pretty nicely until I began implementing pitch bend capabilities.
The way that I´m doing it is by the use of the pow function.


uint8_t Pitch_Range = 2; // value can be changed with MIDI CC commands
//The result of this functions will be used to multiply the base freq of
//a voice
float pitch_to_factor(uint8_t pitch) {
int pitch_value = (pitch - 64) * Pitch_Range;
return powf(2, pitch_value/ 768.0);
}


As you migth expect it works but it is way too intense for the CPU.
As far as I understand from your Flash Synth post I need to have a lookup table of the pitch bend factors from -1 to +1 semitone but then how do I scale those values for other semitone ranges?

-------------
[top]
mit Posted: 3 Aug 2020, 02:09 PM
Avatar
yeah whatever

Admin
Posts: 564
Joined: 4-May 16
There's a few ways you can go about this.

If you have a pitch bend lookup table for one semitone, you can just multiply it several times to get a bigger bend range.

So if the pitch wheel was at +100%, the table would say the bend factor is 2**(1/12) = 1.0594630943592953. If the bend range is 4, you would multiply the frequency by 1.059... four times.

However for big bend ranges that way is slow and prone to floating point errors, especially if the values are float32 instead of double floats.

The way I do it on the Flash Synth is to use two lookup tables. One has 128 values, and tells me the base frequency of the midi note, using equal temperament. The other table is the +/- one semitone table. To work out the frequency, I split the bend amount into two parts, the whole number of semitones, and the fraction. I then add the whole number onto the midi note number, then use the other table to adjust by the fraction amount. This gives 14-bit resolution bends with any bend range, and just two lookup tables.

One problem is that the Flash Synth supports alternate tunings, so this way won't work if the distance between midi notes is not constant. For the tuning table modes, I just forced the bend range to a fixed amount, because I'm not sure it even makes sense otherwise.

I will upload the code for the flash synth soon, I promise...

-------------
[top]
DAVID Posted: 3 Aug 2020, 09:13 PM
Avatar
I love mcus

Member
Posts: 237
Joined: 10-September 17
Thanks Mit, it now works flawlessly and I have also increased the pitch bend res from 7 bits to 11 and the difference between those when having a really big pitchbend range (96 in my case) it´s humongous.


uint16_t pitch_to_value(uint16_t pitch,uint8_t notenum) {
pitch >>=3;
int pitch_value = (pitch - 1024) * Pitch_Range;
int whole = pitch_value / 1024;
float fraction = pitch_value / 1024.0 - whole;
return miditofreq[notenum+whole]*pitchbend[(int)(fraction*1023+1024)];
}


Last edit by DAVID at 3 Aug 2020, 09:13 PM

-------------
[top]

Sign in to post a reply.