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