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
47extern int cnvIpaToXsampa(const char16_t* ipaString, size_t ipaStringSize, char** outXsampaString);
48extern char * createPhonemeString( const char * xsampa, int length );
49
50SvoxSsmlParser::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
64SvoxSsmlParser::~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
76int SvoxSsmlParser::initSuccessful()
77{
78    return (mParser && m_data);
79}
80
81int 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        ALOGI("Parser error at line %d: %s\n", (int)XML_GetCurrentLineNumber(mParser), XML_ErrorString(XML_GetErrorCode(mParser)));
89    }
90    return status;
91}
92
93char* SvoxSsmlParser::getParsedDocument()
94{
95    return m_data;
96}
97
98char* SvoxSsmlParser::getParsedDocumentLanguage()
99{
100    return m_docLanguage;
101}
102
103void SvoxSsmlParser::starttagHandler(void* data, const XML_Char* element, const XML_Char** attributes)
104{
105    ((SvoxSsmlParser*)data)->startElement(element, attributes);
106}
107
108void 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                ALOGE("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                ALOGE("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                ALOGE("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            ALOGE("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                ALOGE("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                    ALOGE("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                    ALOGE("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            ALOGE("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                ALOGE("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                    ALOGE("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                ALOGE("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                ALOGE("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                    ALOGE("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                        ALOGE("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                    ALOGE("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                        ALOGE("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                        ALOGE("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                    ALOGE("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                        ALOGE("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                        ALOGE("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                        ALOGE("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                    ALOGE("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                        ALOGE("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                ALOGE("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                        ALOGE("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
483void SvoxSsmlParser::endtagHandler(void* data, const XML_Char* element)
484{
485    ((SvoxSsmlParser*)data)->endElement(element);
486}
487
488void 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                ALOGE("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                ALOGE("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                    ALOGE("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                ALOGE("Error: failed to allocate memory for string!\n");
550                return;
551            }
552        }
553        strcat(m_data, "</usesig>");
554    }
555}
556
557void SvoxSsmlParser::textHandler(void* data, const XML_Char* text, int length)
558{
559    ((SvoxSsmlParser*)data)->textElement(text, length);
560}
561
562void 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        ALOGE("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            ALOGE("Error: failed to allocate memory for string!\n");
583            return;
584        }
585    }
586    strcat(m_data, content);
587    delete [] content;
588}
589
590/**
591convertToSvoxPitch
592Converts SSML pitch labels to SVOX pitch levels
593*/
594char* 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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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*/
664char* 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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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/**
731convertToSvoxVolume
732Converts SSML volume labels to SVOX volume levels
733*/
734char* 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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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/**
811convertBreakStrengthToTime
812Converts SSML break strength labels to SVOX break time
813*/
814char* 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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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            ALOGE("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/**
881growDataSize
882Increases the size of the internal text storage member
883*/
884int 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