russell mcclellan

russell.mcclellan@gmail.com

Eurorack Digital Oscillator

It's been a while, but I've released yet another completed eurorack oscillator design. This one is based on another classic 80s design, this time a high-frequency purely digital oscillator.

Eurorack Digital Oscillator

background

A synthesizer oscillator's job is to create an audio waveform at a controllable frequency. In polyphonic synthesizers, stable tuning is especially important, since the human ear is very sensitive to out-of-tune notes when chords are played. Unfortunately, it's not particularly easy or cost-effective to create an analog oscillator with stable tuning. For a great summary of the techniques engineers have used to stabilize analog oscillators, please see this report by open music labs. The challenges of cheaply stabilizing oscillators led to the designs of digitally controlled oscillators, where an analog oscillator is synchronized to a digital oscillator. Roland's juno series of synthesizers initially used DCOs, but switched to a purely digital design for the alpha juno line. This design is heavily inspired by the one from the alpha juno series.

why does it go so fast?

One traditional problem with digital oscillators is the problem of aliasing. Aliasing usually shows up in the context of digital recordings - if we try to sample audio signals that contain high frequencies, they appear in our recordings as low frequencies. It's impossible to distinguish these "aliased" low frequencies from low frequencies that were actually there, so a proper recording can never be recovered once aliasing is introduced. The normal answer to this is to apply an analog low-pass filter to the signal before sampling so that no high frequencies will remain by the time we get around to sampling.

So, aliasing can destroy digital recordings, but what do they have to do with digital oscillators? Well, it's a bit of a complicated answer (and one that I hope to answer more fully in a future post), but basically, the first algorithm you'd think of for a digital saw wave is equivalent to sampling an analog saw wave. But, an analog saw wave contains a full harmonic series, which is to say, infinitely high frequencies. So, no matter how high our sampling rate, we'll get some aliasing in our output. There are other algorithms for generating saw waves that don't have this problem, but we'll leave those for another day.

This oscillator (and the alpha juno it's based on), use this naive algorithm that's equivalent to sampling an analog saw wave. So, how come they don't have audible aliasing? They run the algorithm at a very high sampling rate. Since the amplitudes of each harmonic in a saw wave are lower than the last, by setting our sampling rate to much higher than the rate of the saw wave, we can ensure that any aliased harmonics are fairly low in amplitude. For typical audio rates (say, 400 hertz), the alpha juno runs the oscillator at 2 megahertz! This is much faster than digital to analog converters that we are used to, which run in the low kilohertz (typically 48 kilohertz these days).

Audio people usually think of using high sampling rates to reproduce high frequency signals; but in this case we're using the high sampling rate to reproduce low frequency signals with a simple algorithm.

how does it go so fast?

Outputting a signal at 2 megahertz or above is not realistic using a cheap microcontroller, even using recent chips. However, it's totally reasonable for fpgas or cplds, which are programmable logic circuits rather than microprocessors. In this case, we have a very inexpensive (a dollar or two) lattice MachXO CPLD, connected directly to a simple R2R DAC.

The cpld is programmed using haskell, which can be transpiled to verilog through the clash compiler.

To manage the analog to digital converter, I'm using an avr microcontroller programmed with the arduino tools. This using tuning look tables and sends the cpld tuning data over a bespoke parallel interface.

The four-layer PCB was designed with kicad.

As usual, all the design files are available on github.

how does it get tuned?

One of my biggest surprises doing this project was the complexity of designing a proper tuning procedure for the oscillator. There's a fair number of parameters in the tuning system, and interesting trade-offs for each choice. This is written up in detail in a jupyter notebook in the source repo.

All images and text are licensed under a Creative Commons Attribution 3.0 United States License, except as noted. Linked code, and embedded code examples are licensed separately.