Browse Source

Avoid underflowing ph_list3 (#2082)

master
Samuel Thibault 5 months ago
parent
commit
8afe77ba8e
No account linked to committer's email address

+ 1
- 1
src/libespeak-ng/dictionary.c View File

@@ -468,7 +468,7 @@ char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int
if (plist == NULL)
InterpretPhoneme2(ph->code, &phdata);
else
InterpretPhoneme(NULL, 0, plist, &phdata, NULL);
InterpretPhoneme(NULL, 0, plist, plist, &phdata, NULL);

p = phdata.ipa_string;
if (*p == 0x20) {

+ 6
- 6
src/libespeak-ng/phonemelist.c View File

@@ -41,7 +41,7 @@
#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 void ReInterpretPhoneme(PHONEME_TAB *ph, PHONEME_TAB *ph2, PHONEME_LIST *plist3, PHONEME_LIST *plist3_start, 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
@@ -296,7 +296,7 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence)

if (ph == NULL) continue;

InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata);
InterpretPhoneme(tr, 0x100, plist3, ph_list3, &phdata, &worddata);

if ((alternative = phdata.pd_param[pd_CHANGE_NEXTPHONEME]) > 0) {
ph_list3[j+1].ph = phoneme_tab[alternative];
@@ -315,7 +315,7 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence)
plist3->ph = ph;
plist3->phcode = alternative;

ReInterpretPhoneme(ph, ph2, plist3, tr, &phdata, &worddata);
ReInterpretPhoneme(ph, ph2, plist3, ph_list3, tr, &phdata, &worddata);
}

if ((alternative = phdata.pd_param[pd_CHANGEPHONEME]) > 0) {
@@ -328,7 +328,7 @@ void MakePhonemeList(Translator *tr, int post_pause, bool start_sentence)
if (alternative == 1)
deleted = true; // NULL phoneme, discard
else {
ReInterpretPhoneme(ph, ph2, plist3, tr, &phdata, &worddata);
ReInterpretPhoneme(ph, ph2, plist3, ph_list3, tr, &phdata, &worddata);
}
}

@@ -579,7 +579,7 @@ static void SetRegressiveVoicing(int regression, PHONEME_LIST2 *plist2, PHONEME_
}
}

