Electronique > Réalisations > Effets > Delay (réverbération/écho) 004

Dernière mise à jour : 28/01/2024

Présentation

Cette unité de retard audio qui travaille dans le domaine du numérique repose sur le principe de la modulation delta 1 bit.  

delay_004d_pcb_3d_front

L'indispensable convertisseur analogique numérique (CAN) est construit avec un comparateur de tension et une bascule D, tandis que le convertisseur numérique analogique (CNA) se contente d'une bascule de même type et d'un réseau intégrateur RC. Les signaux de commande sont obtenus avec des composants logiques traditionnels, aucun microprocesseur (et donc aucun programme) n'est requis. La fréquence de travail du convertisseur, fixée à 1 MHz, permet une bande passante de 20 kHz pour un temps de retard dépassant la seconde.

Plusieurs schémas ont été étudiés, tous sont basés sur le même principe de fonctionnement :

- schéma 004a : utilisation d'une mémoire vive "62256" de 256k (32k x 8 bits) sous-exploitée, retard maximum 4 ms (à 1 MHz)
- schéma 004b : utilisation d'une mémoire vive "62256" de 256k (32k x 8 bits) pleinement exploitée, retard maximum 32 ms (à 1 MHz)
- schéma 004c/004d : utilisation d'une mémoire vive "CY62158H" de 8 Mb (1 M * 8 bits), retard maximum 1024 ms (à 1 MHz), 1 voie
- schéma 004e : utilisation d'une mémoire vive "CY62158H" de 8 Mb (1 M * 8 bits), retard maximum 1024 ms (à 1 MHz), 8 voies
- schéma 004f : utilisation d'une mémoire vive "CY62158H" de 8 Mb (1 M * 8 bits), retard maximum 8192 ms (à 1 MHz)

Le but de cette série de montages est de montrer qu'on peut réaliser une ligne à retard audio de bonne qualité avec peu de moyens.

