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