Python Scipy FFT wav 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23377665/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:52:45  来源:igfitidea点击:

Python Scipy FFT wav files

pythonscipyfft

提问by user1802143

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?

我有一些 wav 文件。我想使用 SciPy FFT 来绘制这些 wav 文件的频谱。我该怎么做呢?

回答by yshk

Pythonprovides 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 cdthere within terminal. These lines in the pythonprompt should be enough: (omit >>>)

Python提供了几个 api 来相当快地做到这一点。我从这个链接下载了羊叫声 wav 文件。您可以将其保存在桌面和cd终端内。python提示中的这些行应该足够了:(省略>>>

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.

为了获得正确的输出,您必须将 转换xlabel为频谱图的频率。

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:

如果您必须处理一堆文件,您可以将其实现为一个函数:将这些行放在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.wavand test2.wavin the current working dir, the following command in pythonprompt interface is sufficient: import test2 map(test2.f, ['test.wav','test2.wav'])

说,我有test.wav并且test2.wav在当前的工作目录中,python提示界面中的以下命令就足够了: 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 globpackage:

假设您有 100 个这样的文件并且您不想单独键入它们的名称,则需要以下glob包:

import glob
import test2
files = glob.glob('./*.wav')
for ele in files:
    f(ele)
quit()

You will need to add getparamsin the test2.f if your .wav files are not of the same bit.

getparams如果您的 .wav 文件不是同一位,您将需要添加test2.f。

回答by bunkus

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()