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 picosig.c 18 * 19 * Signal Generation 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 #include "picoos.h" 30 #include "picodsp.h" 31 #include "picosig2.h" 32 #include "picodata.h" 33 #include "picosig.h" 34 #include "picodbg.h" 35 #include "picokpdf.h" 36 37 #ifdef __cplusplus 38 extern "C" { 39 #endif 40 #if 0 41 } 42 #endif 43 44 #define PICOSIG_IN_BUFF_SIZE PICODATA_BUFSIZE_SIG /*input buffer size for SIG */ 45 #define PICOSIG_OUT_BUFF_SIZE PICODATA_BUFSIZE_SIG /*output buffer size for SIG*/ 46 47 #define PICOSIG_COLLECT 0 48 #define PICOSIG_SCHEDULE 1 49 #define PICOSIG_PLAY 2 50 #define PICOSIG_PROCESS 3 51 #define PICOSIG_FEED 4 52 53 /*---------------------------------------------------------- 54 // Internal function declarations 55 //---------------------------------------------------------*/ 56 57 static picodata_step_result_t sigStep(register picodata_ProcessingUnit this, 58 picoos_int16 mode, picoos_uint16 * numBytesOutput); 59 60 /*---------------------------------------------------------- 61 // Name : sig_subobj 62 // Function: subobject definition for the sig processing 63 // Shortcut: sig 64 //---------------------------------------------------------*/ 65 typedef struct sig_subobj 66 { 67 /*----------------------PU voice management------------------------------*/ 68 /* picorsrc_Voice voice; */ 69 /*----------------------PU state management------------------------------*/ 70 picoos_uint8 procState; /* where to take up work at next processing step */ 71 picoos_uint8 retState; /* where to return after next processing step */ 72 picoos_uint8 needMoreInput; /* more data necessary to start processing */ 73 /*----------------------PU input management------------------------------*/ 74 picoos_uint8 inBuf[PICOSIG_IN_BUFF_SIZE]; /* internal input buffer */ 75 picoos_uint16 inBufSize;/* actually allocated size */ 76 picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/ 77 /*Input audio file management*/ 78 picoos_char sInSDFileName[255]; 79 picoos_SDFile sInSDFile; 80 picoos_uint32 sInSDFilePos; 81 /*----------------------PU output management-----------------------------*/ 82 picoos_uint8 outBuf[PICOSIG_OUT_BUFF_SIZE]; /* internal output buffer */ 83 picoos_uint16 outBufSize; /* actually allocated size */ 84 picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/ 85 picoos_bool outSwitch; /* output destination switch 0:buffer, 1:file*/ 86 picoos_char sOutSDFileName[255]; /* output file name */ 87 picoos_SDFile sOutSDFile; /* output file handle */ 88 picoos_single fSampNorm; /* running normalization factor */ 89 picoos_uint32 nNumFrame; /* running count for frame number in output items */ 90 /*---------------------- other working variables ---------------------------*/ 91 picoos_uint8 innerProcState; /*where to take up work at next processing step*/ 92 /*-----------------------Definition of the local storage for this PU--------*/ 93 sig_innerobj_t sig_inner; 94 picoos_single pMod; /*pitch modifier*/ 95 picoos_single vMod; /*Volume modifier*/ 96 picoos_single sMod; /*speaker modifier*/ 97 /*knowledge bases */ 98 picokpdf_PdfMUL pdflfz, pdfmgc; 99 picoos_uint32 scmeanpowLFZ, scmeanpowMGC; 100 picoos_uint32 scmeanLFZ, scmeanMGC; 101 picokpdf_PdfPHS pdfphs; 102 103 } sig_subobj_t; 104 105 /* ****************************************************************************** 106 * generic PU management 107 ********************************************************************************/ 108 109 /** 110 * initialization of the PU (processing unit) 111 * @param this : sig PU object 112 * @return PICO_OK : init ok 113 * @return PICO_ERR_OTHER : init failed 114 * @callgraph 115 * @callergraph 116 */ 117 static pico_status_t sigInitialize(register picodata_ProcessingUnit this, picoos_int32 resetMode) 118 { 119 sig_subobj_t *sig_subObj; 120 if (NULL == this || NULL == this->subObj) { 121 return PICO_ERR_OTHER; 122 } 123 sig_subObj = (sig_subobj_t *) this->subObj; 124 sig_subObj->inBufSize = PICOSIG_IN_BUFF_SIZE; 125 sig_subObj->outBufSize = PICOSIG_OUT_BUFF_SIZE; 126 sig_subObj->inReadPos = 0; 127 sig_subObj->inWritePos = 0; 128 sig_subObj->outReadPos = 0; 129 sig_subObj->outWritePos = 0; 130 sig_subObj->needMoreInput = 0; 131 sig_subObj->procState = PICOSIG_COLLECT; 132 sig_subObj->retState = PICOSIG_COLLECT; 133 sig_subObj->innerProcState = 0; 134 sig_subObj->nNumFrame = 0; 135 136 /*----------------------------------------------------------------- 137 * MANAGE Item I/O control management 138 ------------------------------------------------------------------*/ 139 sig_subObj->sInSDFile = NULL; 140 sig_subObj->sInSDFilePos = 0; 141 sig_subObj->sInSDFileName[0] = '\0'; 142 sig_subObj->outSwitch = 0; /*PU sends output to buffer (nextPU)*/ 143 sig_subObj->sOutSDFile = NULL; 144 sig_subObj->sOutSDFileName[0] = '\0'; 145 sig_subObj->nNumFrame = 0; 146 147 /*----------------------------------------------------------------- 148 * MANAGE LINGWARE INITIALIZATION IF NEEDED 149 ------------------------------------------------------------------*/ 150 if (resetMode == PICO_RESET_FULL) { 151 /*not done when resetting SOFT*/ 152 sig_subObj->pdfmgc = picokpdf_getPdfMUL( 153 this->voice->kbArray[PICOKNOW_KBID_PDF_MGC]); 154 sig_subObj->pdflfz = picokpdf_getPdfMUL( 155 this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); 156 sig_subObj->pdfphs = picokpdf_getPdfPHS( 157 this->voice->kbArray[PICOKNOW_KBID_PDF_PHS]); 158 159 sig_subObj->scmeanpowLFZ = sig_subObj->pdflfz->bigpow 160 - sig_subObj->pdflfz->meanpow; 161 sig_subObj->scmeanpowMGC = sig_subObj->pdfmgc->bigpow 162 - sig_subObj->pdfmgc->meanpow; 163 sig_subObj->scmeanLFZ = (1 << (picoos_uint32) sig_subObj->scmeanpowLFZ); 164 sig_subObj->scmeanMGC = (1 << (picoos_uint32) sig_subObj->scmeanpowMGC); 165 sig_subObj->fSampNorm = PICOSIG_NORM1 * sig_subObj->pdfmgc->amplif; 166 /*----------------------------------------------------------------- 167 * Initialize memory for DSP 168 * ------------------------------------------------------------------*/ 169 sigDspInitialize(&(sig_subObj->sig_inner), resetMode); 170 /*----------------------------------------------------------------- 171 * Initialize modifiers 172 * ------------------------------------------------------------------*/ 173 /*pitch , volume , speaker modifiers*/ 174 sig_subObj->pMod = 1.0f; 175 sig_subObj->vMod = 1.0f; 176 sig_subObj->sMod = 1.0f; 177 } else { 178 /*----------------------------------------------------------------- 179 * Initialize memory for DSP 180 * ------------------------------------------------------------------*/ 181 sigDspInitialize(&(sig_subObj->sig_inner), resetMode); 182 } 183 184 185 return PICO_OK; 186 }/*sigInitialize*/ 187 188 /** 189 * terminates the PU (processing unit) 190 * @param this : sig PU object 191 * @return PICO_OK : termination ok 192 * @return PICO_ERR_OTHER : termination failed 193 * @callgraph 194 * @callergraph 195 */ 196 static pico_status_t sigTerminate(register picodata_ProcessingUnit this) 197 { 198 199 sig_subobj_t *sig_subObj; 200 if (NULL == this || NULL == this->subObj) { 201 return PICO_ERR_OTHER; 202 } 203 sig_subObj = (sig_subobj_t *) this->subObj; 204 205 return PICO_OK; 206 }/*sigTerminate*/ 207 208 /** 209 * deallocates the PU (processing unit) sub object 210 * @param this : sig PU object 211 * @param mm : the engine memory manager 212 * @return PICO_OK : deallocation ok 213 * @return PICO_ERR_OTHER : deallocation failed 214 * @callgraph 215 * @callergraph 216 */ 217 static pico_status_t sigSubObjDeallocate(register picodata_ProcessingUnit this, 218 picoos_MemoryManager mm) 219 { 220 sig_subobj_t *sig_subObj; 221 if ((NULL == this) || ((this)->subObj == NULL)) { 222 return PICO_ERR_OTHER; 223 } 224 sig_subObj = (sig_subobj_t *) (this)->subObj; 225 226 if (sig_subObj->sInSDFile != NULL) { 227 picoos_sdfCloseIn(this->common, &(sig_subObj->sInSDFile)); 228 sig_subObj->sInSDFile = NULL; 229 sig_subObj->sInSDFileName[0] = '\0'; 230 } 231 232 if (sig_subObj->sOutSDFile != NULL) { 233 picoos_sdfCloseOut(this->common, &(sig_subObj->sOutSDFile)); 234 sig_subObj->sOutSDFile = NULL; 235 sig_subObj->sOutSDFileName[0] = '\0'; 236 } 237 238 sigDeallocate(mm, &(sig_subObj->sig_inner)); 239 240 picoos_deallocate(this->common->mm, (void *) &this->subObj); 241 242 return PICO_OK; 243 }/*sigSubObjDeallocate*/ 244 245 /** 246 * creates a new sig processing unit 247 * @param mm : the engine memory manager 248 * @param common : the engine common object 249 * @param cbIn : the PU input buffer 250 * @param cbOut : the PU output buffer 251 * @param voice : the voice descriptor object 252 * @return a valid PU handle if creation is OK 253 * @return NULL if creation is !=OK 254 * @callgraph 255 * @callergraph 256 */ 257 picodata_ProcessingUnit picosig_newSigUnit(picoos_MemoryManager mm, 258 picoos_Common common, picodata_CharBuffer cbIn, 259 picodata_CharBuffer cbOut, picorsrc_Voice voice) 260 { 261 sig_subobj_t *sig_subObj; 262 263 picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, 264 cbOut, voice); 265 if (NULL == this) { 266 return NULL; 267 } 268 this->initialize = sigInitialize; 269 270 PICODBG_DEBUG(("picosig_newSigUnit -- creating SIG PU")); 271 /*Init function pointers*/ 272 this->step = sigStep; 273 this->terminate = sigTerminate; 274 this->subDeallocate = sigSubObjDeallocate; 275 /*sub obj allocation*/ 276 this->subObj = picoos_allocate(mm, sizeof(sig_subobj_t)); 277 278 if (NULL == this->subObj) { 279 PICODBG_ERROR(("Error in Sig Object allocation")); 280 picoos_deallocate(mm, (void *) &this); 281 return NULL; 282 } 283 sig_subObj = (sig_subobj_t *) this->subObj; 284 285 /*----------------------------------------------------------------- 286 * Allocate memory for DSP inner algorithms 287 * ------------------------------------------------------------------*/ 288 if (sigAllocate(mm, &(sig_subObj->sig_inner)) != 0) { 289 PICODBG_ERROR(("Error in Sig Sub Object Allocation")); 290 picoos_deallocate(mm, (void *) &this); 291 return NULL; 292 } 293 294 /*----------------------------------------------------------------- 295 * Initialize memory for DSP (this may be re-used elsewhere, e.g.Reset) 296 * ------------------------------------------------------------------*/ 297 if (PICO_OK != sigInitialize(this, PICO_RESET_FULL)) { 298 PICODBG_ERROR(("Error in iSig Sub Object initialization")); 299 sigDeallocate(mm, &(sig_subObj->sig_inner)); 300 picoos_deallocate(mm, (void *) &this); 301 return NULL; 302 }PICODBG_DEBUG(("SIG PU creation succeded!!")); 303 return this; 304 }/*picosig_newSigUnit*/ 305 306 /** 307 * pdf access for phase 308 * @param this : sig object pointer 309 * @param phsIndex : index of phase vectot in the pdf 310 * @param phsVect : pointer to base of array where to store the phase values 311 * @param numComponents : pointer to the variable to store the number of components 312 * @return PICO_OK : pdf retrieved 313 * @return PICO_ERR_OTHER : pdf not retrieved 314 * @callgraph 315 * @callergraph 316 */ 317 static pico_status_t getPhsFromPdf(register picodata_ProcessingUnit this, 318 picoos_uint16 phsIndex, picoos_int32 *phsVect, 319 picoos_int16 *numComponents) 320 { 321 sig_subobj_t *sig_subObj; 322 picokpdf_PdfPHS pdf; 323 static int nFrame = 0; 324 325 picoos_uint32 nIndexValue; 326 picoos_uint8 *nCurrIndexOffset, *nContent; 327 picoos_uint16 nI; 328 329 if (NULL == this || NULL == this->subObj) { 330 return PICODATA_PU_ERROR; 331 } 332 sig_subObj = (sig_subobj_t *) this->subObj; 333 pdf = sig_subObj->pdfphs; 334 /*check incoming index*/ 335 if (phsIndex >= pdf->numvectors) { 336 return PICODATA_PU_ERROR; 337 } 338 nCurrIndexOffset = ((picoos_uint8*) pdf->indexBase) + phsIndex * sizeof(picoos_uint32); 339 nIndexValue = (0xFF000000 & ((*(nCurrIndexOffset+3)) << 24)) | (0x00FF0000 & ((*(nCurrIndexOffset+2)) << 16)) | 340 (0x0000FF00 & ((*(nCurrIndexOffset+1)) << 8)) | (0x000000FF & ((*nCurrIndexOffset))); 341 nContent = pdf->contentBase; 342 nContent += nIndexValue; 343 *numComponents = (picoos_int16) *nContent++; 344 if (*numComponents>PICODSP_PHASEORDER) { 345 PICODBG_DEBUG(("WARNING : Frame %d -- Phase vector[%d] Components = %d --> too big\n", nFrame, phsIndex, *numComponents)); 346 *numComponents = PICODSP_PHASEORDER; 347 } 348 for (nI=0; nI<*numComponents; nI++) { 349 phsVect[nI] = (picoos_int32) *nContent++; 350 } 351 for (nI=*numComponents; nI<PICODSP_PHASEORDER; nI++) { 352 phsVect[nI] = 0; 353 } 354 nFrame++; 355 return PICO_OK; 356 }/*getPhsFromPdf*/ 357 358 /** 359 * processes one item with sig algo 360 * @param this : the PU object pointer 361 * @param inReadPos : read position in input buffer 362 * @param numinb : number of bytes in input buffer (including header) 363 * @param outWritePos : write position in output buffer 364 * @param numoutb : number of bytes produced in output buffer 365 * @return PICO_OK : processing successful and terminated 366 * @return PICO_STEP_BUSY : processing successful but still things to do 367 * @return PICO_ERR_OTHER : errors 368 * @remarks processes a full input item 369 * @remarks input data is one or more item, taken from local storage 370 * @remarks output data is one or more item, written in local storage 371 * @callgraph 372 * @callergraph 373 */ 374 static pico_status_t sigProcess(register picodata_ProcessingUnit this, 375 picoos_uint16 inReadPos, picoos_uint16 numinb, 376 picoos_uint16 outWritePos, picoos_uint16 *numoutb) 377 { 378 379 register sig_subobj_t * sig_subObj; 380 picoos_int16 n_i; 381 picoos_int16 n_frames, n_count; 382 picoos_int16 *s_data, offset; 383 picoos_int32 f_data, mlt, *t1, *tmp1, *tmp2; 384 picoos_uint16 tmp_uint16; 385 picopal_int16 tmp_int16; 386 picoos_uint16 i, cnt; 387 picoos_int16 hop_p_half; 388 389 sig_subObj = (sig_subobj_t *) this->subObj; 390 391 numinb = numinb; /* avoid warning "var not used in this function"*/ 392 393 /*defaults to 0 for output bytes*/ 394 *numoutb = 0; 395 396 /*Input buffer contains an item FRAME_PAR*/ 397 switch (sig_subObj->innerProcState) { 398 399 case 0: 400 /*--------------------------------------------- 401 Shifting old values 402 ---------------------------------------------*/ 403 for (n_count = 0; n_count < CEPST_BUFF_SIZE-1; n_count++) { 404 sig_subObj->sig_inner.F0Buff[n_count]=sig_subObj->sig_inner.F0Buff[n_count+1]; 405 sig_subObj->sig_inner.PhIdBuff[n_count]=sig_subObj->sig_inner.PhIdBuff[n_count+1]; 406 sig_subObj->sig_inner.VoicingBuff[n_count]=sig_subObj->sig_inner.VoicingBuff[n_count+1]; 407 sig_subObj->sig_inner.FuVBuff[n_count]=sig_subObj->sig_inner.FuVBuff[n_count+1]; 408 } 409 for (n_count = 0; n_count < PHASE_BUFF_SIZE-1; n_count++) { 410 sig_subObj->sig_inner.VoxBndBuff[n_count]=sig_subObj->sig_inner.VoxBndBuff[n_count+1]; 411 } 412 413 tmp1 = sig_subObj->sig_inner.CepBuff[0]; 414 for (n_count = 0; n_count < CEPST_BUFF_SIZE-1; n_count++) { 415 sig_subObj->sig_inner.CepBuff[n_count]=sig_subObj->sig_inner.CepBuff[n_count+1]; 416 } 417 sig_subObj->sig_inner.CepBuff[CEPST_BUFF_SIZE-1]=tmp1; 418 419 tmp1 = sig_subObj->sig_inner.PhsBuff[0]; 420 for (n_count = 0; n_count < PHASE_BUFF_SIZE-1; n_count++) { 421 sig_subObj->sig_inner.PhsBuff[n_count]=sig_subObj->sig_inner.PhsBuff[n_count+1]; 422 } 423 sig_subObj->sig_inner.PhsBuff[PHASE_BUFF_SIZE-1]=tmp1; 424 425 /*--------------------------------------------- 426 Frame related initializations 427 ---------------------------------------------*/ 428 sig_subObj->sig_inner.prevVoiced_p = sig_subObj->sig_inner.voiced_p; 429 /*--------------------------------------------- 430 Get input data from PU buffer in internal buffers 431 -------------------------------------------------*/ 432 /*load the phonetic id code*/ 433 picoos_mem_copy((void *) &sig_subObj->inBuf[inReadPos 434 + sizeof(picodata_itemhead_t)], /*src*/ 435 (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ 436 sig_subObj->sig_inner.PhIdBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16; /*store into newest*/ 437 tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.PhIdBuff[0]; /*assign oldest*/ 438 sig_subObj->sig_inner.phId_p = (picoos_int16) tmp_uint16; /*assign oldest*/ 439 440 /*load pitch values*/ 441 for (i = 0; i < sig_subObj->pdflfz->ceporder; i++) { 442 picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos 443 + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 444 * i * sizeof(tmp_uint16)]), /*src*/ 445 (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ 446 447 sig_subObj->sig_inner.F0Buff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ 448 tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.F0Buff[0]; /*assign oldest*/ 449 450 /*convert in float*/ 451 sig_subObj->sig_inner.F0_p 452 = (tmp_uint16 ? ((picoos_single) tmp_uint16 453 / sig_subObj->scmeanLFZ) : (picoos_single) 0.0); 454 455 if (sig_subObj->sig_inner.F0_p != (picoos_single) 0.0f) { 456 sig_subObj->sig_inner.F0_p = (picoos_single) exp( 457 (picoos_single) sig_subObj->sig_inner.F0_p); 458 459 } 460 /* voicing */ 461 picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos 462 + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 463 * i * sizeof(tmp_uint16) + sizeof(tmp_uint16)]),/*src*/ 464 (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ 465 466 sig_subObj->sig_inner.VoicingBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ 467 tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.VoicingBuff[0]; /*assign oldest*/ 468 469 sig_subObj->sig_inner.voicing = (picoos_single) ((tmp_uint16 470 & 0x01) * 8 + (tmp_uint16 & 0x0e) / 2) 471 / (picoos_single) 15.0f; 472 473 /* unrectified f0 */ 474 picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos 475 + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 476 * i * sizeof(tmp_uint16) + 2 * sizeof(tmp_uint16)]),/*src*/ 477 (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ 478 479 sig_subObj->sig_inner.FuVBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ 480 tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.FuVBuff[0]; /*assign oldest*/ 481 482 sig_subObj->sig_inner.Fuv_p = (picoos_single) tmp_uint16 483 / sig_subObj->scmeanLFZ; 484 sig_subObj->sig_inner.Fuv_p = (picoos_single) EXP((double)sig_subObj->sig_inner.Fuv_p); 485 } 486 /*load cep values*/ 487 offset = inReadPos + sizeof(picodata_itemhead_t) 488 + sizeof(tmp_uint16) + 489 3 * sig_subObj->pdflfz->ceporder * sizeof(tmp_int16); 490 491 tmp1 = sig_subObj->sig_inner.CepBuff[CEPST_BUFF_SIZE-1]; /*store into CURR */ 492 tmp2 = sig_subObj->sig_inner.CepBuff[0]; /*assign oldest*/ 493 494 for (i = 0; i < sig_subObj->pdfmgc->ceporder; i++) { 495 picoos_mem_copy((void *) &(sig_subObj->inBuf[offset + i 496 * sizeof(tmp_int16)]), /*src*/ 497 (void *) &tmp_int16, sizeof(tmp_int16)); /*dest+size*/ 498 499 tmp1 [i] = (picoos_int32) tmp_int16; 500 sig_subObj->sig_inner.wcep_pI[i] = (picoos_int32) tmp2[i]; 501 } 502 503 if (sig_subObj->inBuf[inReadPos+ 3] > sig_subObj->inBuf[inReadPos+ 2]*2 + 8) { 504 /*load phase values*/ 505 /*get the index*/ 506 picoos_mem_copy((void *) &(sig_subObj->inBuf[offset + sig_subObj->pdfmgc->ceporder 507 * sizeof(tmp_int16)]), /*src*/ 508 (void *) &tmp_int16, sizeof(tmp_int16)); /*dest+size*/ 509 510 /*store into buffers*/ 511 tmp1 = sig_subObj->sig_inner.PhsBuff[PHASE_BUFF_SIZE-1]; 512 /*retrieve values from pdf*/ 513 getPhsFromPdf(this, tmp_int16, tmp1, &(sig_subObj->sig_inner.VoxBndBuff[PHASE_BUFF_SIZE-1])); 514 } else { 515 /* no support for phase found */ 516 sig_subObj->sig_inner.VoxBndBuff[PHASE_BUFF_SIZE-1] = 0; 517 } 518 519 /*pitch modifier*/ 520 sig_subObj->sig_inner.F0_p *= sig_subObj->pMod; 521 sig_subObj->sig_inner.Fuv_p *= sig_subObj->pMod; 522 if (sig_subObj->sig_inner.F0_p > 0.0f) { 523 sig_subObj->sig_inner.voiced_p = 1; 524 } else { 525 sig_subObj->sig_inner.voiced_p = 0; 526 } 527 sig_subObj->sig_inner.n_available++; 528 if (sig_subObj->sig_inner.n_available>3) sig_subObj->sig_inner.n_available = 3; 529 530 if (sig_subObj->sig_inner.n_available < 3) { 531 return PICO_STEP_BUSY; 532 } 533 534 sig_subObj->innerProcState = 3; 535 return PICO_STEP_BUSY; 536 537 case 3: 538 /*Convert from mfcc to power spectrum*/ 539 save_transition_frame(&(sig_subObj->sig_inner)); 540 mel_2_lin_lookup(&(sig_subObj->sig_inner), sig_subObj->scmeanpowMGC); 541 sig_subObj->innerProcState += 1; 542 return PICO_STEP_BUSY; 543 544 case 4: 545 /*Reconstruct PHASE SPECTRUM */ 546 phase_spec2(&(sig_subObj->sig_inner)); 547 sig_subObj->innerProcState += 1; 548 return PICO_STEP_BUSY; 549 550 case 5: 551 /*Prepare Envelope spectrum for inverse FFT*/ 552 env_spec(&(sig_subObj->sig_inner)); 553 sig_subObj->innerProcState += 1; 554 return PICO_STEP_BUSY; 555 556 case 6: 557 /*Generate the impulse response of the vocal tract */ 558 impulse_response(&(sig_subObj->sig_inner)); 559 sig_subObj->innerProcState += 1; 560 return PICO_STEP_BUSY; 561 562 case 7: 563 /*Sum up N impulse responses according to excitation */ 564 td_psola2(&(sig_subObj->sig_inner)); 565 sig_subObj->innerProcState += 1; 566 return PICO_STEP_BUSY; 567 568 case 8: 569 /*Ovladd */ 570 overlap_add(&(sig_subObj->sig_inner)); 571 sig_subObj->innerProcState += 1; 572 return PICO_STEP_BUSY; 573 574 case 9: 575 /*----------------------------------------- 576 Save the output FRAME item (0:hop-1) 577 swap remaining buffer 578 ---------------------------------------------*/ 579 n_frames = 2; 580 *numoutb = 0; 581 hop_p_half = (sig_subObj->sig_inner.hop_p) / 2; 582 for (n_count = 0; n_count < n_frames; n_count++) { 583 sig_subObj->outBuf[outWritePos] 584 = (picoos_uint8) PICODATA_ITEM_FRAME; 585 sig_subObj->outBuf[outWritePos + 1] 586 = (picoos_uint8) (hop_p_half); 587 sig_subObj->outBuf[outWritePos + 2] 588 = (picoos_uint8) (sig_subObj->nNumFrame % ((hop_p_half))); 589 sig_subObj->outBuf[outWritePos + 3] 590 = (picoos_uint8) sig_subObj->sig_inner.hop_p; 591 s_data = (picoos_int16 *) &(sig_subObj->outBuf[outWritePos + 4]); 592 593 /*range control and clipping*/ 594 mlt = (picoos_int32) ((sig_subObj->fSampNorm * sig_subObj->vMod) 595 * PICODSP_END_FLOAT_NORM); 596 t1 = &(sig_subObj->sig_inner.WavBuff_p[n_count * (hop_p_half)]); 597 for (n_i = 0; n_i < hop_p_half; n_i++) { /*Normalization*/ 598 f_data = *t1++ * mlt; 599 if (f_data >= 0) 600 f_data >>= 14; 601 else 602 f_data = -(-f_data >> 14); 603 if (f_data > PICOSIG_MAXAMP) 604 f_data = PICOSIG_MAXAMP; 605 if (f_data < PICOSIG_MINAMP) 606 f_data = PICOSIG_MINAMP; 607 *s_data = (picoos_int16) (f_data); 608 s_data++; 609 } 610 sig_subObj->nNumFrame = sig_subObj->nNumFrame + 1; 611 *numoutb += ((picoos_int16) n_i * sizeof(picoos_int16)) + 4; 612 outWritePos += *numoutb; 613 }/*end for n_count*/ 614 /*Swap remaining buffer*/ 615 cnt = sig_subObj->sig_inner.m2_p - sig_subObj->sig_inner.hop_p; 616 tmp1 = sig_subObj->sig_inner.WavBuff_p; 617 tmp2 618 = &(sig_subObj->sig_inner.WavBuff_p[sig_subObj->sig_inner.hop_p]); 619 FAST_DEVICE(cnt,*(tmp1++)=*(tmp2++);) 620 ; 621 cnt = sig_subObj->sig_inner.m2_p - (sig_subObj->sig_inner.m2_p 622 - sig_subObj->sig_inner.hop_p); 623 FAST_DEVICE(cnt,*(tmp1++)=0;) 624 ; 625 sig_subObj->innerProcState = 0; /*reset to step 0*/ 626 sig_subObj->nNumFrame += 2; 627 return PICO_OK; 628 default: 629 return PICO_ERR_OTHER; 630 } 631 return PICO_ERR_OTHER; 632 }/*sigProcess*/ 633 634 /** 635 * selects items to be dealth with by this PU 636 * @param item : pointer to current item head 637 * @return TRUE : item should be managed 638 * @return FALSE : item should be passed on next PU 639 * @remarks item pointed to by *item should be already valid 640 * @callgraph 641 * @callergraph 642 */ 643 static pico_status_t sig_deal_with(const picoos_uint8 *item) 644 { 645 picodata_itemhead_t head; 646 pico_status_t s_result; 647 s_result = FALSE; 648 head.type = item[0]; 649 head.info1 = item[1]; 650 head.info2 = item[2]; 651 head.len = item[3]; 652 switch (head.type) { 653 case PICODATA_ITEM_FRAME_PAR: 654 /*the only item that is managed by sig, so far, is "FRAME_PAR"*/ 655 s_result = TRUE; 656 break; 657 case PICODATA_ITEM_CMD: 658 if ((head.info1 == PICODATA_ITEMINFO1_CMD_PLAY) || (head.info1 659 == PICODATA_ITEMINFO1_CMD_SAVE) || (head.info1 660 == PICODATA_ITEMINFO1_CMD_UNSAVE)) { 661 if (head.info2 == PICODATA_ITEMINFO2_CMD_TO_SIG) { 662 return TRUE; 663 } 664 } 665 if ((head.info1 == PICODATA_ITEMINFO1_CMD_PITCH) || (head.info1 666 == PICODATA_ITEMINFO1_CMD_VOLUME) || (head.info1 667 == PICODATA_ITEMINFO1_CMD_SPEAKER)) { 668 return TRUE; 669 } 670 break; 671 default: 672 break; 673 } 674 return s_result; 675 } /*sig_deal_with*/ 676 677 /** 678 * selects items to be managed as commands by this PU 679 * @param item : pointer to current item head 680 * @return TRUE : item should be managed as a command 681 * @return FALSE : item is not a PU command 682 * @remarks item pointed to by *item should be already valid 683 * @callgraph 684 * @callergraph 685 */ 686 static pico_status_t sig_is_command(const picoos_uint8 *item) 687 { 688 picodata_itemhead_t head; 689 head.type = item[0]; 690 head.info1 = item[1]; 691 head.info2 = item[2]; 692 head.len = item[3]; 693 switch (head.type) { 694 case PICODATA_ITEM_CMD: 695 if ((head.info1 == PICODATA_ITEMINFO1_CMD_PLAY) || (head.info1 696 == PICODATA_ITEMINFO1_CMD_SAVE) || (head.info1 697 == PICODATA_ITEMINFO1_CMD_UNSAVE)) { 698 if (head.info2 == PICODATA_ITEMINFO2_CMD_TO_SIG) { 699 return TRUE; 700 } 701 } 702 if ((head.info1 == PICODATA_ITEMINFO1_CMD_PITCH) || (head.info1 703 == PICODATA_ITEMINFO1_CMD_VOLUME) || (head.info1 704 == PICODATA_ITEMINFO1_CMD_SPEAKER)) { 705 return TRUE; 706 } 707 break; 708 default: 709 break; 710 } 711 return FALSE; 712 } /*sig_is_command*/ 713 714 /** 715 * performs a step of the sig processing 716 * @param this : pointer to current PU (Control Unit) 717 * @param mode : mode for the PU 718 * @param numBytesOutput : pointer to number of bytes produced (output) 719 * @param this : pointer to current PU (Control Unit) 720 * @return one of the "picodata_step_result_t" values 721 * @callgraph 722 * @callergraph 723 */ 724 static picodata_step_result_t sigStep(register picodata_ProcessingUnit this, 725 picoos_int16 mode, picoos_uint16 * numBytesOutput) 726 { 727 register sig_subobj_t * sig_subObj; 728 pico_status_t s_result; 729 picoos_bool b_res; 730 pico_status_t s_deal_with; 731 picoos_uint16 blen; 732 picoos_uint16 numinb, numoutb; 733 pico_status_t rv; 734 picoos_int16 *s_data; 735 picoos_int16 hop_p_half; 736 picoos_uint32 n_samp, n_i; 737 picoos_char s_temp_file_name[255]; 738 picoos_uint32 n_start, n_fram, n_bytes; 739 picoos_single f_value; 740 picoos_uint16 n_value; 741 picoos_uint32 n_pos; 742 /*wav file play volume control*/ 743 picoos_int16 *s_t1; 744 picoos_int32 sf_data, sf_mlt; 745 picoos_uint32 sf; 746 picoos_encoding_t enc; 747 picoos_uint32 numSamples; 748 749 numinb = 0; 750 numoutb = 0; 751 rv = PICO_OK; 752 s_result = PICO_OK; 753 754 if (NULL == this || NULL == this->subObj) { 755 return PICODATA_PU_ERROR; 756 } 757 sig_subObj = (sig_subobj_t *) this->subObj; 758 759 /*Init number of output bytes*/ 760 *numBytesOutput = 0; 761 762 mode = mode; /* avoid warning "var not used in this function" */ 763 764 while (1) { /* exit via return */ 765 766 PICODBG_DEBUG(("picosig.sigStep -- doing state %i",sig_subObj->procState)); 767 768 switch (sig_subObj->procState) { 769 770 case PICOSIG_COLLECT: 771 /* ************** item collector ***********************************/ 772 /*collecting items from the PU input buffer*/ 773 s_result = picodata_cbGetItem(this->cbIn, 774 &(sig_subObj->inBuf[sig_subObj->inWritePos]), 775 sig_subObj->inBufSize - sig_subObj->inWritePos, &blen); 776 777 PICODBG_DEBUG(("picosig.sigStep -- got item, status: %d",rv)); 778 779 if (s_result == PICO_EOF) { 780 /*no items available : remain in state 0 and return idle*/ 781 return PICODATA_PU_IDLE; 782 } 783 if ((PICO_OK == s_result) && (blen > 0)) { 784 /* we now have one item : CHECK IT */ 785 s_result = picodata_is_valid_item( 786 &(sig_subObj->inBuf[sig_subObj->inWritePos]), blen); 787 if (s_result != TRUE) { 788 PICODBG_DEBUG(("picosig.sigStep -- item is not valid: discard")); 789 /*Item not valid : remain in state PICOSIG_COLLECT*/ 790 return PICODATA_PU_BUSY; 791 } 792 /*item ok: it could be sent to schedule state*/ 793 sig_subObj->inWritePos += blen; 794 sig_subObj->needMoreInput = FALSE; 795 sig_subObj->procState = PICOSIG_SCHEDULE; 796 /* uncomment next to split into two steps */ 797 return PICODATA_PU_ATOMIC; 798 } 799 /*no EOF, no OK --> errors : remain in state PICOSIG_COLLECT and return error*/ 800 return PICODATA_PU_ERROR; 801 break; 802 803 case PICOSIG_SCHEDULE: 804 /* *************** item processing ***********************************/ 805 numinb = PICODATA_ITEM_HEADSIZE 806 + sig_subObj->inBuf[sig_subObj->inReadPos + 3]; 807 808 /*verify that current item has to be dealth with by this PU*/ 809 s_deal_with = sig_deal_with( 810 &(sig_subObj->inBuf[sig_subObj->inReadPos])); 811 812 switch (s_deal_with) { 813 814 case TRUE: 815 /* we have to manage this item */ 816 if (FALSE == sig_is_command( 817 &(sig_subObj->inBuf[sig_subObj->inReadPos]))) 818 { 819 /*no commands, item to deal with : switch to process state*/ 820 sig_subObj->procState = PICOSIG_PROCESS; 821 sig_subObj->retState = PICOSIG_COLLECT; 822 return PICODATA_PU_BUSY; /*data still to process or to feed*/ 823 824 } else { 825 826 /*we need to manage this item as a SIG command-item*/ 827 828 switch (sig_subObj->inBuf[sig_subObj->inReadPos + 1]) { 829 830 case PICODATA_ITEMINFO1_CMD_PLAY: 831 /*CMD recognized : consume the command */ 832 sig_subObj->inReadPos += numinb; 833 if (sig_subObj->inReadPos 834 >= sig_subObj->inWritePos) { 835 sig_subObj->inReadPos = 0; 836 sig_subObj->inWritePos = 0; 837 } 838 /*default next state setting*/ 839 sig_subObj->procState = 840 sig_subObj->retState = PICOSIG_COLLECT; 841 842 /*--------- wav file play management --------------*/ 843 if (sig_subObj->sInSDFile != NULL) { 844 /*input wav file is already open : return*/ 845 return PICODATA_PU_BUSY; 846 } 847 /*get temp file name*/ 848 picoos_strlcpy( 849 (picoos_char*) s_temp_file_name, 850 (picoos_char*) &(sig_subObj->inBuf[sig_subObj->inReadPos 851 + 4]), 852 sig_subObj->inBuf[sig_subObj->inReadPos 853 + 3] + 1); 854 /*avoid input/output file name clashes*/ 855 if (sig_subObj->sOutSDFile != NULL) { 856 if (picoos_strncmp( 857 (picoos_char*) s_temp_file_name, 858 (picoos_char*) sig_subObj->sOutSDFileName, 859 picoos_strlen( 860 (picoos_char*) s_temp_file_name)) 861 == 0) { 862 PICODBG_WARN(("input and output files has the same name!\n")); 863 return PICODATA_PU_BUSY; 864 } 865 } 866 /*actual sampled data file open*/ 867 b_res = picoos_sdfOpenIn(this->common, 868 &(sig_subObj->sInSDFile), 869 s_temp_file_name, &sf, 870 &enc, &numSamples); 871 if (b_res != TRUE) { 872 PICODBG_DEBUG(("Error on opening file %s\n", s_temp_file_name)); 873 sig_subObj->sInSDFile = NULL; 874 sig_subObj->sInSDFileName[0] = '\0'; 875 return PICODATA_PU_BUSY; 876 } 877 /*input file handle is now valid : store filename*/ 878 picoos_strlcpy( 879 (picoos_char*) sig_subObj->sInSDFileName, 880 (picoos_char*) s_temp_file_name, 881 sig_subObj->inBuf[sig_subObj->inReadPos 882 + 3] + 1); 883 sig_subObj->sInSDFilePos = 0; 884 /*switch to state PLAY and return*/ 885 sig_subObj->procState = 886 sig_subObj->retState = PICOSIG_PLAY; 887 return PICODATA_PU_BUSY; 888 break; 889 890 case PICODATA_ITEMINFO1_CMD_SAVE: 891 /*CMD recognized : consume the command */ 892 sig_subObj->inReadPos += numinb; 893 if (sig_subObj->inReadPos 894 >= sig_subObj->inWritePos) { 895 sig_subObj->inReadPos = 0; 896 sig_subObj->inWritePos = 0; 897 } 898 /*prepare return state*/ 899 sig_subObj->procState = PICOSIG_COLLECT; 900 sig_subObj->retState = PICOSIG_COLLECT; 901 /*check about output file*/ 902 if ((sig_subObj->sOutSDFile != NULL) 903 || (sig_subObj->outSwitch == 1)) { 904 /*output sig file is already active : return*/ 905 return PICODATA_PU_BUSY; 906 } 907 /*get temp file name*/ 908 picoos_strlcpy( 909 (picoos_char*) s_temp_file_name, 910 (picoos_char*) &(sig_subObj->inBuf[sig_subObj->inReadPos 911 + 4]), 912 sig_subObj->inBuf[sig_subObj->inReadPos 913 + 3] + 1); 914 /*check extension*/ 915 if (picoos_has_extension(s_temp_file_name, 916 PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION) 917 == FALSE){ 918 /*extension unsupported : return*/ 919 return PICODATA_PU_BUSY; 920 } 921 /*avoid input/output file name clashes*/ 922 if (sig_subObj->sInSDFile != NULL) { 923 if (picoos_strncmp( 924 (picoos_char*) sig_subObj->sInSDFileName, 925 (picoos_char*) s_temp_file_name, 926 picoos_strlen( 927 (picoos_char*) sig_subObj->sInSDFileName)) 928 == 0) { 929 /*input and output files has the same name : do not allow opening for writing*/ 930 PICODBG_WARN(("input and output files has the same name!\n")); 931 return PICODATA_PU_BUSY; 932 } 933 } 934 /*try to open*/ 935 picoos_sdfOpenOut(this->common, 936 &(sig_subObj->sOutSDFile), 937 s_temp_file_name, 938 SAMPLE_FREQ_16KHZ, PICOOS_ENC_LIN); 939 if (sig_subObj->sOutSDFile == NULL) { 940 PICODBG_DEBUG(("Error on opening file %s\n", sig_subObj->sOutSDFileName)); 941 sig_subObj->outSwitch = 0; 942 sig_subObj->sOutSDFileName[0] = '\0'; 943 } else { 944 /*open OK*/ 945 sig_subObj->outSwitch = 1; 946 /*store output filename*/ 947 picoos_strlcpy( 948 (picoos_char*) sig_subObj->sOutSDFileName, 949 (picoos_char*) s_temp_file_name, 950 sig_subObj->inBuf[sig_subObj->inReadPos + 3] + 1); 951 } 952 return PICODATA_PU_BUSY; 953 break; 954 955 case PICODATA_ITEMINFO1_CMD_UNSAVE: 956 /*CMD recognized : consume the command */ 957 sig_subObj->inReadPos += numinb; 958 if (sig_subObj->inReadPos 959 >= sig_subObj->inWritePos) { 960 sig_subObj->inReadPos = 0; 961 sig_subObj->inWritePos = 0; 962 } 963 /*prepare return state*/ 964 sig_subObj->procState = PICOSIG_COLLECT; 965 sig_subObj->retState = PICOSIG_COLLECT; 966 /*close the output file if any*/ 967 if ((sig_subObj->sOutSDFile == NULL) 968 || (sig_subObj->outSwitch == 0)) { 969 /*output sig file is not active : return*/ 970 PICODBG_DEBUG(("Error on requesting a binary samples file output closing : no file output handle exist\n")); 971 return PICODATA_PU_BUSY; 972 } 973 picoos_sdfCloseOut(this->common, 974 &(sig_subObj->sOutSDFile)); 975 sig_subObj->outSwitch = 0; 976 sig_subObj->sOutSDFile = NULL; 977 sig_subObj->sOutSDFileName[0] = '\0'; 978 return PICODATA_PU_BUSY; 979 break; 980 981 case PICODATA_ITEMINFO1_CMD_PITCH: 982 case PICODATA_ITEMINFO1_CMD_VOLUME: 983 case PICODATA_ITEMINFO1_CMD_SPEAKER: 984 n_pos = 4; 985 picoos_read_mem_pi_uint16( 986 &(sig_subObj->inBuf[sig_subObj->inReadPos]), 987 &n_pos, &n_value); 988 b_res = FALSE; 989 switch (sig_subObj->inBuf[sig_subObj->inReadPos + 2]) { 990 case 'a' : 991 /*absloute modifier*/ 992 f_value = (picoos_single) n_value 993 / (picoos_single) 100.0f; 994 b_res = TRUE; 995 break; 996 case 'r' : 997 /*relative modifier*/ 998 f_value = (picoos_single) n_value 999 / (picoos_single) 1000.0f; 1000 b_res = TRUE; 1001 break; 1002 default : 1003 f_value = (picoos_single)0; /*avoid warnings*/ 1004 break; 1005 } 1006 if (b_res) { 1007 switch (sig_subObj->inBuf[sig_subObj->inReadPos + 1]) { 1008 case PICODATA_ITEMINFO1_CMD_PITCH : 1009 sig_subObj->pMod = f_value; 1010 break; 1011 case PICODATA_ITEMINFO1_CMD_VOLUME : 1012 sig_subObj->vMod = f_value; 1013 break; 1014 case PICODATA_ITEMINFO1_CMD_SPEAKER : 1015 sig_subObj->sMod = f_value; 1016 sig_subObj->sig_inner.sMod_p 1017 = sig_subObj->sMod; 1018 /*call the function needed to initialize the speaker factor*/ 1019 mel_2_lin_init( 1020 &(sig_subObj->sig_inner)); 1021 break; 1022 default : 1023 break; 1024 } 1025 } 1026 1027 /*CMD recognized : consume the command */ 1028 sig_subObj->inReadPos += numinb; 1029 if (sig_subObj->inReadPos 1030 >= sig_subObj->inWritePos) { 1031 sig_subObj->inReadPos = 0; 1032 sig_subObj->inWritePos = 0; 1033 } 1034 /*prepare proc state*/ 1035 sig_subObj->procState = PICOSIG_COLLECT; 1036 sig_subObj->retState = PICOSIG_COLLECT; 1037 return PICODATA_PU_BUSY; 1038 break; 1039 default: 1040 break; 1041 }/*switch command type*/ 1042 } /*end if is command*/ 1043 break; 1044 1045 case FALSE: 1046 1047 /*we DO NOT have to deal with this item on this PU. 1048 * Normally these are still alive boundary or flush items*/ 1049 /*copy item from PU input to PU output buffer, 1050 * i.e. make it ready to FEED*/ 1051 s_result = picodata_copy_item( 1052 &(sig_subObj->inBuf[sig_subObj->inReadPos]), 1053 numinb, 1054 &(sig_subObj->outBuf[sig_subObj->outWritePos]), 1055 sig_subObj->outBufSize - sig_subObj->outWritePos, 1056 &numoutb); 1057 if (s_result != PICO_OK) { 1058 /*item not prepared properly to be sent to next PU : 1059 * do not change state and retry next time*/ 1060 sig_subObj->procState = PICOSIG_SCHEDULE; 1061 sig_subObj->retState = PICOSIG_COLLECT; 1062 return PICODATA_PU_BUSY; /*data still to process or to feed*/ 1063 } 1064 1065 /*if end of sentence reset number of frames(only needed for debugging purposes)*/ 1066 if ((sig_subObj->inBuf[sig_subObj->inReadPos] 1067 == PICODATA_ITEM_BOUND) 1068 && ((sig_subObj->inBuf[sig_subObj->inReadPos + 1] 1069 == PICODATA_ITEMINFO1_BOUND_SEND) 1070 || (sig_subObj->inBuf[sig_subObj->inReadPos 1071 + 1] 1072 == PICODATA_ITEMINFO1_BOUND_TERM))) { 1073 PICODBG_INFO(("End of sentence - Processed frames : %d", 1074 sig_subObj->nNumFrame)); 1075 sig_subObj->nNumFrame = 0; 1076 } 1077 1078 /*item processed and put in oputput buffer : consume the item*/ 1079 sig_subObj->inReadPos += numinb; 1080 sig_subObj->outWritePos += numoutb; 1081 if (sig_subObj->inReadPos >= sig_subObj->inWritePos) { 1082 /* inBuf exhausted */ 1083 sig_subObj->inReadPos = 0; 1084 sig_subObj->inWritePos = 0; 1085 sig_subObj->needMoreInput = FALSE; 1086 } 1087 sig_subObj->procState = PICOSIG_FEED; 1088 sig_subObj->retState = PICOSIG_COLLECT; 1089 return PICODATA_PU_BUSY; /*data still to process or to feed*/ 1090 break; 1091 1092 default: 1093 break; 1094 }/*end switch s_deal_with*/ 1095 1096 break; /*end case sig_schedule*/ 1097 1098 case PICOSIG_PROCESS: 1099 /* *************** item processing ***********************************/ 1100 numinb = PICODATA_ITEM_HEADSIZE 1101 + sig_subObj->inBuf[sig_subObj->inReadPos + 3]; 1102 1103 /*Process a full item*/ 1104 s_result = sigProcess(this, sig_subObj->inReadPos, numinb, 1105 sig_subObj->outWritePos, &numoutb); 1106 1107 if (s_result == PICO_OK) { 1108 sig_subObj->inReadPos += numinb; 1109 if (sig_subObj->inReadPos >= sig_subObj->inWritePos) { 1110 sig_subObj->inReadPos = 0; 1111 sig_subObj->inWritePos = 0; 1112 sig_subObj->needMoreInput = FALSE; 1113 } 1114 sig_subObj->outWritePos += numoutb; 1115 sig_subObj->procState = PICOSIG_FEED; 1116 sig_subObj->retState = PICOSIG_COLLECT; 1117 PICODBG_DEBUG(("picosig.sigStep -- leaving PICO_PROC, inReadPos = %i, outWritePos = %i",sig_subObj->inReadPos, sig_subObj->outWritePos)); 1118 return PICODATA_PU_BUSY; /*data to feed*/ 1119 } 1120 return PICODATA_PU_BUSY; /*data still to process : remain in PROCESS STATE*/ 1121 break; 1122 1123 case PICOSIG_PLAY: 1124 1125 /*management of wav file play*/ 1126 s_data = (picoos_int16 *) &(sig_subObj->outBuf[sig_subObj->outWritePos + 4]); 1127 hop_p_half = sig_subObj->sig_inner.hop_p / 2; 1128 /*read directly into PU output buffer*/ 1129 n_samp = hop_p_half; 1130 b_res = picoos_sdfGetSamples(sig_subObj->sInSDFile, 1131 sig_subObj->sInSDFilePos, &n_samp, s_data); 1132 sig_subObj->sInSDFilePos += n_samp; 1133 1134 if ((FALSE == b_res) || (0 == n_samp)) { 1135 /*file play is complete or file read error*/ 1136 picoos_sdfCloseIn(this->common, &(sig_subObj->sInSDFile)); 1137 sig_subObj->sInSDFile = NULL; 1138 sig_subObj->sInSDFileName[0] = '\0'; 1139 sig_subObj->procState = PICOSIG_COLLECT; 1140 sig_subObj->retState = PICOSIG_COLLECT; 1141 return PICODATA_PU_BUSY; /*check if data in input buffer*/ 1142 } 1143 /*-----------------------------------*/ 1144 /*Volume control of wav file playback*/ 1145 /* (code borrowed from sigProcess)*/ 1146 /*Volume mod and clipping control */ 1147 /* directly into PU output buffer*/ 1148 /*-----------------------------------*/ 1149 sf_mlt = (picoos_int32) ((sig_subObj->vMod) * 16.0f); 1150 s_t1 = &(s_data[0]); 1151 1152 for (n_i = 0; n_i < n_samp; n_i++) { 1153 if (*s_t1 != 0) { 1154 sf_data = (picoos_int32) (*s_t1) * sf_mlt; 1155 sf_data >>= 4; 1156 if (sf_data > PICOSIG_MAXAMP) { 1157 sf_data = PICOSIG_MAXAMP; 1158 } else if (sf_data < PICOSIG_MINAMP) { 1159 sf_data = PICOSIG_MINAMP; 1160 } 1161 *s_t1 = (picoos_int16) (sf_data); 1162 } 1163 s_t1++; 1164 } 1165 /*Add header info*/ 1166 sig_subObj->outBuf[sig_subObj->outWritePos] 1167 = (picoos_uint8) PICODATA_ITEM_FRAME; 1168 sig_subObj->outBuf[sig_subObj->outWritePos + 1] 1169 = (picoos_uint8) n_samp; 1170 sig_subObj->outBuf[sig_subObj->outWritePos + 2] 1171 = (picoos_uint8) (sig_subObj->nNumFrame % (hop_p_half)); /*number of frame % 64*/ 1172 sig_subObj->outBuf[sig_subObj->outWritePos + 3] 1173 = (picoos_uint8) n_samp * 2; 1174 /*Item content*/ 1175 sig_subObj->outWritePos += (n_samp * sizeof(picoos_int16)) + 4; /*including header*/ 1176 sig_subObj->procState = PICOSIG_FEED; 1177 sig_subObj->retState = PICOSIG_PLAY; 1178 break; 1179 1180 case PICOSIG_FEED: 1181 /* ************** item output/feeding ***********************************/ 1182 switch (sig_subObj->outSwitch) { 1183 case 0: 1184 /*feeding items to PU output buffer*/ 1185 s_result = picodata_cbPutItem(this->cbOut, 1186 &(sig_subObj->outBuf[sig_subObj->outReadPos]), 1187 sig_subObj->outWritePos - sig_subObj->outReadPos, 1188 &numoutb); 1189 break; 1190 case 1: 1191 /*feeding items to file*/ 1192 if (sig_subObj->outBuf[sig_subObj->outReadPos] 1193 == PICODATA_ITEM_FRAME) { 1194 if ((sig_subObj->sOutSDFile) != NULL) { 1195 n_start = (picoos_uint32) (sig_subObj->outReadPos) 1196 + PICODATA_ITEM_HEADSIZE; 1197 n_bytes = (picoos_uint32) sig_subObj->outBuf[(sig_subObj->outReadPos) 1198 + PICODATA_ITEMIND_LEN]; 1199 n_fram = (picoos_uint32) sig_subObj->outBuf[(sig_subObj->outReadPos) 1200 + PICODATA_ITEMIND_INFO2]; 1201 if (picoos_sdfPutSamples( 1202 sig_subObj->sOutSDFile, 1203 n_bytes / 2, 1204 (picoos_int16*) &(sig_subObj->outBuf[n_start]))) { 1205 PICODBG_DEBUG(("Nframe:%d - Nbytes %d\n", n_fram, n_bytes)); 1206 numoutb = n_bytes + 4; 1207 s_result = PICO_OK; 1208 /* also feed item to next PU */ 1209 s_result = picodata_cbPutItem( 1210 this->cbOut, 1211 &(sig_subObj->outBuf[sig_subObj->outReadPos]), 1212 sig_subObj->outWritePos 1213 - sig_subObj->outReadPos, 1214 &numoutb); 1215 } else { 1216 /*write error : close file + cleanup handles*/ 1217 if (sig_subObj->sOutSDFile != NULL) { 1218 picoos_sdfCloseOut(this->common, &(sig_subObj->sOutSDFile)); 1219 sig_subObj->sOutSDFile = NULL; 1220 } 1221 sig_subObj->sOutSDFileName[0] = '\0'; 1222 sig_subObj->outSwitch = 0; 1223 PICODBG_DEBUG(("Error in writing :%d bytes to output file %s\n", numoutb, &(sig_subObj->sOutSDFileName[0]))); 1224 s_result = PICO_ERR_OTHER; 1225 } 1226 } 1227 } else { 1228 /*continue to feed following PU with items != FRAME */ 1229 s_result = picodata_cbPutItem( 1230 this->cbOut, 1231 &(sig_subObj->outBuf[sig_subObj->outReadPos]), 1232 sig_subObj->outWritePos - sig_subObj->outReadPos, 1233 &numoutb); 1234 } 1235 break; 1236 default: 1237 s_result = PICO_ERR_OTHER; 1238 break; 1239 } 1240 PICODBG_DEBUG(("picosig.sigStep -- put item, status: %d",s_result)); 1241 1242 if (PICO_OK == s_result) { 1243 1244 sig_subObj->outReadPos += numoutb; 1245 *numBytesOutput = numoutb; 1246 /*-------------------------*/ 1247 /*reset the output pointers*/ 1248 /*-------------------------*/ 1249 if (sig_subObj->outReadPos >= sig_subObj->outWritePos) { 1250 sig_subObj->outReadPos = 0; 1251 sig_subObj->outWritePos = 0; 1252 sig_subObj->procState = sig_subObj->retState; 1253 } 1254 return PICODATA_PU_BUSY; 1255 1256 } else if (PICO_EXC_BUF_OVERFLOW == s_result) { 1257 1258 PICODBG_DEBUG(("picosig.sigStep ** feeding, overflow, PICODATA_PU_OUT_FULL")); 1259 return PICODATA_PU_OUT_FULL; 1260 1261 } else if ((PICO_EXC_BUF_UNDERFLOW == s_result) 1262 || (PICO_ERR_OTHER == s_result)) { 1263 1264 PICODBG_DEBUG(("picosig.sigStep ** feeding problem, discarding item")); 1265 sig_subObj->outReadPos = 0; 1266 sig_subObj->outWritePos = 0; 1267 sig_subObj->procState = sig_subObj->retState; 1268 return PICODATA_PU_ERROR; 1269 1270 } 1271 break; 1272 default: 1273 /*NOT feeding items*/ 1274 s_result = PICO_EXC_BUF_IGNORE; 1275 break; 1276 }/*end switch*/ 1277 return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ 1278 1279 }/*end while*/ 1280 return PICODATA_PU_IDLE; 1281 }/*sigStep*/ 1282 1283 #ifdef __cplusplus 1284 } 1285 #endif 1286 1287 /* Picosig.c end */ 1288