[sdiy] Wavetables
Paul Maddox
paul.Maddox.mail-list at Synth.net
Sat Jan 22 10:24:39 CET 2011
Matt,
> In furtherance of my understanding of digital systems, I have decided to
> construct a wavetable-based waveform generator.
good stuff !
> I'm still going to cheat by using an 8-bit DAC rather than building that
> side by hand, but the general scheme is a series of flipflops providing
> address stepping from an incoming square wave selecting locations from an
> EPROM or E2PROM (probably use the latter as easier to erase) hard-wired to
> permanent read, data lines feeding the DAC.
all you really need as a counter, in your case 8 bits.
Driving it, you need a phase accumulator type software.
> I'm going to do the square wave source as a separate module to make this
> more versatile - this I *will* be doing with a microcontroller, probably an
> ATTINY2313, since I have a few kicking around and I'm familiar with them.
ok, though you could it using two AT2313's and a single DAC in very few parts.
> MIDI comes in to the UART, note on starts a timer set up as a square wave
> generator running at n.f where f is the not frequency from a lookup table
> and n is the number of samples that make up a cycle in the prom data.
ok, so here's where we get interesting.
What you describe there is a constant sample rate playback system.
i.e. your DAC update happens at a regular interval, say 44100 times a second.
BUT,
with the discrete logic you're planning on using you could use a
variable sample rate playback
i.e. the DAC updates whenever a change arrives, be it 10 times a
second or 100,000 times a second.
> 1) The actual sampling issue is where I get out of my depth. (My math ain't
> good. Really ain't good.) Assuming that I need to cover the (slightly
> limited*) frequency range provided by MIDI note numbers, the system needs to
> be able to produce waveforms from 27.5Hz to 4186Hz. As the waveform being
> output is actually a set of steps, as far as I can see, the quality of the
> waveform will get WORSE as frequency DECREASES (even with a capacitor on the
> output of the DAC.)
if you use the fixed sample rate DAC updating, YES, it will, this is
called aliasing, which is a slightly incorrect term, what it should be
called is frequency mirrored aliasing. This is caused when the thing
your pushing into your fixed update rate is changeing faster that the
update rate.
Best example of this is in old films where the wheels on a car start
by turning the correct way is it speeds up, then they appear to stay
still, then go backwards. the Camera is providing the fixed sample
rate update (25 frames a second) and the wheel is the variable speed.
Using a variable sample rate playback (as I did with the Monowave and
am doing with Zira) I achieved a 3.6Khz audio tone with no loss in
quality and no aliasing (frequency mirroring).
> 2) I know how to create sine tables (surprise, surprise) but what are the
> corresponding formulae for creating tables of triangle and sawtooth values?
excel is your friend for this :-)
> Is this just plain trigonometry, where you're dealing with a right-angled
> triangle? (What I really can't figure is whether these waveforms are always
> above the line, or whether they have a negative component because the line
> is actually half-way up the waveform.)
they need to be 50% above "zero" and 50% below "zero". if you you're
using 256 samples, and 8 bits, you'd have "zero" as something like
127, which means you have 126 values below that and 127 above. so you
need to be a little careful.
> 3) This is just laziness but also for the prevention of transcription
> errors: does anyone have a machine-readable file of MIDI notes to frequency?
There's a formula out there for that, but to get from your frequency
to your value in your control word for your counter you'll need to
understand your sample rate, bit depth and so on.
For examples of how I did the monowave oscillators have a look at the
schematics in this zip file ;
http://www.vacoloco.net/synths/monowave/downloads/MonowaveFiles.zip
I used an an AT90s1200 to provide more "oscillator" this was
controlled from a main CPU using a look up table, out of that comes a
variable speed square wave. This is fed into a counter chip (4024) and
this drives the lower 8 bits of an EPROM, the output of the EPROM goes
straight to a DAC. so every time I update the address on the EPROM the
DAC changes.
the other "fringe" benefit was that from the 4024 I also got a sub
oscillator "for free" by using the next step output in the counter :-)
For the at90s1200 I used what's called a phase-accumulator approach to
generating the signal.
there's a techy explanation here that I wrote a while back -
http://ppg.synth.net/wave22/
basically the idea is this, and try it you'll see what I mean..
I give you a number which we'll call control, say "1", and you must
add it to another number which starts at zero, call this the
accumulator, once a second.
ow, when you get to, , or exceed, 100 you hold your hand up, reset the
accumulator, and keep adding the control to the accumulator.
When you reach 100 again you lower your hand and reset the accumulator.
you hand is your square wave output to drive your counter circuit
(f/f's in your email).
it takes 200 seconds to get a complete wave.
now I give you 10 for your control..... it takes 20 seconds.
now I give you 50 for your control..... it takes 4 seconds.
if I give you 100 for control, it takes 2 seconds.
so we can go from 2 second periods to 200 seconds without varying the
sample rate of the output, this means you get no aliasing (frequency
mirroring).
however, if you're planning on using your 2313 to do this to feed your
f/f counter, there will be a limit as to how quickly you can add two
numbers and output the square wave due to the speed of the CPU and
everything else you'll be doing (MIDI, etc).
On the monowave I ran the 90s1200 at 12Mhz, the loop took 13 cycles to
compute, but I had a 24 bit control word.
so, the FASTEST I could do was 461539hz for the square wave output,
but the SLOWEST I could do is that divided by 2^24 (16777216) which is
0.0275hz....
Now, this isn't the range of the output wave because this is just a square wave.
On the monowave I used this output to drive the 4024 counter *AND* A0
on the eprom, so to get a full waveform out took this number divided
by 7 steps (128).
So I can go from 0.000215 hz to 3605.77 hz.... what's more I can do it
in steps of 0.0002 hz and without any aliasing caused by frequency
mirroring.
There a huge trade off to be had based on the number of bits in your
accumulator, your control word, the speed you clock the addition at
and the depth of the waveform (be it 8 bit wave or 12 bit, or even 16
bit).
So, my advice, avoid fixed sample rate playback systems if you can,
especially when you're looking at building hardware that allows you to
use variable sample rate playback.
Paul
More information about the Synth-diy
mailing list