mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-10-31 05:35:35 +00:00
MerGe branch 'phonemelist_cleanup'
This commit is contained in:
+105
-108
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user