Synthèse vovale

Expression du besoin

Certaines applications ont besoin de communiquer de manière sonore avec l’utilisateur. Ces applications doivent utiliser un système Text To Speech permettant de transformer un message écrit en un message parlé.

Notions de base

La synthèse vocale est une technique informatique de synthèse sonore qui permet de créer de la parole artificielle à partir de n’importe quel texte. Pour obtenir ce résultat, elle s’appuie à la fois sur des techniques de traitement linguistique, notamment pour transformer le texte orthographique en une version phonétique prononçable sans ambiguïté, et sur des techniques de traitement du signal pour transformer cette version phonétique en son numérisé écoutable sur un haut parleur.

Terminologie

Text To Speech
Text To Speech est un système informatique permettant de transformer un texte écrit en un texte parlé.
Phonème
Un phonème est la plus petite unité discrète ou distinctive (c’est-à-dire permettant de distinguer des mots les uns des autres) que l’on puisse isoler par segmentation dans la chaîne parlée. Un phonème est en réalité une entité abstraite, qui peut correspondre à plusieurs sons.
Transcription phonétique
La première opération à réaliser par un logiciel de synthèse vocale est de transcrire le texte, généralement écrit sous une forme orthographique, en une séquence de phonèmes, qui représentent exactement les sons qui doivent être prononcés. La technique classique pour réaliser la transcription phonétique est d’appliquer à la suite de lettres composant le texte une série de règles de réécritures dépendant du contexte.
Formants
La synthèse par formants repose typiquement sur la description des trois premiers formants du spectre de la parole. Chaque formant (maximum du spectre de parole) est classiquement décrit par trois paramètres, sa fréquence (en Hz), son amplitude (en dB) et sa bande passante (en Hz). L’amplitude représente l’intensité du signal à la fréquence du formant tandis que la bande passante représente la largeur du spectre autour du maximum formantique.
Prosodie
La prosodie est l’inflexion, le ton, la tonalité, l’intonation, l’accent, la modulation que nous donnons à notre langage oral en fonction de nos émotions et de l’influence que nous désirons avoir sur nos interlocuteurs. En outre, c’est l’étude des traits phoniques, c’est-à-dire l’étude du rythme (vitesse d’élocution), l’accent et l’intonation.
Intonation
L’intonation constitue l’un des trois éléments de la prosodie, les deux autres paramètres prosodiques étant le rythme et l’intensité. En fait, pour être perçue comme naturelle, la synthèse vocale nécessite d’imiter une prosodie naturelle dans son ensemble. Ceci nécessite de reproduire aussi un rythme naturel, c’est-à-dire une durée naturelle des sons élémentaires (phonèmes). Quant à l’intensité, qui correspond aussi au volume sonore, elle est beaucoup moins critique que l’intonation ou le rythme pour obtenir un rendu naturel. L’intonation se mesure par la fréquence fondamentale de la voix. C’est une fréquence variable au cours du temps correspondant à la fréquence de vibration des cordes vocales pendant l’énonciation de la phrase, et qui s’observe aisément comme la périodicité du signal vocal. Typiquement la fréquence fondamentale d’une voix masculine possède une plage de variation dans la zone des 80 Hz à 150 Hz tandis que celle d’une voix féminine se situera plutôt dans la zone des 140 Hz à 200 Hz.

MBROLA et eSpeak

MBROLA est un algorithme de synthèse vocale. Il ne fait pas directement la transformation de texte en voix. Il traite des fichiers de phonèmes. Une autre application, capable de décomposer du texte en phonème est donc nécessaire. Les voix de mbrola donnent un rendu plus naturel que les voix de espeak (lesquelles sont très “robotiques”), d’où l’intérêt de combiner les deux. La page web du projet MBROLA fournit des bases de données de diphones pour un grand nombre de langues parlées.

Lien MBROLA : tcts.fpms.ac.be

eSpeak est un logiciel open source compact de synthèse vocale fonctionnant sous les systèmes d’exploitation Linux, Windows, Mac OS et d’autres plateformes.

eSpeak utilise les formants comme méthode de synthèse, permettant de fournir un large choix de langues pour une taille réduite. La plupart des développements sur les langues gérées par eSpeak sont basés sur les informations trouvées sur Wikipédia et sur les retours des utilisateurs de langue maternelle. eSpeak est utilisé par des projets comme NVDA (NonVisual Desktop Access), Ubuntu et OLPC, et est également utilisé par Google Traduction.

Lien eSpeak : espeak.sourceforge.net

Ressources

Objectifs

Être capable de faire “parler” une application.

Préparation

Il vous faudra tout d’abord installer espeak :

$ sudo apt-get install espeak libespeak-dev

Il vous faudra ensuite installer mbrola :

$ sudo vim /etc/apt/sources.list 
deb-src http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi

$ sudo apt-get update

$ sudo apt-get build-dep unrar-nonfree

$ sudo apt-get source -b unrar-nonfree

$ sudo dpkg -i unrar*.deb

$ wget http://tcts.fpms.ac.be/synthesis/mbrola/bin/armlinux/mbrola.rar

$ unrar e mbrola.rar

$ sudo mv mbrola /usr/bin

$ sudo chmod 777 /usr/bin/mbrola

$ sudo mkdir /usr/share/mbrola

$ sudo mkdir /usr/share/mbrola/voices

$ wget http://tcts.fpms.ac.be/synthesis/mbrola/dba/fr1/fr1-990204.zip

$ unzip fr1*.zip

$ sudo mv fr1/fr1 /usr/share/mbrola/voices/

Séquence 1 : test de eSpeak et MBROLA

$ espeak -v mb/mb-fr1 "Toto"

