• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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