[1.46.39]

Fixes to speaking characters from foreign alphabets.
Allow $textmode and $text to translate between words in different alphabets.


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@305 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
jonsd
2013-03-01 20:45:05 +00:00
parent 6ee501b5bb
commit 3eb5cb58d7
25 changed files with 687 additions and 568 deletions
+38 -29
View File
@@ -51,15 +51,21 @@ static char letterGroupsDefined[N_LETTER_GROUPS];
MNEM_TAB mnem_rules[] = {
{"unpr", 0x01},
{"w_alt1", 0x11},
{"w_alt2", 0x12},
{"w_alt3", 0x13},
// {"w_alt4", 0x14},
{"w_alt4", 0x14},
{"w_alt5", 0x15},
{"w_alt6", 0x16},
{"w_alt", 0x11}, // note: put longer names before their sub-strings
{"p_alt1", 0x21},
{"p_alt2", 0x22},
{"p_alt3", 0x23},
// {"p_alt4", 0x24},
{"p_alt4", 0x24},
{"p_alt5", 0x25},
{"p_alt6", 0x26},
{"p_alt", 0x21},
{NULL, -1} };
@@ -83,24 +89,22 @@ MNEM_TAB mnem_flags[] = {
// these set the corresponding numbered bit if dictionary_flags
{"$pause", 8}, /* ensure pause before this word */
{"$only", 9}, /* only match on this word without suffix */
{"$onlys", 10}, /* only match with none, or with 's' suffix */
{"$strend", 11}, /* full stress if at end of clause */
{"$strend2", 12}, /* full stress if at end of clause, or only followed by unstressed */
{"$unstressend",13}, /* reduce stress at end of clause */
{"$atend", 14}, /* use this pronunciation if at end of clause */
{"$atstart", 15}, // use this pronunciation at start of clause
{"$abbrev", 17}, /* use this pronuciation rather than split into letters */
{"$stem", 18}, // must have a suffix
{"$pause", 8}, // ensure pause before this word
{"$strend", 9}, // full stress if at end of clause
{"$strend2", 10}, // full stress if at end of clause, or only followed by unstressed
{"$unstressend",11}, // reduce stress at end of clause
{"$abbrev", 13}, // use this pronuciation rather than split into letters
// language specific
{"$double", 19}, // IT double the initial consonant of next word
{"$alt", 20}, // use alternative pronunciation
{"$alt1", 20}, // synonym for $alt
{"$alt2", 21},
{"$alt3", 22},
{"$double", 14}, // IT double the initial consonant of next word
{"$alt", 15}, // use alternative pronunciation
{"$alt1", 15}, // synonym for $alt
{"$alt2", 16},
{"$alt3", 17},
{"$alt4", 18},
{"$alt5", 19},
{"$alt6", 20},
{"$combine", 23}, // Combine with the next word
{"$dot", 24}, // ignore '.' after this word (abbreviation)
@@ -111,18 +115,23 @@ MNEM_TAB mnem_flags[] = {
{"$text", 29}, // word translates to replcement text, not phonemes
// flags in dictionary word 2
{"$verbf", 0x20}, /* verb follows */
{"$verbsf", 0x21}, /* verb follows, allow -s suffix */
{"$nounf", 0x22}, /* noun follows */
{"$pastf", 0x23}, /* past tense follows */
{"$verb", 0x24}, /* use this pronunciation when its a verb */
{"$noun", 0x25}, /* use this pronunciation when its a noun */
{"$past", 0x26}, /* use this pronunciation when its past tense */
{"$verbextend",0x28}, /* extend influence of 'verb follows' */
{"$capital", 0x29}, /* use this pronunciation if initial letter is upper case */
{"$allcaps", 0x2a}, /* use this pronunciation if initial letter is upper case */
{"$verbf", 0x20}, // verb follows
{"$verbsf", 0x21}, // verb follows, allow -s suffix
{"$nounf", 0x22}, // noun follows
{"$pastf", 0x23}, // past tense follows
{"$verb", 0x24}, // use this pronunciation when its a verb
{"$noun", 0x25}, // use this pronunciation when its a noun
{"$past", 0x26}, // use this pronunciation when its past tense
{"$verbextend",0x28}, // extend influence of 'verb follows'
{"$capital", 0x29}, // use this pronunciation if initial letter is upper case
{"$allcaps", 0x2a}, // use this pronunciation if initial letter is upper case
{"$accent", 0x2b}, // character name is base-character name + accent name
{"$sentence",0x2d}, // only if this clause is a sentence (i.e. terminator is {. ? !} not {, ; :}
{"$only", 0x2e}, // only match on this word without suffix
{"$onlys", 0x2f}, // only match with none, or with 's' suffix
{"$stem", 0x30}, // must have a suffix
{"$atend", 0x31}, // use this pronunciation if at end of clause
{"$atstart", 0x32}, // use this pronunciation at start of clause
// doesn't set dictionary_flags
{"$?", 100}, // conditional rule, followed by byte giving the condition number
@@ -611,7 +620,7 @@ static char nullstring[] = {0};
// PROBLEM vowel reductions are not applied to the translated phonemes
// condition rules are not applied
TranslateWord(translator,phonetic,0,NULL);
TranslateWord(translator,phonetic,0,NULL,NULL);
text_not_phonemes = 0;
strncpy0(encoded_ph, word_phonemes, N_WORD_BYTES-4);
+14 -7
View File
@@ -3012,10 +3012,10 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
int no_phonemes;
int skipwords;
int ix;
int c;
const char *word_end;
const char *word1;
int wflags = 0;
// int wflags2;
char word_buf[N_WORD_BYTES+1];
if(wtab != NULL)
@@ -3165,20 +3165,20 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
if((end_flags & FLAG_SUFX)==0)
{
// no suffix has been removed
if(dictionary_flags & FLAG_STEM)
if(dictionary_flags2 & FLAG_STEM)
continue; // this word must have a suffix
}
if((end_flags & SUFX_P) && (dictionary_flags & (FLAG_ONLY | FLAG_ONLY_S)))
if((end_flags & SUFX_P) && (dictionary_flags2 & (FLAG_ONLY | FLAG_ONLY_S)))
continue; // $only or $onlys, don't match if a prefix has been removed
if(end_flags & FLAG_SUFX)
{
// a suffix was removed from the word
if(dictionary_flags & FLAG_ONLY)
if(dictionary_flags2 & FLAG_ONLY)
continue; // no match if any suffix
if((dictionary_flags & FLAG_ONLY_S) && ((end_flags & FLAG_SUFX_S)==0))
if((dictionary_flags2 & FLAG_ONLY_S) && ((end_flags & FLAG_SUFX_S)==0))
{
// only a 's' suffix allowed, but the suffix wasn't 's'
continue;
@@ -3212,13 +3212,13 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
continue;
}
if((dictionary_flags & FLAG_ATEND) && (word_end < tr->clause_end))
if((dictionary_flags2 & FLAG_ATEND) && (word_end < tr->clause_end))
{
// only use this pronunciation if it's the last word of the clause
continue;
}
if((dictionary_flags & FLAG_ATSTART) && !(wtab->flags & FLAG_FIRST_WORD))
if((dictionary_flags2 & FLAG_ATSTART) && !(wtab->flags & FLAG_FIRST_WORD))
{
// only use this pronunciation if it's the first word of a clause
continue;
@@ -3318,6 +3318,12 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
fprintf(f_trans,"' [%s] %s\n",ph_decoded,print_dictionary_flags(flags));
}
}
ix = utf8_in(&c, word);
if((word[ix] == 0) && !IsAlpha(c))
{
flags[0] |= FLAG_MAX3;
}
return(word_end);
}
@@ -3390,6 +3396,7 @@ int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *f
found = LookupDict2(tr, word, word1, ph_out, flags, end_flags, wtab);
if(flags[0] & FLAG_MAX3)
{
if(strcmp(ph_out, tr->phonemes_repeat) == 0)
+5 -5
View File
@@ -464,7 +464,7 @@ void Lexicon_It(int pass)
}
// translate
TranslateWord(translator,&word1[1],0, NULL);
TranslateWord(translator,&word1[1],0, NULL, NULL);
DecodePhonemes(word_phonemes,phonemes);
stress_posn1 = 0;
@@ -487,7 +487,7 @@ void Lexicon_It(int pass)
vowel_ix++;
}
TranslateWord(translator,&word2[1],0, NULL);
TranslateWord(translator,&word2[1],0, NULL, NULL);
DecodePhonemes(word_phonemes,phonemes2);
vowel_ix = 1;
@@ -802,7 +802,7 @@ void Lexicon_De()
}
// translate
TranslateWord(translator,&word2[1],0, NULL);
TranslateWord(translator,&word2[1],0, NULL, NULL);
DecodePhonemes2(word_phonemes,phonemes); // also need to change some phoneme names
@@ -1042,7 +1042,7 @@ void Lexicon_Bg()
*pw1 = 0;
// translate
TranslateWord(translator, &word[2],0, NULL);
TranslateWord(translator, &word[2],0, NULL, NULL);
DecodePhonemes(word_phonemes,phonemes);
// find the stress position in the translation
@@ -1300,7 +1300,7 @@ void Lexicon_Ru()
}
// translate
TranslateWord(translator, &word2[1],0, NULL);
TranslateWord(translator, &word2[1],0, NULL, NULL);
DecodePhonemes(word_phonemes,phonemes);
// find the stress position in the translation
+2 -2
View File
@@ -89,10 +89,10 @@ wxMenuBar *MakeMenu(int type, const char *dict_name)
// DATA MENU
data_menu = new wxMenu;
data_menu->Append(MENU_COMPILE_PH, _("Compile &phoneme data"));
data_menu->Append(MENU_COMPILE_PH2, _("Change sample &rate"));
data_menu->Append(MENU_COMPILE_DICT, _("Compile &dictionary"));
data_menu->Append(MENU_COMPILE_DICT_DEBUG, _("Compile dictionary (debu&g)"));
data_menu->Append(MENU_COMPILE_PH, _("Compile &phoneme data"));
data_menu->Append(MENU_COMPILE_PH2, _("Change sample &rate"));
data_menu->AppendSeparator();
data_menu->Append(MENU_COMPILE_MBROLA, _("Compile &mbrola phonemes list..."));
data_menu->Append(MENU_COMPILE_INTONATION, _("Compile &intonation data"));
+23 -11
View File
@@ -656,20 +656,32 @@ int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
current_alphabet = alphabet;
if((alphabet != NULL) && !(alphabet->flags & AL_DONT_NAME))
{
phontab_1 = tr->phoneme_tab_ix;
ph_buf2[0] = 0;
if(Lookup(translator, alphabet->name, ph_alphabet) == 0) // the original language for the current voice
{
// Can't find the local name for this alphabet, use the English name
phontab_1 = tr->phoneme_tab_ix;
ph_alphabet[2] = SetTranslator2("en"); // overwrites previous contents of translator2
if(Lookup(translator2, alphabet->name, &ph_alphabet[3]) != 0)
{
ph_alphabet[0] = phonPAUSE;
ph_alphabet[1] = phonSWITCH;
len = strlen(&ph_alphabet[3]) + 3;
ph_alphabet[len] = phonSWITCH; // switch back
ph_alphabet[len+1] = phontab_1;
ph_alphabet[len+2] = 0;
}
Lookup(translator2, alphabet->name, ph_buf2);
}
else
if(translator != tr)
{
phontab_1 = tr->phoneme_tab_ix;
strcpy(ph_buf2, ph_alphabet);
ph_alphabet[2] = translator->phoneme_tab_ix;
}
if(ph_buf2[0] != 0)
{
// we used a different language for the alphabet name (now in ph_buf2)
ph_alphabet[0] = phonPAUSE;
ph_alphabet[1] = phonSWITCH;
strcpy(&ph_alphabet[3], ph_buf2);
len = strlen(ph_buf2) + 3;
ph_alphabet[len] = phonSWITCH;
ph_alphabet[len+1] = phontab_1;
ph_alphabet[len+2] = 0;
}
}
}
@@ -876,7 +888,7 @@ static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB
nextflags = 0;
if(IsAlpha(c2))
{
nextflags = TranslateWord(tr, &word_end[2], 0, NULL);
nextflags = TranslateWord(tr, &word_end[2], 0, NULL, NULL);
}
if((tr->prev_dict_flags & FLAG_ALT_TRANS) && ((c2 == 0) || (wtab[0].flags & FLAG_COMMA_AFTER) || iswdigit(c2)))
+2 -2
View File
@@ -35,8 +35,8 @@
#include "translate.h"
#include "wave.h"
const char *version_string = "1.46.38 27.Feb.13";
const int version_phdata = 0x014636;
const char *version_string = "1.46.39 01.Mar.13";
const int version_phdata = 0x014639;
int option_device_number = -1;
FILE *f_logespeak = NULL;
+7
View File
@@ -808,6 +808,13 @@ Translator *SelectTranslator(const char *name)
}
break;
case L('g','a'): // irish
{
tr->langopts.stress_rule = STRESSPOSN_1L;
tr->langopts.numbers = 1;
}
break;
case L('h','i'): // Hindi
case L('n','e'): // Nepali
case L('p','a'): // Punjabi
+19 -7
View File
@@ -807,8 +807,8 @@ int ChangeEquivalentPhonemes(Translator *tr, int lang2, char *phonemes)
int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wtab)
{//===========================================================================
int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wtab, char *word_out)
{//==================================================================================================
// word1 is terminated by space (0x20) character
char *word1;
@@ -943,6 +943,9 @@ int TranslateWord(Translator *tr, char *word_start, int next_pause, WORD_TAB *wt
if(dictionary_flags[0] & FLAG_TEXTMODE)
{
if(word_out != NULL)
strcpy(word_out, word1);
first_char = word1[0];
stress_bits = dictionary_flags[0] & 0x7f;
found = LookupDictList(tr, &word1, phonemes, dictionary_flags2, 0, wtab); // the text replacement
@@ -1760,6 +1763,7 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
int word_flags;
int word_copy_len;
char word_copy[N_WORD_BYTES+1];
char word_replaced[N_WORD_BYTES+1];
char old_dictionary_name[40];
if((f_logespeak != NULL) && (logging_type & 8))
@@ -1871,7 +1875,8 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
while(((c2 = word_copy[ix] = word[ix]) != ' ') && (c2 != 0) && (ix < N_WORD_BYTES)) ix++;
word_copy_len = ix;
flags = TranslateWord(translator, word, next_pause, wtab);
word_replaced[2] = 0;
flags = TranslateWord(translator, word, next_pause, wtab, &word_replaced[2]);
if(flags & FLAG_SPELLWORD)
{
@@ -1906,7 +1911,7 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
{
strcpy(ph_buf,word_phonemes);
flags2[0] = TranslateWord(translator, p2+1, 0, wtab+1);
flags2[0] = TranslateWord(translator, p2+1, 0, wtab+1, NULL);
if((flags2[0] & FLAG_WAS_UNPRONOUNCABLE) || (word_phonemes[0] == phonSWITCH))
ok = 0;
@@ -1934,12 +1939,12 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
if(ok)
{
*p2 = '-'; // replace next space by hyphen
flags = TranslateWord(translator, word, next_pause, wtab); // translate the combined word
flags = TranslateWord(translator, word, next_pause, wtab, NULL); // translate the combined word
if((sylimit > 0) && (CountSyllables(p) > (sylimit & 0x1f)))
{
// revert to separate words
*p2 = ' ';
flags = TranslateWord(translator, word, next_pause, wtab);
flags = TranslateWord(translator, word, next_pause, wtab, NULL);
}
else
{
@@ -1967,7 +1972,14 @@ static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pa
{
// re-translate the word using the new translator
wtab[0].flags |= FLAG_TRANSLATOR2;
flags = TranslateWord(translator2, word, next_pause, wtab);
if(word_replaced[2] != 0)
{
word_replaced[0] = 0; // byte before the start of the word
word_replaced[1] = ' ';
flags = TranslateWord(translator2, &word_replaced[1], next_pause, wtab, NULL);
}
else
flags = TranslateWord(translator2, word, next_pause, wtab, NULL);
// strcpy((char *)p,translator2->word_phonemes);
if(p[0] == phonSWITCH)
{
+20 -20
View File
@@ -37,26 +37,18 @@
#define FLAG_SKIPWORDS 0x80
#define FLAG_PREPAUSE 0x100
#define FLAG_ONLY 0x200
#define FLAG_ONLY_S 0x400
#define BITNUM_FLAG_ONLY 9 // bit 9 is set
#define BITNUM_FLAG_ONLY_S 10 // bit 10 is set
#define FLAG_STRESS_END 0x200 // full stress if at end of clause
#define FLAG_STRESS_END2 0x400 // full stress if at end of clause, or only followed by unstressed
#define FLAG_UNSTRESS_END 0x800 // reduce stress at end of clause
#define FLAG_SPELLWORD 0x1000 // re-translate the word as individual letters, separated by spaces
#define FLAG_ABBREV 0x2000 // spell as letters, even with a vowel, OR use specified pronunciation rather than split into letters
#define FLAG_DOUBLING 0x4000 // doubles the following consonant
#define FLAG_STRESS_END 0x800 /* full stress if at end of clause */
#define FLAG_STRESS_END2 0x1000 /* full stress if at end of clause, or only followed by unstressed */
#define FLAG_UNSTRESS_END 0x2000 /* reduce stress at end of clause */
#define FLAG_ATEND 0x4000 /* use this pronunciation if at end of clause */
#define FLAG_ATSTART 0x8000 // use this pronunciation if at start of clause
#define FLAG_SPELLWORD 0x10000 // re-translate the word as individual letters, separated by spaces
#define FLAG_ABBREV 0x20000 // spell as letters, even with a vowel, OR use specified pronunciation rather than split into letters
#define FLAG_STEM 0x40000 // must have a suffix
#define FLAG_DOUBLING 0x80000 // doubles the following consonant
#define BITNUM_FLAG_ALT 19 // bit number of FLAG_ALT_TRANS - 1
#define FLAG_ALT_TRANS 0x100000 // language specific
#define FLAG_ALT2_TRANS 0x200000 // language specific
#define FLAG_ALT3_TRANS 0x400000 // language specific
#define FLAG_COMBINE 0x800000 // combine with the next word
#define BITNUM_FLAG_ALT 14 // bit number of FLAG_ALT_TRANS - 1
#define FLAG_ALT_TRANS 0x8000 // language specific
#define FLAG_ALT2_TRANS 0x10000 // language specific
#define FLAG_ALT3_TRANS 0x20000 // language specific
#define FLAG_COMBINE 0x40000 // combine with the next word
#define FLAG_ALLOW_DOT 0x01000000 // ignore '.' after word (abbreviation)
#define FLAG_NEEDS_DOT 0x02000000 // only if the word is followed by a dot
@@ -83,8 +75,16 @@
#define FLAG_ACCENT 0x800 // character name is base-character name + accent name
#define FLAG_HYPHENATED 0x1000 // multiple-words, but needs hyphen between parts 1 and 2
#define FLAG_SENTENCE 0x2000 // only if the clause is a sentence
#define FLAG_ONLY 0x4000
#define FLAG_ONLY_S 0x8000
#define FLAG_STEM 0x10000 // must have a suffix
#define FLAG_ATEND 0x20000 /* use this pronunciation if at end of clause */
#define FLAG_ATSTART 0x30000 // use this pronunciation if at start of clause
#define BITNUM_FLAG_ALLCAPS 0x2a
#define BITNUM_FLAG_HYPHENATED 0x2c
#define BITNUM_FLAG_ONLY 0x2e
#define BITNUM_FLAG_ONLY_S 0x2f
// wordflags, flags in source word
@@ -714,7 +714,7 @@ int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy);
int Unpronouncable(Translator *tr, char *word, int posn);
void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags, int tonic, int prev_stress);
int TranslateRules(Translator *tr, char *p, char *phonemes, int size, char *end_phonemes, int end_flags, unsigned int *dict_flags);
int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab);
int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab, char *word_out);
void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *tone, char **voice_change);
int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix_top, int n_buf, int *tone_type, char *voice_change);
+13 -6
View File
@@ -798,14 +798,25 @@ voice_t *LoadVoice(const char *vname, int control)
break;
case V_DICTRULES: // conditional dictionary rules and list entries
case V_NUMBERS:
// 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((key==V_DICTRULES) && (n < 32))
conditional_rules |= (1 << n);
else
if((key==V_NUMBERS) && (n < 32))
langopts->numbers |= (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++;
}
@@ -837,10 +848,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))
+1 -1
View File
@@ -535,7 +535,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t* time)
#else
// notdef USE_SADA
void wave_init() {}
init wave_init() {}
void* wave_open(const char* the_api) {return (void *)1;}
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {return theSize;}
int wave_close(void* theHandler) {return 0;}