Digital Anti Aliasing Filter For Waveform Band Limiting

I am working on some waveform generation software and I am trying to figure out what the best type of filter would be to use a an Anti Aliasing filter for my algorithm. I am generating my waves in a "Raw" mathematical way, meaning that i am creating a ramp for a saw wave and my square wave consists of pure 1's and 0's. The issue is that this technique is inherently not band limited. I would like to implement low pass filter into the algorithm in order to filter of the harmonic being generated that are higher than the nyquist limit.

What would be the ideal filter design for this? What kind of roll of would i need?

I am doing this in c++ but i don't neccesarily need an answer in c++. just an equation or some resources would be good as well.

Thanks

edit: I am not changing the sampling rate at any point in the chain. But i am still experiencing some aliasing somehow.

here is my code:

double _DSP::Saw_Wave(double* _frequency,_DSP::Saw_Data* _data){
double _val = _data->_phasor;
_data->_phasor += 2.0*(1.0/(_DSP::Sample_Rate::Samples_Per_Second()/ *_frequency));
if (_data->_phasor>_data->_tolerance) {
_data->_phasor-=2.0;
}
return _val ;
}

typedef struct Saw_Data{
double _phasor = 0.0;
double _tolerance = 1.0;
}Saw_Data;

where _DSP::SampleRate::Samples_Per_Second() is the sampling rate.

the code generates the proper wave and frequency but has unwanted low frequency information when played at higher frequencies.

• Please specify if there are any sampling frequency changes between signal generation and later processing. If you generate your signals in discrete time, there is no way you can produce frequency components "higher than the Nyquist limit"; spectrum is periodic $2\pi$ in discrete time. – Juancho May 1 '14 at 21:25
• are you trying to produce classic analog waveforms with suppressed or eliminated aliases? you might want to ask about this on the music-dsp mailing list. – robert bristow-johnson May 5 '14 at 2:18

I am generating my waves in a "Raw" mathematical way, meaning that i am creating a ramp for a saw wave and my square wave consists of pure 1's and 0's. The issue is that this technique is inherently not band limited. I would like to implement low pass filter into the algorithm in order to filter of the harmonic being generated that are higher than the nyquist limit.

You can't do this. You've already aliased the frequencies when you generated the waves in that way. You can't remove them with a filter.

You're essentially sampling the pure mathematical signal without using an antialiasing filter first. It's not possible to add the antialiasing filter after sampling. You will just filter the already-aliased signal. Bandlimiting has to occur before sampling. You need to change the way you generate the waveforms if you want them to be bandlimited. You could generate them using additive synthesis, as I've demonstrated here, or you could generate them the simple way at a much higher sampling rate to minimize the aliasing, then antialias filter, then decimate. Or you could use BLIT or BLEP, etc. (I think those are both "reduced-aliasing" not 100% eliminated, but I'm not sure.)

• Okay cool. I am relatively new to DSP programming/theory so this helps a lot. – Alex Zywicki May 1 '14 at 21:44
• @AlexZywicki Do you understand what I meant about sampling the mathematical signal though? – endolith May 1 '14 at 21:59
• I believe so. You are saying that the mathematical signal that i am generating already contains frequencies that are beyond the nyquist limit when they are sampled. I guess i just don't get why i can't run the signal through a filter and remove the harmonics that exceed the limit. In my head it seems like it would work, but i am probably wrong. – Alex Zywicki May 1 '14 at 22:04
• I have added an answer explaining why using a filter doesn't work. – pichenettes May 1 '14 at 22:23
• @endolith It took me a moment but I know i get it now. The frequencies that would be filtered off if we were going from analog to digital have already folded back into the wave and because of that the low pass filter can't remove them. Thank you for the help – Alex Zywicki May 1 '14 at 22:34

Let us say your sample rate is 48kHz.

You are generating a sawtooth wave at a fundamental frequency of 10kHz, using your code.

