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
38 extern "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 
57 static 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  //---------------------------------------------------------*/
65 typedef 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  */
sigInitialize(register picodata_ProcessingUnit this,picoos_int32 resetMode)117 static 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  */
sigTerminate(register picodata_ProcessingUnit this)196 static 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  */
sigSubObjDeallocate(register picodata_ProcessingUnit this,picoos_MemoryManager mm)217 static 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  */
picosig_newSigUnit(picoos_MemoryManager mm,picoos_Common common,picodata_CharBuffer cbIn,picodata_CharBuffer cbOut,picorsrc_Voice voice)257 picodata_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  */
getPhsFromPdf(register picodata_ProcessingUnit this,picoos_uint16 phsIndex,picoos_int32 * phsVect,picoos_int16 * numComponents)317 static 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  */
sigProcess(register picodata_ProcessingUnit this,picoos_uint16 inReadPos,picoos_uint16 numinb,picoos_uint16 outWritePos,picoos_uint16 * numoutb)374 static 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  */
sig_deal_with(const picoos_uint8 * item)643 static 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  */
sig_is_command(const picoos_uint8 * item)686 static 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  */
sigStep(register picodata_ProcessingUnit this,picoos_int16 mode,picoos_uint16 * numBytesOutput)724 static 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