La synthèse vocale de l'EXL100

L'EXL100 d'Exelvision est équipé du synthétiseur de parole TMS5220 de Texas Instruments. Cet article décrit les principales fonctions du circuit, le processus de commande par l'unité centrale et la méthode de programmation des sons.

Auteur............: Daniel Coulom - Février 2009
Site internet...: DCexel, émulateur des ordinateurs exelvision.

Introduction

L'une des originalités de l'EXL100 est la présence sur la carte mère du synthétiseur de parole TMS5220 de Texas Instruments. La plupart des constructeurs français de l'époque proposaient la synthèse vocale en option. Exelvision l'offrait en standard sur tous ses modèles.

Le manque de documentation précise sur la génération des sons n'a pas facilité le travail des développeurs. Seule l'équipe d'Exelvision était capable de définir les chaînes de commandes nécessaires, et les explications confuses du magazine Exelement Vôtre ne permettaient pas de comprendre le processus de création de nouveaux sons.

Vingt-cinq ans plus tard, cet article a pour ambition de dévoiler les mystères de la synthèse vocale de l'EXL100 et de pallier le manque de documentation officielle.

1- Le synthétiseur vocal TMS5220

Le TMS5220 est décrit dans le TMS5220 Voice Synthesis Processor Data Manual[1]. Voici ce qu'il faut en retenir pour comprendre le processus de production des sons :

Le processeur de synthèse vocale, ou VSP (Voice Synthesis Processor), assure les fonctions suivantes :

2- Le dialogue entre l'unité centrale et le synthétiseur vocal

L'unité centrale TMS7020 n'a pas d'interface directe avec le TMS5220. Toutes les communications passent par un autre microprocesseur, le TMS7041, chargé de la gestion des entrées-sorties. Le dialogue entre le TMS7020 et le TMS7041 utilise le registre périphérique P48, appelé boîte à lettres. Il est composé de huit bits. Le dialogue est contrôlé par trois bits des registres périphériques :
- Le bit b0 du registre P4, écrit par le TMS7041 et lu par le TMS7020
- Les bits b0 et b1 du registre P6, écrits par le TMS7020 et lus par le TMS7041

Dans le sens TMS7020 vers TMS7041, le TMS7020 dépose un octet de commande dans le registre P48, et indique au TMS7041 qu'il doit le lire en passant à 1 le bit b0 de P6. Le TMS7041 répond par une interruption 1 d'acknowledge, identifiée par le bit b0 de P4 à 1. Si la commande nécessite des données complémentaires, elles sont transmises octet par octet de la même façon par le registre P48. Chaque réception d'octet est confirmée par une interruption 1 d'acknowledge émise par le TMS7041.

-----------------------------------------------------------------------
Envoi d'un octet au TMS7041 (l'octet à envoyer est dans B)
-----------------------------------------------------------------------
F9C6 05        EINT                  active les interruptions
F9C7 768102fc  BTJO   %>81,R2,$F9C7  attente 7041 pret
F9CB 06        DINT                  desactive les interruptions
F9CC b6        XCHB   A              place l'octet a envoyer dans A  
F9CD 8b0130    STA    @>0130         ecriture de l'octet dans P48
F9D0 b6        XCHB   A              remet l'octet dans B            
F9D1 748002    OR     %>80,R2        set FLGCOM bit (attente acknowledge)
F9D4 a40106    ORP    %>01,P6        b0 de P6 a 1 = demande de traitement
F9D7 05        EINT                  active les interruptions
F9D8 0a        RETS   

Dans le sens TMS7041 vers TMS7020, le code de la commande est placé dans le registre P48, puis le TMS7041 envoie une interruption 1 de demande de lecture au TMS7020. Pour différencier cette interruption d'un acknowledge, le bit b0 de P4 est mis à 0. Le TMS7020 accuse réception en mettant le bit b1 de P6 à 1. Si la commande nécessite des données complémentaires, elles sont transmises octet par octet de la même façon par le registre P48, avec interruption 1 de demande de lecture et confirmation de réception par la mise à 1 du bit b1 de P6.

