sem2 done
This commit is contained in:
265
semestralka2/analyza_experimental.m
Normal file
265
semestralka2/analyza_experimental.m
Normal file
@@ -0,0 +1,265 @@
|
||||
clc;
|
||||
close all;
|
||||
clear all;
|
||||
|
||||
%% === STAGE 0: Load Audio Files ===
|
||||
[y, Fs] = audioread('sem2.wav');
|
||||
[y1, Fs1] = audioread('flac.wav');
|
||||
[y2, Fs2] = audioread('flac2.wav');
|
||||
|
||||
% Ensure mono
|
||||
if size(y,2) > 1, y = mean(y,2); end
|
||||
if size(y1,2) > 1, y1 = mean(y1,2); end
|
||||
if size(y2,2) > 1, y2 = mean(y2,2); end
|
||||
|
||||
fprintf('Loaded audio files:\n');
|
||||
fprintf(' sem2.wav: %d samples, Fs = %d Hz\n', length(y), Fs);
|
||||
fprintf(' flac.wav: %d samples, Fs = %d Hz\n', length(y1), Fs1);
|
||||
fprintf(' flac2.wav: %d samples, Fs = %d Hz\n', length(y2), Fs2);
|
||||
|
||||
%% === STAGE 1: IIR Notch Filter ===
|
||||
fprintf('\n=== STAGE 1: Notch Filtering ===\n');
|
||||
|
||||
N2 = length(y2);
|
||||
X2 = fft(y2);
|
||||
halfN2 = floor(N2/2);
|
||||
freq2 = (0:halfN2-1) * (Fs2/N2);
|
||||
|
||||
magX2 = abs(X2(1:halfN2));
|
||||
[pks, locs] = findpeaks(magX2, 'NPeaks', 10, 'SortStr', 'descend', 'MinPeakDistance', 5);
|
||||
f_peaks = freq2(locs);
|
||||
f_peaks = f_peaks(f_peaks > 10);
|
||||
if length(f_peaks) > 5
|
||||
f_peaks = f_peaks(1:5);
|
||||
end
|
||||
|
||||
fprintf('Detected tonal noise frequencies: ');
|
||||
fprintf('%.1f Hz, ', f_peaks);
|
||||
fprintf('\n');
|
||||
|
||||
r = 0.995;
|
||||
sos_all = [];
|
||||
gain_all = 1;
|
||||
|
||||
for k = 1:length(f_peaks)
|
||||
wo = f_peaks(k) / (Fs2/2);
|
||||
if wo > 0 && wo < 1
|
||||
bw = 0.005;
|
||||
[b_notch, a_notch] = iirnotch(wo, bw);
|
||||
[sos, g] = tf2sos(b_notch, a_notch);
|
||||
sos_all = [sos_all; sos];
|
||||
gain_all = gain_all * g;
|
||||
end
|
||||
end
|
||||
|
||||
if ~isempty(sos_all)
|
||||
y_notch = filtfilt(sos_all, gain_all, double(y));
|
||||
y2_notch = filtfilt(sos_all, gain_all, double(y2));
|
||||
else
|
||||
y_notch = double(y);
|
||||
y2_notch = double(y2);
|
||||
end
|
||||
|
||||
fprintf('Notch filtering complete.\n');
|
||||
|
||||
%% === STAGE 2: Spectral Subtraction ===
|
||||
fprintf('\n=== STAGE 2: Spectral Subtraction ===\n');
|
||||
params.frameLen = 2048;
|
||||
params.hopLen = 512;
|
||||
params.nfft = 2048;
|
||||
params.alpha = 4.0;
|
||||
params.beta = 0.002;
|
||||
params.gamma = 1.0;
|
||||
[y_specsub, ~] = spectral_subtraction(y_notch, y2_notch, Fs, params);
|
||||
fprintf('Spectral subtraction complete.\n');
|
||||
|
||||
%% === STAGE 3: MMSE-LSA Enhancement ===
|
||||
fprintf('\n=== STAGE 3: MMSE-LSA Enhancement ===\n');
|
||||
params_mmse.frameLen = 2048;
|
||||
params_mmse.hopLen = 512;
|
||||
params_mmse.nfft = 2048;
|
||||
params_mmse.alphaDD = 0.98;
|
||||
params_mmse.minGain = 0.1;
|
||||
params_mmse.noisePowSmooth = 0.7;
|
||||
[y_mmse, ~] = mmse_lsa_denoise(y_specsub, y2_notch, Fs, params_mmse);
|
||||
fprintf('MMSE-LSA enhancement complete.\n');
|
||||
|
||||
%% === STAGE 4: Post-processing ===
|
||||
fprintf('\n=== STAGE 4: Post-processing ===\n');
|
||||
[b_hp, a_hp] = butter(2, 80/(Fs/2), 'high');
|
||||
y_final = filtfilt(b_hp, a_hp, y_mmse);
|
||||
y_final = y_final / (max(abs(y_final)) + eps) * 0.95;
|
||||
fprintf('Post-processing complete.\n');
|
||||
|
||||
%% === Save outputs ===
|
||||
audiowrite('sem2_stage1_notch.wav', y_notch/max(abs(y_notch)+eps)*0.95, Fs);
|
||||
audiowrite('sem2_stage2_specsub.wav', y_specsub/max(abs(y_specsub)+eps)*0.95, Fs);
|
||||
audiowrite('sem2_stage3_mmse.wav', y_mmse/max(abs(y_mmse)+eps)*0.95, Fs);
|
||||
audiowrite('sem2_final_cleaned.wav', y_final, Fs);
|
||||
|
||||
y2_cleaned = spectral_subtraction(y2_notch, y2_notch, Fs2, params);
|
||||
y2_cleaned = mmse_lsa_denoise(y2_cleaned, y2_notch, Fs2, params_mmse);
|
||||
y2_cleaned = y2_cleaned / (max(abs(y2_cleaned)) + eps) * 0.95;
|
||||
audiowrite('flac2_final_cleaned.wav', y2_cleaned, Fs2);
|
||||
fprintf('\n✅ All files saved!\n');
|
||||
|
||||
%% === SIMPLE VISUALIZATION (same style as older system) ===
|
||||
t = (0:length(y)-1)/Fs;
|
||||
|
||||
figure;
|
||||
subplot(3,1,1);
|
||||
plot(t, y); grid on;
|
||||
title('Original sem2.wav');
|
||||
xlabel('Time [s]'); ylabel('Amplitude');
|
||||
|
||||
subplot(3,1,2);
|
||||
plot(t, y_notch); grid on;
|
||||
title('After Notch Filtering');
|
||||
xlabel('Time [s]'); ylabel('Amplitude');
|
||||
|
||||
subplot(3,1,3);
|
||||
plot(t, y_final); grid on;
|
||||
title('Final Cleaned sem2\_final\_cleaned.wav');
|
||||
xlabel('Time [s]'); ylabel('Amplitude');
|
||||
|
||||
figure;
|
||||
subplot(3,1,1);
|
||||
plot((0:length(y2)-1)/Fs2, y2); grid on;
|
||||
title('Original flac2.wav (Noise Sample)');
|
||||
xlabel('Time [s]'); ylabel('Amplitude');
|
||||
|
||||
subplot(3,1,2);
|
||||
plot((0:length(y2_notch)-1)/Fs2, y2_notch); grid on;
|
||||
title('After Notch Filtering (Noise)');
|
||||
xlabel('Time [s]'); ylabel('Amplitude');
|
||||
|
||||
subplot(3,1,3);
|
||||
plot((0:length(y2_cleaned)-1)/Fs2, y2_cleaned); grid on;
|
||||
title('Cleaned flac2.wav (Noise Reference)');
|
||||
xlabel('Time [s]'); ylabel('Amplitude');
|
||||
|
||||
fprintf('\nProcessing summary:\n');
|
||||
fprintf(' - Stage 1 removed %d tonal frequencies\n', length(f_peaks));
|
||||
fprintf(' - Stage 2 applied spectral subtraction (α = %.1f)\n', params.alpha);
|
||||
fprintf(' - Stage 3 applied MMSE-LSA (α_DD = %.2f)\n', params_mmse.alphaDD);
|
||||
fprintf(' - Final result saved as sem2_final_cleaned.wav (best quality)\n');
|
||||
|
||||
|
||||
function [y_out, noise_psd] = spectral_subtraction(x, noise_ref, Fs, p)
|
||||
x = x(:);
|
||||
noise_ref = noise_ref(:);
|
||||
frameLen = p.frameLen; hopLen = p.hopLen; nfft = p.nfft;
|
||||
alpha = p.alpha; beta = p.beta; gamma = p.gamma;
|
||||
win = hamming(frameLen, 'periodic');
|
||||
|
||||
[N_stft, ~, ~] = stft(noise_ref, Fs, 'Window', win, ...
|
||||
'OverlapLength', frameLen-hopLen, 'FFTLength', nfft);
|
||||
noise_psd = mean(abs(N_stft).^2, 2);
|
||||
noise_psd = movmean(noise_psd, 5);
|
||||
|
||||
[X_stft, ~, ~] = stft(x, Fs, 'Window', win, ...
|
||||
'OverlapLength', frameLen-hopLen, 'FFTLength', nfft);
|
||||
|
||||
[nFreq, nFrames] = size(X_stft);
|
||||
Y_stft = zeros(size(X_stft));
|
||||
|
||||
for k = 1:nFrames
|
||||
X_frame = X_stft(:, k);
|
||||
X_mag = abs(X_frame);
|
||||
X_phase = angle(X_frame);
|
||||
X_pow = X_mag.^2;
|
||||
snr_post = X_pow ./ (noise_psd + eps);
|
||||
alpha_freq = alpha * (1 + 0.5 * (1 - min(snr_post, 4)/4));
|
||||
Y_pow = X_pow - alpha_freq .* noise_psd;
|
||||
Y_pow = max(Y_pow, beta * X_pow);
|
||||
Y_mag = sqrt(max(Y_pow, 0));
|
||||
Y_stft(:, k) = Y_mag .* exp(1j * X_phase);
|
||||
end
|
||||
|
||||
y_out = istft(Y_stft, Fs, 'Window', win, ...
|
||||
'OverlapLength', frameLen-hopLen, ...
|
||||
'FFTLength', nfft, 'ConjugateSymmetric', true);
|
||||
y_out = y_out(1:min(length(y_out), length(x)));
|
||||
if length(y_out) < length(x)
|
||||
y_out = [y_out; zeros(length(x)-length(y_out),1)];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function [y_out, G_all] = mmse_lsa_denoise(x, noise_ref, Fs, p)
|
||||
x = x(:); noise_ref = noise_ref(:);
|
||||
frameLen = p.frameLen; hopLen = p.hopLen; nfft = p.nfft;
|
||||
alphaDD = p.alphaDD; Gmin = p.minGain;
|
||||
win = hamming(frameLen, 'periodic');
|
||||
|
||||
[N_stft, ~, ~] = stft(noise_ref, Fs, 'Window', win, ...
|
||||
'OverlapLength', frameLen-hopLen, 'FFTLength', nfft);
|
||||
lambda_d = mean(abs(N_stft).^2, 2);
|
||||
lambda_d = movmean(lambda_d, 5);
|
||||
|
||||
[X_stft, ~, ~] = stft(x, Fs, 'Window', win, ...
|
||||
'OverlapLength', frameLen-hopLen, 'FFTLength', nfft);
|
||||
|
||||
[nFreq, nFrames] = size(X_stft);
|
||||
Y_stft = zeros(size(X_stft));
|
||||
G_all = zeros(nFreq, nFrames);
|
||||
xi_prev = ones(nFreq, 1);
|
||||
|
||||
for k = 1:nFrames
|
||||
X_frame = X_stft(:, k);
|
||||
X_mag = abs(X_frame);
|
||||
X_phase = angle(X_frame);
|
||||
X_pow = X_mag.^2;
|
||||
gamma_k = X_pow ./ (lambda_d + eps);
|
||||
xi_ml = max(gamma_k - 1, 0);
|
||||
xi = alphaDD * xi_prev + (1 - alphaDD) * xi_ml;
|
||||
xi = max(xi, 1e-6);
|
||||
v = xi .* gamma_k ./ (1 + xi);
|
||||
G = zeros(nFreq,1);
|
||||
for i = 1:nFreq
|
||||
if v(i) < 0.01
|
||||
G(i) = xi(i)/(1+xi(i));
|
||||
else
|
||||
G(i) = xi(i)/(1+xi(i)) * exp(0.5 * expint_approx(v(i)));
|
||||
end
|
||||
end
|
||||
G = max(G, Gmin);
|
||||
G = movmean(G, 3);
|
||||
Y_mag = G .* X_mag;
|
||||
Y_stft(:,k) = Y_mag .* exp(1j*X_phase);
|
||||
G_all(:,k) = G;
|
||||
xi_prev = xi;
|
||||
end
|
||||
|
||||
y_out = istft(Y_stft, Fs, 'Window', win, ...
|
||||
'OverlapLength', frameLen-hopLen, ...
|
||||
'FFTLength', nfft, 'ConjugateSymmetric', true);
|
||||
y_out = y_out(1:min(length(y_out), length(x)));
|
||||
if length(y_out) < length(x)
|
||||
y_out = [y_out; zeros(length(x)-length(y_out),1)];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function y = expint_approx(x)
|
||||
if x < 1e-10
|
||||
y = -log(1e-10) - 0.5772;
|
||||
elseif x < 1
|
||||
y = -log(x) - 0.5772156649;
|
||||
term = x;
|
||||
for n = 1:50
|
||||
y = y + term / n;
|
||||
term = -term * x / (n + 1);
|
||||
if abs(term) < 1e-10, break; end
|
||||
end
|
||||
else
|
||||
y = exp(-x) / x;
|
||||
term = 1;
|
||||
for n = 1:10
|
||||
term = -term * n / x;
|
||||
y = y + term * exp(-x) / x;
|
||||
if abs(term) < 1e-10, break; end
|
||||
end
|
||||
end
|
||||
y = -y;
|
||||
end
|
||||
Reference in New Issue
Block a user