在NVH工程领域,主动降噪技术相较于传统被动降噪,其降噪收益更为显著。例如,针对某一低频噪声峰值,主动降噪可实现5dB左右的明显衰减;而基于传递路径的结构优化,由于单个噪声峰值往往是多个传递路径共同作用的结果,并非由某一单一零部件或单体路径单独贡献,因此在制定可工程化的NVH优化方案时,难以获得显著的降噪效果。即便叠加多个结构优化方案,最终的主观噪声评价也无法实现质的提升,验收结果往往仅处于可接受的边缘。

在此背景下,LMS(Least Mean Square,最小均方)算法作为一种基于随机梯度下降的自适应滤波算法,被广泛应用于主动降噪系统中。该算法通过实时调整滤波器系数,使系统输出的“抗噪声”信号能够最大程度抵消原始噪声,最终让误差麦克风检测到的残余噪声趋近于零。当然这个基础算法有些弊端,因此在LMS算法的基础上已衍生出多种改进算法,本文将从公式和数值计算两个维度,详细解析这一基础算法的核心逻辑。

设X(n)为轮芯振动参考信号,P(z)为车身结构声学传递路径;轮芯振动经传递路径激励车身壁板,最终向乘员舱辐射形成人耳处噪声,记为期望信号d(n)。
W(z)为自适应滤波器(如三阶滤波器初始权值可设为[0,0,0])。参考信号X(n)经滤波器加权输出控制信号:y(n)=wT(n)x(n),y(n)作为抵消反向声波,用于抵消舱内原始噪声d(n)。
定义残余误差信号:e(n)=d(n)−y(n)=d(n)−wT(n)x(n)
以参考信号X(n)驱动LMS算法完成滤波器权值自适应更新,权值迭代基础公式为:w(n+1)=w(n)−μ∇J(w)式中:μ为固定学习率;代价函数采用均方误差J(w)=E[e2(n)],工程中用瞬时误差平方近似数学期望,即J(w)≈e2(n);∇J(w)为代价函数对权向量的梯度。
梯度方向是代价函数增长最快的方向,迭代公式中引入负梯度,使滤波器权值沿代价函数最快下降的方向更新。对梯度求解并化简后,得到LMS标准权值更新公式:w(n+1)=w(n)+μe(n)x(n)
基础前提设定
1.3阶横向滤波器W(行向量),初始权重W(0)=[0,0,0]
2.LMS更新公式:W(n+1)=W(n)+μ⋅e(n)⋅x(n),μ=0.1
3.信号链路划分三条并行通路:
通路①原生噪声通路:轮芯振动参考信号x(t)经车身/空气路径传递,形成人耳处原始噪声d(t);
通路②降噪抵消通路:参考信号经滤波器权重运算,输出抵消声y(t),误差信号e(t)=d(t)−y(t);
通路③LMS权重更新通路:参考输入向量+误差信号,实时迭代更新滤波器权重,实现自适应降噪。
第一时刻:t=0~t=0.001s
通路①原生噪声
轮芯初始振动:x(t=0)=2
经物理路径传递延时0.001s,人耳处原始噪声:d(t=0.001)=2.1(这里经过路径传递数值2.1只是举个例子,输入和输出有强相关性)
通路②抵消输出运算当前滤波器初始权重:W(t=0)=[0,0,0]
参考信号延时向量:x(t=0)=[2,0,0](参考输入向量,新样本移入、旧样本移出)
抵消声输出:y(t=0.001)=WT(0)⋅x(0)=0
残余误差信号:e(t=0.001)=d(0.001)−y(0.001)=2.1−0=2.1
通路③LMS权重迭代
代入LMS更新公式:
W(0.001)=W(0)+μ⋅e(0.001)⋅x(0)=[0,0,0]+0.1×2.1×[2,0,0]=[0.42,0,0]
第二时刻:t=0.001~t=0.002s
通路①原生噪声
下一时刻轮芯振动:x(t=0.001)=2.05
经固定路径延时传递,人耳处原始噪声:d(t=0.002)=2.13
通路②抵消输出运算
滤波器更新后权重:W(t=0.001)=[0.42,0,0]
参考信号滑动更新:新样本移入、旧样本移出,重构延时向量x(t=0.001)=[2.05,2,0]
抵消声输出:
y(t=0.002)=WT(t=0.001)⋅x(t=0.001)=0.861
残余误差信号:
e(t=0.002)=d(t=0.002)−y(t=0.002)=2.13−0.861=1.269
通路③LMS权重迭代
以上一时刻权重为基础,结合当前误差、参考向量更新:
W(t=0.002) =W(t=0.001)+μ⋅e(t=0.001)⋅x(t=0.001)=[0.42,0,0]+0.1×2.1×[2.05,2,0]=[0.8505,0.42,0]
import numpy as np
import matplotlib.pyplot as plt
# =====================解决Matplotlib中文显示问题=====================
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'WenQuanYi Zen Hei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'
# ==========================================================================
class LMSFilter:
"""
标准LMS自适应滤波器实现。
适用于实时或离线处理,用于系统辨识、噪声消除等场景。
"""
def __init__(self, filter_order, step_size=0.01):
"""
初始化滤波器。
参数:
filter_order (int): 滤波器阶数(抽头数)。阶数越高,模型能力越强,但计算量越大,收敛可能越慢。
step_size (float): 步长参数 μ。必须在稳定范围内 (0 < μ < 2/输入功率)。通常从0.01这样的小值开始尝试。
"""
self.order = filter_order
self.mu = step_size
# 初始化滤波器权重为零向量
self.weights = np.zeros(filter_order)
# 用于存储最近的输入样本,构成输入向量x(n)
self.input_buffer = np.zeros(filter_order)
def adapt(self, desired, reference):
"""
处理一个采样点,并更新滤波器。
参数:
desired (float): 期望信号 d(n),即主输入(如带噪语音)。
reference (float): 参考输入 x(n),与干扰噪声相关(如参考麦克风采集的噪声)。
返回:
output (float): 滤波器输出 y(n)。
error (float): 误差信号 e(n),通常作为系统输出(降噪后的信号)。
"""
# 更新输入缓冲区:将新参考样本移入,最旧的样本移出
self.input_buffer[1:] = self.input_buffer[:-1]
self.input_buffer[0] = reference
# 计算滤波器输出:权重向量与输入向量的内积
output = np.dot(self.weights, self.input_buffer)
# 计算瞬时误差
error = desired - output
# LMS核心:更新权重向量-input_buffer 参考信号序列
self.weights += self.mu * error * self.input_buffer
return output, error
def filter(self, desired_signal, reference_signal):
"""
批量处理整个信号序列。
参数:
desired_signal (np.array): 期望信号序列。
reference_signal (np.array): 参考信号序列。必须与desired_signal长度相同。
返回:
output_signal (np.array): 滤波器输出序列(预测的噪声)。
error_signal (np.array): 误差信号序列(估计的干净信号)。
weights_history (np.array): 权重向量的历史记录,用于分析收敛过程。
"""
n_samples = len(desired_signal)
output_signal = np.zeros(n_samples)
error_signal = np.zeros(n_samples)
# 可选:记录权重变化,用于调试和分析
weights_history = np.zeros((n_samples, self.order))
for i in range(n_samples):
output_signal[i], error_signal[i] = self.adapt(desired_signal[i], reference_signal[i])
weights_history[i, :] = self.weights
return output_signal, error_signal, weights_history
def test_lms_basic():
"""基础测试:滤除一个正弦波干扰。"""
np.random.seed(42) # 确保结果可复现
Fs = 1000 # 采样率
t = np.arange(0, 1.0, 1 / Fs) # 1秒时长
# 生成干净信号(我们想保留的): 10Hz正弦波
clean = 0.5 * np.sin(2 * np.pi * 10 * t)
# 生成干扰噪声: 50Hz正弦波
noise = 0.8 * np.sin(2 * np.pi * 50 * t)
# 主输入:干净信号与噪声的混合
desired = clean + noise
# 参考输入:我们得到的噪声参考,可能与实际噪声有幅度和相位差异
# 这里模拟一个简单的线性失真:幅度变化+加一点随机扰动
reference = 1.2 * noise + 0.05 * np.random.randn(len(t))
# 创建并应用LMS滤波器
lms = LMSFilter(filter_order=32, step_size=0.02)
# 我们关心的是error_signal,即降噪后的输出
_, error_signal, weights_history = lms.filter(desired, reference)
# 可视化结果
fig, axes = plt.subplots(3, 1, figsize=(10, 8))
axes[0].plot(t, desired, 'b', alpha=0.7, label='带噪信号(Desired)')
axes[0].plot(t, clean, 'r--', linewidth=2, label='原始干净信号(目标)')
axes[0].set_ylabel('幅度')
axes[0].set_title('输入信号对比')
axes[0].legend()
axes[0].grid(True)
axes[1].plot(t, error_signal, 'g', label='LMS输出(Error)')
axes[1].plot(t, clean, 'r--', linewidth=2, label='原始干净信号')
axes[1].set_ylabel('幅度')
axes[1].set_title('降噪效果对比')
axes[1].legend()
axes[1].grid(True)
# 绘制某个权重系数的收敛过程
axes[2].plot(weights_history[:, 5], 'm') # 跟踪第6个权重的变化
axes[2].set_xlabel('采样点')
axes[2].set_ylabel('权重值')
axes[2].set_title('滤波器权重收敛过程(示例: w[5])')
axes[2].grid(True)
plt.tight_layout()
plt.show()
# 计算并打印性能指标:均方误差(MSE)改善
mse_before = np.mean((desired - clean) ** 2)
mse_after = np.mean((error_signal - clean) ** 2)
print(f"降噪前MSE:{mse_before:.6f}")
print(f"降噪后MSE:{mse_after:.6f}")
print(f"MSE改善: {10 * np.log10(mse_before / mse_after):.2f} dB")
if __name__ == "__main__":
test_lms_basic()