com_svox_picottsengine.cpp revision 39358f0dacad8cece6c2d3ef1055030f57090c79
139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi/* com_svox_picottsengine.cpp
239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
3b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
4b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
5b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Licensed under the Apache License, Version 2.0 (the "License");
6b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * you may not use this file except in compliance with the License.
7b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * You may obtain a copy of the License at
8b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
9b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *     http://www.apache.org/licenses/LICENSE-2.0
10b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
11b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Unless required by applicable law or agreed to in writing, software
12b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * distributed under the License is distributed on an "AS IS" BASIS,
13b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * See the License for the specific language governing permissions and
15b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * limitations under the License.
1639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
1739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    This is the Manager layer.  It sits on top of the native Pico engine
1839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    and provides the interface to the defined Google TTS engine API.
1939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    The Google engine API is the boundary to allow a TTS engine to be swapped.
2039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    The Manager layer also provide the SSML tag interpretation.
2139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    The supported SSML tags are mapped to corresponding tags natively supported by Pico.
2239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    Native Pico functions always begin with picoXXX.
2339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
2439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    In the Pico engine, the language cannot be changed indpendently of the voice.
2539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    If either the voice or locale/language are changed, a new resource is loaded.
2639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
2739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    Only a subset of SSML 1.0 tags are supported.
2839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    Some SSML tags involve significant complexity.
2939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    If the language is changed through an SSML tag, there is a latency for the load.
3039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
3139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    History:
3239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    2009-07-01 -- clean up & documentation
3339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    2009-06-29 -- integrated SSML parser and IPA to XSAMPA conversion
3439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    2009-06-29 -- revised for C90 compliance
3539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    2009-06-04 -- updated for new TtsEngine interface
3639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    2009-05-18 -- initial version
3739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
3839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
3939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi ToDo:
4039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi - duplicate 'phoneme ph='                              ***
4139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi - normalize IPA strings                                **
4239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi - change voice as well as language                     *
4339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi   Changing of voice/language is complex due to potentially multiple swaps
4439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi   under SSML and the latent effects.  This requires storing a history of tags/sets.
45b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
46b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
47b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <stdio.h>
48b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <unistd.h>
49b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
50b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define LOG_TAG "SVOX Pico Engine"
51b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
52b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <utils/Log.h>
5339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#include <utils/String16.h>                     /* for strlen16 */
54b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <android_runtime/AndroidRuntime.h>
55b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <tts/TtsEngine.h>
5639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#include <cutils/jstring.h>
57b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <picoapi.h>
58b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <picodefs.h>
5939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#include "svox_ssml_parser.h"
60b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
61b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenusing namespace android;
62b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
63b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* adaptation layer defines */
644eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi#define PICO_MEM_SIZE       2500000
6554823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi/* speaking rate    */
6639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#define PICO_MIN_RATE        20
67b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define PICO_MAX_RATE       500
6839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#define PICO_DEF_RATE       100
6954823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi/* speaking pitch   */
7039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#define PICO_MIN_PITCH       50
71b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define PICO_MAX_PITCH      200
7239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#define PICO_DEF_PITCH      100
7354823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi/* speaking volume  */
7439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#define PICO_MIN_VOLUME       0
75b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define PICO_MAX_VOLUME     500
7639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#define PICO_DEF_VOLUME     250
7739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
7854823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi/* string constants */
79b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define MAX_OUTBUF_SIZE     128
8039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * PICO_LINGWARE_PATH             = "/sdcard/svox/";
8139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * PICO_VOICE_NAME                = "PicoVoice";
8239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * PICO_SPEED_OPEN_TAG            = "<speed level='%d'>";
8339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * PICO_SPEED_CLOSE_TAG           = "</speed>";
8439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * PICO_PITCH_OPEN_TAG            = "<pitch level='%d'>";
8539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * PICO_PITCH_CLOSE_TAG           = "</pitch>";
8639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * PICO_VOLUME_OPEN_TAG           = "<volume level='%d'>";
8739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * PICO_VOLUME_CLOSE_TAG          = "</volume>";
8839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * PICO_PHONEME_OPEN_TAG          = "<phoneme ph='";
8939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
9039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi/* supported voices
9139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi   Pico does not seperately specify the voice and locale.   */
9239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * picoSupportedLangIso3[]        = { "eng",              "eng",              "deu",              "spa",              "fra",              "ita" };
9339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * picoSupportedCountryIso3[]     = { "USA",              "GBR",              "DEU",              "ESP",              "FRA",              "ITA" };
9439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * picoSupportedLang[]            = { "en-rUS",           "en-rGB",           "de-rDE",           "es-rES",           "fr-rFR",           "it-rIT" };
9539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * picoInternalLang[]             = { "en-US",            "en-GB",            "de-DE",            "es-ES",            "fr-FR",            "it-IT" };
9639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * picoInternalTaLingware[]       = { "en-US_ta.bin",     "en-GB_ta.bin",     "de-DE_ta.bin",     "es-ES_ta.bin",     "fr-FR_ta.bin",     "it-IT_ta.bin" };
9739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * picoInternalSgLingware[]       = { "en-US_lh0_sg.bin", "en-GB_kh0_sg.bin", "de-DE_gl0_sg.bin", "es-ES_zl0_sg.bin", "fr-FR_nk0_sg.bin", "it-IT_cm0_sg.bin" };
9839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * picoInternalUtppLingware[]     = { "en-US_utpp.bin",   "en-GB_utpp.bin",   "de-DE_utpp.bin",   "es-ES_utpp.bin",   "fr-FR_utpp.bin",   "it-IT_utpp.bin" };
9939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst int picoNumSupportedVocs              = 6;
100b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
10154823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi/* supported properties */
10239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst char * picoSupportedProperties[]      = { "language", "rate", "pitch", "volume" };
10339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviconst int    picoNumSupportedProperties     = 4;
104b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
10554823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
10654823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi/* adapation layer global variables */
10739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel TrivisynthDoneCB_t * picoSynthDoneCBPtr;
10839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivivoid *          picoMemArea         = NULL;
10939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_System     picoSystem          = NULL;
11039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Resource   picoTaResource      = NULL;
11139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Resource   picoSgResource      = NULL;
11239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Resource   picoUtppResource    = NULL;
11339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Engine     picoEngine          = NULL;
11439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Char *     picoTaFileName      = NULL;
11539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Char *     picoSgFileName      = NULL;
11639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Char *     picoUtppFileName    = NULL;
11739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Char *     picoTaResourceName  = NULL;
11839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Char *     picoSgResourceName  = NULL;
11939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivipico_Char *     picoUtppResourceName = NULL;
12054823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Triviint     picoSynthAbort = 0;
12139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivichar *  picoProp_currLang   = NULL;                 /* current language */
12254823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Triviint     picoProp_currRate   = PICO_DEF_RATE;        /* current rate     */
12354823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Triviint     picoProp_currPitch  = PICO_DEF_PITCH;       /* current pitch    */
12454823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Triviint     picoProp_currVolume = PICO_DEF_VOLUME;      /* current volume   */
12554823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
1269b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Triviint picoCurrentLangIndex = -1;
127b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
128b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
129b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* internal helper functions */
130b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
13139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi/** checkForLocale
13239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  Check whether the requested locale is among the supported locales.
13339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @locale -  the locale to check, either in xx or xx-rYY format
13439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  return index of the locale, or -1 if not supported.
135b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
13639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivistatic int checkForLocale( const char * locale )
137b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
13854823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi     int found = -1;                                         /* language not found   */
13939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi     int i;
14039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi     if (locale == NULL) {
14139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        LOGE("checkForLanguage called with NULL language");
14239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        return found;
14339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi     }
14454823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
14554823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    /* Verify that the requested locale is a locale that we support.    */
14639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    for (i = 0; i < picoNumSupportedVocs; i ++)
147b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
14839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (strcmp(locale, picoSupportedLang[i]) == 0)  /* in array */
149b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
150b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            found = i;
151b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
152b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
15354823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    };
15439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
15539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* The locale was not found.    */
156b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (found < 0)
157b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
15854823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi        /* We didn't find an exact match; it may have been specified with only the first 2 characters.
15939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi           This could overmatch ISO 639-3 language codes.%%                                   */
16039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        for (i = 0; i < picoNumSupportedVocs; i ++)
161b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
16239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            if (strncmp(locale, picoSupportedLang[i], 2) == 0)
163b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            {
164b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                found = i;
165b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                break;
166b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
167b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
168b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (found < 0)
169b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
17039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            LOGE("TtsEngine::set language called with unsupported locale");
171b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
17254823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    };
173b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return found;
174b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
175b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
17654823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
177b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** cleanResources
17854823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi *  Unloads any loaded Pico resources.
179b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
18054823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivistatic void cleanResources( void )
181b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
182b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoEngine)
183b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
18454823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi        pico_disposeEngine( picoSystem, &picoEngine );
18539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        pico_releaseVoiceDefinition( picoSystem, (pico_Char *) PICO_VOICE_NAME );
186b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoEngine = NULL;
187b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
188b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoUtppResource)
189b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
19054823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi        pico_unloadResource( picoSystem, &picoUtppResource );
191b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoUtppResource = NULL;
192b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
193b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoTaResource)
194b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
19554823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi        pico_unloadResource( picoSystem, &picoTaResource );
196b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoTaResource = NULL;
197b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
198b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoSgResource)
199b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
20054823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi        pico_unloadResource( picoSystem, &picoSgResource );
201b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoSgResource = NULL;
202b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
2039b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    picoCurrentLangIndex = -1;
204b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
205b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
20654823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
207b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** cleanFiles
20854823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi *  Frees any memory allocated for file and resource strings.
209b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
21054823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivistatic void cleanFiles( void )
211b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
212b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoProp_currLang)
213b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
21439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        free( picoProp_currLang );
215b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoProp_currLang = NULL;
216b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
2174eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
218b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoTaFileName)
219b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
22039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        free( picoTaFileName );
221b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoTaFileName = NULL;
222b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
2234eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
224b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoSgFileName)
225b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
22639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        free( picoSgFileName );
227b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoSgFileName = NULL;
228b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
2294eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
230b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoUtppFileName)
231b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
23239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        free( picoUtppFileName );
233b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoUtppFileName = NULL;
234b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
2354eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
236b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoTaResourceName)
237b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
23839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        free( picoTaResourceName );
239b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoTaResourceName = NULL;
240b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
2414eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
242b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoSgResourceName)
243b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
24439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        free( picoSgResourceName );
245b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoSgResourceName = NULL;
246b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
2474eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
248b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoUtppResourceName)
249b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
25039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        free( picoUtppResourceName );
251b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoUtppResourceName = NULL;
252b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
253b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
254b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
2559b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi/** hasResourcesForLanguage
2569b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi *  Check to see if the resources required to load the language at the specified index
2579b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi *  are properly installed
2589b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi *  @langIndex - the index of the language to check the resources for. The index is valid.
2599b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi *  return true if the required resources are installed, false otherwise
2609b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi */
2619b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivistatic bool hasResourcesForLanguage(int langIndex) {
2629b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    FILE * pFile;
2639b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    char* fileName = (char*)malloc(PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE);
2649b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
2659b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    strcpy((char*)fileName, PICO_LINGWARE_PATH);
2669b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    strcat((char*)fileName, (const char*)picoInternalTaLingware[langIndex]);
2679b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    pFile = fopen(fileName,"r");
2689b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    if (pFile == NULL){
2699b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        free(fileName);
2709b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        return false;
2719b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    } else {
2729b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        fclose (pFile);
2739b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    }
2749b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
2759b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    strcpy((char*)fileName, PICO_LINGWARE_PATH);
2769b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    strcat((char*)fileName, (const char*)picoInternalSgLingware[langIndex]);
2779b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    pFile = fopen(fileName, "r");
2789b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    if (pFile == NULL) {
2799b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        free(fileName);
2809b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        return false;
2819b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    } else {
2829b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        fclose(pFile);
2839b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        free(fileName);
2849b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        return true;
2859b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    }
2869b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi}
2879b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
2884eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi/** doLanguageSwitchFromLangIndex
28939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  Switch to the requested locale.
29039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  If the locale is already loaded, it returns immediately.
29139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  If another locale is already is loaded, it will first be unloaded and the new one then loaded.
29239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  If no locale is loaded, the requested locale will be loaded.
29339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @langIndex -  the index of the locale/voice to load, which is guaranteed to be supported.
294b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return TTS_SUCCESS or TTS_FAILURE
2954eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi */
29639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivistatic tts_result doLanguageSwitchFromLangIndex( int langIndex )
297b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
29839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int ret;                                        /* function result code */
29939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
30039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* If we already have a loaded locale, check whether it is the same one as requested.   */
301b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoProp_currLang && (strcmp(picoProp_currLang, picoSupportedLang[langIndex]) == 0))
302b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
3034eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGI("Language already loaded (%s == %s)", picoProp_currLang, picoSupportedLang[langIndex]);
304b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_SUCCESS;
305b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
306b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
30739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* It is not the same locale; unload the current one first. */
308b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    cleanResources();
3094eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
31039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Allocate memory for file and resource names.     */
311b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    cleanFiles();
31239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoProp_currLang   = (char *)      malloc( 10 );
31339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoTaFileName      = (pico_Char *) malloc( PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE );
31439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoSgFileName      = (pico_Char *) malloc( PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE );
31539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoUtppFileName    = (pico_Char *) malloc( PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE );
31639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoTaResourceName  = (pico_Char *) malloc( PICO_MAX_RESOURCE_NAME_SIZE );
31739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoSgResourceName  = (pico_Char *) malloc( PICO_MAX_RESOURCE_NAME_SIZE );
31839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoUtppResourceName =(pico_Char *) malloc( PICO_MAX_RESOURCE_NAME_SIZE );
31939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
32039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Set the path and file names for resource files.  */
32139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    strcpy((char *) picoTaFileName,   PICO_LINGWARE_PATH);
32239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    strcat((char *) picoTaFileName,   (const char *) picoInternalTaLingware[langIndex]);
32339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    strcpy((char *) picoSgFileName,   PICO_LINGWARE_PATH);
32439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    strcat((char *) picoSgFileName,   (const char *) picoInternalSgLingware[langIndex]);
32539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    strcpy((char *) picoUtppFileName, PICO_LINGWARE_PATH);
32639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    strcat((char *) picoUtppFileName, (const char *) picoInternalUtppLingware[langIndex]);
32739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
32839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Load the text analysis Lingware resource file.   */
32939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ret = pico_loadResource( picoSystem, picoTaFileName, &picoTaResource );
330b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != ret)
331b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
3324eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGE("Failed to load textana resource for %s [%d]", picoSupportedLang[langIndex], ret);
333b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanResources();
334b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanFiles();
335b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
336b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
3374eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
33839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Load the signal generation Lingware resource file.   */
33939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ret = pico_loadResource( picoSystem, picoSgFileName, &picoSgResource );
340b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != ret)
341b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
3424eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGE("Failed to load siggen resource for %s [%d]", picoSupportedLang[langIndex], ret);
343b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanResources();
344b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanFiles();
345b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
346b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
3474eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
34839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Load the utpp Lingware resource file if exists - NOTE: this file is optional
34939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       and is currently not used. Loading is only attempted for future compatibility.
35039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       If this file is not present the loading will still succeed.                      */
35139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ret = pico_loadResource( picoSystem, picoUtppFileName, &picoUtppResource );
35239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if ((PICO_OK != ret) && (ret != PICO_EXC_CANT_OPEN_FILE))
35339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
3544eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGE("Failed to load utpp resource for %s [%d]", picoSupportedLang[langIndex], ret);
355b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanResources();
356b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanFiles();
357b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
35839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
3594eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
36039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Get the text analysis resource name.     */
36139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ret = pico_getResourceName( picoSystem, picoTaResource, (char *) picoTaResourceName );
362b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != ret)
363b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
3644eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGE("Failed to get textana resource name for %s [%d]", picoSupportedLang[langIndex], ret);
365b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanResources();
366b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanFiles();
367b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
368b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
3694eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
37039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Get the signal generation resource name. */
37139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ret = pico_getResourceName( picoSystem, picoSgResource, (char *) picoSgResourceName );
372b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK == ret && picoUtppResource != NULL)
373b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
37439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        /* Get utpp resource name - optional: see note above.   */
37539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        ret = pico_getResourceName( picoSystem, picoUtppResource, (char *) picoUtppResourceName );
376b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (PICO_OK != ret)
377b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
3784eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi            LOGE("Failed to get utpp resource name for %s [%d]", picoSupportedLang[langIndex], ret);
379b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            cleanResources();
380b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            cleanFiles();
381b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_FAILURE;
382b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
383b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
384b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != ret)
385b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
3864eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGE("Failed to get siggen resource name for %s [%d]", picoSupportedLang[langIndex], ret);
387b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanResources();
388b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanFiles();
389b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
390b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
3914eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
39239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Create a voice definition.   */
39339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ret = pico_createVoiceDefinition( picoSystem, (const pico_Char *) PICO_VOICE_NAME );
394b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != ret)
395b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
3964eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGE("Failed to create voice for %s [%d]", picoSupportedLang[langIndex], ret);
397b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanResources();
398b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanFiles();
399b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
400b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
4014eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
40239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Add the text analysis resource to the voice. */
40339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ret = pico_addResourceToVoiceDefinition( picoSystem, (const pico_Char *) PICO_VOICE_NAME, picoTaResourceName );
404b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != ret)
405b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
4064eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGE("Failed to add textana resource to voice for %s [%d]", picoSupportedLang[langIndex], ret);
407b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanResources();
408b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanFiles();
409b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
410b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
4114eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
41239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Add the signal generation resource to the voice. */
41339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ret = pico_addResourceToVoiceDefinition( picoSystem, (const pico_Char *) PICO_VOICE_NAME, picoSgResourceName );
414b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK == ret && picoUtppResource != NULL)
415b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
41639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        /* Add utpp resource to voice - optional: see note above.   */
41739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        ret = pico_addResourceToVoiceDefinition( picoSystem, (const pico_Char *) PICO_VOICE_NAME, picoUtppResourceName );
418b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (PICO_OK != ret)
419b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
4204eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi            LOGE("Failed to add utpp resource to voice for %s [%d]", picoSupportedLang[langIndex], ret);
421b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            cleanResources();
422b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            cleanFiles();
423b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_FAILURE;
424b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
425b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
4264eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
427b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != ret)
428b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
4294eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGE("Failed to add siggen resource to voice for %s [%d]", picoSupportedLang[langIndex], ret);
430b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanResources();
431b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanFiles();
432b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
433b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
434b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
43539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ret = pico_newEngine( picoSystem, (const pico_Char *) PICO_VOICE_NAME, &picoEngine );
436b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != ret)
437b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
4384eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi        LOGE("Failed to create engine for %s [%d]", picoSupportedLang[langIndex], ret);
439b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanResources();
440b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        cleanFiles();
441b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
442b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
4434eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
44439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Set the current locale/voice.    */
44539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    strcpy( picoProp_currLang, picoSupportedLang[langIndex] );
446b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    LOGI("loaded %s successfully", picoProp_currLang);
447b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return TTS_SUCCESS;
448b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
449b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
45039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
4514eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi/** doLanguageSwitch
45239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  Switch to the requested locale.
45339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  If this locale is already loaded, it returns immediately.
45439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  If another locale is already loaded, this will first be unloaded
45539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  and the new one then loaded.
45639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  If no locale is loaded, the requested will be loaded.
45739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @locale -  the locale to check, either in xx or xx-rYY format (i.e "en" or "en-rUS")
4584eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi *  return TTS_SUCCESS or TTS_FAILURE
4594eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi*/
46039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivistatic tts_result doLanguageSwitch( const char * locale )
4614eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi{
46239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int loclIndex;                              /* locale index */
4634eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
46439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Load the new locale. */
46539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    loclIndex = checkForLocale( locale );
46639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if (loclIndex < 0)
46739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
46839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        LOGE("Tried to swith to non-supported locale %s", locale);
46939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        return TTS_FAILURE;
47039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
47139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    LOGI("Found supported locale %s", picoSupportedLang[loclIndex]);
47239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    return doLanguageSwitchFromLangIndex( loclIndex );
4734eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi}
4744eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
47539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
476b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** doAddProperties
47739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  Add <speed>, <pitch> and <volume> tags to the text,
47839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  if the properties have been set to non-default values, and return the new string.
47939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  The calling function is responsible for freeing the returned string.
480b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @str - text to apply tags to
481b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return new string with tags applied
482b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
48339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivistatic char * doAddProperties( const char * str )
484b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
48539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    char *  data = NULL;
48639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int     haspitch, hasspeed, hasvol;                 /* parameters           */
48739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int     textlen;                                    /* property string length   */
4884eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
48939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    haspitch = 0; hasspeed = 0; hasvol = 0;
49039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    textlen = strlen(str) + 1;
49154823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    if (picoProp_currPitch != PICO_DEF_PITCH)           /* non-default pitch    */
492b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
493b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        textlen += strlen(PICO_PITCH_OPEN_TAG) + 5;
494b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        textlen += strlen(PICO_PITCH_CLOSE_TAG);
495b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        haspitch = 1;
496b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
49754823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    if (picoProp_currRate != PICO_DEF_RATE)             /* non-default rate     */
498b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
499b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        textlen += strlen(PICO_SPEED_OPEN_TAG) + 5;
500b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        textlen += strlen(PICO_SPEED_CLOSE_TAG);
501b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        hasspeed = 1;
502b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
50354823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    if (picoProp_currVolume != PICO_DEF_VOLUME)         /* non-default volume   */
504b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
505b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        textlen += strlen(PICO_VOLUME_OPEN_TAG) + 5;
506b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        textlen += strlen(PICO_VOLUME_CLOSE_TAG);
507b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        hasvol = 1;
508b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
5094eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
51039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Compose the property strings.    */
51139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    data = (char *) malloc( textlen );                  /* allocate string      */
512b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (!data)
513b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
514b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return NULL;
515b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
51654823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    memset(data, 0, textlen);                           /* clear it             */
517b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (haspitch)
518b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
519b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        char* tmp = (char*)malloc(strlen(PICO_PITCH_OPEN_TAG) + strlen(PICO_PITCH_CLOSE_TAG) + 5);
520b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        sprintf(tmp, PICO_PITCH_OPEN_TAG, picoProp_currPitch);
521b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcat(data, tmp);
522b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        free(tmp);
523b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
5244eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
525b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (hasspeed)
526b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
527b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        char* tmp = (char*)malloc(strlen(PICO_SPEED_OPEN_TAG) + strlen(PICO_SPEED_CLOSE_TAG) + 5);
528b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        sprintf(tmp, PICO_SPEED_OPEN_TAG, picoProp_currRate);
529b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcat(data, tmp);
530b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        free(tmp);
531b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
5324eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
533b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (hasvol)
534b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
535b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        char* tmp = (char*)malloc(strlen(PICO_VOLUME_OPEN_TAG) + strlen(PICO_VOLUME_CLOSE_TAG) + 5);
536b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        sprintf(tmp, PICO_VOLUME_OPEN_TAG, picoProp_currVolume);
537b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcat(data, tmp);
538b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        free(tmp);
539b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
5404eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
541b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    strcat(data, str);
5424eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
543b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (hasvol)
544b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
545b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcat(data, PICO_VOLUME_CLOSE_TAG);
546b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
5474eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
548b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (hasspeed)
549b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
550b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcat(data, PICO_SPEED_CLOSE_TAG);
551b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
5524eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
553b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (haspitch)
554b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
555b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcat(data, PICO_PITCH_CLOSE_TAG);
556b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
5574eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
558b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return data;
559b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
560b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
56154823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
56239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi/** createPhonemeString
56339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  Wrap all individual words in <phoneme> tags.
56439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  The Pico <phoneme> tag only supports one word in each tag,
56539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  therefore they must be individually wrapped!
56639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @xsampa - text to convert to Pico phomene string
56739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @length - length of the input string
56839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  return new string with tags applied
56939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi*/
57039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivistatic char * createPhonemeString( const char * xsampa, int length )
57139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi{
57239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    char *  convstring = NULL;
57339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int     origStrLen = strlen(xsampa);
57439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int     numWords   = 1;
57539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int     start, totalLength, i, j;
57639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
57739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi  for (i = 0; i < origStrLen; i ++)
57839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      {
57939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      if (xsampa[i] == ' ')
58039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi          numWords ++;
58139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      }
58239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
58339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi  if (numWords == 1)
58439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      {
58539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      convstring = new char[origStrLen + 17];
58639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      convstring[0] = '\0';
58739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      strcat(convstring, "<phoneme ph='");
58839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      strcat(convstring, xsampa);
58939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      strcat(convstring, "'/>");
59039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      }
59139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi  else
59239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      {
59339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      char * words[numWords];
59439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      start = 0; totalLength = 0; i = 0; j = 0;
59539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      for (i=0, j=0; i < origStrLen; i ++)
59639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi          {
59739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi          if (xsampa[i] == ' ')
59839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              {
59939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              words[j]    = new char[i+1-start+17];
60039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              words[j][0] = '\0';
60139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              strcat( words[j], "<phoneme ph='");
60239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              strncat(words[j], xsampa+start, i-start);
60339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              strcat( words[j], "'/>");
60439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              start = i + 1;
60539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              j ++;
60639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              totalLength += strlen(words[j-1]);
60739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi              }
60839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi          }
60939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      words[j]    = new char[i+1-start+17];
61039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      words[j][0] = '\0';
61139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      strcat(words[j], "<phoneme ph='");
61239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      strcat(words[j], xsampa+start);
61339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      strcat(words[j], "'/>");
61439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      totalLength += strlen(words[j]);
61539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      convstring = new char[totalLength + 1];
61639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      convstring[0] = '\0';
61739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      for (i=0; i < numWords; i ++)
61839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
61939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            strcat(convstring, words[i]);
62039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            delete [] words[i];
62139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
62239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      }
62339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi  return convstring;
62439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi}
62539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
62639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
62739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi/* The XSAMPA uses as many as 4 characters to represent a single IPA code.  */
62839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivitypedef struct tagPhnArr
62939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {
63039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    char16_t    strIPA;             /* IPA Unicode symbol       */
63139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    char        strXSAMPA[5];       /* SAMPA sequence           */
63239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    } PArr;
63339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
63439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi#define phn_cnt (133)
63539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
63639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel TriviPArr    PhnAry[phn_cnt] = {
63739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
63839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* XSAMPA conversion table      */
63939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
64039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Vowels (23) complete     */
64139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x025B,        "E"},
64239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0251,        "A"},
64339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0254,        "O"},
64439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x00F8,        "2"},
64539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0153,        "9"},
64639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0276,        "&"},
64739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0252,        "Q"},
64839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x028C,        "V"},
64939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0264,        "7"},
65039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x026F,        "M"},
65139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0268,        "1"},
65239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0289,        "}"},
65339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x026A,        "I"},
65439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x028F,        "Y"},
65539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x028A,        "U"},
65639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0259,        "@"},
65739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0275,        "8"},
65839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0250,        "6"},
65939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x00E6,        "{"},
66039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x025C,        "3"},
66139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x025A,        "@'"},
66239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x025E,        "3\\"},
66339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0258,        "@\\"},
66439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
66539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Consonants (60) complete */
66639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0288,        "t'"},
66739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0256,        "d'"},
66839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x025F,        "J\\"},
66939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0261,        "g"},
67039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0262,        "G\\"},
67139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0294,        "?"},
67239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0271,        "F"},
67339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0273,        "n'"},
67439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0272,        "J"},
67539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x014B,        "N"},
67639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0274,        "N\\"},
67739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0299,        "B\\"},
67839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0280,        "R\\"},
67939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x027E,        "4"},
68039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x027D,        "r'"},
68139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0278,        "p\\"},
68239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x03B2,        "B"},
68339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x03B8,        "T"},
68439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x00F0,        "D"},
68539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0283,        "S"},
68639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0292,        "Z"},
68739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0282,        "s'"},
68839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0290,        "z'"},
68939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x00E7,        "C"},
69039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x029D,        "j\\"},
69139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0263,        "G"},
69239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x03C7,        "X"},
69339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0281,        "R"},
69439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0127,        "X\\"},
69539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0295,        "?\\"},
69639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0266,        "h\\"},
69739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x026C,        "K"},
69839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x026E,        "K\\"},
69939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x028B,        "P"},
70039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0279,        "r\\"},
70139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x027B,        "r\\'"},
70239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0270,        "M\\"},
70339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x026D,        "l'"},
70439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x028E,        "L"},
70539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x029F,        "L\\"},
70639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0253,        "b_<"},
70739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0257,        "d_<"},
70839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0284,        "J\\_<"},
70939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0260,        "g_<"},
71039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x029B,        "G\\_<"},
71139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x028D,        "W"},
71239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0265,        "H"},
71339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x029C,        "H\\"},
71439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02A1,        ">\\"},
71539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02A2,        "<\\"},
71639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0298,        "O\\"},
71739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x01C0,        "|\\"},
71839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x01C3,        "!\\"},
71939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x01C2,        "=\\"},
72039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x01C1,        "|\\|\\"},
72139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x027A,        "l\\"},
72239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0255,        "s\\"},
72339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0291,        "z\\"},
72439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0267,        "x\\"},
72539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x026B,        "l_G"},
72639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
72739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Diacritics (34)  */
72839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02BC,        "_>"},
72939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0325,        "_0"},
73039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x030A,        "_0"},
73139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x032C,        "_v"},
73239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02B0,        "_h"},
73339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0324,        "_t"},
73439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0330,        "_k"},
73539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x033C,        "_N"},
73639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x032A,        "_d"},
73739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x033A,        "_a"},
73839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x033B,        "_m"},
73939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0339,        "_O"},
74039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x031C,        "_c"},
74139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x031F,        "_+"},
74239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0320,        "_-"},
74339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0308,        "_"},       /* centralized %%   */
74439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x033D,        "_x"},
74539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0318,        "_A"},
74639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0319,        "_q"},
74739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02DE,        "'"},
74839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02B7,        "_w"},
74939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02B2,        "_j"},
75039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02E0,        "_G"},
75139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02E4,        "_?\\"},
75239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0303,        "~"},
75339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x207F,        "_n"},
75439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02E1,        "_l"},
75539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x031A,        "_}"},
75639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0334,        "_e"},
75739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x031D,        "_r"},
75839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x031E,        "_o"},
75939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0329,        "="},
76039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x032F,        "_^"},
76139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02D0,        ":"},
76239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
76339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Others (10) incomplete%% */
76439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0361,        "_"},
76539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x035C,        "_"},
76639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02C8,        ""},
76739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02CC,        "%"},
76839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02D1,        ":\\"},
76939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x0306,        "_X"},
77039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x2016,        "||"},
77139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x203F,        "-\\"},
77239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x2197,        "<R>"},
77339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x2198,        "<F>"},
77439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
77539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Affricates (6) complete  */
77639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02A3,        "d_z"},
77739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02A4,        "d_Z"},
77839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02A5,        "d_z\\"},
77939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02A6,        "t_s"},
78039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02A7,        "t_S"},
78139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {0x02A8,        "t_s\\"}
78239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    };
78339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
78439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
78539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivivoid CnvIPAPnt( const char16_t IPnt, char * XPnt )
78639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi{
78739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    char16_t        ThisPnt = IPnt;                     /* local copy of single IPA codepoint   */
78839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int             idx;                                /* index into table         */
78939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
79039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Convert an individual IPA codepoint.
79139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       A single IPA code could map to a string.
79239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       Search the table.  If it is not found, use the same character.
79339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       Since most codepoints can be contained within 16 bits,
79439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       they are represented as wide chars.              */
79539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    XPnt[0] = 0;                                        /* clear the result string  */
79639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
79739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Search the table for the conversion. */
79839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    for (idx = 0; idx < phn_cnt; idx ++)                /* for each item in table   */
79939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      if (IPnt == PhnAry[idx].strIPA)                   /* matches IPA code         */
80039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
80139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        strcat( XPnt, (const char *)&(PhnAry[idx].strXSAMPA) ); /* copy the XSAMPA string   */
80239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        return;
80339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
80439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    strcat(XPnt, (const char *)&ThisPnt);               /* just copy it             */
80539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi}
80639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
80739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
80839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi/** cnvIpaToXsampa
80939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  Convert an IPA character string to an XSAMPA character string.
81039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @ipaString - input IPA string to convert
81139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @outXsampaString - converted XSAMPA string is passed back in this parameter
81239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  return size of the new string
81339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi*/
81439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Triviint cnvIpaToXsampa( const char16_t * ipaString, char ** outXsampaString )
81539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi{
81639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    size_t      xsize;                                  /* size of result               */
81739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    size_t      ilen;                                   /* input length                 */
81839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int         ipidx;                                  /* index into IPA string        */
81939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    char *      XPnt;                                   /* short XSAMPA char sequence   */
82039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
82139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Convert an IPA string to an XSAMPA string and store the xsampa string in *outXsampaString.
82239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       It is the responsibility of the caller to free the allocated string.
82339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       Increment through the string.  For each base & combination convert it to the XSAMP equivalent.
82439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       Because of the XSAMPA limitations, not all IPA characters will be covered.       */
82539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    XPnt = (char *) malloc(6);
82639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    xsize   = (4 * strlen16(ipaString)) + 8;            /* assume more than double size */
82739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
82839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    *outXsampaString = (char *) malloc( xsize );        /* allocate return string   */
82939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    *outXsampaString[0] = 0;
83039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    xsize = 0;                                          /* clear final              */
83139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    ilen = strlen16(ipaString);                         /* length of input UTF-16   */
83239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    for (ipidx = 0; ipidx < ilen; ipidx ++)             /* for each IPA code        */
83339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
83439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        CnvIPAPnt( ipaString[ipidx], XPnt );            /* get converted string     */
83539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        strcat((char *)*outXsampaString, XPnt );        /* concatenate XSAMPA       */
83639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        };
83739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    free(XPnt);
83839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    xsize = strlen(*outXsampaString);                   /* get the final length     */
83939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    return xsize;
84039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi}
84139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
84239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
84339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
84439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi/* Google Engine API function implementations */
845b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
846b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** init
84739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  Allocates Pico memory block and initializes the Pico system.
848b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  synthDoneCBPtr - Pointer to callback function which will receive generated samples
849b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return tts_result
850b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
85154823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivitts_result TtsEngine::init( synthDoneCB_t synthDoneCBPtr )
852b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
853b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (synthDoneCBPtr == NULL)
854b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
855b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("Callback pointer is NULL");
856b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
857b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
8584eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
85939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoMemArea = malloc( PICO_MEM_SIZE );
860b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (!picoMemArea)
861b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
862b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("Failed to allocate memory for Pico system");
863b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
864b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
8654eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
86639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    pico_Status ret = pico_initialize( picoMemArea, PICO_MEM_SIZE, &picoSystem );
867b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (PICO_OK != ret)
868b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
869b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("Failed to initialize Pico system");
87039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        free( picoMemArea );
871b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoMemArea = NULL;
872b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
873b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
8744eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
875b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoSynthDoneCBPtr = synthDoneCBPtr;
8769b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
8779b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    picoCurrentLangIndex = -1;
8789b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
879b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return TTS_SUCCESS;
880b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
881b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
88254823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
883b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** shutdown
88454823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi *  Unloads all Pico resources; terminates Pico system and frees Pico memory block.
885b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return tts_result
886b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
88754823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivitts_result TtsEngine::shutdown( void )
888b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
889b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    cleanResources();
8904eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
891b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoSystem)
892b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
893b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        pico_terminate(&picoSystem);
894b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoSystem = NULL;
895b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
896b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (picoMemArea)
897b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
898b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        free(picoMemArea);
899b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoMemArea = NULL;
900b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
9014eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
902b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    cleanFiles();
903b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return TTS_SUCCESS;
904b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
905b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
90639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
90739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi/** loadLanguage
90839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  Load a new language.
90939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @lang - string with ISO 3 letter language code.
91039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @country - string with ISO 3 letter country code .
91139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @variant - string with language variant for that language and country pair.
91239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  return tts_result
91339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi*/
91439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivitts_result TtsEngine::loadLanguage(const char *lang, const char *country, const char *variant)
91539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi{
91639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    return TTS_FAILURE;
91739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    //return setProperty("language", value, size);
91839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi}
91939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
92039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
92139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi/** setLanguage
92239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  Load a new language (locale).  Use the ISO 639-3 language codes.
92339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @lang - string with ISO 639-3 language code.
92439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @country - string with ISO 3 letter country code.
92539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @variant - string with language variant for that language and country pair.
92639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  return tts_result
92739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi */
92839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivitts_result TtsEngine::setLanguage( const char * lang, const char * country, const char * variant )
92939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi{
93039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int langIndex;
93139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int countryIndex;
93239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int i;
93339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
93439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if (lang == NULL)
93539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
93639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        LOGE("TtsEngine::setLanguage called with NULL language");
93739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        return TTS_FAILURE;
93839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
93939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
94039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* We look for a match on the language first
94139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       then we look for a match on the country.
94239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       If no match on the language:
94339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi             return an error.
94439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       If match on the language, but no match on the country:
94539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi             load the language found for the language match.
94639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       If match on the language, and match on the country:
94739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi             load the language found for the country match.     */
94839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
94939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Find a match on the language.    */
95039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    langIndex = -1;                                     /* no match */
95139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    for (i = 0; i < picoNumSupportedVocs; i ++)
95239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
95339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (strcmp(lang, picoSupportedLangIso3[i]) == 0)
95439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
95539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            langIndex = i;
95639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            break;
95739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
95839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
95939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if (langIndex < 0)
96039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
96139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        /* The language isn't supported.    */
96239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        LOGE("TtsEngine::setLanguage called with unsupported language");
96339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        return TTS_FAILURE;
96439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
96539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
96639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Find a match on the country, if there is one.    */
96739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if (country != NULL)
96839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
96939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        countryIndex = -1;
97039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        for (i = langIndex; i < picoNumSupportedVocs; i ++)
97139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
97239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            if (   (strcmp(lang,    picoSupportedLangIso3[i])    == 0)
97339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                && (strcmp(country, picoSupportedCountryIso3[i]) == 0))
97439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                {
97539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                countryIndex = i;
97639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                break;
97739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                }
97839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
97939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
98039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (countryIndex < 0)
98139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
98239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            /* We didn't find a match on the country, but we had a match on the language.
98339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi               Use that language.                                                       */
98439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            LOGI("TtsEngine::setLanguage found matching language(%s) but not matching country(%s).",
98539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                    lang, country);
98639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
98739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        else
98839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
98939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            /* We have a match on both the language and the country.    */
99039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            langIndex = countryIndex;
99139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
99239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
99339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
99439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    return doLanguageSwitchFromLangIndex( langIndex );      /* switch the language  */
99539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi}
99639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
99739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
998b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi/** isLanguageAvailable
999b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi *  Returns the level of support for a language.
1000b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi *  @lang - string with ISO 3 letter language code.
1001b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi *  @country - string with ISO 3 letter country code .
1002b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi *  @variant - string with language variant for that language and country pair.
10039b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi *  return tts_support_result
1004b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi*/
1005b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivitts_support_result TtsEngine::isLanguageAvailable(const char *lang, const char *country,
1006b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi            const char *variant) {
10079b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    int langIndex = -1;
10089b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    int countryIndex = -1;
10099b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    //-------------------------
10109b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    // language matching
10119b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    // if no language specified
10129b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    if (lang == NULL)  {
10139b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        LOGE("TtsEngine::isLanguageAvailable called with no language");
10149b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        return TTS_LANG_NOT_SUPPORTED;
10159b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    }
10169b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
10179b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    // find a match on the language
101839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    for (int i = 0; i < picoNumSupportedVocs; i++)
10199b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    {
10209b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        if (strcmp(lang, picoSupportedLangIso3[i]) == 0) {
10219b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi            langIndex = i;
10229b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi            break;
10239b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        }
10249b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    }
10259b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    if (langIndex < 0) {
10269b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        // language isn't supported
10279b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        LOGV("TtsEngine::isLanguageAvailable called with unsupported language");
10289b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        return TTS_LANG_NOT_SUPPORTED;
10299b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    }
10309b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
10319b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    //-------------------------
10329b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    // country matching
10339b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    // if no country specified
10349b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    if ((country == NULL) || (strlen(country) == 0)) {
10359b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        // check installation of matched language
10369b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        return (hasResourcesForLanguage(langIndex) ? TTS_LANG_AVAILABLE : TTS_LANG_MISSING_DATA);
10379b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    }
1038b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi
10399b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    // find a match on the country
104039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    for (int i = langIndex; i < picoNumSupportedVocs; i++) {
10419b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        if ((strcmp(lang, picoSupportedLangIso3[i]) == 0)
10429b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi                && (strcmp(country, picoSupportedCountryIso3[i]) == 0)) {
10439b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi            countryIndex = i;
10449b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi            break;
10459b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        }
10469b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    }
10479b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    if (countryIndex < 0)  {
10489b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        // we didn't find a match on the country, but we had a match on the language
10499b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        // check installation of matched language
10509b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        return (hasResourcesForLanguage(langIndex) ? TTS_LANG_AVAILABLE : TTS_LANG_MISSING_DATA);
10519b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    } else {
10529b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        // we have a match on the language and the country
10539b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        langIndex = countryIndex;
10549b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        // check installation of matched language + country
10559b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        return (hasResourcesForLanguage(langIndex) ? TTS_LANG_COUNTRY_AVAILABLE : TTS_LANG_MISSING_DATA);
10569b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    }
10579b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
10589b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    // no variants supported in this library, TTS_LANG_COUNTRY_VAR_AVAILABLE cannot be returned.
1059b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi}
1060b8f46add889c597c8c305691b1aa656d68bfa5c8Jean-Michel Trivi
10614eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
1062b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** getLanguage
106354823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi *  Get the currently loaded language - if any.
10649b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi *  @lang - string with current ISO 3 letter language code, empty string if no loaded language.
10659b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi *  @country - string with current ISO 3 letter country code, empty string if no loaded language.
10669b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi *  @variant - string with current language variant, empty string if no loaded language.
1067b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return tts_result
1068b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
10699b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivitts_result TtsEngine::getLanguage(char *language, char *country, char *variant)
10709b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi{
10719b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    if (picoCurrentLangIndex == -1) {
10729b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        strcpy(language, "\0");
10739b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        strcpy(country, "\0");
10749b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        strcpy(variant, "\0");
10759b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    } else {
10765f6105e73f0c74acd10126175d4952ade10a0b05Jean-Michel Trivi        strcpy(language, picoSupportedLangIso3[picoCurrentLangIndex]);
10775f6105e73f0c74acd10126175d4952ade10a0b05Jean-Michel Trivi        strcpy(country, picoSupportedCountryIso3[picoCurrentLangIndex]);
10789b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        // no variant in this implementation
10799b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi        strcpy(variant, "\0");
10809b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    }
10819b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    return TTS_SUCCESS;
10829b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi}
10839b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
10849b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi
10859b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi/** setAudioFormat
10869b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi * sets the audio format to use for synthesis, returns what is actually used.
10879b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi * @encoding - reference to encoding format
10889b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi * @rate - reference to sample rate
10899b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi * @channels - reference to number of channels
10909b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi * return tts_result
10919b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi * */
10929b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivitts_result TtsEngine::setAudioFormat(AudioSystem::audio_format& encoding, uint32_t& rate,
10939b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi            int& channels)
1094b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
10959b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    // ignore the input parameters, the enforced audio parameters are fixed here
10969b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    encoding = AudioSystem::PCM_16_BIT;
10979b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    rate = 16000;
10989b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    channels = 1;
10999b08cc440f25c4722ca112642be87053fc47f918Jean-Michel Trivi    return TTS_SUCCESS;
1100b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
1101b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
110254823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
1103b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** setProperty
110454823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi *  Set property. The supported properties are:  language, rate, pitch and volume.
1105b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @property - name of property to set
1106b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @value - value to set
1107b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @size - size of value
1108b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return tts_result
1109b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
111054823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivitts_result TtsEngine::setProperty( const char * property, const char * value, const size_t size )
1111b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
111239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int rate;
111339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int pitch;
111439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int volume;
111539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
111639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Set a specific property for the engine.
111739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       Supported properties include: language (locale), rate, pitch, volume.    */
111854823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    /* Sanity check */
1119b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (property == NULL)
112039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
1121b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("setProperty called with property NULL");
1122b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_PROPERTY_UNSUPPORTED;
112339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
11244eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
1125b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (value == NULL)
112639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
1127b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("setProperty called with value NULL");
1128b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_VALUE_INVALID;
112939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
11304eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
1131b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (strncmp(property, "language", 8) == 0)
1132b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
113339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        /* Verify it's in correct format.   */
113439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (strlen(value) != 2 && strlen(value) != 6)
113539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
1136b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            LOGE("change language called with incorrect format");
1137b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_VALUE_INVALID;
113839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
11394eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
114039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        /* Try to switch to specified language. */
1141b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (doLanguageSwitch(value) == TTS_FAILURE)
114239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
1143b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            LOGE("failed to load language");
1144b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_FAILURE;
114539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
1146b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        else
114739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
1148b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_SUCCESS;
114939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
1150b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
1151b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    else if (strncmp(property, "rate", 4) == 0)
115239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
115339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        rate = atoi(value);
115439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (rate < PICO_MIN_RATE)
115539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            rate = PICO_MIN_RATE;
115639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (rate > PICO_MAX_RATE)
115739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            rate = PICO_MAX_RATE;
1158b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoProp_currRate = rate;
1159b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_SUCCESS;
116039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
1161b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    else if (strncmp(property, "pitch", 5) == 0)
116239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
116339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        pitch = atoi(value);
116439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (pitch < PICO_MIN_PITCH)
116539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            pitch = PICO_MIN_PITCH;
116639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (pitch > PICO_MAX_PITCH)
116739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            pitch = PICO_MAX_PITCH;
1168b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoProp_currPitch = pitch;
1169b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_SUCCESS;
117039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
1171b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    else if (strncmp(property, "volume", 6) == 0)
117239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
117339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        volume = atoi(value);
117439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (volume < PICO_MIN_VOLUME)
117539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            volume = PICO_MIN_VOLUME;
117639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (volume > PICO_MAX_VOLUME)
117739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            volume = PICO_MAX_VOLUME;
1178b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoProp_currVolume = volume;
1179b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_SUCCESS;
118039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
1181b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
1182b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return TTS_PROPERTY_UNSUPPORTED;
1183b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
1184b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
118554823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
1186b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** getProperty
118754823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi *  Get the property.  Supported properties are:  language, rate, pitch and volume.
1188b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @property - name of property to get
118939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @value    - buffer which will receive value of property
119039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @iosize   - size of value - if size is too small on return this will contain actual size needed
1191b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return tts_result
1192b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
119339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivitts_result TtsEngine::getProperty( const char * property, char * value, size_t * iosize )
1194b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
119539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Get the property for the engine.
119639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi       This property was previously set by setProperty or by default.       */
119754823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    /* sanity check */
1198b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (property == NULL)
119939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
1200b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("getProperty called with property NULL");
1201b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_PROPERTY_UNSUPPORTED;
120239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
12034eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
1204b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (value == NULL)
120539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
1206b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("getProperty called with value NULL");
1207b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_VALUE_INVALID;
120839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
12094eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
1210b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (strncmp(property, "language", 8) == 0)
1211b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
121239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        if (picoProp_currLang == NULL)
121339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
1214b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            strcpy(value, "");
121539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
1216b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        else
1217b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            {
121839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            if (*iosize < strlen(picoProp_currLang)+1)
121939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                {
1220b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                *iosize = strlen(picoProp_currLang) + 1;
1221b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                return TTS_PROPERTY_SIZE_TOO_SMALL;
122239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                }
1223b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            strcpy(value, picoProp_currLang);
122439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
1225b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_SUCCESS;
122639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
1227b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    else if (strncmp(property, "rate", 4) == 0)
122839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
1229b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        char tmprate[4];
1230b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        sprintf(tmprate, "%d", picoProp_currRate);
1231b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (*iosize < strlen(tmprate)+1)
1232b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
1233b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            *iosize = strlen(tmprate) + 1;
1234b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_PROPERTY_SIZE_TOO_SMALL;
1235b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
1236b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcpy(value, tmprate);
1237b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_SUCCESS;
123839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
1239b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    else if (strncmp(property, "pitch", 5) == 0)
124039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
1241b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        char tmppitch[4];
1242b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        sprintf(tmppitch, "%d", picoProp_currPitch);
1243b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (*iosize < strlen(tmppitch)+1)
1244b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
1245b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            *iosize = strlen(tmppitch) + 1;
1246b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_PROPERTY_SIZE_TOO_SMALL;
1247b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
1248b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcpy(value, tmppitch);
1249b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_SUCCESS;
125039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
1251b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    else if (strncmp(property, "volume", 6) == 0)
125239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
1253b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        char tmpvol[4];
1254b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        sprintf(tmpvol, "%d", picoProp_currVolume);
1255b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (*iosize < strlen(tmpvol)+1)
125639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
1257b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            *iosize = strlen(tmpvol) + 1;
1258b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_PROPERTY_SIZE_TOO_SMALL;
125939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
1260b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcpy(value, tmpvol);
1261b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_SUCCESS;
126239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
126339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
126439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Unknown property */
126539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    LOGE("Unsupported property");
126639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    return TTS_PROPERTY_UNSUPPORTED;
1267b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
1268b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
126954823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
1270b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** synthesizeText
127154823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi *  Synthesizes a text string.
127239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  The text string could be annotated with SSML tags.
127339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @text     - text to synthesize
127439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi *  @buffer   - buffer which will receive generated samples
1275b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @bufferSize - size of buffer
1276b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @userdata - pointer to user data which will be passed back to callback function
1277b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return tts_result
1278b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
127939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivitts_result TtsEngine::synthesizeText( const char * text, int8_t * buffer, size_t bufferSize, void * userdata )
1280b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
128139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int         err;
128239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    int         cbret;
128339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    pico_Char * inp = NULL;
128439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    pico_Char * local_text = NULL;
128539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    short       outbuf[MAX_OUTBUF_SIZE/2];
128639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    pico_Int16  bytes_sent, bytes_recv, text_remaining, out_data_type;
1287b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    pico_Status ret;
128839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    SvoxSsmlParser * parser = NULL;
12894eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
129039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoSynthAbort = 0;
1291b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (text == NULL)
129239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
1293b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("synthesizeText called with NULL string");
1294b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
129539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
12964eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
1297b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (buffer == NULL)
129839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        {
1299b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("synthesizeText called with NULL buffer");
1300b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
130139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        }
13024eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
130339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if ((strncmp(text, "<speak", 6) == 0) ||
130439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        (strncmp(text, "<?xml",  5) == 0)   )
130539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {
130639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      /* SSML input */
130739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      parser = new SvoxSsmlParser();
130839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      if (parser && parser->initSuccessful())
130939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      {
131039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    err = parser->parseDocument(text, 1);
131139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if (err == XML_STATUS_ERROR)
131239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {
131339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      LOGI("Warning: SSML document parsed with errors");
131439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    }
131539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    char * parsed_text = parser->getParsedDocument();
131639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if (parsed_text)
131739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {
131839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      /* Add property tags to the string - if any.    */
131939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      local_text = (pico_Char *) doAddProperties( parsed_text );
132039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      if (!local_text)
132139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      {
132239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        LOGE("Failed to allocate memory for text string");
132339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        delete parser;
132439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        return TTS_FAILURE;
132539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      }
132639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      char * lang = parser->getParsedDocumentLanguage();
132739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      if (doLanguageSwitch(lang) == TTS_FAILURE)
132839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      {
132939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        LOGE("Failed to switch to language specified in SSML document.");
133039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        delete parser;
133139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        return TTS_FAILURE;
133239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      }
133339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      delete parser;
133439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    }
133539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    else
133639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    {
133739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      LOGE("Failed to parse SSML document");
133839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      delete parser;
133939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      return TTS_FAILURE;
134039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    }
134139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      }
134239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      else
134339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      {
134439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    LOGE("Failed to create SSML parser");
134539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if (parser) delete parser;
134639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    return TTS_FAILURE;
134739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      }
134839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    }
134939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    else
1350b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
135139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      /* Add property tags to the string - if any.    */
135239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      local_text = (pico_Char *) doAddProperties( text );
135339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      if (!local_text)
135439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      {
1355b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        LOGE("Failed to allocate memory for text string");
1356b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        return TTS_FAILURE;
135739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi      }
1358b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
13594eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
136039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    text_remaining = strlen((const char *) local_text) + 1;
13614eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
136239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    inp = (pico_Char *) local_text;
13634eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
1364b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    size_t bufused = 0;
13654eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
136654823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi    /* synthesis loop   */
1367b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    while (text_remaining)
1368b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    {
1369b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (picoSynthAbort)
137039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
137139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            ret = pico_resetEngine( picoEngine );
1372b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            break;
137339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
13744eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
137554823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi        /* Feed the text into the engine.   */
137639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        ret = pico_putTextUtf8( picoEngine, inp, text_remaining, &bytes_sent );
1377b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (ret != PICO_OK)
137839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            {
1379b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            LOGE("Error synthesizing string '%s': [%d]", text, ret);
138039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            if (local_text)
138139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                free( local_text );
1382b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_FAILURE;
138339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            }
13844eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
1385b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        text_remaining -= bytes_sent;
1386b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        inp += bytes_sent;
1387b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        do
1388b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
1389b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if (picoSynthAbort)
1390b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            {
1391b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                break;
1392b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
139354823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi            /* Retrieve the samples and add them to the buffer. */
139439358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            ret = pico_getData( picoEngine, (void *) outbuf, MAX_OUTBUF_SIZE, &bytes_recv, &out_data_type );
1395b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if (bytes_recv)
1396b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                {
139739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                if ((bufused + bytes_recv) <= bufferSize)
139839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                    {
139939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                    memcpy(buffer+bufused, (int8_t *) outbuf, bytes_recv);
1400b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    bufused += bytes_recv;
140139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                    }
1402b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                else
140339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                    {
140454823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi                    /* The buffer filled; pass this on to the callback function.    */
140539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                    cbret = picoSynthDoneCBPtr(userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_PENDING);
1406b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    if (cbret == TTS_CALLBACK_HALT)
140739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                        {
1408b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        LOGI("Halt requested by caller. Halting.");
1409b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        picoSynthAbort = 1;
1410b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                        break;
141139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                        }
1412b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    bufused = 0;
141339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                    memcpy(buffer, (int8_t *) outbuf, bytes_recv);
14144eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi                    bufused += bytes_recv;
141539358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi                    }
1416b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                }
1417b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        } while (PICO_STEP_BUSY == ret);
14184eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
141939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        /* This chunk of synthesis is finished; pass the remaining samples.
142054823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi           Use 16 KHz, 16-bit samples.                                              */
1421b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (!picoSynthAbort)
1422b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
142339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            picoSynthDoneCBPtr( userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_PENDING);
1424b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
1425b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picoSynthAbort = 0;
14264eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
1427b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (ret != PICO_STEP_IDLE)
1428b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        {
1429b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            LOGE("Error occurred during synthesis [%d]", ret);
1430b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if (local_text) free(local_text);
143139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            LOGV("Synth loop: sending TTS_SYNTH_DONE after error");
143239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi            picoSynthDoneCBPtr( userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_DONE);
1433b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return TTS_FAILURE;
1434b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
1435b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
143639358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi
143739358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    /* Synthesis is done; notify the caller */
143839358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    LOGV("Synth loop: sending TTS_SYNTH_DONE after all done, or was asked to stop");
143939358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    picoSynthDoneCBPtr( userdata, 16000, AudioSystem::PCM_16_BIT, 1, buffer, bufused, TTS_SYNTH_DONE);
14404eea6515d68b88ebd2215309283d467b3212aa2bJean-Michel Trivi
144139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    if (local_text) {
144239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi        free( local_text );
144339358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    }
1444b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return TTS_SUCCESS;
1445b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
1446b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
144754823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
1448b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** synthesizeIpa
144954823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi *  Synthesizes a phonetic string in IPA format.
145039358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    The Pico engine understands only XSAMPA, so the IPA must be converted.
145139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    The string must also be parceled into words since it can only hanlde a word at a time.
145239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    Each phonemic word must be wrapped with a tag.
1453b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @ipa - phonetic string to synthesize
1454b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @buffer - buffer which will receive generated samples
1455b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @bufferSize - size of buffer
1456b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  @userdata - pointer to user data which will be passed back to callback function
1457b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return tts_result
1458b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
145954823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivitts_result TtsEngine::synthesizeIpa( const char * ipa, int8_t * buffer, size_t bufferSize, void * userdata )
1460b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
146139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    // deprecated call
146239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivi    return TTS_FAILURE;
146354823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
1464b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
1465b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
146654823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
1467b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/** stop
146854823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi *  Aborts the running synthesis.
1469b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *  return tts_result
1470b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen*/
147139358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel Trivitts_result TtsEngine::stop( void )
1472b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
1473b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picoSynthAbort = 1;
1474b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return TTS_SUCCESS;
1475b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
1476b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
147754823983fdcb4ee88d9a6c4e680ff2064dd95929Jean-Michel Trivi
1478b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#ifdef __cplusplus
1479b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenextern "C" {
1480b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
1481b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
148239358f0dacad8cece6c2d3ef1055030f57090c79Jean-Michel TriviTtsEngine * getTtsEngine( void )
1483b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
1484b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return new TtsEngine();
1485b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
1486b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
1487b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#ifdef __cplusplus
1488b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
1489b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
1490b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
1491