Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 7335
1
"""This file contains code used in "Think DSP",
2
by Allen B. Downey, available from greenteapress.com
3
4
Copyright 2015 Allen B. Downey
5
License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html
6
"""
7
8
from __future__ import print_function, division
9
10
import thinkdsp
11
import thinkplot
12
13
import numpy as np
14
import matplotlib.pyplot as plt
15
16
PI2 = 2 * np.pi
17
FORMATS = ['pdf', 'eps']
18
19
20
def plot_beeps():
21
wave = thinkdsp.read_wave('253887__themusicalnomad__positive-beeps.wav')
22
wave.normalize()
23
24
thinkplot.preplot(3)
25
26
# top left
27
ax1 = plt.subplot2grid((4, 2), (0, 0), rowspan=2)
28
plt.setp(ax1.get_xticklabels(), visible=False)
29
30
wave.plot()
31
thinkplot.config(title='Input waves', legend=False)
32
33
# bottom left
34
imp_sig = thinkdsp.Impulses([0.01, 0.4, 0.8, 1.2],
35
amps=[1, 0.5, 0.25, 0.1])
36
impulses = imp_sig.make_wave(start=0, duration=1.3,
37
framerate=wave.framerate)
38
39
ax2 = plt.subplot2grid((4, 2), (2, 0), rowspan=2, sharex=ax1)
40
impulses.plot()
41
thinkplot.config(xlabel='Time (s)')
42
43
# center right
44
convolved = wave.convolve(impulses)
45
46
ax3 = plt.subplot2grid((4, 2), (1, 1), rowspan=2)
47
plt.title('Convolution')
48
convolved.plot()
49
thinkplot.config(xlabel='Time (s)')
50
51
thinkplot.save(root='sampling1',
52
formats=FORMATS,
53
legend=False)
54
55
XLIM = [-22050, 22050]
56
57
def plot_am():
58
wave = thinkdsp.read_wave('105977__wcfl10__favorite-station.wav')
59
wave.unbias()
60
wave.normalize()
61
62
# top
63
ax1 = thinkplot.preplot(6, rows=4)
64
spectrum = wave.make_spectrum(full=True)
65
spectrum.plot(label='spectrum')
66
67
thinkplot.config(xlim=XLIM, xticklabels='invisible')
68
69
#second
70
carrier_sig = thinkdsp.CosSignal(freq=10000)
71
carrier_wave = carrier_sig.make_wave(duration=wave.duration,
72
framerate=wave.framerate)
73
modulated = wave * carrier_wave
74
75
ax2 = thinkplot.subplot(2, sharey=ax1)
76
modulated.make_spectrum(full=True).plot(label='modulated')
77
thinkplot.config(xlim=XLIM, xticklabels='invisible')
78
79
# third
80
demodulated = modulated * carrier_wave
81
demodulated_spectrum = demodulated.make_spectrum(full=True)
82
83
ax3 = thinkplot.subplot(3, sharey=ax1)
84
demodulated_spectrum.plot(label='demodulated')
85
thinkplot.config(xlim=XLIM, xticklabels='invisible')
86
87
#fourth
88
ax4 = thinkplot.subplot(4, sharey=ax1)
89
demodulated_spectrum.low_pass(10000)
90
demodulated_spectrum.plot(label='filtered')
91
thinkplot.config(xlim=XLIM, xlabel='Frequency (Hz)')
92
93
thinkplot.save(root='sampling2',
94
formats=FORMATS)
95
96
#carrier_spectrum = carrier_wave.make_spectrum(full=True)
97
#carrier_spectrum.plot()
98
99
100
#convolved = spectrum.convolve(carrier_spectrum)
101
#convolved.plot()
102
103
104
#reconvolved = convolved.convolve(carrier_spectrum)
105
#reconvolved.plot()
106
107
108
def sample(wave, factor):
109
"""Simulates sampling of a wave.
110
111
wave: Wave object
112
factor: ratio of the new framerate to the original
113
"""
114
ys = np.zeros(len(wave))
115
ys[::factor] = wave.ys[::factor]
116
ts = wave.ts[:]
117
return thinkdsp.Wave(ys, ts, wave.framerate)
118
119
120
def make_impulses(wave, factor):
121
ys = np.zeros(len(wave))
122
ys[::factor] = 1
123
ts = np.arange(len(wave)) / wave.framerate
124
return thinkdsp.Wave(ys, ts, wave.framerate)
125
126
127
def plot_segments(original, filtered):
128
start = 1
129
duration = 0.01
130
original.segment(start=start, duration=duration).plot(color='gray')
131
filtered.segment(start=start, duration=duration).plot()
132
133
134
def plot_sampling(wave, root):
135
ax1 = thinkplot.preplot(2, rows=2)
136
wave.make_spectrum(full=True).plot(label='spectrum')
137
138
thinkplot.config(xlim=XLIM, xticklabels='invisible')
139
140
ax2 = thinkplot.subplot(2)
141
sampled = sample(wave, 4)
142
sampled.make_spectrum(full=True).plot(label='sampled')
143
thinkplot.config(xlim=XLIM, xlabel='Frequency (Hz)')
144
145
thinkplot.save(root=root,
146
formats=FORMATS)
147
148
149
def plot_sampling2(wave, root):
150
ax1 = thinkplot.preplot(6, rows=4)
151
wave.make_spectrum(full=True).plot(label='spectrum')
152
thinkplot.config(xlim=XLIM, xticklabels='invisible')
153
154
ax2 = thinkplot.subplot(2)
155
impulses = make_impulses(wave, 4)
156
impulses.make_spectrum(full=True).plot(label='impulses')
157
thinkplot.config(xlim=XLIM, xticklabels='invisible')
158
159
ax3 = thinkplot.subplot(3)
160
sampled = wave * impulses
161
spectrum = sampled.make_spectrum(full=True)
162
spectrum.plot(label='sampled')
163
thinkplot.config(xlim=XLIM, xticklabels='invisible')
164
165
ax4 = thinkplot.subplot(4)
166
spectrum.low_pass(5512.5)
167
spectrum.plot(label='filtered')
168
thinkplot.config(xlim=XLIM, xlabel='Frequency (Hz)')
169
170
thinkplot.save(root=root,
171
formats=FORMATS)
172
173
174
def plot_sampling3(wave, root):
175
ax1 = thinkplot.preplot(6, rows=3)
176
wave.make_spectrum(full=True).plot(label='spectrum')
177
thinkplot.config(xlim=XLIM, xticklabels='invisible')
178
179
impulses = make_impulses(wave, 4)
180
181
ax2 = thinkplot.subplot(2)
182
sampled = wave * impulses
183
spectrum = sampled.make_spectrum(full=True)
184
spectrum.plot(label='sampled')
185
thinkplot.config(xlim=XLIM, xticklabels='invisible')
186
187
ax3 = thinkplot.subplot(3)
188
spectrum.low_pass(5512.5)
189
spectrum.plot(label='filtered')
190
thinkplot.config(xlim=XLIM, xlabel='Frequency (Hz)')
191
192
thinkplot.save(root=root,
193
formats=FORMATS)
194
195
#filtered = spectrum.make_wave()
196
#plot_segments(wave, filtered)
197
198
199
def make_boxcar(spectrum, factor):
200
"""Makes a boxcar filter for the given spectrum.
201
202
spectrum: Spectrum to be filtered
203
factor: sampling factor
204
"""
205
fs = np.copy(spectrum.fs)
206
hs = np.zeros_like(spectrum.hs)
207
208
cutoff = spectrum.framerate / 2 / factor
209
for i, f in enumerate(fs):
210
if abs(f) <= cutoff:
211
hs[i] = 1
212
return thinkdsp.Spectrum(hs, fs, spectrum.framerate, full=spectrum.full)
213
214
215
216
def plot_sinc_demo(wave, factor, start=None, duration=None):
217
218
def make_sinc(t, i, y):
219
"""Makes a shifted, scaled copy of the sinc function."""
220
sinc = boxcar.make_wave()
221
sinc.shift(t)
222
sinc.roll(i)
223
sinc.scale(y * factor)
224
return sinc
225
226
def plot_mini_sincs(wave):
227
"""Plots sinc functions for each sample in wave."""
228
t0 = wave.ts[0]
229
for i in range(0, len(wave), factor):
230
sinc = make_sinc(t0, i, wave.ys[i])
231
seg = sinc.segment(start, duration)
232
seg.plot(color='green', linewidth=0.5, alpha=0.3)
233
if i == 0:
234
total = sinc
235
else:
236
total += sinc
237
238
seg = total.segment(start, duration)
239
seg.plot(color='blue', alpha=0.5)
240
241
sampled = sample(wave, factor)
242
spectrum = sampled.make_spectrum()
243
boxcar = make_boxcar(spectrum, factor)
244
245
start = wave.start if start is None else start
246
duration = wave.duration if duration is None else duration
247
248
sampled.segment(start, duration).plot_vlines(color='gray')
249
wave.segment(start, duration).plot(color='gray')
250
plot_mini_sincs(wave)
251
252
253
def plot_sincs(wave):
254
start = 1.0
255
duration = 0.01
256
factor = 4
257
258
short = wave.segment(start=start, duration=duration)
259
#short.plot()
260
261
sampled = sample(short, factor)
262
#sampled.plot_vlines(color='gray')
263
264
spectrum = sampled.make_spectrum(full=True)
265
boxcar = make_boxcar(spectrum, factor)
266
267
sinc = boxcar.make_wave()
268
sinc.shift(sampled.ts[0])
269
sinc.roll(len(sinc)//2)
270
271
thinkplot.preplot(2, cols=2)
272
sinc.plot()
273
thinkplot.config(xlabel='Time (s)')
274
275
thinkplot.subplot(2)
276
boxcar.plot()
277
thinkplot.config(xlabel='Frequency (Hz)',
278
ylim=[0, 1.05],
279
xlim=[-boxcar.max_freq, boxcar.max_freq])
280
281
thinkplot.save(root='sampling6',
282
formats=FORMATS)
283
284
return
285
286
# CAUTION: don't call plot_sinc_demo with a large wave or it will
287
# fill memory and crash
288
plot_sinc_demo(short, 4)
289
thinkplot.config(xlabel='Time (s)')
290
thinkplot.save(root='sampling7',
291
formats=FORMATS)
292
293
start = short.start + 0.004
294
duration = 0.00061
295
plot_sinc_demo(short, 4, start, duration)
296
thinkplot.config(xlabel='Time (s)',
297
xlim=[start, start+duration],
298
ylim=[-0.06, 0.17], legend=False)
299
thinkplot.save(root='sampling8',
300
formats=FORMATS)
301
302
303
def kill_yticklabels():
304
axis = plt.gca()
305
plt.setp(axis.get_yticklabels(), visible=False)
306
307
308
def show_impulses(wave, factor, i):
309
thinkplot.subplot(i)
310
thinkplot.preplot(2)
311
impulses = make_impulses(wave, factor)
312
impulses.segment(0, 0.001).plot_vlines(linewidth=2, xfactor=1000)
313
if i == 1:
314
thinkplot.config(title='Impulse train',
315
ylim=[0, 1.05])
316
else:
317
thinkplot.config(xlabel='Time (ms)',
318
ylim=[0, 1.05])
319
320
thinkplot.subplot(i+1)
321
impulses.make_spectrum(full=True).plot()
322
kill_yticklabels()
323
if i == 1:
324
thinkplot.config(title='DFT of impulse train',
325
xlim=[-22400, 22400])
326
else:
327
thinkplot.config(xlabel='Frequency (Hz)',
328
xlim=[-22400, 22400])
329
330
331
def plot_impulses(wave):
332
thinkplot.preplot(rows=2, cols=2)
333
show_impulses(wave, 4, 1)
334
show_impulses(wave, 8, 3)
335
thinkplot.save('sampling9',
336
formats=FORMATS)
337
338
339
def main():
340
wave = thinkdsp.read_wave('328878__tzurkan__guitar-phrase-tzu.wav')
341
wave.normalize()
342
343
plot_sampling3(wave, 'sampling5')
344
plot_sincs(wave)
345
346
plot_beeps()
347
plot_am()
348
349
wave = thinkdsp.read_wave('263868__kevcio__amen-break-a-160-bpm.wav')
350
wave.normalize()
351
plot_impulses(wave)
352
353
plot_sampling(wave, 'sampling3')
354
plot_sampling2(wave, 'sampling4')
355
356
357
if __name__ == '__main__':
358
main()
359
360