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