| /* |
| * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /** |
| * @file picosig.c |
| * |
| * Signal Generation PU - Implementation |
| * |
| * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland |
| * All rights reserved. |
| * |
| * History: |
| * - 2009-04-20 -- initial version |
| * |
| */ |
| |
| #include "picoos.h" |
| #include "picodsp.h" |
| #include "picosig2.h" |
| #include "picodata.h" |
| #include "picosig.h" |
| #include "picodbg.h" |
| #include "picokpdf.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| #if 0 |
| } |
| #endif |
| |
| #define PICOSIG_IN_BUFF_SIZE PICODATA_BUFSIZE_SIG /*input buffer size for SIG */ |
| #define PICOSIG_OUT_BUFF_SIZE PICODATA_BUFSIZE_SIG /*output buffer size for SIG*/ |
| |
| #define PICOSIG_COLLECT 0 |
| #define PICOSIG_SCHEDULE 1 |
| #define PICOSIG_PLAY 2 |
| #define PICOSIG_PROCESS 3 |
| #define PICOSIG_FEED 4 |
| |
| /*---------------------------------------------------------- |
| // Internal function declarations |
| //---------------------------------------------------------*/ |
| |
| static picodata_step_result_t sigStep(register picodata_ProcessingUnit this, |
| picoos_int16 mode, picoos_uint16 * numBytesOutput); |
| |
| /*---------------------------------------------------------- |
| // Name : sig_subobj |
| // Function: subobject definition for the sig processing |
| // Shortcut: sig |
| //---------------------------------------------------------*/ |
| typedef struct sig_subobj |
| { |
| /*----------------------PU voice management------------------------------*/ |
| /* picorsrc_Voice voice; */ |
| /*----------------------PU state management------------------------------*/ |
| picoos_uint8 procState; /* where to take up work at next processing step */ |
| picoos_uint8 retState; /* where to return after next processing step */ |
| picoos_uint8 needMoreInput; /* more data necessary to start processing */ |
| /*----------------------PU input management------------------------------*/ |
| picoos_uint8 inBuf[PICOSIG_IN_BUFF_SIZE]; /* internal input buffer */ |
| picoos_uint16 inBufSize;/* actually allocated size */ |
| picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/ |
| /*Input audio file management*/ |
| picoos_char sInSDFileName[255]; |
| picoos_SDFile sInSDFile; |
| picoos_uint32 sInSDFilePos; |
| /*----------------------PU output management-----------------------------*/ |
| picoos_uint8 outBuf[PICOSIG_OUT_BUFF_SIZE]; /* internal output buffer */ |
| picoos_uint16 outBufSize; /* actually allocated size */ |
| picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/ |
| picoos_bool outSwitch; /* output destination switch 0:buffer, 1:file*/ |
| picoos_char sOutSDFileName[255]; /* output file name */ |
| picoos_SDFile sOutSDFile; /* output file handle */ |
| picoos_single fSampNorm; /* running normalization factor */ |
| picoos_uint32 nNumFrame; /* running count for frame number in output items */ |
| /*---------------------- other working variables ---------------------------*/ |
| picoos_uint8 innerProcState; /*where to take up work at next processing step*/ |
| /*-----------------------Definition of the local storage for this PU--------*/ |
| sig_innerobj_t sig_inner; |
| picoos_single pMod; /*pitch modifier*/ |
| picoos_single vMod; /*Volume modifier*/ |
| picoos_single sMod; /*speaker modifier*/ |
| /*knowledge bases */ |
| picokpdf_PdfMUL pdflfz, pdfmgc; |
| picoos_uint32 scmeanpowLFZ, scmeanpowMGC; |
| picoos_uint32 scmeanLFZ, scmeanMGC; |
| picokpdf_PdfPHS pdfphs; |
| |
| } sig_subobj_t; |
| |
| /* ****************************************************************************** |
| * generic PU management |
| ********************************************************************************/ |
| |
| /** |
| * initialization of the PU (processing unit) |
| * @param this : sig PU object |
| * @return PICO_OK : init ok |
| * @return PICO_ERR_OTHER : init failed |
| * @callgraph |
| * @callergraph |
| */ |
| static pico_status_t sigInitialize(register picodata_ProcessingUnit this, picoos_int32 resetMode) |
| { |
| sig_subobj_t *sig_subObj; |
| if (NULL == this || NULL == this->subObj) { |
| return PICO_ERR_OTHER; |
| } |
| sig_subObj = (sig_subobj_t *) this->subObj; |
| sig_subObj->inBufSize = PICOSIG_IN_BUFF_SIZE; |
| sig_subObj->outBufSize = PICOSIG_OUT_BUFF_SIZE; |
| sig_subObj->inReadPos = 0; |
| sig_subObj->inWritePos = 0; |
| sig_subObj->outReadPos = 0; |
| sig_subObj->outWritePos = 0; |
| sig_subObj->needMoreInput = 0; |
| sig_subObj->procState = PICOSIG_COLLECT; |
| sig_subObj->retState = PICOSIG_COLLECT; |
| sig_subObj->innerProcState = 0; |
| sig_subObj->nNumFrame = 0; |
| |
| /*----------------------------------------------------------------- |
| * MANAGE Item I/O control management |
| ------------------------------------------------------------------*/ |
| sig_subObj->sInSDFile = NULL; |
| sig_subObj->sInSDFilePos = 0; |
| sig_subObj->sInSDFileName[0] = '\0'; |
| sig_subObj->outSwitch = 0; /*PU sends output to buffer (nextPU)*/ |
| sig_subObj->sOutSDFile = NULL; |
| sig_subObj->sOutSDFileName[0] = '\0'; |
| sig_subObj->nNumFrame = 0; |
| |
| /*----------------------------------------------------------------- |
| * MANAGE LINGWARE INITIALIZATION IF NEEDED |
| ------------------------------------------------------------------*/ |
| if (resetMode == PICO_RESET_FULL) { |
| /*not done when resetting SOFT*/ |
| sig_subObj->pdfmgc = picokpdf_getPdfMUL( |
| this->voice->kbArray[PICOKNOW_KBID_PDF_MGC]); |
| sig_subObj->pdflfz = picokpdf_getPdfMUL( |
| this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); |
| sig_subObj->pdfphs = picokpdf_getPdfPHS( |
| this->voice->kbArray[PICOKNOW_KBID_PDF_PHS]); |
| |
| sig_subObj->scmeanpowLFZ = sig_subObj->pdflfz->bigpow |
| - sig_subObj->pdflfz->meanpow; |
| sig_subObj->scmeanpowMGC = sig_subObj->pdfmgc->bigpow |
| - sig_subObj->pdfmgc->meanpow; |
| sig_subObj->scmeanLFZ = (1 << (picoos_uint32) sig_subObj->scmeanpowLFZ); |
| sig_subObj->scmeanMGC = (1 << (picoos_uint32) sig_subObj->scmeanpowMGC); |
| sig_subObj->fSampNorm = PICOSIG_NORM1 * sig_subObj->pdfmgc->amplif; |
| /*----------------------------------------------------------------- |
| * Initialize memory for DSP |
| * ------------------------------------------------------------------*/ |
| sigDspInitialize(&(sig_subObj->sig_inner), resetMode); |
| /*----------------------------------------------------------------- |
| * Initialize modifiers |
| * ------------------------------------------------------------------*/ |
| /*pitch , volume , speaker modifiers*/ |
| sig_subObj->pMod = 1.0f; |
| sig_subObj->vMod = 1.0f; |
| sig_subObj->sMod = 1.0f; |
| } else { |
| /*----------------------------------------------------------------- |
| * Initialize memory for DSP |
| * ------------------------------------------------------------------*/ |
| sigDspInitialize(&(sig_subObj->sig_inner), resetMode); |
| } |
| |
| |
| return PICO_OK; |
| }/*sigInitialize*/ |
| |
| /** |
| * terminates the PU (processing unit) |
| * @param this : sig PU object |
| * @return PICO_OK : termination ok |
| * @return PICO_ERR_OTHER : termination failed |
| * @callgraph |
| * @callergraph |
| */ |
| static pico_status_t sigTerminate(register picodata_ProcessingUnit this) |
| { |
| |
| sig_subobj_t *sig_subObj; |
| if (NULL == this || NULL == this->subObj) { |
| return PICO_ERR_OTHER; |
| } |
| sig_subObj = (sig_subobj_t *) this->subObj; |
| |
| return PICO_OK; |
| }/*sigTerminate*/ |
| |
| /** |
| * deallocates the PU (processing unit) sub object |
| * @param this : sig PU object |
| * @param mm : the engine memory manager |
| * @return PICO_OK : deallocation ok |
| * @return PICO_ERR_OTHER : deallocation failed |
| * @callgraph |
| * @callergraph |
| */ |
| static pico_status_t sigSubObjDeallocate(register picodata_ProcessingUnit this, |
| picoos_MemoryManager mm) |
| { |
| sig_subobj_t *sig_subObj; |
| if ((NULL == this) || ((this)->subObj == NULL)) { |
| return PICO_ERR_OTHER; |
| } |
| sig_subObj = (sig_subobj_t *) (this)->subObj; |
| |
| if (sig_subObj->sInSDFile != NULL) { |
| picoos_sdfCloseIn(this->common, &(sig_subObj->sInSDFile)); |
| sig_subObj->sInSDFile = NULL; |
| sig_subObj->sInSDFileName[0] = '\0'; |
| } |
| |
| if (sig_subObj->sOutSDFile != NULL) { |
| picoos_sdfCloseOut(this->common, &(sig_subObj->sOutSDFile)); |
| sig_subObj->sOutSDFile = NULL; |
| sig_subObj->sOutSDFileName[0] = '\0'; |
| } |
| |
| sigDeallocate(mm, &(sig_subObj->sig_inner)); |
| |
| picoos_deallocate(this->common->mm, (void *) &this->subObj); |
| |
| return PICO_OK; |
| }/*sigSubObjDeallocate*/ |
| |
| /** |
| * creates a new sig processing unit |
| * @param mm : the engine memory manager |
| * @param common : the engine common object |
| * @param cbIn : the PU input buffer |
| * @param cbOut : the PU output buffer |
| * @param voice : the voice descriptor object |
| * @return a valid PU handle if creation is OK |
| * @return NULL if creation is !=OK |
| * @callgraph |
| * @callergraph |
| */ |
| picodata_ProcessingUnit picosig_newSigUnit(picoos_MemoryManager mm, |
| picoos_Common common, picodata_CharBuffer cbIn, |
| picodata_CharBuffer cbOut, picorsrc_Voice voice) |
| { |
| sig_subobj_t *sig_subObj; |
| |
| picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, |
| cbOut, voice); |
| if (NULL == this) { |
| return NULL; |
| } |
| this->initialize = sigInitialize; |
| |
| PICODBG_DEBUG(("picosig_newSigUnit -- creating SIG PU")); |
| /*Init function pointers*/ |
| this->step = sigStep; |
| this->terminate = sigTerminate; |
| this->subDeallocate = sigSubObjDeallocate; |
| /*sub obj allocation*/ |
| this->subObj = picoos_allocate(mm, sizeof(sig_subobj_t)); |
| |
| if (NULL == this->subObj) { |
| PICODBG_ERROR(("Error in Sig Object allocation")); |
| picoos_deallocate(mm, (void *) &this); |
| return NULL; |
| } |
| sig_subObj = (sig_subobj_t *) this->subObj; |
| |
| /*----------------------------------------------------------------- |
| * Allocate memory for DSP inner algorithms |
| * ------------------------------------------------------------------*/ |
| if (sigAllocate(mm, &(sig_subObj->sig_inner)) != 0) { |
| PICODBG_ERROR(("Error in Sig Sub Object Allocation")); |
| picoos_deallocate(mm, (void *) &this); |
| return NULL; |
| } |
| |
| /*----------------------------------------------------------------- |
| * Initialize memory for DSP (this may be re-used elsewhere, e.g.Reset) |
| * ------------------------------------------------------------------*/ |
| if (PICO_OK != sigInitialize(this, PICO_RESET_FULL)) { |
| PICODBG_ERROR(("Error in iSig Sub Object initialization")); |
| sigDeallocate(mm, &(sig_subObj->sig_inner)); |
| picoos_deallocate(mm, (void *) &this); |
| return NULL; |
| }PICODBG_DEBUG(("SIG PU creation succeded!!")); |
| return this; |
| }/*picosig_newSigUnit*/ |
| |
| /** |
| * pdf access for phase |
| * @param this : sig object pointer |
| * @param phsIndex : index of phase vectot in the pdf |
| * @param phsVect : pointer to base of array where to store the phase values |
| * @param numComponents : pointer to the variable to store the number of components |
| * @return PICO_OK : pdf retrieved |
| * @return PICO_ERR_OTHER : pdf not retrieved |
| * @callgraph |
| * @callergraph |
| */ |
| static pico_status_t getPhsFromPdf(register picodata_ProcessingUnit this, |
| picoos_uint16 phsIndex, picoos_int32 *phsVect, |
| picoos_int16 *numComponents) |
| { |
| sig_subobj_t *sig_subObj; |
| picokpdf_PdfPHS pdf; |
| static int nFrame = 0; |
| |
| picoos_uint32 nIndexValue; |
| picoos_uint8 *nCurrIndexOffset, *nContent; |
| picoos_uint16 nI; |
| |
| if (NULL == this || NULL == this->subObj) { |
| return PICODATA_PU_ERROR; |
| } |
| sig_subObj = (sig_subobj_t *) this->subObj; |
| pdf = sig_subObj->pdfphs; |
| /*check incoming index*/ |
| if (phsIndex >= pdf->numvectors) { |
| return PICODATA_PU_ERROR; |
| } |
| nCurrIndexOffset = ((picoos_uint8*) pdf->indexBase) + phsIndex * sizeof(picoos_uint32); |
| nIndexValue = (0xFF000000 & ((*(nCurrIndexOffset+3)) << 24)) | (0x00FF0000 & ((*(nCurrIndexOffset+2)) << 16)) | |
| (0x0000FF00 & ((*(nCurrIndexOffset+1)) << 8)) | (0x000000FF & ((*nCurrIndexOffset))); |
| nContent = pdf->contentBase; |
| nContent += nIndexValue; |
| *numComponents = (picoos_int16) *nContent++; |
| if (*numComponents>PICODSP_PHASEORDER) { |
| PICODBG_DEBUG(("WARNING : Frame %d -- Phase vector[%d] Components = %d --> too big\n", nFrame, phsIndex, *numComponents)); |
| *numComponents = PICODSP_PHASEORDER; |
| } |
| for (nI=0; nI<*numComponents; nI++) { |
| phsVect[nI] = (picoos_int32) *nContent++; |
| } |
| for (nI=*numComponents; nI<PICODSP_PHASEORDER; nI++) { |
| phsVect[nI] = 0; |
| } |
| nFrame++; |
| return PICO_OK; |
| }/*getPhsFromPdf*/ |
| |
| /** |
| * processes one item with sig algo |
| * @param this : the PU object pointer |
| * @param inReadPos : read position in input buffer |
| * @param numinb : number of bytes in input buffer (including header) |
| * @param outWritePos : write position in output buffer |
| * @param numoutb : number of bytes produced in output buffer |
| * @return PICO_OK : processing successful and terminated |
| * @return PICO_STEP_BUSY : processing successful but still things to do |
| * @return PICO_ERR_OTHER : errors |
| * @remarks processes a full input item |
| * @remarks input data is one or more item, taken from local storage |
| * @remarks output data is one or more item, written in local storage |
| * @callgraph |
| * @callergraph |
| */ |
| static pico_status_t sigProcess(register picodata_ProcessingUnit this, |
| picoos_uint16 inReadPos, picoos_uint16 numinb, |
| picoos_uint16 outWritePos, picoos_uint16 *numoutb) |
| { |
| |
| register sig_subobj_t * sig_subObj; |
| picoos_int16 n_i; |
| picoos_int16 n_frames, n_count; |
| picoos_int16 *s_data, offset; |
| picoos_int32 f_data, mlt, *t1, *tmp1, *tmp2; |
| picoos_uint16 tmp_uint16; |
| picopal_int16 tmp_int16; |
| picoos_uint16 i, cnt; |
| picoos_int16 hop_p_half; |
| |
| sig_subObj = (sig_subobj_t *) this->subObj; |
| |
| numinb = numinb; /* avoid warning "var not used in this function"*/ |
| |
| /*defaults to 0 for output bytes*/ |
| *numoutb = 0; |
| |
| /*Input buffer contains an item FRAME_PAR*/ |
| switch (sig_subObj->innerProcState) { |
| |
| case 0: |
| /*--------------------------------------------- |
| Shifting old values |
| ---------------------------------------------*/ |
| for (n_count = 0; n_count < CEPST_BUFF_SIZE-1; n_count++) { |
| sig_subObj->sig_inner.F0Buff[n_count]=sig_subObj->sig_inner.F0Buff[n_count+1]; |
| sig_subObj->sig_inner.PhIdBuff[n_count]=sig_subObj->sig_inner.PhIdBuff[n_count+1]; |
| sig_subObj->sig_inner.VoicingBuff[n_count]=sig_subObj->sig_inner.VoicingBuff[n_count+1]; |
| sig_subObj->sig_inner.FuVBuff[n_count]=sig_subObj->sig_inner.FuVBuff[n_count+1]; |
| } |
| for (n_count = 0; n_count < PHASE_BUFF_SIZE-1; n_count++) { |
| sig_subObj->sig_inner.VoxBndBuff[n_count]=sig_subObj->sig_inner.VoxBndBuff[n_count+1]; |
| } |
| |
| tmp1 = sig_subObj->sig_inner.CepBuff[0]; |
| for (n_count = 0; n_count < CEPST_BUFF_SIZE-1; n_count++) { |
| sig_subObj->sig_inner.CepBuff[n_count]=sig_subObj->sig_inner.CepBuff[n_count+1]; |
| } |
| sig_subObj->sig_inner.CepBuff[CEPST_BUFF_SIZE-1]=tmp1; |
| |
| tmp1 = sig_subObj->sig_inner.PhsBuff[0]; |
| for (n_count = 0; n_count < PHASE_BUFF_SIZE-1; n_count++) { |
| sig_subObj->sig_inner.PhsBuff[n_count]=sig_subObj->sig_inner.PhsBuff[n_count+1]; |
| } |
| sig_subObj->sig_inner.PhsBuff[PHASE_BUFF_SIZE-1]=tmp1; |
| |
| /*--------------------------------------------- |
| Frame related initializations |
| ---------------------------------------------*/ |
| sig_subObj->sig_inner.prevVoiced_p = sig_subObj->sig_inner.voiced_p; |
| /*--------------------------------------------- |
| Get input data from PU buffer in internal buffers |
| -------------------------------------------------*/ |
| /*load the phonetic id code*/ |
| picoos_mem_copy((void *) &sig_subObj->inBuf[inReadPos |
| + sizeof(picodata_itemhead_t)], /*src*/ |
| (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ |
| sig_subObj->sig_inner.PhIdBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16; /*store into newest*/ |
| tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.PhIdBuff[0]; /*assign oldest*/ |
| sig_subObj->sig_inner.phId_p = (picoos_int16) tmp_uint16; /*assign oldest*/ |
| |
| /*load pitch values*/ |
| for (i = 0; i < sig_subObj->pdflfz->ceporder; i++) { |
| picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos |
| + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 |
| * i * sizeof(tmp_uint16)]), /*src*/ |
| (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ |
| |
| sig_subObj->sig_inner.F0Buff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ |
| tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.F0Buff[0]; /*assign oldest*/ |
| |
| /*convert in float*/ |
| sig_subObj->sig_inner.F0_p |
| = (tmp_uint16 ? ((picoos_single) tmp_uint16 |
| / sig_subObj->scmeanLFZ) : (picoos_single) 0.0); |
| |
| if (sig_subObj->sig_inner.F0_p != (picoos_single) 0.0f) { |
| sig_subObj->sig_inner.F0_p = (picoos_single) exp( |
| (picoos_single) sig_subObj->sig_inner.F0_p); |
| |
| } |
| /* voicing */ |
| picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos |
| + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 |
| * i * sizeof(tmp_uint16) + sizeof(tmp_uint16)]),/*src*/ |
| (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ |
| |
| sig_subObj->sig_inner.VoicingBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ |
| tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.VoicingBuff[0]; /*assign oldest*/ |
| |
| sig_subObj->sig_inner.voicing = (picoos_single) ((tmp_uint16 |
| & 0x01) * 8 + (tmp_uint16 & 0x0e) / 2) |
| / (picoos_single) 15.0f; |
| |
| /* unrectified f0 */ |
| picoos_mem_copy((void *) &(sig_subObj->inBuf[inReadPos |
| + sizeof(picodata_itemhead_t) + sizeof(tmp_uint16) + 3 |
| * i * sizeof(tmp_uint16) + 2 * sizeof(tmp_uint16)]),/*src*/ |
| (void *) &tmp_uint16, sizeof(tmp_uint16)); /*dest+size*/ |
| |
| sig_subObj->sig_inner.FuVBuff[CEPST_BUFF_SIZE-1] = (picoos_int16) tmp_uint16;/*store into newest*/ |
| tmp_uint16 = (picoos_int16) sig_subObj->sig_inner.FuVBuff[0]; /*assign oldest*/ |
| |
| sig_subObj->sig_inner.Fuv_p = (picoos_single) tmp_uint16 |
| / sig_subObj->scmeanLFZ; |
| sig_subObj->sig_inner.Fuv_p = (picoos_single) EXP((double)sig_subObj->sig_inner.Fuv_p); |
| } |
| /*load cep values*/ |
| offset = inReadPos + sizeof(picodata_itemhead_t) |
| + sizeof(tmp_uint16) + |
| 3 * sig_subObj->pdflfz->ceporder * sizeof(tmp_int16); |
| |
| tmp1 = sig_subObj->sig_inner.CepBuff[CEPST_BUFF_SIZE-1]; /*store into CURR */ |
| tmp2 = sig_subObj->sig_inner.CepBuff[0]; /*assign oldest*/ |
| |
| for (i = 0; i < sig_subObj->pdfmgc->ceporder; i++) { |
| picoos_mem_copy((void *) &(sig_subObj->inBuf[offset + i |
| * sizeof(tmp_int16)]), /*src*/ |
| (void *) &tmp_int16, sizeof(tmp_int16)); /*dest+size*/ |
| |
| tmp1 [i] = (picoos_int32) tmp_int16; |
| sig_subObj->sig_inner.wcep_pI[i] = (picoos_int32) tmp2[i]; |
| } |
| |
| if (sig_subObj->inBuf[inReadPos+ 3] > sig_subObj->inBuf[inReadPos+ 2]*2 + 8) { |
| /*load phase values*/ |
| /*get the index*/ |
| picoos_mem_copy((void *) &(sig_subObj->inBuf[offset + sig_subObj->pdfmgc->ceporder |
| * sizeof(tmp_int16)]), /*src*/ |
| (void *) &tmp_int16, sizeof(tmp_int16)); /*dest+size*/ |
| |
| /*store into buffers*/ |
| tmp1 = sig_subObj->sig_inner.PhsBuff[PHASE_BUFF_SIZE-1]; |
| /*retrieve values from pdf*/ |
| getPhsFromPdf(this, tmp_int16, tmp1, &(sig_subObj->sig_inner.VoxBndBuff[PHASE_BUFF_SIZE-1])); |
| } else { |
| /* no support for phase found */ |
| sig_subObj->sig_inner.VoxBndBuff[PHASE_BUFF_SIZE-1] = 0; |
| } |
| |
| /*pitch modifier*/ |
| sig_subObj->sig_inner.F0_p *= sig_subObj->pMod; |
| sig_subObj->sig_inner.Fuv_p *= sig_subObj->pMod; |
| if (sig_subObj->sig_inner.F0_p > 0.0f) { |
| sig_subObj->sig_inner.voiced_p = 1; |
| } else { |
| sig_subObj->sig_inner.voiced_p = 0; |
| } |
| sig_subObj->sig_inner.n_available++; |
| if (sig_subObj->sig_inner.n_available>3) sig_subObj->sig_inner.n_available = 3; |
| |
| if (sig_subObj->sig_inner.n_available < 3) { |
| return PICO_STEP_BUSY; |
| } |
| |
| sig_subObj->innerProcState = 3; |
| return PICO_STEP_BUSY; |
| |
| case 3: |
| /*Convert from mfcc to power spectrum*/ |
| save_transition_frame(&(sig_subObj->sig_inner)); |
| mel_2_lin_lookup(&(sig_subObj->sig_inner), sig_subObj->scmeanpowMGC); |
| sig_subObj->innerProcState += 1; |
| return PICO_STEP_BUSY; |
| |
| case 4: |
| /*Reconstruct PHASE SPECTRUM */ |
| phase_spec2(&(sig_subObj->sig_inner)); |
| sig_subObj->innerProcState += 1; |
| return PICO_STEP_BUSY; |
| |
| case 5: |
| /*Prepare Envelope spectrum for inverse FFT*/ |
| env_spec(&(sig_subObj->sig_inner)); |
| sig_subObj->innerProcState += 1; |
| return PICO_STEP_BUSY; |
| |
| case 6: |
| /*Generate the impulse response of the vocal tract */ |
| impulse_response(&(sig_subObj->sig_inner)); |
| sig_subObj->innerProcState += 1; |
| return PICO_STEP_BUSY; |
| |
| case 7: |
| /*Sum up N impulse responses according to excitation */ |
| td_psola2(&(sig_subObj->sig_inner)); |
| sig_subObj->innerProcState += 1; |
| return PICO_STEP_BUSY; |
| |
| case 8: |
| /*Ovladd */ |
| overlap_add(&(sig_subObj->sig_inner)); |
| sig_subObj->innerProcState += 1; |
| return PICO_STEP_BUSY; |
| |
| case 9: |
| /*----------------------------------------- |
| Save the output FRAME item (0:hop-1) |
| swap remaining buffer |
| ---------------------------------------------*/ |
| n_frames = 2; |
| *numoutb = 0; |
| hop_p_half = (sig_subObj->sig_inner.hop_p) / 2; |
| for (n_count = 0; n_count < n_frames; n_count++) { |
| sig_subObj->outBuf[outWritePos] |
| = (picoos_uint8) PICODATA_ITEM_FRAME; |
| sig_subObj->outBuf[outWritePos + 1] |
| = (picoos_uint8) (hop_p_half); |
| sig_subObj->outBuf[outWritePos + 2] |
| = (picoos_uint8) (sig_subObj->nNumFrame % ((hop_p_half))); |
| sig_subObj->outBuf[outWritePos + 3] |
| = (picoos_uint8) sig_subObj->sig_inner.hop_p; |
| s_data = (picoos_int16 *) &(sig_subObj->outBuf[outWritePos + 4]); |
| |
| /*range control and clipping*/ |
| mlt = (picoos_int32) ((sig_subObj->fSampNorm * sig_subObj->vMod) |
| * PICODSP_END_FLOAT_NORM); |
| t1 = &(sig_subObj->sig_inner.WavBuff_p[n_count * (hop_p_half)]); |
| for (n_i = 0; n_i < hop_p_half; n_i++) { /*Normalization*/ |
| f_data = *t1++ * mlt; |
| if (f_data >= 0) |
| f_data >>= 14; |
| else |
| f_data = -(-f_data >> 14); |
| if (f_data > PICOSIG_MAXAMP) |
| f_data = PICOSIG_MAXAMP; |
| if (f_data < PICOSIG_MINAMP) |
| f_data = PICOSIG_MINAMP; |
| *s_data = (picoos_int16) (f_data); |
| s_data++; |
| } |
| sig_subObj->nNumFrame = sig_subObj->nNumFrame + 1; |
| *numoutb += ((picoos_int16) n_i * sizeof(picoos_int16)) + 4; |
| outWritePos += *numoutb; |
| }/*end for n_count*/ |
| /*Swap remaining buffer*/ |
| cnt = sig_subObj->sig_inner.m2_p - sig_subObj->sig_inner.hop_p; |
| tmp1 = sig_subObj->sig_inner.WavBuff_p; |
| tmp2 |
| = &(sig_subObj->sig_inner.WavBuff_p[sig_subObj->sig_inner.hop_p]); |
| FAST_DEVICE(cnt,*(tmp1++)=*(tmp2++);) |
| ; |
| cnt = sig_subObj->sig_inner.m2_p - (sig_subObj->sig_inner.m2_p |
| - sig_subObj->sig_inner.hop_p); |
| FAST_DEVICE(cnt,*(tmp1++)=0;) |
| ; |
| sig_subObj->innerProcState = 0; /*reset to step 0*/ |
| sig_subObj->nNumFrame += 2; |
| return PICO_OK; |
| default: |
| return PICO_ERR_OTHER; |
| } |
| return PICO_ERR_OTHER; |
| }/*sigProcess*/ |
| |
| /** |
| * selects items to be dealth with by this PU |
| * @param item : pointer to current item head |
| * @return TRUE : item should be managed |
| * @return FALSE : item should be passed on next PU |
| * @remarks item pointed to by *item should be already valid |
| * @callgraph |
| * @callergraph |
| */ |
| static pico_status_t sig_deal_with(const picoos_uint8 *item) |
| { |
| picodata_itemhead_t head; |
| pico_status_t s_result; |
| s_result = FALSE; |
| head.type = item[0]; |
| head.info1 = item[1]; |
| head.info2 = item[2]; |
| head.len = item[3]; |
| switch (head.type) { |
| case PICODATA_ITEM_FRAME_PAR: |
| /*the only item that is managed by sig, so far, is "FRAME_PAR"*/ |
| s_result = TRUE; |
| break; |
| case PICODATA_ITEM_CMD: |
| if ((head.info1 == PICODATA_ITEMINFO1_CMD_PLAY) || (head.info1 |
| == PICODATA_ITEMINFO1_CMD_SAVE) || (head.info1 |
| == PICODATA_ITEMINFO1_CMD_UNSAVE)) { |
| if (head.info2 == PICODATA_ITEMINFO2_CMD_TO_SIG) { |
| return TRUE; |
| } |
| } |
| if ((head.info1 == PICODATA_ITEMINFO1_CMD_PITCH) || (head.info1 |
| == PICODATA_ITEMINFO1_CMD_VOLUME) || (head.info1 |
| == PICODATA_ITEMINFO1_CMD_SPEAKER)) { |
| return TRUE; |
| } |
| break; |
| default: |
| break; |
| } |
| return s_result; |
| } /*sig_deal_with*/ |
| |
| /** |
| * selects items to be managed as commands by this PU |
| * @param item : pointer to current item head |
| * @return TRUE : item should be managed as a command |
| * @return FALSE : item is not a PU command |
| * @remarks item pointed to by *item should be already valid |
| * @callgraph |
| * @callergraph |
| */ |
| static pico_status_t sig_is_command(const picoos_uint8 *item) |
| { |
| picodata_itemhead_t head; |
| head.type = item[0]; |
| head.info1 = item[1]; |
| head.info2 = item[2]; |
| head.len = item[3]; |
| switch (head.type) { |
| case PICODATA_ITEM_CMD: |
| if ((head.info1 == PICODATA_ITEMINFO1_CMD_PLAY) || (head.info1 |
| == PICODATA_ITEMINFO1_CMD_SAVE) || (head.info1 |
| == PICODATA_ITEMINFO1_CMD_UNSAVE)) { |
| if (head.info2 == PICODATA_ITEMINFO2_CMD_TO_SIG) { |
| return TRUE; |
| } |
| } |
| if ((head.info1 == PICODATA_ITEMINFO1_CMD_PITCH) || (head.info1 |
| == PICODATA_ITEMINFO1_CMD_VOLUME) || (head.info1 |
| == PICODATA_ITEMINFO1_CMD_SPEAKER)) { |
| return TRUE; |
| } |
| break; |
| default: |
| break; |
| } |
| return FALSE; |
| } /*sig_is_command*/ |
| |
| /** |
| * performs a step of the sig processing |
| * @param this : pointer to current PU (Control Unit) |
| * @param mode : mode for the PU |
| * @param numBytesOutput : pointer to number of bytes produced (output) |
| * @param this : pointer to current PU (Control Unit) |
| * @return one of the "picodata_step_result_t" values |
| * @callgraph |
| * @callergraph |
| */ |
| static picodata_step_result_t sigStep(register picodata_ProcessingUnit this, |
| picoos_int16 mode, picoos_uint16 * numBytesOutput) |
| { |
| register sig_subobj_t * sig_subObj; |
| pico_status_t s_result; |
| picoos_bool b_res; |
| pico_status_t s_deal_with; |
| picoos_uint16 blen; |
| picoos_uint16 numinb, numoutb; |
| pico_status_t rv; |
| picoos_int16 *s_data; |
| picoos_int16 hop_p_half; |
| picoos_uint32 n_samp, n_i; |
| picoos_char s_temp_file_name[255]; |
| picoos_uint32 n_start, n_fram, n_bytes; |
| picoos_single f_value; |
| picoos_uint16 n_value; |
| picoos_uint32 n_pos; |
| /*wav file play volume control*/ |
| picoos_int16 *s_t1; |
| picoos_int32 sf_data, sf_mlt; |
| picoos_uint32 sf; |
| picoos_encoding_t enc; |
| picoos_uint32 numSamples; |
| |
| numinb = 0; |
| numoutb = 0; |
| rv = PICO_OK; |
| s_result = PICO_OK; |
| |
| if (NULL == this || NULL == this->subObj) { |
| return PICODATA_PU_ERROR; |
| } |
| sig_subObj = (sig_subobj_t *) this->subObj; |
| |
| /*Init number of output bytes*/ |
| *numBytesOutput = 0; |
| |
| mode = mode; /* avoid warning "var not used in this function" */ |
| |
| while (1) { /* exit via return */ |
| |
| PICODBG_DEBUG(("picosig.sigStep -- doing state %i",sig_subObj->procState)); |
| |
| switch (sig_subObj->procState) { |
| |
| case PICOSIG_COLLECT: |
| /* ************** item collector ***********************************/ |
| /*collecting items from the PU input buffer*/ |
| s_result = picodata_cbGetItem(this->cbIn, |
| &(sig_subObj->inBuf[sig_subObj->inWritePos]), |
| sig_subObj->inBufSize - sig_subObj->inWritePos, &blen); |
| |
| PICODBG_DEBUG(("picosig.sigStep -- got item, status: %d",rv)); |
| |
| if (s_result == PICO_EOF) { |
| /*no items available : remain in state 0 and return idle*/ |
| return PICODATA_PU_IDLE; |
| } |
| if ((PICO_OK == s_result) && (blen > 0)) { |
| /* we now have one item : CHECK IT */ |
| s_result = picodata_is_valid_item( |
| &(sig_subObj->inBuf[sig_subObj->inWritePos]), blen); |
| if (s_result != TRUE) { |
| PICODBG_DEBUG(("picosig.sigStep -- item is not valid: discard")); |
| /*Item not valid : remain in state PICOSIG_COLLECT*/ |
| return PICODATA_PU_BUSY; |
| } |
| /*item ok: it could be sent to schedule state*/ |
| sig_subObj->inWritePos += blen; |
| sig_subObj->needMoreInput = FALSE; |
| sig_subObj->procState = PICOSIG_SCHEDULE; |
| /* uncomment next to split into two steps */ |
| return PICODATA_PU_ATOMIC; |
| } |
| /*no EOF, no OK --> errors : remain in state PICOSIG_COLLECT and return error*/ |
| return PICODATA_PU_ERROR; |
| break; |
| |
| case PICOSIG_SCHEDULE: |
| /* *************** item processing ***********************************/ |
| numinb = PICODATA_ITEM_HEADSIZE |
| + sig_subObj->inBuf[sig_subObj->inReadPos + 3]; |
| |
| /*verify that current item has to be dealth with by this PU*/ |
| s_deal_with = sig_deal_with( |
| &(sig_subObj->inBuf[sig_subObj->inReadPos])); |
| |
| switch (s_deal_with) { |
| |
| case TRUE: |
| /* we have to manage this item */ |
| if (FALSE == sig_is_command( |
| &(sig_subObj->inBuf[sig_subObj->inReadPos]))) |
| { |
| /*no commands, item to deal with : switch to process state*/ |
| sig_subObj->procState = PICOSIG_PROCESS; |
| sig_subObj->retState = PICOSIG_COLLECT; |
| return PICODATA_PU_BUSY; /*data still to process or to feed*/ |
| |
| } else { |
| |
| /*we need to manage this item as a SIG command-item*/ |
| |
| switch (sig_subObj->inBuf[sig_subObj->inReadPos + 1]) { |
| |
| case PICODATA_ITEMINFO1_CMD_PLAY: |
| /*CMD recognized : consume the command */ |
| sig_subObj->inReadPos += numinb; |
| if (sig_subObj->inReadPos |
| >= sig_subObj->inWritePos) { |
| sig_subObj->inReadPos = 0; |
| sig_subObj->inWritePos = 0; |
| } |
| /*default next state setting*/ |
| sig_subObj->procState = |
| sig_subObj->retState = PICOSIG_COLLECT; |
| |
| /*--------- wav file play management --------------*/ |
| if (sig_subObj->sInSDFile != NULL) { |
| /*input wav file is already open : return*/ |
| return PICODATA_PU_BUSY; |
| } |
| /*get temp file name*/ |
| picoos_strlcpy( |
| (picoos_char*) s_temp_file_name, |
| (picoos_char*) &(sig_subObj->inBuf[sig_subObj->inReadPos |
| + 4]), |
| sig_subObj->inBuf[sig_subObj->inReadPos |
| + 3] + 1); |
| /*avoid input/output file name clashes*/ |
| if (sig_subObj->sOutSDFile != NULL) { |
| if (picoos_strncmp( |
| (picoos_char*) s_temp_file_name, |
| (picoos_char*) sig_subObj->sOutSDFileName, |
| picoos_strlen( |
| (picoos_char*) s_temp_file_name)) |
| == 0) { |
| PICODBG_WARN(("input and output files has the same name!\n")); |
| return PICODATA_PU_BUSY; |
| } |
| } |
| /*actual sampled data file open*/ |
| b_res = picoos_sdfOpenIn(this->common, |
| &(sig_subObj->sInSDFile), |
| s_temp_file_name, &sf, |
| &enc, &numSamples); |
| if (b_res != TRUE) { |
| PICODBG_DEBUG(("Error on opening file %s\n", s_temp_file_name)); |
| sig_subObj->sInSDFile = NULL; |
| sig_subObj->sInSDFileName[0] = '\0'; |
| return PICODATA_PU_BUSY; |
| } |
| /*input file handle is now valid : store filename*/ |
| picoos_strlcpy( |
| (picoos_char*) sig_subObj->sInSDFileName, |
| (picoos_char*) s_temp_file_name, |
| sig_subObj->inBuf[sig_subObj->inReadPos |
| + 3] + 1); |
| sig_subObj->sInSDFilePos = 0; |
| /*switch to state PLAY and return*/ |
| sig_subObj->procState = |
| sig_subObj->retState = PICOSIG_PLAY; |
| return PICODATA_PU_BUSY; |
| break; |
| |
| case PICODATA_ITEMINFO1_CMD_SAVE: |
| /*CMD recognized : consume the command */ |
| sig_subObj->inReadPos += numinb; |
| if (sig_subObj->inReadPos |
| >= sig_subObj->inWritePos) { |
| sig_subObj->inReadPos = 0; |
| sig_subObj->inWritePos = 0; |
| } |
| /*prepare return state*/ |
| sig_subObj->procState = PICOSIG_COLLECT; |
| sig_subObj->retState = PICOSIG_COLLECT; |
| /*check about output file*/ |
| if ((sig_subObj->sOutSDFile != NULL) |
| || (sig_subObj->outSwitch == 1)) { |
| /*output sig file is already active : return*/ |
| return PICODATA_PU_BUSY; |
| } |
| /*get temp file name*/ |
| picoos_strlcpy( |
| (picoos_char*) s_temp_file_name, |
| (picoos_char*) &(sig_subObj->inBuf[sig_subObj->inReadPos |
| + 4]), |
| sig_subObj->inBuf[sig_subObj->inReadPos |
| + 3] + 1); |
| /*check extension*/ |
| if (picoos_has_extension(s_temp_file_name, |
| PICODATA_PUTYPE_WAV_OUTPUT_EXTENSION) |
| == FALSE){ |
| /*extension unsupported : return*/ |
| return PICODATA_PU_BUSY; |
| } |
| /*avoid input/output file name clashes*/ |
| if (sig_subObj->sInSDFile != NULL) { |
| if (picoos_strncmp( |
| (picoos_char*) sig_subObj->sInSDFileName, |
| (picoos_char*) s_temp_file_name, |
| picoos_strlen( |
| (picoos_char*) sig_subObj->sInSDFileName)) |
| == 0) { |
| /*input and output files has the same name : do not allow opening for writing*/ |
| PICODBG_WARN(("input and output files has the same name!\n")); |
| return PICODATA_PU_BUSY; |
| } |
| } |
| /*try to open*/ |
| picoos_sdfOpenOut(this->common, |
| &(sig_subObj->sOutSDFile), |
| s_temp_file_name, |
| SAMPLE_FREQ_16KHZ, PICOOS_ENC_LIN); |
| if (sig_subObj->sOutSDFile == NULL) { |
| PICODBG_DEBUG(("Error on opening file %s\n", sig_subObj->sOutSDFileName)); |
| sig_subObj->outSwitch = 0; |
| sig_subObj->sOutSDFileName[0] = '\0'; |
| } else { |
| /*open OK*/ |
| sig_subObj->outSwitch = 1; |
| /*store output filename*/ |
| picoos_strlcpy( |
| (picoos_char*) sig_subObj->sOutSDFileName, |
| (picoos_char*) s_temp_file_name, |
| sig_subObj->inBuf[sig_subObj->inReadPos + 3] + 1); |
| } |
| return PICODATA_PU_BUSY; |
| break; |
| |
| case PICODATA_ITEMINFO1_CMD_UNSAVE: |
| /*CMD recognized : consume the command */ |
| sig_subObj->inReadPos += numinb; |
| if (sig_subObj->inReadPos |
| >= sig_subObj->inWritePos) { |
| sig_subObj->inReadPos = 0; |
| sig_subObj->inWritePos = 0; |
| } |
| /*prepare return state*/ |
| sig_subObj->procState = PICOSIG_COLLECT; |
| sig_subObj->retState = PICOSIG_COLLECT; |
| /*close the output file if any*/ |
| if ((sig_subObj->sOutSDFile == NULL) |
| || (sig_subObj->outSwitch == 0)) { |
| /*output sig file is not active : return*/ |
| PICODBG_DEBUG(("Error on requesting a binary samples file output closing : no file output handle exist\n")); |
| return PICODATA_PU_BUSY; |
| } |
| picoos_sdfCloseOut(this->common, |
| &(sig_subObj->sOutSDFile)); |
| sig_subObj->outSwitch = 0; |
| sig_subObj->sOutSDFile = NULL; |
| sig_subObj->sOutSDFileName[0] = '\0'; |
| return PICODATA_PU_BUSY; |
| break; |
| |
| case PICODATA_ITEMINFO1_CMD_PITCH: |
| case PICODATA_ITEMINFO1_CMD_VOLUME: |
| case PICODATA_ITEMINFO1_CMD_SPEAKER: |
| n_pos = 4; |
| picoos_read_mem_pi_uint16( |
| &(sig_subObj->inBuf[sig_subObj->inReadPos]), |
| &n_pos, &n_value); |
| b_res = FALSE; |
| switch (sig_subObj->inBuf[sig_subObj->inReadPos + 2]) { |
| case 'a' : |
| /*absloute modifier*/ |
| f_value = (picoos_single) n_value |
| / (picoos_single) 100.0f; |
| b_res = TRUE; |
| break; |
| case 'r' : |
| /*relative modifier*/ |
| f_value = (picoos_single) n_value |
| / (picoos_single) 1000.0f; |
| b_res = TRUE; |
| break; |
| default : |
| f_value = (picoos_single)0; /*avoid warnings*/ |
| break; |
| } |
| if (b_res) { |
| switch (sig_subObj->inBuf[sig_subObj->inReadPos + 1]) { |
| case PICODATA_ITEMINFO1_CMD_PITCH : |
| sig_subObj->pMod = f_value; |
| break; |
| case PICODATA_ITEMINFO1_CMD_VOLUME : |
| sig_subObj->vMod = f_value; |
| break; |
| case PICODATA_ITEMINFO1_CMD_SPEAKER : |
| sig_subObj->sMod = f_value; |
| sig_subObj->sig_inner.sMod_p |
| = sig_subObj->sMod; |
| /*call the function needed to initialize the speaker factor*/ |
| mel_2_lin_init( |
| &(sig_subObj->sig_inner)); |
| break; |
| default : |
| break; |
| } |
| } |
| |
| /*CMD recognized : consume the command */ |
| sig_subObj->inReadPos += numinb; |
| if (sig_subObj->inReadPos |
| >= sig_subObj->inWritePos) { |
| sig_subObj->inReadPos = 0; |
| sig_subObj->inWritePos = 0; |
| } |
| /*prepare proc state*/ |
| sig_subObj->procState = PICOSIG_COLLECT; |
| sig_subObj->retState = PICOSIG_COLLECT; |
| return PICODATA_PU_BUSY; |
| break; |
| default: |
| break; |
| }/*switch command type*/ |
| } /*end if is command*/ |
| break; |
| |
| case FALSE: |
| |
| /*we DO NOT have to deal with this item on this PU. |
| * Normally these are still alive boundary or flush items*/ |
| /*copy item from PU input to PU output buffer, |
| * i.e. make it ready to FEED*/ |
| s_result = picodata_copy_item( |
| &(sig_subObj->inBuf[sig_subObj->inReadPos]), |
| numinb, |
| &(sig_subObj->outBuf[sig_subObj->outWritePos]), |
| sig_subObj->outBufSize - sig_subObj->outWritePos, |
| &numoutb); |
| if (s_result != PICO_OK) { |
| /*item not prepared properly to be sent to next PU : |
| * do not change state and retry next time*/ |
| sig_subObj->procState = PICOSIG_SCHEDULE; |
| sig_subObj->retState = PICOSIG_COLLECT; |
| return PICODATA_PU_BUSY; /*data still to process or to feed*/ |
| } |
| |
| /*if end of sentence reset number of frames(only needed for debugging purposes)*/ |
| if ((sig_subObj->inBuf[sig_subObj->inReadPos] |
| == PICODATA_ITEM_BOUND) |
| && ((sig_subObj->inBuf[sig_subObj->inReadPos + 1] |
| == PICODATA_ITEMINFO1_BOUND_SEND) |
| || (sig_subObj->inBuf[sig_subObj->inReadPos |
| + 1] |
| == PICODATA_ITEMINFO1_BOUND_TERM))) { |
| PICODBG_INFO(("End of sentence - Processed frames : %d", |
| sig_subObj->nNumFrame)); |
| sig_subObj->nNumFrame = 0; |
| } |
| |
| /*item processed and put in oputput buffer : consume the item*/ |
| sig_subObj->inReadPos += numinb; |
| sig_subObj->outWritePos += numoutb; |
| if (sig_subObj->inReadPos >= sig_subObj->inWritePos) { |
| /* inBuf exhausted */ |
| sig_subObj->inReadPos = 0; |
| sig_subObj->inWritePos = 0; |
| sig_subObj->needMoreInput = FALSE; |
| } |
| sig_subObj->procState = PICOSIG_FEED; |
| sig_subObj->retState = PICOSIG_COLLECT; |
| return PICODATA_PU_BUSY; /*data still to process or to feed*/ |
| break; |
| |
| default: |
| break; |
| }/*end switch s_deal_with*/ |
| |
| break; /*end case sig_schedule*/ |
| |
| case PICOSIG_PROCESS: |
| /* *************** item processing ***********************************/ |
| numinb = PICODATA_ITEM_HEADSIZE |
| + sig_subObj->inBuf[sig_subObj->inReadPos + 3]; |
| |
| /*Process a full item*/ |
| s_result = sigProcess(this, sig_subObj->inReadPos, numinb, |
| sig_subObj->outWritePos, &numoutb); |
| |
| if (s_result == PICO_OK) { |
| sig_subObj->inReadPos += numinb; |
| if (sig_subObj->inReadPos >= sig_subObj->inWritePos) { |
| sig_subObj->inReadPos = 0; |
| sig_subObj->inWritePos = 0; |
| sig_subObj->needMoreInput = FALSE; |
| } |
| sig_subObj->outWritePos += numoutb; |
| sig_subObj->procState = PICOSIG_FEED; |
| sig_subObj->retState = PICOSIG_COLLECT; |
| PICODBG_DEBUG(("picosig.sigStep -- leaving PICO_PROC, inReadPos = %i, outWritePos = %i",sig_subObj->inReadPos, sig_subObj->outWritePos)); |
| return PICODATA_PU_BUSY; /*data to feed*/ |
| } |
| return PICODATA_PU_BUSY; /*data still to process : remain in PROCESS STATE*/ |
| break; |
| |
| case PICOSIG_PLAY: |
| |
| /*management of wav file play*/ |
| s_data = (picoos_int16 *) &(sig_subObj->outBuf[sig_subObj->outWritePos + 4]); |
| hop_p_half = sig_subObj->sig_inner.hop_p / 2; |
| /*read directly into PU output buffer*/ |
| n_samp = hop_p_half; |
| b_res = picoos_sdfGetSamples(sig_subObj->sInSDFile, |
| sig_subObj->sInSDFilePos, &n_samp, s_data); |
| sig_subObj->sInSDFilePos += n_samp; |
| |
| if ((FALSE == b_res) || (0 == n_samp)) { |
| /*file play is complete or file read error*/ |
| picoos_sdfCloseIn(this->common, &(sig_subObj->sInSDFile)); |
| sig_subObj->sInSDFile = NULL; |
| sig_subObj->sInSDFileName[0] = '\0'; |
| sig_subObj->procState = PICOSIG_COLLECT; |
| sig_subObj->retState = PICOSIG_COLLECT; |
| return PICODATA_PU_BUSY; /*check if data in input buffer*/ |
| } |
| /*-----------------------------------*/ |
| /*Volume control of wav file playback*/ |
| /* (code borrowed from sigProcess)*/ |
| /*Volume mod and clipping control */ |
| /* directly into PU output buffer*/ |
| /*-----------------------------------*/ |
| sf_mlt = (picoos_int32) ((sig_subObj->vMod) * 16.0f); |
| s_t1 = &(s_data[0]); |
| |
| for (n_i = 0; n_i < n_samp; n_i++) { |
| if (*s_t1 != 0) { |
| sf_data = (picoos_int32) (*s_t1) * sf_mlt; |
| sf_data >>= 4; |
| if (sf_data > PICOSIG_MAXAMP) { |
| sf_data = PICOSIG_MAXAMP; |
| } else if (sf_data < PICOSIG_MINAMP) { |
| sf_data = PICOSIG_MINAMP; |
| } |
| *s_t1 = (picoos_int16) (sf_data); |
| } |
| s_t1++; |
| } |
| /*Add header info*/ |
| sig_subObj->outBuf[sig_subObj->outWritePos] |
| = (picoos_uint8) PICODATA_ITEM_FRAME; |
| sig_subObj->outBuf[sig_subObj->outWritePos + 1] |
| = (picoos_uint8) n_samp; |
| sig_subObj->outBuf[sig_subObj->outWritePos + 2] |
| = (picoos_uint8) (sig_subObj->nNumFrame % (hop_p_half)); /*number of frame % 64*/ |
| sig_subObj->outBuf[sig_subObj->outWritePos + 3] |
| = (picoos_uint8) n_samp * 2; |
| /*Item content*/ |
| sig_subObj->outWritePos += (n_samp * sizeof(picoos_int16)) + 4; /*including header*/ |
| sig_subObj->procState = PICOSIG_FEED; |
| sig_subObj->retState = PICOSIG_PLAY; |
| break; |
| |
| case PICOSIG_FEED: |
| /* ************** item output/feeding ***********************************/ |
| switch (sig_subObj->outSwitch) { |
| case 0: |
| /*feeding items to PU output buffer*/ |
| s_result = picodata_cbPutItem(this->cbOut, |
| &(sig_subObj->outBuf[sig_subObj->outReadPos]), |
| sig_subObj->outWritePos - sig_subObj->outReadPos, |
| &numoutb); |
| break; |
| case 1: |
| /*feeding items to file*/ |
| if (sig_subObj->outBuf[sig_subObj->outReadPos] |
| == PICODATA_ITEM_FRAME) { |
| if ((sig_subObj->sOutSDFile) != NULL) { |
| n_start = (picoos_uint32) (sig_subObj->outReadPos) |
| + PICODATA_ITEM_HEADSIZE; |
| n_bytes = (picoos_uint32) sig_subObj->outBuf[(sig_subObj->outReadPos) |
| + PICODATA_ITEMIND_LEN]; |
| n_fram = (picoos_uint32) sig_subObj->outBuf[(sig_subObj->outReadPos) |
| + PICODATA_ITEMIND_INFO2]; |
| if (picoos_sdfPutSamples( |
| sig_subObj->sOutSDFile, |
| n_bytes / 2, |
| (picoos_int16*) &(sig_subObj->outBuf[n_start]))) { |
| PICODBG_DEBUG(("Nframe:%d - Nbytes %d\n", n_fram, n_bytes)); |
| numoutb = n_bytes + 4; |
| s_result = PICO_OK; |
| /* also feed item to next PU */ |
| s_result = picodata_cbPutItem( |
| this->cbOut, |
| &(sig_subObj->outBuf[sig_subObj->outReadPos]), |
| sig_subObj->outWritePos |
| - sig_subObj->outReadPos, |
| &numoutb); |
| } else { |
| /*write error : close file + cleanup handles*/ |
| if (sig_subObj->sOutSDFile != NULL) { |
| picoos_sdfCloseOut(this->common, &(sig_subObj->sOutSDFile)); |
| sig_subObj->sOutSDFile = NULL; |
| } |
| sig_subObj->sOutSDFileName[0] = '\0'; |
| sig_subObj->outSwitch = 0; |
| PICODBG_DEBUG(("Error in writing :%d bytes to output file %s\n", numoutb, &(sig_subObj->sOutSDFileName[0]))); |
| s_result = PICO_ERR_OTHER; |
| } |
| } |
| } else { |
| /*continue to feed following PU with items != FRAME */ |
| s_result = picodata_cbPutItem( |
| this->cbOut, |
| &(sig_subObj->outBuf[sig_subObj->outReadPos]), |
| sig_subObj->outWritePos - sig_subObj->outReadPos, |
| &numoutb); |
| } |
| break; |
| default: |
| s_result = PICO_ERR_OTHER; |
| break; |
| } |
| PICODBG_DEBUG(("picosig.sigStep -- put item, status: %d",s_result)); |
| |
| if (PICO_OK == s_result) { |
| |
| sig_subObj->outReadPos += numoutb; |
| *numBytesOutput = numoutb; |
| /*-------------------------*/ |
| /*reset the output pointers*/ |
| /*-------------------------*/ |
| if (sig_subObj->outReadPos >= sig_subObj->outWritePos) { |
| sig_subObj->outReadPos = 0; |
| sig_subObj->outWritePos = 0; |
| sig_subObj->procState = sig_subObj->retState; |
| } |
| return PICODATA_PU_BUSY; |
| |
| } else if (PICO_EXC_BUF_OVERFLOW == s_result) { |
| |
| PICODBG_DEBUG(("picosig.sigStep ** feeding, overflow, PICODATA_PU_OUT_FULL")); |
| return PICODATA_PU_OUT_FULL; |
| |
| } else if ((PICO_EXC_BUF_UNDERFLOW == s_result) |
| || (PICO_ERR_OTHER == s_result)) { |
| |
| PICODBG_DEBUG(("picosig.sigStep ** feeding problem, discarding item")); |
| sig_subObj->outReadPos = 0; |
| sig_subObj->outWritePos = 0; |
| sig_subObj->procState = sig_subObj->retState; |
| return PICODATA_PU_ERROR; |
| |
| } |
| break; |
| default: |
| /*NOT feeding items*/ |
| s_result = PICO_EXC_BUF_IGNORE; |
| break; |
| }/*end switch*/ |
| return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ |
| |
| }/*end while*/ |
| return PICODATA_PU_IDLE; |
| }/*sigStep*/ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| /* Picosig.c end */ |