First harmonic is at 10kHz. Second harmonic at 20kHz. Third harmonic at 30kHz. But since your signal is inherently sampled at 48kHz, anything above Nyquist gets aliased back into the 0..24kHz band. The 30kHz harmonic is 6kHz above Nyquist, so it gets folded back to 24-6 = 18kHz. Fourth harmonic at 40kHz, 16kHz above Nyquist, folded back to 8kHz which is below your fundamental! Next harmonic at 50kHz, 26kHz above Nyquist, folded back to 2kHz.

I recommend you to use Sonic Visualizer or any other audio analysis tool, and monitor the spectra of the signals coming out of your code. You'll see the undertones created by your code.

Since you are already working with a 48kHz sample rate / 24kHz Nyquist frequency, everything your algorithm generates will be folded into this band; and obviously no simple filter shape - low-pass, high-pass could filter the spurious 18kHz, 8kHz, 2kHz and so on tones.

The only filter that could possibly work would be a comb-filter with a cutoff frequency equal to your fundamental - but it is tricky to design, and still won't handle the case where the fundamental divides the sample rate.

Thus, you need to use a technique which directly synthesize (approximately) band-limited data - additive synthesis, band-limited wavetables, or minBLEP.

OR:

You generate your data as a ridiculously high sample rate - to the point that you can consider that aliasing will be negligible; and then low-pass filter.

For example, let us say that you request that no alias image should be above -48dB (which is still very lax!). This means that only the 252th harmonic of your sawtooth wave can be aliased (its amplitude will be 0.004, or -48dB). So your Nyquist frequency has to be above the frequency of the 252th harmonics of the highest pitched note. Let us say 4kHz is the highest fundamental frequency you want to synthesize. This means a sample rate of 2 x 4000 x 252 = 2 MHz.

So if you have lots of computational resources to waste, you can run your synthesis code at 2 MHz, then apply a brickwall low-pass filter at 24kHz, and resample at 48kHz. But this would be a very stupid thing to do...

• Thanks the combination of your answer and Endoliths answer have cleared it up for me. – Alex Zywicki May 1 '14 at 22:35
• To complete my answer, there is actually a commercial product which generates sawtooth signals the naive way - just like your code - and uses a high-pass filter with a cutoff-frequency a bit below the fundamental to remove all aliased harmonics below the fundamental. The idea is that the most annoying aliased harmonics are those with low frequencies. But this was in 97... – pichenettes May 1 '14 at 23:05
• Worth reading: acoustics.hut.fi/~jpekonen/teaching/gl/… – pichenettes May 1 '14 at 23:30
• in my opinion, and in my direct experience, J. Pekonen greatly overstates the number of wavetables needed to well represent a particular waveform over the range of the keyboard. if your sample rate is 48 kHz (so Nyquist is 24 kHz) and you don't care too much about what happens above 19.88 kHz (like, if you have to, you can LPF out everything above 19.88 kHz), then you need only two wavetables per octave of use. a 64-key synth will need only 10 wavetables to cover a well-bandlimited sawtooth throughout the entire 5 octave keyboard. Jussi is just wrong when he says 600 wavetables. – robert bristow-johnson May 5 '14 at 2:55

there are four ways i know of to create bandlimited waveforms that approximate or sound like classic analog waveforms (that are not bandlimited much until they hit the loudspeaker).

1. the BLIT and BLEP methods.

2. additive synthesis with a limit on the harmonics.

3. wavetable synthesis with interpolation between wavetables. (this is what i would recommend.)

4. deriving the functional definition of a mostly bandlimited waveform and implementing that mathematical function. like what might a simple filtered version of the square wave or sawtooth wave look like in the time domain?

remember, when harmonics fold over and become inharmonic aliases, you want to avoid that, but you might be able to tolerate a little bit of that, so to make your life easier.

You can reduce the aliases by doing a simple linear interpolation for the single sample where the phase accumulator wraps around. It won't completely eliminate the problem but it should help. Use the ratio of ( phase modulo max phase ) to the phase increment.

Bob