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