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 picocep.c
18 *
19 * Phonetic to Acoustic Mapping 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 /**
30 * @addtogroup picocep
31 * <b> Pico Cepstral Smoothing </b>\n
32 *
33 itemtype, iteminfo1, iteminfo2, content -> TYPE(INFO1,INFO2)content
34 in the following
35
36 items input
37
38 processed:
39
40 - PHONE(PHONID,StatesPerPhone)[FramesPerState|f0Index|mgcIndex]{StatesPerPhone}
41
42 (StatesPerPhone is a constant (5) for the time being. The content size is therfore allways 34)
43
44 unprocessed:
45 - all other item types are forwarded through the PU without modification
46
47 items output
48
49 FRAME(PHONID,F0 [?])ceps{25}
50
51 each PHONE produces at least StatesPerPhone FRAME (if each state has FramesPerState == 1), but usually more.
52
53 minimal input size (before processing starts)
54
55 other limitations
56
57 */
58 #include "picodefs.h"
59 #include "picoos.h"
60 #include "picodbg.h"
61 #include "picodata.h"
62 #include "picokpdf.h"
63 #include "picodsp.h"
64 #include "picocep.h"
65
66 #ifdef __cplusplus
67 extern "C" {
68 #endif
69 #if 0
70 }
71 #endif
72
73 #define PICOCEP_MAXWINLEN 10000 /* maximum number of frames that can be smoothed, i.e. maximum sentence length */
74 #define PICOCEP_MSGSTR_SIZE 32
75 #define PICOCEP_IN_BUFF_SIZE PICODATA_BUFSIZE_DEFAULT
76
77 #define PICOCEP_OUT_DATA_FORMAT PICODATA_ITEMINFO1_FRAME_PAR_DATA_FORMAT_FIXED /* we output coefficients as fixed point values */
78
79 #define PICOCEP_STEPSTATE_COLLECT 0
80 #define PICOCEP_STEPSTATE_PROCESS_PARSE 1
81 #define PICOCEP_STEPSTATE_PROCESS_SMOOTH 2
82 #define PICOCEP_STEPSTATE_PROCESS_FRAME 3
83 #define PICOCEP_STEPSTATE_FEED 4
84
85 #define PICOCEP_LFZINVPOW 31 /* cannot be higher than 31 because 1<<invpow must fit in uint32 */
86 #define PICOCEP_MGCINVPOW 24
87 #define PICOCEP_LFZDOUBLEDEC 1
88 #define PICOCEP_MGCDOUBLEDEC 0
89
90 typedef enum picocep_WantMeanOrIvar
91 {
92 PICOCEP_WANTMEAN, PICOCEP_WANTIVAR
93 } picocep_WantMeanOrIvar_t;
94
95 typedef enum picocep_WantStaticOrDeltax
96 {
97 PICOCEP_WANTSTATIC, PICOCEP_WANTDELTA, PICOCEP_WANTDELTA2
98 } picocep_WantStaticOrDelta_t;
99
100 /*
101 * Fixedpoint arithmetic (might go into a separate module if general enough and needed by other modules)
102 */
103
104 #if defined(PICO_DEBUG) || defined(PICO_DEVEL_MODE)
105 int numlongmult = 0, numshortmult = 0;
106 #endif
107
108 #define POW1 (0x1)
109 #define POW2 (0x2)
110 #define POW3 (0x4)
111 #define POW4 (0x8)
112 #define POW5 (0x10)
113 #define POW6 (0x20)
114 #define POW7 (0x40)
115 #define POW8 (0x80)
116 #define POW9 (0x100)
117 #define POW10 (0x200)
118 #define POW11 (0x400)
119 #define POW12 (0x800)
120 #define POW13 (0x1000)
121 #define POW14 (0x2000)
122 #define POW15 (0x4000)
123 #define POW16 (0x8000)
124 #define POW17 (0x10000)
125 #define POW18 (0x20000)
126 #define POW19 (0x40000)
127 #define POW20 (0x80000)
128 #define POW21 (0x100000)
129 #define POW22 (0x200000)
130 #define POW23 (0x400000)
131 #define POW24 (0x800000)
132 #define POW25 (0x1000000)
133 #define POW26 (0x2000000)
134 #define POW27 (0x4000000)
135 #define POW28 (0x8000000)
136 #define POW29 (0x10000000)
137 #define POW30 (0x20000000)
138 #define POW31 (0x40000000)
139
140 /* item num restriction: maximum number of extended item heads in headx */
141 #define PICOCEP_MAXNR_HEADX 60
142 /* item num restriction: maximum size of all item contents together in cont */
143 #define PICOCEP_MAXSIZE_CBUF 7680 /* (128 * PICOCEP_MAXNR_HEADX) */
144
145 typedef struct
146 {
147 picodata_itemhead_t head;
148 picoos_uint16 cind;
149 picoos_uint16 frame; /* sync position */
150 } picoacph_headx_t;
151
152 /*----------------------------------------------------------
153 // Name : cep_subobj
154 // Function: subobject definition for the cep processing
155 // Shortcut: cep
156 //---------------------------------------------------------*/
157 typedef struct cep_subobj
158 {
159 /*----------------------PU voice management------------------------------*/
160 /* picorsrc_Voice voice; */
161 /*----------------------PU state management------------------------------*/
162 picoos_uint8 procState; /* where to take up work at next processing step */
163 picoos_bool needMoreInput; /* more data necessary to start processing */
164 /* picoos_uint8 force; *//* forced processing (needMoreData but buffers full */
165 picoos_uint8 sentenceEnd;
166 picoos_uint8 feedFollowState;
167 picoos_bool inIgnoreState;
168 /*----------------------PU input management------------------------------*/
169 picoos_uint8 inBuf[PICODATA_MAX_ITEMSIZE]; /* internal input buffer */
170 picoos_uint16 inBufSize; /* actually allocated size */
171 picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/
172 picoos_uint16 nextInPos;
173
174 picoacph_headx_t headx[PICOCEP_MAXNR_HEADX];
175 picoos_uint16 headxBottom; /* bottom */
176 picoos_uint16 headxWritePos; /* next free position; headx is empty if headxBottom == headxWritePos */
177
178 picoos_uint8 cbuf[PICOCEP_MAXSIZE_CBUF];
179 picoos_uint16 cbufBufSize; /* actually allocated size */
180 picoos_uint16 cbufWritePos; /* length, 0 if empty */
181
182 /*----------------------PU output management-----------------------------*/
183 picodata_itemhead_t framehead;
184 picoos_uint8 outBuf[PICODATA_MAX_ITEMSIZE]; /* internal output buffer (one item) */
185 picoos_uint16 outBufSize; /* allocated outBuf size */
186 picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/
187
188 picoos_uint32 nNumFrames;
189 /*---------------------- other working variables ---------------------------*/
190
191 picoos_int32 diag0[PICOCEP_MAXWINLEN], diag1[PICOCEP_MAXWINLEN],
192 diag2[PICOCEP_MAXWINLEN], WUm[PICOCEP_MAXWINLEN],
193 invdiag0[PICOCEP_MAXWINLEN];
194
195 /*---------------------- constants --------------------------------------*/
196 picoos_int32 xi[5], x1[2], x2[3], xm[3], xn[2];
197 picoos_int32 xsqi[5], xsq1[2], xsq2[3], xsqm[3], xsqn[2];
198
199 picoos_uint32 scmeanpowLFZ, scmeanpowMGC;
200 picoos_uint32 scmeanLFZ, scmeanMGC;
201
202 /*---------------------- indices --------------------------------------*/
203 /* index buffer to hold indices as input for smoothing */
204 picoos_uint16 indicesLFZ[PICOCEP_MAXWINLEN];
205 picoos_uint16 indicesMGC[PICOCEP_MAXWINLEN];
206 picoos_uint16 indexReadPos, indexWritePos;
207 picoos_uint16 activeEndPos; /* end position of indices to be considered */
208
209 /* this is used for input and output */
210 picoos_uint8 phoneId[PICOCEP_MAXWINLEN]; /* synchronised with indexReadPos */
211
212 /*---------------------- coefficients --------------------------------------*/
213 /* output coefficients buffer */
214 picoos_int16 * outF0;
215 picoos_uint16 outF0ReadPos, outF0WritePos;
216 picoos_int16 * outXCep;
217 picoos_uint32 outXCepReadPos, outXCepWritePos; /* uint32 needed for MAXWINLEN*ceporder > 2^16 */
218 picoos_uint8 * outVoiced;
219 picoos_uint16 outVoicedReadPos, outVoicedWritePos;
220
221 /*---------------------- LINGWARE related data -------------------*/
222 /* pdflfz knowledge base */
223 picokpdf_PdfMUL pdflfz, pdfmgc;
224
225 } cep_subobj_t;
226
227 /**
228 * picocep_highestBit
229 * @brief find the highest non-zero bit in input x
230 * @remarks this may be implemented by comparing x to powers of 2
231 * or instead of calling this function perform multiplication
232 * and consult overflow register if available on target
233 * @note implemented as a series of macros
234 */
235
236 #define picocep_highestBitNZ(x) (x>=POW17?(x>=POW25?(x>=POW29?(x>=POW31?31:(x>=POW30?30:29)):(x>=POW27?(x>=POW28?28:27):(x>=POW26?26:25))):(x>=POW21?(x>=POW23?(x>=POW24?24:23):(x>=POW22?22:21)):(x>=POW19?(x>=POW20?20:19):(x>=POW18?18:17)))):(x>=POW9?(x>=POW13?(x>=POW15?(x>=POW16?16:15):(x>=POW14?14:13)):(x>=POW11?(x>=POW12?12:11):(x>=POW10?10:9))):(x>=POW5?(x>=POW7?(x>=POW8?8:7):(x>=POW6?6:5)):(x>=POW3?(x>=POW4?4:3):(x>=POW2?2:1)))))
237 #define picocep_highestBitU(x) (x==0?0:picocep_highestBitNZ(x))
238 #define picocep_highestBitS(x,zz) (x==0?0:(x<0?((zz)=(-x),picocep_highestBitNZ(zz)):picocep_highestBitNZ(x)))
239
240 /* ------------------------------------------------------------------------------
241 Internal function definitions
242 ---------------------------------------------------------------------------------*/
243
244 static void initSmoothing(cep_subobj_t * cep);
245
246 static picoos_int32 getFromPdf(picokpdf_PdfMUL pdf, picoos_uint32 vecstart,
247 picoos_uint8 cepnum, picocep_WantMeanOrIvar_t wantMeanOrIvar,
248 picocep_WantStaticOrDelta_t wantStaticOrDeltax);
249
250 static void invMatrix(cep_subobj_t * cep, picoos_uint16 N,
251 picoos_int16 *smoothcep, picoos_uint8 cepnum,
252 picokpdf_PdfMUL pdf, picoos_uint8 invpow, picoos_uint8 invDoubleDec);
253
254 static picoos_uint8 makeWUWandWUm(cep_subobj_t * cep, picokpdf_PdfMUL pdf,
255 picoos_uint16 *indices, picoos_uint16 b, picoos_uint16 N,
256 picoos_uint8 cepnum);
257
258 static void getDirect(picokpdf_PdfMUL pdf, picoos_uint16 *indices,
259 picoos_uint16 activeEndPos,
260 picoos_uint8 cepnum, picoos_int16 *smoothcep);
261
262 static void getVoiced(picokpdf_PdfMUL pdf, picoos_uint16 *indices,
263 picoos_uint16 activeEndPos,
264 picoos_uint8 *smoothcep);
265
266 static picoos_uint16 get_pi_uint16(picoos_uint8 * buf, picoos_uint16 *pos);
267
268 static void treat_phone(cep_subobj_t * cep, picodata_itemhead_t * ihead);
269
270 static picoos_uint8 forwardingItem(picodata_itemhead_t * ihead);
271
272 static picodata_step_result_t cepStep(register picodata_ProcessingUnit this,
273 picoos_int16 mode, picoos_uint16 * numBytesOutput);
274
275 /* --------------------------------------------
276 * generic PU management
277 * --------------------------------------------
278 */
279
280 /**
281 * initialization of a cep PU (processing unit)
282 * @param this : handle to a cep PU struct
283 * @return PICO_OK : init succeded
284 * @return PICO_ERR_OTHER : init failed
285 * @callgraph
286 * @callergraph
287 */
cepInitialize(register picodata_ProcessingUnit this,picoos_int32 resetMode)288 static pico_status_t cepInitialize(register picodata_ProcessingUnit this, picoos_int32 resetMode)
289 {
290 /*pico_status_t nRes;*/
291 cep_subobj_t * cep;
292 if (NULL == this || NULL == this->subObj) {
293 return PICO_ERR_OTHER;
294 }
295 cep = (cep_subobj_t *) this->subObj;
296 /* inBuf */
297 cep->inBufSize = PICODATA_BUFSIZE_CEP;
298 cep->inReadPos = 0;
299 cep->inWritePos = 0;
300 /* headx and cbuf */
301 cep->headxBottom = cep->headxWritePos = 0;
302 cep->cbufBufSize = PICOCEP_MAXSIZE_CBUF;
303 cep->cbufWritePos = 0;
304 /* outBuf */
305 cep->outBufSize = PICODATA_MAX_ITEMSIZE;
306 cep->outReadPos = 0;
307 cep->outWritePos = 0;
308 /* indices* */
309 cep->indexReadPos = 0;
310 cep->indexWritePos = 0;
311 /* outCep, outF0, outVoiced */
312 cep->outXCepReadPos = 0;
313 cep->outXCepWritePos = 0;
314 cep->outVoicedReadPos = 0;
315 cep->outVoicedWritePos = 0;
316 cep->outF0ReadPos = 0;
317 cep->outF0WritePos = 0;
318
319 cep->needMoreInput = 0;
320 cep->inIgnoreState = 0;
321 cep->sentenceEnd = FALSE;
322 cep->procState = PICOCEP_STEPSTATE_COLLECT;
323
324 cep->nNumFrames = 0;
325
326 /*-----------------------------------------------------------------
327 * MANAGE Item I/O control management
328 ------------------------------------------------------------------*/
329 cep->activeEndPos = PICOCEP_MAXWINLEN;
330
331 if (resetMode == PICO_RESET_FULL) {
332 /* kb pdflfz */
333 cep->pdflfz = picokpdf_getPdfMUL(
334 this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]);
335
336 /* kb pdfmgc */
337 cep->pdfmgc = picokpdf_getPdfMUL(
338 this->voice->kbArray[PICOKNOW_KBID_PDF_MGC]);
339
340 /* kb tab phones */
341 /* cep->phones =
342 picoktab_getPhones(this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); */
343
344 /*---------------------- other working variables ---------------------------*/
345 /* define the (constant) FRAME_PAR item header */
346 cep->framehead.type = PICODATA_ITEM_FRAME_PAR;
347 cep->framehead.info1 = PICOCEP_OUT_DATA_FORMAT;
348 cep->framehead.info2 = cep->pdfmgc->ceporder;
349 cep->framehead.len = sizeof(picoos_uint16) + (cep->framehead.info2 + 4)
350 * sizeof(picoos_uint16);
351 cep->scmeanpowLFZ = cep->pdflfz->bigpow - cep->pdflfz->meanpow;
352 cep->scmeanpowMGC = cep->pdfmgc->bigpow - cep->pdfmgc->meanpow;
353
354 cep->scmeanLFZ = (1 << (picoos_uint32) cep->scmeanpowLFZ);
355
356 cep->scmeanMGC = (1 << (picoos_uint32) cep->scmeanpowMGC);
357
358 }
359 /* constants used in makeWUWandWUm */
360 initSmoothing(cep);
361
362
363 return PICO_OK;
364 }/*cepInitialize*/
365
366 /**
367 * termination of a cep PU (processing unit)
368 * @param this : handle to a cep PU struct
369 * @return PICO_OK : termination succeded
370 * @return PICO_ERR_OTHER : termination failed
371 * @callgraph
372 * @callergraph
373 */
cepTerminate(register picodata_ProcessingUnit this)374 static pico_status_t cepTerminate(register picodata_ProcessingUnit this)
375 {
376 return PICO_OK;
377 }
378
379 /**
380 * deallocation of a cep PU internal sub object
381 * @param this : handle to a cep PU struct
382 * @param mm : handle of the engine memory manager
383 * @return PICO_OK : deallocation succeded
384 * @return PICO_ERR_OTHER : deallocation failed
385 * @callgraph
386 * @callergraph
387 */
cepSubObjDeallocate(register picodata_ProcessingUnit this,picoos_MemoryManager mm)388 static pico_status_t cepSubObjDeallocate(register picodata_ProcessingUnit this,
389 picoos_MemoryManager mm)
390 {
391
392 mm = mm; /* avoid warning "var not used in this function"*/
393 #if defined(PICO_DEVEL_MODE)
394 printf("number of long mult is %d, number of short mult is %i\n",numlongmult,numshortmult);
395 #else
396 PICODBG_INFO_MSG(("number of long mult is %d, number of short mult is %i\n",numlongmult,numshortmult));
397 #endif
398 if (NULL != this) {
399 cep_subobj_t * cep = (cep_subobj_t *) this->subObj;
400 picoos_deallocate(this->common->mm, (void *) &cep->outXCep);
401 picoos_deallocate(this->common->mm, (void *) &cep->outVoiced);
402 picoos_deallocate(this->common->mm, (void *) &cep->outF0);
403 picoos_deallocate(this->common->mm, (void *) &this->subObj);
404 }
405 return PICO_OK;
406 }
407
408 /**
409 * creates a new cep PU (processing unit)
410 * @param mm : engine memory manager object pointer
411 * @param common : engine common object pointer
412 * @param cbIn : PU input buffer
413 * @param cbOut : PU output buffer
414 * @param voice : the voice descriptor object
415 * @return a valid PU handle if creation succeded
416 * @return NULL : creation failed
417 * @callgraph
418 * @callergraph
419 */
picocep_newCepUnit(picoos_MemoryManager mm,picoos_Common common,picodata_CharBuffer cbIn,picodata_CharBuffer cbOut,picorsrc_Voice voice)420 picodata_ProcessingUnit picocep_newCepUnit(picoos_MemoryManager mm,
421 picoos_Common common, picodata_CharBuffer cbIn,
422 picodata_CharBuffer cbOut, picorsrc_Voice voice)
423 {
424 picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn,
425 cbOut, voice);
426 cep_subobj_t * cep;
427
428 if (this == NULL) {
429 return NULL;
430 }
431 this->initialize = cepInitialize;
432
433 PICODBG_DEBUG(("set this->step to cepStep"));
434
435 this->step = cepStep;
436 this->terminate = cepTerminate;
437 this->subDeallocate = cepSubObjDeallocate;
438 this->subObj = picoos_allocate(mm, sizeof(cep_subobj_t));
439
440 cep = (cep_subobj_t *) this->subObj;
441
442 if (this->subObj == NULL) {
443 picoos_deallocate(mm, (void*) &this);
444 return NULL;
445 };
446
447 /* allocate output coeeficient buffers */
448 cep->outF0 = (picoos_int16 *) picoos_allocate(this->common->mm,
449 PICOCEP_MAXWINLEN * PICOKPDF_MAX_MUL_LFZ_CEPORDER
450 * sizeof(picoos_int16));
451 cep->outXCep = (picoos_int16 *) picoos_allocate(this->common->mm,
452 PICOCEP_MAXWINLEN * PICOKPDF_MAX_MUL_MGC_CEPORDER
453 * sizeof(picoos_int16));
454 cep->outVoiced = (picoos_uint8 *) picoos_allocate(this->common->mm,
455 PICOCEP_MAXWINLEN * sizeof(picoos_uint8));
456
457 if ((NULL == cep->outF0) || (NULL == cep->outXCep) || (NULL
458 == cep->outVoiced)) {
459 picoos_deallocate(this->common->mm, (void *) &(cep->outF0));
460 picoos_deallocate(this->common->mm, (void *) &(cep->outXCep));
461 picoos_deallocate(this->common->mm, (void *) &(cep->outVoiced));
462 picoos_deallocate(mm, (void*) &cep);
463 picoos_deallocate(mm, (void*) &this);
464 return NULL;
465 }
466 cepInitialize(this, PICO_RESET_FULL);
467
468 return this;
469 }/*picocep_newCepUnit*/
470
471 /* --------------------------------------------
472 * processing and internal functions
473 * --------------------------------------------
474 */
475
476 /**
477 * multiply by 1<<pow and check overflow
478 * @param a : input value
479 * @param pow : shift value
480 * @return multiplied value
481 * @callgraph
482 * @callergraph
483 */
picocep_fixptmultpow(picoos_int32 a,picoos_uint8 pow)484 static picoos_int32 picocep_fixptmultpow(picoos_int32 a, picoos_uint8 pow)
485 {
486 picoos_int32 b;
487 picoos_int32 zzz;
488
489 if (picocep_highestBitS(a,zzz) + pow < 32) {
490 b = a << pow;
491 } else {
492 /* clip to maximum positive or negative value */
493 b = 1 << 31; /* maximum negative value */
494 if (a > 0) {
495 b -= 1; /* maximum positive value */
496 }PICODBG_WARN(("picocep_fixptmultpow warning: overflow in fixed point multiplication %i*1<<%i. Clipping to %i\n", a, pow, b));
497 }
498 return b;
499 }
500
501 /**
502 * divide by 1<<pow with rounding
503 * @param a : input value
504 * @param pow : shift value
505 * @return divided value
506 * @callgraph
507 * @callergraph
508 */
picocep_fixptdivpow(picoos_int32 a,picoos_uint8 pow)509 static picoos_int32 picocep_fixptdivpow(picoos_int32 a, picoos_uint8 pow)
510 {
511 picoos_int32 big;
512
513 if (a == 0) {
514 return a;
515 }
516 big = 1 << (pow - 1);
517 if (a > 0) {
518 a = (a + big) >> pow;
519 } else {
520 a = -1 * ((-1 * a + big) >> pow);
521 }
522
523 return a;
524 }
525
526 /**
527 * fixed point multiplication of x and y for large values of x or y or both
528 * @param x,y : operands 1 & 2, in fixed point S:M:N representation
529 * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits
530 * @param invDoubleDec : boolean indicating that x has double decimal size.
531 * do extra division by 1<<bigpow so that result has again single decimal size
532 * @return z(int) : result, in fixed point S:M:N representation
533 * @callgraph
534 * @callergraph
535 */
picocep_fixptmultdouble(picoos_int32 x,picoos_int32 y,picoos_uint8 bigpow,picoos_uint8 invDoubleDec)536 static picoos_int32 picocep_fixptmultdouble(picoos_int32 x, picoos_int32 y,
537 picoos_uint8 bigpow, picoos_uint8 invDoubleDec)
538 {
539 picoos_int32 a, b, c, d, e, z;
540 picoos_int32 big;
541
542 big = 1 << bigpow;
543
544 /* a = floor(x/big); */
545 if (x >= 0) {
546 a = x >> bigpow;
547 b = x - (a << bigpow);
548 } else {
549 a = -1 * ((x * -1) >> bigpow); /* most significant 2 bytes of x */
550 b = x - (a << bigpow);
551 }
552
553 /* least significant 2 bytes of x i.e. x modulo big */
554 /* c = floor(y/big); */
555 if (y >= 0) {
556 c = y >> bigpow;
557 d = y - (c << bigpow);
558 } else {
559 c = -1 * ((y * -1) >> bigpow);
560 d = y - (c << bigpow);
561 }
562
563 if (invDoubleDec == 1) {
564 e = a * d + b * c + picocep_fixptdivpow(b * d, bigpow);
565 z = a * c + picocep_fixptdivpow(e, bigpow);
566 } else {
567 z = ((a * c) << bigpow) + (a * d + b * c) + picocep_fixptdivpow(b * d,
568 bigpow); /* 4 mult and 3 add instead of 1 mult. */
569 }
570
571 return z;
572 }
573
574 /**
575 * fixed point multiplication of x and y
576 * @param x,y : operands 1 & 2, in fixed point S:M:N representation
577 * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits
578 * @param invDoubleDec : boolean indicating that x has double decimal size.
579 * do extra division by 1<<bigpow so that result has again single decimal size
580 * @return z(int) : result, in fixed point S:M:N representation
581 * Notes
582 * - input and output values are 32 bit signed integers
583 * meant to represent a S.M.N encoding of a floating point value where
584 * - S : 1 sign bit
585 * - M : number of binary integer digits (M=32-1-N)
586 * - N : number of binary decimal digits (N=log2(big))
587 * the routine supports 2 methods
588 * -# standard multiplication of x and y
589 * -# long multiplication of x and y
590 * under PICO_DEBUG the number of double and single precision multiplications is monitored for accuracy/performance tuning
591 * Calls
592 * - picocep_highestBit
593 * - picocep_fixptmultdouble
594 * @callgraph
595 * @callergraph
596 */
picocep_fixptmult(picoos_int32 x,picoos_int32 y,picoos_uint8 bigpow,picoos_uint8 invDoubleDec)597 static picoos_int32 picocep_fixptmult(picoos_int32 x, picoos_int32 y,
598 picoos_uint8 bigpow, picoos_uint8 invDoubleDec)
599 {
600 picoos_int32 z;
601 picoos_uint8 multsz, pow;
602 picoos_int32 zz1, zz2;
603
604 /* in C, the evaluation order of f() + g() is not defined, so
605 * if both have a side effect on e.g. zz, the outcome of zz is not defined.
606 * For that reason, picocep_highestBitS(x,zz) + picocep_highestBitS(y,zz)
607 * would generate a warning "operation on zz may be undefined" which we
608 * avoid by using two different variables zz1 and zz2 */
609 multsz = picocep_highestBitS(x,zz1) + picocep_highestBitS(y,zz2);
610 pow = bigpow;
611 if (invDoubleDec == 1) {
612 pow += bigpow;
613 }
614
615 if (multsz <= 30) { /* x*y < 1<<30 is safe including rounding in picocep_fixptdivpow, x*y < 1<<31 is safe but not with rounding */
616 /* alternatively perform multiplication and consult overflow register */
617 z = picocep_fixptdivpow(x * y, pow);
618 #if defined(PICO_DEBUG)
619 numshortmult++; /* keep track of number of short multiplications */
620 #endif
621 } else {
622 #if defined(PICO_DEBUG)
623 if (multsz> 31 + pow) {
624 PICODBG_WARN(("picocep_fixptmult warning: overflow in fixed point multiplication %i*%i, multsz = %i, pow = %i, decrease bigpow\n", x, y, multsz, pow));
625 }
626 #endif
627 z = picocep_fixptmultdouble(x, y, bigpow, invDoubleDec); /* perform long multiplication for large x and y */
628 #if defined(PICO_DEBUG)
629 numlongmult++; /* keep track of number of long multiplications */
630 #endif
631 }
632 return z;
633 }/* picocep_fixptmult */
634
635 /**
636 * fixed point ^division of a vs b
637 * @param a,b : operands 1 & 2, in fixed point S:M:N representation
638 * @param bigpow (int) : normalization factor=2**N, where N=number of binary decimal digits
639 * @return z(int) : result, in fixed point S:M:N representation
640 * Notes
641 * - input and output values are 32 bit signed integers
642 * meant to represent a S.M.N encoding of a floating point value where
643 * - S : 1 sign bit
644 * - M : number of binary integer digits (M=32-1-N)
645 * - N : number of binary decimal digits (N=log2(big))
646 * - standard implementation of division by iteratively calculating
647 * the remainder and setting corresponding bit
648 * calculate integer part by integer division (DIV),
649 * then add X bits of precision in decimal part
650 * @callgraph
651 * @callergraph
652 */
picocep_fixptdiv(picoos_int32 a,picoos_int32 b,picoos_uint8 bigpow)653 static picoos_int32 picocep_fixptdiv(picoos_int32 a, picoos_int32 b,
654 picoos_uint8 bigpow)
655 {
656 picoos_int32 r, c, f, h, stop;
657 r = (a < 0) ? -a : a; /* take absolute value; b is already guaranteed to be positive in smoothing operation */
658 if (r == 0) {
659 return 0;
660 }
661 c = 0;
662 stop = 0;
663
664 /* can speed up slightly by setting stop = 2 => slightly less precision */
665 h = r / b; /* in first loop h can be multiple bits, after first loop h can only be 0 or 1 */
666 /* faster implementation on target by using comparison instead of DIV? */
667 /* For our LDL even in first loop h <= 1, but not in backward step */
668 c = c + (h << bigpow); /* after first loop simply set bit */
669 r = r - h * b; /* corresponds to modulo operation */
670 bigpow--;
671 r <<= 1;
672
673 while ((bigpow > stop) && (r != 0)) { /* calculate bigpow bits after fixed point */
674 /* can speed up slightly by setting stop = 2 => slightly less precision */
675 if (r >= b) {
676 c += (1 << bigpow); /* after first loop simply set bit */
677 r -= b; /* corresponds to modulo operation */
678 }
679 bigpow--;
680 r <<= 1;
681 }
682
683 if (r != 0) {
684 f = r + (b >> 1);
685 if (f >= b) {
686 if (f >= b + b) {
687 c += 2;
688 } else {
689 c++;
690 }
691 }
692 }
693 /* final step: do rounding (experimentally improves accuracy for our problem) */
694 c = (a >= 0) ? c : -c; /* b is guaranteed to be positive because corresponds to diag0 */
695 return c;
696 }/* picocep_fixptdiv */
697
698 /**
699 * perform inversion of diagonal element of WUW matrix
700 * @param d : diagonal element to be inverted
701 * @param rowscpow (int) : fixed point base for each dimension of the vectors stored in the database
702 * @param bigpow (int) : fixed point base used during cepstral smoothing
703 * @param invpow : fixed point base of inverted pivot elements
704 * @return inverted pivot element
705 * @note
706 * - d is guaranteed positive
707 * @callgraph
708 * @callergraph
709 */
picocep_fixptInvDiagEle(picoos_uint32 d,picoos_uint8 * rowscpow,picoos_uint8 bigpow,picoos_uint8 invpow)710 static picoos_int32 picocep_fixptInvDiagEle(picoos_uint32 d,
711 picoos_uint8* rowscpow, picoos_uint8 bigpow, picoos_uint8 invpow)
712 {
713 picoos_uint32 r, b, c, h, f, stop;
714 picoos_uint8 dlen;
715 /* picoos_int32 zz; */
716 c = 0;
717 stop = 0;
718
719 dlen = picocep_highestBitU(d);
720 if (invpow + bigpow > 30 + dlen) { /* c must be < 2^32, hence d which is >= 2^(dlen-1) must be > 2^(invpow+bigpow-32), or invpow+bigpow must be <= dlen+30*/
721 *rowscpow = invpow + bigpow - 30 - dlen;PICODBG_DEBUG(("input to picocep_fixptInvDiagEle is %i <= 1<<%i = 1<<invpow+bigpow-32. Choose lower invpow. For now scaling row by 1<<%i\n", d, invpow+bigpow-32, *rowscpow));
722 } else {
723 *rowscpow = 0;
724 }
725 r = 1 << invpow;
726 b = d << (*rowscpow);
727
728 /* first */
729 h = r / b;
730 if (h > 0) {
731 c += (h << bigpow);
732 r -= h * b;
733 }
734 bigpow--;
735 r <<= 1;
736
737 /* loop */
738 while ((bigpow > stop) && (r != 0)) {
739 if (r >= b) {
740 c += (1 << bigpow);
741 r -= b;
742 }
743 bigpow--;
744 r <<= 1;
745 }
746
747 if (r != 0) {
748 f = r + (b >> 1);
749 if (f >= b) {
750 if (f >= b + b) {
751 c += 2;
752 } else {
753 c++;
754 }
755 }
756 }
757
758 return c;
759 }/* picocep_fixptInvDiagEle */
760
761 /**
762 * perform division of two operands a and b by multiplication by inverse of b
763 * @param a (int32) : operand 1 in fixed point S:M:N representation
764 * @param invb(uint32) : inverse of operand b, in fixed point P:Q representation (sign is positive)
765 * @param bigpow(uint8) : N = bigpow when invDoubleDec==0, else N = 2*bigpow
766 * @param invpow(uint8) : Q = invpow = number of binary decimal digits for invb
767 * @param invDoubleDec : boolean to indicate that a and the return value c have 2*N binary decimal digits instead of N
768 * @return c(int32) : result in fixed point S:v:w where w = 2*N when invDoubleDec == 1
769 * @note Calls
770 * - picocep_fixptmult
771 * @callgraph
772 * @callergraph
773 */
picocep_fixptinv(picoos_int32 a,picoos_uint32 invb,picoos_uint8 bigpow,picoos_uint8 invpow,picoos_uint8 invDoubleDec)774 static picoos_int32 picocep_fixptinv(picoos_int32 a, picoos_uint32 invb,
775 picoos_uint8 bigpow, picoos_uint8 invpow, picoos_uint8 invDoubleDec)
776 {
777 picoos_int32 c;
778 picoos_int8 normpow;
779
780 c = picocep_fixptmult(a, invb, bigpow, invDoubleDec);
781
782 /* if invDoubleDec==0, picocep_fixptmult assumes a and invb are in base 1<<bigpow and returns c = (a*b)/1<<bigpow
783 Since invb is in base 1<<invpow instead of 1<<bigpow, normalize c by 1<<(bigpow-invpow)
784 if invDoubleDec==1:
785 multiply additionally by 1<<bigpow*2 (for invb and c) so that base of c is again 2*bigpow
786 this can be seen by setting a=A*big, b=B*big, invb=big2/B, mult(a,invb) = a*invb/(big*big) = A/B*big*big2/(big*big) = A/B*big2/big
787 and we want c = A/B*big*big => normfactor = big^3/big2
788 */
789 if (invDoubleDec == 1) {
790 normpow = 3 * bigpow;
791 } else {
792 normpow = bigpow;
793 }
794 if (normpow < invpow) {
795 /* divide with rounding */
796 c = picocep_fixptdivpow(c, invpow - normpow);
797 } else {
798 c = picocep_fixptmultpow(c, normpow - invpow);
799 }
800 return c;
801 }
802
803 /**
804 * initializes the coefficients to calculate delta and delta-delta values and the squares of the coefficients
805 * @param cep : the CEP PU sub-object handle
806 * @callgraph
807 * @callergraph
808 */
initSmoothing(cep_subobj_t * cep)809 static void initSmoothing(cep_subobj_t * cep)
810 {
811 cep->xi[0] = 1;
812 cep->xi[1] = -1;
813 cep->xi[2] = 2;
814 cep->xi[3] = -4;
815 cep->xi[4] = 2;
816 cep->xsqi[0] = 1;
817 cep->xsqi[1] = 1;
818 cep->xsqi[2] = 4;
819 cep->xsqi[3] = 16;
820 cep->xsqi[4] = 4;
821
822 cep->x1[0] = -1;
823 cep->x1[1] = 2;
824 cep->xsq1[0] = 1;
825 cep->xsq1[1] = 4;
826
827 cep->x2[0] = -1;
828 cep->x2[1] = -4;
829 cep->x2[2] = 2;
830 cep->xsq2[0] = 1;
831 cep->xsq2[1] = 16;
832 cep->xsq2[2] = 4;
833
834 cep->xm[0] = 1;
835 cep->xm[1] = 2;
836 cep->xm[2] = -4;
837 cep->xsqm[0] = 1;
838 cep->xsqm[1] = 4;
839 cep->xsqm[2] = 16;
840
841 cep->xn[0] = 1;
842 cep->xn[1] = 2;
843 cep->xsqn[0] = 1;
844 cep->xsqn[1] = 4;
845 }
846
847 /**
848 * matrix inversion
849 * @param cep : PU sub object pointer
850 * @param N
851 * @param smoothcep : pointer to picoos_int16, sequence of smoothed cepstral vectors
852 * @param cepnum : cepstral dimension to be treated
853 * @param pdf : pdf resource
854 * @param invpow : fixed point base for inverse
855 * @param invDoubleDec : boolean indicating that result of picocep_fixptinv has fixed point base 2*bigpow
856 * picocep_fixptmult absorbs double decimal size by dividing its result by extra factor big
857 * @return void
858 * @remarks diag0, diag1, diag2, WUm, invdiag0 globals needed in this function (object members in pico)
859 * @callgraph
860 * @callergraph
861 */
invMatrix(cep_subobj_t * cep,picoos_uint16 N,picoos_int16 * smoothcep,picoos_uint8 cepnum,picokpdf_PdfMUL pdf,picoos_uint8 invpow,picoos_uint8 invDoubleDec)862 static void invMatrix(cep_subobj_t * cep, picoos_uint16 N,
863 picoos_int16 *smoothcep, picoos_uint8 cepnum,
864 picokpdf_PdfMUL pdf, picoos_uint8 invpow, picoos_uint8 invDoubleDec)
865 {
866 picoos_int32 j, v1, v2, h;
867 picoos_uint32 k;
868 picoos_uint8 rowscpow, prevrowscpow;
869 picoos_uint8 ceporder = pdf->ceporder;
870 picoos_uint8 bigpow = pdf->bigpow;
871 picoos_uint8 meanpow = pdf->meanpow;
872
873 /* LDL factorization */
874 prevrowscpow = 0;
875 cep->invdiag0[0] = picocep_fixptInvDiagEle(cep->diag0[0], &rowscpow,
876 bigpow, invpow); /* inverse has fixed point basis 1<<invpow */
877 cep->diag1[0] = picocep_fixptinv((cep->diag1[0]) << rowscpow,
878 cep->invdiag0[0], bigpow, invpow, invDoubleDec); /* perform division via inverse */
879 cep->diag2[0] = picocep_fixptinv((cep->diag2[0]) << rowscpow,
880 cep->invdiag0[0], bigpow, invpow, invDoubleDec);
881 cep->WUm[0] = (cep->WUm[0]) << rowscpow; /* if diag0 too low, multiply LHS and RHS of row in matrix equation by 1<<rowscpow */
882 for (j = 1; j < N; j++) {
883 /* do forward substitution */
884 cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag1[j - 1],
885 cep->WUm[j - 1], bigpow, invDoubleDec);
886 if (j > 1) {
887 cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag2[j - 2],
888 cep->WUm[j - 2], bigpow, invDoubleDec);
889 }
890
891 /* update row j */
892 v1 = picocep_fixptmult((cep->diag1[j - 1]) / (1 << rowscpow),
893 cep->diag0[j - 1], bigpow, invDoubleDec); /* undo scaling by 1<<rowscpow because diag1(j-1) refers to symm ele in column j-1 not in row j-1 */
894 cep->diag0[j] = cep->diag0[j] - picocep_fixptmult(cep->diag1[j - 1],
895 v1, bigpow, invDoubleDec);
896 if (j > 1) {
897 v2 = picocep_fixptmult((cep->diag2[j - 2]) / (1 << prevrowscpow),
898 cep->diag0[j - 2], bigpow, invDoubleDec); /* undo scaling by 1<<prevrowscpow because diag1(j-2) refers to symm ele in column j-2 not in row j-2 */
899 cep->diag0[j] = cep->diag0[j] - picocep_fixptmult(
900 cep->diag2[j - 2], v2, bigpow, invDoubleDec);
901 }
902 prevrowscpow = rowscpow;
903 cep->invdiag0[j] = picocep_fixptInvDiagEle(cep->diag0[j], &rowscpow,
904 bigpow, invpow); /* inverse has fixed point basis 1<<invpow */
905 cep->WUm[j] = (cep->WUm[j]) << rowscpow;
906 if (j < N - 1) {
907 h = picocep_fixptmult(cep->diag2[j - 1], v1, bigpow, invDoubleDec);
908 cep->diag1[j] = picocep_fixptinv((cep->diag1[j] - h) << rowscpow,
909 cep->invdiag0[j], bigpow, invpow, invDoubleDec); /* eliminate column j below pivot */
910 }
911 if (j < N - 2) {
912 cep->diag2[j] = picocep_fixptinv((cep->diag2[j]) << rowscpow,
913 cep->invdiag0[j], bigpow, invpow, invDoubleDec); /* eliminate column j below pivot */
914 }
915 }
916
917 /* divide all entries of WUm by diag0 */
918 for (j = 0; j < N; j++) {
919 cep->WUm[j] = picocep_fixptinv(cep->WUm[j], cep->invdiag0[j], bigpow,
920 invpow, invDoubleDec);
921 if (invDoubleDec == 1) {
922 cep->WUm[j] = picocep_fixptdivpow(cep->WUm[j], bigpow);
923 }
924 }
925
926 /* backward substitution */
927 for (j = N - 2; j >= 0; j--) {
928 cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag1[j], cep->WUm[j
929 + 1], bigpow, invDoubleDec);
930 if (j < N - 2) {
931 cep->WUm[j] = cep->WUm[j] - picocep_fixptmult(cep->diag2[j],
932 cep->WUm[j + 2], bigpow, invDoubleDec);
933 }
934 }
935 /* copy N frames into smoothcep (only for coeff # "cepnum") */
936 /* coefficients normalized to occupy short; for correct waveform energy, divide by (1<<(bigpow-meanpow)) then convert e.g. to picoos_single */
937 k = cepnum;
938 for (j = 0; j < N; j++) {
939 smoothcep[k] = (picoos_int16)(cep->WUm[j]/(1<<meanpow));
940 k += ceporder;
941 }
942
943 }/* invMatrix*/
944
945 /**
946 * Calculate matrix products needed to implement the solution
947 * @param cep : PU sub object pointer
948 * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3
949 * @param indices : indices of pdf vectors for all frames in current sentence
950 * @param b, N : to be smoothed frames indices (range will be from b to b+N-1)
951 * @param cepnum : cepstral dimension to be treated
952 * @return void
953 * @remarks diag0, diag1, diag2, WUm, invdiag0 globals needed in this function (object members in pico)
954 * @remarks WUW --> At x W x A
955 * @remarks WUm --> At x W x b
956 * @callgraph
957 * @callergraph
958 */
makeWUWandWUm(cep_subobj_t * cep,picokpdf_PdfMUL pdf,picoos_uint16 * indices,picoos_uint16 b,picoos_uint16 N,picoos_uint8 cepnum)959 static picoos_uint8 makeWUWandWUm(cep_subobj_t * cep, picokpdf_PdfMUL pdf,
960 picoos_uint16 *indices, picoos_uint16 b, picoos_uint16 N,
961 picoos_uint8 cepnum)
962 {
963 picoos_uint16 Id[2], Idd[3];
964 /*picoos_uint32 vecstart, k;*/
965 picoos_uint32 vecstart;
966 picoos_int32 *x = NULL, *xsq = NULL;
967 picoos_int32 mean, ivar;
968 picoos_uint16 i, j, numd = 0, numdd = 0;
969 picoos_uint8 vecsize = pdf->vecsize;
970 picoos_int32 prev_WUm, prev_diag0, prev_diag1, prev_diag1_1, prev_diag2;
971
972 prev_WUm = prev_diag0 = prev_diag1 = prev_diag1_1 = prev_diag2 = 0;
973 for (i = 0; i < N; i++) {
974
975 if ((1 < i) && (i < N - 2)) {
976 x = cep->xi;
977 xsq = cep->xsqi;
978 numd = 2;
979 numdd = 3;
980 Id[0] = Idd[0] = i - 1;
981 Id[1] = Idd[2] = i + 1;
982 Idd[1] = i;
983 } else if (i == 0) {
984 x = cep->x1;
985 xsq = cep->xsq1;
986 numd = numdd = 1;
987 Id[0] = Idd[0] = 1;
988 } else if (i == 1) {
989 x = cep->x2;
990 xsq = cep->xsq2;
991 numd = 1;
992 numdd = 2;
993 Id[0] = Idd[1] = 2;
994 Idd[0] = 1;
995 } else if (i == N - 2) {
996 x = cep->xm;
997 xsq = cep->xsqm;
998 numd = 1;
999 numdd = 2;
1000 Id[0] = Idd[0] = N - 3;
1001 Idd[1] = N - 2;
1002 } else if (i == N - 1) {
1003 x = cep->xn;
1004 xsq = cep->xsqn;
1005 numd = numdd = 1;
1006 Id[0] = Idd[0] = N - 2;
1007 }
1008
1009 /* process static means and static inverse variances */
1010 if (i > 0 && indices[b + i] == indices[b + i - 1]) {
1011 cep->diag0[i] = prev_diag0;
1012 cep->WUm[i] = prev_WUm;
1013 } else {
1014 vecstart = indices[b + i] * vecsize;
1015 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR,
1016 PICOCEP_WANTSTATIC);
1017 prev_diag0 = cep->diag0[i] = ivar << 2; /* multiply ivar by 4 (4 used to be first entry of xsq) */
1018 mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN,
1019 PICOCEP_WANTSTATIC);
1020 prev_WUm = cep->WUm[i] = mean << 1; /* multiply mean by 2 (2 used to be first entry of x) */
1021 }
1022
1023 /* process delta means and delta inverse variances */
1024 for (j = 0; j < numd; j++) {
1025 vecstart = indices[b + Id[j]] * vecsize;
1026 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR,
1027 PICOCEP_WANTDELTA);
1028 cep->diag0[i] += xsq[j] * ivar;
1029
1030 mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN,
1031 PICOCEP_WANTDELTA);
1032 if (mean != 0) {
1033 cep->WUm[i] += x[j] * mean;
1034 }
1035 }
1036
1037 /* process delta delta means and delta delta inverse variances */
1038 for (j = 0; j < numdd; j++) {
1039 vecstart = indices[b + Idd[j]] * vecsize;
1040 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR,
1041 PICOCEP_WANTDELTA2);
1042 cep->diag0[i] += xsq[numd + j] * ivar;
1043
1044 mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN,
1045 PICOCEP_WANTDELTA2);
1046 if (mean != 0) {
1047 cep->WUm[i] += x[numd + j] * mean;
1048 }
1049 }
1050
1051 cep->diag0[i] = (cep->diag0[i] + 2) / 4; /* long DIV with rounding */
1052 cep->WUm[i] = (cep->WUm[i] + 1) / 2; /* long DIV with rounding */
1053
1054 /* calculate diag(A,-1) */
1055 if (i < N - 1) {
1056 if (i < N - 2) {
1057 if (i > 0 && indices[b + i + 1] == indices[b + i]) {
1058 cep->diag1[i] = prev_diag1;
1059 } else {
1060 vecstart = indices[b + i + 1] * vecsize;
1061 /*
1062 diag1[i] = getFromPdf(pdf, vecstart, numvuv, ceporder, numdeltas, cepnum,
1063 bigpow, meanpowUm, ivarpow, PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2);
1064 */
1065 prev_diag1 = cep->diag1[i] = getFromPdf(pdf, vecstart,
1066 cepnum, PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2);
1067 }
1068 /*
1069 k = vecstart +pdf->numvuv+pdf->ceporder*2 + pdf->numdeltas*3 +
1070 pdf->ceporder*2 +cepnum;
1071 cep->diag1[i] = (picoos_int32)(pdf->content[k]) << pdf->bigpow;
1072 */
1073 } else {
1074 cep->diag1[i] = 0;
1075 }
1076 if (i > 0) {
1077 if (i > 1 && indices[b + i] == indices[b + i - 1]) {
1078 cep->diag1[i] += prev_diag1_1;
1079 } else {
1080 vecstart = indices[b + i] * vecsize;
1081 /*
1082 k = vecstart + pdf->numvuv + pdf->ceporder * 2 + pdf->numdeltas * 3 + pdf->ceporder * 2 + cepnum;
1083 cep->diag1[i] += (picoos_int32)(pdf->content[k]) << pdf->bigpow; */
1084 /* cepnum'th delta delta ivar */
1085
1086 prev_diag1_1 = getFromPdf(pdf, vecstart, cepnum,
1087 PICOCEP_WANTIVAR, PICOCEP_WANTDELTA2);
1088 cep->diag1[i] += prev_diag1_1;
1089 }
1090
1091 } /*i < N-1 */
1092 cep->diag1[i] *= -2;
1093 }
1094 }
1095
1096 /* calculate diag(A,-2) */
1097 for (i = 0; i < N - 2; i++) {
1098 if (i > 0 && indices[b + i + 1] == indices[b + i]) {
1099 cep->diag2[i] = prev_diag2;
1100 } else {
1101 vecstart = indices[b + i + 1] * vecsize;
1102 /*
1103 k = vecstart + pdf->numvuv + pdf->ceporder * 2 + pdf->numdeltas * 3 + pdf->ceporder * 2 + cepnum;
1104 cep->diag2[i] = (picoos_int32)(pdf->content[k]) << pdf->bigpow;
1105 k -= pdf->ceporder;
1106 ivar = (picoos_int32)(pdf->content[k]) << pdf->bigpow;
1107 */
1108 cep->diag2[i] = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR,
1109 PICOCEP_WANTDELTA2);
1110 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR,
1111 PICOCEP_WANTDELTA);
1112 cep->diag2[i] -= (ivar + 2) / 4;
1113 prev_diag2 = cep->diag2[i];
1114 }
1115 }
1116
1117 return 0;
1118 }/* makeWUWandWUm */
1119
1120 /**
1121 * Retrieve actual values for MGC from PDF resource
1122 * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3
1123 * @param vecstart : indices of pdf vectors for all frames in current sentence
1124 * @param cepnum : cepstral dimension to be treated
1125 * @param wantMeanOrIvar : flag to select mean or variance values
1126 * @param wantStaticOrDeltax : flag to select static or delta values
1127 * @return the actual value retrieved
1128 * @callgraph
1129 * @callergraph
1130 */
getFromPdf(picokpdf_PdfMUL pdf,picoos_uint32 vecstart,picoos_uint8 cepnum,picocep_WantMeanOrIvar_t wantMeanOrIvar,picocep_WantStaticOrDelta_t wantStaticOrDeltax)1131 static picoos_int32 getFromPdf(picokpdf_PdfMUL pdf, picoos_uint32 vecstart,
1132 picoos_uint8 cepnum, picocep_WantMeanOrIvar_t wantMeanOrIvar,
1133 picocep_WantStaticOrDelta_t wantStaticOrDeltax)
1134 {
1135 picoos_uint8 s, ind;
1136 picoos_uint8 *p;
1137 picoos_uint8 ceporder, ceporder2, cc;
1138 picoos_uint32 k;
1139 picoos_int32 mean = 0, ivar = 0;
1140
1141 if (pdf->numdeltas == 0xFF) {
1142 switch (wantMeanOrIvar) {
1143 case PICOCEP_WANTMEAN:
1144 switch (wantStaticOrDeltax) {
1145 case PICOCEP_WANTSTATIC:
1146 p = pdf->content
1147 + (vecstart + pdf->numvuv + cepnum * 2); /* cepnum'th static mean */
1148 mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8))
1149 | *p) << (pdf->meanpowUm[cepnum]);
1150 break;
1151 case PICOCEP_WANTDELTA:
1152 cc = pdf->ceporder + cepnum;
1153 p = pdf->content + (vecstart + pdf->numvuv + cc * 2); /* cepnum'th delta mean */
1154 mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8))
1155 | *p) << (pdf->meanpowUm[cc]);
1156 break;
1157 case PICOCEP_WANTDELTA2:
1158 cc = pdf->ceporder * 2 + cepnum;
1159 p = pdf->content + (vecstart + pdf->numvuv + cc * 2); /* cepnum'th delta delta mean */
1160 mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8))
1161 | *p) << (pdf->meanpowUm[cc]);
1162 break;
1163 default:
1164 /* should never come here */
1165 PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax));
1166 }
1167 return mean;
1168 break;
1169 case PICOCEP_WANTIVAR:
1170 switch (wantStaticOrDeltax) {
1171 case PICOCEP_WANTSTATIC:
1172 k = vecstart + pdf->numvuv + pdf->ceporder * 6 + cepnum; /* cepnum'th static ivar */
1173 ivar = (picoos_int32) (pdf->content[k])
1174 << (pdf->ivarpow[cepnum]);
1175 break;
1176 case PICOCEP_WANTDELTA:
1177 ceporder = pdf->ceporder;
1178 k = vecstart + pdf->numvuv + ceporder * 7 + cepnum; /* cepnum'th delta ivar */
1179 ivar = (picoos_int32) (pdf->content[k])
1180 << (pdf->ivarpow[ceporder + cepnum]);
1181 break;
1182 case PICOCEP_WANTDELTA2:
1183 ceporder = pdf->ceporder;
1184 k = vecstart + pdf->numvuv + ceporder * 8 + cepnum; /* cepnum'th delta delta ivar */
1185 ivar = (picoos_int32) (pdf->content[k])
1186 << (pdf->ivarpow[2 * ceporder + cepnum]);
1187 break;
1188 default:
1189 /* should never get here */
1190 PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax));
1191 }
1192 return ivar;
1193 break;
1194 default:
1195 /* should never come here */
1196 PICODBG_ERROR(("unknown type wantMeanOrIvar = %n", wantMeanOrIvar));
1197 return 0;
1198 }
1199 } else {
1200 switch (wantMeanOrIvar) {
1201 case PICOCEP_WANTMEAN:
1202 switch (wantStaticOrDeltax) {
1203 case PICOCEP_WANTSTATIC:
1204 p = pdf->content
1205 + (vecstart + pdf->numvuv + cepnum * 2); /* cepnum'th static mean */
1206 mean = ((picoos_int32) ((picoos_int16) (*(p + 1) << 8))
1207 | *p) << (pdf->meanpowUm[cepnum]);
1208 return mean;
1209 break;
1210 case PICOCEP_WANTDELTA:
1211 ceporder = pdf->ceporder;
1212 s = 0;
1213 ind = 0;
1214 while ((s < pdf->numdeltas) && (ind < cepnum || (ind
1215 == 0 && cepnum == 0))) { /* rawmean deltas are sparse so investigate indices in column */
1216 k = vecstart + pdf->numvuv + ceporder * 2 + s; /* s'th delta index */
1217 ind = (picoos_uint8) (pdf->content[k]); /* is already picoos_uint8 but just to make explicit */
1218 if (ind == cepnum) {
1219 k = vecstart + pdf->numvuv + ceporder * 2
1220 + pdf->numdeltas + s * 2; /* s'th sparse delta mean, corresponds to cepnum'th delta mean */
1221 mean
1222 = ((picoos_int32) ((picoos_int16) ((pdf->content[k
1223 + 1]) << 8)) | pdf->content[k])
1224 << (pdf->meanpowUm[ceporder
1225 + cepnum]);
1226 return mean;
1227 }
1228 s++;
1229 }
1230 return 0;
1231 break;
1232 case PICOCEP_WANTDELTA2:
1233 ceporder = pdf->ceporder;
1234 ceporder2 = ceporder * 2;
1235 s = pdf->numdeltas;
1236 ind = 2 * ceporder;
1237 while ((s-- > 0) && (ind > ceporder + cepnum)) { /* rawmean deltas are sparse so investigate indices in column */
1238 k = vecstart + pdf->numvuv + ceporder2 + s; /* s'th delta index */
1239 ind = (picoos_uint8) (pdf->content[k]); /* is already picoos_uint8 but just to make explicit */
1240 if (ind == ceporder + cepnum) {
1241 k = vecstart + pdf->numvuv + ceporder2
1242 + pdf->numdeltas + s * 2; /* s'th sparse delta mean, corresponds to cepnum'th delta delta mean */
1243 mean
1244 = ((picoos_int32) ((picoos_int16) ((pdf->content[k
1245 + 1]) << 8)) | pdf->content[k])
1246 << (pdf->meanpowUm[ceporder2
1247 + cepnum]);
1248 return mean;
1249 }
1250 }
1251 return 0;
1252 break;
1253 default:
1254 PICODBG_ERROR(("getFromPdf: unknown type wantStaticOrDeltax = %i\n", wantStaticOrDeltax));
1255 return 0;
1256 }
1257 break;
1258 case PICOCEP_WANTIVAR:
1259 switch (wantStaticOrDeltax) {
1260 case PICOCEP_WANTSTATIC:
1261 k = vecstart + pdf->numvuv + pdf->ceporder * 2
1262 + pdf->numdeltas * 3 + cepnum; /* cepnum'th static ivar */
1263 ivar = (picoos_int32) (pdf->content[k])
1264 << (pdf->ivarpow[cepnum]);
1265 break;
1266 case PICOCEP_WANTDELTA:
1267 ceporder = pdf->ceporder;
1268 k = vecstart + pdf->numvuv + ceporder * 3
1269 + pdf->numdeltas * 3 + cepnum; /* cepnum'th delta ivar */
1270 ivar = (picoos_int32) (pdf->content[k])
1271 << (pdf->ivarpow[ceporder + cepnum]);
1272 break;
1273 case PICOCEP_WANTDELTA2:
1274 ceporder2 = 2 * pdf->ceporder;
1275 k = vecstart + pdf->numvuv + ceporder2 + pdf->numdeltas
1276 * 3 + ceporder2 + cepnum; /* cepnum'th delta delta ivar */
1277 ivar = (picoos_int32) (pdf->content[k])
1278 << (pdf->ivarpow[ceporder2 + cepnum]);
1279 break;
1280 default:
1281 PICODBG_ERROR(("unknown type wantStaticOrDeltax = %i", wantStaticOrDeltax));
1282 }
1283 return ivar;
1284 break;
1285 default:
1286 PICODBG_ERROR(("unknown type wantMeanOrIvar = %i", wantMeanOrIvar));
1287 return 0;
1288 }
1289 }
1290 return 0;
1291 }
1292
1293 /**
1294 * Retrieve actual values for MGC from PDF resource - Variant "Direct"
1295 * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3
1296 * @param indices : indices of pdf vectors for all frames in current sentence
1297 * @param activeEndPos : ??
1298 * @param cepnum : cepstral dimension to be treated
1299 * @param smoothcep : ??
1300 * @return the actual value retrieved
1301 * @callgraph
1302 * @callergraph
1303 */
getDirect(picokpdf_PdfMUL pdf,picoos_uint16 * indices,picoos_uint16 activeEndPos,picoos_uint8 cepnum,picoos_int16 * smoothcep)1304 static void getDirect(picokpdf_PdfMUL pdf, picoos_uint16 *indices,
1305 picoos_uint16 activeEndPos,
1306 picoos_uint8 cepnum, picoos_int16 *smoothcep)
1307 {
1308 picoos_uint16 i;
1309 picoos_uint32 j;
1310 picoos_uint32 vecstart;
1311 picoos_int32 mean, ivar;
1312 picoos_int32 prev_mean;
1313 picoos_uint8 vecsize = pdf->vecsize;
1314 picoos_uint8 order = pdf->ceporder;
1315
1316 j = cepnum;
1317 prev_mean = 0;
1318 for (i = 0; i < activeEndPos; i++) {
1319 if (i > 0 && indices[i] == indices[i - 1]) {
1320 mean = prev_mean;
1321 } else {
1322 vecstart = indices[i] * vecsize;
1323 mean = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTMEAN,
1324 PICOCEP_WANTSTATIC);
1325 ivar = getFromPdf(pdf, vecstart, cepnum, PICOCEP_WANTIVAR,
1326 PICOCEP_WANTSTATIC);
1327 prev_mean = mean = picocep_fixptdiv(mean, ivar, pdf->bigpow);
1328 }
1329 smoothcep[j] = (picoos_int16)(mean/(1<<pdf->meanpow));
1330 j += order;
1331 }
1332 }
1333
1334 /**
1335 * Retrieve actual values for voicing from PDF resource
1336 * @param pdf : pointer to picoos_uint8, sequence of pdf vectors, each vector of length 1+ceporder*2+numdeltas*3+ceporder*3
1337 * @param indices : indices of pdf vectors for all frames in current sentence
1338 * @param activeEndPos : end position of indices to be considered
1339 * @return smoothcep : the values retrieved
1340 * @callgraph
1341 * @callergraph
1342 */
getVoiced(picokpdf_PdfMUL pdf,picoos_uint16 * indices,picoos_uint16 activeEndPos,picoos_uint8 * smoothcep)1343 static void getVoiced(picokpdf_PdfMUL pdf, picoos_uint16 *indices,
1344 picoos_uint16 activeEndPos,
1345 picoos_uint8 *smoothcep)
1346 {
1347 picoos_uint16 i, j;
1348 picoos_uint32 vecstart;
1349 picoos_uint8 vecsize = pdf->vecsize;
1350
1351 if (pdf->numvuv == 0) {
1352 /* do nothing */
1353 } else {
1354 for (i = 0, j = 0; i < activeEndPos; i++, j++) {
1355 vecstart = indices[i] * vecsize;
1356 smoothcep[j] = pdf->content[vecstart]; /* odd value is voiced, even if unvoiced */
1357 }
1358 }
1359 }
1360
1361 /** reads platform-independent uint16 from buffer at *pos and advances *pos
1362 * @param buf : buffer picoos_uint8
1363 * @param *pos : start position inside buffer of pi uint16
1364 * @return the uint16
1365 * @callgraph
1366 * @callergraph
1367 */
get_pi_uint16(picoos_uint8 * buf,picoos_uint16 * pos)1368 static picoos_uint16 get_pi_uint16(picoos_uint8 * buf, picoos_uint16 *pos)
1369 {
1370 picoos_uint16 res;
1371 res = buf[(*pos)] | ((picoos_uint16) buf[(*pos) + 1] << 8);
1372 *pos += 2;
1373 return res;
1374 }
1375 /**
1376 * Looks up indices of one phone item and fills index buffers. Consumes Item
1377 * @param cep : the CEP PU sub object pointer
1378 * @param ihead : pointer to the start of the phone item
1379 * @callgraph
1380 * @callergraph
1381 */
treat_phone(cep_subobj_t * cep,picodata_itemhead_t * ihead)1382 static void treat_phone(cep_subobj_t * cep, picodata_itemhead_t * ihead)
1383 {
1384 picoos_uint16 state, frame, frames;
1385 picoos_uint16 indlfz, indmgc;
1386 picoos_uint16 pos;
1387 picoos_uint8 bufferFull;
1388
1389 /* treat all states
1390 * for each state, repeat putting the index into the index buffer framesperstate times.
1391 */
1392 /* set state and frame to the first state and frame in the phone to be considered */
1393 state = 0; /* the first state to be considered */
1394 frame = 0; /* the first frame to be considered */
1395 /* numFramesPerState: 2 byte, lf0Index: 2 byte, mgcIndex: 2 byte -> 6 bytes per state */
1396 PICODBG_DEBUG(("skipping to phone state %i ",state));
1397 pos = cep->inReadPos + PICODATA_ITEM_HEADSIZE + state * 6;
1398 /* */
1399 PICODBG_DEBUG(("state info starts at inBuf pos %i ",pos));
1400 /* get the current frames per state */
1401 frames = get_pi_uint16(cep->inBuf, &pos);
1402 /* */
1403 PICODBG_DEBUG(("number of frames for this phone state: %i",frames));
1404 /* */
1405 PICODBG_DEBUG(("PARSE starting with frame %i",frame));
1406
1407 bufferFull = cep->indexWritePos >= PICOCEP_MAXWINLEN;
1408 while ((state < ihead->info2) && (bufferFull == FALSE)) {
1409
1410 /* get the current state's lf0 and mgc indices and adjust according to state */
1411 /* the indices have to be calculated as follows:
1412 * new index = (index-1) + stateoffset(state) */
1413
1414 indlfz = get_pi_uint16(cep->inBuf, &pos); /* lfz index */
1415 indlfz += -1 + cep->pdflfz->stateoffset[state]; /* transform index */
1416 indmgc = get_pi_uint16(cep->inBuf, &pos); /* mgc index */
1417 indmgc += -1 + cep->pdfmgc->stateoffset[state]; /* transform index */
1418
1419 /* are we reaching the end of the index buffers? */
1420 if ((cep->indexWritePos - frame) + frames > PICOCEP_MAXWINLEN) {
1421 /* number of frames that will still fit */
1422 frames = PICOCEP_MAXWINLEN - (cep->indexWritePos - frame);
1423 bufferFull = TRUE;
1424 PICODBG_DEBUG(("smoothing buffer full at state=%i frame=%i",state, frame));
1425 }
1426 while (frame < frames) {
1427 cep->indicesMGC[cep->indexWritePos] = indmgc;
1428 cep->indicesLFZ[cep->indexWritePos] = indlfz;
1429 cep->phoneId[cep->indexWritePos] = ihead->info1;
1430 cep->indexWritePos++;
1431 frame++;
1432 }
1433 /* proceed to next state */
1434 PICODBG_DEBUG(("finished state %i with %i frames, now at index write pos %i",
1435 state, frames,cep->indexWritePos));
1436 state++;
1437 if (state < ihead->info2) {
1438 frame = 0;
1439 frames = get_pi_uint16(cep->inBuf, &pos);
1440 }
1441 }
1442 /* consume the phone item */
1443 cep->inReadPos = cep->nextInPos;
1444 /* */
1445 PICODBG_DEBUG(("finished phone, advancing inReadPos to %i",cep->inReadPos));
1446 }
1447
1448 /**
1449 * Returns true if an Item has to be forwarded to next PU
1450 * @param ihead : pointer to item head structure
1451 * @return TRUE : the item should be forwarded
1452 * @return FALSE : the item should be consumed
1453 * @callgraph
1454 * @callergraph
1455 */
forwardingItem(picodata_itemhead_t * ihead)1456 static picoos_uint8 forwardingItem(picodata_itemhead_t * ihead)
1457 {
1458 if ((PICODATA_ITEM_CMD == ihead->type) && (PICODATA_ITEMINFO1_CMD_IGNSIG
1459 == ihead->info1)) {
1460 return FALSE;
1461 } else {
1462 return TRUE;
1463 }
1464 }
1465
1466 /**
1467 * performs a step of the cep processing
1468 * @param this : pointer to current PU (Control Unit)
1469 * @param mode : mode for the PU (not used)
1470 * @param numBytesOutput : pointer to output number fo bytes produced
1471 * @return one of the "picodata_step_result_t" values
1472 * @callgraph
1473 * @callergraph
1474 */
cepStep(register picodata_ProcessingUnit this,picoos_int16 mode,picoos_uint16 * numBytesOutput)1475 static picodata_step_result_t cepStep(register picodata_ProcessingUnit this,
1476 picoos_int16 mode, picoos_uint16 * numBytesOutput)
1477 {
1478 register cep_subobj_t * cep;
1479 picodata_itemhead_t ihead /* , ohead */;
1480 picoos_uint8 * icontents;
1481 pico_status_t sResult = PICO_OK;
1482 picoos_uint16 blen, clen;
1483 picoos_uint16 numinb, numoutb;
1484
1485 #if defined (PICO_DEBUG)
1486 picoos_char msgstr[PICOCEP_MSGSTR_SIZE];
1487 #endif
1488 numinb = 0;
1489 numoutb = 0;
1490
1491 if (NULL == this || NULL == this->subObj) {
1492 return PICODATA_PU_ERROR;
1493 }
1494 cep = (cep_subobj_t *) this->subObj;
1495 mode = mode; /* avoid warning "var not used in this function"*/
1496
1497 /*Init number of output bytes*/
1498 *numBytesOutput = 0;
1499
1500 while (1) { /* exit via return */
1501
1502 PICODBG_DEBUG(("doing pu state %i", cep->procState));
1503
1504 switch (cep->procState) {
1505
1506 case PICOCEP_STEPSTATE_COLLECT:
1507 /* *************** item collector ***********************************/
1508
1509 PICODBG_TRACE(("COLLECT"));
1510
1511 /*collecting items from the PU input buffer*/
1512 sResult = picodata_cbGetItem(this->cbIn,
1513 &(cep->inBuf[cep->inWritePos]), cep->inBufSize
1514 - cep->inWritePos, &blen);
1515 if (PICO_EOF == sResult) { /* there are no more items available and we always need more data here */
1516 PICODBG_DEBUG(("COLLECT need more data, returning IDLE"));
1517 return PICODATA_PU_IDLE;
1518 }
1519
1520 PICODBG_DEBUG(("got item, status: %d", sResult));
1521
1522 if ((PICO_OK == sResult) && (blen > 0)) {
1523 /* we now have one item */
1524 cep->inWritePos += blen;
1525 cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE;
1526 } else {
1527 /* ignore item and stay in collect */
1528 PICODBG_ERROR(("COLLECT got bad result %i", sResult));
1529 cep->inReadPos = cep->inWritePos = 0;
1530 }
1531 /* return PICODATA_PU_ATOMIC; */
1532 break;
1533
1534 case PICOCEP_STEPSTATE_PROCESS_PARSE:
1535 /* **************** put item indices into index buffers (with repetition) ******************/
1536
1537 PICODBG_TRACE(("PARSE"));
1538
1539 PICODBG_DEBUG(("getting info from inBuf in range: [%i,%i[", cep->inReadPos, cep->inWritePos));
1540 if (cep->inWritePos <= cep->inReadPos) {
1541 /* no more items in inBuf */
1542 /* we try to get more data */
1543 PICODBG_DEBUG(("no more items in inBuf, try to collect more"));
1544 /* cep->needMoreInput = TRUE; */
1545 cep->inReadPos = cep->inWritePos = 0;
1546 cep->procState = PICOCEP_STEPSTATE_COLLECT;
1547 break;
1548 }
1549 /* look at the current item */
1550 /*verify that current item is valid */
1551 if (!picodata_is_valid_item(cep->inBuf + cep->inReadPos,
1552 cep->inWritePos - cep->inReadPos)) {
1553 PICODBG_ERROR(("found invalid item"));
1554 sResult = picodata_get_iteminfo(
1555 cep->inBuf + cep->inReadPos, cep->inWritePos
1556 - cep->inReadPos, &ihead, &icontents);PICODBG_DEBUG(("PARSE bad item %s",picodata_head_to_string(&ihead,msgstr,PICOCEP_MSGSTR_SIZE)));
1557
1558 return PICODATA_PU_ERROR;
1559 }
1560
1561 sResult = picodata_get_iteminfo(cep->inBuf + cep->inReadPos,
1562 cep->inWritePos - cep->inReadPos, &ihead, &icontents);
1563
1564 if (PICO_EXC_BUF_UNDERFLOW == sResult) {
1565 /* no more items in inBuf */
1566 /* we try to get more data */
1567 PICODBG_DEBUG(("no more items in inBuf, try to collect more"));
1568 /* cep->needMoreInput = TRUE; */
1569 cep->inReadPos = cep->inWritePos = 0;
1570 cep->procState = PICOCEP_STEPSTATE_COLLECT;
1571 break;
1572 } else if (PICO_OK != sResult) {
1573 PICODBG_ERROR(("unknown exception (sResult == %i)",sResult));
1574 return (picodata_step_result_t) picoos_emRaiseException(
1575 this->common->em, sResult, NULL, NULL);
1576 break;
1577 }
1578
1579 PICODBG_DEBUG(("PARSE looking at item %s",picodata_head_to_string(&ihead,msgstr,PICOCEP_MSGSTR_SIZE)));
1580
1581 cep->nextInPos = PICODATA_ITEM_HEADSIZE + ihead.len;
1582
1583 /* we decide what to do next depending on the item and the state of the index buffer:
1584 * - process buffer if buffer not empty and sentence end or flush or ignsig/start (don't consume item yet)
1585 * - fill buffer with (part of) phone contents if item is a phone
1586 * - consume or copy for later output otherwise
1587 */
1588
1589 if (cep->inIgnoreState) {
1590 if ((PICODATA_ITEM_CMD == ihead.type)
1591 && (PICODATA_ITEMINFO1_CMD_IGNSIG == ihead.info1)
1592 && (PICODATA_ITEMINFO2_CMD_END == ihead.info2)) {
1593 cep->inIgnoreState = 0;
1594 }PICODBG_DEBUG(("cep: PARSE consuming item of inBuf"));
1595 cep->inReadPos = cep->nextInPos;
1596 break;
1597 }
1598
1599 /* see if it is a sentence end boundary or termination boundary (flush) and there are indices to smooth -> smooth */
1600 if ((PICODATA_ITEM_BOUND == ihead.type)
1601 && ((PICODATA_ITEMINFO1_BOUND_SEND == ihead.info1)
1602 || (PICODATA_ITEMINFO1_BOUND_TERM == ihead.info1))
1603 && (cep->indexWritePos > 0)) {
1604 /* we smooth the buffer */
1605 cep->activeEndPos = cep->indexWritePos;
1606 cep->sentenceEnd = TRUE;
1607 /* output whatever we got */
1608 PICODBG_DEBUG(("cep: PARSE found sentence terminator; setting activeEndPos to %i",cep->activeEndPos));
1609 cep->procState = PICOCEP_STEPSTATE_PROCESS_SMOOTH;
1610 break;
1611 } else if (PICODATA_ITEM_PHONE == ihead.type) {
1612 /* it is a phone */
1613 PICODBG_DEBUG(("cep: PARSE treating PHONE"));
1614 treat_phone(cep, &ihead);
1615
1616 } else {
1617 if ((PICODATA_ITEM_CMD == ihead.type)
1618 && (PICODATA_ITEMINFO1_CMD_IGNSIG == ihead.info1)
1619 && (PICODATA_ITEMINFO2_CMD_START == ihead.info2)) {
1620 cep->inIgnoreState = 1;
1621 }
1622 /* sentence end or flush remaining after frame or other non-processable item, e.g. command */
1623 /* do we have to forward? */
1624 if (forwardingItem(&ihead)) {
1625 /* if no active frames, output immediately */
1626 if (cep->indexWritePos <= 0) {
1627 /* copy item to outBuf */
1628 PICODBG_DEBUG(("PARSE copy item in inBuf to outBuf"));
1629 picodata_copy_item(cep->inBuf + cep->inReadPos,
1630 cep->inWritePos - cep->inReadPos,
1631 cep->outBuf, cep->outBufSize, &blen);
1632 cep->outWritePos += blen;
1633 PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG],
1634 (picoos_uint8 *)"cep: do forward item ",
1635 cep->outBuf, PICODATA_MAX_ITEMSIZE);
1636 /* output item and then go to parse to treat a new item. */
1637 cep->feedFollowState
1638 = PICOCEP_STEPSTATE_PROCESS_PARSE;
1639 cep->procState = PICOCEP_STEPSTATE_FEED;
1640 } else if ((cep->headxWritePos < PICOCEP_MAXNR_HEADX)
1641 && (cep->cbufWritePos + ihead.len
1642 < cep->cbufBufSize)) {
1643 /* there is enough space to store item */
1644 PICODBG_DEBUG(("unhandled item (type %c, length %i). Storing associated with index %i",ihead.type, ihead.len, cep->indexWritePos));
1645 sResult
1646 = picodata_get_itemparts(
1647 cep->inBuf + cep->inReadPos,
1648 cep->inWritePos - cep->inReadPos,
1649 &(cep->headx[cep->headxWritePos].head),
1650 &(cep->cbuf[cep->cbufWritePos]),
1651 cep->cbufBufSize
1652 - cep->cbufWritePos, &clen);
1653
1654 if (sResult != PICO_OK) {
1655 PICODBG_ERROR(("problem getting item parts"));
1656 picoos_emRaiseException(this->common->em,
1657 sResult, NULL, NULL);
1658 return PICODATA_PU_ERROR;
1659 }
1660 /* remember sync position */
1661 cep->headx[cep->headxWritePos].frame
1662 = cep->indexWritePos;
1663
1664 if (clen > 0) {
1665 cep->headx[cep->headxWritePos].cind
1666 = cep->cbufWritePos;
1667 cep->cbufWritePos += clen;
1668 } else {
1669 cep->headx[cep->headxWritePos].cind = 0;
1670 }
1671 cep->headxWritePos++;
1672 } else {
1673 /* buffer full, smooth and output whatever we got */
1674 PICODBG_DEBUG(("PARSE is forced to smooth prematurely; setting activeEndPos to %i", cep->activeEndPos));
1675 cep->procState = PICOCEP_STEPSTATE_PROCESS_SMOOTH;
1676 /* don't consume item yet */
1677 break;
1678 }
1679 } else {
1680 }PICODBG_DEBUG(("cep: PARSE consuming item of inBuf"));
1681 cep->inReadPos = cep->nextInPos;
1682 }
1683 break;
1684
1685 case PICOCEP_STEPSTATE_PROCESS_SMOOTH:
1686 /* **************** smooth (indexed) coefficients and store smoothed in outBuffers ****************/
1687
1688 PICODBG_TRACE(("SMOOTH"));
1689 {
1690 picokpdf_PdfMUL pdf;
1691
1692 /* picoos_uint16 framesTreated = 0; */
1693 picoos_uint8 cepnum;
1694 picoos_uint16 N;
1695
1696 N = cep->activeEndPos; /* numframes in current step */
1697
1698 /* the range to be smoothed starts at 0 and is N long */
1699
1700 /* smooth each cepstral dimension separately */
1701 /* still to be experimented if higher order coeff can remain unsmoothed, i.e. simple copy from pdf */
1702
1703 /* reset the f0, ceps and voiced outfuffers */
1704 cep->outXCepReadPos = cep->outXCepWritePos = 0;
1705 cep->outVoicedReadPos = cep->outVoicedWritePos = 0;
1706 cep->outF0ReadPos = cep->outF0WritePos = 0;
1707
1708 PICODBG_DEBUG(("smoothing %d frames\n", N));
1709
1710 /* smooth f0 */
1711 pdf = cep->pdflfz;
1712 for (cepnum = 0; cepnum < pdf->ceporder; cepnum++) {
1713 if (cep->activeEndPos <= 0) {
1714 /* do nothing */
1715 } else if (3 < N) {
1716 makeWUWandWUm(cep, pdf, cep->indicesLFZ, 0, N,
1717 cepnum); /* update diag0, diag1, diag2, WUm */
1718 invMatrix(cep, N, cep->outF0 + cep->outF0WritePos, cepnum, pdf,
1719 PICOCEP_LFZINVPOW, PICOCEP_LFZDOUBLEDEC);
1720 } else {
1721 getDirect(pdf, cep->indicesLFZ, cep->activeEndPos,
1722 cepnum, cep->outF0 + cep->outF0WritePos);
1723 }
1724 }/* end for cepnum */
1725 cep->outF0WritePos += cep->activeEndPos * pdf->ceporder;
1726
1727 /* smooth mgc */
1728 pdf = cep->pdfmgc;
1729 for (cepnum = 0; cepnum < pdf->ceporder; cepnum++) {
1730 if (cep->activeEndPos <= 0) {
1731 /* do nothing */
1732 } else if (3 < N) {
1733 makeWUWandWUm(cep, pdf, cep->indicesMGC, 0, N,
1734 cepnum); /* update diag0, diag1, diag2, WUm */
1735 invMatrix(cep, N, cep->outXCep
1736 + cep->outXCepWritePos, cepnum,
1737 pdf, PICOCEP_MGCINVPOW,
1738 PICOCEP_MGCDOUBLEDEC);
1739 } else {
1740 getDirect(pdf, cep->indicesMGC, cep->activeEndPos,
1741 cepnum, cep->outXCep + cep->outXCepWritePos);
1742 }
1743 }/* end for cepnum */
1744 cep->outXCepWritePos += cep->activeEndPos * pdf->ceporder;
1745
1746 getVoiced(pdf, cep->indicesMGC, cep->activeEndPos, cep->outVoiced
1747 + cep->outVoicedWritePos);
1748 cep->outVoicedWritePos += cep->activeEndPos;
1749
1750 }
1751 /* setting indexReadPos to the next active index to be used. (will be advanced by FRAME when
1752 * reading the phoneId */
1753 cep->indexReadPos = 0;
1754 cep->procState = PICOCEP_STEPSTATE_PROCESS_FRAME;
1755 return PICODATA_PU_BUSY; /*data to feed*/
1756
1757 break;
1758
1759 case PICOCEP_STEPSTATE_PROCESS_FRAME:
1760
1761 /* *************** creating output items (type FRAME) ***********************************/
1762
1763 PICODBG_TRACE(("FRAME"));
1764
1765 if ((cep->headxBottom < cep->headxWritePos)
1766 && (cep->headx[cep->headxBottom].frame
1767 <= cep->indexReadPos)) {
1768
1769 /* output item in headx/cbuf */
1770 /* copy item to outBuf */
1771 PICODBG_DEBUG(("FRAME copy item in inBuf to outBuf"));
1772 picodata_put_itemparts(
1773 &(cep->headx[cep->headxBottom].head),
1774 &(cep->cbuf[cep->headx[cep->headxBottom].cind]),
1775 cep->headx[cep->headxBottom].head.len, cep->outBuf,
1776 cep->outBufSize, &blen);
1777 cep->outWritePos += blen;
1778 /* consume item in headx/cbuf */
1779 PICODBG_DEBUG(("PARSE consuming item of headx/cbuf"));
1780 cep->headxBottom++;
1781
1782 /* output item and then go to parse to treat a new item. */
1783 cep->feedFollowState = PICOCEP_STEPSTATE_PROCESS_FRAME;
1784 cep->procState = PICOCEP_STEPSTATE_FEED;
1785 break;
1786 }
1787
1788 if (cep->indexReadPos < cep->activeEndPos) {
1789 /*------------ there are frames to output ----------------------------------------*/
1790 /* still frames to output, create new FRAME_PAR item */
1791
1792 cep->nNumFrames++;
1793
1794 PICODBG_DEBUG(("FRAME creating FRAME_PAR: active: [0,%i[, read=%i, write=%i",
1795 cep->activeEndPos, cep->indexReadPos, cep->indexWritePos
1796 ));
1797
1798 /* create FRAME_PAR items from cep->outXX one by one */
1799
1800 /* converting the ceps shorts into floats:
1801 * scmeanpow = pdf->bigpow - pdf->meanpow;
1802 * for all sval:
1803 * fval = (picoos_single) sval / scmeanpow;
1804 */
1805
1806 cep->outWritePos = cep->outReadPos = 0;
1807 cep->outBuf[cep->outWritePos++] = cep->framehead.type;
1808 cep->outBuf[cep->outWritePos++] = cep->framehead.info1;
1809 cep->outBuf[cep->outWritePos++] = cep->framehead.info2;
1810 cep->outBuf[cep->outWritePos++] = cep->framehead.len;
1811
1812 PICODBG_DEBUG(("FRAME writing position after header: %i",cep->outWritePos));
1813
1814 {
1815 picoos_uint16 tmpUint16;
1816 picoos_int16 tmpInt16;
1817 picoos_uint16 i;
1818
1819 /* */
1820 PICODBG_DEBUG(("FRAME reading phoneId[%i] = %c:",cep->indexReadPos, cep->phoneId[cep->indexReadPos]));
1821 /* */
1822
1823 tmpUint16
1824 = (picoos_uint16) cep->phoneId[cep->indexReadPos];
1825
1826 picoos_mem_copy((void *) &tmpUint16,
1827 (void *) &cep->outBuf[cep->outWritePos],
1828 sizeof(tmpUint16));
1829
1830 cep->outWritePos += sizeof(tmpUint16);
1831
1832 PICODBG_DEBUG(("FRAME writing position after phone id: %i",cep->outWritePos));
1833
1834 for (i = 0; i < cep->pdflfz->ceporder; i++) {
1835
1836 tmpUint16 = (cep->outVoiced[cep->outVoicedReadPos]
1837 & 0x01) ? cep->outF0[cep->outF0ReadPos]
1838 : (picoos_uint16) 0;
1839
1840 picoos_mem_copy((void *) &tmpUint16,
1841 (void *) &cep->outBuf[cep->outWritePos],
1842 sizeof(tmpUint16));
1843 cep->outWritePos += sizeof(tmpUint16);
1844
1845 tmpUint16
1846 = (picoos_uint16) (cep->outVoiced[cep->outVoicedReadPos]);
1847 picoos_mem_copy((void *) &tmpUint16,
1848 (void *) &cep->outBuf[cep->outWritePos],
1849 sizeof(tmpUint16));
1850 cep->outWritePos += sizeof(tmpUint16);
1851 tmpUint16
1852 = (picoos_uint16) (cep->outF0[cep->outF0ReadPos]);
1853 picoos_mem_copy((void *) &tmpUint16,
1854 (void *) &cep->outBuf[cep->outWritePos],
1855 sizeof(tmpUint16));
1856 cep->outWritePos += sizeof(tmpUint16);
1857
1858 cep->outVoicedReadPos++;
1859 cep->outF0ReadPos++;
1860 }
1861
1862 PICODBG_DEBUG(("FRAME writing position after f0: %i",cep->outWritePos));
1863
1864 for (i = 0; i < cep->pdfmgc->ceporder; i++) {
1865 tmpInt16 = cep->outXCep[cep->outXCepReadPos++];
1866 picoos_mem_copy((void *) &tmpInt16,
1867 (void *) &cep->outBuf[cep->outWritePos],
1868 sizeof(tmpInt16));
1869 cep->outWritePos += sizeof(tmpInt16);
1870 }
1871
1872 PICODBG_DEBUG(("FRAME writing position after cepstrals: %i",cep->outWritePos));
1873
1874 tmpUint16
1875 = (picoos_uint16) cep->indicesMGC[cep->indexReadPos++];
1876
1877 picoos_mem_copy((void *) &tmpUint16,
1878 (void *) &cep->outBuf[cep->outWritePos],
1879 sizeof(tmpUint16));
1880
1881 PICODBG_DEBUG(("FRAME writing position after mgc index: %i",cep->outWritePos));
1882
1883 cep->outWritePos += sizeof(tmpUint16);
1884
1885 }
1886 /* finished to create FRAME_PAR, now output and then come back*/
1887 cep->feedFollowState = PICOCEP_STEPSTATE_PROCESS_FRAME;
1888 cep->procState = PICOCEP_STEPSTATE_FEED;
1889
1890 } else if (cep->sentenceEnd) {
1891 /*------------ no more frames to output at end of sentence ----------------------------------------*/
1892 PICODBG_INFO(("End of sentence - Processed frames : %d",
1893 cep->nNumFrames));
1894 cep->nNumFrames = 0;PICODBG_DEBUG(("FRAME no more active frames for this sentence"));
1895 /* no frames left in this sentence*/
1896 /* reset for new sentence */
1897 initSmoothing(cep);
1898 cep->sentenceEnd = FALSE;
1899 cep->indexReadPos = cep->indexWritePos = 0;
1900 cep->activeEndPos = PICOCEP_MAXWINLEN;
1901 cep->headxBottom = cep->headxWritePos = 0;
1902 cep->cbufWritePos = 0;
1903 cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE;
1904 } else {
1905 /*------------ no more frames can be output but sentence end not reached ----------------------------------------*/
1906 PICODBG_DEBUG(("Maximum number of frames per sentence reached"));
1907 cep->procState = PICOCEP_STEPSTATE_PROCESS_PARSE;
1908 }
1909 /*----------------------------------------------------*/
1910 break;
1911
1912 case PICOCEP_STEPSTATE_FEED:
1913 /* ***********************************************************************/
1914 /* FEED: combine input item with pos/phon pairs to output item */
1915 /* ***********************************************************************/
1916
1917 PICODBG_DEBUG(("FEED"));
1918
1919 PICODBG_DEBUG(("FEED putting outBuf item into cb"));
1920
1921 /*feeding items to PU output buffer*/
1922 sResult = picodata_cbPutItem(this->cbOut, cep->outBuf,
1923 cep->outBufSize, &blen);
1924
1925 if (PICO_EXC_BUF_OVERFLOW == sResult) {
1926 /* we have to redo this item */
1927 PICODBG_DEBUG(("FEED got overflow, returning PICODATA_PU_OUT_FULL"));
1928 return PICODATA_PU_OUT_FULL;
1929 } else if (PICO_OK == sResult) {
1930
1931 if (cep->outBuf[0] != 'k') {
1932 PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG],
1933 (picoos_uint8 *)"cep: ",
1934 cep->outBuf, PICODATA_MAX_ITEMSIZE);
1935 }
1936
1937 *numBytesOutput += blen;
1938 /*-------------------------*/
1939 /*reset the output pointers*/
1940 /*-------------------------*/
1941 if (cep->outReadPos >= cep->outWritePos) {
1942 cep->outReadPos = 0;
1943 cep->outWritePos = 0;
1944 }
1945 cep->procState = cep->feedFollowState;
1946 PICODBG_DEBUG(("FEED ok, going back to procState %i", cep->procState));
1947 return PICODATA_PU_BUSY;
1948 } else {
1949 PICODBG_DEBUG(("FEED got exception %i when trying to output item",sResult));
1950 cep->procState = cep->feedFollowState;
1951 return (picodata_step_result_t) sResult;
1952 }
1953 break;
1954
1955 default:
1956 /*NOT feeding items*/
1957 sResult = PICO_EXC_BUF_IGNORE;
1958 break;
1959 }/*end switch (cep->procState) */
1960 return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/
1961
1962 }/*end while*/
1963 /* we should never come here */
1964 return PICODATA_PU_ERROR;
1965 }/*cepStep*/
1966
1967 /* Picocep.c end */
1968