|
| 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 numpy |
| 11 | +import thinkstats2 |
| 12 | +import thinkdsp |
| 13 | +import thinkplot |
| 14 | + |
| 15 | +""" |
| 16 | +Samples used in this file |
| 17 | +
|
| 18 | +http://www.freesound.org/people/ciccarelli/sounds/132736/download/ |
| 19 | +132736__ciccarelli__ocean-waves.wav |
| 20 | +
|
| 21 | +http://www.freesound.org/people/Q.K./sounds/56311/download/ |
| 22 | +56311__q-k__rain-06.wav |
| 23 | +
|
| 24 | +http://www.freesound.org/people/erkanozan/sounds/51743/download/ |
| 25 | +51743__erkanozan__applause.wav |
| 26 | +
|
| 27 | +http://www.freesound.org/people/britishpirate93/sounds/162313/download/ |
| 28 | +162313__britishpirate93__16-inch-crash.wav |
| 29 | +
|
| 30 | +""" |
| 31 | + |
| 32 | +FILENAMES = [ |
| 33 | + '132736__ciccarelli__ocean-waves.wav', |
| 34 | + '56311__q-k__rain-06.wav', |
| 35 | + '51743__erkanozan__applause.wav', |
| 36 | + '162313__britishpirate93__16-inch-crash.wav', |
| 37 | + '75341__neotone__cymbol-scraped.wav', |
| 38 | + '181934__landub__applause2.wav', |
| 39 | + '87594__ohrwurm__occurs-applause.wav', |
| 40 | + '104466__dkmedic__t-flush.wav', |
| 41 | + '180929__docquesting__crowd-noise.wav', |
| 42 | + '695__memexikon__ocarina.wav', |
| 43 | +] |
| 44 | + |
| 45 | +STARTS = [0.6, 2.0, 0.1, 0.3, 0.1, 1.0, 11.0, 4.0, 0.5, 0.5] |
| 46 | + |
| 47 | + |
| 48 | + |
| 49 | +def segment_spectrum(filename, start, duration=1.0): |
| 50 | + """Plots the spectrum of a segment of a WAV file. |
| 51 | +
|
| 52 | + Output file names are the given filename plus a suffix. |
| 53 | +
|
| 54 | + filename: string |
| 55 | + start: start time in s |
| 56 | + duration: segment length in s |
| 57 | + """ |
| 58 | + wave = thinkdsp.read_wave(filename) |
| 59 | + plot_waveform(wave) |
| 60 | + |
| 61 | + # extract a segment |
| 62 | + segment = wave.segment(start, duration) |
| 63 | + segment.ys = segment.ys[:1024] |
| 64 | + print(len(segment.ys)) |
| 65 | + |
| 66 | + segment.normalize() |
| 67 | + segment.apodize() |
| 68 | + spectrum = segment.make_spectrum() |
| 69 | + |
| 70 | + segment.play() |
| 71 | + |
| 72 | + # plot the spectrum |
| 73 | + n = len(spectrum.hs) |
| 74 | + spectrum.plot() |
| 75 | + |
| 76 | + thinkplot.save(root=filename, |
| 77 | + xlabel='frequency (Hz)', |
| 78 | + ylabel='amplitude density') |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | +def plot_waveform(wave, start=1.30245, duration=0.00683): |
| 83 | + """Plots a short window from a wave. |
| 84 | +
|
| 85 | + duration: float |
| 86 | + """ |
| 87 | + segment = wave.segment(start, duration) |
| 88 | + segment.normalize() |
| 89 | + |
| 90 | + segment.plot() |
| 91 | + thinkplot.save(root='waveform', |
| 92 | + xlabel='time (s)', |
| 93 | + axis=[0, duration, -1.05, 1.05]) |
| 94 | + |
| 95 | + |
| 96 | +def process_files(): |
| 97 | + indices = range(len(FILENAMES)) |
| 98 | + #indices = [9] |
| 99 | + |
| 100 | + for i, (filename, start) in enumerate(zip(FILENAMES, STARTS)): |
| 101 | + if i in indices: |
| 102 | + segment_spectrum(filename, start) |
| 103 | + |
| 104 | + |
| 105 | +def make_periodogram(signal, n=1000): |
| 106 | + """Generates n spectra and plots their average. |
| 107 | +
|
| 108 | + signal: Signal object |
| 109 | + n: number of spectra to average |
| 110 | + """ |
| 111 | + specs = [] |
| 112 | + for i in range(n): |
| 113 | + wave = signal.make_wave(duration=1.0, framerate=1024) |
| 114 | + spec = wave.make_spectrum() |
| 115 | + specs.append(spec) |
| 116 | + |
| 117 | + spectrum = sum(specs) |
| 118 | + print(spectrum.estimate_slope()) |
| 119 | + spectrum.plot_power() |
| 120 | + thinkplot.show(xlabel='frequency (Hz)', |
| 121 | + ylabel='power density', |
| 122 | + xscale='log', |
| 123 | + yscale='log') |
| 124 | + |
| 125 | + |
| 126 | +def main(): |
| 127 | + thinkdsp.random_seed(19) |
| 128 | + signal = thinkdsp.BrownianNoise() |
| 129 | + make_periodogram(signal) |
| 130 | + |
| 131 | + |
| 132 | +if __name__ == '__main__': |
| 133 | + main() |
0 commit comments