next up previous contents
suivant: Cryptographie monter: SOUTENANCE FINALE MARVIN (Modest-encoding précédent: Structures d'apprentissage & Réseaux   Table des matières

Sous-sections

Traitement du signal
Création de l'empreinte vocale

Introduction

Dans le projet MARVIN, une des composantes principale mais aussi une des grande difficulté est la création de l'empreinte vocale. En effet, nous devons concevoir celle-ci afin qu'elle soit trés caractéristique d'un individu (deux individus différents auront une empreinte distincte) tout en restant à peu près la même pour le même locuteur.
Cette partie présentera les différents développements et recherches qui ont été effectués autour de cet objectif. Le principe général est assez simple : après avoir recupéré le signal vocal et s'être placé sur une voyelle, nous transformons le signal en représentation fréquentielle de façon à récupérer une empreinte bien spécifique à l'utilisateur. Pour cela, nous utilisons la MFCC (Mel Frequency Cepstral Coefficients) qui elle même est l'application, comme nous le verrons par la suite de la FFT (Fast Fourier Transform) et de la DCT (Discret Cosinus Transform).

Création de l'empreinte

Fonctionnement général

Schéma

\includegraphics[]{paol.ps}


Schéma général de fonctionnement


Différentes phases

\includegraphics[]{wav.ps}


Signal échantillonné


\includegraphics[]{energie.ps}


Energie du signal


\includegraphics[]{wavenergie.ps}


Echantillonage du signal au point de plus haute énergie


\includegraphics[]{mfcc3d.ps}


MFCC sur cette partie du signal (plan 3D)


\includegraphics[]{mfcc2d.ps}


MFCC sur cette partie du signal (plan 2D)


\includegraphics[]{empex.ps}


Empreinte vocale (moyenne)


La MFCC

Introduction

La MFCC est la dernière amélioration que nous avons effectué dans le fonctionnement de MARVIN. La méthode précedente, une application directe de la FFT sur une certaine partie du signal, ne nous donnait pas de résultats assez bon et le taux d'erreur en reconnaissance était trop important, ceci rendant son utilisation caduque.
La MFCC (Mel Frequency Cepstral Coefficients) est une extraction de caractéristique du signal développée autour de la FFT et de la DCT, ceci sur une échelle de Mel. Nous avons découvert ce principe (qui finalement paraît être le plus utilisé en identification du locuteur) grâce à un article d'un laboratoire de recherche de Jussieu : le LISIF.

Fonctionnement théorique

La MFCC se décompose en phases :

Implémentation

L'implémentation de la MFCC nous posa de nombreux problèmes. En effet, la théorie trouvée sur internet ne nous permettait pas de pousser très loin nos recherches (en particulier le banc de filtres). Cependant les tâtonnements et les résultats de Matlab nous ont permis d'arriver peu à peu à une solution satisfaisante.

\includegraphics[height=12cm]{mfccmarvin.ps}


MFCC sur le mot 'marvin'


Exemples d'empreinte

\includegraphics[]{empex.ps}


Empreinte vocale (sujet 1)


\includegraphics[]{emp2.ps}


Empreinte vocale 2 (sujet 1)


\includegraphics[]{emp3.ps}


Empreinte vocale 3 (sujet 1)


\includegraphics[]{p3.ps}


Empreinte vocale 3 (sujet 2)


Recherches et outils développés

Introduction

Notre projet n'a pas toujours eu le même principe. Avant de commencer MARVIN, nous n'avions aucune connaissances en traitement du signal. Nous sommes donc passé par énormement d'étapes et de tâtonnements.

Nous nous sommes donc intéressé a plusieurs traitements :

Toutes ces opérations ont été recodées (à part le LPC), mais pas toutes utilisées (Spectrogramme, Spline, LPC). Nous allons dans la suite de cette partie présenter le cheminement de nos recherches.

L'acquisition

Introduction

L'acquisition est vraiment une partie dont l'intérêt mathématique est nul et ce n'est que du code pur, donc rien d'intérressant. Mais en voici tout de même le fonctionnement.

Fonctionnement

Dans cette partie, nous devions faire une procédure qui nous permettait de récupérer par le microphone un tableau Amplitude / Secondes : A(dB) / t(s).
La carte son renvoie dans son fichier "device" associé (/dev/audio ou /dev/dsp), des octets correspondant aux dB rentrés dans le microphone.
Le procédé est simple : Comment récupérer les octets ressortant de la carte son ? Nous avions tout d'abord pensé utiliser une librairie de son mais aucune ne nous paraissait utilisable soit par le manque de la fonction d'enregistrement du son soit par la lourdeur imposée. Ensuite, en collaboration avec un autre groupe, nous avions trouvé un programme C qui faisait l'enregistrement sans lib extraordinaire. Nous voulions en extraire ses fonctions d'enregistrement. Puis à force de chercher des informations sur les devices, nous avons vite compris que beaucoup de fonctions existaient déjà. Ainsi open (de /dev/dsp) nous permet de faire une copie bit à bit de ce qui ressort du device. Tout cela marche grace à la fonction IOCTL.
Au final, on ressort un son de fréquence 11025Hz.

La FFT

Introduction

La transformée de Fourier s'applique aussi bien sur les signaux continus (périodiques ou pas) que sur les signaux discrets. C'est ce dernier cas qui nous intérresse dans la mesure où lors de l'acquisition, les données que l'on enregistre sont des ensembles de valeurs à des instants périodiques dans le temps. Ce sont des valeurs représentant des signaux échantillonnés (quelconques). Nous allons donc utiliser la transformée de Fourier appliquée à ces types de signaux.

Recherches sur l'analyse du signal

Signal périodique de période T

Soit un signal périodique $x(t)$
On suppose que le signal est périodique de période T (qui est supérieure à l'interval sur lequel on l'a coupé) et que l'on a la fonction qui permet d'obtenir cette représentation, on l'appelle $xT(t)$. Le développement en séries de Fourrier d'une fonction périodique est l'approximation de cette fonction par une série d'autres fonctions sinusoidales. Par exemple si on a deux fonctions continues $x_1(t)$ et $x_2(t)$ sur un intervalle [t1 ; t2] et on cherche à approximer $x_1(t)$ par $x_2(t)$. Il s'agit de trouver un scalaire $c$ tel que :

\begin{displaymath}x_1(t) \approx c * x_2(t)\end{displaymath}

Pour la minimisation de l'erreur quadratique, on a :

\begin{displaymath}\epsilon = \frac{1}{t2-t1} * \int_{t1}^{t2} (x_1(t) - c * x_2(t))^2 dt\end{displaymath}

On constate que $c$ est minimum pour $\frac{d(\epsilon)}{dt} = 0$ c'est à dire

\begin{displaymath}c = \frac{\int_{t1}^{t2} x_1(t) * x_2(t) dt}{\int_{t1}^{t2} (x_2(t))^2 dt}\end{displaymath}

Exemple, on a un signal rectangulaire de période $2\pi$ et d'amplitude 1. On a : $x_2(t)= \sin t$ d'où $c = \frac{4}{\pi}$. On utilise le même procédé si on veut approximer une fonction continue $x(t)$ par une famille de fonctions continues ${x_i(t)}$ et qui possède la propriété:

\begin{displaymath}\forall \ i,\ j \ i\neq j \int_{t1}^{t2} x_i(t) * x_j(t) dt = 0\end{displaymath}

on a :

\begin{displaymath}\epsilon = \frac{1}{t2-t1} * \int_{t1}^{t2} (x(t)- \sum_{i=1}^{n} c_i * x_i(t))^2 dt\end{displaymath}

ainsi

\begin{displaymath}c_i = \frac{\int_{t1}^{t2} x(t) * x_i(t) dt}{\int_{t1}^{t2} x_i(t)^2) dt}\end{displaymath}

