3. 语音信号的预加重处理
任务目标
实现一阶预加重滤波器,对语音信号进行高频提升,并通过频谱对比验证处理效果。预加重用于补偿语音发声过程中高频分量的自然衰减,是语音识别与TTS前端处理的常用步骤。
实现方案
预加重滤波器采用一阶差分方程:y[n] = x[n] - α·x[n-1],其中α为预加重系数(通常取0.95~0.98)。本案例使用Python实现,生成一段包含低频基频与高频共振峰特征的合成语音信号作为输入,完成滤波后对比滤波前后的幅度谱。
完整代码
import numpy as np
import matplotlib.pyplot as plt
# 参数设置
fs = 16000 # 采样率 16kHz
duration = 0.1 # 信号时长 100ms
alpha = 0.97 # 预加重系数
n = np.arange(int(fs * duration))
t = n / fs
# 合成语音信号:基频150Hz + 三次谐波 + 高频共振峰成分
f0 = 150
signal = (0.6 * np.sin(2 * np.pi * f0 * t) +
0.3 * np.sin(2 * np.pi * 3 * f0 * t) +
0.1 * np.sin(2 * np.pi * 12 * f0 * t))
# 预加重滤波:y[n] = x[n] - alpha * x[n-1]
preemphasized = np.copy(signal)
for i in range(1, len(signal)):
preemphasized[i] = signal[i] - alpha * signal[i-1]
# 计算幅度谱(使用汉宁窗减少频谱泄漏)
window = np.hanning(len(signal))
spec_orig = np.abs(np.fft.rfft(signal * window))
spec_pre = np.abs(np.fft.rfft(preemphasized * window))
freqs = np.fft.rfftfreq(len(signal), 1/fs)
# 绘制频谱对比
plt.figure(figsize=(10, 4))
plt.plot(freqs, 20*np.log10(spec_orig + 1e-10), label='原始信号', linewidth=1)
plt.plot(freqs, 20*np.log10(spec_pre + 1e-10), label='预加重后', linewidth=1, alpha=0.8)
plt.xlabel('频率 (Hz)')
plt.ylabel('幅度 (dB)')
plt.title('预加重前后频谱对比 (α=0.97)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.xlim(0, 4000)
plt.tight_layout()
plt.savefig('preemphasis_spectrum.png', dpi=150)
plt.show()
# 打印低频与高频段的增益差(用于验证)
low_band = (freqs > 100) & (freqs < 300)
high_band = (freqs > 1500) & (freqs < 2500)
low_gain = 20*np.log10(np.mean(spec_pre[low_band]) / (np.mean(spec_orig[low_band]) + 1e-10))
high_gain = 20*np.log10(np.mean(spec_pre[high_band]) / (np.mean(spec_orig[high_band]) + 1e-10))
print(f"低频段(100-300Hz)平均增益: {low_gain:.2f} dB")
print(f"高频段(1500-2500Hz)平均增益: {high_gain:.2f} dB")
运行方式
- 安装依赖:
pip install numpy matplotlib - 将上述代码保存为
preemphasis.py,执行python preemphasis.py
验证方法
运行后观察频谱对比图,应满足以下条件即判定通过:
- 预加重后的频谱在高频段(>1kHz)整体高于原始频谱,且频率越高提升越明显,呈现约6dB/倍频程的上升趋势
- 低频段(<300Hz)幅度基本不变或略有下降,符合一阶高通特性
- 控制台输出的高频段平均增益应显著大于低频段平均增益(典型差值>10dB)
预期输出示例(基于代码逻辑推导):低频段平均增益约-0.5~0.5 dB,高频段平均增益约+8~12 dB,具体数值取决于信号频谱分布与α取值。
常见问题
- 若频谱图出现严重泄漏,可增加信号时长或改用凯塞窗
- α取值越接近1,高频提升越强,但可能引入低频衰减过大;实际语音处理中常用0.95~0.98
- 本实现采用逐样本循环,适合教学演示;工程应用中应使用
scipy.signal.lfilter([1, -alpha], [1], signal)实现等效滤波