diff options
Diffstat (limited to 'navit/support/espeak/phonemelist.c')
-rw-r--r--[-rwxr-xr-x] | navit/support/espeak/phonemelist.c | 677 |
1 files changed, 331 insertions, 346 deletions
diff --git a/navit/support/espeak/phonemelist.c b/navit/support/espeak/phonemelist.c index d663e2e94..07d6fd3d7 100755..100644 --- a/navit/support/espeak/phonemelist.c +++ b/navit/support/espeak/phonemelist.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005 to 2007 by Jonathan Duddington * + * Copyright (C) 2005 to 2014 by Jonathan Duddington * * email: jonsd@users.sourceforge.net * * * * This program is free software; you can redistribute it and/or modify * @@ -38,20 +38,8 @@ extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes -static int ChangePhonemes(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) -{//================================================================================================================= -// Called for each phoneme in the phoneme list, to allow a language to make changes -// ph The current phoneme - - if(tr->translator_name == L('r','u')) - return(ChangePhonemes_ru(tr, phlist, n_ph, index, ph, ch)); - - return(0); -} - - -static int SubstitutePhonemes(Translator *tr, PHONEME_LIST2 *plist_out) -{//==================================================================== +static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) +{//=================================================================== // Copy the phonemes list and perform any substitutions that are required for the // current voice int ix; @@ -59,113 +47,47 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST2 *plist_out) int replace_flags; int n_plist_out = 0; int word_end; - int max_stress = -1; - int switched_language = 0; - int max_stress_posn=0; - int n_syllables = 0; - int syllable = 0; - int syllable_stressed = 0; PHONEME_LIST2 *plist2; - PHONEME_LIST2 *pl; PHONEME_TAB *next=NULL; for(ix=0; (ix < n_ph_list2) && (n_plist_out < N_PHONEME_LIST); ix++) { plist2 = &ph_list2[ix]; - if(plist2->phcode == phonSWITCH) - switched_language ^= 1; - // don't do any substitution if the language has been temporarily changed - if(switched_language == 0) + if(!(plist2->synthflags & SFLAG_SWITCHED_LANG)) { if(ix < (n_ph_list2 -1)) next = phoneme_tab[ph_list2[ix+1].phcode]; - + word_end = 0; if((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE))) word_end = 1; // this phoneme is the end of a word - - if(tr->langopts.phoneme_change != 0) - { - // this language does changes to phonemes after translation - int flags; - CHANGEPH ch; - if(plist2->sourceix) - { - // start of a word, find the stressed vowel - syllable = 0; - syllable_stressed = 0; - n_syllables = 0; - - max_stress = -1; - max_stress_posn = ix; - for(k=ix; k < n_ph_list2; k++) - { - if(((pl = &ph_list2[k])->sourceix != 0) && (k > ix)) - break; - - pl->stress &= 0xf; - - if(phoneme_tab[pl->phcode]->type == phVOWEL) - { - n_syllables++; - - if(pl->stress > max_stress) - { - syllable_stressed = n_syllables; - max_stress = pl->stress; - max_stress_posn = k; - } - } - } - } - if(phoneme_tab[plist2->phcode]->type == phVOWEL) - { - syllable++; - } - - // make any language specific changes - flags = 0; - if(ix == max_stress_posn) - flags |= 2; - if(ix > max_stress_posn) - flags |= 4; - if(ph_list2[ix].synthflags & SFLAG_DICTIONARY) - flags |= 8; - ch.flags = flags | word_end; - - ch.stress = plist2->stress; - ch.stress_highest = max_stress; - ch.n_vowels = n_syllables; - ch.vowel_this = syllable; - ch.vowel_stressed = syllable_stressed; - - ChangePhonemes(tr, ph_list2, n_ph_list2, ix, phoneme_tab[ph_list2[ix].phcode], &ch); - } - // check whether a Voice has specified that we should replace this phoneme for(k=0; k<n_replace_phonemes; k++) { if(plist2->phcode == replace_phonemes[k].old_ph) { replace_flags = replace_phonemes[k].type; - + if((replace_flags & 1) && (word_end == 0)) continue; // this replacement only occurs at the end of a word - - if((replace_flags & 2) && ((plist2->stress & 0x7) > 3)) + + if((replace_flags & 2) && ((plist2->stresslevel & 0x7) > 3)) continue; // this replacement doesn't occur in stressed syllables - + + if((replace_flags & 4) && (plist2->sourceix == 0)) + continue; // this replacement only occurs at the start of a word + // substitute the replacement phoneme plist2->phcode = replace_phonemes[k].new_ph; - if((plist2->stress > 1) && (phoneme_tab[plist2->phcode]->phflags & phUNSTRESSED)) - plist2->stress = 0; // the replacement must be unstressed + if((plist2->stresslevel > 1) && (phoneme_tab[plist2->phcode]->phflags & phUNSTRESSED)) + plist2->stresslevel = 0; // the replacement must be unstressed break; } } - + if(plist2->phcode == 0) { continue; // phoneme has been replaced by NULL, so don't copy it @@ -173,7 +95,10 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST2 *plist_out) } // copy phoneme into the output list - memcpy(&plist_out[n_plist_out++],plist2,sizeof(PHONEME_LIST2)); + memcpy(&plist_out[n_plist_out],plist2,sizeof(PHONEME_LIST2)); + plist_out[n_plist_out].ph = phoneme_tab[plist2->phcode]; + plist_out[n_plist_out].type = plist_out[n_plist_out].ph->type; + n_plist_out++; } return(n_plist_out); } // end of SubstitutePhonemes @@ -188,22 +113,30 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) int insert_ph = 0; PHONEME_LIST *phlist; PHONEME_TAB *ph; - PHONEME_TAB *prev, *next, *next2; + PHONEME_TAB *next, *next2; int unstress_count = 0; int word_stress = 0; - int switched_language = 0; + int current_phoneme_tab; int max_stress; int voicing; int regression; int end_sourceix; int alternative; - int first_vowel=0; // first vowel in a word - PHONEME_LIST2 ph_list3[N_PHONEME_LIST]; + int delete_count; + int word_start; + int inserted; + int deleted; + PHONEME_DATA phdata; - static PHONEME_LIST2 ph_list2_null = {0,0,0,0,0}; - PHONEME_LIST2 *plist2 = &ph_list2_null; - PHONEME_LIST2 *plist2_inserted = NULL; + int n_ph_list3; + PHONEME_LIST *plist3; + PHONEME_LIST *plist3_inserted = NULL; + PHONEME_LIST ph_list3[N_PHONEME_LIST]; + PHONEME_LIST2 *plist2; + WORD_PH_DATA worddata; + + memset(&worddata, 0, sizeof(worddata)); plist2 = ph_list2; phlist = phoneme_list; end_sourceix = plist2[n_ph_list2-1].sourceix; @@ -212,9 +145,9 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) max_stress = 0; for(j = n_ph_list2-3; j>=0; j--) { - // start with the last phoneme (before the terminating pauses) and move forwards - if((plist2[j].stress & 0x7f) > max_stress) - max_stress = plist2[j].stress & 0x7f; + // start with the last phoneme (before the terminating pauses) and move backwards + if((plist2[j].stresslevel & 0x7f) > max_stress) + max_stress = plist2[j].stresslevel & 0x7f; if(plist2[j].sourceix != 0) break; } @@ -225,10 +158,10 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) { if(plist2[j].synthflags & SFLAG_PROMOTE_STRESS) // dictionary flags indicated that this stress can be promoted { - plist2[j].stress = 4; // promote to stressed + plist2[j].stresslevel = 4; // promote to stressed break; } - if(plist2[j].stress >= 4) + if(plist2[j].stresslevel >= 4) { // found a stressed syllable, so stop looking break; @@ -236,11 +169,48 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) } } + // look for switch of phoneme tables + delete_count = 0; + current_phoneme_tab = tr->phoneme_tab_ix; + for(j = 0; j < n_ph_list2; j++) + { + if(current_phoneme_tab != tr->phoneme_tab_ix) + { + plist2[j].synthflags |= SFLAG_SWITCHED_LANG; + } + + if(delete_count > 0) + { + memcpy(&plist2[j-delete_count], &plist2[j], sizeof(plist2[0])); + } + + if(plist2[j].phcode == phonSWITCH) + { + if((!(plist2[j].synthflags & SFLAG_EMBEDDED)) && ( + (plist2[j].tone_ph == current_phoneme_tab) || + (plist2[j+1].phcode == phonSWITCH) || + ((plist2[j+1].phcode == phonPAUSE) && (plist2[j+2].phcode == phonSWITCH)) + )) + { + // delete this phonSWITCH if it's switching to the current phoneme table, or + // delete this phonSWITCH if its followed by another phonSWITCH + delete_count++; + } + else + { + current_phoneme_tab = plist2[j].tone_ph; + } + } + + } + n_ph_list2 -= delete_count; + if((regression = tr->langopts.param[LOPT_REGRESSIVE_VOICING]) != 0) { // set consonant clusters to all voiced or all unvoiced // Regressive int type; + int stop_propagation = 0; voicing = 0; for(j=n_ph_list2-1; j>=0; j--) @@ -249,43 +219,48 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) if(ph == NULL) continue; - if(ph->code == phonSWITCH) - switched_language ^= 1; - if(switched_language) + if(plist2[j].synthflags & SFLAG_SWITCHED_LANG) + { + stop_propagation = 0; + voicing = 0; + if(regression & 0x100) + voicing = 1; // word-end devoicing continue; + } type = ph->type; if(regression & 0x2) { - // LANG=Russian, [v] amd [v;] don't cause regression, or [R^] - if((ph->mnemonic == 'v') || (ph->mnemonic == ((';'<<8)+'v')) || ((ph->mnemonic & 0xff)== 'R')) - type = phLIQUID; + // [v] amd [v;] don't cause regression, or [R^] + if(((ph->mnemonic & 0xff) == 'v') || ((ph->mnemonic & 0xff)== 'R')) + { + stop_propagation = 1; + if(regression & 0x10) + voicing = 0; + } } if((type==phSTOP) || type==(phFRICATIVE)) { - if(voicing==0) + if((voicing==0) && (regression & 0xf)) { voicing = 1; } - else - if((voicing==2) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING)) + else if((voicing==2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants { - plist2[j].phcode = ph->alternative_ph; // change to voiced equivalent + plist2[j].phcode = ph->end_type; // change to voiced equivalent } } - else - if((type==phVSTOP) || type==(phVFRICATIVE)) + else if((type==phVSTOP) || type==(phVFRICATIVE)) { - if(voicing==0) + if((voicing==0) && (regression & 0xf)) { voicing = 2; } - else - if((voicing==1) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING)) + else if((voicing==1) && (ph->end_type != 0)) { - plist2[j].phcode = ph->alternative_ph; // change to unvoiced equivalent + plist2[j].phcode = ph->end_type; // change to unvoiced equivalent } } else @@ -301,234 +276,257 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) voicing = 0; } } - if((regression & 0x4) && (plist2[j].sourceix)) + if(stop_propagation) { - // stop propagation at a word boundary voicing = 0; + stop_propagation = 0; + } + + if(plist2[j].sourceix) + { + if(regression & 0x04) + { + // stop propagation at a word boundary + voicing = 0; + } + if(regression & 0x100) + { + // devoice word-final consonants, unless propagating voiced + if(voicing == 0) + { + voicing = 1; + } + } } } } - n_ph_list2 = SubstitutePhonemes(tr,ph_list3) - 2; + n_ph_list3 = SubstitutePhonemes(tr,ph_list3) - 2; + + for(j=0; (j < n_ph_list3) && (ix < N_PHONEME_LIST-3);) + { + if(ph_list3[j].sourceix) + { + // start of a word + int k; + int nextw; + word_stress = 0; + + // find the highest stress level in this word + for(nextw=j; nextw < n_ph_list3;) + { + if(ph_list3[nextw].stresslevel > word_stress) + word_stress = ph_list3[nextw].stresslevel; + + nextw++; + if(ph_list3[nextw].sourceix) + break; // start of the next word + } + for(k=j; k<nextw; k++) + { + ph_list3[k].wordstress = word_stress; + } + j = nextw; + } + else + { + j++; + } + } // transfer all the phonemes of the clause into phoneme_list ph = phoneme_tab[phonPAUSE]; - switched_language = 0; + ph_list3[0].ph = ph; + word_start = 1; - for(j=0; insert_ph || ((j < n_ph_list2) && (ix < N_PHONEME_LIST-3)); j++) + for(j=0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) { - prev = ph; - - plist2 = &ph_list3[j]; + plist3 = &ph_list3[j]; + inserted = 0; + deleted = 0; if(insert_ph != 0) { // we have a (linking) phoneme which we need to insert here - next = phoneme_tab[plist2->phcode]; // this phoneme, i.e. after the insert + next = phoneme_tab[plist3->phcode]; // this phoneme, i.e. after the insert // re-use the previous entry for the inserted phoneme. - // That's OK because we don't look backwards from plist2 + // That's OK because we don't look backwards from plist3 *** but CountVowelPosition() and isAfterStress does !!! j--; - plist2 = plist2_inserted = &ph_list3[j]; - memset(plist2, 0, sizeof(*plist2)); - plist2->phcode = insert_ph; + plist3 = plist3_inserted = &ph_list3[j]; + if(j > 0) + { + // move all previous phonemes in the word back one place + int k; + if(word_start > 0) + { + k = word_start; + word_start--; + } + else + { + k = 2; // No more space, don't loose the start of word mark at ph_list2[word_start] + } + for(; k<=j; k++) + memcpy(&ph_list3[k-1], &ph_list3[k], sizeof(*plist3)); + } + memset(&plist3[0], 0, sizeof(*plist3)); + plist3->phcode = insert_ph; ph = phoneme_tab[insert_ph]; + plist3->ph = ph; insert_ph = 0; + inserted = 1; // don't insert the same phoneme repeatedly } else { // otherwise get the next phoneme from the list - ph = phoneme_tab[plist2->phcode]; + if(plist3->sourceix != 0) + word_start = j; - if(plist2->phcode == phonSWITCH) - { - // change phoneme table - SelectPhonemeTable(plist2->tone_number); - switched_language ^= SFLAG_SWITCHED_LANG; - } - next = phoneme_tab[(plist2+1)->phcode]; // the phoneme after this one - } + ph = phoneme_tab[plist3->phcode]; + plist3[0].ph = ph; - if(plist2->sourceix) - { - // start of a word - int k; - word_stress = 0; - first_vowel = 1; - - // find the highest stress level in this word - for(k=j+1; k < n_ph_list2; k++) + if(plist3->phcode == phonSWITCH) { - if(ph_list3[k].sourceix) - break; // start of the next word - - if(ph_list3[k].stress > word_stress) - word_stress = ph_list3[k].stress; + // change phoneme table + SelectPhonemeTable(plist3->tone_ph); } + next = phoneme_tab[plist3[1].phcode]; // the phoneme after this one + plist3[1].ph = next; } if(ph == NULL) continue; - if(ph->type == phVOWEL) - { - // check for consecutive unstressed syllables - if(plist2->stress == 0) - { - // an unstressed vowel - unstress_count++; - if((unstress_count > 1) && ((unstress_count & 1)==0)) - { - // in a sequence of unstressed syllables, reduce alternate syllables to 'diminished' - // stress. But not for the last phoneme of a stressed word - if((tr->langopts.stress_flags & 0x2) || ((word_stress > 3) && ((plist2+1)->sourceix!=0))) - { - // An unstressed final vowel of a stressed word - unstress_count=1; // try again for next syllable - } - else - { - plist2->stress = 1; // change stress to 'diminished' - } - } - } - else - { - unstress_count = 0; - } - } - - alternative = 0; - - if(ph->alternative_ph > 0) - { - switch(ph->phflags & phALTERNATIVE) - { - // This phoneme changes if vowel follows, or doesn't follow, depending on its phNOTFOLLOWS flag - case phBEFORENOTVOWEL: - if(next->type != phVOWEL) - alternative = ph->alternative_ph; - break; - - case phBEFORENOTVOWEL2: // LANG=tr - if(((plist2+1)->sourceix != 0) || - ((next->type != phVOWEL) && ((phoneme_tab[(plist2+2)->phcode]->type != phVOWEL) || ((plist2+2)->sourceix != 0)))) - { - alternative = ph->alternative_ph; - } - break; - - case phBEFOREVOWELPAUSE: - if((next->type == phVOWEL) || (next->type == phPAUSE)) - alternative = ph->alternative_ph; - break; - - case phBEFOREVOWEL: - if(next->type == phVOWEL) - alternative = ph->alternative_ph; - break; + InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata); - case phBEFORE_R: - if(next->phflags & phRHOTIC) - { - alternative = ph->alternative_ph; - } - break; - } - } - if(ph->phflags & phBEFOREPAUSE) + if((alternative = phdata.pd_param[pd_CHANGE_NEXTPHONEME]) > 0) { - if(next->type == phPAUSE) - alternative = ph->link_out; // replace with the link_out phoneme + ph_list3[j+1].ph = phoneme_tab[alternative]; + ph_list3[j+1].phcode = alternative; + ph_list3[j+1].type = phoneme_tab[alternative]->type; + next = phoneme_tab[alternative]; } - if(alternative == 1) - continue; // NULL phoneme, discard - - if(alternative > 1) + if(((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0) && (inserted == 0)) { + // PROBLEM: if we insert a phoneme before a vowel then we loose the stress. PHONEME_TAB *ph2; ph2 = ph; + + insert_ph = plist3->phcode; ph = phoneme_tab[alternative]; + plist3->ph = ph; + plist3->phcode = alternative; if(ph->type == phVOWEL) { - plist2->synthflags |= SFLAG_SYLLABLE; + plist3->synthflags |= SFLAG_SYLLABLE; if(ph2->type != phVOWEL) - plist2->stress = 0; // change from non-vowel to vowel, make sure it's unstressed + plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed } else - plist2->synthflags &= ~SFLAG_SYLLABLE; - } + plist3->synthflags &= ~SFLAG_SYLLABLE; - if(tr->langopts.param[LOPT_REDUCE_T]) - { - if((ph->mnemonic == 't') && (plist2->sourceix == 0) && ((prev->type == phVOWEL) || (prev->mnemonic == 'n'))) - { - if(((plist2+1)->sourceix == 0) && ((plist2+1)->stress < 3) && (next->type == phVOWEL)) - { - ph = phoneme_tab[phonT_REDUCED]; - } - } + // re-interpret the changed phoneme + // But it doesn't obey a second ChangePhoneme() + InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata); } - - while((ph->reduce_to != 0) && (!(plist2->synthflags & SFLAG_DICTIONARY) || (tr->langopts.param[LOPT_REDUCE] & 1))) + if((alternative = phdata.pd_param[pd_CHANGEPHONEME]) > 0) { - int reduce_level; - int stress_level; - int reduce = 0; - - reduce_level = (ph->phflags >> 28) & 7; + PHONEME_TAB *ph2; + ph2 = ph; + ph = phoneme_tab[alternative]; + plist3->ph = ph; + plist3->phcode = alternative; - if(ph->type == phVOWEL) + if(alternative == 1) { - stress_level = plist2->stress; + deleted = 1; // NULL phoneme, discard } else { - // consonant, get stress from the following vowel - if(next->type == phVOWEL) - stress_level = (plist2+1)->stress; + if(ph->type == phVOWEL) + { + plist3->synthflags |= SFLAG_SYLLABLE; + if(ph2->type != phVOWEL) + plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed + } else - break; - } + plist3->synthflags &= ~SFLAG_SYLLABLE; - if((stress_level == 1) && (first_vowel)) - stress_level = 0; // ignore 'dimished' stress on first syllable - - if(stress_level == 1) - reduce = 1; // stress = 'reduced' + // re-interpret the changed phoneme + // But it doesn't obey a second ChangePhoneme() + InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata); + } + } - if(stress_level < reduce_level) - reduce =1; + if((ph->type == phVOWEL) && (deleted == 0)) + { + PHONEME_LIST *p; - if((word_stress < 4) && (tr->langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= word_stress)) + // Check for consecutive unstressed syllables, even across word boundaries. + // Do this after changing phonemes according to stress level. + if(plist3->stresslevel <= 1) { - // don't reduce the most stressed syllable in an unstressed word - reduce = 0; - } + // an unstressed vowel + unstress_count++; - if(reduce) - ph = phoneme_tab[ph->reduce_to]; + if(tr->langopts.stress_flags & 0x08) + { + // change sequences of consecutive unstressed vowels in unstressed words to diminished stress (TEST) + for(p=plist3+1; p->type != phPAUSE; p++) + { + if(p->type == phVOWEL) + { + if(p->stresslevel <= 1) + { + if(plist3->wordstress < 4) + plist3->stresslevel = 0; + if(p->wordstress < 4) + p->stresslevel = 0; + } + break; + } + } + } + else + { + if((unstress_count > 1) && ((unstress_count & 1)==0)) + { + // in a sequence of unstressed syllables, reduce alternate syllables to 'diminished' + // stress. But not for the last phoneme of a stressed word + if((tr->langopts.stress_flags & S_NO_DIM) || ((word_stress > 3) && ((plist3+1)->sourceix!=0))) + { + // An unstressed final vowel of a stressed word + unstress_count=1; // try again for next syllable + } + else + { + plist3->stresslevel = 0; // change stress to 'diminished' + } + } + } + } else - break; + { + unstress_count = 0; + } } - if(ph->type == phVOWEL) - first_vowel = 0; - - if((plist2+1)->synthflags & SFLAG_LENGTHEN) + if((plist3+1)->synthflags & SFLAG_LENGTHEN) { static char types_double[] = {phFRICATIVE,phVFRICATIVE,phNASAL,phLIQUID,0}; - if(strchr(types_double,next->type)) + if((j > 0) && (strchr(types_double,next->type))) { // lengthen this consonant by doubling it + // BUT, can't insert a phoneme at position plist3[0] because it crashes PrevPh() insert_ph = next->code; - (plist2+1)->synthflags ^= SFLAG_LENGTHEN; + (plist3+1)->synthflags ^= SFLAG_LENGTHEN; } } - if((plist2+1)->sourceix != 0) + if((plist3+1)->sourceix != 0) { int x; @@ -551,7 +549,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) else insert_ph = phonPAUSE_VSHORT; } - + if((ph->type == phVOWEL) && ((x = tr->langopts.vowel_pause & 0x03) != 0)) { // adjacent vowels over a word boundary @@ -560,8 +558,8 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) else insert_ph = phonPAUSE_VSHORT; } - - if(((plist2+1)->stress >= 4) && (tr->langopts.vowel_pause & 0x100)) + + if(((plist3+1)->stresslevel >= 4) && (tr->langopts.vowel_pause & 0x100)) { // pause before a words which starts with a stressed vowel insert_ph = phonPAUSE_SHORT; @@ -569,7 +567,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) } } - if(plist2 != plist2_inserted) + if((plist3 != plist3_inserted) && (ix > 0)) { if((x = (tr->langopts.word_gap & 0x7)) != 0) { @@ -586,33 +584,12 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) } } - next2 = phoneme_tab[(plist2+2)->phcode]; + next2 = phoneme_tab[plist3[2].phcode]; + plist3[2].ph = next2; - if((insert_ph == 0) && (ph->link_out != 0) && !(ph->phflags & phBEFOREPAUSE) && (((plist2+1)->synthflags & SFLAG_EMBEDDED)==0)) + if((insert_ph == 0) && (phdata.pd_param[pd_APPENDPHONEME] != 0)) { - if(ph->phflags & phAPPENDPH) - { - // always append the specified phoneme, unless it already is the next phoneme - if((ph->link_out != (plist2+1)->phcode) && (next->type == phVOWEL)) -// if(ph->link_out != (plist2+1)->phcode) - { - insert_ph = ph->link_out; - } - } - else - if(((tr->langopts.word_gap & 8)==0) || ((plist2+1)->sourceix == 0)) - { - // This phoneme can be linked to a following vowel by inserting a linking phoneme - if(next->type == phVOWEL) - insert_ph = ph->link_out; - else - if(next->code == phonPAUSE_SHORT) - { - // Pause followed by Vowel, replace the Short Pause with the linking phoneme, - if(next2->type == phVOWEL) - (plist2+1)->phcode = ph->link_out; // replace pause by linking phoneme - } - } + insert_ph = phdata.pd_param[pd_APPENDPHONEME]; } if(ph->phflags & phVOICED) @@ -623,62 +600,70 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) // not yet implemented } - phlist[ix].ph = ph; - phlist[ix].type = ph->type; - phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module - phlist[ix].synthflags = plist2->synthflags | switched_language; - phlist[ix].stresslevel = plist2->stress & 0xf; - phlist[ix].tone_ph = plist2->tone_number; - phlist[ix].sourceix = 0; - - if(plist2->sourceix != 0) + if(deleted == 0) { - phlist[ix].sourceix = plist2->sourceix; - phlist[ix].newword = 1; // this phoneme is the start of a word + phlist[ix].ph = ph; + phlist[ix].type = ph->type; + phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module + phlist[ix].synthflags = plist3->synthflags; + phlist[ix].stresslevel = plist3->stresslevel & 0xf; + phlist[ix].wordstress = plist3->wordstress; + phlist[ix].tone_ph = plist3->tone_ph; + phlist[ix].sourceix = 0; + phlist[ix].phcode = ph->code; + + if(plist3->sourceix != 0) + { + phlist[ix].sourceix = plist3->sourceix; + phlist[ix].newword = 1; // this phoneme is the start of a word - if(start_sentence) + if(start_sentence) + { + phlist[ix].newword = 5; // start of sentence + start of word + start_sentence = 0; + } + } + else { - phlist[ix].newword = 5; // start of sentence + start of word - start_sentence = 0; + phlist[ix].newword = 0; } - } - else - { - phlist[ix].newword = 0; - } - phlist[ix].length = ph->std_length; - if((ph->code == phonPAUSE_LONG) && (option_wordgap > 0)) - { - phlist[ix].ph = phoneme_tab[phonPAUSE_SHORT]; - phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed - } + // phlist[ix].length = ph->std_length; + phlist[ix].length = phdata.pd_param[i_SET_LENGTH]*2; + if((ph->code == phonPAUSE_LONG) && (option_wordgap > 0) && (plist3[1].sourceix != 0)) + { + phlist[ix].ph = phoneme_tab[phonPAUSE_SHORT]; + phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed + } - if(ph->type==phVOWEL || ph->type==phLIQUID || ph->type==phNASAL || ph->type==phVSTOP || ph->type==phVFRICATIVE) - { - phlist[ix].length = 128; // length_mod - phlist[ix].env = PITCHfall; - } + if(ph->type==phVOWEL || ph->type==phLIQUID || ph->type==phNASAL || ph->type==phVSTOP || ph->type==phVFRICATIVE || (ph->phflags & phPREVOICE)) + { + phlist[ix].length = 128; // length_mod + phlist[ix].env = PITCHfall; + } - phlist[ix].prepause = 0; - phlist[ix].amp = 20; // default, will be changed later - phlist[ix].pitch1 = 0x400; - phlist[ix].pitch2 = 0x400; - ix++; + phlist[ix].prepause = 0; + phlist[ix].amp = 20; // default, will be changed later + phlist[ix].pitch1 = 255; + phlist[ix].pitch2 = 255; + ix++; + } } phlist[ix].newword = 2; // end of clause - phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes + phlist[ix].phcode = phonPAUSE; + phlist[ix].type = phPAUSE; // terminate with 2 Pause phonemes phlist[ix].length = post_pause; // length of the pause, depends on the punctuation phlist[ix].sourceix = end_sourceix; phlist[ix].synthflags = 0; + phlist[ix++].ph = phoneme_tab[phonPAUSE]; - phlist[ix++].ph = phoneme_tab[phonPAUSE]; - phlist[ix].type = phPAUSE; + phlist[ix].phcode = phonPAUSE; + phlist[ix].type = phPAUSE; phlist[ix].length = 0; phlist[ix].sourceix=0; phlist[ix].synthflags = 0; - phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT]; + phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT]; n_phoneme_list = ix; } // end of MakePhonemeList |