mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-06 15:12:24 +00:00
Merge branch 'master' into android
Conflicts: platforms/windows/make_espeakedit.iss
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@ DATADIR=${PREFIX}/share/espeak-data
|
||||
|
||||
# remove -fno-exceptions if it causes problems with stdio library on some platforms (ARM)
|
||||
|
||||
RELEASE = 1.46
|
||||
RELEASE = 1.47
|
||||
SPEAK = speak
|
||||
ESPEAK = espeak
|
||||
ESPEAKEDIT = espeakedit
|
||||
|
||||
+15
-5
@@ -104,9 +104,8 @@ static keywtab_t k_conditions[] = {
|
||||
{"next2PhW", tWHICH_PHONEME, 6},
|
||||
{"nextVowel",tWHICH_PHONEME, 7},
|
||||
{"prevVowel",tWHICH_PHONEME, 8},
|
||||
// {"next2PhW", tWHICH_PHONEME, 0x800},
|
||||
|
||||
// {"numVowels", tTEST, 0x000},
|
||||
{"next3PhW", tWHICH_PHONEME, 9},
|
||||
{"prev2PhW", tWHICH_PHONEME, 10},
|
||||
|
||||
{"PreVoicing", tTEST, 0xf01},
|
||||
{"KlattSynth", tTEST, 0xf02},
|
||||
@@ -1051,8 +1050,13 @@ static wxString CompileAllDictionaries()
|
||||
fclose(f_in);
|
||||
}
|
||||
|
||||
LoadVoice(voicename,0);
|
||||
|
||||
if(LoadVoice(voicename,1) == NULL)
|
||||
{
|
||||
wxLogError(wxString::Format(_T("Can't find voice '%s' for dictionary '%s'"), wxString(voicename, wxConvLocal).c_str(), dictstr.c_str()));
|
||||
report = report + dictstr + _T(" No Voice, ");
|
||||
errors ++;
|
||||
}
|
||||
else
|
||||
if((err = CompileDictionary(path_dsource, dictname,log,NULL,0)) > 0)
|
||||
{
|
||||
report = report + dictstr + wxString::Format(_T(" %d, "),err);
|
||||
@@ -2742,6 +2746,7 @@ int CompilePhoneme(int compile_phoneme)
|
||||
int count;
|
||||
int c;
|
||||
char *p;
|
||||
int vowel_length_factor = 100; // for testing
|
||||
char number_buf[12];
|
||||
char ipa_buf[N_ITEM_STRING+1];
|
||||
PHONEME_TAB phoneme_out2;
|
||||
@@ -2844,6 +2849,11 @@ int CompilePhoneme(int compile_phoneme)
|
||||
|
||||
case i_SET_LENGTH:
|
||||
value = NextItemMax(511);
|
||||
if(phoneme_out->type == phVOWEL)
|
||||
{
|
||||
value = (value * vowel_length_factor)/100;
|
||||
}
|
||||
|
||||
if(after_if == 0)
|
||||
{
|
||||
phoneme_out->std_length = value/2;
|
||||
|
||||
+5
-5
@@ -470,12 +470,12 @@ static int compile_line(char *linebuf, char *dict_line, int *hash)
|
||||
}
|
||||
|
||||
ix = 0;
|
||||
if(isdigit(*p))
|
||||
if(IsDigit09(*p))
|
||||
{
|
||||
ix += (*p-'0');
|
||||
p++;
|
||||
}
|
||||
if(isdigit(*p))
|
||||
if(IsDigit09(*p))
|
||||
{
|
||||
ix = ix*10 + (*p-'0');
|
||||
p++;
|
||||
@@ -542,7 +542,7 @@ static int compile_line(char *linebuf, char *dict_line, int *hash)
|
||||
case 1:
|
||||
if((c == '-') && multiple_words)
|
||||
{
|
||||
if(isdigit(word[0]))
|
||||
if(IsDigit09(word[0]))
|
||||
{
|
||||
multiple_numeric_hyphen = 1;
|
||||
}
|
||||
@@ -1156,7 +1156,7 @@ static void copy_rule_string(char *string, int &state)
|
||||
sxflags |= SUFX_M;
|
||||
break;
|
||||
default:
|
||||
if(isdigit(c))
|
||||
if(IsDigit09(c))
|
||||
value = (value*10) + (c - '0');
|
||||
break;
|
||||
}
|
||||
@@ -1575,7 +1575,7 @@ static int compile_lettergroup(char *input, FILE *f_out)
|
||||
char item_length[N_LETTERGP_ITEMS];
|
||||
|
||||
p = input;
|
||||
if(!isdigit(p[0]) || !isdigit(p[1]))
|
||||
if(!IsDigit09(p[0]) || !IsDigit09(p[1]))
|
||||
{
|
||||
fprintf(f_log,"%5d: Expected 2 digits after '.L'\n",linenum);
|
||||
error_count++;
|
||||
|
||||
+12
-9
@@ -611,7 +611,7 @@ char *WritePhMnemonic(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int
|
||||
break; // # is subscript-h, but only for consonants
|
||||
|
||||
// ignore digits after the first character
|
||||
if(!first && isdigit(c))
|
||||
if(!first && IsDigit09(c))
|
||||
continue;
|
||||
|
||||
if((c >= 0x20) && (c < 128))
|
||||
@@ -1499,8 +1499,8 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
else
|
||||
{
|
||||
// no long vowels or consonant clusters
|
||||
if(vowel_count > 4)
|
||||
stressed_syllable = vowel_count - 3;
|
||||
if(vowel_count > 5)
|
||||
stressed_syllable = vowel_count - 3; // more than 4 syllables
|
||||
else
|
||||
stressed_syllable = vowel_count - 1;
|
||||
}
|
||||
@@ -2698,7 +2698,7 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
{
|
||||
if(tr->langopts.alt_alphabet == alphabet->offset)
|
||||
{
|
||||
sprintf(phonemes,"%c%s",phonSWITCH, tr->langopts.alt_alphabet_lang);
|
||||
sprintf(phonemes,"%c%s",phonSWITCH, WordToString2(tr->langopts.alt_alphabet_lang));
|
||||
return(0);
|
||||
}
|
||||
if(alphabet->flags & AL_WORDS)
|
||||
@@ -2988,6 +2988,7 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
|
||||
const char *word_end;
|
||||
const char *word1;
|
||||
int wflags = 0;
|
||||
int lookup_symbol;
|
||||
char word_buf[N_WORD_BYTES+1];
|
||||
char dict_flags_buf[80];
|
||||
|
||||
@@ -2996,6 +2997,7 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
|
||||
wflags = wtab->flags;
|
||||
}
|
||||
|
||||
lookup_symbol = flags[1] & FLAG_LOOKUP_SYMBOL;
|
||||
word1 = word;
|
||||
if(tr->transpose_min > 0)
|
||||
{
|
||||
@@ -3182,9 +3184,9 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
|
||||
continue;
|
||||
}
|
||||
|
||||
if((dictionary_flags2 & FLAG_ATEND) && (word_end < translator->clause_end))
|
||||
if((dictionary_flags2 & FLAG_ATEND) && (word_end < translator->clause_end) && (lookup_symbol==0))
|
||||
{
|
||||
// only use this pronunciation if it's the last word of the clause
|
||||
// only use this pronunciation if it's the last word of the clause, or called from Lookup()
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3196,7 +3198,7 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
|
||||
|
||||
if((dictionary_flags2 & FLAG_SENTENCE) && !(translator->clause_terminator & CLAUSE_BIT_SENTENCE))
|
||||
{
|
||||
// only uis this clause is a sentence , i.e. terminator is {. ? !} not {, : :}
|
||||
// only if this clause is a sentence , i.e. terminator is {. ? !} not {, : :}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3364,7 +3366,7 @@ int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *f
|
||||
if(((c = *word1++)==0) || (c == ' '))
|
||||
break;
|
||||
|
||||
if((c=='.') && (length > 0) && (isdigit(word[length-1])))
|
||||
if((c=='.') && (length > 0) && (IsDigit09(word[length-1])))
|
||||
break; // needed for lang=hu, eg. "december 2.-ig"
|
||||
|
||||
word[length] = c;
|
||||
@@ -3475,7 +3477,8 @@ int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *f
|
||||
int Lookup(Translator *tr, const char *word, char *ph_out)
|
||||
{//===================================================
|
||||
unsigned int flags[2];
|
||||
flags[0] = flags[1] = 0;
|
||||
flags[0] = 0;
|
||||
flags[1] = FLAG_LOOKUP_SYMBOL;
|
||||
char *word1 = (char *)word;
|
||||
return(LookupDictList(tr, &word1, ph_out, flags, 0, NULL));
|
||||
}
|
||||
|
||||
+15
-4
@@ -128,13 +128,16 @@ void DisplayVoices(FILE *f_out, char *language)
|
||||
const char *p;
|
||||
int len;
|
||||
int count;
|
||||
int c;
|
||||
int j;
|
||||
const espeak_VOICE *v;
|
||||
const char *lang_name;
|
||||
char age_buf[12];
|
||||
char buf[80];
|
||||
const espeak_VOICE **voices;
|
||||
espeak_VOICE voice_select;
|
||||
|
||||
static char genders[4] = {' ','M','F',' '};
|
||||
static char genders[4] = {'-','M','F','-'};
|
||||
|
||||
if((language != NULL) && (language[0] != 0))
|
||||
{
|
||||
@@ -150,7 +153,7 @@ void DisplayVoices(FILE *f_out, char *language)
|
||||
voices = espeak_ListVoices(NULL);
|
||||
}
|
||||
|
||||
fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Langs\n");
|
||||
fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Languages\n");
|
||||
|
||||
for(ix=0; (v = voices[ix]) != NULL; ix++)
|
||||
{
|
||||
@@ -168,8 +171,16 @@ void DisplayVoices(FILE *f_out, char *language)
|
||||
|
||||
if(count==0)
|
||||
{
|
||||
fprintf(f_out,"%2d %-12s%s%c %-17s %-11s ",
|
||||
p[0],lang_name,age_buf,genders[v->gender],v->name,v->identifier);
|
||||
for(j=0; j < sizeof(buf); j++)
|
||||
{
|
||||
// replace spaces in the name
|
||||
if((c = v->name[j]) == ' ')
|
||||
c = '_';
|
||||
if((buf[j] = c) == 0)
|
||||
break;
|
||||
}
|
||||
fprintf(f_out,"%2d %-12s%s%c %-20s %-13s ",
|
||||
p[0],lang_name,age_buf,genders[v->gender],buf,v->identifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+42
-30
@@ -608,7 +608,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
|
||||
char ph_buf[80];
|
||||
char ph_buf2[80];
|
||||
char ph_alphabet[80];
|
||||
char hexbuf[6];
|
||||
char hexbuf[12];
|
||||
static char pause_string[] = {phonPAUSE, 0};
|
||||
|
||||
ph_buf[0] = 0;
|
||||
@@ -695,6 +695,9 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
|
||||
|
||||
if(ph_buf[0] == 0)
|
||||
{
|
||||
if((al_offset != 0) && (al_offset == translator->langopts.alt_alphabet))
|
||||
language = translator->langopts.alt_alphabet_lang;
|
||||
else
|
||||
if((alphabet != NULL) && (alphabet->language != 0) && !(al_flags & AL_NOT_LETTERS))
|
||||
language = alphabet->language;
|
||||
else
|
||||
@@ -797,7 +800,7 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
|
||||
|
||||
len = strlen(phonemes);
|
||||
|
||||
if(tr->langopts.accents & 2)
|
||||
if(tr->langopts.accents & 2) // 'capital' before or after the word ?
|
||||
sprintf(ph_buf2,"%c%s%s%s",0xff,ph_alphabet,ph_buf,capital);
|
||||
else
|
||||
sprintf(ph_buf2,"%c%s%s%s",0xff,ph_alphabet,capital,ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress()
|
||||
@@ -877,6 +880,7 @@ void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars)
|
||||
// Numbers
|
||||
|
||||
static char ph_ordinal2[12];
|
||||
static char ph_ordinal2x[12];
|
||||
|
||||
|
||||
static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB *wtab, int roman)
|
||||
@@ -981,7 +985,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
|
||||
flags[0] = 0;
|
||||
flags[1] = 0;
|
||||
|
||||
if(((tr->langopts.numbers & NUM_ROMAN_CAPITALS) && !(wtab[0].flags & FLAG_ALL_UPPER)) || isdigit(word[-2]))
|
||||
if(((tr->langopts.numbers & NUM_ROMAN_CAPITALS) && !(wtab[0].flags & FLAG_ALL_UPPER)) || IsDigit09(word[-2]))
|
||||
return(0); // not '2xx'
|
||||
|
||||
word_start = word;
|
||||
@@ -1020,7 +1024,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
|
||||
n_digits++;
|
||||
}
|
||||
|
||||
if(isdigit(word[0]))
|
||||
if(IsDigit09(word[0]))
|
||||
return(0); // eg. 'xx2'
|
||||
|
||||
acc += prev;
|
||||
@@ -1303,7 +1307,11 @@ static int LookupNum2(Translator *tr, int value, const int control, char *ph_out
|
||||
if(control & 4)
|
||||
{
|
||||
sprintf(string,"_%d%cx",value,ord_type); // LANG=hu, special word for 1. 2. when there are no higher digits
|
||||
found = Lookup(tr, string, ph_digits);
|
||||
if((found = Lookup(tr, string, ph_digits)) != 0)
|
||||
{
|
||||
if(ph_ordinal2x[0] != 0)
|
||||
strcpy(ph_ordinal, ph_ordinal2x); // alternate pronunciation (lang=an)
|
||||
}
|
||||
}
|
||||
if(found == 0)
|
||||
{
|
||||
@@ -1363,8 +1371,7 @@ static int LookupNum2(Translator *tr, int value, const int control, char *ph_out
|
||||
else
|
||||
{
|
||||
|
||||
if((is_ordinal) &&
|
||||
((units == 0) || (tr->langopts.numbers & NUM_SWAP_TENS) || (tr->langopts.numbers2 & NUM2_MULTIPLE_ORDINAL)))
|
||||
if(is_ordinal)
|
||||
{
|
||||
sprintf(string,"_%dX%c", tens, ord_type);
|
||||
if(Lookup(tr, string, ph_tens) != 0)
|
||||
@@ -1458,7 +1465,7 @@ static int LookupNum2(Translator *tr, int value, const int control, char *ph_out
|
||||
{
|
||||
Lookup(tr, "_0and", ph_and);
|
||||
|
||||
if((is_ordinal) && (tr->langopts.numbers2 & NUM2_MULTIPLE_ORDINAL))
|
||||
if((is_ordinal) && (tr->langopts.numbers2 & NUM2_ORDINAL_NO_AND))
|
||||
ph_and[0] = 0;
|
||||
|
||||
if(tr->langopts.numbers & NUM_SWAP_TENS)
|
||||
@@ -1607,9 +1614,9 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null
|
||||
}
|
||||
|
||||
if(tr->langopts.numbers2 & 0x200)
|
||||
sprintf(ph_thousands,"%s%s",ph_10T,ph_digits); // say "thousands" before its number, not after
|
||||
sprintf(ph_thousands,"%s%c%s%c",ph_10T,phonEND_WORD,ph_digits,phonEND_WORD); // say "thousands" before its number, not after
|
||||
else
|
||||
sprintf(ph_thousands,"%s%s",ph_digits,ph_10T);
|
||||
sprintf(ph_thousands,"%s%c%s%c",ph_digits,phonEND_WORD,ph_10T,phonEND_WORD);
|
||||
|
||||
hundreds %= 10;
|
||||
if((hundreds == 0) && (say_zero_hundred == 0))
|
||||
@@ -1742,7 +1749,7 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(ph_out,"%s%s%s",buf1,ph_hundred_and,buf2);
|
||||
sprintf(ph_out,"%s%s%c%s",buf1,ph_hundred_and,phonEND_WORD,buf2);
|
||||
|
||||
return(0);
|
||||
} // end of LookupNum3
|
||||
@@ -1753,12 +1760,12 @@ bool CheckThousandsGroup(char *word, int group_len)
|
||||
// Is this a group of 3 digits which looks like a thousands group?
|
||||
int ix;
|
||||
|
||||
if(isdigit(word[group_len]) || isdigit(-1))
|
||||
if(IsDigit09(word[group_len]) || IsDigit09(-1))
|
||||
return(false);
|
||||
|
||||
for(ix=0; ix < group_len; ix++)
|
||||
{
|
||||
if(!isdigit(word[ix]))
|
||||
if(!IsDigit09(word[ix]))
|
||||
return(false);
|
||||
}
|
||||
return(true);
|
||||
@@ -1790,6 +1797,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
int suffix_ix;
|
||||
int skipwords = 0;
|
||||
int group_len;
|
||||
int len;
|
||||
char *p;
|
||||
char string[32]; // for looking up entries in **_list
|
||||
char buf1[100];
|
||||
@@ -1808,7 +1816,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
digit_lookup = buf_digit_lookup;
|
||||
number_control = control;
|
||||
|
||||
for(ix=0; isdigit(word[ix]); ix++) ;
|
||||
for(ix=0; IsDigit09(word[ix]); ix++) ;
|
||||
n_digits = ix;
|
||||
value = this_value = atoi(word);
|
||||
|
||||
@@ -1817,14 +1825,14 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
group_len = 4;
|
||||
|
||||
// is there a previous thousands part (as a previous "word") ?
|
||||
if((n_digits == group_len) && (word[-2] == tr->langopts.thousands_sep) && isdigit(word[-3]))
|
||||
if((n_digits == group_len) && (word[-2] == tr->langopts.thousands_sep) && IsDigit09(word[-3]))
|
||||
{
|
||||
prev_thousands = 1;
|
||||
}
|
||||
else if((tr->langopts.thousands_sep == ' ') || (tr->langopts.numbers & NUM_ALLOW_SPACE))
|
||||
{
|
||||
// thousands groups can be separated by spaces
|
||||
if((n_digits == 3) && !(wtab->flags & FLAG_MULTIPLE_SPACES) && isdigit(word[-2]))
|
||||
if((n_digits == 3) && !(wtab->flags & FLAG_MULTIPLE_SPACES) && IsDigit09(word[-2]))
|
||||
{
|
||||
prev_thousands = 1;
|
||||
}
|
||||
@@ -1846,7 +1854,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
if((word[ix] == '.') && !isdigit(word[ix+1]) && !isdigit(word[ix+2]) && !(wtab[1].flags & FLAG_NOSPACE))
|
||||
if((word[ix] == '.') && !IsDigit09(word[ix+1]) && !IsDigit09(word[ix+2]) && !(wtab[1].flags & FLAG_NOSPACE))
|
||||
{
|
||||
// remove dot unless followed by another number
|
||||
word[ix] = 0;
|
||||
@@ -1875,7 +1883,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
{
|
||||
ordinal = 2;
|
||||
}
|
||||
else if(!isdigit(suffix[0])) // not _#9 (tab)
|
||||
else if(!IsDigit09(suffix[0])) // not _#9 (tab)
|
||||
{
|
||||
sprintf(string,"_#%s",suffix);
|
||||
if(Lookup(tr, string, ph_ordinal2))
|
||||
@@ -1884,6 +1892,8 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
ordinal = 2;
|
||||
flags[0] |= FLAG_SKIPWORDS;
|
||||
skipwords = 1;
|
||||
sprintf(string,"_x#%s",suffix);
|
||||
Lookup(tr, string, ph_ordinal2x); // is there an alternate pronunciation?
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1898,7 +1908,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
|
||||
if((word[0] == '0') && (prev_thousands == 0) && (word[1] != ' ') && (word[1] != tr->langopts.decimal_sep))
|
||||
{
|
||||
if((n_digits == 2) && (word[3] == ':') && isdigit(word[5]) && isspace(word[7]))
|
||||
if((n_digits == 2) && (word[3] == ':') && IsDigit09(word[5]) && isspace(word[7]))
|
||||
{
|
||||
// looks like a time 02:30, omit the leading zero
|
||||
}
|
||||
@@ -1967,7 +1977,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
if((word[n_digits] == tr->langopts.decimal_sep) && isdigit(word[n_digits+1]))
|
||||
if((word[n_digits] == tr->langopts.decimal_sep) && IsDigit09(word[n_digits+1]))
|
||||
{
|
||||
// this "word" ends with a decimal point
|
||||
Lookup(tr, "_dpt", ph_append);
|
||||
@@ -2012,8 +2022,8 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
char *p2;
|
||||
// look for combinations of the number with the next word
|
||||
p = word;
|
||||
while(isdigit(p[1])) p++; // just use the last digit
|
||||
if(isdigit(p[-1]))
|
||||
while(IsDigit09(p[1])) p++; // just use the last digit
|
||||
if(IsDigit09(p[-1]))
|
||||
{
|
||||
p2 = p - 1;
|
||||
if(LookupDictList(tr, &p2, buf_digit_lookup, flags, FLAG_SUFX, wtab)) // lookup 2 digits
|
||||
@@ -2066,9 +2076,9 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
|
||||
LookupNum3(tr, value, ph_buf, suppress_null, thousandplex, prev_thousands | ordinal | decimal_point);
|
||||
if((thousandplex > 0) && (tr->langopts.numbers2 & 0x200))
|
||||
sprintf(ph_out,"%s%s%s%s",ph_zeros,ph_append,ph_buf2,ph_buf); // say "thousands" before its number
|
||||
sprintf(ph_out,"%s%s%c%s%s",ph_zeros,ph_append,phonEND_WORD,ph_buf2,ph_buf); // say "thousands" before its number
|
||||
else
|
||||
sprintf(ph_out,"%s%s%s%s",ph_zeros,ph_buf2,ph_buf,ph_append);
|
||||
sprintf(ph_out,"%s%s%s%c%s",ph_zeros,ph_buf2,ph_buf,phonEND_WORD,ph_append);
|
||||
|
||||
|
||||
while(decimal_point)
|
||||
@@ -2076,7 +2086,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
n_digits++;
|
||||
|
||||
decimal_count = 0;
|
||||
while(isdigit(word[n_digits+decimal_count]))
|
||||
while(IsDigit09(word[n_digits+decimal_count]))
|
||||
decimal_count++;
|
||||
|
||||
// if(decimal_count > 1)
|
||||
@@ -2095,7 +2105,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
decimal_count--;
|
||||
n_digits++;
|
||||
}
|
||||
if((decimal_count <= max_decimal_count) && isdigit(word[n_digits]))
|
||||
if((decimal_count <= max_decimal_count) && IsDigit09(word[n_digits]))
|
||||
{
|
||||
LookupNum3(tr, atoi(&word[n_digits]), buf1, 0,0,0);
|
||||
strcat(ph_out,buf1);
|
||||
@@ -2146,19 +2156,20 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
while(isdigit(c = word[n_digits]) && (strlen(ph_out) < (N_WORD_PHONEMES - 10)))
|
||||
while(IsDigit09(c = word[n_digits]) && (strlen(ph_out) < (N_WORD_PHONEMES - 10)))
|
||||
{
|
||||
// speak any remaining decimal fraction digits individually
|
||||
value = word[n_digits++] - '0';
|
||||
LookupNum2(tr, value, 2, buf1);
|
||||
strcat(ph_out,buf1);
|
||||
len = strlen(ph_out);
|
||||
sprintf(&ph_out[len],"%c%s", phonEND_WORD, buf1);
|
||||
}
|
||||
|
||||
// something after the decimal part ?
|
||||
if(Lookup(tr, "_dpt2", buf1))
|
||||
strcat(ph_out,buf1);
|
||||
|
||||
if((c == tr->langopts.decimal_sep) && isdigit(word[n_digits+1]))
|
||||
if((c == tr->langopts.decimal_sep) && IsDigit09(word[n_digits+1]))
|
||||
{
|
||||
Lookup(tr, "_dpt", buf1);
|
||||
strcat(ph_out,buf1);
|
||||
@@ -2178,7 +2189,8 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
if((tr->langopts.numbers & NUM_NOPAUSE) && (next_char == ' '))
|
||||
utf8_in(&next_char,p);
|
||||
|
||||
if(!iswalpha(next_char) && !((wtab[thousandplex].flags & FLAG_HYPHEN_AFTER) && (thousands_exact != 0)))
|
||||
if(!iswalpha(next_char) && (thousands_exact==0))
|
||||
// if(!iswalpha(next_char) && !((wtab[thousandplex].flags & FLAG_HYPHEN_AFTER) && (thousands_exact != 0)))
|
||||
strcat(ph_out,str_pause); // don't add pause for 100s, 6th, etc.
|
||||
}
|
||||
|
||||
|
||||
+7
-4
@@ -124,6 +124,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
int alternative;
|
||||
int delete_count;
|
||||
int word_start;
|
||||
int inserted;
|
||||
PHONEME_DATA phdata;
|
||||
|
||||
int n_ph_list3;
|
||||
@@ -341,9 +342,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
{
|
||||
plist3 = &ph_list3[j];
|
||||
|
||||
if(plist3->sourceix != 0)
|
||||
word_start = j;
|
||||
|
||||
inserted = 0;
|
||||
if(insert_ph != 0)
|
||||
{
|
||||
// we have a (linking) phoneme which we need to insert here
|
||||
@@ -374,10 +373,14 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
ph = phoneme_tab[insert_ph];
|
||||
plist3->ph = ph;
|
||||
insert_ph = 0;
|
||||
inserted = 1; // don't insert the same phoneme repeatedly
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise get the next phoneme from the list
|
||||
if(plist3->sourceix != 0)
|
||||
word_start = j;
|
||||
|
||||
ph = phoneme_tab[plist3->phcode];
|
||||
plist3[0].ph = ph;
|
||||
|
||||
@@ -394,7 +397,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
|
||||
InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata);
|
||||
|
||||
if((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0)
|
||||
if(((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0) && (inserted == 0))
|
||||
{
|
||||
// PROBLEM: if we insert a phoneme before a vowel then we loose the stress.
|
||||
PHONEME_TAB *ph2;
|
||||
|
||||
+2
-2
@@ -1292,10 +1292,10 @@ static int attrnumber(const wchar_t *pw, int default_value, int type)
|
||||
{//==================================================================
|
||||
int value = 0;
|
||||
|
||||
if((pw == NULL) || !isdigit(*pw))
|
||||
if((pw == NULL) || !IsDigit09(*pw))
|
||||
return(default_value);
|
||||
|
||||
while(isdigit(*pw))
|
||||
while(IsDigit09(*pw))
|
||||
{
|
||||
value = value*10 + *pw++ - '0';
|
||||
}
|
||||
|
||||
+28
-20
@@ -160,13 +160,16 @@ void DisplayVoices(FILE *f_out, char *language)
|
||||
const char *p;
|
||||
int len;
|
||||
int count;
|
||||
int c;
|
||||
int j;
|
||||
const espeak_VOICE *v;
|
||||
const char *lang_name;
|
||||
char age_buf[12];
|
||||
char buf[80];
|
||||
const espeak_VOICE **voices;
|
||||
espeak_VOICE voice_select;
|
||||
|
||||
static char genders[4] = {' ','M','F',' '};
|
||||
static char genders[4] = {'-','M','F','-'};
|
||||
|
||||
if((language != NULL) && (language[0] != 0))
|
||||
{
|
||||
@@ -182,7 +185,7 @@ void DisplayVoices(FILE *f_out, char *language)
|
||||
voices = espeak_ListVoices(NULL);
|
||||
}
|
||||
|
||||
fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Langs\n");
|
||||
fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Languages\n");
|
||||
|
||||
for(ix=0; (v = voices[ix]) != NULL; ix++)
|
||||
{
|
||||
@@ -200,8 +203,16 @@ void DisplayVoices(FILE *f_out, char *language)
|
||||
|
||||
if(count==0)
|
||||
{
|
||||
fprintf(f_out,"%2d %-12s%s%c %-17s %-11s ",
|
||||
p[0],lang_name,age_buf,genders[v->gender],v->name,v->identifier);
|
||||
for(j=0; j < sizeof(buf); j++)
|
||||
{
|
||||
// replace spaces in the name
|
||||
if((c = v->name[j]) == ' ')
|
||||
c = '_';
|
||||
if((buf[j] = c) == 0)
|
||||
break;
|
||||
}
|
||||
fprintf(f_out,"%2d %-12s%s%c %-20s %-13s ",
|
||||
p[0],lang_name,age_buf,genders[v->gender],buf,v->identifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -750,11 +761,22 @@ int main (int argc, char **argv)
|
||||
init_path(argv[0],data_path);
|
||||
initialise();
|
||||
|
||||
if(voicename[0] == 0)
|
||||
strcpy(voicename,"default");
|
||||
|
||||
if(SetVoiceByName(voicename) != EE_OK)
|
||||
{
|
||||
memset(&voice_select,0,sizeof(voice_select));
|
||||
voice_select.languages = voicename;
|
||||
if(SetVoiceByProperties(&voice_select) != EE_OK)
|
||||
{
|
||||
fprintf(stderr,"%svoice '%s'\n",err_load,voicename);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if(flag_compile)
|
||||
{
|
||||
LoadVoice(voicename,5);
|
||||
|
||||
#ifdef PLATFORM_DOS
|
||||
char path_dsource[sizeof(path_home)+20];
|
||||
strcpy(path_dsource,path_home);
|
||||
@@ -776,20 +798,6 @@ int main (int argc, char **argv)
|
||||
}
|
||||
|
||||
|
||||
if(voicename[0] == 0)
|
||||
strcpy(voicename,"default");
|
||||
|
||||
if(SetVoiceByName(voicename) != EE_OK)
|
||||
{
|
||||
memset(&voice_select,0,sizeof(voice_select));
|
||||
voice_select.languages = voicename;
|
||||
if(SetVoiceByProperties(&voice_select) != EE_OK)
|
||||
{
|
||||
fprintf(stderr,"%svoice '%s'\n",err_load,voicename);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
SetParameter(espeakRATE,speed,0);
|
||||
SetParameter(espeakVOLUME,amp,0);
|
||||
SetParameter(espeakCAPITALS,option_capitals,0);
|
||||
|
||||
+18
-2
@@ -35,8 +35,8 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.46.53 16.Mar.13";
|
||||
const int version_phdata = 0x014640;
|
||||
const char *version_string = "1.47.03c 23.Mar.13";
|
||||
const int version_phdata = 0x014701;
|
||||
|
||||
int option_device_number = -1;
|
||||
FILE *f_logespeak = NULL;
|
||||
@@ -615,6 +615,7 @@ static int CountVowelPosition(PHONEME_LIST *plist)
|
||||
static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, USHORT *p_prog, WORD_PH_DATA *worddata)
|
||||
{//========================================================================================================================
|
||||
int which;
|
||||
int ix;
|
||||
unsigned int data;
|
||||
int instn;
|
||||
int instn2;
|
||||
@@ -705,6 +706,21 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist,
|
||||
return(false); // no previous vowel
|
||||
plist = &(worddata->prev_vowel);
|
||||
break;
|
||||
|
||||
case 9: // next3PhW
|
||||
for(ix=1; ix<=3; ix++)
|
||||
{
|
||||
if(plist[ix].sourceix)
|
||||
return(false);
|
||||
}
|
||||
plist = &plist[3];
|
||||
break;
|
||||
|
||||
case 10: // prev2PhW
|
||||
if((plist[0].sourceix) || (plist[-1].sourceix))
|
||||
return(false);
|
||||
plist-=2;
|
||||
break;
|
||||
}
|
||||
|
||||
if((which == 0) || (which == 5))
|
||||
|
||||
+28
-9
@@ -103,6 +103,19 @@ ALPHABET alphabets [] = {
|
||||
};
|
||||
|
||||
|
||||
ALPHABET *AlphabetFromName(const char *name)
|
||||
{//==========================================
|
||||
ALPHABET *alphabet;
|
||||
|
||||
for(alphabet=alphabets; alphabet->name != NULL; alphabet++)
|
||||
{
|
||||
if(strcmp(name, &alphabet->name[1]) == 0)
|
||||
return(alphabet);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
ALPHABET *AlphabetFromChar(int c)
|
||||
{//===============================
|
||||
// Find the alphabet from a character.
|
||||
@@ -276,8 +289,8 @@ static const char transpose_map_latin[] = {
|
||||
tr->langopts.param2[LOPT_BRACKET_PAUSE] = 2; // pauses when announcing bracket names
|
||||
tr->langopts.max_initial_consonants = 3;
|
||||
tr->langopts.replace_chars = NULL;
|
||||
tr->langopts.ascii_language = ""; // Non-Latin alphabet languages, use this language to speak Latin words, default is English
|
||||
|
||||
tr->langopts.ascii_language[0] = 0; // Non-Latin alphabet languages, use this language to speak Latin words, default is English
|
||||
tr->langopts.alt_alphabet_lang = L('e','n');
|
||||
|
||||
SetLengthMods(tr,201);
|
||||
// tr->langopts.length_mods = length_mods_en;
|
||||
@@ -526,9 +539,10 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.stress_flags = S_MID_DIM | S_FINAL_DIM; // use 'diminished' for unstressed final syllable
|
||||
tr->letter_bits_offset = OFFSET_BENGALI;
|
||||
SetIndicLetters(tr); // call this after setting OFFSET_BENGALI
|
||||
SetLetterBitsRange(tr,LETTERGP_B,0x01,0x01); // candranindu
|
||||
SetLetterBitsRange(tr,LETTERGP_F,0x3e,0x4c); // vowel signs, but not virama
|
||||
|
||||
tr->langopts.numbers = 0x1;
|
||||
tr->langopts.numbers = NUM_SWAP_TENS;
|
||||
tr->langopts.break_numbers = 0x24924aa8; // for languages which have numbers for 100,000 and 100,00,000, eg Hindi
|
||||
}
|
||||
break;
|
||||
@@ -666,7 +680,7 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.param[LOPT_SONORANT_MIN] = 130; // limit the shortening of sonorants before short vowels
|
||||
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA;
|
||||
tr->langopts.numbers2 = 0x2 | NUM2_MULTIPLE_ORDINAL; // variant form of numbers before thousands
|
||||
tr->langopts.numbers2 = 0x2 | NUM2_MULTIPLE_ORDINAL | NUM2_ORDINAL_NO_AND; // variant form of numbers before thousands
|
||||
|
||||
if(name2 == L_grc)
|
||||
{
|
||||
@@ -720,7 +734,7 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.param[LOPT_SONORANT_MIN] = 120; // limit the shortening of sonorants before short vowels
|
||||
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_AND_UNITS | NUM_OMIT_1_HUNDRED | NUM_OMIT_1_THOUSAND | NUM_ROMAN | NUM_ROMAN_AFTER;
|
||||
tr->langopts.numbers2 = NUM2_MULTIPLE_ORDINAL;
|
||||
tr->langopts.numbers2 = NUM2_MULTIPLE_ORDINAL | NUM2_ORDINAL_NO_AND;
|
||||
|
||||
if(name2 == L('c','a'))
|
||||
{
|
||||
@@ -732,7 +746,7 @@ Translator *SelectTranslator(const char *name)
|
||||
if(name2 == L('a','n'))
|
||||
{
|
||||
tr->langopts.stress_flags = S_FINAL_SPANISH | S_FINAL_DIM_ONLY | S_FINAL_NO_2;
|
||||
tr->langopts.numbers2 = 0;
|
||||
tr->langopts.numbers2 = NUM2_ORDINAL_NO_AND;
|
||||
}
|
||||
else
|
||||
if(name2 == L_pap)
|
||||
@@ -828,6 +842,7 @@ Translator *SelectTranslator(const char *name)
|
||||
{
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.numbers = 1;
|
||||
tr->langopts.accents = 2; // 'capital' after letter name
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -960,6 +975,7 @@ SetLengthMods(tr,3); // all equal
|
||||
break;
|
||||
|
||||
case L('i','d'): // Indonesian
|
||||
case L('m','s'): // Malay
|
||||
{
|
||||
static const short stress_lengths_id[8] = {160, 200, 180, 180, 0, 0, 220, 240};
|
||||
static const unsigned char stress_amps_id[8] = {16,18, 18,18, 20,22, 22,21 };
|
||||
@@ -1054,7 +1070,7 @@ SetLengthMods(tr,3); // all equal
|
||||
tr->langopts.numbers = NUM_VIGESIMAL | NUM_AND_UNITS | NUM_OMIT_1_HUNDRED |NUM_OMIT_1_THOUSAND | NUM_DFRACTION_5 | NUM_ROMAN;
|
||||
|
||||
tr->langopts.alt_alphabet = OFFSET_CYRILLIC;
|
||||
tr->langopts.alt_alphabet_lang = "ru";
|
||||
tr->langopts.alt_alphabet_lang = L('r','u');
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1084,6 +1100,7 @@ SetLengthMods(tr,3); // all equal
|
||||
|
||||
case L('k','l'): // Greenlandic
|
||||
{
|
||||
SetupTranslator(tr,stress_lengths_equal,stress_amps_equal);
|
||||
tr->langopts.stress_rule = 12;
|
||||
tr->langopts.stress_flags = S_NO_AUTO_2;
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_SWAP_TENS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_ORDINAL_DOT | NUM_1900 | NUM_ROMAN | NUM_ROMAN_CAPITALS | NUM_ROMAN_ORDINAL;
|
||||
@@ -1263,7 +1280,7 @@ SetLengthMods(tr,3); // all equal
|
||||
tr->langopts.stress_rule = STRESSPOSN_1R; // stress on final syllable
|
||||
tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2 | S_INITIAL_2 | S_PRIORITY_STRESS;
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_DFRACTION_2 | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_ROMAN;
|
||||
tr->langopts.numbers2 = NUM2_MULTIPLE_ORDINAL | NUM2_NO_TEEN_ORDINALS;
|
||||
tr->langopts.numbers2 = NUM2_MULTIPLE_ORDINAL | NUM2_NO_TEEN_ORDINALS | NUM2_ORDINAL_NO_AND;
|
||||
SetLetterVowel(tr,'y');
|
||||
ResetLetterBits(tr,0x2);
|
||||
SetLetterBits(tr,1,"bcdfgjkmnpqstvxz"); // B hard consonants, excluding h,l,r,w,y
|
||||
@@ -1296,7 +1313,7 @@ SetLengthMods(tr,3); // all equal
|
||||
tr->langopts.stress_rule = STRESSPOSN_2R;
|
||||
tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2;
|
||||
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
|
||||
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words. Need to allow "bw'" prefix
|
||||
tr->langopts.numbers = NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_DFRACTION_2 | NUM_AND_HUNDRED;
|
||||
tr->langopts.numbers2 = 0x200; // say "thousands" before its number
|
||||
}
|
||||
@@ -1413,6 +1430,8 @@ SetLengthMods(tr,3); // all equal
|
||||
tr->langopts.vowel_pause = 1;
|
||||
tr->langopts.stress_rule = STRESSPOSN_2R;
|
||||
tr->langopts.stress_flags = S_FINAL_DIM_ONLY | S_FINAL_NO_2;
|
||||
tr->langopts.max_initial_consonants = 4; // for example: mwngi
|
||||
|
||||
|
||||
tr->langopts.numbers = NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_SINGLE_AND | NUM_OMIT_1_HUNDRED;
|
||||
tr->langopts.break_numbers = 0x49249268; // for languages which have numbers for 100,000 and 1,000,000
|
||||
|
||||
+7
-6
@@ -378,6 +378,7 @@ void SetLengthMods(Translator *tr, int value)
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsAlpha(unsigned int c)
|
||||
{//========================
|
||||
// Replacement for iswalph() which also checks for some in-word symbols
|
||||
@@ -433,8 +434,8 @@ int IsAlpha(unsigned int c)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int IsDigit09(unsigned int c)
|
||||
{//=========================
|
||||
int IsDigit09(unsigned int c)
|
||||
{//============================
|
||||
if((c >= '0') && (c <= '9'))
|
||||
return(1);
|
||||
return(0);
|
||||
@@ -971,7 +972,7 @@ int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wt
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((found==0) && (dictionary_flags[0] & FLAG_SKIPWORDS))
|
||||
else if((found==0) && (dictionary_flags[0] & FLAG_SKIPWORDS) && !(dictionary_flags[0] & FLAG_ABBREV))
|
||||
{
|
||||
// grouped words, but no translation. Join the words with hyphens.
|
||||
wordx = word1;
|
||||
@@ -2315,10 +2316,10 @@ static int EmbeddedCommand(unsigned int &source_index)
|
||||
source_index++;
|
||||
}
|
||||
|
||||
if(isdigit(source[source_index]))
|
||||
if(IsDigit09(source[source_index]))
|
||||
{
|
||||
value = atoi(&source[source_index]);
|
||||
while(isdigit(source[source_index]))
|
||||
while(IsDigit09(source[source_index]))
|
||||
source_index++;
|
||||
}
|
||||
|
||||
@@ -3335,7 +3336,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
|
||||
while(pn < &number_buf[sizeof(number_buf)-20])
|
||||
{
|
||||
if(!isdigit(c = *pw++) && (c != tr->langopts.decimal_sep))
|
||||
if(!IsDigit09(c = *pw++) && (c != tr->langopts.decimal_sep))
|
||||
break;
|
||||
|
||||
*pn++ = c;
|
||||
|
||||
+7
-2
@@ -83,6 +83,7 @@
|
||||
#define FLAG_STEM 0x10000 // must have a suffix
|
||||
#define FLAG_ATEND 0x20000 /* use this pronunciation if at end of clause */
|
||||
#define FLAG_ATSTART 0x40000 // use this pronunciation if at start of clause
|
||||
#define FLAG_LOOKUP_SYMBOL 0x40000000 // to indicate called from Lookup()
|
||||
|
||||
#define BITNUM_FLAG_ALLCAPS 0x2a
|
||||
#define BITNUM_FLAG_HYPHENATED 0x2c
|
||||
@@ -502,6 +503,7 @@ typedef struct {
|
||||
#define NUM2_THOUSANDS_VAR4 0x100
|
||||
#define NUM2_THOUSANDS_VAR5 0x140
|
||||
|
||||
#define NUM2_ORDINAL_NO_AND 0x800
|
||||
#define NUM2_MULTIPLE_ORDINAL 0x1000
|
||||
#define NUM2_NO_TEEN_ORDINALS 0x2000
|
||||
#define NUM2_MYRIADS 0x4000
|
||||
@@ -510,6 +512,7 @@ typedef struct {
|
||||
// bits 1-4 use variant form of numbers before thousands,millions,etc.
|
||||
// bits 6-8 use different forms of thousand, million, etc (M MA MB)
|
||||
// bit9=(LANG=rw) say "thousand" and "million" before its number, not after
|
||||
// bit11=(LANG=es,an) don't say 'and' between tens and units for ordinal numbers
|
||||
// bit12=(LANG=el,es) use ordinal form of hundreds and tens as well as units
|
||||
// bit13=(LANG=pt) don't use 11-19 numbers to make ordinals
|
||||
// bit14=(LANG=ko) use myriads (groups of 4 digits) not thousands (groups of 3)
|
||||
@@ -542,9 +545,9 @@ typedef struct {
|
||||
int testing; // testing options: bit 1= specify stressed syllable in the form: "outdoor/2"
|
||||
int listx; // compile *_listx after *list
|
||||
const unsigned int *replace_chars; // characters to be substitutes
|
||||
const char *ascii_language; // switch to this language for Latin characters
|
||||
char ascii_language[8]; // switch to this language for Latin characters
|
||||
int alt_alphabet; // offset for another language to recognize
|
||||
const char *alt_alphabet_lang; // language for the alt_alphabet
|
||||
int alt_alphabet_lang; // language for the alt_alphabet
|
||||
int max_lengthmod;
|
||||
int lengthen_tonic; // lengthen the tonic syllable
|
||||
int suffix_add_e; // replace a suffix (which has the SUFX_E flag) with this character
|
||||
@@ -706,6 +709,7 @@ void InitNamedata(void);
|
||||
void InitText(int flags);
|
||||
void InitText2(void);
|
||||
int IsDigit(unsigned int c);
|
||||
int IsDigit09(unsigned int c);
|
||||
int IsAlpha(unsigned int c);
|
||||
int IsVowel(Translator *tr, int c);
|
||||
int isspace2(unsigned int c);
|
||||
@@ -713,6 +717,7 @@ int towlower2(unsigned int c);
|
||||
void GetTranslatedPhonemeString(char *phon_out, int n_phon_out, int use_ipa);
|
||||
const char *WordToString2(unsigned int word);
|
||||
ALPHABET *AlphabetFromChar(int c);
|
||||
ALPHABET *AlphabetFromName(const char *name);
|
||||
|
||||
Translator *SelectTranslator(const char *name);
|
||||
int SetTranslator2(const char *name);
|
||||
|
||||
+78
-19
@@ -110,6 +110,7 @@ enum {
|
||||
V_FAST,
|
||||
V_SPEED,
|
||||
V_DICTMIN,
|
||||
V_ALPHABET2,
|
||||
|
||||
// these need a phoneme table to have been specified
|
||||
V_REPLACE,
|
||||
@@ -161,6 +162,7 @@ static MNEM_TAB keyword_tab[] = {
|
||||
{"fast_test2", V_FAST},
|
||||
{"speed", V_SPEED},
|
||||
{"dict_min", V_DICTMIN},
|
||||
{"alphabet2", V_ALPHABET2},
|
||||
|
||||
// these just set a value in langopts.param[]
|
||||
{"l_dieresis", 0x100+LOPT_DIERESES},
|
||||
@@ -396,10 +398,10 @@ void VoiceReset(int tone_only)
|
||||
// Set voice to the default values
|
||||
|
||||
int pk;
|
||||
// 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_heights[N_PEAKS] = {130,128,120,116,100,100,128,128,128}; // changed for v.1.47
|
||||
static unsigned char default_widths[N_PEAKS] = {140,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] = {128,128,128,160,171,171,128,128,128};
|
||||
|
||||
static int breath_widths[N_PEAKS] = {0,200,200,400,400,400,600,600,600};
|
||||
|
||||
@@ -420,7 +422,7 @@ void VoiceReset(int tone_only)
|
||||
voice->n_harmonic_peaks = 5;
|
||||
voice->peak_shape = 0;
|
||||
voice->voicing = 64;
|
||||
voice->consonant_amp = 85; // change to 85 for v.1.47 was 100
|
||||
voice->consonant_amp = 90; // change to 85 for v.1.47 was 100
|
||||
voice->consonant_ampv = 100;
|
||||
voice->samplerate = samplerate_native;
|
||||
memset(voice->klattv,0,sizeof(voice->klattv));
|
||||
@@ -448,7 +450,6 @@ void VoiceReset(int tone_only)
|
||||
// adjust formant smoothing depending on sample rate
|
||||
formant_rate[pk] = (formant_rate_22050[pk] * 22050)/samplerate;
|
||||
}
|
||||
voice->height[2] = 240; // reduce F2 slightly
|
||||
|
||||
// This table provides the opportunity for tone control.
|
||||
// Adjustment of harmonic amplitudes, steps of 8Hz
|
||||
@@ -532,6 +533,21 @@ static int Read8Numbers(char *data_in,int *data)
|
||||
}
|
||||
|
||||
|
||||
static unsigned int StringToWord2(const char *string)
|
||||
{//======================================================
|
||||
// Convert a language name string to a word such as L('e','n')
|
||||
int ix;
|
||||
int c;
|
||||
unsigned int value = 0;
|
||||
|
||||
for(ix=0; (ix<4) & ((c = string[ix]) != 0); ix++)
|
||||
{
|
||||
value = (value << 8) | (c & 0xff);
|
||||
}
|
||||
return(value);
|
||||
}
|
||||
|
||||
|
||||
voice_t *LoadVoice(const char *vname, int control)
|
||||
{//===============================================
|
||||
// control, bit 0 1= no_default
|
||||
@@ -573,6 +589,7 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
int stress_lengths[8];
|
||||
int stress_add[8];
|
||||
char names[8][40];
|
||||
char name1[40];
|
||||
char name2[80];
|
||||
const char *voice_dir;
|
||||
|
||||
@@ -583,11 +600,11 @@ 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
|
||||
|
||||
// which directory to look for a named voice
|
||||
// which directory to look for a named voice. List of voice names, must end in a space.
|
||||
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 ";
|
||||
"fa fa-pin hi hy hy-west id ka kn ku ml ms ne pa ta tr vi vi-hue zh zh-yue ";
|
||||
static const char *voices_europe =
|
||||
"an 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 ";
|
||||
"an bg bs ca cs cy da de el en en-us es et fi fr fr-be ga hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";
|
||||
|
||||
|
||||
strncpy0(voicename, vname, sizeof(voicename));
|
||||
@@ -962,12 +979,10 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
case V_MBROLA:
|
||||
{
|
||||
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)
|
||||
name2[0] = 0;
|
||||
sscanf(p,"%s %s %d",name1,name2,&srate);
|
||||
if(LoadMbrolaTable(name1,name2,srate) != EE_OK)
|
||||
{
|
||||
fprintf(stderr,"mbrola voice not found\n");
|
||||
}
|
||||
@@ -990,6 +1005,28 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
sscanf(p,"%d",&dict_min);
|
||||
break;
|
||||
|
||||
case V_ALPHABET2:
|
||||
{
|
||||
ALPHABET *alphabet;
|
||||
name1[0] = name2[0] = 0;
|
||||
sscanf(p, "%s %s", name1, name2);
|
||||
|
||||
if(strcmp(name1, "latin") == 0)
|
||||
{
|
||||
strncpy0(langopts->ascii_language,name2,sizeof(langopts->ascii_language));
|
||||
}
|
||||
else if((alphabet = AlphabetFromName(name1)) != 0)
|
||||
{
|
||||
langopts->alt_alphabet = alphabet->offset;
|
||||
langopts->alt_alphabet_lang = StringToWord2(name2);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"alphabet name '%s' not found\n", name1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if((key & 0xff00) == 0x100)
|
||||
{
|
||||
@@ -1098,7 +1135,7 @@ static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir)
|
||||
// The voice name has a +variant suffix
|
||||
variant_num = 0;
|
||||
*p++ = 0; // delete the suffix from the voice name
|
||||
if(isdigit(*p))
|
||||
if(IsDigit09(*p))
|
||||
{
|
||||
variant_num = atoi(p); // variant number
|
||||
}
|
||||
@@ -1191,10 +1228,10 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s
|
||||
|
||||
p = voice->languages; // list of languages+dialects for which this voice is suitable
|
||||
|
||||
if(strcmp(spec_language,"mbrola")==0)
|
||||
if(spec_n_parts < 0)
|
||||
{
|
||||
// only list mbrola voices
|
||||
if(memcmp(voice->identifier,"mb/",3) == 0)
|
||||
// match on the subdirectory
|
||||
if(memcmp(voice->identifier, spec_language, spec_lang_len) == 0)
|
||||
return(100);
|
||||
return(0);
|
||||
}
|
||||
@@ -1327,6 +1364,7 @@ static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int
|
||||
int lang_len=0;
|
||||
espeak_VOICE *vp;
|
||||
char language[80];
|
||||
char buf[sizeof(path_home)+80];
|
||||
|
||||
// count number of parts in the specified language
|
||||
if((voice_select->languages != NULL) && (voice_select->languages[0] != 0))
|
||||
@@ -1339,6 +1377,26 @@ static int SetVoiceScores(espeak_VOICE *voice_select, espeak_VOICE **voices, int
|
||||
n_parts++;
|
||||
}
|
||||
}
|
||||
|
||||
if((n_parts == 1) && (control & 1))
|
||||
{
|
||||
if(strcmp(language, "mbrola") == 0)
|
||||
{
|
||||
language[2] = 0; // truncate to "mb"
|
||||
lang_len = 2;
|
||||
}
|
||||
|
||||
sprintf(buf, "%s/voices/%s", path_home, language);
|
||||
if(GetFileLength(buf) == -2)
|
||||
{
|
||||
// A subdirectory name has been specified. List all the voices in that subdirectory
|
||||
language[lang_len++] = PATHSEP;
|
||||
language[lang_len] = 0;
|
||||
n_parts = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// select those voices which match the specified language
|
||||
nv = 0;
|
||||
for(ix=0; ix<n_voices_list; ix++)
|
||||
@@ -1866,11 +1924,12 @@ ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec)
|
||||
}
|
||||
else
|
||||
{
|
||||
// list all: omit variant voices and mbrola voices
|
||||
// list all: omit variant voices and mbrola voices and test voices
|
||||
j = 0;
|
||||
for(ix=0; (v = voices_list[ix]) != NULL; ix++)
|
||||
{
|
||||
if((v->languages[0] != 0) && (strcmp(&v->languages[1],"variant") != 0) && (memcmp(v->identifier,"mb/",3) != 0))
|
||||
if((v->languages[0] != 0) && (strcmp(&v->languages[1],"variant") != 0)
|
||||
&& (memcmp(v->identifier,"mb/",3) != 0) && (memcmp(v->identifier,"test/",5) != 0))
|
||||
{
|
||||
voices[j++] = v;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user