1 /*
2 * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include "svox_ssml_parser.h"
19 #include <utils/Log.h>
20 #include <cutils/jstring.h>
21 #include <string.h>
22 #include <utils/String16.h>
23
24 #define SSML_PITCH_XLOW "50"
25 #define SSML_PITCH_LOW "75"
26 #define SSML_PITCH_MEDIUM "100"
27 #define SSML_PITCH_HIGH "150"
28 #define SSML_PITCH_XHIGH "200"
29 #define SSML_RATE_XSLOW "30"
30 #define SSML_RATE_SLOW "60"
31 #define SSML_RATE_MEDIUM "100"
32 #define SSML_RATE_FAST "250"
33 #define SSML_RATE_XFAST "500"
34 #define SSML_VOLUME_SILENT "0"
35 #define SSML_VOLUME_XLOW "25"
36 #define SSML_VOLUME_LOW "70"
37 #define SSML_VOLUME_MEDIUM "120"
38 #define SSML_VOLUME_LOUD "300"
39 #define SSML_VOLUME_XLOUD "450"
40 #define SSML_BREAK_NONE "0ms"
41 #define SSML_BREAK_XWEAK "100ms"
42 #define SSML_BREAK_WEAK "300ms"
43 #define SSML_BREAK_MEDIUM "600ms"
44 #define SSML_BREAK_STRONG "1s"
45 #define SSML_BREAK_XSTRONG "3s"
46
47 extern int cnvIpaToXsampa(const char16_t* ipaString, size_t ipaStringSize, char** outXsampaString);
48 extern char * createPhonemeString( const char * xsampa, int length );
49
SvoxSsmlParser()50 SvoxSsmlParser::SvoxSsmlParser() : m_isInBreak(0), m_appendix(NULL), m_docLanguage(NULL)
51 {
52 mParser = XML_ParserCreate("UTF-8");
53 if (mParser)
54 {
55 XML_SetElementHandler(mParser, starttagHandler, endtagHandler);
56 XML_SetCharacterDataHandler(mParser, textHandler);
57 XML_SetUserData(mParser, (void*)this);
58 m_datasize = 512;
59 m_data = new char[m_datasize];
60 if (!m_data)
61 {
62 ALOGE("Error: failed to allocate memory for string!\n");
63 } else {
64 memset(m_data, 0, m_datasize);
65 }
66 }
67 }
68
~SvoxSsmlParser()69 SvoxSsmlParser::~SvoxSsmlParser()
70 {
71 if (mParser)
72 XML_ParserFree(mParser);
73 if (m_data)
74 delete [] m_data;
75 if (m_appendix)
76 delete [] m_appendix;
77 if (m_docLanguage)
78 delete [] m_docLanguage;
79 }
80
initSuccessful()81 int SvoxSsmlParser::initSuccessful()
82 {
83 return (mParser && m_data);
84 }
85
parseDocument(const char * ssmldoc,int isFinal)86 int SvoxSsmlParser::parseDocument(const char* ssmldoc, int isFinal)
87 {
88 int doclen = (int)strlen(ssmldoc) + 1;
89 int status = XML_Parse(mParser, ssmldoc, doclen, isFinal);
90 if (status == XML_STATUS_ERROR)
91 {
92 /* Note: for some reason Expat almost always complains about invalid tokens, even when document is well formed */
93 ALOGI("Parser error at line %d: %s\n", (int)XML_GetCurrentLineNumber(mParser), XML_ErrorString(XML_GetErrorCode(mParser)));
94 }
95 return status;
96 }
97
getParsedDocument()98 char* SvoxSsmlParser::getParsedDocument()
99 {
100 return m_data;
101 }
102
getParsedDocumentLanguage()103 char* SvoxSsmlParser::getParsedDocumentLanguage()
104 {
105 return m_docLanguage;
106 }
107
starttagHandler(void * data,const XML_Char * element,const XML_Char ** attributes)108 void SvoxSsmlParser::starttagHandler(void* data, const XML_Char* element, const XML_Char** attributes)
109 {
110 ((SvoxSsmlParser*)data)->startElement(element, attributes);
111 }
112
startElement(const XML_Char * element,const XML_Char ** attributes)113 void SvoxSsmlParser::startElement(const XML_Char* element, const XML_Char** attributes)
114 {
115 if (strcmp(element, "speak") == 0)
116 {
117 if (strlen(m_data) > 0)
118 {
119 /* we have old data, get rid of it and reallocate memory */
120 delete m_data;
121 m_data = NULL;
122 m_datasize = 512;
123 m_data = new char[m_datasize];
124 if (!m_data)
125 {
126 ALOGE("Error: failed to allocate memory for string!\n");
127 return;
128 } else {
129 memset(m_data, 0, m_datasize);
130 }
131 }
132
133 /* the only attribute supported in the speak tag is xml:lang, all others are ignored */
134 for (int i = 0; attributes[i]; i += 2)
135 {
136 if (strcmp(attributes[i], "xml:lang") == 0)
137 {
138 if (!m_docLanguage)
139 {
140 m_docLanguage = new char[strlen(attributes[i+1])+1];
141 }
142 strcpy(m_docLanguage, attributes[i+1]);
143 break;
144 }
145 }
146 }
147 else if (strcmp(element, "p") == 0) /* currently no attributes are supported for <p> */
148 {
149 if (strlen(m_data) + 4 > (size_t)m_datasize)
150 {
151 if (!growDataSize(100))
152 {
153 ALOGE("Error: failed to allocate memory for string!\n");
154 return;
155 }
156 }
157 strcat(m_data, "<p>");
158 }
159 else if (strcmp(element, "s") == 0) /* currently no attributes are supported for <s> */
160 {
161 if (strlen(m_data) + 4 > (size_t)m_datasize)
162 {
163 if (!growDataSize(100))
164 {
165 ALOGE("Error: failed to allocate memory for string!\n");
166 return;
167 }
168 }
169 strcat(m_data, "<s>");
170 }
171 else if (strcmp(element, "phoneme") == 0) /* only ipa and xsampa alphabets are supported */
172 {
173 int alpha = 1; /* set to 1 if alphabet is ipa */
174 int tagComplete = 0; /* set to 1 if phoneme tag has already been added */
175 char16_t* ph = NULL;
176 char* xsampastr = NULL;
177 size_t phsize = 0;
178 size_t xsampasize = 0;
179
180 for (int i = 0; attributes[i]; i += 2)
181 {
182 if (strcmp(attributes[i], "alphabet") == 0)
183 {
184 if (strcmp(attributes[i+1], "xsampa") == 0)
185 {
186 alpha = 0;
187 }
188 }
189 if (strcmp(attributes[i], "ph") == 0)
190 {
191 ph = new char16_t[strlen8to16(attributes[i+1]) + 1];
192 ph = strdup8to16(attributes[i+1], &phsize);
193 }
194 }
195 if (!ph)
196 {
197 /* error, no phonetic string */
198 ALOGE("Error: bad SSML syntax, ph attribute not supplied.");
199 return;
200 }
201
202 if (alpha)
203 {
204 /* need to convert phoneme string to xsampa */
205 xsampasize = cnvIpaToXsampa(ph, phsize, &xsampastr);
206 delete [] ph;
207 if (!xsampastr)
208 {
209 ALOGE("Error: failed to allocate memory for IPA string conversion");
210 return;
211 }
212 }
213 else
214 {
215 xsampastr = strndup16to8(ph, phsize);
216 xsampasize = strlen(xsampastr);
217 delete [] ph;
218 }
219
220 /* split XSAMPA string into multiple phonemes if needed */
221 if (strstr(xsampastr, " ") || strstr(xsampastr, "#")) /* check again to see if we have multiple words */
222 {
223 char* phonstr = createPhonemeString(xsampastr, strlen(xsampastr) + 1);
224 free(xsampastr);
225 xsampastr = NULL;
226 xsampastr = (char*)malloc(strlen(phonstr) + 1);
227 strcpy(xsampastr, phonstr);
228 free(phonstr);
229 phonstr = NULL;
230 tagComplete = 1;
231 }
232
233 if (tagComplete)
234 {
235 if (strlen(m_data) + strlen(xsampastr) + 1 > (size_t)m_datasize)
236 {
237 if (!growDataSize(100))
238 {
239 ALOGE("Error: failed to allocate memory for string!");
240 free(xsampastr);
241 return;
242 }
243 }
244 }
245 else
246 {
247 if (strlen(m_data) + strlen(xsampastr) + 17 > (size_t)m_datasize)
248 {
249 if (!growDataSize(100))
250 {
251 ALOGE("Error: failed to allocate memory for string!");
252 free(xsampastr);
253 return;
254 }
255 }
256 strcat(m_data, "<phoneme ph='");
257 }
258
259 strcat(m_data, xsampastr);
260 free(xsampastr);
261
262 if (!tagComplete)
263 {
264 if (strlen(m_data) + 4 > (size_t)m_datasize)
265 {
266 if (!growDataSize(100))
267 {
268 ALOGE("Error: failed to allocate memory for string!\n");
269 return;
270 }
271 }
272 strcat(m_data, "'/>");
273 }
274
275 m_isInBreak = 1; /* set flag to indicate any text between open and close tag is to be discarded */
276 }
277 else if (strcmp(element, "break") == 0)
278 {
279 if (strlen(m_data) + 17 > (size_t)m_datasize)
280 {
281 if (!growDataSize(100))
282 {
283 ALOGE("Error: failed to allocate memory for string!\n");
284 return;
285 }
286 }
287 strcat(m_data, "<break time='");
288 char* time = NULL;
289
290 for (int i = 0; attributes[i]; i += 2)
291 {
292 if (strcmp(attributes[i], "time") == 0)
293 {
294 time = new char[strlen(attributes[i+1]) + 1];
295 if (!time)
296 {
297 ALOGE("Error: failed to allocate memory for string!\n");
298 return;
299 }
300 strcpy(time, attributes[i+1]);
301 }
302 else if (strcmp(attributes[i], "strength") == 0 && !time)
303 {
304 time = convertBreakStrengthToTime(attributes[i+1]);
305 }
306 }
307 if (!time)
308 {
309 time = new char[6];
310 if (!time)
311 {
312 ALOGE("Error: failed to allocate memory for string!\n");
313 return;
314 }
315 strcpy(time, SSML_BREAK_WEAK); /* if no time or strength attributes are specified, default to weak break */
316 }
317 if (strlen(m_data) + strlen(time) + 4 > (size_t)m_datasize)
318 {
319 if (!growDataSize(100))
320 {
321 ALOGE("Error: failed to allocate memory for string!\n");
322 return;
323 }
324 }
325 strcat(m_data, time);
326 strcat(m_data, "'/>");
327 m_isInBreak = 1; /* set flag to indicate any text between open and close tag is to be discarded */
328 }
329 else if (strcmp(element, "prosody") == 0) /* only pitch, rate and volume attributes are supported */
330 {
331 for (int i = 0; attributes[i]; i += 2)
332 {
333 if (strcmp(attributes[i], "pitch") == 0)
334 {
335 char* svoxpitch = convertToSvoxPitch(attributes[i+1]);
336 if (!svoxpitch)
337 {
338 ALOGE("Error: failed to allocate memory for string!\n");
339 return;
340 }
341 if (!svoxpitch)
342 {
343 svoxpitch = new char[4];
344 if (!svoxpitch)
345 {
346 ALOGE("Error: failed to allocate memory for string!\n");
347 return;
348 }
349 strcpy(svoxpitch, "100");
350 }
351 char* pitch = new char[17 + strlen(svoxpitch)];
352 if (!pitch)
353 {
354 ALOGE("Error: failed to allocate memory for string!\n");
355 return;
356 }
357 sprintf(pitch, "<pitch level='%s'>", svoxpitch);
358 if (strlen(m_data) + strlen(pitch) + 1 > (size_t)m_datasize)
359 {
360 if (!growDataSize(100))
361 {
362 ALOGE("Error: failed to allocate memory for string!\n");
363 return;
364 }
365 }
366 strcat(m_data, pitch);
367 if (!m_appendix)
368 {
369 m_appendix = new char[30];
370 m_appendix[0] = '\0';
371 }
372 strcat(m_appendix, "</pitch>");
373 delete [] svoxpitch;
374 delete [] pitch;
375 }
376 else if (strcmp(attributes[i], "rate") == 0)
377 {
378 char* svoxrate = convertToSvoxRate(attributes[i+1]);
379 if (!svoxrate)
380 {
381 svoxrate = new char[4];
382 if (!svoxrate)
383 {
384 ALOGE("Error: failed to allocate memory for string!\n");
385 return;
386 }
387 strcpy(svoxrate, "100");
388 }
389 char* rate = new char[17 + strlen(svoxrate)];
390 if (!rate)
391 {
392 ALOGE("Error: failed to allocate memory for string!\n");
393 return;
394 }
395 sprintf(rate, "<speed level='%s'>", svoxrate);
396 if (strlen(m_data) + strlen(rate) + 1 > (size_t)m_datasize)
397 {
398 if (!growDataSize(100))
399 {
400 ALOGE("Error: failed to allocate memory for string!\n");
401 return;
402 }
403 }
404 strcat(m_data, rate);
405 if (!m_appendix)
406 {
407 m_appendix = new char[30];
408 if (!m_appendix)
409 {
410 ALOGE("Error: failed to allocate memory for string!\n");
411 return;
412 }
413 m_appendix[0] = '\0';
414 }
415 strcat(m_appendix, "</speed>");
416 delete [] svoxrate;
417 delete [] rate;
418 }
419 else if (strcmp(attributes[i], "volume") == 0)
420 {
421 char* svoxvol = convertToSvoxVolume(attributes[i+1]);
422 if (!svoxvol)
423 {
424 svoxvol = new char[4];
425 if (!svoxvol)
426 {
427 ALOGE("Error: failed to allocate memory for string!\n");
428 return;
429 }
430 strcpy(svoxvol, "100");
431 }
432 char* volume = new char[18 + strlen(svoxvol)];
433 if (!volume)
434 {
435 ALOGE("Error: failed to allocate memory for string!\n");
436 return;
437 }
438 sprintf(volume, "<volume level='%s'>", svoxvol);
439 if (strlen(m_data) + strlen(volume) + 1 > (size_t)m_datasize)
440 {
441 if (!growDataSize(100))
442 {
443 ALOGE("Error: failed to allocate memory for string!\n");
444 return;
445 }
446 }
447 strcat(m_data, volume);
448 if (!m_appendix)
449 {
450 m_appendix = new char[30];
451 m_appendix[0] = '\0';
452 }
453 strcat(m_appendix, "</volume>");
454 delete [] svoxvol;
455 delete [] volume;
456 }
457 }
458 }
459 else if (strcmp(element, "audio") == 0) /* only 16kHz 16bit wav files are supported as src */
460 {
461 if (strlen(m_data) + 17 > (size_t)m_datasize)
462 {
463 if (!growDataSize(100))
464 {
465 ALOGE("Error: failed to allocate memory for string!\n");
466 return;
467 }
468 }
469 strcat(m_data, "<usesig file='");
470
471 for (int i = 0; attributes[i]; i += 2)
472 {
473 if (strcmp(attributes[i], "src") == 0)
474 {
475 if (strlen(m_data) + strlen(attributes[i+1]) + 1 > (size_t)m_datasize)
476 {
477 if (!growDataSize(100))
478 {
479 ALOGE("Error: failed to allocate memory for string!\n");
480 return;
481 }
482 }
483 strcat(m_data, attributes[i+1]);
484 }
485 }
486 strcat(m_data, "'>");
487 }
488 }
489
endtagHandler(void * data,const XML_Char * element)490 void SvoxSsmlParser::endtagHandler(void* data, const XML_Char* element)
491 {
492 ((SvoxSsmlParser*)data)->endElement(element);
493 }
494
endElement(const XML_Char * element)495 void SvoxSsmlParser::endElement(const XML_Char* element)
496 {
497 if (strcmp(element, "speak") == 0)
498 {
499 /* do nothing */
500 }
501 else if (strcmp(element, "p") == 0)
502 {
503 if (strlen(m_data) + 5 > (size_t)m_datasize)
504 {
505 if (!growDataSize(100))
506 {
507 ALOGE("Error: failed to allocate memory for string!\n");
508 return;
509 }
510 }
511 strcat(m_data, "</p>");
512 }
513 else if (strcmp(element, "s") == 0)
514 {
515 if (strlen(m_data) + 5 > (size_t)m_datasize)
516 {
517 if (!growDataSize(100))
518 {
519 ALOGE("Error: failed to allocate memory for string!\n");
520 return;
521 }
522 }
523 strcat(m_data, "</s>");
524 }
525 else if (strcmp(element, "phoneme") == 0)
526 {
527 m_isInBreak = 0; /* indicate we are no longer in phoneme tag */
528 }
529 else if (strcmp(element, "break") == 0)
530 {
531 m_isInBreak = 0; /* indicate we are no longer in break tag */
532 }
533 else if (strcmp(element, "prosody") == 0)
534 {
535 if (m_appendix)
536 {
537 if (strlen(m_data) + strlen(m_appendix) + 1 > (size_t)m_datasize)
538 {
539 if (!growDataSize(100))
540 {
541 ALOGE("Error: failed to allocate memory for string!\n");
542 return;
543 }
544 }
545 strcat(m_data, m_appendix);
546 delete [] m_appendix;
547 m_appendix = NULL;
548 }
549 }
550 else if (strcmp(element, "audio") == 0)
551 {
552 if (strlen(m_data) + 10 > (size_t)m_datasize)
553 {
554 if (!growDataSize(100))
555 {
556 ALOGE("Error: failed to allocate memory for string!\n");
557 return;
558 }
559 }
560 strcat(m_data, "</usesig>");
561 }
562 }
563
textHandler(void * data,const XML_Char * text,int length)564 void SvoxSsmlParser::textHandler(void* data, const XML_Char* text, int length)
565 {
566 ((SvoxSsmlParser*)data)->textElement(text, length);
567 }
568
textElement(const XML_Char * text,int length)569 void SvoxSsmlParser::textElement(const XML_Char* text, int length)
570 {
571 if (m_isInBreak)
572 {
573 return; /* handles the case when someone has added text inside the break or phoneme tag - this text is thrown away */
574 }
575
576 char* content = new char[length + 1];
577 if (!content)
578 {
579 ALOGE("Error: failed to allocate memory for string!\n");
580 return;
581 }
582 strncpy(content, text, length);
583 content[length] = '\0';
584
585 if (strlen(m_data) + strlen(content) + 1 > (size_t)m_datasize)
586 {
587 if (!growDataSize(100))
588 {
589 ALOGE("Error: failed to allocate memory for string!\n");
590 return;
591 }
592 }
593 strcat(m_data, content);
594 delete [] content;
595 }
596
597 /**
598 convertToSvoxPitch
599 Converts SSML pitch labels to SVOX pitch levels
600 */
convertToSvoxPitch(const char * value)601 char* SvoxSsmlParser::convertToSvoxPitch(const char* value)
602 {
603 char* converted = NULL;
604 if (strcmp(value, "x-low") == 0)
605 {
606 converted = new char[4];
607 if (!converted)
608 {
609 ALOGE("Error: failed to allocate memory for string!\n");
610 return NULL;
611 }
612 strcpy(converted, SSML_PITCH_XLOW);
613 }
614 else if (strcmp(value, "low") == 0)
615 {
616 converted = new char[4];
617 if (!converted)
618 {
619 ALOGE("Error: failed to allocate memory for string!\n");
620 return NULL;
621 }
622 strcpy(converted, SSML_PITCH_LOW);
623 }
624 else if (strcmp(value, "medium") == 0)
625 {
626 converted = new char[4];
627 if (!converted)
628 {
629 ALOGE("Error: failed to allocate memory for string!\n");
630 return NULL;
631 }
632 strcpy(converted, SSML_PITCH_MEDIUM);
633 }
634 else if (strcmp(value, "default") == 0)
635 {
636 converted = new char[4];
637 if (!converted)
638 {
639 ALOGE("Error: failed to allocate memory for string!\n");
640 return NULL;
641 }
642 strcpy(converted, SSML_PITCH_MEDIUM);
643 }
644 else if (strcmp(value, "high") == 0)
645 {
646 converted = new char[4];
647 if (!converted)
648 {
649 ALOGE("Error: failed to allocate memory for string!\n");
650 return NULL;
651 }
652 strcpy(converted, SSML_PITCH_HIGH);
653 }
654 else if (strcmp(value, "x-high") == 0)
655 {
656 converted = new char[4];
657 if (!converted)
658 {
659 ALOGE("Error: failed to allocate memory for string!\n");
660 return NULL;
661 }
662 strcpy(converted, SSML_PITCH_XHIGH);
663 }
664 return converted;
665 }
666
667 /**
668 convertToSvoxRate
669 Converts SSML rate labels to SVOX speed levels
670 */
convertToSvoxRate(const char * value)671 char* SvoxSsmlParser::convertToSvoxRate(const char* value)
672 {
673 char* converted = NULL;
674 if (strcmp(value, "x-slow") == 0)
675 {
676 converted = new char[4];
677 if (!converted)
678 {
679 ALOGE("Error: failed to allocate memory for string!\n");
680 return NULL;
681 }
682 strcpy(converted, SSML_RATE_XSLOW);
683 }
684 else if (strcmp(value, "slow") == 0)
685 {
686 converted = new char[4];
687 if (!converted)
688 {
689 ALOGE("Error: failed to allocate memory for string!\n");
690 return NULL;
691 }
692 strcpy(converted, SSML_RATE_SLOW);
693 }
694 else if (strcmp(value, "medium") == 0)
695 {
696 converted = new char[4];
697 if (!converted)
698 {
699 ALOGE("Error: failed to allocate memory for string!\n");
700 return NULL;
701 }
702 strcpy(converted, SSML_RATE_MEDIUM);
703 }
704 else if (strcmp(value, "default") == 0)
705 {
706 converted = new char[4];
707 if (!converted)
708 {
709 ALOGE("Error: failed to allocate memory for string!\n");
710 return NULL;
711 }
712 strcpy(converted, SSML_RATE_MEDIUM);
713 }
714 else if (strcmp(value, "fast") == 0)
715 {
716 converted = new char[4];
717 if (!converted)
718 {
719 ALOGE("Error: failed to allocate memory for string!\n");
720 return NULL;
721 }
722 strcpy(converted, SSML_RATE_FAST);
723 }
724 else if (strcmp(value, "x-fast") == 0)
725 {
726 converted = new char[4];
727 if (!converted)
728 {
729 ALOGE("Error: failed to allocate memory for string!\n");
730 return NULL;
731 }
732 strcpy(converted, SSML_RATE_XFAST);
733 }
734 return converted;
735 }
736
737 /**
738 convertToSvoxVolume
739 Converts SSML volume labels to SVOX volume levels
740 */
convertToSvoxVolume(const char * value)741 char* SvoxSsmlParser::convertToSvoxVolume(const char* value)
742 {
743 char* converted = NULL;
744 if (strcmp(value, "silent") == 0)
745 {
746 converted = new char[4];
747 if (!converted)
748 {
749 ALOGE("Error: failed to allocate memory for string!\n");
750 return NULL;
751 }
752 strcpy(converted, SSML_VOLUME_SILENT);
753 }
754 else if (strcmp(value, "x-low") == 0)
755 {
756 converted = new char[4];
757 if (!converted)
758 {
759 ALOGE("Error: failed to allocate memory for string!\n");
760 return NULL;
761 }
762 strcpy(converted, SSML_VOLUME_XLOW);
763 }
764 else if (strcmp(value, "low") == 0)
765 {
766 converted = new char[4];
767 if (!converted)
768 {
769 ALOGE("Error: failed to allocate memory for string!\n");
770 return NULL;
771 }
772 strcpy(converted, SSML_VOLUME_LOW);
773 }
774 else if (strcmp(value, "medium") == 0)
775 {
776 converted = new char[4];
777 if (!converted)
778 {
779 ALOGE("Error: failed to allocate memory for string!\n");
780 return NULL;
781 }
782 strcpy(converted, SSML_VOLUME_MEDIUM);
783 }
784 else if (strcmp(value, "default") == 0)
785 {
786 converted = new char[4];
787 if (!converted)
788 {
789 ALOGE("Error: failed to allocate memory for string!\n");
790 return NULL;
791 }
792 strcpy(converted, SSML_VOLUME_MEDIUM);
793 }
794 else if (strcmp(value, "loud") == 0)
795 {
796 converted = new char[4];
797 if (!converted)
798 {
799 ALOGE("Error: failed to allocate memory for string!\n");
800 return NULL;
801 }
802 strcpy(converted, SSML_VOLUME_LOUD);
803 }
804 else if (strcmp(value, "x-loud") == 0)
805 {
806 converted = new char[4];
807 if (!converted)
808 {
809 ALOGE("Error: failed to allocate memory for string!\n");
810 return NULL;
811 }
812 strcpy(converted, SSML_VOLUME_XLOUD);
813 }
814 return converted;
815 }
816
817 /**
818 convertBreakStrengthToTime
819 Converts SSML break strength labels to SVOX break time
820 */
convertBreakStrengthToTime(const char * value)821 char* SvoxSsmlParser::convertBreakStrengthToTime(const char* value)
822 {
823 char* converted = NULL;
824 if (strcmp(value, "none") == 0)
825 {
826 converted = new char[6];
827 if (!converted)
828 {
829 ALOGE("Error: failed to allocate memory for string!\n");
830 return NULL;
831 }
832 strcpy(converted, SSML_BREAK_NONE);
833 }
834 else if (strcmp(value, "x-weak") == 0)
835 {
836 converted = new char[6];
837 if (!converted)
838 {
839 ALOGE("Error: failed to allocate memory for string!\n");
840 return NULL;
841 }
842 strcpy(converted, SSML_BREAK_XWEAK);
843 }
844 else if (strcmp(value, "weak") == 0)
845 {
846 converted = new char[6];
847 if (!converted)
848 {
849 ALOGE("Error: failed to allocate memory for string!\n");
850 return NULL;
851 }
852 strcpy(converted, SSML_BREAK_WEAK);
853 }
854 else if (strcmp(value, "medium") == 0)
855 {
856 converted = new char[6];
857 if (!converted)
858 {
859 ALOGE("Error: failed to allocate memory for string!\n");
860 return NULL;
861 }
862 strcpy(converted, SSML_BREAK_MEDIUM);
863 }
864 else if (strcmp(value, "strong") == 0)
865 {
866 converted = new char[6];
867 if (!converted)
868 {
869 ALOGE("Error: failed to allocate memory for string!\n");
870 return NULL;
871 }
872 strcpy(converted, SSML_BREAK_STRONG);
873 }
874 else if (strcmp(value, "x-strong") == 0)
875 {
876 converted = new char[6];
877 if (!converted)
878 {
879 ALOGE("Error: failed to allocate memory for string!\n");
880 return NULL;
881 }
882 strcpy(converted, SSML_BREAK_XSTRONG);
883 }
884 return converted;
885 }
886
887 /**
888 growDataSize
889 Increases the size of the internal text storage member
890 */
growDataSize(int sizeToGrow)891 int SvoxSsmlParser::growDataSize(int sizeToGrow)
892 {
893 char* tmp = new char[m_datasize];
894 if (!tmp)
895 return 0;
896
897 strcpy(tmp, m_data);
898 delete [] m_data;
899 m_data = NULL;
900 m_data = new char[m_datasize + sizeToGrow];
901 if (!m_data)
902 {
903 m_data = tmp;
904 return 0;
905 }
906 m_datasize += sizeToGrow;
907 strcpy(m_data, tmp);
908 delete [] tmp;
909 tmp = NULL;
910 return 1;
911 }
912