-----------------------------------------------------------------------
Table des adresses de traitement des fonctions de l'IRQ 1
-----------------------------------------------------------------------
FA39 fa33 00=inutilise
FA3B fa66 01=reception code touche clavier/joystick 0
FA3D fa8e 02=reception code touche joystick 1
FA3F f9a4 03=demande 8 octets LPC supplementaires pour le synthetiseur   
FA41 f99e 04=fin d'execution de la synthese vocale  
FA43 fa33 05=inutilise
FA45 fa33 06=inutilise
FA47 fbd2 07=envoi de donnees du 7041 (generateur et logo exelvision)
FA49 fa5f 08=confirmation de l'initialisation du 7041
FA4B fc95 09=information : interface serie prete
FA4D fc9a 10=information : interface serie non prete
FA4F fa51 11=demande d'extinction ecran apres 8 minutes d'inactivite clavier

La synthèse vocale commence par le TRAP 4. Le code commande B9 est envoyé au TMS7041. Il est suivi des 24 premiers octets de la chaîne LPC. Le TMS7041 envoie ces informations au TMS5220, qui commence le processus de décodage et de synthèse à la réception du huitième octet. Le nombre maximum de bits de commande pour une trame est de 50. Avec huit octets il y aura toujours assez de bits pour générer la première trame.

-----------------------------------------------------------------------
TRAP04  Lancement du speech synthetizer
-----------------------------------------------------------------------
F96F 980a08    MOVD   R10,R8       R10=adresse de la chaine de commande
F972 73fd02    AND    %>FD,R2      clear FLGCOM bit 1 (speech en cours)
F975 5209      MOV    %>09,B       B=9 demarrage du synthetiseur
F977 8ef9c6    CALL   $F9C6        envoi commande B9 au TMS7041
F97A 8ef987    CALL   $F987        envoi 8 octets au speech synthetiser 
F97D 8ef987    CALL   $F987        envoi 8 octets au speech synthetiser
F980 740202    OR     %>02,R2      set FLGCOM bit 1 (speech en cours)
F983 8ef987    CALL   $F987        envoi 8 octets au speech synthetiser               
F986 0a        RETS                retour

Dès que le nombre d'octets restant à traiter dans le buffer du TMS5220 devient inférieur à 8, une requête d'octets supplémentaires est émise. Le TMS7041 la répercute au TMS7020 par la commande 03 (demande d'un nouveau buffer de la chaîne de commande LPC). Le TMS7020 envoie alors 8 octets supplémentaires, toujours par l'intermédiaire du TMS7041.

Lorsque le TMS5220 reçoit dans la chaîne de commandes LPC un code énergie 15, c'est la fin de la synthèse vocale. Cette information est transmise au TMS7041, qui émet alors une interruption 1 avec la fonction 04, à destination du TMS7020.

-----------------------------------------------------------------------
Envoi de 8 octets au synthetiseur
-----------------------------------------------------------------------
F987 5208      MOV    %>08,B       compteur de boucles pour huit octets
F989 9a08      LDA    *R8          octet a envoyer lu a l'adresse R8
F98B c8        PUSH   B            empile le compteur de boucles     
F98C c0        MOV    A,B          B=octet a envoyer
F98D 8ef9c6    CALL   $F9C6        envoi octet au 7041
F990 d308      INC    R8           R8 pointe vers octet suivant
F992 790007    ADC    %>00,R7      retenue dans l'octet de pois fort
F995 c9        POP    B            depile le compteur de boucles
F996 caf1      DJNZ   B,$F989      boucle huit fois
F998 0a        RETS                       

3- La création d'un chaîne de commande LPC

Le gros problème des programmeurs de l'EXL100 était l'impossibilité de composer leur propre synthèse vocale. Seuls quelques phonèmes et quelques mots étaient fournis par exelvision et pouvaient être réutilisés. Faute de logiciel de création de chaîne LPC il était impossible d'en créer d'autres. Aujourd'hui cet obstacle a disparu, car le logiciel est disponible sur internet. Il s'appelle QBOXPRO. On peut facilement le trouver en tapant ce nom dans un moteur de recherche. Il est accompagné de deux fichiers d'aide et d'exemples de création de chaînes LPC. Son utilisation n'est pas très simple et nécessite quelques explications complémentaires :

1) C'est un programme 16 bits de conception ancienne, pouvant dérouter les non-initiés. Il n'accepte pas les noms longs pour les répertoires ni pour les fichiers. Le fichier de paramètres QBOXPRO.INI doit être impérativement dans le répertoire d'installation de Windows (en général c:\windows). La fermeture des fenêtres ne se fait pas par un bouton en forme de croix, mais par la fonction Exit du menu. L'installation par défaut est dans C:\QBOX. Ce répertoire peut être modifié dans le fichier .ini, à condition d'utiliser toujours les noms courts style DOS; Par exemple Documents and settings devient DOCUME˜1

2) La table de paramètres QV5220.COD fournie pour le TMS5220 ne correspond pas exactement à celle de l'EXL100. Il est conseillé de la remplacer par une table contenant exactement les paramètres des annexes 3 et 4. On peut la nommer EXL100.COD et remplacer QV5220.COD par EXL100.COD dans qboxpro.ini. Il faut aussi limiter le nombre de coefficients de réflexion à 10 en remplaçant LPCNB=12 par LPCNB=10.

3) Plus grave : le fichier wav en entrée doit être en mono 16 bits 8 kHz. Mais avec 8 kHz le nombre d'échantillons par trame est imposé à 160 par QBOXPRO, alors qu'il est de 200 pour l'EXL100 (trames de 25 ms). J'ai trouvé une solution pas très orthodoxe : dans le fichier .wav 8 kHz, remplacer les octets 24 et 25, initialement à 401F (8000) par 1027 (10000). Ainsi QBOXPRO croit que c'est un fichier à 10 kHz et calcule alors avec 200 échantillons par trame. Si on joue la chaîne LPC dans QBOXPRO, elle est trop aigüe. Elle est rétablie à la bonne vitesse dans l 'EXL100.

Moyennant ces précautions et un peu d'habileté dans le découpage des mots et le réglage des paramètres, il est possible d'obtenir des chaînes LPC produisant des phrases parfaitement compréhensibles si on les joue avec l'EXL100.

qboxpro

Annexes

1- Codes des commandes du TMS5220

Les x sont des bits non significatifs de valeur quelconque. Les a sont des bits désignant une adresse :

x000xxxx : Nop = pas d'action
x001xxxx : Read Byte = lecture octet à l'adresse courante de la ROM externe
x010xxxx : Nop = pas d'action
x011xxxx : Read and Branch = 
x100aaaa : Load Address = modification adresse courante de la ROM externe
x101xxxx : Speak = synthèse vocale à partir des données en ROM
x110xxxx : Speak External = synthèse vocale à partir des données reçues
x111xxxx : Reset = initialisation du synthétiseur

2- Algorithme de décompression de la chaîne de commande LPC

La chaîne de commande LPC est composée de bits. Il n'y a pas d'alignement sur des frontières d'octets. Les bits sont lus dans chaque octet successif en partant du bit de poids faible (b0), jusqu'au bit de poids fort (b7).
Pour chaque trame on lit le code de l'énergie sur 4 bits. Si ce code est 0 (silence) ou 15 (fin de la synthèse vocale) les dix coefficients de réflexion sont mis à zéro. Il n'y a pas d'autres bits à lire pour cette trame.
Sinon on lit l'indicateur de répétition sur 1 bit et le code du pitch (tonalité) sur 6 bits. Si l'indicateur de répétition est à 1 il n'y a pas d'autre bit à lire, les dix coefficients de réflexion sont inchangés.
Sinon on lit les codes des coefficients K1 (5 bits) K2 (5 bits) K3 (4 bits) et K4 (4 bits). Si le pitch est zéro, les coefficients K5 à K10 sont mis à zéro et il n'y a pas d'autres bits à lire pour cette trame.
Sinon on lit les codes des coefficients K5 (4 bits), K6 (4 bits), K7 (4 bits), K8 (3 bits), K9 (3 bits) et K10 (3 bits).
Les valeurs de l'énergie, du pitch et des coefficients de réflexion sont recherchées à partir des codes dans les tables en annexes 3 et 4.

3- Table des valeurs de l'énergie et du pitch (tonalité)

Valeurs de l'énergie codées sur 5 bits de 0 à 31

0, 52, 87, 123, 174, 246, 348, 491, 694, 981, 1385, 1957, 2764, 3904, 5514, 7789

Valeurs du pitch (tonalité) codées sur 6 bits de 0 à 63

 0,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29
