【问题标题】:Python Scipy FFT wav filesPython Scipy FFT wav 文件
【发布时间】:2014-06-16 03:48:19
【问题描述】:

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

【问题讨论】:

  • 尝试谷歌搜索每个步骤(读取 wav 文件,对数据使用 FFT)。应该不难,遇到困难就回来。

标签: python scipy fft


【解决方案1】:

Python 提供了几个 api 来相当快地完成这项工作。我从this link 下载了sheep-bleats 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()

这是输入信号的图:

这是频谱

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

k = arange(len(data))
T = len(data)/fs  # where fs is the sampling frequency
frqLabel = k/T  

如果你必须处理一堆文件,你可以将其实现为一个函数: 把这些行放在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')

说,我在当前工作目录中有test.wavtest2.wavpython提示界面中的以下命令就足够了: 导入测试2 地图(test2.f,['test.wav','test2.wav'])

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

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

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

【讨论】:

  • 好答案!您可能想要删除 >>> 以便 OP 和其他人可以复制和粘贴。我还发现,如果您的代码绘制图表时包含图片,这有助于答案。
  • 谢谢。我已经更新了帖子,删除了提示并添加了新图片。
  • 如何连接多个 wav 文件?我有很多小的 wav 文件。
  • a = data.T[0]应该是a = data.T[0:data.size]
  • @Boris 的pythonic 方式是d = len(c) // 2,它立即执行整数除法并避免任何需要转换结果。考虑到它的年龄,答案可能是为python2编写的,如果两个操作数都是整数,那么整数除法是标准,在python3中它默认为浮点除法。
【解决方案2】:

您可以使用以下代码进行转换:

#!/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()

【讨论】:

  • 效果很好。但是,您需要修复除法运算符;将 N/2 更改为 N//2 因为该操作会创建一个浮点数
  • @pbgnz 仅适用于 Python 3,或者如果您在 Python 2 中使用了 from __future__ import division
猜你喜欢
  • 2014-09-16
  • 2017-09-11
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 2018-05-08
  • 2012-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多