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