I’ve spent a lot of time in the development of the Rockit 8 Bit Synth dealing with aliasing. I made a MATLAB simulation to get to the heart of the issue visually. The script simulates the wavetable synthesis process by generating a sawtooth wavetable and playing back that wavetable to generate a 50% duty cycle square wave output. This output is plotted along with the Fast Fourier Transform (the frequency) of the signal By adjusting some parameters, the amount of aliasing in the signal can be increased or decreased, providing a visual tool for understanding the factors that contribute to aliasing in wavetable synthesis. Click through for a thorough explanation.
The MATLAB Script
First, let’s take a look at how the MATLAB script works. Check out the script here.
Let’s break it down. The script simulates the process of wavetable synthesis in the way that I demonstrated in my post about wavetable synthesis. First, we calculate sine wavetables which we will use to generate another wavetable using Fourier summations. In this case, we generate a sawtooth wavetable. Summing together two sawtooth wavetables 180 degrees out of phase, we create a square wave signal. This may seem like an extra step since we could just generate a square wave from the sine tables using a Fourier series, but this is how it’s done in my synth and that’s what I wanted to simulate. Finally, the script plots the playback of the square wave oscillator and below that shows the frequency content of that signal. Super, n’est-ce pas?
Fundamentals of Aliasing
I’ve previously written about aliasing here and here. But, let’s state it simply again. Aliasing is the presence of unwanted frequency components in the signals you are trying to generate as a result of violating some fundamental principles of digital signal processing. The golden rule is that wavetables cannot contain frequencies above the Nyquist rate, half the sample rate, and be played back without containing aliasing. Frequencies above the Nyquist rate wrap around the Nyquist rate like a mirror and show up as aliases at lower frequencies. This is a result of the math involved. If you want a thorough explanation of that, there are many good textbooks on Digital Signal Processing. I recommend this one.
The Script in Action
Let’s take a look at the output of the script. First, with a clean signal, and then with increasing amounts of aliasing.
The script contains a magic factor, the aliasing factor. When set to 1, the wavetable will contain no frequencies above the Nyquist rate. The result is oscillator perfection.
The top part of the image is the wavetable oscillator output and the bottom part is the frequency content. A square wave is composed of a fundamental frequency and it’s odd harmonics, strictly. Here we have 2kHz square wave, composed of 2, 6, 10 and 14 kHz, which is the fundamental frequency and its 3rd, 5th, and 7th harmonic. In an ideal playback scenario, this signal would be a clean 2kHz square wave. Other factors can introduce aliasing and other artifacts like jitter which could ruin an otherwise perfect synthesis scenario, but let’s not ruin what perfection we’ve got.
A Little Bit of Aliasing
If we increase the aliasing factor to 2, meaning the wavetable will contain frequencies up to twice the Nyquist rate, aliasing rears its ugly head.
We can see aliases appearing as small extra frequency components. The largest one is closest to the end on the right. This component is the alias of the 9th harmonic at 18kHz. The Nyquist rate is half the sample rate, or 32768/2 = 16384. So the alias shows up at 14768Hz, which is 16384Hz – 18000Hz + 16384Hz. The Nyquist frequency is a mirror point. What is above it wraps around it like a mirror. What if we make the aliasing really bad?
If we set the aliasing factor to 10, meaning the wavetable contains frequencies up to 10 times the Nyquist rate, we get this:
Now, we can see the real ugliness of aliasing. The aliases are almost as large as the desired harmonics. This signals will sound like the original plus a bunch of extra high frequency components. Yuck! If we use an non-bandlimited wavetable meaning that it contains infinite frequencies, the problem reaches it’s maximum which will be several degrees worse than the image above.
This MATLAB simulation is a great way to see aliasing in action and to change parameters that can reduce and eliminate the aliasing. You can see that my sample rate is low at 32768Hz. Increasing the sample rate allows the signal to contain more harmonics without aliasing, improving the quality of the output. This comes a cost of clock cycles, reducing the amount of time you have to calculate each sample. I’m looking into my options in that regard, but the point remains the same. Wavetables must be bandlimited. Break this rule and you will hear aliasing!