: permet le balisage du texte comme paragraphe ou phrase
: nécessaire dans la balise pour indiquer le type de structure
Voix
: élément vide qui marque le changement d'un élément de la voix
: optionnel, change le genre de la voix (female, male, neutral)
: optionnel, indique l'age de la voix (child, teenager, adult,...)
< variant> : optionnel, indique une variante des autres caractéristiques de la voix afin de prononcer le texte
: optionnel, indique une voix précise présente dans le moteur
Construction du texte
< sayas> : précise l'interprétation de l'élément qui suit
< class> : nécessaire dans la balise sayas pour indiquer le format du texte
: la chaîne suivante est un nombre
: la chaîne suivante est une heure
: la chaîne suivante est un nom propre
: la chaîne suivante est un numéro de téléphone
: la chaîne suivante est un e-mail
: la chaîne suivante est une adresse
: la chaîne suivante est une devise
: la chaîne suivante est une mesure
: la chaîne suivante est un entier, une fraction ou un réel
Prononciation
< phoneme> : contient une chaîne de caractères qui sera considérée comme un phonème
< original> : optionnel, représente la chaîne de caractères à laquelle se rapporte le phonème
Intonation
< emphasis> : spécifie le niveau de l'emphase
< level> : optionnel, indique le niveau de l'emphase
Temps de Pause
< break> : élément vide qui marque une pause sur la sortie audio
< size> : optionnel, prend ses valeurs dans ("none", "small", "medium" (default value), ou "large")
: optionnel, indique le temps de pause
Hauteur de la voix
: spécifie les informations prosodiques
: optionnel, spécifie le taux de mots à la minute
: optionnel, spécifie le niveau sonore de la sortie sur une échelle entre 0 et 1
: optionnel, spécifie la hauteur, en Hertz, de la voix
: optionnel, spécifie le taux de variation du pitch
Propriétés de contrôle
: permet l'inclusion d'un moteur TTS spécifique
: identifie la voix du synthétiseur
: nécessite des attributs ayant une valeur d’information pour le synthétiseur
Exemples de fichier
Testing the
sayas
tag.
1234
1 2 3 4
4/3/01
12:34am
This will be replaced
This is fast and high-pitched and
this
is emphatic
This is slower, lower and quieter,
and here comes a large marked pause
and another
test marker which you can detect with a SpeakableListener.
Le développement
A l’aide des outils expliqués ci dessus, nous avons pu programmer notre application. Cette programmation s’est faite en deux étapes successives. Il a tout d’abord fallu transformer le fichier qui devait être « prononcé » au format JSML puis le synthétiser.
Modification du fichier d’entrée
La phase d’analyse de fichier xml crée un fichier appelé .res. Ce fichier est composé de phrases (interprétation lors de l’analyse) et de balises JSML. Pour que ces balises soient correctement interprétées, le texte doit être délimité par des tags spécifiques de début et de fin d’un document JSML soit et . En l’absence de ces balises, le fichier est considéré comme un fichier texte et toutes celles contenues dans le fichier seront considérées comme des caractères et des mots quelconques. Par exemple, la balise servant à modifier la voix du narrateur en une voix masculine sera lue normalement si le texte n’est pas encapsulé dans les bons tags. Dans le cas où le fichier ne contient aucune balise JSML, c’est à dire dans le cas où c’est un texte simple, l’ajout des délimiteurs ne modifiera en rien sa lecture. La voix utilisée sera celle définie par défaut et ne sera pas modifiée.
Le résultat de cette transformation sera analysé et lu par le moteur TTS. Il était donc indispensable de stocker ce résultat pour qu’il puisse être récupéré par le moteur. Deux choix se présentaient alors :
soit le stockage sous forme de fichier
soit le stockage dans un objet Java
Dans le premier cas, il suffisait de créer un nouveau fichier, d’y copier les informations c’est à dire tag ouvrant puis le contenu du ficher « .res » et enfin le tag fermant.
Dans le deuxième cas, il fallait créer un objet « String » et y concaténer les informations. La première solution semblait la plus naturelle mais elle impliquait une utilisation du disque puis un accès à celui ci lorsqu’il aurait fallu ouvrir le fichier. De plus, ce fichier n’étant que temporaire, il nous semblait inutile d’en garder une trace. Nous avons donc opté pour la seconde solution qui ne consiste qu’à stocker le fichier dans une variable dans le même format qu’une chaîne de caractères. Cette variable est ensuite passée en paramètre de la fonction de synthèse vocale.
Synthèse Vocale
Une fois que le fichier se trouve dans le bon format, il ne reste plus qu’à le passer à la synthèse vocale pour qu’il puisse être analysé puis parlé.
Cette synthèse se fait grâce à un synthétiseur préalablement initialisé. Cette initialisation est fonction à la fois de la distribution du moteur choisi mais aussi de la variable ‘Locale’ du système. Nous pensions que la langue utilisée pour écouter les fichiers XML était la langue du pays dans lequel l’utilisateur se trouvait, représentée par la variable Locale. Or, l’utilisateur doit pouvoir lire des fichiers en anglais alors que sa Locale est « France ». Nous lui avons donné cette possibilité en lui faisant modifier, s’il le désire, sa variable Locale.
L’initialisation du synthétiseur devrait normalement se faire dans un premier temps sur le moteur puis sur la variable Locale. Cet ordre de sélection n’est pas possible car nous ne possédons pas toutes les langues sur la SAPI5.
En effet, si la SAPI5 avait été disponible en français, lors de l’initialisation, nous aurions d’abord sélectionné le moteur puis, selon la variable Locale, les voix correspondantes. Or, la SAPI5 avec une variable Locale France n’existe pas encore, donc, pour le moment, nous faisons notre choix sur la variable Locale. Si celle-ci est France, le moteur choisi sera la SAPI4 sinon, ce sera la SAPI5.
De plus, certains moteurs, n’apparaissant pas dans notre application, possèdent leur variable Locale à une certaine valeur mais proposent des voix de nationalités différentes. Or, lors du chargement du moteur, le synthétiseur récupère toutes les voix disponibles dans le moteur. Ce cas de figure ne nous satisfaisant pas, nous avons choisi des moteurs qui à une instance de la variable locale correspondent une seule nationalité de voix.
Une fois le synthétiseur initialisé, il doit être alloué et mis en attente. Cette attente s’arrête lorsqu’on lui demande de dire une chaîne de caractères ou un fichier. Une fois le discours prononcé, le synthétiseur se remet en attente d’un nouveau signal.
Cette période d’attente / discours prend faire lors de la désallocation du synthétiseur.
Nous allons maintenant passer à l’étude du portage vers le Pocket PC.
Etude du Portage vers Pocket PC
Alors que le développement du Parser XML et de l'application TextToSpeech en Java se poursuivait, deux membres du groupe de projet se sont tournés vers l'étude de la portabilité sur Pocket PC, afin de se familiariser avec les environnements de développement et les différentes solutions disponibles.
Nous nous sommes donc procurés auprès de M. Tigli un des IPAQ Compaq disponibles à l'ESSI, doté d'un processeur ARM, de 32 Mo de mémoire et du système d'exploitation Windows CE 3.0. Les différentes recherches que nous avions effectuées nous ont permis de nous poser directement les bonnes questions :
Quelle(s) API(s) de TextToSpeech pouvaient tourner correctement sous Windows CE 3.0 ?
Quel langage était le plus approprié pour porter l'application ?
Les solutions envisagées permettraient-elles de répondre entièrement au cahier des charges ?
Outils de travail
L'environnement Java
Le développement ayant débuté en Java, il nous fallait installer un environnement sur le Pocket PC afin de faire tourner l'application finale. Après une étude comparative des différents environnements JAVA existant, notre choix s'est porté sur Jeode.
Les différents environnements Java pour Pocket PC :
Jeode ne permet pas d'utiliser les classes des packages Swing pour le développement d'interfaces graphiques, mais cela ne constituait pas une priorité pour le projet.
Après l'installation, une nouvelle application est disponible sur le Pocket PC : la console EVM. Celle ci permet d'exécuter un programme Java, l'utilisateur ayant seulement besoin de lancer le programme puis de saisir le nom de la classe à exécuter.
Seuls les fichiers .class doivent se trouver sur le PC, puisque Jeode ne permet pas la compilation, en effet il ne s’agit « que » d’une JRE (Java Runtime Environment). En effet toute la partie développement ce fait sur un ordinateur personnel.
Les différentes options d'exécution Java peuvent être précisées dans le raccourci qui permet d'exécuter EVM :
Classpath : -cp
Mode verbose : -v
Propriétés : -D
Aide : -h
…
Par exemple, pour éviter que la console ne se ferme après chaque exécution, il faut lancer le programme avec l’option :
-Djeode.evm.console.local.keep=TRUE
Le répertoire de travail pris en compte par EVM est le répertoire racine du Pocket PC. Pour exécuter d'autres applications, il faut donc préciser le chemin complet du fichier .class dans la ligne de commande, ou définir un Classpath ( avec la commande –cp ).
Pour une documentation plus complète sur Jeode, nous nous sommes référés à cette page : HYPERLINK "http://www.cs.unc.edu/~lindsey/7ds/notes/jeode/" http://www.cs.unc.edu/~lindsey/7ds/notes/jeode/
L'API TextToSpeech
Une fois Jeode installé et testé avec différents programmes Java plus ou moins complexes (utilisation d'archives .jar dans différents répertoires) afin de voir comment les différentes options étaient gérées, nous avons pu rechercher une API de TextToSpeech et un moteur qui soient compatibles avec Windows CE 3.0.
Etant donné que le développement Java de l'application TextToSpeech était bien avancé, nous avons décidé de rechercher une API Java qui fonctionnerait sur Pocket PC. Malheureusement, après des recherches plutôt longues nous nous sommes aperçus que les API dont nous disposions étaient trop volumineuses pour le Pocket PC. De plus, il nous fallait un moteur TextToSpeech.
Le site de Microsoft a permis de cerner un peu mieux le problème de la synthèse vocale sous Windows CE. Windows CE ne dispose que de la SAPI 3.0.
Pour installer la SAPI 5.0, il faut faire la mise à jour Windows .NET (qui est payante).
Après quelques temps, nous avons trouvé sur le site de Elan un SDK pour Windows CE 3.0 (et .NET) qui permettait de développer une application TextToSpeech sur Pocket PC. Une documentation permettait de développer sa propre application en C++ / Win32.
En raison du peu d'espace de stockage disponible sur le Pocket PC, une seule langue peut être installée à la fois (durant toute notre phase de développement, il s'agissait du Français), en effet chaque langue nécessite 5 Mo afin de s’installer. Cette installation permet d'obtenir deux modèles de voix, masculin et féminin.
Le SDK développé par Elan l’a été en tenant comptes des spécifications de la SAPI 4.0 de Microsoft, bien que Windows CE ne supporte pas cette API. Ce choix permet de créer des applications compatibles avec les autres programmes fonctionnant sous Windows.
Caractéristiques de la SAPI
La SAPI utilise l’interface COM qui est supportée par Windows CE.
Les spécifications de la SAPI définissent trois types de composants pour le Text To Speech :
Le composant « Voice Text » permet à l’application d’utiliser la synthèse vocale intégrée sur la machine depuis une interface de haut niveau.
Le composant « DirectTextToSpeech » permet à l’application d’attaquer le moteur de TextToSpeech directement à partir d’une interface de bas niveau.
Le composant Audio gère le son généré par le moteur.
Le composant VoiceText ne peut pas être utilisé dans notre cas : il nécessite une interface logicielle entre le moteur et l’application, application fournie par Microsoft.
Le composant DirectTextToSpeech définit trois types d’objets COM :
Engine object : cet objet représente un certain mode d’opération pour le TTS (selon différentes propriétés : une langue, une voix, un encodage audio, un échantillonnage)
Engine enumerator : cet objet permet d’obtenir une énumération des engine object pour une mode de synthèse donné et permet la sélection d’un mode particulier ainsi que la création de l’objet correspondant.
TextToSpeech enumerator : cet objet fonctionne de la même manière que l’objet engine enumerator en appelant ce dernier pour chaque mode de synthèse disponible.
Dans un système SAPI complet, l’application choisit le mode de synthèse en faisant appel au TextToSpeech enumerator fourni par Microsoft. Dans notre cas, l’application doit s’adresser à l’objet énumérateur d’Elan TTS.
Le composant Audio permet de connecter une sortie audio à un moteur (sortie multimédia, fichier…). Microsoft fournit un ensemble de composants audio. Les fournisseurs de l’application et du moteur TextToSpeech sont libres de fournir leurs propres composants audio.
Le moteur d’Elan propose deux types de composants audio pour Windows CE :
la sortie vers un fichier développée par Elan, que nous n’utilisons pas dans notre application.
une sortie multimédia (son) obtenue en recompilant pour Windows CE la sortie multimédia fournie par Microsoft dans le SDK pour sa SAPI.
Toutes les interfaces liées à ces objets sont définies dans le fichier speech.h. Ce fichier est disponible pour la version 2.10 de Windows CE (cette version avait été développée pour AutoPC embarqué et offre une synthèse vocale basée sur la SAPI). Cette version de speech.h a été utilisée pour compiler le moteur de synthèse d’Elan sous Windows CE 3.0.
L’application que nous avons écrite à partir des exemples de code source fournis avec le moteur d’Elan ne représente qu’une possibilité d’implémentation du TextToSpeech sous Pocket PC en utilisant le moteur d’Elan. Plusieurs fonctionnalités n’ont pas été utilisées.
Programmer une application en utilisant SAPI
Une application typique reposant sur la SAPI de Microsoft utilise trois types d’objets :
L’application doit choisir la sortie vers laquelle sera redirigée la voix. Cela se fait en créant un audio destination object vers lequel le moteur enverra les données audio.
L’application crée un objet engine enumerator. Elle utilise l’interface ITTSEnum pour obtenir une description des différentes voix installées sur le système. Dans notre cas, l’espace de stockage du Pocket PC ne permettant pas l’installation de plusieurs voix, notre application choisit la seule voix disponible (voix féminine en français). L’application peut utiliser la liste renvoyée par l’énumérateur pour présenter à l’utilisateur les voix disponibles sous forme de liste. Le moteur peut alors être choisi en utilisant la structure TTSModeInfo, qui procure des informations détaillées sur le mode de synthèse utilisé par un moteur donné. Ceci permet également d’obtenir la GUID qui est nécessaire pour l’étape suivante.
L’application passe ensuite l’identifiant (GUID) de la voix choisie ainsi que l’objet audio destination à l’engine enumerator en appelant la méthode select(). Ceci entraîne la création d’un objet engine.
L’objet engine négocie ensuite un format audio en accord avec l’objet audio de destination.
L’application est prête à utiliser les fonctions TextToSpeech fournies par les interfaces de l’objet engine.
L’application peut utiliser une interface de notification (ITTSNotifySink) afin d’être informée des changements de statuts globaux du comportement du TextToSpeech, par exemple « prononciation en cours ».
L’objet engine est alors prêt à accepter et mettre en queue plusieurs champs de texte depuis l’application pour ensuite les synthétiser vers l’objet de destination audio.
Chaque texte envoyé au moteur peut être associé à un objet de notification (ITTSBufNotifySink) créé par l’application et auquel le moteur peut envoyer différentes informations comme le mot prononcé à l’instant t.
Tutorial de programmation
Ce tutorial a pour but d'exposer les principales étapes de création d'une application de synthèse vocale reposant sur le moteur TextToSpeech d'Elan et le SDK fourni. Le code source de l'application que nous avons réalisée constitue un bon exemple de développement (même s'il est sans doute perfectible…).
Pour implémenter les fonctionnalités TextToSpeech, il faut tout d’abord initialiser les librairies OLE en utilisant la fonction CoInitializex.
Créer une instance d’un ADO (Audio Destination Object) utilisé pour la sortie du son généré par le moteur.
Sélectionner un moteur dans la liste des moteurs disponibles (ou en choisir un par défaut dans le cas de notre application) grâce à l’objet engine enumerator. La structure TTSMODEINFO est utilisée pour spécifier le moteur que l’on désire charger.
Créer une instance d’un buffer de notification (ITTSBufNotifySink) utilisée par le moteur pour avertir l’application des évènements liés aux buffers de texte.
Créer une instance d’un objet de notification (ITTSNotifySink) utilisé par le moteur pour avertir l’application des changements d’états dans la synthèse vocale.
Envoyer un texte au moteur à travers l’objet engine.
Récupérer et traiter les évènements des objets ITTSBufNotifySink et ITTSNotifySink.
Une application SAPI peut être avertie des changements d’état par deux objets distincts de notification :
ITTSNotifySink
ITTSBufNotifySink
Ces interfaces doivent être supportées par l’application et utilisées par le moteur TextToSpeech. Le nom des méthodes supportées par ces interfaces est fourni par Microsoft et ne peut pas être modifié.
L'environnement de développement
Pour développer cette application, il nous fallait installer Embedded Visual Tools, équivalent de Visual C++ pour le développement sur Pocket PC. La version 4.0 de Embedded Visual Tools étant exclusivement dédiée au développement vers plate-forme .NET, il faut donc installer la version 3, qui elle est prévue pour développer des applications pour WindowsCE.
Nous avons également essayé d'installer différents émulateurs Pocket PC fournis par Microsoft afin de développer sur une seule machine sans avoir à transférer les données sur l'IPAQ, mais cette solution a vite montré ses limites, d’autant plus qu’il ne s’agit que d’un émulateur et que le fonctionnement d’un programme sur un émulateur peut différer de celui tournant sur une vraie machine.
Phase de développement
Le programme Win32
En nous aidant de la documentation technique dont nous disposions et du code source qui était fourni avec le moteur de TextToSpeech d'Elan, nous avons pu développer notre propre application qui utilise le moteur Pocket Speech d'Elan.
Cette application permet à l'utilisateur de saisir n'importe quel texte qui sera prononcé par le moteur TextToSpeech. Il faut tout d'abord initialiser l'application, ce qui entraîne la sélection du moteur et le chargement de la voix. Ensuite, le bouton "Charger" permet de créer une phrase par défaut qui sera affichée puis prononcée lorsque l'utilisateur appuie sur le bouton "Dire". En effet, pour un utilisateur novice, il n’est pas très aisé de taper du texte sur un Pocket PC. Cette fonctionnalité est une fonction de confort très utile pour faire une démonstration rapide du fonctionnement du programme.
Les parties principales du code de l'application sont fournies en annexe.
Intégration du code Win32 dans l'application finale
Après la réalisation de l'application graphique pour le Pocket PC en Win32, il était nécessaire de pouvoir intégrer le code dans le but de pouvoir l'utiliser avec les composants Java développées pour les autres parties du projet. La meilleure solution pour implémenter cette fonctionnalité était de créer une classe Java et d'utiliser JNI pour utiliser les fonctions C++ (natives) se trouvant dans une DLL.
Nous avons donc repris le code de l'application pour créer une DLL pour Windows CE avec Embedded Visual Tools.
Création de la classe Java
Le modèle décidé pour implémenter la chaîne de traitement, en prenant en compte la DLL pour Windows CE, est le suivant :
En nous appuyant sur ce schéma, nous avons donc créé une classe TTSDriver, chargée d'assurer le rôle d'interface avec la DLL.
Etant donné que nous disposions déjà d'une application graphique qui fonctionnait sous Pocket PC, nous savions comment serait organisée la DLL et nous avions déjà une idée à propos de l’implémentation la classe Java.
Celle-ci doit comporter trois déclarations de fonctions natives, dont le code sera inclus dans le fichier .cpp qui génèrera la DLL. Les trois fonctions sont celles indispensables à la lecture d'un texte à haute voix : init(), speak( String ) et quit(). Le rôle de ces fonctions sera détaillé plus tard lors de l'explication de la création de la DLL.
De plus, la classe TTSDriver doit charger la librairie, ce qui se fait avec le code suivant :
static {
System.loadLibrary("hello");
}
En dehors de ces fonctions, la classe TTSDriver ne doit comporter qu'une méthode main() qui permet de faire appel aux fonctions de la DLL. Le code contenu dans la méthode main instancie un objet de type TTSDriver et appelle dans l'ordre les trois fonctions citées ci-dessus.
Le listing de la classe Java est fourni en annexe.
Génération du fichier .h
Après compilation du fichier java pour obtenir une classe TTSDriver, il faut utiliser la commande javah pour générer un fichier TTSDriver.h qui contient les prototypes des fonctions déclarées natives.
%> javah TTSDriver
Le listing de ce header est fourni en annexe.
Création du fichier .cpp
Il faut ensuite créer un fichier .cpp qui contient le corps des fonctions déclarées dans TTSDriver.h.
Le code de ce fichier a donc la structure suivante :
#include "jni.h"
#include "TTS_Driver.h"
/* ici se trouvent les include propres au code C++ de l'application */
JNIExport void JNICALL Java_TTSDriver_init (JNIEnv *env, jobject jo) { }
JNIExport void JNICALL Java_TTSDriver_speak (JNIEnv *env, jobject jo, jstring textToSpeak ) { }
JNIExport void JNICALL Java_TTSDriver_quit (JNIEnv *env, jobject jo) { }
Création de la DLL
Cette étape se déroule sous Embedded Visual C++ exactement comme sous Visual C++. Lors de la création d'un nouveau projet, il suffit de sélectionner "Win CE Dynamic Link Library", en ayant choisi le bon type de processeur (ARM dans notre cas).
Une fois le projet créé, il faut ajouter les fichiers sources ainsi que les headers (fichiers .h) dans l'onglet Fileview.
En ce qui concerne la DLL que nous devions développer, plusieurs fichiers devaient être modifiés puisque nous avions comme base le code source d'une application graphique.
L'onglet "Ressources" permet de supprimer tout ce qui est lié à l'interface graphique proprement dite : fenêtre, boîte de dialogue, boutons. Il faut ensuite retirer du code les éléments exclusivement liés aux composants graphiques.
Nous avons conservé les fonctions principales de l'application qui interagissaient avec les éléments système et audio. Ainsi, nous obtenions un fichier .cpp sans fonction WinMain() mais qui disposait des trois fonctions utiles pour lire un texte à voix haute : init(), qui permet de sélectionner le bon moteur TextToSpeech et la bonne voix, speak(TCHAR *texte, UINT taille) qui prononce le texte passé en paramètres et quit() qui s'occupe de libérer correctement les ressources et la mémoire utilisée par l'application.
Le corps de ces fonctions, ainsi que les déclarations de variables globales, de même que les include, doivent être reportées dans le fichier TTSDrive.cpp qui a été généré dans l'étape précédente.
Il faut ensuite compiler, toujours sous Embedded Visual C++, en prenant garde de fixer les bonnes options :
Plate-forme : Pocket PC
ARM Release
Concernant le choix de "Release", il est également possible d'utiliser une compilation en précisant "Debug" pour cette propriété. Malheureusement, nous avons manqué de temps pour tester cette fonctionnalité lors de notre développement.
Une fois cela terminé, nous disposons dans le répertoire de projet (ici, …\TTSDriver\) d'un fichier TTSDriver.dll. Il faut donc copier ce fichier sur le Pocket PC, dans le même répertoire que TTSDriver.class, puis lancer l'exécution de ce dernier sous EVM de Jeode.
Exécution du programme et Problèmes rencontrés
Lors des premières exécutions, le programme se lançait et chargeait correctement la librairie mais la prononciation du texte ne fonctionnait pas et EVM ne quittait pas l'application. Notre manque de maîtrise du fonctionnement des DLL sur Windows CE ne nous a pas permis de résoudre tous nos problèmes rapidement, et encore maintenant cette partie ne fonctionne pas suffisamment pour faire partie de l'application générale.
Actuellement, nos difficultés se décomposent en deux parties :
L'application rend la main tout de suite après avoir initialisé et la prononciation ne se fait pas. Pour remédier à cela, nous avons rajouté une instruction avant d'appeler la fonction quit(). Cela permet d'entendre que le programme prononce effectivement le texte, mais l'application n'est plus quittée et doit être terminée.
La gestion des variables JNI de type jstring ne se fait pas de la même manière que ce que nous avions déjà rencontré lors de nos précédents essais de programmation en utilisant JNI sur PC. Théoriquement, l'accès aux chaînes de caractères Java depuis une fonction native se fait grâce à un code similaire à celui-ci :
JNIEXPORT jstring JNICALL
Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring mystring)
{
char buf[128];
const char *str = (*env)->GetStringUTFChars(env, mystring, 0);
// Traitement de la chaîne
(*env)->ReleaseStringUTFChars(env, prompt, str);
...
Or, il semble que la librairie jni.h fournie avec Embedded Visual C++ ne définisse pas de la même manière les fonctions qui permettent de traiter les chaînes.
Toujours est-il que lorsque le programme parvient à faire prononcer du texte, il ne peut s'agir que de texte que nous avons implémenté dans la fonction, et non une chaîne résultant du traitement du paramètre passé par le programme Java.
Les listings sont fournis en annexe.
Le JavaBean
A terme, il aurait été intéressant de fournir notre application sous la forme de JavaBean, ce qui permet de l'intégrer plus facilement à d'autres applications. Etant donné que nous n'avons pas pu poursuivre jusqu'au bout le développement, nous n'avons pas réalisé cette phase de travail, mais nous disposons tout de même d'éléments utiles pour cette étape.
Rendre toutes les classes Java utilisées (l'application principale, le parser XML, l'interface permettant d'accéder à la DLL) compatibles avec JavaBean : elles doivent posséder un constructeur par défaut (sans paramètres) ainsi que des accesseurs en lecture et en écriture pour chacune de leurs variables.
Créer des classes Info afin de fournir les informations les plus détaillées possibles à la classe Introspector de JavaBean. Le but étant de permettre à des composants extérieurs de connaître le maximum de renseignements sur les composants utilisés dans l'application TextToSpeech.
Tutorial :
Afin de pouvoir lancer le programme de démonstration, il faut au préalable installer une série de programmes ( sur le Pocket PC et aussi sur le PC )
PC :
Active Sync ( pour lier le Pocket PC au PC )
Embeded Tools ( serial, mise a jour du Service Pack, Install d’un SDK, … à )
Pocket PC:
Il faut installer deux programmes sur le Pocket PC ( dans notre cas le Java n’est pas nécessaire, car nous n’avons pas eu le temps de développer la :
- Jeode : Machine Virtuelle Java ( installation lancé a à partir du PC ).
- Elan ( transférer les fichier sur le Pocket PC et les lancer : minimum : le moteur et une voix. )
Installation de Jeode :
Il faut lancer l’installation de Jeode sur le PC.
Il faut au préalable avoir lancé Active Sync et branché le Pocket PC ( allumé ).
Lorsqu’on lance le programme d’installation, on nous demande quelle langue on veut utiliser pour l’installation. Ici on choisit le français.
Un programme d’installation se lance :
Il va copier des fichiers sur le disque dur du PC avant de lancer l’installation de Jeode sur le Pocket PC :
Ensuite il lance l’installation du programme sur le Pocket PC :
Dans un premier temps, le programme d’installation copie les fichiers sur le Pocket PC :
Puis il installe le programme sur le Pocket PC :
A la fin de l’installation, le répertoire « Program Files » doit contenir un répertoire Jeode qui contient un exécutable EVM ( Embeded Virtual Machine ).
Il s’agit de la Machine Virtuelle Java pour le Pocket PC.
Quand on lance l’exécutable on obtient une console avec une invite qui permet de passer les paramètres souhaités à l’interpréteur Java.
Par exemple : Hello ( pour que cela marche il faut bien sur que le fichier Hello.class se trouve dans le répertoire racine du Pocket PC ).
Sur le PC, un message nous demande de vérifier que tout s’est bien passé.
Il suffit juste de cliquer sur le bouton « OK » pour achever l’installation de Jéode.
L’installation de la Machine Virtuelle Java est alors terminée, il faut maintenant installer le moteur de Synthèse Vocale.
Installation d’ELAN :
Pour cela, il faut copier les fichiers d’installation sur le Pocket PC afin d’installer le programme.
On procède de la manière suivante :
Copier le fichier d’installation du moteur, ainsi que les fichiers correspondants aux langues que l’on veux installer (vérifier que l’on dispose de suffisamment de mémoire disponible sur le Pocket PC, en effet la mémoire est assez limitée. Pour savoir comment vérifier l’espace disponible, veuillez vous reporter à la section « Vérifier l’espace disponible sur le Pocket PC »). Pour copier les fichiers sur le Pocket PC, utiliser Active Sync.
On obtient le résultat suivant sur le Pocket PC :
Une fois les fichiers d’installation sur le Pocket PC il faut les lancer. Pour cela il suffit de cliquer sur les fichiers. Installation en cours :
Pour vérifier que le programme est bien installé, on peut vérifier que les fichiers se sont bien copiés dans le bon répertoire : lancer l’explorateur de fichiers, puis aller dans le répertoire « Program Files », il doit se trouver un répertoire « ELAN Speech » qui contient lui même un répertoire « Data » contenant les fichiers nécessaires à la synthèse vocale en français.
Apres avoir chargé le programme de démonstration sur le Pocket PC ( grâce a Active Sync ) le lancer. Pour l’utiliser : il faut dans un premier temps cliquer sur le bouton « Initialiser », puis entrer un texte dans la zone de texte, mais pour plus de simplicité vous pouvez cliquer sur le bouton charger qui chargera un texte de démonstration dans la zone de texte qu’il ne restera plus qu’a synthétiser en cliquant sur le bouton « Go ».
Vérification de la mémoire disponible sur le Pocket PC :
Menu Démarrer, Paramètres, Mémoire, Progr. en cours d’exécution, et vérifier qu’il y a assez de place en mémoire et le cas échéant ajuster le curseur d’allocation de mémoire (plus pour le stockage ou plus pour la mémoire vive destinée aux programmes qui tournent).
Afin de réaliser les copies d’écran du Pocket PC nous avons utilisés un programme spécifique : IA ScreenShot qui est en version de démonstration pour 15 jours (d’ou le petit logo en bas des captures d’écran du Pocket PC).
On peut le configurer pour pouvoir prendre des copies d’écran avec un bouton sur le Pocket PC ou après X secondes.
Bilan
Objectifs atteints
L'objectif de ce projet était de concevoir un logiciel permettant l’analyse d’un fichier XLM en vue de la substitution de balises par du texte défini dans un fichier de correspondance, afin de le mettre en forme en vue de sa lecture par un moteur de text-to-speech.
Par ailleurs, il était important de réaliser une étude sur le portage vers Pocket PC.
La plupart de ces objectifs ont été atteints, et le logiciel possède même des particularités très importantes.
D’une part, il permet de sortir un texte en jsml, mais il ne s’agit que d’une fonctionnalité particulière, car il peut aussi bien générer du html, des images vectorielles, utiliser les informations d’une base de données… Ceci a été rendu possible grâce à la conception préalable que nous avons réalisée.
D’autre part, le portage sous Pocket PC a bien avancé, mais il reste à faire fonctionner la DLL.
Il convient de préciser que nous sommes arrivés à générer du jsml, mais aussi du html lors de nos tests, à partir du même document xml.
Il reste cependant à terminer la fusion des différents modules de l’application. Il convient cependant de préciser que les modules (analyseur XSD, analyseur XML et interface entre analyseurs et moteur text-to-speech) utilisés séparément semblent fonctionner correctement.
Expérience apportée
Nous avons essayé de sortir du cadre éducatif pour nous projeter dans le monde du travail en réalisant un logiciel le plus professionnel possible (distribution sur CD, package, documentation, tutoriaux, ainsi que ce rapport).
Tout d’abord, d’un point de vue organisation, il nous a été nécessaire de créer différentes équipes afin de mener à bien notre projet. De plus, le projet demandé une adaptation et une intégration importante car nous ne connaissions pas le fonctionnement soit du langage d’ écriture des fichiers, soit de l’application Text To Speech. Sur ces aspects là du projet, nous pensons avoir atteint notre objectif.
Propositions d'extension
Il pourrait être judicieux d’utiliser des JavaBeans afin de livrer notre application sous la forme d’un composant facilement réutilisable et pouvant être intégré, par exemple, au projet de Werable Computer réalisé en 3ième année.
En définitive, nous avons réalisé un logiciel répondant aux attentes du proposant, à la fois efficace et simple d'utilisation.
Un des chemins d'extension est la possibilité d’utiliser le parseur xml pour générer des fichiers de n’importe quel format à balises à partir de fichier xml. En effet, pour le moment, nous ne traitons les fichiers en format xml qu’en fichier au format jsml. Ainsi, le parseur pourrait se développer de son coté et être utilisé par d’autre programme n’ayant rien à voir avec l’application présente.
Une autre extension peut être l’augmentation du nombre de voix et du nombre de langues. L’application pourrait alors intéresser un plus grande nombre de personnes. Cette extension suppose alors une nouvelle extension du parseur afin qu’il gère plus de langues. Il est à noter que l’application connaîtra une extension naturelle lorsqu’il existera sur le marché des moteurs SAPI5 supportant d’autres langages.
Enfin, lorsque le développement d’une application complète de synthèse vocale sera achevé, il nous sera possible de nous pencher sur le problème de la reconnaissance vocale. Cette fonctionnalité, qui demande davantage de ressources systèmes, pourrait s’avérer plus complexe à porter vers un Pocket PC.
Conclusion
La partie du projet qui consistait à fusionner les différents éléments n’a pas été complètement effectuée. Par exemple, nous ne disposons pas d’une chaîne qui permet à une application sur Pocket PC d’analyser un fichier XML avant de prononcer son contenu.
Cependant, nous disposons de plusieurs composants qui fonctionnent indépendamment et qui ont subi différentes phases de tests. De plus, nous avons ouvert la voie vers la phase d’intégration finale.
En ce qui concerne le travail accompli, il faut remarquer que nous avons réussi à couvrir toutes les parties du projet, à savoir l’analyse et la substitution des balises par du texte, la synthèse vocale ainsi que le portage sur Pocket PC.
Par ailleurs, nous avons intégré à notre distribution les différents programmes nécessaires pour poursuivre le développement aisément. Nous leur avons associé des tutoriaux et des aides complètes afin que d’autres étudiants puissent poursuivre notre travail.
Enfin, ce projet nous a été particulièrement bénéfique. En effet, nous n’avions aucune notion de synthèse vocale ni de développement sur Pocket PC. En revanche, nous avions une expérience limitée en programmation Win 32 et en XML.
Le travail que nous avons accompli nous a donc permis d’acquérir de nouvelles connaissances ainsi que de nouvelles méthodes de travail : travail en équipe, phase d’intégration, suivi d’un planning… Ces apports pourraient nous permettre de trouver un stage dans le domaine du XML et de la synthèse vocale voire de continuer des projets proches de celui-ci.
Table des matières
TOC \o "9-9" \h \z \t "Titre 1;2;Titre 2;3;Titre 3;4;Titre 4;5;Titre 5;6;Titre 6;7;Titre 7;8;Titre 8;9;Titre 0;1" HYPERLINK \l "_Toc31458164" Sommaire PAGEREF _Toc31458164 \h 3
HYPERLINK \l "_Toc31458165" Introduction PAGEREF _Toc31458165 \h 4
HYPERLINK \l "_Toc31458166" 1 Présentation des objectifs PAGEREF _Toc31458166 \h 4
HYPERLINK \l "_Toc31458167" 2 Développement du sujet PAGEREF _Toc31458167 \h 4
HYPERLINK \l "_Toc31458168" 2.1 Les analyseurs PAGEREF _Toc31458168 \h 5
HYPERLINK \l "_Toc31458169" 2.1.1 Le parseur XSD PAGEREF _Toc31458169 \h 5
HYPERLINK \l "_Toc31458170" Présentation du parseur XSD PAGEREF _Toc31458170 \h 5
HYPERLINK \l "_Toc31458171" Définition d’une XSD PAGEREF _Toc31458171 \h 5
HYPERLINK \l "_Toc31458172" Les objectifs PAGEREF _Toc31458172 \h 6
HYPERLINK \l "_Toc31458173" Les contraintes PAGEREF _Toc31458173 \h 6
HYPERLINK \l "_Toc31458174" Le fonctionnement PAGEREF _Toc31458174 \h 7
HYPERLINK \l "_Toc31458175" Etude des différentes phases du programme PAGEREF _Toc31458175 \h 7
HYPERLINK \l "_Toc31458176" Les types PAGEREF _Toc31458176 \h 7
HYPERLINK \l "_Toc31458177" Les types simples PAGEREF _Toc31458177 \h 8
HYPERLINK \l "_Toc31458178" Problème PAGEREF _Toc31458178 \h 8
HYPERLINK \l "_Toc31458179" Solution PAGEREF _Toc31458179 \h 9
HYPERLINK \l "_Toc31458180" Les types complexes et les groupes PAGEREF _Toc31458180 \h 9
HYPERLINK \l "_Toc31458181" Problème PAGEREF _Toc31458181 \h 10
HYPERLINK \l "_Toc31458182" Solution PAGEREF _Toc31458182 \h 10
HYPERLINK \l "_Toc31458183" Les éléments PAGEREF _Toc31458183 \h 11
HYPERLINK \l "_Toc31458184" Problème PAGEREF _Toc31458184 \h 11
HYPERLINK \l "_Toc31458185" Solution PAGEREF _Toc31458185 \h 12
HYPERLINK \l "_Toc31458186" Les opérations complexes PAGEREF _Toc31458186 \h 12
HYPERLINK \l "_Toc31458187" Problème PAGEREF _Toc31458187 \h 12
HYPERLINK \l "_Toc31458188" Solution PAGEREF _Toc31458188 \h 13
HYPERLINK \l "_Toc31458189" La gestion des erreurs PAGEREF _Toc31458189 \h 14
HYPERLINK \l "_Toc31458190" Les erreurs syntaxiques PAGEREF _Toc31458190 \h 15
HYPERLINK \l "_Toc31458191" Les erreurs sémantiques PAGEREF _Toc31458191 \h 15
HYPERLINK \l "_Toc31458192" 2.1.2 Le parseur XML PAGEREF _Toc31458192 \h 16
HYPERLINK \l "_Toc31458193" Présentation du parseur XML PAGEREF _Toc31458193 \h 16
HYPERLINK \l "_Toc31458194" Les objectifs PAGEREF _Toc31458194 \h 16
HYPERLINK \l "_Toc31458195" Les contraintes PAGEREF _Toc31458195 \h 16
HYPERLINK \l "_Toc31458196" Etude des 2 parties du programme PAGEREF _Toc31458196 \h 17
HYPERLINK \l "_Toc31458197" Le parseur XML PAGEREF _Toc31458197 \h 17
HYPERLINK \l "_Toc31458198" Le parseur SAX PAGEREF _Toc31458198 \h 17
HYPERLINK \l "_Toc31458199" Différence avec le parseur DOM PAGEREF _Toc31458199 \h 18
HYPERLINK \l "_Toc31458200" Utilisation des résultats du parseur XSD PAGEREF _Toc31458200 \h 19
HYPERLINK \l "_Toc31458201" Les structures de données PAGEREF _Toc31458201 \h 19
HYPERLINK \l "_Toc31458202" Algorithme PAGEREF _Toc31458202 \h 23
HYPERLINK \l "_Toc31458203" Fichier Type PAGEREF _Toc31458203 \h 23
HYPERLINK \l "_Toc31458204" Le générateur de documents multiforme PAGEREF _Toc31458204 \h 25
HYPERLINK \l "_Toc31458205" Le fichier texte PAGEREF _Toc31458205 \h 25
HYPERLINK \l "_Toc31458206" Les balises PAGEREF _Toc31458206 \h 25
HYPERLINK \l "_Toc31458207" La syntaxe PAGEREF _Toc31458207 \h 25
HYPERLINK \l "_Toc31458208" Exemple PAGEREF _Toc31458208 \h 26
HYPERLINK \l "_Toc31458209" Document XML : PAGEREF _Toc31458209 \h 26
HYPERLINK \l "_Toc31458210" Fichier TEXTE : PAGEREF _Toc31458210 \h 26
HYPERLINK \l "_Toc31458211" Sortie Finale : PAGEREF _Toc31458211 \h 27
HYPERLINK \l "_Toc31458212" L’algorithme PAGEREF _Toc31458212 \h 27
HYPERLINK \l "_Toc31458213" Exemple d’application PAGEREF _Toc31458213 \h 29
HYPERLINK \l "_Toc31458214" Sortie texte PAGEREF _Toc31458214 \h 29
HYPERLINK \l "_Toc31458215" Sortie JSML PAGEREF _Toc31458215 \h 30
HYPERLINK \l "_Toc31458216" Sortie HTML PAGEREF _Toc31458216 \h 30
HYPERLINK \l "_Toc31458217" Commentaire PAGEREF _Toc31458217 \h 31
HYPERLINK \l "_Toc31458218" JSML: PAGEREF _Toc31458218 \h 31
HYPERLINK \l "_Toc31458219" HTML: PAGEREF _Toc31458219 \h 31
HYPERLINK \l "_Toc31458220" 2.2 Interface entre analyseurs et moteur Text To Speech PAGEREF _Toc31458220 \h 32
HYPERLINK \l "_Toc31458221" 2.2.1 Outils de travail et de développement PAGEREF _Toc31458221 \h 32
HYPERLINK \l "_Toc31458222" La JSAPI PAGEREF _Toc31458222 \h 32
HYPERLINK \l "_Toc31458223" Les SAPI PAGEREF _Toc31458223 \h 34
HYPERLINK \l "_Toc31458224" Le langage JSML PAGEREF _Toc31458224 \h 35
HYPERLINK \l "_Toc31458225" Description du langage PAGEREF _Toc31458225 \h 35
HYPERLINK \l "_Toc31458226" Les balises JSML PAGEREF _Toc31458226 \h 36
HYPERLINK \l "_Toc31458227" Exemples de fichier PAGEREF _Toc31458227 \h 38
HYPERLINK \l "_Toc31458228" 2.2.2 Le développement PAGEREF _Toc31458228 \h 39
HYPERLINK \l "_Toc31458229" Modification du fichier d’entrée PAGEREF _Toc31458229 \h 39
HYPERLINK \l "_Toc31458230" Synthèse Vocale PAGEREF _Toc31458230 \h 40
HYPERLINK \l "_Toc31458231" 2.3 Etude du Portage vers Pocket PC PAGEREF _Toc31458231 \h 40
HYPERLINK \l "_Toc31458232" 2.3.1 Outils de travail PAGEREF _Toc31458232 \h 41
HYPERLINK \l "_Toc31458233" L'environnement Java PAGEREF _Toc31458233 \h 41
HYPERLINK \l "_Toc31458234" L'API TextToSpeech PAGEREF _Toc31458234 \h 42
HYPERLINK \l "_Toc31458235" Caractéristiques de la SAPI PAGEREF _Toc31458235 \h 43
HYPERLINK \l "_Toc31458236" Programmer une application en utilisant SAPI PAGEREF _Toc31458236 \h 44
HYPERLINK \l "_Toc31458237" Tutorial de programmation PAGEREF _Toc31458237 \h 45
HYPERLINK \l "_Toc31458238" L'environnement de développement PAGEREF _Toc31458238 \h 46
HYPERLINK \l "_Toc31458239" 2.3.2 Phase de développement PAGEREF _Toc31458239 \h 46
HYPERLINK \l "_Toc31458240" Le programme Win32 PAGEREF _Toc31458240 \h 46
HYPERLINK \l "_Toc31458241" Intégration du code Win32 dans l'application finale PAGEREF _Toc31458241 \h 47
HYPERLINK \l "_Toc31458242" Création de la classe Java PAGEREF _Toc31458242 \h 48
HYPERLINK \l "_Toc31458243" Génération du fichier .h PAGEREF _Toc31458243 \h 49
HYPERLINK \l "_Toc31458244" Création du fichier .cpp PAGEREF _Toc31458244 \h 49
HYPERLINK \l "_Toc31458245" Création de la DLL PAGEREF _Toc31458245 \h 49
HYPERLINK \l "_Toc31458246" Exécution du programme et Problèmes rencontrés PAGEREF _Toc31458246 \h 50
HYPERLINK \l "_Toc31458247" Le JavaBean PAGEREF _Toc31458247 \h 51
HYPERLINK \l "_Toc31458248" 3 Bilan PAGEREF _Toc31458248 \h 61
HYPERLINK \l "_Toc31458249" 3.1 Objectifs atteints PAGEREF _Toc31458249 \h 61
HYPERLINK \l "_Toc31458250" 3.2 Expérience apportée PAGEREF _Toc31458250 \h 62
HYPERLINK \l "_Toc31458251" 3.3 Propositions d'extension PAGEREF _Toc31458251 \h 62
HYPERLINK \l "_Toc31458252" Conclusion PAGEREF _Toc31458252 \h 63
HYPERLINK \l "_Toc31458253" Table des matières PAGEREF _Toc31458253 \h 64
XSD : XML Schema Definition : Schéma de définition XML
XML : eXtended Markup Language : langage étendu de balises, standardisé par le w3c
La liste des facettes prises en compte dans le programme est disponible à l’adresse : HYPERLINK "http://www.w3.org/TR/xmlschema-0/#SimpleTypeFacets" http://www.w3.org/TR/xmlschema-0/#SimpleTypeFacets
TTS : Text To Speech
PAGE
nom élément
type
maximum_occurrences
minimum_occurrences
mode_utilisation
hashtable éléments
Element
Attribut
TypeSimple
TypeComplexe
hashtable types
Type
longueur_minimale
longueur_maximale
valeur_minimale
valeur_maximale
total_chiffres
total_decimal
liste_valeurs
expression_reguliere
espaces_blancs
liste_attributs
liste_elements
ordre
nom
est_complexe
nom élément
Entite
nom
entite
mode_utilisation
maximum_occurrences
minimum_occurrences
type
Entite
nom
entite
…
Vector
Couple
Couple
Vector
…
nom
entite
nom
entite
…
[E, F]
[B, C, D]
[A]
Le parser est à la balise
Le parser est à la balise
[B, C, D]
[A]
XML :
__xmlMarkupValuesOrder
__xmlMarkupOrder
(STRING)
(VECTOR)
A
Valeur balise
Nom balise
(COUPLESTRING)
(VECTOR)
Nom balise
Texte contenu dans le .txt correspondant
(VECTOR)
Hashtable (Value)
Hashtable (Key)
Nom balise
Valeur attribut
Nom attribut
(COUPLESTRING)
(VECTOR)
Hashtable (Value)
Hashtable (Key)
Nom balise
Valeur attribut
Nom attribut
(VECTOR)
(VECTOR)
Hashtable (Value)
Hashtable (Key)
Nom
Fabricant
Couleur
Voiture
(VECTOR)
Nom de la balise
(VECTOR)
EMBED PBrush
EMBED PBrush
TTSDriver.class
(gère la DLL)
TTSDriver.DLL
(Windows CE)
TextToSpeech.class
(Application principale
XMLParser.class
Fichier XML
Texte
Voix
PAGE 2
T U i j k l ‡ ˆ ‰ Š ‹ Œ ¦ § ¨ Á Â Ã Ä Å Æ Ç È É ä å æ ç è é ÿ õï ê êÝÕÏÕ»ÝÕ«Õ£—£‰—£—Ý«ÝÕÏÕuÝÕ«Õ£—£g—£— jüL UmH nH u &jL >*B*UmH nH ph ÿ u jL UmH nH u j UmH nH umH nH u CJ OJ QJ ^J aJ mH nH u&j‹K >*B*UmH nH ph ÿ u mH nH u0J mH nH uj 0J UmH nH u j U
5>*CJ j 5>*CJ U ( æ ç E F G I R S T Ç s È — \ Á ù ö ñ ñ è æ è à à ñ Ý ñ ñ Ö Ö Ï È È Ï È È Ï È
Æ (d#
Æ pd#
Æ ¸d#
@&