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é.
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.
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
Être capable de faire “parler” une application.
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/
$ 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
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