Par exemple, si on reprend l'exemple précédent, $x_i(t) = \sin(i*t)$ , d'où $c_i = \frac{4}{\pi}*i$ si i impair ou $c_i = 0$ si i pair.

pour $n=4$

\begin{displaymath}x(t) \approx \frac{4}{\pi} * (\sin t + \frac{1}{3} * \sin(3t) + \frac{1}{5} * \sin(5t) + \frac{1}{7} * \sin(7t))\end{displaymath}

Cette première approche vous donne une idée globale de l'utilité des coefficients $c$ pour l'approximation d'une fonction. Revenons au signal périodique $xT(t)$ de période T. Une onde (représentation d'une période de xT) peut être décomposée en une superposition d'ondes sinusoïdales. Celles-ci sont liées de façon harmonique c'est à dire que leur fréquence sont des harmoniques (des multiples) d'une fondamentale (fréquence minimale ).



En appliquant la série de Fourrier sur $xT(t)$, on obtient :

\begin{displaymath}xT(t) = x_o + x_1(t) + x_2(t) + x_3(t) + ... + x_n(t)\end{displaymath}

avec $x_o$ composante continue qui représente la moyenne de $xT(t)$. $x_1$ harmonique 1, $x_2$ harmonique 2, $x_3$ harmonique 3,..., $x_n$ harmonique n


