Sample rate conversion: down

In doubling the sample rate, we inserted zeros between existing samples, then used a lowpass filter to remove the resulting alias in the audio band. To resample at half the current rate, we use a lowpass filter to remove audio above half of the new audio band, which would otherwise alias, then remove every other sample.

Here’s an example: First, I created a linear sweep of a sine wave, from 0 Hz to 44 kHz over 4 seconds, at a sample rate of 88.2 kHz. This audio clip is the result of downsampling by discarding every other sample without filtering first, and playing at a sample rate of 44.1 kHz; note how the sweep folds back and heads downward in the second half—aliasing:

Rising sine sweep, downsampled without filtering
Audio Player

This time, we do it right; the clip is filtered first, removing everything above 22 kHz, then every other sample is discarded, and played back at 44.1 kHz:

Rising sine sweep, downsampled after filtering
Audio Player

The filter was created with our windowed-sinc calculator, set to remove signal above 0.25 of the 88.2 kHz sample rate. Since we intend to drop every other sample after filtering, we can step iterations of the filter by two, and calculate only the samples we’ll keep. We use each of the coefficients on consecutive samples of the signal, but advance the input index by two instead of one before calculating the next output sample.

The practice of dropping samples is called “decimation”. The term means to remove one in every ten—a gruesome practice employed by the Roman army. In signal processing, it’s used to mean the removal of an arbitrary number of samples in a group. For instance, here we are decimating by a factor of two when we drop every other sample. Decimating by a factor of four would mean retaining one sample, dropping three, and repeating the process for all samples.

Note: The above sound examples are mp3 format, for improved browser compatibility. If you want to take a look at the files in a sound editor, you’ll get a more accurate view with the original uncompressed files (right-click and “save as”): non-filtered, non-filtered.

Posted in Aliasing, Digital Audio, Filters, Sample Rate Conversion | Leave a comment

A closer look at upsampling filters

100
-1.00
0
50
100
150
200
250
-1.00
-0.50
0.00
0.50
1.00
0.00
-150
0.00
0.50
1.00
1.50
2.00
-150
-100
-50
0
Interpolation type:
 Show impulse response

In this demonstration, we generate a sine wave sweep from low in the audio band to near the Nyquist Frequency, which is half the sample rate. You can view it in the upper chart.

Next, we upsample by a factor of two, by inserting a zero between each sample, and view the frequency response using various forms of interpolation in the lower chart:

  • None is no interpolation—you can see the sine samples alternating with zero in the upper chart, and a complete lack of stop-band rejection in the frequency response. (Note that inserting zeros lowers the average signal level by half, or 6dB, as you can see in the lower chart.)
  • Zero-order hold repeats the previous sample, in place of the zeros. This is the same as convolving the upsampled signal with filter coefficients { 1.0, 1.0 }.
  • Linear replaces zero samples with the average of two adjacent original samples. This is the same as convolving the upsampled signal with { 0.5, 1.0, 0.5 }.
  • Sinc 1 uses coefficients generated from a Kaiser-windowed sinc set to 0.5, or “half-band”. Half-band filters have the characteristic that every other coefficient is zero, making them much more efficient to implement, but at the expensive of poor aliasing characteristics near the Nyquist frequency. They are typically used in cases where subsequent steps, such as in multi-rate conversion, will clean up any response problems. This one uses 31 coefficients, 15 of which are zero and can be eliminated.
  • Sinc 2 is a Kaiser-windowed sinc with a lower cutoff setting to minimize aliasing (also 31 coefficients).
  • Sinc 3 is similar, but has better filter characteristics, due to using more coefficients (71).

Posted in Aliasing, Digital Audio, Filters, FIR Filters, Impulse Response, Sample Rate Conversion, Widgets | 1 Comment

Sample rate conversion: up

Once we have a suitable set of FIR filter coefficients from our windowed sinc calculator, it’s time to apply them.

Again, our recipe for doubling the sample rate:

1) Insert a zero between existing samples. (This is the upsampling step, doubling the sample rate and doubling the usable audio bandwidth, but leaving an alias of the original signal in the upper half of the widened audio band.)

2) Remove the aliased image with a lowpass filter. (You can also view this as interpolating between existing samples in the time domain.)

