[1]:
from IPython.display import Audio
[2]:
import numpy
import matplotlib.pyplot as plt
%matplotlib inline
39. What does a sinusoid sound like?¶
We all have advanced frequency detectors in our ears. This notebook will show how listening to signals gives you a whole different way to understand the frequency domain.
We start by constructing a musically relevant note as a pure sine wave
[48]:
fs = 44100 # sampling frequency, Hz This is the rate at which CDs are sampled.
T = 0.5 # note length, seconds
A = 440 # Note frequency, Hz
twopi = 2*numpy.pi
t = numpy.linspace(0, T, int(T*fs), endpoint=False) # time variable
dt = t[1] # Sampling time
def note(frequency):
return numpy.sin(twopi*frequency*t) # pure sine wave at 440 Hz
# load a NumPy array
Audio(note(A), rate=fs)
[48]:
Now we construct the Chromatic 12 note scale:
[49]:
scalet = numpy.linspace(0, T*13, int(T*fs*13), endpoint=False)
scale = numpy.concatenate([note(A*2**(i/12.)) for i in range(13)])
[50]:
Audio(scale, rate=fs)
[50]:
Of course, this is quite a large number of points, you can’t really see what’s going on
[55]:
plt.plot(scalet, scale)
[55]:
[<matplotlib.lines.Line2D at 0x124602b70>]

You can see the sinusoids better if you zoom in
[56]:
Nzoom = 1000
plt.plot(scalet[:Nzoom], scale[:Nzoom])
[56]:
[<matplotlib.lines.Line2D at 0x11b71b208>]

Let’s listen to the effect of running this through a first order filter.
We’ll use the convolution, so we first obtain the impulse response of the filter
[57]:
omega = 440*twopi # (440 cycles/second)*(2 pi radians / cycle)
tau = 1/omega
first_order_impulse = numpy.exp(-t/tau)
[58]:
plt.plot(t[:Nzoom], first_order_impulse[:Nzoom])
[58]:
[<matplotlib.lines.Line2D at 0x11cc9cef0>]

Then we calculate the output signal via convolution. Recall that when we wrote \(y(s) = G_f(s)u(s)\), this was equivalent to calculating \(y(t) = g_f(t)*u(t)\) where the \(*\) represents convolution. In this case the filtered signal is \(y(t)\) and the original scale is \(u(t)\).
[59]:
def filtersignal(signal):
return numpy.convolve(signal, first_order_impulse, 'same')/len(signal)*len(first_order_impulse)
[60]:
filtered = filtersignal(scale)
As a side note: This is not how filtering is done in practice, you can see this process takes a while.
[61]:
Audio(filtered, rate=fs)
[61]: