19b6df1b9130d07f2a81b45acd179a5cec042d4b
[feed/packages.git] / sound / svox / patches / 0003-pico2wave-Convert-text-to-.wav-using-svox-text-to-sp.patch
1 From 8bec80dccc9f4fe147a500486813f4e89a0d56d8 Mon Sep 17 00:00:00 2001
2 From: Mathieu Parent <math.parent@gmail.com>
3 Date: Sun, 25 Oct 2009 15:19:01 +0100
4 Subject: [PATCH 3/7] pico2wave: Convert text to .wav using svox text-to-speech system.
5
6 ---
7 pico/.gitignore | 1 +
8 pico/Makefile.am | 7 +
9 pico/bin/pico2wave.c | 341 ++++++++++++++++++++++++++++++++++++++++++++++++++
10 pico/configure.in | 3 +
11 4 files changed, 352 insertions(+), 0 deletions(-)
12 create mode 100644 pico/bin/pico2wave.c
13
14 diff --git a/pico/.gitignore b/pico/.gitignore
15 index 4235569..a110298 100644
16 --- a/pico/.gitignore
17 +++ b/pico/.gitignore
18 @@ -29,4 +29,5 @@ libtool
19 *.lo
20 .libs
21 libttspico.la
22 +pico2wave
23
24 diff --git a/pico/Makefile.am b/pico/Makefile.am
25 index 6d8a10c..0d9472d 100644
26 --- a/pico/Makefile.am
27 +++ b/pico/Makefile.am
28 @@ -34,3 +34,10 @@ libttspico_la_SOURCES = \
29 lib/picotrns.c \
30 lib/picowa.c
31
32 +bin_PROGRAMS = pico2wave
33 +pico2wave_SOURCES = \
34 + bin/pico2wave.c
35 +pico2wave_LDADD = \
36 + libttspico.la -lm -lpopt
37 +pico2wave_CFLAGS = -Wall -I lib
38 +
39 diff --git a/pico/bin/pico2wave.c b/pico/bin/pico2wave.c
40 new file mode 100644
41 index 0000000..0c035a7
42 --- /dev/null
43 +++ b/pico/bin/pico2wave.c
44 @@ -0,0 +1,342 @@
45 +/* pico2wave.c
46 +
47 + * Copyright (C) 2009 Mathieu Parent <math.parent@gmail.com>
48 + *
49 + * Licensed under the Apache License, Version 2.0 (the "License");
50 + * you may not use this file except in compliance with the License.
51 + * You may obtain a copy of the License at
52 + *
53 + * http://www.apache.org/licenses/LICENSE-2.0
54 + *
55 + * Unless required by applicable law or agreed to in writing, software
56 + * distributed under the License is distributed on an "AS IS" BASIS,
57 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
58 + * See the License for the specific language governing permissions and
59 + * limitations under the License.
60 + *
61 + * Convert text to .wav using svox text-to-speech system.
62 + *
63 + */
64 +
65 +
66 +#include <popt.h>
67 +#include <stdio.h>
68 +#include <stdint.h>
69 +#include <stdlib.h>
70 +#include <string.h>
71 +
72 +#include <picoapi.h>
73 +#include <picoapid.h>
74 +#include <picoos.h>
75 +
76 +
77 +/* adaptation layer defines */
78 +#define PICO_MEM_SIZE 2500000
79 +#define DummyLen 100000000
80 +
81 +/* string constants */
82 +#define MAX_OUTBUF_SIZE 128
83 +const char * PICO_LINGWARE_PATH = "./lang/";
84 +const char * PICO_VOICE_NAME = "PicoVoice";
85 +
86 +/* supported voices
87 + Pico does not separately specify the voice and locale. */
88 +const char * picoSupportedLangIso3[] = { "eng", "eng", "deu", "spa", "fra", "ita" };
89 +const char * picoSupportedCountryIso3[] = { "USA", "GBR", "DEU", "ESP", "FRA", "ITA" };
90 +const char * picoSupportedLang[] = { "en-US", "en-GB", "de-DE", "es-ES", "fr-FR", "it-IT" };
91 +const char * picoInternalLang[] = { "en-US", "en-GB", "de-DE", "es-ES", "fr-FR", "it-IT" };
92 +const 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" };
93 +const 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" };
94 +const 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" };
95 +const int picoNumSupportedVocs = 6;
96 +
97 +/* adapation layer global variables */
98 +void * picoMemArea = NULL;
99 +pico_System picoSystem = NULL;
100 +pico_Resource picoTaResource = NULL;
101 +pico_Resource picoSgResource = NULL;
102 +pico_Resource picoUtppResource = NULL;
103 +pico_Engine picoEngine = NULL;
104 +pico_Char * picoTaFileName = NULL;
105 +pico_Char * picoSgFileName = NULL;
106 +pico_Char * picoUtppFileName = NULL;
107 +pico_Char * picoTaResourceName = NULL;
108 +pico_Char * picoSgResourceName = NULL;
109 +pico_Char * picoUtppResourceName = NULL;
110 +int picoSynthAbort = 0;
111 +
112 +
113 +int main(int argc, const char *argv[]) {
114 + char * wavefile = NULL;
115 + char * lang = "en-US";
116 + int langIndex = -1, langIndexTmp = -1;
117 + char * text;
118 + int8_t * buffer;
119 + size_t bufferSize = 256;
120 +
121 + /* Parsing options */
122 + poptContext optCon; /* context for parsing command-line options */
123 + int opt; /* used for argument parsing */
124 +
125 + struct poptOption optionsTable[] = {
126 + { "wave", 'w', POPT_ARG_STRING, &wavefile, 0,
127 + "Write output to this WAV file (extension SHOULD be .wav)", "filename.wav" },
128 + { "lang", 'l', POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &lang, 0,
129 + "Language", "lang" },
130 + POPT_AUTOHELP
131 + POPT_TABLEEND
132 + };
133 + optCon = poptGetContext(NULL, argc, argv, optionsTable, POPT_CONTEXT_POSIXMEHARDER);
134 + poptSetOtherOptionHelp(optCon, "<words>");
135 +
136 + /* Reporting about invalid extra options */
137 + while ((opt = poptGetNextOpt(optCon)) != -1) {
138 + switch (opt) {
139 + default:
140 + fprintf(stderr, "Invalid option %s: %s\n",
141 + poptBadOption(optCon, 0), poptStrerror(opt));
142 + poptPrintHelp(optCon, stderr, 0);
143 + exit(1);
144 + }
145 + }
146 +
147 + /* Mandatory option: --wave */
148 + if(!wavefile) {
149 + fprintf(stderr, "Mandatory option: %s\n\n",
150 + "--wave=filename.wav");
151 + poptPrintHelp(optCon, stderr, 0);
152 + exit(1);
153 + }
154 + /* option: --lang */
155 + for(langIndexTmp =0; langIndexTmp<picoNumSupportedVocs; langIndexTmp++) {
156 + if(!strcmp(picoSupportedLang[langIndexTmp], lang)) {
157 + langIndex = langIndexTmp;
158 + break;
159 + }
160 + }
161 + if(langIndex == -1) {
162 + fprintf(stderr, "Unknown language: %s\nValid languages:\n",
163 + lang);
164 + for(langIndexTmp =0; langIndexTmp<picoNumSupportedVocs; langIndexTmp++) {
165 + fprintf(stderr, "%s\n", picoSupportedLang[langIndexTmp]);
166 + }
167 + lang = "en-US";
168 + fprintf(stderr, "\n");
169 + poptPrintHelp(optCon, stderr, 0);
170 + exit(1);
171 + }
172 +
173 + /* Remaining argument is <words> */
174 + const char **extra_argv;
175 + extra_argv = poptGetArgs(optCon);
176 + if(extra_argv) {
177 + text = (char *) &(*extra_argv)[0];
178 + } else {
179 + //TODO: stdin not supported yet.
180 + fprintf(stderr, "Missing argument: %s\n\n",
181 + "<words>");
182 + poptPrintHelp(optCon, stderr, 0);
183 + exit(1);
184 + }
185 +
186 + poptFreeContext(optCon);
187 +
188 + buffer = malloc( bufferSize );
189 +
190 + int ret, getstatus;
191 + pico_Char * inp = NULL;
192 + pico_Char * local_text = NULL;
193 + short outbuf[MAX_OUTBUF_SIZE/2];
194 + pico_Int16 bytes_sent, bytes_recv, text_remaining, out_data_type;
195 + pico_Retstring outMessage;
196 +
197 + picoSynthAbort = 0;
198 +
199 + picoMemArea = malloc( PICO_MEM_SIZE );
200 + if((ret = pico_initialize( picoMemArea, PICO_MEM_SIZE, &picoSystem ))) {
201 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
202 + fprintf(stderr, "Cannot initialize pico (%i): %s\n", ret, outMessage);
203 + goto terminate;
204 + }
205 +
206 + /* Load the text analysis Lingware resource file. */
207 + picoTaFileName = (pico_Char *) malloc( PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE );
208 + strcpy((char *) picoTaFileName, PICO_LINGWARE_PATH);
209 + strcat((char *) picoTaFileName, (const char *) picoInternalTaLingware[langIndex]);
210 + if((ret = pico_loadResource( picoSystem, picoTaFileName, &picoTaResource ))) {
211 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
212 + fprintf(stderr, "Cannot load text analysis resource file (%i): %s\n", ret, outMessage);
213 + goto unloadTaResource;
214 + }
215 +
216 + /* Load the signal generation Lingware resource file. */
217 + picoSgFileName = (pico_Char *) malloc( PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE );
218 + strcpy((char *) picoSgFileName, PICO_LINGWARE_PATH);
219 + strcat((char *) picoSgFileName, (const char *) picoInternalSgLingware[langIndex]);
220 + if((ret = pico_loadResource( picoSystem, picoSgFileName, &picoSgResource ))) {
221 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
222 + fprintf(stderr, "Cannot load signal generation Lingware resource file (%i): %s\n", ret, outMessage);
223 + goto unloadSgResource;
224 + }
225 +
226 + /* Load the utpp Lingware resource file if exists - NOTE: this file is optional
227 + and is currently not used. Loading is only attempted for future compatibility.
228 + If this file is not present the loading will still succeed. //
229 + picoUtppFileName = (pico_Char *) malloc( PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE );
230 + strcpy((char *) picoUtppFileName, PICO_LINGWARE_PATH);
231 + strcat((char *) picoUtppFileName, (const char *) picoInternalUtppLingware[langIndex]);
232 + ret = pico_loadResource( picoSystem, picoUtppFileName, &picoUtppResource );
233 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
234 + printf("pico_loadResource: %i: %s\n", ret, outMessage);
235 + */
236 +
237 + /* Get the text analysis resource name. */
238 + picoTaResourceName = (pico_Char *) malloc( PICO_MAX_RESOURCE_NAME_SIZE );
239 + if((ret = pico_getResourceName( picoSystem, picoTaResource, (char *) picoTaResourceName ))) {
240 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
241 + fprintf(stderr, "Cannot get the text analysis resource name (%i): %s\n", ret, outMessage);
242 + goto unloadUtppResource;
243 + }
244 +
245 + /* Get the signal generation resource name. */
246 + picoSgResourceName = (pico_Char *) malloc( PICO_MAX_RESOURCE_NAME_SIZE );
247 + if((ret = pico_getResourceName( picoSystem, picoSgResource, (char *) picoSgResourceName ))) {
248 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
249 + fprintf(stderr, "Cannot get the signal generation resource name (%i): %s\n", ret, outMessage);
250 + goto unloadUtppResource;
251 + }
252 +
253 +
254 + /* Create a voice definition. */
255 + if((ret = pico_createVoiceDefinition( picoSystem, (const pico_Char *) PICO_VOICE_NAME ))) {
256 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
257 + fprintf(stderr, "Cannot create voice definition (%i): %s\n", ret, outMessage);
258 + goto unloadUtppResource;
259 + }
260 +
261 + /* Add the text analysis resource to the voice. */
262 + if((ret = pico_addResourceToVoiceDefinition( picoSystem, (const pico_Char *) PICO_VOICE_NAME, picoTaResourceName ))) {
263 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
264 + fprintf(stderr, "Cannot add the text analysis resource to the voice (%i): %s\n", ret, outMessage);
265 + goto unloadUtppResource;
266 + }
267 +
268 + /* Add the signal generation resource to the voice. */
269 + if((ret = pico_addResourceToVoiceDefinition( picoSystem, (const pico_Char *) PICO_VOICE_NAME, picoSgResourceName ))) {
270 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
271 + fprintf(stderr, "Cannot add the signal generation resource to the voice (%i): %s\n", ret, outMessage);
272 + goto unloadUtppResource;
273 + }
274 +
275 + /* Create a new Pico engine. */
276 + if((ret = pico_newEngine( picoSystem, (const pico_Char *) PICO_VOICE_NAME, &picoEngine ))) {
277 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
278 + fprintf(stderr, "Cannot create a new pico engine (%i): %s\n", ret, outMessage);
279 + goto disposeEngine;
280 + }
281 +
282 + local_text = (pico_Char *) text ;
283 + text_remaining = strlen((const char *) local_text) + 1;
284 +
285 + inp = (pico_Char *) local_text;
286 +
287 + size_t bufused = 0;
288 +
289 + picoos_Common common = (picoos_Common) pico_sysGetCommon(picoSystem);
290 +
291 + picoos_SDFile sdOutFile = NULL;
292 +
293 + picoos_bool done = TRUE;
294 + if(TRUE != (done = picoos_sdfOpenOut(common, &sdOutFile,
295 + (picoos_char *) wavefile, SAMPLE_FREQ_16KHZ, PICOOS_ENC_LIN)))
296 + {
297 + fprintf(stderr, "Cannot open output wave file\n");
298 + ret = 1;
299 + goto disposeEngine;
300 + }
301 +
302 + /* synthesis loop */
303 + while (text_remaining) {
304 + /* Feed the text into the engine. */
305 + if((ret = pico_putTextUtf8( picoEngine, inp, text_remaining, &bytes_sent ))) {
306 + pico_getSystemStatusMessage(picoSystem, ret, outMessage);
307 + fprintf(stderr, "Cannot put Text (%i): %s\n", ret, outMessage);
308 + goto disposeEngine;
309 + }
310 +
311 + text_remaining -= bytes_sent;
312 + inp += bytes_sent;
313 +
314 + do {
315 + if (picoSynthAbort) {
316 + goto disposeEngine;
317 + }
318 + /* Retrieve the samples and add them to the buffer. */
319 + getstatus = pico_getData( picoEngine, (void *) outbuf,
320 + MAX_OUTBUF_SIZE, &bytes_recv, &out_data_type );
321 + if((getstatus !=PICO_STEP_BUSY) && (getstatus !=PICO_STEP_IDLE)){
322 + pico_getSystemStatusMessage(picoSystem, getstatus, outMessage);
323 + fprintf(stderr, "Cannot get Data (%i): %s\n", getstatus, outMessage);
324 + goto disposeEngine;
325 + }
326 + if (bytes_recv) {
327 + if ((bufused + bytes_recv) <= bufferSize) {
328 + memcpy(buffer+bufused, (int8_t *) outbuf, bytes_recv);
329 + bufused += bytes_recv;
330 + } else {
331 + done = picoos_sdfPutSamples(
332 + sdOutFile,
333 + bufused / 2,
334 + (picoos_int16*) (buffer));
335 + bufused = 0;
336 + memcpy(buffer, (int8_t *) outbuf, bytes_recv);
337 + bufused += bytes_recv;
338 + }
339 + }
340 + } while (PICO_STEP_BUSY == getstatus);
341 + /* This chunk of synthesis is finished; pass the remaining samples. */
342 + if (!picoSynthAbort) {
343 + done = picoos_sdfPutSamples(
344 + sdOutFile,
345 + bufused / 2,
346 + (picoos_int16*) (buffer));
347 + }
348 + picoSynthAbort = 0;
349 + }
350 +
351 + if(TRUE != (done = picoos_sdfCloseOut(common, &sdOutFile)))
352 + {
353 + fprintf(stderr, "Cannot close output wave file\n");
354 + ret = 1;
355 + goto disposeEngine;
356 + }
357 +
358 +disposeEngine:
359 + if (picoEngine) {
360 + pico_disposeEngine( picoSystem, &picoEngine );
361 + pico_releaseVoiceDefinition( picoSystem, (pico_Char *) PICO_VOICE_NAME );
362 + picoEngine = NULL;
363 + }
364 +unloadUtppResource:
365 + if (picoUtppResource) {
366 + pico_unloadResource( picoSystem, &picoUtppResource );
367 + picoUtppResource = NULL;
368 + }
369 +unloadSgResource:
370 + if (picoSgResource) {
371 + pico_unloadResource( picoSystem, &picoSgResource );
372 + picoSgResource = NULL;
373 + }
374 +unloadTaResource:
375 + if (picoTaResource) {
376 + pico_unloadResource( picoSystem, &picoTaResource );
377 + picoTaResource = NULL;
378 + }
379 +terminate:
380 + if (picoSystem) {
381 + pico_terminate(&picoSystem);
382 + picoSystem = NULL;
383 + }
384 + exit(ret);
385 +}
386 +
387 diff --git a/pico/configure.in b/pico/configure.in
388 index 0afb56d..349eb1d 100644
389 --- a/pico/configure.in
390 +++ b/pico/configure.in
391 @@ -14,3 +14,6 @@ AC_CONFIG_FILES([Makefile])
392 AC_OUTPUT
393
394 AC_CONFIG_MACRO_DIR([m4])
395 +
396 +AC_CHECK_LIB(popt, poptGetContext)
397 +
398 --
399 1.7.1
400