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 picopam.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 #include "picodefs.h"
30 #include "picoos.h"
31 #include "picodbg.h"
32 #include "picodata.h"
33 #include "picopam.h"
34 #include "picokdt.h"
35 #include "picokpdf.h"
36 #include "picoktab.h"
37 #include "picokdbg.h"
38 #include "picodsp.h"
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 #if 0
44 }
45 #endif
46 
47 #define PICOPAM_IN_BUFF_SIZE PICODATA_BUFSIZE_PAM    /*input buffer size for PAM */
48 #define PICOPAM_OUT_PAM_SIZE PICODATA_BUFSIZE_PAM    /*output buffer size for PAM*/
49 #define PICOPAM_DT_NRLFZ    5    /* nr of lfz decision trees per phoneme */
50 #define PICOPAM_DT_NRMGC    5    /* nr of mgc decision trees per phoneme */
51 #define PICOPAM_NRSTPF      5    /* nr of states per phone */
52 
53 #define PICOPAM_COLLECT     0
54 #define PICOPAM_SCHEDULE    1
55 #define PICOPAM_IMMEDIATE   2
56 #define PICOPAM_FORWARD     3
57 #define PICOPAM_FORWARD_FORCE_TERM 4
58 #define PICOPAM_PROCESS     5
59 #define PICOPAM_PLAY        6
60 #define PICOPAM_FEED        7
61 
62 #define PICOPAM_CONTINUE       100
63 #define PICOPAM_GOTO_SCHEDULE  1
64 #define PICOPAM_FLUSH_RECEIVED 6
65 #define PICOPAM_GOTO_FEED      7
66 #define PICOPAM_PRE_SYLL_ENDED 10
67 
68 #define PICOPAM_BREAK_ADD_SIZE 4        /*syllable feature vector increment dued to BREAK and SILENCE*/
69 #define PICOPAM_VECT_SIZE 64+PICOPAM_BREAK_ADD_SIZE /*syllable feature vector size (bytes)*/
70 #define PICOPAM_INVEC_SIZE 60           /*phone feature vector size */
71 #define PICOPAM_MAX_SYLL_PER_SENT 100   /*maximum number of syllables per sentece*/
72 #define PICOPAM_MAX_PH_PER_SENT 400     /*maximum number of phonemes  per sentece*/
73 #define PICOPAM_MAX_ITEM_PER_SENT 255   /*maximum number of attached items per sentence*/
74 #define PICOPAM_MAX_ITEM_SIZE_PER_SENT 4096 /*maximum size of attached items per sentence*/
75 
76 #define PICOPAM_READY 20 /*PAM could start backward processing*/
77 #define PICOPAM_MORE  21 /*PAM has still to collect */
78 #define PICOPAM_NA    22 /*PAM has not to deal with this item*/
79 #define PICOPAM_ERR   23 /*input item is not a valid item*/
80 
81 /*sentence types:cfr pam_map_sentence_type*/
82 #define PICOPAM_DECLARATIVE   0
83 #define PICOPAM_INTERROGATIVE 1
84 #define PICOPAM_EXCLAMATIVE   2
85 
86 #define PICOPAM_T   0
87 #define PICOPAM_P   1
88 #define PICOPAM_p   2
89 #define PICOPAM_Y   3
90 
91 #if 1
92 #define PAM_PHR2_WITH_PR1 1 /*deal with PHR2 boundaries as with PHR1*/
93 #else
94 #define PAM_PHR2_WITH_PR3 1 /*deal with PHR2 boundaries as with PHR3*/
95 #endif
96 
97 #define PICOPAM_DONT_CARE_VALUE  250 /*don't care value for tree printout    */
98 #define PICOPAM_DONT_CARE_VAL    10  /*don't care value for tree feeding     */
99 #define PICOPAM_PH_DONT_CARE_VAL 7   /*don't care value for tree feeding (phonetic)*/
100 
101 #define PICOPAM_MAX_STATES_PER_PHONE 5 /*number of states per phone    */
102 #define PICOPAM_STATE_SIZE_IN_ITEM   6 /*size of a state in frame item */
103 #define PICOPAM_FRAME_ITEM_SIZE      4+PICOPAM_MAX_STATES_PER_PHONE*PICOPAM_STATE_SIZE_IN_ITEM
104 
105 #define PICOPAM_DIR_FORW 0 /*forward adapter processing*/
106 #define PICOPAM_DIR_BACK 1 /*backward adapter processing*/
107 #define PICOPAM_DIR_SIL  2 /*final silence attributes*/
108 
109 #define PICOPAM_SYLL_PAUSE  0 /*syllable but containing a pause phone*/
110 #define PICOPAM_SYLL_SYLL   1 /*a real syllable with phonemes*/
111 
112 #define PICOPAM_EVENT_P_BOUND 0 /*primary boundary*/
113 #define PICOPAM_EVENT_S_BOUND 1 /*secondary boundary*/
114 #define PICOPAM_EVENT_W_BOUND 3 /*word boundary*/
115 #define PICOPAM_EVENT_SYLL    4 /*syllable*/
116 
117 /* ----- CONSTANTS FOR BREAK COMMAND SUPPORT ----- */
118 #define PICOPAM_PWIDX_SBEG 0
119 #define PICOPAM_PWIDX_PHR1 1
120 #define PICOPAM_PWIDX_PHR2 2
121 #define PICOPAM_PWIDX_SEND 3
122 #define PICOPAM_PWIDX_DEFA 4
123 #define PICOPAM_PWIDX_SIZE 5
124 
125 /*----------------------------------------------------------------*/
126 /*structure related to the feature vectors for feeding the trees  */
127 /*NOTE : the same data structure is used to manage the syllables  */
128 /*       Using the first 8 fields for marking the boundaries      */
129 /*       and using the last 4 bytes as follows                    */
130 /*     byte 61 : 1st attached non PAM item id(0=no item attached) */
131 /*               in the "sSyllItemOffs" data structure            */
132 /*     byte 62 : last attached non PAM item id(0=no item attached)*/
133 /*               in the "sSyllItemOffs" data structure            */
134 /*     byte 63..64 : offset of the start of the syllable in       */
135 /*                   the "sPhIds" data structure                  */
136 typedef struct
137 {
138     picopal_uint8 phoneV[PICOPAM_VECT_SIZE];
139 } sFtVect, *pSftVect;
140 
141 /*----------------------------------------------------------
142  Name    :   pam_subobj
143  Function:   subobject definition for the pam processing
144  Shortcut:   pam
145  ---------------------------------------------------------*/
146 typedef struct pam_subobj
147 {
148     /*----------------------PU voice management------------------------------*/
149     /* picorsrc_Voice voice; */
150     /*----------------------PU state management------------------------------*/
151     picoos_uint8 procState; /* where to take up work at next processing step */
152     picoos_uint8 retState; /* where to go back from feed state at next p.s. */
153     picoos_uint8 needMoreInput; /* more data necessary to start processing   */
154     /*----------------------PU input management------------------------------*/
155     picoos_uint8 inBuf[PICOPAM_IN_BUFF_SIZE]; /* internal input buffer */
156     picoos_uint16 inBufSize; /* actually allocated size */
157     picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/
158     /*----------------------PU output management-----------------------------*/
159     picoos_uint8 outBuf[PICOPAM_OUT_PAM_SIZE]; /* internal output buffer */
160     picoos_uint16 outBufSize; /* actually allocated size */
161     picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/
162     /*---------------------- adapter working buffers    --------------------*/
163     picoos_uint8 *sPhFeats; /*feature vector for a single phone      */
164     sFtVect *sSyllFeats; /*Syllable feature vector set for the
165      full sentence                          */
166     picoos_uint8 *sPhIds; /*phone ids for the full sentence        */
167     picoos_uint8 *sSyllItems; /*items attached to the syllable         */
168     picoos_int16 *sSyllItemOffs;/*offset of items attached to the syllable*/
169     /*---------------------- adapter general variables ---------------------*/
170     picoos_int16 nTotalPhonemes; /*number of phonemes in the sentence*/
171     picoos_int16 nCurrPhoneme; /*current phoneme in the sentence   */
172     picoos_int16 nSyllPhoneme; /*current phoneme in the syllable   */
173     picoos_int16 nCurrSyllable; /*current syllable in the sentence  */
174     picoos_int16 nTotalSyllables; /*number of syllables in the sentence -> J1*/
175     picoos_uint8 nLastAttachedItemId;/*last attached item id*/
176     picoos_uint8 nCurrAttachedItem; /*current attached item*/
177     picoos_int16 nAttachedItemsSize; /*total size of the attached items*/
178     picoos_uint8 sType; /*Sentence type*/
179     picoos_uint8 pType; /*Phrase type*/
180     picoos_single pMod; /*pitch modifier*/
181     picoos_single dMod; /*Duration modifier*/
182     picoos_single dRest; /*Duration modifier rest*/
183     /*---------------------- adapter specific component variables ----------*/
184     picoos_uint8 a3_overall_syllable; /* A3 */
185     picoos_uint8 a3_primary_phrase_syllable;
186     picoos_uint8 b4_b5_syllable; /* B4,B5 */
187     picoos_uint8 b6_b7_syllable; /* B6,B7 */
188     picoos_uint8 b6_b7_state;
189     picoos_uint8 b8_b9_stressed_syllable; /* B8,B9 */
190     picoos_uint8 b10_b11_accented_syllable; /* B10,B11 */
191     picoos_uint8 b12_b13_syllable; /* B12,B13 */
192     picoos_uint8 b12_b13_state;
193     picoos_uint8 b14_b15_syllable; /* B14,B15 */
194     picoos_uint8 b14_b15_state;
195     picoos_uint8 b17_b19_syllable; /* B17,B19 */
196     picoos_uint8 b17_b19_state;
197     picoos_uint8 b18_b20_b21_syllable; /* B18,B20,B21 */
198     picoos_uint8 b18_b20_b21_state;
199     picoos_uint8 c3_overall_syllable; /* C3 */
200     picoos_uint8 c3_primary_phrase_syllable;
201     picoos_uint8 d2_syllable_in_word; /* D2 */
202     picoos_uint8 d2_prev_syllable_in_word;
203     picoos_uint8 d2_current_primary_phrase_word;
204     picoos_int8 e1_syllable_word_start; /* E1 */
205     picoos_int8 e1_syllable_word_end;
206     picoos_uint8 e1_content;
207     picoos_int8 e2_syllable_word_start; /* E2 */
208     picoos_int8 e2_syllable_word_end;
209     picoos_uint8 e3_e4_word; /* E3,E4 */
210     picoos_uint8 e3_e4_state;
211     picoos_uint8 e5_e6_content_word; /* E5,E6 */
212     picoos_uint8 e5_e6_content;
213     picoos_uint8 e7_e8_word; /* E7,E8 */
214     picoos_uint8 e7_e8_content;
215     picoos_uint8 e7_e8_state;
216     picoos_uint8 e9_e11_word; /* E9,E11 */
217     picoos_uint8 e9_e11_saw_word;
218     picoos_uint8 e9_e11_state;
219     picoos_uint8 e10_e12_e13_word; /* E10,E12,E13 */
220     picoos_uint8 e10_e12_e13_state;
221     picoos_uint8 e10_e12_e13_saw_word;
222     picoos_uint8 f2_overall_word; /* F2 */
223     picoos_uint8 f2_word_syllable;
224     picoos_uint8 f2_next_word_syllable;
225     picoos_uint8 f2_current_primary_phrase_word;
226     picoos_int8 g1_current_secondary_phrase_syllable; /*G1 */
227     picoos_int8 g1_current_syllable;
228     picoos_int8 g2_current_secondary_phrase_word; /*G2 */
229     picoos_int8 g2_current_word;
230     picoos_uint8 h1_current_secondary_phrase_syll; /*H1 */
231     picoos_uint8 h2_current_secondary_phrase_word; /*H2 */
232     picoos_uint8 h3_h4_current_secondary_phrase_word; /*H3,H4 */
233     picoos_uint8 h5_current_phrase_type; /*H5 */
234 
235     picoos_uint8 h5_syllable; /* H5 */
236     picoos_uint8 h5_state;
237 
238     picoos_uint8 i1_secondary_phrase_syllable; /*I1 */
239     picoos_uint8 i1_next_secondary_phrase_syllable;
240     picoos_uint8 i2_secondary_phrase_word; /*I2 */
241     picoos_uint8 i2_next_secondary_phrase_word;
242     picoos_uint8 j1_utterance_syllable; /*J1 */
243     picoos_uint8 j2_utterance_word; /*J2 */
244     picoos_uint8 j3_utterance_sec_phrases; /*J3 */
245     /*---------------------- constant data -------------------*/
246     picoos_uint16 sil_weights[PICOPAM_PWIDX_SIZE][PICOPAM_MAX_STATES_PER_PHONE];
247     /*---------------------- LINGWARE related data -------------------*/
248     picokdt_DtPAM dtdur; /* dtdur knowledge base */
249     picokdt_DtPAM dtlfz[PICOPAM_DT_NRLFZ]; /* dtlfz knowledge bases */
250     picokdt_DtPAM dtmgc[PICOPAM_DT_NRMGC]; /* dtmgc knowledge bases */
251     /*---------------------- Pdfs related data -------------------*/
252     picokpdf_PdfDUR pdfdur; /* pdfdur knowledge base */
253     picokpdf_PdfMUL pdflfz; /* pdflfz knowledge base */
254     /*---------------------- Tree traversal related data -------------------*/
255     picoos_uint16 durIndex;
256     picoos_uint8 numFramesState[PICOPAM_DT_NRLFZ];
257     picoos_uint16 lf0Index[PICOPAM_DT_NRLFZ];
258     picoos_uint16 mgcIndex[PICOPAM_DT_NRMGC];
259     /*---------------------- temps for updating the feature vector ---------*/
260     picoos_uint16 phonDur;
261     picoos_single phonF0[PICOPAM_DT_NRLFZ];
262     /*---------------------- Phones related data  -------------------*/
263     picoktab_Phones tabphones;
264 } pam_subobj_t;
265 
266 
267 /* ----- CONSTANTS FOR FEATURE VECTOR BUILDING (NOT PREFIXED WITH "PICOPAM_" FOR BREVITY) ----- */
268 #define  P1  0              /*field 1 of the input vector*/
269 #define  P2  1
270 #define  P3  2
271 #define  P4  3
272 #define  P5  4
273 #define  P6  5
274 #define  P7  6
275 #define  bnd 6              /*boundary type item associated to the syllable = P7 */
276 #define  P8  7
277 #define  A3  8
278 #define  B1  9
279 #define  B2  10
280 #define  B3  11
281 #define  B4  12
282 #define  B5  13
283 #define  B6  14
284 #define  B7  15
285 #define  B8  16
286 #define  B9  17
287 #define  B10 18
288 #define  B11 19
289 #define  B12 20
290 #define  B13 21
291 #define  B14 22
292 #define  B15 23
293 #define  B16 24
294 #define  B17 25
295 #define  B18 26
296 #define  B19 27
297 #define  B20 28
298 #define  B21 29
299 #define  C3  30
300 #define  D2  31
301 #define  E1  32
302 #define  E2  33
303 #define  E3  34
304 #define  E4  35
305 #define  E5  36
306 #define  E6  37
307 #define  E7  38
308 #define  E8  39
309 #define  E9  40
310 #define  E10 41
311 #define  E11 42
312 #define  E12 43
313 #define  E13 44
314 #define  F2  45
315 #define  G1  46
316 #define  G2  47
317 #define  H1  48
318 #define  H2  49
319 #define  H3  50
320 #define  H4  51
321 #define  H5  52
322 #define  I1  53
323 #define  I2  54
324 #define  J1  55
325 #define  J2  56
326 #define  J3  57
327 #define  DUR 58             /*duration component*/
328 #define  F0  59             /*F0 component*/
329 #define  ITM 60             /*Item Offset into sSyllItems item list*/
330 #define  itm 61             /*second byte of the Item Offset */
331 #define  FID 62             /*Phoneme offset in the sPhIds phoneme list*/
332 #define  fid 63             /*second byte of the Phoneme offset */
333 #define  Min 64             /*offset to min syllable duration (uint 16,pauses)*/
334 #define  Max 66             /*offset to max syllable duration (uint 16,pauses)*/
335 /* -------------------------------------------------------------------
336  PAM feature vector indices position changes,
337   ------------------------------------------------------------------- */
338 #define  T_B1  8
339 #define  T_B2  9
340 #define  T_B3  10
341 #define  T_B4  11
342 #define  T_B5  12
343 #define  T_B6  13
344 #define  T_B7  14
345 #define  T_B8  15
346 #define  T_B9  16
347 #define  T_B10 17
348 #define  T_B11 18
349 #define  T_B12 19
350 #define  T_B13 20
351 #define  T_B14 21
352 #define  T_B15 22
353 #define  T_B16 23
354 #define  T_B17 24
355 #define  T_B18 25
356 #define  T_B19 26
357 #define  T_B20 27
358 #define  T_B21 28
359 #define  T_E1  29
360 #define  T_E2  30
361 #define  T_E3  31
362 #define  T_E4  32
363 #define  T_E5  33
364 #define  T_E6  34
365 #define  T_E7  35
366 #define  T_E8  36
367 #define  T_E9  37
368 #define  T_E10 38
369 #define  T_E11 39
370 #define  T_E12 40
371 #define  T_E13 41
372 #define  T_A3  42
373 #define  T_C3  43
374 #define  T_D2  44
375 #define  T_F2  45
376 #define  T_G1  46
377 #define  T_I1  47
378 #define  T_G2  48
379 #define  T_I2  49
380 #define  T_H1  50
381 #define  T_H2  51
382 #define  T_H3  52
383 #define  T_H4  53
384 #define  T_H5  54
385 
386 /*------------------------------------------------------------------
387  Service routines :
388  ------------------------------------------------------------------*/
389 static pico_status_t pam_initialize(register picodata_ProcessingUnit this, picoos_int32 resetMode);
390 static pico_status_t pam_terminate(register picodata_ProcessingUnit this);
391 static pico_status_t pam_allocate(picoos_MemoryManager mm, pam_subobj_t *pam);
392 static void pam_deallocate(picoos_MemoryManager mm, pam_subobj_t *pam);
393 static pico_status_t pam_subobj_deallocate(register picodata_ProcessingUnit this,
394         picoos_MemoryManager mm);
395 /*------------------------------------------------------------------
396  Processing routines :
397  ------------------------------------------------------------------*/
398 static picodata_step_result_t pam_step(register picodata_ProcessingUnit this,
399         picoos_int16 mode, picoos_uint16 * numBytesOutput);
400 static pico_status_t pam_deal_with(const picoos_uint8 *item);
401 /*Utility*/
402 static picoos_uint8 pam_get_vowel_name(register picodata_ProcessingUnit this,
403         picoos_uint8 *item, picoos_uint8 *pos);
404 static picoos_uint8 pam_get_pause_id(register picodata_ProcessingUnit this);
405 
406 static picoos_uint8 pam_map_sentence_type(picoos_uint8 iteminfo1,
407         picoos_uint8 iteminfo2);
408 static picoos_uint8 pam_map_phrase_type(picoos_uint8 iteminfo1,
409         picoos_uint8 iteminfo2);
410 
411 /*Adapter*/
412 static pico_status_t pam_reset_processors(register picodata_ProcessingUnit this);
413 static pico_status_t pam_reset_processors_back(
414         register picodata_ProcessingUnit this);
415 static pico_status_t pam_create_syllable(register picodata_ProcessingUnit this,
416         picoos_uint8 syllType, picoos_uint8 *sContent, picoos_uint8 sentType,
417         picoos_uint8 phType, picoos_uint8 uBoundType, picoos_uint16 uMin,
418         picoos_uint16 uMax);
419 static pico_status_t pam_process_event_feature(
420         register picodata_ProcessingUnit this, picoos_uint8 nFeat,
421         picoos_uint8 event_type, picoos_uint8 direction);
422 static pico_status_t pam_process_event(register picodata_ProcessingUnit this,
423         picoos_uint8 event_type, picoos_uint8 direction);
424 static pico_status_t pam_adapter_forward_step(
425         register picodata_ProcessingUnit this, picoos_uint8 *itemBase);
426 static pico_status_t pam_adapter_backward_step(
427         register picodata_ProcessingUnit this);
428 static pico_status_t pam_do_pause(register picodata_ProcessingUnit this);
429 static pico_status_t pam_adapter_do_pauses(register picodata_ProcessingUnit this);
430 /*-------------- tree traversal ---------------------------------------*/
431 static pico_status_t pam_expand_vector(register picodata_ProcessingUnit this);
432 static picoos_uint8 pam_do_tree(register picodata_ProcessingUnit this,
433         const picokdt_DtPAM dtpam, const picoos_uint8 *invec,
434         const picoos_uint8 inveclen, picokdt_classify_result_t *dtres);
435 static pico_status_t pam_get_f0(register picodata_ProcessingUnit this,
436         picoos_uint16 *lf0Index, picoos_uint8 nState, picoos_single *phonF0);
437 static pico_status_t pam_get_duration(register picodata_ProcessingUnit this,
438         picoos_uint16 durIndex, picoos_uint16 *phonDur,
439         picoos_uint8 *numFramesState);
440 static pico_status_t pam_update_vector(register picodata_ProcessingUnit this);
441 /*-------------- FINAL ITEM FEEDING -----------------------------------------*/
442 static pico_status_t pam_put_item(register picodata_ProcessingUnit this,
443                 picoos_uint8 *outBuff, picoos_uint16 outWritePos,
444                 picoos_uint8 *bytesWr);
445 
446 static pico_status_t pam_put_term(picoos_uint8 *outBuff,
447         picoos_uint16 outWritePos, picoos_uint8 *bytesWr);
448 
449 static pico_status_t is_pam_command(const picoos_uint8 *qItem);
450 
451 static void get_default_boundary_limit(picoos_uint8 uBoundType,
452         picoos_uint16 *uMinDur, picoos_uint16 *uMaxDur);
453 
454 /* -------------------------------------------------------------
455  * Pico System functions
456  * -------------------------------------------------------------
457  */
458 
459 /**
460  * allocation for PAM memory on pam PU
461  * @param    mm : handle to engine memory manager
462  * @param    pam : handle to a pam struct
463  * @return  PICO_OK : allocation successful
464  * @return    PICO_ERR_OTHER : allocation errors
465  * @callgraph
466  * @callergraph
467  */
pam_allocate(picoos_MemoryManager mm,pam_subobj_t * pam)468 static pico_status_t pam_allocate(picoos_MemoryManager mm, pam_subobj_t *pam)
469 {
470     picoos_uint8 *data;
471     picoos_int16 *dataI;
472 
473     pam->sSyllFeats = NULL;
474     pam->sPhIds = NULL;
475     pam->sPhFeats = NULL;
476     pam->sSyllItems = NULL;
477     pam->sSyllItemOffs = NULL;
478 
479     /*-----------------------------------------------------------------
480      * PAM Local buffers ALLOCATION
481      ------------------------------------------------------------------*/
482     /*PAM Local buffers*/
483     data = (picopal_uint8 *) picoos_allocate(mm, sizeof(sFtVect)
484             * PICOPAM_MAX_SYLL_PER_SENT);
485     if (data == NULL)
486         return PICO_ERR_OTHER;
487     pam->sSyllFeats = (sFtVect*) data;
488 
489     data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8)
490             * PICOPAM_MAX_PH_PER_SENT);
491     if (data == NULL) {
492         pam_deallocate(mm, pam);
493         return PICO_ERR_OTHER;
494     }
495     pam->sPhIds = (picopal_uint8*) data;
496 
497     data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8)
498             * PICOPAM_VECT_SIZE);
499     if (data == NULL) {
500         pam_deallocate(mm, pam);
501         return PICO_ERR_OTHER;
502     }
503     pam->sPhFeats = (picopal_uint8*) data;
504 
505     data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8)
506             * PICOPAM_MAX_ITEM_SIZE_PER_SENT);
507     if (data == NULL) {
508         pam_deallocate(mm, pam);
509         return PICO_ERR_OTHER;
510     }
511     pam->sSyllItems = (picopal_uint8*) data;
512 
513     dataI = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16)
514             * PICOPAM_MAX_ITEM_PER_SENT);
515     if (data == NULL) {
516         pam_deallocate(mm, pam);
517         return PICO_ERR_OTHER;
518     }
519     pam->sSyllItemOffs = (picoos_int16*) dataI;
520 
521     return PICO_OK;
522 }/*pam_allocate*/
523 
524 /**
525  * frees allocation for DSP memory on PAM PU
526  * @param    mm : memory manager
527  * @param    pam : pam PU internal sub-object
528  * @return   void
529  * @remarks  modified and inserted in sub obj removal PP 15.09.08
530  * @callgraph
531  * @callergraph
532  */
pam_deallocate(picoos_MemoryManager mm,pam_subobj_t * pam)533 static void pam_deallocate(picoos_MemoryManager mm, pam_subobj_t *pam)
534 {
535     /*-----------------------------------------------------------------
536      * Memory de-allocations
537      * ------------------------------------------------------------------*/
538     if (pam->sSyllFeats != NULL)
539         picoos_deallocate(mm, (void *) &pam->sSyllFeats);
540     if (pam->sPhIds != NULL)
541         picoos_deallocate(mm, (void *) &pam->sPhIds);
542     if (pam->sPhFeats != NULL)
543         picoos_deallocate(mm, (void *) &pam->sPhFeats);
544     if (pam->sSyllItems != NULL)
545         picoos_deallocate(mm, (void *) &pam->sSyllItems);
546     if (pam->sSyllItemOffs != NULL)
547         picoos_deallocate(mm, (void *) &pam->sSyllItemOffs);
548 
549 }/*pam_deallocate*/
550 
551 /**
552  * initialization of a pam PU
553  * @param    this : handle to a PU struct
554  * @return     PICO_OK : init OK
555  * @return    PICO_ERR_OTHER : error on getting pkbs addresses
556  * @callgraph
557  * @callergraph
558  */
pam_initialize(register picodata_ProcessingUnit this,picoos_int32 resetMode)559 static pico_status_t pam_initialize(register picodata_ProcessingUnit this, picoos_int32 resetMode)
560 {
561     pico_status_t nI, nJ;
562     pam_subobj_t *pam;
563 
564     if (NULL == this || NULL == this->subObj) {
565         return PICO_ERR_OTHER;
566     }
567     pam = (pam_subobj_t *) this->subObj;
568     pam->inBufSize = PICOPAM_IN_BUFF_SIZE;
569     pam->outBufSize = PICOPAM_OUT_PAM_SIZE;
570     pam->inReadPos = 0;
571     pam->inWritePos = 0;
572     pam->outReadPos = 0;
573     pam->outWritePos = 0;
574     pam->needMoreInput = 0;
575     pam->procState = 0;
576 
577     /*-----------------------------------------------------------------
578      * MANAGE INTERNAL INITIALIZATION
579      ------------------------------------------------------------------*/
580     /*init the syllable structure*/
581     for (nI = 0; nI < PICOPAM_MAX_SYLL_PER_SENT; nI++)
582         for (nJ = 0; nJ < PICOPAM_VECT_SIZE; nJ++)
583             pam->sSyllFeats[nI].phoneV[nJ] = 0;
584 
585     for (nI = 0; nI < PICOPAM_MAX_PH_PER_SENT; nI++)
586         pam->sPhIds[nI] = 0;
587 
588     for (nI = 0; nI < PICOPAM_VECT_SIZE; nI++)
589         pam->sPhFeats[nI] = 0;
590 
591     for (nI = 0; nI < PICOPAM_MAX_ITEM_SIZE_PER_SENT; nI++)
592         pam->sSyllItems[nI] = 0;
593 
594     for (nI = 0; nI < PICOPAM_MAX_ITEM_PER_SENT; nI++)
595         pam->sSyllItemOffs[nI] = 0;
596 
597     /*Other variables*/
598     pam_reset_processors(this);
599     pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0;
600     pam->nAttachedItemsSize = 0;
601 
602     if (resetMode == PICO_RESET_SOFT) {
603         /*following initializations needed only at startup or after a full reset*/
604         return PICO_OK;
605     }
606 
607     /*pitch and duration modifiers*/
608     pam->pMod = 1.0f;
609     pam->dMod = 1.0f;
610     pam->dRest = 0.0f;
611 
612 
613     /* constant tables */
614     {
615         picoos_uint8 i, j;
616         picoos_uint16 tmp_weights[PICOPAM_PWIDX_SIZE][PICOPAM_MAX_STATES_PER_PHONE] = {
617         {10, 10, 10, 10, 1 }, /*SBEG*/
618         { 1, 4, 8, 4, 1 }, /*PHR1*/
619         { 1, 4, 8, 4, 1 }, /*PHR2*/
620         { 1, 10, 10, 10, 10 },/*SEND*/
621         { 1, 1, 1, 1, 1 } /*DEFAULT*/
622         };
623         for (i = 0; i < PICOPAM_PWIDX_SIZE; i++) {
624             for (j = 0; j < PICOPAM_PWIDX_SIZE; j++) {
625                 pam->sil_weights[j][j] = tmp_weights[i][j];
626             }
627         }
628     }
629 
630 
631 /*-----------------------------------------------------------------
632      * MANAGE LINGWARE INITIALIZATION IF NEEDED
633      ------------------------------------------------------------------*/
634     /* kb dtdur */
635     pam->dtdur = picokdt_getDtPAM(this->voice->kbArray[PICOKNOW_KBID_DT_DUR]);
636     if (pam->dtdur == NULL) {
637         picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL,
638                 NULL);
639         return PICO_ERR_OTHER;
640     }PICODBG_DEBUG(("got dtdur"));
641 
642     /* kb dtlfz* */
643     pam->dtlfz[0] = picokdt_getDtPAM(
644             this->voice->kbArray[PICOKNOW_KBID_DT_LFZ1]);
645     pam->dtlfz[1] = picokdt_getDtPAM(
646             this->voice->kbArray[PICOKNOW_KBID_DT_LFZ2]);
647     pam->dtlfz[2] = picokdt_getDtPAM(
648             this->voice->kbArray[PICOKNOW_KBID_DT_LFZ3]);
649     pam->dtlfz[3] = picokdt_getDtPAM(
650             this->voice->kbArray[PICOKNOW_KBID_DT_LFZ4]);
651     pam->dtlfz[4] = picokdt_getDtPAM(
652             this->voice->kbArray[PICOKNOW_KBID_DT_LFZ5]);
653     for (nI = 0; nI < PICOPAM_DT_NRLFZ; nI++) {
654         if (pam->dtlfz[nI] == NULL) {
655             picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING,
656                     NULL, NULL);
657             return PICO_ERR_OTHER;
658         }PICODBG_DEBUG(("got dtlfz%d", nI+1));
659     }
660 
661     /* kb dtmgc* */
662     pam->dtmgc[0] = picokdt_getDtPAM(
663             this->voice->kbArray[PICOKNOW_KBID_DT_MGC1]);
664     pam->dtmgc[1] = picokdt_getDtPAM(
665             this->voice->kbArray[PICOKNOW_KBID_DT_MGC2]);
666     pam->dtmgc[2] = picokdt_getDtPAM(
667             this->voice->kbArray[PICOKNOW_KBID_DT_MGC3]);
668     pam->dtmgc[3] = picokdt_getDtPAM(
669             this->voice->kbArray[PICOKNOW_KBID_DT_MGC4]);
670     pam->dtmgc[4] = picokdt_getDtPAM(
671             this->voice->kbArray[PICOKNOW_KBID_DT_MGC5]);
672     for (nI = 0; nI < PICOPAM_DT_NRMGC; nI++) {
673         if (pam->dtmgc[nI] == NULL) {
674             picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING,
675                     NULL, NULL);
676             return PICO_ERR_OTHER;
677         }PICODBG_DEBUG(("got dtmgc%d", nI+1));
678     }
679 
680     /* kb pdfdur* */
681     pam->pdfdur = picokpdf_getPdfDUR(
682             this->voice->kbArray[PICOKNOW_KBID_PDF_DUR]);
683     if (pam->pdfdur == NULL) {
684         picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL,
685                 NULL);
686         return PICO_ERR_OTHER;
687     }PICODBG_DEBUG(("got pdfdur"));
688 
689     /* kb pdflfz* */
690     pam->pdflfz = picokpdf_getPdfMUL(
691             this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]);
692     if (pam->pdflfz == NULL) {
693         picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL,
694                 NULL);
695         return PICO_ERR_OTHER;
696     }PICODBG_DEBUG(("got pdflfz"));
697 
698     /* kb tabphones */
699     pam->tabphones = picoktab_getPhones(
700             this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]);
701     if (pam->tabphones == NULL) {
702         picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL,
703                 NULL);
704         return PICO_ERR_OTHER;
705     }PICODBG_DEBUG(("got tabphones"));
706 
707     return PICO_OK;
708 }/*pam_initialize*/
709 
710 /**
711  * termination of a pam PU
712  * @param    this : handle to a pam PU struct
713  * @return PICO_OK
714  * @callgraph
715  * @callergraph
716  */
pam_terminate(register picodata_ProcessingUnit this)717 static pico_status_t pam_terminate(register picodata_ProcessingUnit this)
718 {
719 
720     pam_subobj_t *pam;
721 
722     if (NULL == this || NULL == this->subObj) {
723         return PICO_ERR_OTHER;
724     }
725     pam = (pam_subobj_t *) this->subObj;
726 
727     return PICO_OK;
728 }/*pam_terminate*/
729 
730 /**
731  * deallocaton of a pam PU
732  * @param    this : handle to a pam PU struct
733  * @param    mm : engine memory manager
734  * @return  PICO_OK
735  * @callgraph
736  * @callergraph
737  */
pam_subobj_deallocate(register picodata_ProcessingUnit this,picoos_MemoryManager mm)738 static pico_status_t pam_subobj_deallocate(register picodata_ProcessingUnit this,
739         picoos_MemoryManager mm)
740 {
741 
742     pam_subobj_t* pam;
743 
744     if (NULL != this) {
745         pam = (pam_subobj_t *) this->subObj;
746         mm = mm; /* avoid warning "var not used in this function"*/
747         /*-----------------------------------------------------------------
748          * Memory de-allocations
749          * ------------------------------------------------------------------*/
750         if (pam->sSyllFeats != NULL) {
751             picoos_deallocate(this->common->mm, (void *) &pam->sSyllFeats);
752         }
753         if (pam->sPhIds != NULL) {
754             picoos_deallocate(this->common->mm, (void *) &pam->sPhIds);
755         }
756         if (pam->sPhFeats != NULL) {
757             picoos_deallocate(this->common->mm, (void *) &pam->sPhFeats);
758         }
759         if (pam->sSyllItems != NULL) {
760             picoos_deallocate(this->common->mm, (void *) &pam->sSyllItems);
761         }
762         if (pam->sSyllItemOffs != NULL) {
763             picoos_deallocate(this->common->mm, (void *) &pam->sSyllItemOffs);
764         }
765         picoos_deallocate(this->common->mm, (void *) &this->subObj);
766     }
767 
768     return PICO_OK;
769 }/*pam_subobj_deallocate*/
770 
771 /**
772  * creates a new pam processing unit
773  * @param    mm    : engine memory manager
774  * @param    common : engine common object pointer
775  * @param    cbIn : pointer to input buffer
776  * @param    cbOut : pointer to output buffer
777  * @param    voice : pointer to voice structure
778  * @return this : pam PU handle if success
779  * @return    NULL : if error
780  * @callgraph
781  * @callergraph
782  */
picopam_newPamUnit(picoos_MemoryManager mm,picoos_Common common,picodata_CharBuffer cbIn,picodata_CharBuffer cbOut,picorsrc_Voice voice)783 picodata_ProcessingUnit picopam_newPamUnit(picoos_MemoryManager mm,
784         picoos_Common common, picodata_CharBuffer cbIn,
785         picodata_CharBuffer cbOut, picorsrc_Voice voice)
786 {
787 
788     register pam_subobj_t * pam;
789 
790     picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn,
791             cbOut, voice);
792     if (this == NULL) {
793         return NULL;
794     }
795     this->initialize = pam_initialize;
796 
797     PICODBG_DEBUG(("picotok_newPamUnit -- set this->step to pam_step"));
798 
799     this->step = pam_step;
800     this->terminate = pam_terminate;
801     this->subDeallocate = pam_subobj_deallocate;
802     this->subObj = picoos_allocate(mm, sizeof(pam_subobj_t));
803     if (this->subObj == NULL) {
804         PICODBG_ERROR(("Error in Pam Object allocation"));
805         picoos_deallocate(mm, (void*) &this);
806         return NULL;
807     };
808 
809     /*-----------------------------------------------------------------
810      * Allocate internal memory for PAM (only at PU creation time)
811      * ------------------------------------------------------------------*/
812     pam = (pam_subobj_t *) this->subObj;
813     if (PICO_OK != pam_allocate(mm, pam)) {
814         PICODBG_ERROR(("Error in Pam buffers Allocation"));
815         picoos_deallocate(mm, (void *) &this->subObj);
816         picoos_deallocate(mm, (void *) &this);
817         return NULL;
818     }
819 
820     /*-----------------------------------------------------------------
821      * Initialize memory for PAM (this may be re-used elsewhere, e.g.Reset)
822      * ------------------------------------------------------------------*/
823     if (PICO_OK != pam_initialize(this, PICO_RESET_FULL)) {
824         PICODBG_ERROR(("problem initializing the pam sub-object"));
825     }
826     return this;
827 }/*picopam_newPamUnit*/
828 
829 /*-------------------------------------------------------------------------------
830  PROCESSING AND INTERNAL FUNCTIONS
831  --------------------------------------------------------------------------------*/
832 
833 /**
834  * initializes default duration limits for boundary items
835  * @param    uBoundType : type of input boundary type
836  * @param    *uMinDur, *uMaxDur : addresses of values to initialize
837  * @return  void
838  * @remarks    so far initializes to 0 both values; this will leave the values given by tree prediction
839  * @callgraph
840  * @callergraph
841  */
get_default_boundary_limit(picoos_uint8 uBoundType,picoos_uint16 * uMinDur,picoos_uint16 * uMaxDur)842 static void get_default_boundary_limit(picoos_uint8 uBoundType,
843         picoos_uint16 *uMinDur, picoos_uint16 *uMaxDur)
844 {
845     switch (uBoundType) {
846         case PICODATA_ITEMINFO1_BOUND_SBEG:
847             *uMinDur = 0;
848             *uMaxDur = 20;
849             break;
850         case PICODATA_ITEMINFO1_BOUND_SEND:
851             *uMinDur = 550;
852             *uMaxDur = 650;
853             break;
854         case PICODATA_ITEMINFO1_BOUND_TERM:
855             *uMinDur = 0;
856             *uMaxDur = 0;
857             break;
858         case PICODATA_ITEMINFO1_BOUND_PHR0:
859             *uMinDur = 0;
860             *uMaxDur = 0;
861             break;
862         case PICODATA_ITEMINFO1_BOUND_PHR1:
863             *uMinDur = 275;
864             *uMaxDur = 325;
865             break;
866         case PICODATA_ITEMINFO1_BOUND_PHR2:
867             *uMinDur = 4;
868             *uMaxDur = 60;
869             break;
870         case PICODATA_ITEMINFO1_BOUND_PHR3:
871             *uMinDur = 0;
872             *uMaxDur = 0;
873             break;
874         default:
875             break;
876     }
877 
878 }/*get_default_boundary_limit*/
879 
880 /**
881  * checks if "neededSize" is available on "nCurrPhoneme"
882  * @param    pam : pam subobj
883  * @param    neededSize : the requested size
884  * @return    PICO_OK : size is available
885  * @return    !=PICO_OK : size not available
886  * @callgraph
887  * @callergraph
888  */
check_phones_size(pam_subobj_t * pam,picoos_int16 neededSize)889 static pico_status_t check_phones_size(pam_subobj_t *pam,
890         picoos_int16 neededSize)
891 {
892     if ((pam->nCurrPhoneme + neededSize) > PICOPAM_MAX_PH_PER_SENT - 1) {
893         return PICO_ERR_OTHER;
894     }
895     return PICO_OK;
896 }/*check_phones_size*/
897 
898 /**
899  * checks if neededSize is available on "nCurrSyllable"
900  * @param    pam : pam subobj
901  * @param    neededSize : the requested size
902  * @return    PICO_OK : size is available
903  * @return    !=PICO_OK : size not available
904  * @callgraph
905  * @callergraph
906  */
check_syllables_size(pam_subobj_t * pam,picoos_int16 neededSize)907 static pico_status_t check_syllables_size(pam_subobj_t *pam,
908         picoos_int16 neededSize)
909 {
910     if ((pam->nCurrSyllable + neededSize) > PICOPAM_MAX_SYLL_PER_SENT - 1) {
911         return PICO_ERR_OTHER;
912     }
913     return PICO_OK;
914 }/*check_syllables_size*/
915 
916 /**
917  * verifies that local storage has enough space to receive 1 item
918  * @param    this : pointer to current PU struct
919  * @param    item : pointer to current item head
920  * @return    TRUE : resource limits would be reached during processing of input item
921  * @return    FALSE : item could be processed normally
922  * @remarks item pointed to by *item should be already valid
923  * @callgraph
924  * @callergraph
925  */
pamCheckResourceLimits(register picodata_ProcessingUnit this,const picoos_uint8 * item)926 static pico_status_t pamCheckResourceLimits(
927         register picodata_ProcessingUnit this, const picoos_uint8 *item)
928 {
929     register pam_subobj_t * pam;
930     picodata_itemhead_t head;
931     pico_status_t sResult;
932     if (NULL == this || NULL == this->subObj) {
933         return PICODATA_PU_ERROR;
934     }
935     pam = (pam_subobj_t *) this->subObj;
936     sResult = TRUE; /*default : resource limits reached*/
937     head.type = item[0];
938     head.info1 = item[1];
939     head.info2 = item[2];
940     head.len = item[3];
941 
942     switch (head.type) {
943         /*commands that generate syllables/phonemes*/
944         case PICODATA_ITEM_SYLLPHON:
945             if (pam->nCurrSyllable >= PICOPAM_MAX_SYLL_PER_SENT - 2) {
946                 return sResult; /*no room for more syllables*/
947             }
948             if ((pam->nCurrPhoneme + head.len) >= PICOPAM_MAX_PH_PER_SENT - 2) {
949                 return sResult; /*no room for more phoneme*/
950             }
951             break;
952         case PICODATA_ITEM_BOUND:
953             if ((head.info1 == PICODATA_ITEMINFO1_BOUND_SBEG) || (head.info1
954                     == PICODATA_ITEMINFO1_BOUND_SEND) || (head.info1
955                     == PICODATA_ITEMINFO1_BOUND_TERM) || (head.info1
956                     == PICODATA_ITEMINFO1_BOUND_PHR1)
957 #ifdef PAM_PHR2_WITH_PR1
958                     || (head.info1 == PICODATA_ITEMINFO1_BOUND_PHR2)
959 #endif
960             ) {
961 
962                 if (pam->nCurrSyllable >= PICOPAM_MAX_SYLL_PER_SENT - 2) {
963                     return sResult; /*no room for more syllables*/
964                 }
965                 if ((pam->nCurrPhoneme + 1) >= PICOPAM_MAX_PH_PER_SENT - 2) {
966                     return sResult; /*no room for more phoneme*/
967                 }
968             }
969             break;
970 
971         default:
972             /*all other commands has to be queued*/
973             if ((pam->nAttachedItemsSize + head.len)
974                     >= PICOPAM_MAX_ITEM_SIZE_PER_SENT - 1) {
975                 return sResult; /*no room for more items*/
976             }
977             break;
978     }
979     return FALSE; /*no resource limits apply to current item*/
980 } /*pamCheckResourceLimits*/
981 
982 /**
983  * selects items to be sent to next PU immedately
984  * @param    this : pointer to current PU struct
985  * @param    item : pointer to current item head
986  * @return    TRUE : item should be passed on next PU NOW
987  * @return    FALSE : item should not be passed on next PU now but should be processed
988  * @remarks item pointed to by *item should be already valid
989  * @callgraph
990  * @callergraph
991  */
pam_check_immediate(register picodata_ProcessingUnit this,const picoos_uint8 * item)992 static pico_status_t pam_check_immediate(register picodata_ProcessingUnit this,
993         const picoos_uint8 *item)
994 {
995     register pam_subobj_t * pam;
996     if (NULL == this || NULL == this->subObj) {
997         return PICODATA_PU_ERROR;
998     }
999     pam = (pam_subobj_t *) this->subObj;
1000 
1001     if (pam->nCurrSyllable <= -1) {
1002         if (item[0] == PICODATA_ITEM_SYLLPHON)
1003             return FALSE;
1004         if ((item[0] == PICODATA_ITEM_BOUND) && (item[1]
1005                 == PICODATA_ITEMINFO1_BOUND_SBEG))
1006             return FALSE;
1007         if (is_pam_command((picoos_uint8 *) item) == TRUE)
1008             return FALSE;
1009         return TRUE; /*no need to process data : send it*/
1010     }
1011     return FALSE; /*syllable struct not void : do standard processing*/
1012 
1013 } /*pam_check_immediate*/
1014 
1015 /**
1016  * checks if the input item has to be queued in local storage for later resynch
1017  * @param    this : pointer to current PU struct
1018  * @param    item : pointer to current item head
1019  * @return    TRUE : item should be queued
1020  * @return    FALSE : item should not be queued
1021  * @remarks item pointed to by *item should be already valid
1022  * @callgraph
1023  * @callergraph
1024  */
pam_hastobe_queued(register picodata_ProcessingUnit this,const picoos_uint8 * item)1025 static pico_status_t pam_hastobe_queued(register picodata_ProcessingUnit this,
1026         const picoos_uint8 *item)
1027 {
1028     register pam_subobj_t * pam;
1029     picodata_itemhead_t head;
1030     if (NULL == this || NULL == this->subObj) {
1031         return PICODATA_PU_ERROR;
1032     }
1033     pam = (pam_subobj_t *) this->subObj;
1034     head.type = item[0];
1035     head.info1 = item[1];
1036 
1037     switch (head.type) {
1038         /*commands that generate syllables/phonemes*/
1039         case PICODATA_ITEM_SYLLPHON:
1040             return FALSE; /*no queue needed*/
1041             break;
1042         case PICODATA_ITEM_BOUND:
1043             if ((head.info1 == PICODATA_ITEMINFO1_BOUND_PHR3)
1044 #ifdef PAM_PHR2_WITH_PR3
1045                     ||(head.info1==PICODATA_ITEMINFO1_BOUND_PHR2)
1046 #endif
1047                     || (head.info1 == PICODATA_ITEMINFO1_BOUND_PHR0)) {
1048                 return FALSE; /*no queue needed*/
1049             }
1050             break;
1051 
1052         default:
1053             /*all other items has to be queued*/
1054             break;
1055     }
1056     return TRUE; /*item has to be queued*/
1057 } /*pam_hastobe_queued*/
1058 
1059 /**
1060  * queue item in local storage for later resynch
1061  * @param    this : pointer to current PU struct
1062  * @param    item : pointer to current item head
1063  * @return    TRUE : item queued
1064  * @return    FALSE : item not queued because of errors
1065  * @remarks item pointed to by *item should be already valid
1066  * @callgraph
1067  * @callergraph
1068  */
pam_queue(register picodata_ProcessingUnit this,const picoos_uint8 * item)1069 static pico_status_t pam_queue(register picodata_ProcessingUnit this,
1070         const picoos_uint8 *item)
1071 {
1072     register pam_subobj_t * pam;
1073     picodata_itemhead_t head;
1074     picoos_uint8 nI;
1075     pico_status_t sResult;
1076     if (NULL == this || NULL == this->subObj) {
1077         return PICODATA_PU_ERROR;
1078     }
1079     pam = (pam_subobj_t *) this->subObj;
1080     sResult = TRUE; /*default : item queued*/
1081     head.type = item[0];
1082     head.info1 = item[1];
1083     head.info2 = item[2];
1084     head.len = item[3];
1085 
1086     /*test condition on enough room to store current item in the "sSyllItems" area*/
1087     if ((pam->nAttachedItemsSize + head.len + sizeof(picodata_itemhead_t))
1088             >= PICOPAM_MAX_ITEM_SIZE_PER_SENT - 1) {
1089         return FALSE; /*resource limit reached*/
1090     }
1091     /*store current offset*/
1092     pam->sSyllItemOffs[pam->nLastAttachedItemId] = pam->nAttachedItemsSize;
1093     /*store the item to the "sSyllItems" area*/
1094     for (nI = 0; nI < (head.len + sizeof(picodata_itemhead_t)); nI++) {
1095         pam->sSyllItems[pam->nAttachedItemsSize + nI] = item[nI];
1096     }
1097     /*increment the attached items area*/
1098     pam->nAttachedItemsSize += nI;
1099 
1100     /*increment id*/
1101     pam->nLastAttachedItemId++;
1102     /*set start(if not initialized) and end ids of queued items in sSyllFeats*/
1103     if (pam->nCurrSyllable > -1) {
1104         /*normal case : the item is attached to current syllable*/
1105         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] == 0) {
1106             pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM]
1107                     = pam->nLastAttachedItemId;
1108         }
1109         pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]
1110                 = pam->nLastAttachedItemId;
1111     } else {
1112         /*special case : an item is requested to be queued even if no
1113          syllables has been assigned to the sentence structure :
1114          -->> use syll 0*/
1115         if (pam->sSyllFeats[0].phoneV[ITM] == 0) {
1116             pam->sSyllFeats[0].phoneV[ITM] = pam->nLastAttachedItemId;
1117         }
1118         pam->sSyllFeats[0].phoneV[itm] = pam->nLastAttachedItemId;
1119     }
1120     return TRUE; /*item queued successfully*/
1121 } /*pam_queue*/
1122 
1123 /**
1124  * selects items to be dealth with by the PU processing
1125  * @param    item : pointer to current item head
1126  * @return    TRUE : item should be processed
1127  * @return    FALSE : item should not be processed (maybe it ontains commands or items for other PUs)
1128  * @remarks item pointed to by *item should be already valid
1129  * @callgraph
1130  * @callergraph
1131  */
pam_deal_with(const picoos_uint8 * item)1132 static pico_status_t pam_deal_with(const picoos_uint8 *item)
1133 {
1134     picodata_itemhead_t head;
1135     pico_status_t sResult;
1136     sResult = FALSE;
1137     head.type = item[0];
1138     head.info1 = item[1];
1139     head.info2 = item[2];
1140     head.len = item[3];
1141     switch (head.type) {
1142         case PICODATA_ITEM_SYLLPHON:
1143         case PICODATA_ITEM_BOUND:
1144             sResult = TRUE;
1145             break;
1146         default:
1147             break;
1148     }
1149     return sResult;
1150 } /*pam_deal_with*/
1151 
1152 /**
1153  * returns true if more items has to be produced for current syllable
1154  * @param    this : Pam object pointer
1155  * @return    TRUE : item is to be produced
1156  * @return    FALSE : item is not to be produced
1157  * @remarks item pointed to by *item should be already valid
1158  * @callgraph
1159  * @callergraph
1160  */
pamHasToProcess(register picodata_ProcessingUnit this)1161 static picoos_uint8 pamHasToProcess(register picodata_ProcessingUnit this)
1162 {
1163     register pam_subobj_t * pam;
1164     picoos_uint8 nCond1, nCond2, nCond3;
1165 
1166     if (NULL == this || NULL == this->subObj) {
1167         return PICODATA_PU_ERROR;
1168     }
1169     pam = (pam_subobj_t *) this->subObj;
1170     /*conditions originating a "NOT to be processed" result */
1171     nCond1 = pam->nCurrSyllable <= -1;
1172     nCond2 = pam->nCurrSyllable >= pam->nTotalSyllables;
1173     nCond3 = pam->nSyllPhoneme
1174             >= pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3];
1175 
1176     if ((nCond1) || (nCond2) || (nCond3))
1177         return FALSE;
1178 
1179     return TRUE;
1180 } /*pamHasToProcess*/
1181 
1182 /**
1183  * modifies the process flags in order to point to next valid syllable phone or item to be produced
1184  * @param    this : Pam object pointer
1185  * @return    TRUE : item has to be produced
1186  * @return    FALSE : item has not to be produced
1187  * @callgraph
1188  * @callergraph
1189  */
pamUpdateProcess(register picodata_ProcessingUnit this)1190 static pico_status_t pamUpdateProcess(register picodata_ProcessingUnit this)
1191 {
1192     register pam_subobj_t * pam;
1193 
1194     if (NULL == this || NULL == this->subObj) {
1195         return PICODATA_PU_ERROR;
1196     }
1197     pam = (pam_subobj_t *) this->subObj;
1198 
1199     if (pam->nCurrSyllable == -1) {
1200         /*this to be able to manage sudden PU cleanup after FLUSH CMD*/
1201         return PICO_OK;
1202     }
1203     /*check number of phonemes for current syllable*/
1204     if (pam->nSyllPhoneme < pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] - 1) {
1205         pam->nSyllPhoneme++;
1206         return PICO_OK;
1207     }
1208     if (pam->nSyllPhoneme == pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] - 1) {
1209         /*this helps in identifyng the end of syllable condition in PamHasToProcess*/
1210         pam->nSyllPhoneme++;
1211     }
1212     /*previous syllable phonemes are complete: test if any items are tied to this syllable*/
1213     if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] > 0) {
1214         /*there are items tied to this syllable*/
1215         if (pam->nCurrAttachedItem == 0) {
1216             /*if it is the first item to be regenerated initialize it*/
1217             pam->nCurrAttachedItem
1218                     = pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM];
1219             return PICO_OK;
1220         } else {
1221             /*not the first item : check if more*/
1222             if (pam->nCurrAttachedItem
1223                     < pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) {
1224                 /*more tied items to be regenerated*/
1225                 pam->nCurrAttachedItem++;
1226                 return PICO_OK;
1227             }
1228         }
1229     }
1230     /*previous syllable phonemes and items are complete: switch to next syllable*/
1231     if (pam->nCurrSyllable < pam->nTotalSyllables - 1) {
1232         pam->nCurrSyllable++;
1233         pam->nSyllPhoneme = 0;
1234         pam->nCurrAttachedItem = 0;
1235         return PICO_OK;
1236     }
1237     /*no more phonemes or items to be produced*/
1238     pam->nCurrSyllable++;
1239     pam->nSyllPhoneme = 0;
1240     return PICO_ERR_OTHER;
1241 
1242 } /*pamUpdateProcess*/
1243 
1244 /**
1245  * returns true if more items has to be popped for current syllable
1246  * @param    this : Pam object pointer
1247  * @return    TRUE : item has to be popped
1248  * @return    FALSE : item has not to be popped
1249  * @callgraph
1250  * @callergraph
1251  */
pamHasToPop(register picodata_ProcessingUnit this)1252 static picoos_uint8 pamHasToPop(register picodata_ProcessingUnit this)
1253 {
1254     register pam_subobj_t * pam;
1255 
1256     if (NULL == this || NULL == this->subObj) {
1257         return PICODATA_PU_ERROR;
1258     }
1259     pam = (pam_subobj_t *) this->subObj;
1260 
1261     /*Preliminary condition : at least 1 syllable*/
1262     if (pam->nCurrSyllable <= -1)
1263         return FALSE;
1264 
1265     /*Preliminary condition : not maximum number of syllables*/
1266     if (pam->nCurrSyllable >= pam->nTotalSyllables)
1267         return FALSE;
1268 
1269     /*Preliminary condition : start and end offset in current item > 0 */
1270     if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0)
1271             || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0))
1272         return FALSE;
1273 
1274     /*Final condition : current popped item less or eq to maximum*/
1275     if (pam->nCurrAttachedItem
1276             > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm])
1277         return FALSE;
1278 
1279     return TRUE;
1280 } /*pamHasToPop*/
1281 
1282 /**
1283  * returns the address of an item to be popped from the current syllable queue
1284  * @param    this : Pam object pointer
1285  * @return    pop_address : item address
1286  * @return    NULL : item not poppable
1287  * @callgraph
1288  * @callergraph
1289  */
pamPopItem(register picodata_ProcessingUnit this)1290 static picoos_uint8 *pamPopItem(register picodata_ProcessingUnit this)
1291 {
1292     register pam_subobj_t * pam;
1293     picoos_uint8 nItem;
1294     if (NULL == this || NULL == this->subObj) {
1295         return NULL;
1296     }
1297     pam = (pam_subobj_t *) this->subObj;
1298 
1299     /*Preliminary condition : at least 1 syllable*/
1300     if (pam->nCurrSyllable <= -1)
1301         return NULL;
1302 
1303     /*Preliminary condition : not maximum number of syllables*/
1304     if (pam->nCurrSyllable >= pam->nTotalSyllables)
1305         return NULL;
1306 
1307     /*Preliminary condition : start and end offset in current item > 0 */
1308     if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0)
1309             || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0))
1310         return NULL;
1311 
1312     /*Final condition : current popped item less than maximum*/
1313     if (pam->nCurrAttachedItem
1314             > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm])
1315         return NULL;
1316 
1317     nItem = pam->nCurrAttachedItem;
1318     /*please note : nItem-1 should match with actions performed in function "pam_queue(..)" */
1319     return &(pam->sSyllItems[pam->sSyllItemOffs[nItem - 1]]);
1320 
1321 } /*pamPopItem*/
1322 
1323 /**
1324  * returns the address of an item popped from the syllable 0 queue
1325  * @param    this : Pam object pointer
1326  * @return    pop_address : item address
1327  * @return    NULL : item not poppable
1328  * @remarks the item is popped only if it has been inserted in the queue before the first
1329  * @remarks item assigned to the syllable 0 i.e.
1330  * @remarks AttachedItem<=pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]-1
1331  * @callgraph
1332  * @callergraph
1333  */
pamPopAttachedSy0(register picodata_ProcessingUnit this)1334 static picoos_uint8 *pamPopAttachedSy0(register picodata_ProcessingUnit this)
1335 {
1336     register pam_subobj_t * pam;
1337     picoos_uint8 nItem;
1338     if (NULL == this || NULL == this->subObj) {
1339         return NULL;
1340     }
1341     pam = (pam_subobj_t *) this->subObj;
1342 
1343     /*should be syllable 0*/
1344     if (pam->nCurrSyllable != 0)
1345         return NULL;
1346 
1347     /*start and end offset in current item > 0 */
1348     if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0)
1349             || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0))
1350         return NULL;
1351 
1352     /*if current popped item is > 0 test end condition*/
1353     if (pam->nCurrAttachedItem > 0) {
1354         /*Other condition : current popped item less than maximum*/
1355         if (pam->nCurrAttachedItem
1356                 > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] - 1)
1357             return NULL;
1358     }
1359     nItem = pam->nCurrAttachedItem;
1360     return &(pam->sSyllItems[pam->sSyllItemOffs[nItem]]);
1361 
1362 } /*pamPopAttachedSy0*/
1363 
1364 /**
1365  * pdf access for duration
1366  * @param    this : Pam object pointer
1367  * @param    durIndex : index of duration in the pdf
1368  * @param    phonDur : pointer to base of array where to store the duration values
1369  * @param    numFramesState : pointer to base of array where to store the number of frames per state
1370  * @return    PICO_OK : pdf retrieved
1371  * @return    PICO_ERR_OTHER : pdf not retrieved
1372  * @remarks Modifies phonDur (the requested duration value)
1373  * @remarks Modifies numFramesState (the requested number of frames per state (vector))
1374  * @callgraph
1375  * @callergraph
1376  */
pam_get_duration(register picodata_ProcessingUnit this,picoos_uint16 durIndex,picoos_uint16 * phonDur,picoos_uint8 * numFramesState)1377 static pico_status_t pam_get_duration(register picodata_ProcessingUnit this,
1378         picoos_uint16 durIndex, picoos_uint16 *phonDur,
1379         picoos_uint8 *numFramesState)
1380 {
1381     pam_subobj_t *pam;
1382     picokpdf_PdfDUR pdf;
1383     picoos_uint8 *durItem;
1384     picoos_uint16 nFrameSize, nI;
1385     picoos_single fValue;
1386     pam = (pam_subobj_t *) this->subObj;
1387     if (NULL == this || NULL == this->subObj) {
1388         return PICODATA_PU_ERROR;
1389     }
1390     pdf = pam->pdfdur;
1391     /*make the index 0 based*/
1392     if (durIndex > 0)
1393         durIndex--;
1394 
1395     /* check */
1396     if (durIndex > pdf->numframes - 1) {
1397         PICODBG_ERROR(("PAM durPdf access error, index overflow -> index: %d , numframes: %d", durIndex, pdf->numframes));
1398         return PICO_ERR_OTHER;
1399     }
1400     /* base pointer */
1401     durItem = &(pdf->content[durIndex * pdf->vecsize]);
1402     if (durItem == NULL) {
1403         PICODBG_ERROR(("PAM durPdf access error , frame pointer = NULL"));
1404         return PICO_ERR_OTHER;
1405     }
1406     nFrameSize = pdf->sampperframe / 16;
1407     *phonDur = ((pdf->phonquant[((*durItem) & 0xF0) >> 4]) * nFrameSize);
1408     numFramesState[0] = pdf->statequant[((*durItem) & 0x0F)];
1409     durItem++;
1410     numFramesState[1] = pdf->statequant[((*durItem) & 0xF0) >> 4];
1411     numFramesState[2] = pdf->statequant[((*durItem) & 0x0F)];
1412     durItem++;
1413     numFramesState[3] = pdf->statequant[((*durItem) & 0xF0) >> 4];
1414     numFramesState[4] = pdf->statequant[((*durItem) & 0x0F)];
1415 
1416     /*modification of the duration information based on the duration modifier*/
1417     *phonDur = (picoos_uint16) (((picoos_single) * phonDur) * pam->dMod);
1418     for (nI = 0; nI < 5; nI++) {
1419         fValue = pam->dRest + (picoos_single) numFramesState[nI] * pam->dMod;
1420         numFramesState[nI] = (picoos_uint8) (fValue);
1421         pam->dRest = fValue - (picoos_single) numFramesState[nI];
1422     }
1423     return PICO_OK;
1424 }/*pam_get_duration*/
1425 
1426 /**
1427  * pdf access for pitch
1428  * @param    this : Pam object pointer
1429  * @param    lf0Index : pointer to variable to receive index of pitch in the pdf
1430  * @param    nI : number of the phone's state
1431  * @param    phonF0 : pointer to variable to receive the pitch value
1432  * @return    PICO_OK : pdf retrieved
1433  * @return    PICO_ERR_OTHER : pdf not retrieved
1434  * @remarks Modifies phonDur (the requested duration value)
1435  * @remarks Modifies phonF0 (the requested pitch value (scalar))
1436  * @callgraph
1437  * @callergraph
1438  */
pam_get_f0(register picodata_ProcessingUnit this,picoos_uint16 * lf0Index,picoos_uint8 nI,picoos_single * phonF0)1439 static pico_status_t pam_get_f0(register picodata_ProcessingUnit this,
1440         picoos_uint16 *lf0Index, picoos_uint8 nI, picoos_single *phonF0)
1441 {
1442     pam_subobj_t *pam;
1443     picoos_uint8 *lfItem, numstreams;
1444     picoos_uint16 lf0IndexOffset, sTemp;
1445     picoos_single lfum, lfivar, lfz;
1446 
1447     pam = (pam_subobj_t *) this->subObj;
1448     if (NULL == this || NULL == this->subObj) {
1449         return PICODATA_PU_ERROR;
1450     }
1451     lf0IndexOffset = lf0Index[nI];
1452 
1453     /*make the index 0 based*/
1454     if (lf0IndexOffset > 0)
1455         lf0IndexOffset--;
1456 
1457     lf0IndexOffset += pam->pdflfz->stateoffset[nI];
1458     if (lf0IndexOffset > pam->pdflfz->numframes - 1) {
1459         PICODBG_ERROR(("PAM flfzPdf access error, index overflow -> index: %d , numframes: %d", lf0Index, pam->pdflfz->numframes));
1460         return PICO_ERR_OTHER;
1461     }
1462     /* base pointer */
1463     lf0IndexOffset *= pam->pdflfz->vecsize;
1464 
1465     lfItem = &(pam->pdflfz->content[lf0IndexOffset]);
1466     sTemp = (picoos_uint16) (((lfItem[1] << 8)) | lfItem[0]);
1467 
1468     lfum = (picoos_single) (sTemp << (pam->pdflfz->meanpowUm[0]));
1469     numstreams = 3;
1470     lfivar = (picoos_single) (((picoos_uint16) lfItem[numstreams * 2])
1471             << pam->pdflfz->ivarpow[0]);
1472     lfz = (picoos_single) lfum / (picoos_single) lfivar;
1473     lfz = (picoos_single) exp((double) lfz);
1474     phonF0[nI] = (picoos_single) lfz;
1475 
1476     /*pitch modoification*/
1477     phonF0[nI] *= pam->pMod;
1478     return PICO_OK;
1479 }/*pam_get_f0*/
1480 
1481 /**
1482  * elementary rounding function
1483  * @param    fIn : (real) input value
1484  * @return    the rounded value
1485  * @callgraph
1486  * @callergraph
1487  */
f_round(picoos_single fIn)1488 static picoos_single f_round(picoos_single fIn)
1489 {
1490     picoos_int32 iVal;
1491     picoos_single fVal;
1492 
1493     iVal = (picoos_int32) fIn;
1494     fVal = (picoos_single) iVal;
1495 
1496     if (fIn > (picoos_single) 0.0f) {
1497         if ((fIn - fVal) < (picoos_single) 0.5f)
1498             return fVal;
1499         else
1500             return fVal + (picoos_single) 1.0f;
1501     } else {
1502         if ((fVal - fIn) < (picoos_single) 0.5f)
1503             return fVal;
1504         else
1505             return fVal - (picoos_single) 1.0f;
1506     }
1507 }/*f_round*/
1508 
1509 /**
1510  * updates the input vector for PAM
1511  * @param    this : Pam object pointer
1512  * @return    PICO_OK : update successful
1513  * @return    PICO_ERR_OTHER : errors on retrieving the PU pointer
1514  * @remarks Modifies pam->sPhFeats[]
1515  * @callgraph
1516  * @callergraph
1517  */
pam_update_vector(register picodata_ProcessingUnit this)1518 static pico_status_t pam_update_vector(register picodata_ProcessingUnit this)
1519 {
1520     pam_subobj_t *pam;
1521     picoos_uint8 numstates, nI;
1522     picoos_single fDur, f0avg, f0quant, minf0, maxf0, durquant1, durquant2,
1523             mindur, maxdur1, maxdur2;
1524 
1525     pam = (pam_subobj_t *) this->subObj;
1526     if (NULL == this || NULL == this->subObj) {
1527         return PICO_ERR_OTHER;
1528     }
1529     /*default init*/
1530     pam->sPhFeats[DUR] = 0;
1531     pam->sPhFeats[F0] = 0;
1532     /*
1533      Hard coded parameters for quantization
1534      */
1535     numstates = PICOPAM_NRSTPF;
1536     f0quant = 30.0f;
1537     minf0 = 90.0f;
1538     maxf0 = 360.0f;
1539 
1540     durquant1 = 20.0f;
1541     durquant2 = 100.0f;
1542     mindur = 40.0f;
1543     maxdur1 = 160.0f;
1544     maxdur2 = 600.0f;
1545     f0avg = 0.0f;
1546     for (nI = 0; nI < numstates; nI++)
1547         f0avg += pam->phonF0[nI];
1548     f0avg /= (picoos_single) numstates;
1549 
1550     f0avg = f_round(f0avg / f0quant) * f0quant;
1551     if (f0avg < minf0)
1552         f0avg = minf0;
1553     if (f0avg > maxf0)
1554         f0avg = maxf0;
1555 
1556     /*make initial silence of sentence shorter (see also pam_put_item)*/
1557     if ((pam->nCurrSyllable == 0) && (pam->nSyllPhoneme == 0)) {
1558         pam->phonDur = 2 * 4;
1559     }
1560 
1561     fDur = (picoos_single) pam->phonDur;
1562     fDur = f_round(fDur / durquant1) * durquant1;
1563     if (fDur < mindur)
1564         fDur = mindur;
1565     if (fDur > maxdur1) {
1566         fDur = f_round(fDur / durquant2) * durquant2;
1567         if (fDur > maxdur2)
1568             fDur = maxdur2;
1569     }
1570     pam->sPhFeats[DUR] = (picoos_uint8) (fDur / (picoos_single) 10.0f);
1571     pam->sPhFeats[F0] = (picoos_uint8) (f0avg / (picoos_single) 10.0f);
1572 
1573     return PICO_OK;
1574 }/*pam_update_vector*/
1575 
1576 /**
1577  * compress a single feature in the range 0..9
1578  * @param    inVal : the value to be compressed
1579  * @return    compVal : the compressed value
1580  * @callgraph
1581  * @callergraph
1582  */
pamCompressComponent(picoos_uint8 inVal)1583 static picoos_uint8 pamCompressComponent(picoos_uint8 inVal)
1584 {
1585     if (inVal <= 5)
1586         return inVal;
1587     if ((5 < inVal) && (inVal <= 10))
1588         return 6;
1589     if ((10 < inVal) && (inVal <= 20))
1590         return 7;
1591     if ((20 < inVal) && (inVal <= 30))
1592         return 8;
1593     return 9;
1594 }/*pamCompressComponent*/
1595 
1596 /**
1597  * prepares the input vector for tree feeding
1598  * @param    this : Pam object pointer
1599  * @return    PICO_OK : vector expanded
1600  * @return    PICO_ERR_OTHER : errors on expansion or retrieving the PU pointer
1601  * @remarks Modifies pam->sPhFeats[]
1602  * @callgraph
1603  * @callergraph
1604  */
pam_expand_vector(register picodata_ProcessingUnit this)1605 static pico_status_t pam_expand_vector(register picodata_ProcessingUnit this)
1606 {
1607     pam_subobj_t *pam;
1608     picoos_uint8 *inVect, *phonVect, *outVect, nI;
1609     picoos_int16 nOffs, nOffs1, nLen;
1610     pam = (pam_subobj_t *) this->subObj;
1611     if (NULL == this || NULL == this->subObj) {
1612         return PICODATA_PU_ERROR;
1613     }
1614     inVect = &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[0]);
1615     phonVect = &(pam->sPhIds[0]);
1616     outVect = &(pam->sPhFeats[0]);
1617     /*just copy back*/
1618     for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++)
1619         outVect[nI] = inVect[nI];
1620     /*now fill missing fields*/
1621     picoos_mem_copy((void*) &(inVect[FID]), &nOffs, sizeof(nOffs));
1622     /*offset to first phone of current syllable*/
1623     nOffs = nOffs + pam->nSyllPhoneme; /*offset to current phone of current syllable*/
1624     nLen = inVect[B3]; /*len of current syllable*/
1625     if (pam->nSyllPhoneme >= nLen) {
1626         /*error on addressing current phone*/
1627         return PICO_ERR_OTHER;
1628     }
1629     /*previous of the previous phone*/
1630     nOffs1 = nOffs - 2;
1631     if (nOffs1 >= 0)
1632         outVect[P1] = phonVect[nOffs1];
1633     else
1634         outVect[P1] = PICOPAM_PH_DONT_CARE_VAL;
1635     /*previous  phone*/
1636     nOffs1 = nOffs - 1;
1637     if (nOffs1 >= 0)
1638         outVect[P2] = phonVect[nOffs1];
1639     else
1640         outVect[P2] = PICOPAM_PH_DONT_CARE_VAL;
1641     /*^current phone*/
1642     outVect[P3] = phonVect[nOffs];
1643 
1644     /*next phone*/
1645     nOffs1 = nOffs + 1;
1646     if (nOffs1 < pam->nTotalPhonemes)
1647         outVect[P4] = phonVect[nOffs1];
1648     else
1649         outVect[P4] = PICOPAM_PH_DONT_CARE_VAL;
1650     /*next of the next phone*/
1651     nOffs1 = nOffs + 2;
1652     if (nOffs1 < pam->nTotalPhonemes)
1653         outVect[P5] = phonVect[nOffs1];
1654     else
1655         outVect[P5] = PICOPAM_PH_DONT_CARE_VAL;
1656     /*pos of curr phone with respect to left syllable boundary*/
1657     outVect[P6] = pam->nSyllPhoneme + 1;
1658     /*pos of curr phone with respect to right syllable boundary*/
1659     outVect[P7] = nLen - pam->nSyllPhoneme;
1660     /*is current phone in consonant syllable boundary? (1:yes)*/
1661     if (pam->nSyllPhoneme < inVect[P8])
1662         outVect[P8] = 1;
1663     else
1664         outVect[P8] = 0;
1665     return PICO_OK;
1666 }/*pam_expand_vector*/
1667 
1668 /**
1669  * compresses the input vector for PAM
1670  * @param    this : Pam object pointer
1671  * @return    PICO_OK : compression successful
1672  * @return    PICO_ERR_OTHER : errors on retrieving the PU pointer
1673  * @remarks Modifies pam->sPhFeats[]
1674  * @callgraph
1675  * @callergraph
1676  */
pamCompressVector(register picodata_ProcessingUnit this)1677 static pico_status_t pamCompressVector(register picodata_ProcessingUnit this)
1678 {
1679     pam_subobj_t *pam;
1680     picoos_uint8 *outVect, nI;
1681     pam = (pam_subobj_t *) this->subObj;
1682     if (NULL == this || NULL == this->subObj) {
1683         return PICODATA_PU_ERROR;
1684     }
1685     outVect = &(pam->sPhFeats[0]);
1686     for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) {
1687         switch (nI) {
1688             case P1:
1689             case P2:
1690             case P3:
1691             case P4:
1692             case P5:
1693             case B1:
1694             case B2:
1695             case B16:
1696             case E1:
1697             case H5:
1698                 /*don't do any compression*/
1699                 break;
1700             default:
1701                 /*do compression*/
1702                 if (outVect[nI] != PICOPAM_DONT_CARE_VALUE)
1703                     outVect[nI] = pamCompressComponent(outVect[nI]);
1704                 else
1705                     outVect[nI] = PICOPAM_DONT_CARE_VAL;
1706                 break;
1707         }
1708     }
1709     return PICO_OK;
1710 }/*pamCompressVector*/
1711 
1712 /**
1713  * reorganizes the input vector for PAM
1714  * @param    this : Pam object pointer
1715  * @return    PICO_OK : reorganization successful
1716  * @return    PICO_ERR_OTHER : errors on retrieving the PU pointer
1717  * @remarks Modifies pam->sPhFeats[]
1718  * @callgraph
1719  * @callergraph
1720  */
pamReorgVector(register picodata_ProcessingUnit this)1721 static pico_status_t pamReorgVector(register picodata_ProcessingUnit this)
1722 {
1723     pam_subobj_t *pam;
1724     picoos_uint8 *outVect, inVect[60], nI;
1725     pam = (pam_subobj_t *) this->subObj;
1726     if (NULL == this || NULL == this->subObj) {
1727         return PICODATA_PU_ERROR;
1728     }
1729     outVect = &(pam->sPhFeats[0]);
1730     for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) inVect[nI] = outVect[nI];
1731     /*reorganize*/
1732     for (nI = T_B1; nI <= T_H5; nI++) {
1733         switch (nI) {
1734             case T_B1:
1735                 outVect[T_B1] = inVect[B1];
1736                 break;
1737             case T_B2:
1738                 outVect[T_B2] = inVect[B2];
1739                 break;
1740             case T_B3:
1741                 outVect[T_B3] = inVect[B3];
1742                 break;
1743             case T_B4:
1744                 outVect[T_B4] = inVect[B4];
1745                 break;
1746             case T_B5:
1747                 outVect[T_B5] = inVect[B5];
1748                 break;
1749             case T_B6:
1750                 outVect[T_B6] = inVect[B6];
1751                 break;
1752             case T_B7:
1753                 outVect[T_B7] = inVect[B7];
1754                 break;
1755             case T_B8:
1756                 outVect[T_B8] = inVect[B8];
1757                 break;
1758             case T_B9:
1759                 outVect[T_B9] = inVect[B9];
1760                 break;
1761             case T_B10:
1762                 outVect[T_B10] = inVect[B10];
1763                 break;
1764             case T_B11:
1765                 outVect[T_B11] = inVect[B11];
1766                 break;
1767             case T_B12:
1768                 outVect[T_B12] = inVect[B12];
1769                 break;
1770             case T_B13:
1771                 outVect[T_B13] = inVect[B13];
1772                 break;
1773             case T_B14:
1774                 outVect[T_B14] = inVect[B14];
1775                 break;
1776             case T_B15:
1777                 outVect[T_B15] = inVect[B15];
1778                 break;
1779             case T_B16:
1780                 outVect[T_B16] = inVect[B16];
1781                 break;
1782             case T_B17:
1783                 outVect[T_B17] = inVect[B17];
1784                 break;
1785             case T_B18:
1786                 outVect[T_B18] = inVect[B18];
1787                 break;
1788             case T_B19:
1789                 outVect[T_B19] = inVect[B19];
1790                 break;
1791             case T_B20:
1792                 outVect[T_B20] = inVect[B20];
1793                 break;
1794             case T_B21:
1795                 outVect[T_B21] = inVect[B21];
1796                 break;
1797 
1798             case T_E1:
1799                 outVect[T_E1] = inVect[E1];
1800                 break;
1801             case T_E2:
1802                 outVect[T_E2] = inVect[E2];
1803                 break;
1804             case T_E3:
1805                 outVect[T_E3] = inVect[E3];
1806                 break;
1807             case T_E4:
1808                 outVect[T_E4] = inVect[E4];
1809                 break;
1810             case T_E5:
1811                 outVect[T_E5] = inVect[E5];
1812                 break;
1813             case T_E6:
1814                 outVect[T_E6] = inVect[E6];
1815                 break;
1816             case T_E7:
1817                 outVect[T_E7] = inVect[E7];
1818                 break;
1819             case T_E8:
1820                 outVect[T_E8] = inVect[E8];
1821                 break;
1822             case T_E9:
1823                 outVect[T_E9] = inVect[E9];
1824                 break;
1825             case T_E10:
1826                 outVect[T_E10] = inVect[E10];
1827                 break;
1828             case T_E11:
1829                 outVect[T_E11] = inVect[E11];
1830                 break;
1831             case T_E12:
1832                 outVect[T_E12] = inVect[E12];
1833                 break;
1834             case T_E13:
1835                 outVect[T_E13] = inVect[E13];
1836                 break;
1837 
1838             case T_A3:
1839                 outVect[T_A3] = inVect[A3];
1840                 break;
1841             case T_C3:
1842                 outVect[T_C3] = inVect[C3];
1843                 break;
1844             case T_D2:
1845                 outVect[T_D2] = inVect[D2];
1846                 break;
1847             case T_F2:
1848                 outVect[T_F2] = inVect[F2];
1849                 break;
1850 
1851             case T_G1:
1852                 outVect[T_G1] = inVect[G1];
1853                 break;
1854             case T_I1:
1855                 outVect[T_I1] = inVect[I1];
1856                 break;
1857 
1858             case T_G2:
1859                 outVect[T_G2] = inVect[G2];
1860                 break;
1861             case T_I2:
1862                 outVect[T_I2] = inVect[I2];
1863                 break;
1864 
1865             case T_H1:
1866                 outVect[T_H1] = inVect[H1];
1867                 break;
1868             case T_H2:
1869                 outVect[T_H2] = inVect[H2];
1870                 break;
1871             case T_H3:
1872                 outVect[T_H3] = inVect[H3];
1873                 break;
1874             case T_H4:
1875                 outVect[T_H4] = inVect[H4];
1876                 break;
1877             case T_H5:
1878                 outVect[T_H5] = inVect[H5];
1879                 break;
1880         }
1881     }
1882     return PICO_OK;
1883 }/*pamReorgVector*/
1884 
1885 /**
1886  * puts a PAM item into PU output buffer
1887  * @param    this : Pam object pointer
1888  * @param    outBuff    : output buffer base pointer
1889  * @param    outWritePos : offset in output buffer
1890  * @param    *bytesWr : actual bytes written
1891  * @return    PICO_OK : put successful
1892  * @return    PICO_ERR_OTHER : errors on retrieving the PU pointer
1893  * @callgraph
1894  * @callergraph
1895  */
pam_put_item(register picodata_ProcessingUnit this,picoos_uint8 * outBuff,picoos_uint16 outWritePos,picoos_uint8 * bytesWr)1896 static pico_status_t pam_put_item(register picodata_ProcessingUnit this,
1897         picoos_uint8 *outBuff, picoos_uint16 outWritePos, picoos_uint8 *bytesWr)
1898 {
1899     pam_subobj_t *pam;
1900     picoos_uint8 *sDest, nI, nType, nIdx, fde;
1901     picoos_uint32 pos, pos32;
1902     picoos_int16 ft, dt;
1903     picoos_uint16 uMinDur, uMaxDur;
1904     pam = (pam_subobj_t *) this->subObj;
1905     if (NULL == this || NULL == this->subObj) {
1906         return PICODATA_PU_ERROR;
1907     }
1908     sDest = &(outBuff[outWritePos]);
1909     sDest[0] = PICODATA_ITEM_PHONE; /*Item type*/
1910     sDest[1] = pam->sPhFeats[P3]; /*phonetic id*/
1911     sDest[2] = PICOPAM_NRSTPF; /*number of states per phone*/
1912     sDest[3] = sizeof(picoos_uint16) * PICOPAM_NRSTPF * 3; /*size of the item*/
1913     pos = 4;
1914     /*make initial silence of sentence shorter (see also UpdateVector)*/
1915     if ((pam->nCurrSyllable == 0) && (pam->nSyllPhoneme == 0)) {
1916         for (nI = 0; nI < PICOPAM_NRSTPF - 1; nI++)
1917             pam->numFramesState[nI] = 0;
1918         pam->numFramesState[nI] = 2;
1919     } else {
1920         /*manage silence syllables with prescribed durations*/
1921         pos32 = Min;
1922         picoos_read_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV,
1923                 &pos32, &uMinDur);
1924         pos32 = Max;
1925         picoos_read_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV,
1926                 &pos32, &uMaxDur);
1927 
1928         if (uMaxDur > 0) {
1929             /* Select weights*/
1930             nType = pam->sSyllFeats[pam->nCurrSyllable].phoneV[bnd];
1931             switch (nType) {
1932                 case PICODATA_ITEMINFO1_BOUND_SBEG:
1933                     nIdx = PICOPAM_PWIDX_SBEG;
1934                     break;
1935                 case PICODATA_ITEMINFO1_BOUND_PHR1:
1936                     nIdx = PICOPAM_PWIDX_PHR1;
1937                     break;
1938                 case PICODATA_ITEMINFO1_BOUND_PHR2:
1939                     nIdx = PICOPAM_PWIDX_PHR2;
1940                     break;
1941                 case PICODATA_ITEMINFO1_BOUND_SEND:
1942                 case PICODATA_ITEMINFO1_BOUND_TERM:
1943                     nIdx = PICOPAM_PWIDX_SEND;
1944                     break;
1945                 default:
1946                     nIdx = PICOPAM_PWIDX_DEFA;
1947                     break;
1948             }
1949             fde = 2;
1950             ft = 0;
1951             dt = 0;
1952             picodata_transformDurations(
1953                     fde,            /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */
1954                     PICOPAM_NRSTPF, /* number of states per phone */
1955                     &(pam->numFramesState[0]), /* estimated durations */
1956                     pam->sil_weights[nIdx],  /* integer weights */
1957                     uMinDur,        /* minimum target duration in ms */
1958                     uMaxDur,        /* maximum target duration in ms */
1959                     ft,             /* factor to be multiplied to get the target */
1960                     &dt             /* in/out, rest in ms */
1961                     );
1962         }
1963     }
1964     /*put data*/
1965     for (nI = 0; nI < PICOPAM_NRSTPF; nI++) {
1966         picoos_write_mem_pi_uint16(sDest, &pos,
1967                 (picoos_uint16) pam->numFramesState[nI]);
1968         picoos_write_mem_pi_uint16(sDest, &pos,
1969                 (picoos_uint16) pam->lf0Index[nI]);
1970         picoos_write_mem_pi_uint16(sDest, &pos,
1971                 (picoos_uint16) pam->mgcIndex[nI]);
1972     }
1973     *bytesWr = sizeof(picodata_itemhead_t) + sizeof(picoos_uint16)
1974             * PICOPAM_NRSTPF * 3;
1975     return PICO_OK;
1976 }/*pam_put_item*/
1977 
1978 /**
1979  * puts a non PAM (queued) item into PU output buffer
1980  * @param    qItem : pointer to item to put
1981  * @param    outBuff    : output buffer base pointer
1982  * @param    outWritePos : offset in output buffer
1983  * @param    *bytesWr : actual bytes written
1984  * @return    PICO_OK : put successful
1985  * @return    PICO_ERR_OTHER : errors on retrieving the PU pointer
1986  * @callgraph
1987  * @callergraph
1988  */
pam_put_qItem(picoos_uint8 * qItem,picoos_uint8 * outBuff,picoos_uint16 outWritePos,picoos_uint8 * bytesWr)1989 static pico_status_t pam_put_qItem(picoos_uint8 *qItem, picoos_uint8 *outBuff,
1990         picoos_uint16 outWritePos, picoos_uint8 *bytesWr)
1991 {
1992     picoos_uint8 *sDest, nI;
1993     sDest = &(outBuff[outWritePos]);
1994     *bytesWr = sizeof(picodata_itemhead_t);
1995     for (nI = 0; nI < (sizeof(picodata_itemhead_t) + qItem[3]); nI++) {
1996         sDest[nI] = qItem[nI];
1997     }
1998     *bytesWr = nI;
1999     return PICO_OK;
2000 }/*pam_put_qItem*/
2001 
2002 /**
2003  * tells if an item is a PAM command (except play)
2004  * @param    qItem : input item to test
2005  * @return    TRUE : qItem is a PAM command (except play)
2006  * @return    FALSE : qItem not a PAM command
2007  * @callgraph
2008  * @callergraph
2009  */
is_pam_command(const picoos_uint8 * qItem)2010 static pico_status_t is_pam_command(const picoos_uint8 * qItem)
2011 {
2012     switch (qItem[0]) {
2013 
2014         case PICODATA_ITEM_CMD:
2015             switch (qItem[1]) {
2016                 case PICODATA_ITEMINFO1_CMD_FLUSH:
2017                     /* flush is for all PU's and as such it is also for PAM*/
2018                 case PICODATA_ITEMINFO1_CMD_PITCH:
2019                 case PICODATA_ITEMINFO1_CMD_SPEED:
2020                     return TRUE;
2021                     break;
2022                 default:
2023                     break;
2024             }
2025     }
2026     return FALSE;
2027 }/*is_pam_command*/
2028 
2029 /**
2030  * tells if an item is a PAM PLAY command
2031  * @param    qItem : input item to test
2032  * @return    TRUE : qItem is a PAM PLAY command
2033  * @return    FALSE : qItem not a PAM PLAY command
2034  * @callgraph
2035  * @callergraph
2036  */
is_pam_play_command(picoos_uint8 * qItem)2037 static pico_status_t is_pam_play_command(picoos_uint8 *qItem)
2038 {
2039     switch (qItem[0]) {
2040 
2041         case PICODATA_ITEM_CMD:
2042             switch (qItem[1]) {
2043                 case PICODATA_ITEMINFO1_CMD_PLAY:
2044                     if (qItem[2] == PICODATA_ITEMINFO2_CMD_TO_PAM)
2045                         return TRUE;
2046                     break;
2047                 default:
2048                     break;
2049             }
2050     }
2051     return FALSE;
2052 }/*is_pam_play_command*/
2053 
2054 /**
2055  * command processor for PAM pu
2056  * @param    this : Pam item subobject
2057  * @param    qItem : input item pointer
2058  * @return    PICOPAM_FLUSH_RECEIVED : when a FLUSH is received
2059  * @return    PICOPAM_CONTINUE : normal command processing
2060  * @return    PICODATA_PU_ERROR : errors in accessing data
2061  * @callgraph
2062  * @callergraph
2063  */
pamDoCommand(register picodata_ProcessingUnit this,picoos_uint8 * qItem)2064 static pico_status_t pamDoCommand(register picodata_ProcessingUnit this,
2065         picoos_uint8 *qItem)
2066 {
2067     pam_subobj_t *pam;
2068     picoos_single fValue;
2069     picoos_uint16 nValue;
2070     picoos_uint32 nPos;
2071     pam = (pam_subobj_t *) this->subObj;
2072     if (NULL == this || NULL == this->subObj) {
2073         return PICODATA_PU_ERROR;
2074     }
2075     if (qItem[0] == PICODATA_ITEM_CMD) {
2076         switch (qItem[1]) {
2077             case PICODATA_ITEMINFO1_CMD_FLUSH:
2078                 /* flush is for all PU's and as such it is also for PAM : implement the flush!!*/
2079                 pam_reset_processors(this);
2080                 pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0;
2081                 pam->nAttachedItemsSize = 0;
2082                 return PICOPAM_FLUSH_RECEIVED;
2083                 break;
2084 
2085             case PICODATA_ITEMINFO1_CMD_PITCH:
2086             case PICODATA_ITEMINFO1_CMD_SPEED:
2087                 nPos = 4;
2088                 picoos_read_mem_pi_uint16(qItem, &nPos, &nValue);
2089                 if (qItem[2] == 'a') {
2090                     /*absloute modifier*/
2091                     fValue = (picoos_single) nValue / (picoos_single) 100.0f;
2092                     if (qItem[1] == PICODATA_ITEMINFO1_CMD_PITCH)
2093                         pam->pMod = fValue;
2094                     if (qItem[1] == PICODATA_ITEMINFO1_CMD_SPEED)
2095                         pam->dMod = (1.0f / fValue);
2096                 }
2097                 if (qItem[2] == 'r') {
2098                     /*relative modifier*/
2099                     fValue = (picoos_single) nValue / (picoos_single) 1000.0f;
2100                     if (qItem[1] == PICODATA_ITEMINFO1_CMD_PITCH)
2101                         pam->pMod *= (1.0f / fValue);
2102                     if (qItem[1] == PICODATA_ITEMINFO1_CMD_SPEED)
2103                         pam->dMod *= (1.0f / fValue);
2104                 }
2105                 return PICOPAM_CONTINUE;
2106                 break;
2107 
2108             default:
2109                 break;
2110         }/*end switch  switch (qItem[1])*/
2111     }/*end if (qItem[0]==PICODATA_ITEM_CMD)*/
2112     return PICOPAM_CONTINUE;
2113 }/*pamDoCommand*/
2114 
2115 /**
2116  * defines if an item has to be sent to following PUs
2117  * @param    qItem : input item pointer
2118  * @return    TRUE : item has to be transmitted to following PUs
2119  * @return    FALSE : item has to be consumed internallz on PAM
2120  * @callgraph
2121  * @callergraph
2122  */
isItemToPut(picoos_uint8 * qItem)2123 static pico_status_t isItemToPut(picoos_uint8 *qItem)
2124 {
2125     switch (qItem[0]) {
2126         case PICODATA_ITEM_CMD:
2127             /* is a command*/
2128             if (PICODATA_ITEMINFO1_CMD_SPEED == qItem[1]) {
2129                 /* SPEED consumed here*/
2130                 return FALSE;
2131             }
2132             break;
2133         case PICODATA_ITEM_BOUND:
2134             switch (qItem[1]) {
2135                 case PICODATA_ITEMINFO1_BOUND_SBEG:
2136                 case PICODATA_ITEMINFO1_BOUND_PHR0:
2137                 case PICODATA_ITEMINFO1_BOUND_PHR1:
2138                 case PICODATA_ITEMINFO1_BOUND_PHR2:
2139                 case PICODATA_ITEMINFO1_BOUND_PHR3:
2140                     /*boudary items consumed here except SEND,TERM*/
2141                     return FALSE;
2142                     break;
2143                 default:
2144                     break;
2145             }
2146             break;
2147         default:
2148             break;
2149     }
2150     /*all other items not explicitly mentioned here
2151      are transmitted to next PUs*/
2152     return TRUE;
2153 }/*isItemToPut*/
2154 
2155 /**
2156  * pushes a boundary TERM item into some buffer
2157  * @param    outBuff : output buffer base pointer
2158  * @param    outWritePos : offset in output buffer
2159  * @param    *bytesWr : actual bytes written
2160  * @return    PICO_OK
2161  * @remarks    used while forcing TERM input items in forward processing
2162  * @callgraph
2163  * @callergraph
2164  */
pam_put_term(picoos_uint8 * outBuff,picoos_uint16 outWritePos,picoos_uint8 * bytesWr)2165 static pico_status_t pam_put_term(picoos_uint8 *outBuff,
2166         picoos_uint16 outWritePos, picoos_uint8 *bytesWr)
2167 {
2168     picoos_uint8 *sDest;
2169     sDest = &(outBuff[outWritePos]);
2170     sDest[0] = PICODATA_ITEM_BOUND; /*Item type*/
2171     sDest[1] = PICODATA_ITEMINFO1_BOUND_TERM;
2172     sDest[2] = PICODATA_ITEMINFO2_BOUNDTYPE_T;
2173     sDest[3] = 0; /*item size*/
2174     *bytesWr = 4;
2175     return PICO_OK;
2176 }/*pam_put_term*/
2177 
2178 /**
2179  * translates one full phone into a PHONE Item including DT Dur, F0 and CEP trees feature generation and traversal
2180  * @param    this : Pam item subobject pointer
2181  * @return    PICO_OK : processing successful
2182  * @return    PICODATA_PU_ERROR : error accessing PAM object
2183  * @return    !=PICO_OK : processing errors
2184  * @callgraph
2185  * @callergraph
2186  */
pamPhoneProcess(register picodata_ProcessingUnit this)2187 static pico_status_t pamPhoneProcess(register picodata_ProcessingUnit this)
2188 {
2189     pam_subobj_t *pam;
2190     pico_status_t sResult;
2191     picokdt_classify_result_t dTreeResult;
2192     picoos_uint8 nI, bWr;
2193 
2194     pam = (pam_subobj_t *) this->subObj;
2195     if (NULL == this || NULL == this->subObj) {
2196         return PICODATA_PU_ERROR;
2197     }
2198     /*expands current phone in current syllable in the corresponding vector pam->sPhFeats[]*/
2199     sResult = pam_expand_vector(this);
2200     sResult = pamCompressVector(this);
2201     sResult = pamReorgVector(this);
2202 
2203     /*tree traversal for duration*/
2204     if (!pam_do_tree(this, pam->dtdur, &(pam->sPhFeats[0]), PICOPAM_INVEC_SIZE,
2205             &dTreeResult)) {
2206         PICODBG_WARN(("problem using pam tree dtdur, using fallback value"));
2207         dTreeResult.class = 0;
2208     }
2209     pam->durIndex = dTreeResult.class;
2210     sResult = pam_get_duration(this, pam->durIndex, &(pam->phonDur),
2211             &(pam->numFramesState[0]));
2212 
2213     /*tree traversal for pitch*/
2214     for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) {
2215         if (!pam_do_tree(this, pam->dtlfz[nI], &(pam->sPhFeats[0]),
2216                 PICOPAM_INVEC_SIZE, &dTreeResult)) {
2217             PICODBG_WARN(("problem using pam tree lf0Tree, using fallback value"));
2218             dTreeResult.class = 0;
2219         }
2220         pam->lf0Index[nI] = dTreeResult.class;
2221     }
2222 
2223     /*pdf access for pitch*/
2224     for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) {
2225         sResult = pam_get_f0(this, &(pam->lf0Index[0]), nI, &(pam->phonF0[0]));
2226     }
2227 
2228     /*update vector with duration and pitch for cep tree traversal*/
2229     sResult = pam_update_vector(this);
2230     /*cep tree traversal*/
2231     for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) {
2232 
2233         if (!pam_do_tree(this, pam->dtmgc[nI], &(pam->sPhFeats[0]),
2234                 PICOPAM_INVEC_SIZE, &dTreeResult)) {
2235             PICODBG_WARN(("problem using pam tree lf0Tree, using fallback value"));
2236             dTreeResult.class = 0;
2237         }
2238         pam->mgcIndex[nI] = dTreeResult.class;
2239     }
2240     /*put item to output buffer*/
2241     sResult = pam_put_item(this, pam->outBuf, pam->outWritePos, &bWr);
2242     if (sResult == PICO_OK)
2243         pam->outWritePos += bWr;
2244     else
2245         return sResult;
2246     return PICO_OK;
2247 }/*pamPhoneProcess*/
2248 
2249 /**
2250  * manages first syllable attached items when seen before SBEG
2251  * @param    this  : Pam item subobject pointer
2252  * @return    PICO_OK (0) : default return code --> means no more items to be processed before 1st syllable
2253  * @return    PICOPAM_GOTO_FEED : go to feed state after this
2254  * @return    PICOPAM_GOTO_SCHEDULE : flush received
2255  * @return    PICODATA_PU_ERROR : errors
2256  * @callgraph
2257  * @callergraph
2258  */
pamDoPreSyll(register picodata_ProcessingUnit this)2259 static pico_status_t pamDoPreSyll(register picodata_ProcessingUnit this)
2260 {
2261     pam_subobj_t *pam;
2262     pico_status_t sResult;
2263     picoos_uint8 bWr, nRc;
2264     picoos_uint8 *qItem;
2265     nRc = PICOPAM_PRE_SYLL_ENDED;
2266     pam = (pam_subobj_t *) this->subObj;
2267     if (NULL == this || NULL == this->subObj) {
2268         return PICODATA_PU_ERROR;
2269     }
2270     /*regenerate initial items before the phonemes*/
2271     if (((qItem = pamPopAttachedSy0(this)) != NULL) && !((qItem[0]
2272             == PICODATA_ITEM_BOUND) && (qItem[1]
2273             == PICODATA_ITEMINFO1_BOUND_SBEG))) {
2274          if (isItemToPut(qItem)) {
2275             pam_put_qItem(qItem, pam->outBuf, pam->outWritePos, &bWr);/*popped item has to be sent to next PU*/
2276             pam->outWritePos += bWr;
2277             nRc = PICOPAM_GOTO_FEED;
2278         }
2279 
2280         if (is_pam_command(qItem) == TRUE) {
2281             nRc = pamDoCommand(this, qItem); /*popped item is a PAM command : do it NOW!!*/
2282             if ((nRc == PICOPAM_FLUSH_RECEIVED) || (nRc == PICODATA_PU_ERROR)) {
2283                 /*FLUSH command RECEIVED or errors: stop ALL PROCESSING*/
2284                 return nRc;
2285             }
2286         }
2287         pam->nCurrAttachedItem++;
2288         if (nRc == 0)
2289             return PICOPAM_CONTINUE;
2290         else
2291             return nRc;
2292     }
2293     /*SBEG item management*/
2294     if ((qItem != NULL) && (qItem[0] == PICODATA_ITEM_BOUND) && (qItem[1]
2295             == PICODATA_ITEMINFO1_BOUND_SBEG)) {
2296         sResult = pam_put_qItem(qItem, pam->outBuf, pam->outWritePos, &bWr);
2297         pam->outWritePos += bWr;
2298         pam->nCurrAttachedItem++;
2299         nRc = PICOPAM_GOTO_FEED;
2300     }
2301     return nRc;
2302 }/*pamDoPreSyll*/
2303 
2304 /**
2305  * performs a step of the pam processing
2306  * @param    this : Pam item subobject pointer
2307  * @param    mode : mode for the PU
2308  * @param    *numBytesOutput : pointer to output number fo bytes produced
2309  * @return    PICODATA_PU_IDLE : nothing to do
2310  * @return    PICODATA_PU_BUSY : still tasks undergoing
2311  * @return    PICODATA_PU_ERROR : errors on processing
2312  * @callgraph
2313  * @callergraph
2314  */
pam_step(register picodata_ProcessingUnit this,picoos_int16 mode,picoos_uint16 * numBytesOutput)2315 static picodata_step_result_t pam_step(register picodata_ProcessingUnit this,
2316         picoos_int16 mode, picoos_uint16 * numBytesOutput)
2317 {
2318 
2319     register pam_subobj_t * pam;
2320 
2321     pico_status_t sResult;
2322     picoos_uint16 blen, numinb, numoutb;
2323     pico_status_t rv;
2324     picoos_uint8 bWr;
2325     picoos_uint8 bForcedItem[4];
2326     picoos_uint8 *qItem;
2327 
2328     numinb = 0;
2329     numoutb = 0;
2330     rv = PICO_OK;
2331 
2332     if (NULL == this || NULL == this->subObj) {
2333         return PICODATA_PU_ERROR;
2334     }
2335     pam = (pam_subobj_t *) this->subObj;
2336     mode = mode; /* avoid warning "var not used in this function"*/
2337     /*Init number of output bytes*/
2338     *numBytesOutput = 0;
2339 
2340     while (1) { /* exit via return */
2341 
2342         PICODBG_DEBUG(("pam_step -- doing state %i",pam->procState));
2343 
2344         switch (pam->procState) {
2345 
2346             case PICOPAM_COLLECT:
2347                 /* *************** item collector ***********************************/
2348                 /*collecting items from the PU input buffer*/
2349                 sResult = picodata_cbGetItem(this->cbIn,
2350                         &(pam->inBuf[pam->inWritePos]), pam->inBufSize
2351                                 - pam->inWritePos, &blen);
2352                 if (sResult != PICO_OK) {
2353                     if (sResult == PICO_EOF) {
2354                         /*no items available : remain in state 0 and return idle*/
2355                         return PICODATA_PU_IDLE;
2356                     } else {
2357                         /*errors : remain in state 0 and return error*/
2358                         PICODBG_DEBUG(("pam_step(PICOPAM_COLLECT) -- Errors on item buffer input, status: %d",sResult));
2359                         return PICODATA_PU_ERROR;
2360                     }
2361                 }
2362 
2363                 PICODBG_DEBUG(("pam_step -- got item, status: %d",sResult));
2364                 sResult = picodata_is_valid_item(
2365                         &(pam->inBuf[pam->inWritePos]), blen);
2366                 if (sResult != TRUE) {
2367                     /*input item is not valid : consume the input item and stay in COLLECT*/
2368                     pam->inWritePos += blen;
2369                     pam->inReadPos += blen;
2370                     if (pam->inReadPos >= pam->inWritePos) {
2371                         pam->inReadPos = 0;
2372                         pam->inWritePos = 0;
2373                     }PICODBG_DEBUG(("pam_step -- item is not valid, type: %d",pam->inBuf[pam->inWritePos]));
2374                     return PICODATA_PU_BUSY;
2375                 }
2376 
2377                 /*update input write pointer + move to "schedule" state*/
2378                 pam->inWritePos += blen;
2379                 pam->procState = PICOPAM_SCHEDULE;
2380                 return PICODATA_PU_BUSY;
2381 
2382             case PICOPAM_SCHEDULE:
2383                 /* check out if more items are available */
2384                 if (pam->inReadPos >= pam->inWritePos) {
2385                     /*no more items : back to collect state*/
2386                     pam->procState = PICOPAM_COLLECT;
2387                     return PICODATA_PU_BUSY;
2388                 }
2389                 /* we have one full valid item, with len>0 starting at
2390                  pam->inBuf[pam->inReadPos]; here we decide how to elaborate it */
2391 
2392                 /* PLAY management */
2393                 if (is_pam_play_command(&(pam->inBuf[pam->inReadPos])) == TRUE) {
2394                     /*consume the input item : it has been managed*/
2395                     pam->inReadPos += pam->inBuf[pam->inReadPos + 3]
2396                             + sizeof(picodata_itemhead_t);
2397                     if (pam->inReadPos >= pam->inWritePos) {
2398                         pam->inReadPos = 0;
2399                         pam->inWritePos = 0;
2400                     }
2401                     /*stay in schedule*/
2402                     return PICODATA_PU_BUSY;
2403                 }
2404 
2405                 if (pam_check_immediate(this, &(pam->inBuf[pam->inReadPos]))) {
2406                     /* item has to be sent to next PU NOW : switch to "immediate" state */
2407                     pam->procState = PICOPAM_IMMEDIATE;
2408                     return PICODATA_PU_BUSY;
2409                 }
2410                 if (pamCheckResourceLimits(this, &(pam->inBuf[pam->inReadPos]))) {
2411                     /* item would not fit into local buffers -->> free some space -->>
2412                      switch to "force term" state */
2413                     pam->procState = PICOPAM_FORWARD_FORCE_TERM;
2414                     return PICODATA_PU_BUSY;
2415                 }
2416 
2417                 if (pam_deal_with(&(pam->inBuf[pam->inReadPos]))) {
2418                     /* item has to be managed by the "forward" state : switch to forward state*/
2419                     pam->procState = PICOPAM_FORWARD;
2420                     return PICODATA_PU_BUSY;
2421                 }
2422 
2423                 if (pam_hastobe_queued(this, &(pam->inBuf[pam->inReadPos]))) {
2424                     /* item is not for PAM so it has to be queued internally */
2425                     pam_queue(this, &(pam->inBuf[pam->inReadPos]));
2426                     /*consume the input item : it has been queued*/
2427                     pam->inReadPos += pam->inBuf[pam->inReadPos + 3]
2428                             + sizeof(picodata_itemhead_t);
2429                     if (pam->inReadPos >= pam->inWritePos) {
2430                         pam->inReadPos = 0;
2431                         pam->inWritePos = 0;
2432                     }
2433                     return PICODATA_PU_BUSY;
2434                 }
2435                 /*if we get here something wrong happened. Being the the item valid,
2436                  switch to "immediate" state -> send it to next PU -> */
2437                 PICODBG_DEBUG(("pam_step (PICOPAM_SCHEDULE) -- unexpected item is sent to next PU !!"));
2438                 pam->procState = PICOPAM_IMMEDIATE;
2439                 return PICODATA_PU_BUSY;
2440                 break; /*PICOPAM_SCHEDULE*/
2441 
2442             case PICOPAM_FORWARD:
2443                 /*we have one full valid item, with len>0 starting at pam->inBuf[pam->inReadPos].
2444                  furthermore this item should be in the set {BOUND,SYLL}.
2445                  No other items should arrive here*/
2446                 sResult = pam_adapter_forward_step(this,
2447                         &(pam->inBuf[pam->inReadPos]));
2448                 /*decide if this item has to be queued for later re-synchronization
2449                  normally this is only done for SEND/TERM items*/
2450                 if (pam_hastobe_queued(this, &(pam->inBuf[pam->inReadPos]))) {
2451                     /*item has to be queued iternally in local storage*/
2452                     pam_queue(this, &(pam->inBuf[pam->inReadPos]));
2453                 }
2454                 /*now assign next state according to Forward results*/
2455                 switch (sResult) {
2456                     case PICOPAM_READY:
2457                         pam->needMoreInput = FALSE;
2458                         /*consume the input item : it has already been stored*/
2459                         pam->inReadPos += pam->inBuf[pam->inReadPos + 3]
2460                                 + sizeof(picodata_itemhead_t);
2461                         if (pam->inReadPos >= pam->inWritePos) {
2462                             pam->inReadPos = 0;
2463                             pam->inWritePos = 0;
2464                         }
2465                         /*activate backward processing*/
2466                         sResult = pam_adapter_backward_step(this);
2467                         if (sResult == PICO_OK) {
2468                             pam->procState = PICOPAM_PROCESS;
2469                             return PICODATA_PU_BUSY;
2470                         } else {
2471                             PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD) -- wrong return from BackwardStep: %d -- Buffered sentence will be discarded",sResult));
2472                             pam_reset_processors(this);
2473                             pam->nLastAttachedItemId = pam->nCurrAttachedItem
2474                                     = 0;
2475                             pam->nAttachedItemsSize = 0;
2476 
2477                             pam->procState = PICOPAM_SCHEDULE;
2478                             return PICODATA_PU_BUSY;
2479                         }
2480                         break;
2481 
2482                     case PICOPAM_MORE:
2483                         pam->needMoreInput = TRUE;
2484                         /*consume the input item : it has already been stored*/
2485                         pam->inReadPos += pam->inBuf[pam->inReadPos + 3]
2486                                 + sizeof(picodata_itemhead_t);
2487                         if (pam->inReadPos >= pam->inWritePos) {
2488                             /*input is finished and PAM need more data :
2489                              clenaup input buffer + switch state back to "schedule state"
2490                              */
2491                             pam->inReadPos = 0;
2492                             pam->inWritePos = 0;
2493                             pam->procState = PICOPAM_SCHEDULE;
2494                             return PICODATA_PU_ATOMIC;
2495                         } else {
2496                             /*input is not finished and need more data :
2497                              remain in state "PICOPAM_FORWARD" */
2498                             return PICODATA_PU_ATOMIC;
2499                         }
2500                         break;
2501 
2502                     case PICOPAM_NA:
2503                     default:
2504                         /*this item has not been stored in internal buffers:
2505                          assign this item to the management of
2506                          "immediate" state*/
2507                         pam->procState = PICOPAM_IMMEDIATE;
2508                         return PICODATA_PU_BUSY;
2509                         break;
2510                 } /*end switch sResult*/
2511                 break; /*PICOPAM_FORWARD*/
2512 
2513             case PICOPAM_FORWARD_FORCE_TERM:
2514                 /*we have one full valid item, with len>0
2515                  starting at pam->inBuf[pam->inReadPos] but we decided
2516                  to force a TERM item before, without losing the item in
2517                  inBuf[inReadPos] : --> generate a TERM item and do the
2518                  forward processing */
2519                 pam_put_term(bForcedItem, 0, &bWr);
2520                 sResult = pam_adapter_forward_step(this, &(bForcedItem[0]));
2521                 switch (sResult) {
2522                     case PICOPAM_READY:
2523                         pam_queue(this, &(bForcedItem[0]));
2524                         /*activate backward processing*/
2525                         sResult = pam_adapter_backward_step(this);
2526                         if (sResult == PICO_OK) {
2527                             pam->procState = PICOPAM_PROCESS;
2528                             return PICODATA_PU_BUSY;
2529                         } else {
2530                             PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD_FORCE_TERM) -- wrong return from BackwardStep: %d -- Buffered sentence will be discarded",sResult));
2531                             pam_reset_processors(this);
2532                             pam->nLastAttachedItemId = pam->nCurrAttachedItem
2533                                     = 0;
2534                             pam->nAttachedItemsSize = 0;
2535 
2536                             pam->procState = PICOPAM_SCHEDULE;
2537                             return PICODATA_PU_BUSY;
2538                         }
2539                         break;
2540 
2541                     default:
2542                         PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD_FORCE_TERM) -- Forced a TERM but processing do not appear to end -- Buffered sentence will be discarded",sResult));
2543                         pam_reset_processors(this);
2544                         pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0;
2545                         pam->nAttachedItemsSize = 0;
2546 
2547                         pam->procState = PICOPAM_SCHEDULE;
2548                         return PICODATA_PU_BUSY;
2549                         break;
2550 
2551                 } /*end switch sResult*/
2552                 break; /*PICOPAM_FORWARD_FORCE_TERM*/
2553 
2554             case PICOPAM_PROCESS:
2555 
2556                 if ((PICOPAM_FRAME_ITEM_SIZE + 4) > (pam->outBufSize
2557                         - pam->outWritePos)) {
2558                     /*WARNING (buffer overflow): leave status unchanged until output buffer free */
2559                     return PICODATA_PU_BUSY;
2560                 }
2561 
2562                 if (pam->nCurrSyllable == 0) {
2563                     sResult = pamDoPreSyll(this);
2564                     if (sResult == PICOPAM_GOTO_FEED) {
2565                         /*
2566                          items pushed to output buffer :
2567                          switch to "feed" but then back
2568                          to "process"
2569                          */
2570                         pam->retState = PICOPAM_PROCESS;
2571                         pam->procState = PICOPAM_FEED;
2572                         return PICODATA_PU_BUSY;
2573                     }
2574                     if (sResult == PICOPAM_CONTINUE) {
2575                         /*
2576                          items processed (maybe commands) :
2577                          return (maybe we need to process other
2578                          items in pre_syll) and then back to "process"
2579                          */
2580                         pam->retState = PICOPAM_PROCESS;
2581                         pam->procState = PICOPAM_PROCESS;
2582                         return PICODATA_PU_BUSY;
2583                     }
2584 
2585                     if ((sResult == PICOPAM_FLUSH_RECEIVED) || (sResult
2586                             == PICODATA_PU_ERROR)) {
2587                         /*
2588                          items processed were a flush or
2589                          problems found: switch to "schedule"
2590                          and abort all processing
2591                          */
2592                         pam->retState = PICOPAM_SCHEDULE;
2593                         pam->procState = PICOPAM_SCHEDULE;
2594                         return PICODATA_PU_BUSY;
2595                     }
2596                     if (sResult == PICOPAM_PRE_SYLL_ENDED) {
2597                         /*
2598                          we get here when     pam->nCurrSyllable==0 and
2599                          no more items to be processed before the syllable
2600                          */
2601                         sResult = sResult;
2602                     }
2603                 }
2604 
2605                 if (pamHasToProcess(this)) {
2606                     if (pamPhoneProcess(this) == PICO_OK) {
2607                         sResult = pamUpdateProcess(this);
2608                         pam->procState = PICOPAM_FEED; /*switch to feed*/
2609                         return PICODATA_PU_BUSY;
2610                     } else {
2611                         PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- NULL return from pamPhoneProcess"));
2612                         return PICODATA_PU_ERROR;
2613                     }
2614                 }
2615 
2616                 if (pamHasToPop(this) != FALSE) {
2617                     if ((qItem = pamPopItem(this)) == NULL) {
2618                         PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- NULL return from pamPopItem"));
2619                         return PICODATA_PU_ERROR;
2620                     }
2621 
2622                     if (isItemToPut(qItem)) {
2623                         /*popped item has to be sent to next PU*/
2624                         sResult = pam_put_qItem(qItem, pam->outBuf,
2625                                 pam->outWritePos, &bWr);
2626                         if (sResult != PICO_OK) {
2627                             PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- Error on writing item to output buffer"));
2628                             return PICODATA_PU_ERROR;
2629                         }
2630                         pam->outWritePos += bWr; /*item write ok*/
2631                         pam->procState = PICOPAM_FEED; /*switch to feed*/
2632                     }
2633 
2634                     /*moved command processing here (after pam_put_qItem) because of FLUSH command could erase
2635                      * the syllable structure and make it impossible to transmit the flush to other PUs*/
2636                     if (is_pam_command(qItem) == TRUE) {
2637                         sResult = pamDoCommand(this, qItem); /*popped item is a PAM command : do it NOW!!*/
2638                         if ((sResult == PICOPAM_FLUSH_RECEIVED) || (sResult
2639                                 == PICODATA_PU_ERROR)) {
2640                             pam->retState = PICOPAM_SCHEDULE;
2641                             pam->procState = PICOPAM_SCHEDULE; /*switch to schedule */
2642                             return PICODATA_PU_BUSY;
2643                         }
2644                     }
2645                     /*update PAM status: if more items attached to the current syllable
2646                      stay in current syllable, otherwise move to next syllable and switch
2647                      to processing phones */
2648                     sResult = pamUpdateProcess(this); /*both "doCommand" or "put" : update PAM status*/
2649                     return PICODATA_PU_BUSY;
2650                 } else {
2651                     pam->procState = PICOPAM_SCHEDULE; /*switch to schedule */
2652                     return PICODATA_PU_BUSY;
2653                 }
2654 
2655                 break; /*PICOPAM_PROCESS*/
2656 
2657             case PICOPAM_IMMEDIATE:
2658                 /* *** item is output NOW!!! */
2659                 /*context: full valid item, with len> starting at pam->inBuf[pam->inReadPos]*/
2660                 numinb = PICODATA_ITEM_HEADSIZE
2661                         + pam->inBuf[pam->inReadPos + 3];
2662                 sResult = picodata_copy_item(&(pam->inBuf[pam->inReadPos]),
2663                         numinb, &(pam->outBuf[pam->outWritePos]),
2664                         pam->outBufSize - pam->outWritePos, &numoutb);
2665 
2666                 if (sResult == PICO_OK) {
2667                     pam->inReadPos += numinb;
2668                     if (pam->inReadPos >= pam->inWritePos) {
2669                         pam->inReadPos = 0;
2670                         pam->inWritePos = 0;
2671                         pam->needMoreInput = FALSE;
2672                     }
2673                     pam->outWritePos += numoutb;
2674                     pam->procState = PICOPAM_FEED; /*switch to FEED state*/
2675                     pam->retState = PICOPAM_SCHEDULE; /*back to SCHEDULE after FEED*/
2676                 } else {
2677                     /*
2678                      PICO_EXC_BUF_IGNORE
2679                      PICO_EXC_BUF_UNDERFLOW
2680                      PICO_EXC_BUF_OVERFLOW
2681                      */
2682                     PICODBG_DEBUG(("pam_step(PICOPAM_IMMEDIATE) --- wrong return from picodata_copy_item:%d",sResult));
2683                     return PICODATA_PU_ERROR;
2684                 }
2685                 return PICODATA_PU_BUSY;
2686                 break; /*PICOPAM_IMMEDIATE*/
2687 
2688             case PICOPAM_FEED:
2689                 /* *************** item output/feeding ***********************************/
2690                 /*feeding items to PU output buffer*/
2691                 sResult = picodata_cbPutItem(this->cbOut,
2692                         &(pam->outBuf[pam->outReadPos]), pam->outWritePos
2693                                 - pam->outReadPos, &numoutb);
2694                 PICODBG_DEBUG(("pam_step -- put item, status: %d",sResult));
2695                 if (PICO_OK == sResult) {
2696 
2697                     PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG],
2698                             (picoos_uint8 *)"pam: ",
2699                             pam->outBuf + pam->outReadPos, pam->outBufSize);
2700 
2701                     pam->outReadPos += numoutb;
2702                     *numBytesOutput = numoutb;
2703                     if (pam->outReadPos >= pam->outWritePos) {
2704                         /*reset the output pointers*/
2705                         pam->outReadPos = 0;
2706                         pam->outWritePos = 0;
2707                         /*switch to appropriate state*/
2708                         switch (pam->retState) {
2709                             case PICOPAM_IMMEDIATE:
2710                                 pam->procState = PICOPAM_IMMEDIATE;
2711                                 pam->retState = PICOPAM_SCHEDULE;
2712                                 return PICODATA_PU_BUSY;
2713                                 break;
2714                             case PICOPAM_PLAY:
2715                                 pam->procState = PICOPAM_PLAY;
2716                                 pam->retState = PICOPAM_SCHEDULE;
2717                                 return PICODATA_PU_BUSY;
2718                                 break;
2719                             default:
2720                                 break;
2721                         }
2722                         /*Define next state
2723                          a)process (if current sentence has more data to process)
2724                          b)schedule (no more data to process in current sentence)
2725                          NOTE : case b)also happens when dealing with non BOUND/SYLL items*/
2726                         if ((pamHasToProcess(this)) || (pamHasToPop(this))) {
2727                             pam->procState = PICOPAM_PROCESS;
2728                         } else {
2729                             pam->nCurrSyllable = -1;
2730                             pam_reset_processors(this);
2731                             pam->nLastAttachedItemId = pam->nCurrAttachedItem
2732                                     = 0;
2733                             pam->nAttachedItemsSize = 0;
2734 
2735                             pam->nSyllPhoneme = 0;
2736                             pam->procState = PICOPAM_SCHEDULE;
2737                         }
2738                     }
2739                     return PICODATA_PU_BUSY;
2740 
2741                 } else if (PICO_EXC_BUF_OVERFLOW == sResult) {
2742 
2743                     PICODBG_DEBUG(("pam_step ** feeding, overflow, PICODATA_PU_OUT_FULL"));
2744                     return PICODATA_PU_OUT_FULL;
2745 
2746                 } else if ((PICO_EXC_BUF_UNDERFLOW == sResult)
2747                         || (PICO_ERR_OTHER == sResult)) {
2748 
2749                     PICODBG_DEBUG(("pam_step ** feeding problem, discarding item"));
2750                     pam->outReadPos = 0;
2751                     pam->outWritePos = 0;
2752                     pam->procState = PICOPAM_COLLECT;
2753                     return PICODATA_PU_ERROR;
2754 
2755                 }
2756                 break; /*PICOPAM_FEED*/
2757 
2758             default:
2759                 /*NOT feeding items*/
2760                 sResult = PICO_EXC_BUF_IGNORE;
2761                 break;
2762         }/*end switch*/
2763         return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/
2764 
2765     }/*end while*/
2766     return PICODATA_PU_IDLE;
2767 }/*pam_step*/
2768 
2769 /**
2770  * performs one step of a PamTree
2771  * @param    this : Pam item subobject pointer
2772  * @param    dtpam : the Pam decision tree
2773  * @param    *invec : the input vector pointer
2774  * @param    inveclen : length of the input vector
2775  * @param    *dtres : the classification result
2776  * @return    dtres->set : the result of tree traversal
2777  * @callgraph
2778  * @callergraph
2779  */
pam_do_tree(register picodata_ProcessingUnit this,const picokdt_DtPAM dtpam,const picoos_uint8 * invec,const picoos_uint8 inveclen,picokdt_classify_result_t * dtres)2780 static picoos_uint8 pam_do_tree(register picodata_ProcessingUnit this,
2781         const picokdt_DtPAM dtpam, const picoos_uint8 *invec,
2782         const picoos_uint8 inveclen, picokdt_classify_result_t *dtres)
2783 {
2784     picoos_uint8 okay;
2785 
2786     okay = TRUE;
2787     /* construct input vector, which is set in dtpam */
2788     if (!picokdt_dtPAMconstructInVec(dtpam, invec, inveclen)) {
2789         /* error constructing invec */
2790         PICODBG_WARN(("problem with invec"));
2791         picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, NULL, NULL);
2792         okay = FALSE;
2793     }
2794     /* classify */
2795     if (okay && (!picokdt_dtPAMclassify(dtpam))) {
2796         /* error doing classification */
2797         PICODBG_WARN(("problem classifying"));
2798         picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, NULL,
2799                 NULL);
2800         okay = FALSE;
2801     }
2802     /* decompose */
2803     if (okay && (!picokdt_dtPAMdecomposeOutClass(dtpam, dtres))) {
2804         /* error decomposing */
2805         PICODBG_WARN(("problem decomposing"));
2806         picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, NULL, NULL);
2807         okay = FALSE;
2808     }
2809 
2810     PICODBG_TRACE(("dtpam output class: %d", dtres->class));
2811 
2812     return dtres->set;
2813 }/*pam_do_tree*/
2814 
2815 /**
2816  * returns the carrier vowel id inside a syllable
2817  * @param    this : Pam item subobject pointer
2818  * @param    item : the full syllable item
2819  * @param    *pos : pointer to the variable to receive the position of the carrier vowel
2820  * @return    the phonetic id for the carrier vowel inside the syllable
2821  * @callgraph
2822  * @callergraph
2823  */
pam_get_vowel_name(register picodata_ProcessingUnit this,picoos_uint8 * item,picoos_uint8 * pos)2824 static picoos_uint8 pam_get_vowel_name(register picodata_ProcessingUnit this,
2825         picoos_uint8 *item, picoos_uint8 *pos)
2826 {
2827     pam_subobj_t *pam;
2828     picoos_uint8 *phon, nI, nCond1;
2829     if (NULL == this || NULL == this->subObj) {
2830         return 0;
2831     }
2832     pam = (pam_subobj_t *) this->subObj;
2833 
2834     if (item == NULL)
2835         return 0;
2836     if (item[3] == 0)
2837         return 0;
2838     phon = &item[4];
2839     for (nI = 0; nI < item[3]; nI++) {
2840         nCond1 = picoktab_isSyllCarrier(pam->tabphones, phon[nI]);
2841         if (nCond1) {
2842             *pos = nI;
2843             return phon[nI];
2844         }
2845     }
2846     return 0;
2847 }/*pam_get_vowel_name */
2848 
2849 /**
2850  * returns the pause phone id in the current ph.alphabet
2851  * @param    this : Pam sub object pointer
2852  * @return    the (numeric) phonetic id of the pause phone in current phonetic alphabet
2853  * @return    0 :  errors on getting the pam subobject pointer
2854  * @callgraph
2855  * @callergraph
2856  */
pam_get_pause_id(register picodata_ProcessingUnit this)2857 static picoos_uint8 pam_get_pause_id(register picodata_ProcessingUnit this)
2858 {
2859     picoos_uint8 nVal1;
2860     /*picoos_uint8 nVal2; */
2861     pam_subobj_t *pam;
2862     if (NULL == this || NULL == this->subObj) {
2863         return 0;
2864     }
2865     pam = (pam_subobj_t *) this->subObj;
2866     nVal1 = picoktab_getPauseID(pam->tabphones);
2867     return nVal1;
2868 }/*pam_get_pause_id */
2869 
2870 /**
2871  * returns the pam sentence type (declarative, interrogative...)
2872  * @param    iteminfo1 : the boundary item info 1
2873  * @param    iteminfo2 : the boundary item info 2
2874  * @return    the sentence type suitably encoded for trees
2875  * @callgraph
2876  * @callergraph
2877  */
pam_map_sentence_type(picoos_uint8 iteminfo1,picoos_uint8 iteminfo2)2878 static picoos_uint8 pam_map_sentence_type(picoos_uint8 iteminfo1,
2879         picoos_uint8 iteminfo2)
2880 {
2881     switch (iteminfo2) {
2882         case PICODATA_ITEMINFO2_BOUNDTYPE_P:
2883             return PICOPAM_DECLARATIVE;
2884         case PICODATA_ITEMINFO2_BOUNDTYPE_T:
2885             return PICOPAM_DECLARATIVE;
2886         case PICODATA_ITEMINFO2_BOUNDTYPE_Q:
2887             return PICOPAM_INTERROGATIVE;
2888         case PICODATA_ITEMINFO2_BOUNDTYPE_E:
2889             return PICOPAM_DECLARATIVE;
2890         default:
2891             return PICOPAM_DECLARATIVE;
2892     }
2893     iteminfo1 = iteminfo1; /* avoid warning "var not used in this function"*/
2894     return PICOPAM_DECLARATIVE;
2895 }/*pam_map_sentence_type */
2896 
2897 /**
2898  * returns the pam phrase type
2899  * @param    iteminfo1 : the boundary item info 1
2900  * @param    iteminfo2 : the boundary item info 2
2901  * @return    the phrase type suitably encoded for trees
2902  * @callgraph
2903  * @callergraph
2904  */
pam_map_phrase_type(picoos_uint8 iteminfo1,picoos_uint8 iteminfo2)2905 static picoos_uint8 pam_map_phrase_type(picoos_uint8 iteminfo1,
2906         picoos_uint8 iteminfo2)
2907 {
2908 
2909     switch (iteminfo2) {
2910         case PICODATA_ITEMINFO2_BOUNDTYPE_P:
2911             switch (iteminfo1) {
2912                 case PICODATA_ITEMINFO1_BOUND_PHR1:
2913 #                ifdef PAM_PHR2_WITH_PR1
2914                 case PICODATA_ITEMINFO1_BOUND_PHR2:
2915 #                endif
2916                     return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */
2917                     break;
2918                 case PICODATA_ITEMINFO1_BOUND_PHR3:
2919 #                ifdef PAM_PHR2_WITH_PR3
2920                     case PICODATA_ITEMINFO1_BOUND_PHR2 :
2921 #                endif
2922                     return PICOPAM_p; /*current_prhase type = "p" (encoded to 2) */
2923                     break;
2924                 case PICODATA_ITEMINFO1_BOUND_SBEG:
2925                     return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */
2926                     break;
2927                 default:
2928                     PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo1"));
2929                     return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */
2930                     break;
2931             }
2932         case PICODATA_ITEMINFO2_BOUNDTYPE_T:
2933             return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */
2934             break;
2935         case PICODATA_ITEMINFO2_BOUNDTYPE_E:
2936             return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */
2937             break;
2938         case PICODATA_ITEMINFO2_BOUNDTYPE_Q:
2939             return PICOPAM_Y; /*current_prhase type = "T" (encoded to 0) */
2940             break;
2941         default:
2942             PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo2"));
2943             return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */
2944             break;
2945     }PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo2"));
2946     return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */
2947 
2948 }/*pam_map_phrase_type */
2949 
2950 /**
2951  * does the cleanup of the sub object processors flags at sentence start
2952  * @param    this : pointer to PAM PU sub object pointer
2953  * @return    PICO_OK : reset OK
2954  * @return    PICO_ERR_OTHER : errors on getting pam sub obj pointer
2955  * @callgraph
2956  * @callergraph
2957  */
pam_reset_processors(register picodata_ProcessingUnit this)2958 static pico_status_t pam_reset_processors(register picodata_ProcessingUnit this)
2959 {
2960     pam_subobj_t *pam;
2961     if (NULL == this || NULL == this->subObj) {
2962         return PICO_ERR_OTHER;
2963     }
2964     pam = (pam_subobj_t *) this->subObj;
2965 
2966     pam->nCurrSyllable = -1;
2967     pam->nTotalPhonemes = pam->nSyllPhoneme = pam->nCurrPhoneme
2968             = pam->nTotalSyllables = pam->sType = pam->pType = 0;
2969     pam->dRest = 0.0f;
2970     /*set all to 0*/
2971     pam->a3_overall_syllable    = pam->a3_primary_phrase_syllable   = pam->b4_b5_syllable =
2972         pam->b6_b7_syllable     = pam->b6_b7_state                  = pam->b8_b9_stressed_syllable =
2973         pam->b10_b11_accented_syllable  = pam->b12_b13_syllable     = pam->b12_b13_state =
2974         pam->b14_b15_syllable   = pam->b14_b15_state                = pam->b17_b19_syllable =
2975         pam->b17_b19_state      = pam->b18_b20_b21_syllable         = pam->b18_b20_b21_state =
2976         pam->c3_overall_syllable= pam->c3_primary_phrase_syllable   = pam->d2_syllable_in_word =
2977         pam->d2_prev_syllable_in_word = pam->d2_current_primary_phrase_word = pam->e1_syllable_word_start =
2978         pam->e1_syllable_word_end= pam->e1_content                  = pam->e2_syllable_word_start =
2979         pam->e2_syllable_word_end= pam->e3_e4_word                  = pam->e3_e4_state =
2980         pam->e5_e6_content_word = pam->e5_e6_content                = pam->e7_e8_word =
2981         pam->e7_e8_content      = pam->e7_e8_state                  = pam->e9_e11_word =
2982         pam->e9_e11_saw_word    = pam->e9_e11_state                 = pam->e10_e12_e13_word =
2983         pam->e10_e12_e13_state  = pam->e10_e12_e13_saw_word         = pam->f2_overall_word =
2984         pam->f2_word_syllable   = pam->f2_next_word_syllable        = pam->f2_current_primary_phrase_word =
2985         pam->g1_current_secondary_phrase_syllable                   = pam->g1_current_syllable =
2986         pam->g2_current_secondary_phrase_word                       = pam->g2_current_word =
2987         pam->h1_current_secondary_phrase_syll                       = pam->h2_current_secondary_phrase_word =
2988         pam->h3_h4_current_secondary_phrase_word                    = pam->h5_current_phrase_type =
2989         pam->h5_syllable        = pam->h5_state                     = pam->i1_secondary_phrase_syllable =
2990         pam->i1_next_secondary_phrase_syllable                      = pam->i2_secondary_phrase_word =
2991         pam->i2_next_secondary_phrase_word                          = pam->j1_utterance_syllable =
2992         pam->j2_utterance_word  = pam->j3_utterance_sec_phrases     = 0;
2993     /*Override 0 with 1*/
2994     pam->b4_b5_syllable         = pam->b17_b19_syllable             = pam->b18_b20_b21_syllable =
2995         pam->e9_e11_word        = pam->e10_e12_e13_word             = pam->e7_e8_word =
2996         pam->h2_current_secondary_phrase_word                       = 1;
2997     /*Override 0 with -1*/
2998     pam->e1_syllable_word_start = pam->e1_syllable_word_end         = pam->e2_syllable_word_start =
2999         pam->e2_syllable_word_end                                   = -1;
3000 
3001     return PICO_OK;
3002 }/*pam_reset_processors*/
3003 
3004 /**
3005  * does the cleanup of the sub object processors flags before the backward step
3006  * @param    this : pointer to PAM PU sub object pointer
3007  * @return    PICO_OK : reset OK
3008  * @return    PICO_ERR_OTHER : errors on getting pam sub obj pointer
3009  * @callgraph
3010  * @callergraph
3011  */
pam_reset_processors_back(register picodata_ProcessingUnit this)3012 static pico_status_t pam_reset_processors_back(
3013         register picodata_ProcessingUnit this)
3014 {
3015     pam_subobj_t *pam;
3016     if (NULL == this || NULL == this->subObj) {
3017         return PICO_ERR_OTHER;
3018     }
3019     pam = (pam_subobj_t *) this->subObj;
3020 
3021     /*set all to 0*/
3022     pam->a3_overall_syllable
3023         = pam->a3_primary_phrase_syllable
3024         = pam->b4_b5_syllable
3025         = pam->b6_b7_syllable
3026         = pam->b6_b7_state
3027         = pam->b8_b9_stressed_syllable
3028         = pam->b10_b11_accented_syllable
3029         = pam->b12_b13_syllable
3030         = pam->b12_b13_state
3031         = pam->b14_b15_syllable
3032         = pam->b14_b15_state
3033         = pam->b17_b19_syllable
3034         = pam->b17_b19_state
3035         = pam->b18_b20_b21_syllable
3036         = pam->b18_b20_b21_state
3037         = pam->c3_overall_syllable
3038         = pam->c3_primary_phrase_syllable
3039         = pam->d2_syllable_in_word
3040         = pam->d2_prev_syllable_in_word
3041         = pam->d2_current_primary_phrase_word
3042         = pam->e1_syllable_word_start
3043         = pam->e1_syllable_word_end
3044         = pam->e1_content
3045         = pam->e2_syllable_word_start
3046         = pam->e2_syllable_word_end
3047         = pam->e3_e4_word
3048         = pam->e3_e4_state
3049         = pam->e5_e6_content_word
3050         = pam->e5_e6_content
3051         = pam->e7_e8_word
3052         = pam->e7_e8_content
3053         = pam->e7_e8_state
3054         = pam->e9_e11_word
3055         = pam->e9_e11_saw_word
3056         = pam->e9_e11_state
3057         = pam->e10_e12_e13_word
3058         = pam->e10_e12_e13_state
3059         = pam->e10_e12_e13_saw_word
3060         = pam->f2_overall_word
3061         = pam->f2_word_syllable
3062         = pam->f2_next_word_syllable
3063         = pam->f2_current_primary_phrase_word
3064         = pam->g1_current_secondary_phrase_syllable
3065         = pam->g1_current_syllable
3066         = pam->g2_current_secondary_phrase_word
3067         = pam->g2_current_word
3068         = pam->h1_current_secondary_phrase_syll
3069         = pam->h2_current_secondary_phrase_word
3070         = pam->h3_h4_current_secondary_phrase_word
3071         = pam->h5_current_phrase_type
3072         = pam->h5_state
3073         = pam->i1_secondary_phrase_syllable
3074         = pam->i1_next_secondary_phrase_syllable
3075         = pam->i2_secondary_phrase_word
3076         = pam->i2_next_secondary_phrase_word
3077         = 0;
3078     /*Override 0 with 1*/
3079     pam->b4_b5_syllable = pam->b17_b19_syllable = pam->b18_b20_b21_syllable
3080         = pam->e9_e11_word = pam->e10_e12_e13_word = pam->e7_e8_word
3081         = pam->h2_current_secondary_phrase_word = 1;
3082     /*Override 0 with -1*/
3083     pam->e1_syllable_word_start = pam->e1_syllable_word_end
3084         = pam->e2_syllable_word_start = pam->e2_syllable_word_end = -1;
3085 
3086     return PICO_OK;
3087 }/*pam_reset_processors_back*/
3088 
3089 /**
3090  * processes an input event for a specific feature
3091  * @param    this : pointer to PAM PU sub object pointer
3092  * @param    nFeat : feature column to process
3093  * @param    event_type : event id among syll/boundprim/boundsec/boundword
3094  * @param    direction : forward(0)/backward(1)
3095  * @return    PICO_OK : process OK
3096  * @return    PICO_ERR_OTHER : errors on getting pam sub obj pointer
3097  * @callgraph
3098  * @callergraph
3099  */
pam_process_event_feature(register picodata_ProcessingUnit this,picoos_uint8 nFeat,picoos_uint8 event_type,picoos_uint8 direction)3100 static pico_status_t pam_process_event_feature(
3101         register picodata_ProcessingUnit this, picoos_uint8 nFeat,
3102         picoos_uint8 event_type, picoos_uint8 direction)
3103 {
3104     picoos_uint8 sDest, nI;
3105     picoos_uint16 syllCurr;
3106     pam_subobj_t *pam;
3107     if (NULL == this || NULL == this->subObj) {
3108         return PICO_ERR_OTHER;
3109     }
3110     pam = (pam_subobj_t *) this->subObj;
3111     syllCurr = pam->nCurrSyllable;
3112     switch (nFeat) {
3113         case A3:
3114             /*processor for A3*/
3115             switch (direction) {
3116                 case PICOPAM_DIR_FORW:
3117                     if (event_type == PICOPAM_EVENT_SYLL) {
3118                         if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1]
3119                                 == 1) || (pam->a3_primary_phrase_syllable >= 1)) {
3120                             if (pam->a3_overall_syllable < 1)
3121                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3]
3122                                         = 0;
3123                             else
3124                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3]
3125                                         = pam->sSyllFeats[pam->nCurrSyllable
3126                                                 - 1].phoneV[B3];
3127                         } else {
3128                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] = 0;
3129                         }
3130                         pam->a3_primary_phrase_syllable++;
3131                         pam->a3_overall_syllable++;
3132                     }
3133                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3134                         pam->a3_primary_phrase_syllable = 0;
3135                     }
3136                     break;
3137                 case PICOPAM_DIR_BACK:
3138                     /*do nothing*/
3139                     break;
3140             }
3141             break;
3142         case B1:
3143         case B2:
3144         case B3:
3145             /*done in createSyllable*/
3146             break;
3147         case B4:/*processor for B4,B5*/
3148             switch (direction) {
3149                 case PICOPAM_DIR_FORW:
3150                     sDest = B4;
3151                     break;
3152                 case PICOPAM_DIR_BACK:
3153                     sDest = B5;
3154                     break;
3155                 default:
3156                     sDest = B4;
3157                     break;
3158             }
3159             if (event_type == PICOPAM_EVENT_SYLL) {
3160                 if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] == 0) {
3161                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3162                             = pam->b4_b5_syllable;
3163                     pam->b4_b5_syllable++;
3164                 } else {
3165                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] = 0;
3166                 }
3167             }
3168             if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
3169                     == PICOPAM_EVENT_S_BOUND) || (event_type
3170                     == PICOPAM_EVENT_P_BOUND)) {
3171                 pam->b4_b5_syllable = 1;
3172             }
3173             break;
3174         case B5:/*processor for B5 : done in B4*/
3175             break;
3176         case B6:/*processor for B6,B7*/
3177             switch (direction) {
3178                 case PICOPAM_DIR_FORW:
3179                     sDest = B6;
3180                     break;
3181                 case PICOPAM_DIR_BACK:
3182                     sDest = B7;
3183                     break;
3184                 default:
3185                     sDest = B6;
3186                     break;
3187             }
3188             switch (pam->b6_b7_state) {
3189                 case 0:
3190                     if (event_type == PICOPAM_EVENT_SYLL)
3191                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3192                                 = PICOPAM_DONT_CARE_VALUE;
3193                     if (event_type == PICOPAM_EVENT_S_BOUND) {
3194                         pam->b6_b7_syllable = 1;
3195                         pam->b6_b7_state = 1;
3196                     }
3197                     break;
3198                 case 1:
3199                     if (event_type == PICOPAM_EVENT_SYLL) {
3200                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3201                                 = pam->b6_b7_syllable;
3202                         pam->b6_b7_syllable++;
3203                     }
3204                     if (event_type == PICOPAM_EVENT_S_BOUND) {
3205                         pam->b6_b7_syllable = 1;
3206                     }
3207                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3208                         pam->b6_b7_state = 0;
3209                     }
3210                     break;
3211                 default:
3212                     break;
3213             }
3214             break;
3215         case B7:/*Done in B6*/
3216             break;
3217         case B8:/*processor for B8,B9*/
3218             switch (direction) {
3219                 case PICOPAM_DIR_FORW:
3220                     sDest = B8;
3221                     break;
3222                 case PICOPAM_DIR_BACK:
3223                     sDest = B9;
3224                     break;
3225                 default:
3226                     sDest = B8;
3227                     break;
3228             }
3229             if (event_type == PICOPAM_EVENT_SYLL) {
3230                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3231                         = pam->b8_b9_stressed_syllable;
3232                 if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1)
3233                     pam->b8_b9_stressed_syllable++;
3234             }
3235             if (event_type == PICOPAM_EVENT_P_BOUND) {
3236                 pam->b8_b9_stressed_syllable = 0;
3237             }
3238 
3239             break;
3240         case B9:/*done in B8*/
3241             break;
3242         case B10:/*processor for B10, B11*/
3243             switch (direction) {
3244                 case PICOPAM_DIR_FORW:
3245                     sDest = B10;
3246                     break;
3247                 case PICOPAM_DIR_BACK:
3248                     sDest = B11;
3249                     break;
3250                 default:
3251                     sDest = B10;
3252                     break;
3253             }
3254             if (event_type == PICOPAM_EVENT_SYLL) {
3255                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3256                         = pam->b10_b11_accented_syllable;
3257                 if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1)
3258                     pam->b10_b11_accented_syllable++;
3259             }
3260             if (event_type == PICOPAM_EVENT_P_BOUND) {
3261                 pam->b10_b11_accented_syllable = 0;
3262             }
3263             break;
3264         case B11:/*done in B10*/
3265             break;
3266         case B12:/*processor for B12,B13*/
3267             switch (direction) {
3268                 case PICOPAM_DIR_FORW:
3269                     sDest = B12;
3270                     break;
3271                 case PICOPAM_DIR_BACK:
3272                     sDest = B13;
3273                     break;
3274                 default:
3275                     sDest = B12;
3276                     break;
3277             }
3278             switch (pam->b12_b13_state) {
3279                 case 0:
3280                     if (event_type == PICOPAM_EVENT_SYLL) {
3281                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 0)
3282                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3283                                     = PICOPAM_DONT_CARE_VALUE;
3284                         else {
3285                             pam->b12_b13_syllable = 0;
3286                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3287                                     = PICOPAM_DONT_CARE_VALUE;
3288                             pam->b12_b13_state = 1;
3289                         }
3290                     }
3291                     break;
3292                 case 1:
3293                     if (event_type == PICOPAM_EVENT_SYLL) {
3294                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3295                                 = pam->b12_b13_syllable;
3296                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1)
3297                             pam->b12_b13_syllable = 0;
3298                         else
3299                             pam->b12_b13_syllable++;
3300                         pam->b12_b13_state = 2;
3301                     }
3302                     if (event_type == PICOPAM_EVENT_P_BOUND)
3303                         pam->b12_b13_state = 0;
3304                     break;
3305                 case 2:
3306                     if (event_type == PICOPAM_EVENT_SYLL) {
3307                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3308                                 = pam->b12_b13_syllable;
3309                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1)
3310                             pam->b12_b13_syllable = 0;
3311                         else
3312                             pam->b12_b13_syllable++;
3313                     }
3314                     if (event_type == PICOPAM_EVENT_P_BOUND)
3315                         pam->b12_b13_state = 0;
3316 
3317                     break;
3318                 default:
3319                     break;
3320             }
3321             break;
3322         case B13:/*done in B12*/
3323             break;
3324 
3325         case B14:/*processor for B14, B15*/
3326             switch (direction) {
3327                 case PICOPAM_DIR_FORW:
3328                     sDest = B14;
3329                     break;
3330                 case PICOPAM_DIR_BACK:
3331                     sDest = B15;
3332                     break;
3333                 default:
3334                     sDest = B14;
3335                     break;
3336             }
3337             switch (pam->b14_b15_state) {
3338                 case 0:
3339                     if (event_type == PICOPAM_EVENT_SYLL) {
3340                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 0)
3341                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3342                                     = PICOPAM_DONT_CARE_VALUE;
3343                         else {
3344                             pam->b14_b15_syllable = 0;
3345                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3346                                     = PICOPAM_DONT_CARE_VALUE;
3347                             pam->b14_b15_state = 1;
3348                         }
3349                     }
3350                     break;
3351                 case 1:
3352                     if (event_type == PICOPAM_EVENT_SYLL) {
3353                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3354                                 = pam->b14_b15_syllable;
3355                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1)
3356                             pam->b14_b15_syllable = 0;
3357                         else
3358                             pam->b14_b15_syllable++;
3359                         pam->b14_b15_state = 2;
3360                     }
3361                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3362                         pam->b14_b15_state = 0;
3363                     }
3364                     break;
3365                 case 2:
3366                     if (event_type == PICOPAM_EVENT_SYLL) {
3367                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3368                                 = pam->b14_b15_syllable;
3369                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1)
3370                             pam->b14_b15_syllable = 0;
3371                         else
3372                             pam->b14_b15_syllable++;
3373                     }
3374                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3375                         pam->b14_b15_state = 0;
3376                     }
3377                     break;
3378                 default:
3379                     break;
3380             }
3381             break;
3382         case B15:/*Processor for B15 : done in B14*/
3383             break;
3384         case B16:/*done in createSyllable*/
3385             break;
3386         case B17:/*processor for B17, B19 unified */
3387             switch (direction) {
3388                 case PICOPAM_DIR_FORW:
3389                     switch (pam->b17_b19_state) {
3390                         case 0:
3391                             if (event_type == PICOPAM_EVENT_SYLL) {
3392                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17]
3393                                         = PICOPAM_DONT_CARE_VALUE;
3394                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19]
3395                                         = pam->b17_b19_syllable;
3396                                 pam->b17_b19_syllable++;
3397                             }
3398                             if (((event_type == PICOPAM_EVENT_P_BOUND)
3399                                     || (event_type == PICOPAM_EVENT_S_BOUND))
3400                                     && (pam->b17_b19_syllable > 1)) {
3401                                 if (event_type == PICOPAM_EVENT_P_BOUND)
3402                                     pam->b17_b19_syllable = 1;
3403                                 pam->b17_b19_state = 1;
3404                             }
3405                             break;
3406                         case 1:
3407                             if (event_type == PICOPAM_EVENT_SYLL) {
3408                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17]
3409                                         = pam->b17_b19_syllable;
3410                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19]
3411                                         = PICOPAM_DONT_CARE_VALUE;
3412                                 pam->b17_b19_syllable++;
3413                             }
3414                             if (event_type == PICOPAM_EVENT_P_BOUND) {
3415                                 pam->b17_b19_syllable = 1;
3416                             }
3417                             break;
3418                         default:
3419                             break;
3420                     }
3421                     break;
3422                 case PICOPAM_DIR_BACK:
3423                     /*do nothing*/
3424                     break;
3425             }
3426             break;
3427         case B18:/*processor for B18, B20, B21 unfied*/
3428             switch (direction) {
3429                 case PICOPAM_DIR_FORW:/*do nothing*/
3430                     break;
3431                 case PICOPAM_DIR_BACK:
3432                     switch (pam->b18_b20_b21_state) {
3433                         case 0:
3434                             if (event_type == PICOPAM_EVENT_SYLL) {
3435                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18]
3436                                         = PICOPAM_DONT_CARE_VALUE;
3437                                 if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6]
3438                                         == PICOPAM_DECLARATIVE) {
3439                                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20]
3440                                             = pam->b18_b20_b21_syllable;
3441                                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21]
3442                                             = PICOPAM_DONT_CARE_VALUE;
3443                                 } else {
3444                                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20]
3445                                             = PICOPAM_DONT_CARE_VALUE;
3446                                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21]
3447                                             = pam->b18_b20_b21_syllable;
3448                                 }
3449                                 pam->b18_b20_b21_syllable++;
3450                             }
3451                             if (((event_type == PICOPAM_EVENT_P_BOUND)
3452                                     || (event_type == PICOPAM_EVENT_S_BOUND))
3453                                     && (pam->b18_b20_b21_syllable > 1)) {
3454                                 if (event_type == PICOPAM_EVENT_P_BOUND)
3455                                     pam->b18_b20_b21_syllable = 1;
3456                                 pam->b18_b20_b21_state = 1;
3457                             }
3458                             break;
3459                         case 1:
3460                             if (event_type == PICOPAM_EVENT_SYLL) {
3461                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18]
3462                                         = pam->b18_b20_b21_syllable;
3463                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20]
3464                                         = PICOPAM_DONT_CARE_VALUE;
3465                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21]
3466                                         = PICOPAM_DONT_CARE_VALUE;
3467                                 pam->b18_b20_b21_syllable++;
3468                             }
3469                             if (event_type == PICOPAM_EVENT_P_BOUND) {
3470                                 pam->b18_b20_b21_syllable = 1;
3471                             }
3472                             break;
3473                         default:
3474                             break;
3475                     }
3476                     break;
3477             }
3478             break;
3479         case B19:/*processor for B19 : done in B17*/
3480             break;
3481         case B20:/*processor for B20 : done in B18*/
3482             break;
3483         case B21:/*processor for B21 : done in B18*/
3484             break;
3485         case C3:/*processor for C3*/
3486             switch (direction) {
3487                 case PICOPAM_DIR_FORW:
3488                     /*do nothing*/
3489                     break;
3490                 case PICOPAM_DIR_BACK:
3491                     if (event_type == PICOPAM_EVENT_SYLL) {
3492                         if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1]
3493                                 == 1) || (pam->c3_primary_phrase_syllable >= 1)) {
3494                             if (pam->c3_overall_syllable < 1)
3495                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3]
3496                                         = 0;
3497                             else
3498                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3]
3499                                         = pam->sSyllFeats[pam->nCurrSyllable
3500                                                 + 1].phoneV[B3];
3501                         } else {
3502                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] = 0;
3503                         }
3504                         pam->c3_primary_phrase_syllable++;
3505                         pam->c3_overall_syllable++;
3506                     }
3507                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3508                         pam->c3_primary_phrase_syllable = 0;
3509                     }
3510                     break;
3511             }
3512             break;
3513         case D2:/*processor for D2*/
3514             switch (direction) {
3515                 case PICOPAM_DIR_FORW:
3516                     if (event_type == PICOPAM_EVENT_SYLL) {
3517                         if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1]
3518                                 == 1) || (pam->d2_current_primary_phrase_word
3519                                 >= 1))
3520                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2]
3521                                     = pam->d2_prev_syllable_in_word;
3522                         else
3523                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] = 0;
3524 
3525                         pam->d2_syllable_in_word++;
3526                     }
3527                     if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
3528                             == PICOPAM_EVENT_S_BOUND) || (event_type
3529                             == PICOPAM_EVENT_P_BOUND)) {
3530                         pam->d2_current_primary_phrase_word = 1;
3531                         pam->d2_prev_syllable_in_word
3532                                 = pam->d2_syllable_in_word;
3533                         pam->d2_syllable_in_word = 0;
3534                         /*pam->d2_current_primary_phrase_word++;*/
3535                     }
3536                     if ((event_type == PICOPAM_EVENT_P_BOUND)) {
3537                         pam->d2_current_primary_phrase_word = 0;
3538                     }
3539                     break;
3540                 case PICOPAM_DIR_BACK:
3541                     /*do nothing*/
3542                     break;
3543             }
3544             break;
3545         case E1:/*processor for E1*/
3546             switch (direction) {
3547                 case PICOPAM_DIR_FORW: /*remember : content syllable indicator already on P5*/
3548                     if (event_type == PICOPAM_EVENT_SYLL) {
3549                         if (pam->e1_syllable_word_start == -1)
3550                             pam->e1_syllable_word_start
3551                                     = (picoos_int8) pam->nCurrSyllable;
3552                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1)
3553                             pam->e1_content = 1;
3554                         pam->e1_syllable_word_end
3555                                 = (picoos_int8) pam->nCurrSyllable;
3556                     }
3557                     if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
3558                             == PICOPAM_EVENT_S_BOUND) || (event_type
3559                             == PICOPAM_EVENT_P_BOUND)) {
3560                         if ((pam->e1_syllable_word_start != -1)
3561                                 && (pam->e1_syllable_word_end != -1)) {
3562                             for (nI = pam->e1_syllable_word_start; nI
3563                                     <= pam->e1_syllable_word_end; nI++)
3564                                 pam->sSyllFeats[nI].phoneV[E1]
3565                                         = pam->e1_content;
3566                         }
3567                         pam->e1_content = 0;
3568                         pam->e1_syllable_word_start = -1;
3569                         pam->e1_syllable_word_end = -1;
3570                     }
3571                     break;
3572                 case PICOPAM_DIR_BACK:
3573                     /*do nothing*/
3574                     break;
3575             }
3576             break;
3577         case E2:/*processor for E2*/
3578             switch (direction) {
3579                 case PICOPAM_DIR_FORW:
3580                     if (event_type == PICOPAM_EVENT_SYLL) {
3581                         if (pam->e2_syllable_word_start == -1)
3582                             pam->e2_syllable_word_start
3583                                     = (picoos_int8) pam->nCurrSyllable;
3584                         pam->e2_syllable_word_end
3585                                 = (picoos_int8) pam->nCurrSyllable;
3586                     }
3587                     if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
3588                             == PICOPAM_EVENT_S_BOUND) || (event_type
3589                             == PICOPAM_EVENT_P_BOUND)) {
3590                         if ((pam->e2_syllable_word_start != -1)
3591                                 && (pam->e2_syllable_word_end != -1)) {
3592                             for (nI = pam->e2_syllable_word_start; nI
3593                                     <= pam->e2_syllable_word_end; nI++)
3594                                 pam->sSyllFeats[nI].phoneV[E2]
3595                                         = pam->e2_syllable_word_end
3596                                                 - pam->e2_syllable_word_start
3597                                                 + 1;
3598                         }
3599                         pam->e1_content = 0;
3600                         pam->e2_syllable_word_start = -1;
3601                         pam->e2_syllable_word_end = -1;
3602                     }
3603                     break;
3604                 case PICOPAM_DIR_BACK:
3605                     break;
3606             }
3607             break;
3608         case E3:/*processor for E3,E4*/
3609             switch (direction) {
3610                 case PICOPAM_DIR_FORW:
3611                     sDest = E3;
3612                     break;
3613                 case PICOPAM_DIR_BACK:
3614                     sDest = E4;
3615                     break;
3616                 default:
3617                     sDest = E3;
3618                     break;
3619             }
3620             switch (pam->e3_e4_state) {
3621                 case 0:
3622                     if (event_type == PICOPAM_EVENT_SYLL)
3623                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3624                                 = PICOPAM_DONT_CARE_VALUE;
3625                     if (event_type == PICOPAM_EVENT_S_BOUND) {
3626                         pam->e3_e4_word = 1;
3627                         pam->e3_e4_state = 1;
3628                     }
3629                     break;
3630                 case 1:
3631                     if (event_type == PICOPAM_EVENT_SYLL)
3632                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3633                                 = pam->e3_e4_word;
3634                     if (event_type == PICOPAM_EVENT_S_BOUND)
3635                         pam->e3_e4_word = 1;
3636                     if (event_type == PICOPAM_EVENT_W_BOUND)
3637                         pam->e3_e4_word++;
3638                     if (event_type == PICOPAM_EVENT_P_BOUND)
3639                         pam->e3_e4_state = 0;
3640                     break;
3641                 default:
3642                     break;
3643             }
3644             break;
3645         case E4:/*processor for E4 : done in E3*/
3646             break;
3647         case E5:/*processor for E5,E6*/
3648             switch (direction) {
3649                 case PICOPAM_DIR_FORW:
3650                     sDest = E5;
3651                     break;
3652                 case PICOPAM_DIR_BACK:
3653                     sDest = E6;
3654                     break;
3655                 default:
3656                     sDest = E5;
3657                     break;
3658             }
3659             if (event_type == PICOPAM_EVENT_SYLL) {
3660                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3661                         = pam->e5_e6_content_word;
3662                 if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1)
3663                     pam->e5_e6_content = 1;
3664             }
3665             if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
3666                     == PICOPAM_EVENT_S_BOUND) || (event_type
3667                     == PICOPAM_EVENT_P_BOUND)) {
3668                 if (pam->e5_e6_content == 1)
3669                     pam->e5_e6_content_word++;
3670                 pam->e5_e6_content = 0;
3671                 if (event_type == PICOPAM_EVENT_P_BOUND)
3672                     pam->e5_e6_content_word = 0;
3673             }
3674             break;
3675         case E6:/*processor for E6 : done in E5*/
3676             break;
3677         case E7:/*processor for E7,E8*/
3678             switch (direction) {
3679                 case PICOPAM_DIR_FORW:
3680                     sDest = E7;
3681                     break;
3682                 case PICOPAM_DIR_BACK:
3683                     sDest = E8;
3684                     break;
3685                 default:
3686                     sDest = E7;
3687                     break;
3688             }
3689             switch (pam->e7_e8_state) {
3690                 case 0:
3691                     if (event_type == PICOPAM_EVENT_SYLL) {
3692                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3693                                 = PICOPAM_DONT_CARE_VALUE;
3694                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1)
3695                             pam->e7_e8_content = 1;
3696                     }
3697                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3698                         pam->e7_e8_content = 0;
3699                     }
3700 
3701                     if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
3702                             == PICOPAM_EVENT_S_BOUND)) {
3703                         if (pam->e7_e8_content == 1) {
3704                             pam->e7_e8_word = 0;
3705                             pam->e7_e8_content = 0;
3706                             pam->e7_e8_state = 1;
3707                         }
3708                     }
3709                     break;
3710                 case 1:
3711                     if (event_type == PICOPAM_EVENT_SYLL) {
3712                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
3713                                 = pam->e7_e8_word;
3714                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1)
3715                             pam->e7_e8_content = 1;
3716                     }
3717                     if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
3718                             == PICOPAM_EVENT_S_BOUND)) {
3719                         if (pam->e7_e8_content == 1) {
3720                             pam->e7_e8_word = 0;
3721                             pam->e7_e8_content = 0;
3722                         } else {
3723                             pam->e7_e8_word++;
3724                         }
3725                     }
3726                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3727                         pam->e7_e8_state = 0;
3728                         pam->e7_e8_content = 0; /*<<<<<< added */
3729                     }
3730 
3731                 default:
3732                     break;
3733             }
3734             break;
3735         case E8:/*processor for E8 : done in E7*/
3736             break;
3737         case E9:
3738             /*processor for E9, E11*/
3739             switch (direction) {
3740                 case PICOPAM_DIR_FORW:
3741                     switch (pam->e9_e11_state) {
3742                         case 0:
3743                             if (event_type == PICOPAM_EVENT_SYLL) {
3744                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9]
3745                                         = PICOPAM_DONT_CARE_VALUE;
3746                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11]
3747                                         = pam->e9_e11_word;
3748                                 pam->e9_e11_saw_word = 1; /*new variable, needs to be initialized to 0*/
3749                             }
3750                             if (event_type == PICOPAM_EVENT_W_BOUND)
3751                                 pam->e9_e11_word++;
3752                             if (((event_type == PICOPAM_EVENT_P_BOUND)
3753                                     || (event_type == PICOPAM_EVENT_S_BOUND))
3754                                     && (pam->e9_e11_saw_word == 1)) { /* modified*/
3755                                 if (event_type == PICOPAM_EVENT_P_BOUND)
3756                                     pam->e9_e11_word = 1;
3757                                 else
3758                                     pam->e9_e11_word++; /*modified*/
3759                                 pam->e9_e11_state = 1;
3760                             }
3761                             break;
3762                         case 1:
3763                             if (event_type == PICOPAM_EVENT_SYLL) {
3764                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9]
3765                                         = pam->e9_e11_word;
3766                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11]
3767                                         = PICOPAM_DONT_CARE_VALUE;
3768                             }
3769                             if ((event_type == PICOPAM_EVENT_W_BOUND)
3770                                     || (event_type == PICOPAM_EVENT_S_BOUND))
3771                                 pam->e9_e11_word++;
3772                             if (event_type == PICOPAM_EVENT_P_BOUND)
3773                                 pam->e9_e11_word = 1;
3774                             break;
3775                         default:
3776                             break;
3777                     }
3778                     break;
3779                 case PICOPAM_DIR_BACK:
3780                     /*do nothing*/
3781                     break;
3782             }
3783             break;
3784         case E10:/*processor for E10, E12, E13 unified*/
3785             switch (direction) {
3786                 case PICOPAM_DIR_FORW:/*do nothing*/
3787                     break;
3788                 case PICOPAM_DIR_BACK:
3789                     switch (pam->e10_e12_e13_state) {
3790                         case 0:
3791                             if (event_type == PICOPAM_EVENT_SYLL) {
3792                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[E10]
3793                                         = PICOPAM_DONT_CARE_VALUE;
3794                                 pam->e10_e12_e13_saw_word = 1;
3795                                 if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6]
3796                                         == PICOPAM_DECLARATIVE) {
3797                                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12]
3798                                             = pam->e10_e12_e13_word;
3799                                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13]
3800                                             = PICOPAM_DONT_CARE_VALUE;
3801                                 } else {
3802                                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12]
3803                                             = PICOPAM_DONT_CARE_VALUE;
3804                                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13]
3805                                             = pam->e10_e12_e13_word;
3806                                 }
3807                             }
3808                             if (event_type == PICOPAM_EVENT_W_BOUND)
3809                                 pam->e10_e12_e13_word++;
3810 
3811                             /*if (((event_type==PICOPAM_EVENT_P_BOUND)||(event_type==PICOPAM_EVENT_S_BOUND))&&(pam->e10_e12_e13_word>1))    {*/
3812                             if (((event_type == PICOPAM_EVENT_P_BOUND)
3813                                     || (event_type == PICOPAM_EVENT_S_BOUND))
3814                                     && (pam->e10_e12_e13_saw_word > 0)) {
3815                                 if (event_type == PICOPAM_EVENT_P_BOUND)
3816                                     pam->e10_e12_e13_word = 1;
3817                                 else
3818                                     pam->e10_e12_e13_word++;
3819                                 pam->e10_e12_e13_state = 1;
3820                             }
3821                             break;
3822                         case 1:
3823                             if (event_type == PICOPAM_EVENT_SYLL) {
3824                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[E10]
3825                                         = pam->e10_e12_e13_word;
3826                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12]
3827                                         = PICOPAM_DONT_CARE_VALUE;
3828                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13]
3829                                         = PICOPAM_DONT_CARE_VALUE;
3830                             }
3831                             if ((event_type == PICOPAM_EVENT_W_BOUND)
3832                                     || (event_type == PICOPAM_EVENT_S_BOUND))
3833                                 pam->e10_e12_e13_word++;
3834                             if (event_type == PICOPAM_EVENT_P_BOUND)
3835                                 pam->e10_e12_e13_word = 1;
3836                             break;
3837                         default:
3838                             break;
3839                     }
3840                     break;
3841             }
3842             break;
3843 
3844         case E11:/*processor for E11 : done in E9*/
3845             break;
3846         case E12:/*processor for E12 : done in E10*/
3847             break;
3848         case E13:/*processor for E13 : done in E10*/
3849             break;
3850 
3851         case F2:
3852             switch (direction) {
3853                 case PICOPAM_DIR_FORW:/*do nothing*/
3854                     break;
3855                 case PICOPAM_DIR_BACK:
3856                     if (event_type == PICOPAM_EVENT_SYLL) {
3857                         if (pam->f2_current_primary_phrase_word >= 1)/*at least second word in current primary phrase*/
3858                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2]
3859                                     = pam->f2_next_word_syllable;
3860                         else
3861                             /*first word in current primary phrase*/
3862                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] = 0;
3863                         pam->f2_word_syllable++;
3864                     }
3865                     if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
3866                             == PICOPAM_EVENT_S_BOUND) || (event_type
3867                             == PICOPAM_EVENT_P_BOUND)) {/*word - end : switch*/
3868                         pam->f2_next_word_syllable = pam->f2_word_syllable;
3869                         pam->f2_word_syllable = 0;
3870                     }
3871                     if (event_type == PICOPAM_EVENT_P_BOUND)/*mark first word in current primary phrase*/
3872                         pam->f2_current_primary_phrase_word = 0;
3873                     else /*mark next word in current primary phrase(enables output in PICOPAM_EVENT_SYLL)*/
3874                     if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
3875                             == PICOPAM_EVENT_S_BOUND))
3876                         pam->f2_current_primary_phrase_word++;
3877                     break;
3878             }
3879             break;
3880         case G1:
3881             switch (direction) {
3882                 case PICOPAM_DIR_FORW:
3883                     if (event_type == PICOPAM_EVENT_SYLL) {
3884                         if (pam->g1_current_secondary_phrase_syllable > 0)
3885                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1]
3886                                     = pam->g1_current_secondary_phrase_syllable;
3887                         else
3888                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] = 0;
3889                         pam->g1_current_syllable++;
3890                     }
3891                     if (event_type == PICOPAM_EVENT_S_BOUND) {
3892                         pam->g1_current_secondary_phrase_syllable
3893                                 = pam->g1_current_syllable;
3894                         pam->g1_current_syllable = 0;
3895                     }
3896                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3897                         pam->g1_current_secondary_phrase_syllable = 0;
3898                         pam->g1_current_syllable = 0;
3899                     }
3900                 case PICOPAM_DIR_BACK: /*do nothing*/
3901                     break;
3902             }
3903             break;
3904         case G2:
3905             switch (direction) {
3906                 case PICOPAM_DIR_FORW:
3907                     if (event_type == PICOPAM_EVENT_SYLL) {
3908                         if (pam->g2_current_secondary_phrase_word > 0)
3909                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2]
3910                                     = pam->g2_current_secondary_phrase_word;
3911                         else
3912                             pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] = 0;
3913                     }
3914                     if (event_type == PICOPAM_EVENT_W_BOUND)
3915                         pam->g2_current_word++;
3916 
3917                     if (event_type == PICOPAM_EVENT_S_BOUND) {
3918                         pam->g2_current_secondary_phrase_word
3919                                 = pam->g2_current_word + 1;
3920                         pam->g2_current_word = 0;
3921                     }
3922                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3923                         pam->g2_current_secondary_phrase_word = 0;
3924                         pam->g2_current_word = 0;
3925                     }
3926                     break;
3927                 case PICOPAM_DIR_BACK: /*do nothing*/
3928                     break;
3929             }
3930             break;
3931         case H1:
3932             switch (direction) {
3933                 case PICOPAM_DIR_FORW:
3934                     if (event_type == PICOPAM_EVENT_SYLL) {
3935                         pam->h1_current_secondary_phrase_syll++;
3936                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1]
3937                                 = pam->h1_current_secondary_phrase_syll;
3938                     }
3939                     if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type
3940                             == PICOPAM_EVENT_P_BOUND))
3941                         pam->h1_current_secondary_phrase_syll = 0;
3942                     break;
3943                 case PICOPAM_DIR_BACK:
3944                     if (event_type == PICOPAM_EVENT_SYLL)
3945                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1]
3946                                 = pam->h1_current_secondary_phrase_syll;
3947                     if (event_type == PICOPAM_EVENT_S_BOUND)
3948                         pam->h1_current_secondary_phrase_syll
3949                                 = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1];
3950                     if (event_type == PICOPAM_EVENT_P_BOUND)
3951                         pam->h1_current_secondary_phrase_syll
3952                                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1];
3953                     break;
3954             }
3955             break;
3956         case H2:
3957             switch (direction) {
3958                 case PICOPAM_DIR_FORW:
3959                     if (event_type == PICOPAM_EVENT_SYLL) {
3960                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2]
3961                                 = pam->h2_current_secondary_phrase_word;
3962                     }
3963                     if (event_type == PICOPAM_EVENT_W_BOUND) {
3964                         pam->h2_current_secondary_phrase_word++;
3965                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2]
3966                                 = pam->h2_current_secondary_phrase_word;
3967                     }
3968                     if (event_type == PICOPAM_EVENT_S_BOUND) {
3969                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2]
3970                                 = pam->h2_current_secondary_phrase_word + 1;
3971                         pam->h2_current_secondary_phrase_word = 0;
3972                     }
3973                     if (event_type == PICOPAM_EVENT_P_BOUND) {
3974                         if (pam->nCurrSyllable > 1)
3975                             pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]
3976                                     = pam->h2_current_secondary_phrase_word + 1;
3977                         pam->h2_current_secondary_phrase_word = 0;
3978                     }
3979                     break;
3980                 case PICOPAM_DIR_BACK:
3981                     if (event_type == PICOPAM_EVENT_SYLL)
3982                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2]
3983                                 = pam->h2_current_secondary_phrase_word;
3984                     if (event_type == PICOPAM_EVENT_S_BOUND)
3985                         pam->h2_current_secondary_phrase_word
3986                                 = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2];
3987                     if (event_type == PICOPAM_EVENT_P_BOUND)
3988                         pam->h2_current_secondary_phrase_word
3989                                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2];
3990                     break;
3991             }
3992             break;
3993         case H3:/*processor for H3,H4 unified */
3994             switch (direction) {
3995                 case PICOPAM_DIR_FORW:
3996                     sDest = H3;
3997                     break;
3998                 case PICOPAM_DIR_BACK:
3999                     sDest = H4;
4000                     break;
4001                 default:
4002                     sDest = H3;
4003                     break;
4004             }
4005             if (event_type == PICOPAM_EVENT_SYLL) {
4006                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest]
4007                         = pam->h3_h4_current_secondary_phrase_word;
4008             }
4009             if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type
4010                     == PICOPAM_EVENT_P_BOUND))
4011                 pam->h3_h4_current_secondary_phrase_word++;
4012             break;
4013         case H4: /*processor for H4 : already in H3*/
4014             break;
4015 
4016         case H5:/*processor for H5*/
4017             switch (direction) {
4018                 case PICOPAM_DIR_FORW:
4019                     break;
4020                 case PICOPAM_DIR_BACK:
4021                     switch (pam->h5_state) {
4022                         case 0:
4023                             if (event_type == PICOPAM_EVENT_SYLL)
4024                                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5]
4025                                         = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5];
4026                             if (event_type == PICOPAM_EVENT_S_BOUND) {
4027                                 pam->h5_state = 1;
4028                             }
4029                             break;
4030                         case 1:
4031                             if (event_type == PICOPAM_EVENT_SYLL) {
4032                                 if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5]
4033                                         == PICOPAM_P)
4034                                         && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1]
4035                                                 == 0))
4036                                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5]
4037                                             = PICOPAM_p;
4038                             }
4039                             if (event_type == PICOPAM_EVENT_P_BOUND) {
4040                                 pam->h5_state = 0;
4041                             }
4042                             break;
4043                         default:
4044                             break;
4045                     }
4046                     break;
4047 
4048                 default:
4049                     break;
4050             }
4051             break;
4052 
4053         case I1:/*processor for I1*/
4054             switch (direction) {
4055                 case PICOPAM_DIR_FORW:
4056                     if (event_type == PICOPAM_EVENT_SYLL) {
4057                         pam->i1_secondary_phrase_syllable++;
4058                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1]
4059                                 = pam->i1_secondary_phrase_syllable;
4060                     }
4061                     if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type
4062                             == PICOPAM_EVENT_P_BOUND))
4063                         pam->i1_secondary_phrase_syllable = 0;
4064                     break;
4065                 case PICOPAM_DIR_BACK:
4066                     if (event_type == PICOPAM_EVENT_SYLL) {
4067                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1]
4068                                 = pam->i1_next_secondary_phrase_syllable;
4069                     }
4070                     if (event_type == PICOPAM_EVENT_S_BOUND) {
4071                         pam->i1_next_secondary_phrase_syllable
4072                                 = pam->i1_secondary_phrase_syllable;
4073                         pam->i1_secondary_phrase_syllable
4074                                 = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1];
4075                     }
4076                     if (event_type == PICOPAM_EVENT_P_BOUND) {
4077                         pam->i1_next_secondary_phrase_syllable = 0;
4078                         pam->i1_secondary_phrase_syllable
4079                                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[I1];
4080                     }
4081                     break;
4082             }
4083             break;
4084         case I2: /*processor for I2*/
4085             switch (direction) {
4086                 case PICOPAM_DIR_FORW:
4087                     if (event_type == PICOPAM_EVENT_SYLL) {
4088                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2]
4089                                 = pam->i2_secondary_phrase_word;
4090                     }
4091                     if (event_type == PICOPAM_EVENT_W_BOUND)
4092                         pam->i2_secondary_phrase_word++;
4093 
4094                     if ((event_type == PICOPAM_EVENT_P_BOUND) || (event_type
4095                             == PICOPAM_EVENT_S_BOUND))
4096                         pam->i2_secondary_phrase_word = 1;
4097 
4098                     break;
4099                 case PICOPAM_DIR_BACK:
4100                     if (event_type == PICOPAM_EVENT_SYLL) {
4101                         pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2]
4102                                 = pam->i2_next_secondary_phrase_word;
4103                     }
4104                     if (event_type == PICOPAM_EVENT_S_BOUND) {
4105                         pam->i2_next_secondary_phrase_word
4106                                 = pam->i2_secondary_phrase_word;
4107                         pam->i2_secondary_phrase_word
4108                                 = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2];
4109                     }
4110                     if (event_type == PICOPAM_EVENT_P_BOUND) {
4111                         pam->i2_next_secondary_phrase_word = 0;
4112                         pam->i2_secondary_phrase_word
4113                                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[I2];
4114                     }
4115                     break;
4116             }
4117             break;
4118         case J1: /*processor for J1 */
4119             switch (direction) {
4120                 case PICOPAM_DIR_FORW:
4121                     if (event_type == PICOPAM_EVENT_SYLL) {
4122                         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] != 1)
4123                             pam->j1_utterance_syllable++;
4124                     }
4125                     break;
4126                 case PICOPAM_DIR_BACK:
4127                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[J1]
4128                             = pam->j1_utterance_syllable;
4129                     break;
4130             }
4131             break;
4132         case J2: /*processor for J2*/
4133             switch (direction) {
4134                 case PICOPAM_DIR_FORW:
4135                     if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type
4136                             == PICOPAM_EVENT_S_BOUND) || (event_type
4137                             == PICOPAM_EVENT_P_BOUND))
4138                         pam->j2_utterance_word++;
4139                     break;
4140                 case PICOPAM_DIR_BACK:
4141                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[J2]
4142                             = pam->j2_utterance_word - 1;
4143                     break;
4144             }
4145             break;
4146         case J3: /*processor for J3*/
4147             switch (direction) {
4148                 case PICOPAM_DIR_FORW:
4149                     if (event_type == PICOPAM_EVENT_S_BOUND) {
4150                         pam->j3_utterance_sec_phrases++;
4151                         break;
4152                     }
4153                     if (event_type == PICOPAM_EVENT_P_BOUND) {
4154                         pam->j3_utterance_sec_phrases++;
4155                         break;
4156                     }
4157                     break;
4158                 case PICOPAM_DIR_BACK:
4159                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[J3]
4160                             = pam->j3_utterance_sec_phrases - 1;
4161                     break;
4162             }
4163             break;
4164     }
4165     return PICO_OK;
4166 }/*pam_process_event_feature*/
4167 
4168 /**
4169  * processes an input event spanning it to all column features
4170  * @param    this : pointer to PAM PU sub object pointer
4171  * @param    event_type : event id among syll/boundprim/boundsec/boundword
4172  * @param    direction : forward(0)/backward(1)
4173  * @return    PICO_OK : process OK
4174  * @return    PICO_ERR_OTHER : errors on getting pam sub obj pointer
4175  * @callgraph
4176  * @callergraph
4177  */
pam_process_event(register picodata_ProcessingUnit this,picoos_uint8 event_type,picoos_uint8 direction)4178 static pico_status_t pam_process_event(register picodata_ProcessingUnit this,
4179         picoos_uint8 event_type, picoos_uint8 direction)
4180 {
4181     picoos_uint8 nFeat;
4182     pico_status_t nResult;
4183 
4184     pam_subobj_t *pam;
4185     if (NULL == this || NULL == this->subObj) {
4186         return PICO_ERR_OTHER;
4187     }
4188     pam = (pam_subobj_t *) this->subObj;
4189 
4190     if (direction == PICOPAM_DIR_FORW) {
4191         if (event_type == PICOPAM_EVENT_P_BOUND)
4192             /*primary boundary*/
4193             pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] = 1;
4194         if (event_type == PICOPAM_EVENT_S_BOUND)
4195             /*secondary boundary*/
4196             pam->sSyllFeats[pam->nCurrSyllable].phoneV[P3] = 1;
4197         if (event_type == PICOPAM_EVENT_W_BOUND)
4198             /*word boundary*/
4199             pam->sSyllFeats[pam->nCurrSyllable].phoneV[P4] = 1;
4200     }
4201     for (nFeat = A3; nFeat <= J3; nFeat++) {
4202         nResult = pam_process_event_feature(this, nFeat, event_type, direction);
4203         if (nResult != PICO_OK)
4204             return nResult;
4205     }
4206     return PICO_OK;
4207 }/*pam_process_event*/
4208 
4209 /**
4210  * inserts a syllable inside the subobj sentence data struct.
4211  * @param    this : pointer to PAM PU sub object pointer
4212  * @param    syllType  : the syllable type (pause/syllable)
4213  * @param    sContent : the item content
4214  * @param    sentType : the sentence type
4215  * @param    phType : the phrase type
4216  * @param    uBoundType : the boundary type (only for silence syllables)
4217  * @param    uMinDur, uMaxDur : the mimimum and maximum duration (only for silence syllables)
4218  * @return    PICO_OK : syllable creation successful
4219  * @return    PICO_ERR_OTHER : errors in one internal function (check_phones_size..)
4220  * @callgraph
4221  * @callergraph
4222  */
pam_create_syllable(register picodata_ProcessingUnit this,picoos_uint8 syllType,picoos_uint8 * sContent,picoos_uint8 sentType,picoos_uint8 phType,picoos_uint8 uBoundType,picoos_uint16 uMinDur,picoos_uint16 uMaxDur)4223 static pico_status_t pam_create_syllable(register picodata_ProcessingUnit this,
4224         picoos_uint8 syllType, picoos_uint8 *sContent, picoos_uint8 sentType,
4225         picoos_uint8 phType, picoos_uint8 uBoundType, picoos_uint16 uMinDur,
4226         picoos_uint16 uMaxDur)
4227 {
4228     pam_subobj_t *pam;
4229     picoos_uint8 nI;
4230     picoos_uint8 pos;
4231     /* picoos_uint8    *npUi16; */
4232     picoos_uint32 pos32;
4233 
4234     if (NULL == this || NULL == this->subObj) {
4235         return PICO_ERR_OTHER;
4236     }
4237     pam = (pam_subobj_t *) this->subObj;
4238     pos = 0;
4239     /*check buffer full condition on number of syllables*/
4240     if (check_syllables_size(pam, 1) != PICO_OK) {
4241         return PICO_ERR_OTHER;
4242     }
4243 
4244     if (syllType == PICOPAM_SYLL_PAUSE) {
4245         /*check buffer full condition on number of phonemes*/
4246         if (check_phones_size(pam, 1) != PICO_OK) {
4247             return PICO_ERR_OTHER;
4248         }
4249     }
4250     if (syllType == PICOPAM_SYLL_SYLL) {
4251         /*check item availability*/
4252         if (sContent == NULL) {
4253             return PICO_ERR_OTHER;
4254         }
4255         /*check buffer full condition  on number of phonemes*/
4256         if (check_phones_size(pam, sContent[3]) != PICO_OK) {
4257             return PICO_ERR_OTHER;
4258         }
4259     }
4260 
4261     /*open new syllable*/
4262     pam->nCurrSyllable = pam->nCurrSyllable + 1;
4263     /*cleanup*/
4264     for (nI = 0; nI < PICOPAM_VECT_SIZE; nI++) {
4265         if (pam->nCurrSyllable > 0) {
4266             pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0;
4267         } else {
4268             if ((nI >= ITM) && (nI <= itm)) {
4269                 if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] > 0) {
4270                     /*do not cleanup "attached item offset" fields (ITM, itm):
4271                      an already existing attached item could be lost*/
4272                 } else {
4273                     /*cleanup "attached item offset"*/
4274                     pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0;
4275                 }
4276             } else {
4277                 /*cleanup all fields except "attached item offset" (ITM, itm)*/
4278                 pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0;
4279             }
4280         }
4281     }
4282     /*set minimum and maximum duration values*/
4283     if ((uMinDur == 0) && (uMaxDur == 0) && (syllType == PICOPAM_SYLL_PAUSE)) {
4284         /*both 0 : use default duration limits for boundaries*/
4285         get_default_boundary_limit(uBoundType, &uMinDur, &uMaxDur);
4286     }
4287     if (uMinDur > 0) {
4288         pos32 = Min;
4289         picoos_write_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV,
4290                 &pos32, uMinDur);
4291     }
4292     if (uMaxDur > 0) {
4293         pos32 = Max;
4294         picoos_write_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV,
4295                 &pos32, uMaxDur);
4296     }
4297     /*END OF BREAK COMMAND SUPPORT*/
4298 
4299     if (syllType == PICOPAM_SYLL_PAUSE) {
4300         /*initialize a pause syllable*/
4301         if (sentType == PICOPAM_DECLARATIVE)
4302             pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6]
4303                     = PICOPAM_DECLARATIVE;
4304         if (sentType == PICOPAM_INTERROGATIVE)
4305             pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6]
4306                     = PICOPAM_INTERROGATIVE;
4307 
4308         pam->sSyllFeats[pam->nCurrSyllable].phoneV[bnd] = uBoundType;
4309         pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] = 1; /*this means the syllable contains a pause-silence*/
4310         pam->sSyllFeats[pam->nCurrSyllable].phoneV[P8] = 1;
4311 
4312         /*b1,b2,b9,b11,b13,b15,e1,e6,e8,e10 already set to 0*/
4313 
4314         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3]
4315                 = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B4]
4316                         = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B5]
4317                                 = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B6]
4318                                         = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B7]
4319                                                 = 1;
4320 
4321         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B16]
4322                 = PICOPAM_PH_DONT_CARE_VAL; /*name of the vowel in the syllable = NONE */
4323 
4324         pam->sSyllFeats[pam->nCurrSyllable].phoneV[E2]
4325                 = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E3]
4326                         = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E4] = 1;
4327 
4328         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = phType;
4329 
4330         /*Store current phonetic codes in input phonetic string*/
4331         pam->sPhIds[pam->nCurrPhoneme] = pam_get_pause_id(this);
4332         picoos_mem_copy((void*) &pam->nCurrPhoneme,
4333                 &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[FID]),
4334                 sizeof(pam->nCurrPhoneme));
4335         pam->nCurrPhoneme++;
4336         pam->nTotalPhonemes++;
4337         /*add 1 to total number of syllables*/
4338         pam->nTotalSyllables++;
4339 
4340         return PICO_OK;
4341     }
4342     if (syllType == PICOPAM_SYLL_SYLL) {
4343         /*initialize a real syllable*/
4344         if (sContent[2] > PICODATA_ACC0)
4345             pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] = 1; /*set content syllable indicator*/
4346         if (sentType == PICOPAM_DECLARATIVE)
4347             pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6]
4348                     = PICOPAM_DECLARATIVE;
4349         if (sentType == PICOPAM_INTERROGATIVE)
4350             pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6]
4351                     = PICOPAM_INTERROGATIVE;
4352 
4353         if ((sContent[2] >= PICODATA_ACC1) && (sContent[2] <= PICODATA_ACC4))
4354             /*stressed*/
4355             pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] = 1;
4356 
4357         if ((sContent[2] >= PICODATA_ACC1) && (sContent[2] <= PICODATA_ACC2))
4358             /*accented*/
4359             pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] = 1;
4360 
4361         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] = sContent[3];/*len*/
4362 
4363         if (pam->nCurrSyllable > 30)
4364             pam->nCurrSyllable = pam->nCurrSyllable;
4365 
4366         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B16] = pam_get_vowel_name(this,
4367                 sContent, &pos); /*name of the vowel in the syllable*/
4368 
4369         pam->sSyllFeats[pam->nCurrSyllable].phoneV[P8] = pos; /*temp for storing the position of the vowel*/
4370 
4371         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = phType;
4372 
4373         /*Store current phonetic codes in input phonetic string*/
4374         picoos_mem_copy((void*) &pam->nCurrPhoneme,
4375                 &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[FID]),
4376                 sizeof(pam->nCurrPhoneme));
4377         for (nI = 0; nI < sContent[3]; nI++)
4378             pam->sPhIds[pam->nCurrPhoneme + nI] = sContent[4 + nI];
4379         pam->nCurrPhoneme += nI;
4380         pam->nTotalPhonemes += nI;
4381         /*add 1 to total number of syllables*/
4382         pam->nTotalSyllables++;
4383         return PICO_OK;
4384     }
4385     /*if no SyllType has been identified -->> error*/
4386     return PICO_ERR_OTHER;
4387 }/*pam_create_syllable*/
4388 
4389 /**
4390  * performs the forward step of the PAM adapter
4391  * @param    this : pointer to PAM PU sub object pointer
4392  * @param    itemBase : pointer to current item
4393  * @return    PICOPAM_READY : forward step ok, the sentence is complete
4394  * @return  PICOPAM_MORE : forward step ok, but more data needed to complete the sentence
4395  * @return    PICO_ERR_OTHER : errors in one internal function (CreateSyllable..)
4396  * @callgraph
4397  * @callergraph
4398  */
pam_adapter_forward_step(register picodata_ProcessingUnit this,picoos_uint8 * itemBase)4399 static pico_status_t pam_adapter_forward_step(
4400         register picodata_ProcessingUnit this, picoos_uint8 *itemBase)
4401 {
4402     register pam_subobj_t * pam;
4403     pico_status_t sResult;
4404     picoos_uint16 uMinDur, uMaxDur;
4405     picoos_uint32 nPos;
4406 
4407     if (NULL == this || NULL == this->subObj) {
4408         return PICO_ERR_OTHER;
4409     }
4410     pam = (pam_subobj_t *) this->subObj;
4411     uMinDur = uMaxDur = 0; /*default 0 : not initialized*/
4412     switch (itemBase[0]) {
4413         case PICODATA_ITEM_BOUND:
4414             /*received a boundary item*/
4415             switch (itemBase[1]) {
4416                 case PICODATA_ITEMINFO1_BOUND_SBEG:
4417                 case PICODATA_ITEMINFO1_BOUND_PHR1:
4418 #ifdef PAM_PHR2_WITH_PR1
4419                 case PICODATA_ITEMINFO1_BOUND_PHR2:
4420 #endif
4421                 case PICODATA_ITEMINFO1_BOUND_SEND:
4422                 case PICODATA_ITEMINFO1_BOUND_TERM:
4423                     if (itemBase[3] == 2 * sizeof(picoos_uint16)) {
4424                         /*only when the item len duration is equal to 2 int16 --> get the values*/
4425                         nPos = 4;
4426                         picoos_read_mem_pi_uint16(itemBase, &nPos, &uMinDur);
4427                         picoos_read_mem_pi_uint16(itemBase, &nPos, &uMaxDur);
4428                     }
4429                     break;
4430                 default:
4431                     break;
4432             }
4433             switch (itemBase[1]) {
4434                 case PICODATA_ITEMINFO1_BOUND_SBEG:
4435                     /* received a sentence init boundary */
4436                     pam_reset_processors(this); /*reset all processor variables*/
4437                     pam->sType
4438                             = pam_map_sentence_type(itemBase[1], itemBase[2]);
4439                     pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]);
4440                     /*create silence syll and process P_BOUND event*/
4441                     sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL,
4442                             pam->sType, pam->pType, itemBase[1], uMinDur,
4443                             uMaxDur);
4444                     if (sResult != PICO_OK)
4445                         return sResult;
4446                     sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND,
4447                             PICOPAM_DIR_FORW);
4448                     if (sResult != PICO_OK)
4449                         return sResult;
4450                     return PICOPAM_MORE;
4451                     break;
4452 
4453                 case PICODATA_ITEMINFO1_BOUND_PHR1:
4454 #ifdef PAM_PHR2_WITH_PR1
4455                 case PICODATA_ITEMINFO1_BOUND_PHR2:
4456 #endif
4457                     /*received a primary boundary*/
4458                     pam->sType
4459                             = pam_map_sentence_type(itemBase[1], itemBase[2]);
4460                     pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]);
4461                     /*create silence syll and process P_BOUND event*/
4462                     sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL,
4463                             pam->sType, pam->pType, itemBase[1], uMinDur,
4464                             uMaxDur);
4465                     if (sResult != PICO_OK)
4466                         return sResult;
4467                     sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND,
4468                             PICOPAM_DIR_FORW);
4469                     if (sResult != PICO_OK)
4470                         return sResult;
4471                     return PICOPAM_MORE;
4472                     break;
4473 
4474 #ifdef PAM_PHR2_WITH_PR3
4475                     case PICODATA_ITEMINFO1_BOUND_PHR2 :
4476 #endif
4477                 case PICODATA_ITEMINFO1_BOUND_PHR3:
4478                     /*received a secondary boundary*/
4479                     /*process S_BOUND event*/
4480                     sResult = pam_process_event(this, PICOPAM_EVENT_S_BOUND,
4481                             PICOPAM_DIR_FORW);
4482                     /*determine new sentence and Phrase types for following syllables*/
4483                     pam->sType
4484                             = pam_map_sentence_type(itemBase[1], itemBase[2]);
4485                     pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]);
4486                     if (sResult != PICO_OK)
4487                         return sResult;
4488                     return PICOPAM_MORE;
4489                     break;
4490 
4491                 case PICODATA_ITEMINFO1_BOUND_PHR0:
4492                     /*received a word end boundary*/
4493                     /*process W_BOUND event*/
4494                     sResult = pam_process_event(this, PICOPAM_EVENT_W_BOUND,
4495                             PICOPAM_DIR_FORW);
4496                     if (sResult != PICO_OK)
4497                         return sResult;
4498                     return PICOPAM_MORE;
4499                     break;
4500 
4501                 case PICODATA_ITEMINFO1_BOUND_SEND:
4502                     /*received a SEND boundary*/
4503                     /*insert a new silence syllable and process P_BOUND event*/
4504                     /*create silence syll and process P_BOUND event*/
4505                     sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL,
4506                             pam->sType, pam->pType, itemBase[1], uMinDur,
4507                             uMaxDur);
4508                     if (sResult != PICO_OK)
4509                         return sResult;
4510                     sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND,
4511                             PICOPAM_DIR_FORW);
4512                     if (sResult != PICO_OK)
4513                         return sResult;
4514                     return PICOPAM_READY;
4515                     break;
4516 
4517                 case PICODATA_ITEMINFO1_BOUND_TERM:
4518                     /* received a flush boundary*/
4519                     if (pam->nCurrSyllable == -1) {
4520                         return PICOPAM_NA;
4521                     }
4522                     /*insert a new silence syllable and process P_BOUND event*/
4523                     /*create silence syll and process P_BOUND event*/
4524                     sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL,
4525                             pam->sType, pam->pType, itemBase[1], uMinDur,
4526                             uMaxDur);
4527                     if (sResult != PICO_OK)
4528                         return sResult;
4529                     sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND,
4530                             PICOPAM_DIR_FORW);
4531                     if (sResult != PICO_OK)
4532                         return sResult;
4533                     return PICOPAM_READY;
4534                     break;
4535 
4536                 default:
4537                     /*boundary type not known*/
4538                     return PICOPAM_NA;
4539                     break;
4540             }/*end switch (itemBase[1])*/
4541             break; /*end case PICODATA_ITEM_BOUND*/
4542 
4543         case PICODATA_ITEM_SYLLPHON:
4544             /*received a syllable item*/
4545             /*    ------------------------------------------------------------------
4546              following code has to be used if we do expect
4547              SYLL items arrive even without SBEG items starting the sentence.
4548              this may happen after a term has been issued to make room in local storage.
4549              */
4550             if (pam->nCurrSyllable == -1) {
4551                 pam_reset_processors(this);
4552                 /*insert an SBEG with sType and pType taken from previous sentence*/
4553                 sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL,
4554                         pam->sType, pam->pType, PICODATA_ITEMINFO1_BOUND_SBEG,
4555                         0, 0);
4556                 if (sResult != PICO_OK)
4557                     return sResult;
4558                 sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND,
4559                         PICOPAM_DIR_FORW);
4560                 if (sResult != PICO_OK)
4561                     return sResult;
4562             }
4563             /* ------------------------------------------------------------------*/
4564             sResult = pam_create_syllable(this, PICOPAM_SYLL_SYLL, itemBase,
4565                     pam->sType, pam->pType, 0, 0, 0);
4566             if (sResult != PICO_OK)
4567                 return sResult;
4568             sResult = pam_process_event(this, PICOPAM_EVENT_SYLL,
4569                     PICOPAM_DIR_FORW);
4570             if (sResult != PICO_OK)
4571                 return sResult;
4572             return PICOPAM_MORE;
4573             break;
4574 
4575         default:
4576             return PICOPAM_NA;
4577             break;
4578     }
4579     return PICO_ERR_OTHER;
4580 }/*pam_adapter_forward_step*/
4581 
4582 /**
4583  * performs the backward step of the PAM adapter
4584  * @param    this : pointer to PAM PU sub object pointer
4585  * @return    PICO_OK : backward step complete
4586  * @return  PICO_ERR_OTHER : errors on retrieving the PU pointer
4587  * @remarks derived in some parts from the pam forward code
4588  * @callgraph
4589  * @callergraph
4590  */
pam_adapter_backward_step(register picodata_ProcessingUnit this)4591 static pico_status_t pam_adapter_backward_step(
4592         register picodata_ProcessingUnit this)
4593 {
4594     register pam_subobj_t * pam;
4595     picoos_uint8 nProcessed;
4596     picoos_uint16 nSyll;
4597 
4598     if (NULL == this || NULL == this->subObj) {
4599         return PICO_ERR_OTHER;
4600     }
4601     pam = (pam_subobj_t *) this->subObj;
4602 
4603     /*Resets the processors for the backward step*/
4604     pam_reset_processors_back(this);
4605     /*Do the backward step*/
4606     nSyll = pam->nCurrSyllable;
4607     while (pam->nCurrSyllable >= 0) {
4608         nProcessed = 0;
4609         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] == 1) {
4610             /*primary boundary*/
4611             pam_process_event(this, PICOPAM_EVENT_P_BOUND, PICOPAM_DIR_BACK);
4612             pam->nCurrSyllable--;
4613             nProcessed = 1;
4614         }
4615         if ((nProcessed == 0)
4616                 && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P3] == 1)) {
4617             /*secondary boundary*/
4618             pam_process_event(this, PICOPAM_EVENT_S_BOUND, PICOPAM_DIR_BACK);
4619             pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK);
4620             pam->nCurrSyllable--;
4621             nProcessed = 1;
4622         }
4623         if ((nProcessed == 0)
4624                 && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P4] == 1)) {
4625             /*word boundary*/
4626             pam_process_event(this, PICOPAM_EVENT_W_BOUND, PICOPAM_DIR_BACK);
4627             pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK);
4628             pam->nCurrSyllable--;
4629             nProcessed = 1;
4630         }
4631         if (nProcessed == 0) {
4632             /*non boundaried syllable*/
4633             pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK);
4634             pam->nCurrSyllable--;
4635             nProcessed = 0;
4636         }
4637     }/*end while (pam->nCurrSyllable>=0)*/
4638     /*reset syllpointer to original value*/
4639     pam->nCurrSyllable = nSyll;
4640     /*Perform pause processing*/
4641     pam_adapter_do_pauses(this);
4642     pam->nCurrSyllable = 0;
4643     pam->nSyllPhoneme = 0;
4644 
4645     return PICO_OK;
4646 }/*pam_adapter_backward_step*/
4647 
4648 /**
4649  * processes a pause (silence) syllable after backward processing
4650  * @param    this : pointer to PAM PU sub object pointer : processes a pause (silence) syllable after backward processing
4651  * @return    PICO_OK : backward step complete
4652  * @return  PICO_ERR_OTHER : errors on retrieving the PU pointer
4653  * @remarks pam->nCurrSyllable should point to a pause item
4654  * @remarks this function should be called after backward processing
4655  * @remarks this function corresponds to initializing silence phonemes with
4656  * @remarks values derived from previous or following syllables
4657  * @callgraph
4658  * @callergraph
4659  */
pam_do_pause(register picodata_ProcessingUnit this)4660 static pico_status_t pam_do_pause(register picodata_ProcessingUnit this)
4661 {
4662     picoos_uint16 syllCurr;
4663     pam_subobj_t *pam;
4664     if (NULL == this || NULL == this->subObj) {
4665         return PICO_ERR_OTHER;
4666     }
4667     pam = (pam_subobj_t *) this->subObj;
4668     syllCurr = pam->nCurrSyllable;
4669 
4670     /*processor for all features that can be inherited from previous syll (or word/phrase)*/
4671     if (pam->nCurrSyllable > 0) {
4672         pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3]
4673                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B3];
4674         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B8]
4675                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B8];
4676         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B10]
4677                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B10];
4678         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B12]
4679                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B12];
4680         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B14]
4681                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B14];
4682         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17]
4683                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B17];
4684         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19]
4685                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B19];
4686         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20]
4687                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B20];
4688         pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21]
4689                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B21];
4690 
4691         pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2]
4692                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E2];
4693         pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1]
4694                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1];
4695         pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2]
4696                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2];
4697 
4698         pam->sSyllFeats[pam->nCurrSyllable].phoneV[E5]
4699                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E5];
4700         pam->sSyllFeats[pam->nCurrSyllable].phoneV[E7]
4701                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E7];
4702         pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9]
4703                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E9];
4704         pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11]
4705                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E11];
4706         pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12]
4707                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E12];
4708         pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13]
4709                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E13];
4710         pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13]
4711                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E13];
4712 
4713         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1]
4714                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1];
4715         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2]
4716                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2];
4717         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H3]
4718                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H3];
4719         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H4]
4720                 = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H4];
4721 
4722     } else {
4723         pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3]
4724             =pam->sSyllFeats[pam->nCurrSyllable].phoneV[B8]
4725             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B10]
4726             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B12]
4727             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B14]
4728             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17]
4729             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19]
4730             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20]
4731             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21]
4732             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E5]
4733             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9]
4734             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11]
4735             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12]
4736             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1]
4737             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2]
4738             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H3]
4739             = 0;
4740 
4741         /*init values different from 0*/
4742         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H4]
4743             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[J3];
4744         pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = PICOPAM_p;
4745 
4746     }
4747 
4748     /*processor for all features that can be inherited from next syll (or word/phrase)*/
4749     if (pam->nCurrSyllable < pam->nTotalSyllables - 1) {
4750         /*non last syllable*/
4751         pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3]
4752                 = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[B3];
4753         pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2]
4754                 = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[E2];
4755         pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1]
4756                 = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[H1];
4757         pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2]
4758                 = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[H2];
4759     } else {
4760         /*last syllable*/
4761         pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3]
4762             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2]
4763             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1]
4764             = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2]
4765             = 0;
4766     }
4767 
4768     /*Other fixed values derived from de-facto standard*/
4769     pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] = 0;
4770 
4771     return PICO_OK;
4772 }/*pam_do_pause*/
4773 
4774 /**
4775  * performs the initialization of pause "syllables"
4776  * @param    this : pointer to PAM PU sub object pointer : processes a pause (silence) syllable after backward processing
4777  * @return    PICO_OK : pause processing successful
4778  * @return  PICO_ERR_OTHER : errors on retrieving the PU pointer
4779  * @callgraph
4780  * @callergraph
4781  */
pam_adapter_do_pauses(register picodata_ProcessingUnit this)4782 static pico_status_t pam_adapter_do_pauses(register picodata_ProcessingUnit this)
4783 {
4784     register pam_subobj_t * pam;
4785     picoos_uint16 nSyll;
4786 
4787     if (NULL == this || NULL == this->subObj) {
4788         return PICO_ERR_OTHER;
4789     }
4790     pam = (pam_subobj_t *) this->subObj;
4791 
4792     /*Do the pause processing*/
4793     nSyll = pam->nCurrSyllable;
4794     while (pam->nCurrSyllable >= 0) {
4795         if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] == 1) {
4796             /*pause processing*/
4797             pam_do_pause(this);
4798         }
4799         pam->nCurrSyllable--;
4800     }/*end while (pam->nCurrSyllable>=0)*/
4801     /*reset syllpointer to original value*/
4802     pam->nCurrSyllable = nSyll;
4803     return PICOPAM_READY;
4804 }/*pam_adapter_do_pauses*/
4805 
4806 #ifdef __cplusplus
4807 }
4808 #endif
4809 
4810 /* picopam.c end */
4811