目的:
从wav格式音频中提取出某单一频率的信号,并以时域图形式呈现。
目前的实现思路:
通过FFT变换得到频域表达,包括各频率分量freqs与对应的振幅值fft_data,假设需要提取的单一频率为500hz,在频率分量中找到500hz所对应的索引(经FFT变换后得到的频率分量非整数,故无500hz存在,选择最接近500hz的频率分量,即500.00011hz),如下图所示:
因此,索引为6035,提取出fft_data[6035]和fft_data[-6035]即为单一频率500hz的振幅值,之后通过IFFT变换,从频域表达转换为时域表达,得到单一频率的时域图,如下图所示,为一个正弦波,其中左图为完整时间的时域图,右图为选取10ms的时域图:
为了验证上述方法的可靠性,使用带通滤波器方法和上述方法,提取400至500hz频率范围信号并以时域图形式呈现,结果如下图所示:
原始音频全频段
方法一:带通滤波器,允许400~500hz频率声音通过
方法二:提取400~500hz频率索引对应的振幅值,通过逆fft变换得到
由上可知,对于提取某频率范围信号,使用方法一和方法二得到同样的结果,认为方法二可靠,对于提取单一频率信号,带通滤波器不适用,使用方法二得到的单频信号为标准正弦波,但由于现场声音复杂,应该是同一频率多个相位的正弦波叠加,而非标准正弦波,存在矛盾。
或者有无其他提取单一频率信号的方法可供参考学习,请求指导!
# 读取WAV文件
sample_rate, audio_data = wavfile.read('E:\\Pycharmprojects\\2025\\shuiting\\BS\\MDJL\\data\\BS_MDJL_20250115_233221.wav')
# 计算FFT
fft_data = np.fft.fft(audio_data)
# 计算频率轴
freqs = np.fft.fftfreq(len(audio_data), 1/sample_rate)
# 找到500Hz的频率索引
target_freq = 500
target_idx = np.argmin(np.abs(freqs - target_freq))
# 提取大于等于500小于501hz的分量
fft_data_filtered = np.zeros_like(fft_data)
fft_data_filtered[target_idx] = fft_data[target_idx]
fft_data_filtered[-target_idx] = fft_data[-target_idx] # 考虑到对称性
# 通过逆FFT转换回时域
filtered_signal = np.fft.ifft(fft_data_filtered)
# 绘制时域图
plt.figure(figsize=(8, 6))
time1 = np.linspace(0, len(audio_data) / sample_rate, len(audio_data))
filtered_audio_data = filtered_signal.real
# 绘制完整时间轴的时域图
plt.plot(time1, filtered_audio_data, label=str(target_freq) + 'Hz Signal')
plt.title('时域图')
plt.xlabel('时间(s)')
plt.ylabel('振幅')
# plt.ylim(-500, 500) # 设置y轴范围
plt.legend(loc='upper right')
plt.grid(True)
plt.tight_layout()
plt.show()