Chose curieuse, la particularité des montages proposés (tout du moins jusqu'à la version 004d) est de gâcher de la mémoire. Je le dis sans honte, car je sais me rattraper.

   

Avertissements

   

Préambule à l'étude

Avant d'analyser les schémas "définitifs" proposés, faisons un tour rapide des besoins et des moyens mis en œuvre pour ne pas être déçus. Compteur binaire, mémoire RAM, comparateur de tension, bascules D et portes logiques... le temps est aux révisions.
   
Principe de fonctionnement

Le signal audio (analogique) à retarder est "numérisé" grâce à un convertisseur basé sur la modulation delta. Le résultat est un unique bit de donnée qui n'arrête pas de changer de valeur (0 ou 1) au gré des variations d'amplitude du signal audio entrant. Dans le schéma, ce "bit variable" est appelé Din (Data_In), donnée qui entre dans la ligne à retard et qui en ressort plus tard à l'endroit marqué Dout (Data_Out).
Pour ne pas tout mélanger, je traiterai séparément le cas du convertisseur delta et celui de la ligne à retard numérique.

   
Convertisseur modulation delta
Le principe de base est visible sur le synoptique (schéma très simplifié) suivant :

bases_audio_effets_delay_principes_sampling_digital_delta

Dans un premier temps, j'ai travaillé sur les convertisseurs AN et NA, la sortie du premier (broche 5 de U1:A) étant directement reliée à l'entrée du second (broche 12 de U1:B), sans aucune ligne à retard entre les deux (ligne notée Data).
   
test_modulation-delta
   
Sur le front montant du signal d'horloge Clock, la bascule U2:A délivre sur sa sortie Q (broche 5) un état logique qui dépend de l'état de la sortie du comparateur de tension U1. Cette sortie de comparateur dépend elle-même de l'amplitude du signal audio actuellement appliqué sur son entrée [+] et de l'amplitude du signal appliqué sur l'entrée [-] qui lui-même est représentatif d'une amplitude passée. On dispose ainsi sur la sortie du comparateur d'un état logique 0 ou 1 qui change continuellement, en fonction des variations d'amplitude instantanées du signal audio entrant et de ses variations antérieures.

L'objectif principal avec ce premier morceau d'électronique était d'obtenir les meilleurs résultats possibles du côté analogique, c'est à dire avec le minimum de différences entre le signal d'entrée analogique (avant conversion AN) et celui de sortie analogique (après conversion NA).

Mine de rien, cette "simple" mise au point a nécessité de nombreuses heures de travail, car sans les calculs imbuvables auxquels je refuse de me plier, il me fallait procéder par "approximations successives" pour plusieurs valeurs de composants. J'ai finalement trouvé des valeurs qui (me) conviennent, à en juger les courbes entrée/sortie visibles sur les graphes suivants (entrée en vert et sortie en rouge).
   
test_modulation-delta_001a
   
test_modulation-delta_001b  
Le signal de sortie filtré (en rouge) est une restitution assez fidèle du signal d'entrée (en vert)
   

Les simulations bien sûr devraient être suivies d'essais pratiques pour vérifier que tout se passe comme attendu. Pour cela, un circuit imprimé a déjà été réalisé pour la seule partie "conversions", voir § Prototypes.

Une fois passée cette délicate épreuve d'essais multiples sur la section "analogique", j'ai pu passer à la section de retard numérique.

   

Ligne à retard numérique

Dans le principe, un simple registre à décalage série convient pour récupérer à un instant T2 une valeur de donnée insérée à un instant T1, selon un rythme (et donc temps de retard) imposé par une horloge externe. Malheureusement, les registres à décalage qu'on trouve facilement possèdent un nombre très réduit de bits de décalage. Par exemple, les registres à décalage "SN74165" ou "SN74495" ne travaillent que sur 8 bits et il faudrait au bas mot plusieurs centaines de boîtiers pour obtenir un retard de seulement quelques millisecondes !

   
test_shift-register-74597_001a
Principe de base - Cela fonctionne, mais le temps de retard serait ridiculement faible pour un usage en audio
   
Il faut donc trouver autre chose que de simples registres à décalage. Bien sûr, on pense rapidement aux mémoires vives (RAM) qui intègrent des milliers ou des millions de cellules. Seulement voilà, une cellule mémoire est faite pour être lue ou écrite, pas pour être décalée. On peut bien sûr imaginer une logique de commande basée sur un microprocesseur ou microcontrôleur afin d'écrire et lire les données aux moments adéquats (comme cela est fait dans mon Delay 003), mais dans ce cas, l'objectif annoncé en début d'article (pas de MCU) devient caduque. Pour cette raison, il fallait ruser...

Le principe adopté en définitive est d'une simplicité enfantine quand on y réfléchit (même quand on n'y réfléchit pas). Il consiste à lire le contenu d'une cellule mémoire qui contient une ancienne information avant d'y écrire une nouvelle. Aussitôt après cette étape rapide de lecture et d'écriture, on passe à l'adresse mémoire suivante et on renouvelle l'opération. Une fois parcourue la totalité de la zone mémoire, on revient au point de départ et on continue la manœuvre. Si la mémoire comporte 4000 cellules et qu'on passe de l'une à l'autre au rythme de 100 us (fréquence d'horloge de 10 kHz), alors les données enregistrées "ressortent" 400 ms plus tard. 

Chouette alors, on dispose de 400 ms avec seulement 4000 bits ! Petite pause, jeune padawan, cela ne suffit pas (ce serait trop beau).

Rappelons les points essentiels (à retenir) pour une opération d'échantillonnage :

Bien entendu, l'utilisation d'une fréquence d'horloge (et donc fréquence de décalage) aussi élevée raccourcit beaucoup le temps de retard et il faut compenser cette baisse par un nombre accru de cellules mémoire. Fort heureusement, les données retardées sont peu sensibles au bruit de fond et leur "régénération" d'une cellule à l'autre est "automatique" et en aucune manière problématique. On peut donc ajouter autant de cellules mémoire qu'on le désire, sans craindre de baisse de qualité sonore. C'est le point fort des lignes à retard numériques...

Il reste toutefois un point noir pour les phases d'écriture et de lecture dans un espace mémoire donné, puisque dans une mémoire la même ligne de donnée peut aussi bien servir en écriture qu'en lecture, grâce à un signal de commande de type WE (Write Enable). La méthode adoptée ici repose sur une caractéristique "ennuyeuse" des portes logiques qui est leur temps de transit entrée/sortie non nul. Ici, j'utilise des portes logiques TTL de type 74HC04 (les mêmes que celles que j'utilise dans quelques unes de mes interfaces MIDI) dont le temps de transit d'environ 10 ns est mis à profit pour retarder les signaux de commande utilisés pour écrire ou lire dans les cellules mémoire. Il serait très difficile de faire aussi vite avec un microcontrôleur et de plus, le circuit est plus simple ! Voyons cela de près.

