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_frames
frame = 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_frames
start_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/contentcnj/53643.html
五、其他方法與工具
- Wiener Filter(維納濾波):另一種經典的頻域方法,比譜減法更優,但需要估計語音和噪聲的功率譜密度。
- 深度學習方法:使用CNN、RNN或Transformer等神經網絡直接從數據中學習一個端到端的映射函數(從帶噪混響語音到純凈語音)。這需要大量的數據和計算資源,但通常能取得最好的效果。MATLAB的Deep Learning Toolbox 可以用于實現。
- MATLAB 函數:除了
dsp.WPEDereverberator,還可以探索audioDeviceReader,stft,istft,dsp.STFT,dsp.ISTFT,dsp.LMSFilter等強大工具。
浙公網安備 33010602011771號