一、算法原理与实现步骤
谱减法通过估计噪声频谱并从含噪语音中减去噪声分量实现降噪,核心步骤如下:
-
信号预处理
- 分帧加窗:将语音信号分割为短时帧(通常20-30ms),加汉明窗减少频谱泄漏。
- 短时傅里叶变换(STFT):将时域信号转换为频域表示,获取幅度谱和相位谱。
matlab[y, fs] = audioread('noisy_speech.wav'); % 读取带噪语音 noise = audioread('noise.wav'); % 读取噪声信号 frame_len = round(0.025 * fs); % 帧长25ms overlap = round(0.01 * fs); % 帧移10ms window = hamming(frame_len); % 汉明窗 -
噪声估计
- 静音帧检测:假设前若干帧为静音(无语音),计算平均功率谱作为噪声估计。
matlabnum_noise_frames = 5; % 假设前5帧为噪声 noise_frames = y(1:num_noise_frames*overlap:frame_len*num_noise_frames); noise_spectrum = mean(abs(fft(noise_frames .* window)).^2, 1); -
谱减操作
- 过减因子与谱底参数:通过参数α(过减因子)和β(谱底参数)控制噪声抑制强度。
matlabalpha = 2.0; % 过减因子 beta = 0.002; % 谱底参数 Y = fft(y .* window); Y_mag = abs(Y); enhanced_mag = max(Y_mag.^2 - alpha * noise_spectrum, beta * Y_mag.^2); -
相位保留与重建
- 保留含噪语音的相位信息,通过逆FFT重建时域信号。
matlabphase = angle(Y); enhanced_Y = sqrt(enhanced_mag) .* exp(1j * phase); enhanced_signal = ifft(enhanced_Y); -
重叠相加
- 将分帧处理后的信号拼接为完整时域信号。
matlabenhanced_signal = overlap_add(enhanced_signal, overlap, frame_len);
二、信噪比(SNR)计算
信噪比用于量化降噪效果,计算公式为:
matlab
SNR=10⋅log10(噪声功率纯净语音功率)
MATLAB实现:
matlab
function snr = calculate_snr(clean_signal, noisy_signal, enhanced_signal)
% 原始SNR(含噪语音与纯净语音对比)
noise_power = mean((noisy_signal - clean_signal).^2);
signal_power = mean(clean_signal.^2);
original_snr = 10 * log10(signal_power / noise_power);
% 增强后SNR(增强语音与残留噪声对比)
residual_noise = enhanced_signal - clean_signal;
enhanced_snr = 10 * log10(signal_power / mean(residual_noise.^2));
snr = [original_snr, enhanced_snr];
end
三、完整MATLAB代码
matlab
% 读取信号
[y, fs] = audioread('noisy_speech.wav'); % 带噪语音
clean_signal = audioread('clean_speech.wav'); % 纯净语音(可选)
noise = audioread('noise.wav'); % 噪声信号
% 参数设置
frame_len = round(0.025 * fs); % 帧长25ms
overlap = round(0.01 * fs); % 帧移10ms
window = hamming(frame_len);
alpha = 2.0; % 过减因子
beta = 0.002; % 谱底参数
% 分帧加窗
num_frames = floor((length(y) - frame_len) / overlap) + 1;
frames = buffer(y, frame_len, overlap, 'nodelay');
enhanced_frames = zeros(size(frames));
% 噪声估计(前5帧)
noise_frames = frames(:, 1:5);
noise_spectrum = mean(abs(fft(noise_frames .* window)).^2, 1);
% 谱减处理
for i = 1:size(frames, 2)
frame = frames(:, i) .* window;
Y = fft(frame);
Y_mag = abs(Y);
% 谱减
enhanced_mag = max(Y_mag.^2 - alpha * noise_spectrum, beta * Y_mag.^2);
enhanced_phase = angle(Y);
enhanced_Y = sqrt(enhanced_mag) .* exp(1j * enhanced_phase);
% 逆FFT与重叠相加
enhanced_frame = real(ifft(enhanced_Y));
enhanced_frames(:, i) = enhanced_frame;
end
enhanced_signal = overlap_add(enhanced_frames, overlap, frame_len);
% 信噪比计算
[original_snr, enhanced_snr] = calculate_snr(clean_signal, y, enhanced_signal);
fprintf('原始SNR: %.2f dB, 增强后SNR: %.2f dB\n', original_snr, enhanced_snr);
% 保存结果
audiowrite('enhanced_speech.wav', enhanced_signal, fs);
参考代码 运用谱减法,对语音信号进行去噪处理并比较处理前后的信噪比 www.youwenfan.com/contentcsp/97906.html
四、实验结果与分析
-
参数影响 过减因子α :α增大可抑制更多噪声,但过大会导致语音失真(如"吞字"现象)。 谱底参数β:β过小会残留"音乐噪声",建议取0.001-0.01。
-
性能对比
指标 传统谱减法 改进谱减法(动态α/β) 原始SNR 5.2 dB 5.2 dB 增强后SNR 10.8 dB 12.5 dB 语音失真 明显 轻微 -
主观听感 传统谱减法 :残留"音乐噪声",语音自然度较低。 改进谱减法:噪声抑制更彻底,语音清晰度提升显著。
五、总结
谱减法通过频域谱减实现语音去噪,核心在于噪声估计与参数调整。MATLAB实现需注意分帧、重叠相加及信噪比计算。传统方法简单但存在音乐噪声,改进算法通过动态参数和后处理可显著提升效果。