Home | History | Annotate | Download | only in tts
      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 
     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 
     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 
     76 int SvoxSsmlParser::initSuccessful()
     77 {
     78     return (mParser && m_data);
     79 }
     80 
     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 
     93 char* SvoxSsmlParser::getParsedDocument()
     94 {
     95     return m_data;
     96 }
     97 
     98 char* SvoxSsmlParser::getParsedDocumentLanguage()
     99 {
    100     return m_docLanguage;
    101 }
    102 
    103 void SvoxSsmlParser::starttagHandler(void* data, const XML_Char* element, const XML_Char** attributes)
    104 {
    105     ((SvoxSsmlParser*)data)->startElement(element, attributes);
    106 }
    107 
    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 
    483 void SvoxSsmlParser::endtagHandler(void* data, const XML_Char* element)
    484 {
    485     ((SvoxSsmlParser*)data)->endElement(element);
    486 }
    487 
    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 
    557 void SvoxSsmlParser::textHandler(void* data, const XML_Char* text, int length)
    558 {
    559     ((SvoxSsmlParser*)data)->textElement(text, length);
    560 }
    561 
    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 */
    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 */
    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 */
    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 */
    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 */
    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