A simple Arduino-based Synth

I've been footering about with Arduinos for a while now, and have been considering using one as the basis of a simple monophonic synthesizer. I ran across some code for a DDS sine generator which described how to use a PWM output to get 8-bit sample playback going. This seemed like a reasonable place to start, so I adapted it to other waveforms. Of course, it wasn't going to be simple - generating a sine wave is easy but if you want to generate more complex waveforms that would be musically useful, you very quickly run afoul of the dreaded "aliasing". Now, this occurs when the wave generated has significant partials at frequencies higher than the Nyquist limit (half the sample rate). To eliminate them, you must generate a bandlimited waveform that doesn't have these higher partials. Easier said than done!

Poking about on the musicdsp archive I found a couple of references to Norio Tomisawa's work on bandlimited sawtooth generators using sinewaves with feedback phase modulation applied. This means they work like the feedback operator on an FM synth - as you increase the feedback, they become more sawtooth-y. Generate two of them, and you can subtract them to get a bandlimited squarewave. Great. Reduce the amount of modulation and you can simulate a simple lowpass filter as the upper partials disappear leaving you with a sinewave. Even better.

Okay, but can we implement it quickly, in an AVR? Turns out, yes. I used the sine lookup table from the DDS sine generator, calculated the feedback term and added that in, wrapping the lookup at 256 samples so it didn't go off the end of the table. It's also important to remember that since we're using unsigned values there will be an oddly-shifting DC offset - not a lot I can do about that. I tried using signed values but obviously the AVR libc routines were slower than the AVR's hardware (but unsigned-only) multiply.

So, does it work? It does work. Since the Arduino has a USB port I set it to 38400bps and wrote a little USB-to-Serial converter program which you'll need to compile:

alsabridge.c

And of course the Arduino sketch itself:

arduinobee.pde

Grab alsabridge.c and compile with gcc alsabridge.c -o alsabridge -lasound. Then grab arduinobee.pde (the name is a play on nekobee, one of my other projects) and build it in the Arduino environment. I've only tried it with a Freeduino with an AVR328 but I don't see why it wouldn't work on a 168. The ALSA to serial bridge requires that the Arduino is on /dev/ttyUSB0 but you can change that in the source, near the bottom. To start it:

 $ ./alsabridge &
 Serial port handle is 4
 $ aconnect "E-MU XMidi1X1" ALSABridge

Obviously, you need to substitute the name of the MIDI device for whatever you're using to send MIDI. You can use a sequencer and ALSABridge will just show up as another MIDI port.

I'll be adding more things to this little synth, like maybe the ability to edit the sounds. The only real way of changing the envelopes is to edit the sketch, although you can switch between saw and square waves by playing with different velocities. Please get in touch if you try it out, and let me know how you get on.

Posted by gordonjcp on December 6, 2010

Comments

Comments are closed

To prevent spam, comments are no longer allowed after sixty days.