diff options
Diffstat (limited to 'pico/lib/picosig.c')
-rw-r--r-- | pico/lib/picosig.c | 1280 |
1 files changed, 1280 insertions, 0 deletions
diff --git a/pico/lib/picosig.c b/pico/lib/picosig.c new file mode 100644 index 0000000..be44b3c --- /dev/null +++ b/pico/lib/picosig.c @@ -0,0 +1,1280 @@ +/* + * 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) +{ + 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 + ------------------------------------------------------------------*/ + 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)); + + /*----------------------------------------------------------------- + * Initialize modifiers + * ------------------------------------------------------------------*/ + /*pitch , volume , speaker modifiers*/ + sig_subObj->pMod = 1.0f; + sig_subObj->vMod = 1.0f; + sig_subObj->sMod = 1.0f; + + 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)) { + 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 */ |