On a alors :

\begin{displaymath}x_1(t)= M_1* \sin(wt+\phi_1), x_2(t)= M_2*\sin(wt+\phi_2), x_3(t)= M_3*\sin(wt+\phi_3), ..., x_n(t)= M_n*\sin(wt+\phi_n)\end{displaymath}

On admet qu'une onde périodique est une superposition d'ondes sinusoïdales harmoniquement liées. Par la méthode de Fourrier, on peut passer de l'analyse temporelle d'un signal à son analyse fréquentielle. Posons D la valeur de crête à crête d'une onde périodique : $M_n= \frac{D}{n\pi}$.
Le spectre du signal $xT(t)$ va nous donner un graphique où sera représenté en abcisses la fréquence (correspondant à la fréquence des différentes harmoniques de xT) et en ordonnées la valeur de crête associée (pour chaque harmonique). Normalement, le spectre d'un signal varie d'un signal périodique à un autre. Dans le cadre de la décomposition du signal sonore, on va pouvoir se servir des valeurs de crêtes des différentes harmoniques pour distinguer chaque enregistrement.


Revenons à un cas plus général : supposons que l'ensemble des fonctions $x_i(t)$ soient constituées


avec $i = 0, 1, 2, ...$ on en déduit :

\begin{displaymath}\int_{t1}^{t2} (x_i(t))^2 dt = \frac{T}{2}\end{displaymath}

pour $i \neq 0$ et

\begin{displaymath}xT(t) = a_o + \sum_{n=1}^{+\infty} a_n * \cos \left(\frac{n*2\pi}{T} *t \right) + b_n * \sin \left(\frac{n*2\pi}{T}*t\right)\end{displaymath}

avec


$a_n = \frac{2}{T} * \int_{\frac{-T}{2}}^{\frac{T}{2}} xT(t)* \cos \left(\frac{n*2\pi}{T}*t\right) dt$

$b_n = \frac{2}{T} * \int_{\frac{-T}{2}}^{\frac{T}{2}} xT(t)* \sin \left(\frac{n*2\pi}{T}*t\right) dt$

$a_o = \frac{1}{T} * \int_{\frac{-T}{2}}^{\frac{T}{2}} xT(t) dt$

$b_o = 0$


On obtient une décomposition de xT(t) en séries de Fourier

\begin{displaymath}xT(t)= \sum_{n=-\infty}^{+\infty} c_n * e^{\frac{j*n*2\pi}{T}*t}\end{displaymath}

avec


$c_n = \frac{a_n-j.b_n}{2}$ pour n > 0

$c_n = \frac{a_n+j.b_n}{2}$ pour n < 0

$c_o = a_o$


d'où

\begin{displaymath}c_n = \frac{1}{T} * \int_{\frac{-T}{2}}^{\frac{T}{2}} xT(t) *e^{\frac{-j*n*2\pi}{T}*t}.dt\end{displaymath}

$c_n$ est appelée coefficient de Fourrier.
La suite des coefficients complexes $c_n$ constitue le spectre (de raies) du signal périodique xT(t). Par analogie avec le cas particulier de l'onde, $c_n$ représente la valeur de crête de l'harmonique n de l'onde.

Signal non périodique

On suppose à présent qu'on a un signal $x(t)$ non périodique (dont on connaît l'équation) qui est pris sur un temps T. $x(t)$ étant non périodique, on peut le considérer comme une fonction périodique de période T avec T qui tend vers l'infini. Posons $f = \frac{n}{T}$ ; f est comparable à une fréquence et correspond par analogie au premier cas à la fréquence de l'harmonique n. Le spectre de $x(t)$ serait continu si celui-ci n'était pas identiquement nul. Appelons $X(f)$ la transformée de Fourrier de $x(t)$ (spectre de $x(t)$).

\begin{displaymath}X(f) = \lim_{+\infty} T*c_n\end{displaymath}


\begin{displaymath}X(f) = \int_{-\infty}^{\infty} x(t)*e^{-j*2\pi *f*t} dt\end{displaymath}

