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 * @file picodata.c 18 * 19 * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland 20 * All rights reserved. 21 * 22 * History: 23 * - 2009-04-20 -- initial version 24 * 25 */ 26 27 #include "picodefs.h" 28 #include "picoos.h" 29 #include "picodbg.h" 30 #include "picorsrc.h" 31 #include "picotrns.h" 32 #include "picodata.h" 33 34 #ifdef __cplusplus 35 extern "C" { 36 #endif 37 #if 0 38 } 39 #endif 40 41 /* we output coefficients as fixed point values */ 42 #define PICOCEP_OUT_DATA_FORMAT PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED 43 44 /* *************************************************************** 45 * CharBuffer * 46 *****************************************************************/ 47 48 /* 49 * method signatures 50 */ 51 typedef pico_status_t (* picodata_cbPutItemMethod) (register picodata_CharBuffer this, 52 const picoos_uint8 *buf, const picoos_uint16 blenmax, 53 picoos_uint16 *blen); 54 55 typedef pico_status_t (* picodata_cbGetItemMethod) (register picodata_CharBuffer this, 56 picoos_uint8 *buf, const picoos_uint16 blenmax, 57 picoos_uint16 *blen, const picoos_uint8 issd); 58 59 typedef pico_status_t (* picodata_cbSubResetMethod) (register picodata_CharBuffer this); 60 typedef pico_status_t (* picodata_cbSubDeallocateMethod) (register picodata_CharBuffer this, picoos_MemoryManager mm); 61 62 typedef struct picodata_char_buffer 63 { 64 picoos_char *buf; 65 picoos_uint16 rear; /* next free position to write */ 66 picoos_uint16 front; /* next position to read */ 67 picoos_uint16 len; /* empty: len = 0, full: len = size */ 68 picoos_uint16 size; 69 70 picoos_Common common; 71 72 picodata_cbGetItemMethod getItem; 73 picodata_cbPutItemMethod putItem; 74 75 picodata_cbSubResetMethod subReset; 76 picodata_cbSubDeallocateMethod subDeallocate; 77 void * subObj; 78 } char_buffer_t; 79 80 81 static pico_status_t data_cbPutItem(register picodata_CharBuffer this, 82 const picoos_uint8 *buf, const picoos_uint16 blenmax, 83 picoos_uint16 *blen); 84 85 static pico_status_t data_cbGetItem(register picodata_CharBuffer this, 86 picoos_uint8 *buf, const picoos_uint16 blenmax, 87 picoos_uint16 *blen, const picoos_uint8 issd); 88 89 pico_status_t picodata_cbReset(register picodata_CharBuffer this) 90 { 91 this->rear = 0; 92 this->front = 0; 93 this->len = 0; 94 if (NULL != this->subObj) { 95 return this->subReset(this); 96 } else { 97 return PICO_OK; 98 } 99 } 100 101 /* CharBuffer constructor */ 102 picodata_CharBuffer picodata_newCharBuffer(picoos_MemoryManager mm, 103 picoos_Common common, 104 picoos_objsize_t size) 105 { 106 picodata_CharBuffer this; 107 108 this = (picodata_CharBuffer) picoos_allocate(mm, sizeof(*this)); 109 PICODBG_DEBUG(("new character buffer, size=%i", size)); 110 if (NULL == this) { 111 return NULL; 112 } 113 this->buf = picoos_allocate(mm, size); 114 if (NULL == this->buf) { 115 picoos_deallocate(mm, (void*) &this); 116 return NULL; 117 } 118 this->size = size; 119 this->common = common; 120 121 this->getItem = data_cbGetItem; 122 this->putItem = data_cbPutItem; 123 124 this->subReset = NULL; 125 this->subDeallocate = NULL; 126 this->subObj = NULL; 127 128 picodata_cbReset(this); 129 return this; 130 } 131 132 void picodata_disposeCharBuffer(picoos_MemoryManager mm, 133 picodata_CharBuffer *this) 134 { 135 if (NULL != (*this)) { 136 /* terminate */ 137 if (NULL != (*this)->subObj) { 138 (*this)->subDeallocate(*this,mm); 139 } 140 picoos_deallocate(mm,(void*)&(*this)->buf); 141 picoos_deallocate(mm,(void*)this); 142 } 143 } 144 145 pico_status_t picodata_cbPutCh(register picodata_CharBuffer this, 146 picoos_char ch) 147 { 148 if (this->len < this->size) { 149 this->buf[this->rear++] = ch; 150 this->rear %= this->size; 151 this->len++; 152 return PICO_OK; 153 } else { 154 return PICO_EXC_BUF_OVERFLOW; 155 } 156 } 157 158 159 picoos_int16 picodata_cbGetCh(register picodata_CharBuffer this) 160 { 161 picoos_char ch; 162 if (this->len > 0) { 163 ch = this->buf[this->front++]; 164 this->front %= this->size; 165 this->len--; 166 return ch; 167 } else { 168 return PICO_EOF; 169 } 170 } 171 172 /* *************************************************************** 173 * items: CharBuffer functions * 174 *****************************************************************/ 175 176 static pico_status_t data_cbGetItem(register picodata_CharBuffer this, 177 picoos_uint8 *buf, const picoos_uint16 blenmax, 178 picoos_uint16 *blen, const picoos_uint8 issd) 179 { 180 picoos_uint16 i; 181 182 if (this->len < PICODATA_ITEM_HEADSIZE) { /* item not in cb? */ 183 *blen = 0; 184 if (this->len == 0) { /* is cb empty? */ 185 PICODBG_DEBUG(("no item to get")); 186 return PICO_EOF; 187 } else { /* cb not empty, but not a valid item */ 188 PICODBG_WARN(("problem getting item, incomplete head, underflow")); 189 } 190 return PICO_EXC_BUF_UNDERFLOW; 191 } 192 *blen = PICODATA_ITEM_HEADSIZE + (picoos_uint8)(this->buf[((this->front) + 193 PICODATA_ITEMIND_LEN) % this->size]); 194 195 /* if getting speech data in item */ 196 if (issd) { 197 /* check item type */ 198 if (this->buf[this->front] != PICODATA_ITEM_FRAME) { 199 PICODBG_WARN(("item type mismatch for speech data: %c", 200 this->buf[this->front])); 201 for (i=0; i<*blen; i++) { 202 this->front++; 203 this->front %= this->size; 204 this->len--; 205 } 206 *blen = 0; 207 return PICO_OK; 208 } 209 } 210 211 if (*blen > this->len) { /* item in cb not complete? */ 212 PICODBG_WARN(("problem getting item, incomplete content, underflow; " 213 "blen=%d, len=%d", *blen, this->len)); 214 *blen = 0; 215 return PICO_EXC_BUF_UNDERFLOW; 216 } 217 if (blenmax < *blen) { /* buf not large enough? */ 218 PICODBG_WARN(("problem getting item, overflow")); 219 *blen = 0; 220 return PICO_EXC_BUF_OVERFLOW; 221 } 222 223 /* if getting speech data in item */ 224 if (issd) { 225 /* skip item header */ 226 for (i = 0; i < PICODATA_ITEM_HEADSIZE; i++) { 227 this->front++; 228 this->front %= this->size; 229 this->len--; 230 } 231 *blen -= PICODATA_ITEM_HEADSIZE; 232 } 233 234 /* all ok, now get item (or speech data only) */ 235 for (i = 0; i < *blen; i++) { 236 buf[i] = (picoos_uint8)(this->buf[this->front++]); 237 this->front %= this->size; 238 this->len--; 239 } 240 241 #if defined(PICO_DEBUG) 242 if (issd) { 243 PICODBG_DEBUG(("got speech data: %d samples", *blen)); 244 } else { 245 PICODBG_DEBUG(("got item: %c|%d|%d|%d||", buf[PICODATA_ITEMIND_TYPE], 246 buf[PICODATA_ITEMIND_INFO1], buf[PICODATA_ITEMIND_INFO2], 247 buf[PICODATA_ITEMIND_LEN])); 248 for (i=PICODATA_ITEM_HEADSIZE; i<*blen; i++) { 249 if (buf[PICODATA_ITEMIND_TYPE] == PICODATA_ITEM_WORDGRAPH) { 250 PICODBG_DEBUG(("%c", buf[i])); 251 } else { 252 PICODBG_DEBUG((" %d", buf[i])); 253 } 254 } 255 } 256 #endif 257 258 return PICO_OK; 259 } 260 261 static pico_status_t data_cbPutItem(register picodata_CharBuffer this, 262 const picoos_uint8 *buf, const picoos_uint16 blenmax, 263 picoos_uint16 *blen) 264 { 265 picoos_uint16 i; 266 267 if (blenmax < PICODATA_ITEM_HEADSIZE) { /* itemlen not accessible? */ 268 PICODBG_WARN(("problem putting item, underflow")); 269 *blen = 0; 270 return PICO_EXC_BUF_UNDERFLOW; 271 } 272 *blen = buf[PICODATA_ITEMIND_LEN] + PICODATA_ITEM_HEADSIZE; 273 if (*blen > (this->size - this->len)) { /* cb not enough space? */ 274 PICODBG_WARN(("problem putting item, overflow")); 275 *blen = 0; 276 return PICO_EXC_BUF_OVERFLOW; 277 } 278 if (*blen > blenmax) { /* item in buf not completely accessible? */ 279 PICODBG_WARN(("problem putting item, underflow")); 280 *blen = 0; 281 return PICO_EXC_BUF_UNDERFLOW; 282 } 283 /* all ok, now put complete item */ 284 285 #if defined(PICO_DEBUG) 286 PICODBG_DEBUG(("putting item: %c|%d|%d|%d||", 287 buf[PICODATA_ITEMIND_TYPE], 288 buf[PICODATA_ITEMIND_INFO1], 289 buf[PICODATA_ITEMIND_INFO2], 290 buf[PICODATA_ITEMIND_LEN])); 291 for (i=PICODATA_ITEM_HEADSIZE; i<*blen; i++) { 292 if (buf[PICODATA_ITEMIND_TYPE] == PICODATA_ITEM_WORDGRAPH) { 293 PICODBG_DEBUG(("%c", buf[i])); 294 } else { 295 PICODBG_DEBUG((" %d", buf[i])); 296 } 297 } 298 #endif 299 300 for (i = 0; i < *blen; i++) { 301 /* put single byte */ 302 this->buf[this->rear++] = (picoos_char)buf[i]; 303 this->rear %= this->size; 304 this->len++; 305 } 306 return PICO_OK; 307 } 308 309 /*---------------------------------------------------------- 310 * Names : picodata_cbGetItem 311 * picodata_cbGetSpeechData 312 * Function: gets one item from 'this' and writes it on 'blenmax' sized 'buf'. 313 * gets one item from 'this' and writes the speech data to 314 * 'blenmax' sized 'buf'. 315 * Returns : PICO_OK : one item was copied 316 * PICO_EOF : 'this' is empty; no new items available 317 * PICO_BUF_UNDERFLOW : 'this' doesn't contain a full/valid item 318 * PICO_BUF_OVERFLOW : 'buf[blenmax]' too small to hold item 319 * on return, '*blen' contains the number of bytes written to 'buf' 320 * ---------------------------------------------------------*/ 321 pico_status_t picodata_cbGetItem(register picodata_CharBuffer this, 322 picoos_uint8 *buf, const picoos_uint16 blenmax, 323 picoos_uint16 *blen) 324 { 325 return this->getItem(this, buf, blenmax, blen, FALSE); 326 } 327 328 pico_status_t picodata_cbGetSpeechData(register picodata_CharBuffer this, 329 picoos_uint8 *buf, const picoos_uint16 blenmax, 330 picoos_uint16 *blen) 331 { 332 333 return this->getItem(this, buf, blenmax, blen, TRUE); 334 } 335 336 337 pico_status_t picodata_cbPutItem(register picodata_CharBuffer this, 338 const picoos_uint8 *buf, const picoos_uint16 blenmax, 339 picoos_uint16 *blen) 340 { 341 342 return this->putItem(this,buf,blenmax,blen); 343 } 344 345 /* unsafe, just for measuring purposes */ 346 picoos_uint8 picodata_cbGetFrontItemType(register picodata_CharBuffer this) 347 { 348 return this->buf[this->front]; 349 } 350 /* *************************************************************** 351 * items: support function * 352 *****************************************************************/ 353 354 picoos_uint8 is_valid_itemtype(const picoos_uint8 ch) { 355 switch (ch) { 356 case PICODATA_ITEM_WSEQ_GRAPH: 357 case PICODATA_ITEM_TOKEN: 358 case PICODATA_ITEM_WORDGRAPH: 359 case PICODATA_ITEM_WORDINDEX: 360 case PICODATA_ITEM_WORDPHON: 361 case PICODATA_ITEM_SYLLPHON: 362 case PICODATA_ITEM_BOUND: 363 case PICODATA_ITEM_PUNC: 364 case PICODATA_ITEM_CMD: 365 case PICODATA_ITEM_PHONE: 366 case PICODATA_ITEM_FRAME: 367 case PICODATA_ITEM_FRAME_PAR: 368 return TRUE; 369 break; 370 case PICODATA_ITEM_OTHER: 371 default: 372 break; 373 } 374 PICODBG_WARN(("item type problem: %c", ch)); 375 return FALSE; 376 } 377 378 picoos_uint8 picodata_is_valid_itemhead(const picodata_itemhead_t *head) { 379 if ((NULL != head) && is_valid_itemtype(head->type)) { 380 return TRUE; 381 } else { 382 PICODBG_WARN(("item header problem")); 383 return FALSE; 384 } 385 } 386 387 /* ***************************************************/ 388 389 390 pico_status_t picodata_get_itemparts_nowarn( 391 const picoos_uint8 *buf, const picoos_uint16 blenmax, 392 picodata_itemhead_t *head, picoos_uint8 *content, 393 const picoos_uint16 clenmax, picoos_uint16 *clen) 394 { 395 if (blenmax >= PICODATA_ITEM_HEADSIZE) { 396 head->type = buf[PICODATA_ITEMIND_TYPE]; 397 head->info1 = buf[PICODATA_ITEMIND_INFO1]; 398 head->info2 = buf[PICODATA_ITEMIND_INFO2]; 399 head->len = buf[PICODATA_ITEMIND_LEN]; 400 *clen = head->len; 401 if (blenmax >= (*clen + PICODATA_ITEM_HEADSIZE)) { 402 if (clenmax >= head->len) { 403 picoos_uint16 i; 404 for (i=0; i<head->len; i++) { 405 content[i] = buf[PICODATA_ITEM_HEADSIZE+i]; 406 } 407 return PICO_OK; 408 } 409 *clen = 0; 410 return PICO_EXC_BUF_OVERFLOW; 411 } 412 } 413 *clen = 0; 414 return PICO_EXC_BUF_UNDERFLOW; 415 } 416 417 pico_status_t picodata_get_itemparts( 418 const picoos_uint8 *buf, const picoos_uint16 blenmax, 419 picodata_itemhead_t *head, picoos_uint8 *content, 420 const picoos_uint16 clenmax, picoos_uint16 *clen) 421 { 422 pico_status_t status = picodata_get_itemparts_nowarn(buf,blenmax,head,content,clenmax,clen); 423 if (PICO_EXC_BUF_OVERFLOW == status) { 424 PICODBG_WARN(("problem getting item, overflow")); 425 } else if (PICO_EXC_BUF_UNDERFLOW == status) { 426 PICODBG_WARN(("problem getting item, overflow")); 427 } 428 return status; 429 } 430 pico_status_t picodata_put_itemparts(const picodata_itemhead_t *head, 431 const picoos_uint8 *content, const picoos_uint16 clenmax, 432 picoos_uint8 *buf, const picoos_uint16 blenmax, picoos_uint16 *blen) 433 { 434 *blen = head->len + PICODATA_ITEM_HEADSIZE; 435 if (blenmax >= *blen) { 436 if (clenmax >= head->len) { 437 picoos_uint16 i; 438 buf[PICODATA_ITEMIND_TYPE] = head->type; 439 buf[PICODATA_ITEMIND_INFO1] = head->info1; 440 buf[PICODATA_ITEMIND_INFO2] = head->info2; 441 buf[PICODATA_ITEMIND_LEN] = head->len; 442 for (i=0; i<head->len; i++) { 443 buf[PICODATA_ITEM_HEADSIZE+i] = content[i]; 444 } 445 return PICO_OK; 446 } 447 PICODBG_WARN(("problem putting item, underflow")); 448 *blen = 0; 449 return PICO_EXC_BUF_UNDERFLOW; 450 } 451 PICODBG_WARN(("problem putting item, overflow")); 452 *blen = 0; 453 return PICO_EXC_BUF_OVERFLOW; 454 } 455 456 pico_status_t picodata_get_iteminfo( 457 picoos_uint8 *buf, const picoos_uint16 blenmax, 458 picodata_itemhead_t *head, picoos_uint8 **content) { 459 if (blenmax >= PICODATA_ITEM_HEADSIZE) { 460 head->type = buf[PICODATA_ITEMIND_TYPE]; 461 head->info1 = buf[PICODATA_ITEMIND_INFO1]; 462 head->info2 = buf[PICODATA_ITEMIND_INFO2]; 463 head->len = buf[PICODATA_ITEMIND_LEN]; 464 if (head->len == 0) { 465 *content = NULL; 466 } else { 467 *content = &buf[PICODATA_ITEM_HEADSIZE]; 468 } 469 return PICO_OK; 470 } 471 return PICO_EXC_BUF_UNDERFLOW; 472 } 473 474 pico_status_t picodata_copy_item(const picoos_uint8 *inbuf, 475 const picoos_uint16 inlenmax, picoos_uint8 *outbuf, 476 const picoos_uint16 outlenmax, picoos_uint16 *numb) 477 { 478 if (picodata_is_valid_item(inbuf, inlenmax)) { 479 *numb = PICODATA_ITEM_HEADSIZE + inbuf[PICODATA_ITEMIND_LEN]; 480 } else { 481 *numb = 0; 482 } 483 if (*numb > 0) { 484 if (outlenmax >= inlenmax) { 485 picoos_uint16 i; 486 for (i=0; i<*numb; i++) { 487 outbuf[i] = inbuf[i]; 488 } 489 return PICO_OK; 490 } else { 491 PICODBG_WARN(("buffer problem, out: %d > in: %d", outlenmax, inlenmax)); 492 *numb = 0; 493 return PICO_EXC_BUF_OVERFLOW; 494 } 495 } else { 496 PICODBG_WARN(("item problem in inbuf")); 497 return PICO_ERR_OTHER; 498 } 499 } 500 501 pico_status_t picodata_set_iteminfo1(picoos_uint8 *buf, 502 const picoos_uint16 blenmax, const picoos_uint8 info) { 503 if (PICODATA_ITEMIND_INFO1 < blenmax) { 504 buf[PICODATA_ITEMIND_INFO1] = info; 505 return PICO_OK; 506 } else 507 return PICO_EXC_BUF_UNDERFLOW; 508 } 509 510 pico_status_t picodata_set_iteminfo2(picoos_uint8 *buf, 511 const picoos_uint16 blenmax, const picoos_uint8 info) { 512 if (PICODATA_ITEMIND_INFO2 < blenmax) { 513 buf[PICODATA_ITEMIND_INFO2] = info; 514 return PICO_OK; 515 } else 516 return PICO_EXC_BUF_UNDERFLOW; 517 } 518 519 /* sets the len field in the header contained in the item in buf; 520 return values: 521 PICO_OK <- all ok 522 PICO_EXC_BUF_UNDERFLOW <- underflow in buf 523 */ 524 pico_status_t picodata_set_itemlen(picoos_uint8 *buf, 525 const picoos_uint16 blenmax, const picoos_uint8 len) { 526 if (PICODATA_ITEMIND_LEN < blenmax) { 527 buf[PICODATA_ITEMIND_LEN] = len; 528 return PICO_OK; 529 } else 530 return PICO_EXC_BUF_UNDERFLOW; 531 } 532 533 picoos_uint8 picodata_is_valid_item(const picoos_uint8 *item, 534 const picoos_uint16 ilenmax) 535 { 536 if (ilenmax >= PICODATA_ITEM_HEADSIZE) { 537 picodata_itemhead_t head; 538 head.type = item[0]; 539 head.info1 = item[1]; 540 head.info2 = item[2]; 541 head.len = item[3]; 542 if ((ilenmax >= (head.len + PICODATA_ITEM_HEADSIZE)) && 543 picodata_is_valid_itemhead(&head)) 544 { 545 return TRUE; 546 } 547 } 548 return FALSE; 549 } 550 551 /* *************************************************************** 552 * ProcessingUnit * 553 *****************************************************************/ 554 picoos_uint16 picodata_get_default_buf_size (picodata_putype_t puType) 555 { 556 return (PICODATA_PUTYPE_TEXT == puType) ? PICODATA_BUFSIZE_TEXT 557 : (PICODATA_PUTYPE_TOK == puType) ? PICODATA_BUFSIZE_TOK 558 : (PICODATA_PUTYPE_PR == puType) ? PICODATA_BUFSIZE_PR 559 : (PICODATA_PUTYPE_PR == puType) ? PICODATA_BUFSIZE_PR 560 : (PICODATA_PUTYPE_WA == puType) ? PICODATA_BUFSIZE_WA 561 : (PICODATA_PUTYPE_SA == puType) ? PICODATA_BUFSIZE_SA 562 : (PICODATA_PUTYPE_ACPH == puType) ? PICODATA_BUFSIZE_ACPH 563 : (PICODATA_PUTYPE_SPHO == puType) ? PICODATA_BUFSIZE_SPHO 564 : (PICODATA_PUTYPE_PAM == puType) ? PICODATA_BUFSIZE_PAM 565 : (PICODATA_PUTYPE_CEP == puType) ? PICODATA_BUFSIZE_CEP 566 : (PICODATA_PUTYPE_SIG == puType) ? PICODATA_BUFSIZE_SIG 567 : (PICODATA_PUTYPE_SINK == puType) ? PICODATA_BUFSIZE_SINK 568 : PICODATA_BUFSIZE_DEFAULT; 569 } 570 571 572 typedef struct simple_pu_data 573 { 574 picorsrc_Voice voice; 575 } simple_pu_data_t; 576 577 static pico_status_t puSimpleInitialize (register picodata_ProcessingUnit this, picoos_int32 resetMode) { 578 return PICO_OK; 579 } 580 581 static pico_status_t puSimpleTerminate (register picodata_ProcessingUnit this) { 582 return PICO_OK; 583 } 584 585 static picodata_step_result_t puSimpleStep (register picodata_ProcessingUnit this, 586 picoos_int16 mode, 587 picoos_uint16 * numBytesOutput) { 588 picoos_int16 ch; 589 picoos_int16 result = PICO_OK; 590 mode = mode; /*PP 13.10.08 : fix warning "var not used in this function"*/ 591 *numBytesOutput = 0; 592 while ((result == PICO_OK) && (ch = picodata_cbGetCh(this->cbIn)) != PICO_EOF) { 593 result = picodata_cbPutCh(this->cbOut,(picoos_char) ch); 594 (*numBytesOutput)++; 595 } 596 if (PICO_OK != result) { 597 (*numBytesOutput)--; 598 } 599 if (PICO_OK == result) { 600 return PICODATA_PU_IDLE; 601 } else { 602 return PICODATA_PU_ERROR; 603 } 604 } 605 606 607 picodata_ProcessingUnit picodata_newProcessingUnit( 608 picoos_MemoryManager mm, 609 picoos_Common common, 610 picodata_CharBuffer cbIn, 611 picodata_CharBuffer cbOut, 612 picorsrc_Voice voice) 613 { 614 picodata_ProcessingUnit this = (picodata_ProcessingUnit) picoos_allocate(mm, sizeof(*this)); 615 if (this == NULL) { 616 picoos_emRaiseException(common->em,PICO_EXC_OUT_OF_MEM,NULL,NULL); 617 return NULL; 618 } 619 this->common = common; 620 this->cbIn = cbIn; 621 this->cbOut = cbOut; 622 this->voice = voice; 623 this->initialize = puSimpleInitialize; 624 this->terminate = puSimpleTerminate; 625 this->step = puSimpleStep; 626 this->subDeallocate = NULL; 627 this->subObj = NULL; 628 return this; 629 } 630 631 void picodata_disposeProcessingUnit( 632 picoos_MemoryManager mm, 633 picodata_ProcessingUnit * this) 634 { 635 if (NULL != (*this)) { 636 /* terminate */ 637 if (NULL != (*this)->subObj) { 638 (*this)->subDeallocate(*this,mm); 639 } 640 picoos_deallocate(mm,(void *)this); 641 } 642 643 } 644 645 646 picodata_CharBuffer picodata_getCbIn(picodata_ProcessingUnit this) 647 { 648 if (NULL == this) { 649 picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); 650 return NULL; 651 } else { 652 return this->cbIn; 653 } 654 } 655 656 picodata_CharBuffer picodata_getCbOut(picodata_ProcessingUnit this) 657 { 658 if (NULL == this) { 659 picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); 660 return NULL; 661 } else { 662 return this->cbOut; 663 } 664 } 665 666 pico_status_t picodata_setCbIn(picodata_ProcessingUnit this, picodata_CharBuffer cbIn) 667 { 668 if (NULL == this) { 669 picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); 670 return PICO_ERR_OTHER; 671 } else { 672 this->cbIn = cbIn; 673 return PICO_OK; 674 } 675 676 } 677 678 pico_status_t picodata_setCbOut(picodata_ProcessingUnit this, picodata_CharBuffer cbOut) 679 { 680 if (NULL == this) { 681 picoos_emRaiseException(this->common->em,PICO_ERR_NULLPTR_ACCESS,NULL,NULL); 682 return PICO_ERR_OTHER; 683 } else { 684 this->cbOut = cbOut; 685 return PICO_OK; 686 } 687 } 688 689 690 /* *************************************************************** 691 * auxiliary functions * 692 *****************************************************************/ 693 694 static void transDurUniform( 695 picoos_uint8 frame_duration_exp, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */ 696 picoos_int8 array_length, 697 picoos_uint8 * inout, 698 picoos_int16 inputdur, /* input duration in ms */ 699 picoos_int16 targetdur, /* target duration in ms */ 700 picoos_int16 * restdur /* in/out, rest in ms */ 701 ) 702 { 703 picoos_int8 i; 704 picoos_int32 fact, rest; 705 706 /* calculate rest and factor in number of frames (in PICODATA_PICODATA_PRECISION) */ 707 rest = (*restdur) << (PICODATA_PRECISION - frame_duration_exp); 708 fact = (targetdur << (PICODATA_PRECISION - frame_duration_exp)) / inputdur; 709 710 for (i = 0; i < array_length; i++) { 711 rest += fact * inout[i]; 712 /* instead of rounding, we carry the rest to the next state */ 713 inout[i] = rest >> PICODATA_PRECISION; 714 rest -= inout[i] << PICODATA_PRECISION; 715 } 716 (*restdur) = rest >> (PICODATA_PRECISION - frame_duration_exp); 717 } 718 719 static void transDurWeighted( 720 picoos_uint8 frame_duration_exp, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */ 721 picoos_int8 array_length, 722 picoos_uint8 * inout, 723 const picoos_uint16 * weight, /* integer weights */ 724 picoos_int16 inputdur, /* input duration in ms */ 725 picoos_int16 targetdur, /* target duration in ms */ 726 picoos_int16 * restdur /* in/out, rest in ms */ 727 ) 728 { 729 picoos_int8 i; 730 picoos_int32 fact, rest, out, weighted_sum; 731 732 /* calculate rest and factor in number of frames (in PICODATA_PICODATA_PRECISION) */ 733 rest = (*restdur) << (PICODATA_PRECISION - frame_duration_exp); 734 weighted_sum = 0; 735 for (i=0; i < array_length; i++) { 736 weighted_sum += inout[i] * weight[i]; 737 } 738 if (0 == weighted_sum) { 739 transDurUniform(frame_duration_exp,array_length,inout,inputdur,targetdur,restdur); 740 return; 741 } 742 /* get the additive change factor in PICODATA_PRECISION: */ 743 if (targetdur > inputdur) { 744 fact = ((targetdur - inputdur) << (PICODATA_PRECISION-frame_duration_exp))/ weighted_sum; 745 } else { 746 fact = -((inputdur - targetdur) << (PICODATA_PRECISION-frame_duration_exp))/ weighted_sum; 747 } 748 749 /* input[i] * fact * weight[i] is the additive modification in PICODATA_PRECISION */ 750 for (i=0; i < array_length; i++) { 751 rest += fact * inout[i] * weight[i]; 752 /* instead of rounding, we carry the rest to the next state */ 753 out = inout[i] + (rest >> PICODATA_PRECISION); 754 if (out < 0) { 755 out = 0; 756 } 757 rest -= ((out-inout[i]) << PICODATA_PRECISION); 758 inout[i] = out; 759 } 760 (*restdur) = rest >> (PICODATA_PRECISION - frame_duration_exp); 761 } 762 763 764 765 void picodata_transformDurations( 766 picoos_uint8 frame_duration_exp, 767 picoos_int8 array_length, 768 picoos_uint8 * inout, 769 const picoos_uint16 * weight, /* integer weights */ 770 picoos_int16 mintarget, /* minimum target duration in ms */ 771 picoos_int16 maxtarget, /* maximum target duration in ms */ 772 picoos_int16 facttarget, /* factor to be multiplied with original length to get the target 773 the factor is fixed-point with PICODATA_PRECISION PICODATA_PRECISION, i.e. 774 the factor as float would be facttarget / PICODATA_PRECISION_FACT 775 if factor is 0, only min/max are considered */ 776 picoos_int16 * dur_rest /* in/out, rest in ms */ 777 ) 778 { 779 picoos_int32 inputdur, targetdur; 780 picoos_int8 i; 781 782 /* find the original duration in ms */ 783 inputdur = 0; 784 for (i=0; i < array_length; i++) { 785 inputdur += inout[i]; 786 } 787 788 PICODBG_TRACE(("######## transforming duration fact=%i, limits = [%i,%i] (input frames: %i)",facttarget,mintarget,maxtarget, inputdur)); 789 790 inputdur <<= frame_duration_exp; 791 792 /* find the target duration */ 793 if (facttarget) { 794 targetdur = (facttarget * inputdur + PICODATA_PREC_HALF) >> PICODATA_PRECISION; 795 } else { 796 targetdur = inputdur; 797 } 798 799 /* we need to modify input if there is an explicit factor or input is not in the target range */ 800 if (facttarget || (targetdur < mintarget) || (maxtarget < targetdur)) { 801 /* make sure we are in the limits */ 802 if (targetdur < mintarget) { 803 targetdur = mintarget; 804 } else if (maxtarget < targetdur) { 805 targetdur = maxtarget; 806 } 807 /* perform modification */ 808 if (NULL == weight) { 809 transDurUniform(frame_duration_exp,array_length,inout,inputdur,targetdur,dur_rest); 810 } else { 811 transDurWeighted(frame_duration_exp,array_length,inout,weight,inputdur,targetdur,dur_rest); 812 } 813 } 814 } 815 816 817 818 extern picoos_uint8 picodata_getPuTypeFromExtension(picoos_uchar * filename, picoos_bool input) 819 { 820 if (input) { 821 if (picoos_has_extension(filename, PICODATA_PUTYPE_TOK_INPUT_EXTENSION)) { 822 return PICODATA_ITEMINFO2_CMD_TO_TOK; 823 } 824 else if (picoos_has_extension(filename, PICODATA_PUTYPE_PR_INPUT_EXTENSION)) { 825 return PICODATA_ITEMINFO2_CMD_TO_PR; 826 } 827 else if (picoos_has_extension(filename, PICODATA_PUTYPE_WA_INPUT_EXTENSION)) { 828 return PICODATA_ITEMINFO2_CMD_TO_WA; 829 } 830 else if (picoos_has_extension(filename, PICODATA_PUTYPE_SA_INPUT_EXTENSION)) { 831 return PICODATA_ITEMINFO2_CMD_TO_SA; 832 } 833 else if (picoos_has_extension(filename, PICODATA_PUTYPE_ACPH_INPUT_EXTENSION)) { 834 return PICODATA_ITEMINFO2_CMD_TO_ACPH; 835 } 836 else if (picoos_has_extension(filename, PICODATA_PUTYPE_SPHO_INPUT_EXTENSION)) { 837 return PICODATA_ITEMINFO2_CMD_TO_SPHO; 838 } 839 else if (picoos_has_extension(filename, PICODATA_PUTYPE_PAM_INPUT_EXTENSION)) { 840 return PICODATA_ITEMINFO2_CMD_TO_PAM; 841 } 842 else if (picoos_has_extension(filename, PICODATA_PUTYPE_CEP_INPUT_EXTENSION)) { 843 return PICODATA_ITEMINFO2_CMD_TO_CEP; 844 } 845 else if (picoos_has_extension(filename, PICODATA_PUTYPE_SIG_INPUT_EXTENSION) || 846 picoos_has_extension(filename, PICODATA_PUTYPE_WAV_INPUT_EXTENSION)) { 847 return PICODATA_ITEMINFO2_CMD_TO_SIG; 848 } 849 else { 850 return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN; 851 } 852 } 853 else { 854 if (picoos_has_extension(filename, PICODATA_PUTYPE_TOK_OUTPUT_EXTENSION)) { 855 return PICODATA_ITEMINFO2_CMD_TO_TOK; 856 } 857 else if (picoos_has_extension(filename, PICODATA_PUTYPE_PR_OUTPUT_EXTENSION)) { 858 return PICODATA_ITEMINFO2_CMD_TO_PR; 859 } 860 else if (picoos_has_extension(filename, PICODATA_PUTYPE_WA_OUTPUT_EXTENSION)) { 861 return PICODATA_ITEMINFO2_CMD_TO_WA; 862 } 863 else if (picoos_has_extension(filename, PICODATA_PUTYPE_SA_OUTPUT_EXTENSION)) { 864 return PICODATA_ITEMINFO2_CMD_TO_SA; 865 } 866 else if (picoos_has_extension(filename, PICODATA_PUTYPE_ACPH_OUTPUT_EXTENSION)) { 867 return PICODATA_ITEMINFO2_CMD_TO_ACPH; 868 } 869 else if (picoos_has_extension(filename, PICODATA_PUTYPE_SPHO_OUTPUT_EXTENSION)) { 870 return PICODATA_ITEMINFO2_CMD_TO_SPHO; 871 } 872 else if (picoos_has_extension(filename, PICODATA_PUTYPE_PAM_OUTPUT_EXTENSION)) { 873 return PICODATA_ITEMINFO2_CMD_TO_PAM; 874 } 875 else if (picoos_has_extension(filename, PICODATA_PUTYPE_CEP_OUTPUT_EXTENSION)) { 876 return PICODATA_ITEMINFO2_CMD_TO_CEP; 877 } 878 else if (picoos_has_extension(filename, PICODATA_PUTYPE_SIG_OUTPUT_EXTENSION) || 879 picoos_has_extension(filename, PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION)) { 880 return PICODATA_ITEMINFO2_CMD_TO_SIG; 881 } 882 else { 883 return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN; 884 } 885 } 886 return PICODATA_ITEMINFO2_CMD_TO_UNKNOWN; 887 } 888 889 890 891 892 /** 893 * 894 * @param transducer 895 * @param common 896 * @param xsampa_parser 897 * @param svoxpa_parser 898 * @param xsampa2svoxpa_mapper 899 * @param inputPhones 900 * @param alphabet 901 * @param outputPhoneIds 902 * @param maxOutputPhoneIds 903 * @return 904 */ 905 pico_status_t picodata_mapPAStrToPAIds(picotrns_SimpleTransducer transducer, 906 picoos_Common common, picokfst_FST xsampa_parser, 907 picokfst_FST svoxpa_parser, picokfst_FST xsampa2svoxpa_mapper, 908 picoos_uchar * inputPhones, picoos_uchar * alphabet, 909 picoos_uint8 * outputPhoneIds, picoos_int32 maxOutputPhoneIds) 910 { 911 pico_status_t status = PICO_OK; 912 if (picoos_strcmp(alphabet, PICODATA_XSAMPA) == 0) { 913 if ((NULL != xsampa_parser) && (NULL != xsampa2svoxpa_mapper)) { 914 picotrns_stInitialize(transducer); 915 status = picotrns_stAddWithPlane(transducer, inputPhones, 916 PICOKFST_PLANE_ASCII); 917 if (PICO_OK != status) { 918 picoos_emRaiseWarning(common->em, status, NULL, 919 (picoos_char *) "phoneme sequence too long (%s)", 920 inputPhones); 921 } else { 922 status = picotrns_stTransduce(transducer, xsampa_parser); 923 if (PICO_OK != status) { 924 picoos_emRaiseWarning(common->em, status, NULL, 925 (picoos_char *) "not recognized as xsampa (%s)", 926 inputPhones); 927 } else { 928 status = picotrns_stTransduce(transducer, xsampa2svoxpa_mapper); 929 if (PICO_OK != status) { 930 picoos_emRaiseWarning(common->em, status, NULL, 931 (picoos_char *) "illeagal phoneme sequence (%s)", 932 inputPhones); 933 } else { 934 status = picotrns_stGetSymSequence(transducer, outputPhoneIds, 935 maxOutputPhoneIds); 936 } 937 } 938 } 939 return status; 940 } 941 } else if (picoos_strcmp(alphabet, PICODATA_SVOXPA) == 0) { 942 if ((NULL != svoxpa_parser)) { 943 picotrns_stInitialize(transducer); 944 status = picotrns_stAddWithPlane(transducer, inputPhones, 945 PICOKFST_PLANE_ASCII); 946 if (PICO_OK == status) { 947 status = picotrns_stTransduce(transducer, svoxpa_parser); 948 } 949 if (PICO_OK == status) { 950 status = picotrns_stGetSymSequence(transducer, outputPhoneIds, 951 maxOutputPhoneIds); 952 } 953 return status; 954 } 955 } 956 picoos_strlcpy(outputPhoneIds, (picoos_char *) "", maxOutputPhoneIds); 957 picoos_emRaiseWarning(common->em, PICO_EXC_NAME_ILLEGAL, NULL, 958 (picoos_char *) "alphabet not supported (%s)", alphabet); 959 return PICO_EXC_NAME_ILLEGAL; 960 961 } 962 963 #if defined (PICO_DEBUG) 964 /* *************************************************************** 965 * For Debugging only * 966 *****************************************************************/ 967 968 969 /* put string representation of 'itemtype' into 'str' (allocated size 'strsize') 970 * return 'str' */ 971 static picoos_char * data_itemtype_to_string(const picoos_uint8 itemtype, 972 picoos_char * str, picoos_uint16 strsize) 973 { 974 picoos_char * tmpstr; 975 switch (itemtype) { 976 case PICODATA_ITEM_BOUND: 977 tmpstr = (picoos_char *)"BOUND"; 978 break; 979 case PICODATA_ITEM_FRAME_PAR: 980 tmpstr = (picoos_char *)"FRAME_PAR"; 981 break; 982 case PICODATA_ITEM_PHONE: 983 tmpstr = (picoos_char *)"PHONE"; 984 break; 985 case PICODATA_ITEM_CMD: 986 tmpstr = (picoos_char *)"CMD"; 987 break; 988 case PICODATA_ITEM_ERR: 989 tmpstr = (picoos_char *)"ERR"; 990 break; 991 case PICODATA_ITEM_FRAME: 992 tmpstr = (picoos_char *)"FRAME"; 993 break; 994 case PICODATA_ITEM_OTHER: 995 tmpstr = (picoos_char *)"OTHER"; 996 break; 997 case PICODATA_ITEM_PUNC: 998 tmpstr = (picoos_char *)"PUNC"; 999 break; 1000 case PICODATA_ITEM_SYLLPHON: 1001 tmpstr = (picoos_char *)"SYLLPHON"; 1002 break; 1003 case PICODATA_ITEM_WORDGRAPH: 1004 tmpstr = (picoos_char *)"WORDGRAPH"; 1005 break; 1006 case PICODATA_ITEM_WORDINDEX: 1007 tmpstr = (picoos_char *)"WORDINDEX"; 1008 break; 1009 case PICODATA_ITEM_WORDPHON: 1010 tmpstr = (picoos_char *)"WORDPHON"; 1011 break; 1012 case PICODATA_ITEM_WSEQ_GRAPH: 1013 tmpstr = (picoos_char *)"WSEQ_GRAPH"; 1014 break; 1015 default: 1016 tmpstr = (picoos_char *)"UNKNOWN"; 1017 break; 1018 } 1019 picopal_slprintf((picopal_char *) str, strsize, (picopal_char *)"%s", 1020 tmpstr); 1021 return str; 1022 } 1023 1024 1025 picoos_char * picodata_head_to_string(const picodata_itemhead_t *head, 1026 picoos_char * str, picoos_uint16 strsize) 1027 { 1028 picoos_uint16 typelen; 1029 1030 if (NULL == head) { 1031 picoos_strlcpy(str,(picoos_char *)"[head is NULL]",strsize); 1032 } else { 1033 data_itemtype_to_string(head->type, str, strsize); 1034 typelen = picoos_strlen(str); 1035 picopal_slprintf((picopal_char *) str+typelen, strsize-typelen, 1036 (picopal_char *)"|%c|%c|%i", head->info1, head->info2, 1037 head->len); 1038 } 1039 1040 return str; 1041 } 1042 1043 void picodata_info_item(const picoknow_KnowledgeBase kb, 1044 const picoos_uint8 *pref6ch, 1045 const picoos_uint8 *item, 1046 const picoos_uint16 itemlenmax, 1047 const picoos_char *filterfn) 1048 { 1049 #define SA_USE_PHST 1 1050 picoos_uint16 i; 1051 picoos_uint8 ch; 1052 1053 if ((itemlenmax < 4) || (item == NULL)) { 1054 PICODBG_INFO_MSG(("invalid item\n")); 1055 } 1056 1057 /* first 6 char used for prefix */ 1058 PICODBG_INFO_MSG_F(filterfn, ("%6s(", pref6ch)); 1059 1060 /* type */ 1061 ch = item[0]; 1062 if ((32 <= ch) && (ch < 127)) { 1063 PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch)); 1064 } else { 1065 PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); 1066 } 1067 /* info1 */ 1068 ch = item[1]; 1069 if ((32 <= ch) && (ch < 127)) 1070 switch (item[0]) { 1071 case PICODATA_ITEM_PUNC: 1072 case PICODATA_ITEM_BOUND: 1073 case PICODATA_ITEM_CMD: 1074 case PICODATA_ITEM_TOKEN: 1075 case PICODATA_ITEM_FRAME_PAR: 1076 PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch)); 1077 break; 1078 default: 1079 PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); 1080 } 1081 else 1082 PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); 1083 1084 /* info2 */ 1085 ch = item[2]; 1086 if ((32 <= ch) && (ch < 127)) 1087 switch (item[0]) { 1088 case PICODATA_ITEM_PUNC: 1089 case PICODATA_ITEM_BOUND: 1090 case PICODATA_ITEM_CMD: 1091 case PICODATA_ITEM_WORDPHON: 1092 case PICODATA_ITEM_SYLLPHON: 1093 PICODBG_INFO_MSG_F(filterfn, ("'%c',", ch)); 1094 break; 1095 default: 1096 PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); 1097 } 1098 else 1099 PICODBG_INFO_MSG_F(filterfn, ("%3d,", ch)); 1100 1101 /* len */ 1102 ch = item[3]; 1103 PICODBG_INFO_MSG_F(filterfn, ("%3d)", ch)); 1104 1105 for (i = 0; i < ch; i++) { 1106 if ((item[0] == PICODATA_ITEM_WSEQ_GRAPH) || 1107 (item[0] == PICODATA_ITEM_TOKEN) || 1108 (item[0] == PICODATA_ITEM_WORDGRAPH) || 1109 ((item[0] == PICODATA_ITEM_CMD) && !((item[1] == PICODATA_ITEMINFO1_CMD_SPEED) || 1110 (item[1] == PICODATA_ITEMINFO1_CMD_PITCH) || 1111 (item[1] == PICODATA_ITEMINFO1_CMD_VOLUME) || 1112 (item[1] == PICODATA_ITEMINFO1_CMD_SPELL) || 1113 (item[1] == PICODATA_ITEMINFO1_CMD_SIL)))) { 1114 PICODBG_INFO_MSG_F(filterfn, ("%c", item[4 + i])); 1115 } else { 1116 PICODBG_INFO_MSG_F(filterfn, ("%4d", item[4 + i])); 1117 } 1118 } 1119 1120 #if defined (SA_USE_PHST) 1121 { 1122 #include "picokdbg.h" 1123 picoos_uint8 j; 1124 picokdbg_Dbg kdbg; 1125 kdbg = picokdbg_getDbg(kb); 1126 1127 if ((item[0] == PICODATA_ITEM_WORDPHON) || 1128 (item[0] == PICODATA_ITEM_SYLLPHON) || 1129 ((item[0] == PICODATA_ITEM_CMD) && (item[1] == PICODATA_ITEMINFO1_CMD_PHONEME))) { 1130 if (picokdbg_getPhoneSym(kdbg, item[4])) { 1131 PICODBG_INFO_MSG_F(filterfn, (" ")); 1132 for (j = 0; j < item[3]; j++) { 1133 PICODBG_INFO_MSG_F(filterfn, ("%s", 1134 picokdbg_getPhoneSym(kdbg, item[4 + j]))); 1135 } 1136 } 1137 } 1138 } 1139 #endif 1140 1141 PICODBG_INFO_MSG_F(filterfn, ("\n")); 1142 } 1143 1144 1145 #endif /* PICO_DEBUG */ 1146 1147 #ifdef __cplusplus 1148 } 1149 #endif 1150 1151 1152 /* picodata.c end */ 1153