[sdiy] Coding digital waveforms
Tom Wiltshire
tom at electricdruid.net
Thu Dec 17 16:40:40 CET 2009
Justin,
> At the moment I'm just using a counter to increment through an
> array of values that output to a DAC. It's a fixed frequency at the
> moment - but the plan is to set up a variable to tell it how 'fast'
> to run through the array - or how many of the values to use. It's
> basic and there's loads of room for improvement - but so far it works.
>
> So firstly - considering that my code game is pretty basic - is
> there a better way of handling it than this?
Not really. What you've got is the standard method. You can improve
the frequency resolution and accuracy by adding extra bits to the low
end of the counter. So for example if you have 256 entries in your
waveform table, you use a 16-bit counter, and then only use the top 8
bits as the index into the table. This effectively gives you sub-
sample accuracy. If you do use interpolation, you can use the lower 8-
bits as the interpolation index.
In terms of how much accuracy is required, I used a 24-bit counter
and a 16-bit frequency increment in my own LFO. I've seen other
designs that get away with a 16-bit counter - it depends a bit on the
output sample rate. By the time you're up to 32-bit counters, you've
got incredible frequency resolution, and this is probably far beyond
what you need for an LFO.
> and secondly - to smooth the output (which is obviously 'stepped'
> right now) - should I be looking at some type of 'lag' circuit
> (i.e. the resistor/diode/cap combo) - or something else?
The two options are interpolation on the digital side and filtering
on the analogue side. Or some mixture of both, I guess.
Jerry mentioned execution times and latency, which he's right to
point out. The typical way to alleviate these problems is to work on
the *next* sample, not the current one. If you've got a timer
interrupt or something similar that is setting the output sample
rate, the plan looks like this:
1) Start the interrupt
2) Get the stored sample value from memory (in some variable called
SAMPLE_OUT or whatever).
3) Send it to the DAC
4) Start calculating the next sample
5) Finish calculating the next sample and store it in SAMPLE_OUT.
6) Finish the interrupt
This way, step 4 can vary in length widely and there won't be any
jitter in the sample output, since steps 1,2, & 3 will always take
the same amount of time.
HTH,
Tom
More information about the Synth-diy
mailing list