les conditions pour qu'on puisse appliquer la transformée de Fourrier sur une fonction $x(t)$ non périodique sont : Signal discret On suppose que le signal $x(t)$ que l'on doit étudier n'est pas connu, c'est-à-dire qu'il n'existe pas de fonction qui permette de représenter $x(t)$ en fonction du temps,(c'est un signal discontinu). Cette hypothèse semble la plus probable étant donné que chaque enregistrement de voie semble unique. C'est sous cette forme que se presentera le signal par la suite. Le signal $x(t)$ est donc constitué d'un ensemble de signaux $x(tn)$ qui sont définis que pour des instants appartenant à un ensemble dénombrable. t= {t1,t2,...,tn} et on note $x(tn)=x_n$. {$x_n$} est appelé signal discret.


Supposons qu'il y ait une relation entre les éléments de la suite {$x_n$};


La transformation de Fourier du signal {$x_n$} est :

\begin{displaymath}X(f) = \sum_{n=-\infty}^{+\infty} (x_n * e^{-j * 2\pi * f * n})\end{displaymath}

X(f) est un signal périodique de periode 1. Cette transformation n'existe que si les signaux sont absolument sommables :

\begin{displaymath}\sum_{n=-\infty}^{+\infty} \vert x_n\vert < +\infty\end{displaymath}

on obtient alors : |X(f)| le spectre fréquentiel d'amplitude de {$x_n$} et qui est une fonction paire.

\begin{displaymath}Re ( X(f) ) = \sum_{n=-\infty}^{+\infty} x_n * \cos(2*\pi *f*n)\end{displaymath}

$\underline X(f)$ le spectre fréquentiel de phase de {$x_n$} et qui est une fonction impaire

\begin{displaymath}Im ( X(f) ) = -\sum_{n=-\infty}^{+\infty} x_n*\sin(2*\pi *f*n)\end{displaymath}

$\vert X(f)\vert^2$ le spectre d'énergie de {$x_n$}.


Maintenant, il existe le problème du calcul de f et le cas où le nombre de $x_n$ est infini. Pour le résoudre: on pose $Af = \frac{1}{N}$ avec N points entre 0 et 1. $f = \frac{h}{N}$ h= 0,1,2,3,...,N

\begin{displaymath}X(f) = \sum_{n=-\infty}^{+\infty} x_n*e^{-j2\pi *f*n}\end{displaymath}


\begin{displaymath}X \left( \frac{h}{N} \right) = \sum_{n=-\infty}^{+\infty} x_n * e^{-j*2\pi *\frac{h}{N}*n}\end{displaymath}

or $X_h=X(\frac{h}{N})$

\begin{displaymath}X_h = \sum_{n=-\infty}^{+\infty} x_n * e^{-j*2\pi * \frac{h}{N}*n}\end{displaymath}

posons a nouveau $W_n= e^{(-j*2* \pi * \frac{h}{N})}$ on a :

\begin{displaymath}X_h = \sum_{n=0}^{N-1} (x_n * W_n^{n*k}) \ \ \ \ h = 0, 1, 2, 3, ..., N-1\end{displaymath}

si $(x_n)$ s'annule à partir de n = N


$X_h$ est appelée transformée de Fourrier discrète (TFD), d'ordre N. on peut représenter la TFD sous forme matricielle en mettant :



on a donc : $\underline X = W * \underline x$
ceci constitue les premieres recherches qui nous ont permis de coder la transformee de Fourierpar la suite en utilisant la TFD basee sur l'algorithme de Cooley et Turkey.

Transformée de Fourier Discrète (TFD)

La TFD permet de passer de la représentation temporelle d'un signal à sa représentation fréquentielle. Elle est définie de la manière suivante:

\begin{displaymath}X(s) = \sum_{n=0}^{N-1} (x(n)*e^{-j * 2\pi * n * s /N})\end{displaymath}

avec :
$N$ le nombre total d'échantillons.
$x(n)$ l'amplitude de l'échantillon à la position $n$.
On fait varier $s$ de 1 jusqu'au nombre total de valeurs que l'on désire.
Supposons maintenant que l'on dispose d'un enregistrement de N échantillons et que l'on cherche à appliquer la TFD sur ce signal. En se servant d'un algorithme qui appliquerait la formule, le calcul de chaque valeur de $X(s)$ nécessiterait $N$ additions et $N$ multiplications complexes. Si on veut $N$ valeurs de $X(s)$, l'algorithme nécessiterait donc $N^2$ additions et $N^2$ multiplications complexes. Étant donné que le nombre d'échantillons que l'on a pour chaque enregistrement est très élevé (de même pour le nombre de valeurs désirées), l'application de cet algorithme nous prendrait beaucoup de temps et ralentirait le programme. Ce qui nous a conduit à appliquer la Transformée de Fourier Rapide (qui est moins coûteux en temps). En effet, nous avons tenté de coder Fourier sans la FFT (une Fourier lente en somme) mais la recherche exhaustive et les opérations demandent réellement trop de temps à la machine.

La Transformée de Fourier Rapide (FFT)

La FFT s'applique sur un signal dont le nombre d'échantillons est une puissance de 2. L'algorithme de la FFT a été mise au point en 1965 par Cooley et Tuckey. La FFT est une version rapide de la TFD.

Algorithme de la FFT

Racines complexes de l'unité: On définit une n ième racine complexe de l'unité un nombre complexe $w$ tel que :

\begin{displaymath}w^n = 1 \end{displaymath}

Il y a $n$ racines n ième complexe de l'unité. Elles valent :

\begin{displaymath}e^{2\pi * i * k /n} \end{displaymath}

pour k = 0, 1, ..., n-1
En utilisant la définition de l'exponentielle

\begin{displaymath}e^{i.x} = cos(x) + i.sin(x) \end{displaymath}

On constate que les n racines complexes de l'unité sont espacées de façon régulière autour d'un cercle de rayon unitaire centré à l'origine du plan complexe. La valeur

\begin{displaymath}w_n= e^{2\pi * i/n} \end{displaymath}

est appelée la racine n ième principale de l'unité. On voit que :

\begin{displaymath}w_n^n = w_n^0
= 1\end{displaymath}

ce qui entraîne :

\begin{eqnarray*}
w_n^j * w_n^k &= & w_n^{j+k} \\
&= & w_n^{(j+k) \ mod \ n} \\
\end{eqnarray*}



De même,

\begin{displaymath}w_n^{-1} = w_n^{n-1} \end{displaymath}

Remarque :
* Lemme de l'annulation : $\forall \ n >= 0, \forall \ k >= 0$, et $d > 0$,

\begin{displaymath}w_{d*n}^{d * k} = w_n^k \end{displaymath}

* pour $\forall \ n > 0$, avec $n$ pair :

\begin{displaymath}w_n^{n/2} = w_2 = -1 \end{displaymath}

* Lemme de la bipartition :


Si $n > 0$ est pair, les carrés des n racines nièmes de l'unité sont les $n/2$ racines $(n/2)$ iemes de l'unité.
Démonstration D'après le lemme de l'annulation, on a :

\begin{displaymath}(w_n^k)^2 = w_{n/2}^k \end{displaymath}

pour tout entier positif k.
On remarque que l'on élève au carré toutes les racines $n$ ièmes de l'unité, chaque racine $(n/2)$ ième de l'unité est obtenue exactement deux fois, puisque

\begin{eqnarray*}
(w_n^{k+n/2})^2 &= & w_n^{2k+n} \\
&= & w_n^{2k} * w_n^n \\
&= & w_n^{2k} \\
&= & (w_n^k)^2 \\
\end{eqnarray*}



donc $w_n^k$ et $w_n^{k+n/2}$ ont le même carré.
Ce lemme est important pour l'approche "diviser pour régner" dont nous nous servirons dans le calcul récursif de la FFT. * Lemme de la sommation :
$\forall$ entier $n \geq 1$, et $\forall$ entier positif $k$ non divisible par $n$,

\begin{displaymath}\sum_{j=0}^{n-1} ( (w_n^k)^j) = 0 \end{displaymath}

Principe de la Transformée de Fourier Rapide :
La FFT tire parti des propriétés particulières des racines complexes de l'unité, elle permet de calculer la TFD en $n * \ log \ n$ opérations. Elle fait appel à une stratégie "diviser pour régner", en utilisant séparément les coefficients d'indice pairs et impairs de A(j) qui représente une série de n échantillons; pour définir les deux nouvelles séries A[0] et A[1] de longueur n/2 :
A[0] = { a(0) ; a(2) ; a(4) ; a(6) ; ... ; a(n-2) }
A[1] = { a(1) ; a(3) ; a(5) ; a(7) ; ... ; a(n-1) }
On constate que A[0] contient tous les coefficients d'indice pair de A (la représentation binaire de l'indice se termine par 0), et que A[1] contient tous les coefficients d'indice impair (la représentation binaire de l'indice se termine par 1). On a : $A(j) = A[0] + A[1]$
Problème qui consiste à évaluer A(j) en $w_n^0$, $w_n^1$, $w_n^2$, ..., $w_n^{n-1}$ se ramène a évaluer les deux séries A[0] et A[1] de longueur $n/2$ aux points $(w_n^0)^2$, $(w_n^1)^2$, $(w_n^2)^2$, ..., $(w_n^{n-1})^2$
D'après les remarques faites ci-dessus, cette liste de valeurs est composée seulement de $n/2$ racines $n/2$ ièmes de l'unité, chaque racine apparaissant exactement 2 fois. Ainsi les séries A[0] et A[1] de longueur $n/2$ sont utilisées récursivement pour les $n/2$ racines $n/2$ ièmes de l'unité. Ces sous problèmes ont exactement la même forme que le problème initial, mais sont moins grands de moitié.
Nous avons réduit un calcul de la TFD à $n$ éléments en 2 calcul de TFD à $n/2$ éléments. Cette décomposition est a l'origine du principe algorithmique décrit ci-dessous :


