无法正确生成 Numpy FFT

Can't generate Numpy FFT properly

我试图找到人们在 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 的第二个大峰值对应于 "negative frequency":DFT 输出的后半部分是冗余的,是前半部分的镜像副本。