Schéma 004a

Dans le schéma qui suit, simplifié à l'extrême, la totalité de l'espace mémoire de la RAM 62256 n'est pas mise à profit. Seules les lignes d'adresses A0 à A11 sont en effet utilisées, les autres sont en permanence reliées à la masse. Il s'agit d'un schéma de base que nous étendrons par la suite (le but ici est juste d'analyser le fonctionnement).

delay_004a
Un schéma simple... et 100% fonctionnel !
   

Ce qui suit doit être assimilé pour comprendre le séquencement de l'ensemble :

- Le signal d'horloge Clk est un signal carré de 1 MHz qui rythme l'ensemble
- Le compteur binaire U3 s'incrémente (ses sorties Qx changent d'état) quand le signal clock passe à l'état bas (1->0)
- L'état logique de la ligne RE (Read Enable) est l'inverse de celui de la ligne WE (Write Enable) grâce à la porte logique U6:F
- Quand WE = 0 et RE = 1, la mémoire RAM est en phase d'écriture et sa ligne D0 est connectée à la ligne Din grâce à U5:A
- Quand WE = 1 et RE = 0, la mémoire RAM est en phase de lecture et sa ligne D0 est connectée à la ligne Dout grâce à U5:B

Le graphe ci-après permet de visualiser ce qui se passe dans un très court instant :

   
delay_004_graph_clk-we-re_001a
   

Séquencement de l'ensemble

On part d'un moment où Clk = 0 (WE = 1 et RE = 0, adresse mémoire quelconque) et on regarde ce qui se passe quand Clk passe de 0 à 1.

1 - La bascule U2:A prend en compte le nouvel état logique fourni par le comparateur de tension U1. Cet état est verrouillé sur la sortie Q de la bascule (broche 5) et est disponible sur la ligne Din qui permettra la sauvegarde en RAM de la donnée actuelle.
2 - Un très bref instant plus tard (10 ns), la ligne WE (Write Enable) passe à l'état logique bas (1->0). La mémoire RAM passe alors en mode d'écriture et sa ligne D0 se déconnecte de la ligne Dout car la porte U5:B s'ouvre. A ce stade, les sorties Qx du compteur binaire U3 ne changent pas d'état, elles conservent l'état qu'elles avaient quand l'entrée du compteur avait reçu un front descendant (1->0).
3 - Un très bref instant plus tard (10 ns), la ligne RE (Read Enable) passe à l'état logique haut (0->1), ce qui a pour conséquence de relier la ligne Din à la ligne de donnée D0 de la RAM. La RAM, qui est en mode écriture, prend en compte (stocke) cette nouvelle valeur injectée sur sa ligne D0.

Maintenant, regardons ce qui se passe quand Clk passe de 1 à 0.

