• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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