Prédisez la sonorité d'une église

Dans le chapitre précédent, vous avez vu qu'il suffisait de connaître la réponse impulsionnelle pour prédire la sortie d'un système linéaire.

Un exemple qui s'y prête bien est la réponse acoustique.

Voici la situation :

  • Je vais vous donner la réponse impulsionnelle sonore d'une église. 
  • Je vais vous donner un son studio de vache qui meugle.
  • Vous allez prédire ce que nous pourrions entendre si cette même vache meuglait dans cette église (avouez que c'est utile comme étude).

Acquisition/visualisation des données

Son de vache

Vous trouverez ici deux fichiers,

et  qui sont les données nécessaires pour cette étude.

% acquisition des données
[vache, F] = audioread('cow.wav');


Comme d'habitude, le son étant stéréophonique, vache contient en fait deux colonnes.

Vous n'allez travailler que sur la voix gauche :

vacheG = vache(:,1); % selection d'une seule voix


N'hésitez pas à écouter ce son, il est magnifique.

Réponse impulsionnelle

Ici, la réponse impulsionnelle qui vous est donnée est celle d'une église.

[clap, F2] = audioread('clap.wav');


Vous pouvez vérifier que les deux fréquences F et F2 sont identiques, ce qui signifie que l'enregistrement de la vache et de la réponse impulsionnelle s'est fait avec la même fréquence d'échantillonnage.

Si vous l'écoutez, vous remarquerez la chose suivante. La réponse impulsionnelle acoustique de cette église correspond à ce qui serait enregistré par un microphone et qu'un bruit d'intensité très forte et très courte a été produit dans cette église. Voilà une façon auditive de se représenter un Dirac.

Vous remarquerez ainsi que le "clap" semble durer (cela est dû aux nombreuses réflexions des sons sur les parois de l'église).

Convolution

Vous aimeriez bien utiliser la convolution pour prédire comment la vache va "sonner" dans cette église, mais pour cela, il faut que l'église constitue bien un système linéaire et invariant.

Est-ce le cas ?

  • Invariant : tant que les murs, les meubles, et que la température, humidité, etc., ne changent ou ne bougent pas, il n'y a pas de raison que l'église change sa façon de résonner...
  • Linéaire : voilà qui est plus délicat. Ici les signaux qui nous intéressent sont des signaux sonores, qui correspondent à des amplitudes de vibration des couches d'air. Il se trouve que ce phénomène ondulatoire est linéaire (tant que l'amplitude de vibration n'est pas trop grande). C'est-à-dire que deux ondes sonores s'ajoutent et peuvent interférer d'ailleurs. Nous allons admettre que nous sommes bien dans le régime linéaire de l'église.

Nous pouvons donc utiliser la convolution pour prédire le résultat sonore :

prediction = conv(vacheG,clapG); % attention, vu la taille des signaux, il se peut que cette étape soit longue sur des ordinateurs peu performants


Voilà, vous pouvez essayer d'écouter le résultat (attention à vos oreilles) :

sound(prediction,F); % baissez le son !


C'est horrible ! le son sature énormément.

Comment cela se fait-il ? Comme le signal clap n'était pas de somme totale égale à 1, le résultat de la convolution est d'amplitude beaucoup plus grande que le signal de départ.

Normalisation du niveau sonore

Pour avoir un résultat écoutable, il faut normaliser le signal obtenu. Mais comment le normaliser ?

Il y a beaucoup de choix possibles, nous pourrions vouloir que la puissance de sortie soit la même que la puissance d'entrée. Vouloir que l'énergie de sortie soit la même que l'énergie d'entrée. Ou bien encore, nous pourrions tout simplement souhaiter que jamais l'amplitude de sortie ne dépasse 1 (pour qu'il n'y ait jamais saturation).

Ici, je pense qu'un bon critère serait que le nouveau signal ait le même "niveau sonore" que le signal d'origine.

Et là se pose une question très intéressante : que signifie "niveau sonore" ? Là encore il va falloir faire un choix. Le choix que je vais faire est de dire que niveau sonore signifie : valeur efficace du signal pendant les trois première secondes (pour prendre des durées équivalentes).

%calcul des valeurs efficaces
debutOri = vacheG(1:F*3); %en trois secondes, il y a F*3 points
P_ori = sqrt(sum(debutOri .* debutOri) / length(debutOri))

% Même chose pour la prédiction
debutPred = prediction(1:F*3);
P_pred = sqrt(sum(debutPred .* debutPred) / length(debutPred))


Ces quelques lignes de scripts nous permettent d'établir qu'effectivement le son prédit est de très forte valeur efficace :

P_ori = 0.14354
P_pred = 3.2641


Plus exactement, la prédiction est 23 fois trop forte. Nous allons donc normaliser le son avec ce critère :

prediction = prediction * P_ori/P_pred; % normalisation


Maintenant, vous devriez pouvoir écouter sereinement le résultat de votre prédiction.

sound(prediction,F); % vous n'avez plus besoin de baisser le son !

Voilà, vous venez de prédire ce que nous pourrions entendre si une vache rentrait dans une église.