[sdiy] lookup table oscillators
Gordon JC Pearce
gordonjcp at gjcp.net
Fri Apr 1 09:01:08 CEST 2011
On Fri, 2011-04-01 at 01:59 -0400, dan snazelle wrote:
> i tried reading the Hal Chamberlin writeup tonight but it confused me
> quickly as it was technical in a way that honestly did not make a lot
> of sense to me partially because he did not show any code for how to
> do it.
> i am not so great at math and there was a lot of math stuff I did not
> quite understand.
>
> I really do want to understand though as i would like to experiment
> with these on the arduino
https://github.com/gordonjcp/gyoza
http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/
It's called a "phase accumulator". Imagine you've got a table of 256
values that holds a sinewave. Every time you're ready for a new sample,
you read a value from the table and increase the pointer by one. Now
with a 32kHz sample rate that would give you a 32000/256 = 125Hz
sinewave. Now the most obvious way of changing that pitch would be to
change the sample rate, but it's hard to do that for more than one
oscillator (well, it's not, but you need multiple timers, DACs etc).
The other way is to not just increment the counter by one every time you
call for another sample. If you increment by two you'll get a 250Hz
tone, three will give you 375Hz, and so on. Okay, so what about the
frequencies in between? Well, just add a non-integer value to the
pointer! If you add (say) 1.3 to the sample pointer, then truncate so
you only use the integer part as the index into the wavetable then you
go like this: 0, 1.3, 2.6, 3.9, 5.2, 6.5, 7.8, 9.1 and so on - and
notice that we skipped sample 4 and 8 entirely? This would give us a
162.5Hz sine wave.
Now for speed's sake on a platform like the AVR, you wouldn't do the
phase accumulator using floats - you'd use a 32-bit int and then just
take the top eight bits as the wavetable index. Early on in your
program you compute a bunch of constants that map note frequency and
sample rate to the phase accumulator offset, so you don't need to do a
slow floating-point routine in the interrupt handler.
HTH
Gordon MM0YEQ
More information about the Synth-diy
mailing list