Removing needless calculations

When we implement these two steps, using our FIR filter, we see that every other multiply is by zero, and can be skipped. So, we can omit the zero-insertion step altogether, and just alternate between using the odd and even coefficients on our exiting samples.

You can either index through the coefficients table by steps of two, or split the table into two tables—off and even. This is often called a “polyphase” implementation.

Our 2x oversampling task comes down to this:

1) Buffer enough of the input samples to allow for room to run the FIR filter over the required number of samples.

2) For the current sample, and each new sample that comes in, generate two new samples for the output buffer by applying the odd (ordinal—first, third, fifth…) samples, then the even.

A sketch of the code

In C, we’d do something like this for each new input sample, creating two new output samples:

double coefs[] = { -0.000649, -0.001047, 0.003211, 0.010679,
  0.005956, -0.022766, -0.049404, -0.013106, 0.116023, 0.276227,
  0.349750, 0.276227, 0.116023, -0.013106, -0.049405, -0.022766,
  0.005956, 0.010680, 0.003211, -0.001047, -0.000649 };
long coefsLen = sizeof(coefs) / sizeof(*coefs);   // count 'em

for (n = 0; n <= 1; n++) {      // twice: starting at 1st, then 2nd
  index = indexOfLastSample;    // start at the most recent sample
  double outVal = 0;
  for (m = n; m < coefsLen; m += 2)        // for every other coef
    outVal += inBuf[index--] * coefs[m];   // multiply accumulate

  WriteOutput(outVal);	        // output the new sample
}

Of course, you must ensure that inBuf contains enough samples ((coefLen + 1) / 2). Most likely, you’ll use a circular buffer, so you’ll need to test index for less than zero and wrap around when needed. For instance:

for (m = n; m < coefsLen; m += 2) {    // for every other coef
  outVal += inBuf[index] * coefs[m];   // multiply accumulate
  if (--index < 0)
    index += inBufLength;              // wrap buffer index
}

This example uses a very small filter length (21), and the number of digits in each have been reduced by rounding, in order to allow for a smaller listing, so this is not a high-quality example. But you can substitute a filter of any length for high-quality results.

Additional notes on our filter implementation

When upsampling, signal energy gets distributed over the aliased images, so we must compensate to maintain the signal gain in the region of interest. This means we’ll need a gain of two when doubling the sample rate, and it’s convenient to build it into the coefficients. (Another way of looking at the gain loss is to observe that we compensated for DC gain in the coefficients, but recall that we are only using every other coefficient for each output sample—we need to double it to get back to unity gain.)

Our coefficient calculator always generates an odd number of coefficients. The reason is that we’d like to use an odd-length filter is that the center aligns with a sample exactly, giving us an integer number of samples of delay at the output. We could just as easily generate a windowed sinc that centers between samples for an even number of coefficients, but if we want to align the audio with other samples later, it’s easier to delay in whole numbers of samples than fractions.

The coefficients are always symmetrical, so you don’t need to store the entire table, and you can also take advantage of that symmetry under certain conditions. For instance, in cases where addition is less costly than multiplication, you can add corresponding samples that share the same coefficient value, and save a multiply. This was once a significant optimization, but is usually not an issue with modern processors.

The example shown is written for clarity first, with reasonable performance. You could improve it by using modulo indexing on the input buffer (use a power-of-two sized buffer and AND the index with a mask instead of testing it and wrapping it). You could use a single FOR loop, stepping through the coefficients by one and alternating between output samples. In C++, you could use template meta programming to have the compiler unroll the loops altogether. DSP chips typically combine no-cost modulo indexing with single cycle multiply-accumulate with dual data fetching and zero-cycle looping to result in a cost of one cycle per coefficient.

Depending on quality requirements, we might need a very long list of coefficients. Long convolutions are implemented more efficiently as multiplication in the frequency domain—you could use the FFT to implement the filter.

Posted in Aliasing, Convolution, Digital Audio, Filters, FIR Filters, Sample Rate Conversion | 7 Comments

Building a windowed sinc filter

As promised, here’s our windowed sinc calculator for building a 2x oversampling filter:

100
0.00
0
50
100
150
0.00
0.25
0.50
0.75
1.00
0.00
-150
0.00
0.50
1.00
1.50
2.00
-150
-100
-50
0
0.00
-150
0.00
0.10
0.20
0.30
0.40
0.50
-150
-100
-50
0
 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.

Posted in Digital Audio, Filters, FIR Filters, Impulse Response, Sample Rate Conversion, Widgets | 14 Comments

Towards practical resampling

In a previous article, we looked at sample rate conversion in the frequency domain. Let’s take a quick second look in the time domain as reinforcement of principles behind sample rate conversion, before developing a practical rate convertor.

In an ideal digital to analog convertor, we output a pulse train in which each pulse’s amplitude corresponds to a sample value. The pulse train is processed by a lowpass “reconstruction” filter, to arrive at our smooth analog signal output. Theoretically, we want a perfect impulse into a perfect “brick wall” lowpass filter—one with no phase shift.

A perfect impulse into our perfect lowpass filter would give an output response of the sinc function; here is the “normalized” sinc function:

sin (π * x) / (π * x) { or 1, for x = 0 }

Here’s what it looks like, as does the output of our perfect filter when pinged by a perfect unit impulse (the curve tails off infinitely in both directions):

When we feed the filter with our impulse train, representing output samples, the individually responses for each impulse add together to make the analog output waveform. Here’s an example with three non-zero samples:

From this it should be apparent how to convert samples rates—sum those individual impulse responses for every new point that you need to determine. For instance, if you want to double the sample rate, simply calculate the points on that curve that are half-way between existing samples.

Need further convincing? Before moving on, let’s take a look at a digital square wave (-1,-1,-1,-1,+1,+1,+1,+1…), and sum the individual sinc impulse responses:

You probably recognize that as the look of a bandlimited square wave, so it looks like we’re on the right track.

Making it practical

The problem with our filter is in its perfection. Even if we could make this ideal filter from real-world components, we would wait forever for the output—the output would build slowly for an infinite amount of time until it peaked at a height corresponding to the input impulse, then die out over an infinite amount of time.

Fortunately, the sinc function gets smaller and smaller in each direction. We could let it run in both directions until the “lobes” got so small that they wouldn’t contribute to the quantized output, and truncate it from there. That’s still a long ways, which translates into a lot of output delay and a lot of calculations for the task we’re building up to. Fortunately, since the lobes are getting smaller and smaller, we can make a rough approximation by hastening their retreat with a window function that tapers the curve quicker. (Tapering gives better results than simply chopping off the ends—a rectangular window.)

Luckily for us, the difference between ideal and our tapered approximation is small, error-wise. This shouldn’t be surprising, since we know that real-world lowpass filters are far from perfect in cutoff slope, yet we find them very useful and audibly pleasing.

In addition to scaling the sinc function with the window, this is a good time to normalize the function for unity gain. The DC gain of the filter is the sum of the coefficients—this is true of any FIR filter. (This should be apparent, if you consider the output for the case of all input samples being 1.0.) The gain will vary depending on the filter settings, and be pretty close to the inverse of the factor used to calculate the sinc (for a filter with cutoff set to half the audio band, it will be about two, for instance). We simply divide each coefficient by the sum of the coefficients to achieve unity gain.

Putting the pieces together

Before continuing, here are some observations to keep in mind:

1) We chose the sinc function because it is the impulse response of a lowpass filter with an infinitely steep slope at cutoff (“brick wall”), and linear phase. (We may not always require linear phase, but in the general case, that’s what we want.)

2) We use a window function to convert our ideal filter into a practical one. It’s not the only way. We could trade off errors in a different way (the Park-McClellan algorithm, for instance). This article uses a windowed-sinc function because it’s a popular choice, and is easy to understand and implement.

There are many popular choices for window functions. Any of them give better results than simply truncating the sinc curve. The Kaiser window is an excellent choice for audio; it’s more complicated to calculate than most, but has the advantage of being able to set the level of tradeoff between stopband attenuation and sharpness of the cutoff easily. The cutoff steepness is dictated mainly by the number of side-lobes of the sinc response that we keep, hence the length of the filter. And because we’ve deviated from the perfect filter, we’ll need to set the cutoff below the ideal.