static void ReInterpretPhoneme(PHONEME_TAB *ph, PHONEME_TAB *ph2, PHONEME_LIST *plist3, Translator *tr, PHONEME_DATA *phdata, WORD_PH_DATA *worddata) {
static void ReInterpretPhoneme(PHONEME_TAB *ph, PHONEME_TAB *ph2, PHONEME_LIST *plist3, PHONEME_LIST *plist3_start, Translator *tr, PHONEME_DATA *phdata, WORD_PH_DATA *worddata) {
if (ph->type == phVOWEL) {
plist3->synthflags |= SFLAG_SYLLABLE;
if (ph2->type != phVOWEL)
@@ -589,5 +589,5 @@ if (ph->type == phVOWEL) {

// re-interpret the changed phoneme
// But it doesn't obey a second ChangePhoneme()
InterpretPhoneme(tr, 0x100, plist3, phdata, worddata);
InterpretPhoneme(tr, 0x100, plist3, plist3_start, phdata, worddata);
}

+ 3
- 3
src/libespeak-ng/synth_mbrola.c View File

@@ -479,7 +479,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, bool resume, FILE *f_mb

if (released == false)
p->synthflags |= SFLAG_NEXT_PAUSE;
InterpretPhoneme(NULL, 0, p, &phdata, NULL);
InterpretPhoneme(NULL, 0, p, plist, &phdata, NULL);
len = DoSample3(&phdata, 0, -1);

len = (len * 1000)/samplerate; // convert to mS
@@ -490,7 +490,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, bool resume, FILE *f_mb
break;
case phFRICATIVE:
len = 0;
InterpretPhoneme(NULL, 0, p, &phdata, NULL);
InterpretPhoneme(NULL, 0, p, plist, &phdata, NULL);
if (p->synthflags & SFLAG_LENGTHEN)
len = DoSample3(&phdata, p->length, -1); // play it twice for [s:] etc.
len += DoSample3(&phdata, p->length, -1);
@@ -500,7 +500,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, bool resume, FILE *f_mb
case phNASAL:
if (next->type != phVOWEL) {
memset(&fmtp, 0, sizeof(fmtp));
InterpretPhoneme(NULL, 0, p, &phdata, NULL);
InterpretPhoneme(NULL, 0, p, plist, &phdata, NULL);
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
len = DoSpect2(p->ph, 0, &fmtp, p, -1);
len = (len * 1000)/samplerate;

+ 16
- 8
src/libespeak-ng/synthdata.c View File

@@ -451,21 +451,21 @@ static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition,

}

static int CountVowelPosition(PHONEME_LIST *plist)
static int CountVowelPosition(PHONEME_LIST *plist, PHONEME_LIST *plist_start)
{
int count = 0;

for (;;) {
if (plist->ph->type == phVOWEL)
count++;
if (plist->sourceix != 0)
if (plist->sourceix != 0 || plist == plist_start)
break;
plist--;
}
return count;
}

static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, unsigned short *p_prog, WORD_PH_DATA *worddata)
static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_LIST *plist_start, unsigned short *p_prog, WORD_PH_DATA *worddata)
{
unsigned int data;
int instn;
@@ -515,6 +515,8 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist,
{
case 0: // prevPh
case 5: // prevPhW
if (plist < plist_start+1)
return false;
plist--;
check_endtype = true;
break;
@@ -553,6 +555,8 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist,
plist = &plist[3];
break;
case 10: // prev2PhW
if (plist < plist_start + 2)
return false;
if ((plist[0].sourceix) || (plist[-1].sourceix))
return false;
plist -= 2;
@@ -562,6 +566,8 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist,

if ((which == 0) || (which == 5)) {
if (plist->phcode == 1) {
if (plist <= plist_start)
return false;
// This is a NULL phoneme, a phoneme has been deleted so look at the previous phoneme
plist--;
}
@@ -614,6 +620,8 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist,
if (plist->sourceix != 0)
return false;
do {
if (plist <= plist_start)
return false;
plist--;
if ((plist->stresslevel & 0xf) >= 4)
return true;
@@ -633,9 +641,9 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist,
case isVoiced:
return (ph->type == phVOWEL) || (ph->type == phLIQUID) || (ph->phflags & phVOICED);
case isFirstVowel:
return CountVowelPosition(plist) == 1;
return CountVowelPosition(plist, plist_start) == 1;
case isSecondVowel:
return CountVowelPosition(plist) == 2;
return CountVowelPosition(plist, plist_start) == 2;
case isTranslationGiven:
return (plist->synthflags & SFLAG_DICTIONARY) != 0;
}
@@ -733,7 +741,7 @@ static int NumInstnWords(unsigned short *prog)
}
}

void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata)
void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_LIST *plist_start, PHONEME_DATA *phdata, WORD_PH_DATA *worddata)
{
// control:
// bit 0: PreVoicing
@@ -839,7 +847,7 @@ void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_
truth = true;
while ((instn & 0xe000) == 0x2000) {
// process a sequence of conditions, using boolean accumulator
truth2 = InterpretCondition(tr, control, plist, prog, worddata);
truth2 = InterpretCondition(tr, control, plist, plist_start, prog, worddata);
prog += NumInstnWords(prog);
if (*prog == i_NOT) {
truth2 = truth2 ^ 1;
@@ -986,5 +994,5 @@ void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata)
plist[1].ph = phoneme_tab[phcode];
plist[2].sourceix = 1;

InterpretPhoneme(NULL, 0, &plist[1], phdata, NULL);
InterpretPhoneme(NULL, 0, &plist[1], plist, phdata, NULL);
}

+ 1
- 0
src/libespeak-ng/synthdata.h View File

@@ -34,6 +34,7 @@ extern "C"
void InterpretPhoneme(Translator *tr,
int control,
PHONEME_LIST *plist,
PHONEME_LIST *plist_start,
PHONEME_DATA *phdata,
WORD_PH_DATA *worddata);


+ 11
- 11
src/libespeak-ng/synthesize.c View File

@@ -1256,7 +1256,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)
if (ph->phflags & phPREVOICE) {
// a period of voicing before the release
memset(&fmtp, 0, sizeof(fmtp));
InterpretPhoneme(NULL, 0x01, p, &phdata, &worddata);
InterpretPhoneme(NULL, 0x01, p, phoneme_list, &phdata, &worddata);
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];

@@ -1268,12 +1268,12 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)
DoSpect2(ph, 0, &fmtp, p, 0);
}

InterpretPhoneme(NULL, 0, p, &phdata, &worddata);
InterpretPhoneme(NULL, 0, p, phoneme_list, &phdata, &worddata);
phdata.pd_control |= pd_DONTLENGTHEN;
DoSample3(&phdata, 0, 0);
break;
case phFRICATIVE:
InterpretPhoneme(NULL, 0, p, &phdata, &worddata);
InterpretPhoneme(NULL, 0, p, phoneme_list, &phdata, &worddata);

if (p->synthflags & SFLAG_LENGTHEN)
DoSample3(&phdata, p->length, 0); // play it twice for [s:] etc.
@@ -1302,7 +1302,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)

