Convolution

Soient x,yCZx,y \in \mathbb C^\mathbb Z deux vecteurs à support fini. Leur convolution est définie par
(1)(xy)(n)=k=x(k)y(nk)(1)\quad\quad (x*y)(n)=\sum_{k=-\infty}^\infty x(k)y(n-k)
C’est une opération bilinéaire, commutative et associative.
Par exemple, si on note en=(,0,1,0,)e_n=(\ldots,0,1,0,\ldots) où le seul “1” se trouve sur la position d’indice nn, on a
epeq=ep+q et epe0=ep.e_p*e_q=e_{p+q} \quad\text{ et }\quad e_p*e_0=e_p.
Si x=k=xkekx=\sum_{k=-\infty}^\infty x_k e_k est à support fini, on a par linéarité
xeq=k=xkek+p=k=xkpek et xe0=x. x*e_q=\sum_{k=-\infty}^\infty x_k e_{k+p}=\sum_{k=-\infty}^\infty x_{k-p}e_k \quad\text{ et }\quad x*e_0=x.
Donc la convolution par epe_p corresponde à la translation de xx à droite pp unités. Et e0e_0 est l’élément neutre pour la convolution.

Il existe aussi une fonction conv dans SciLab.
Si X et Y sont des vecteurs dans SciLab le résultat de conv(A,B) sera

(2) ans(n)=k=0n\sum_{k=0}^nX(k+1)*Y(n-k)

pour tout 1n1\leq n\leq length(X)+length(Y)-1.
Dans la formule ci-dessus, il y potentiellement des valeurs de X et Y non définies, elles sont considérer égales à 0.

La différence entre (1) et (2) s’explique par les faits suivants :

Exercice 1 Écrire une fonction mon_conv qui fera la même chose que la fonction conv, c’est à dire elle implémente la formule (2).
Essayez aussi lancer conv([1,2,3],[1,0,0,0]) et conv([1,2,3],[1,0]), etc. Le même avec my_conv.

Application

On va utiliser la convolution pour modéliser un simple écho.
Si un son est représenté par vecteur xCZx\in \mathbb C^\mathbb Z, son écho est le même son un peu plus tard et peut être affaibli, i.e. λxer\lambda x*e_r avec r=Nr=\mathbb N qui corresponde au retard et λ]0,1[\lambda \in ]0,1[ qui est le facteur d’affaiblissement du son. Voici exemple complet en SciLab

[X,frequence] = wavread('coyote_howl.wav');
clf();
subplot(3,1,1);
plot(1:length(X),X);
r=1*frequence;
lambda=1;
Y=[1,zeros(1,r),lambda]
subplot(3,1,2);
plot(1:length(Y),Y);
echo=conv(X,Y);
subplot(3,1,3);
plot(1:length(echo),echo);
sound(echo,frequence);

Voici les sons à essayer :
coyote_howl.wav
t2_hasta_la_vista.wav

On peut aussi expérimenter faire la convolution d’un son réel avec une sinusoïde de fréquences différentes en remplaçant la ligne correspondante par

Y=[sin(0.005*(1:length(X)))];

Ou encore on peut essayer :

Y=[zeros(1,5000)];
Y(1:500:5000)=1;

Ce qu’est peut être plus intéressant et plus pratique est qu’on puisse simuler numériquement la réverbération d’un espace physique ou virtuel. Ceci s’appelle réverbération à convolution et est achevé par convolution d’un signal (son réel, musique, etc.) par une réponse impulsionnelle de l’espace qu’on veut simuler (le plus souvent c’est un enregistrement de ce qu’on écoute réellement dans ce espace lorsque on émet un e0e_0).
Essayez:

[X,frequence] = wavread('coyote_howl.wav');
//t2_hasta_la_vista.wav
clf();
subplot(3,1,1);
plot2d(X);
[Y,frequence2] = wavread('BIG-HALL.wav');
subplot(3,1,2);
Y=Y(1,1:4:length(Y(1,:)));//Y est en stereo et a une autre frequence
plot2d(Y(1,:));
echo=conv(X,Y);
subplot(3,1,3);
plot(echo);
sound(echo,frequence);

Voici les fichiers de réponses impulsionnelles :
BIG-HALL.wav
DAMPED-CAVE.wav
MINI-CAVES.wav
PIPE-CARPET.wav
SMALL-CHURCH.wav
WIDE-HALL.wav

Une autre utilisation de convolution est pour débruitage du signal.
Essayez :

[X,frequence] = wavread('coyote_howl.wav');
//t2_hasta_la_vista.wav
clf();
subplot(3,1,1);
plot2d(X);
Xbruite = X+0.05*rand(1,length(X));
subplot(3,1,2);
plot2d(Xbruite);
sound(Xbruite,frequence);
n=10;
Y=ones(1,n)/n;
Xdebruite=conv(Xbruite,Y);
//echo(2,:)=conv(X,Y(2,:));
subplot(3,1,3);
plot(Xdebruite);
sound(Xdebruite,frequence);

Written with StackEdit.