Here is what our normalized windowed sinc looks like, along with its components:

Coming next

Next up, we’ll have a have a windowed-sinc calculator that will help us compute coefficients for a high-quality sample rate convertor.

Posted in Digital Audio, Filters, FIR Filters, Impulse Response, Sample Rate Conversion | 7 Comments

The sound of dither

Dithering is about spreading errors out, so that they aren’t related to the sampled signal. A constant background hiss is easier to ignore than tones that change depending on signal frequencies and amplitude.

Here’s a fixed-frequency sine wave, truncated to seven bits:

7-bit sine tone, no dither
Audio Player

Here’s the same signal dithered, truncated to seven bits:

7-bit sine tone, dithered
Audio Player

Notice the problems with the non-dithered example, especially in the tail as the signal fades out and fewer bits are used.

Here’s a swept sine wave, first simply truncated to seven bits:

7-bit sine sweep, no dither
Audio Player


And again dithered:

7-bit sine sweep, dithered
Audio Player


Note the aliased frequencies in the non-dithered sweep, and how the tail sounds like a square wave as it fades out.

In both cases, the dithered signal maintains the sine tone throughout, at the expensive of added “hiss”.

There are things we can do to make the hiss less obtrusive, but of course at the more normal 16-bit sample size, the dither-noise level is far lower than these extreme examples.

Read the EarLevel article on dither.

Posted in Digital Audio, Dither | 7 Comments

Blog birth

Sometimes I get email asking a question—a question that I think others might have. Sometimes I’d like to write some helpful notes, but maybe it doesn’t warrant a full article. Or sometimes I’d like to address a subject in pieces. So, I’m going to try a blog. I won’t write every day, and no promise to be regular about writing. But it will be a place where I can address these things in bite-sized pieces. In addition, I’ve moved my older web articles to the blog to make it easier to find things.

Posted in Uncategorized | 3 Comments

Sample rate conversion

Here we explain how sample rate conversion works. As an essential prerequisite, you must understand the principals of sampling. Even if you understand sampling already, read our explanation of the process here. The viewpoint and terms used there are mirrored here, and are key to this explanation. Read it now—take a quick look at to refresh your memory if you’ve read it before—then come back here for the rest.

Upsampling

Sometimes we need to change the sample rate after the fact. We might need to match converter hardware running at a different rate, or we might want to increase the frequency headroom; for instance, frequency modulation, pitch shift, and distortion algorithms can add higher frequency components that might otherwise alias into the passband if we don’t raise the ceiling.

Let’s consider the common case of increasing the sample rate by a factor of two—maybe we have some music recorded at 48 kHz, and want to combine it with tracks recorded at 96 kHz, with 96 kHz playback. This means we need to generate a new sample between each existing sample. One way might be to offset the new sample by half the difference of the two existing samples surrounding it. This is linear interpolation—essentially a poor low-pass filter, and the results aren’t very good, leaving us with a reduced frequency response and aliasing. There are better ways to interpolate the new sample points, but there is one that is essentially perfect, creating no new frequency components, and not changing the frequency response. We can do this because the original signal was band-limited to begin with, so we know the characteristics of what lies between the sampled points—it’s essentially the shape dictated by the original low pass filter we used in the sampling process. By reversing the process, we can get the original band-limited signal back, and resample it at twice the original rate—having lost nothing.

We don’t need to know the exact characteristics of the original low-pass—it was certainly one that was of high enough quality to get the job done (or we’d already been suffering from the resulting aliasing), so we just use another. The obvious approach is to convert back to analog, letting the low pass filter reconstruct the continuous signal, then re-sample it at twice the original rate.

Converting to analog and back to digital seems a waste—we’re already digital and would like to avoid running through hardware—and filters can be done mathematically in the digital domain. Looking at the diagram, we see that we don’t need two filters. The one with the higher cut-off frequency doesn’t do anything interesting, since the other filter removes those frequencies anyway, so we discard it and keep the lower filter.

The filter is a linear process, and we suspect that we can move it to one side, putting the D/A and A/D components next to each other, where they cancel except for the change in sample rate. Then, conceptually, we just need to double the number of samples to upsample by a factor of two, and low-pass filter. But what does that mean—should we simply repeat each sample? Average the surrounding samples? And does it make a difference whether we filter before or after? We suspect that we need to filter after the rate change, since running a full-band low-pass filter doesn’t really do anything.

