Parole

Annexe technique · Accueil · English

La parole est faite d'enregistrements mis bout à bout, pas d'un signal synthétisé : une seule voix, découpée en fragments de phonèmes et de transitions, est réassemblée à partir de suites de phonèmes. Il n'y a aucun code de conversion texte-phonèmes dans le jeu : chaque réplique a été convertie à l'avance et stockée. tools/maup_speech.py porte le moteur et ajoute un traitement du français, écrit pour ce projet, afin de pouvoir dire n'importe quel texte.

python3 -I tools/maup_speech.py "Je vous attendais." -o out.wav [--voice male]
python3 -I tools/maup_speech.py --phrase 1 -o out.wav
python3 -I tools/maup_speech.py --phonemes "ZetEEdAA" -o out.wav

Échantillons

Son Source
La réplique du jeu « J'étais dans ma chambre. » Phrase 1, stockée dans le jeu
La même réplique produite par les règles du français Texte, via text_to_phonemes
Une nouvelle phrase, voix rapide Texte absent du jeu
La même phrase, voix lente Texte absent du jeu

Jusqu'où chaque partie est vérifiée

Partie État
Script de fragments (compile_words) Identique au code de maup.exe dans un émulateur sur 449 phrases sur 450 ; l'autre est la particularité décrite sous « Pilote »
Décodage audio (render_script) Mêmes échantillons que le lecteur Sound Blaster du jeu dans un émulateur, sur les 450 phrases
Fréquence d'échantillonnage Lue dans le code (diviseur PIT), pas mesurée
Durée des pauses Estimée : le jeu utilise des boucles d'attente dépendantes du processeur
Traitement du français Pas dans le jeu : écrit pour ce projet. 95,2 % des phonèmes concordent avec les 450 phrases du jeu, et les durées de phrases sont corrélées à 0,997. Ces phrases ont aussi servi à le régler, donc un texte nouveau fera moins bien
Sortie réelle du jeu Pas comparée à un enregistrement du jeu en marche

Lancez python3 -I tools/verify_speech.py pour refaire les contrôles dans l'émulateur (environ 90 s, nécessite unicorn).

Données

Les deux enregistrements sont dans G4.CON.

Enregistrement 0x2C, phrases. 460 décalages gros-boutiens relatifs à 0x398, puis des mots. La phrase n est la chaîne n de la classe 5 : le dialogue. 450 sont utilisées. Chaque mot :

Bits Signification
15-12 durée, le seul champ utilisé par le pilote
11-6 deux champs de 3 bits que le pilote lit sans jamais s'en servir, peut-être restes d'une autre version
5-0 phonème
Codes Phonèmes (nom ASCII de l'outil)
00-0D i, é e, è E, a, (04 inutilisé), o ouvert O, o, ou u, u y, eu 2, schwa @, in I, an A, on U
16-25 p b m f v t d n s z l, ch S, j Z, k g r
2D-30 yod j, w, u de « lui » H, gn N
3C, 3D, 3E pause courte, pause longue, hiatus sans pause

Les libellés ont été déduits du texte aligné ; le pilote ne connaît que les numéros. Les codes 0E-15 sont gérés par le pilote, mais aucune phrase ne les utilise.

Enregistrement 0x2B, échantillons. Des tables de mots gros-boutiens, puis l'audio en 0x508 :

Décalage Entrées Utilisé par l'opération du script
0x000 22 entrées de voyelles de 6 octets, avec 4 limites partageant la première de l'entrée suivante 0
0x086 ensemble de consonnes 1 2
0x15A ensemble de consonnes 2 6
0x22E transitions : (vowel + consonant * 14), 2 octets chacune 4

Pilote

Le service INT 0FEh 0x1E = EA 0x166ED est appelé une seule fois, depuis MAUPITI1 EA 0x1191B, avec la phrase, le personnage et les deux enregistrements.

  1. Compilation, EA 0x167D8. Une fenêtre de trois phonèmes (précédent, actuel, suivant) produit un script de triplets (op, a, b) : quel fragment de quelle table. La classe du phonème vient du code et de la table DS:F72 ; DS:FA6 et DS:F8C choisissent des variantes selon la voyelle voisine.
  2. Lecture du script, EA 0x1605E, qui traduit chaque triplet en plage d'échantillons.
  3. Lecture audio. Le timer 0 est reprogrammé à la fréquence d'échantillonnage, avec un échantillon par interruption. Trois sorties : PWM sur le haut-parleur du PC (EA 0x16245), DAC direct de la Sound Blaster, commande DSP 0x10 (EA 0x163C6), et port 0x389 (EA 0x1654B).

Décodage. Chaque octet donne deux échantillons, le quartet haut d'abord. Un échantillon ajoute la table DS:1212 au précédent, modulo 256, en partant de 0x80 dans chaque fragment : -36 -28 -21 -15 -10 -6 -3 -1 0 1 3 6 10 15 21 28.

Voix. Il n'y a qu'un seul jeu d'enregistrements. La hauteur ne vient que de la vitesse de lecture. La table de sélection en MAUPITI1 EA 0x11864 a neuf entrées, qui semblent être les neuf personnages dans leur ordre habituel (déduit) :

Personnages Sélecteur Diviseur PIT Fréquence
Maguy, Sue, Anita au-dessus de 0 0x50 14 915 Hz
Roy, Bruce, Anton, Chris, Bob, Juste 0 ou moins 0x59 13 407 Hz

Avec une Sound Blaster, les deux deviennent 0x6E quand le test de vitesse près de EA 0x1738C donne moins de 12 (déduit : une machine lente).

Particularité. La boucle de compilation compare les décalages comme des nombres signés, donc la phrase 368 (« Tu as besoin de moi, biquet? »), qui franchit le décalage 0x8000, s'arrête après son premier phonème dans le code émulé. Probablement aussi dans le jeu. L'outil joue la phrase entière. Le portage conserve aussi un enchaînement en EA 0x16C74 qui ressemble à un bogue : il ignore la voyelle suivante pour choisir une variante de consonne.

Le traitement du français

text_to_phonemes applique une liste d'exceptions et des règles ordonnées sur les lettres, puis la liaison, la chute du schwa et les habitudes du jeu (je dévoisé devant une consonne sourde, n + yod écrit gn). phonemes_to_words ajoute les durées : paires de voyelles longues devant une pause, voyelles courtes ailleurs, et la durée la plus fréquente pour chaque consonne.

Limites connues : l'orthographe française est irrégulière, donc les mots inhabituels seront faux ; les terminaisons verbales en -ent ne sont reconnues qu'après un pronom sujet ; et il n'y a pas d'intonation, comme dans le jeu lui-même. Pour une prononciation exacte, utilisez --phonemes.

Précédent : Texte et polices · Suivant : Noms · Annexe technique · Accueil