$ espeak -X -q -v mb/mb-fr1 "Toto"
Translate 'toto'
  1 t        [t]
  5 _) t     [t]

  1 o        [O]

  1 t        [t]

 22 o (_     [o]
  1 o        [O]

 tOt'o

$ espeak -s 110 -v mb/mb-fr1 "Toto"

$ espeak -v mb/mb-fr1 "Toto mange des bananes" | mbrola /usr/share/mbrola/fr1/fr1 - - | aplay

Séquence 2 : programme de test de eSpeak et MBROLA

Un programme de test :

#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>

using namespace std;

#include "espeak/speak_lib.h"

/* g++ -o test-espeak test-espeak.cpp -lespeak */

void liste()
{
   const espeak_VOICE **voices = NULL;
   espeak_VOICE voice_select;
   const espeak_VOICE *v;
   
   voices = espeak_ListVoices(NULL);
   
   for(int ix=0; (v = voices[ix]) != NULL; ix++)
   {
      cout << "Language shortsign : " << v->languages << endl;
      cout << "Identifier : " << v->identifier << endl;
      cout << "Age : " << v->age << endl;
      cout << "Gender : " << v->gender << endl;
      cout << "Name : " << v->name << endl;
      cout << "Variant : " << v->variant << endl;
      cout << endl;
   }
}

void version()
{
    const char *eSpeakVersionInfo = NULL;
    
    eSpeakVersionInfo = espeak_Info(NULL);
    cout << "SyntheseVocale version : " << eSpeakVersionInfo << endl;
}


int main()
{   
    string texte = "alarme température";
    string voice("mb-fr1"); // ("fr") ou ("fr+f3")
    int speed = 130; // espeakRATE
    int volume = 80; // espeakVOLUME
    int pitch = 40; // espakPITCH
    int range = 60; // espeakRANGE
    int punctuation = 0; // espeakPUNCTUATION
    int gender = 2;
    int samplerate = 22050;
    const char *data_path = NULL; // use default path for espeak-data
    
    version();
   
    samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0);
    //samplerate = espeak_Initialize(AUDIO_OUTPUT_SYNCH_PLAYBACK, 0, data_path, 0);
    cout << "Samplerate : " << samplerate << endl;

    if(espeak_SetVoiceByName(voice.c_str()) != EE_OK)
        cerr << "espeak_SetVoiceByName error !" << endl;
    else
    {
        cout << "Selected language : " << voice << endl;
    }

    cout << "Gender : " << gender << endl;
    if(gender >= 0 && gender <= 2)
    {
        espeak_VOICE *voice_spec = espeak_GetCurrentVoice();
        //memset(voice_spec, 0, sizeof(espeak_VOICE)); // Zero out the voice first
        //voice_spec->languages = "fr";
        //voice_spec->identifier = "mb-fr1";
        voice_spec->gender = gender;
        //voice_spec->age = 25;
        //voice_spec->variant = 1;
        int status = espeak_SetVoiceByProperties(voice_spec);
        //cout << "Status : " << status << endl;
        voice_spec = espeak_GetCurrentVoice();
        //cout << "Language shortsign : " << voice_spec->languages << endl;
        //cout << "Identifier : " << voice_spec->identifier << endl;
        //cout << "Age : " << (int)voice_spec->age << endl;
        //cout << "Gender : " << (int)voice_spec->gender << endl;
        //cout << "Name : " << voice_spec->name << endl;
        //cout << "Variant : " << (int)voice_spec->variant << endl;
        //cout << endl;
    }
      
    cout << "Speed : " << speed << endl;
    if(speed >= 80 && speed <= 450)
    {
      espeak_SetParameter(espeakRATE, speed, 0);
    }
    cout << "Volume : " << volume << endl;
    // volume in range 0-100 (0=silence)
    if(volume >= 0 && volume <= 100)
    {
      espeak_SetParameter(espeakVOLUME, volume, 0);
    }
    cout << "Pitch : " << pitch << endl;
    // base pitch in range 0-100 (50=normal)
    if(pitch >= 0 && pitch <= 100)
    {
      espeak_SetParameter(espeakPITCH, pitch, 0);
    }
    cout << "Range : " << range << endl;
    // pitch range in range 0-100 (0=monotone, 50=normal)
    if(range >= 0 && range <= 100)
    {
      espeak_SetParameter(espeakRANGE, range, 0);
    }
    cout << "Punctuation : " << punctuation << endl;
    // 0 no punctuation, 1 say punctuation
    if(punctuation >= 0 && punctuation <= 1)
    {
      espeak_SetParameter(espeakPUNCTUATION, punctuation, 0);
    }    

    cout << "-- " << texte << endl;
    espeak_Synth((char *)texte.c_str(), texte.length()+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);
    espeak_Synchronize(); // appel bloquant
   
    return 0;
}

Pour fabriquer ce programme de test (ajout de -lespeak à l’édition de liens), il vous faudra utiliser ce fichier Makefile :

CXX=g++

GENERIC_CFLAGS := -fpermissive
GENERIC_LIBS := -lespeak

TARGET=test-espeak

HEADERFILES := $(wildcard *.h)
SRCFILES    := $(wildcard *.cpp)
OBJFILES    := $(patsubst %.cpp, %.o, $(SRCFILES))

.PHONY: clean $(TARGET)

all: $(TARGET)

%.o: %.cpp %.h
    $(CXX) -o $@ -c $< $(GENERIC_CFLAGS)

$(TARGET): $(OBJFILES)
    $(CXX) -o $(TARGET) $^ $(GENERIC_CFLAGS) $(GENERIC_LIBS)

clean: 
    rm -f $(TARGET) $(OBJFILES) *~

Code source : test-mo-espeak.zip

Voir aussi : activite-classe-synthese-vocale.html

Retour au sommaire