We can see how to double the samples and what the filter does by looking back at how we sampled the signal in the first place. Recall that the existing samples represent the pulse-amplitude modulated result of the analog to digital conversion stage. Let’s look at that signal again:

With that in mind, the in-between samples are obvious—they are all the value zero. The result of inserting a zero between each of our existing samples is that the signal we have doesn’t change at all—and therefore neither does the spectrum—but the sample rate does. Here’s our spectrum again, before inserting zeros:

Here’s what we have after inserting a zero between each sample:

Essentially, we’ve doubled the number of samples, doubling our available bandwidth, but in doing so we’ve revealed an aliased image in the widened passband. Now it’s apparent why we need the low-pass filter—to remove the alias from the passband:

That’s it—to double the sample rate, we insert a zero between each sample, and low-pass filter to clear the extended part of the audio band. Any low-pass filter will do, as long as you pick one steep enough to get the job done, removing the aliased copy without removing much of the existing signal band. Most often, a linear phase FIR filter is used—performance is good at the relatively high cut-off frequency, phase is maintained, and we have good control over its characteristics.

Downsampling

The process of reducing the sample rate—downsampling—is similar, except we low-pass filter first, to reduce the bandwidth, then discard samples. The filter stage is essential, since the signal will alias if we try to fit it into a narrower band without removing the portion that can’t be encoded at the lower rate. So, we set the filter cut-off to half the new, lower sample rate, then simply discard every other sample for a 2:1 downsample ratio. (Yes, the result will be slightly different depending on whether you discard the odd samples or even ones. And no, it doesn’t matter, just as the exact sampling phase didn’t matter when you converted from analog to digital in the first place.)

Conclusion

We’ve gone through a lot to explain this, but if you understand the reasons, it’s easy to see what to do in other situation. For instance, if we need to upsample by a factor of four, we look at our pulse-amplitude modulated signal and note that there is nothing but a zero level between our existing impulses, so we insert three zeros between our existing samples. Then low-pass filter the result, with the frequency cut-off set to include our original frequency band and block everything above it to remove the aliased copies from the new passband.

There are some added wrinkles. For larger conversion ratios, we do the conversion in multiple smaller steps and exploit some optimizations with less computation than doing a single large ratio conversion. For non-integer ratios, such as conversion from 44.1 kHz to 48 kHz, most text books suggest a combination of upsampling and downsample as a ratio of integers (upsampling by a factor of 160 and downsampling by a factor of 147 in this case), but it can also be done in a single step, fractionally.

Posted in Digital Audio, Sample Rate Conversion | 16 Comments

Sampling in-depth

Here we lay the foundation. We’ll look at analog to digital conversion, and we’ll look at the spectrum of the resulting digital signal. We’ll use that knowledge to help understand the conversion process back to analog. Though we can build real-world converters that work as described, we’re not building practical converters here; we’re interested in the mathematical concepts involved and their relationships to digital signal processing.

Analog to digital conversion

The sampling theorem says that we can describe, uniquely, a continuous (analog) signal with evenly-spaced discrete (digital) samples, as long as the sampling rate is greater than twice the highest frequency component in the continuous signal. To ensure that we don’t violate that condition, we preface the analog to digital conversion with a low pass filter, set to pass frequencies below half the sample rate, and block those above:

The sampling process—basically taking repeated measurements as a fixed interval—can be viewed in a number of ways; here’s one that can help us understand some important aspects of sampling:

The input signal, after filtering to ensure our bandwidth condition, is modulated (multiplied) by a pulse train of unit amplitude. The result is a pulse-amplitude modulated signal. We measure the height of each modulated pulse, and store the numerical values as our samples.

The spectrum of a sampled signal

While our original signal can be anything, we must limit the frequency spectrum of the signal we sample to half the sampling rate—again, we ensure this condition by placing a low-pass filter before the sampling stage. So, we can represent the spectral limits of the signal by showing the response curve of the low-pass filter:

Here we’re showing positive and negative frequencies, in order to make the following more obvious.