30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  44,  46,  48
50,  52,  53,  56,  58,  60,  62,  65,  68,  70,  72,  76,  78,  80,  84,  86
91,  94,  98, 101, 105, 109, 114, 118, 122, 127, 132, 137, 142, 148, 153, 159

4- Table des valeurs des coefficients de réflexion K1 à K10

Valeurs de K1 codées sur 5 bits de 0 à 31

-0.97850, -0.97270, -0.97070, -0.96680, -0.96290, -0.95900, -0.95310, -0.94140
-0.93360, -0.92580, -0.91600, -0.90620, -0.89650, -0.88280, -0.86910, -0.85350
-0.80420, -0.74058, -0.66019, -0.56116, -0.44296, -0.30706, -0.15735, -0.00005
 0.15725,  0.30696,  0.44288,  0.56109,  0.66013,  0.74054,  0.80416,  0.85350

Valeurs de K2 codées sur 5 bits de 0 à 31

-0.64000, -0.58999, -0.53500, -0.47507, -0.41039, -0.34129, -0.26830, -0.19209
-0.11350, -0.03345,  0.04702,  0.12690,  0.20515,  0.28087,  0.35325,  0.42163
 0.48553,  0.54464,  0.59878,  0.64796,  0.69227,  0.73190,  0.76714,  0.79828
 0.82567,  0.84965,  0.87057,  0.88875,  0.90451,  0.91813,  0.92988,  0.98830

Valeurs de K3 codées sur 4 bits de 0 à 15

-0.86000, -0.75467, -0.64933, -0.54400, -0.43867, -0.33333, -0.22800, -0.12267
-0.01733,  0.08800,  0.19333,  0.29867,  0.40400,  0.50933,  0.61467,  0.72000

Valeurs de K4 codées sur 4 bits de 0 à 15

-0.64000, -0.53145, -0.42289, -0.31434, -0.20579, -0.09723,  0.01132,  0.11987
 0.22843,  0.33698,  0.44553,  0.55409,  0.66264,  0.77119,  0.87975,  0.98830

Valeurs de K5 codées sur 4 bits de 0 à 15

-0.64000, -0.54933, -0.45867, -0.36800, -0.27733, -0.18667, -0.09600, -0.00533
 0.08533,  0.17600,  0.26667,  0.35733,  0.44800,  0.53867,  0.62933,  0.72000

Valeurs de K6 codées sur 4 bits de 0 à 15

-0.50000, -0.41333, -0.32667, -0.24000, -0.15333, -0.06667,  0.02000,  0.10667
 0.19333,  0.28000,  0.36667,  0.45333,  0.54000,  0.62667,  0.71333,  0.80000

Valeurs de K7 codées sur 4 bits de 0 à 15

-0.60000, -0.50667, -0.41333, -0.32000, -0.22667, -0.13333, -0.04000,  0.05333
 0.14667,  0.24000,  0.33333,  0.42667,  0.52000,  0.61333,  0.70667,  0.80000

Valeurs de K8 codées sur 3 bits de 0 à 7

-0.50000, -0.31429, -0.12857,  0.05714,  0.24286,  0.42857,  0.61429,  0.80000

Valeurs de K9 codées sur 3 bits de 0 à 7

-0.50000, -0.34286, -0.18571, -0.02857,  0.12857,  0.28571,  0.44286,  0.60000

Valeurs de K10 codées sur 3 bits de 0 à 7

-0.40000, -0.25714, -0.11429,  0.02857,  0.17143,  0.31429,  0.45714,  0.60000

5- Autres tables de la rom du TMS5220

Coefficients d'interpolation pour les huit périodes d'une trame

8,  8,  8,  4,  4,  2,  2,  1

Valeurs de chirp de 0 à 41

 0,  42, -44,  50, -78,  18,  37,  20,   2, -31, -59,   2,  95,  90
 5,  15,  38,  -4, -91, -91, -42, -35, -36,  -4,  37,  43,  34,  33
15,  -1,  -8, -18, -19, -17,  -9, -10,  -6,   0,   3,   2,   1,   0

Biliographie

[1] TMS5220 Voice Synthesis Processor Data Manual, Texas Instruments, June 1981
[2] United States Patent #4335277, Ajay K. Puri, June 15, 1982

Ces ouvrages sont consultables en ligne sur le site dcexel à la page Documentation