FFT Recc(A) /* A est un tableau qui représente les échantillons d'une acquisition vocale */
1 $n$ $\leftarrow$ longueur(A) /* n est une puissance de 2 */
2 si $n$ = 1
3 alors retourne A
4 $w_n$ $\leftarrow$ $e^{2\pi * i/n}$
5 $w$ $\leftarrow$ 1
6 A[0] $\leftarrow$ { a(0) ; a(2) ; a(4) ; ... ; a(n-2) } /* tableau des valeurs d'indice pair de A */
7 A[1] $\leftarrow$ { a(1) ; a(3) ; a(5) ; ... ; a(n-1) } /* tableau des valeurs d'indice impair de A */
8 y[0] $\leftarrow$ FFT Recc(A[0])
9 y[1] $\leftarrow$ FFT Recc(A[1])
10 pour $k$ $\leftarrow$ 0 à $n/2$ - 1 faire
11 $y_k$ $\leftarrow$ $y_k[0] + w * y_k[1]$
12 $y_{k+(n/2)}$ $\leftarrow$ $y_k[0] - w * y_k[1]$
13 $w$ $\leftarrow$ $w * w_n$
14 retourne $y$
Fonctionnement de la fonction FFT Recc :
La TFD d'un élément est l'élément lui même, car dans ce cas :

