这是读取音频文件的FFT的正确方法是什么? (蟒+ WAV)

问题描述 投票:0回答:1

音频文件是具有变化samplerates和10-30ms的长度16位单声道PCM音频文件。

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倍,是其他测试是一致的。这个可以吗?而且是代码是否正确?

python audio fft wav
1个回答
1
投票

通过调用plt.plot()只有一个y阵列和没有相应x阵列,它将使用0, 1, ..., N-1作为x值。这不是我们真正想要的,我们希望在x轴的频率。

让我们来表示你的情节,现在看到x值由“点索引”。让该阵列的长度是N和取样频率是fs。当计算的FFT中,时段索引0对应于0 Hz的频率。下一个二进制位索引1对应于频率fs / N赫兹。这是因为FFT将有N值和0赫兹到fs赫兹,所以每一步都是fs / N赫兹。因此,下一个区段对应于2 * fs / N赫兹,等等。而最后仓N-1(N-1)/N * fs赫兹,所以几乎fs赫兹。

如果我们要创造一个你有幅度谱与频率的情节,那么我们需要手工创建一个包含每个分级指数的实际频率的频率向量。幸运的是,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')

就这样,高峰期应该是在正确的位置。

如果你只希望看到一个单面的频谱,那么你就可以裁剪都freqyVals像你在问题的代码已经这样做了。

© www.soinside.com 2019 - 2024. All rights reserved.