Merge branch 'master' into android

Conflicts:
	platforms/windows/make_espeakedit.iss
This commit is contained in:
Reece H. Dunn
2013-03-26 02:59:43 +00:00
95 changed files with 2765 additions and 5014 deletions
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}