\begin{eqnarray*}
y_0 &= & a(0) * w_1^0\\
&= & a(0) * 1\\
&= & a(0)\\
\end{eqnarray*}



Les lignes 6 et 7 définissent les séries A[0] et A[1]. Les lignes 4, 5, et 13 garantissent que $w$ est bien mis a jour de sorte qu'a chaque exécution des lignes 11 et 12, $w = w_n^k$. Les lignes 8 et 9 calculent récursivement les TFD en $n/2$, en effectuant pour k = 0, 1, ..., n/2-1, les affectations :

\begin{displaymath}y_k[0] = A[0] * (w_{n/2}^k)\end{displaymath}


\begin{displaymath}y_k[1] = A[1] * (w_{n/2}^k),\end{displaymath}

ou, puisque $w_{n/2}^k = w_n^{2k}$

\begin{displaymath}y_k[0] = A[0] * (w_n^{2k})\end{displaymath}


\begin{displaymath}y_k[1] = A[1] * (w_n^{2k})\end{displaymath}

Les lignes 11 et 12 combinent les résultats des calculs récursifs de TFD en $n/2$ pour $y_0$, $y_1$, ..., $y_{n/2-1}$, la ligne 11 génère :

\begin{displaymath}y_k = y_k[0] + w_n^k * y_k[1]
= A(w_n^k)\end{displaymath}

La ligne 12 donne :

\begin{displaymath}y_{k+(n/2)} = y_k[0] - w_n^k * y_k[1]
= A[0](w_n^{2k+n}) + w_n^{k+(n/2)} * A[1](w_n^{2k+n})
= A(w_n^{k+(n/2)})\end{displaymath}

D'où la série $y$ retourne par FFT Recc est la transformée discrète de la série $A$. C'est ce principe que nous avons utilise pour appliquer la transformée de Fourier sur un ensemble de valeurs donnés par un enregistrement.

