diff --git a/src/applicationSons.m b/src/applicationSons.m index 128cd9b11fbe26db6ab9ca9f87f51b098b4594cf..56354420bcad633af45bc35666a1e13870cc8181 100644 --- a/src/applicationSons.m +++ b/src/applicationSons.m @@ -1,11 +1,20 @@ fileName_cello = "wav/single_tone_cello-a3.wav"; fileName_piano1 = "wav/single_tone_piano1.wav"; fileName_piano2 = "wav/single_tone_piano2.wav"; +fileName_sax_alto = "wav/single_tone_sax-alto-a3.wav"; +fileName_sax_soprano = "wav/single_tone_sax-soprano-a3.wav"; +fileName_trumpet = "wav/single_tone_trumpet-a3.wav"; [x_cello, fs_cello] = audioread(fileName_cello); [x_piano1, fs_piano1] = audioread(fileName_piano1); [x_piano2, fs_piano2] = audioread(fileName_piano2); +[x_sax_alto, fs_sax_alto] = audioread(fileName_sax_alto); +[x_sax_soprano, fs_sax_soprano] = audioread(fileName_sax_soprano); +[x_trumpet, fs_trumpet] = audioread(fileName_trumpet); [amplitude_cello, f1_cello] = analyseSonHarmonique(x_cello, fs_cello); [amplitude_piano1, f1_piano1] = analyseSonHarmonique(x_piano1, fs_piano1); -[amplitude_piano2, f1_piano2] = analyseSonHarmonique(x_piano2, fs_piano2); \ No newline at end of file +[amplitude_piano2, f1_piano2] = analyseSonHarmonique(x_piano2, fs_piano2); +[amplitude_sax_alto, f1_sax_alto] = analyseSonHarmonique(x_sax_alto, fs_sax_alto); +[amplitude_sax_soprano, f1_sax_soprano] = analyseSonHarmonique(x_sax_soprano, fs_sax_soprano); +[amplitude_trumpet, f1_trumpet] = analyseSonHarmonique(x_trumpet, fs_trumpet); \ No newline at end of file diff --git a/src/comparaisonPianos.m b/src/comparaisonPianos.m index 6f7dd113b292e3557023943baa33ea89aa315009..160b4a4a8e4cbc5113b471f8d9e694617ab0453a 100644 --- a/src/comparaisonPianos.m +++ b/src/comparaisonPianos.m @@ -29,14 +29,86 @@ legend('Piano 1', 'Piano 2'); % Calcul des fondamentales [~, index1] = max(amplitude_piano1); % Trouver l'indice de la fréquence fondamentale [~, index2] = max(amplitude_piano2); % Trouver l'indice de la fréquence fondamentale -f1 = f1(index1); % Fréquence fondamentale -f2 = f2(index2); % Fréquence fondamentale -disp(['Fréquence fondamentale Piano 1 : ', num2str(f1), ' Hz']); -disp(['Fréquence fondamentale Piano 2 : ', num2str(f2), ' Hz']); +ff1 = f1(index1); % Fréquence fondamentale +ff2 = f2(index2); % Fréquence fondamentale +disp(['Fréquence fondamentale Piano 1 : ', num2str(ff1), ' Hz']); +disp(['Fréquence fondamentale Piano 2 : ', num2str(ff2), ' Hz']); + +% Index des harmoniques +harmonic_indices1 = [index1, index1*2, index1*3, index1*4, index1*5, index1*6, index1*7]; +harmonic_indices2 = [index2, index2*2, index2*3, index2*4, index2*5, index2*6, index2*7]; + +% Fréquences des harmoniques théoriques +fh1theorique = ff1 * (1:7); % Fréquences théoriques des harmoniques +fh2theorique = ff2 * (1:7); % Fréquences théoriques des harmoniques + +disp(['Fréquences harmoniques théoriques Piano 1 : ', num2str(fh1theorique)]); +disp(['Fréquences harmoniques théoriques Piano 2 : ', num2str(fh2theorique)]); + +% Trouver les indices des harmoniques en cherchant les pics près des fréquences attendues +window_width = 50; % Hz - largeur de recherche autour de la fréquence théorique + +% Mesure des harmoniques pour Piano 1 +ff1_harmonics = zeros(1, 7); +for h = 1:7 + expected_freq = fh1theorique(h); + % Trouver les indices proches de la fréquence harmonique théorique + [~, idx] = min(abs(f1 - expected_freq)); + % Chercher le maximum local dans une fenêtre autour de cet indice + start_idx = max(1, idx - 10); + end_idx = min(length(f1), idx + 10); + [~, max_local_idx] = max(amplitude_piano1(start_idx:end_idx)); + harmonics_idx1 = start_idx + max_local_idx - 1; + ff1_harmonics(h) = f1(harmonics_idx1); +end + +% Mesure des harmoniques pour Piano 2 +ff2_harmonics = zeros(1, 7); +for h = 1:7 + expected_freq = fh2theorique(h); + % Trouver les indices proches de la fréquence harmonique théorique + [~, idx] = min(abs(f2 - expected_freq)); + % Chercher le maximum local dans une fenêtre autour de cet indice + start_idx = max(1, idx - 10); + end_idx = min(length(f2), idx + 10); + [~, max_local_idx] = max(amplitude_piano2(start_idx:end_idx)); + harmonics_idx2 = start_idx + max_local_idx - 1; + ff2_harmonics(h) = f2(harmonics_idx2); +end + +% Assigner les harmoniques individuelles pour plus de clarté +ff1_1 = ff1_harmonics(1); +ff1_2 = ff1_harmonics(2); +ff1_3 = ff1_harmonics(3); +ff1_4 = ff1_harmonics(4); +ff1_5 = ff1_harmonics(5); +ff1_6 = ff1_harmonics(6); +ff1_7 = ff1_harmonics(7); + +ff2_1 = ff2_harmonics(1); +ff2_2 = ff2_harmonics(2); +ff2_3 = ff2_harmonics(3); +ff2_4 = ff2_harmonics(4); +ff2_5 = ff2_harmonics(5); +ff2_6 = ff2_harmonics(6); +ff2_7 = ff2_harmonics(7); % Calcul des degrés d'inharmonicité pour 5 harmoniques -deg1 = [1200*log2(f1/f1), 1200*log2(f1/2*f1), 1200*log2(f1/3*f1), 1200*log2(f1/4*f1), 1200*log2(f1/5*f1), 1200*log2(f1/6*f1), 1200*log2(f1/7*f1), 1200*log2(f1/8*f1)]; -deg2 = [1200*log2(f2/f2), 1200*log2(f2/2*f2), 1200*log2(f2/3*f2), 1200*log2(f2/4*f2), 1200*log2(f2/5*f2), 1200*log2(f2/6*f2), 1200*log2(f2/7*f2), 1200*log2(f2/8*f2)]; +deg1 = [abs(1200*(log2(ff1_1)-log2(ff1_1))), ... + abs(1200*(log2(ff1_2)-log2(2*ff1_1))), ... + abs(1200*(log2(ff1_3)-log2(3*ff1_1))), ... + abs(1200*(log2(ff1_4)-log2(4*ff1_1))), ... + abs(1200*(log2(ff1_5)-log2(5*ff1_1))), ... + abs(1200*(log2(ff1_6)-log2(6*ff1_1))), ... + abs(1200*(log2(ff1_7)-log2(7*ff1_1)))]; +deg2 = [abs(1200*(log2(ff2_1)-log2(ff2_1))), ... + abs(1200*(log2(ff2_2)-log2(2*ff2_1))), ... + abs(1200*(log2(ff2_3)-log2(3*ff2_1))), ... + abs(1200*(log2(ff2_4)-log2(4*ff2_1))), ... + abs(1200*(log2(ff2_5)-log2(5*ff2_1))), ... + abs(1200*(log2(ff2_6)-log2(6*ff2_1))), ... + abs(1200*(log2(ff2_7)-log2(7*ff2_1)))]; + disp(['Degré d inharmonicité Piano 1 : ', num2str(deg1)]); disp(['Degré d inharmonicité Piano 2 : ', num2str(deg2)]); @@ -51,10 +123,10 @@ legend('Piano 1', 'Piano 2'); % Récupérer les amplitudes des 8 premières harmoniques du piano1 harmonic_amplitudes = zeros(1, 8); -harmonic_frequencies = f1 * (1:8); % Fréquences des 8 premières harmoniques +harmonic_frequencies = ff1 * (1:8); % Fréquences des 8 premières harmoniques for k = 1:8 - [~, idx] = min(abs(f1 - harmonic_frequencies(k))); % Trouver l'indice de la fréquence harmonique + [~, idx] = min(abs(ff1 - harmonic_frequencies(k))); % Trouver l'indice de la fréquence harmonique harmonic_amplitudes(k) = abs(singalFFTpiano1(idx)); % Amplitude correspondante end @@ -70,9 +142,6 @@ end % Normaliser le signal synthétisé synthesized_signal = synthesized_signal / max(abs(synthesized_signal)); -% Écouter le son généré -sound(synthesized_signal, fs_piano1); - % Sauvegarder le son généré dans un fichier audiowrite('synthesized_piano1.wav', synthesized_signal, fs_piano1); @@ -100,9 +169,6 @@ envelope = envelope(1:length(t)); % Appliquer l'enveloppe au signal synthétisé synthesized_signal = synthesized_signal .* envelope; -% Écouter le son avec l'enveloppe ADSR -sound(synthesized_signal, fs_piano1); - % Sauvegarder le son avec l'enveloppe ADSR dans un fichier audiowrite('synthesized_piano1_with_adsr.wav', synthesized_signal, fs_piano1); @@ -123,9 +189,6 @@ synthesized_signal_ifft = real(ifft(spectrum)); % Normaliser le signal synthétisé synthesized_signal_ifft = synthesized_signal_ifft / max(abs(synthesized_signal_ifft)); -% Écouter le son généré -sound(synthesized_signal_ifft, fs_piano1); - % Sauvegarder le son généré dans un fichier audiowrite('synthesized_piano1_ifft.wav', synthesized_signal_ifft, fs_piano1); diff --git a/src/filtered_sawtooth.wav b/src/filtered_sawtooth.wav new file mode 100644 index 0000000000000000000000000000000000000000..15c9ff303277e26eb7c3d8582ccd70f82e3db398 Binary files /dev/null and b/src/filtered_sawtooth.wav differ diff --git a/src/filtered_square.wav b/src/filtered_square.wav new file mode 100644 index 0000000000000000000000000000000000000000..c1b7907d9cbb63ee2f90915a4cd8be22c13261cf Binary files /dev/null and b/src/filtered_square.wav differ diff --git a/src/original_sawtooth.wav b/src/original_sawtooth.wav new file mode 100644 index 0000000000000000000000000000000000000000..d67b8a72f133c61206fefdc068e1bee4c3b21479 Binary files /dev/null and b/src/original_sawtooth.wav differ diff --git a/src/original_square.wav b/src/original_square.wav new file mode 100644 index 0000000000000000000000000000000000000000..e47d7ab71468da05ee241852692ee89fa3080c50 Binary files /dev/null and b/src/original_square.wav differ diff --git a/src/syntheseSoustractive.m b/src/syntheseSoustractive.m index 4cf6fd05043e291b7be2df6987e4fdc8fec5392e..bfd94e1f78c67a27eda4b4f6c15bcb8f3988c6ea 100644 --- a/src/syntheseSoustractive.m +++ b/src/syntheseSoustractive.m @@ -56,57 +56,161 @@ xlabel('Fréquence (Hz)'); ylabel('Amplitude'); % Filtrage passe-bas d'ordre 1 -% y(k) = 0.5 * (x(k) + x(k-1)) +% Implémentation du filtre y(k) = 0.5 * (x(k) + x(k-1)) +b = [0.5, 0.5]; % Coefficients du numérateur +a = [1]; % Coefficients du dénominateur +% Application du filtre aux signaux +filtered_square = filter(b, a, square_signal); +filtered_sawtooth = filter(b, a, sawtooth_signal); -% Application du filtre au signal carré -square_filtered = filter([0.5, 0.5], 1, square_signal); +% Calcul du spectre des signaux filtrés +filtered_square_fft = fftshift(fft(filtered_square)); +filtered_square_magnitude = abs(filtered_square_fft) / N; + +filtered_sawtooth_fft = fftshift(fft(filtered_sawtooth)); +filtered_sawtooth_magnitude = abs(filtered_sawtooth_fft) / N; + +% Calcul de la réponse en fréquence théorique du filtre +omega = 2 * pi * f / Fs; % Fréquences normalisées +H = 0.5 * (1 + exp(-1j * omega)); % Réponse en fréquence théorique +H_magnitude = abs(H); + +% Application de la réponse théorique aux spectres originaux +theoretical_filtered_square = square_magnitude .* H_magnitude; +theoretical_filtered_sawtooth = sawtooth_magnitude .* H_magnitude; -% Application du filtre au signal dent de scie -sawtooth_filtered = filter([0.5, 0.5], 1, sawtooth_signal); +% Affichage de la réponse en fréquence du filtre +figure; +plot(f, H_magnitude); +title('Réponse en fréquence du filtre passe-bas d''ordre 1'); +xlabel('Fréquence (Hz)'); +ylabel('Gain'); +grid on; +xlim([-100, 100]); -% Affichage des signaux filtrés +% Affichage des résultats du filtrage figure; % Signal carré filtré -subplot(2, 1, 1); -plot(t, square_filtered); -title('Signal carré filtré (passe-bas)'); +subplot(2, 2, 1); +plot(t, square_signal, 'b'); +hold on; +plot(t, filtered_square, 'r'); +title('Signal carré original et filtré'); xlabel('Temps (s)'); ylabel('Amplitude'); -xlim([0 5*T]); % Limiter l'axe des x pour une meilleure visualisation +xlim([0 5*T]); +legend('Original', 'Filtré'); + +% Comparaison des spectres théorique et réel du signal carré filtré +subplot(2, 2, 2); +plot(f, filtered_square_magnitude, 'r'); +hold on; +plot(f, theoretical_filtered_square, 'g--'); +title('Spectres du signal carré filtré'); +xlabel('Fréquence (Hz)'); +ylabel('Amplitude'); +legend('Spectre réel', 'Spectre théorique'); +xlim([-100, 100]); % Zoom sur les basses fréquences % Signal dent de scie filtré -subplot(2, 1, 2); -plot(t, sawtooth_filtered); -title('Signal dent de scie filtré (passe-bas)'); +subplot(2, 2, 3); +plot(t, sawtooth_signal, 'b'); +hold on; +plot(t, filtered_sawtooth, 'r'); +title('Signal dent de scie original et filtré'); xlabel('Temps (s)'); ylabel('Amplitude'); -xlim([0 5*T]); % Limiter l'axe des x pour une meilleure visualisation - -% Calcul du spectre des signaux filtrés -square_filtered_fft = fftshift(fft(square_filtered)); -square_filtered_magnitude = abs(square_filtered_fft) / N; -sawtooth_filtered_fft = fftshift(fft(sawtooth_filtered)); -sawtooth_filtered_magnitude = abs(sawtooth_filtered_fft) / N; - +xlim([0 5*T]); +legend('Original', 'Filtré'); -% Affichage des spectres des signaux filtrés +% Comparaison des spectres théorique et réel du signal dent de scie filtré +subplot(2, 2, 4); +plot(f, filtered_sawtooth_magnitude, 'r'); +hold on; +plot(f, theoretical_filtered_sawtooth, 'g--'); +title('Spectres du signal dent de scie filtré'); +xlabel('Fréquence (Hz)'); +ylabel('Amplitude'); +legend('Spectre réel', 'Spectre théorique'); +xlim([-100, 100]); % Zoom sur les basses fréquences + +% Synthèse sonore pour écoute et comparaison +% Paramètres pour la synthèse audio +duration = 2; % Durée en secondes +audio_Fs = 44100; % Fréquence d'échantillonnage pour l'audio (standard) + +% Paramètres des signaux +freq = 440; % Fréquence fondamentale en Hz (La4) +audio_t = 0:1/audio_Fs:duration-1/audio_Fs; % Vecteur temps pour l'audio + +% Génération des signaux source à fréquence audible +audio_square = A * square(2 * pi * freq * audio_t); +audio_sawtooth = A * sawtooth(2 * pi * freq * audio_t); + +% New filter +d = designfilt('lowpassfir','FilterOrder',2,'HalfPowerFrequency',0.25) +filterAnalyzer(d) + +% Création d'une enveloppe ADSR simple +attack_time = 0.1; % secondes +decay_time = 0.2; % secondes +sustain_level = 0.7; % niveau de sustain (0-1) +release_time = 0.3; % secondes +sustain_time = duration - (attack_time + decay_time + release_time); + +% Nombre d'échantillons pour chaque phase +attack_samples = round(attack_time * audio_Fs); +decay_samples = round(decay_time * audio_Fs); +sustain_samples = round(sustain_time * audio_Fs); +release_samples = round(release_time * audio_Fs); + +% Création des segments de l'enveloppe +attack = linspace(0, 1, attack_samples); +decay = linspace(1, sustain_level, decay_samples); +sustain = ones(1, sustain_samples) * sustain_level; +release = linspace(sustain_level, 0, release_samples); + +% Assemblage de l'enveloppe complète +envelope = [attack, decay, sustain, release]; + +% Application du filtre passe-bas existant et de l'enveloppe +filtered_square = filter(d, audio_square) .* envelope; +filtered_sawtooth = filter(d, audio_sawtooth) .* envelope; + +% Normalisation pour éviter l'écrêtage +audio_square = audio_square / max(abs(audio_square)); +audio_sawtooth = audio_sawtooth / max(abs(audio_sawtooth)); +filtered_square = 0.9 * filtered_square / max(abs(filtered_square)); +filtered_sawtooth = 0.9 * filtered_sawtooth / max(abs(filtered_sawtooth)); + +% Application de l'enveloppe aux signaux audio +audio_square = audio_square .* envelope; +audio_sawtooth = audio_sawtooth .* envelope; + +% Stocker les signaux audio dans des fichiers +audiowrite('filtered_square.wav', filtered_square, audio_Fs); +audiowrite('filtered_sawtooth.wav', filtered_sawtooth, audio_Fs); +audiowrite('original_square.wav', audio_square, audio_Fs); +audiowrite('original_sawtooth.wav', audio_sawtooth, audio_Fs); + +% Affichage des FFT des signaux audio sur le même graphique figure; - - -% Spectre du signal carré filtré -subplot(2, 2, 1); -plot(f, square_filtered_magnitude); -title('Spectre du signal carré filtré'); +subplot(2, 1, 1); +plot(f, abs(fftshift(fft(audio_square)))/N); +hold on; +plot(f, abs(fftshift(fft(filtered_square)))/N); +title('FFT du signal carré et du signal carré filtré'); xlabel('Fréquence (Hz)'); ylabel('Amplitude'); -xlim([-Fs/2 Fs/2]); % Limiter l'axe des x pour une meilleure visualisation - - -% Spectre du signal dent de scie filtré -subplot(2, 2, 2); -plot(f, sawtooth_filtered_magnitude); -title('Spectre du signal dent de scie filtré'); +legend('Signal carré', 'Signal carré filtré'); +xlim([-100, 100]); % Zoom sur les basses fréquences +subplot(2, 1, 2); +plot(f, abs(fftshift(fft(audio_sawtooth)))/N); +hold on; +plot(f, abs(fftshift(fft(filtered_sawtooth)))/N); +title('FFT du signal dent de scie et du signal dent de scie filtré'); xlabel('Fréquence (Hz)'); ylabel('Amplitude'); -xlim([-Fs/2 Fs/2]); % Limiter l'axe des x pour une meilleure visualisation +legend('Signal dent de scie', 'Signal dent de scie filtré'); +xlim([-100, 100]); % Zoom sur les basses fréquences