Antialiasing For Dummies

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Is there such a thing? This is the most difficult topic I've run into so far. Any interesting papers that I find read: Math math math aliasing MATH MATH MATH, and Bob's yer uncle!

I'm looking at upsample-> filter-> downsample. From what I've read, it's possible to do this in a single step by zero padding every other sample (for 2x over sampling)?

It's possible I've just read too much random stuff regarding filters while recalling earlier days when Euler made some sort of sense. The math is slowing me down a bit, but the concepts based on discrete electronics are beyond me as I know very little about electronic circuits.

I guess my question is, what is a good source for information on filters that starts with poles with a nod to circuitry, goes through DFT, statedness, IIR, FIR and ends up at oversampling? Best book, best website, etc. It can't be too basic, but it can't be too advanced.

Thanks!
I started on Logic 5 with a PowerBook G4 550Mhz. I now have a MacBook Air M1 and it's ~165x faster! So, why is my music not proportionally better? :(

Post

No, there is no such thing, but any signal processing book tackles this. Unfortunately, not everyone understands the duality between time and frequency (especially the aspect where pople think you can filter in the spectral domain).

No, it is not possible to upsample in one step using zero padding, you explicitly need to filter the result, because you aliased your spectrum by using this technique. The one step method is by using a polyphase filter (which is actually just a FIR over zero-padding, but without saying it).

Post

The basics are as follows.

There is a theorem that states it is possible to reconstruct a bandlimited signal after it has been sampled, if sampling rate is at least twice the highest frequency that the original signal contains. This is called the sampling theorem, named after a man named Nyquist.

The result is like an array of numbers. It is being called the sampled or discrete signal. It can be interpreted in a number of different ways. Assume that each of these views below (a), (b) and (c) are a different mental pictures or interpretations of the same thing.

a) it's just an array of numbers (which is one way to interpret it)
b) it is a continuous (analog) signal with zero values in every point except the samples, represented as an array of numbers corresponding to the samples, stored digitally in a computer program.
c) what we get from a digital to analog converter when that array of numbers is used as a source.

(a) is what you work on, i.e. what your software code/algorithms sees. It is assumed that such algorithms are doing linear and time invariant operations (theoretically, at least).
(b) is the assumption behind statements such as "the sampled signal contains the same frequency spectrum repeated forever up to infinity". Fourier transform of signal (b) is exactly that.
(c) is what eventually matters, so it is natural that this is the default (but, somewhat wrong), view. Only (b) is theoretically correct. When the array (a) is fed to a digital analog converter you get the very first copy of that repeated spectrum contained in picture (b), i.e. the band [0..N/2] where N is the sampling rate, as an analog signal.

