<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>EarLevel Engineering</title>
	<atom:link href="http://www.earlevel.com/main/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.earlevel.com/main</link>
	<description>Practical digital audio signal processing</description>
	<lastBuildDate>Mon, 05 Dec 2011 18:23:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Biquad formulas</title>
		<link>http://www.earlevel.com/main/2011/01/02/biquad-formulas/</link>
		<comments>http://www.earlevel.com/main/2011/01/02/biquad-formulas/#comments</comments>
		<pubDate>Sun, 02 Jan 2011 22:39:10 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[Filters]]></category>
		<category><![CDATA[IIR Filters]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=88</guid>
		<description><![CDATA[For fixed filters, we can plug biquad coefficients into our programs. But often, we need to calculate them on the fly, to user settings or changes in sample rate. As a companion to the biquad calculator, here are the formulas &#8230; <a href="http://www.earlevel.com/main/2011/01/02/biquad-formulas/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For fixed filters, we can plug biquad coefficients into our programs. But often, we need to calculate them on the fly, to user settings or changes in sample rate. As a companion to the biquad <a href="2010/12/20/biquad-calculator">calculator</a>, here are the formulas used, in JavaScript; refer to our article on <a href="2003/02/28/biquads">biquads</a> for implementation diagrams:</p>
<pre>
function calcBiquad(type, Fc, Fs, Q, peakGain) {
    var a0,a1,a2,b1,b2,norm;

    var V = Math.pow(10, Math.abs(peakGain) / 20);
    var K = Math.tan(Math.PI * Fc / Fs);
    switch (type) {
        case "lowpass":
            norm = 1 / (1 + K / Q + K * K);
            a0 = K * K * norm;
            a1 = 2 * a0;
            a2 = a0;
            b1 = 2 * (K * K - 1) * norm;
            b2 = (1 - K / Q + K * K) * norm;
            break;

        case "highpass":
            norm = 1 / (1 + K / Q + K * K);
            a0 = 1 * norm;
            a1 = -2 * a0;
            a2 = a0;
            b1 = 2 * (K * K - 1) * norm;
            b2 = (1 - K / Q + K * K) * norm;
            break;

        case "bandpass":
            norm = 1 / (1 + K / Q + K * K);
            a0 = K / Q * norm;
            a1 = 0;
            a2 = -a0;
            b1 = 2 * (K * K - 1) * norm;
            b2 = (1 - K / Q + K * K) * norm;
            break;

        case "notch":
            norm = 1 / (1 + K / Q + K * K);
            a0 = (1 + K * K) * norm;
            a1 = 2 * (K * K - 1) * norm;
            a2 = a0;
            b1 = a1;
            b2 = (1 - K / Q + K * K) * norm;
            break;

        case "peak":
            if (peakGain >= 0) {    // boost
                norm = 1 / (1 + 1/Q * K + K * K);
                a0 = (1 + V/Q * K + K * K) * norm;
                a1 = 2 * (K * K - 1) * norm;
                a2 = (1 - V/Q * K + K * K) * norm;
                b1 = a1;
                b2 = (1 - 1/Q * K + K * K) * norm;
            }
            else {    // cut
                norm = 1 / (1 + V/Q * K + K * K);
                a0 = (1 + 1/Q * K + K * K) * norm;
                a1 = 2 * (K * K - 1) * norm;
                a2 = (1 - 1/Q * K + K * K) * norm;
                b1 = a1;
                b2 = (1 - V/Q * K + K * K) * norm;
            }
            break;
        case "lowShelf":
            if (peakGain >= 0) {    // boost
                norm = 1 / (1 + Math.SQRT2 * K + K * K);
                a0 = (1 + Math.sqrt(2*V) * K + V * K * K) * norm;
                a1 = 2 * (V * K * K - 1) * norm;
                a2 = (1 - Math.sqrt(2*V) * K + V * K * K) * norm;
                b1 = 2 * (K * K - 1) * norm;
                b2 = (1 - Math.SQRT2 * K + K * K) * norm;
            }
            else {    // cut
                norm = 1 / (1 + Math.sqrt(2*V) * K + V * K * K);
                a0 = (1 + Math.SQRT2 * K + K * K) * norm;
                a1 = 2 * (K * K - 1) * norm;
                a2 = (1 - Math.SQRT2 * K + K * K) * norm;
                b1 = 2 * (V * K * K - 1) * norm;
                b2 = (1 - Math.sqrt(2*V) * K + V * K * K) * norm;
            }
            break;
        case "highShelf":
            if (peakGain >= 0) {    // boost
                norm = 1 / (1 + Math.SQRT2 * K + K * K);
                a0 = (V + Math.sqrt(2*V) * K + K * K) * norm;
                a1 = 2 * (K * K - V) * norm;
                a2 = (V - Math.sqrt(2*V) * K + K * K) * norm;
                b1 = 2 * (K * K - 1) * norm;
                b2 = (1 - Math.SQRT2 * K + K * K) * norm;
            }
            else {    // cut
                norm = 1 / (V + Math.sqrt(2*V) * K + K * K);
                a0 = (1 + Math.SQRT2 * K + K * K) * norm;
                a1 = 2 * (K * K - 1) * norm;
                a2 = (1 - Math.SQRT2 * K + K * K) * norm;
                norm = 1 / (1 + Math.sqrt(2/V) * K + K * K / V);
                b1 = 2 * (K * K / V - 1) * norm;
                b2 = (1 - Math.sqrt(2/V) * K + K * K / V) * norm;
            }
            break;
    }

    return [ a0, a1, a2, b1, b2 ];
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2011/01/02/biquad-formulas/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>A biquad calculator</title>
		<link>http://www.earlevel.com/main/2010/12/20/biquad-calculator/</link>
		<comments>http://www.earlevel.com/main/2010/12/20/biquad-calculator/#comments</comments>
		<pubDate>Tue, 21 Dec 2010 03:14:50 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[Filters]]></category>
		<category><![CDATA[IIR Filters]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=79</guid>
		<description><![CDATA[Something useful: a biquad filter coefficient calculator... <a href="http://www.earlevel.com/main/2010/12/20/biquad-calculator/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div id="container1-20101220" style="width:600px; height:200px;"></div>
<form name=biquad_params>
<table style="background-color:#FFFFFF;border:0;margin:0;width:600px">
<tr>
<td style="vertical-align:top">Type:<br />
<select name=Type onchange="drawIt_biquad()">
<option value="lowpass">lowpass</option>
<option value="highpass">highpass</option>
<option value="bandpass">bandpass</option>
<option value="notch">notch</option>
<option value="peak">peak</option>
<option value="lowShelf">low shelf</option>
<option value="highShelf">high shelf</option>
</select>
<td style="vertical-align:top">
Plot:<br />
<select name=PlotType onchange="drawIt_biquad()">
<option value="linear">linear</option>
<option value="log">log</option>
</select>
</td>
</tr>
</table>
</form>
<table style="background-color:#FFFFFF;border:0;margin:0;width:600px">
<tr>
<td style="vertical-align:top;border:0">
<div>
<input id="biquad_Fs" name="Fs" value="44100" style="text-align:right;width:4em;margin: 0 6px 6px 0;" type="text" onchange="drawIt_biquad()" />Sample rate (Hz)</div>
<div>
<input id="biquad_Fc" name="Fc" value="10000" style="text-align:right;width:4em;margin: 0 6px 6px 0;" type="text" onchange="drawIt_biquad()" />Fc (Hz)</div>
<div>
<input id="biquad_Q" name="Q" value="0.7071" style="text-align:right;width:4em;margin: 0 6px 6px 0;" type="text" onchange="drawIt_biquad()" />Q</div>
<div>
<input id="biquad_Gain" name="Gain" value="6.0" style="text-align:right;width:4em;margin: 0 6px 6px 0;" type="text" onchange="drawIt_biquad()" />Gain (dB)</div>
</td>
<td style="vertical-align:bottom;border:0">
<textarea id="biquad_coefsList" rows="5" cols="32" readonly="readonly" ></textarea>
</td>
</tr>
</table>
<p><!--[if IE]><script language="javascript" type="text/javascript" src="/scripts/utils/flotr/lib/excanvas.js"></script><![endif]--><script type="text/javascript" src="/scripts/utils/flotr/lib/prototype.js"></script><script type="text/javascript" src="/scripts/utils/flotr/flotr.js"></script><script type="text/javascript" src="/scripts/widgets/20101220/biquads.js"></script></p>
<p>Something useful: a biquad filter coefficient calculator. Set the filter <em>Type</em>, the <em>Sample rate</em> (or 1.0 for &#8220;normalized&#8221; frequency), and cutoff of center frequency <em>Fc</em>. You can adjust <em>Q</em> for lowpass, highpass, bandpass, notch, and peak filters (use 0.7071&#8211;which is 1 divided by the square root of 2&#8211;for Butterworth lowpass and highpass), and <em>Gain</em> for peak and shelving filters. View the frequency response with a linear or log scale. You can copy and past the resulting coefficients into your programs.</p>
<p>More info on biquads in previous posts, <a href="/main/2003/02/28/biquads">here</a> and <a href="/main/2003/03/02/the-bilinear-z-transform">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2010/12/20/biquad-calculator/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Sample rate conversion: down</title>
		<link>http://www.earlevel.com/main/2010/12/20/sample-rate-conversion-down/</link>
		<comments>http://www.earlevel.com/main/2010/12/20/sample-rate-conversion-down/#comments</comments>
		<pubDate>Tue, 21 Dec 2010 01:49:20 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Aliasing]]></category>
		<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[Filters]]></category>
		<category><![CDATA[Sample Rate Conversion]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=82</guid>
		<description><![CDATA[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 &#8230; <a href="http://www.earlevel.com/main/2010/12/20/sample-rate-conversion-down/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.earlevel.com/main/2010/12/05/sample-rate-conversion-up">doubling</a> 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.</p>
<p>Here&#8217;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:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2010/12/lin-sweep-2x-down.mp3">Sine sweep, downsampled without filtering</a></p>
<p>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:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2010/12/lin-sweep-2x-down-sinc.mp3">Sine sweep, downsampled after filtering</a></p>
<p>The filter was created with our <a href="http://www.earlevel.com/main/2010/12/05/building-a-windowed-sinc-filter">windowed-sinc calculator</a>, 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&#8217;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.</p>
<p>The practice of dropping samples is called &#8220;decimation&#8221;. The term means to remove one in every ten—a gruesome practice employed by the Roman army. In signal processing, it&#8217;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.</p>
<p>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&#8217;ll get a more accurate view with the original uncompressed files (right-click and &#8220;save as&#8221;): <a href='http://www.earlevel.com/main/wp-content/uploads/2010/12/lin-sweep-2x-down.wav'>non-filtered</a>, <a href='http://www.earlevel.com/main/wp-content/uploads/2010/12/lin-sweep-2x-down-sinc.wav'>non-filtered</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2010/12/20/sample-rate-conversion-down/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2010/12/lin-sweep-2x-down-sinc.mp3" length="65315" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2010/12/lin-sweep-2x-down.mp3" length="65311" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2010/12/lin-sweep-2x-down.wav" length="352844" type="audio/wav" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2010/12/lin-sweep-2x-down-sinc.wav" length="352844" type="audio/wav" />
		</item>
		<item>
		<title>A closer look at upsampling filters</title>
		<link>http://www.earlevel.com/main/2010/12/11/a-closer-look-at-upsampling-filters/</link>
		<comments>http://www.earlevel.com/main/2010/12/11/a-closer-look-at-upsampling-filters/#comments</comments>
		<pubDate>Sat, 11 Dec 2010 20:32:49 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Aliasing]]></category>
		<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[FIR Filters]]></category>
		<category><![CDATA[Filters]]></category>
		<category><![CDATA[Impulse Response]]></category>
		<category><![CDATA[Sample Rate Conversion]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=73</guid>
		<description><![CDATA[Interpolation type: None Zero-order hold Linear Sinc 1 Sinc 2 Sinc 3 &#160;Show impulse response Sweep! In this demonstration, we generate a sine wave sweep from low in the audio band to near the Nyquist Frequency, which is half the &#8230; <a href="http://www.earlevel.com/main/2010/12/11/a-closer-look-at-upsampling-filters/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div id="container1-20101211" style="width:600px; height:200px;"></div>
<div id="container2-20101211" style="width:600px; height:200px;"></div>
<form name=params>
Interpolation type:<br />
<select name=irType onchange="doIRTypeSelect()" onmouseup="startSim();">
<option value="none">None</option>
<option value="zoh">Zero-order hold</option>
<option value="linear">Linear</option>
<option value="sinc 1">Sinc 1</option>
<option value="sinc 2" selected>Sinc 2</option>
<option value="sinc 3">Sinc 3</option>
</select>
<input type="checkbox" checked="checked" name=showIR onchange="doShowCheckbox()">&nbsp;Show impulse response<br />
</form>
<p><button onClick="startSim()">Sweep!</button></p>
<p>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.</p>
<p>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:</p>
<ul>
<li><strong>None</strong> 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.)
</li>
<li><strong>Zero-order hold</strong> 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 }.
</li>
<li><strong>Linear</strong> 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 }.
</li>
<li><strong>Sinc 1</strong> uses coefficients generated from a Kaiser-windowed sinc set to 0.5, or &#8220;half-band&#8221;. 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.
</li>
<li><strong>Sinc 2</strong> is a Kaiser-windowed sinc with a lower cutoff setting to minimize aliasing (also 31 coefficients).
</li>
<li><strong>Sinc 3</strong> is similar, but has better filter characteristics, due to using more coefficients (71).
</ul>
</li>
<p><!--[if IE]><script language="javascript" type="text/javascript" src="/scripts/utils/flotr/lib/excanvas.js"></script><![endif]--><script type="text/javascript" src="/scripts/utils/flotr/lib/prototype.js"></script><script type="text/javascript" src="/scripts/utils/flotr/flotr.js"></script><script type="text/javascript" src="/scripts/utils/dsputils.js"></script><script type="text/javascript" src="/scripts/widgets/20101211/sweepSim.js"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2010/12/11/a-closer-look-at-upsampling-filters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sample rate conversion: up</title>
		<link>http://www.earlevel.com/main/2010/12/05/sample-rate-conversion-up/</link>
		<comments>http://www.earlevel.com/main/2010/12/05/sample-rate-conversion-up/#comments</comments>
		<pubDate>Sun, 05 Dec 2010 21:51:54 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Aliasing]]></category>
		<category><![CDATA[Convolution]]></category>
		<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[FIR Filters]]></category>
		<category><![CDATA[Filters]]></category>
		<category><![CDATA[Sample Rate Conversion]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=65</guid>
		<description><![CDATA[Once we have a suitable set of FIR filter coefficients from our windowed sinc calculator, it&#8217;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, &#8230; <a href="http://www.earlevel.com/main/2010/12/05/sample-rate-conversion-up/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Once we have a suitable set of FIR filter coefficients from our <a href="http://www.earlevel.com/main/2010/12/05/building-a-windowed-sinc-filter">windowed sinc calculator</a>, it&#8217;s time to apply them.</p>
<p>Again, our recipe for doubling the sample rate:</p>
<p>1) <em>Insert a zero between existing samples.</em> (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.)</p>
<p>2) <em>Remove the aliased image with a lowpass filter.</em> (You can also view this as interpolating between existing samples in the time domain.)</p>
<h3>Removing needless calculations</h3>
<p>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.</p>
<p>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 &#8220;polyphase&#8221; implementation.</p>
<p>Our 2x oversampling task comes down to this:</p>
<p>1) Buffer enough of the input samples to allow for room to run the FIR filter over the required number of samples.</p>
<p>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.</p>
<h3>A sketch of the code</h3>
<p>In C, we&#8217;d do something like this for each new input sample, creating two new output samples:</p>
<pre>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 &lt;= 1; n++) {      // twice: starting at 1st, then 2nd
  index = indexOfLastSample;    // start at the most recent sample
  double outVal = 0;
  for (m = n; m &lt; coefsLen; m += 2)        // for every other coef
    outVal += inBuf[index--] * coefs[m];   // multiply accumulate

  WriteOutput(outVal);	        // output the new sample
}</pre>
<p>Of course, you must ensure that <code>inBuf</code> contains enough samples (<code>(coefLen + 1) / 2</code>). Most likely, you&#8217;ll use a circular buffer, so you&#8217;ll need to test <code>index</code> for less than zero and wrap around when needed. For instance:</p>
<pre>for (m = n; m &lt; coefsLen; m += 2) {    // for every other coef
  outVal += inBuf[index] * coefs[m];   // multiply accumulate
  if (--index &lt; 0)
    index += inBufLength;              // wrap buffer index
}</pre>
<p>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.</p>
<h3>Additional notes on our filter implementation</h3>
<p>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&#8217;ll need a gain of two when doubling the sample rate, and it&#8217;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.)</p>
<p>Our coefficient calculator always generates an odd number of coefficients. The reason is that we&#8217;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&#8217;s easier to delay in whole numbers of samples than fractions.</p>
<p>The coefficients are always symmetrical, so you don&#8217;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.</p>
<p>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.</p>
<p>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.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2010/12/05/sample-rate-conversion-up/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Building a windowed sinc filter</title>
		<link>http://www.earlevel.com/main/2010/12/05/building-a-windowed-sinc-filter/</link>
		<comments>http://www.earlevel.com/main/2010/12/05/building-a-windowed-sinc-filter/#comments</comments>
		<pubDate>Sun, 05 Dec 2010 20:06:53 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[FIR Filters]]></category>
		<category><![CDATA[Filters]]></category>
		<category><![CDATA[Impulse Response]]></category>
		<category><![CDATA[Sample Rate Conversion]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=67</guid>
		<description><![CDATA[As promised, here&#8217;s our windowed sinc calculator for building a 2x oversampling filter: &#160;Factor &#160;Length &#160;Rejection &#160;Gain Notes: Use the Tab or Enter keys to effect changes (most browsers), or press Calculate. The frequency axis is in multiples of the &#8230; <a href="http://www.earlevel.com/main/2010/12/05/building-a-windowed-sinc-filter/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As <a href="http://www.earlevel.com/main/2010/11/23/towards-a-practical-oversampling-filter">promised</a>, here&#8217;s our windowed sinc calculator for building a 2x oversampling filter:</p>
<div id="container1-20101205" style="width:600px; height:200px;"></div>
<div id="container2-20101205" style="width:600px; height:200px;"></div>
<div id="container3-20101205" style="width:600px; height:200px;"></div>
<div>
<input id="factor" name="factor" value=".47" style="text-align:right;width:4em;margin:0 0 6px 0" type="text" onchange="drawIt()" />&nbsp;Factor</div>
<div>
<input id="windowLen" name="windowLen" value="199" style="text-align:right;width:4em;margin:0 0 6px 0" type="text" onchange="drawIt()" />&nbsp;Length</div>
<div>
<input id="rejection" name="rejection" value="90" style="text-align:right;width:4em;margin:0 0 6px 0" type="text" onchange="drawIt()" />&nbsp;Rejection</div>
<input name="calc" value="Calculate" onclick="drawIt();" type="button" style="width:8em" />
<div><textarea id="coeffsList" rows="8" cols="100" readonly="readonly" style="font-size:12px;line-height:14px"></textarea></div>
<input id="gain" name="gain" value="2" style="text-align:right;width:4em;margin:0 0 4px 0" type="text" onchange="drawIt()" />&nbsp;Gain</p>
<h3>Notes:</h3>
<ul>
<li>Use the Tab or Enter keys to effect changes (most browsers), or press Calculate.</li>
<li>The frequency axis is in multiples of the Nyquist frequency.</li>
<li>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.)</li>
<li>For example, a 2x upsampling filter: Set <em>Rejection</em> to the stop-band rejection is dB. Set <em>Length</em> to the number of taps you want to use (more taps for a steeper filter, but higher processing cost). Set <em>Factor</em> 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 <em>Gain</em> to 2.</li>
<li>Tip: You can copy and paste the coefficients into a text file, and save with an extension of &#8220;.csv&#8221; if you want to read the values into a spreadsheet for further manipulation.</li>
</ul>
<p><!--[if IE]><script language="javascript" type="text/javascript" src="/scripts/utils/flotr/lib/excanvas.js"></script><![endif]--><script type="text/javascript" src="/scripts/utils/flotr/lib/prototype.js"></script><script type="text/javascript" src="/scripts/utils/flotr/flotr.js"></script><script type="text/javascript" src="/scripts/utils/dsputils.js"></script><script type="text/javascript" src="/scripts/widgets/20101205/sincCalc2x.js"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2010/12/05/building-a-windowed-sinc-filter/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Towards practical resampling</title>
		<link>http://www.earlevel.com/main/2010/11/23/towards-a-practical-oversampling-filter/</link>
		<comments>http://www.earlevel.com/main/2010/11/23/towards-a-practical-oversampling-filter/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 08:21:05 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[FIR Filters]]></category>
		<category><![CDATA[Filters]]></category>
		<category><![CDATA[Impulse Response]]></category>
		<category><![CDATA[Sample Rate Conversion]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=55</guid>
		<description><![CDATA[In a previous article, we looked at sample rate conversion in the frequency domain. Let&#8217;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 &#8230; <a href="http://www.earlevel.com/main/2010/11/23/towards-a-practical-oversampling-filter/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://www.earlevel.com/main/2007/07/03/sample-rate-conversion">previous article</a>, we looked at sample rate conversion in the frequency domain. Let&#8217;s take a quick second look in the time domain as reinforcement of principles behind sample rate conversion, before developing a practical rate convertor.</p>
<p>In an ideal digital to analog convertor, we output a pulse train in which each pulse&#8217;s amplitude corresponds to a sample value. The pulse train is processed by a lowpass &#8220;reconstruction&#8221; filter, to arrive at our smooth analog signal output. Theoretically, we want a perfect impulse into a perfect &#8220;brick wall&#8221; lowpass filter—one with no phase shift.</p>
<p>A perfect impulse into our perfect lowpass filter would give an output response of the sinc function; here is the &#8220;normalized&#8221; sinc function:</p>
<p>sin (π * x) / (π * x) { or 1, for x = 0 }</p>
<p>Here&#8217;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):</p>
<p><a href="http://www.earlevel.com/main/wp-content/uploads/2010/11/sinc.png"><img class="alignnone size-full wp-image-59" title="sinc" src="http://www.earlevel.com/main/wp-content/uploads/2010/11/sinc.png" alt="" width="531" height="209" /></a></p>
<p>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&#8217;s an example with three non-zero samples:</p>
<p><a href="http://www.earlevel.com/main/wp-content/uploads/2010/11/sum-of-sincs.png"><img class="alignnone size-full wp-image-58" title="sum-of-sincs" src="http://www.earlevel.com/main/wp-content/uploads/2010/11/sum-of-sincs.png" alt="" width="531" height="208" /></a></p>
<p>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.</p>
<p>Need further convincing? Before moving on, let&#8217;s take a look at a digital square wave (-1,-1,-1,-1,+1,+1,+1,+1…), and sum the individual sinc impulse responses:</p>
<p><a href="http://www.earlevel.com/main/wp-content/uploads/2010/11/square-wave-reconstruction.png"><img class="alignnone size-full wp-image-57" title="square-wave-reconstruction" src="http://www.earlevel.com/main/wp-content/uploads/2010/11/square-wave-reconstruction.png" alt="" width="531" height="205" /></a></p>
<p>You probably recognize that as the look of a bandlimited square wave, so it looks like we&#8217;re on the right track.</p>
<h3>Making it practical</h3>
<p>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.</p>
<p>Fortunately, the sinc function gets smaller and smaller in each direction. We could let it run in both directions until the &#8220;lobes&#8221; got so small that they wouldn&#8217;t contribute to the quantized output, and truncate it from there. That&#8217;s still a long ways, which translates into a lot of output delay and a lot of calculations for the task we&#8217;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.)</p>
<p>Luckily for us, the difference between ideal and our tapered approximation is small, error-wise. This shouldn&#8217;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.</p>
<p>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.</p>
<h3>Putting the pieces together</h3>
<p>Before continuing, here are some observations to keep in mind:</p>
<p>1) We chose the sinc function because it is the impulse response of a lowpass filter with an infinitely steep slope at cutoff (&#8220;brick wall&#8221;), and linear phase. (We may not always require linear phase, but in the general case, that&#8217;s what we want.)</p>
<p>2) We use a window function to convert our ideal filter into a practical one. It&#8217;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&#8217;s a popular choice, and is easy to understand and implement.</p>
<p>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&#8217;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&#8217;ve deviated from the perfect filter, we&#8217;ll need to set the cutoff below the ideal.</p>
<p>Here is what our normalized windowed sinc looks like, along with its components:</p>
<p><a href="http://www.earlevel.com/main/wp-content/uploads/2010/11/windowed-sinc.png"><img class="alignnone size-full wp-image-56" title="windowed-sinc" src="http://www.earlevel.com/main/wp-content/uploads/2010/11/windowed-sinc.png" alt="" width="533" height="192" /></a></p>
<h3>Coming next</h3>
<p>Next up, we&#8217;ll have a have a windowed-sinc calculator that will help us compute coefficients for a high-quality sample rate convertor.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2010/11/23/towards-a-practical-oversampling-filter/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>The sound of dither</title>
		<link>http://www.earlevel.com/main/2010/11/07/the-sound-of-dither/</link>
		<comments>http://www.earlevel.com/main/2010/11/07/the-sound-of-dither/#comments</comments>
		<pubDate>Mon, 08 Nov 2010 05:00:11 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[Dither]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/blog/?p=5</guid>
		<description><![CDATA[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 &#8230; <a href="http://www.earlevel.com/main/2010/11/07/the-sound-of-dither/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>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.</p>
<p>Here’s a fixed-frequency sine wave, truncated to seven bits:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2010/11/7bit_no_dither.mp3">7-bit sine tone, no dither</a></p>
<p>Here’s the same signal dithered, truncated to seven bits:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2010/11/7bit_dithered.mp3">7-bit sine tone, dithered</a></p>
<p>Notice the problems with the non-dithered example, especially in the tail as the signal fades out and fewer bits are used.</p>
<p>Here’s a swept sine wave, first simply truncated to seven bits:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2010/11/7bit_sweep_no_dither.mp3">7-bit sine sweep, no dither</a></p>
<p>And again dithered:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2010/11/7bit_sweep_dithered.mp3">7-bit sine sweep, dithered</a></p>
<p>Note the aliased frequencies in the non-dithered sweep, and how the tail sounds like a square wave as it fades out.</p>
<p>In both cases, the dithered signal maintains the sine tone throughout, at the expensive of added “hiss”.</p>
<p>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.</p>
<p>Read the EarLevel article on <a href="http://www.earlevel.com/main/1996/10/20/what-is-dither">dither</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2010/11/07/the-sound-of-dither/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2010/11/7bit_no_dither.mp3" length="51022" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2010/11/7bit_dithered.mp3" length="51021" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2010/11/7bit_sweep_dithered.mp3" length="51027" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2010/11/7bit_sweep_no_dither.mp3" length="51028" type="audio/mpeg" />
		</item>
		<item>
		<title>Blog birth</title>
		<link>http://www.earlevel.com/main/2010/11/07/blog-birth/</link>
		<comments>http://www.earlevel.com/main/2010/11/07/blog-birth/#comments</comments>
		<pubDate>Mon, 08 Nov 2010 04:00:21 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/blog/?p=4</guid>
		<description><![CDATA[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. &#8230; <a href="http://www.earlevel.com/main/2010/11/07/blog-birth/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>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&#8217;ve moved my older web articles to the blog to make it easier to find things.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2010/11/07/blog-birth/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Sample rate conversion</title>
		<link>http://www.earlevel.com/main/2007/07/03/sample-rate-conversion/</link>
		<comments>http://www.earlevel.com/main/2007/07/03/sample-rate-conversion/#comments</comments>
		<pubDate>Wed, 04 Jul 2007 04:00:34 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[Sample Rate Conversion]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/blog/?p=12</guid>
		<description><![CDATA[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 &#8230; <a href="http://www.earlevel.com/main/2007/07/03/sample-rate-conversion/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>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 <a href="/main/2007/07/03/sampling-in-depth">here</a>. 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&#8217;ve read it before—then come back here for the rest.</p>
<h3>Upsampling</h3>
<p>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&#8217;t raise the ceiling.</p>
<p>Let&#8217;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&#8217;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&#8217;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.</p>
<p>We don&#8217;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&#8217;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.</p>
<p><img class="alignnone" title="digToAnaToDig" src="/DigitalAudio/images/digToAnaToDig.png" alt="" width="663" height="122" /></p>
<p>Converting to analog and back to digital seems a waste—we&#8217;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&#8217;t need two filters. The one with the higher cut-off frequency doesn&#8217;t do anything interesting, since the other filter removes those frequencies anyway, so we discard it and keep the lower filter.</p>
<p>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&#8217;t really do anything.</p>
<p>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&#8217;s look at that signal again:</p>
<p><span style="font-size: 13px; font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px;"><img class="alignnone" title="pamSignal" src="/DigitalAudio/images/pamSignal.png" alt="" width="421" height="103" /></span></p>
<p>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&#8217;t change at all—and therefore neither does the spectrum—but the sample rate does. Here&#8217;s our spectrum again, before inserting zeros:</p>
<p><img class="alignnone" title="spectrum" src="/DigitalAudio/images/spectrum.png" alt="" width="614" height="106" /></p>
<p>Here&#8217;s what we have after inserting a zero between each sample:</p>
<p><img class="alignnone" title="spectrum2xPre" src="/DigitalAudio/images/spectrum2xPre.png" alt="" width="614" height="106" /></p>
<p>Essentially, we&#8217;ve doubled the number of samples, doubling our available bandwidth, but in doing so we&#8217;ve revealed an aliased image in the widened passband. Now it&#8217;s apparent why we need the low-pass filter—to remove the alias from the passband:</p>
<p><img class="alignnone" title="spectrum2xPost" src="/DigitalAudio/images/spectrum2xPost.png" alt="" width="614" height="106" /></p>
<p>That&#8217;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.</p>
<h3>Downsampling</h3>
<p>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&#8217;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&#8217;t matter, just as the exact sampling phase didn&#8217;t matter when you converted from analog to digital in the first place.)</p>
<h3>Conclusion</h3>
<p>We&#8217;ve gone through a lot to explain this, but if you understand the reasons, it&#8217;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.</p>
<p>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.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2007/07/03/sample-rate-conversion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

