Up FIR FII Codeur LPC Le filtre de pré-emphase

L'aspect technique

Cette page a pour but de présenter l'aspect plus technique du projet. Elle explique aussi les choix de programmation faits.

La théorie 

Cette partie aborde les différents blocs de l'analyseur sous leur aspect théorique. Les différents blocs nécessitant des explications plus détaillées seront abordés comme le filtre et le codeur LPC.

Le filtre RII

Le filtre RIF

Le codeur LPC

Les choix de programmation

La conception de cet analyseur a été envisagée dans le cadre du projet du service de Traitement du sognal et de l'information de fournir sur son site des programmes de démonstration des thèmes abordés dans le cadre des cours. C'est pourquoi, ce programme a été conçu de façon modulaire.

Chaque élément représenté sous la forme d'un bloc réalise une tâche précise et est indépendant du reste du programme. Chaque bloc utilisé peut donc être réutilisé tel quel dans un autre programme à condition de respecter les règles de programmation établies.

Tout bloc se compose de l'interface suivante:

  1. un fréquence de travail propre qui représente en règle générale la fréquence d'échantillonnage du système

  2. une fonction réalisant le traitement des données, que ce soit des échantillons ou des blocs d'échantillons. Cette fonction permet en même temps à la fonction de se comporter comme une source de donnée.

  3. une source de donnée dans laquelle ce bloc lira les informations à traiter. Il s'agira en règle générale d'une référence à un autre bloc 

Un bloc lit donc soit des échantillons (Sample) ,soit des blocs d'échantillons (Frame) et se comporte pour le bloc suivant soit comme une source d'échantillons ,soit comme une source de blocs d'échantillons.

En respectant cet interface, un bloc se comporte comme un bloc dans Simulink®. 

La fonction réalisant le traitement des données et représentant réellement la fonction de transfert du bloc réalise en général les trois fonctions suivantes dans l'ordre indiqué :

  1. Lire l'échantillon ou les échantillons nécessaires dans sa source de donnnées.
  2. Traiter les données;c'est à dire exécuter la fonction de transfert
  3. Renvoyer les données.

On peut représenter cela comme suit :

Cette approche est appelée non tamponnée et synchrone. En effet le dernier bloc demande un échantillon au bloc précédent qui lui même le demande au bloc précédent et ainsi de suite. Arrivé au premier bloc ,celui-ci fourni son échantillon au suivant qui le traite et renvoie le résultat au bloc suivant,etc. Cette méthode est simple et parfaitement adaptée à l'élaboration d'une chaine de traitement échantillon par échantillon.

Un autre approche qui avait été envisagée mais qui n'a pas été retenu pour des raisons de complexité était une approche tamponnée asynchrone. Dans une telle approche,chaque bloc contient un tampon soit en entrée,soit en sortie et exécute de façon continue sa fonction de transfert dans une tâche (thread) tournant de façon séparée du reste du programme. Cette approche a un avantage non négligeable au niveau de l'indépendance des différents blocs mais nécessite des méchanisme de   synchronisation des threads. Dans une telle approche les tampons peuvnt être vus comme des tunnels dans lesquels circule l'information de façon séquentielle. On peut examiner les données qui y transitent facilement. Ce sont l'équivalent des flèches dans un schéma bloc. Mais la complexité d'écriture et de gestion d'une telle approche annule tout les avantages. De plus dans un environnement mono-processeur,on ne peut pas tirer parti d'une exécution parallèle du traitement.

Pour pouvoir intégrer certaines fonctions comme le codeur LPC, il a été nécessaire de programmer les librairies de fonction manipulant les complexes et les polynomes. Cela a été réalisé dans une optique orientée objet sous la fome de deux classes Complex et TPolynom.

Le langage utilisé est le Delphi version 4. Il a l'énorme avantage de fournir un environnement de programmation rapide et aisé pour tout ce qui est graphique. Par contre j'ai éprouvé des problèmes au niveau de la gestion de la mémoire et des threads quand la complexité du programme augmente. J'ai eu des problèmes de renvoi de référence à des objets échangé entre les différents blocs. Un autre grand problème est l'interfaçage rudimentaire pour accéder au périphériques son au niveau de l'échantillon ou du décodage de fichiers Wave.

J'avait aussi développé une version de ce programme en Java. Malheureusement les outils de déboggage et l'interfaçage graphique sont difficile à utilisé ou relativement peu performants. C'est donc évidemment à ce niveau là que les obstacles se sont posés,ce qui m'a forcer à passer sous Delphi. Par contre un autre avantage est que les problèmes qui se sont posés en Delphi ne se posent pas en Java. De plus ce langage permet d'utilliser certaines particularités de l'approche objet non présentes en Delphi qui permettent une programmation plus rigoureuse.

Je vais m'arrêter ici dans la description de la programmation car ce n'est pas le sujet du projet.

Voici les sources en Delphi et en Java.