blob: f224e65cae116b7134e00cfddda4ec48a974d434 [file] [log] [blame]
/*
* 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 */