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