EXEMPLES AUDIO

Contenu

Exemples d’utilisation des fonctions audio et de visualisation et traitements temps réels.

 

Mots clés

analogique, temps réel.

 

Fichiers MUSTIG associés

ACQUIS.MTG, GENESIG.MTG, FILTR_RII.MTG,  FILTR_RIF.MTG, dans le répertoire “ACQUIS”

 

Exemples commentés voisins

Filtrage, Analyse spectrale, Filtrage RIF,  convolution par TFD.

 

Acquisition de signal

Taille des buffers d'acquisition

 

Le buffer d'acquisition en entrée est une zone de mémoire où sont mémorisées les échantillons acquis (au rythme de la fréquence d'acquisition) avant d'être traités (lus par blocs par l'un des  modules "ADC 2 Voies" ou "ADC nVoies"). Dans les cas de traitement régulier, il suffit que ce buffer soit de taille un peu supérieure à la taille des blocs multipliée par le nombre de voies. Une bonne sécurité est de majorer d'un facteur deux. Dans le cas de traitement à durée variable (typiquement écriture de résultats sur fichiers disques) il sera nécessaire d'augmenter notablement la taille.

Le seul inconvenient à surdimensionner les buffers d'entrée est de réserver de la mémoire.

 

Le buffer d'acquisition en sortie fonctionne de manière analogue. Par contre, il est déconseillé de surdimensionner inutilement ce buffer, car cela crée un retard proportionnel à la taille de ce buffer.

 

Acquisition d’un seul bloc

Le graphe ci-dessous réalise l’acquisition et la visualisation d’un bloc de signal. La macro “Init Acq” (construite avec le module “ADinit”) fixe la fréquence d’échantillonnage et la taille des zones tampons  (“buffers”). Ces zones doivent être dimensionnées à une taille supérieure au produit de la taille des blocs acquis par le nombre de voies. Ici, la sortie analogique n’étant pas utilisée, la taille du buffer de sortie est fixée à une valeur très petite (une valeur nulle n’est pas autorisée).

La macro “Init Acq” fournit la fréquence d’échantillonnage (qui est la fréquence, réalisable par la carte, la plus proche de la fréquence demandée), en kilohertz. Cette valeur est convertie en seconde pour fixer le pas de la variable “t”.

Le module “ADC2Voies” réalise l’acquisition et la conversion numérique d’un bloc de signal analogique, sur deux voies. On se contente ici de le visualiser.

On constate que si on redemande le calcul de la courbe visualisée, une nouvelle acquisition est réalisée. De la même façon, si on ajoute un traitement, l’acquisition sera refaite. Ce fonctionnement, qui peut sembler anormal à un habitué de Mustig, est plus pratique dans beaucoup de cas. Si l’on désire analyser un transitoire, on pourra l’enregistrer dans un fichier (en remplaçant la “Visu” par une macro d’écriture de fichier), et relire ce fichier pour le traiter.

 

Acquisition continue de blocs

On réalise ici suite infinie d’acquisition de blocs qui sont visualisés au fur et à mesure. Cela réalise une fonction analogue à celle d’un oscilloscope.

Pour réaliser cette acquisition continue, il suffit de reboucler dans un paquet MUSTIG les deux bornes entrée et sortie “synchro” du module  “ADC2Voies”. (Ces bornes de “synchro” ne véhiculent pas de réelle information, mais servent seulement à spécifier que les acquisitions de blocs se font les unes après les autres.)

 

On obtient alors la macro “Acq_2/t/x” de la bibliothèque “Bib_au32”.

On remarquera, dans les paramètres de cette macro, que l’on a mis le flag “Temps-réel” à “0”. En effet, pour une simple visualisation de signal, il n’est pas gênant de perdre des échantillons entre les blocs. (Avec un oscilloscope analogique, le signal est toujours perdu pendant le retour de balayage). En conséquence, la taille du buffer nécessaire est encore le produit de la taille des blocs acquis par le nombre de voies.

En sortie, on dispose d’un signal constitué de blocs fonctions de la variable “t”, et indicés par la variable “x”. Cela est analogue à la sortie d’une macro de lecture d’un fichier disque par blocs.

