Antialiasing filters - IIR or FIR? Examples?

DSP, Plug-in and Host development discussion.
User avatar
KVRist
373 posts since 28 Nov, 2013 from Germany

Post Wed May 27, 2015 10:54 am

Hello,

I am currently playing around with the concept of phase distortion. My Python prototype distorts the phase of a simple sine wave. When I set the distortion to high values to achieve something like a saw wave it will result in aliasing. I know why it occurs and now would like to do something to get rid of it (or most of it). So I'd like to do the following:
  1. Oversample the phase distortion oscillator, e.g. by four times.
  2. Apply an antialiasing filter around 20 kHz.
  3. Downsample by only using every fourth sample of the result.
I hope that this is the correct way to oversample in this case. I guess part 1 and 3 are rather easy. However, I currently have no idea of how to do the filtering. I have searched Google but have not found anything concrete. Only lots of explanations of why it's done. :)

So here are my questions:
  • What kind of filters are "usually" used as antialising filters (in interactive cases)? IIR filters? FIR filters?
  • Can someone provide me with an example implementation of an antialiasing filter or some good filter coefficients?
Thanks in advance!
Passed 303 posts. Next stop: 808.

KVRian
1379 posts since 26 Apr, 2004 from UK

Post Wed May 27, 2015 11:55 am

In my case, I'm using a FIR, and the coefficients come from http://yehar.com/blog/wp-content/upload ... iginal.pdf
They work well and are easy to implement: https://github.com/mbrucher/AudioTK/blo ... Filter.cpp

User avatar
KVRist

Topic Starter

373 posts since 28 Nov, 2013 from Germany

Post Wed May 27, 2015 12:43 pm

Hi Matt,
Miles1981 wrote:In my case, I'm using a FIR, and the coefficients come from http://yehar.com/blog/wp-content/upload ... iginal.pdf
They work well and are easy to implement: https://github.com/mbrucher/AudioTK/blo ... Filter.cpp
Thanks for that interesting paper and the link! Do I understand correctly that the paper and the code that you have linked is more about upsampling a signal that is only available in sampled form? I am asking because my problem is more about how to implement the lowpass filter that will filter an already oversampled signal around 20 KHz (step 2).

My signal can be considered as already oversampled because all I am doing is sine evaluations for certain phases and in my case I would simply evaluate the sine twice or four times as often. So my situation is as follows. Let's assume the target/output sample rate is 44.1 kHz and that I am doing 2x oversampling:
  1. Generate the phase distorted signal as if the target rate was 88.2 kHz, i.e. evaluate the sine 88200 times for one second of sound.
  2. Lowpass filter the 88.2 kHz signal at 20 kHz. Due to the increased band width a filter with a relatively gentle slope can be used here. My main question is how such an antialiasing lowpass filter would look like. I guess it should not color the signal too much and that this step might therefore have rather high quality requirements.
  3. Throw away every second sample to reach the target rate of 44.1 kHz.
Passed 303 posts. Next stop: 808.

User avatar
KVRist
156 posts since 26 Sep, 2001 from Paris, France

Post Wed May 27, 2015 2:08 pm

Have a look at this http://dspguru.com/dsp/faqs/multirate
You want to implement a sinc FIR which has the advantage of being linear phase, thereby preserving transients and phase relations.
You'll have to choose cutoff and band rejection with respect to your application, for a given filter size.
Polyphase filtering will allow you to implement filtering+decimation in a most efficient way.

Since you know in advance the spectral contents of your signal, I suppose you could choose a rather low cutoff point, with a small filter size whilst still having good stop-band (aliasing) rejection.

And maybe you could get rid of the up/downsampling altogether by computing the anti-aliased waveform 'directly', ie by using some BLIT type techniques.

KVRian
1379 posts since 26 Apr, 2004 from UK

Post Thu May 28, 2015 12:51 am

Sorry, I read too fast. In your case, I would just filter with a Bessel or Butterworth low pass (also available in my library). Nothing too fancy, but it works great!

KVRer
19 posts since 13 Jan, 2012

Post Thu May 28, 2015 3:55 am

Just want to point out to half-band filters for these tasks.

If you oversample by a power of two, like in your example by a factor of four, then you can use a chain of half-band filters to get rid of the unwanted harmonics.

Half-band filters are in a nutshell FIR low-pass filters that have their cut-off point exactly at 1/4 of the sample rate. E.g. they throw away the upper half of the harmonic content. They are attractive, because half of the FIR coefficients become zero, and the others are symmetric. This naturally leads to a very slick and fast implementation.

They also work *very well* in a multi-rate filter configuration.

User avatar
KVRist

Topic Starter

373 posts since 28 Nov, 2013 from Germany

Post Thu May 28, 2015 10:41 am

Thanks for the information and the links so far!
torusle wrote:If you oversample by a power of two, like in your example by a factor of four, then you can use a chain of half-band filters to get rid of the unwanted harmonics.
So, if I would do four 4x oversampling at a 44.1 kHz sample rate I would cascade two half-band filters where the first one downsamples from 176.4 kHz to 88.2 kHz and the second one from 88.2 kHz to 44.1 kHz?
Passed 303 posts. Next stop: 808.

KVRer
19 posts since 13 Jan, 2012

Post Fri May 29, 2015 1:39 am

BlitBit wrote: So, if I would do four 4x oversampling at a 44.1 kHz sample rate I would cascade two half-band filters where the first one downsamples from 176.4 kHz to 88.2 kHz and the second one from 88.2 kHz to 44.1 kHz?
Exactly!