Oversampling (zero padding in this case) introduces a part of the picture (b) into the scene visible in picture (a). As a result, one portion of the infinitely repeated spectrum becomes visible digitally, i.e. it becomes visible to your algorithm(s). Before that it was only conceptual, but after zero-padding, some part of that conceptual reality becomes concrete. You get rid of that repeated image with a low pass filter ( one that has a good roll-off rate). Then you are left with another picture in the view of (a) at another (a higher) sample rate, conceptually correspoinding to another picture in view (b), but since the repeated image is now deleted, this new picture looks like exactly the previous image, but its resolution is higher. Call these new signals (a') and (b'). You can process that new signal at the new sampling rate using the picture (a'). If the signal is still properly band limited, you can throw away every M-1 sample of M samples and keep one, that is called downsampling. This is similar to sampling an analog signal. i.e. the sampling theorem needs to be taken into account. Eventually you have a third signal, with views (a''), (b''). When you feed the signal (a'') to an analog digital converter running at the sampling rate of (a''), then you get (c'') from its analog output.

I hope that makes sense.
~stratum~

Post

Miles1981 wrote:No, there is no such thing, but any signal processing book tackles this. Unfortunately, not everyone understands the duality between time and frequency (especially the aspect where pople think you can filter in the spectral domain).

No, it is not possible to upsample in one step using zero padding, you explicitly need to filter the result, because you aliased your spectrum by using this technique. The one step method is by using a polyphase filter (which is actually just a FIR over zero-padding, but without saying it).
Thanks Miles. Any particular text you can recommend? I do prefer dead tree editions for this type of reading. :lol:

Regarding polyphase filters, it is my understanding that you design the filter so that every other coefficient is zero, thus the zero padding, or whatever you want to call it. Or, maybe I'm conflating here and it really is as simple as feeding the filter s1, s2, s3, etc. instead of generating the samples in between (which is trivial for me--I can oversample at any rate.)

As you can see, I need a single source to read so I can coalesce all this input I've shoved into my brain. :D
Last edited by syntonica on Thu Dec 08, 2016 11:36 pm, edited 1 time in total.
I started on Logic 5 with a PowerBook G4 550Mhz. I now have a MacBook Air M1 and it's ~165x faster! So, why is my music not proportionally better? :(

Post

stratum wrote: (a) is what you work on, i.e. what your software code/algorithms sees. It is assumed that such algorithms are doing linear and time invariant operations (theoretically, at least).
Not always, I hope! :lol: Otherwise the only reason for oversampling is better filter accuracy near Nyquist (to the best of my somewhat limited knowledge).

Post

stratum wrote:This is called the sampling theorem, named after a man named Nyquist.
Thanks, but I know Harry quite well. Have you met his friend Claude? :wink: :hihi:

I do appreciate the help, I do, but as I said, I'm kind of in the middle here--everything I find is either way too basic, or way too advanced. Thus, the desire to read up on filters from their basics since to understand the math, it helps if I have concrete examples as to what it's actually doing. (This is why me and advanced particle physics did not get along very well!)

Actually, I just stumbled upon Miller Puckette's book online at UCSD, so I well give it a try to see if it can fill in the blanks for me. It doesn't look too basic for my needs.
I started on Logic 5 with a PowerBook G4 550Mhz. I now have a MacBook Air M1 and it's ~165x faster! So, why is my music not proportionally better? :(

Post

Have you watched these? Not really about filters but could help fill some gaps...

https://xiph.org/video/

Post

I do appreciate the help, I do, but as I said, I'm kind of in the middle here--everything I find is either way too basic, or way too advanced.
This stuff is pretty basic when properly understood and there is nothing more to it. The "advanced" part you see is about something else, probably. Perhaps about the design of the filters used and about the design choices that are made that serve a specific purpose related to a specific application. One could also use many different interpolation algorihms instead of just zero padding.
Last edited by stratum on Fri Dec 09, 2016 8:41 am, edited 1 time in total.
~stratum~

Post

Not always, I hope! :lol: Otherwise the only reason for oversampling is better filter accuracy near Nyquist (to the best of my somewhat limited knowledge).
That's what the phrase 'theoretically at least' was meant to convey without getting into details:-)
Last edited by stratum on Fri Dec 09, 2016 8:00 pm, edited 1 time in total.
~stratum~

Post

syntonica wrote:Is there such a thing? This is the most difficult topic I've run into so far.
You can try my articles here:

http://www.earlevel.com/main/category/d ... ?order=ASC

A shame I've had a video on the topic on hold for the past year and a half while tied up in software development. Maybe a couple of months into 2017 it'll be out.

The good news, is that it's a pretty simple topic when not presented math-first.
My audio DSP blog: earlevel.com

Post

Oversampling can be made simple by applying Sinc function windowed by one of popular window functions. You may see for Lanczos resampling here:
https://en.wikipedia.org/wiki/Lanczos_resampling
You may take the kernel with 2 or 3 lobes and calculate convolution with original signal (do not forget that for 3x oversampling your input signal sequence s1 s2 s3 ... should look like s1 0 0 s2 0 0 s3 0 0 ... before convolution) .
For example, here's Lanczos 2x resampling with kernel of 2 lobes:

Code: Select all

        /** Perform lanczos resampling, destination buffer must be cleared and contain only
         * convolution tail from previous resampling
         *
         * @param dst destination buffer of count*2 samples + 8 extra samples for convolution tail
         * @param src source buffer of count samples
         * @param count number of samples
         */
        void lanczos_resample_2x2(float *dst, const float *src, size_t count)
        {
            while (count--)
            {
                float s     = *(src++);

                // Apply Lanczos 2x2 kernel
                dst[1]     -= 0.1664152316035080f * s;
                dst[3]     += 0.6203830132406946f * s;
                dst[4]     += s;
                dst[5]     += 0.6203830132406946f * s;
                dst[7]     -= 0.1664152316035080f * s;

                // Move destination buffer
                dst        += 2;
            }
        }
The downsampling is simple: you can apply lowpass filter (for example, Chebyshev type 1 with high slope (many poles)) and then take every Nth sample from the filtered sequence.

Post

squaresine wrote:
stratum wrote: (a) is what you work on, i.e. what your software code/algorithms sees. It is assumed that such algorithms are doing linear and time invariant operations (theoretically, at least).
Not always, I hope! :lol: Otherwise the only reason for oversampling is better filter accuracy near Nyquist (to the best of my somewhat limited knowledge).
The theory says so, but in reality music processing is nonlinear and so much variant :P I'd drop that part as it has no use.
Blog ------------- YouTube channel
Tricky-Loops wrote: (...)someone like Armin van Buuren who claims to make a track in half an hour and all his songs sound somewhat boring(...)

Post

The theory says so, but in reality music processing is nonlinear and so much variant :P I'd drop that part as it has no use.
It has use in putting things in proper perspective. Much confusion I have observed in KVR threads arise from not separating theory from practice. Somebody asks a filter design question then somebody else goes on to explain what's being done in a state of the art EQ plugin without explaining design concerns and what is being accomplished and why. Then, only the ones who already know understand what's being explained:-) What a rocket science. I guess the OP was confused for similar reasons in spite of the fact that the subject matter is very simple.
~stratum~