The spectrum of the impulse train we’re using to multiply the input signal looks like this:

That is, the spectrum of an impulse train in time is an impulse train in frequency. In the time domain, the impulses are spaced at multiples of the sampling period, and in the frequency domain at multiples of the sampling frequency.

The result of the multiplication in the time domain is a convolution in the frequency domain—the result in the frequency domain is that we have spectral reflections of the original signal, centered on multiples of the sampling rate:

We don’t mind the reflections, since they stay out of the way of the signal band we care about, but if we had used a poorer low-pass filter or set its frequency too high, the reflections would overlap into the band we’re interested in—this is called aliasing (from here on we’ll look at the positive frequencies only, to save space, noting that the negative side is just a reflection):


A consequence of aliasing is that frequencies that exceed half the sample rate reflect back into our band of interest. For instance, a sine wave that sweeps in frequency above half the sample rate will seem to reverse and turn back down. High harmonics that cross over will be inverted, imparting an inharmonic tone to the sound. Once we let this happen, there is no way to tell the good from the bad, so we must minimize aliasing by using acceptable filters.

Now that we understand what we’ve done to the signal by sampling it, we can look at the process of converting the signal back to a continuous signal.

Digital to analog conversion

To convert from samples to the continuous domain, we perform what is pretty much the inverse process. In principal, we first turn the numbers into a pulse-amplitude modulated signal. This signal has the information we need, but carries some extra that we don’t want—images of our signal, aliased copies that appear at multiples of the sample rate. So, we strip off the high-frequency clones with a low-pass filter. Effectively, this smoothes the pulse train into the signal we desire.

Note that the digital to analog conversion is similar to our analog to digital conversion, almost in reverse, except that in the case of converting from analog, the low-pass filter is precautionary—to guarantee we limit the bandwidth to avoid aliasing—while in the conversion from digital, the filter plays an integral role in reconstructing the signal. For that reason, the latter is often called the reconstruction filter.

Posted in Digital Audio, Sampling Theory | 2 Comments

The bilinear z transform

The bilinear transform is the most popular method of converting analog filter prototypes in the s domain to the z domain so we can implement them as digital filters. The reason we are interested in these s domain filters is that analog filter theory has been around longer than digital filter theory, so we have available to us a number of popular and useful filters in the s domain. The standard biquads used heavily in audio processing are direct implementations from the s domain using the bilinear transform.

The theory of the bilinear transform is well documented in DSP texts and on the web, so rather than spend time going into the theory, we’ll cut to the chase and show how to do the transform, using a second order lowpass filter as an example.

The s domain transfer function of a second order lowpass filter is

To move to the z domain, we need to substitute for s in terms of z. At the same time, we “pre-warp” the response using the tan function in order to wrap the infinite s plane onto the circular z plane. The combined substitution is

Here’s our z domain transfer function after substituting for s:

In order to solve for our filter coefficients, we need to get the equation into the form of a second order polynomial in the numerator (the zeros) and another second order polynomial in the denominator (the poles). That is, we need it to look something like this:

It helps to use a math package to cut down on some of the tedious work. If we take the right side of the equation and ask MathCad to “simplify”, it gives

The first thing we see is that there are too many Q’s, so divide the top and bottom by Q, resulting in

Now combine terms in the numerator and rearrange in descending powers of z; do the same for the denominator:

The z operator means delay, and its power tell us how many samples. Positive powers of z are in the future, and negative powers are in the past. Our filter can’t see into the future (we call such filters “non-causal”), so we need to reduce the powers of z to zero and below (to make it causal). To do this we multiply the numerator and denominator by , which subtracts two from each power of z, and gives us our final form:

Our coefficients are now evident:

Because the b0 coefficient is associated with y[n], the filter output, we divide everything by b0 to normalize the filter. Here we also note some convenient relationships between the “a” coefficients:

As a further efficiency, you can compute the common numerator term once and use it where needed. When calculating the coefficients, Q is the filter Q value (for a Butterworth lowpass, where the passband is flat with no corner peaking, use 0.7071, which is the reciprocal of the square root of two). Recall that we defined K as

where Fc is the filter corner frequency you want, and Fs is the sample rate.

Posted in Digital Audio, Filters, IIR Filters | 29 Comments