As promised, here’s our windowed sinc calculator for building a 2x oversampling filter:
Factor
Length
Rejection
Gain
Notes:
- Use the Tab or Enter keys to effect changes (most browsers), or press Calculate.
- The frequency axis is in multiples of the Nyquist frequency.
- This page is designed specifically to generate and view filters for the current sample rate doubling tutorial, hence the view of 0.50 of the original sample rate with folded frequency components and default gain value. However, you can use it to generate an arbitrary windowed-sinc lowpass. (The folded frequency components in the lower view are there to help you keep an eye on the results—they are not alias components at this point.)
- For example, a 2x upsampling filter: Set Rejection to the stop-band rejection is dB. Set Length to the number of taps you want to use (more taps for a steeper filter, but higher processing cost). Set Factor to a value less than 0.5, but as close to 0.5 as possible in order to get the maxmimum bandwidth while avoiding foldback (aliasing). Set Gain to 2.
- Tip: You can copy and paste the coefficients into a text file, and save with an extension of “.csv” if you want to read the values into a spreadsheet for further manipulation.
How and where do we use all these values?I want to know, as im still new to DSP and such things
Good point—I should do an implementation tutorial for beginners some time. For now, do a web search for information on FIR filters. Implementation is fairly easy—the most difficult part is making sure you have access to the last n samples, where n is the number of coefficients. Then for every new (filtered) output sample, you need to multiply each coefficient by its corresponding sample, and sum that into the total. The basic operation is easy—a single FOR loop, fundamentally—but most of the code work is in buffering the input, and the logic to wrap around the buffer when iterating the filter. Because those details are so implementation-dependent, it’s not simple to show a small code snippet that you can actually use, especially without making assumptions about the reader’s programming experience and language of choice.
What keeps confusing me with upsampling and downsampling: do you need full (or say 80 dB) rejection at the nyquist (=half the) frequency of original or of destination sample rate?
When upsampling, raising the sample rate exposes the aliased copies of the audio of interest—you need to clear the aliases by lowpass filtering. For instance, if you start with 0-20 kHz audio sampled at 48 kHz, and up the sample rate to 96 kHz by inserting a zero between each sample, you need to lowpass filter with the cutoff around 20 kHz. Think of it as preserving the audio you recorded, and while removing the aliases. Take a look at Amp simulation oversampling.
When downsampling, you need to first clear everything above the band of interest, so you’d filter with a cutoff around 20 kHz (always something less than half the sample rate) before reducing the rate.
Okay I understand from this that as a general rule the passband needs to stay at least under half of the lowest of both frequencies.
upsampling 20 kHz to 40 kHz: stay under 10 kHz
downsampling 96 kHz to 48 kHz: stay under 24 kHz
Stricter rules can apply depending on the band of interest.
Also, with upsampling using windowed sinc, is it allowed to keep the original samples or do you need to replace them by filtered samples?
It depends…obviously, it needs to be an odd-order filter, with 1 for the center tap. A half-band filter (for 2x conversion) ensures the other taps won’t contribute, but otherwise it depends on frequency content of the signal, and the filter characteristics—if any of the regional signal is filtered, it changes the amplitude.
I would like to understand it from a numeric point-of-view. I would like to know if my understanding is correct.
Sorry it became such a long story…
Suppose we want to upsample our signal by a factor 2.
We insert null-samples after each original sample. The intermediate signal is zero where n is odd (with n=0..numSamples-1)
We will compensate the loss of energy with a gain of 2 while filtering.
We start with an odd ordered filter:
factor=0.5 taps=41 reject=90 gain=2
The resulting coefficients are zero where m is even (with m = 0..taps-1) except the center coefficient being 1.0. (how convenient!)
I believe the latter only holds for particular parameters (factor == 0.5)?
Convoluting the intermediate signal will yield a kind of moire effect:
Where the null-coefficients and null-samples nicely overlap, a new sample is generated in a normal FIR manner.
This happens for every even sample of the resulting signal.
When the null-coefficients and null-samples don’t overlap, all multiplications yield zero, except for the center tap: this “weighted average” yields an original sample.
This happens for every odd sample of the resulting signal.
So when applying this filter, the original samples were left untouched.
So for efficiency reasons you might as well apply this filter with the null-coefficients and center coefficient left out and apply that to the original signal directly.
The resulting samples are then to be interleaved between the original signal samples, after shifting them half the number of taps.
Yes, half-band filters are useful in sample rate conversion. Keep in mind that the cutoff point is down only 3 dB, so you have potential aliasing, but that can be accounted for in multistage conversion.
What window is that? Does the above implementation use Kaiser window?
Yes, kaiser.
I implemented the same thing but I’m getting different coefficients for same factor, length and rejection. How are you calculating your beta values? Are you using Kaiser formula? i.e. for 90dB attenuation is your beta = 0.1102*(90-8.7) = 8.95926?
ah, I was scaling the factor incorrectly in my sinc function (was multiplying by 2). The coefficients now look the same. I’ll do some more tests.
As a side note, I would like to thank you for this great blog. Been visiting this site regularly past few years. A lot of my Audio DSP questions were answered here. So thank you!
Great! I original drew from “Rabiner and Gold” for the Kaiser, many years ago, a great fit for audio.