Implémentation

Après avoir étudié pas mal de codes ...nous nous sommes lancé nous même dans notre propre implémentation (une dérive de ButterFly). Nous nous somme basé sur un tableau de complexes dont le type est DOUBLE. La fonction en elle même prend en paramètre le tableau de complexe en entrée et le tableau de sortie ainsi que la taille de la fenêtre le nombre de bits utilisé pour la FFT (le coefficient de la puissance de 2) est calculé en travaillant directement sur la mémoire (ou se trouve le 1 des octets du nombre ) le oméga, l'angle initialisé est normalement à $2\pi$ mais dans notre cas, on prendra $-2\pi$ pour avoir les même résultats que Matlab. Ensuite, après les initialisations, on vérifie que le nombre d'échantillons sur lesquels on travaille est bien une puissance de 2. Après, on copie les données sur le tableau de sortie et on fait l'inversion des bits en même temps, cela en travaillant toujours sur les octets. Ensuite on parcourt le tableau toute les puissances de deux ( échantillons 2, 4, 8 ...) et à chaque fois, on parcours la suite du tableau. On prends un petit delta de l'angle (oméga par rapport ou l'on est) et on applique les équations de Fourier. On modifie le tableau en conséquence à chaque fois. Ensuite on normalise. Voilà. On a fait les quelques optimisations découvertes dans les autres codes. Spécialement le fait de travailler bit à bit et non sur les doubles directement.

Le cepstre

Introduction

Le cepstre est utilisé pour l'analyse spectrale homomorphique, et il permet aussi d'extraire la fréquence fondamentale d'un signal de la parole et de déterminer la fréquence des formants. On distingue le cepstre complexe et le cepstre réel (qui est celui dont nous nous sommes servis).

Le cepstre complexe

En général, particulièrement dans le signal de parole, le signal reçu $f$ résulte de la convolution (produit) d'une excitation $h1$ (le signal de la source) et d'une réponse impulsionnelle $h2$ (le bruit) :

\begin{displaymath}f = h1 * h2\end{displaymath}

Par une opération appelée déconvolution l'analyse homomorphique permet dans certain cas de séparer les signaux $h1$ et $h2$. Le principe de la méthode est de calculer le logarithme de la transformée en $z$ du signal (que l'on appelle $F$) dont on déterminera par la suite l'original. Ainsi, le signal $F$ obtenu de $f$ par une opération non linéaire est appelé cepstre complexe associé au signal $f$. On a :

\begin{displaymath}F(n) = H1(n) + H2(n)\end{displaymath}

L'espace de représentation du cepstre (appelé espace quéfrentiel) est homogène au temps. On peut parfois arriver à isoler les signaux $H1$ et $H2$ par filtrage temporel. Pour cela, on applique l'opération inverse sur $H1$ et $H2$ afin d'obtenir $h1$ et $h2$.

Remarque

Si on dispose d'un signal minimum phase, alors on peut calculer son cepstre a partir du module de la transformée de Fourier. Si $f$ est un signal réel alors $F$ sera aussi réel.

Le cepstre réel

Le cepstre réel est la transformation que nous avons employé pour avoir la fréquence fondamentale d'un enregistrement de voix et la fréquence des formants (qui la constituent).

Principe

Pour calculer le cepstre réel on applique la formule la plus classique : Elle se sert de la transformée de Fourier à court terme, basée sur l'application de 2 TFD(transformée de Fourier discrète). Au départ, on suppose qu'on dispose d'un enregistrement de voix échantillonné f(n) qui est la convolution du signal de la source par le filtre correspondant au conduit : $f(n) = s(n) * b(n)$. On applique une première transformée discrète sur le signal et on obtient le signal F(n). Ensuite, on calcule son module, on met la partie imaginaire du signal à 0 et on se sert du log du signal pour séparer les 2 composants :



\begin{displaymath}F(n) = S(n) * B(n)\end{displaymath}


\begin{displaymath}log(\vert F(n)\vert) = log(\vert S(n)\vert) + log(\vert B(n)\vert)\end{displaymath}


Enfin, on applique une FFT inverse sur ce signal. Le cepstre réel correspond à la partie réelle de ce qu'on a en sortie.

Utilisation


Remarque

Les coefficients cepstraux ne présentent pas des variations intra-locuteurs de même ampleur. La variance des coefficients cepstraux décroît avec leur ordre.

Hamming

