我正在尝试查找在wav文件中讲话的人的频谱,但是在此之前,我想我会尝试仅使用一个简单的200hz音频文件来做到这一点。在下面的代码中,我读了200hz文件并将其绘制在屏幕上。 注意:200hz文件的采样率为192000。我的块大小是该值的1/10,因此每19200个采样
from scipy.io import wavfile
import numpy as np
### This is just for drawing
import matplotlib.pyplot as plt
import matplotlib.animation as animation
### Above is for drawing
# Read the .wav file
sample_rate, data = wavfile.read('200hz.wav')
CHUNK_SAMPLES_PER_SECOND = 10
CHUNK = sample_rate / CHUNK_SAMPLES_PER_SECOND
# Now compute the spectrum on a given frame
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
# Now, lets just draw the plot
for frame in range(len(data) / CHUNK):
ax1.clear()
frame_data = data[frame * CHUNK:(frame + 1) * CHUNK, 0] # normally 2 channel, take 1st channel
frame_data = frame_data * 1.0 / frame_data.max()
#### Below, activate those to use the FFT ####
# frame_data = np.fft.fft(frame_data) # Calculate FFT on dataset
# frame_data = frame_data * 1.0 / frame_data.max() # Normalize FFT data
# ax1.set_xlabel('frequency')
ax1.plot(np.abs(frame_data), '-')
ax1.set_xlabel('sample')
ax1.set_ylabel('volume')
plt.pause(1.0 / CHUNK_SAMPLES_PER_SECOND)
上面的代码产生:
对我来说,这看起来是正确的。由于我仅以192000的采样率进行19200个采样,因此绘图应为0.1秒。因此,一个200 Hz的信号应具有大约20个全波。
然后,当我通过取消注释来启用以下代码时:
#### Below, activate those to use the FFT ####
# frame_data = np.fft.fft(frame_data) # Calculate FFT on dataset
# frame_data = frame_data * 1.0 / frame_data.max() # Normalize FFT data
# ax1.set_xlabel('frequency')
它会生成一个看起来很时髦的fft图表:
我想我期望它显示的是一个大约200hz的峰值,或者至少一个明确定义的信号频率峰值。谢谢!
编辑:
我添加了我正在使用here的实际音频文件。
我还将Y轴调整为对数刻度,并将x轴范围调整为以下值:
最佳答案
您的频率轴从0到19200。这是不正确的,通过占用较小的块,您并没有降低采样频率。它应该从0到192000。
因此,假设沿该轴的每个值都乘以10。这样,您将在200 Hz处看到一个峰值,如预期的那样,并且在该整数倍处得到了一堆峰值,这是预期的。请注意,您的样品不是完美的正弦波,由于形状原因,它会产生很多谐波。
还要注意,接近192000 Hz的第二个大峰值对应于“负频率”:DFT输出的后一半是冗余的,是前一半的镜像副本。
关于python - 无法正确产生Numpy FFT,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51888790/