4 - Le compteur binaire U3 s'incrémente de 1 point, une ou plusieurs de ses sorties Qx changent donc d'état. Cela a pour conséquence de positionner la RAM sur un nouvel emplacement mémoire - qui servira lors de la prochaine phase d'écriture.
5 - Un très bref instant plus tard (10 ns), la ligne WE (Write Enable) passe à l'état logique haut (0->1). La mémoire RAM passe alors en mode de lecture et sa ligne D0 se connecte à la ligne Dout car la porte U5:B se ferme. On récupère donc ici une ancienne donnée mémorisée.
6 - Un très bref instant plus tard (10 ns), la ligne RE (Read Enable) passe à l'état logique bas (1->0). La ligne D0 de la RAM se déconnecte de la ligne Din car la porte U5:A s'ouvre (voir remarque ci-après).

Remarque : idéalement, la chronologie d'ouverture et de fermeture des portes logiques U5:A et U5:B devrait être telle qu'aucune des deux portes ne se ferme simultanément. Ici, on observe cet état indésirable pendant quelques ns, mais cela n'a pas de conséquence néfaste, car la mémoire RAM est à cet instant en mode de lecture et la bascule U2:B ne réagit pas au front descendant de l'horloge Clk.

Ceci étant vu, voyons ce qu'on obtient après balayage de la mémoire RAM, avec ses phases alternées d'écriture et de lecture. 

Avec 12 lignes d'adressage de la mémoire (adressage 12 bits, de A0 à A11), on ne peut accéder qu'à 4096 cellules (2 puissance 12). En utilisant un rythme d'horloge de 1 MHz (période 1 us), 4096 us suffisent pour balayer entièrement la zone mémoire adressable. Dans ces conditions, le retard ne peut pas dépasser une durée de 4 ms - durée insuffisante pour créer un effet d'écho.
   
delay_004a_graph_001a
Signal entrant (trace en vert) et signal retardé (trace en rouge), le retard n'est que de 4 ms

Pour augmenter le temps de retard en conservant la même mémoire 62256, il faut simplement avoir accès à la totalité de ses cellules et pour cela il nous faut un compteur binaire doté de davantage de sorties. Pas facile à trouver ? Qu'importe, nous allons chaîner deux compteurs, ce qui nous donne le schéma 004b où la totalité des adresses mémoire est désormais utilisée.

   

Schéma 004b

Avec le schéma révisé suivant, la mémoire se rend pleinement utile et jubile (on la comprend) ! Comme les circuits de conversion AN et NA ne changent pas, inutile de les redessiner.

delay_004b
 
Le retard est effectivement augmenté comme prévu, mais...
   
delay_004a_graph_001b
   
... grosse déception, car il n'est au maximum que de 32 ms. Finalement c'est logique, puisqu'on double le retard à chaque fois qu'on ajoute une ligne d'adresse (l'ajout d'une ligne d'adresse double le nombre de cellules accessibles). Avec 3 lignes d'adresses en plus (15 au lieu de 12), on a bien multiplié par 8 (2 puissance 3) le nombre de cellules utilisables, ainsi que le temps de retard.

Deux solutions permettent d'allonger davantage le temps de retard : soit on trouve un circuit mémoire de plus grande capacité, soit on réduit la fréquence d'horloge Clk. Pour la seconde solution, c'est hors de question ! Voilà pourquoi on aboutit au schéma 004c.

   

Schéma 004c

Adieu mémoire vive "62256" de 256k (32k x 8 bits) et bienvenue mémoire vive "CY62158H" de 8 Mb (1 M * 8 bits). Là encore, les circuits de conversion AN et NA ne changent pas, inutile de les redessiner.
   
delay_004c
   
Si j'ai bien tout compris, la mémoire "CY62158H" de 8 Mb possède 32 fois plus de cellules mémoire, on devrait donc pouvoir atteindre un retard maximal de 32 * 32 ms, soit 1024 ms - largement de quoi produire un effet d'écho. Et c'est effectivement ce qu'on obtient. Cool !

