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 2014 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
12
13
import thinkdsp
14
import thinkplot
15
16
PI2 = math.pi * 2
17
18
19
def synthesize1(amps, freqs, ts):
20
"""Synthesize a mixture of complex sinusoids with given amps and freqs.
21
22
amps: amplitudes
23
freqs: frequencies in Hz
24
ts: times to evaluate the signal
25
26
returns: wave array
27
"""
28
components = [thinkdsp.ComplexSinusoid(freq, amp)
29
for amp, freq in zip(amps, freqs)]
30
signal = thinkdsp.SumSignal(*components)
31
32
ys = signal.evaluate(ts)
33
return ys
34
35
36
def synthesize2(amps, freqs, ts):
37
"""Synthesize a mixture of cosines with given amps and freqs.
38
39
amps: amplitudes
40
freqs: frequencies in Hz
41
ts: times to evaluate the signal
42
43
returns: wave array
44
"""
45
i = complex(0, 1)
46
args = numpy.outer(ts, freqs)
47
M = numpy.exp(i * PI2 * args)
48
ys = numpy.dot(M, amps)
49
return ys
50
51
52
def analyze1(ys, freqs, ts):
53
"""Analyze a mixture of cosines and return amplitudes.
54
55
Works for the general case where M is not orthogonal.
56
57
ys: wave array
58
freqs: frequencies in Hz
59
ts: times where the signal was evaluated
60
61
returns: vector of amplitudes
62
"""
63
args = numpy.outer(ts, freqs)
64
M = numpy.exp(i * PI2 * args)
65
amps = numpy.linalg.solve(M, ys)
66
return amps
67
68
69
def analyze2(ys, freqs, ts):
70
"""Analyze a mixture of cosines and return amplitudes.
71
72
Assumes that freqs and ts are chosen so that M is orthogonal.
73
74
ys: wave array
75
freqs: frequencies in Hz
76
ts: times where the signal was evaluated
77
78
returns: vector of amplitudes
79
"""
80
81
def analyze2(ys, freqs, ts):
82
args = numpy.outer(ts, freqs)
83
M = numpy.exp(i * PI2 * args)
84
amps = M.conj().transpose().dot(ys) / N
85
return amps
86
87
88
def dft(ys):
89
i = complex(0, 1)
90
N = len(ys)
91
ts = numpy.arange(N) / N
92
freqs = numpy.arange(N)
93
args = numpy.outer(ts, freqs)
94
M = numpy.exp(i * PI2 * args)
95
amps = M.conj().transpose().dot(ys)
96
return amps
97
98
99
def idft(amps):
100
ys = dft(amps) / N
101
return ys
102
103
104
def make_figures():
105
"""Makes figures showing complex signals.
106
"""
107
amps = numpy.array([0.6, 0.25, 0.1, 0.05])
108
freqs = [100, 200, 300, 400]
109
framerate = 11025
110
111
ts = numpy.linspace(0, 1, framerate)
112
ys = synthesize1(amps, freqs, ts)
113
print(ys)
114
115
thinkplot.preplot(2)
116
n = framerate / 25
117
thinkplot.plot(ts[:n], ys[:n].real, label='real')
118
thinkplot.plot(ts[:n], ys[:n].imag, label='imag')
119
thinkplot.save(root='dft1',
120
xlabel='Time (s)',
121
ylim=[-1.05, 1.05],
122
loc='lower right')
123
124
ys = synthesize2(amps, freqs, ts)
125
126
amps2 = amps * numpy.exp(1.5j)
127
ys2 = synthesize2(amps2, freqs, ts)
128
129
thinkplot.preplot(2)
130
thinkplot.plot(ts[:n], ys.real[:n], label=r'$\phi_0 = 0$')
131
thinkplot.plot(ts[:n], ys2.real[:n], label=r'$\phi_0 = 1.5$')
132
thinkplot.save(root='dft2',
133
xlabel='Time (s)',
134
ylim=[-1.05, 1.05],
135
loc='lower right')
136
137
138
framerate = 10000
139
signal = thinkdsp.SawtoothSignal(freq=500)
140
wave = signal.make_wave(duration=0.1, framerate=framerate)
141
hs = dft(wave.ys)
142
amps = numpy.absolute(hs)
143
144
N = len(hs)
145
fs = numpy.arange(N) * framerate / N
146
thinkplot.plot(fs, amps)
147
thinkplot.save(root='dft3',
148
xlabel='Frequency (Hz)',
149
ylabel='Amplitude',
150
legend=False)
151
152
153
154
def main():
155
numpy.set_printoptions(precision=3, suppress=True)
156
make_figures()
157
158
159
if __name__ == '__main__':
160
main()
161
162