喜欢大海的CC 2025-02-18 16:42 采纳率: 0%
浏览 36

从wav格式音频中提取出某单一频率的信号

目的:
从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()
  • 写回答

3条回答 默认 最新

  • 阿里嘎多学长 2025-02-18 16:42
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    解决方案

    你可以使用 Python 语言和 SciPy 库来实现从 WAV 文件中提取单一频率的信号。下面是一个示例代码:

    import numpy as np
    from scipy.io import wavfile
    from scipy.fftpack import fft
    
    # 读取 WAV 文件
    sample_rate, data = wavfile.read('input.wav')
    
    # 计算 FFT
    fft_data = fft(data)
    
    # 获取频率数组
    freqs = np.fft.fftfreq(len(data), 1/sample_rate)
    
    # 提取 500 Hz 的频率分量
    index = np.where((freqs >= 490) & (freqs <= 510))[0][0]
    amp = fft_data[index]
    
    # 生成时域图
    time_domain = np.real(np.fft.ifft(fft_data * np.exp(-2j * np.pi * 500 * np.arange(len(data)) / sample_rate)))
    
    # 可视化时域图
    import matplotlib.pyplot as plt
    plt.plot(time_domain)
    plt.xlabel('Time (s)')
    plt.ylabel('Amplitude')
    plt.show()
    

    这个代码首先读取 WAV 文件,然后计算 FFT,获取频率数组。接着,使用 np.where 函数找到 500 Hz 的频率分量的索引,然后提取该频率分量的振幅值。最后,使用 np.realnp.fft.ifft 函数将频域信号转换回时域信号,并可视化时域图。

    请注意,这个代码假设了输入 WAV 文件的采样率为 44.1 kHz,如果你的采样率不同,需要相应地调整代码。

    评论

报告相同问题?

问题事件

  • 创建了问题 2月18日