基于非负矩阵分解(NMF)的单通道语音信号分离系统
项目介绍
本项目实现了一套完整的基于监督式非负矩阵分解(Supervised NMF)的单通道语音分离解决方案。系统旨在解决经典的“鸡尾酒会问题”,即在仅有一个麦克风录制的情况下,将混合音频中的不同声源这一复杂任务转化为矩阵分解问题。
该代码不依赖于MATLAB信号处理工具箱中的高级封装函数(如内置的stft/istft),而是从底层手动实现了短时傅里叶变换(STFT)及其逆变换(ISTFT),以及完整的NMF迭代优化算法。系统通过预先学习源信号的特征字典(基矩阵),利用这些先验知识在混合信号中精确计算激活系数,最后结合软掩蔽(Soft Masking)技术重构出目标语音。
核心功能与特性
- 监督式NMF分离流程:实现了“先训练,后分离”的监督学习模式,分别从纯净源信号中学习特征基矩阵,再用于混合信号的分解。
- 灵活的损失函数支持:NMF求解器内置了两种常见的乘性更新规则,支持广义KL散度(Beta=1)和欧几里得距离(Beta=2),可根据信号特性调整。
- 底层信号处理实现:手动编写了STFT和ISTFT(采用Overlap-Add重叠相加法),能够更好地控制信号重建过程中的窗函数归一化和相位处理。
- 频域软掩蔽重构:采用类似维纳滤波(Wiener Filtering)的软掩蔽策略,利用分解得到的幅度谱构建时频掩膜,并结合混合信号的原始相位进行波形重建。
- 合成数据生成:内置数据生成模块,可生成具有调幅调频(AM-FM)特性的模拟语音谐波信号,无需外部音频文件即可直接运行演示。
- 可视化与评估:提供时域波形对比、功率谱密度对比、语谱图绘制,并自动计算和输出信噪比(SNR)以量化分离性能。
系统要求
- MATLAB R2016b 或更高版本推荐(主要为了保证绘图和基础矩阵运算的兼容性)。
- 不需要额外的特殊工具箱(核心算法均为原生矩阵运算实现)。
详细实现逻辑
main.m 脚本按照以下严格的流程执行语音分离任务:
1. 参数配置与环境初始化
系统首先初始化关键参数,包括采样率(16kHz)、FFT点数(1024)、帧移和窗长。同时定义了NMF算法的超参数,如基向量数目(字典原子数)、训练与测试阶段的迭代次数,以及用于控制更新规则的 Beta 值。
2. 多源数据模拟
通过生成函数创建两路具有不同基频和谐波结构的模拟信号:
- 源信号1:模拟基频在200Hz附近波动且包含丰富谐波的语音,具有间歇性特征。
- 源信号2:模拟基频在500Hz附近波动的干扰声音,包含不同的包络特征。
- 混合处理:将两路信号线性叠加并进行归一化处理,构建单通道混合观测信号。
3. 时频变换 (STFT)
对源信号和混合信号分别应用短时傅里叶变换。使用汉明窗(Hamming Window)对信号分帧,通过FFT将时域信号转换为时频域的复数频谱。系统分别提取源信号的幅度谱用于字典训练,提取混合信号的幅度谱用于分离,同时保留混合信号的相位谱用于后续的波形重构。
4. 字典学习 (训练阶段)
利用 NMF 算法分别对两个源信号的幅度谱进行分解。
- 固定源1的幅度谱 $V_1$,求解其基矩阵 $W_1$。
- 固定源2的幅度谱 $V_2$,求解其基矩阵 $W_2$。
这一步获得了代表各自分离源频域特征的“字典”。随后将 $W_1$ 和 $W_2$ 横向拼接,构成全局基矩阵 $W_{concat}$。
5. 信号分离 (测试阶段)
进入监督分离过程,将混合信号的幅度谱 $V_{mix}$ 作为输入:
- 固定拼接好的全局基矩阵 $W_{concat}$ 不变。
- 随机初始化激活矩阵 $H$。
- 利用NMF迭代算法仅更新 $H$,使其满足 $V_{mix} approx W_{concat} times H$。
求解得到的 $H$ 包含了两个源在混合信号中的时间激活权重。
6. 波形重构与掩蔽
- 激活分解:将求解出的 $H$ 按行拆分为对应源1的 $H_1$ 和对应源2的 $H_2$。
- 近似谱计算:通过 $V_{approx_1} = W_1 times H_1$ 计算各源的估计幅度谱。
- 软掩蔽构建:计算每个时频点的能量占比,生成软掩码(Soft Mask)。例如源1的掩码为 $Mask_1 = V_{approx_1} / (V_{approx_1} + V_{approx_2} + epsilon)$。
- 相位结合:将掩码应用到混合信号的原始幅度谱上,并结合混合信号的原始相位,生成分离后的复数谱。
- 时域恢复:调用 ISTFT 函数,使用重叠相加法将复数谱还原为时域波形,并处理窗函数引入的增益效应。
7. 性能评估与可视化
最后,系统计算每路信号分离前后的信噪比(SNR),并在控制台打印增益情况。同时弹出图形窗口,展示:
- 原始源信号、混合信号、分离信号的波形对比。
- 源信号与分离信号的功率谱密度(PSD)曲线对比。
- 源信号与混合信号的语谱图(Spectrogram)对比。
关键算法与函数分析
以下是代码中关键函数的具体实现细节:
nmf_solver (标准NMF求解器)
这是用于训练阶段的核心函数。
- 输入:非负矩阵 V,基向量数 r,迭代次数,Beta值。
- 初始化:随机初始化 W 和 H,并对 W 进行列归一化。
- 迭代更新:根据 Beta 值选择更新公式。
*
Beta=2 (欧氏距离):使用基于最小二乘误差的乘性更新规则。
*
Beta=1 (KL散度):使用基于广义Kullback-Leibler散度的乘性更新规则,适用于泊松噪声模型,通常对音频谱分解效果更好。
- 归一化:每次迭代后重新归一化 W 并调整 H,保持乘积尺度一致。
nmf_update_h_only (固定基矩阵更新)
这是用于分离阶段的专用函数。
- 逻辑:完全复用了标准 NMF 的更新推导,但强制 不更新 W。
- 作用:确保在分离混合信号时,系统只能使用训练阶段学到的特征(W),而通过调整激活系数(H)来拟合混合信号。
compute_stft (短时傅里叶变换)
- 实现:手动循环实现分帧、加窗和FFT。
- 细节:只保留 FFT 结果的前一半(即 $N/2 + 1$ 个点),因为实数信号的频谱是共轭对称的,这样可以减少计算量。
compute_istft (逆短时傅里叶变换)
- 实现:基于 Overlap-Add(OLA)算法。
- 谱重建:首先利用共轭对称性将单边谱恢复为双边全频带谱。
- IFFT:对每一帧进行 IFFT 变换取实部。
- 重叠相加:将时域帧叠加到输出缓冲区的对应位置。
- 窗函数归一化:记录每个样点处累加的窗函数平方和,最后做一个除法归一化,以消除重叠带来的幅度调制效应。
generate_synthetic_data (合成数据生成)
- 逻辑:通过叠加不同频率的正弦波(模拟基频和谐波)通过调制(AM-FM)来生成信号。
- 目的:提供无需外部文件即可验证分离算法有效性的测试数据。
使用方法
- 打开 MATLAB。
- 将当前目录切换到包含
main.m 的文件夹。 - 在命令窗口输入
main 并回车。 - 观察控制台输出的训练进度和 SNR 结果,以及弹出的波形和频谱对比图。