Bien, nous disposons désormais d'une unité de retard de bonne qualité sonore et doté d'un long temps de retard, mais comment régler le temps de retard ? Ah oui, ce détail m'avait échappé... réfléchissons.

   
Réglage du temps de retard

Avec la méthode de lecture et d'écriture dans la RAM adoptée dans notre système, on est obligé d'attendre un balayage complet de toutes les zones mémoire de la RAM pour retrouver notre signal retardé. Cela signifie qu'en l'état, le temps de retard est toujours à son maximum. C'est un peu embêtant...  Deux méthodes ont donc été mises en œuvre pour pouvoir ajuster le temps de retard à la valeur désirée :

- réduction ajustable de la plage mémoire accessible (choix d'une plage de valeurs)
- ajustage de la fréquence du signal d'horloge Clk dans une plage réduite de 500 kHz à 1,5 MHz (ajustage fin).

Cela nous conduit au schéma 004d (on n'arrête pas le progrès).

   

Schéma 004d

Le schéma 004 nous montre comment réduire la plage de balayage de la mémoire RAM en vue de réduire le temps de retard.
   
delay_004d
   

La solution est très simple : il suffit de mettre les compteurs binaires U3 et U7 à zéro quand on atteind une certaine limite. Ici, cette limite correspond à l'activation d'une des lignes de sortie des compteurs binaires et donc également des lignes d'adresse de la RAM. Pour cela, un commutateur rotatif à 12 positions (SW1) remet les compteurs à zéro quand une de leurs lignes de sortie Qx passe à l'état logique haut, ce qui les empêche de continuer leur course folle.

Exemple 1 : commutateur rotatif SW1 placé en position Q9. Dans ce cas, les compteurs U3 et U7 se remettent instantanément à zéro quand la ligne Q9 s'active, ce qui signifie que le balayage de la RAM ne concernera que ses lignes d'adresse de A0 à A8, soit 9 lignes d'adresse seulement. Dans ces conditions, le temps de retard est limité à 0,5 ms (2 puissance 9 = 512).
Exemple 2 : commutateur rotatif SW1 placé en position Q13. Dans ce cas, les compteurs U3 et U7 se remettent instantanément à zéro quand la ligne Q13 s'active, ce qui signifie que le balayage de la RAM ne concerne que ses lignes d'adresse de A0 à A12, soit 13 lignes d'adresse seulement. Dans ces conditions, le temps de retard est limité à 8 ms (2 puissance 13 = 8192).
Exemple 3 : commutateur rotatif SW1 placé en position Qnc. Dans ce cas, les compteurs U3 et U7 ne se remettent pas à zéro de façon prématuré, ce qui signifie que le balayage de la RAM concerne la totalité de ses lignes d'adresse de A0 à A19, soit 20 lignes d'adresse. Dans ces conditions, le temps de retard est à son maximum de 1024 ms (2 puissance 20 = 1048576).

Cette façon de faire implique un rapport de durée de 2 entre chaque plage. Il nous faut désormais pouvoir ajuster la durée désirée au sein d'une même plage. Pour cela, nous allons utiliser un oscillateur non pas de fréquence fixe 1 MHz, mais de fréquence ajustable entre 500 kHz et 1,5 MHz. Son schéma est le suivant, vous y retrouverez les portes logiques initialement libellées U6:E et U6:F visibles sur les schémas précédents.

delay_004_osc-adj
74HC04 et 74HC14 acceptés, mais 74HC14 conseillé
   
Remarques :

   

Alimentation (pour tous les schémas proposés ci-devant)
L'alimentation doit être de type simple, de valeur +5V, comme celle décrite à la page Alimentation simple 001.

   

Extensions anti-gâchis

Je vous ai averti en début d'article et n'ai pas menti en disant que je gâchais de la mémoire vive. En effet, quel dommage de n'utiliser qu'un seul bit sur les 8 à un emplacement mémoire donné ! Pour profiter des bits de données non utilisés, j'ai pensé à deux pistes "anti-gâchis" :

Si de nouveaux schémas doivent apparaître, ce sera dans les lignes qui suivent.

   

Schéma 004e

Utilisation des bits non utilisés de la RAM pour faire du multi-canal (simple stéréo ou 8 canaux).

Schéma non dessiné

La partie supérieure du schéma 004a (conversions AN et NA) doit être dupliquée en autant d'exemplaires que vous souhaitez de voies indépendantes (maximum 8 voies en tout). Le circuit de retard numérique reste le même (schéma 004a, 004b, 004c ou 004d), sauf que bien sûr on utilise désormais tout ou partie des lignes D1 à D7 de la mémoire RAM et que pour chaque ligne utilisée il faut ajouter deux interrupteurs électroniques de type 74HC4066 (ou autres compatibles).

   

Schéma 004f

Utilisation des bits non utilisés de la RAM pour allonger le temps de retard dans un rapport de 8.

   

Simple idée de départ - schéma non testé dans le monde réel, mais simulation prometteuse !

   
delay_004f

La simulation est prometteuse dans le sens où elle montre que cela fonctionne en théorie. Mais comme un autre élément à fait son apparition dans le système (compteur U8), il convient de vérifier que cela fonctionne réellement en pratique, avec prise en compte des nouveaux temps de transit. A vrai dire, je suis assez confiant, puisqu'en cas de dysfonctionnement on peut toujours ajouter une porte logique ici ou là pour retarder un signal qui arriverait trop vite (dans le domaine des nanosecondes, bien sûr).

   

Prototype(s)

Dans un premier temps, j'ai décidé de tester la seule partie conversions A/N+N/A. Pour cela, j'ai réalisé un circuit imprimé dédié à ce test.
   
test_modulation-delta_pcb_3d_front test_modulation-delta_pcb_copper_top  test_modulation-delta_proto_rm_001b   
   
Le comparateur rapide choisi pour les tests étant en boîtier CMS, j'ai du le souder sur un adaptateur SO8-DIL8. J'ai commencé les tests avec un signal sinus de 1 kHz (voir copie écran oscilloscope plus loin) et j'ai ensuite passé de la musique un peu plus sympa. Dans les deux cas, signal d'horloge de 1 MHz (avec une horloge à 100 kHz, le signal de sortie n'est vraiment pas terrible, comme on pouvait s'y attendre).
   
test_modulation-delta_proto_rm_001c test_modulation-delta_proto_rm_001d test_modulation-delta_proto_rm_001e
   
Le système fonctionne dans les grandes lignes, comme en attestent les copies d'écran suivantes.

test_modulation-delta_proto_rm_001_scope_001b test_modulation-delta_proto_rm_001_scope_001a
Trace supérieure = signal audio de sortie (1kHz), avant filtrage passe-bas
   
Il est important de noter que le signal de sortie 1 kHz représenté par la trace supérieure n'est pas filtré et que pour cette raison, la composante 1 MHz résiduelle est relativement élevée. Les tests effectués avec de la musique ne sont pas concluants, il y a une espèce de gazouillis dans le haut du spectre. Pas le temps dans l'immédiat d'investiguer, je mets donc ce projet en pause.

Pour la partie ligne à retard (mémoire), aucun prototype n'a été réalisé à ce jour. Une seule raison à cela : difficulté d'approvisionnement ou prix prohibitif des circuits intégrés de mémoires...

   

Circuit(s) imprimé(s)

Aucun circuit imprimé réalisé. Vue 3D uniquement pour aperçu des composants utilisés pour la version 004d.

   

Historique

28/01/2024
- Tests partiels du convertisseur delta-sigma. Projet mis en pause suite à mauvais fonctionnement du proto.
17/12/2023
- Ajout photo prototype de test de la section conversions A/N+N/A. Ce proto n'est pas en état de fonctionner, il lui manque un composant.
03/09/2023
- Première mise à disposition.