我正在尝试查找在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/

10-12 07:25