if ((prev->type == phVOWEL) || (ph->phflags & phPREVOICE)) {
// a period of voicing before the release
InterpretPhoneme(NULL, 0x01, p, &phdata, &worddata);
InterpretPhoneme(NULL, 0x01, p, phoneme_list, &phdata, &worddata);
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];

@@ -1321,7 +1321,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)
StartSyllable();
} else
p->synthflags |= SFLAG_NEXT_PAUSE;
InterpretPhoneme(NULL, 0, p, &phdata, &worddata);
InterpretPhoneme(NULL, 0, p, phoneme_list, &phdata, &worddata);
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
fmtp.wav_addr = phdata.sound_addr[pd_ADDWAV];
@@ -1353,7 +1353,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)
StartSyllable();
else
p->synthflags |= SFLAG_NEXT_PAUSE;
InterpretPhoneme(NULL, 0, p, &phdata, &worddata);
InterpretPhoneme(NULL, 0, p, phoneme_list, &phdata, &worddata);
memset(&fmtp, 0, sizeof(fmtp));
fmtp.std_length = phdata.pd_param[i_SET_LENGTH]*2;
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
@@ -1375,7 +1375,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)
if (prev->type == phNASAL)
last_frame = NULL;

InterpretPhoneme(NULL, 0, p, &phdata, &worddata);
InterpretPhoneme(NULL, 0, p, phoneme_list, &phdata, &worddata);
fmtp.std_length = phdata.pd_param[i_SET_LENGTH]*2;
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
fmtp.fmt_amp = phdata.sound_param[pd_FMT];
@@ -1408,7 +1408,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)

if (next->type == phVOWEL)
StartSyllable();
InterpretPhoneme(NULL, 0, p, &phdata, &worddata);
InterpretPhoneme(NULL, 0, p, phoneme_list, &phdata, &worddata);

if ((value = (phdata.pd_param[i_PAUSE_BEFORE] - p->prepause)) > 0)
DoPause(value, 1);
@@ -1425,7 +1425,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)

memset(&fmtp, 0, sizeof(fmtp));

InterpretPhoneme(NULL, 0, p, &phdata, &worddata);
InterpretPhoneme(NULL, 0, p, phoneme_list, &phdata, &worddata);
fmtp.std_length = phdata.pd_param[i_SET_LENGTH] * 2;
vowelstart_prev = 0;

@@ -1434,7 +1434,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)
fmtp.fmt_length = phdata.sound_param[pd_VWLSTART];
} else if (prev->type != phPAUSE) {
// check the previous phoneme
InterpretPhoneme(NULL, 0, prev, &phdata_prev, NULL);
InterpretPhoneme(NULL, 0, prev, phoneme_list, &phdata_prev, NULL);
if (((fmtp.fmt_addr = phdata_prev.sound_addr[pd_VWLSTART]) != 0) && (phdata_prev.pd_control & pd_FORNEXTPH)) {
// a vowel start has been specified by the previous phoneme
vowelstart_prev = 1;
@@ -1509,7 +1509,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, bool resume)
fmtp.fmt2_lenadj = phdata.sound_param[pd_VWLEND];
else if (next->type != phPAUSE) {
fmtp.fmt2_lenadj = 0;
InterpretPhoneme(NULL, 0, next, &phdata_next, NULL);
InterpretPhoneme(NULL, 0, next, phoneme_list, &phdata_next, NULL);

fmtp.use_vowelin = 1;
fmtp.transition0 = phdata_next.vowel_transition[2]; // always do vowel_transition, even if ph_VWLEND ?? consider [N]

+ 1
- 1
tests/ssml/badly-escaped1.expected View File

@@ -1 +1 @@
kəmpˈa͡ɪl ænd flˈæʃ lˈɪnɪɪd͡ʒ ˈændɹɔ͡ɪd ˌo͡ʊˈɛs
kəmpˈa͡ɪl ænd flˈæʃ lˈɪnɪʲɪd͡ʒ ˈændɹɔ͡ɪd ˌo͡ʊˈɛs

+ 1
- 1
tests/ssml/spec-example-1.expected View File

@@ -3,7 +3,7 @@
juː hæv fˈɔː͡ɹ nˈuː mˈɛsɪd͡ʒᵻz

ðə fˈɜːst ɪz fɹʌm stˈɛfəni wˈɪljəmz ænd ɚɹˈa͡ɪvd æt
θɹˈiː fˈɔː͡ɹɾi fˈa͡ɪv pˌiːˈɛm
θɹˈiː fˈɔː͡ɹɾi fˈa͡ɪv pˌiːʲˈɛm

ðə sˈʌbd͡ʒɛkt ɪz skˈiː tɹˈɪp


Loading…
Cancel
Save