📚 The CoCalc Library - books, templates and other resources
License: OTHER
"""This file contains code used in "Think DSP",1by Allen B. Downey, available from greenteapress.com23Copyright 2014 Allen B. Downey4License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html5"""67from __future__ import print_function, division89import numpy as np1011import thinkdsp12import thinkplot1314PI2 = np.pi * 2151617def synthesize1(amps, fs, ts):18"""Synthesize a mixture of cosines with given amps and fs.1920amps: amplitudes21fs: frequencies in Hz22ts: times to evaluate the signal2324returns: wave array25"""26components = [thinkdsp.CosSignal(freq, amp)27for amp, freq in zip(amps, fs)]28signal = thinkdsp.SumSignal(*components)2930ys = signal.evaluate(ts)31return ys323334def synthesize2(amps, fs, ts):35"""Synthesize a mixture of cosines with given amps and fs.3637amps: amplitudes38fs: frequencies in Hz39ts: times to evaluate the signal4041returns: wave array42"""43args = np.outer(ts, fs)44M = np.cos(PI2 * args)45ys = np.dot(M, amps)46return ys474849def analyze1(ys, fs, ts):50"""Analyze a mixture of cosines and return amplitudes.5152Works for the general case where M is not orthogonal.5354ys: wave array55fs: frequencies in Hz56ts: times where the signal was evaluated5758returns: vector of amplitudes59"""60args = np.outer(ts, fs)61M = np.cos(PI2 * args)62amps = np.linalg.solve(M, ys)63return amps646566def analyze2(ys, fs, ts):67"""Analyze a mixture of cosines and return amplitudes.6869Assumes that fs and ts are chosen so that M is orthogonal.7071ys: wave array72fs: frequencies in Hz73ts: times where the signal was evaluated7475returns: vector of amplitudes76"""77args = np.outer(ts, fs)78M = np.cos(PI2 * args)79amps = np.dot(M, ys) / 280return amps818283def dct_iv(ys):84"""Computes DCT-IV.8586ys: wave array8788returns: vector of amplitudes89"""90N = len(ys)91ts = (0.5 + np.arange(N)) / N92fs = (0.5 + np.arange(N)) / 293args = np.outer(ts, fs)94M = np.cos(PI2 * args)95amps = np.dot(M, ys) / 296return amps979899def synthesize_example():100"""Synthesizes a sum of sinusoids and plays it.101"""102amps = np.array([0.6, 0.25, 0.1, 0.05])103fs = [100, 200, 300, 400]104105framerate = 11025106ts = np.linspace(0, 1, 11025)107ys = synthesize2(amps, fs, ts)108wave = thinkdsp.Wave(ys, framerate)109wave.normalize()110wave.apodize()111wave.play()112113n = len(fs)114amps2 = analyze1(ys[:n], fs, ts[:n])115print(amps)116print(amps2)117118119def test1():120amps = np.array([0.6, 0.25, 0.1, 0.05])121N = 4.0122time_unit = 0.001123ts = np.arange(N) / N * time_unit124max_freq = N / time_unit / 2125fs = np.arange(N) / N * max_freq126args = np.outer(ts, fs)127M = np.cos(PI2 * args)128return M129130131def test2():132"""133"""134amps = np.array([0.6, 0.25, 0.1, 0.05])135N = 4.0136ts = (0.5 + np.arange(N)) / N137fs = (0.5 + np.arange(N)) / 2138print('amps', amps)139print('ts', ts)140print('fs', fs)141ys = synthesize2(amps, fs, ts)142amps2 = analyze2(ys, fs, ts)143print('amps', amps)144print('amps2', amps2)145146147def test_dct():148"""149"""150amps = np.array([0.6, 0.25, 0.1, 0.05])151N = 4.0152ts = (0.5 + np.arange(N)) / N153fs = (0.5 + np.arange(N)) / 2154ys = synthesize2(amps, fs, ts)155156amps2 = dct_iv(ys)157print('amps', amps)158print('amps2', amps2)159160161def dct_plot():162signal = thinkdsp.TriangleSignal(freq=400)163wave = signal.make_wave(duration=1.0, framerate=10000)164dct = wave.make_dct()165dct.plot()166thinkplot.config(xlabel='Frequency (Hz)', ylabel='DCT')167thinkplot.save(root='dct1',168formats=['pdf', 'eps'])169170171def main():172np.set_printoptions(precision=3, suppress=True)173174test1()175test2()176dct_plot()177178179if __name__ == '__main__':180main()181182183