[sdiy] Wavetable Design Update
Tom Wiltshire
tom at electricdruid.net
Wed Feb 2 11:20:46 CET 2011
On 2 Feb 2011, at 06:28, Matthew Smith wrote:
> * How to convert from my note numbers (these will be all the MIDI-defined notes plus intermediate detune values) to the prescaler/counter values to plug into AVR's onboard counter. I would appear to have two options: a lookup table (would not fit in ATTINY2313 FLASH) or to calculate these at note-on. I'm favouring the second approach for flexibility (would even allow an actual frequency to be specified rather than a note number) but haven't the foggiest how to work out the algorithm required.
I've battled with this one, and tried two approaches.
Attempt One:
As Dave Manley described. There's a exponential 'Pitch' number based on MIDI notes. I used a 16-bit variable where the top 7 bits were the MIDI note and the bottom 9 bits gave the between-notes position -eg 512 steps per semitone.
This then has to be converted to a linear frequency increment, in my case 32-bit.
I found two different ways to do this conversion. One was to use a large lookup table. I had 512x32-bit entries, or an entry every 1/4 of a semitone, and then do linear interp between those points. The second way is to work out the note and octave first, which involves dividing the note number by 12 to get the octave and using the modulus as the note. Now, I hate division since it's about the most expensive operation there is. But once you've got the two parts, you can look up the note in a table that only covers one octave, and then use shifts to move it for other octaves. If you store the increments for the top octave (the biggest increments) then you can use downshifts and not lose any accuracy. If you store the bottom octave and upshift instead, you start shifting zeros into the low bits when you get up to the top octaves and lose accuracy.
Attempt two:
I gave up on the MIDI note numbers. Instead I had a 16-bit Pitch variable based on octaves. It covered an 8 octave range (although 16 would be easy to) with the top 3 bits indicating octave and the bottom 13bits indicating position within the octave. This gives 682 and 2/3rds values per semitone, slightly better than method one. This is because the range has been reduced from MIDI's 10 octaves to 8. I used another simple lookup table to convert between incoming MIDI note numbers and the Pitch variable. Modulations are then applied to the pitch variable, which is then converted to a frequency increment using a one octave table and shifted as described above.
Obviously now no division has to be done now, since we have the octave and sub-octave position by simply masking the required bits. The only downside of this method is that MIDI notes do not fall *exactly* on the available pitch values. However, since the steps are so small (1/682th of a semitone) this is so far beyond being perceptible that you'll never know.
So, there you go. My history with Note Numbers and Frequency Increments. Ack!
Tom
More information about the Synth-diy
mailing list