##ThinkDSP
This notebook contains code examples from Chapter 11: Modulation and sampling
Copyright 2015 Allen Downey
Special thanks to my colleague Siddhartan Govindasamy; the sequence of topics in this notebook is based on material he developed for Signals and Systems at Olin College, which he and Oscar Mur-Miranda and I co-taught in Spring 2015.
###Convolution with impulses
To demonstrate the effect of convolution with impulses, I'll load a short beep sound.
Here's what it sounds like.
And here's a sequence of 4 impulses with diminishing amplitudes:
If we convolve the wave with the impulses, we get 4 shifted, scaled copies of the original sound.
And here's what it sounds like.
###Amplitude modulation (AM)
The previous example gives some insight into how AM works.
First I'll load a recording that sounds like AM radio.
Here's what the spectrum looks like:
For the following examples, it will be more useful to look at the full spectrum, which includes the negative frequencies. Since we are starting with a real signal, the spectrum is always symmetric.
Amplitude modulation works my multiplying the input signal by a "carrier wave", which is a cosine, 10 kHz in this example.
The *
operator performs elementwise multiplication.
The result sounds pretty horrible.
Why? Because multiplication in the time domain corresponds to convolution in the frequency domain. The DFT of the carrier wave is two impulses; convolution with those impulses makes shifted, scaled copies of the spectrum.
Specifically, AM modulation has the effect of splitting the spectrum in two halves and shifting the frequencies by 10 kHz (notice that the amplitudes are half what they were in the previous plot).
To recover the signal, we modulate it again.
Each half of the spectrum gets split and shifted again. Two of the quarters get shifted to 0 and added up. The other two are at $\pm$20Khz
If you listen to it now, it sounds pretty good. You probably can't hear the extra components at high frequencies.
If we compare the input and output signals, they are pretty close.
If the high frequency components bother you, you can clobber them by applying a low pass filter. In this example, I use a "brick wall" filter that cuts off sharply at 10 kHz. In real applications, we would use a more gentle filter.
Here's what it sounds like after filtering.
To understand how AM works, let's see what's going on in the frequency domain.
When we multiply two signals in the time domain, that corresponds to convolution in the frequency domain. The carrier wave is a cosine at 10 kHz, so its spectrum is two impulses, at 10 kHz
As we saw in the beep example, convolution with impulses makes shifted, scaled copies.
After one convolution, we have two peaks. After two convolutions, we have four.
And that's how AM works. Now let's talk about sampling.
###Sampling
I'll start with a recording of a drum break. If you don't know about the Amen break, you might want to read this: https://en.wikipedia.org/wiki/Amen_break
This signal is sampled at 44100 Hz. Here's what it sounds like.
And here's the spectrum:
Even though this signal has already been sampled, let's pretend it hasn't. So we'll treat the original wave as if it were a continuous analog signal.
Now I'm going to sample it at 1/4 of the framerate (11025 Hz) by keeping every 4th sample and setting the rest to zero.
The result doesn't sound very good. It has a bunch of extra high frequency components.
If we look at the spectrum, we can see the extra components.
To understand where those came from, it helps to think of sampling as multiplication with an "impulse train". The following function is similar to sample
, but it makes the impulse train explicit.
Multiplying by impulses
has the same effect as sample
.
Now if we look at the spectrum of impulses
, we can see what's going on in the frequency domain.
Multiplying by impulses
makes 4 shifted copies of the original spectrum. One of them wraps around from the negative end of the spectrum to the positive, which is why there are 5 peaks in the spectrum off the sampled wave.
As we take fewer samples, they get farther apart in the time domain and the copies of the spectrum get closer together in the frequency domain.
As you vary the sampling factor, below, you can see the effect.
To recover the original wave, we can apply a low pass filter to clobber the unwanted copies. The wave was sampled at 11025 Hz, so we'll cut it off at the Nyquist frequency, 5512.5.
The result sounds quite different from the original, for two reasons:
Because we had to cut off frequencies about 5512.5 Hz, we lost some of the high frequency components of the original signal.
Even for the frequencies below 5512.5 Hz, the spectrum is not quite right, because it includes contributions leftover from the extra copies.
We can see that the original and the sampled/filtered signal are not the same:
Sampling didn't work very well with this signal because it contains a lot of components above the Nyquist frequency.
###Sampling, take two
Let's try again with a bass guitar intro (can you name that tune?).
Unless you have good speakers, it might not sound very good.
Here's the spectrum. Not a lot of high frequency components!
Here's the spectrum after sampling:
And here's what it sounds like:
Now, instead of using Spectrum.low_pass
, I'm going to make the low pass filter explicitly. I'm calling it boxcar
because it looks like the boxcar smoothing window from Chapter 8.
Here's what it looks like:
Now we can apply the filter by multiplying in the frequency domain.
Now if we listen to the sampled/filtered wave, it sounds pretty good.
And if we compare it to the original, it is almost identical.
It's not completely identical because the original signal had some tiny components above the Nyquist frequency. But the differences are small.
Multiplying the spectrum of the sampled signal and the boxcar filter, in the frequency domain, corresponds to convolution in the time domain. And you might wonder what the convolution window looks like. We can find out by computing the wave that corresponds to the boxcar filter.
It's the sinc function, which you can read about at https://en.wikipedia.org/wiki/Sinc_function
###Sinc interpolation
Multiplying by a boxcar filter corresponds to convolution with a sinc function, which has the effect of interpolating between the samples. To see how that works, let's zoom in on a short segment of the signal:
Now I'll sample the signal and show the samples using vertical lines:
We can use the sampled spectrum to construct the sinc function. In this example I
Shift the sinc function in time so it lines up with the sampled segment (both start at 1.0 seconds).
Roll the sinc function so the peak is in the middle, just because it looks better that way.
The following figure shows how convolution makes lots of shifted, scaled copies of the sinc function and adds them up.
In this figure:
The thin green lines are the shifted, scaled copies of the sinc function.
The blue line is the sum of the sinc functions.
The gray line (which you mostly can't see) is the original function.
The sum of the sinc functions interpolates between the samples and recovers the original wave. At the beginning and end, where the interpolation deviates from the original; the problem is that the original is not periodic, so the sinc interpolation breaks at the boundaries.
If we zoom in on a short segment, we can see how it works more clearly.
The vertical gray lines are the samples.
Again, the thin green lines are the shifted, scaled copies of the sinc function.
In this segment, the interpolation matches the original wave very well.
Notice that each sinc function has a peak at the location of one sample and the value 0 at every other sample location. That way, when we add them up, the sum passes through each of the samples.