diff options
Diffstat (limited to 'lib/picopam.c')
-rw-r--r-- | lib/picopam.c | 4803 |
1 files changed, 4803 insertions, 0 deletions
diff --git a/lib/picopam.c b/lib/picopam.c new file mode 100644 index 0000000..02e5cc2 --- /dev/null +++ b/lib/picopam.c @@ -0,0 +1,4803 @@ +/* + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file picopam.c + * + * Phonetic to Acoustic Mapping PU - Implementation + * + * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland + * All rights reserved. + * + * History: + * - 2009-04-20 -- initial version + * + */ + +#include "picodefs.h" +#include "picoos.h" +#include "picodbg.h" +#include "picodata.h" +#include "picopam.h" +#include "picokdt.h" +#include "picokpdf.h" +#include "picoktab.h" +#include "picokdbg.h" +#include "picodsp.h" + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#define PICOPAM_IN_BUFF_SIZE PICODATA_BUFSIZE_PAM /*input buffer size for PAM */ +#define PICOPAM_OUT_PAM_SIZE PICODATA_BUFSIZE_PAM /*output buffer size for PAM*/ +#define PICOPAM_DT_NRLFZ 5 /* nr of lfz decision trees per phoneme */ +#define PICOPAM_DT_NRMGC 5 /* nr of mgc decision trees per phoneme */ +#define PICOPAM_NRSTPF 5 /* nr of states per phone */ + +#define PICOPAM_COLLECT 0 +#define PICOPAM_SCHEDULE 1 +#define PICOPAM_IMMEDIATE 2 +#define PICOPAM_FORWARD 3 +#define PICOPAM_FORWARD_FORCE_TERM 4 +#define PICOPAM_PROCESS 5 +#define PICOPAM_PLAY 6 +#define PICOPAM_FEED 7 + +#define PICOPAM_CONTINUE 100 +#define PICOPAM_GOTO_SCHEDULE 1 +#define PICOPAM_FLUSH_RECEIVED 6 +#define PICOPAM_GOTO_FEED 7 +#define PICOPAM_PRE_SYLL_ENDED 10 + +#define PICOPAM_BREAK_ADD_SIZE 4 /*syllable feature vector increment dued to BREAK and SILENCE*/ +#define PICOPAM_VECT_SIZE 64+PICOPAM_BREAK_ADD_SIZE /*syllable feature vector size (bytes)*/ +#define PICOPAM_INVEC_SIZE 60 /*phone feature vector size */ +#define PICOPAM_MAX_SYLL_PER_SENT 100 /*maximum number of syllables per sentece*/ +#define PICOPAM_MAX_PH_PER_SENT 400 /*maximum number of phonemes per sentece*/ +#define PICOPAM_MAX_ITEM_PER_SENT 255 /*maximum number of attached items per sentence*/ +#define PICOPAM_MAX_ITEM_SIZE_PER_SENT 4096 /*maximum size of attached items per sentence*/ + +#define PICOPAM_READY 20 /*PAM could start backward processing*/ +#define PICOPAM_MORE 21 /*PAM has still to collect */ +#define PICOPAM_NA 22 /*PAM has not to deal with this item*/ +#define PICOPAM_ERR 23 /*input item is not a valid item*/ + +/*sentence types:cfr pam_map_sentence_type*/ +#define PICOPAM_DECLARATIVE 0 +#define PICOPAM_INTERROGATIVE 1 +#define PICOPAM_EXCLAMATIVE 2 + +#define PICOPAM_T 0 +#define PICOPAM_P 1 +#define PICOPAM_p 2 +#define PICOPAM_Y 3 + +#if 1 +#define PAM_PHR2_WITH_PR1 1 /*deal with PHR2 boundaries as with PHR1*/ +#else +#define PAM_PHR2_WITH_PR3 1 /*deal with PHR2 boundaries as with PHR3*/ +#endif + +#define PICOPAM_DONT_CARE_VALUE 250 /*don't care value for tree printout */ +#define PICOPAM_DONT_CARE_VAL 10 /*don't care value for tree feeding */ +#define PICOPAM_PH_DONT_CARE_VAL 7 /*don't care value for tree feeding (phonetic)*/ + +#define PICOPAM_MAX_STATES_PER_PHONE 5 /*number of states per phone */ +#define PICOPAM_STATE_SIZE_IN_ITEM 6 /*size of a state in frame item */ +#define PICOPAM_FRAME_ITEM_SIZE 4+PICOPAM_MAX_STATES_PER_PHONE*PICOPAM_STATE_SIZE_IN_ITEM + +#define PICOPAM_DIR_FORW 0 /*forward adapter processing*/ +#define PICOPAM_DIR_BACK 1 /*backward adapter processing*/ +#define PICOPAM_DIR_SIL 2 /*final silence attributes*/ + +#define PICOPAM_SYLL_PAUSE 0 /*syllable but containing a pause phone*/ +#define PICOPAM_SYLL_SYLL 1 /*a real syllable with phonemes*/ + +#define PICOPAM_EVENT_P_BOUND 0 /*primary boundary*/ +#define PICOPAM_EVENT_S_BOUND 1 /*secondary boundary*/ +#define PICOPAM_EVENT_W_BOUND 3 /*word boundary*/ +#define PICOPAM_EVENT_SYLL 4 /*syllable*/ + +/* ----- CONSTANTS FOR BREAK COMMAND SUPPORT ----- */ +#define PICOPAM_PWIDX_SBEG 0 +#define PICOPAM_PWIDX_PHR1 1 +#define PICOPAM_PWIDX_PHR2 2 +#define PICOPAM_PWIDX_SEND 3 +#define PICOPAM_PWIDX_DEFA 4 +#define PICOPAM_PWIDX_SIZE 5 + +/*----------------------------------------------------------------*/ +/*structure related to the feature vectors for feeding the trees */ +/*NOTE : the same data structure is used to manage the syllables */ +/* Using the first 8 fields for marking the boundaries */ +/* and using the last 4 bytes as follows */ +/* byte 61 : 1st attached non PAM item id(0=no item attached) */ +/* in the "sSyllItemOffs" data structure */ +/* byte 62 : last attached non PAM item id(0=no item attached)*/ +/* in the "sSyllItemOffs" data structure */ +/* byte 63..64 : offset of the start of the syllable in */ +/* the "sPhIds" data structure */ +typedef struct +{ + picopal_uint8 phoneV[PICOPAM_VECT_SIZE]; +} sFtVect, *pSftVect; + +/*---------------------------------------------------------- + Name : pam_subobj + Function: subobject definition for the pam processing + Shortcut: pam + ---------------------------------------------------------*/ +typedef struct pam_subobj +{ + /*----------------------PU voice management------------------------------*/ + /* picorsrc_Voice voice; */ + /*----------------------PU state management------------------------------*/ + picoos_uint8 procState; /* where to take up work at next processing step */ + picoos_uint8 retState; /* where to go back from feed state at next p.s. */ + picoos_uint8 needMoreInput; /* more data necessary to start processing */ + /*----------------------PU input management------------------------------*/ + picoos_uint8 inBuf[PICOPAM_IN_BUFF_SIZE]; /* internal input buffer */ + picoos_uint16 inBufSize; /* actually allocated size */ + picoos_uint16 inReadPos, inWritePos; /* next pos to read/write from/to inBuf*/ + /*----------------------PU output management-----------------------------*/ + picoos_uint8 outBuf[PICOPAM_OUT_PAM_SIZE]; /* internal output buffer */ + picoos_uint16 outBufSize; /* actually allocated size */ + picoos_uint16 outReadPos, outWritePos; /* next pos to read/write from/to outBuf*/ + /*---------------------- adapter working buffers --------------------*/ + picoos_uint8 *sPhFeats; /*feature vector for a single phone */ + sFtVect *sSyllFeats; /*Syllable feature vector set for the + full sentence */ + picoos_uint8 *sPhIds; /*phone ids for the full sentence */ + picoos_uint8 *sSyllItems; /*items attached to the syllable */ + picoos_int16 *sSyllItemOffs;/*offset of items attached to the syllable*/ + /*---------------------- adapter general variables ---------------------*/ + picoos_int16 nTotalPhonemes; /*number of phonemes in the sentence*/ + picoos_int16 nCurrPhoneme; /*current phoneme in the sentence */ + picoos_int16 nSyllPhoneme; /*current phoneme in the syllable */ + picoos_int16 nCurrSyllable; /*current syllable in the sentence */ + picoos_int16 nTotalSyllables; /*number of syllables in the sentence -> J1*/ + picoos_uint8 nLastAttachedItemId;/*last attached item id*/ + picoos_uint8 nCurrAttachedItem; /*current attached item*/ + picoos_int16 nAttachedItemsSize; /*total size of the attached items*/ + picoos_uint8 sType; /*Sentence type*/ + picoos_uint8 pType; /*Phrase type*/ + picoos_single pMod; /*pitch modifier*/ + picoos_single dMod; /*Duration modifier*/ + picoos_single dRest; /*Duration modifier rest*/ + /*---------------------- adapter specific component variables ----------*/ + picoos_uint8 a3_overall_syllable; /* A3 */ + picoos_uint8 a3_primary_phrase_syllable; + picoos_uint8 b4_b5_syllable; /* B4,B5 */ + picoos_uint8 b6_b7_syllable; /* B6,B7 */ + picoos_uint8 b6_b7_state; + picoos_uint8 b8_b9_stressed_syllable; /* B8,B9 */ + picoos_uint8 b10_b11_accented_syllable; /* B10,B11 */ + picoos_uint8 b12_b13_syllable; /* B12,B13 */ + picoos_uint8 b12_b13_state; + picoos_uint8 b14_b15_syllable; /* B14,B15 */ + picoos_uint8 b14_b15_state; + picoos_uint8 b17_b19_syllable; /* B17,B19 */ + picoos_uint8 b17_b19_state; + picoos_uint8 b18_b20_b21_syllable; /* B18,B20,B21 */ + picoos_uint8 b18_b20_b21_state; + picoos_uint8 c3_overall_syllable; /* C3 */ + picoos_uint8 c3_primary_phrase_syllable; + picoos_uint8 d2_syllable_in_word; /* D2 */ + picoos_uint8 d2_prev_syllable_in_word; + picoos_uint8 d2_current_primary_phrase_word; + picoos_int8 e1_syllable_word_start; /* E1 */ + picoos_int8 e1_syllable_word_end; + picoos_uint8 e1_content; + picoos_int8 e2_syllable_word_start; /* E2 */ + picoos_int8 e2_syllable_word_end; + picoos_uint8 e3_e4_word; /* E3,E4 */ + picoos_uint8 e3_e4_state; + picoos_uint8 e5_e6_content_word; /* E5,E6 */ + picoos_uint8 e5_e6_content; + picoos_uint8 e7_e8_word; /* E7,E8 */ + picoos_uint8 e7_e8_content; + picoos_uint8 e7_e8_state; + picoos_uint8 e9_e11_word; /* E9,E11 */ + picoos_uint8 e9_e11_saw_word; + picoos_uint8 e9_e11_state; + picoos_uint8 e10_e12_e13_word; /* E10,E12,E13 */ + picoos_uint8 e10_e12_e13_state; + picoos_uint8 e10_e12_e13_saw_word; + picoos_uint8 f2_overall_word; /* F2 */ + picoos_uint8 f2_word_syllable; + picoos_uint8 f2_next_word_syllable; + picoos_uint8 f2_current_primary_phrase_word; + picoos_int8 g1_current_secondary_phrase_syllable; /*G1 */ + picoos_int8 g1_current_syllable; + picoos_int8 g2_current_secondary_phrase_word; /*G2 */ + picoos_int8 g2_current_word; + picoos_uint8 h1_current_secondary_phrase_syll; /*H1 */ + picoos_uint8 h2_current_secondary_phrase_word; /*H2 */ + picoos_uint8 h3_h4_current_secondary_phrase_word; /*H3,H4 */ + picoos_uint8 h5_current_phrase_type; /*H5 */ + + picoos_uint8 h5_syllable; /* H5 */ + picoos_uint8 h5_state; + + picoos_uint8 i1_secondary_phrase_syllable; /*I1 */ + picoos_uint8 i1_next_secondary_phrase_syllable; + picoos_uint8 i2_secondary_phrase_word; /*I2 */ + picoos_uint8 i2_next_secondary_phrase_word; + picoos_uint8 j1_utterance_syllable; /*J1 */ + picoos_uint8 j2_utterance_word; /*J2 */ + picoos_uint8 j3_utterance_sec_phrases; /*J3 */ + /*---------------------- constant data -------------------*/ + picoos_uint16 sil_weights[PICOPAM_PWIDX_SIZE][PICOPAM_MAX_STATES_PER_PHONE]; + /*---------------------- LINGWARE related data -------------------*/ + picokdt_DtPAM dtdur; /* dtdur knowledge base */ + picokdt_DtPAM dtlfz[PICOPAM_DT_NRLFZ]; /* dtlfz knowledge bases */ + picokdt_DtPAM dtmgc[PICOPAM_DT_NRMGC]; /* dtmgc knowledge bases */ + /*---------------------- Pdfs related data -------------------*/ + picokpdf_PdfDUR pdfdur; /* pdfdur knowledge base */ + picokpdf_PdfMUL pdflfz; /* pdflfz knowledge base */ + /*---------------------- Tree traversal related data -------------------*/ + picoos_uint16 durIndex; + picoos_uint8 numFramesState[PICOPAM_DT_NRLFZ]; + picoos_uint16 lf0Index[PICOPAM_DT_NRLFZ]; + picoos_uint16 mgcIndex[PICOPAM_DT_NRMGC]; + /*---------------------- temps for updating the feature vector ---------*/ + picoos_uint16 phonDur; + picoos_single phonF0[PICOPAM_DT_NRLFZ]; + /*---------------------- Phones related data -------------------*/ + picoktab_Phones tabphones; +} pam_subobj_t; + + +/* ----- CONSTANTS FOR FEATURE VECTOR BUILDING (NOT PREFIXED WITH "PICOPAM_" FOR BREVITY) ----- */ +#define P1 0 /*field 1 of the input vector*/ +#define P2 1 +#define P3 2 +#define P4 3 +#define P5 4 +#define P6 5 +#define P7 6 +#define bnd 6 /*boundary type item associated to the syllable = P7 */ +#define P8 7 +#define A3 8 +#define B1 9 +#define B2 10 +#define B3 11 +#define B4 12 +#define B5 13 +#define B6 14 +#define B7 15 +#define B8 16 +#define B9 17 +#define B10 18 +#define B11 19 +#define B12 20 +#define B13 21 +#define B14 22 +#define B15 23 +#define B16 24 +#define B17 25 +#define B18 26 +#define B19 27 +#define B20 28 +#define B21 29 +#define C3 30 +#define D2 31 +#define E1 32 +#define E2 33 +#define E3 34 +#define E4 35 +#define E5 36 +#define E6 37 +#define E7 38 +#define E8 39 +#define E9 40 +#define E10 41 +#define E11 42 +#define E12 43 +#define E13 44 +#define F2 45 +#define G1 46 +#define G2 47 +#define H1 48 +#define H2 49 +#define H3 50 +#define H4 51 +#define H5 52 +#define I1 53 +#define I2 54 +#define J1 55 +#define J2 56 +#define J3 57 +#define DUR 58 /*duration component*/ +#define F0 59 /*F0 component*/ +#define ITM 60 /*Item Offset into sSyllItems item list*/ +#define itm 61 /*second byte of the Item Offset */ +#define FID 62 /*Phoneme offset in the sPhIds phoneme list*/ +#define fid 63 /*second byte of the Phoneme offset */ +#define Min 64 /*offset to min syllable duration (uint 16,pauses)*/ +#define Max 66 /*offset to max syllable duration (uint 16,pauses)*/ +/* ------------------------------------------------------------------- + PAM feature vector indices position changes, + ------------------------------------------------------------------- */ +#define T_B1 8 +#define T_B2 9 +#define T_B3 10 +#define T_B4 11 +#define T_B5 12 +#define T_B6 13 +#define T_B7 14 +#define T_B8 15 +#define T_B9 16 +#define T_B10 17 +#define T_B11 18 +#define T_B12 19 +#define T_B13 20 +#define T_B14 21 +#define T_B15 22 +#define T_B16 23 +#define T_B17 24 +#define T_B18 25 +#define T_B19 26 +#define T_B20 27 +#define T_B21 28 +#define T_E1 29 +#define T_E2 30 +#define T_E3 31 +#define T_E4 32 +#define T_E5 33 +#define T_E6 34 +#define T_E7 35 +#define T_E8 36 +#define T_E9 37 +#define T_E10 38 +#define T_E11 39 +#define T_E12 40 +#define T_E13 41 +#define T_A3 42 +#define T_C3 43 +#define T_D2 44 +#define T_F2 45 +#define T_G1 46 +#define T_I1 47 +#define T_G2 48 +#define T_I2 49 +#define T_H1 50 +#define T_H2 51 +#define T_H3 52 +#define T_H4 53 +#define T_H5 54 + +/*------------------------------------------------------------------ + Service routines : + ------------------------------------------------------------------*/ +static pico_status_t pam_initialize(register picodata_ProcessingUnit this); +static pico_status_t pam_terminate(register picodata_ProcessingUnit this); +static pico_status_t pam_allocate(picoos_MemoryManager mm, pam_subobj_t *pam); +static void pam_deallocate(picoos_MemoryManager mm, pam_subobj_t *pam); +static pico_status_t pam_subobj_deallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm); +/*------------------------------------------------------------------ + Processing routines : + ------------------------------------------------------------------*/ +static picodata_step_result_t pam_step(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput); +static pico_status_t pam_deal_with(const picoos_uint8 *item); +/*Utility*/ +static picoos_uint8 pam_get_vowel_name(register picodata_ProcessingUnit this, + picoos_uint8 *item, picoos_uint8 *pos); +static picoos_uint8 pam_get_pause_id(register picodata_ProcessingUnit this); + +static picoos_uint8 pam_map_sentence_type(picoos_uint8 iteminfo1, + picoos_uint8 iteminfo2); +static picoos_uint8 pam_map_phrase_type(picoos_uint8 iteminfo1, + picoos_uint8 iteminfo2); + +/*Adapter*/ +static pico_status_t pam_reset_processors(register picodata_ProcessingUnit this); +static pico_status_t pam_reset_processors_back( + register picodata_ProcessingUnit this); +static pico_status_t pam_create_syllable(register picodata_ProcessingUnit this, + picoos_uint8 syllType, picoos_uint8 *sContent, picoos_uint8 sentType, + picoos_uint8 phType, picoos_uint8 uBoundType, picoos_uint16 uMin, + picoos_uint16 uMax); +static pico_status_t pam_process_event_feature( + register picodata_ProcessingUnit this, picoos_uint8 nFeat, + picoos_uint8 event_type, picoos_uint8 direction); +static pico_status_t pam_process_event(register picodata_ProcessingUnit this, + picoos_uint8 event_type, picoos_uint8 direction); +static pico_status_t pam_adapter_forward_step( + register picodata_ProcessingUnit this, picoos_uint8 *itemBase); +static pico_status_t pam_adapter_backward_step( + register picodata_ProcessingUnit this); +static pico_status_t pam_do_pause(register picodata_ProcessingUnit this); +static pico_status_t pam_adapter_do_pauses(register picodata_ProcessingUnit this); +/*-------------- tree traversal ---------------------------------------*/ +static pico_status_t pam_expand_vector(register picodata_ProcessingUnit this); +static picoos_uint8 pam_do_tree(register picodata_ProcessingUnit this, + const picokdt_DtPAM dtpam, const picoos_uint8 *invec, + const picoos_uint8 inveclen, picokdt_classify_result_t *dtres); +static pico_status_t pam_get_f0(register picodata_ProcessingUnit this, + picoos_uint16 *lf0Index, picoos_uint8 nState, picoos_single *phonF0); +static pico_status_t pam_get_duration(register picodata_ProcessingUnit this, + picoos_uint16 durIndex, picoos_uint16 *phonDur, + picoos_uint8 *numFramesState); +static pico_status_t pam_update_vector(register picodata_ProcessingUnit this); +/*-------------- FINAL ITEM FEEDING -----------------------------------------*/ +static pico_status_t pam_put_item(register picodata_ProcessingUnit this, + picoos_uint8 *outBuff, picoos_uint16 outWritePos, + picoos_uint8 *bytesWr); + +static pico_status_t pam_put_term(picoos_uint8 *outBuff, + picoos_uint16 outWritePos, picoos_uint8 *bytesWr); + +static pico_status_t is_pam_command(const picoos_uint8 *qItem); + +static void get_default_boundary_limit(picoos_uint8 uBoundType, + picoos_uint16 *uMinDur, picoos_uint16 *uMaxDur); + +/* ------------------------------------------------------------- + * Pico System functions + * ------------------------------------------------------------- + */ + +/** + * allocation for PAM memory on pam PU + * @param mm : handle to engine memory manager + * @param pam : handle to a pam struct + * @return PICO_OK : allocation successful + * @return PICO_ERR_OTHER : allocation errors + * @callgraph + * @callergraph + */ +static pico_status_t pam_allocate(picoos_MemoryManager mm, pam_subobj_t *pam) +{ + picoos_uint8 *data; + picoos_int16 *dataI; + + pam->sSyllFeats = NULL; + pam->sPhIds = NULL; + pam->sPhFeats = NULL; + pam->sSyllItems = NULL; + pam->sSyllItemOffs = NULL; + + /*----------------------------------------------------------------- + * PAM Local buffers ALLOCATION + ------------------------------------------------------------------*/ + /*PAM Local buffers*/ + data = (picopal_uint8 *) picoos_allocate(mm, sizeof(sFtVect) + * PICOPAM_MAX_SYLL_PER_SENT); + if (data == NULL) + return PICO_ERR_OTHER; + pam->sSyllFeats = (sFtVect*) data; + + data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8) + * PICOPAM_MAX_PH_PER_SENT); + if (data == NULL) { + pam_deallocate(mm, pam); + return PICO_ERR_OTHER; + } + pam->sPhIds = (picopal_uint8*) data; + + data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8) + * PICOPAM_VECT_SIZE); + if (data == NULL) { + pam_deallocate(mm, pam); + return PICO_ERR_OTHER; + } + pam->sPhFeats = (picopal_uint8*) data; + + data = (picopal_uint8 *) picoos_allocate(mm, sizeof(picopal_uint8) + * PICOPAM_MAX_ITEM_SIZE_PER_SENT); + if (data == NULL) { + pam_deallocate(mm, pam); + return PICO_ERR_OTHER; + } + pam->sSyllItems = (picopal_uint8*) data; + + dataI = (picoos_int16 *) picoos_allocate(mm, sizeof(picoos_int16) + * PICOPAM_MAX_ITEM_PER_SENT); + if (data == NULL) { + pam_deallocate(mm, pam); + return PICO_ERR_OTHER; + } + pam->sSyllItemOffs = (picoos_int16*) dataI; + + return PICO_OK; +}/*pam_allocate*/ + +/** + * frees allocation for DSP memory on PAM PU + * @param mm : memory manager + * @param pam : pam PU internal sub-object + * @return void + * @remarks modified and inserted in sub obj removal PP 15.09.08 + * @callgraph + * @callergraph + */ +static void pam_deallocate(picoos_MemoryManager mm, pam_subobj_t *pam) +{ + /*----------------------------------------------------------------- + * Memory de-allocations + * ------------------------------------------------------------------*/ + if (pam->sSyllFeats != NULL) + picoos_deallocate(mm, (void *) &pam->sSyllFeats); + if (pam->sPhIds != NULL) + picoos_deallocate(mm, (void *) &pam->sPhIds); + if (pam->sPhFeats != NULL) + picoos_deallocate(mm, (void *) &pam->sPhFeats); + if (pam->sSyllItems != NULL) + picoos_deallocate(mm, (void *) &pam->sSyllItems); + if (pam->sSyllItemOffs != NULL) + picoos_deallocate(mm, (void *) &pam->sSyllItemOffs); + +}/*pam_deallocate*/ + +/** + * initialization of a pam PU + * @param this : handle to a PU struct + * @return PICO_OK : init OK + * @return PICO_ERR_OTHER : error on getting pkbs addresses + * @callgraph + * @callergraph + */ +static pico_status_t pam_initialize(register picodata_ProcessingUnit this) +{ + pico_status_t nI, nJ; + pam_subobj_t *pam; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + pam->inBufSize = PICOPAM_IN_BUFF_SIZE; + pam->outBufSize = PICOPAM_OUT_PAM_SIZE; + pam->inReadPos = 0; + pam->inWritePos = 0; + pam->outReadPos = 0; + pam->outWritePos = 0; + pam->needMoreInput = 0; + pam->procState = 0; + + /*----------------------------------------------------------------- + * MANAGE INTERNAL INITIALIZATION + ------------------------------------------------------------------*/ + /*init the syllable structure*/ + for (nI = 0; nI < PICOPAM_MAX_SYLL_PER_SENT; nI++) + for (nJ = 0; nJ < PICOPAM_VECT_SIZE; nJ++) + pam->sSyllFeats[nI].phoneV[nJ] = 0; + + for (nI = 0; nI < PICOPAM_MAX_PH_PER_SENT; nI++) + pam->sPhIds[nI] = 0; + + for (nI = 0; nI < PICOPAM_VECT_SIZE; nI++) + pam->sPhFeats[nI] = 0; + + for (nI = 0; nI < PICOPAM_MAX_ITEM_SIZE_PER_SENT; nI++) + pam->sSyllItems[nI] = 0; + + for (nI = 0; nI < PICOPAM_MAX_ITEM_PER_SENT; nI++) + pam->sSyllItemOffs[nI] = 0; + + /*Other variables*/ + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0; + pam->nAttachedItemsSize = 0; + + /*pitch and duration modifiers*/ + pam->pMod = 1.0f; + pam->dMod = 1.0f; + pam->dRest = 0.0f; + + + /* constant tables */ + { + picoos_uint8 i, j; + picoos_uint16 tmp_weights[PICOPAM_PWIDX_SIZE][PICOPAM_MAX_STATES_PER_PHONE] = { + {10, 10, 10, 10, 1 }, /*SBEG*/ + { 1, 4, 8, 4, 1 }, /*PHR1*/ + { 1, 4, 8, 4, 1 }, /*PHR2*/ + { 1, 10, 10, 10, 10 },/*SEND*/ + { 1, 1, 1, 1, 1 } /*DEFAULT*/ + }; + for (i = 0; i < PICOPAM_PWIDX_SIZE; i++) { + for (j = 0; j < PICOPAM_PWIDX_SIZE; j++) { + pam->sil_weights[j][j] = tmp_weights[i][j]; + } + } + } +/*----------------------------------------------------------------- + * MANAGE LINGWARE INITIALIZATION IF NEEDED + ------------------------------------------------------------------*/ + /* kb dtdur */ + pam->dtdur = picokdt_getDtPAM(this->voice->kbArray[PICOKNOW_KBID_DT_DUR]); + if (pam->dtdur == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, + NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got dtdur")); + + /* kb dtlfz* */ + pam->dtlfz[0] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ1]); + pam->dtlfz[1] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ2]); + pam->dtlfz[2] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ3]); + pam->dtlfz[3] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ4]); + pam->dtlfz[4] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_LFZ5]); + for (nI = 0; nI < PICOPAM_DT_NRLFZ; nI++) { + if (pam->dtlfz[nI] == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got dtlfz%d", nI+1)); + } + + /* kb dtmgc* */ + pam->dtmgc[0] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC1]); + pam->dtmgc[1] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC2]); + pam->dtmgc[2] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC3]); + pam->dtmgc[3] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC4]); + pam->dtmgc[4] = picokdt_getDtPAM( + this->voice->kbArray[PICOKNOW_KBID_DT_MGC5]); + for (nI = 0; nI < PICOPAM_DT_NRMGC; nI++) { + if (pam->dtmgc[nI] == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, + NULL, NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got dtmgc%d", nI+1)); + } + + /* kb pdfdur* */ + pam->pdfdur = picokpdf_getPdfDUR( + this->voice->kbArray[PICOKNOW_KBID_PDF_DUR]); + if (pam->pdfdur == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, + NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got pdfdur")); + + /* kb pdflfz* */ + pam->pdflfz = picokpdf_getPdfMUL( + this->voice->kbArray[PICOKNOW_KBID_PDF_LFZ]); + if (pam->pdflfz == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, + NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got pdflfz")); + + /* kb tabphones */ + pam->tabphones = picoktab_getPhones( + this->voice->kbArray[PICOKNOW_KBID_TAB_PHONES]); + if (pam->tabphones == NULL) { + picoos_emRaiseException(this->common->em, PICO_EXC_KB_MISSING, NULL, + NULL); + return PICO_ERR_OTHER; + }PICODBG_DEBUG(("got tabphones")); + + return PICO_OK; +}/*pam_initialize*/ + +/** + * termination of a pam PU + * @param this : handle to a pam PU struct + * @return PICO_OK + * @callgraph + * @callergraph + */ +static pico_status_t pam_terminate(register picodata_ProcessingUnit this) +{ + + pam_subobj_t *pam; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + return PICO_OK; +}/*pam_terminate*/ + +/** + * deallocaton of a pam PU + * @param this : handle to a pam PU struct + * @param mm : engine memory manager + * @return PICO_OK + * @callgraph + * @callergraph + */ +static pico_status_t pam_subobj_deallocate(register picodata_ProcessingUnit this, + picoos_MemoryManager mm) +{ + + pam_subobj_t* pam; + + if (NULL != this) { + pam = (pam_subobj_t *) this->subObj; + mm = mm; /* avoid warning "var not used in this function"*/ + /*----------------------------------------------------------------- + * Memory de-allocations + * ------------------------------------------------------------------*/ + if (pam->sSyllFeats != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sSyllFeats); + } + if (pam->sPhIds != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sPhIds); + } + if (pam->sPhFeats != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sPhFeats); + } + if (pam->sSyllItems != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sSyllItems); + } + if (pam->sSyllItemOffs != NULL) { + picoos_deallocate(this->common->mm, (void *) &pam->sSyllItemOffs); + } + picoos_deallocate(this->common->mm, (void *) &this->subObj); + } + + return PICO_OK; +}/*pam_subobj_deallocate*/ + +/** + * creates a new pam processing unit + * @param mm : engine memory manager + * @param common : engine common object pointer + * @param cbIn : pointer to input buffer + * @param cbOut : pointer to output buffer + * @param voice : pointer to voice structure + * @return this : pam PU handle if success + * @return NULL : if error + * @callgraph + * @callergraph + */ +picodata_ProcessingUnit picopam_newPamUnit(picoos_MemoryManager mm, + picoos_Common common, picodata_CharBuffer cbIn, + picodata_CharBuffer cbOut, picorsrc_Voice voice) +{ + + register pam_subobj_t * pam; + + picodata_ProcessingUnit this = picodata_newProcessingUnit(mm, common, cbIn, + cbOut, voice); + if (this == NULL) { + return NULL; + } + this->initialize = pam_initialize; + + PICODBG_DEBUG(("picotok_newPamUnit -- set this->step to pam_step")); + + this->step = pam_step; + this->terminate = pam_terminate; + this->subDeallocate = pam_subobj_deallocate; + this->subObj = picoos_allocate(mm, sizeof(pam_subobj_t)); + if (this->subObj == NULL) { + PICODBG_ERROR(("Error in Pam Object allocation")); + picoos_deallocate(mm, (void*) &this); + return NULL; + }; + + /*----------------------------------------------------------------- + * Allocate internal memory for PAM (only at PU creation time) + * ------------------------------------------------------------------*/ + pam = (pam_subobj_t *) this->subObj; + if (PICO_OK != pam_allocate(mm, pam)) { + PICODBG_ERROR(("Error in Pam buffers Allocation")); + picoos_deallocate(mm, (void *) &this->subObj); + picoos_deallocate(mm, (void *) &this); + return NULL; + } + + /*----------------------------------------------------------------- + * Initialize memory for PAM (this may be re-used elsewhere, e.g.Reset) + * ------------------------------------------------------------------*/ + if (PICO_OK != pam_initialize(this)) { + PICODBG_ERROR(("problem initializing the pam sub-object")); + } + return this; +}/*picopam_newPamUnit*/ + +/*------------------------------------------------------------------------------- + PROCESSING AND INTERNAL FUNCTIONS + --------------------------------------------------------------------------------*/ + +/** + * initializes default duration limits for boundary items + * @param uBoundType : type of input boundary type + * @param *uMinDur, *uMaxDur : addresses of values to initialize + * @return void + * @remarks so far initializes to 0 both values; this will leave the values given by tree prediction + * @callgraph + * @callergraph + */ +static void get_default_boundary_limit(picoos_uint8 uBoundType, + picoos_uint16 *uMinDur, picoos_uint16 *uMaxDur) +{ + switch (uBoundType) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + *uMinDur = 0; + *uMaxDur = 20; + break; + case PICODATA_ITEMINFO1_BOUND_SEND: + *uMinDur = 550; + *uMaxDur = 650; + break; + case PICODATA_ITEMINFO1_BOUND_TERM: + *uMinDur = 0; + *uMaxDur = 0; + break; + case PICODATA_ITEMINFO1_BOUND_PHR0: + *uMinDur = 0; + *uMaxDur = 0; + break; + case PICODATA_ITEMINFO1_BOUND_PHR1: + *uMinDur = 275; + *uMaxDur = 325; + break; + case PICODATA_ITEMINFO1_BOUND_PHR2: + *uMinDur = 4; + *uMaxDur = 60; + break; + case PICODATA_ITEMINFO1_BOUND_PHR3: + *uMinDur = 0; + *uMaxDur = 0; + break; + default: + break; + } + +}/*get_default_boundary_limit*/ + +/** + * checks if "neededSize" is available on "nCurrPhoneme" + * @param pam : pam subobj + * @param neededSize : the requested size + * @return PICO_OK : size is available + * @return !=PICO_OK : size not available + * @callgraph + * @callergraph + */ +static pico_status_t check_phones_size(pam_subobj_t *pam, + picoos_int16 neededSize) +{ + if ((pam->nCurrPhoneme + neededSize) > PICOPAM_MAX_PH_PER_SENT - 1) { + return PICO_ERR_OTHER; + } + return PICO_OK; +}/*check_phones_size*/ + +/** + * checks if neededSize is available on "nCurrSyllable" + * @param pam : pam subobj + * @param neededSize : the requested size + * @return PICO_OK : size is available + * @return !=PICO_OK : size not available + * @callgraph + * @callergraph + */ +static pico_status_t check_syllables_size(pam_subobj_t *pam, + picoos_int16 neededSize) +{ + if ((pam->nCurrSyllable + neededSize) > PICOPAM_MAX_SYLL_PER_SENT - 1) { + return PICO_ERR_OTHER; + } + return PICO_OK; +}/*check_syllables_size*/ + +/** + * verifies that local storage has enough space to receive 1 item + * @param this : pointer to current PU struct + * @param item : pointer to current item head + * @return TRUE : resource limits would be reached during processing of input item + * @return FALSE : item could be processed normally + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pamCheckResourceLimits( + register picodata_ProcessingUnit this, const picoos_uint8 *item) +{ + register pam_subobj_t * pam; + picodata_itemhead_t head; + pico_status_t sResult; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + sResult = TRUE; /*default : resource limits reached*/ + head.type = item[0]; + head.info1 = item[1]; + head.info2 = item[2]; + head.len = item[3]; + + switch (head.type) { + /*commands that generate syllables/phonemes*/ + case PICODATA_ITEM_SYLLPHON: + if (pam->nCurrSyllable >= PICOPAM_MAX_SYLL_PER_SENT - 2) { + return sResult; /*no room for more syllables*/ + } + if ((pam->nCurrPhoneme + head.len) >= PICOPAM_MAX_PH_PER_SENT - 2) { + return sResult; /*no room for more phoneme*/ + } + break; + case PICODATA_ITEM_BOUND: + if ((head.info1 == PICODATA_ITEMINFO1_BOUND_SBEG) || (head.info1 + == PICODATA_ITEMINFO1_BOUND_SEND) || (head.info1 + == PICODATA_ITEMINFO1_BOUND_TERM) || (head.info1 + == PICODATA_ITEMINFO1_BOUND_PHR1) +#ifdef PAM_PHR2_WITH_PR1 + || (head.info1 == PICODATA_ITEMINFO1_BOUND_PHR2) +#endif + ) { + + if (pam->nCurrSyllable >= PICOPAM_MAX_SYLL_PER_SENT - 2) { + return sResult; /*no room for more syllables*/ + } + if ((pam->nCurrPhoneme + 1) >= PICOPAM_MAX_PH_PER_SENT - 2) { + return sResult; /*no room for more phoneme*/ + } + } + break; + + default: + /*all other commands has to be queued*/ + if ((pam->nAttachedItemsSize + head.len) + >= PICOPAM_MAX_ITEM_SIZE_PER_SENT - 1) { + return sResult; /*no room for more items*/ + } + break; + } + return FALSE; /*no resource limits apply to current item*/ +} /*pamCheckResourceLimits*/ + +/** + * selects items to be sent to next PU immedately + * @param this : pointer to current PU struct + * @param item : pointer to current item head + * @return TRUE : item should be passed on next PU NOW + * @return FALSE : item should not be passed on next PU now but should be processed + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pam_check_immediate(register picodata_ProcessingUnit this, + const picoos_uint8 *item) +{ + register pam_subobj_t * pam; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + + if (pam->nCurrSyllable <= -1) { + if (item[0] == PICODATA_ITEM_SYLLPHON) + return FALSE; + if ((item[0] == PICODATA_ITEM_BOUND) && (item[1] + == PICODATA_ITEMINFO1_BOUND_SBEG)) + return FALSE; + if (is_pam_command((picoos_uint8 *) item) == TRUE) + return FALSE; + return TRUE; /*no need to process data : send it*/ + } + return FALSE; /*syllable struct not void : do standard processing*/ + +} /*pam_check_immediate*/ + +/** + * checks if the input item has to be queued in local storage for later resynch + * @param this : pointer to current PU struct + * @param item : pointer to current item head + * @return TRUE : item should be queued + * @return FALSE : item should not be queued + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pam_hastobe_queued(register picodata_ProcessingUnit this, + const picoos_uint8 *item) +{ + register pam_subobj_t * pam; + picodata_itemhead_t head; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + head.type = item[0]; + head.info1 = item[1]; + + switch (head.type) { + /*commands that generate syllables/phonemes*/ + case PICODATA_ITEM_SYLLPHON: + return FALSE; /*no queue needed*/ + break; + case PICODATA_ITEM_BOUND: + if ((head.info1 == PICODATA_ITEMINFO1_BOUND_PHR3) +#ifdef PAM_PHR2_WITH_PR3 + ||(head.info1==PICODATA_ITEMINFO1_BOUND_PHR2) +#endif + || (head.info1 == PICODATA_ITEMINFO1_BOUND_PHR0)) { + return FALSE; /*no queue needed*/ + } + break; + + default: + /*all other items has to be queued*/ + break; + } + return TRUE; /*item has to be queued*/ +} /*pam_hastobe_queued*/ + +/** + * queue item in local storage for later resynch + * @param this : pointer to current PU struct + * @param item : pointer to current item head + * @return TRUE : item queued + * @return FALSE : item not queued because of errors + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pam_queue(register picodata_ProcessingUnit this, + const picoos_uint8 *item) +{ + register pam_subobj_t * pam; + picodata_itemhead_t head; + picoos_uint8 nI; + pico_status_t sResult; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + sResult = TRUE; /*default : item queued*/ + head.type = item[0]; + head.info1 = item[1]; + head.info2 = item[2]; + head.len = item[3]; + + /*test condition on enough room to store current item in the "sSyllItems" area*/ + if ((pam->nAttachedItemsSize + head.len + sizeof(picodata_itemhead_t)) + >= PICOPAM_MAX_ITEM_SIZE_PER_SENT - 1) { + return FALSE; /*resource limit reached*/ + } + /*store current offset*/ + pam->sSyllItemOffs[pam->nLastAttachedItemId] = pam->nAttachedItemsSize; + /*store the item to the "sSyllItems" area*/ + for (nI = 0; nI < (head.len + sizeof(picodata_itemhead_t)); nI++) { + pam->sSyllItems[pam->nAttachedItemsSize + nI] = item[nI]; + } + /*increment the attached items area*/ + pam->nAttachedItemsSize += nI; + + /*increment id*/ + pam->nLastAttachedItemId++; + /*set start(if not initialized) and end ids of queued items in sSyllFeats*/ + if (pam->nCurrSyllable > -1) { + /*normal case : the item is attached to current syllable*/ + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] == 0) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] + = pam->nLastAttachedItemId; + } + pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] + = pam->nLastAttachedItemId; + } else { + /*special case : an item is requested to be queued even if no + syllables has been assigned to the sentence structure : + -->> use syll 0*/ + if (pam->sSyllFeats[0].phoneV[ITM] == 0) { + pam->sSyllFeats[0].phoneV[ITM] = pam->nLastAttachedItemId; + } + pam->sSyllFeats[0].phoneV[itm] = pam->nLastAttachedItemId; + } + return TRUE; /*item queued successfully*/ +} /*pam_queue*/ + +/** + * selects items to be dealth with by the PU processing + * @param item : pointer to current item head + * @return TRUE : item should be processed + * @return FALSE : item should not be processed (maybe it ontains commands or items for other PUs) + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static pico_status_t pam_deal_with(const picoos_uint8 *item) +{ + picodata_itemhead_t head; + pico_status_t sResult; + sResult = FALSE; + head.type = item[0]; + head.info1 = item[1]; + head.info2 = item[2]; + head.len = item[3]; + switch (head.type) { + case PICODATA_ITEM_SYLLPHON: + case PICODATA_ITEM_BOUND: + sResult = TRUE; + break; + default: + break; + } + return sResult; +} /*pam_deal_with*/ + +/** + * returns true if more items has to be produced for current syllable + * @param this : Pam object pointer + * @return TRUE : item is to be produced + * @return FALSE : item is not to be produced + * @remarks item pointed to by *item should be already valid + * @callgraph + * @callergraph + */ +static picoos_uint8 pamHasToProcess(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint8 nCond1, nCond2, nCond3; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + /*conditions originating a "NOT to be processed" result */ + nCond1 = pam->nCurrSyllable <= -1; + nCond2 = pam->nCurrSyllable >= pam->nTotalSyllables; + nCond3 = pam->nSyllPhoneme + >= pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3]; + + if ((nCond1) || (nCond2) || (nCond3)) + return FALSE; + + return TRUE; +} /*pamHasToProcess*/ + +/** + * modifies the process flags in order to point to next valid syllable phone or item to be produced + * @param this : Pam object pointer + * @return TRUE : item has to be produced + * @return FALSE : item has not to be produced + * @callgraph + * @callergraph + */ +static pico_status_t pamUpdateProcess(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + + if (pam->nCurrSyllable == -1) { + /*this to be able to manage sudden PU cleanup after FLUSH CMD*/ + return PICO_OK; + } + /*check number of phonemes for current syllable*/ + if (pam->nSyllPhoneme < pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] - 1) { + pam->nSyllPhoneme++; + return PICO_OK; + } + if (pam->nSyllPhoneme == pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] - 1) { + /*this helps in identifyng the end of syllable condition in PamHasToProcess*/ + pam->nSyllPhoneme++; + } + /*previous syllable phonemes are complete: test if any items are tied to this syllable*/ + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] > 0) { + /*there are items tied to this syllable*/ + if (pam->nCurrAttachedItem == 0) { + /*if it is the first item to be regenerated initialize it*/ + pam->nCurrAttachedItem + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM]; + return PICO_OK; + } else { + /*not the first item : check if more*/ + if (pam->nCurrAttachedItem + < pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) { + /*more tied items to be regenerated*/ + pam->nCurrAttachedItem++; + return PICO_OK; + } + } + } + /*previous syllable phonemes and items are complete: switch to next syllable*/ + if (pam->nCurrSyllable < pam->nTotalSyllables - 1) { + pam->nCurrSyllable++; + pam->nSyllPhoneme = 0; + pam->nCurrAttachedItem = 0; + return PICO_OK; + } + /*no more phonemes or items to be produced*/ + pam->nCurrSyllable++; + pam->nSyllPhoneme = 0; + return PICO_ERR_OTHER; + +} /*pamUpdateProcess*/ + +/** + * returns true if more items has to be popped for current syllable + * @param this : Pam object pointer + * @return TRUE : item has to be popped + * @return FALSE : item has not to be popped + * @callgraph + * @callergraph + */ +static picoos_uint8 pamHasToPop(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + + /*Preliminary condition : at least 1 syllable*/ + if (pam->nCurrSyllable <= -1) + return FALSE; + + /*Preliminary condition : not maximum number of syllables*/ + if (pam->nCurrSyllable >= pam->nTotalSyllables) + return FALSE; + + /*Preliminary condition : start and end offset in current item > 0 */ + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0) + || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0)) + return FALSE; + + /*Final condition : current popped item less or eq to maximum*/ + if (pam->nCurrAttachedItem + > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) + return FALSE; + + return TRUE; +} /*pamHasToPop*/ + +/** + * returns the address of an item to be popped from the current syllable queue + * @param this : Pam object pointer + * @return pop_address : item address + * @return NULL : item not poppable + * @callgraph + * @callergraph + */ +static picoos_uint8 *pamPopItem(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint8 nItem; + if (NULL == this || NULL == this->subObj) { + return NULL; + } + pam = (pam_subobj_t *) this->subObj; + + /*Preliminary condition : at least 1 syllable*/ + if (pam->nCurrSyllable <= -1) + return NULL; + + /*Preliminary condition : not maximum number of syllables*/ + if (pam->nCurrSyllable >= pam->nTotalSyllables) + return NULL; + + /*Preliminary condition : start and end offset in current item > 0 */ + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0) + || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0)) + return NULL; + + /*Final condition : current popped item less than maximum*/ + if (pam->nCurrAttachedItem + > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]) + return NULL; + + nItem = pam->nCurrAttachedItem; + /*please note : nItem-1 should match with actions performed in function "pam_queue(..)" */ + return &(pam->sSyllItems[pam->sSyllItemOffs[nItem - 1]]); + +} /*pamPopItem*/ + +/** + * returns the address of an item popped from the syllable 0 queue + * @param this : Pam object pointer + * @return pop_address : item address + * @return NULL : item not poppable + * @remarks the item is popped only if it has been inserted in the queue before the first + * @remarks item assigned to the syllable 0 i.e. + * @remarks AttachedItem<=pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm]-1 + * @callgraph + * @callergraph + */ +static picoos_uint8 *pamPopAttachedSy0(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint8 nItem; + if (NULL == this || NULL == this->subObj) { + return NULL; + } + pam = (pam_subobj_t *) this->subObj; + + /*should be syllable 0*/ + if (pam->nCurrSyllable != 0) + return NULL; + + /*start and end offset in current item > 0 */ + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[ITM] <= 0) + || (pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] <= 0)) + return NULL; + + /*if current popped item is > 0 test end condition*/ + if (pam->nCurrAttachedItem > 0) { + /*Other condition : current popped item less than maximum*/ + if (pam->nCurrAttachedItem + > pam->sSyllFeats[pam->nCurrSyllable].phoneV[itm] - 1) + return NULL; + } + nItem = pam->nCurrAttachedItem; + return &(pam->sSyllItems[pam->sSyllItemOffs[nItem]]); + +} /*pamPopAttachedSy0*/ + +/** + * pdf access for duration + * @param this : Pam object pointer + * @param durIndex : index of duration in the pdf + * @param phonDur : pointer to base of array where to store the duration values + * @param numFramesState : pointer to base of array where to store the number of frames per state + * @return PICO_OK : pdf retrieved + * @return PICO_ERR_OTHER : pdf not retrieved + * @remarks Modifies phonDur (the requested duration value) + * @remarks Modifies numFramesState (the requested number of frames per state (vector)) + * @callgraph + * @callergraph + */ +static pico_status_t pam_get_duration(register picodata_ProcessingUnit this, + picoos_uint16 durIndex, picoos_uint16 *phonDur, + picoos_uint8 *numFramesState) +{ + pam_subobj_t *pam; + picokpdf_PdfDUR pdf; + picoos_uint8 *durItem; + picoos_uint16 nFrameSize, nI; + picoos_single fValue; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pdf = pam->pdfdur; + /*make the index 0 based*/ + if (durIndex > 0) + durIndex--; + + /* check */ + if (durIndex > pdf->numframes - 1) { + PICODBG_ERROR(("PAM durPdf access error, index overflow -> index: %d , numframes: %d", durIndex, pdf->numframes)); + return PICO_ERR_OTHER; + } + /* base pointer */ + durItem = &(pdf->content[durIndex * pdf->vecsize]); + if (durItem == NULL) { + PICODBG_ERROR(("PAM durPdf access error , frame pointer = NULL")); + return PICO_ERR_OTHER; + } + nFrameSize = pdf->sampperframe / 16; + *phonDur = ((pdf->phonquant[((*durItem) & 0xF0) >> 4]) * nFrameSize); + numFramesState[0] = pdf->statequant[((*durItem) & 0x0F)]; + durItem++; + numFramesState[1] = pdf->statequant[((*durItem) & 0xF0) >> 4]; + numFramesState[2] = pdf->statequant[((*durItem) & 0x0F)]; + durItem++; + numFramesState[3] = pdf->statequant[((*durItem) & 0xF0) >> 4]; + numFramesState[4] = pdf->statequant[((*durItem) & 0x0F)]; + + /*modification of the duration information based on the duration modifier*/ + *phonDur = (picoos_uint16) (((picoos_single) * phonDur) * pam->dMod); + for (nI = 0; nI < 5; nI++) { + fValue = pam->dRest + (picoos_single) numFramesState[nI] * pam->dMod; + numFramesState[nI] = (picoos_uint8) (fValue); + pam->dRest = fValue - (picoos_single) numFramesState[nI]; + } + return PICO_OK; +}/*pam_get_duration*/ + +/** + * pdf access for pitch + * @param this : Pam object pointer + * @param lf0Index : pointer to variable to receive index of pitch in the pdf + * @param nI : number of the phone's state + * @param phonF0 : pointer to variable to receive the pitch value + * @return PICO_OK : pdf retrieved + * @return PICO_ERR_OTHER : pdf not retrieved + * @remarks Modifies phonDur (the requested duration value) + * @remarks Modifies phonF0 (the requested pitch value (scalar)) + * @callgraph + * @callergraph + */ +static pico_status_t pam_get_f0(register picodata_ProcessingUnit this, + picoos_uint16 *lf0Index, picoos_uint8 nI, picoos_single *phonF0) +{ + pam_subobj_t *pam; + picoos_uint8 *lfItem, numstreams; + picoos_uint16 lf0IndexOffset, sTemp; + picoos_single lfum, lfivar, lfz; + + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + lf0IndexOffset = lf0Index[nI]; + + /*make the index 0 based*/ + if (lf0IndexOffset > 0) + lf0IndexOffset--; + + lf0IndexOffset += pam->pdflfz->stateoffset[nI]; + if (lf0IndexOffset > pam->pdflfz->numframes - 1) { + PICODBG_ERROR(("PAM flfzPdf access error, index overflow -> index: %d , numframes: %d", lf0Index, pam->pdflfz->numframes)); + return PICO_ERR_OTHER; + } + /* base pointer */ + lf0IndexOffset *= pam->pdflfz->vecsize; + + lfItem = &(pam->pdflfz->content[lf0IndexOffset]); + sTemp = (picoos_uint16) (((lfItem[1] << 8)) | lfItem[0]); + + lfum = (picoos_single) (sTemp << (pam->pdflfz->meanpowUm[0])); + numstreams = 3; + lfivar = (picoos_single) (((picoos_uint16) lfItem[numstreams * 2]) + << pam->pdflfz->ivarpow[0]); + lfz = (picoos_single) lfum / (picoos_single) lfivar; + lfz = (picoos_single) exp((double) lfz); + phonF0[nI] = (picoos_single) lfz; + + /*pitch modoification*/ + phonF0[nI] *= pam->pMod; + return PICO_OK; +}/*pam_get_f0*/ + +/** + * elementary rounding function + * @param fIn : (real) input value + * @return the rounded value + * @callgraph + * @callergraph + */ +static picoos_single f_round(picoos_single fIn) +{ + picoos_int32 iVal; + picoos_single fVal; + + iVal = (picoos_int32) fIn; + fVal = (picoos_single) iVal; + + if (fIn > (picoos_single) 0.0f) { + if ((fIn - fVal) < (picoos_single) 0.5f) + return fVal; + else + return fVal + (picoos_single) 1.0f; + } else { + if ((fVal - fIn) < (picoos_single) 0.5f) + return fVal; + else + return fVal - (picoos_single) 1.0f; + } +}/*f_round*/ + +/** + * updates the input vector for PAM + * @param this : Pam object pointer + * @return PICO_OK : update successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks Modifies pam->sPhFeats[] + * @callgraph + * @callergraph + */ +static pico_status_t pam_update_vector(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + picoos_uint8 numstates, nI; + picoos_single fDur, f0avg, f0quant, minf0, maxf0, durquant1, durquant2, + mindur, maxdur1, maxdur2; + + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + /*default init*/ + pam->sPhFeats[DUR] = 0; + pam->sPhFeats[F0] = 0; + /* + Hard coded parameters for quantization + */ + numstates = PICOPAM_NRSTPF; + f0quant = 30.0f; + minf0 = 90.0f; + maxf0 = 360.0f; + + durquant1 = 20.0f; + durquant2 = 100.0f; + mindur = 40.0f; + maxdur1 = 160.0f; + maxdur2 = 600.0f; + f0avg = 0.0f; + for (nI = 0; nI < numstates; nI++) + f0avg += pam->phonF0[nI]; + f0avg /= (picoos_single) numstates; + + f0avg = f_round(f0avg / f0quant) * f0quant; + if (f0avg < minf0) + f0avg = minf0; + if (f0avg > maxf0) + f0avg = maxf0; + + /*make initial silence of sentence shorter (see also pam_put_item)*/ + if ((pam->nCurrSyllable == 0) && (pam->nSyllPhoneme == 0)) { + pam->phonDur = 2 * 4; + } + + fDur = (picoos_single) pam->phonDur; + fDur = f_round(fDur / durquant1) * durquant1; + if (fDur < mindur) + fDur = mindur; + if (fDur > maxdur1) { + fDur = f_round(fDur / durquant2) * durquant2; + if (fDur > maxdur2) + fDur = maxdur2; + } + pam->sPhFeats[DUR] = (picoos_uint8) (fDur / (picoos_single) 10.0f); + pam->sPhFeats[F0] = (picoos_uint8) (f0avg / (picoos_single) 10.0f); + + return PICO_OK; +}/*pam_update_vector*/ + +/** + * compress a single feature in the range 0..9 + * @param inVal : the value to be compressed + * @return compVal : the compressed value + * @callgraph + * @callergraph + */ +static picoos_uint8 pamCompressComponent(picoos_uint8 inVal) +{ + if (inVal <= 5) + return inVal; + if ((5 < inVal) && (inVal <= 10)) + return 6; + if ((10 < inVal) && (inVal <= 20)) + return 7; + if ((20 < inVal) && (inVal <= 30)) + return 8; + return 9; +}/*pamCompressComponent*/ + +/** + * prepares the input vector for tree feeding + * @param this : Pam object pointer + * @return PICO_OK : vector expanded + * @return PICO_ERR_OTHER : errors on expansion or retrieving the PU pointer + * @remarks Modifies pam->sPhFeats[] + * @callgraph + * @callergraph + */ +static pico_status_t pam_expand_vector(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + picoos_uint8 *inVect, *phonVect, *outVect, nI; + picoos_int16 nOffs, nOffs1, nLen; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + inVect = &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[0]); + phonVect = &(pam->sPhIds[0]); + outVect = &(pam->sPhFeats[0]); + /*just copy back*/ + for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) + outVect[nI] = inVect[nI]; + /*now fill missing fields*/ + picoos_mem_copy((void*) &(inVect[FID]), &nOffs, sizeof(nOffs)); + /*offset to first phone of current syllable*/ + nOffs = nOffs + pam->nSyllPhoneme; /*offset to current phone of current syllable*/ + nLen = inVect[B3]; /*len of current syllable*/ + if (pam->nSyllPhoneme >= nLen) { + /*error on addressing current phone*/ + return PICO_ERR_OTHER; + } + /*previous of the previous phone*/ + nOffs1 = nOffs - 2; + if (nOffs1 >= 0) + outVect[P1] = phonVect[nOffs1]; + else + outVect[P1] = PICOPAM_PH_DONT_CARE_VAL; + /*previous phone*/ + nOffs1 = nOffs - 1; + if (nOffs1 >= 0) + outVect[P2] = phonVect[nOffs1]; + else + outVect[P2] = PICOPAM_PH_DONT_CARE_VAL; + /*^current phone*/ + outVect[P3] = phonVect[nOffs]; + + /*next phone*/ + nOffs1 = nOffs + 1; + if (nOffs1 < pam->nTotalPhonemes) + outVect[P4] = phonVect[nOffs1]; + else + outVect[P4] = PICOPAM_PH_DONT_CARE_VAL; + /*next of the next phone*/ + nOffs1 = nOffs + 2; + if (nOffs1 < pam->nTotalPhonemes) + outVect[P5] = phonVect[nOffs1]; + else + outVect[P5] = PICOPAM_PH_DONT_CARE_VAL; + /*pos of curr phone with respect to left syllable boundary*/ + outVect[P6] = pam->nSyllPhoneme + 1; + /*pos of curr phone with respect to right syllable boundary*/ + outVect[P7] = nLen - pam->nSyllPhoneme; + /*is current phone in consonant syllable boundary? (1:yes)*/ + if (pam->nSyllPhoneme < inVect[P8]) + outVect[P8] = 1; + else + outVect[P8] = 0; + return PICO_OK; +}/*pam_expand_vector*/ + +/** + * compresses the input vector for PAM + * @param this : Pam object pointer + * @return PICO_OK : compression successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks Modifies pam->sPhFeats[] + * @callgraph + * @callergraph + */ +static pico_status_t pamCompressVector(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + picoos_uint8 *outVect, nI; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + outVect = &(pam->sPhFeats[0]); + for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) { + switch (nI) { + case P1: + case P2: + case P3: + case P4: + case P5: + case B1: + case B2: + case B16: + case E1: + case H5: + /*don't do any compression*/ + break; + default: + /*do compression*/ + if (outVect[nI] != PICOPAM_DONT_CARE_VALUE) + outVect[nI] = pamCompressComponent(outVect[nI]); + else + outVect[nI] = PICOPAM_DONT_CARE_VAL; + break; + } + } + return PICO_OK; +}/*pamCompressVector*/ + +/** + * reorganizes the input vector for PAM + * @param this : Pam object pointer + * @return PICO_OK : reorganization successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks Modifies pam->sPhFeats[] + * @callgraph + * @callergraph + */ +static pico_status_t pamReorgVector(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + picoos_uint8 *outVect, inVect[60], nI; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + outVect = &(pam->sPhFeats[0]); + for (nI = 0; nI < PICOPAM_INVEC_SIZE; nI++) inVect[nI] = outVect[nI]; + /*reorganize*/ + for (nI = T_B1; nI <= T_H5; nI++) { + switch (nI) { + case T_B1: + outVect[T_B1] = inVect[B1]; + break; + case T_B2: + outVect[T_B2] = inVect[B2]; + break; + case T_B3: + outVect[T_B3] = inVect[B3]; + break; + case T_B4: + outVect[T_B4] = inVect[B4]; + break; + case T_B5: + outVect[T_B5] = inVect[B5]; + break; + case T_B6: + outVect[T_B6] = inVect[B6]; + break; + case T_B7: + outVect[T_B7] = inVect[B7]; + break; + case T_B8: + outVect[T_B8] = inVect[B8]; + break; + case T_B9: + outVect[T_B9] = inVect[B9]; + break; + case T_B10: + outVect[T_B10] = inVect[B10]; + break; + case T_B11: + outVect[T_B11] = inVect[B11]; + break; + case T_B12: + outVect[T_B12] = inVect[B12]; + break; + case T_B13: + outVect[T_B13] = inVect[B13]; + break; + case T_B14: + outVect[T_B14] = inVect[B14]; + break; + case T_B15: + outVect[T_B15] = inVect[B15]; + break; + case T_B16: + outVect[T_B16] = inVect[B16]; + break; + case T_B17: + outVect[T_B17] = inVect[B17]; + break; + case T_B18: + outVect[T_B18] = inVect[B18]; + break; + case T_B19: + outVect[T_B19] = inVect[B19]; + break; + case T_B20: + outVect[T_B20] = inVect[B20]; + break; + case T_B21: + outVect[T_B21] = inVect[B21]; + break; + + case T_E1: + outVect[T_E1] = inVect[E1]; + break; + case T_E2: + outVect[T_E2] = inVect[E2]; + break; + case T_E3: + outVect[T_E3] = inVect[E3]; + break; + case T_E4: + outVect[T_E4] = inVect[E4]; + break; + case T_E5: + outVect[T_E5] = inVect[E5]; + break; + case T_E6: + outVect[T_E6] = inVect[E6]; + break; + case T_E7: + outVect[T_E7] = inVect[E7]; + break; + case T_E8: + outVect[T_E8] = inVect[E8]; + break; + case T_E9: + outVect[T_E9] = inVect[E9]; + break; + case T_E10: + outVect[T_E10] = inVect[E10]; + break; + case T_E11: + outVect[T_E11] = inVect[E11]; + break; + case T_E12: + outVect[T_E12] = inVect[E12]; + break; + case T_E13: + outVect[T_E13] = inVect[E13]; + break; + + case T_A3: + outVect[T_A3] = inVect[A3]; + break; + case T_C3: + outVect[T_C3] = inVect[C3]; + break; + case T_D2: + outVect[T_D2] = inVect[D2]; + break; + case T_F2: + outVect[T_F2] = inVect[F2]; + break; + + case T_G1: + outVect[T_G1] = inVect[G1]; + break; + case T_I1: + outVect[T_I1] = inVect[I1]; + break; + + case T_G2: + outVect[T_G2] = inVect[G2]; + break; + case T_I2: + outVect[T_I2] = inVect[I2]; + break; + + case T_H1: + outVect[T_H1] = inVect[H1]; + break; + case T_H2: + outVect[T_H2] = inVect[H2]; + break; + case T_H3: + outVect[T_H3] = inVect[H3]; + break; + case T_H4: + outVect[T_H4] = inVect[H4]; + break; + case T_H5: + outVect[T_H5] = inVect[H5]; + break; + } + } + return PICO_OK; +}/*pamReorgVector*/ + +/** + * puts a PAM item into PU output buffer + * @param this : Pam object pointer + * @param outBuff : output buffer base pointer + * @param outWritePos : offset in output buffer + * @param *bytesWr : actual bytes written + * @return PICO_OK : put successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_put_item(register picodata_ProcessingUnit this, + picoos_uint8 *outBuff, picoos_uint16 outWritePos, picoos_uint8 *bytesWr) +{ + pam_subobj_t *pam; + picoos_uint8 *sDest, nI, nType, nIdx, fde; + picoos_uint32 pos, pos32; + picoos_int16 ft, dt; + picoos_uint16 uMinDur, uMaxDur; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + sDest = &(outBuff[outWritePos]); + sDest[0] = PICODATA_ITEM_PHONE; /*Item type*/ + sDest[1] = pam->sPhFeats[P3]; /*phonetic id*/ + sDest[2] = PICOPAM_NRSTPF; /*number of states per phone*/ + sDest[3] = sizeof(picoos_uint16) * PICOPAM_NRSTPF * 3; /*size of the item*/ + pos = 4; + /*make initial silence of sentence shorter (see also UpdateVector)*/ + if ((pam->nCurrSyllable == 0) && (pam->nSyllPhoneme == 0)) { + for (nI = 0; nI < PICOPAM_NRSTPF - 1; nI++) + pam->numFramesState[nI] = 0; + pam->numFramesState[nI] = 2; + } else { + /*manage silence syllables with prescribed durations*/ + pos32 = Min; + picoos_read_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, + &pos32, &uMinDur); + pos32 = Max; + picoos_read_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, + &pos32, &uMaxDur); + + if (uMaxDur > 0) { + /* Select weights*/ + nType = pam->sSyllFeats[pam->nCurrSyllable].phoneV[bnd]; + switch (nType) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + nIdx = PICOPAM_PWIDX_SBEG; + break; + case PICODATA_ITEMINFO1_BOUND_PHR1: + nIdx = PICOPAM_PWIDX_PHR1; + break; + case PICODATA_ITEMINFO1_BOUND_PHR2: + nIdx = PICOPAM_PWIDX_PHR2; + break; + case PICODATA_ITEMINFO1_BOUND_SEND: + case PICODATA_ITEMINFO1_BOUND_TERM: + nIdx = PICOPAM_PWIDX_SEND; + break; + default: + nIdx = PICOPAM_PWIDX_DEFA; + break; + } + fde = 2; + ft = 0; + dt = 0; + picodata_transformDurations( + fde, /* 2's exponent of frame duration in ms, e.g. 2 for 4ms, 3 for 8ms */ + PICOPAM_NRSTPF, /* number of states per phone */ + &(pam->numFramesState[0]), /* estimated durations */ + pam->sil_weights[nIdx], /* integer weights */ + uMinDur, /* minimum target duration in ms */ + uMaxDur, /* maximum target duration in ms */ + ft, /* factor to be multiplied to get the target */ + &dt /* in/out, rest in ms */ + ); + } + } + /*put data*/ + for (nI = 0; nI < PICOPAM_NRSTPF; nI++) { + picoos_write_mem_pi_uint16(sDest, &pos, + (picoos_uint16) pam->numFramesState[nI]); + picoos_write_mem_pi_uint16(sDest, &pos, + (picoos_uint16) pam->lf0Index[nI]); + picoos_write_mem_pi_uint16(sDest, &pos, + (picoos_uint16) pam->mgcIndex[nI]); + } + *bytesWr = sizeof(picodata_itemhead_t) + sizeof(picoos_uint16) + * PICOPAM_NRSTPF * 3; + return PICO_OK; +}/*pam_put_item*/ + +/** + * puts a non PAM (queued) item into PU output buffer + * @param qItem : pointer to item to put + * @param outBuff : output buffer base pointer + * @param outWritePos : offset in output buffer + * @param *bytesWr : actual bytes written + * @return PICO_OK : put successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_put_qItem(picoos_uint8 *qItem, picoos_uint8 *outBuff, + picoos_uint16 outWritePos, picoos_uint8 *bytesWr) +{ + picoos_uint8 *sDest, nI; + sDest = &(outBuff[outWritePos]); + *bytesWr = sizeof(picodata_itemhead_t); + for (nI = 0; nI < (sizeof(picodata_itemhead_t) + qItem[3]); nI++) { + sDest[nI] = qItem[nI]; + } + *bytesWr = nI; + return PICO_OK; +}/*pam_put_qItem*/ + +/** + * tells if an item is a PAM command (except play) + * @param qItem : input item to test + * @return TRUE : qItem is a PAM command (except play) + * @return FALSE : qItem not a PAM command + * @callgraph + * @callergraph + */ +static pico_status_t is_pam_command(const picoos_uint8 * qItem) +{ + switch (qItem[0]) { + + case PICODATA_ITEM_CMD: + switch (qItem[1]) { + case PICODATA_ITEMINFO1_CMD_FLUSH: + /* flush is for all PU's and as such it is also for PAM*/ + case PICODATA_ITEMINFO1_CMD_PITCH: + case PICODATA_ITEMINFO1_CMD_SPEED: + return TRUE; + break; + default: + break; + } + } + return FALSE; +}/*is_pam_command*/ + +/** + * tells if an item is a PAM PLAY command + * @param qItem : input item to test + * @return TRUE : qItem is a PAM PLAY command + * @return FALSE : qItem not a PAM PLAY command + * @callgraph + * @callergraph + */ +static pico_status_t is_pam_play_command(picoos_uint8 *qItem) +{ + switch (qItem[0]) { + + case PICODATA_ITEM_CMD: + switch (qItem[1]) { + case PICODATA_ITEMINFO1_CMD_PLAY: + if (qItem[2] == PICODATA_ITEMINFO2_CMD_TO_PAM) + return TRUE; + break; + default: + break; + } + } + return FALSE; +}/*is_pam_play_command*/ + +/** + * command processor for PAM pu + * @param this : Pam item subobject + * @param qItem : input item pointer + * @return PICOPAM_FLUSH_RECEIVED : when a FLUSH is received + * @return PICOPAM_CONTINUE : normal command processing + * @return PICODATA_PU_ERROR : errors in accessing data + * @callgraph + * @callergraph + */ +static pico_status_t pamDoCommand(register picodata_ProcessingUnit this, + picoos_uint8 *qItem) +{ + pam_subobj_t *pam; + picoos_single fValue; + picoos_uint16 nValue; + picoos_uint32 nPos; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + if (qItem[0] == PICODATA_ITEM_CMD) { + switch (qItem[1]) { + case PICODATA_ITEMINFO1_CMD_FLUSH: + /* flush is for all PU's and as such it is also for PAM : implement the flush!!*/ + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0; + pam->nAttachedItemsSize = 0; + return PICOPAM_FLUSH_RECEIVED; + break; + + case PICODATA_ITEMINFO1_CMD_PITCH: + case PICODATA_ITEMINFO1_CMD_SPEED: + nPos = 4; + picoos_read_mem_pi_uint16(qItem, &nPos, &nValue); + if (qItem[2] == 'a') { + /*absloute modifier*/ + fValue = (picoos_single) nValue / (picoos_single) 100.0f; + if (qItem[1] == PICODATA_ITEMINFO1_CMD_PITCH) + pam->pMod = fValue; + if (qItem[1] == PICODATA_ITEMINFO1_CMD_SPEED) + pam->dMod = (1.0f / fValue); + } + if (qItem[2] == 'r') { + /*relative modifier*/ + fValue = (picoos_single) nValue / (picoos_single) 1000.0f; + if (qItem[1] == PICODATA_ITEMINFO1_CMD_PITCH) + pam->pMod *= (1.0f / fValue); + if (qItem[1] == PICODATA_ITEMINFO1_CMD_SPEED) + pam->dMod *= (1.0f / fValue); + } + return PICOPAM_CONTINUE; + break; + + default: + break; + }/*end switch switch (qItem[1])*/ + }/*end if (qItem[0]==PICODATA_ITEM_CMD)*/ + return PICOPAM_CONTINUE; +}/*pamDoCommand*/ + +/** + * defines if an item has to be sent to following PUs + * @param qItem : input item pointer + * @return TRUE : item has to be transmitted to following PUs + * @return FALSE : item has to be consumed internallz on PAM + * @callgraph + * @callergraph + */ +static pico_status_t isItemToPut(picoos_uint8 *qItem) +{ + switch (qItem[0]) { + case PICODATA_ITEM_CMD: + /* is a command*/ + if (PICODATA_ITEMINFO1_CMD_SPEED == qItem[1]) { + /* SPEED consumed here*/ + return FALSE; + } + break; + case PICODATA_ITEM_BOUND: + switch (qItem[1]) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + case PICODATA_ITEMINFO1_BOUND_PHR0: + case PICODATA_ITEMINFO1_BOUND_PHR1: + case PICODATA_ITEMINFO1_BOUND_PHR2: + case PICODATA_ITEMINFO1_BOUND_PHR3: + /*boudary items consumed here except SEND,TERM*/ + return FALSE; + break; + default: + break; + } + break; + default: + break; + } + /*all other items not explicitly mentioned here + are transmitted to next PUs*/ + return TRUE; +}/*isItemToPut*/ + +/** + * pushes a boundary TERM item into some buffer + * @param outBuff : output buffer base pointer + * @param outWritePos : offset in output buffer + * @param *bytesWr : actual bytes written + * @return PICO_OK + * @remarks used while forcing TERM input items in forward processing + * @callgraph + * @callergraph + */ +static pico_status_t pam_put_term(picoos_uint8 *outBuff, + picoos_uint16 outWritePos, picoos_uint8 *bytesWr) +{ + picoos_uint8 *sDest; + sDest = &(outBuff[outWritePos]); + sDest[0] = PICODATA_ITEM_BOUND; /*Item type*/ + sDest[1] = PICODATA_ITEMINFO1_BOUND_TERM; + sDest[2] = PICODATA_ITEMINFO2_BOUNDTYPE_T; + sDest[3] = 0; /*item size*/ + *bytesWr = 4; + return PICO_OK; +}/*pam_put_term*/ + +/** + * translates one full phone into a PHONE Item including DT Dur, F0 and CEP trees feature generation and traversal + * @param this : Pam item subobject pointer + * @return PICO_OK : processing successful + * @return PICODATA_PU_ERROR : error accessing PAM object + * @return !=PICO_OK : processing errors + * @callgraph + * @callergraph + */ +static pico_status_t pamPhoneProcess(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + pico_status_t sResult; + picokdt_classify_result_t dTreeResult; + picoos_uint8 nI, bWr; + + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + /*expands current phone in current syllable in the corresponding vector pam->sPhFeats[]*/ + sResult = pam_expand_vector(this); + sResult = pamCompressVector(this); + sResult = pamReorgVector(this); + + /*tree traversal for duration*/ + if (!pam_do_tree(this, pam->dtdur, &(pam->sPhFeats[0]), PICOPAM_INVEC_SIZE, + &dTreeResult)) { + PICODBG_WARN(("problem using pam tree dtdur, using fallback value")); + dTreeResult.class = 0; + } + pam->durIndex = dTreeResult.class; + sResult = pam_get_duration(this, pam->durIndex, &(pam->phonDur), + &(pam->numFramesState[0])); + + /*tree traversal for pitch*/ + for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) { + if (!pam_do_tree(this, pam->dtlfz[nI], &(pam->sPhFeats[0]), + PICOPAM_INVEC_SIZE, &dTreeResult)) { + PICODBG_WARN(("problem using pam tree lf0Tree, using fallback value")); + dTreeResult.class = 0; + } + pam->lf0Index[nI] = dTreeResult.class; + } + + /*pdf access for pitch*/ + for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) { + sResult = pam_get_f0(this, &(pam->lf0Index[0]), nI, &(pam->phonF0[0])); + } + + /*update vector with duration and pitch for cep tree traversal*/ + sResult = pam_update_vector(this); + /*cep tree traversal*/ + for (nI = 0; nI < PICOPAM_MAX_STATES_PER_PHONE; nI++) { + + if (!pam_do_tree(this, pam->dtmgc[nI], &(pam->sPhFeats[0]), + PICOPAM_INVEC_SIZE, &dTreeResult)) { + PICODBG_WARN(("problem using pam tree lf0Tree, using fallback value")); + dTreeResult.class = 0; + } + pam->mgcIndex[nI] = dTreeResult.class; + } + /*put item to output buffer*/ + sResult = pam_put_item(this, pam->outBuf, pam->outWritePos, &bWr); + if (sResult == PICO_OK) + pam->outWritePos += bWr; + else + return sResult; + return PICO_OK; +}/*pamPhoneProcess*/ + +/** + * manages first syllable attached items when seen before SBEG + * @param this : Pam item subobject pointer + * @return PICO_OK (0) : default return code --> means no more items to be processed before 1st syllable + * @return PICOPAM_GOTO_FEED : go to feed state after this + * @return PICOPAM_GOTO_SCHEDULE : flush received + * @return PICODATA_PU_ERROR : errors + * @callgraph + * @callergraph + */ +static pico_status_t pamDoPreSyll(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + pico_status_t sResult; + picoos_uint8 bWr, nRc; + picoos_uint8 *qItem; + nRc = PICOPAM_PRE_SYLL_ENDED; + pam = (pam_subobj_t *) this->subObj; + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + /*regenerate initial items before the phonemes*/ + if (((qItem = pamPopAttachedSy0(this)) != NULL) && !((qItem[0] + == PICODATA_ITEM_BOUND) && (qItem[1] + == PICODATA_ITEMINFO1_BOUND_SBEG))) { + if (isItemToPut(qItem)) { + pam_put_qItem(qItem, pam->outBuf, pam->outWritePos, &bWr);/*popped item has to be sent to next PU*/ + pam->outWritePos += bWr; + nRc = PICOPAM_GOTO_FEED; + } + + if (is_pam_command(qItem) == TRUE) { + nRc = pamDoCommand(this, qItem); /*popped item is a PAM command : do it NOW!!*/ + if ((nRc == PICOPAM_FLUSH_RECEIVED) || (nRc == PICODATA_PU_ERROR)) { + /*FLUSH command RECEIVED or errors: stop ALL PROCESSING*/ + return nRc; + } + } + pam->nCurrAttachedItem++; + if (nRc == 0) + return PICOPAM_CONTINUE; + else + return nRc; + } + /*SBEG item management*/ + if ((qItem != NULL) && (qItem[0] == PICODATA_ITEM_BOUND) && (qItem[1] + == PICODATA_ITEMINFO1_BOUND_SBEG)) { + sResult = pam_put_qItem(qItem, pam->outBuf, pam->outWritePos, &bWr); + pam->outWritePos += bWr; + pam->nCurrAttachedItem++; + nRc = PICOPAM_GOTO_FEED; + } + return nRc; +}/*pamDoPreSyll*/ + +/** + * performs a step of the pam processing + * @param this : Pam item subobject pointer + * @param mode : mode for the PU + * @param *numBytesOutput : pointer to output number fo bytes produced + * @return PICODATA_PU_IDLE : nothing to do + * @return PICODATA_PU_BUSY : still tasks undergoing + * @return PICODATA_PU_ERROR : errors on processing + * @callgraph + * @callergraph + */ +static picodata_step_result_t pam_step(register picodata_ProcessingUnit this, + picoos_int16 mode, picoos_uint16 * numBytesOutput) +{ + + register pam_subobj_t * pam; + + pico_status_t sResult; + picoos_uint16 blen, numinb, numoutb; + pico_status_t rv; + picoos_uint8 bWr; + picoos_uint8 bForcedItem[4]; + picoos_uint8 *qItem; + + numinb = 0; + numoutb = 0; + rv = PICO_OK; + + if (NULL == this || NULL == this->subObj) { + return PICODATA_PU_ERROR; + } + pam = (pam_subobj_t *) this->subObj; + mode = mode; /* avoid warning "var not used in this function"*/ + /*Init number of output bytes*/ + *numBytesOutput = 0; + + while (1) { /* exit via return */ + + PICODBG_DEBUG(("pam_step -- doing state %i",pam->procState)); + + switch (pam->procState) { + + case PICOPAM_COLLECT: + /* *************** item collector ***********************************/ + /*collecting items from the PU input buffer*/ + sResult = picodata_cbGetItem(this->cbIn, + &(pam->inBuf[pam->inWritePos]), pam->inBufSize + - pam->inWritePos, &blen); + if (sResult != PICO_OK) { + if (sResult == PICO_EOF) { + /*no items available : remain in state 0 and return idle*/ + return PICODATA_PU_IDLE; + } else { + /*errors : remain in state 0 and return error*/ + PICODBG_DEBUG(("pam_step(PICOPAM_COLLECT) -- Errors on item buffer input, status: %d",sResult)); + return PICODATA_PU_ERROR; + } + } + + PICODBG_DEBUG(("pam_step -- got item, status: %d",sResult)); + sResult = picodata_is_valid_item( + &(pam->inBuf[pam->inWritePos]), blen); + if (sResult != TRUE) { + /*input item is not valid : consume the input item and stay in COLLECT*/ + pam->inWritePos += blen; + pam->inReadPos += blen; + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + }PICODBG_DEBUG(("pam_step -- item is not valid, type: %d",pam->inBuf[pam->inWritePos])); + return PICODATA_PU_BUSY; + } + + /*update input write pointer + move to "schedule" state*/ + pam->inWritePos += blen; + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + + case PICOPAM_SCHEDULE: + /* check out if more items are available */ + if (pam->inReadPos >= pam->inWritePos) { + /*no more items : back to collect state*/ + pam->procState = PICOPAM_COLLECT; + return PICODATA_PU_BUSY; + } + /* we have one full valid item, with len>0 starting at + pam->inBuf[pam->inReadPos]; here we decide how to elaborate it */ + + /* PLAY management */ + if (is_pam_play_command(&(pam->inBuf[pam->inReadPos])) == TRUE) { + /*consume the input item : it has been managed*/ + pam->inReadPos += pam->inBuf[pam->inReadPos + 3] + + sizeof(picodata_itemhead_t); + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + } + /*stay in schedule*/ + return PICODATA_PU_BUSY; + } + + if (pam_check_immediate(this, &(pam->inBuf[pam->inReadPos]))) { + /* item has to be sent to next PU NOW : switch to "immediate" state */ + pam->procState = PICOPAM_IMMEDIATE; + return PICODATA_PU_BUSY; + } + if (pamCheckResourceLimits(this, &(pam->inBuf[pam->inReadPos]))) { + /* item would not fit into local buffers -->> free some space -->> + switch to "force term" state */ + pam->procState = PICOPAM_FORWARD_FORCE_TERM; + return PICODATA_PU_BUSY; + } + + if (pam_deal_with(&(pam->inBuf[pam->inReadPos]))) { + /* item has to be managed by the "forward" state : switch to forward state*/ + pam->procState = PICOPAM_FORWARD; + return PICODATA_PU_BUSY; + } + + if (pam_hastobe_queued(this, &(pam->inBuf[pam->inReadPos]))) { + /* item is not for PAM so it has to be queued internally */ + pam_queue(this, &(pam->inBuf[pam->inReadPos])); + /*consume the input item : it has been queued*/ + pam->inReadPos += pam->inBuf[pam->inReadPos + 3] + + sizeof(picodata_itemhead_t); + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + } + return PICODATA_PU_BUSY; + } + /*if we get here something wrong happened. Being the the item valid, + switch to "immediate" state -> send it to next PU -> */ + PICODBG_DEBUG(("pam_step (PICOPAM_SCHEDULE) -- unexpected item is sent to next PU !!")); + pam->procState = PICOPAM_IMMEDIATE; + return PICODATA_PU_BUSY; + break; /*PICOPAM_SCHEDULE*/ + + case PICOPAM_FORWARD: + /*we have one full valid item, with len>0 starting at pam->inBuf[pam->inReadPos]. + furthermore this item should be in the set {BOUND,SYLL}. + No other items should arrive here*/ + sResult = pam_adapter_forward_step(this, + &(pam->inBuf[pam->inReadPos])); + /*decide if this item has to be queued for later re-synchronization + normally this is only done for SEND/TERM items*/ + if (pam_hastobe_queued(this, &(pam->inBuf[pam->inReadPos]))) { + /*item has to be queued iternally in local storage*/ + pam_queue(this, &(pam->inBuf[pam->inReadPos])); + } + /*now assign next state according to Forward results*/ + switch (sResult) { + case PICOPAM_READY: + pam->needMoreInput = FALSE; + /*consume the input item : it has already been stored*/ + pam->inReadPos += pam->inBuf[pam->inReadPos + 3] + + sizeof(picodata_itemhead_t); + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + } + /*activate backward processing*/ + sResult = pam_adapter_backward_step(this); + if (sResult == PICO_OK) { + pam->procState = PICOPAM_PROCESS; + return PICODATA_PU_BUSY; + } else { + PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD) -- wrong return from BackwardStep: %d -- Buffered sentence will be discarded",sResult)); + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem + = 0; + pam->nAttachedItemsSize = 0; + + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + } + break; + + case PICOPAM_MORE: + pam->needMoreInput = TRUE; + /*consume the input item : it has already been stored*/ + pam->inReadPos += pam->inBuf[pam->inReadPos + 3] + + sizeof(picodata_itemhead_t); + if (pam->inReadPos >= pam->inWritePos) { + /*input is finished and PAM need more data : + clenaup input buffer + switch state back to "schedule state" + */ + pam->inReadPos = 0; + pam->inWritePos = 0; + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_ATOMIC; + } else { + /*input is not finished and need more data : + remain in state "PICOPAM_FORWARD" */ + return PICODATA_PU_ATOMIC; + } + break; + + case PICOPAM_NA: + default: + /*this item has not been stored in internal buffers: + assign this item to the management of + "immediate" state*/ + pam->procState = PICOPAM_IMMEDIATE; + return PICODATA_PU_BUSY; + break; + } /*end switch sResult*/ + break; /*PICOPAM_FORWARD*/ + + case PICOPAM_FORWARD_FORCE_TERM: + /*we have one full valid item, with len>0 + starting at pam->inBuf[pam->inReadPos] but we decided + to force a TERM item before, without losing the item in + inBuf[inReadPos] : --> generate a TERM item and do the + forward processing */ + pam_put_term(bForcedItem, 0, &bWr); + sResult = pam_adapter_forward_step(this, &(bForcedItem[0])); + switch (sResult) { + case PICOPAM_READY: + pam_queue(this, &(bForcedItem[0])); + /*activate backward processing*/ + sResult = pam_adapter_backward_step(this); + if (sResult == PICO_OK) { + pam->procState = PICOPAM_PROCESS; + return PICODATA_PU_BUSY; + } else { + PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD_FORCE_TERM) -- wrong return from BackwardStep: %d -- Buffered sentence will be discarded",sResult)); + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem + = 0; + pam->nAttachedItemsSize = 0; + + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + } + break; + + default: + PICODBG_DEBUG(("pam_step (PICOPAM_FORWARD_FORCE_TERM) -- Forced a TERM but processing do not appear to end -- Buffered sentence will be discarded",sResult)); + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem = 0; + pam->nAttachedItemsSize = 0; + + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + break; + + } /*end switch sResult*/ + break; /*PICOPAM_FORWARD_FORCE_TERM*/ + + case PICOPAM_PROCESS: + + if ((PICOPAM_FRAME_ITEM_SIZE + 4) > (pam->outBufSize + - pam->outWritePos)) { + /*WARNING (buffer overflow): leave status unchanged until output buffer free */ + return PICODATA_PU_BUSY; + } + + if (pam->nCurrSyllable == 0) { + sResult = pamDoPreSyll(this); + if (sResult == PICOPAM_GOTO_FEED) { + /* + items pushed to output buffer : + switch to "feed" but then back + to "process" + */ + pam->retState = PICOPAM_PROCESS; + pam->procState = PICOPAM_FEED; + return PICODATA_PU_BUSY; + } + if (sResult == PICOPAM_CONTINUE) { + /* + items processed (maybe commands) : + return (maybe we need to process other + items in pre_syll) and then back to "process" + */ + pam->retState = PICOPAM_PROCESS; + pam->procState = PICOPAM_PROCESS; + return PICODATA_PU_BUSY; + } + + if ((sResult == PICOPAM_FLUSH_RECEIVED) || (sResult + == PICODATA_PU_ERROR)) { + /* + items processed were a flush or + problems found: switch to "schedule" + and abort all processing + */ + pam->retState = PICOPAM_SCHEDULE; + pam->procState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + } + if (sResult == PICOPAM_PRE_SYLL_ENDED) { + /* + we get here when pam->nCurrSyllable==0 and + no more items to be processed before the syllable + */ + sResult = sResult; + } + } + + if (pamHasToProcess(this)) { + if (pamPhoneProcess(this) == PICO_OK) { + sResult = pamUpdateProcess(this); + pam->procState = PICOPAM_FEED; /*switch to feed*/ + return PICODATA_PU_BUSY; + } else { + PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- NULL return from pamPhoneProcess")); + return PICODATA_PU_ERROR; + } + } + + if (pamHasToPop(this) != FALSE) { + if ((qItem = pamPopItem(this)) == NULL) { + PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- NULL return from pamPopItem")); + return PICODATA_PU_ERROR; + } + + if (isItemToPut(qItem)) { + /*popped item has to be sent to next PU*/ + sResult = pam_put_qItem(qItem, pam->outBuf, + pam->outWritePos, &bWr); + if (sResult != PICO_OK) { + PICODBG_DEBUG(("pam_step(PICOPAM_PROCESS) --- Error on writing item to output buffer")); + return PICODATA_PU_ERROR; + } + pam->outWritePos += bWr; /*item write ok*/ + pam->procState = PICOPAM_FEED; /*switch to feed*/ + } + + /*moved command processing here (after pam_put_qItem) because of FLUSH command could erase + * the syllable structure and make it impossible to transmit the flush to other PUs*/ + if (is_pam_command(qItem) == TRUE) { + sResult = pamDoCommand(this, qItem); /*popped item is a PAM command : do it NOW!!*/ + if ((sResult == PICOPAM_FLUSH_RECEIVED) || (sResult + == PICODATA_PU_ERROR)) { + pam->retState = PICOPAM_SCHEDULE; + pam->procState = PICOPAM_SCHEDULE; /*switch to schedule */ + return PICODATA_PU_BUSY; + } + } + /*update PAM status: if more items attached to the current syllable + stay in current syllable, otherwise move to next syllable and switch + to processing phones */ + sResult = pamUpdateProcess(this); /*both "doCommand" or "put" : update PAM status*/ + return PICODATA_PU_BUSY; + } else { + pam->procState = PICOPAM_SCHEDULE; /*switch to schedule */ + return PICODATA_PU_BUSY; + } + + break; /*PICOPAM_PROCESS*/ + + case PICOPAM_IMMEDIATE: + /* *** item is output NOW!!! */ + /*context: full valid item, with len> starting at pam->inBuf[pam->inReadPos]*/ + numinb = PICODATA_ITEM_HEADSIZE + + pam->inBuf[pam->inReadPos + 3]; + sResult = picodata_copy_item(&(pam->inBuf[pam->inReadPos]), + numinb, &(pam->outBuf[pam->outWritePos]), + pam->outBufSize - pam->outWritePos, &numoutb); + + if (sResult == PICO_OK) { + pam->inReadPos += numinb; + if (pam->inReadPos >= pam->inWritePos) { + pam->inReadPos = 0; + pam->inWritePos = 0; + pam->needMoreInput = FALSE; + } + pam->outWritePos += numoutb; + pam->procState = PICOPAM_FEED; /*switch to FEED state*/ + pam->retState = PICOPAM_SCHEDULE; /*back to SCHEDULE after FEED*/ + } else { + /* + PICO_EXC_BUF_IGNORE + PICO_EXC_BUF_UNDERFLOW + PICO_EXC_BUF_OVERFLOW + */ + PICODBG_DEBUG(("pam_step(PICOPAM_IMMEDIATE) --- wrong return from picodata_copy_item:%d",sResult)); + return PICODATA_PU_ERROR; + } + return PICODATA_PU_BUSY; + break; /*PICOPAM_IMMEDIATE*/ + + case PICOPAM_FEED: + /* *************** item output/feeding ***********************************/ + /*feeding items to PU output buffer*/ + sResult = picodata_cbPutItem(this->cbOut, + &(pam->outBuf[pam->outReadPos]), pam->outWritePos + - pam->outReadPos, &numoutb); + PICODBG_DEBUG(("pam_step -- put item, status: %d",sResult)); + if (PICO_OK == sResult) { + + PICODATA_INFO_ITEM(this->voice->kbArray[PICOKNOW_KBID_DBG], + (picoos_uint8 *)"pam: ", + pam->outBuf + pam->outReadPos, pam->outBufSize); + + pam->outReadPos += numoutb; + *numBytesOutput = numoutb; + if (pam->outReadPos >= pam->outWritePos) { + /*reset the output pointers*/ + pam->outReadPos = 0; + pam->outWritePos = 0; + /*switch to appropriate state*/ + switch (pam->retState) { + case PICOPAM_IMMEDIATE: + pam->procState = PICOPAM_IMMEDIATE; + pam->retState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + break; + case PICOPAM_PLAY: + pam->procState = PICOPAM_PLAY; + pam->retState = PICOPAM_SCHEDULE; + return PICODATA_PU_BUSY; + break; + default: + break; + } + /*Define next state + a)process (if current sentence has more data to process) + b)schedule (no more data to process in current sentence) + NOTE : case b)also happens when dealing with non BOUND/SYLL items*/ + if ((pamHasToProcess(this)) || (pamHasToPop(this))) { + pam->procState = PICOPAM_PROCESS; + } else { + pam->nCurrSyllable = -1; + pam_reset_processors(this); + pam->nLastAttachedItemId = pam->nCurrAttachedItem + = 0; + pam->nAttachedItemsSize = 0; + + pam->nSyllPhoneme = 0; + pam->procState = PICOPAM_SCHEDULE; + } + } + return PICODATA_PU_BUSY; + + } else if (PICO_EXC_BUF_OVERFLOW == sResult) { + + PICODBG_DEBUG(("pam_step ** feeding, overflow, PICODATA_PU_OUT_FULL")); + return PICODATA_PU_OUT_FULL; + + } else if ((PICO_EXC_BUF_UNDERFLOW == sResult) + || (PICO_ERR_OTHER == sResult)) { + + PICODBG_DEBUG(("pam_step ** feeding problem, discarding item")); + pam->outReadPos = 0; + pam->outWritePos = 0; + pam->procState = PICOPAM_COLLECT; + return PICODATA_PU_ERROR; + + } + break; /*PICOPAM_FEED*/ + + default: + /*NOT feeding items*/ + sResult = PICO_EXC_BUF_IGNORE; + break; + }/*end switch*/ + return PICODATA_PU_BUSY; /*check if there is more data to process after feeding*/ + + }/*end while*/ + return PICODATA_PU_IDLE; +}/*pam_step*/ + +/** + * performs one step of a PamTree + * @param this : Pam item subobject pointer + * @param dtpam : the Pam decision tree + * @param *invec : the input vector pointer + * @param inveclen : length of the input vector + * @param *dtres : the classification result + * @return dtres->set : the result of tree traversal + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_do_tree(register picodata_ProcessingUnit this, + const picokdt_DtPAM dtpam, const picoos_uint8 *invec, + const picoos_uint8 inveclen, picokdt_classify_result_t *dtres) +{ + picoos_uint8 okay; + + okay = TRUE; + /* construct input vector, which is set in dtpam */ + if (!picokdt_dtPAMconstructInVec(dtpam, invec, inveclen)) { + /* error constructing invec */ + PICODBG_WARN(("problem with invec")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_INVECTOR, NULL, NULL); + okay = FALSE; + } + /* classify */ + if (okay && (!picokdt_dtPAMclassify(dtpam))) { + /* error doing classification */ + PICODBG_WARN(("problem classifying")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_CLASSIFICATION, NULL, + NULL); + okay = FALSE; + } + /* decompose */ + if (okay && (!picokdt_dtPAMdecomposeOutClass(dtpam, dtres))) { + /* error decomposing */ + PICODBG_WARN(("problem decomposing")); + picoos_emRaiseWarning(this->common->em, PICO_WARN_OUTVECTOR, NULL, NULL); + okay = FALSE; + } + + PICODBG_TRACE(("dtpam output class: %d", dtres->class)); + + return dtres->set; +}/*pam_do_tree*/ + +/** + * returns the carrier vowel id inside a syllable + * @param this : Pam item subobject pointer + * @param item : the full syllable item + * @param *pos : pointer to the variable to receive the position of the carrier vowel + * @return the phonetic id for the carrier vowel inside the syllable + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_get_vowel_name(register picodata_ProcessingUnit this, + picoos_uint8 *item, picoos_uint8 *pos) +{ + pam_subobj_t *pam; + picoos_uint8 *phon, nI, nCond1; + if (NULL == this || NULL == this->subObj) { + return 0; + } + pam = (pam_subobj_t *) this->subObj; + + if (item == NULL) + return 0; + if (item[3] == 0) + return 0; + phon = &item[4]; + for (nI = 0; nI < item[3]; nI++) { + nCond1 = picoktab_isSyllCarrier(pam->tabphones, phon[nI]); + if (nCond1) { + *pos = nI; + return phon[nI]; + } + } + return 0; +}/*pam_get_vowel_name */ + +/** + * returns the pause phone id in the current ph.alphabet + * @param this : Pam sub object pointer + * @return the (numeric) phonetic id of the pause phone in current phonetic alphabet + * @return 0 : errors on getting the pam subobject pointer + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_get_pause_id(register picodata_ProcessingUnit this) +{ + picoos_uint8 nVal1; + /*picoos_uint8 nVal2; */ + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return 0; + } + pam = (pam_subobj_t *) this->subObj; + nVal1 = picoktab_getPauseID(pam->tabphones); + return nVal1; +}/*pam_get_pause_id */ + +/** + * returns the pam sentence type (declarative, interrogative...) + * @param iteminfo1 : the boundary item info 1 + * @param iteminfo2 : the boundary item info 2 + * @return the sentence type suitably encoded for trees + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_map_sentence_type(picoos_uint8 iteminfo1, + picoos_uint8 iteminfo2) +{ + switch (iteminfo2) { + case PICODATA_ITEMINFO2_BOUNDTYPE_P: + return PICOPAM_DECLARATIVE; + case PICODATA_ITEMINFO2_BOUNDTYPE_T: + return PICOPAM_DECLARATIVE; + case PICODATA_ITEMINFO2_BOUNDTYPE_Q: + return PICOPAM_INTERROGATIVE; + case PICODATA_ITEMINFO2_BOUNDTYPE_E: + return PICOPAM_DECLARATIVE; + default: + return PICOPAM_DECLARATIVE; + } + iteminfo1 = iteminfo1; /* avoid warning "var not used in this function"*/ + return PICOPAM_DECLARATIVE; +}/*pam_map_sentence_type */ + +/** + * returns the pam phrase type + * @param iteminfo1 : the boundary item info 1 + * @param iteminfo2 : the boundary item info 2 + * @return the phrase type suitably encoded for trees + * @callgraph + * @callergraph + */ +static picoos_uint8 pam_map_phrase_type(picoos_uint8 iteminfo1, + picoos_uint8 iteminfo2) +{ + + switch (iteminfo2) { + case PICODATA_ITEMINFO2_BOUNDTYPE_P: + switch (iteminfo1) { + case PICODATA_ITEMINFO1_BOUND_PHR1: +# ifdef PAM_PHR2_WITH_PR1 + case PICODATA_ITEMINFO1_BOUND_PHR2: +# endif + return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */ + break; + case PICODATA_ITEMINFO1_BOUND_PHR3: +# ifdef PAM_PHR2_WITH_PR3 + case PICODATA_ITEMINFO1_BOUND_PHR2 : +# endif + return PICOPAM_p; /*current_prhase type = "p" (encoded to 2) */ + break; + case PICODATA_ITEMINFO1_BOUND_SBEG: + return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */ + break; + default: + PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo1")); + return PICOPAM_P; /*current_prhase type = "P" (encoded to 1) */ + break; + } + case PICODATA_ITEMINFO2_BOUNDTYPE_T: + return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ + break; + case PICODATA_ITEMINFO2_BOUNDTYPE_E: + return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ + break; + case PICODATA_ITEMINFO2_BOUNDTYPE_Q: + return PICOPAM_Y; /*current_prhase type = "T" (encoded to 0) */ + break; + default: + PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo2")); + return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ + break; + }PICODBG_DEBUG(("Map pam_map_phrase_type : unexpected iteminfo2")); + return PICOPAM_T; /*current_prhase type = "T" (encoded to 0) */ + +}/*pam_map_phrase_type */ + +/** + * does the cleanup of the sub object processors flags at sentence start + * @param this : pointer to PAM PU sub object pointer + * @return PICO_OK : reset OK + * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_reset_processors(register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + pam->nCurrSyllable = -1; + pam->nTotalPhonemes = pam->nSyllPhoneme = pam->nCurrPhoneme + = pam->nTotalSyllables = pam->sType = pam->pType = 0; + pam->dRest = 0.0f; + /*set all to 0*/ + pam->a3_overall_syllable = pam->a3_primary_phrase_syllable = pam->b4_b5_syllable = + pam->b6_b7_syllable = pam->b6_b7_state = pam->b8_b9_stressed_syllable = + pam->b10_b11_accented_syllable = pam->b12_b13_syllable = pam->b12_b13_state = + pam->b14_b15_syllable = pam->b14_b15_state = pam->b17_b19_syllable = + pam->b17_b19_state = pam->b18_b20_b21_syllable = pam->b18_b20_b21_state = + pam->c3_overall_syllable= pam->c3_primary_phrase_syllable = pam->d2_syllable_in_word = + pam->d2_prev_syllable_in_word = pam->d2_current_primary_phrase_word = pam->e1_syllable_word_start = + pam->e1_syllable_word_end= pam->e1_content = pam->e2_syllable_word_start = + pam->e2_syllable_word_end= pam->e3_e4_word = pam->e3_e4_state = + pam->e5_e6_content_word = pam->e5_e6_content = pam->e7_e8_word = + pam->e7_e8_content = pam->e7_e8_state = pam->e9_e11_word = + pam->e9_e11_saw_word = pam->e9_e11_state = pam->e10_e12_e13_word = + pam->e10_e12_e13_state = pam->e10_e12_e13_saw_word = pam->f2_overall_word = + pam->f2_word_syllable = pam->f2_next_word_syllable = pam->f2_current_primary_phrase_word = + pam->g1_current_secondary_phrase_syllable = pam->g1_current_syllable = + pam->g2_current_secondary_phrase_word = pam->g2_current_word = + pam->h1_current_secondary_phrase_syll = pam->h2_current_secondary_phrase_word = + pam->h3_h4_current_secondary_phrase_word = pam->h5_current_phrase_type = + pam->h5_syllable = pam->h5_state = pam->i1_secondary_phrase_syllable = + pam->i1_next_secondary_phrase_syllable = pam->i2_secondary_phrase_word = + pam->i2_next_secondary_phrase_word = pam->j1_utterance_syllable = + pam->j2_utterance_word = pam->j3_utterance_sec_phrases = 0; + /*Override 0 with 1*/ + pam->b4_b5_syllable = pam->b17_b19_syllable = pam->b18_b20_b21_syllable = + pam->e9_e11_word = pam->e10_e12_e13_word = pam->e7_e8_word = + pam->h2_current_secondary_phrase_word = 1; + /*Override 0 with -1*/ + pam->e1_syllable_word_start = pam->e1_syllable_word_end = pam->e2_syllable_word_start = + pam->e2_syllable_word_end = -1; + + return PICO_OK; +}/*pam_reset_processors*/ + +/** + * does the cleanup of the sub object processors flags before the backward step + * @param this : pointer to PAM PU sub object pointer + * @return PICO_OK : reset OK + * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_reset_processors_back( + register picodata_ProcessingUnit this) +{ + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + /*set all to 0*/ + pam->a3_overall_syllable + = pam->a3_primary_phrase_syllable + = pam->b4_b5_syllable + = pam->b6_b7_syllable + = pam->b6_b7_state + = pam->b8_b9_stressed_syllable + = pam->b10_b11_accented_syllable + = pam->b12_b13_syllable + = pam->b12_b13_state + = pam->b14_b15_syllable + = pam->b14_b15_state + = pam->b17_b19_syllable + = pam->b17_b19_state + = pam->b18_b20_b21_syllable + = pam->b18_b20_b21_state + = pam->c3_overall_syllable + = pam->c3_primary_phrase_syllable + = pam->d2_syllable_in_word + = pam->d2_prev_syllable_in_word + = pam->d2_current_primary_phrase_word + = pam->e1_syllable_word_start + = pam->e1_syllable_word_end + = pam->e1_content + = pam->e2_syllable_word_start + = pam->e2_syllable_word_end + = pam->e3_e4_word + = pam->e3_e4_state + = pam->e5_e6_content_word + = pam->e5_e6_content + = pam->e7_e8_word + = pam->e7_e8_content + = pam->e7_e8_state + = pam->e9_e11_word + = pam->e9_e11_saw_word + = pam->e9_e11_state + = pam->e10_e12_e13_word + = pam->e10_e12_e13_state + = pam->e10_e12_e13_saw_word + = pam->f2_overall_word + = pam->f2_word_syllable + = pam->f2_next_word_syllable + = pam->f2_current_primary_phrase_word + = pam->g1_current_secondary_phrase_syllable + = pam->g1_current_syllable + = pam->g2_current_secondary_phrase_word + = pam->g2_current_word + = pam->h1_current_secondary_phrase_syll + = pam->h2_current_secondary_phrase_word + = pam->h3_h4_current_secondary_phrase_word + = pam->h5_current_phrase_type + = pam->h5_state + = pam->i1_secondary_phrase_syllable + = pam->i1_next_secondary_phrase_syllable + = pam->i2_secondary_phrase_word + = pam->i2_next_secondary_phrase_word + = 0; + /*Override 0 with 1*/ + pam->b4_b5_syllable = pam->b17_b19_syllable = pam->b18_b20_b21_syllable + = pam->e9_e11_word = pam->e10_e12_e13_word = pam->e7_e8_word + = pam->h2_current_secondary_phrase_word = 1; + /*Override 0 with -1*/ + pam->e1_syllable_word_start = pam->e1_syllable_word_end + = pam->e2_syllable_word_start = pam->e2_syllable_word_end = -1; + + return PICO_OK; +}/*pam_reset_processors_back*/ + +/** + * processes an input event for a specific feature + * @param this : pointer to PAM PU sub object pointer + * @param nFeat : feature column to process + * @param event_type : event id among syll/boundprim/boundsec/boundword + * @param direction : forward(0)/backward(1) + * @return PICO_OK : process OK + * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_process_event_feature( + register picodata_ProcessingUnit this, picoos_uint8 nFeat, + picoos_uint8 event_type, picoos_uint8 direction) +{ + picoos_uint8 sDest, nI; + picoos_uint16 syllCurr; + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + syllCurr = pam->nCurrSyllable; + switch (nFeat) { + case A3: + /*processor for A3*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] + == 1) || (pam->a3_primary_phrase_syllable >= 1)) { + if (pam->a3_overall_syllable < 1) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] + = 0; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] + = pam->sSyllFeats[pam->nCurrSyllable + - 1].phoneV[B3]; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] = 0; + } + pam->a3_primary_phrase_syllable++; + pam->a3_overall_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->a3_primary_phrase_syllable = 0; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case B1: + case B2: + case B3: + /*done in createSyllable*/ + break; + case B4:/*processor for B4,B5*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B4; + break; + case PICOPAM_DIR_BACK: + sDest = B5; + break; + default: + sDest = B4; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] == 0) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b4_b5_syllable; + pam->b4_b5_syllable++; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] = 0; + } + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + pam->b4_b5_syllable = 1; + } + break; + case B5:/*processor for B5 : done in B4*/ + break; + case B6:/*processor for B6,B7*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B6; + break; + case PICOPAM_DIR_BACK: + sDest = B7; + break; + default: + sDest = B6; + break; + } + switch (pam->b6_b7_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->b6_b7_syllable = 1; + pam->b6_b7_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b6_b7_syllable; + pam->b6_b7_syllable++; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->b6_b7_syllable = 1; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b6_b7_state = 0; + } + break; + default: + break; + } + break; + case B7:/*Done in B6*/ + break; + case B8:/*processor for B8,B9*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B8; + break; + case PICOPAM_DIR_BACK: + sDest = B9; + break; + default: + sDest = B8; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b8_b9_stressed_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1) + pam->b8_b9_stressed_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b8_b9_stressed_syllable = 0; + } + + break; + case B9:/*done in B8*/ + break; + case B10:/*processor for B10, B11*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B10; + break; + case PICOPAM_DIR_BACK: + sDest = B11; + break; + default: + sDest = B10; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b10_b11_accented_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1) + pam->b10_b11_accented_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b10_b11_accented_syllable = 0; + } + break; + case B11:/*done in B10*/ + break; + case B12:/*processor for B12,B13*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B12; + break; + case PICOPAM_DIR_BACK: + sDest = B13; + break; + default: + sDest = B12; + break; + } + switch (pam->b12_b13_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + else { + pam->b12_b13_syllable = 0; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + pam->b12_b13_state = 1; + } + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b12_b13_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1) + pam->b12_b13_syllable = 0; + else + pam->b12_b13_syllable++; + pam->b12_b13_state = 2; + } + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->b12_b13_state = 0; + break; + case 2: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b12_b13_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] == 1) + pam->b12_b13_syllable = 0; + else + pam->b12_b13_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->b12_b13_state = 0; + + break; + default: + break; + } + break; + case B13:/*done in B12*/ + break; + + case B14:/*processor for B14, B15*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = B14; + break; + case PICOPAM_DIR_BACK: + sDest = B15; + break; + default: + sDest = B14; + break; + } + switch (pam->b14_b15_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + else { + pam->b14_b15_syllable = 0; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + pam->b14_b15_state = 1; + } + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b14_b15_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1) + pam->b14_b15_syllable = 0; + else + pam->b14_b15_syllable++; + pam->b14_b15_state = 2; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b14_b15_state = 0; + } + break; + case 2: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->b14_b15_syllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] == 1) + pam->b14_b15_syllable = 0; + else + pam->b14_b15_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b14_b15_state = 0; + } + break; + default: + break; + } + break; + case B15:/*Processor for B15 : done in B14*/ + break; + case B16:/*done in createSyllable*/ + break; + case B17:/*processor for B17, B19 unified */ + switch (direction) { + case PICOPAM_DIR_FORW: + switch (pam->b17_b19_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] + = pam->b17_b19_syllable; + pam->b17_b19_syllable++; + } + if (((event_type == PICOPAM_EVENT_P_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + && (pam->b17_b19_syllable > 1)) { + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->b17_b19_syllable = 1; + pam->b17_b19_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] + = pam->b17_b19_syllable; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] + = PICOPAM_DONT_CARE_VALUE; + pam->b17_b19_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b17_b19_syllable = 1; + } + break; + default: + break; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case B18:/*processor for B18, B20, B21 unfied*/ + switch (direction) { + case PICOPAM_DIR_FORW:/*do nothing*/ + break; + case PICOPAM_DIR_BACK: + switch (pam->b18_b20_b21_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] + = PICOPAM_DONT_CARE_VALUE; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + == PICOPAM_DECLARATIVE) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = pam->b18_b20_b21_syllable; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = PICOPAM_DONT_CARE_VALUE; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = pam->b18_b20_b21_syllable; + } + pam->b18_b20_b21_syllable++; + } + if (((event_type == PICOPAM_EVENT_P_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + && (pam->b18_b20_b21_syllable > 1)) { + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->b18_b20_b21_syllable = 1; + pam->b18_b20_b21_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] + = pam->b18_b20_b21_syllable; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = PICOPAM_DONT_CARE_VALUE; + pam->b18_b20_b21_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->b18_b20_b21_syllable = 1; + } + break; + default: + break; + } + break; + } + break; + case B19:/*processor for B19 : done in B17*/ + break; + case B20:/*processor for B20 : done in B18*/ + break; + case B21:/*processor for B21 : done in B18*/ + break; + case C3:/*processor for C3*/ + switch (direction) { + case PICOPAM_DIR_FORW: + /*do nothing*/ + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) { + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] + == 1) || (pam->c3_primary_phrase_syllable >= 1)) { + if (pam->c3_overall_syllable < 1) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] + = 0; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] + = pam->sSyllFeats[pam->nCurrSyllable + + 1].phoneV[B3]; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] = 0; + } + pam->c3_primary_phrase_syllable++; + pam->c3_overall_syllable++; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->c3_primary_phrase_syllable = 0; + } + break; + } + break; + case D2:/*processor for D2*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] + == 1) || (pam->d2_current_primary_phrase_word + >= 1)) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] + = pam->d2_prev_syllable_in_word; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] = 0; + + pam->d2_syllable_in_word++; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + pam->d2_current_primary_phrase_word = 1; + pam->d2_prev_syllable_in_word + = pam->d2_syllable_in_word; + pam->d2_syllable_in_word = 0; + /*pam->d2_current_primary_phrase_word++;*/ + } + if ((event_type == PICOPAM_EVENT_P_BOUND)) { + pam->d2_current_primary_phrase_word = 0; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case E1:/*processor for E1*/ + switch (direction) { + case PICOPAM_DIR_FORW: /*remember : content syllable indicator already on P5*/ + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->e1_syllable_word_start == -1) + pam->e1_syllable_word_start + = (picoos_int8) pam->nCurrSyllable; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) + pam->e1_content = 1; + pam->e1_syllable_word_end + = (picoos_int8) pam->nCurrSyllable; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + if ((pam->e1_syllable_word_start != -1) + && (pam->e1_syllable_word_end != -1)) { + for (nI = pam->e1_syllable_word_start; nI + <= pam->e1_syllable_word_end; nI++) + pam->sSyllFeats[nI].phoneV[E1] + = pam->e1_content; + } + pam->e1_content = 0; + pam->e1_syllable_word_start = -1; + pam->e1_syllable_word_end = -1; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case E2:/*processor for E2*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->e2_syllable_word_start == -1) + pam->e2_syllable_word_start + = (picoos_int8) pam->nCurrSyllable; + pam->e2_syllable_word_end + = (picoos_int8) pam->nCurrSyllable; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + if ((pam->e2_syllable_word_start != -1) + && (pam->e2_syllable_word_end != -1)) { + for (nI = pam->e2_syllable_word_start; nI + <= pam->e2_syllable_word_end; nI++) + pam->sSyllFeats[nI].phoneV[E2] + = pam->e2_syllable_word_end + - pam->e2_syllable_word_start + + 1; + } + pam->e1_content = 0; + pam->e2_syllable_word_start = -1; + pam->e2_syllable_word_end = -1; + } + break; + case PICOPAM_DIR_BACK: + break; + } + break; + case E3:/*processor for E3,E4*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = E3; + break; + case PICOPAM_DIR_BACK: + sDest = E4; + break; + default: + sDest = E3; + break; + } + switch (pam->e3_e4_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->e3_e4_word = 1; + pam->e3_e4_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->e3_e4_word; + if (event_type == PICOPAM_EVENT_S_BOUND) + pam->e3_e4_word = 1; + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->e3_e4_word++; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e3_e4_state = 0; + break; + default: + break; + } + break; + case E4:/*processor for E4 : done in E3*/ + break; + case E5:/*processor for E5,E6*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = E5; + break; + case PICOPAM_DIR_BACK: + sDest = E6; + break; + default: + sDest = E5; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->e5_e6_content_word; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) + pam->e5_e6_content = 1; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) { + if (pam->e5_e6_content == 1) + pam->e5_e6_content_word++; + pam->e5_e6_content = 0; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e5_e6_content_word = 0; + } + break; + case E6:/*processor for E6 : done in E5*/ + break; + case E7:/*processor for E7,E8*/ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = E7; + break; + case PICOPAM_DIR_BACK: + sDest = E8; + break; + default: + sDest = E7; + break; + } + switch (pam->e7_e8_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = PICOPAM_DONT_CARE_VALUE; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) + pam->e7_e8_content = 1; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->e7_e8_content = 0; + } + + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND)) { + if (pam->e7_e8_content == 1) { + pam->e7_e8_word = 0; + pam->e7_e8_content = 0; + pam->e7_e8_state = 1; + } + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->e7_e8_word; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] == 1) + pam->e7_e8_content = 1; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND)) { + if (pam->e7_e8_content == 1) { + pam->e7_e8_word = 0; + pam->e7_e8_content = 0; + } else { + pam->e7_e8_word++; + } + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->e7_e8_state = 0; + pam->e7_e8_content = 0; /*<<<<<< added */ + } + + default: + break; + } + break; + case E8:/*processor for E8 : done in E7*/ + break; + case E9: + /*processor for E9, E11*/ + switch (direction) { + case PICOPAM_DIR_FORW: + switch (pam->e9_e11_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] + = pam->e9_e11_word; + pam->e9_e11_saw_word = 1; /*new variable, needs to be initialized to 0*/ + } + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->e9_e11_word++; + if (((event_type == PICOPAM_EVENT_P_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + && (pam->e9_e11_saw_word == 1)) { /* modified*/ + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e9_e11_word = 1; + else + pam->e9_e11_word++; /*modified*/ + pam->e9_e11_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] + = pam->e9_e11_word; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] + = PICOPAM_DONT_CARE_VALUE; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + pam->e9_e11_word++; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e9_e11_word = 1; + break; + default: + break; + } + break; + case PICOPAM_DIR_BACK: + /*do nothing*/ + break; + } + break; + case E10:/*processor for E10, E12, E13 unified*/ + switch (direction) { + case PICOPAM_DIR_FORW:/*do nothing*/ + break; + case PICOPAM_DIR_BACK: + switch (pam->e10_e12_e13_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E10] + = PICOPAM_DONT_CARE_VALUE; + pam->e10_e12_e13_saw_word = 1; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + == PICOPAM_DECLARATIVE) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = pam->e10_e12_e13_word; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = PICOPAM_DONT_CARE_VALUE; + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = pam->e10_e12_e13_word; + } + } + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->e10_e12_e13_word++; + + /*if (((event_type==PICOPAM_EVENT_P_BOUND)||(event_type==PICOPAM_EVENT_S_BOUND))&&(pam->e10_e12_e13_word>1)) {*/ + if (((event_type == PICOPAM_EVENT_P_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + && (pam->e10_e12_e13_saw_word > 0)) { + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e10_e12_e13_word = 1; + else + pam->e10_e12_e13_word++; + pam->e10_e12_e13_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E10] + = pam->e10_e12_e13_word; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = PICOPAM_DONT_CARE_VALUE; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = PICOPAM_DONT_CARE_VALUE; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) + || (event_type == PICOPAM_EVENT_S_BOUND)) + pam->e10_e12_e13_word++; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->e10_e12_e13_word = 1; + break; + default: + break; + } + break; + } + break; + + case E11:/*processor for E11 : done in E9*/ + break; + case E12:/*processor for E12 : done in E10*/ + break; + case E13:/*processor for E13 : done in E10*/ + break; + + case F2: + switch (direction) { + case PICOPAM_DIR_FORW:/*do nothing*/ + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->f2_current_primary_phrase_word >= 1)/*at least second word in current primary phrase*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] + = pam->f2_next_word_syllable; + else + /*first word in current primary phrase*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] = 0; + pam->f2_word_syllable++; + } + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) {/*word - end : switch*/ + pam->f2_next_word_syllable = pam->f2_word_syllable; + pam->f2_word_syllable = 0; + } + if (event_type == PICOPAM_EVENT_P_BOUND)/*mark first word in current primary phrase*/ + pam->f2_current_primary_phrase_word = 0; + else /*mark next word in current primary phrase(enables output in PICOPAM_EVENT_SYLL)*/ + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND)) + pam->f2_current_primary_phrase_word++; + break; + } + break; + case G1: + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->g1_current_secondary_phrase_syllable > 0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] + = pam->g1_current_secondary_phrase_syllable; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] = 0; + pam->g1_current_syllable++; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->g1_current_secondary_phrase_syllable + = pam->g1_current_syllable; + pam->g1_current_syllable = 0; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->g1_current_secondary_phrase_syllable = 0; + pam->g1_current_syllable = 0; + } + case PICOPAM_DIR_BACK: /*do nothing*/ + break; + } + break; + case G2: + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->g2_current_secondary_phrase_word > 0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] + = pam->g2_current_secondary_phrase_word; + else + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] = 0; + } + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->g2_current_word++; + + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->g2_current_secondary_phrase_word + = pam->g2_current_word + 1; + pam->g2_current_word = 0; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->g2_current_secondary_phrase_word = 0; + pam->g2_current_word = 0; + } + break; + case PICOPAM_DIR_BACK: /*do nothing*/ + break; + } + break; + case H1: + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->h1_current_secondary_phrase_syll++; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] + = pam->h1_current_secondary_phrase_syll; + } + if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) + pam->h1_current_secondary_phrase_syll = 0; + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] + = pam->h1_current_secondary_phrase_syll; + if (event_type == PICOPAM_EVENT_S_BOUND) + pam->h1_current_secondary_phrase_syll + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1]; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->h1_current_secondary_phrase_syll + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1]; + break; + } + break; + case H2: + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->h2_current_secondary_phrase_word; + } + if (event_type == PICOPAM_EVENT_W_BOUND) { + pam->h2_current_secondary_phrase_word++; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->h2_current_secondary_phrase_word; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->h2_current_secondary_phrase_word + 1; + pam->h2_current_secondary_phrase_word = 0; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + if (pam->nCurrSyllable > 1) + pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2] + = pam->h2_current_secondary_phrase_word + 1; + pam->h2_current_secondary_phrase_word = 0; + } + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->h2_current_secondary_phrase_word; + if (event_type == PICOPAM_EVENT_S_BOUND) + pam->h2_current_secondary_phrase_word + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2]; + if (event_type == PICOPAM_EVENT_P_BOUND) + pam->h2_current_secondary_phrase_word + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]; + break; + } + break; + case H3:/*processor for H3,H4 unified */ + switch (direction) { + case PICOPAM_DIR_FORW: + sDest = H3; + break; + case PICOPAM_DIR_BACK: + sDest = H4; + break; + default: + sDest = H3; + break; + } + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[sDest] + = pam->h3_h4_current_secondary_phrase_word; + } + if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) + pam->h3_h4_current_secondary_phrase_word++; + break; + case H4: /*processor for H4 : already in H3*/ + break; + + case H5:/*processor for H5*/ + switch (direction) { + case PICOPAM_DIR_FORW: + break; + case PICOPAM_DIR_BACK: + switch (pam->h5_state) { + case 0: + if (event_type == PICOPAM_EVENT_SYLL) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5]; + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->h5_state = 1; + } + break; + case 1: + if (event_type == PICOPAM_EVENT_SYLL) { + if ((pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] + == PICOPAM_P) + && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] + == 0)) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] + = PICOPAM_p; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->h5_state = 0; + } + break; + default: + break; + } + break; + + default: + break; + } + break; + + case I1:/*processor for I1*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->i1_secondary_phrase_syllable++; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] + = pam->i1_secondary_phrase_syllable; + } + if ((event_type == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) + pam->i1_secondary_phrase_syllable = 0; + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] + = pam->i1_next_secondary_phrase_syllable; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->i1_next_secondary_phrase_syllable + = pam->i1_secondary_phrase_syllable; + pam->i1_secondary_phrase_syllable + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1]; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->i1_next_secondary_phrase_syllable = 0; + pam->i1_secondary_phrase_syllable + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[I1]; + } + break; + } + break; + case I2: /*processor for I2*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] + = pam->i2_secondary_phrase_word; + } + if (event_type == PICOPAM_EVENT_W_BOUND) + pam->i2_secondary_phrase_word++; + + if ((event_type == PICOPAM_EVENT_P_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND)) + pam->i2_secondary_phrase_word = 1; + + break; + case PICOPAM_DIR_BACK: + if (event_type == PICOPAM_EVENT_SYLL) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] + = pam->i2_next_secondary_phrase_word; + } + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->i2_next_secondary_phrase_word + = pam->i2_secondary_phrase_word; + pam->i2_secondary_phrase_word + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2]; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->i2_next_secondary_phrase_word = 0; + pam->i2_secondary_phrase_word + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[I2]; + } + break; + } + break; + case J1: /*processor for J1 */ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_SYLL) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] != 1) + pam->j1_utterance_syllable++; + } + break; + case PICOPAM_DIR_BACK: + pam->sSyllFeats[pam->nCurrSyllable].phoneV[J1] + = pam->j1_utterance_syllable; + break; + } + break; + case J2: /*processor for J2*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if ((event_type == PICOPAM_EVENT_W_BOUND) || (event_type + == PICOPAM_EVENT_S_BOUND) || (event_type + == PICOPAM_EVENT_P_BOUND)) + pam->j2_utterance_word++; + break; + case PICOPAM_DIR_BACK: + pam->sSyllFeats[pam->nCurrSyllable].phoneV[J2] + = pam->j2_utterance_word - 1; + break; + } + break; + case J3: /*processor for J3*/ + switch (direction) { + case PICOPAM_DIR_FORW: + if (event_type == PICOPAM_EVENT_S_BOUND) { + pam->j3_utterance_sec_phrases++; + break; + } + if (event_type == PICOPAM_EVENT_P_BOUND) { + pam->j3_utterance_sec_phrases++; + break; + } + break; + case PICOPAM_DIR_BACK: + pam->sSyllFeats[pam->nCurrSyllable].phoneV[J3] + = pam->j3_utterance_sec_phrases - 1; + break; + } + break; + } + return PICO_OK; +}/*pam_process_event_feature*/ + +/** + * processes an input event spanning it to all column features + * @param this : pointer to PAM PU sub object pointer + * @param event_type : event id among syll/boundprim/boundsec/boundword + * @param direction : forward(0)/backward(1) + * @return PICO_OK : process OK + * @return PICO_ERR_OTHER : errors on getting pam sub obj pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_process_event(register picodata_ProcessingUnit this, + picoos_uint8 event_type, picoos_uint8 direction) +{ + picoos_uint8 nFeat; + pico_status_t nResult; + + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + if (direction == PICOPAM_DIR_FORW) { + if (event_type == PICOPAM_EVENT_P_BOUND) + /*primary boundary*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] = 1; + if (event_type == PICOPAM_EVENT_S_BOUND) + /*secondary boundary*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P3] = 1; + if (event_type == PICOPAM_EVENT_W_BOUND) + /*word boundary*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P4] = 1; + } + for (nFeat = A3; nFeat <= J3; nFeat++) { + nResult = pam_process_event_feature(this, nFeat, event_type, direction); + if (nResult != PICO_OK) + return nResult; + } + return PICO_OK; +}/*pam_process_event*/ + +/** + * inserts a syllable inside the subobj sentence data struct. + * @param this : pointer to PAM PU sub object pointer + * @param syllType : the syllable type (pause/syllable) + * @param sContent : the item content + * @param sentType : the sentence type + * @param phType : the phrase type + * @param uBoundType : the boundary type (only for silence syllables) + * @param uMinDur, uMaxDur : the mimimum and maximum duration (only for silence syllables) + * @return PICO_OK : syllable creation successful + * @return PICO_ERR_OTHER : errors in one internal function (check_phones_size..) + * @callgraph + * @callergraph + */ +static pico_status_t 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) +{ + pam_subobj_t *pam; + picoos_uint8 nI; + picoos_uint8 pos; + /* picoos_uint8 *npUi16; */ + picoos_uint32 pos32; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + pos = 0; + /*check buffer full condition on number of syllables*/ + if (check_syllables_size(pam, 1) != PICO_OK) { + return PICO_ERR_OTHER; + } + + if (syllType == PICOPAM_SYLL_PAUSE) { + /*check buffer full condition on number of phonemes*/ + if (check_phones_size(pam, 1) != PICO_OK) { + return PICO_ERR_OTHER; + } + } + if (syllType == PICOPAM_SYLL_SYLL) { + /*check item availability*/ + if (sContent == NULL) { + return PICO_ERR_OTHER; + } + /*check buffer full condition on number of phonemes*/ + if (check_phones_size(pam, sContent[3]) != PICO_OK) { + return PICO_ERR_OTHER; + } + } + + /*open new syllable*/ + pam->nCurrSyllable = pam->nCurrSyllable + 1; + /*cleanup*/ + for (nI = 0; nI < PICOPAM_VECT_SIZE; nI++) { + if (pam->nCurrSyllable > 0) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0; + } else { + if ((nI >= ITM) && (nI <= itm)) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] > 0) { + /*do not cleanup "attached item offset" fields (ITM, itm): + an already existing attached item could be lost*/ + } else { + /*cleanup "attached item offset"*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0; + } + } else { + /*cleanup all fields except "attached item offset" (ITM, itm)*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[nI] = 0; + } + } + } + /*set minimum and maximum duration values*/ + if ((uMinDur == 0) && (uMaxDur == 0) && (syllType == PICOPAM_SYLL_PAUSE)) { + /*both 0 : use default duration limits for boundaries*/ + get_default_boundary_limit(uBoundType, &uMinDur, &uMaxDur); + } + if (uMinDur > 0) { + pos32 = Min; + picoos_write_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, + &pos32, uMinDur); + } + if (uMaxDur > 0) { + pos32 = Max; + picoos_write_mem_pi_uint16(pam->sSyllFeats[pam->nCurrSyllable].phoneV, + &pos32, uMaxDur); + } + /*END OF BREAK COMMAND SUPPORT*/ + + if (syllType == PICOPAM_SYLL_PAUSE) { + /*initialize a pause syllable*/ + if (sentType == PICOPAM_DECLARATIVE) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + = PICOPAM_DECLARATIVE; + if (sentType == PICOPAM_INTERROGATIVE) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + = PICOPAM_INTERROGATIVE; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[bnd] = uBoundType; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P1] = 1; /*this means the syllable contains a pause-silence*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P8] = 1; + + /*b1,b2,b9,b11,b13,b15,e1,e6,e8,e10 already set to 0*/ + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B4] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B5] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B6] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B7] + = 1; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B16] + = PICOPAM_PH_DONT_CARE_VAL; /*name of the vowel in the syllable = NONE */ + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E2] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E3] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E4] = 1; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = phType; + + /*Store current phonetic codes in input phonetic string*/ + pam->sPhIds[pam->nCurrPhoneme] = pam_get_pause_id(this); + picoos_mem_copy((void*) &pam->nCurrPhoneme, + &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[FID]), + sizeof(pam->nCurrPhoneme)); + pam->nCurrPhoneme++; + pam->nTotalPhonemes++; + /*add 1 to total number of syllables*/ + pam->nTotalSyllables++; + + return PICO_OK; + } + if (syllType == PICOPAM_SYLL_SYLL) { + /*initialize a real syllable*/ + if (sContent[2] > PICODATA_ACC0) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P5] = 1; /*set content syllable indicator*/ + if (sentType == PICOPAM_DECLARATIVE) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + = PICOPAM_DECLARATIVE; + if (sentType == PICOPAM_INTERROGATIVE) + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P6] + = PICOPAM_INTERROGATIVE; + + if ((sContent[2] >= PICODATA_ACC1) && (sContent[2] <= PICODATA_ACC4)) + /*stressed*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B1] = 1; + + if ((sContent[2] >= PICODATA_ACC1) && (sContent[2] <= PICODATA_ACC2)) + /*accented*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B2] = 1; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B3] = sContent[3];/*len*/ + + if (pam->nCurrSyllable > 30) + pam->nCurrSyllable = pam->nCurrSyllable; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B16] = pam_get_vowel_name(this, + sContent, &pos); /*name of the vowel in the syllable*/ + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[P8] = pos; /*temp for storing the position of the vowel*/ + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = phType; + + /*Store current phonetic codes in input phonetic string*/ + picoos_mem_copy((void*) &pam->nCurrPhoneme, + &(pam->sSyllFeats[pam->nCurrSyllable].phoneV[FID]), + sizeof(pam->nCurrPhoneme)); + for (nI = 0; nI < sContent[3]; nI++) + pam->sPhIds[pam->nCurrPhoneme + nI] = sContent[4 + nI]; + pam->nCurrPhoneme += nI; + pam->nTotalPhonemes += nI; + /*add 1 to total number of syllables*/ + pam->nTotalSyllables++; + return PICO_OK; + } + /*if no SyllType has been identified -->> error*/ + return PICO_ERR_OTHER; +}/*pam_create_syllable*/ + +/** + * performs the forward step of the PAM adapter + * @param this : pointer to PAM PU sub object pointer + * @param itemBase : pointer to current item + * @return PICOPAM_READY : forward step ok, the sentence is complete + * @return PICOPAM_MORE : forward step ok, but more data needed to complete the sentence + * @return PICO_ERR_OTHER : errors in one internal function (CreateSyllable..) + * @callgraph + * @callergraph + */ +static pico_status_t pam_adapter_forward_step( + register picodata_ProcessingUnit this, picoos_uint8 *itemBase) +{ + register pam_subobj_t * pam; + pico_status_t sResult; + picoos_uint16 uMinDur, uMaxDur; + picoos_uint32 nPos; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + uMinDur = uMaxDur = 0; /*default 0 : not initialized*/ + switch (itemBase[0]) { + case PICODATA_ITEM_BOUND: + /*received a boundary item*/ + switch (itemBase[1]) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + case PICODATA_ITEMINFO1_BOUND_PHR1: +#ifdef PAM_PHR2_WITH_PR1 + case PICODATA_ITEMINFO1_BOUND_PHR2: +#endif + case PICODATA_ITEMINFO1_BOUND_SEND: + case PICODATA_ITEMINFO1_BOUND_TERM: + if (itemBase[3] == 2 * sizeof(picoos_uint16)) { + /*only when the item len duration is equal to 2 int16 --> get the values*/ + nPos = 4; + picoos_read_mem_pi_uint16(itemBase, &nPos, &uMinDur); + picoos_read_mem_pi_uint16(itemBase, &nPos, &uMaxDur); + } + break; + default: + break; + } + switch (itemBase[1]) { + case PICODATA_ITEMINFO1_BOUND_SBEG: + /* received a sentence init boundary */ + pam_reset_processors(this); /*reset all processor variables*/ + pam->sType + = pam_map_sentence_type(itemBase[1], itemBase[2]); + pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]); + /*create silence syll and process P_BOUND event*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, itemBase[1], uMinDur, + uMaxDur); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + + case PICODATA_ITEMINFO1_BOUND_PHR1: +#ifdef PAM_PHR2_WITH_PR1 + case PICODATA_ITEMINFO1_BOUND_PHR2: +#endif + /*received a primary boundary*/ + pam->sType + = pam_map_sentence_type(itemBase[1], itemBase[2]); + pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]); + /*create silence syll and process P_BOUND event*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, itemBase[1], uMinDur, + uMaxDur); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + +#ifdef PAM_PHR2_WITH_PR3 + case PICODATA_ITEMINFO1_BOUND_PHR2 : +#endif + case PICODATA_ITEMINFO1_BOUND_PHR3: + /*received a secondary boundary*/ + /*process S_BOUND event*/ + sResult = pam_process_event(this, PICOPAM_EVENT_S_BOUND, + PICOPAM_DIR_FORW); + /*determine new sentence and Phrase types for following syllables*/ + pam->sType + = pam_map_sentence_type(itemBase[1], itemBase[2]); + pam->pType = pam_map_phrase_type(itemBase[1], itemBase[2]); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + + case PICODATA_ITEMINFO1_BOUND_PHR0: + /*received a word end boundary*/ + /*process W_BOUND event*/ + sResult = pam_process_event(this, PICOPAM_EVENT_W_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + + case PICODATA_ITEMINFO1_BOUND_SEND: + /*received a SEND boundary*/ + /*insert a new silence syllable and process P_BOUND event*/ + /*create silence syll and process P_BOUND event*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, itemBase[1], uMinDur, + uMaxDur); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_READY; + break; + + case PICODATA_ITEMINFO1_BOUND_TERM: + /* received a flush boundary*/ + if (pam->nCurrSyllable == -1) { + return PICOPAM_NA; + } + /*insert a new silence syllable and process P_BOUND event*/ + /*create silence syll and process P_BOUND event*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, itemBase[1], uMinDur, + uMaxDur); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_READY; + break; + + default: + /*boundary type not known*/ + return PICOPAM_NA; + break; + }/*end switch (itemBase[1])*/ + break; /*end case PICODATA_ITEM_BOUND*/ + + case PICODATA_ITEM_SYLLPHON: + /*received a syllable item*/ + /* ------------------------------------------------------------------ + following code has to be used if we do expect + SYLL items arrive even without SBEG items starting the sentence. + this may happen after a term has been issued to make room in local storage. + */ + if (pam->nCurrSyllable == -1) { + pam_reset_processors(this); + /*insert an SBEG with sType and pType taken from previous sentence*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_PAUSE, NULL, + pam->sType, pam->pType, PICODATA_ITEMINFO1_BOUND_SBEG, + 0, 0); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_P_BOUND, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + } + /* ------------------------------------------------------------------*/ + sResult = pam_create_syllable(this, PICOPAM_SYLL_SYLL, itemBase, + pam->sType, pam->pType, 0, 0, 0); + if (sResult != PICO_OK) + return sResult; + sResult = pam_process_event(this, PICOPAM_EVENT_SYLL, + PICOPAM_DIR_FORW); + if (sResult != PICO_OK) + return sResult; + return PICOPAM_MORE; + break; + + default: + return PICOPAM_NA; + break; + } + return PICO_ERR_OTHER; +}/*pam_adapter_forward_step*/ + +/** + * performs the backward step of the PAM adapter + * @param this : pointer to PAM PU sub object pointer + * @return PICO_OK : backward step complete + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks derived in some parts from the pam forward code + * @callgraph + * @callergraph + */ +static pico_status_t pam_adapter_backward_step( + register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint8 nProcessed; + picoos_uint16 nSyll; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + /*Resets the processors for the backward step*/ + pam_reset_processors_back(this); + /*Do the backward step*/ + nSyll = pam->nCurrSyllable; + while (pam->nCurrSyllable >= 0) { + nProcessed = 0; + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] == 1) { + /*primary boundary*/ + pam_process_event(this, PICOPAM_EVENT_P_BOUND, PICOPAM_DIR_BACK); + pam->nCurrSyllable--; + nProcessed = 1; + } + if ((nProcessed == 0) + && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P3] == 1)) { + /*secondary boundary*/ + pam_process_event(this, PICOPAM_EVENT_S_BOUND, PICOPAM_DIR_BACK); + pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK); + pam->nCurrSyllable--; + nProcessed = 1; + } + if ((nProcessed == 0) + && (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P4] == 1)) { + /*word boundary*/ + pam_process_event(this, PICOPAM_EVENT_W_BOUND, PICOPAM_DIR_BACK); + pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK); + pam->nCurrSyllable--; + nProcessed = 1; + } + if (nProcessed == 0) { + /*non boundaried syllable*/ + pam_process_event(this, PICOPAM_EVENT_SYLL, PICOPAM_DIR_BACK); + pam->nCurrSyllable--; + nProcessed = 0; + } + }/*end while (pam->nCurrSyllable>=0)*/ + /*reset syllpointer to original value*/ + pam->nCurrSyllable = nSyll; + /*Perform pause processing*/ + pam_adapter_do_pauses(this); + pam->nCurrSyllable = 0; + pam->nSyllPhoneme = 0; + + return PICO_OK; +}/*pam_adapter_backward_step*/ + +/** + * processes a pause (silence) syllable after backward processing + * @param this : pointer to PAM PU sub object pointer : processes a pause (silence) syllable after backward processing + * @return PICO_OK : backward step complete + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @remarks pam->nCurrSyllable should point to a pause item + * @remarks this function should be called after backward processing + * @remarks this function corresponds to initializing silence phonemes with + * @remarks values derived from previous or following syllables + * @callgraph + * @callergraph + */ +static pico_status_t pam_do_pause(register picodata_ProcessingUnit this) +{ + picoos_uint16 syllCurr; + pam_subobj_t *pam; + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + syllCurr = pam->nCurrSyllable; + + /*processor for all features that can be inherited from previous syll (or word/phrase)*/ + if (pam->nCurrSyllable > 0) { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B3]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B8] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B8]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B10] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B10]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B12] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B12]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B14] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B14]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B17]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B19]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B20]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[B21]; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[D2] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E2]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G1] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[G2] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E5] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E5]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E7] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E7]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E9]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E11]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E12]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E13]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[E13] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[E13]; + + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H1]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H2]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H3] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H3]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H4] + = pam->sSyllFeats[pam->nCurrSyllable - 1].phoneV[H4]; + + } else { + pam->sSyllFeats[pam->nCurrSyllable].phoneV[A3] + =pam->sSyllFeats[pam->nCurrSyllable].phoneV[B8] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B10] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B12] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B14] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B17] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B19] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B20] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[B21] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E5] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E9] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E11] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[E12] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H1] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H2] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[H3] + = 0; + + /*init values different from 0*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H4] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[J3]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[H5] = PICOPAM_p; + + } + + /*processor for all features that can be inherited from next syll (or word/phrase)*/ + if (pam->nCurrSyllable < pam->nTotalSyllables - 1) { + /*non last syllable*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] + = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[B3]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] + = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[E2]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] + = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[H1]; + pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] + = pam->sSyllFeats[pam->nCurrSyllable + 1].phoneV[H2]; + } else { + /*last syllable*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[C3] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[F2] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I1] + = pam->sSyllFeats[pam->nCurrSyllable].phoneV[I2] + = 0; + } + + /*Other fixed values derived from de-facto standard*/ + pam->sSyllFeats[pam->nCurrSyllable].phoneV[B18] = 0; + + return PICO_OK; +}/*pam_do_pause*/ + +/** + * performs the initialization of pause "syllables" + * @param this : pointer to PAM PU sub object pointer : processes a pause (silence) syllable after backward processing + * @return PICO_OK : pause processing successful + * @return PICO_ERR_OTHER : errors on retrieving the PU pointer + * @callgraph + * @callergraph + */ +static pico_status_t pam_adapter_do_pauses(register picodata_ProcessingUnit this) +{ + register pam_subobj_t * pam; + picoos_uint16 nSyll; + + if (NULL == this || NULL == this->subObj) { + return PICO_ERR_OTHER; + } + pam = (pam_subobj_t *) this->subObj; + + /*Do the pause processing*/ + nSyll = pam->nCurrSyllable; + while (pam->nCurrSyllable >= 0) { + if (pam->sSyllFeats[pam->nCurrSyllable].phoneV[P2] == 1) { + /*pause processing*/ + pam_do_pause(this); + } + pam->nCurrSyllable--; + }/*end while (pam->nCurrSyllable>=0)*/ + /*reset syllpointer to original value*/ + pam->nCurrSyllable = nSyll; + return PICOPAM_READY; +}/*pam_adapter_do_pauses*/ + +#ifdef __cplusplus +} +#endif + +/* picopam.c end */ |