Polyphonic Arduino synthesizer

If you’re interested in building an Arduino-based ROM-pler, this next project is for you!

One of my long term dreams is to build a low-cost 60s-style combo organ. My latest project uses an Arduino UNO as a sample playback, sound synthesis engine. Although the waveforms are taken from the old VOX Continental and Farfisa Mini Compact organs, the design and code could easily use single cycle waveforms from a vintage synth, a string machine, your first born child, whatever! The 60s combo organ project is essentially a software ROM-pler that plays back up to five waveforms at a 22,050Hz sampling rate.

The project hardware consists of an Arduino UNO and a Narbotic Instruments MidiVOX shield. The MidiVOX shield has a Microchip Technologies MCP4921 12-bit digital to analog converter (DAC) and an opto-isolated MIDI input. Although the MidiVOX is no longer in production, it’s basic circuitry is easy to recreate; several other popular audio shields use the MCP4921.

Waveforms are stored in the Arduino’s program memory (PROGMEM), just like code. Program memory is non-volatile and the waveforms are ready to go just like a pre-loaded sketch. The combo organ sketch sets up TIMER1 to generate interrupts at a 22,050Hz sample playback rate. The interrupt handler reads the next sample for each of five virtual tone generators, sums the samples together, and writes the next aggregate sample to the DAC.

MIDI communication is performed through the standard Arduino MIDI library (version 4.2). The sketch registers two callback functions via the library: a note ON handler and a note OFF handler. The MIDI note handlers configure the five virtual tone generators. The sketch’s loop() function is trivial — it merely calls the MIDI library read() function and checks a reset button on the MidiVOX shield.

We all know that Direct Digital Synthesis (DDS) — the usual approach for sample playback — is a compute intensive technique for sound synthesis. DDS dynamically shifts the pitch of a stored waveform from its root pitch (the frequency of the sampled note) to the target pitch (the frequency of the MIDI note played by the musician). DDS performs waveform pitch-shifting through phase accumulation and interpolation. Floating point arithmetic is too slow and most DDS implementations use fixed point arithmetic. Even then, the computational load is heavy.

So, how did I achieve five note polyphony? Instead of storing a single waveform at a single root pitch, my approach stores twelve waveforms — one waveform for each basic pitch in the chromatic scale. The algorithm uses integer phase increments, thereby eliminating floating or fixed point arithmetic and interpolation entirely. The approach requires more space, but is quite fast. Each sampled instrument occupies 20% of program memory, allowing up to four different instruments before running out of PROGMEM.

Here are two quick MP3 demo files: a Farfisa-type sound and a and a VOX-type sound. I created the vibrato by routing the audio signal through an inexpensive Behringer UV300 vibrato pedal.

As usual, we always publish code. Need a cheap ROM-pler? Now you’ve got one!

Update 22 July 2016: If you’re into retro, be sure to check out the Arduino lo-fi beat box project. Filled with lo-fi TR-808 goodness!