MATLAB实现语音去混响与去噪
一、概念
- 噪声:通常指加性背景噪声,如风扇声、人群嘈杂声、电流声等。其特点是与原始语音信号是相加关系。
- 混响:由声音在封闭空间内经墙壁、天花板等表面多次反射形成。它使语音听起来有“回音”,导致发音模糊、清晰度下降。混响可以看作原始语音信号与一个房间冲激响应 的卷积。
因此,接收到的信号模型可以表示为:
y(t) = s(t) * h(t) + n(t)
其中:
s(t)
是纯净语音信号。h(t)
是房间冲激响应。n(t)
是加性噪声。y(t)
是麦克风接收到的信号。*
表示卷积操作。
去混响的目标是解卷积,即从 y(t)
中估计出 s(t)
。
去噪的目标是消除加性分量 n(t)
。
二、基础方法:谱减法去噪
这是一种简单且有效的经典去噪方法。其核心思想是:从带噪语音的频谱幅度中,减去估计出的噪声频谱幅度,而保留相位信息(因为相位对人类感知影响较小)。
MATLAB 实现步骤:
- 预处理:将语音信号分帧、加窗(如汉明窗)。
- STFT:对每一帧进行短时傅里叶变换,得到复数频谱
Y(t, f)
。其幅度为|Y(t, f)|
,相位为∠Y(t, f)
。 - 噪声估计:在语音开始前的“寂静”段(只有噪声)计算平均噪声幅度谱
|N(f)|
。 - 谱减:对每一帧语音频谱进行如下计算:
|X_enhanced(t, f)| = |Y(t, f)| - α * |N(f)|
其中α
是过减因子(通常 >=1),用于更激进地抑制噪声。 - 半波整流:为避免出现负值,将结果取最大值。
|X_enhanced(t, f)| = max(|X_enhanced(t, f)|, β * |Y(t, f)|)
其中β
是谱下限参数(如0.02),保留一部分噪声以防止 musical noise。 - 重构信号:将处理后的幅度谱
|X_enhanced(t, f)|
与原始相位谱∠Y(t, f)
结合,进行逆STFT,重叠相加得到去噪后的时域信号。
MATLAB 代码示例 (谱减法):
function enhanced_signal = spectral_subtraction(noisy_signal, fs, noise_start, noise_end)% 参数设置frame_length = round(0.025 * fs); % 25ms 一帧overlap_length = round(0.01 * fs); % 10ms 重叠alpha = 1.5; % 过减因子beta = 0.02; % 谱下限参数% 1. 分帧frames = buffer(noisy_signal, frame_length, overlap_length, 'nodelay');num_frames = size(frames, 2);window = hamming(frame_length);% 2. 估计噪声(假设前若干帧为纯噪声)noise_frames = frames(:, 1:50); % 取前50帧作为噪声noise_mag_avg = mean(abs(fft(noise_frames .* window, [], 1)), 2);% 初始化输出帧enhanced_frames = zeros(frame_length, num_frames);% 3. 处理每一帧for i = 1:num_framesframe = frames(:, i) .* window;frame_fft = fft(frame);mag = abs(frame_fft);phase = angle(frame_fft);% 执行谱减enhanced_mag = mag - alpha * noise_mag_avg;enhanced_mag = max(enhanced_mag, beta * mag); % 半波整流% 合成复数频谱并逆变换enhanced_fft = enhanced_mag .* exp(1j * phase);enhanced_frame = real(ifft(enhanced_fft));enhanced_frames(:, i) = enhanced_frame;end% 4. 重叠相加重构信号enhanced_signal = overlap_add(enhanced_frames, overlap_length);enhanced_signal = enhanced_signal(1:length(noisy_signal)); % 修剪长度
end% 重叠相加函数(可使用MATLAB信号处理工具箱中的相关函数实现)
function output = overlap_add(frames, overlap_len)[frame_len, num_frames] = size(frames);output = zeros(1, (frame_len - overlap_len) * num_frames + overlap_len);for i = 1:num_framesstart_idx = (i-1) * (frame_len - overlap_len) + 1;end_idx = start_idx + frame_len - 1;output(start_idx:end_idx) = output(start_idx:end_idx) + frames(:, i)';end
end
三、进阶方法:加权预测误差去混响
对于混响,一个非常有效且学术上流行的方法是加权预测误差。其核心思想是:混响可以被建模为早期反射(有益)和晚期反射(有害)之和。WPE通过线性预测来估计并减去这些晚期反射。
WPE 基本原理:
假设当前频点的值可以由过去若干帧的同一频点的值线性预测得到,这个预测值就代表了混响(晚期反射)部分。原始信号减去这个预测值,就得到了去混响的信号。
MATLAB 实现 (可使用 wpe
函数):
MATLAB的语音处理工具箱 提供了直接可用的 dsp.WPEDereverberator
系统对象,极大简化了实现。
% 使用MATLAB内置的WPE去混响器
% 首先确保有 Audio Toolbox 和 DSP System Toolbox% 创建去混响器对象
wpeDereverberator = dsp.WPEDereverberator(...'PredictionDelay', 2, ... % 预测延迟(通常1-3)'FilterLength', 128, ... % 预测滤波器长度'ForgettingFactor', 0.99, ... % 遗忘因子(RLS自适应参数)'SmoothingFactor', 0.98); % 平滑因子% 应用去混响
dereverbedSignal = wpeDereverberator(reverberantAudioInput);% 聆听结果
soundsc(dereverbedSignal, fs);
四、完整流程示例:先去噪,再去混响
在实际应用中,通常先进行去噪,然后再去混响,效果更好。
% 主程序:语音增强(去噪+去混响)
clear; clc; close all;% 1. 读取带噪带混响的音频文件
[input_signal, fs] = audioread('your_noisy_reverberant_speech.wav');
input_signal = mean(input_signal, 2); % 转为单声道
input_signal = input_signal / max(abs(input_signal)); % 归一化% 2. 首先进行谱减法去噪
fprintf('Denoising using Spectral Subtraction...\n');
denoised_signal = spectral_subtraction(input_signal, fs, 1, 0.5*fs); % 假设前0.5秒是噪声% 3. 然后进行WPE去混响
fprintf('Dereverberating using WPE...\n');
wpeDereverberator = dsp.WPEDereverberator('PredictionDelay', 2, 'FilterLength', 128);
enhanced_signal = wpeDereverberator(denoised_signal);% 4. 聆听和比较结果
fprintf('Playing original signal...\n');
soundsc(input_signal, fs);
pause(length(input_signal)/fs + 1);fprintf('Playing enhanced signal...\n');
soundsc(enhanced_signal, fs);% 5. 保存结果
audiowrite('enhanced_speech.wav', enhanced_signal, fs);% 6. 绘制波形图进行对比
t = (0:length(input_signal)-1) / fs;
figure('Position', [100, 100, 1200, 600]);
subplot(3,1,1);
plot(t, input_signal);
title('Original Noisy and Reverberant Signal');
xlabel('Time (s)'); ylabel('Amplitude'); grid on; xlim([0, t(end)]);subplot(3,1,2);
plot(t, denoised_signal);
title('After Denoising (Spectral Subtraction)');
xlabel('Time (s)'); ylabel('Amplitude'); grid on; xlim([0, t(end)]);subplot(3,1,3);
plot(t, enhanced_signal);
title('After Dereverberation (WPE) - Final Enhanced Signal');
xlabel('Time (s)'); ylabel('Amplitude'); grid on; xlim([0, t(end)]);
推荐代码 语音去混响与去噪 www.youwenfan.com/contentcsh/53643.html
五、其他方法与工具
- Wiener Filter(维纳滤波):另一种经典的频域方法,比谱减法更优,但需要估计语音和噪声的功率谱密度。
- 深度学习方法:使用CNN、RNN或Transformer等神经网络直接从数据中学习一个端到端的映射函数(从带噪混响语音到纯净语音)。这需要大量的数据和计算资源,但通常能取得最好的效果。MATLAB的Deep Learning Toolbox 可以用于实现。
- MATLAB 函数:除了
dsp.WPEDereverberator
,还可以探索audioDeviceReader
,stft
,istft
,dsp.STFT
,dsp.ISTFT
,dsp.LMSFilter
等强大工具。