Browse Source

Prevent compile-phonemes use of phontab, en_dict

espeak-ng --compile-phonemes generates phontab, but during the
generation it starts by reading the old phontab.  If works just fine,
apart from an error message, if this doesn't exist but if it does exist
it is not clear whether it might end up using old or bad data (e.g.
possibly crashing if phontab is corrupted making it very non-obvious how
to fix the problem...)

The same applies to en_dict as a result of espeak-ng defaulting to the
voice 'en'; again the phontab build works if en_dict is absent but a
spurious message is output.  It's not clear what would happen if someone
tried to build a reduced espeak-ng configuration with just one (non
'en') language.

The fix is to change espeak_ng_CompilePhonemeDataPath to call LoadVoice
with a new flag to indicate the voice structure is just required to
compile phoneme data (I changed the error message as well to make it
clear where it comes from - there are two identical error messages, the
other one is in voices.c)

Within LoadVoice the flag causes LoadVoice to not set a default language
or voicename and to skip loading the old phontab or dictionary (both of
which fail in a git clean -dfx build).

I checked the result by doing a compile from-scratch build sequence with
and without the patch, i.e. I did:

git clean -dfx
./autogen.sh
./configure --prefix=a-test-directory
make
make install

Then I compared the two copies of "a-test-directory" as well as the log
file output:

$ diff -r logs/*
diff -r logs/original/make.log logs/patched/make.log
175,176d174
< Unknown phoneme table: 'en'
< Can't read dictionary file:
'/home/jbowler/src/espeak-ng/master/espeak-ng-data/en_dict'

$ diff --no-dereference -r local.original local.patched
Binary files local.original/bin/speak-ng and local.patched/bin/speak-ng differ
Binary files local.original/lib/libespeak-ng.a and local.patched/lib/libespeak-ng.a differ
Binary files local.original/lib/libespeak-ng.so.1.1.51 and local.patched/lib/libespeak-ng.so.1.1.51 differ

So the change has not altered phontab or any of the other generated
files, only the binaries as would be expected.  (Note that I am
comparing truely clean builds; what you get if you download the source
and build from scratch.  This is the standard approach for people who
build for distribution.)

Signed-off-by: John Bowler <[email protected]>
master
John Bowler 4 years ago
parent
commit
18d807d680
2 changed files with 27 additions and 10 deletions
  1. 2
    2
      src/libespeak-ng/compiledata.c
  2. 25
    8
      src/libespeak-ng/voices.c

+ 2
- 2
src/libespeak-ng/compiledata.c View File

@@ -1853,7 +1853,7 @@ static PHONEME_TAB_LIST *FindPhonemeTable(const char *string)
if (strcmp(phoneme_tab_list2[ix].name, string) == 0)
return &phoneme_tab_list2[ix];
}
error("Unknown phoneme table: '%s'", string);
error("compile: unknown phoneme table: '%s'", string);
return NULL;
}

@@ -2541,7 +2541,7 @@ espeak_ng_CompilePhonemeDataPath(long rate,

samplerate_native = samplerate = rate;
LoadPhData(NULL, NULL);
if (LoadVoice("", 0) == NULL)
if (LoadVoice("", 8/*compiling phonemes*/) == NULL)
return ENS_VOICE_NOT_FOUND;

WavegenInit(rate, 0);

+ 25
- 8
src/libespeak-ng/voices.c View File

@@ -477,6 +477,9 @@ voice_t *LoadVoice(const char *vname, int control)
// bit 1 1 = change tone only, not language
// bit 2 1 = don't report error on LoadDictionary
// bit 4 1 = vname = full path
// bit 8 1 = INTERNAL: compiling phonemes; do not try to
// load the phoneme table
// bit 16 1 = UNDOCUMENTED

FILE *f_voice = NULL;
char *p;
@@ -526,7 +529,7 @@ voice_t *LoadVoice(const char *vname, int control)
if (GetFileLength(buf) <= 0)
return NULL;
} else {
if (voicename[0] == 0)
if (voicename[0] == 0 && !(control & 8)/*compiling phonemes*/)
strcpy(voicename, ESPEAKNG_DEFAULT_VOICE);

sprintf(path_voices, "%s%cvoices%c", path_home, PATHSEP, PATHSEP);
@@ -540,7 +543,11 @@ voice_t *LoadVoice(const char *vname, int control)

f_voice = fopen(buf, "r");

language_type = "en"; // default
if (!(control & 8)/*compiling phonemes*/)
language_type = "en"; // default
else
language_type = "";

if (f_voice == NULL) {
if (control & 3)
return NULL; // can't open file
@@ -867,18 +874,28 @@ voice_t *LoadVoice(const char *vname, int control)
if (tone_only)
new_translator = translator;
else {
if ((ix = SelectPhonemeTableName(phonemes_name)) < 0) {
if (!!(control & 8/*compiling phonemes*/)) {
/* Set by espeak_ng_CompilePhonemeDataPath when it
* calls LoadVoice("", 8) to set up a dummy(?) voice.
* As phontab may not yet exist this avoids the spurious
* error message and guarantees consistent results by
* not actually reading a potentially bogus phontab...
*/
ix = 0;
} else if ((ix = SelectPhonemeTableName(phonemes_name)) < 0) {
fprintf(stderr, "Unknown phoneme table: '%s'\n", phonemes_name);
ix = 0;
}
voice->phoneme_tab_ix = ix;
new_translator->phoneme_tab_ix = ix;
new_translator->dict_min_size = dict_min;
LoadDictionary(new_translator, new_dictionary, control & 4);
if (dictionary_name[0] == 0) {
DeleteTranslator(new_translator);
return NULL; // no dictionary loaded
}
if (!(control & 8/*compiling phonemes*/)) {
LoadDictionary(new_translator, new_dictionary, control & 4);
if (dictionary_name[0] == 0) {
DeleteTranslator(new_translator);
return NULL; // no dictionary loaded
}
}

new_translator->dict_condition = conditional_rules;


Loading…
Cancel
Save