<?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>Thu, 10 May 2012 17:32:27 +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>A wavetable oscillator—Part 3</title>
		<link>http://www.earlevel.com/main/2012/05/09/a-wavetable-oscillator%e2%80%94part-3/</link>
		<comments>http://www.earlevel.com/main/2012/05/09/a-wavetable-oscillator%e2%80%94part-3/#comments</comments>
		<pubDate>Thu, 10 May 2012 07:48:05 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[Oscillators]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=112</guid>
		<description><![CDATA[In Part 2, we looked at how to use subtables designed to cover one octave each, removing upper harmonics for each higher octave to avoid aliasing. Here&#8217;s a view of the nine wavetables for our sawtooth oscillator, with the starting &#8230; <a href="http://www.earlevel.com/main/2012/05/09/a-wavetable-oscillator%e2%80%94part-3/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.earlevel.com/main/2012/05/08/a-wavetable-oscillator—part-2/">Part 2</a>, we looked at how to use subtables designed to cover one octave each, removing upper harmonics for each higher octave to avoid aliasing. Here&#8217;s a view of the nine wavetables for our sawtooth oscillator, with the starting frequency and number of harmonics for each octave:</p>
<p><a href="http://www.earlevel.com/main/wp-content/uploads/2012/05/wavetables.png"><img src="http://www.earlevel.com/main/wp-content/uploads/2012/05/wavetables.png" alt="" title="wavetables" width="1742" height="314" class="alignnone size-full wp-image-113" /></a></p>
<p>The table size for each subtable is 2048 samples of single precision floating point. We&#8217;re using a double precision floating point phase accumulator. Here&#8217;s the result, with an exponential sweep from 20 Hz to 20 kHz:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2012/05/saw-2048-lin-20-20k-20s.mp3">Sawtooth sweep 20Hz-20kHz, 20s</a></p>
<p>That sounds&#8230;good! Some observations:</p>
<ul>
<li>The wave starts out a little short of harmonics—we knew it would, because we built our lowest table for 40 Hz and up.</li>
<li>You probably can&#8217;t hear the very end of the sweep, because the frequency is too high.</li>
<li>If you play it back on a good audio system and listen carefully, you can hear at least two &#8220;ticks&#8221; in the audio, nearing the end of the sweep, about 2 seconds apart.</li>
</ul>
<p>The ticks are due to the abrupt change in energy as we switch to the next table with fewer harmonics. It&#8217;s much easier to notice it on in the high range, since the relative power lost is larger (stronger harmonics are dropped). This might be especially noticeable with a strong vibrato that spans tables on a very high note. You can see the transisitons in our sweep:<br />
<a href="http://www.earlevel.com/main/wp-content/uploads/2012/05/Sweep-view.png"><img src="http://www.earlevel.com/main/wp-content/uploads/2012/05/Sweep-view.png" alt="" title="Sweep-view" width="425" height="118" class="alignnone size-full wp-image-118" /></a><br />
It would be easy to fix—with a higher sample rate, or by crossfading the switch. Or, you can ask yourself how often you&#8217;ve ever played sustained notes that high&#8230;with strong vibrato&#8230;soloed in a mix&#8230;with the synth filter missing. The fact is that all synthesizer oscillators make tradeoffs such as this. Either way, we&#8217;ll carry on and keep this oscillator simple and easy to understand.</p>
<h3>Other waveforms</h3>
<p>So far, we&#8217;re building the waves computationally. We could sample a single cycle of anything, resample it into a wavetable length of our choice, then use an FFT to get the spectrum, and modify the spectrum as needed for our additional octave tables. This is where the wavetable oscillator has a huge advantage over analog oscillators—any combination of harmonics is possible. For now, we&#8217;ll just deal with completing the classic synthesizer waveforms. For most analog synthesizers, that means a sawtooth and a variable-width pulse (rectangle) wave.</p>
<p>The Minimoog had just three choices of pulse width, but most synthesizers have voltage control of pulse width for pulse width modulation (PWM) effects. At first it might seem that we&#8217;d need to generate many variations of pulses, but fortunately we can create the same thing by subtracting one sawtooth from another at the same frequency but different phase. Then we get our pulse width modulation by controlling the phase offset. Here&#8217;s a square wave (50% pulse) generated using this method:</p>
<p><a class="wpaudio" href='http://www.earlevel.com/main/wp-content/uploads/2012/05/square-2048-lin-20-20k-20s.mp3'>Square wave sweep 20Hz-20kHz, 20s</a></p>
<p>The triangle wave was also found in the Minimoog, and is routine for modular analog synths, but was sacrificed in most classic non-modular analog synths because it&#8217;s not used as often as sawtooth and pulse. Compared with a sawtooth, a triangle has only odd harmonics, and the harmonics fall off as the inverse square of the harmonics number (and they alternate in sign as well), giving it a hollow sound like the square wave (also odd harmonics), but much more mellow sounding due to the fast rolloff of harmonic energy.</p>
<p><a class="wpaudio" href='http://www.earlevel.com/main/wp-content/uploads/2012/05/triangle-2048-lin-20-20k-20s.mp3'>Triangle wave sweep 20Hz-20kHz, 20s</a></p>
<p>We&#8217;ll look more closely at how the oscillator is implemented, as well as give additional observations about wavetable oscillators, in upcoming articles.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2012/05/09/a-wavetable-oscillator%e2%80%94part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2012/05/saw-2048-lin-20-20k-20s.mp3" length="242876" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2012/05/square-2048-lin-20-20k-20s.mp3" length="242879" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2012/05/triangle-2048-lin-20-20k-20s.mp3" length="242881" type="audio/mpeg" />
		</item>
		<item>
		<title>A wavetable oscillator—Part 2</title>
		<link>http://www.earlevel.com/main/2012/05/08/a-wavetable-oscillator%e2%80%94part-2/</link>
		<comments>http://www.earlevel.com/main/2012/05/08/a-wavetable-oscillator%e2%80%94part-2/#comments</comments>
		<pubDate>Tue, 08 May 2012 16:54:45 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Aliasing]]></category>
		<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[Oscillators]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=109</guid>
		<description><![CDATA[From Part 1, we have an oscillator. But we need to broaden it to allow scaling of harmonic content based on pitch so that we have all the harmonic content we need at the low frequency end, and, as we &#8230; <a href="http://www.earlevel.com/main/2012/05/08/a-wavetable-oscillator%e2%80%94part-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>From <a href="http://www.earlevel.com/main/2012/05/04/a-wavetable-oscillator—part-1/">Part 1</a>, we have an oscillator. But we need to broaden it to allow scaling of harmonic content based on pitch so that we have all the harmonic content we need at the low frequency end, and, as we move up, eliminate those harmonics that would be above the the range of hearing and mirror (alias) back into the audible range.</p>
<h3>How many harmonics do we need?</h3>
<p>To start, we pick a lowest wavetable frequency. Let&#8217;s say 40 Hz (it could be 80 Hz, it could be 20 Hz—it could be 1 Hz). The highest harmonic that fits under half our sample rate is 551 (22050 / 40 is 551.25). So, we could make a sawtooth table of 551 harmonics. The top harmonic would be only 10 Hz from the aliasing threshold—Nyquist. If we shift that wavetable up one octave to 80 Hz, the top harmonic would double—which means it would alias back down to 20 Hz. And the top two hundred harmonics would be below 16 kHz&#8230;Ouch! That means as we glide the wavetable frequency from 40 Hz to 80 Hz, we&#8217;ll be inundated with harmonics aliasing downward throughout the audio range.</p>
<p>Of course, we could go the other direction, using that table from 40 Hz downward (and each higher table handling one octave downward similarly). But that means that as we shift down an octave, all of those harmonics at the top of the audio range will shift down to half the audio range—our highest harmonics would now top out at about 11 kHz before the next table takes over and restores harmonics to the top of the audio range. We&#8217;ll hear this shortcoming.</p>
<p>OK, we can cheat some and go for the middle ground. Most people don&#8217;t really hear to 20 kHz—adults are lucky if they can hear 14 kHz. If we go for 368 harmonics, that puts the top harmonic at 14.72 kHz for 40 Hz, and the alias would fold back to 14.66 kHz (44100 &#8211; 14720 x 2). I think this will work fine for me—I did a quick and dirty check a while back and could hear a 14 kHz tone, but not 15 kHz. The rest of you are on your own. Just kidding—instead of requiring each subtable to cover an octave, we could use twice as many and have them cover half of an octave. Or an even smaller increment. Or we could just oversample the oscillator and expand our shallow frequency headroom greatly, from a few kHz to tens of kHz.</p>
<p>I&#8217;ll continue to develop this oscillator in octaves in order to keep the explanation simple (and because I&#8217;m going for &#8220;good&#8221; quality, to leave you to decide if you can sacrifice some quality for performance or memory, or whether you want to improve quality), but the extension to use more closely-spaces subtables is trivial. Oversampling 2x is also easy, but will complicate the explanation—you&#8217;re on your own if you want to go that way, but it&#8217;s a good learning exercise.</p>
<h3>Wavetable size</h3>
<p>First, let&#8217;s back up and figure out how long our tables need to be. Recalling that we need to sample a signal at greater than twice the highest frequency component, that means that for 368 harmonics, we need at least 368 x 2 + 1 samples, or a table length of at least 737 samples. But also remember that we&#8217;ll be using linear interpolation, so we need to oversample for good results. That means at least 2x, for 1474 samples.</p>
<p>We have good reasons to choose a table length that&#8217;s a power of two, however. There are optimizations we can do that take advantage of binary arithmetic, such as zero-cost wrapping of the table index for fixed-point indices, for instance. Plus, we get a huge boost in building these tables if we use the FFT, compared to summing sine waves individually. Also, we&#8217;ll definitely want to use the FFT if we let users define their own waves—and the FFT is best suited for tables whose lengths are a power of two. From 1474, our next highest power of two is 2048, which gives us a bit more oversampling as well. Memory&#8217;s cheap, so no problem going bigger, but let&#8217;s see where this gets us.</p>
<p>The bottom subtable will be used for that first octave and all pitches below. The second subtable takes over from 80 Hz to 160 Hz, and so on, as frequency doubles (and pitch goes up one octave). We use a suitable, progressively smaller range of harmonics for each table as we go up—dropping the upper half of our harmonics for each higher octave. The top table will be a sine wave, always, so we can just add tables until the last one has one harmonic.</p>
<p><i>Next: let&#8217;s hear the results in <a href="http://www.earlevel.com/main/2012/05/09/a-wavetable-oscillator—part-3/">Part 3</a></i></p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2012/05/08/a-wavetable-oscillator%e2%80%94part-2/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>A wavetable oscillator—Part 1</title>
		<link>http://www.earlevel.com/main/2012/05/04/a-wavetable-oscillator%e2%80%94part-1/</link>
		<comments>http://www.earlevel.com/main/2012/05/04/a-wavetable-oscillator%e2%80%94part-1/#comments</comments>
		<pubDate>Sat, 05 May 2012 01:51:10 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[Oscillators]]></category>
		<category><![CDATA[Sample Rate Conversion]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=100</guid>
		<description><![CDATA[There are many ways to make an oscillator. Without looking for further motivation, I&#8217;ll propose a wavetable oscillator. Wavetables are a fairly obvious extension of the general playback of digital audio. Such oscillators are easy to understand, and their extreme &#8230; <a href="http://www.earlevel.com/main/2012/05/04/a-wavetable-oscillator%e2%80%94part-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>There are many ways to make an oscillator. Without looking for further motivation, I&#8217;ll propose a wavetable oscillator. Wavetables are a fairly obvious extension of the general playback of digital audio. Such oscillators are easy to understand, and their extreme flexible make them a very popular choice among synthesizer oscillators.</p>
<h3>Making a tone from a wavetable</h3>
<p>If we start with one cycle of a waveform, we can output the samples one after another, at the sample rate, and repeat the process after getting to the end of the table. Here&#8217;s a sine wave, the most &#8220;fundamental&#8221; (if boring) of all waveforms, at about 440 Hz (&#8220;concert A&#8221;); I say &#8220;about&#8221; because a single cycle at 44.1 k Hz would be 100.227 (44100 / 440) samples, so we round to a whole number to give us 100 samples (441 Hz):</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2012/05/sine-100-sample-cycle.mp3">Sine wave, 441 Hz</a></p>
<p>OK, that gives us one tone at excellent quality. We could have a separate wavetable for each note that we want to play, but that wouldn&#8217;t let us vary the pitch by arbitrary amounts, such as for vibrato or frequency sweeps. Also, we&#8217;d continue to run into the problem of our table needing to be an integer length—a problem that becomes extreme at high frequencies (due to shorter tables).</p>
<h3>Arbitrary pitch from a wavetable</h3>
<p>A first guess at a solution might be to mimic changing the playback rate on a tape recorder by varying the sample rate. This works quite well, and has the advantage that any errors in the waveform (due to a short wavetable or short sample size) remain harmonically related, so they&#8217;re heard as harmonic distortion instead of noise (hiss), and aliasing is not a threat because we&#8217;re raising the sample rate to play higher notes. This technique was used in some early digital synthesizers (such as the Fairlight CMI), but has a glaring weakness: we can&#8217;t multiplex this type of oscillator—each independent voice requires its own variably-clocked DAC.</p>
<p>However, we can do the equivalent shifting with DSP by using sample rate conversion techniques (sometimes called resampling). Because we can resample a wavetable at multiple rates with DSP, we can generate multiple tones digitally, before sending them to a common DAC.</p>
<p>Basically, we simulate the different clocking rates by using a fixed clock and scanning through the wavetable at a different rate. (We&#8217;ll use the CD sample rate of 44.1 kHz for our tests—higher rates are easier, since they give more audio headroom before aliasing, making 44.1 kHz a good test as we develop the algorithm.) So, instead of outputting the first sample, then the second—stepping through the table with an increment of 1—we can step through with a smaller increment for lower pitches and a larger increment for higher pitches.</p>
<p>But we need to decide which sample to use for a fractional offset. The simplest choice is to truncate the fractional index by taking only the integer portion. This has been done in popular instruments of the past, especially early samplers. I&#8217;ll cut straight to a recommendation and suggest that we use linear interpolation—it&#8217;s not much more computationally expensive, and gives us enough improvement in sound quality to be worth the effort. We&#8217;ll discuss linear interpolation more later.</p>
<p>Here&#8217;s our sine wave at a different pitch, using a fractional increment and linear interpolation—middle C (261.626 Hz):</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2012/05/sine-100-sample-table-middle-C.mp3">Sine wave, 261.626 Hz</a></p>
<p>That sounds promising—and note that fractional increments let us get our target pitch exactly this time. To prove it works at any pitch we&#8217;re interested in, here&#8217;s the same technique used with an exponential sweep, changing the wavetable index increment at each cycle to cover a wide range:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2012/05/sine-sweep-100-sample-table-20-20k.mp3">Sine sweep, 20-20,000 Hz</a></p>
<p>That sounds like we may have solved the problem of creating any pitch we want from a wavetable! But let&#8217;s test further&#8230;</p>
<h3>A classic synthesizer waveform</h3>
<p>Sine waves are boring. A staple for classic synthesizers is the sawtooth wave—a harmonically rich waveform that&#8217;s excellent for subtractive synthesis. A single cycle of a sawtooth climbs in value from the lowest value to highest, then resetting instantly to the lowest. We can&#8217;t generate a perfect sawtooth in a wavetable (we can&#8217;t reset instantly, for instance—we must wait till the next sample output), so the proper thing to do is to build a band-limited sawtooth from sine wave harmonics. A band-limited sawtooth wave is made up of a sine wave for the first harmonic, a sine at twice the frequency but half the amplitude for the second harmonic, a sine three times the frequency but a third of the amplitude, etc. Because our wavetable is 100 samples, we can fit a sawtooth of 49 harmonics.</p>
<p>Here&#8217;s what a sawtooth of 441 Hz sounds like:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2012/05/saw-100-sample-cycle.mp3">Sawtooth wave, 441 Hz</a></p>
<p>And here we sweep the range as before:</p>
<p><a class="wpaudio" href="http://www.earlevel.com/main/wp-content/uploads/2012/05/saw-sweep-100-sample-table-20-20k.mp3">Sawtooth sweep, 20-20,000 Hz</a></p>
<p>Yikes! At the higher pitches, the tone is too harmonic-rich, causing strong aliasing. Also, notice that at the lower pitches the sawtooth starts out sounding a bit dull, lacking the highest harmonics.</p>
<p>Clearly, we do not have a suitable wavetable oscillator yet. We need the ability to scale the harmonic content to the pitch required—starting with a wavetable tailored to the lowest pitch we want to produce, and reducing harmonic content as we move up in pitch before it has a chance to fold back as aliasing at half the sample rate.</p>
<p><i>Next: working on a solution in <a href="http://www.earlevel.com/main/2012/05/08/a-wavetable-oscillator—part-2/">Part 2</a></i></p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2012/05/04/a-wavetable-oscillator%e2%80%94part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2012/05/sine-100-sample-cycle.mp3" length="51033" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2012/05/sine-100-sample-table-middle-C.mp3" length="51043" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2012/05/sine-sweep-100-sample-table-20-20k.mp3" length="51047" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2012/05/saw-100-sample-cycle.mp3" length="51032" type="audio/mpeg" />
<enclosure url="http://www.earlevel.com/main/wp-content/uploads/2012/05/saw-sweep-100-sample-table-20-20k.mp3" length="51046" type="audio/mpeg" />
		</item>
		<item>
		<title>A wavetable oscillator—Introduction</title>
		<link>http://www.earlevel.com/main/2012/05/03/a-wavetable-oscillator%e2%80%94introduction/</link>
		<comments>http://www.earlevel.com/main/2012/05/03/a-wavetable-oscillator%e2%80%94introduction/#comments</comments>
		<pubDate>Thu, 03 May 2012 17:51:25 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[Oscillators]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=111</guid>
		<description><![CDATA[Years ago, Cristoph Kemper told me how the Access Virus came to be. He had coded a filter on a DSP and wanted to test it. Of course he needed an oscillator, so he coded that…pretty soon he had a &#8230; <a href="http://www.earlevel.com/main/2012/05/03/a-wavetable-oscillator%e2%80%94introduction/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><i>Years ago, Cristoph Kemper told me how the Access Virus came to be. He had coded a filter on a DSP and wanted to test it. Of course he needed an oscillator, so he coded that…pretty soon he had a synthesizer…</i></p>
<p>Oscillators are an important DSP topic, especially for the musically inclined. Plus…we may want to look more at filters, and need a flexible signal source.</p>
<p>There are many ways to implement oscillators. Yamaha&#8217;s DX7 was a huge early digital synthesizer success using FM (frequency modulation of digital sine waves). There was no classic synthesizer filter in the DX7, because it built the harmonic complexity up from sine wave modulation, unlike the classic subtractive synthesis technique of using filters to change the tone of harmonically complex oscillators.</p>
<p>We&#8217;re going to look at emulating classic analog synthesizer waveforms. In all their simplicity, it&#8217;s hard to not like the sound.</p>
<p>The simplicity comes from simple circuits. Analog synthesizers usually generate a sawtooth by charging a capacitor with a constant current source. The capacitor fills until it hits a trigger point that discharges it, and the process repeats. Increasing the current makes it fill faster, and decreasing it makes it fill slower, controlling the frequency of the sawtooth oscillator. Much of the work is in implemented exponential voltage control, so that a linear voltage change (1 volt per octave is standard) creates an exponential frequency change (which sounds linear to us), and in particular working around temperature terms in the circuit to keep it stable and in tune.</p>
<p>It&#8217;s easy enough for us to use a counter (an accumulator) to take the place of the capacitor, but we have a problem in that we can&#8217;t &#8220;discharge&#8221; (reset) it exactly when we want—only on sample boundaries. This results in aliasing—I won&#8217;t go into that further now, but the point is that it won&#8217;t give us adequate results without a very high sample rate. We need to find another way to emulate a classic analog oscillator.</p>
<p><i>Next: we&#8217;ll look at implementing a wavetable oscillator in <a href="http://www.earlevel.com/main/2012/05/04/a-wavetable-oscillator—part-1/">Part 1</a></i></p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2012/05/03/a-wavetable-oscillator%e2%80%94introduction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convolution—in words</title>
		<link>http://www.earlevel.com/main/2012/03/05/convolution%e2%80%94in-words/</link>
		<comments>http://www.earlevel.com/main/2012/03/05/convolution%e2%80%94in-words/#comments</comments>
		<pubDate>Tue, 06 Mar 2012 07:14:42 +0000</pubDate>
		<dc:creator>Nigel Redmon</dc:creator>
				<category><![CDATA[Convolution]]></category>
		<category><![CDATA[Digital Audio]]></category>
		<category><![CDATA[FIR Filters]]></category>
		<category><![CDATA[Impulse Response]]></category>
		<category><![CDATA[Reverb]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.earlevel.com/main/?p=91</guid>
		<description><![CDATA[Convolution is a convoluted topic—and that’s what it means (convoluted, from Merriam-Webster : “Extremely complex and difficult to follow. Intricately folded, twisted, or coiled.”). Really, it’s more difficult to explain why you would want to use convolution than it is &#8230; <a href="http://www.earlevel.com/main/2012/03/05/convolution%e2%80%94in-words/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Convolution is a convoluted topic—and that’s what it means (<em>convoluted</em>, from Merriam-Webster : “Extremely complex and difficult to follow. Intricately folded, twisted, or coiled.”).</p>
<p>Really, it’s more difficult to explain why you would want to use convolution than it is to explain the mathematical function itself. I wrote a more technical article nearly a year ago, and it went unpublished because I didn’t have time to write the interactive and animated graphs that I wanted to accompany it. Revisiting the topic, I decided it was better to explain it in words from an intuitive point of view, followed by an article on the mathematical implementation later, and audio examples.</p>
<h3>Hello!</h3>
<p>I hope that most people are familiar—from either personal experience, or maybe a cartoon—with the effect of an echo off a distant canyon wall. You shout, and moments later you hear your shout repeated back to you, though not as loud (the original in red, the quieter echo in blue):</p>
<p><a href="http://www.earlevel.com/main/wp-content/uploads/2012/03/hello.png"><img src="http://www.earlevel.com/main/wp-content/uploads/2012/03/hello.png" alt="" title="hello" width="124" height="21" class="alignnone size-full wp-image-95" /></a></p>
<p>If we gave an impulse—perhaps firing a starter piston—we’d hear a response that has the same spacing and amplitude:</p>
<p><a href="http://www.earlevel.com/main/wp-content/uploads/2012/03/pop.png"><img src="http://www.earlevel.com/main/wp-content/uploads/2012/03/pop.png" alt="" title="pop" width="137" height="63" class="alignnone size-full wp-image-94" /></a></p>
<p>Note that we don’t need to go to that canyon to get the same results in a recording studio—we could mix together a shout of “Hello!” with an attenuated and delayed copy of it. Our impulse response tells us, precisely, how much to attenuate and to delay the copy.</p>
<p>Now, consider what happens when you continue to shout instead of pausing to hear the reflection:</p>
<p><a href="http://www.earlevel.com/main/wp-content/uploads/2012/03/4score.png"><img src="http://www.earlevel.com/main/wp-content/uploads/2012/03/4score.png" alt="" title="4score" width="608" height="25" class="alignnone size-full wp-image-96" /></a></p>
<p>A nearby listener would hear the original speech, starting at the beginning (the first pop), and a delayed, quieter copy starting at the time of the second pop. The two speeches would be jumbled together.</p>
<p>Now consider being inside of an empty gymnasium, where you hear not just one discrete echo, but many, including echoes of echoes as the sound bounces between walls. We could get an impulse response of the gym with a starter pistol, and it too would tell us where to overlap copies—of whatever speech or sound might go on in the gym—and their relative volumes.</p>
<p>As you can imagine, piecing together a facsimile from a signal (speech, music…) and the room’s known impulse response gets more complicated (convoluted!) as the impulse response has more features. In the digital realm, our “features” are individual samples, so the complexity is determined by how many samples there are in the impulse response—the longer the impulse response, the greater the number of computations required to scale and add in “copies”. You won’t want to simulate the results of a reverberant room manually like we did with the single-echo example. Fortunately, we can do much better—we can compute the results exactly, given an exact impulse response. We say that we <em>convolve</em> the signal with an impulse response—the process is called <em>convolution</em> (just like we <em>multiply</em> two numbers in a process called <em>multiplication</em>).</p>
<h3>More on getting the impulse response</h3>
<p>There are many ways to generate an impulse. Have you ever gone into a near empty gym or warehouse and clapped your hands together sharply once, to hear the “sound” of the room? You were analyzing its impulse response. Popping a balloon is another way. A perfect impulse has equal amounts of all frequencies—like white noise condensed into a spike. It’s impossible to attain this ideal impulse, but we can get close enough to handle the audio band. Often, however, impulse responses of large rooms are taken by sweeping a sine wave through the audio band—a “chirp”—because it’s easier to get a more accurate result, and better signal to noise ratio, than trying to make a loud impulse that’s practically ideal. In essence, a chirp is an impulse spread over time.</p>
<p>In the digital realm, and impulse can be readily approximated by its band-limit version—a single unit sample in the midst of zero samples. To get the impulse response of a digital filter, for instance, run this single-sample impulse through the filter—the impulse response is its output. For an FIR filter, the impulse response is equal to its coefficients (because, conversely, standard FIR filters are normally implemented by convolution).</p>
<p>And, of course, we can compute an impulse response instead of measuring it. We do this routinely for FIR filters. And to combine two serial FIR filters into one, just convolve their impulse responses (which is to say, their taps). We could calculate the response of an imagined room as well, for use as a reverb effect.</p>
<h3>Using convolution for audio effects</h3>
<p>For changing signals such as music, longer delays have less correlation, and sound like echos, while shorter delays cause more frequency cancellation and sound like filtering. This allows us a wide range of tonal and spacial effects for audio via convolution.</p>
<p>And while I use the term “impulse response” throughout this article, there’s nothing stopping you from convolving any two sounds, including instruments—a trumpet note convolved with a bowed cymbal, for example.</p>
<h4>Limitations</h4>
<p>Convolution is a useful tool for reproducing linear, time-invariant effects.</p>
<p>Linear means that the output simply scales with the input at a constant ratio. An identical input signal half as loud, produces the same output half as loud. Examples of linear effects are typical fixed filters and echos. A distortion pedal is non-linear—playing louder creates not just a louder version of the same sound, but a different sound.</p>
<p>Time-invariant means that the impulse response doesn’t change over time. If you input a signal to a time-invariant system right now, the output will sound the same as doing it five minutes from now—nothing changes except the five minutes. A flanger is not time-invariant. Playing right now, your signal might start at the top of the sweep, while playing at an arbitrary time later it might start mid-sweep or at the bottom.</p>
<p>Convolution is not convenient for time-varying effects, as they would require that the impulse response change constantly. You could do this—cycle through changing, possibly interpolated impulse responses, but that’s not a practical solution for most effects.</p>
<p>Likewise, convolution for non-linear effects would require a different impulse response for different instantaneous levels at the input. To be fully general, that would be for every possible input level (65,636 for 16-bit resolution), though more practically most effects could be done by using much fewer levels and interpolation, because good-sounding audio processes are not completely random—the saturation level of a distortion effect rolls on gradually and monotonically, it doesn’t jump all over the place. Still, convolution loses much of its appeal for non-linear effects, because most non-linear effects can be done more simply other ways.</p>
<h4>Convolution reverb</h4>
<p>Even though convolution has been used in filtering since the dawn of digital audio, most musicians are aware of the term from convolution reverb. Convolution reverb is a boon for giving people access to “realistic” acoustic spaces, but it shares all of the limitations, and more, with algorithmic reverb. It’s an exaggeration to say that it puts your instruments in a real space—more like it puts your instruments through a speaker (or speakers) in a physical space, and gives you the sound mic’d at a point in that space (with multiple mics for multiple impulse responses for stereo and other multi-channel effects processing). And you lose the chance of capturing non-linearities and time variations, which may play a part in some spaces.</p>
<p>Want the effect of a sound coming from within a closed cardboard box? Generate an impulse inside the box, and capture it outside the box. Need the effect of someone shouting for help from inside a storm drain for a movie without making the actor climb into the storm drain? Maybe you can lower a sound generator into a storm drain and mic it from the outside, then convolve the actor’s voice with that impulse response—and no one needs to get dirty. The sound of a telephone or other small speaker? Wire an electrical impulse directly, and mic the output to get the response.</p>
<p>The web has many pre-made impulse responses, so we can use spaces that we don’t have access to. Play your pipe organ sample via the room response of a large cathedral—or play your guitar through a classic spring reverb, played through an antique radio&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earlevel.com/main/2012/03/05/convolution%e2%80%94in-words/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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;
                b1 = 2 * (K * K - V) * norm;
                b2 = (V - Math.sqrt(2*V) * K + K * K) * 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>13</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>
	</channel>
</rss>

