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.
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.
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 :
//determination de l'excitation (extrait de dcexel) int excitation; if(old_pitch == 0) excitation = ((rand() & 1)) ? 16 : -16; //unvoiced else excitation = (samplecount > 40) ? 0 : chirp[samplecount]; //voiced if(++samplecount >= pitch) samplecount = 0;Dans les deux cas, le signal est transformé par un filtre en treillis utilisant les dix coefficients de réflexion K1 à K10.
//lattice filter (extrait de dcexel) u[11] = excitation * energy / 256; for(j = 10; j > 0; j--) { u[j] = u[j + 1] - ((k[j] * x[j]) / 100000); x[j + 1] = x[j] + ((k[j] * u[j]) / 100000); } sample = x[1] = u[1];
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
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.
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
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.
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
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
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
[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
© 2009 - Daniel Coulom