Python Scipy FFT wav files

前端 未结 2 1798
闹比i
闹比i 2020-11-27 13:22

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?

相关标签:
2条回答
  • 2020-11-27 13:28

    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[0] # 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:
    signal

    Here is the spectrum 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 test2.py:

    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[0] # 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 test.wav and test2.wav in the current working dir, the following command in python prompt interface is sufficient: import test2 map(test2.f, ['test.wav','test2.wav'])

    Assuming you have 100 such files and you do not want to type their names individually, you need the glob package:

    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.

    0 讨论(0)
  • 2020-11-27 13:49

    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[0]
    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[1]-t[0])
    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()
    
    0 讨论(0)
提交回复
热议问题