summaryrefslogtreecommitdiffstats
path: root/pico/lib/picosig.c
diff options
context:
space:
mode:
Diffstat (limited to 'pico/lib/picosig.c')
-rw-r--r--pico/lib/picosig.c1280
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 */