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
41extern "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                  */
136typedef 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 ---------------------------------------------------------*/
146typedef 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 ------------------------------------------------------------------*/
389static pico_status_t pam_initialize(register picodata_ProcessingUnit this, picoos_int32 resetMode);
390static pico_status_t pam_terminate(register picodata_ProcessingUnit this);
391static pico_status_t pam_allocate(picoos_MemoryManager mm, pam_subobj_t *pam);
392static void pam_deallocate(picoos_MemoryManager mm, pam_subobj_t *pam);
393static pico_status_t pam_subobj_deallocate(register picodata_ProcessingUnit this,
394        picoos_MemoryManager mm);
395/*------------------------------------------------------------------
396 Processing routines :
397 ------------------------------------------------------------------*/
398static picodata_step_result_t pam_step(register picodata_ProcessingUnit this,
399        picoos_int16 mode, picoos_uint16 * numBytesOutput);
400static pico_status_t pam_deal_with(const picoos_uint8 *item);
401/*Utility*/
402static picoos_uint8 pam_get_vowel_name(register picodata_ProcessingUnit this,
403        picoos_uint8 *item, picoos_uint8 *pos);
404static picoos_uint8 pam_get_pause_id(register picodata_ProcessingUnit this);
405
406static picoos_uint8 pam_map_sentence_type(picoos_uint8 iteminfo1,
407        picoos_uint8 iteminfo2);
408static picoos_uint8 pam_map_phrase_type(picoos_uint8 iteminfo1,
409        picoos_uint8 iteminfo2);
410
411/*Adapter*/
412static pico_status_t pam_reset_processors(register picodata_ProcessingUnit this);
413static pico_status_t pam_reset_processors_back(
414        register picodata_ProcessingUnit this);
415static 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);
419static pico_status_t pam_process_event_feature(
420        register picodata_ProcessingUnit this, picoos_uint8 nFeat,
421        picoos_uint8 event_type, picoos_uint8 direction);
422static pico_status_t pam_process_event(register picodata_ProcessingUnit this,
423        picoos_uint8 event_type, picoos_uint8 direction);
424static pico_status_t pam_adapter_forward_step(
425        register picodata_ProcessingUnit this, picoos_uint8 *itemBase);
426static pico_status_t pam_adapter_backward_step(
427        register picodata_ProcessingUnit this);
428static pico_status_t pam_do_pause(register picodata_ProcessingUnit this);
429static pico_status_t pam_adapter_do_pauses(register picodata_ProcessingUnit this);
430/*-------------- tree traversal ---------------------------------------*/
431static pico_status_t pam_expand_vector(register picodata_ProcessingUnit this);
432static 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);
435static pico_status_t pam_get_f0(register picodata_ProcessingUnit this,
436        picoos_uint16 *lf0Index, picoos_uint8 nState, picoos_single *phonF0);
437static pico_status_t pam_get_duration(register picodata_ProcessingUnit this,
438        picoos_uint16 durIndex, picoos_uint16 *phonDur,
439        picoos_uint8 *numFramesState);
440static pico_status_t pam_update_vector(register picodata_ProcessingUnit this);
441/*-------------- FINAL ITEM FEEDING -----------------------------------------*/
442static pico_status_t pam_put_item(register picodata_ProcessingUnit this,
443                picoos_uint8 *outBuff, picoos_uint16 outWritePos,
444                picoos_uint8 *bytesWr);
445
446static pico_status_t pam_put_term(picoos_uint8 *outBuff,
447        picoos_uint16 outWritePos, picoos_uint8 *bytesWr);
448
449static pico_status_t is_pam_command(const picoos_uint8 *qItem);
450
451static 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 */
468static 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 */
533static 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 */
559static 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 */
717static 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 */
738static 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 */
783picodata_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 */
842static 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 */
889static 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 */
907static 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 */
926static 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 */
992static 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 */
1025static 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 */
1069static 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 */
1132static 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 */
1161static 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 */
1190static 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 */
1252static 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 */
1290static 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 */
1334static 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 */
1377static 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 */
1439static 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 */
1488static 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 */
1518static 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 */
1583static 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 */
1605static 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 */
1677static 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 */
1721static 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 */
1896static 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 */
1989static 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 */
2010static 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 */
2037static 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 */
2064static 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 */
2123static 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 */
2165static 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 */
2187static 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 */
2259static 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 */
2315static 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 */
2780static 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 */
2824static 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 */
2857static 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 */
2878static 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 */
2905static 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 */
2958static 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 */
3012static 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 */
3100static 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 */
4178static 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 */
4223static 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 */
4399static 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 */
4591static 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 */
4660static 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 */
4782static 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