diff --git a/docs/CR_SARAUDIO.pdf b/docs/CR_SARAUDIO.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cf766c6fad9f6135ae47781b4efc64a3011e3216 Binary files /dev/null and b/docs/CR_SARAUDIO.pdf differ diff --git a/src/Q2_1.m b/src/Q2_1.m new file mode 100644 index 0000000000000000000000000000000000000000..e956d8d5be548b16b553897c45df4652427ab774 --- /dev/null +++ b/src/Q2_1.m @@ -0,0 +1,31 @@ +% ------------------------------------------------------------------- +% Generated by MATLAB on 28-May-2025 19:33:47 +% MATLAB version: 24.2.0.2923080 (R2024b) Update 6 +% ------------------------------------------------------------------- +saveVarsMat = load('Q2_1.mat'); + +Fe = 40000; + +N = 4000; + +N2 = 2000; + +Xc = saveVarsMat.Xc; % <4000x1 double> too many elements + +Xs = saveVarsMat.Xs; % <4000x1 double> too many elements + +dur = 0.1; + +duree = 0.1; + +f = saveVarsMat.f; % <1x4000 double> too many elements + +f0 = 440; + +t = saveVarsMat.t; % <4000x1 double> too many elements + +xCarre = saveVarsMat.xCarre; % <4000x1 double> too many elements + +xScie = saveVarsMat.xScie; % <4000x1 double> too many elements + +clear saveVarsMat; diff --git a/src/Q2_2.m b/src/Q2_2.m new file mode 100644 index 0000000000000000000000000000000000000000..1fa0ae4abc502fcae8213fb2ecdc4db3e5fc0653 --- /dev/null +++ b/src/Q2_2.m @@ -0,0 +1,43 @@ +% ------------------------------------------------------------------- +% Generated by MATLAB on 28-May-2025 19:34:34 +% MATLAB version: 24.2.0.2923080 (R2024b) Update 6 +% ------------------------------------------------------------------- +saveVarsMat = load('Q2_2.mat'); + +Fe = 44100; + +H = saveVarsMat.H; % <4096x1 double> too many elements + +N = 4000; + +N2 = 2000; + +Xc = saveVarsMat.Xc; % <4000x1 double> too many elements + +Xs = saveVarsMat.Xs; % <4000x1 double> too many elements + +a = 1; + +b = [0.5 0.5]; + +dur = 0.1; + +duree = 0.1; + +f = saveVarsMat.f; % <1x4000 double> too many elements + +f0 = 440; + +t = saveVarsMat.t; % <4410x1 double> too many elements + +w = saveVarsMat.w; % <4096x1 double> too many elements + +x = saveVarsMat.x; % <4410x1 double> too many elements + +xCarre = saveVarsMat.xCarre; % <4000x1 double> too many elements + +xScie = saveVarsMat.xScie; % <4000x1 double> too many elements + +y = saveVarsMat.y; % <4410x1 double> too many elements + +clear saveVarsMat; diff --git a/src/Q2_3.m b/src/Q2_3.m new file mode 100644 index 0000000000000000000000000000000000000000..1b8b77cc3d8facea91f157d068969ab11ee9546d --- /dev/null +++ b/src/Q2_3.m @@ -0,0 +1,75 @@ +% ------------------------------------------------------------------- +% Generated by MATLAB on 28-May-2025 19:39:16 +% MATLAB version: 24.2.0.2923080 (R2024b) Update 6 +% ------------------------------------------------------------------- +saveVarsMat = load('Q2_3.mat'); + +A = saveVarsMat.A; % <1x2205 double> too many elements + +D = saveVarsMat.D; % <1x8820 double> too many elements + +Duree = 2; + +Fe = 44100; + +H = saveVarsMat.H; % <4096x1 double> too many elements + +N = 88200; + +N2 = 2000; + +N_A = 2205; + +N_D = 8820; + +N_R = 24255; + +N_S = 52920; + +R = saveVarsMat.R; % <1x24255 double> too many elements + +S = saveVarsMat.S; % <1x52920 double> too many elements + +T_Attack = 0.05; + +T_Decay = 0.2; + +T_Release = 0.55; + +T_Sustain = 1.2; + +Xc = saveVarsMat.Xc; % <4000x1 double> too many elements + +Xs = saveVarsMat.Xs; % <4000x1 double> too many elements + +a = 1; + +b = [0.5 0.5]; + +dur = 0.1; + +duree = 0.1; + +env = saveVarsMat.env; % <1x88200 double> too many elements + +f = saveVarsMat.f; % <1x4000 double> too many elements + +f0 = 440; + +f1 = 220; + +fe = 44100; + +t = saveVarsMat.t; % <1x88200 double> too many elements + +w = saveVarsMat.w; % <4096x1 double> too many elements + +x = saveVarsMat.x; % <1x88200 double> too many elements + +xCarre = saveVarsMat.xCarre; % <4000x1 double> too many elements + +xScie = saveVarsMat.xScie; % <4000x1 double> too many elements + +y = saveVarsMat.y; % <1x88200 double> too many elements + +clear saveVarsMat; diff --git a/src/Q2_4.m b/src/Q2_4.m new file mode 100644 index 0000000000000000000000000000000000000000..7693d414adaa9e0d27f99b2532816593fa6bf76a --- /dev/null +++ b/src/Q2_4.m @@ -0,0 +1,31 @@ +% ------------------------------------------------------------------- +% Generated by MATLAB on 28-May-2025 19:39:59 +% MATLAB version: 24.2.0.2923080 (R2024b) Update 6 +% ------------------------------------------------------------------- +saveVarsMat = load('Q2_4.mat'); + +Fe = 44100; + +bank = saveVarsMat.bank; % <3x2 cell> unsupported class at bank{1,1} + +dFIR30 = saveVarsMat.dFIR30; % <1x1 digitalFilter> unsupported class + +dFIR8 = saveVarsMat.dFIR8; % <1x1 digitalFilter> unsupported class + +dIIR = saveVarsMat.dIIR; % <1x1 digitalFilter> unsupported class + +dur = 1; + +h = saveVarsMat.h; % <4096x1 double> too many elements + +k = 3; + +t = saveVarsMat.t; % <44100x1 double> too many elements + +w = saveVarsMat.w; % <4096x1 double> too many elements + +x = saveVarsMat.x; % <44100x1 double> too many elements + +y = saveVarsMat.y; % <44100x1 double> too many elements + +clear saveVarsMat; diff --git a/src/analyse_delay.m b/src/analyse_delay.m new file mode 100644 index 0000000000000000000000000000000000000000..8b6267672bc4cdfd11aa0f05bf8485070858db08 --- /dev/null +++ b/src/analyse_delay.m @@ -0,0 +1,25 @@ +% analyse_delay.m +% Script pour calculer et afficher la réponse impulsionnelle du filtre de delay + +% Paramètres du filtre +g = 0.6; % coefficient d'atténuation +tau = 3; % retard en nombre d'échantillons +N = 100; % longueur du signal + +% Signal d'entrée : impulsion unité +x = zeros(1, N); +x(1) = 1; + +% Vecteurs a et b pour la fonction filter +a = [1, zeros(1, tau-1), g]; +b = 1; + +% Calcul de la réponse impulsionnelle +h = filter(b, a, x); + +% Affichage sans les gros points +stem(0:N-1, h, 'Marker', 'none'); +xlabel('k'); +ylabel('h(k)'); +title('Réponse impulsionnelle du filtre de delay (g = 0.6)'); +grid on; diff --git a/src/effet_delay.m b/src/effet_delay.m new file mode 100644 index 0000000000000000000000000000000000000000..d7ad5dfdea20b6da00534a4a44c80a7e14bb6420 --- /dev/null +++ b/src/effet_delay.m @@ -0,0 +1,23 @@ +function y = effet_delay(x, delay_time, g, Fe) + % Applique un effet de delay simple (IIR) au signal audio x + % x : signal d'entrée (mono/stéréo) + % delay_time : durée du delay en secondes + % g : coefficient d'atténuation + % Fe : fréquence d’échantillonnage (Hz) + % y : signal en sortie avec delay appliqué + + tau = round(delay_time * Fe); % Retard en échantillons + y = zeros(size(x)); % Initialisation + + num_channels = size(x, 2); + + for ch = 1:num_channels + for k = 1:length(x) + if k <= tau + y(k, ch) = x(k, ch); + else + y(k, ch) = x(k, ch) - g * y(k - tau, ch); + end + end + end +end diff --git a/src/effet_delay_filtre.m b/src/effet_delay_filtre.m new file mode 100644 index 0000000000000000000000000000000000000000..68f318700439a31332e2aaa7614454c20bf8a2cc --- /dev/null +++ b/src/effet_delay_filtre.m @@ -0,0 +1,25 @@ +function y = effet_delay_filtre(x, delay_time, g, K, Fe) + % Applique un effet de delay avec filtre (moyenne glissante) dans la boucle + % x : signal audio (mono/stéréo) + % delay_time : temps du delay en secondes + % g : coefficient d’atténuation + % K : taille de la moyenne glissante + % Fe : fréquence d’échantillonnage (Hz) + % y : signal de sortie + + tau = round(delay_time * Fe); + y = zeros(size(x)); + N = length(x); + num_channels = size(x, 2); + + for ch = 1:num_channels + for k = 1:N + if k <= tau + K - 1 + y(k, ch) = x(k, ch); + else + feedback = sum(y(k - tau - (0:K-1), ch)) / K; + y(k, ch) = x(k, ch) - g * feedback; + end + end + end +end diff --git a/src/effet_reverb.m b/src/effet_reverb.m new file mode 100644 index 0000000000000000000000000000000000000000..cca9f1f52d8b3e4cd3347d7a2118b63d2957007e --- /dev/null +++ b/src/effet_reverb.m @@ -0,0 +1,18 @@ +function y = effet_reverb(x, h) +%EFFET_REVERB Applique une réverbération à un signal audio +% x : signal audio source +% h : réponse impulsionnelle estimée de la pièce +% y : signal en sortie avec effet de réverbération + + % Vérification des dimensions + if size(x,2) > 1 + x = x(:); % S'assurer que x est un vecteur colonne + end + + if size(h,2) > 1 + h = h(:); % S'assurer que h est un vecteur colonne + end + + % Application de la réverbération par convolution + y = conv(x, h, 'full'); % on garde toute la convolution +end diff --git a/src/effet_reverb_FFT.m b/src/effet_reverb_FFT.m new file mode 100644 index 0000000000000000000000000000000000000000..2a5aea7b174b1a3f9ab1cc3d70755e26cc59c628 --- /dev/null +++ b/src/effet_reverb_FFT.m @@ -0,0 +1,29 @@ +function [y, temps_execution] = effet_reverb_FFT(x, h) +% EFFET_REVERB_FFT Applique une réverbération par convolution rapide (FFT) +% x : signal audio source +% h : réponse impulsionnelle +% y : signal en sortie (réverbéré) +% temps_execution : temps de calcul en secondes + + % Assurer que x et h sont des vecteurs colonnes + x = x(:); + h = h(:); + + % Début du chronométrage + tic; + + % Taille optimale de la FFT + NFFT = 2^nextpow2(length(x) + length(h) - 1); + + % Calculs dans le domaine fréquentiel + Xf = fft(x, NFFT); + Hf = fft(h, NFFT); + Yf = Xf .* Hf; + + % Retour au domaine temporel + y = ifft(Yf); + y = real(y); % on garde uniquement la partie réelle + + % Fin du chronométrage + temps_execution = toc; +end diff --git a/src/q1_1.m b/src/q1_1.m new file mode 100644 index 0000000000000000000000000000000000000000..98ee9e9cdf81b6c5158b2c3c9929d0a5c283c264 --- /dev/null +++ b/src/q1_1.m @@ -0,0 +1,34 @@ +% Liste des fichiers audio +fichiers = { 'single_tone_celtic-harp-a3.wav', ... + 'single_tone_double-bass-a3.wav', ... + 'single_tone_guitar_nylon_string_a3.wav', ... + 'single_tone_piano1.wav', ... + 'single_tone_piano2.wav', ... + 'single_tone_violin-a3.wav'... + 'single_tone_cymbal-14-hard-hit-a'... + 'single_toy_glockenspiel_a3.wav' + + + +}; + +for i = 1:length(fichiers) + % Lecture du fichier audio + [x, fe] = audioread(fichiers{i}); + + % Transformée de Fourier et centrage du spectre + N = length(x); + X = fftshift(fft(x)); + f = linspace(-fe/2, fe/2, N); + + % Amplitude en décibels + amplitude = 20 * log10(abs(X) + eps); % Ajout de eps pour éviter log(0) + + % Affichage du spectre + figure; + plot(f, amplitude); + xlabel('Fréquence (Hz)'); + ylabel('Amplitude (dB)'); + title(['Spectre de : ', fichiers{i}]); + grid on; +end diff --git a/src/q1_2.m b/src/q1_2.m new file mode 100644 index 0000000000000000000000000000000000000000..b47b4a43c95bf40ff7e263bceaaaffe4f7fd6e31 --- /dev/null +++ b/src/q1_2.m @@ -0,0 +1,31 @@ +% Chargement des sons de piano +[x1, Fs1] = audioread('single_tone_piano1.wav'); +[x2, Fs2] = audioread('single_tone_piano2.wav'); + +% Taille des signaux +N1 = length(x1); +N2 = length(x2); + +% Calcul FFT avec fftshift +X1 = fftshift(fft(x1)); +X2 = fftshift(fft(x2)); + +% Axe fréquentiel centré [-Fe/2, Fe/2] +f1 = (-N1/2:N1/2-1)*(Fs1/N1); +f2 = (-N2/2:N2/2-1)*(Fs2/N2); + +% Amplitude en dB +amp1_dB = 20*log10(abs(X1)/max(abs(X1))); +amp2_dB = 20*log10(abs(X2)/max(abs(X2))); + +% Affichage +figure; +plot(f1, amp1_dB, 'b', 'DisplayName', 'Piano 1'); +hold on; +plot(f2, amp2_dB, 'r', 'DisplayName', 'Piano 2'); +xlabel('Fréquence (Hz)'); +ylabel('Amplitude (dB)'); +title('Spectres des sons de piano (centrés)'); +legend('show'); +xlim([-min(Fs1, Fs2)/2, min(Fs1, Fs2)/2]); % pour avoir le même axe horizontal +grid on; diff --git a/src/q1_4.m b/src/q1_4.m new file mode 100644 index 0000000000000000000000000000000000000000..56ebb349e8da8e42cf4bfd1aff809165f7f0e5d6 --- /dev/null +++ b/src/q1_4.m @@ -0,0 +1,55 @@ +% --- Q4 : Application d’une enveloppe ADSR --- + +% Paramètres de base +Fs = 44100; +dur = 2; % secondes +t = linspace(0, dur, dur*Fs); + +% Fréquences et amplitudes mesurées (issues de Q3) +f_mes = [220.374, 442.041, 663.224, 885.538, 1108.34, 1331.46, 1556.36, 1782.72]; +amps = [4835.3, 3353.6, 728.38, 686.6, 397.52, 597.14, 570.37, 79.851]; + +% Synthèse du signal pur (sans enveloppe) +synth = zeros(size(t)); +for k = 1:length(f_mes) + synth = synth + amps(k) * sin(2*pi*f_mes(k)*t); +end +synth = synth / max(abs(synth)); % Normalisation + +% Paramètres de l'enveloppe ADSR +attack_time = 0.1; +decay_time = 0.1; +sustain_level = 0.6; +release_time = 0.4; +total_samples = length(synth); + +attack_samples = round(attack_time * Fs); +decay_samples = round(decay_time * Fs); +release_samples = round(release_time * Fs); +sustain_samples = total_samples - (attack_samples + decay_samples + release_samples); + +% Création de l'enveloppe ADSR +attack_env = linspace(0, 1, attack_samples); +decay_env = linspace(1, sustain_level, decay_samples); +sustain_env = sustain_level * ones(1, sustain_samples); +release_env = linspace(sustain_level, 0, release_samples); +envelope = [attack_env, decay_env, sustain_env, release_env]; + +% Ajustement si besoin +envelope = envelope(1:total_samples); + +% Application de l’enveloppe +synth_adsr = synth .* envelope; + +% Sauvegarde audio +audiowrite('synth_adsr.wav', synth_adsr, Fs); + +% Affichage du signal dans le temps (zoom) +figure; +plot(t, synth_adsr); +xlim([0 0.6]); ylim([-1 1]); +xlabel('Temps (s)'); +ylabel('Amplitude'); +title('Signal synthétisé avec enveloppe ADSR'); +grid on; +saveas(gcf, 'q4_waveform_adsr.jpg'); diff --git a/src/q1_5.m b/src/q1_5.m new file mode 100644 index 0000000000000000000000000000000000000000..2428ace9274c556ba3a924db5c397eaf68161653 --- /dev/null +++ b/src/q1_5.m @@ -0,0 +1,53 @@ +% Q1.5 - Synthèse par IFFT à partir du spectre artificiel + +clear; close all; + +% Paramètres +Fs = 44100; +N = 2^14; % Nombre d’échantillons +df = Fs / N; % Résolution fréquentielle + +% Fréquences et amplitudes mesurées (issues de Q1.3) +f_mes = [220.374, 442.041, 663.224, 885.538, 1108.34, 1331.46, 1556.36, 1782.72]; +amps = [4835.3, 3353.6, 728.38, 686.6, 397.52, 597.14, 570.37, 79.851]; + +% Création du spectre complexe +X = zeros(1, N); +for k = 1:length(f_mes) + idx = round(f_mes(k) / df) + 1; % index dans le spectre + X(idx) = amps(k); % partie positive + X(N - idx + 2) = conj(amps(k)); % symétrie hermitienne +end + +% Reconstruction du signal par IFFT +x_ifft = real(ifft(X)); % on garde toute l'énergie, pas de normalisation + +% Pour écoute uniquement (pas pour le spectre !) +sound(x_ifft / max(abs(x_ifft)), Fs); +audiowrite('q5_ifft.wav', x_ifft / max(abs(x_ifft)), Fs); + +% Calcul du spectre reconstruit +X_reconstructed = abs(fft(x_ifft)); +f_axis = (0:N-1)*(Fs/N); + +% Génération de la figure demandée +figure; + +% Spectre d’entrée artificiel +subplot(2,1,1) +stem(f_mes, amps, 'Marker', 'none'); +title('Spectre du signal d’entrée (artificiel)', 'FontWeight', 'bold'); +xlabel('Fréquence (Hz)'); +ylabel('Amplitude'); +xlim([0 2000]); grid on; + +% Spectre reconstruit +subplot(2,1,2) +stem(f_axis(1:N/2), X_reconstructed(1:N/2), 'Marker', 'none'); +title('Spectre du signal reconstruit (via IFFT puis FFT)', 'FontWeight', 'bold'); +xlabel('Fréquence (Hz)'); +ylabel('Amplitude'); +xlim([0 2000]); grid on; + +% Sauvegarde +saveas(gcf, 'q5_spectres_ifft.jpg'); diff --git a/src/q3-4.m b/src/q3-4.m new file mode 100644 index 0000000000000000000000000000000000000000..8bda22a3846e9809de69e2059f65a0549d9913ee --- /dev/null +++ b/src/q3-4.m @@ -0,0 +1,32 @@ +% --- ÉTAPE 1 : Charger le signal d’excitation --- +load('signal_excitation.mat'); % contient les signaux xe1, xe2 et la fréquence d’échantillonnage 'fe' + +x = xe1; % On choisit xe1, car son autocorrélation est proche d’un Dirac +x = x / max(abs(x)); % Normalisation pour éviter la saturation + +% --- ÉTAPE 2 : Simuler le signal reçu dans une pièce --- +% La pièce est modélisée comme un filtre avec une réponse impulsionnelle inconnue +y = simule_piece(x, fe); % y = x * h (h est inconnue mais simulée) + +% --- ÉTAPE 3 : Estimer la réponse impulsionnelle --- +% On calcule la corrélation croisée entre y (signal capté) et x (signal émis) +[ryx, lag] = xcorr(y, x); % Corrélation croisée + lags associés + +% --- ÉTAPE 4 : Extraire la partie causale --- +% La réponse impulsionnelle commence à k = 0 (lag = 0) +idx0 = find(lag == 0); % Position du décalage nul +h_est = ryx(idx0:end); % On garde uniquement la partie causale + +% --- ÉTAPE 5 : Construire l’axe temporel --- +t = (0:length(h_est)-1) / fe; % Axe temps en secondes (fe = fréquence d’échantillonnage) + +% --- ÉTAPE 6 : Affichage --- +fig = figure; +plot(t, h_est); +xlabel('Temps (s)'); +ylabel('Amplitude'); +title('Réponse impulsionnelle estimée de la pièce'); +grid on; + +% --- ÉTAPE 7 : Sauvegarde de la figure --- +saveas(fig, 'q3_reponse_impulsionnelle.jpg'); diff --git a/src/q3_14.m b/src/q3_14.m new file mode 100644 index 0000000000000000000000000000000000000000..6e13fabd2e1ce91267c85d1013b8a53f4ec3630e --- /dev/null +++ b/src/q3_14.m @@ -0,0 +1,31 @@ +%Q3.14 +% --- Paramètres du filtre --- +tau = 20; % Retard (en échantillons) +g = 0.8; % Coefficient d'atténuation +Fe = 44100; % Fréquence d'échantillonnage +N = 1000; % Taille pour la DFT (grande pour meilleure résolution) + +% --- Réponse impulsionnelle simulée --- +x = [1; zeros(N-1,1)]; +b = 1; +a = zeros(1, N); a(1) = 1; a(tau+1) = g; % vecteur a avec g au bon endroit +h = filter(b, a, x); % réponse impulsionnelle + +% --- Réponse fréquentielle numérique (via FFT) --- +H_dft = fft(h, N); +H_dft_mag = abs(H_dft(1:N/2)); % module de la réponse sur [0, 0.5] +nu = linspace(0, 0.5, N/2); % fréquence réduite + +% --- Réponse fréquentielle théorique --- +H_theo = 1 ./ sqrt(1 + 2*g*cos(2*pi*nu*tau) + g^2); + +% --- Affichage --- +figure; +plot(nu, H_theo, 'b', 'LineWidth', 1.5); hold on; +plot(nu, H_dft_mag, 'r--', 'LineWidth', 1.2); +xlabel('Fréquence réduite \nu'); +ylabel('Module |H(\nu)|'); +title('Comparaison du module de la réponse en fréquence'); +legend('Théorique', 'Numérique (DFT)'); +grid on; +saveas(gcf, 'q3_14.jpg') \ No newline at end of file diff --git a/src/q3_16.m b/src/q3_16.m new file mode 100644 index 0000000000000000000000000000000000000000..af6bfaabab79e698d2b3b6ccc52e69fac28a01ea --- /dev/null +++ b/src/q3_16.m @@ -0,0 +1,52 @@ +%q3.15-16 + +function y = effet_delay(x, delay_time, g, Fe) + % Applique un effet de delay simple (IIR) au signal audio x + % + % x : signal d'entrée (vecteur mono ou stéréo) + % delay_time : temps du delay en secondes + % g : coefficient d'amortissement + % Fe : fréquence d'échantillonnage (en Hz) + % + % y : signal de sortie modifié avec effet delay + + tau = round(delay_time * Fe); % delay en nombre d'échantillons + y = zeros(size(x)); % initialisation du signal de sortie + + % Pour les signaux mono et stéréo + num_channels = size(x, 2); + + for ch = 1:num_channels + for k = 1:length(x) + if k <= tau + y(k, ch) = x(k, ch); % pas encore de feedback + else + y(k, ch) = x(k, ch) - g * y(k - tau, ch); + end + end + end +end + +% Script pour tester effet_delay sur un son de piano + +% Paramètres +Fe = 44100; % Fréquence d'échantillonnage +delay_time = 0.25; % Delay = 0.25 s +g = 0.9; % Coefficient d'atténuation + +% Chargement du son de piano +[x, Fe_read] = audioread('single_tone_piano1.wav'); +if Fe_read ~= Fe + error('Le fichier audio ne correspond pas à Fe = 44100 Hz.'); +end + +% Application de l'effet +y = effet_delay(x, delay_time, g, Fe); + +% Écoute du résultat +soundsc(y, Fe); + +% Sauvegarde +audiowrite('q.16piano1_delay.wav', y, Fe); + +disp('Effet delay appliqué et sauvegardé dans "piano_delay.wav".'); diff --git a/src/q3_19.m b/src/q3_19.m new file mode 100644 index 0000000000000000000000000000000000000000..832bb7dab6fa3d5363d031878d83aa5da8a602ee --- /dev/null +++ b/src/q3_19.m @@ -0,0 +1,21 @@ +% Question 3.19 – Réponse en fréquence du filtre moyenne glissante + +Fe = 44100; % fréquence d'échantillonnage +K = 10; % taille de la moyenne glissante + +% Réponse impulsionnelle du filtre +h = ones(1, K) / K; + +% Calcul de la réponse en fréquence +N = 1024; % résolution FFT +H = fft(h, N); +f = (0:N-1) * Fe / N; % axe des fréquences en Hz + +% Tracé du module +figure; +plot(f, abs(H)); +title('Module de la réponse en fréquence du filtre moyenne glissante'); +xlabel('Fréquence (Hz)'); +ylabel('|H(f)|'); +grid on; +xlim([0 Fe/2]); % limiter à la bande de Nyquist diff --git a/src/q3_3.m b/src/q3_3.m new file mode 100644 index 0000000000000000000000000000000000000000..bea498edc00e886fa2015e7f634ff34f643fcc74 --- /dev/null +++ b/src/q3_3.m @@ -0,0 +1,30 @@ +% --- Q3.3 : Comparaison des signaux d'excitation --- + +clear; close all; + +% Chargement du fichier contenant xe1, xe2 et Fs +load('signal_excitation.mat'); % le fichier doit contenir xe1, xe2, Fe + +% Calcul des autocorrélations normalisées +[rx1, lags1] = xcorr(xe1, 'coeff'); +[rx2, lags2] = xcorr(xe2, 'coeff'); + +% Affichage des résultats +figure; + +subplot(2,1,1) +plot(lags1, rx1); +title('Autocorrélation de xe1 (normalisée)'); +xlabel('Décalage (échantillons)'); +ylabel('R_{xx}'); +grid on; + +subplot(2,1,2) +plot(lags2, rx2); +title('Autocorrélation de xe2 (normalisée)'); +xlabel('Décalage (échantillons)'); +ylabel('R_{xx}'); +grid on; + +% Sauvegarde optionnelle +saveas(gcf, 'q3_3_autocorrelations.jpg'); diff --git a/src/q_1_3.m b/src/q_1_3.m new file mode 100644 index 0000000000000000000000000000000000000000..f7f00d47aa5fef8754d0bcfc6a3ca3cd0633040f --- /dev/null +++ b/src/q_1_3.m @@ -0,0 +1,41 @@ +% Lecture du signal réel +[x1, Fs] = audioread('single_tone_piano1.wav'); +N = length(x1); +X1 = fft(x1); +f_axis = (0:N-1)*(Fs/N); + +% Fréquences des 8 premières harmoniques (en Hz) +f_mes = [220.374, 442.041, 663.224, 885.538, 1108.34, 1331.46, 1556.36, 1782.72]; + +% Amplitudes mesurées dans la FFT (linéaires) +amps = zeros(1, length(f_mes)); +for k = 1:length(f_mes) + idx = round(f_mes(k) * N / Fs); + amps(k) = abs(X1(idx)); +end + +% Durée de synthèse et vecteur temps +dur = 2; % secondes +t = linspace(0, dur, dur*Fs); + +% Synthèse additive +synth = zeros(size(t)); +for k = 1:length(f_mes) + synth = synth + amps(k) * sin(2*pi*f_mes(k)*t); +end + +% Normalisation et lecture +synth = synth / max(abs(synth)); +sound(synth, Fs); + +% Sauvegarde audio +audiowrite('piano1_synthetise.wav', synth, Fs); + +% Génération de la figure temporelle +figure; +plot(t, synth); +xlabel('Temps (s)'); +ylabel('Amplitude'); +title('Signal synthétisé par addition des 8 premières harmoniques'); +xlim([0 0.05]); % zoom sur 50 ms pour visualiser les cycles +saveas(gcf, 'q3_waveform.jpg'); diff --git a/src/test_effet_delay_16.m b/src/test_effet_delay_16.m new file mode 100644 index 0000000000000000000000000000000000000000..d1954f7b18ba9cfa949ff74d6bea09e603b50c58 --- /dev/null +++ b/src/test_effet_delay_16.m @@ -0,0 +1,15 @@ +% Test de la fonction effet_delay + +Fe = 44100; % Fréquence d'échantillonnage +delay_time = 0.25; % Delay de 250 ms +g = 0.9; % Coefficient d’atténuation + +[x, Fe_read] = audioread('single_tone_piano1.wav'); +if Fe_read ~= Fe + error('Fréquence d’échantillonnage incompatible.'); +end + +y = effet_delay(x, delay_time, g, Fe); + +soundsc(y, Fe); % Écoute +audiowrite('q.16piano1_delay.wav', y, Fe); % Sauvegarde diff --git a/src/test_effet_delay_18.m b/src/test_effet_delay_18.m new file mode 100644 index 0000000000000000000000000000000000000000..be269772f52b65374e5ad1c435c026d5d56fd398 --- /dev/null +++ b/src/test_effet_delay_18.m @@ -0,0 +1,16 @@ +% Test de effet_delay_filtre + +Fe = 44100; % Fréquence d’échantillonnage +delay_time = 0.25; % 250 ms +g = 0.9; % Amortissement +K = 10; % Fenêtre de moyenne glissante + +[x, Fe_read] = audioread('single_tone_piano1.wav'); +if Fe_read ~= Fe + error('Fréquence d’échantillonnage incorrecte.'); +end + +y = effet_delay_filtre(x, delay_time, g, K, Fe); + +soundsc(y, Fe); % Écoute +audiowrite('piano_delay_filtre.wav', y, Fe); % Sauvegarde diff --git a/src/test_effet_reverb.m b/src/test_effet_reverb.m new file mode 100644 index 0000000000000000000000000000000000000000..61378b409d3ba1b7615732a1128c98adb3e53d26 --- /dev/null +++ b/src/test_effet_reverb.m @@ -0,0 +1,44 @@ +% --- Test de la fonction effet_reverb (Q3.6) --- + +clear; close all; + +% Étape 1 : Charger le signal de guitare +[x, Fe] = audioread('single_tone_guitar_nylon_string_a3.wav'); +x = x(:,1); % en cas de signal stéréo, on garde un seul canal +x = x / max(abs(x)); % normalisation pour éviter la saturation + +% Étape 2 : Charger ou estimer la réponse impulsionnelle +load('signal_excitation.mat'); % contient xe1, fe +x_ex = xe1 / max(abs(xe1)); +h = simule_piece(x_ex, fe); % estimation de h à partir de xe1 +[ryx, lag] = xcorr(h, x_ex); +h_est = ryx(find(lag == 0):end); % partie causale + +% Étape 3 : Appliquer la réverbération et mesurer le temps d'exécution +tic; +y = effet_reverb(x, h_est); +temps_execution = toc; + +% Étape 4 : Affichage des signaux +t_x = (0:length(x)-1)/Fe; +t_y = (0:length(y)-1)/Fe; + +figure; + +subplot(2,1,1); +plot(t_x, x, 'b'); +title('Signal original (guitare)'); +xlabel('Temps (s)'); ylabel('Amplitude'); +grid on; + +subplot(2,1,2); +plot(t_y, y / max(abs(y)), 'r'); % normalisation visuelle +title('Signal avec réverbération'); +xlabel('Temps (s)'); ylabel('Amplitude'); +grid on; + +% Étape 5 : Sauvegarde de la figure +saveas(gcf, 'q3_6_reverb_guitare.jpg'); + +% Étape 6 : Affichage du temps +fprintf('Temps d''exécution de la réverbération : %.3f secondes\n', temps_execution); diff --git a/src/test_effet_reverb_fft.m b/src/test_effet_reverb_fft.m new file mode 100644 index 0000000000000000000000000000000000000000..9d16230c931c4abd8b132f88577c8f1239f80566 --- /dev/null +++ b/src/test_effet_reverb_fft.m @@ -0,0 +1,41 @@ +% --- Test de la fonction effet_reverb_FFT (convolution rapide par FFT) --- + +clear; close all; + +% Étape 1 : Charger le signal de guitare +[x, Fe] = audioread('single_tone_guitar_nylon_string_a3.wav'); +x = x(:,1); +x = x / max(abs(x)); + +% Étape 2 : Estimer la réponse impulsionnelle +load('signal_excitation.mat'); % contient xe1, fe +x_ex = xe1 / max(abs(xe1)); +h_sim = simule_piece(x_ex, fe); +[ryx, lag] = xcorr(h_sim, x_ex); +h_est = ryx(find(lag == 0):end); % partie causale + +% Étape 3 : Appliquer l'effet FFT +[y_fft, temps_fft] = effet_reverb_FFT(x, h_est); + +% Étape 4 : Affichage +t_x = (0:length(x)-1)/Fe; +t_y = (0:length(y_fft)-1)/Fe; + +figure; +subplot(2,1,1); +plot(t_x, x); +title('Signal original (guitare)'); +xlabel('Temps (s)'); ylabel('Amplitude'); grid on; + +subplot(2,1,2); +plot(t_y, y_fft / max(abs(y_fft))); +title('Signal avec réverbération (FFT)'); +xlabel('Temps (s)'); ylabel('Amplitude'); grid on; + +% Étape 5 : Écoute et sauvegarde audio +sound(y_fft / max(abs(y_fft)), Fe); +audiowrite('reverb_fft.wav', y_fft / max(abs(y_fft)), Fe); + +% Étape 6 : Sauvegarde de la figure et affichage du temps +saveas(gcf, 'q3_7_reverb_fft.jpg'); +fprintf('Temps d''exécution (FFT) : %.4f secondes\n', temps_fft);