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