Pour réaliser la visualisation, on utilise la macro “Visu animée” (Qui se trouve dans “Bibli-1”). Elle est faite à partie le la macro “Visu” standard, complétée par une macro “Défile”. Cette dernière réalise l’affichage à l’écran puis l’effacement des visualisations successives.

 

Enregistrement disque

Pour réaliser un enregistrement d’un signal analogique dans un fichier disque, Il suffit de brancher une macro “Ecriture2D/t/x”  derrière la macro “Acq_2/t/x”.

Dans ce cas, il est impératif de mettre le flag “Temps-réel” à “1” pour ne pas risquer de perdre d’échantillons. Il sera également utile de fixer la taille du buffer d’entrée à une valeur égale à plusieurs fois la taille des blocs. En effet, la durée d’écriture d’un bloc sur disque n’est pas régulière. Il faut donc un buffer suffisamment grand pour niveler ces irrégularités. Il n’y a pas d’inconvénient à mettre une très grande taille, à condition qu’elle tienne dans la mémoire de la carte. (Tant que le message “mémoire donnée saturée n’apparaît pas).

 

Analyseur de spectre

Le graphe suivant réalise l’acquisition d’un signal, son analyse spectrale et la visualisation de celle-ci.

 

La macro “SpectreTR” est une modification de la macro “Spectre” contenue dans la bibliothèque secondaire “Bibli-1”, et décrite dans l’exemple commenté  “Analyse spectrale”. La somme sur tous les blocs a été remplacée par un filtre passe-bas du premier ordre : on réalise alors une analyse spectrale à moyennage exponentielle. La constante de temps de ce filtre, exprimée en blocs, est facilement accessible.

Notons que la macro “SpectreTR” calcule les transformées de Fourier sur des blocs constitués de deux blocs d’entrée accolés (ce qui revient à utiliser des blocs se chevauchant par moitiés). En conséquence, il est important de ne pas perdre d’information entre les blocs acquis et donc de mettre le flag “Temps réel” à “1”. La taille des buffers devra alors être fixée à 2 fois le produit de la taille des blocs acquis par le nombre de voies.

On constate alors sur la plupart des machines que le fonctionnement temps réel n’est pas possible à la fréquence d’échantillonnage maximum (48KHz). Cela  est dû à une vitesse de tracé insuffisante (le tracé est effectué par le PC). Pour tenir la cadence, il ne faut pas effectuer un tracé  à chaque bloc.

Une première solution serait de faire l’acquisition de blocs beaucoup plus gros (attention à dimensionner les buffers d’acquisition en conséquence!), puis de découper des blocs en sous-blocs et de ne visualiser alors que l’analyse moyennée sur ces blocs. La macro “Spectre” en Bibliothèque peut être paramètrée pour effectuer ce découpage.

Une autre solution, un peu plus souple et moins gourmande en mémoire nécessite une modification de la macro “AcQ_2/t/x” en une macro “Acq_2b/t/b/x. Elle contient un double paquet autour du module ADC2Voies”. Le signal de sortie est alors une suite de “blocs de blocs” indicés par “x”, les blocs élémentaires étant indicés par “b”. La sortie de cette macro est identique à celle du module “découpe” de la solution précédente. La  même macro “Spectre” de Bibliothèque est utilisée, mais elle ne fait pas le découpage.

Génération de signaux

On s’intéresse ici à créer un signal sinusoïdal de fréquence donnée et à l’envoyer sur une sortie analogique.

Génération d’un seul bloc

Le graphe suivant semble remplir la fonction désirée.

On utilise une macro “AcqRest_2/t/x”, qui peut réaliser à la fois l’acquisition (Conversion Analogique-Numérique) et la restitution de signal(conversion Numérique-Analogique). On n’utilise en fait pas les valeurs acquises, mais seulement leur support, dimensionné en nombre de points et pas d’échantillonnage par les réglages de la macro. Le réglage de la fréquence dans la macro “Sinus/t” se fait alors en Hertz.

