This is a part of the solution for the problem I described here.
The code below uses Welch’s method to estimate the spectrum of a wave.
import scipy.fftpack as fftpack import numpy as np import math class FrequencySpectrum: OVERLAP = 0.5 def averaged_spectrum_for_samples(self, audioSamples, windowSize): """Computes the frequency spectrum for the discrete signal defined by audioSamples. Uses Welch's method to divide the signal into overlapping windows. The periodograms of each window are then averaged to measure the power spectrum over the whole signal. audioSamples is a 1-D array Returns an arrray of spectrum components of length windowSize""" windowStep = int(windowSize * FrequencySpectrum.OVERLAP) windows = range(0, audioSamples.shape[0]-windowSize, windowStep) windowSamples = [audioSamples[w:w+windowSize] for w in windows] windowSpectra = np.array([self.spectrum_for_samples(s) for s in windowSamples]) return np.mean(windowSpectra, 0) def spectrum_for_samples(self, audioSamples): """Computes the frequency spectrum of the discrete signal given by audioSamples. audioSamples is a 1-D array The returned spectrum will have as many components as audioSamples has components. All the components of the spectra will be positive, real numbers""" clipped = self._apply_window(audioSamples) frequencies = fftpack.fft(clipped) spectrum = np.array([f*np.conj(f) for f in frequencies], dtype=float) return 10*np.log10(1e-20 + spectrum) def _apply_window(self, audioSamples): """Applies a window function to the discrete signal defined in audioSamples. audioSamples is a 1-D array""" window = np.hanning(audioSamples.shape[0]) return audioSamples * window
import scipy.fftpack as fftpack
import numpy as np
import math
class FrequencySpectrum:
OVERLAP = 0.5
def averaged_spectrum_for_samples(self, audioSamples, windowSize):
"""Computes the frequency spectrum for the discrete signal
defined by audioSamples.
Uses Welch's method to divide the signal into overlapping windows.
The periodograms of each window are then averaged to measure the
power spectrum over the whole signal.
audioSamples is a 1-D array
Returns an arrray of spectrum components of length windowSize"""
windowStep = int(windowSize * FrequencySpectrum.OVERLAP)
windows = range(0, audioSamples.shape[0]-windowSize, windowStep)
windowSamples = [audioSamples[w:w+windowSize] for w in windows]
windowSpectra = np.array([self.spectrum_for_samples(s)
for s in windowSamples])
return np.mean(windowSpectra, 0)
def spectrum_for_samples(self, audioSamples):
"""Computes the frequency spectrum of the discrete signal
given by audioSamples.
audioSamples is a 1-D array
The returned spectrum will have as many components
as audioSamples has components. All the components
of the spectra will be positive, real numbers"""
clipped = self._apply_window(audioSamples)
frequencies = fftpack.fft(clipped)
spectrum = np.array([f*np.conj(f) for f in frequencies], dtype=float)
return 10*np.log10(1e-20 + spectrum)
def _apply_window(self, audioSamples):
"""Applies a window function to the discrete signal
defined in audioSamples.
audioSamples is a 1-D array"""
window = np.hanning(audioSamples.shape[0])
return audioSamples * window
Pingback: Finding Pauses: The Solution (1)