For this assignment (and subsequently improved in the final project), I decided to implement analog-style band-limited oscillators, a la Stilson and Smith (1997). It is believed that the Novation Supernova series of synthesizers use this method. I plan to eventually implement these oscillators in C++, as part of MSTk++.

I implemented a BLIT algorithm as a macro, using a Discrete Summation Formula, because the sum-of-cosines generator built into CLM was giving me scaling problems when sweeping the frequency. You will need this file to run the instruments mentioned below.

I first implemented a sawtooth oscillator, via integration of a band-limited impulse train (BLIT).

Next I made a square wave via integration of a bi-polar BLIT, which includes a pulse-width parameter. Due to linearity of integration, this is mathematically equivalent to generating square waves by subtracting one phase-shifted sawtooth from another. By scaling the negative BLIT component (between 0 and 1), I have added a "morph" control between saw and square.

I next made a triangle ramp oscillator, via integration of the square wave. In this case, the pulse-width controls the slope of the triangle wave, smoothly varying the slope between a ramp (quasi-sawtooth) and a triangle shape. The morph parameter transitions between parabolic and ramp waveforms. In the same manner as the pulse-wave, this is equivalent to summing two parabolic (integrated sawtooth) waves. This instrument is especially prone to DC glitches at the startup, due to the double-integration.

Again due to the linearity of integration, if two BLITs are summed, then only one integration needs to be performed to get a "super-saw." This method is more efficient than simply mixing two saw waves, and has exactly the same cost as generating a single square wave. An interesting idea would be to subtract two sawtooth waves, to get some kind of "super-square". I haven't tried this yet, but it should have some kind of wacky PWM.

This patch is reminiscent of the Roland Alpha Juno series, made famous in the early 90's "hardcore" rave scene: hoover.wav

For the final project, I also generated bandlimited hard-sync sounds. MinBLEPs are good for this (see below), but I haven't quite figured out the implementation. I found some C code that creates bandlimited sync sounds, using two bandlimited wavetable oscillators and a cos^2 window. The trick is to calculate two out-of-phase waveforms, and then crossfade them with the window. Soft-sync can be done by only resetting the slave phase when the master phase resets AND the slave phase is within a given distance from zero. I used the window method with BLITs, to create a hard-sync CLM instrument: good-sync. The sound is very realistic if you ask me!

Listen for yourself: hardsync.wav

The advantage of the BLIT method, is that calculation is constant for all frequencies. In practice, it is more efficient to use additive sines for higher frequencies. Another advantage of the (DSF) BLIT method is that a lowpass filter is built in, by modifying the harmonics and/or rolloff parameter of the DSF. One problem with the BLIT method is that DC transients occur when starting up the integration. This can be minimized by creating a lookup table with integrator initialization values versus frequency (and phase).

Another possible way to reduce processing when doing the phase-shifted and subtract type oscillators (square, ramp) is to use a comb filter to generated the phase-shifted waveform. However this causes a glitch on the first cycle of the waveform, and the slight overhead of an interpolated delay line for modulation.

In retrospect, the ramp waveform is not so great as an audio oscillator, but would be good as an LFO. In this case it would be more effecient to generate a parabolic wave from scratch. By comb filtering the parabola (as above with the square), a variable-slope ramp wave can be generated.

A more elegant method of generating bandlimited waveforms is the MinBlep method, which uses a wavetable of a pre-integrated minimum phase BLIT, to create a minBlep (min-phase BL step). In theory it can generate a bandlimited version of any arbitrary waveform. I have yet to test it out. One disadvantage of this method is that processor load increases with oscillator frequency, as more wavetable transitions have to be pasted in. This would be problematic in a hardware DSP implementation.

On the topic of oversampling, it is speculated that the Nord synths simply generate "naive" waveforms at a very high samplerate; then downsampling (with a proper LPF) is performed at the output. This has the added advantage that higher-order modulations will not alias noticably (for instance, ring mod and FM).

I found to my surprise that CLM did not have a resonant multi-mode filter (I am infatuated with the juicy sound of a low frequency sawtooth through a resonant highpass filter!!). So I implemented an oversampled State Variable Filter (aka Chamberlin filter). It is oversampled in order to make the cutoff frequency more accurate at high frequencies. It will operate as a highpass, lowpass, bandpass, or notch filter. The same algorithm is implemented in my PD extern, svf~.

Here is a page with a good explanation of the State Varible filter (with simplification to the Magic Circle oscillator!):

StateVar @ Earlevel.com

For fancy effects, it is nice to have two filters, and crossfade the output of the first filter with the output of both filters in series. This way you can "morph" between a 12 and 24 dB/octave cutoff slope. I tried to make a with-filter macro, but ran into some strange problems. This is on my to-do list...

Last updated 3/20/03