Files
css/semestralka2/final.m
2025-12-07 00:10:47 +01:00

199 lines
5.7 KiB
Matlab
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

clc;
close all;
clear;
%% === LOAD AUDIO FILES ===
[y1, Fs1] = audioread('flac.wav');
[y2, Fs2] = audioread('flac2.wav');
if size(y1,2) > 1, y1 = mean(y1,2); end
if size(y2,2) > 1, y2 = mean(y2,2); end
t1 = (0:length(y1)-1) / Fs1;
t2 = (0:length(y2)-1) / Fs2;
fprintf('Loaded flac.wav: %d samples, Fs = %d Hz\n', length(y1), Fs1);
fprintf('Loaded flac2.wav: %d samples, Fs = %d Hz\n', length(y2), Fs2);
%% === TIME-DOMAIN WAVEFORMS ===
figure;
subplot(2,1,1);
plot(t1, y1);
xlabel('Time [s]');
ylabel('Amplitude');
title('flac.wav Time Domain');
grid on;
subplot(2,1,2);
plot(t2, y2, 'r');
xlabel('Time [s]');
ylabel('Amplitude');
title('flac2.wav Time Domain');
grid on;
%% === FREQUENCY-DOMAIN ANALYSIS (FFT) ===
N1 = length(y1);
N2 = length(y2);
X1 = fft(y1);
X2 = fft(y2);
freq_shift1 = (-N1/2 : N1/2 - 1) * (Fs1 / N1);
freq_shift2 = (-N2/2 : N2/2 - 1) * (Fs2 / N2);
% --- Real / Imag components ---
figure;
subplot(2,1,1);
plot(freq_shift2, real(fftshift(X2)));
xlabel('Frequency [Hz]');
ylabel('Real Part');
title('flac2.wav Real Part of FFT');
grid on;
subplot(2,1,2);
plot(freq_shift2, imag(fftshift(X2)), 'r');
xlabel('Frequency [Hz]');
ylabel('Imag Part');
title('flac2.wav Imaginary Part of FFT');
grid on;
% --- Magnitude Spectrum ---
figure;
plot(freq_shift2, 20*log10(abs(fftshift(X2)) + eps), 'y');
xlabel('Frequency [Hz]');
ylabel('Magnitude [dB]');
title('flac2.wav Magnitude Spectrum');
xlim([0 2000]);
grid on;
%% === PEAK DETECTION TO FIND TONAL NOISE FREQUENCIES ===
halfN2 = floor(N2/2);
f2 = (0:halfN2-1)*(Fs2/N2);
mag2 = abs(X2(1:halfN2));
[pks, locs] = findpeaks(mag2, 'MinPeakHeight', max(mag2)*0.1, ...
'MinPeakDistance', round(10*N2/Fs2));
f_tonal = f2(locs);
f_tonal = f_tonal(f_tonal > 30 & f_tonal < Fs2/2);
f_tonal = sort(f_tonal(1:min(5, numel(f_tonal))));
fprintf('\nDetected tonal noise frequencies (from flac2.wav):\n');
fprintf(' %.1f Hz\n', f_tonal);
%% === NOTCH FILTER DESIGN (Z-domain zeros/poles) ===
r = 0.995; % pole radius
sos_all = [];
g_all = 1;
for i = 1:length(f_tonal)
f0 = f_tonal(i);
w0 = 2*pi*f0/Fs1; % use Fs1 so it matches flac.wav
z = [exp(1j*w0) exp(-1j*w0)]; % zeros at ±ω0
p = r*z; % poles slightly inside circle
b = real(poly(z));
a = real(poly(p));
b = b / (sum(b)/sum(a)); % normalize gain
[sos_i, g_i] = tf2sos(b, a);
sos_all = [sos_all; sos_i];
g_all = g_all * g_i;
end
%% === VISUALIZE NOTCH FILTER RESPONSE ===
figure;
freqz(sos_all, 2048, Fs1);
title('Notch Filter Cascade Based on flac2 Noise Frequencies');
%% === APPLY NOTCH FILTERS TO SIGNALS ===
y1_filtered = filtfilt(sos_all, g_all, y1); % Apply to flac.wav
y2_filtered = filtfilt(sos_all, g_all, y2); % Apply to flac2.wav
y1_filtered = y1_filtered / max(abs(y1_filtered));
y2_filtered = y2_filtered / max(abs(y2_filtered));
audiowrite('filtered_flac.wav', y1_filtered, Fs1);
audiowrite('filtered_flac2.wav', y2_filtered, Fs2);
fprintf('\nSaved:\n');
fprintf(' filtered_flac.wav (filtered signal)\n');
fprintf(' filtered_flac2.wav (filtered noise sample)\n');
%% === COMPARE ORIGINAL VS FILTERED SPECTRA ===
N_plot = length(y1);
f_plot = (0:N_plot/2-1) * Fs1 / N_plot;
X1_orig = fft(y1);
X1_filt = fft(y1_filtered);
figure;
subplot(2,1,1);
plot(f_plot, 20*log10(abs(X1_orig(1:N_plot/2))+eps));
xlabel('Frequency [Hz]'); ylabel('Magnitude [dB]');
title('flac.wav Original Spectrum');
xlim([0 2000]); grid on;
subplot(2,1,2);
plot(f_plot, 20*log10(abs(X1_filt(1:N_plot/2))+eps), 'r');
xlabel('Frequency [Hz]'); ylabel('Magnitude [dB]');
title('flac.wav After Notch Filtering');
xlim([0 2000]); grid on;
%% === APPLY THE SAME FILTER TO sem2.wav ===
fprintf('\n=== APPLYING DESIGNED FILTER TO sem2.wav ===\n');
[y_sem2, Fs_sem2] = audioread('sem2.wav');
if size(y_sem2,2) > 1, y_sem2 = mean(y_sem2,2); end
if Fs_sem2 ~= Fs1
warning('Sample rates differ resampling sem2.wav to match notch filter design');
y_sem2 = resample(y_sem2, Fs1, Fs_sem2);
Fs_sem2 = Fs1;
end
% --- Step 1: Apply multinotch filter from flac2 noise analysis ---
y_sem2_notch = filtfilt(sos_all, g_all, y_sem2);
% --- Step 2 (optional): add bandpass filter for speech 1008000 Hz ---
[z_bp, p_bp, k_bp] = butter(4, [100 8000]/(Fs_sem2/2), 'bandpass');
[sos_bp, g_bp] = zp2sos(z_bp, p_bp, k_bp);
y_sem2_final = filtfilt(sos_bp, g_bp, y_sem2_notch);
% --- Normalize both versions ---
y_sem2_notch = y_sem2_notch / (max(abs(y_sem2_notch)) + eps) * 0.95;
y_sem2_final = y_sem2_final / (max(abs(y_sem2_final)) + eps) * 0.95;
% --- Save results ---
audiowrite('sem2_notch_filtered.wav', y_sem2_notch, Fs_sem2);
audiowrite('sem2_final.wav', y_sem2_final, Fs_sem2);
fprintf('Saved:\n');
fprintf(' sem2_notch_filtered.wav (notch filters only)\n');
fprintf(' sem2_final.wav (notch + speech bandpass)\n');
%% === VISUAL CHECK BEFORE vs AFTER ===
t_sem2 = (0:length(y_sem2)-1)/Fs_sem2;
N_sem2 = length(y_sem2);
f_sem2 = (0:N_sem2/2-1)*Fs_sem2/N_sem2;
Y_orig = fft(y_sem2);
Y_filt = fft(y_sem2_final);
figure;
subplot(2,1,1);
plot(t_sem2, y_sem2);
xlabel('Time [s]'); ylabel('Amplitude');
title('sem2.wav Original Time Domain'); grid on;
subplot(2,1,2);
plot(t_sem2, y_sem2_final, 'r');
xlabel('Time [s]'); ylabel('Amplitude');
title('sem2\_final.wav After Notch + BandPass'); grid on;
figure;
subplot(2,1,1);
plot(f_sem2, 20*log10(abs(Y_orig(1:N_sem2/2))+eps));
xlabel('Frequency [Hz]'); ylabel('Magnitude [dB]');
title('sem2.wav Original Spectrum');
xlim([0 2000]); grid on;
subplot(2,1,2);
plot(f_sem2, 20*log10(abs(Y_filt(1:N_sem2/2))+eps), 'r');
xlabel('Frequency [Hz]'); ylabel('Magnitude [dB]');
title('sem2\_final.wav After Filtering');
xlim([0 2000]); grid on;