4. 音频信号中的梳状滤波效应模拟

任务目标

生成一段由多个正弦波叠加而成的音频信号,通过一个简单的梳状滤波器(前馈结构)进行处理,并输出处理前后的音频文件供试听对比,从而直观感知梳状滤波器的“梳齿”状频谱特性对音频信号的影响。

实现原理

梳状滤波器通过在信号上叠加一个延迟后的自身副本实现。前馈梳状滤波器的时域表达式为:y[n] = x[n] + g * x[n - D],其中 D 为延迟样本数,g 为反馈增益。其频率响应呈现周期性峰谷,形似梳齿。本案例使用Python和NumPy实现信号生成与滤波,并将结果写入WAV文件。

完整代码

import numpy as np
from scipy.io import wavfile

# 参数设置
sr = 44100                # 采样率
duration = 3.0            # 时长(秒)
freqs = [220, 440, 880, 1760]  # 四个正弦波频率(Hz)
amps = [0.5, 0.3, 0.2, 0.1]    # 对应幅度
D = int(0.005 * sr)       # 延迟5ms
g = 0.7                   # 反馈增益

# 1. 生成多正弦叠加信号
t = np.arange(int(sr * duration)) / sr
x = np.zeros_like(t)
for f, a in zip(freqs, amps):
    x += a * np.sin(2 * np.pi * f * t)

# 归一化到[-1, 1]
x = x / np.max(np.abs(x))

# 2. 前馈梳状滤波
y = np.zeros_like(x)
y[:D] = x[:D]  # 前D个样本无延迟分量
for n in range(D, len(x)):
    y[n] = x[n] + g * x[n - D]

# 归一化
y = y / np.max(np.abs(y))

# 3. 写入WAV文件(16-bit PCM)
wavfile.write('original.wav', sr, (x * 32767).astype(np.int16))
wavfile.write('comb_filtered.wav', sr, (y * 32767).astype(np.int16))

print("已生成 original.wav 和 comb_filtered.wav")
print(f"延迟时间: {D/sr*1000:.1f} ms, 增益: {g}")

运行方式

  1. 安装依赖:pip install numpy scipy
  2. 将上述代码保存为 comb_sim.py 并运行:python comb_sim.py

验证方法

  • 文件生成检查:运行后当前目录应出现 original.wav 和 comb_filtered.wav 两个文件。
  • 频谱验证(可选):使用以下代码检查滤波后频谱在延迟频率的整数倍处出现凹陷:
from scipy.fft import rfft, rfftfreq
import matplotlib.pyplot as plt

for name in ['original.wav', 'comb_filtered.wav']:
    sr, data = wavfile.read(name)
    spec = np.abs(rfft(data[:sr]))  # 取前1秒
    freqs_axis = rfftfreq(sr, 1/sr)
    plt.figure()
    plt.plot(freqs_axis[:5000], spec[:5000])
    plt.title(name)
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Magnitude')
    plt.show()

预期在 1/D 的整数倍频率(即200Hz, 400Hz, 600Hz...)附近出现周期性凹陷,而原始信号频谱在这些频率处无此规律。

  • 听感验证:播放两个WAV文件,滤波后信号中440Hz和880Hz分量明显减弱(因它们恰位于梳齿谷点附近),整体音色变“空”变“薄”。

关键说明

本案例中四个正弦波频率(220, 440, 880, 1760Hz)均为200Hz的整数倍,而延迟5ms对应的梳齿谷点恰在200Hz的整数倍处,因此滤波后所有分量均被不同程度衰减,效果显著。若需保留某些频率,可调整延迟时间或输入信号频率。