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