diff --git a/src/libespeak-ng/phonemelist.c b/src/libespeak-ng/phonemelist.c index e11110e7..16346e4f 100644 --- a/src/libespeak-ng/phonemelist.c +++ b/src/libespeak-ng/phonemelist.c @@ -40,6 +40,9 @@ #include "translate.h" #include "speech.h" +static void SetRegressiveVoicing(int regression, PHONEME_LIST2 *plist2, PHONEME_TAB *ph, Translator *tr); +static void ReInterpretPhoneme(PHONEME_TAB *ph, PHONEME_TAB *ph2, PHONEME_LIST *plist3, Translator *tr, PHONEME_DATA *phdata, WORD_PH_DATA *worddata); + static const unsigned char pause_phonemes[8] = { 0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG }; @@ -122,20 +125,16 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) int j; int insert_ph = 0; PHONEME_LIST *phlist; - PHONEME_TAB *ph; - PHONEME_TAB *next, *next2; + PHONEME_TAB *ph = NULL; + PHONEME_TAB *next; int unstress_count = 0; int word_stress = 0; int current_phoneme_tab; int max_stress; - int voicing; - int regression; int end_sourceix; int alternative; int delete_count; int word_start; - bool inserted; - bool deleted; PHONEME_DATA phdata; bool start_of_clause = true; @@ -212,83 +211,9 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) SelectPhonemeTable(current_phoneme_tab); + int regression; if ((regression = tr->langopts.param[LOPT_REGRESSIVE_VOICING]) != 0) { - // set consonant clusters to all voiced or all unvoiced - // Regressive - int type; - bool stop_propagation = false; - voicing = 0; - - for (j = n_ph_list2-1; j >= 0; j--) { - if (plist2[j].phcode == phonSWITCH) { - /* Find previous phonSWITCH to determine language we're switching back to */ - int k; - for (k = j-1; k >= 0; k--) - if (plist2[k].phcode == phonSWITCH) - break; - if (k >= 0) - SelectPhonemeTable(plist2[k].tone_ph); - else - SelectPhonemeTable(tr->phoneme_tab_ix); - } - ph = phoneme_tab[plist2[j].phcode]; - if (ph == NULL) - continue; - - if (plist2[j].synthflags & SFLAG_SWITCHED_LANG) { - stop_propagation = false; - voicing = 0; - if (regression & 0x100) - voicing = 1; // word-end devoicing - continue; - } - - type = ph->type; - - if (regression & 0x2) { - // [v] amd [v;] don't cause regression, or [R^] - if (((ph->mnemonic & 0xff) == 'v') || ((ph->mnemonic & 0xff) == 'R')) { - stop_propagation = true; - if (regression & 0x10) - voicing = 0; - } - } - - if ((type == phSTOP) || type == (phFRICATIVE)) { - if ((voicing == 0) && (regression & 0xf)) - voicing = 1; - else if ((voicing == 2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants - plist2[j].phcode = ph->end_type; // change to voiced equivalent - } else if ((type == phVSTOP) || type == (phVFRICATIVE)) { - if ((voicing == 0) && (regression & 0xf)) - voicing = 2; - else if ((voicing == 1) && (ph->end_type != 0)) - plist2[j].phcode = ph->end_type; // change to unvoiced equivalent - } else { - if (regression & 0x8) { - // LANG=Polish, propagate through liquids and nasals - if ((type == phPAUSE) || (type == phVOWEL)) - voicing = 0; - } else - voicing = 0; - } - if (stop_propagation) { - voicing = 0; - stop_propagation = false; - } - - 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; - } - } - } + SetRegressiveVoicing(regression, plist2, ph, tr); } SelectPhonemeTable(tr->phoneme_tab_ix); @@ -326,8 +251,8 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) for (j = 0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) { plist3 = &ph_list3[j]; - inserted = false; - deleted = false; + bool inserted = false; + bool deleted = false; if (insert_ph != 0) { // we have a (linking) phoneme which we need to insert here next = phoneme_tab[plist3->phcode]; // this phoneme, i.e. after the insert @@ -390,16 +315,7 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) plist3->ph = ph; plist3->phcode = alternative; - 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 - plist3->synthflags &= ~SFLAG_SYLLABLE; - - // re-interpret the changed phoneme - // But it doesn't obey a second ChangePhoneme() - InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata); + ReInterpretPhoneme(ph, ph2, plist3, tr, &phdata, &worddata); } if ((alternative = phdata.pd_param[pd_CHANGEPHONEME]) > 0) { @@ -412,22 +328,11 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) if (alternative == 1) deleted = true; // NULL phoneme, discard else { - 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 - plist3->synthflags &= ~SFLAG_SYLLABLE; - - // re-interpret the changed phoneme - // But it doesn't obey a second ChangePhoneme() - InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata); + ReInterpretPhoneme(ph, ph2, plist3, tr, &phdata, &worddata); } } if ((ph->type == phVOWEL) && (deleted == false)) { - PHONEME_LIST *p; - // Check for consecutive unstressed syllables, even across word boundaries. // Do this after changing phonemes according to stress level. if (plist3->stresslevel <= 1) { @@ -436,6 +341,7 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) if (tr->langopts.stress_flags & 0x08) { // change sequences of consecutive unstressed vowels in unstressed words to diminished stress (TEST) + PHONEME_LIST *p; for (p = plist3+1; p->type != phPAUSE; p++) { if (p->type == phVOWEL) { if (p->stresslevel <= 1) { @@ -518,8 +424,7 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) } } - next2 = phoneme_tab[plist3[2].phcode]; - plist3[2].ph = next2; + plist3[2].ph = phoneme_tab[plist3[2].phcode]; if ((insert_ph == 0) && (phdata.pd_param[pd_APPENDPHONEME] != 0)) insert_ph = phdata.pd_param[pd_APPENDPHONEME]; @@ -594,3 +499,95 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence) SelectPhonemeTable(tr->phoneme_tab_ix); } + +static void SetRegressiveVoicing(int regression, PHONEME_LIST2 *plist2, PHONEME_TAB *ph, Translator *tr) { + // set consonant clusters to all voiced or all unvoiced + // Regressive + int type; + bool stop_propagation = false; + int voicing = 0; + + for (int j = n_ph_list2-1; j >= 0; j--) { + if (plist2[j].phcode == phonSWITCH) { + /* Find previous phonSWITCH to determine language we're switching back to */ + int k; + for (k = j-1; k >= 0; k--) + if (plist2[k].phcode == phonSWITCH) + break; + if (k >= 0) + SelectPhonemeTable(plist2[k].tone_ph); + else + SelectPhonemeTable(tr->phoneme_tab_ix); + } + ph = phoneme_tab[plist2[j].phcode]; + if (ph == NULL) + continue; + + if (plist2[j].synthflags & SFLAG_SWITCHED_LANG) { + stop_propagation = false; + voicing = 0; + if (regression & 0x100) + voicing = 1; // word-end devoicing + continue; + } + + type = ph->type; + + if (regression & 0x2) { + // [v] amd [v;] don't cause regression, or [R^] + if (((ph->mnemonic & 0xff) == 'v') || ((ph->mnemonic & 0xff) == 'R')) { + stop_propagation = true; + if (regression & 0x10) + voicing = 0; + } + } + + if ((type == phSTOP) || type == (phFRICATIVE)) { + if ((voicing == 0) && (regression & 0xf)) + voicing = 1; + else if ((voicing == 2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants + plist2[j].phcode = ph->end_type; // change to voiced equivalent + } else if ((type == phVSTOP) || type == (phVFRICATIVE)) { + if ((voicing == 0) && (regression & 0xf)) + voicing = 2; + else if ((voicing == 1) && (ph->end_type != 0)) + plist2[j].phcode = ph->end_type; // change to unvoiced equivalent + } else { + if (regression & 0x8) { + // LANG=Polish, propagate through liquids and nasals + if ((type == phPAUSE) || (type == phVOWEL)) + voicing = 0; + } else + voicing = 0; + } + if (stop_propagation) { + voicing = 0; + stop_propagation = false; + } + + 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; + } + } + } + } + +static void ReInterpretPhoneme(PHONEME_TAB *ph, PHONEME_TAB *ph2, PHONEME_LIST *plist3, Translator *tr, PHONEME_DATA *phdata, WORD_PH_DATA *worddata) { +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 + plist3->synthflags &= ~SFLAG_SYLLABLE; + + // re-interpret the changed phoneme + // But it doesn't obey a second ChangePhoneme() + InterpretPhoneme(tr, 0x100, plist3, phdata, worddata); +} \ No newline at end of file