Each Answer to this Q is separated by one/two green lines.
I have a handful of wav files. I’d like to use SciPy FFT to plot the frequency spectrum of these wav files. How would I go about doing this?
Python provides several api to do this fairly quickly. I download the sheep-bleats wav file from this link. You can save it on the desktop and
cd there within terminal. These lines in the
python prompt should be enough: (omit
import matplotlib.pyplot as plt from scipy.fftpack import fft from scipy.io import wavfile # get the api fs, data = wavfile.read('test.wav') # load the data a = data.T # this is a two channel soundtrack, I get the first track b=[(ele/2**8.)*2-1 for ele in a] # this is 8-bit track, b is now normalized on [-1,1) c = fft(b) # calculate fourier transform (complex numbers list) d = len(c)/2 # you only need half of the fft list (real signal symmetry) plt.plot(abs(c[:(d-1)]),'r') plt.show()
Here is a plot for the input signal:
Here is the spectrum
For the correct output, you will have to convert the
xlabelto the frequency for the spectrum plot.
k = arange(len(data)) T = len(data)/fs # where fs is the sampling frequency frqLabel = k/T
If you are have to deal with a bunch of files, you can implement this as a function:
put these lines in the
import matplotlib.pyplot as plt from scipy.io import wavfile # get the api from scipy.fftpack import fft from pylab import * def f(filename): fs, data = wavfile.read(filename) # load the data a = data.T # this is a two channel soundtrack, I get the first track b=[(ele/2**8.)*2-1 for ele in a] # this is 8-bit track, b is now normalized on [-1,1) c = fft(b) # create a list of complex number d = len(c)/2 # you only need half of the fft list plt.plot(abs(c[:(d-1)]),'r') savefig(filename+'.png',bbox_inches="tight")
Say, I have
test2.wav in the current working dir, the following command in
python prompt interface is sufficient:
Assuming you have 100 such files and you do not want to type their names individually, you need the
import glob import test2 files = glob.glob('./*.wav') for ele in files: f(ele) quit()
You will need to add
getparams in the test2.f if your .wav files are not of the same bit.
You could use the following code to do the transform:
#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import print_function import scipy.io.wavfile as wavfile import scipy import scipy.fftpack import numpy as np from matplotlib import pyplot as plt fs_rate, signal = wavfile.read("output.wav") print ("Frequency sampling", fs_rate) l_audio = len(signal.shape) print ("Channels", l_audio) if l_audio == 2: signal = signal.sum(axis=1) / 2 N = signal.shape print ("Complete Samplings N", N) secs = N / float(fs_rate) print ("secs", secs) Ts = 1.0/fs_rate # sampling interval in time print ("Timestep between samples Ts", Ts) t = scipy.arange(0, secs, Ts) # time vector as scipy arange field / numpy.ndarray FFT = abs(scipy.fft(signal)) FFT_side = FFT[range(N/2)] # one side FFT range freqs = scipy.fftpack.fftfreq(signal.size, t-t) fft_freqs = np.array(freqs) freqs_side = freqs[range(N/2)] # one side frequency range fft_freqs_side = np.array(freqs_side) plt.subplot(311) p1 = plt.plot(t, signal, "g") # plotting the signal plt.xlabel('Time') plt.ylabel('Amplitude') plt.subplot(312) p2 = plt.plot(freqs, FFT, "r") # plotting the complete fft spectrum plt.xlabel('Frequency (Hz)') plt.ylabel('Count dbl-sided') plt.subplot(313) p3 = plt.plot(freqs_side, abs(FFT_side), "b") # plotting the positive fft spectrum plt.xlabel('Frequency (Hz)') plt.ylabel('Count single-sided') plt.show()