The fun thing is: FIR filters don't have a state, so you can evaluate them individually for each sample in any order you like. Since you're down-sampling after filtering anyway it would not make sense to run the filter at 176.4kHz and then discard half of the results. Instead run the first filter at 88.2kHz on each second input sample and directly generate the 88.2kHz output.

The same applies to the second cascade which directly outputs a 44.1kHz signal.

If you put these two numbers together you'll effectively get down-sampling and anti-alias filtering of your 176.4kHz signal at the price of a single filter running at 132.3kHz (88.2 + 44.1).

User avatar
KVRist

Topic Starter

373 posts since 28 Nov, 2013 from Germany

Post Wed Jun 03, 2015 11:41 am

torusle wrote: Exactly!

The fun thing is: FIR filters don't have a state, so you can evaluate them individually for each sample in any order you like. Since you're down-sampling after filtering anyway it would not make sense to run the filter at 176.4kHz and then discard half of the results. Instead run the first filter at 88.2kHz on each second input sample and directly generate the 88.2kHz output.

The same applies to the second cascade which directly outputs a 44.1kHz signal.

If you put these two numbers together you'll effectively get down-sampling and anti-alias filtering of your 176.4kHz signal at the price of a single filter running at 132.3kHz (88.2 + 44.1).
Thanks again for all these great tips torusle! I have an implementation that is working but after looking at the results another question has popped up.

Obviously using an FIR will introduce some latency or lag in the system, i.e. if I compare the filtered output to the unfiltered output the filtered output lags behind the unfiltered output by a certain number of samples (that is related to the filter order if I understand correctly).

Is there any way to get rid of this? I found some articles which proposed that the first few sample should be thrown away to synchronize the filtered signal with the unfiltered one. However, I wonder whether such an approach is only feasible for offline cases where all the data is known before hand.

To be more clear let's consider an example. Let's say I have a plugin and the process method is called with a buffer size of 128 samples. Also let's assume that the filter introduces a delay of 8 samples before the "real" filtered signal appears. A "note on" event occurs and my oscillator starts to produce some output. If my filter produces 128 samples from which we need to throw away the first 8 samples it will effectively have created 120 samples that I can put in the buffer. However, for a complete result I will need to compute the next 8 samples which I can only get once I will produce the next 128 samples, i.e. during the next process call which might provide me with other input data.

Am I overthinking this? Do I have to care about these delays? What do other synth implementations do? In my examples even having only a few samples of delay already resulted in quite large phase offsets compared to the unfiltered signal, e.g. offsets of 72 degrees. Also if I have several other oversampling processes in my chain, e.g. for some distortion effect, these numbers will add up to even more delay and make things even worse.
Passed 303 posts. Next stop: 808.

KVRist
426 posts since 21 Jun, 2013

Post Thu Jun 04, 2015 5:27 am

BlitBit wrote:Am I overthinking this? Do I have to care about these delays? What do other synth implementations do? In my examples even having only a few samples of delay already resulted in quite large phase offsets compared to the unfiltered signal, e.g. offsets of 72 degrees.
If you do realtime signal processing, there is no way to get rid of delay (which is based on FIR order of course).

The key is to avoid adding/subtracting delayed signals which creates comb-filter effect. For example, if you do dry/wet mix for your oversampled distortion, you need to delay input signal according to oversampling delay.
BlitBit wrote:Also if I have several other oversampling processes in my chain, e.g. for some distortion effect, these numbers will add up to even more delay and make things even worse.
Yes, but usually you want to avoid multiple oversampling chains because these are not light on CPU.

KVRian
1379 posts since 26 Apr, 2004 from UK

Post Thu Jun 04, 2015 5:50 am

Yes, it's definitely better to keep the sampling rate constant, even if after a process you have to filter some high ferquencies, it's best not to decimate and oversample afterwards.

On the theme of optimization, I'm actually not sure that computing only every other sample will be efficient if the code is optimized. With proper constrution, the computations can be done with SIMD instructions, and having holes will impede this. So in the end, instead of speeding the code by two by halving the number of computations, you may end up slowing it down by a factor of two because you have to use standard FPU code (which is not optimized at all, as I think some CPUs don't have them anymore) for each sample instead of the SIMD units that could compute say 2 samples per instruction.

KVRian
586 posts since 4 Apr, 2010

Post Mon Jun 08, 2015 10:12 pm

A number of good tips already out that that I would have given, so I'll just mention a few points:

Yes, FIR (over IIR), in general. Reasons: phase linear (if designed to be, of course), and while an IIR is far more efficient at low frequencies, FIRs aren't bad at the relatively high frequencies you'll use (which is why you go with multi-rate—multiple relatively high, such as half-band, stages, which you can optimize).

Equiripple designs are more efficient than windowed sinc—a significantly shorter filter for the same transition and stop band performance; while windowed sinc (I recommend kaiser window if you go that way) has a completely flat passband, an equiripple with negligible passband ripple will still have better performance.

2X oversampling isn't much frequency headroom—remember, it's only an octave. But some overestimate how much you might need—if you're really generating a lot of harmonics (such as guitar amp effects), you can start with 6X (more is better, but you decide the tradeoffs—4X isn't enough). 8X is a good number for many demanding effects (maybe more than you need—I'm giving "rules of thumb" here), but if you're strapped for cycles, 6X can be done fairly efficiently in two steps.

Don't forget that efficiency in multi-rate (multi-stage) implementations comes from the ability to allow the first filter(s) to be more lax (cheaper), then tidied up by the final stage.

Don't forget that half-band filters alias significantly (unless you go super steep—and lose the advantage of going half-band to same cycles). So maybe that last stage is not half-band—but it depends on your needs and choices.
My audio DSP blog: earlevel.com

Return to “DSP and Plug-in Development”