Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 7334
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 math
11
import numpy as np
12
13
import thinkdsp
14
import thinkplot
15
16
import matplotlib.pyplot as pyplot
17
18
import warnings
19
warnings.filterwarnings('ignore')
20
21
PI2 = math.pi * 2
22
23
24
def linear_chirp_evaluate(ts, low=440, high=880, amp=1.0):
25
"""Computes the waveform of a linear chirp and prints intermediate values.
26
27
low: starting frequency
28
high: ending frequency
29
amp: amplitude
30
"""
31
print('ts', ts)
32
33
freqs = np.linspace(low, high, len(ts)-1)
34
print('freqs', freqs)
35
36
dts = np.diff(ts)
37
print('dts', dts)
38
39
dphis = np.insert(PI2 * freqs * dts, 0, 0)
40
print('dphis', dphis)
41
42
phases = np.cumsum(dphis)
43
print('phases', phases)
44
45
ys = amp * np.cos(phases)
46
print('ys', ys)
47
48
return ys
49
50
51
def discontinuity(num_periods=30, hamming=False):
52
"""Plots the spectrum of a sinusoid with/without windowing.
53
54
num_periods: how many periods to compute
55
hamming: boolean whether to apply Hamming window
56
"""
57
signal = thinkdsp.SinSignal(freq=440)
58
duration = signal.period * num_periods
59
wave = signal.make_wave(duration)
60
61
if hamming:
62
wave.hamming()
63
64
print(len(wave.ys), wave.ys[0], wave.ys[-1])
65
spectrum = wave.make_spectrum()
66
spectrum.plot(high=880)
67
68
69
def three_spectrums():
70
"""Makes a plot showing three spectrums for a sinusoid.
71
"""
72
thinkplot.preplot(rows=1, cols=3)
73
74
pyplot.subplots_adjust(wspace=0.3, hspace=0.4,
75
right=0.95, left=0.1,
76
top=0.95, bottom=0.1)
77
78
xticks = range(0, 900, 200)
79
80
thinkplot.subplot(1)
81
thinkplot.config(xticks=xticks)
82
discontinuity(num_periods=30, hamming=False)
83
84
thinkplot.subplot(2)
85
thinkplot.config(xticks=xticks, xlabel='Frequency (Hz)')
86
discontinuity(num_periods=30.25, hamming=False)
87
88
thinkplot.subplot(3)
89
thinkplot.config(xticks=xticks)
90
discontinuity(num_periods=30.25, hamming=True)
91
92
thinkplot.save(root='windowing1')
93
94
95
def window_plot():
96
"""Makes a plot showing a sinusoid, hamming window, and their product.
97
"""
98
signal = thinkdsp.SinSignal(freq=440)
99
duration = signal.period * 10.25
100
wave1 = signal.make_wave(duration)
101
wave2 = signal.make_wave(duration)
102
103
ys = np.hamming(len(wave1.ys))
104
ts = wave1.ts
105
window = thinkdsp.Wave(ys, ts, wave1.framerate)
106
107
wave2.hamming()
108
109
thinkplot.preplot(rows=3, cols=1)
110
111
pyplot.subplots_adjust(wspace=0.3, hspace=0.3,
112
right=0.95, left=0.1,
113
top=0.95, bottom=0.05)
114
115
thinkplot.subplot(1)
116
wave1.plot()
117
thinkplot.config(axis=[0, duration, -1.07, 1.07])
118
119
thinkplot.subplot(2)
120
window.plot()
121
thinkplot.config(axis=[0, duration, -1.07, 1.07])
122
123
thinkplot.subplot(3)
124
wave2.plot()
125
thinkplot.config(axis=[0, duration, -1.07, 1.07],
126
xlabel='Time (s)')
127
128
thinkplot.save(root='windowing2')
129
130
131
def chirp_spectrum():
132
"""Plots the spectrum of a one-second one-octave linear chirp.
133
"""
134
signal = thinkdsp.Chirp(start=220, end=440)
135
wave = signal.make_wave(duration=1)
136
137
thinkplot.preplot(3, cols=3)
138
duration = 0.01
139
wave.segment(0, duration).plot(xfactor=1000)
140
thinkplot.config(ylim=[-1.05, 1.05])
141
142
thinkplot.subplot(2)
143
wave.segment(0.5, duration).plot(xfactor=1000)
144
thinkplot.config(yticklabels='invisible',
145
xlabel='Time (ms)')
146
147
thinkplot.subplot(3)
148
wave.segment(0.9, duration).plot(xfactor=1000)
149
thinkplot.config(yticklabels='invisible')
150
151
thinkplot.save('chirp3')
152
153
154
spectrum = wave.make_spectrum()
155
spectrum.plot(high=700)
156
thinkplot.save('chirp1',
157
xlabel='Frequency (Hz)',
158
ylabel='Amplitude')
159
160
161
def chirp_spectrogram():
162
"""Makes a spectrogram of a one-second one-octave linear chirp.
163
"""
164
signal = thinkdsp.Chirp(start=220, end=440)
165
wave = signal.make_wave(duration=1, framerate=11025)
166
spectrogram = wave.make_spectrogram(seg_length=512)
167
168
print('time res', spectrogram.time_res)
169
print('freq res', spectrogram.freq_res)
170
print('product', spectrogram.time_res * spectrogram.freq_res)
171
172
spectrogram.plot(high=700)
173
174
thinkplot.save('chirp2',
175
xlabel='Time (s)',
176
ylabel='Frequency (Hz)')
177
178
179
def overlapping_windows():
180
"""Makes a figure showing overlapping hamming windows.
181
"""
182
n = 256
183
window = np.hamming(n)
184
185
thinkplot.preplot(num=5)
186
start = 0
187
for i in range(5):
188
xs = np.arange(start, start+n)
189
thinkplot.plot(xs, window)
190
191
start += n/2
192
193
thinkplot.save(root='windowing3',
194
xlabel='Index',
195
axis=[0, 800, 0, 1.05])
196
197
198
def invert_spectrogram():
199
"""Tests Spectrogram.make_wave.
200
"""
201
signal = thinkdsp.Chirp(start=220, end=440)
202
wave = signal.make_wave(duration=1, framerate=11025)
203
spectrogram = wave.make_spectrogram(seg_length=512)
204
205
wave2 = spectrogram.make_wave()
206
207
for i, (y1, y2) in enumerate(zip(wave.ys, wave2.ys)):
208
if abs(y1 - y2) > 1e-14:
209
print(i, y1, y2)
210
211
212
def main():
213
chirp_spectrum()
214
chirp_spectrogram()
215
overlapping_windows()
216
window_plot()
217
three_spectrums()
218
219
220
if __name__ == '__main__':
221
main()
222
223