En voici le principe de fonctionnement. Le principe de l'amplification est simple. On crée le signal de Hamming, et on le multiplie a celui que l'on veut amplifier. L'intérêt est d'effacer progressivement le début et la fin du signal tout en amplifiant la partie principale. Pour créer ce signal de Hamming, on utilise cette formule :

\begin{displaymath}H(i)=Ha - Hb * cos\left(\frac{2\pi * i}{n - 1}\right)\end{displaymath}

Le spectrographe

Dans un but expérimental, nous avons dû coder le spectre du signal, une FFT sur tout le signal qui nous permet de voir l'évolution des fréquences dans le temps du signal. Cette "image" de la voix sera entre autre utilisée pour l'aspect graphique du programme. L'aspect code n'est toujours qu'une réutilisation des outils précédemment codés. Ainsi le spectre ne fut pas très compliqué à coder. Pour afficher ce spectre, on a utilisé la Xlib. Une librairie très simple qui affiche tout simplement un point sur un framebuffer ou l'on veut. L'outil n'est pas très puissant mais nettement suffisant pour l'affichage de Spectre.


Décrivons brièvement le fonctionnement :


Nous faisons une FFT de 256 sur les 256 premiers échantillons. On refait une FFT de 256 sur 256 échantillons mais à partir du 128ème échantillons, etc... Ainsi, sur 512 échantillons, nous aurons fait 3 FFT, une de 1 à 256, une de 128 à 384, puis de 256 à 512. C'est ce que l'on appelle des fenêtres de recouvrement. L'affichage ce passe alors ainsi : La couleur (bleu en l'occurrence) peut prendre 256 valeurs. Nous avons un tableau de $256 * [la\ taille\ du\ signal / 128]$ Ainsi, nous avons au fur à mesure du signal une FFT qui sera représentée ainsi :



Voici le spectre d'un signal :

\includegraphics[]{spectre.ps}
L'intensité de chaque pixel montre l'amplitude pour la fréquence associée. On remarque bien la présence des différents mots prononcés. Ainsi, le spectre représente précisément un w

Le spline cubique

Après avoir fait la FFT sur le WAV, nous avons pour intention d'en ressortir l'ensemble caractéristique. Pour pouvoir rentrer notre partie du signal dans le réseau de neurones, celui-ci devra être "lisser". Cela veut dire que, par exemple, si l'on a 200 points mais que le signal final doit faire 20'000 points, on ne va pas simplement compléter les "trous" par des droites mais par des courbes cubiques de manière à ce que tout le signal ne forme plus qu'une grande courbe passant par tous ces points. C'est le principe du spline cubique.

Recherche de polynômes

Première approche :
Au début, nous avions l'intention de trouver un polynôme de degré n-1 (ou n est le nombre de points) qui passerait par tous ces points. Théoriquement, c'est très simple, un simple système d'équation a résoudre, et trouver le polynôme de plus bas degré et de tracer le plus court. Le problème, c'est qu'après avoir codé la résolution de l'équation matricielle obtenue ainsi que le test de degré le plus bas et de tracer le plus court, l'algorithme se montra terriblement lent. Pour résoudre ce problème, nous avons travaillé sur une optimisation grâce aux professeurs de mathématique. En vain, l'algorithme se montrait bien trop lent (plusieurs minutes en fonction du nombre de points).

Deuxième solution, plus dure mais plus efficace :
Après s'être renseigné sur Internet, nous avons trouver un TIPE que était dédier aux splines. Dernière chance, comprendre ce charabia mathématique et tous traduire en algorithme efficace. Pour simplifier l'aspect théorique du spline cubique, voici une explication courte, simple mais complète.
Nous avons $n+1$ points, on veut une courbe lisse qui passe par ces $n+1$ points. Pour ça, nous allons chercher un polynôme cubique qui passe par chaque couple de points définissant les $n$ intervalles.
Les dérivés premières et secondes doivent être continues (pour cela, il suffit de calculer les pentes). Ensuite, pour choisir le polynômes à prendre il faut sélectionner celui dont la dérivée est la même que le polynôme précédent au point d'intersection.
Finalement, grâce à cette technique, le spline marche et nous avons une jolie courbe qui passe par tous nos points...
next up previous contents
suivant: Cryptographie monter: SOUTENANCE FINALE MARVIN (Modest-encoding précédent: Structures d'apprentissage & Réseaux   Table des matières
root 2002-06-18