Post

Lets make this discussion a bit more concrete.

The following code is from wdl-ol, a waveshaping distortion with oversampling.

Code: Select all

void IPlugDistortion::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
  bool isMono = !IsInChannelConnected(1);

  for (int i = 0; i < nFrames; ++i)
  {
    double sample = isMono ? inputs[0][i] : 0.5 * (inputs[0][i] + inputs[1][i]);
    double output;

    for (int j = 0; j < mOversampling; ++j)
    {
      // Upsample
      if (j > 0) sample = 0.;
      mUpsample.Process(sample, mAntiAlias.Coeffs());
      sample = (double)mOversampling * mUpsample.Output();

      // Distortion
      if (WDL_DENORMAL_OR_ZERO_DOUBLE_AGGRESSIVE(&sample))
        sample = 0.;
      else
        sample = mGain * (fast_tanh(mDC + mDrive * sample) - mDistortedDC);

      // Downsample
      mDownsample.Process(sample, mAntiAlias.Coeffs());
      if (j == 0) output = mDownsample.Output();
    }

    outputs[0][i] = outputs[1][i] = output;
  }
}
The design choices observed:

- keep it simple (this is just an example)

- oversampling filter should preserve wave shape (that's why it is a linear-phase filter, https://en.wikipedia.org/wiki/Bessel_filter )

- save cpu cycles, make it efficient (that's why it is a bessel filter instead of being a windowed sinc executed with convolution)

Now a question: Does the bessel filter have good enough roll-off rate and is it good enough to prevent aliasing in this case? Under what conditions is this design appropriate? The answers could be found by testing of course, instead of just speculating. That would involve measurement. One could proceed by:

- quantify the problem before solving it ( make a graph of the aliasing artifacts)

- try different approaches. compare with a windowed sinc, for example. or try linear interpolation instead of zero padding.

- try to observe possible design trade-offs and decide which one is better under what conditions

- is it really necessary to preserve wave shape? what would the result be, if we had used a chebyshev filter?

- subjectively compare solutions. (is the remaining aliasing distortion actually audible? does the idea of preserving the wave shape actually have an advantage over alternatives?)

- should we leave the decision to the user?
~stratum~

Post

stratum wrote:
The theory says so, but in reality music processing is nonlinear and so much variant :P I'd drop that part as it has no use.
It has use in putting things in proper perspective. Much confusion I have observed in KVR threads arise from not separating theory from practice. Somebody asks a filter design question then somebody else goes on to explain what's being done in a state of the art EQ plugin without explaining design concerns and what is being accomplished and why. Then, only the ones who already know understand what's being explained:-) What a rocket science. I guess the OP was confused for similar reasons in spite of the fact that the subject matter is very simple.
Come on. Where is it written that audio algorithms have to be LTI in theory or otherwise.

As for the "rocket science" I recall the thread you're refering to. The topic was on moving from s to z doimain and I offered a simple to apply technique in addition to BLT and MZT which were also discussed. It's strange you'd bring that up to defend an erroneous statement. It comes across as a clumsy deflection IMHO.

OK. I wasn't going to bite, but I did :)

Post Reply

Return to “DSP and Plugin Development”