En fait, ce graphe n’est pas satisfaisant, car la phase du sinus est réinitialisée à chaque bloc. Le résultat n’est correct que pour les valeurs de fréquences telles qu’il y a un nombre entier de périodes par blocs. (En fait, le sinus sera calculé une seule fois, ce qui est économique quand le résultat est satisfaisant).

 

Génération par blocs d’un signal continu

Pour supprimer les discontinuités de phase, il faut calculer la phase du premier point d’un bloc en fonction de celle du dernier point du bloc précédent. Cela est facilement réalisé en ajoutant un deuxième bouclage, selon la variable “b” qui indice les blocs, dans le calcul de la phase, à l’intérieur de la macro “sinus”

     =>  

 

Notons que le générateur de sinus de la bibliothèque utilise un calcul de phase en arithmétique entière. Cela permet d’obtenir simplement un calcul “modulo 2π”. Un calcul en flottant sans précaution est inutilisable en temps réel : le calcul du sinus devient de moins en moins précis à mesure que la phase augmente.

Il est nécessaire de mettre la flag “Temps-réel” à “1”. La taille du buffer de sortie sera fixée à 2 fois le produit de la taille des blocs acquis par le nombre de voies. Cela permet de calculer le bloc suivant pendant que le bloc courant est converti. Attention, contrairement au buffer d’entrée, il n’est pas souhaitable d’augmenter inutilement le  buffer de sortie : cela augmente le retard.

On constatera probablement que la fréquence maximum n’est pas atteinte : le calcul du sinus est relativement lent. L’utilisation d’une table serait plus efficace.

 

Générateur de signaux

La macro générateur de signaux est comparable à un appareil “générateur de fonction”. Elle ne possède pas de sortie : sa sortie est analogique. Les contenus des macros de bibliothèque “Sinus/”, Carré_p/t”, Triangle_p/t” ont été réunis. Une boîte de choix permet d’aiguiller l’une ou l’autre des trois sorties.

 

Filtrages  RII

Dans les deux exemples suivants, on effectue un filtrage numérique sur un signal qui provient de la conversion d’un signal analogique, et on reconvertit en analogique la sortie du filtre numérique. On obtient globalement l’équivalent d’un filtre analogique.

Le graphe suivant semble remplir la fonction désirée. En fait, il n’est pas satisfaisant, car le filtre est réinitialisé à chaque début de bloc. Cela se traduit par des pics à chaque passage d’un bloc à un autre.

Il existe deux solutions. La première consiste à transformer la fonction vectorielle d’acquisition en une fonction scalaire, en utilisant des blocs de taille 1. C’est une solution facile à mettre en oeuvre, mais elle ne fonctionne qu'à fréquence relativement basse.

La deuxième solution est de remplacer toutes les macros “Retard/t” du filtre par des macros “Retard_bc/t/x”(disponible en Bibli-1). Grâce à un double bouclage, cette macro met en premier échantillon d’un bloc de sortie, le dernier échantillon du bloc d’entrée précédent (Voir commentaire des exemples “filtre récursif”).

On remarquera dans ces exemples l’utilisation des reports pour obtenir un graphe linéaire. Sinon, il apparaît bouclé par le fait que les convertisseurs d’entrée et de sortie sont dans la même macro. On remarquera également que l’on a directement connecté le signal acquis sur une entrée de la macro “AcqRest”, donc sur une sortie analogique. Cela permet de mesurer le retard dû aux filtres des convertisseurs et aux mémoires tampon, et par différence, le retard dû au filtre numérique.

Dans toutes les applications de filtrage, il est conseillé de régler la taille du  buffer de sortie au minimum nécessaire pour ne pas augmenter inutilement le retard.

Filtrages  RIF

Pour réaliser un filtre à mémoire finie, il est possible de décrire le filtre par son diagramme de flux. Il faudra alors comme précédemment remplacer les “Retard/t” par des “Retard_bc/t/x”.

 La meilleure solution sera généralement  d’effectuer le filtrage à l’aide de la TFD. La macro “Filtrage par morceaux” réalise un filtrage continu à partir d’un signal découpé en blocs, tel que celui qui sort des macros d’acquisition.

On donne divers exemples de réponse impulsionnelle de filtres.