簡體   English   中英

這是讀取音頻文件FFT的正確方法嗎? (python + wav)

[英]Is this the correct way to read FFT of a audio file? (python + wav)

音頻文件是16位單聲道PCM音頻文件,具有不同的采樣率,長度為10-30ms。

import struct
from pydub import AudioSegment
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack

sound = AudioSegment.from_wav("3000hz.wav")

raw_data = sound.raw_data# needs to be mono
sample_rate = sound.frame_rate
sample_size = sound.sample_width
channels = sound.channels

fmt = "%ih" % sound.frame_count() * channels
amplitudes= struct.unpack(fmt, raw_data)
yVals = scipy.fftpack.fft(amplitudes)

plt.plot(abs(yVals[:(len(yVals)/2)-1]),'r')
plt.show()

帶有3000hz wav文件的輸出(來自在線正弦波發生器)產生了不錯的FFT,但峰值為9000,而不是3000。在其他測試中,相差3倍是一致的。 這個可以嗎? 代碼正確嗎?

通過僅使用y數組而沒有對應的x數組調用plt.plot() ,它將使用0, 1, ..., N-1作為x值。 這不是我們真正想要的,我們想要x軸上的頻率。

讓我們用“ bin index”表示您現在在圖中看到的x值。 假設數組的長度為N ,采樣頻率為fs 在計算FFT時,bin索引0對應於0 Hz的頻率。 下一個二進制索引1對應於頻率fs / N Hz。 這是因為FFT將具有N值,並且從0 Hz到fs Hz,因此每個步都是fs / N Hz。 因此,下一個bin對應於2 * fs / N Hz,依此類推。 而最后一個N-1箱是(N-1)/N * fs Hz,所以幾乎是fs Hz。

如果要創建一個振幅譜與頻率關系圖,則需要手動創建一個頻率矢量,其中包含每個倉位索引的實際頻率。 幸運的是, scipy.fftpack包含了以下功能: fftfreq

freq = scipy.fftpack.fftfreq(n=N, d=1.0 / fs)

然后,我們可以修改對plt.plot()的調用,以將freq用作x值而不是0 ... N-1

plt.plot(freq, abs(yVals), 'r')

這樣,峰值應該在正確的位置。

如果您只想查看單面頻譜,則可以像在問題代碼中已經yVals那樣對freqyVals進行裁剪。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM