Joe Cleveland / Projects

Delay Line Synthesizer Plugin

In my last semester of college I built a synthesizer plugin in C++ that is compatible with the major digital audio workstations (DAWs) such as Abelton Live, Logic Pro, or Pro Tools. The JUCE framework makes this headache free, as it automatically targets the two major plugin formats, Apple AU and VST. Before working on this project, I spent a good bit of time reading the work of Julius Orion Smith (CCRMA) and his work on physical models using digital waveguide synthesis. (Here is a cool online demo of waveguide techniques).

Inspired by this work, I've incorporated a few delay lines with filtered feedback after each oscillator. When the length of these lines is short, they make the synthesizer behave like a Karplus-Strong string synthesizer. When the delay-lines are long, they act as a sort of spring reverb effect. In both cases, I think it sounds quite cool, especially when modifying the length of the lines in real-time, which you can hear in the first of these sound demos:


The basic element of the synthesizer is a harmonic oscillator. Using the 'Shape' control modifies the parameters $s$ in the equation $$ f(angle) = cos(tanh(sin(angle)) * S) $$ which adds more harmonics to the wave as $S$ is increased. To generate the wave, $angle$ is 'rotated' from $0$ to $2\pi$ at a speed depending on the frequency and sample rate. Two of the oscillators are mixed together, and their relative frequencies can be changed to create interesting beating effects.

A big design challenge has been getting the low-pass filter to sound good and run efficiently. From the cutoff and resonance/Q parameters, a frequency response curve is calculated.This curve represents which frequencies in the sound will be amplified, and which will be subtracted.This curve is then converted into an FIR filter kernel using the fast fourier transform. Designing a frequency response curve which sounds pleasing is a bit of an art form, and required some tinkering. In order to apply the filtering, the kernel is convolved with the output signal. The convolution operation is less efficient with larger kernels, however bigger kernels sound much smoother. In future work, I could imagine optimizing this calculation with SIMD instructions or OpenGL.