【问题标题】:Plotting fft from a wav file using python使用python从wav文件中绘制fft
【发布时间】:2015-02-03 01:37:05
【问题描述】:

我正在尝试绘制 wav 文件的频谱,但似乎频谱总是与时域信号匹配,代码如下。

import matplotlib.pyplot as plt
import numpy as np


def plot(data):
    plt.plot(data, color='steelblue')
    plt.figure()
    plt.show()

rate, wav_data = wavfile.read("audio_self/on/on.wav")
plot(wav_data)
plot(np.abs(np.fft.fft(wav_data)))

我是不是做错了什么?

【问题讨论】:

  • 您可能在零处有一个大的尖峰,导致其余数据被缩放到不可见。尝试以不同的颜色绘制 FFT。
  • 注意你调用plotWav,但是你定义了plot。除此之外,您的代码应该可以工作。此外,音频文件应该是单声道的。

标签: python audio signals signal-processing fft


【解决方案1】:

如果您想要两个单独的立体声轨道分别用于左右声道,然后分别制作每个单独的图表,那么除非您像 Frank Zalkow 所说的那样将轨道设为单声道,否则读数会更加准确。这是将立体声轨道分成左右声道的方法:

"""
Plot
"""
#Plots a stereo .wav file
#Decibels on the y-axis
#Frequency Hz on the x-axis

import matplotlib.pyplot as plt
import numpy as np

from pylab import*
from scipy.io import wavfile


def plot(file_name):

    sampFreq, snd = wavfile.read(file_name)

    snd = snd / (2.**15) #convert sound array to float pt. values

    s1 = snd[:,0] #left channel

    s2 = snd[:,1] #right channel

    n = len(s1)
    p = fft(s1) # take the fourier transform of left channel

    m = len(s2) 
    p2 = fft(s2) # take the fourier transform of right channel

    nUniquePts = ceil((n+1)/2.0)
    p = p[0:nUniquePts]
    p = abs(p)

    mUniquePts = ceil((m+1)/2.0)
    p2 = p2[0:mUniquePts]
    p2 = abs(p2)

'''
Left Channel
'''
   p = p / float(n) # scale by the number of points so that
             # the magnitude does not depend on the length 
             # of the signal or on its sampling frequency  
   p = p**2  # square it to get the power 




# multiply by two (see technical document for details)
# odd nfft excludes Nyquist point
    if n % 2 > 0: # we've got odd number of points fft
        p[1:len(p)] = p[1:len(p)] * 2
    else:
        p[1:len(p) -1] = p[1:len(p) - 1] * 2 # we've got even number of points fft

     freqArray = arange(0, nUniquePts, 1.0) * (sampFreq / n);
     plt.plot(freqArray/1000, 10*log10(p), color='k')
     plt.xlabel('LeftChannel_Frequency (kHz)')
     plt.ylabel('LeftChannel_Power (dB)')
     plt.show()

'''
Right Channel
'''
    p2 = p2 / float(m) # scale by the number of points so that
             # the magnitude does not depend on the length 
             # of the signal or on its sampling frequency  
    p2 = p2**2  # square it to get the power 




# multiply by two (see technical document for details)
# odd nfft excludes Nyquist point
    if m % 2 > 0: # we've got odd number of points fft
         p2[1:len(p2)] = p2[1:len(p2)] * 2
    else:
         p2[1:len(p2) -1] = p2[1:len(p2) - 1] * 2 # we've got even number of points fft

    freqArray2 = arange(0, mUniquePts, 1.0) * (sampFreq / m);
    plt.plot(freqArray2/1000, 10*log10(p2), color='k')
    plt.xlabel('RightChannel_Frequency (kHz)')
    plt.ylabel('RightChannel_Power (dB)')
    plt.show()

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2013-08-11
    • 2014-06-16
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2012-05-26
    • 1970-01-01
    相关资源
    最近更新 更多