无法正确生成 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 输出的后半部分是冗余的,是前半部分的镜像副本。
我试图找到人们在 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 输出的后半部分是冗余的,是前半部分的镜像副本。