mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-03 06:12:55 +00:00
Merge branch 'master' into android
This commit is contained in:
+219
-161
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 to 2010 by Jonathan Duddington *
|
||||
* Copyright (C) 2005 to 2013 by Jonathan Duddington *
|
||||
* email: jonsd@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -48,7 +48,8 @@ MNEM_TAB genders [] = {
|
||||
{"unknown", 0},
|
||||
{"male", 1},
|
||||
{"female", 2},
|
||||
{NULL, 0 }};
|
||||
{NULL, 0 }
|
||||
};
|
||||
|
||||
int tone_points[12] = {600,170, 1200,135, 2000,110, 3000,110, -1,0};
|
||||
//int tone_points[12] = {250,200, 400,170, 600,170, 1200,135, 2000,110, -1,0};
|
||||
@@ -62,7 +63,7 @@ int formant_rate[9]; // values adjusted for actual sample rate
|
||||
|
||||
|
||||
#define DEFAULT_LANGUAGE_PRIORITY 5
|
||||
#define N_VOICES_LIST 200
|
||||
#define N_VOICES_LIST 250
|
||||
static int n_voices_list = 0;
|
||||
static espeak_VOICE *voices_list[N_VOICES_LIST];
|
||||
static int len_path_voices;
|
||||
@@ -99,6 +100,7 @@ enum {
|
||||
V_STRESSADD,
|
||||
V_DICTRULES,
|
||||
V_STRESSRULE,
|
||||
V_STRESSOPT,
|
||||
V_CHARSET,
|
||||
V_NUMBERS,
|
||||
V_OPTION,
|
||||
@@ -107,6 +109,7 @@ enum {
|
||||
V_KLATT,
|
||||
V_FAST,
|
||||
V_SPEED,
|
||||
V_DICTMIN,
|
||||
|
||||
// these need a phoneme table to have been specified
|
||||
V_REPLACE,
|
||||
@@ -118,7 +121,8 @@ enum {
|
||||
static MNEM_TAB options_tab[] = {
|
||||
{"reduce_t", LOPT_REDUCE_T},
|
||||
{"bracket", LOPT_BRACKET_PAUSE},
|
||||
{NULL, -1} };
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
static MNEM_TAB keyword_tab[] = {
|
||||
{"name", V_NAME},
|
||||
@@ -128,7 +132,7 @@ static MNEM_TAB keyword_tab[] = {
|
||||
{"formant", V_FORMANT},
|
||||
{"pitch", V_PITCH},
|
||||
{"phonemes", V_PHONEMES},
|
||||
{"translator", V_TRANSLATOR},
|
||||
{"translator", V_TRANSLATOR},
|
||||
{"dictionary", V_DICTIONARY},
|
||||
{"stressLength", V_STRESSLENGTH},
|
||||
{"stressAmp", V_STRESSAMP},
|
||||
@@ -137,6 +141,7 @@ static MNEM_TAB keyword_tab[] = {
|
||||
{"tunes", V_TUNES},
|
||||
{"dictrules", V_DICTRULES},
|
||||
{"stressrule", V_STRESSRULE},
|
||||
{"stressopt", V_STRESSOPT},
|
||||
{"charset", V_CHARSET},
|
||||
{"replace", V_REPLACE},
|
||||
{"words", V_WORDGAP},
|
||||
@@ -155,6 +160,7 @@ static MNEM_TAB keyword_tab[] = {
|
||||
{"klatt", V_KLATT},
|
||||
{"fast_test2", V_FAST},
|
||||
{"speed", V_SPEED},
|
||||
{"dict_min", V_DICTMIN},
|
||||
|
||||
// these just set a value in langopts.param[]
|
||||
{"l_dieresis", 0x100+LOPT_DIERESES},
|
||||
@@ -165,7 +171,8 @@ static MNEM_TAB keyword_tab[] = {
|
||||
{"l_sonorant_min", 0x100+LOPT_SONORANT_MIN},
|
||||
{"l_length_mods", 0x100+LOPT_LENGTH_MODS},
|
||||
{"apostrophe", 0x100+LOPT_APOSTROPHE},
|
||||
{NULL, 0} };
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
#define N_VOICE_VARIANTS 12
|
||||
const char variants_either[N_VOICE_VARIANTS] = {1,2,12,3,13,4,14,5,11,0};
|
||||
@@ -186,6 +193,12 @@ static char *fgets_strip(char *buf, int size, FILE *f_in)
|
||||
if(fgets(buf,size,f_in) == NULL)
|
||||
return(NULL);
|
||||
|
||||
if(buf[0] == '#')
|
||||
{
|
||||
buf[0] = 0;
|
||||
return(buf);
|
||||
}
|
||||
|
||||
len = strlen(buf);
|
||||
while((--len > 0) && isspace(buf[len]))
|
||||
buf[len] = 0;
|
||||
@@ -259,9 +272,9 @@ void ReadTonePoints(char *string, int *tone_pts)
|
||||
tone_pts[ix] = -1;
|
||||
|
||||
sscanf(string,"%d %d %d %d %d %d %d %d %d %d",
|
||||
&tone_pts[0],&tone_pts[1],&tone_pts[2],&tone_pts[3],
|
||||
&tone_pts[4],&tone_pts[5],&tone_pts[6],&tone_pts[7],
|
||||
&tone_pts[8],&tone_pts[9]);
|
||||
&tone_pts[0],&tone_pts[1],&tone_pts[2],&tone_pts[3],
|
||||
&tone_pts[4],&tone_pts[5],&tone_pts[6],&tone_pts[7],
|
||||
&tone_pts[8],&tone_pts[9]);
|
||||
}
|
||||
|
||||
|
||||
@@ -315,8 +328,7 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*lea
|
||||
while(isspace(*p)) p++;
|
||||
strncpy0(vname,p,sizeof(vname));
|
||||
}
|
||||
else
|
||||
if(memcmp(linebuf,"language",8)==0)
|
||||
else if(memcmp(linebuf,"language",8)==0)
|
||||
{
|
||||
priority = DEFAULT_LANGUAGE_PRIORITY;
|
||||
vlanguage[0] = 0;
|
||||
@@ -333,13 +345,11 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*lea
|
||||
n_languages++;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(memcmp(linebuf,"gender",6)==0)
|
||||
else if(memcmp(linebuf,"gender",6)==0)
|
||||
{
|
||||
sscanf(&linebuf[6],"%s %d",vgender,&age);
|
||||
}
|
||||
else
|
||||
if(memcmp(linebuf,"variants",8)==0)
|
||||
else if(memcmp(linebuf,"variants",8)==0)
|
||||
{
|
||||
sscanf(&linebuf[8],"%d",&n_variants);
|
||||
}
|
||||
@@ -386,8 +396,10 @@ void VoiceReset(int tone_only)
|
||||
// Set voice to the default values
|
||||
|
||||
int pk;
|
||||
static unsigned char default_heights[N_PEAKS] = {128,128,120,120,110,110,128,128,128};
|
||||
static unsigned char default_widths[N_PEAKS] = {128,128,128,160,171,171,128,128,128};
|
||||
// static unsigned char default_heights[N_PEAKS] = {140,128,120,110,90,90,128,128,128}; // changed for v.1.47
|
||||
// static unsigned char default_widths[N_PEAKS] = {128,128,128,160,171,171,128,128,128};
|
||||
static unsigned char default_heights[N_PEAKS] = {128,128,120,120,110,110,128,128,128}; // previous version
|
||||
static unsigned char default_widths[N_PEAKS] = {140,128,128,160,171,171,128,128,128};
|
||||
|
||||
static int breath_widths[N_PEAKS] = {0,200,200,400,400,400,600,600,600};
|
||||
|
||||
@@ -408,7 +420,7 @@ void VoiceReset(int tone_only)
|
||||
voice->n_harmonic_peaks = 5;
|
||||
voice->peak_shape = 0;
|
||||
voice->voicing = 64;
|
||||
voice->consonant_amp = 100;
|
||||
voice->consonant_amp = 85; // change to 85 for v.1.47 was 100
|
||||
voice->consonant_ampv = 100;
|
||||
voice->samplerate = samplerate_native;
|
||||
memset(voice->klattv,0,sizeof(voice->klattv));
|
||||
@@ -442,7 +454,7 @@ void VoiceReset(int tone_only)
|
||||
// Adjustment of harmonic amplitudes, steps of 8Hz
|
||||
// value of 128 means no change
|
||||
// memset(voice->tone_adjust,128,sizeof(voice->tone_adjust));
|
||||
SetToneAdjust(voice,tone_points);
|
||||
SetToneAdjust(voice,tone_points);
|
||||
|
||||
// default values of speed factors
|
||||
voice->speedf1 = 256;
|
||||
@@ -516,7 +528,7 @@ static int Read8Numbers(char *data_in,int *data)
|
||||
// Read 8 integer numbers
|
||||
memset(data, 0, 8+sizeof(int));
|
||||
return(sscanf(data_in,"%d %d %d %d %d %d %d %d",
|
||||
&data[0],&data[1],&data[2],&data[3],&data[4],&data[5],&data[6],&data[7]));
|
||||
&data[0],&data[1],&data[2],&data[3],&data[4],&data[5],&data[6],&data[7]));
|
||||
}
|
||||
|
||||
|
||||
@@ -553,14 +565,16 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
char phonemes_name[40];
|
||||
char option_name[40];
|
||||
const char *language_type;
|
||||
char buf[200];
|
||||
char buf[sizeof(path_home)+30];
|
||||
char path_voices[sizeof(path_home)+12];
|
||||
char langname[4];
|
||||
|
||||
int dict_min = 0;
|
||||
int stress_amps[8];
|
||||
int stress_lengths[8];
|
||||
int stress_add[8];
|
||||
char names[8][40];
|
||||
char name2[80];
|
||||
const char *voice_dir;
|
||||
|
||||
int pitch1;
|
||||
int pitch2;
|
||||
@@ -569,10 +583,14 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
static char voice_name[40]; // voice name for current_voice_selected
|
||||
static char voice_languages[100]; // list of languages and priorities for current_voice_selected
|
||||
|
||||
strcpy(voicename,vname);
|
||||
if(voicename[0]==0)
|
||||
strcpy(voicename,"default");
|
||||
// which directory to look for a named voice
|
||||
static const char *voices_asia =
|
||||
"fa fa-pin hi hy hy-west id ka kn ku ml ne pa ta tr vi vi-hue zh zh-yue ";
|
||||
static const char *voices_europe =
|
||||
"bg bs ca cs cy da el es et fi fr-be hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";
|
||||
|
||||
|
||||
strncpy0(voicename, vname, sizeof(voicename));
|
||||
if(control & 0x10)
|
||||
{
|
||||
strcpy(buf,vname);
|
||||
@@ -581,25 +599,34 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(voicename[0]==0)
|
||||
strcpy(voicename,"default");
|
||||
|
||||
sprintf(path_voices,"%s%cvoices%c",path_home,PATHSEP,PATHSEP);
|
||||
sprintf(buf,"%s%s",path_voices,voicename);
|
||||
sprintf(buf,"%s%s",path_voices,voicename); // first, look in the main voices directory
|
||||
|
||||
if(GetFileLength(buf) <= 0)
|
||||
{
|
||||
// look for the voice in a sub-directory of the language name
|
||||
langname[0] = voicename[0];
|
||||
langname[1] = voicename[1];
|
||||
langname[2] = 0;
|
||||
sprintf(buf,"%s%s%c%s",path_voices,langname,PATHSEP,voicename);
|
||||
|
||||
if(GetFileLength(buf) <= 0)
|
||||
// then look in the appropriate subdirectory
|
||||
if((voicename[0]=='m') && (voicename[1]=='b'))
|
||||
{
|
||||
// look in "extra" sub-directory
|
||||
sprintf(buf,"%sextra%c%s",path_voices,PATHSEP,voicename);
|
||||
voice_dir = "mb"; // mbrola voices
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(name2, "%s ", voicename);
|
||||
if(strstr(voices_europe, voicename) != NULL)
|
||||
voice_dir = "europe";
|
||||
else if(strstr(voices_asia, voicename) != NULL)
|
||||
voice_dir = "asia";
|
||||
else
|
||||
voice_dir = "other";
|
||||
|
||||
sprintf(buf,"%s%s%c%s", path_voices,voice_dir,PATHSEP,voicename);
|
||||
|
||||
if(GetFileLength(buf) <= 0)
|
||||
{
|
||||
// look in "test" sub-directory
|
||||
// if not found, look in "test" sub-directory
|
||||
sprintf(buf,"%stest%c%s",path_voices,PATHSEP,voicename);
|
||||
}
|
||||
}
|
||||
@@ -668,48 +695,48 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
switch(key)
|
||||
{
|
||||
case V_LANGUAGE:
|
||||
{
|
||||
unsigned int len;
|
||||
int priority;
|
||||
|
||||
if(tone_only)
|
||||
break;
|
||||
|
||||
priority = DEFAULT_LANGUAGE_PRIORITY;
|
||||
language_name[0] = 0;
|
||||
|
||||
sscanf(p,"%s %d",language_name,&priority);
|
||||
if(strcmp(language_name,"variant") == 0)
|
||||
break;
|
||||
|
||||
len = strlen(language_name) + 2;
|
||||
// check for space in languages[]
|
||||
if(len < (sizeof(voice_languages)-langix-1))
|
||||
{
|
||||
unsigned int len;
|
||||
int priority;
|
||||
voice_languages[langix] = priority;
|
||||
|
||||
if(tone_only)
|
||||
break;
|
||||
|
||||
priority = DEFAULT_LANGUAGE_PRIORITY;
|
||||
language_name[0] = 0;
|
||||
|
||||
sscanf(p,"%s %d",language_name,&priority);
|
||||
if(strcmp(language_name,"variant") == 0)
|
||||
break;
|
||||
|
||||
len = strlen(language_name) + 2;
|
||||
// check for space in languages[]
|
||||
if(len < (sizeof(voice_languages)-langix-1))
|
||||
{
|
||||
voice_languages[langix] = priority;
|
||||
|
||||
strcpy(&voice_languages[langix+1],language_name);
|
||||
langix += len;
|
||||
}
|
||||
|
||||
// only act on the first language line
|
||||
if(language_set == 0)
|
||||
{
|
||||
language_type = strtok(language_name,"-");
|
||||
language_set = 1;
|
||||
strcpy(translator_name,language_type);
|
||||
strcpy(new_dictionary,language_type);
|
||||
strcpy(phonemes_name,language_type);
|
||||
SelectPhonemeTableName(phonemes_name);
|
||||
|
||||
if(new_translator != NULL)
|
||||
DeleteTranslator(new_translator);
|
||||
|
||||
new_translator = SelectTranslator(translator_name);
|
||||
langopts = &new_translator->langopts;
|
||||
}
|
||||
strcpy(&voice_languages[langix+1],language_name);
|
||||
langix += len;
|
||||
}
|
||||
break;
|
||||
|
||||
// only act on the first language line
|
||||
if(language_set == 0)
|
||||
{
|
||||
language_type = strtok(language_name,"-");
|
||||
language_set = 1;
|
||||
strcpy(translator_name,language_type);
|
||||
strcpy(new_dictionary,language_type);
|
||||
strcpy(phonemes_name,language_type);
|
||||
SelectPhonemeTableName(phonemes_name);
|
||||
|
||||
if(new_translator != NULL)
|
||||
DeleteTranslator(new_translator);
|
||||
|
||||
new_translator = SelectTranslator(translator_name);
|
||||
langopts = &new_translator->langopts;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case V_NAME:
|
||||
if(tone_only == 0)
|
||||
@@ -720,14 +747,14 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_GENDER:
|
||||
{
|
||||
int age = 0;
|
||||
char vgender[80];
|
||||
sscanf(p,"%s %d",vgender,&age);
|
||||
current_voice_selected.gender = LookupMnem(genders,vgender);
|
||||
current_voice_selected.age = age;
|
||||
}
|
||||
break;
|
||||
{
|
||||
int age = 0;
|
||||
char vgender[80];
|
||||
sscanf(p,"%s %d",vgender,&age);
|
||||
current_voice_selected.gender = LookupMnem(genders,vgender);
|
||||
current_voice_selected.age = age;
|
||||
}
|
||||
break;
|
||||
|
||||
case V_TRANSLATOR:
|
||||
if(tone_only) break;
|
||||
@@ -735,7 +762,7 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
sscanf(p,"%s",translator_name);
|
||||
|
||||
if(new_translator != NULL)
|
||||
DeleteTranslator(new_translator);
|
||||
DeleteTranslator(new_translator);
|
||||
|
||||
new_translator = SelectTranslator(translator_name);
|
||||
langopts = &new_translator->langopts;
|
||||
@@ -754,16 +781,16 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_PITCH:
|
||||
{
|
||||
double factor;
|
||||
// default is pitch 82 118
|
||||
n = sscanf(p,"%d %d",&pitch1,&pitch2);
|
||||
voice->pitch_base = (pitch1 - 9) << 12;
|
||||
voice->pitch_range = (pitch2 - pitch1) * 108;
|
||||
factor = double(pitch1 - 82)/82;
|
||||
voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch
|
||||
}
|
||||
break;
|
||||
{
|
||||
double factor;
|
||||
// default is pitch 82 118
|
||||
n = sscanf(p,"%d %d",&pitch1,&pitch2);
|
||||
voice->pitch_base = (pitch1 - 9) << 12;
|
||||
voice->pitch_range = (pitch2 - pitch1) * 108;
|
||||
factor = double(pitch1 - 82)/82;
|
||||
voice->formant_factor = (int)((1+factor/4) * 256); // nominal formant shift for a different voice pitch
|
||||
}
|
||||
break;
|
||||
|
||||
case V_STRESSLENGTH: // stressLength
|
||||
stress_lengths_set = Read8Numbers(p,stress_lengths);
|
||||
@@ -799,14 +826,32 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_DICTRULES: // conditional dictionary rules and list entries
|
||||
case V_NUMBERS:
|
||||
case V_STRESSOPT:
|
||||
// expect a list of numbers
|
||||
while(*p != 0)
|
||||
{
|
||||
while(isspace(*p)) p++;
|
||||
n = -1;
|
||||
if(((n = atoi(p)) > 0) && (n < 32))
|
||||
if((n = atoi(p)) > 0)
|
||||
{
|
||||
p++;
|
||||
conditional_rules |= (1 << n);
|
||||
if(n < 32)
|
||||
{
|
||||
if(key==V_DICTRULES)
|
||||
conditional_rules |= (1 << n);
|
||||
else if(key==V_NUMBERS)
|
||||
langopts->numbers |= (1 << n);
|
||||
else if(key==V_STRESSOPT)
|
||||
langopts->stress_flags |= (1 << n);
|
||||
}
|
||||
else
|
||||
{
|
||||
if((key==V_NUMBERS) && (n < 64))
|
||||
langopts->numbers |= (1 << (n-32));
|
||||
else
|
||||
fprintf(stderr,"Bad option number %d\n", n);
|
||||
}
|
||||
}
|
||||
while(isalnum(*p)) p++;
|
||||
}
|
||||
@@ -828,9 +873,9 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
|
||||
case V_STRESSRULE:
|
||||
sscanf(p,"%d %d %d %d",&langopts->stress_rule,
|
||||
&langopts->stress_flags,
|
||||
&langopts->unstressed_wd1,
|
||||
&langopts->unstressed_wd2);
|
||||
&langopts->stress_flags,
|
||||
&langopts->unstressed_wd1,
|
||||
&langopts->unstressed_wd2);
|
||||
break;
|
||||
|
||||
case V_CHARSET:
|
||||
@@ -838,10 +883,6 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
new_translator->charset_a0 = charsets[value];
|
||||
break;
|
||||
|
||||
case V_NUMBERS:
|
||||
sscanf(p,"%d %d",&langopts->numbers,&langopts->numbers2);
|
||||
break;
|
||||
|
||||
case V_OPTION:
|
||||
value2 = 0;
|
||||
if((sscanf(p,"%s %d %d",option_name,&value,&value2) >= 2) && ((ix = LookupMnem(options_tab, option_name)) >= 0))
|
||||
@@ -885,12 +926,12 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_TONE:
|
||||
{
|
||||
int tone_data[12];
|
||||
ReadTonePoints(p,tone_data);
|
||||
SetToneAdjust(voice,tone_data);
|
||||
}
|
||||
break;
|
||||
{
|
||||
int tone_data[12];
|
||||
ReadTonePoints(p,tone_data);
|
||||
SetToneAdjust(voice,tone_data);
|
||||
}
|
||||
break;
|
||||
|
||||
case V_VOICING:
|
||||
if(sscanf(p,"%d",&value)==1)
|
||||
@@ -898,16 +939,16 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_BREATH:
|
||||
voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
|
||||
for(ix=1; ix<8; ix++)
|
||||
{
|
||||
if(ix % 2)
|
||||
voice->breath[ix] = -voice->breath[ix];
|
||||
}
|
||||
voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
|
||||
for(ix=1; ix<8; ix++)
|
||||
{
|
||||
if(ix % 2)
|
||||
voice->breath[ix] = -voice->breath[ix];
|
||||
}
|
||||
break;
|
||||
|
||||
case V_BREATHW:
|
||||
voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
|
||||
voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
|
||||
break;
|
||||
|
||||
case V_CONSONANTS:
|
||||
@@ -919,20 +960,20 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
break;
|
||||
|
||||
case V_MBROLA:
|
||||
{
|
||||
int srate = 16000;
|
||||
char name[40];
|
||||
char phtrans[40];
|
||||
{
|
||||
int srate = 16000;
|
||||
char name[40];
|
||||
char phtrans[40];
|
||||
|
||||
phtrans[0] = 0;
|
||||
sscanf(p,"%s %s %d",name,phtrans,&srate);
|
||||
if(LoadMbrolaTable(name,phtrans,srate) != EE_OK)
|
||||
{
|
||||
fprintf(stderr,"mbrola voice not found\n");
|
||||
}
|
||||
voice->samplerate = srate;
|
||||
phtrans[0] = 0;
|
||||
sscanf(p,"%s %s %d",name,phtrans,&srate);
|
||||
if(LoadMbrolaTable(name,phtrans,srate) != EE_OK)
|
||||
{
|
||||
fprintf(stderr,"mbrola voice not found\n");
|
||||
}
|
||||
break;
|
||||
voice->samplerate = srate;
|
||||
}
|
||||
break;
|
||||
|
||||
case V_KLATT:
|
||||
voice->klattv[0] = 1; // default source: IMPULSIVE
|
||||
@@ -945,6 +986,10 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
SetSpeed(3);
|
||||
break;
|
||||
|
||||
case V_DICTMIN:
|
||||
sscanf(p,"%d",&dict_min);
|
||||
break;
|
||||
|
||||
default:
|
||||
if((key & 0xff00) == 0x100)
|
||||
{
|
||||
@@ -987,6 +1032,7 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
}
|
||||
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)
|
||||
return(NULL); // no dictionary loaded
|
||||
@@ -1011,6 +1057,7 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
translator = new_translator;
|
||||
}
|
||||
|
||||
|
||||
// relative lengths of different stress syllables
|
||||
for(ix=0; ix<stress_lengths_set; ix++)
|
||||
{
|
||||
@@ -1225,15 +1272,14 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s
|
||||
// match on voice name
|
||||
score += 500;
|
||||
}
|
||||
else
|
||||
if(strcmp(voice_spec->name,voice->identifier)==0)
|
||||
else if(strcmp(voice_spec->name,voice->identifier)==0)
|
||||
{
|
||||
score += 400;
|
||||
}
|
||||
}
|
||||
|
||||
if(((voice_spec->gender == 1) || (voice_spec->gender == 2)) &&
|
||||
((voice->gender == 1) || (voice->gender == 2)))
|
||||
((voice->gender == 1) || (voice->gender == 2)))
|
||||
{
|
||||
if(voice_spec->gender == voice->gender)
|
||||
score += 50;
|
||||
@@ -1365,8 +1411,7 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name2)
|
||||
{
|
||||
match_fname = ix; // matching identifier, use this if no matching name
|
||||
}
|
||||
else
|
||||
if(strcmp(last_part,&id[strlen(id)-last_part_len])==0)
|
||||
else if(strcmp(last_part,&id[strlen(id)-last_part_len])==0)
|
||||
{
|
||||
match_fname2 = ix;
|
||||
}
|
||||
@@ -1463,8 +1508,7 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found)
|
||||
gender = 0;
|
||||
if((voice_select2.gender == 2) || ((voice_select2.age > 0) && (voice_select2.age < 13)))
|
||||
gender = 2;
|
||||
else
|
||||
if(voice_select2.gender == 1)
|
||||
else if(voice_select2.gender == 1)
|
||||
gender = 1;
|
||||
|
||||
#define AGE_OLD 60
|
||||
@@ -1595,8 +1639,8 @@ static void GetVoices(const char *path)
|
||||
}
|
||||
#else
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
WIN32_FIND_DATAA FindFileData;
|
||||
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||
WIN32_FIND_DATAA FindFileData;
|
||||
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||
|
||||
#undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string
|
||||
sprintf(fname,"%s\\*",path);
|
||||
@@ -1605,29 +1649,33 @@ static void GetVoices(const char *path)
|
||||
return;
|
||||
|
||||
do {
|
||||
sprintf(fname,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
|
||||
if(n_voices_list >= (N_VOICES_LIST-2))
|
||||
break; // voices list is full
|
||||
|
||||
ftype = GetFileLength(fname);
|
||||
|
||||
if((ftype == -2) && (FindFileData.cFileName[0] != '.'))
|
||||
if(FindFileData.cFileName[0] != '.')
|
||||
{
|
||||
// a sub-sirectory
|
||||
GetVoices(fname);
|
||||
}
|
||||
else
|
||||
if(ftype > 0)
|
||||
{
|
||||
// a regular line, add it to the voices list
|
||||
if((f_voice = fopen(fname,"r")) == NULL)
|
||||
continue;
|
||||
sprintf(fname,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
|
||||
ftype = GetFileLength(fname);
|
||||
|
||||
// pass voice file name within the voices directory
|
||||
voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, FindFileData.cFileName);
|
||||
fclose(f_voice);
|
||||
|
||||
if(voice_data != NULL)
|
||||
if(ftype == -2)
|
||||
{
|
||||
voices_list[n_voices_list++] = voice_data;
|
||||
// a sub-sirectory
|
||||
GetVoices(fname);
|
||||
}
|
||||
else if(ftype > 0)
|
||||
{
|
||||
// a regular line, add it to the voices list
|
||||
if((f_voice = fopen(fname,"r")) == NULL)
|
||||
continue;
|
||||
|
||||
// pass voice file name within the voices directory
|
||||
voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, FindFileData.cFileName);
|
||||
fclose(f_voice);
|
||||
|
||||
if(voice_data != NULL)
|
||||
{
|
||||
voices_list[n_voices_list++] = voice_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(FindNextFileA(hFind, &FindFileData) != 0);
|
||||
@@ -1648,17 +1696,19 @@ static void GetVoices(const char *path)
|
||||
break; // voices list is full
|
||||
}
|
||||
|
||||
if(ent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
sprintf(fname,"%s%c%s",path,PATHSEP,ent->d_name);
|
||||
|
||||
ftype = GetFileLength(fname);
|
||||
|
||||
if((ftype == -2) && (ent->d_name[0] != '.'))
|
||||
if(ftype == -2)
|
||||
{
|
||||
// a sub-sirectory
|
||||
GetVoices(fname);
|
||||
}
|
||||
else
|
||||
if(ftype > 0)
|
||||
else if(ftype > 0)
|
||||
{
|
||||
// a regular line, add it to the voices list
|
||||
if((f_voice = fopen(fname,"r")) == NULL)
|
||||
@@ -1691,15 +1741,23 @@ static void GetVoices(const char *path)
|
||||
espeak_ERROR SetVoiceByName(const char *name)
|
||||
{//=========================================
|
||||
espeak_VOICE *v;
|
||||
int ix;
|
||||
espeak_VOICE voice_selector;
|
||||
char *variant_name;
|
||||
static char buf[60];
|
||||
|
||||
strncpy0(buf,name,sizeof(buf));
|
||||
|
||||
variant_name = ExtractVoiceVariantName(buf, 0, 1);
|
||||
|
||||
for(ix=0; ; ix++)
|
||||
{
|
||||
// convert voice name to lower case (ascii)
|
||||
if((buf[ix] = tolower(buf[ix])) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&voice_selector,0,sizeof(voice_selector));
|
||||
// voice_selector.name = buf;
|
||||
voice_selector.name = (char *)name; // include variant name in voice stack ??
|
||||
|
||||
// first check for a voice with this filename
|
||||
@@ -1798,7 +1856,7 @@ ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec)
|
||||
|
||||
// sort the voices list
|
||||
qsort(voices_list,n_voices_list,sizeof(espeak_VOICE *),
|
||||
(int (__cdecl *)(const void *,const void *))VoiceNameSorter);
|
||||
(int (__cdecl *)(const void *,const void *))VoiceNameSorter);
|
||||
|
||||
|
||||
if(voice_spec)
|
||||
|
||||
Reference in New Issue
Block a user