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 picocep.c 18 * 19 * Phonetic to Acoustic Mapping PU - Implementation 20 * 21 * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland 22 * All rights reserved. 23 * 24 * History: 25 * - 2009-04-20 -- initial version 26 * 27 */ 28 29 /** 30 * @addtogroup picocep 31 * <b> Pico Cepstral Smoothing </b>\n 32 * 33 itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content 34 in the following 35 36 items input 37 38 processed: 39 40 - PHONE(PHONID,StatesPerPhone)[FramesPerState|f0Index|mgcIndex]{StatesPerPhone} 41 42 (StatesPerPhone is a constant (5) for the time being. The content size is therfore allways 34) 43 44 unprocessed: 45 - all other item types are forwarded through the PU without modification 46 47 items output 48 49 FRAME(PHONID,F0 [?])ceps{25} 50 51 each PHONE produces at least StatesPerPhone FRAME (if each state has FramesPerState == 1), but usually more. 52 53 minimal input size (before processing starts) 54 55 other limitations 56 57 */ 58 #include "picodefs.h" 59 #include "picoos.h" 60 #include "picodbg.h" 61 #include "picodata.h" 62 #include "picokpdf.h" 63 #include "picodsp.h" 64 #include "picocep.h" 65 66 #ifdef __cplusplus 67 extern "C" { 68 #endif 69 #if 0 70 } 71 #endif 72 73 #define PICOCEP_MAXWINLEN 10000 /* maximum number of frames that can be smoothed, i.e. maximum sentence length */ 74 #define PICOCEP_MSGSTR_SIZE 32 75 #define PICOCEP_IN_BUFF_SIZE PICODATA_BUFSIZE_DEFAULT 76 77 #define PICOCEP_OUT_DATA_FORMAT PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED /* we output coefficients as fixed point values */ 78 79 #define PICOCEP_STEPSTATE_COLLECT 0 80 #define PICOCEP_STEPSTATE_PROCESS_PARSE 1 81 #define PICOCEP_STEPSTATE_PROCESS_SMOOTH 2 82 #define PICOCEP_STEPSTATE_PROCESS_FRAME 3 83 #define PICOCEP_STEPSTATE_FEED 4 84 85 #define PICOCEP_LFZINVPOW 31 /* cannot be higher than 31 because 1<<invpow must fit in uint32 */ 86 #define PICOCEP_MGCINVPOW 24 87 #define PICOCEP_LFZDOUBLEDEC 1 88 #define PICOCEP_MGCDOUBLEDEC 0 89 90 typedef enum picocep_WantMeanOrIvar 91 { 92 PICOCEP_WANTMEAN, PICOCEP_WANTIVAR 93 } picocep_WantMeanOrIvar_t; 94 95 typedef enum picocep_WantStaticOrDeltax 96 { 97 PICOCEP_WANTSTATIC, PICOCEP_WANTDELTA, PICOCEP_WANTDELTA2 98 } picocep_WantStaticOrDelta_t; 99 100 /* 101 * Fixedpoint arithmetic (might go into a separate module if general enough and needed by other modules) 102 */ 103 104 #if defined(PICO_DEBUG) || defined(PICO_DEVEL_MODE) 105 int numlongmult = 0, numshortmult = 0; 106 #endif 107 108 #define POW1 (0x1) 109 #define POW2 (0x2) 110 #define POW3 (0x4) 111 #define POW4 (0x8) 112 #define POW5 (0x10) 113 #define POW6 (0x20) 114 #define POW7 (0x40) 115 #define POW8 (0x80) 116 #define POW9 (0x100) 117 #define POW10 (0x200) 118 #define POW11 (0x400) 119 #define POW12 (0x800) 120 #define POW13 (0x1000) 121 #define POW14 (0x2000) 122 #define POW15 (0x4000) 123 #define POW16 (0x8000) 124 #define POW17 (0x10000) 125 #define POW18 (0x20000) 126 #define POW19 (0x40000) 127 #define POW20 (0x80000) 128 #define POW21 (0x100000) 129 #define POW22 (0x200000) 130 #define POW23 (0x400000) 131 #define POW24 (0x800000) 132 #define POW25 (0x1000000) 133 #define POW26 (0x2000000) 134 #define POW27 (0x4000000) 135 #define POW28 (0x8000000) 136 #define POW29 (0x10000000) 137 #define POW30 (0x20000000) 138 #define POW31 (0x40000000) 139 140 /* item num restriction: maximum number of extended item heads in headx */ 141 #define PICOCEP_MAXNR_HEADX 60 142 /* item num restriction: maximum size of all item contents together in cont */ 143 #define PICOCEP_MAXSIZE_CBUF 7680 /* (128 * PICOCEP_MAXNR_HEADX) */ 144 145 typedef struct 146 { 147 picodata_itemhead_t head; 148 picoos_uint16 cind; 149 picoos_uint16 frame; /* sync position */ 150 } picoacph_headx_t; 151 152 /*---------------------------------------------------------- 153 // Name : cep_subobj 154 // Function: subobject definition for the cep processing 155 // Shortcut: cep 156 //---------------------------------------------------------*/ 157 typedef struct cep_subobj 158 { 159 /*----------------------PU voice management------------------------------*/ 160 /* picorsrc_Voice voice; */ 161 /*----------------------PU state management------------------------------*/ 162 picoos_uint8 procState; /* where to take up work at next processing step */ 163 picoos_bool needMoreInput; /* more data necessary to start processing */ 164 /* picoos_uint8 force; *//* forced processing (needMoreData but buffers full */ 165 picoos_uint8 sentenceEnd; 166 picoos_uint8 feedFollowState; 167 picoos_bool inIgnoreState; 168 /*----------------------PU input management------------------------------*/ 169 picoos_uint8 inBuf[PICODATA_MAX_ITEMSIZE]; /* internal input buffer */ 170 picoos_uint16 inBufSize; /* actually allocated size */ 171 picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/ 172 picoos_uint16 nextInPos; 173 174 picoacph_headx_t headx[PICOCEP_MAXNR_HEADX]; 175 picoos_uint16 headxBottom; /* bottom */ 176 picoos_uint16 headxWritePos; /* next free position; headx is empty if headxBottom == headxWritePos */ 177 178 picoos_uint8 cbuf[PICOCEP_MAXSIZE_CBUF]; 179 picoos_uint16 cbufBufSize; /* actually allocated size */ 180 picoos_uint16 cbufWritePos; /* length, 0 if empty */ 181 182 /*----------------------PU output management-----------------------------*/ 183 picodata_itemhead_t framehead; 184 picoos_uint8 outBuf[PICODATA_MAX_ITEMSIZE]; /* internal output buffer (one item) */ 185 picoos_uint16 outBufSize; /* allocated outBuf size */ 186 picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/ 187 188 picoos_uint32 nNumFrames; 189 /*---------------------- other working variables ---------------------------*/ 190 191 picoos_int32 diag0[PICOCEP_MAXWINLEN], diag1[PICOCEP_MAXWINLEN], 192 diag2[PICOCEP_MAXWINLEN], WUm[PICOCEP_MAXWINLEN], 193 invdiag0[PICOCEP_MAXWINLEN]; 194 195 /*---------------------- constants --------------------------------------*/ 196 picoos_int32 xi[5], x1[2], x2[3], xm[3], xn[2]; 197 picoos_int32 xsqi[5], xsq1[2], xsq2[3], xsqm[3], xsqn[2]; 198 199 picoos_uint32 scmeanpowLFZ, scmeanpowMGC; 200 picoos_uint32 scmeanLFZ, scmeanMGC; 201 202 /*---------------------- indices --------------------------------------*/ 203 /* index buffer to hold indices as input for smoothing */ 204 picoos_uint16 indicesLFZ[PICOCEP_MAXWINLEN]; 205 picoos_uint16 indicesMGC[PICOCEP_MAXWINLEN]; 206 picoos_uint16 indexReadPos, indexWritePos; 207 picoos_uint16 activeEndPos; /* end position of indices to be considered */ 208 209 /* this is used for input and output */ 210 picoos_uint8 phoneId[PICOCEP_MAXWINLEN]; /* synchronised with indexReadPos */ 211 212 /*---------------------- coefficients --------------------------------------*/ 213 /* output coefficients buffer */ 214 picoos_int16 * outF0; 215 picoos_uint16 outF0ReadPos, outF0WritePos; 216 picoos_int16 * outXCep; 217 picoos_uint32 outXCepReadPos, outXCepWritePos; /* uint32 needed for MAXWINLEN*ceporder > 2^16 */ 218 picoos_uint8 * outVoiced; 219 picoos_uint16 outVoicedReadPos, outVoicedWritePos; 220 221 /*---------------------- LINGWARE related data -------------------*/ 222 /* pdflfz knowledge base */ 223 picokpdf_PdfMUL pdflfz, pdfmgc; 224 225 } cep_subobj_t; 226 227 /** 228 * picocep_highestBit 229 * @brief find the highest non-zero bit in input x 230 * @remarks this may be implemented by comparing x to powers of 2 231 * or instead of calling this function perform multiplication 232 * and consult overflow register if available on target 233 * @note implemented as a series of macros 234 */ 235 236 #define picocep_highestBitNZ(x) (x>=POW17?(x>=POW25?(x>=POW29?(x>=POW31?31:(x>=POW30?30:29)):(x>=POW27?(x>=POW28?28:27):(x>=POW26?26:25))):(x>=POW21?(x>=POW23?(x>=POW24?24:23):(x>=POW22?22:21)):(x>=POW19?(x>=POW20?20:19):(x>=POW18?18:17)))):(x>=POW9?(x>=POW13?(x>=POW15?(x>=POW16?16:15):(x>=POW14?14:13)):(x>=POW11?(x>=POW12?12:11):(x>=POW10?10:9))):(x>=POW5?(x>=POW7?(x>=POW8?8:7):(x>=POW6?6:5)):(x>=POW3?(x>=POW4?4:3):(x>=POW2?2:1))))) 237 #define picocep_highestBitU(x) (x==0?0:picocep_highestBitNZ(x)) 238 #define picocep_highestBitS(x,zz) (x==0?0:(x<0?((zz)=(-x),picocep_highestBitNZ(zz)):picocep_highestBitNZ(x))) 239 240 /* ------------------------------------------------------------------------------ 241 Internal function definitions 242 ---------------------------------------------------------------------------------*/ 243 244 static void initSmoothing(cep_subobj_t * cep); 245 246 static picoos_int32 getFromPdf(picokpdf_PdfMUL pdf, picoos_uint32 vecstart, 247 picoos_uint8 cepnum, picocep_WantMeanOrIvar_t wantMeanOrIvar, 248 picocep_WantStaticOrDelta_t wantStaticOrDeltax); 249 250 static void invMatrix(cep_subobj_t * cep, picoos_uint16 N, 251 picoos_int16 *smoothcep, picoos_uint8 cepnum, 252 picokpdf_PdfMUL pdf, picoos_uint8 invpow, picoos_uint8 invDoubleDec); 253 254 static picoos_uint8 makeWUWandWUm(cep_subobj_t * cep, picokpdf_PdfMUL pdf, 255 picoos_uint16 *indices, picoos_uint16 b, picoos_uint16 N, 256 picoos_uint8 cepnum); 257 258 static void getDirect(picokpdf_PdfMUL pdf, picoos_uint16 *indices, 259 picoos_uint16 activeEndPos, 260 picoos_uint8 cepnum, picoos_int16 *smoothcep); 261 262 static void getVoiced(picokpdf_PdfMUL pdf, picoos_uint16 *indices, 263 picoos_uint16 activeEndPos, 264 picoos_uint8 *smoothcep); 265 266 static picoos_uint16 get_pi_uint16(picoos_uint8 * buf, picoos_uint16 *pos); 267 268 static void treat_phone(cep_subobj_t * cep, picodata_itemhead_t * ihead); 269 270 static picoos_uint8 forwardingItem(picodata_itemhead_t * ihead); 271 272 static picodata_step_result_t cepStep(register picodata_ProcessingUnit this, 273 picoos_int16 mode, picoos_uint16 * numBytesOutput); 274 275 /* -------------------------------------------- 276 * generic PU management 277 * -------------------------------------------- 278 */ 279 280 /** 281 * initialization of a cep PU (processing unit) 282 * @param this : handle to a cep PU struct 283 * @return PICO_OK : init succeded 284 * @return PICO_ERR_OTHER : init failed 285 * @callgraph 286 * @callergraph 287 */ 288 static pico_status_t cepInitialize(register picodata_ProcessingUnit this, picoos_int32 resetMode) 289 { 290 /*pico_status_t nRes;*/ 291 cep_subobj_t * cep; 292 if (NULL == this || NULL == this->subObj) { 293 return PICO_ERR_OTHER; 294 } 295 cep = (cep_subobj_t *) this->subObj; 296 /* inBuf */ 297 cep->inBufSize = PICODATA_BUFSIZE_CEP; 298 cep->inReadPos = 0; 299 cep->inWritePos = 0; 300 /* headx and cbuf */ 301 cep->headxBottom = cep->headxWritePos = 0; 302 cep->cbufBufSize = PICOCEP_MAXSIZE_CBUF; 303 cep->cbufWritePos = 0; 304 /* outBuf */ 305 cep->outBufSize = PICODATA_MAX_ITEMSIZE; 306 cep->outReadPos = 0; 307 cep->outWritePos = 0; 308 /* indices* */ 309 cep->indexReadPos = 0; 310 cep->indexWritePos = 0; 311 /* outCep, outF0, outVoiced */ 312 cep->outXCepReadPos = 0; 313 cep->outXCepWritePos = 0; 314 cep->outVoicedReadPos = 0; 315 cep->outVoicedWritePos = 0; 316 cep->outF0ReadPos = 0; 317 cep->outF0WritePos = 0; 318 319 cep->needMoreInput = 0; 320 cep->inIgnoreState = 0; 321 cep->sentenceEnd = FALSE; 322 cep->procState = PICOCEP_STEPSTATE_COLLECT; 323 324 cep->nNumFrames = 0; 325 326 /*----------------------------------------------------------------- 327 * MANAGE Item I/O control management 328 ------------------------------------------------------------------*/ 329 cep->activeEndPos = PICOCEP_MAXWINLEN; 330 331 if (resetMode == PICO_RESET_FULL) { 332 /* kb pdflfz */ 333 cep->pdflfz = picokpdf_getPdfMUL( 334 this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); 335 336 /* kb pdfmgc */ 337 cep->pdfmgc = picokpdf_getPdfMUL( 338 this->voice->kbArray[PICOKNOW_KBID_PDF_MGC]); 339 340 /* kb tab phones */ 341 /* cep->phones = 342 picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); */ 343 344 /*---------------------- other working variables ---------------------------*/ 345 /* define the (constant) FRAME_PAR item header */ 346 cep->framehead.type = PICODATA_ITEM_FRAME_PAR; 347 cep->framehead.info1 = PICOCEP_OUT_DATA_FORMAT; 348 cep->framehead.info2 = cep->pdfmgc->ceporder; 349 cep->framehead.len = sizeof(picoos_uint16) + (cep->framehead.info2 + 4) 350 * sizeof(picoos_uint16); 351 cep->scmeanpowLFZ = cep->pdflfz->bigpow - cep->pdflfz->meanpow; 352 cep->scmeanpowMGC = cep->pdfmgc->bigpow - cep->pdfmgc->meanpow; 353 354 cep->scmeanLFZ = (1 << (picoos_uint32) cep->scmeanpowLFZ); 355 356 cep->scmeanMGC = (1 << (picoos_uint32) cep->scmeanpowMGC); 357 358 } 359 /* constants used in makeWUWandWUm */ 360 initSmoothing(cep); 361 362 363 return PICO_OK; 364 }/*cepInitialize*/ 365 366 /** 367 * termination of a cep PU (processing unit) 368 * @param this : handle to a cep PU struct 369 * @return PICO_OK : termination succeded 370 * @return PICO_ERR_OTHER : termination failed 371 * @callgraph 372 * @callergraph 373 */ 374 static pico_status_t cepTerminate(register picodata_ProcessingUnit this) 375 { 376 return PICO_OK; 377 } 378 379 /** 380 * deallocation of a cep PU internal sub object 381 * @param this : handle to a cep PU struct 382 * @param mm : handle of the engine memory manager 383 * @return PICO_OK : deallocation succeded 384 * @return PICO_ERR_OTHER : deallocation failed 385 * @callgraph 386 * @callergraph 387 */ 388 static pico_status_t cepSubObjDeallocate(register picodata_ProcessingUnit this, 389 picoos_MemoryManager mm) 390 { 391 392 mm = mm; /* avoid warning "var not used in this function"*/ 393 #if defined(PICO_DEVEL_MODE) 394 printf("number of long mult is %d, number of short mult is %i\n",numlongmult,numshortmult); 395 #else 396 PICODBG_INFO_MSG(("number of long mult is %d, number of short mult is %i\n",numlongmult,numshortmult)); 397 #endif 398 if (NULL != this) { 399 cep_subobj_t * cep = (cep_subobj_t *) this->subObj; 400 picoos_deallocate(this->common->mm, (void *) &cep->outXCep); 401 picoos_deallocate(this->common->mm, (void *) &cep->outVoiced); 402 picoos_deallocate(this->common->mm, (void *) &cep->outF0); 403 picoos_deallocate(this->common->mm, (void *) &this->subObj); 404 } 405 return PICO_OK; 406 } 407 408 /** 409 * creates a new cep PU (processing unit) 410 * @param mm : engine memory manager object pointer 411 * @param common : engine common object pointer 412 * @param cbIn : PU input buffer 413 * @param cbOut : PU output buffer 414 * @param voice : the voice descriptor object 415 * @return a valid PU handle if creation succeded 416 * @return NULL : creation failed 417 * @callgraph 418 * @callergraph 419 */ 420 picodata_ProcessingUnit picocep_newCepUnit(picoos_MemoryManager mm, 421 picoos_Common common, picodata_CharBuffer cbIn, 422 picodata_CharBuffer cbOut, picorsrc_Voice voice) 423 { 424 picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, 425 cbOut, voice); 426 cep_subobj_t * cep; 427 428 if (this == NULL) { 429 return NULL; 430 } 431 this->initialize = cepInitialize; 432 433 PICODBG_DEBUG(("set this->step to cepStep")); 434 435 this->step = cepStep; 436 this->terminate = cepTerminate; 437 this->subDeallocate = cepSubObjDeallocate; 438 this->subObj = picoos_allocate(mm, sizeof(cep_subobj_t)); 439 440 cep = (cep_subobj_t *) this->subObj; 441 442 if (this->subObj == NULL) { 443 picoos_deallocate(mm, (void*) &this); 444 return NULL; 445 }; 446 447 /* allocate output coeeficient buffers */ 448 cep->outF0 = (picoos_int16 *) picoos_allocate(this->common->mm, 449 PICOCEP_MAXWINLEN * PICOKPDF_MAX_MUL_LFZ_CEPORDER 450 * sizeof(picoos_int16)); 451 cep->outXCep = (picoos_int16 *) picoos_allocate(this->common->mm, 452 PICOCEP_MAXWINLEN * PICOKPDF_MAX_MUL_MGC_CEPORDER 453 * sizeof(picoos_int16)); 454 cep->outVoiced = (picoos_uint8 *) picoos_allocate(this->common->mm, 455 PICOCEP_MAXWINLEN * sizeof(picoos_uint8)); 456 457 if ((NULL == cep->outF0) || (NULL == cep->outXCep) || (NULL 458 == cep->outVoiced)) { 459 picoos_deallocate(this->common->mm, (void *) &(cep->outF0)); 460 picoos_deallocate(this->common->mm, (void *) &(cep->outXCep)); 461 picoos_deallocate(this->common->mm, (void *) &(cep->outVoiced)); 462 picoos_deallocate(mm, (void*) &cep); 463 picoos_deallocate(mm, (void*) &this); 464 return NULL; 465 } 466 cepInitialize(this, PICO_RESET_FULL); 467 468 return this; 469 }/*picocep_newCepUnit*/ 470 471 /* -------------------------------------------- 472 * processing and internal functions 473 * -------------------------------------------- 474 */ 475 476 /** 477 * multiply by 1<<pow and check overflow 478 * @param a : input value 479 * @param pow : shift value 480 * @return multiplied value 481 * @callgraph 482 * @callergraph 483 */ 484 static picoos_int32 picocep_fixptmultpow(picoos_int32 a, picoos_uint8 pow) 485 { 486 picoos_int32 b; 487 picoos_int32 zzz; 488 489 if (picocep_highestBitS(a,zzz) + pow < 32) { 490 b = a << pow; 491 } else { 492 /* clip to maximum positive or negative value */ 493 b = 1 << 31; /* maximum negative value */ 494 if (a > 0) { 495 b -= 1; /* maximum positive value */ 496 }PICODBG_WARN(("picocep_fixptmultpow warning: overflow in fixed point multiplication %i*1<<%i. Clipping to %i\n", a, pow, b)); 497 } 498 return b; 499 } 500 501 /** 502 * divide by 1<<pow with rounding 503 * @param a : input value 504 * @param pow : shift value 505 * @return divided value 506 * @callgraph 507 * @callergraph 508 */ 509 static picoos_int32 picocep_fixptdivpow(picoos_int32 a, picoos_uint8 pow) 510 { 511 picoos_int32 big; 512 513 if (a == 0) { 514 return a; 515 } 516 big = 1 << (pow - 1); 517 if (a > 0) { 518 a = (a + big) >> pow; 519 } else { 520 a = -1 * ((-1 * a + big) >> pow); 521 } 522 523 return a; 524 } 525 526 /** 527 * fixed point multiplication of x and y for large values of x or y or both 528 * @param x,y : operands 1 & 2, in fixed point S:M:N representation 529 * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits 530 * @param invDoubleDec : boolean indicating that x has double decimal size. 531 * do extra division by 1<<bigpow so that result has again single decimal size 532 * @return z(int) : result, in fixed point S:M:N representation 533 * @callgraph 534 * @callergraph 535 */ 536 static picoos_int32 picocep_fixptmultdouble(picoos_int32 x, picoos_int32 y, 537 picoos_uint8 bigpow, picoos_uint8 invDoubleDec) 538 { 539 picoos_int32 a, b, c, d, e, z; 540 picoos_int32 big; 541 542 big = 1 << bigpow; 543 544 /* a = floor(x/big); */ 545 if (x >= 0) { 546 a = x >> bigpow; 547 b = x - (a << bigpow); 548 } else { 549 a = -1 * ((x * -1) >> bigpow); /* most significant 2 bytes of x */ 550 b = x - (a << bigpow); 551 } 552 553 /* least significant 2 bytes of x i.e. x modulo big */ 554 /* c = floor(y/big); */ 555 if (y >= 0) { 556 c = y >> bigpow; 557 d = y - (c << bigpow); 558 } else { 559 c = -1 * ((y * -1) >> bigpow); 560 d = y - (c << bigpow); 561 } 562 563 if (invDoubleDec == 1) { 564 e = a * d + b * c + picocep_fixptdivpow(b * d, bigpow); 565 z = a * c + picocep_fixptdivpow(e, bigpow); 566 } else { 567 z = ((a * c) << bigpow) + (a * d + b * c) + picocep_fixptdivpow(b * d, 568 bigpow); /* 4 mult and 3 add instead of 1 mult. */ 569 } 570 571 return z; 572 } 573 574 /** 575 * fixed point multiplication of x and y 576 * @param x,y : operands 1 & 2, in fixed point S:M:N representation 577 * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits 578 * @param invDoubleDec : boolean indicating that x has double decimal size. 579 * do extra division by 1<<bigpow so that result has again single decimal size 580 * @return z(int) : result, in fixed point S:M:N representation 581 * Notes 582 * - input and output values are 32 bit signed integers 583 * meant to represent a S.M.N encoding of a floating point value where 584 * - S : 1 sign bit 585 * - M : number of binary integer digits (M=32-1-N) 586 * - N : number of binary decimal digits (N=log2(big)) 587 * the routine supports 2 methods 588 * -# standard multiplication of x and y 589 * -# long multiplication of x and y 590 * under PICO_DEBUG the number of double and single precision multiplications is monitored for accuracy/performance tuning 591 * Calls 592 * - picocep_highestBit 593 * - picocep_fixptmultdouble 594 * @callgraph 595 * @callergraph 596 */ 597 static picoos_int32 picocep_fixptmult(picoos_int32 x, picoos_int32 y, 598 picoos_uint8 bigpow, picoos_uint8 invDoubleDec) 599 { 600 picoos_int32 z; 601 picoos_uint8 multsz, pow; 602 picoos_int32 zz1, zz2; 603 604 /* in C, the evaluation order of f() + g() is not defined, so 605 * if both have a side effect on e.g. zz, the outcome of zz is not defined. 606 * For that reason, picocep_highestBitS(x,zz) + picocep_highestBitS(y,zz) 607 * would generate a warning "operation on zz may be undefined" which we 608 * avoid by using two different variables zz1 and zz2 */ 609 multsz = picocep_highestBitS(x,zz1) + picocep_highestBitS(y,zz2); 610 pow = bigpow; 611 if (invDoubleDec == 1) { 612 pow += bigpow; 613 } 614 615 if (multsz <= 30) { /* x*y < 1<<30 is safe including rounding in picocep_fixptdivpow, x*y < 1<<31 is safe but not with rounding */ 616 /* alternatively perform multiplication and consult overflow register */ 617 z = picocep_fixptdivpow(x * y, pow); 618 #if defined(PICO_DEBUG) 619 numshortmult++; /* keep track of number of short multiplications */ 620 #endif 621 } else { 622 #if defined(PICO_DEBUG) 623 if (multsz> 31 + pow) { 624 PICODBG_WARN(("picocep_fixptmult warning: overflow in fixed point multiplication %i*%i, multsz = %i, pow = %i, decrease bigpow\n", x, y, multsz, pow)); 625 } 626 #endif 627 z = picocep_fixptmultdouble(x, y, bigpow, invDoubleDec); /* perform long multiplication for large x and y */ 628 #if defined(PICO_DEBUG) 629 numlongmult++; /* keep track of number of long multiplications */ 630 #endif 631 } 632 return z; 633 }/* picocep_fixptmult */ 634 635 /** 636 * fixed point ^division of a vs b 637 * @param a,b : operands 1 & 2, in fixed point S:M:N representation 638 * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits 639 * @return z(int) : result, in fixed point S:M:N representation 640 * Notes 641 * - input and output values are 32 bit signed integers 642 * meant to represent a S.M.N encoding of a floating point value where 643 * - S : 1 sign bit 644 * - M : number of binary integer digits (M=32-1-N) 645 * - N : number of binary decimal digits (N=log2(big)) 646 * - standard implementation of division by iteratively calculating 647 * the remainder and setting corresponding bit 648 * calculate integer part by integer division (DIV), 649 * then add X bits of precision in decimal part 650 * @callgraph 651 * @callergraph 652 */ 653 static picoos_int32 picocep_fixptdiv(picoos_int32 a, picoos_int32 b, 654 picoos_uint8 bigpow) 655 { 656 picoos_int32 r, c, f, h, stop; 657 r = (a < 0) ? -a : a; /* take absolute value; b is already guaranteed to be positive in smoothing operation */ 658 if (r == 0) { 659 return 0; 660 } 661 c = 0; 662 stop = 0; 663 664 /* can speed up slightly by setting stop = 2 => slightly less precision */ 665 h = r / b; /* in first loop h can be multiple bits, after first loop h can only be 0 or 1 */ 666 /* faster implementation on target by using comparison instead of DIV? */ 667 /* For our LDL even in first loop h <= 1, but not in backward step */ 668 c = c + (h << bigpow); /* after first loop simply set bit */ 669 r = r - h * b; /* corresponds to modulo operation */ 670 bigpow--; 671 r <<= 1; 672 673 while ((bigpow > stop) && (r != 0)) { /* calculate bigpow bits after fixed point */ 674 /* can speed up slightly by setting stop = 2 => slightly less precision */ 675 if (r >= b) { 676 c += (1 << bigpow); /* after first loop simply set bit */ 677 r -= b; /* corresponds to modulo operation */ 678 } 679 bigpow--; 680 r <<= 1; 681 } 682 683 if (r != 0) { 684 f = r + (b >> 1); 685 if (f >= b) { 686 if (f >= b + b) { 687 c += 2; 688 } else { 689 c++; 690 } 691 } 692 } 693 /* final step: do rounding (experimentally improves accuracy for our problem) */ 694 c = (a >= 0) ? c : -c; /* b is guaranteed to be positive because corresponds to diag0 */ 695 return c; 696 }/* picocep_fixptdiv */ 697 698 /** 699 * perform inversion of diagonal element of WUW matrix 700 * @param d : diagonal element to be inverted 701 * @param rowscpow (int) : fixed point base for each dimension of the vectors stored in the database 702 * @param bigpow (int) : fixed point base used during cepstral smoothing 703 * @param invpow : fixed point base of inverted pivot elements 704 * @return inverted pivot element 705 * @note 706 * - d is guaranteed positive 707 * @callgraph 708 * @callergraph 709 */ 710 static picoos_int32 picocep_fixptInvDiagEle(picoos_uint32 d, 711 picoos_uint8* rowscpow, picoos_uint8 bigpow, picoos_uint8 invpow) 712 { 713 picoos_uint32 r, b, c, h, f, stop; 714 picoos_uint8 dlen; 715 /* picoos_int32 zz; */ 716 c = 0; 717 stop = 0; 718 719 dlen = picocep_highestBitU(d); 720 if (invpow + bigpow > 30 + dlen) { /* c must be < 2^32, hence d which is >= 2^(dlen-1) must be > 2^(invpow+bigpow-32), or invpow+bigpow must be <= dlen+30*/ 721 *rowscpow = invpow + bigpow - 30 - dlen;PICODBG_DEBUG(("input to picocep_fixptInvDiagEle is %i <= 1<<%i = 1<<invpow+bigpow-32. Choose lower invpow. For now scaling row by 1<<%i\n", d, invpow+bigpow-32, *rowscpow)); 722 } else { 723 *rowscpow = 0; 724 } 725 r = 1 << invpow; 726 b = d << (*rowscpow); 727 728 /* first */ 729 h = r / b; 730 if (h > 0) { 731 c += (h << bigpow); 732 r -= h * b; 733 } 734 bigpow--; 735 r <<= 1; 736 737 /* loop */ 738 while ((bigpow > stop) && (r != 0)) { 739 if (r >= b) { 740 c += (1 << bigpow); 741 r -= b; 742 } 743 bigpow--; 744 r <<= 1; 745 } 746 747 if (r != 0) { 748 f = r + (b >> 1); 749 if (f >= b) { 750 if (f >= b + b) { 751 c += 2; 752 } else { 753 c++; 754 } 755 } 756 } 757 758 return c; 759 }/* picocep_fixptInvDiagEle */ 760 761 /** 762 * perform division of two operands a and b by multiplication by inverse of b 763 * @param a (int32) : operand 1 in fixed point S:M:N representation 764 * @param invb(uint32) : inverse of operand b, in fixed point P:Q representation (sign is positive) 765 * @param bigpow(uint8) : N = bigpow when invDoubleDec==0, else N = 2*bigpow 766 * @param invpow(uint8) : Q = invpow = number of binary decimal digits for invb 767 * @param invDoubleDec : boolean to indicate that a and the return value c have 2*N binary decimal digits instead of N 768 * @return c(int32) : result in fixed point S:v:w where w = 2*N when invDoubleDec == 1 769 * @note Calls 770 * - picocep_fixptmult 771 * @callgraph 772 * @callergraph 773 */ 774 static picoos_int32 picocep_fixptinv(picoos_int32 a, picoos_uint32 invb, 775 picoos_uint8 bigpow, picoos_uint8 invpow, picoos_uint8 invDoubleDec) 776 { 777 picoos_int32 c; 778 picoos_int8 normpow; 779 780 c = picocep_fixptmult(a, invb, bigpow, invDoubleDec); 781 782 /* if invDoubleDec==0, picocep_fixptmult assumes a and invb are in base 1<<bigpow and returns c = (a*b)/1<<bigpow 783 Since invb is in base 1<<invpow instead of 1<<bigpow, normalize c by 1<<(bigpow-invpow) 784 if invDoubleDec==1: 785 multiply additionally by 1<<bigpow*2 (for invb and c) so that base of c is again 2*bigpow 786 this can be seen by setting a=A*big, b=B*big, invb=big2/B, mult(a,invb) = a*invb/(big*big) = A/B*big*big2/(big*big) = A/B*big2/big 787 and we want c = A/B*big*big => normfactor = big^3/big2 788 */ 789 if (invDoubleDec == 1) { 790 normpow = 3 * bigpow; 791 } else { 792 normpow = bigpow; 793 } 794 if (normpow < invpow) { 795 /* divide with rounding */ 796 c = picocep_fixptdivpow(c, invpow - normpow); 797 } else { 798 c = picocep_fixptmultpow(c, normpow - invpow); 799 } 800 return c; 801 } 802 803 /** 804 * initializes the coefficients to calculate delta and delta-delta values and the squares of the coefficients 805 * @param cep : the CEP PU sub-object handle 806 * @callgraph 807 * @callergraph 808 */ 809 static void initSmoothing(cep_subobj_t * cep) 810 { 811 cep->xi[0] = 1; 812 cep->xi[1] = -1; 813 cep->xi[2] = 2; 814 cep->xi[3] = -4; 815 cep->xi[4] = 2; 816 cep->xsqi[0] = 1; 817 cep->xsqi[1] = 1; 818 cep->xsqi[2] = 4; 819 cep->xsqi[3] = 16; 820 cep->xsqi[4] = 4; 821 822 cep->x1[0] = -1; 823 cep->x1[1] = 2; 824 cep->xsq1[0] = 1; 825 cep->xsq1[1] = 4; 826 827 cep->x2[0] = -1; 828 cep->x2[1] = -4; 829 cep->x2[2] = 2; 830 cep->xsq2[0] = 1; 831 cep->xsq2[1] = 16; 832 cep->xsq2[2] = 4; 833 834 cep->xm[0] = 1; 835 cep->xm[1] = 2; 836 cep->xm[2] = -4; 837 cep->xsqm[0] = 1; 838 cep->xsqm[1] = 4; 839 cep->xsqm[2] = 16; 840 841 cep->xn[0] = 1; 842 cep->xn[1] = 2; 843 cep->xsqn[0] = 1; 844 cep->xsqn[1] = 4; 845 } 846 847 /** 848 * matrix inversion 849 * @param cep : PU sub object pointer 850 * @param N 851 * @param smoothcep : pointer to picoos_int16, sequence of smoothed cepstral vectors 852 * @param cepnum : cepstral dimension to be treated 853 * @param pdf : pdf resource 854 * @param invpow : fixed point base for inverse 855 * @param invDoubleDec : boolean indicating that result of picocep_fixptinv has fixed point base 2*bigpow 856 * picocep_fixptmult absorbs double decimal size by dividing its result by extra factor big 857 * @return void 858 * @remarks diag0, diag1, diag2, WUm, invdiag0 globals needed in this function (object members in pico) 859 * @callgraph 860 * @callergraph 861 */ 862 static void invMatrix(cep_subobj_t * cep, picoos_uint16 N, 863 picoos_int16 *smoothcep, picoos_uint8 cepnum, 864 picokpdf_PdfMUL pdf, picoos_uint8 invpow, picoos_uint8 invDoubleDec) 865 { 866 picoos_int32 j, v1, v2, h; 867 picoos_uint32 k; 868 picoos_uint8 rowscpow, prevrowscpow; 869 picoos_uint8 ceporder = pdf->ceporder; 870 picoos_uint8 bigpow = pdf->bigpow; 871 picoos_uint8 meanpow = pdf->meanpow; 872 873 /* LDL factorization */ 874 prevrowscpow = 0; 875 cep->invdiag0[0] = picocep_fixptInvDiagEle(cep->diag0[0], &rowscpow, 876 bigpow, invpow); /* inverse has fixed point basis 1<<invpow */ 877 cep->diag1[0] = picocep_fixptinv((cep->diag1[0]) << rowscpow, 878 cep->invdiag0[0], bigpow, invpow, invDoubleDec); /* perform division via inverse */ 879 cep->diag2[0] = picocep_fixptinv((cep->diag2[0]) << rowscpow, 880 cep->invdiag0[0], bigpow, invpow, invDoubleDec); 881 cep->WUm[0] = (cep->WUm[0]) << rowscpow; /* if diag0 too low, multiply LHS and RHS of row in matrix equation by 1<<rowscpow */ 882 for (j = 1; j < N; j++) { 883 /* do forward substitution */ 884 cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag1[j - 1], 885 cep->WUm[j - 1], bigpow, invDoubleDec); 886 if (j > 1) { 887 cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag2[j - 2], 888 cep->WUm[j - 2], bigpow, invDoubleDec); 889 } 890 891 /* update row j */ 892 v1 = picocep_fixptmult((cep->diag1[j - 1]) / (1 << rowscpow), 893 cep->diag0[j - 1], bigpow, invDoubleDec); /* undo scaling by 1<<rowscpow because diag1(j-1) refers to symm ele in column j-1 not in row j-1 */ 894 cep->diag0[j] = cep->diag0[j] - picocep_fixptmult(cep->diag1[j - 1], 895 v1, bigpow, invDoubleDec); 896 if (j > 1) { 897 v2 = picocep_fixptmult((cep->diag2[j - 2]) / (1 << prevrowscpow), 898 cep->diag0[j - 2], bigpow, invDoubleDec); /* undo scaling by 1<<prevrowscpow because diag1(j-2) refers to symm ele in column j-2 not in row j-2 */ 899 cep->diag0[j] = cep->diag0[j] - picocep_fixptmult( 900 cep->diag2[j - 2], v2, bigpow, invDoubleDec); 901 } 902 prevrowscpow = rowscpow; 903 cep->invdiag0[j] = picocep_fixptInvDiagEle(cep->diag0[j], &rowscpow, 904 bigpow, invpow); /* inverse has fixed point basis 1<<invpow */ 905 cep->WUm[j] = (cep->WUm[j]) << rowscpow; 906 if (j < N - 1) { 907 h = picocep_fixptmult(cep->diag2[j - 1], v1, bigpow, invDoubleDec); 908 cep->diag1[j] = picocep_fixptinv((cep->diag1[j] - h) << rowscpow, 909 cep->invdiag0[j], bigpow, invpow, invDoubleDec); /* eliminate column j below pivot */ 910 } 911 if (j < N - 2) { 912 cep->diag2[j] = picocep_fixptinv((cep->diag2[j]) << rowscpow, 913 cep->invdiag0[j], bigpow, invpow, invDoubleDec); /* eliminate column j below pivot */ 914 } 915 } 916 917 /* divide all entries of WUm by diag0 */ 918 for (j = 0; j < N; j++) { 919 cep->WUm[j] = picocep_fixptinv(cep->WUm[j], cep->invdiag0[j], bigpow, 920 invpow, invDoubleDec); 921 if (invDoubleDec == 1) { 922 cep->WUm[j] = picocep_fixptdivpow(cep->WUm[j], bigpow); 923 } 924 } 925 926 /* backward substitution */ 927 for (j = N - 2; j >= 0; j--) { 928 cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag1[j], cep->WUm[j 929 + 1], bigpow, invDoubleDec); 930 if (j < N - 2) { 931 cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag2[j], 932 cep->WUm[j + 2], bigpow, invDoubleDec); 933 } 934 } 935 /* copy N frames into smoothcep (only for coeff # "cepnum") */ 936 /* coefficients normalized to occupy short; for correct waveform energy, divide by (1<<(bigpow-meanpow)) then convert e.g. to picoos_single */ 937 k = cepnum; 938 for (j = 0; j < N; j++) { 939 smoothcep[k] = (picoos_int16)(cep->WUm[j]/(1<<meanpow)); 940 k += ceporder; 941 } 942 943 }/* invMatrix*/ 944 945 /** 946 * Calculate matrix products needed to implement the solution 947 * @param cep : PU sub object pointer 948 * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 949 * @param indices : indices of pdf vectors for all frames in current sentence 950 * @param b, N : to be smoothed frames indices (range will be from b to b+N-1) 951 * @param cepnum : cepstral dimension to be treated 952 * @return void 953 * @remarks diag0, diag1, diag2, WUm, invdiag0 globals needed in this function (object members in pico) 954 * @remarks WUW --> At x W x A 955 * @remarks WUm --> At x W x b 956 * @callgraph 957 * @callergraph 958 */ 959 static picoos_uint8 makeWUWandWUm(cep_subobj_t * cep, picokpdf_PdfMUL pdf, 960 picoos_uint16 *indices, picoos_uint16 b, picoos_uint16 N, 961 picoos_uint8 cepnum) 962 { 963 picoos_uint16 Id[2], Idd[3]; 964 /*picoos_uint32 vecstart, k;*/ 965 picoos_uint32 vecstart; 966 picoos_int32 *x = NULL, *xsq = NULL; 967 picoos_int32 mean, ivar; 968 picoos_uint16 i, j, numd = 0, numdd = 0; 969 picoos_uint8 vecsize = pdf->vecsize; 970 picoos_int32 prev_WUm, prev_diag0, prev_diag1, prev_diag1_1, prev_diag2; 971 972 prev_WUm = prev_diag0 = prev_diag1 = prev_diag1_1 = prev_diag2 = 0; 973 for (i = 0; i < N; i++) { 974 975 if ((1 < i) && (i < N - 2)) { 976 x = cep->xi; 977 xsq = cep->xsqi; 978 numd = 2; 979 numdd = 3; 980 Id[0] = Idd[0] = i - 1; 981 Id[1] = Idd[2] = i + 1; 982 Idd[1] = i; 983 } else if (i == 0) { 984 x = cep->x1; 985 xsq = cep->xsq1; 986 numd = numdd = 1; 987 Id[0] = Idd[0] = 1; 988 } else if (i == 1) { 989 x = cep->x2; 990 xsq = cep->xsq2; 991 numd = 1; 992 numdd = 2; 993 Id[0] = Idd[1] = 2; 994 Idd[0] = 1; 995 } else if (i == N - 2) { 996 x = cep->xm; 997 xsq = cep->xsqm; 998 numd = 1; 999 numdd = 2; 1000 Id[0] = Idd[0] = N - 3; 1001 Idd[1] = N - 2; 1002 } else if (i == N - 1) { 1003 x = cep->xn; 1004 xsq = cep->xsqn; 1005 numd = numdd = 1; 1006 Id[0] = Idd[0] = N - 2; 1007 } 1008 1009 /* process static means and static inverse variances */ 1010 if (i > 0 && indices[b + i] == indices[b + i - 1]) { 1011 cep->diag0[i] = prev_diag0; 1012 cep->WUm[i] = prev_WUm; 1013 } else { 1014 vecstart = indices[b + i] * vecsize; 1015 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, 1016 PICOCEP_WANTSTATIC); 1017 prev_diag0 = cep->diag0[i] = ivar << 2; /* multiply ivar by 4 (4 used to be first entry of xsq) */ 1018 mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, 1019 PICOCEP_WANTSTATIC); 1020 prev_WUm = cep->WUm[i] = mean << 1; /* multiply mean by 2 (2 used to be first entry of x) */ 1021 } 1022 1023 /* process delta means and delta inverse variances */ 1024 for (j = 0; j < numd; j++) { 1025 vecstart = indices[b + Id[j]] * vecsize; 1026 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, 1027 PICOCEP_WANTDELTA); 1028 cep->diag0[i] += xsq[j] * ivar; 1029 1030 mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, 1031 PICOCEP_WANTDELTA); 1032 if (mean != 0) { 1033 cep->WUm[i] += x[j] * mean; 1034 } 1035 } 1036 1037 /* process delta delta means and delta delta inverse variances */ 1038 for (j = 0; j < numdd; j++) { 1039 vecstart = indices[b + Idd[j]] * vecsize; 1040 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, 1041 PICOCEP_WANTDELTA2); 1042 cep->diag0[i] += xsq[numd + j] * ivar; 1043 1044 mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, 1045 PICOCEP_WANTDELTA2); 1046 if (mean != 0) { 1047 cep->WUm[i] += x[numd + j] * mean; 1048 } 1049 } 1050 1051 cep->diag0[i] = (cep->diag0[i] + 2) / 4; /* long DIV with rounding */ 1052 cep->WUm[i] = (cep->WUm[i] + 1) / 2; /* long DIV with rounding */ 1053 1054 /* calculate diag(A,-1) */ 1055 if (i < N - 1) { 1056 if (i < N - 2) { 1057 if (i > 0 && indices[b + i + 1] == indices[b + i]) { 1058 cep->diag1[i] = prev_diag1; 1059 } else { 1060 vecstart = indices[b + i + 1] * vecsize; 1061 /* 1062 diag1[i] = getFromPdf(pdf, vecstart, numvuv, ceporder, numdeltas, cepnum, 1063 bigpow, meanpowUm, ivarpow, PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2); 1064 */ 1065 prev_diag1 = cep->diag1[i] = getFromPdf(pdf, vecstart, 1066 cepnum, PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2); 1067 } 1068 /* 1069 k = vecstart +pdf->numvuv+pdf->ceporder*2 + pdf->numdeltas*3 + 1070 pdf->ceporder*2 +cepnum; 1071 cep->diag1[i] = (picoos_int32)(pdf->content[k]) << pdf->bigpow; 1072 */ 1073 } else { 1074 cep->diag1[i] = 0; 1075 } 1076 if (i > 0) { 1077 if (i > 1 && indices[b + i] == indices[b + i - 1]) { 1078 cep->diag1[i] += prev_diag1_1; 1079 } else { 1080 vecstart = indices[b + i] * vecsize; 1081 /* 1082 k = vecstart + pdf->numvuv + pdf->ceporder * 2 + pdf->numdeltas * 3 + pdf->ceporder * 2 + cepnum; 1083 cep->diag1[i] += (picoos_int32)(pdf->content[k]) << pdf->bigpow; */ 1084 /* cepnum'th delta delta ivar */ 1085 1086 prev_diag1_1 = getFromPdf(pdf, vecstart, cepnum, 1087 PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2); 1088 cep->diag1[i] += prev_diag1_1; 1089 } 1090 1091 } /*i < N-1 */ 1092 cep->diag1[i] *= -2; 1093 } 1094 } 1095 1096 /* calculate diag(A,-2) */ 1097 for (i = 0; i < N - 2; i++) { 1098 if (i > 0 && indices[b + i + 1] == indices[b + i]) { 1099 cep->diag2[i] = prev_diag2; 1100 } else { 1101 vecstart = indices[b + i + 1] * vecsize; 1102 /* 1103 k = vecstart + pdf->numvuv + pdf->ceporder * 2 + pdf->numdeltas * 3 + pdf->ceporder * 2 + cepnum; 1104 cep->diag2[i] = (picoos_int32)(pdf->content[k]) << pdf->bigpow; 1105 k -= pdf->ceporder; 1106 ivar = (picoos_int32)(pdf->content[k]) << pdf->bigpow; 1107 */ 1108 cep->diag2[i] = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, 1109 PICOCEP_WANTDELTA2); 1110 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, 1111 PICOCEP_WANTDELTA); 1112 cep->diag2[i] -= (ivar + 2) / 4; 1113 prev_diag2 = cep->diag2[i]; 1114 } 1115 } 1116 1117 return 0; 1118 }/* makeWUWandWUm */ 1119 1120 /** 1121 * Retrieve actual values for MGC from PDF resource 1122 * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 1123 * @param vecstart : indices of pdf vectors for all frames in current sentence 1124 * @param cepnum : cepstral dimension to be treated 1125 * @param wantMeanOrIvar : flag to select mean or variance values 1126 * @param wantStaticOrDeltax : flag to select static or delta values 1127 * @return the actual value retrieved 1128 * @callgraph 1129 * @callergraph 1130 */ 1131 static picoos_int32 getFromPdf(picokpdf_PdfMUL pdf, picoos_uint32 vecstart, 1132 picoos_uint8 cepnum, picocep_WantMeanOrIvar_t wantMeanOrIvar, 1133 picocep_WantStaticOrDelta_t wantStaticOrDeltax) 1134 { 1135 picoos_uint8 s, ind; 1136 picoos_uint8 *p; 1137 picoos_uint8 ceporder, ceporder2, cc; 1138 picoos_uint32 k; 1139 picoos_int32 mean = 0, ivar = 0; 1140 1141 if (pdf->numdeltas == 0xFF) { 1142 switch (wantMeanOrIvar) { 1143 case PICOCEP_WANTMEAN: 1144 switch (wantStaticOrDeltax) { 1145 case PICOCEP_WANTSTATIC: 1146 p = pdf->content 1147 + (vecstart + pdf->numvuv + cepnum * 2); /* cepnum'th static mean */ 1148 mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) 1149 | *p) << (pdf->meanpowUm[cepnum]); 1150 break; 1151 case PICOCEP_WANTDELTA: 1152 cc = pdf->ceporder + cepnum; 1153 p = pdf->content + (vecstart + pdf->numvuv + cc * 2); /* cepnum'th delta mean */ 1154 mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) 1155 | *p) << (pdf->meanpowUm[cc]); 1156 break; 1157 case PICOCEP_WANTDELTA2: 1158 cc = pdf->ceporder * 2 + cepnum; 1159 p = pdf->content + (vecstart + pdf->numvuv + cc * 2); /* cepnum'th delta delta mean */ 1160 mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) 1161 | *p) << (pdf->meanpowUm[cc]); 1162 break; 1163 default: 1164 /* should never come here */ 1165 PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax)); 1166 } 1167 return mean; 1168 break; 1169 case PICOCEP_WANTIVAR: 1170 switch (wantStaticOrDeltax) { 1171 case PICOCEP_WANTSTATIC: 1172 k = vecstart + pdf->numvuv + pdf->ceporder * 6 + cepnum; /* cepnum'th static ivar */ 1173 ivar = (picoos_int32) (pdf->content[k]) 1174 << (pdf->ivarpow[cepnum]); 1175 break; 1176 case PICOCEP_WANTDELTA: 1177 ceporder = pdf->ceporder; 1178 k = vecstart + pdf->numvuv + ceporder * 7 + cepnum; /* cepnum'th delta ivar */ 1179 ivar = (picoos_int32) (pdf->content[k]) 1180 << (pdf->ivarpow[ceporder + cepnum]); 1181 break; 1182 case PICOCEP_WANTDELTA2: 1183 ceporder = pdf->ceporder; 1184 k = vecstart + pdf->numvuv + ceporder * 8 + cepnum; /* cepnum'th delta delta ivar */ 1185 ivar = (picoos_int32) (pdf->content[k]) 1186 << (pdf->ivarpow[2 * ceporder + cepnum]); 1187 break; 1188 default: 1189 /* should never get here */ 1190 PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax)); 1191 } 1192 return ivar; 1193 break; 1194 default: 1195 /* should never come here */ 1196 PICODBG_ERROR(("unknown type wantMeanOrIvar = %n", wantMeanOrIvar)); 1197 return 0; 1198 } 1199 } else { 1200 switch (wantMeanOrIvar) { 1201 case PICOCEP_WANTMEAN: 1202 switch (wantStaticOrDeltax) { 1203 case PICOCEP_WANTSTATIC: 1204 p = pdf->content 1205 + (vecstart + pdf->numvuv + cepnum * 2); /* cepnum'th static mean */ 1206 mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8)) 1207 | *p) << (pdf->meanpowUm[cepnum]); 1208 return mean; 1209 break; 1210 case PICOCEP_WANTDELTA: 1211 ceporder = pdf->ceporder; 1212 s = 0; 1213 ind = 0; 1214 while ((s < pdf->numdeltas) && (ind < cepnum || (ind 1215 == 0 && cepnum == 0))) { /* rawmean deltas are sparse so investigate indices in column */ 1216 k = vecstart + pdf->numvuv + ceporder * 2 + s; /* s'th delta index */ 1217 ind = (picoos_uint8) (pdf->content[k]); /* is already picoos_uint8 but just to make explicit */ 1218 if (ind == cepnum) { 1219 k = vecstart + pdf->numvuv + ceporder * 2 1220 + pdf->numdeltas + s * 2; /* s'th sparse delta mean, corresponds to cepnum'th delta mean */ 1221 mean 1222 = ((picoos_int32) ((picoos_int16) ((pdf->content[k 1223 + 1]) << 8)) | pdf->content[k]) 1224 << (pdf->meanpowUm[ceporder 1225 + cepnum]); 1226 return mean; 1227 } 1228 s++; 1229 } 1230 return 0; 1231 break; 1232 case PICOCEP_WANTDELTA2: 1233 ceporder = pdf->ceporder; 1234 ceporder2 = ceporder * 2; 1235 s = pdf->numdeltas; 1236 ind = 2 * ceporder; 1237 while ((s-- > 0) && (ind > ceporder + cepnum)) { /* rawmean deltas are sparse so investigate indices in column */ 1238 k = vecstart + pdf->numvuv + ceporder2 + s; /* s'th delta index */ 1239 ind = (picoos_uint8) (pdf->content[k]); /* is already picoos_uint8 but just to make explicit */ 1240 if (ind == ceporder + cepnum) { 1241 k = vecstart + pdf->numvuv + ceporder2 1242 + pdf->numdeltas + s * 2; /* s'th sparse delta mean, corresponds to cepnum'th delta delta mean */ 1243 mean 1244 = ((picoos_int32) ((picoos_int16) ((pdf->content[k 1245 + 1]) << 8)) | pdf->content[k]) 1246 << (pdf->meanpowUm[ceporder2 1247 + cepnum]); 1248 return mean; 1249 } 1250 } 1251 return 0; 1252 break; 1253 default: 1254 PICODBG_ERROR(("getFromPdf: unknown type wantStaticOrDeltax = %i\n", wantStaticOrDeltax)); 1255 return 0; 1256 } 1257 break; 1258 case PICOCEP_WANTIVAR: 1259 switch (wantStaticOrDeltax) { 1260 case PICOCEP_WANTSTATIC: 1261 k = vecstart + pdf->numvuv + pdf->ceporder * 2 1262 + pdf->numdeltas * 3 + cepnum; /* cepnum'th static ivar */ 1263 ivar = (picoos_int32) (pdf->content[k]) 1264 << (pdf->ivarpow[cepnum]); 1265 break; 1266 case PICOCEP_WANTDELTA: 1267 ceporder = pdf->ceporder; 1268 k = vecstart + pdf->numvuv + ceporder * 3 1269 + pdf->numdeltas * 3 + cepnum; /* cepnum'th delta ivar */ 1270 ivar = (picoos_int32) (pdf->content[k]) 1271 << (pdf->ivarpow[ceporder + cepnum]); 1272 break; 1273 case PICOCEP_WANTDELTA2: 1274 ceporder2 = 2 * pdf->ceporder; 1275 k = vecstart + pdf->numvuv + ceporder2 + pdf->numdeltas 1276 * 3 + ceporder2 + cepnum; /* cepnum'th delta delta ivar */ 1277 ivar = (picoos_int32) (pdf->content[k]) 1278 << (pdf->ivarpow[ceporder2 + cepnum]); 1279 break; 1280 default: 1281 PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax)); 1282 } 1283 return ivar; 1284 break; 1285 default: 1286 PICODBG_ERROR(("unknown type wantMeanOrIvar = %i", wantMeanOrIvar)); 1287 return 0; 1288 } 1289 } 1290 return 0; 1291 } 1292 1293 /** 1294 * Retrieve actual values for MGC from PDF resource - Variant "Direct" 1295 * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 1296 * @param indices : indices of pdf vectors for all frames in current sentence 1297 * @param activeEndPos : ?? 1298 * @param cepnum : cepstral dimension to be treated 1299 * @param smoothcep : ?? 1300 * @return the actual value retrieved 1301 * @callgraph 1302 * @callergraph 1303 */ 1304 static void getDirect(picokpdf_PdfMUL pdf, picoos_uint16 *indices, 1305 picoos_uint16 activeEndPos, 1306 picoos_uint8 cepnum, picoos_int16 *smoothcep) 1307 { 1308 picoos_uint16 i; 1309 picoos_uint32 j; 1310 picoos_uint32 vecstart; 1311 picoos_int32 mean, ivar; 1312 picoos_int32 prev_mean; 1313 picoos_uint8 vecsize = pdf->vecsize; 1314 picoos_uint8 order = pdf->ceporder; 1315 1316 j = cepnum; 1317 prev_mean = 0; 1318 for (i = 0; i < activeEndPos; i++) { 1319 if (i > 0 && indices[i] == indices[i - 1]) { 1320 mean = prev_mean; 1321 } else { 1322 vecstart = indices[i] * vecsize; 1323 mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN, 1324 PICOCEP_WANTSTATIC); 1325 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR, 1326 PICOCEP_WANTSTATIC); 1327 prev_mean = mean = picocep_fixptdiv(mean, ivar, pdf->bigpow); 1328 } 1329 smoothcep[j] = (picoos_int16)(mean/(1<<pdf->meanpow)); 1330 j += order; 1331 } 1332 } 1333 1334 /** 1335 * Retrieve actual values for voicing from PDF resource 1336 * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3 1337 * @param indices : indices of pdf vectors for all frames in current sentence 1338 * @param activeEndPos : end position of indices to be considered 1339 * @return smoothcep : the values retrieved 1340 * @callgraph 1341 * @callergraph 1342 */ 1343 static void getVoiced(picokpdf_PdfMUL pdf, picoos_uint16 *indices, 1344 picoos_uint16 activeEndPos, 1345 picoos_uint8 *smoothcep) 1346 { 1347 picoos_uint16 i, j; 1348 picoos_uint32 vecstart; 1349 picoos_uint8 vecsize = pdf->vecsize; 1350 1351 if (pdf->numvuv == 0) { 1352 /* do nothing */ 1353 } else { 1354 for (i = 0, j = 0; i < activeEndPos; i++, j++) { 1355 vecstart = indices[i] * vecsize; 1356 smoothcep[j] = pdf->content[vecstart]; /* odd value is voiced, even if unvoiced */ 1357 } 1358 } 1359 } 1360 1361 /** reads platform-independent uint16 from buffer at *pos and advances *pos 1362 * @param buf : buffer picoos_uint8 1363 * @param *pos : start position inside buffer of pi uint16 1364 * @return the uint16 1365 * @callgraph 1366 * @callergraph 1367 */ 1368 static picoos_uint16 get_pi_uint16(picoos_uint8 * buf, picoos_uint16 *pos) 1369 { 1370 picoos_uint16 res; 1371 res = buf[(*pos)] | ((picoos_uint16) buf[(*pos) + 1] << 8); 1372 *pos += 2; 1373 return res; 1374 } 1375 /** 1376 * Looks up indices of one phone item and fills index buffers. Consumes Item 1377 * @param cep : the CEP PU sub object pointer 1378 * @param ihead : pointer to the start of the phone item 1379 * @callgraph 1380 * @callergraph 1381 */ 1382 static void treat_phone(cep_subobj_t * cep, picodata_itemhead_t * ihead) 1383 { 1384 picoos_uint16 state, frame, frames; 1385 picoos_uint16 indlfz, indmgc; 1386 picoos_uint16 pos; 1387 picoos_uint8 bufferFull; 1388 1389 /* treat all states 1390 * for each state, repeat putting the index into the index buffer framesperstate times. 1391 */ 1392 /* set state and frame to the first state and frame in the phone to be considered */ 1393 state = 0; /* the first state to be considered */ 1394 frame = 0; /* the first frame to be considered */ 1395 /* numFramesPerState: 2 byte, lf0Index: 2 byte, mgcIndex: 2 byte -> 6 bytes per state */ 1396 PICODBG_DEBUG(("skipping to phone state %i ",state)); 1397 pos = cep->inReadPos + PICODATA_ITEM_HEADSIZE + state * 6; 1398 /* */ 1399 PICODBG_DEBUG(("state info starts at inBuf pos %i ",pos)); 1400 /* get the current frames per state */ 1401 frames = get_pi_uint16(cep->inBuf, &pos); 1402 /* */ 1403 PICODBG_DEBUG(("number of frames for this phone state: %i",frames)); 1404 /* */ 1405 PICODBG_DEBUG(("PARSE starting with frame %i",frame)); 1406 1407 bufferFull = cep->indexWritePos >= PICOCEP_MAXWINLEN; 1408 while ((state < ihead->info2) && (bufferFull == FALSE)) { 1409 1410 /* get the current state's lf0 and mgc indices and adjust according to state */ 1411 /* the indices have to be calculated as follows: 1412 * new index = (index-1) + stateoffset(state) */ 1413 1414 indlfz = get_pi_uint16(cep->inBuf, &pos); /* lfz index */ 1415 indlfz += -1 + cep->pdflfz->stateoffset[state]; /* transform index */ 1416 indmgc = get_pi_uint16(cep->inBuf, &pos); /* mgc index */ 1417 indmgc += -1 + cep->pdfmgc->stateoffset[state]; /* transform index */ 1418 1419 /* are we reaching the end of the index buffers? */ 1420 if ((cep->indexWritePos - frame) + frames > PICOCEP_MAXWINLEN) { 1421 /* number of frames that will still fit */ 1422 frames = PICOCEP_MAXWINLEN - (cep->indexWritePos - frame); 1423 bufferFull = TRUE; 1424 PICODBG_DEBUG(("smoothing buffer full at state=%i frame=%i",state, frame)); 1425 } 1426 while (frame < frames) { 1427 cep->indicesMGC[cep->indexWritePos] = indmgc; 1428 cep->indicesLFZ[cep->indexWritePos] = indlfz; 1429 cep->phoneId[cep->indexWritePos] = ihead->info1; 1430 cep->indexWritePos++; 1431 frame++; 1432 } 1433 /* proceed to next state */ 1434 PICODBG_DEBUG(("finished state %i with %i frames, now at index write pos %i", 1435 state, frames,cep->indexWritePos)); 1436 state++; 1437 if (state < ihead->info2) { 1438 frame = 0; 1439 frames = get_pi_uint16(cep->inBuf, &pos); 1440 } 1441 } 1442 /* consume the phone item */ 1443 cep->inReadPos = cep->nextInPos; 1444 /* */ 1445 PICODBG_DEBUG(("finished phone, advancing inReadPos to %i",cep->inReadPos)); 1446 } 1447 1448 /** 1449 * Returns true if an Item has to be forwarded to next PU 1450 * @param ihead : pointer to item head structure 1451 * @return TRUE : the item should be forwarded 1452 * @return FALSE : the item should be consumed 1453 * @callgraph 1454 * @callergraph 1455 */ 1456 static picoos_uint8 forwardingItem(picodata_itemhead_t * ihead) 1457 { 1458 if ((PICODATA_ITEM_CMD == ihead->type) && (PICODATA_ITEMINFO1_CMD_IGNSIG 1459 == ihead->info1)) { 1460 return FALSE; 1461 } else { 1462 return TRUE; 1463 } 1464 } 1465 1466 /** 1467 * performs a step of the cep processing 1468 * @param this : pointer to current PU (Control Unit) 1469 * @param mode : mode for the PU (not used) 1470 * @param numBytesOutput : pointer to output number fo bytes produced 1471 * @return one of the "picodata_step_result_t" values 1472 * @callgraph 1473 * @callergraph 1474 */ 1475 static picodata_step_result_t cepStep(register picodata_ProcessingUnit this, 1476 picoos_int16 mode, picoos_uint16 * numBytesOutput) 1477 { 1478 register cep_subobj_t * cep; 1479 picodata_itemhead_t ihead /* , ohead */; 1480 picoos_uint8 * icontents; 1481 pico_status_t sResult = PICO_OK; 1482 picoos_uint16 blen, clen; 1483 picoos_uint16 numinb, numoutb; 1484 1485 #if defined (PICO_DEBUG) 1486 picoos_char msgstr[PICOCEP_MSGSTR_SIZE]; 1487 #endif 1488 numinb = 0; 1489 numoutb = 0; 1490 1491 if (NULL == this || NULL == this->subObj) { 1492 return PICODATA_PU_ERROR; 1493 } 1494 cep = (cep_subobj_t *) this->subObj; 1495 mode = mode; /* avoid warning "var not used in this function"*/ 1496 1497 /*Init number of output bytes*/ 1498 *numBytesOutput = 0; 1499 1500 while (1) { /* exit via return */ 1501 1502 PICODBG_DEBUG(("doing pu state %i", cep->procState)); 1503 1504 switch (cep->procState) { 1505 1506 case PICOCEP_STEPSTATE_COLLECT: 1507 /* *************** item collector ***********************************/ 1508 1509 PICODBG_TRACE(("COLLECT")); 1510 1511 /*collecting items from the PU input buffer*/ 1512 sResult = picodata_cbGetItem(this->cbIn, 1513 &(cep->inBuf[cep->inWritePos]), cep->inBufSize 1514 - cep->inWritePos, &blen); 1515 if (PICO_EOF == sResult) { /* there are no more items available and we always need more data here */ 1516 PICODBG_DEBUG(("COLLECT need more data, returning IDLE")); 1517 return PICODATA_PU_IDLE; 1518 } 1519 1520 PICODBG_DEBUG(("got item, status: %d", sResult)); 1521 1522 if ((PICO_OK == sResult) && (blen > 0)) { 1523 /* we now have one item */ 1524 cep->inWritePos += blen; 1525 cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE; 1526 } else { 1527 /* ignore item and stay in collect */ 1528 PICODBG_ERROR(("COLLECT got bad result %i", sResult)); 1529 cep->inReadPos = cep->inWritePos = 0; 1530 } 1531 /* return PICODATA_PU_ATOMIC; */ 1532 break; 1533 1534 case PICOCEP_STEPSTATE_PROCESS_PARSE: 1535 /* **************** put item indices into index buffers (with repetition) ******************/ 1536 1537 PICODBG_TRACE(("PARSE")); 1538 1539 PICODBG_DEBUG(("getting info from inBuf in range: [%i,%i[", cep->inReadPos, cep->inWritePos)); 1540 if (cep->inWritePos <= cep->inReadPos) { 1541 /* no more items in inBuf */ 1542 /* we try to get more data */ 1543 PICODBG_DEBUG(("no more items in inBuf, try to collect more")); 1544 /* cep->needMoreInput = TRUE; */ 1545 cep->inReadPos = cep->inWritePos = 0; 1546 cep->procState = PICOCEP_STEPSTATE_COLLECT; 1547 break; 1548 } 1549 /* look at the current item */ 1550 /*verify that current item is valid */ 1551 if (!picodata_is_valid_item(cep->inBuf + cep->inReadPos, 1552 cep->inWritePos - cep->inReadPos)) { 1553 PICODBG_ERROR(("found invalid item")); 1554 sResult = picodata_get_iteminfo( 1555 cep->inBuf + cep->inReadPos, cep->inWritePos 1556 - cep->inReadPos, &ihead, &icontents);PICODBG_DEBUG(("PARSE bad item %s",picodata_head_to_string(&ihead,msgstr,PICOCEP_MSGSTR_SIZE))); 1557 1558 return PICODATA_PU_ERROR; 1559 } 1560 1561 sResult = picodata_get_iteminfo(cep->inBuf + cep->inReadPos, 1562 cep->inWritePos - cep->inReadPos, &ihead, &icontents); 1563 1564 if (PICO_EXC_BUF_UNDERFLOW == sResult) { 1565 /* no more items in inBuf */ 1566 /* we try to get more data */ 1567 PICODBG_DEBUG(("no more items in inBuf, try to collect more")); 1568 /* cep->needMoreInput = TRUE; */ 1569 cep->inReadPos = cep->inWritePos = 0; 1570 cep->procState = PICOCEP_STEPSTATE_COLLECT; 1571 break; 1572 } else if (PICO_OK != sResult) { 1573 PICODBG_ERROR(("unknown exception (sResult == %i)",sResult)); 1574 return (picodata_step_result_t) picoos_emRaiseException( 1575 this->common->em, sResult, NULL, NULL); 1576 break; 1577 } 1578 1579 PICODBG_DEBUG(("PARSE looking at item %s",picodata_head_to_string(&ihead,msgstr,PICOCEP_MSGSTR_SIZE))); 1580 1581 cep->nextInPos = PICODATA_ITEM_HEADSIZE + ihead.len; 1582 1583 /* we decide what to do next depending on the item and the state of the index buffer: 1584 * - process buffer if buffer not empty and sentence end or flush or ignsig/start (don't consume item yet) 1585 * - fill buffer with (part of) phone contents if item is a phone 1586 * - consume or copy for later output otherwise 1587 */ 1588 1589 if (cep->inIgnoreState) { 1590 if ((PICODATA_ITEM_CMD == ihead.type) 1591 && (PICODATA_ITEMINFO1_CMD_IGNSIG == ihead.info1) 1592 && (PICODATA_ITEMINFO2_CMD_END == ihead.info2)) { 1593 cep->inIgnoreState = 0; 1594 }PICODBG_DEBUG(("cep: PARSE consuming item of inBuf")); 1595 cep->inReadPos = cep->nextInPos; 1596 break; 1597 } 1598 1599 /* see if it is a sentence end boundary or termination boundary (flush) and there are indices to smooth -> smooth */ 1600 if ((PICODATA_ITEM_BOUND == ihead.type) 1601 && ((PICODATA_ITEMINFO1_BOUND_SEND == ihead.info1) 1602 || (PICODATA_ITEMINFO1_BOUND_TERM == ihead.info1)) 1603 && (cep->indexWritePos > 0)) { 1604 /* we smooth the buffer */ 1605 cep->activeEndPos = cep->indexWritePos; 1606 cep->sentenceEnd = TRUE; 1607 /* output whatever we got */ 1608 PICODBG_DEBUG(("cep: PARSE found sentence terminator; setting activeEndPos to %i",cep->activeEndPos)); 1609 cep->procState = PICOCEP_STEPSTATE_PROCESS_SMOOTH; 1610 break; 1611 } else if (PICODATA_ITEM_PHONE == ihead.type) { 1612 /* it is a phone */ 1613 PICODBG_DEBUG(("cep: PARSE treating PHONE")); 1614 treat_phone(cep, &ihead); 1615 1616 } else { 1617 if ((PICODATA_ITEM_CMD == ihead.type) 1618 && (PICODATA_ITEMINFO1_CMD_IGNSIG == ihead.info1) 1619 && (PICODATA_ITEMINFO2_CMD_START == ihead.info2)) { 1620 cep->inIgnoreState = 1; 1621 } 1622 /* sentence end or flush remaining after frame or other non-processable item, e.g. command */ 1623 /* do we have to forward? */ 1624 if (forwardingItem(&ihead)) { 1625 /* if no active frames, output immediately */ 1626 if (cep->indexWritePos <= 0) { 1627 /* copy item to outBuf */ 1628 PICODBG_DEBUG(("PARSE copy item in inBuf to outBuf")); 1629 picodata_copy_item(cep->inBuf + cep->inReadPos, 1630 cep->inWritePos - cep->inReadPos, 1631 cep->outBuf, cep->outBufSize, &blen); 1632 cep->outWritePos += blen; 1633 PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], 1634 (picoos_uint8 *)"cep: do forward item ", 1635 cep->outBuf, PICODATA_MAX_ITEMSIZE); 1636 /* output item and then go to parse to treat a new item. */ 1637 cep->feedFollowState 1638 = PICOCEP_STEPSTATE_PROCESS_PARSE; 1639 cep->procState = PICOCEP_STEPSTATE_FEED; 1640 } else if ((cep->headxWritePos < PICOCEP_MAXNR_HEADX) 1641 && (cep->cbufWritePos + ihead.len 1642 < cep->cbufBufSize)) { 1643 /* there is enough space to store item */ 1644 PICODBG_DEBUG(("unhandled item (type %c, length %i). Storing associated with index %i",ihead.type, ihead.len, cep->indexWritePos)); 1645 sResult 1646 = picodata_get_itemparts( 1647 cep->inBuf + cep->inReadPos, 1648 cep->inWritePos - cep->inReadPos, 1649 &(cep->headx[cep->headxWritePos].head), 1650 &(cep->cbuf[cep->cbufWritePos]), 1651 cep->cbufBufSize 1652 - cep->cbufWritePos, &clen); 1653 1654 if (sResult != PICO_OK) { 1655 PICODBG_ERROR(("problem getting item parts")); 1656 picoos_emRaiseException(this->common->em, 1657 sResult, NULL, NULL); 1658 return PICODATA_PU_ERROR; 1659 } 1660 /* remember sync position */ 1661 cep->headx[cep->headxWritePos].frame 1662 = cep->indexWritePos; 1663 1664 if (clen > 0) { 1665 cep->headx[cep->headxWritePos].cind 1666 = cep->cbufWritePos; 1667 cep->cbufWritePos += clen; 1668 } else { 1669 cep->headx[cep->headxWritePos].cind = 0; 1670 } 1671 cep->headxWritePos++; 1672 } else { 1673 /* buffer full, smooth and output whatever we got */ 1674 PICODBG_DEBUG(("PARSE is forced to smooth prematurely; setting activeEndPos to %i", cep->activeEndPos)); 1675 cep->procState = PICOCEP_STEPSTATE_PROCESS_SMOOTH; 1676 /* don't consume item yet */ 1677 break; 1678 } 1679 } else { 1680 }PICODBG_DEBUG(("cep: PARSE consuming item of inBuf")); 1681 cep->inReadPos = cep->nextInPos; 1682 } 1683 break; 1684 1685 case PICOCEP_STEPSTATE_PROCESS_SMOOTH: 1686 /* **************** smooth (indexed) coefficients and store smoothed in outBuffers ****************/ 1687 1688 PICODBG_TRACE(("SMOOTH")); 1689 { 1690 picokpdf_PdfMUL pdf; 1691 1692 /* picoos_uint16 framesTreated = 0; */ 1693 picoos_uint8 cepnum; 1694 picoos_uint16 N; 1695 1696 N = cep->activeEndPos; /* numframes in current step */ 1697 1698 /* the range to be smoothed starts at 0 and is N long */ 1699 1700 /* smooth each cepstral dimension separately */ 1701 /* still to be experimented if higher order coeff can remain unsmoothed, i.e. simple copy from pdf */ 1702 1703 /* reset the f0, ceps and voiced outfuffers */ 1704 cep->outXCepReadPos = cep->outXCepWritePos = 0; 1705 cep->outVoicedReadPos = cep->outVoicedWritePos = 0; 1706 cep->outF0ReadPos = cep->outF0WritePos = 0; 1707 1708 PICODBG_DEBUG(("smoothing %d frames\n", N)); 1709 1710 /* smooth f0 */ 1711 pdf = cep->pdflfz; 1712 for (cepnum = 0; cepnum < pdf->ceporder; cepnum++) { 1713 if (cep->activeEndPos <= 0) { 1714 /* do nothing */ 1715 } else if (3 < N) { 1716 makeWUWandWUm(cep, pdf, cep->indicesLFZ, 0, N, 1717 cepnum); /* update diag0, diag1, diag2, WUm */ 1718 invMatrix(cep, N, cep->outF0 + cep->outF0WritePos, cepnum, pdf, 1719 PICOCEP_LFZINVPOW, PICOCEP_LFZDOUBLEDEC); 1720 } else { 1721 getDirect(pdf, cep->indicesLFZ, cep->activeEndPos, 1722 cepnum, cep->outF0 + cep->outF0WritePos); 1723 } 1724 }/* end for cepnum */ 1725 cep->outF0WritePos += cep->activeEndPos * pdf->ceporder; 1726 1727 /* smooth mgc */ 1728 pdf = cep->pdfmgc; 1729 for (cepnum = 0; cepnum < pdf->ceporder; cepnum++) { 1730 if (cep->activeEndPos <= 0) { 1731 /* do nothing */ 1732 } else if (3 < N) { 1733 makeWUWandWUm(cep, pdf, cep->indicesMGC, 0, N, 1734 cepnum); /* update diag0, diag1, diag2, WUm */ 1735 invMatrix(cep, N, cep->outXCep 1736 + cep->outXCepWritePos, cepnum, 1737 pdf, PICOCEP_MGCINVPOW, 1738 PICOCEP_MGCDOUBLEDEC); 1739 } else { 1740 getDirect(pdf, cep->indicesMGC, cep->activeEndPos, 1741 cepnum, cep->outXCep + cep->outXCepWritePos); 1742 } 1743 }/* end for cepnum */ 1744 cep->outXCepWritePos += cep->activeEndPos * pdf->ceporder; 1745 1746 getVoiced(pdf, cep->indicesMGC, cep->activeEndPos, cep->outVoiced 1747 + cep->outVoicedWritePos); 1748 cep->outVoicedWritePos += cep->activeEndPos; 1749 1750 } 1751 /* setting indexReadPos to the next active index to be used. (will be advanced by FRAME when 1752 * reading the phoneId */ 1753 cep->indexReadPos = 0; 1754 cep->procState = PICOCEP_STEPSTATE_PROCESS_FRAME; 1755 return PICODATA_PU_BUSY; /*data to feed*/ 1756 1757 break; 1758 1759 case PICOCEP_STEPSTATE_PROCESS_FRAME: 1760 1761 /* *************** creating output items (type FRAME) ***********************************/ 1762 1763 PICODBG_TRACE(("FRAME")); 1764 1765 if ((cep->headxBottom < cep->headxWritePos) 1766 && (cep->headx[cep->headxBottom].frame 1767 <= cep->indexReadPos)) { 1768 1769 /* output item in headx/cbuf */ 1770 /* copy item to outBuf */ 1771 PICODBG_DEBUG(("FRAME copy item in inBuf to outBuf")); 1772 picodata_put_itemparts( 1773 &(cep->headx[cep->headxBottom].head), 1774 &(cep->cbuf[cep->headx[cep->headxBottom].cind]), 1775 cep->headx[cep->headxBottom].head.len, cep->outBuf, 1776 cep->outBufSize, &blen); 1777 cep->outWritePos += blen; 1778 /* consume item in headx/cbuf */ 1779 PICODBG_DEBUG(("PARSE consuming item of headx/cbuf")); 1780 cep->headxBottom++; 1781 1782 /* output item and then go to parse to treat a new item. */ 1783 cep->feedFollowState = PICOCEP_STEPSTATE_PROCESS_FRAME; 1784 cep->procState = PICOCEP_STEPSTATE_FEED; 1785 break; 1786 } 1787 1788 if (cep->indexReadPos < cep->activeEndPos) { 1789 /*------------ there are frames to output ----------------------------------------*/ 1790 /* still frames to output, create new FRAME_PAR item */ 1791 1792 cep->nNumFrames++; 1793 1794 PICODBG_DEBUG(("FRAME creating FRAME_PAR: active: [0,%i[, read=%i, write=%i", 1795 cep->activeEndPos, cep->indexReadPos, cep->indexWritePos 1796 )); 1797 1798 /* create FRAME_PAR items from cep->outXX one by one */ 1799 1800 /* converting the ceps shorts into floats: 1801 * scmeanpow = pdf->bigpow - pdf->meanpow; 1802 * for all sval: 1803 * fval = (picoos_single) sval / scmeanpow; 1804 */ 1805 1806 cep->outWritePos = cep->outReadPos = 0; 1807 cep->outBuf[cep->outWritePos++] = cep->framehead.type; 1808 cep->outBuf[cep->outWritePos++] = cep->framehead.info1; 1809 cep->outBuf[cep->outWritePos++] = cep->framehead.info2; 1810 cep->outBuf[cep->outWritePos++] = cep->framehead.len; 1811 1812 PICODBG_DEBUG(("FRAME writing position after header: %i",cep->outWritePos)); 1813 1814 { 1815 picoos_uint16 tmpUint16; 1816 picoos_int16 tmpInt16; 1817 picoos_uint16 i; 1818 1819 /* */ 1820 PICODBG_DEBUG(("FRAME reading phoneId[%i] = %c:",cep->indexReadPos, cep->phoneId[cep->indexReadPos])); 1821 /* */ 1822 1823 tmpUint16 1824 = (picoos_uint16) cep->phoneId[cep->indexReadPos]; 1825 1826 picoos_mem_copy((void *) &tmpUint16, 1827 (void *) &cep->outBuf[cep->outWritePos], 1828 sizeof(tmpUint16)); 1829 1830 cep->outWritePos += sizeof(tmpUint16); 1831 1832 PICODBG_DEBUG(("FRAME writing position after phone id: %i",cep->outWritePos)); 1833 1834 for (i = 0; i < cep->pdflfz->ceporder; i++) { 1835 1836 tmpUint16 = (cep->outVoiced[cep->outVoicedReadPos] 1837 & 0x01) ? cep->outF0[cep->outF0ReadPos] 1838 : (picoos_uint16) 0; 1839 1840 picoos_mem_copy((void *) &tmpUint16, 1841 (void *) &cep->outBuf[cep->outWritePos], 1842 sizeof(tmpUint16)); 1843 cep->outWritePos += sizeof(tmpUint16); 1844 1845 tmpUint16 1846 = (picoos_uint16) (cep->outVoiced[cep->outVoicedReadPos]); 1847 picoos_mem_copy((void *) &tmpUint16, 1848 (void *) &cep->outBuf[cep->outWritePos], 1849 sizeof(tmpUint16)); 1850 cep->outWritePos += sizeof(tmpUint16); 1851 tmpUint16 1852 = (picoos_uint16) (cep->outF0[cep->outF0ReadPos]); 1853 picoos_mem_copy((void *) &tmpUint16, 1854 (void *) &cep->outBuf[cep->outWritePos], 1855 sizeof(tmpUint16)); 1856 cep->outWritePos += sizeof(tmpUint16); 1857 1858 cep->outVoicedReadPos++; 1859 cep->outF0ReadPos++; 1860 } 1861 1862 PICODBG_DEBUG(("FRAME writing position after f0: %i",cep->outWritePos)); 1863 1864 for (i = 0; i < cep->pdfmgc->ceporder; i++) { 1865 tmpInt16 = cep->outXCep[cep->outXCepReadPos++]; 1866 picoos_mem_copy((void *) &tmpInt16, 1867 (void *) &cep->outBuf[cep->outWritePos], 1868 sizeof(tmpInt16)); 1869 cep->outWritePos += sizeof(tmpInt16); 1870 } 1871 1872 PICODBG_DEBUG(("FRAME writing position after cepstrals: %i",cep->outWritePos)); 1873 1874 tmpUint16 1875 = (picoos_uint16) cep->indicesMGC[cep->indexReadPos++]; 1876 1877 picoos_mem_copy((void *) &tmpUint16, 1878 (void *) &cep->outBuf[cep->outWritePos], 1879 sizeof(tmpUint16)); 1880 1881 PICODBG_DEBUG(("FRAME writing position after mgc index: %i",cep->outWritePos)); 1882 1883 cep->outWritePos += sizeof(tmpUint16); 1884 1885 } 1886 /* finished to create FRAME_PAR, now output and then come back*/ 1887 cep->feedFollowState = PICOCEP_STEPSTATE_PROCESS_FRAME; 1888 cep->procState = PICOCEP_STEPSTATE_FEED; 1889 1890 } else if (cep->sentenceEnd) { 1891 /*------------ no more frames to output at end of sentence ----------------------------------------*/ 1892 PICODBG_INFO(("End of sentence - Processed frames : %d", 1893 cep->nNumFrames)); 1894 cep->nNumFrames = 0;PICODBG_DEBUG(("FRAME no more active frames for this sentence")); 1895 /* no frames left in this sentence*/ 1896 /* reset for new sentence */ 1897 initSmoothing(cep); 1898 cep->sentenceEnd = FALSE; 1899 cep->indexReadPos = cep->indexWritePos = 0; 1900 cep->activeEndPos = PICOCEP_MAXWINLEN; 1901 cep->headxBottom = cep->headxWritePos = 0; 1902 cep->cbufWritePos = 0; 1903 cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE; 1904 } else { 1905 /*------------ no more frames can be output but sentence end not reached ----------------------------------------*/ 1906 PICODBG_DEBUG(("Maximum number of frames per sentence reached")); 1907 cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE; 1908 } 1909 /*----------------------------------------------------*/ 1910 break; 1911 1912 case PICOCEP_STEPSTATE_FEED: 1913 /* ***********************************************************************/ 1914 /* FEED: combine input item with pos/phon pairs to output item */ 1915 /* ***********************************************************************/ 1916 1917 PICODBG_DEBUG(("FEED")); 1918 1919 PICODBG_DEBUG(("FEED putting outBuf item into cb")); 1920 1921 /*feeding items to PU output buffer*/ 1922 sResult = picodata_cbPutItem(this->cbOut, cep->outBuf, 1923 cep->outBufSize, &blen); 1924 1925 if (PICO_EXC_BUF_OVERFLOW == sResult) { 1926 /* we have to redo this item */ 1927 PICODBG_DEBUG(("FEED got overflow, returning PICODATA_PU_OUT_FULL")); 1928 return PICODATA_PU_OUT_FULL; 1929 } else if (PICO_OK == sResult) { 1930 1931 if (cep->outBuf[0] != 'k') { 1932 PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], 1933 (picoos_uint8 *)"cep: ", 1934 cep->outBuf, PICODATA_MAX_ITEMSIZE); 1935 } 1936 1937 *numBytesOutput += blen; 1938 /*-------------------------*/ 1939 /*reset the output pointers*/ 1940 /*-------------------------*/ 1941 if (cep->outReadPos >= cep->outWritePos) { 1942 cep->outReadPos = 0; 1943 cep->outWritePos = 0; 1944 } 1945 cep->procState = cep->feedFollowState; 1946 PICODBG_DEBUG(("FEED ok, going back to procState %i", cep->procState)); 1947 return PICODATA_PU_BUSY; 1948 } else { 1949 PICODBG_DEBUG(("FEED got exception %i when trying to output item",sResult)); 1950 cep->procState = cep->feedFollowState; 1951 return (picodata_step_result_t) sResult; 1952 } 1953 break; 1954 1955 default: 1956 /*NOT feeding items*/ 1957 sResult = PICO_EXC_BUF_IGNORE; 1958 break; 1959 }/*end switch (cep->procState) */ 1960 return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ 1961 1962 }/*end while*/ 1963 /* we should never come here */ 1964 return PICODATA_PU_ERROR; 1965 }/*cepStep*/ 1966 1967 /* Picocep.c end */ 1968