[1.24.12] Produce dictsource/dict_phonemes, a list of which phonemes are used by each language's *_rules and *_list files.

Fix crash with -X option when spelling words (acronyms).
Rules files: added special character X meaning "no vowel until the word boundary". Used for lang=no.


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@14 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
jonsd
2007-05-18 10:52:23 +00:00
parent 50136a6da2
commit f65bf2072b
26 changed files with 266 additions and 110 deletions
+88
View File
@@ -75,6 +75,7 @@
extern void Write4Bytes(FILE *f, int value);
extern void MakeVowelLists(void);
extern void FindPhonemesUsed(void);
extern int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname);
extern char voice_name[];
@@ -1824,6 +1825,76 @@ void Compile::Report(void)
}
static int ph_sorter(char **a, char **b)
{//======================================
int ix;
int t1, t2;
char mnem1[6];
PHONEME_TAB *p1 = (PHONEME_TAB *)(*a);
PHONEME_TAB *p2 = (PHONEME_TAB *)(*b);
t1 = p1->type;
if(t1 > phVOWEL) t1 = phVOWEL+1;
t2 = p2->type;
if(t2 > phVOWEL) t2 = phVOWEL+1;
if((ix = t1 - t2) != 0)
return(ix);
strcpy(mnem1,WordToString(p1->mnemonic));
return(strcasecmp(mnem1,WordToString(p2->mnemonic)));
} /* end of ph_sorter */
void PrintPhonemesUsed(FILE *f, const char *dictname)
{//==================================================
int ix;
PHONEME_TAB *ph;
PHONEME_TAB *ph_tab[N_PHONEME_TAB];
int count = 0;
int n_ph = 0;
int section = 0;
fprintf(f,"\n\nDictionary %s_dict\n",dictname);
fflush(f);
for(ix=0; (ix<N_PHONEME_TAB) && (phoneme_tab[ix] != NULL); ix++)
{
if(phoneme_tab_flags[ix] & 2)
{
ph_tab[n_ph++] = phoneme_tab[ix];
}
}
qsort((void *)ph_tab,n_ph,sizeof(PHONEME_TAB *),(int (*)(const void *,const void *))ph_sorter);
for(ix=0; ix<n_ph; ix++)
{
ph = ph_tab[ix];
if(ph->type > 1)
{
if((ph->type > phVOWEL) && (section == 0))
{
section = 1;
count = 0;
fputc('\n',f);
}
if((count & 0x7) == 0)
fputc('\n',f);
fprintf(f,"%-4s ",WordToString(ph->mnemonic));
count++;
}
}
fputc('\n',f);
} // end of PrintPhonemesUsed
wxString CompileAllDictionaries()
{//==============================
wxString filename;
@@ -1834,6 +1905,7 @@ wxString CompileAllDictionaries()
int errors = 0;
int dict_count = 0;
FILE *log;
FILE *f_phused;
char dictname[80];
char fname_log[80];
char save_voice_name[80];
@@ -1866,6 +1938,13 @@ wxString CompileAllDictionaries()
sprintf(fname_log,"%s%s",path_dsource,"dict_log");
log = fopen(fname_log,"w");
sprintf(fname_log,"%s%s",path_dsource,"dict_phonemes");
f_phused = fopen(fname_log,"w");
if(f_phused)
{
fprintf(f_phused,"Phonemes which are used in the *_rules and *_list files\n");
}
bool cont = dir.GetFirst(&filename, _T("*_rules"), wxDIR_FILES);
while ( cont )
@@ -1883,10 +1962,19 @@ wxString CompileAllDictionaries()
errors += err;
}
if(f_phused != NULL)
{
memset(phoneme_tab_flags,0,sizeof(phoneme_tab_flags));
FindPhonemesUsed();
PrintPhonemesUsed(f_phused,dictname);
}
cont = dir.GetNext(&filename);
}
if(log != NULL)
fclose(log);
if(f_phused != NULL)
fclose(f_phused);
LoadVoice(save_voice_name,1);
+3
View File
@@ -657,6 +657,9 @@ void copy_rule_string(char *string, int &state)
case 'W':
c = RULE_SPELLING;
break;
case 'X':
c = RULE_NOVOWELS;
break;
case 'L':
// expect two digits
c = *p++ - '0';
+32 -3
View File
@@ -1261,7 +1261,11 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int
else
{
// unstressed syllable within a word
v_stress = 1; /* change from 0 (unstressed) to 1 (diminished stress) */
if((vowel_stress[v-1] != 1) || ((langopts.stress_flags & 0x10000) == 0))
{
v_stress = 1; /* change from 0 (unstressed) to 1 (diminished stress) */
vowel_stress[v] = v_stress;
}
}
}
@@ -1383,7 +1387,7 @@ char *Translator::DecodeRule(const char *group, char *rule)
static char output[60];
static char symbols[] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',
'@','&','%','+','#','S','D','Z','A','B','C','H','F','G','Y','N','K','V','L','T'};
'@','&','%','+','#','S','D','Z','A','B','C','H','F','G','Y','N','K','V','L','T','X','?','W'};
match_type = 0;
@@ -1805,6 +1809,23 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec
}
break;
case RULE_NOVOWELS:
{
char *p = post_ptr + letter_xbytes;
while(letter_w != RULE_SPACE)
{
if(IsLetter(letter_w,LETTERGP_VOWEL2))
{
failed = 1;
break;
}
p += utf8_in(&letter_w,p,0);
}
if(!failed)
match.points += (19-distance_right);
}
break;
case RULE_INC_SCORE:
match.points += 20; // force an increase in points
break;
@@ -1932,6 +1953,13 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec
failed = 1;
break;
case RULE_NOVOWELS:
if(word_vowel_count== 0)
match.points += 19;
else
failed =1;
break;
case RULE_IFVERB:
if(expect_verb)
match.points += 1;
@@ -2710,7 +2738,8 @@ int Translator::LookupDictList(char *word1, char *ph_out, unsigned int *flags, i
int Translator::Lookup(char *word, char *ph_out)
{//=============================================
return(LookupDictList(word,ph_out,NULL,0));
unsigned int flags;
return(LookupDictList(word,ph_out,&flags,0));
}
+1 -1
View File
@@ -35,7 +35,7 @@
#include "translate.h"
#include "wave.h"
const char *version_string = "1.24.11 17.May.07";
const char *version_string = "1.24.12 18.May.07";
const int version_phdata = 0x012201;
int option_device_number = -1;
+3 -3
View File
@@ -244,7 +244,7 @@ Translator *SelectTranslator(const char *name)
static const wchar_t replace_chars_hi[11] = {0x966,0x967,0x968,0x969,0x96a,0x96b,0x96c,0x96d,0x96e,0x96f,0}; // digits 0-9
static const unsigned int replacement_chars_hi[11] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0};
static int stress_lengths_hi[8] = {190, 190, 210, 210, 0, 0, 230, 250};
static int stress_amps_hi[8] = {17,14, 20,20, 20,24, 24,22 };
static int stress_amps_hi[8] = {17,14, 20,19, 20,24, 24,22 };
tr = new Translator();
SetupTranslator(tr,stress_lengths_hi,stress_amps_hi);
@@ -252,7 +252,7 @@ Translator *SelectTranslator(const char *name)
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
tr->langopts.stress_rule = 6; // stress on last heaviest syllable
tr->langopts.stress_flags = 0x4; // use 'diminished' for unstressed final syllable
tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable
tr->langopts.numbers = 0x811 + 0x40000;
tr->letter_bits_offset = OFFSET_DEVANAGARI;
tr->langopts.replace_chars = replace_chars_hi;
@@ -392,7 +392,7 @@ Translator *SelectTranslator(const char *name)
case L('n','o'): // Norwegian
{
static int stress_amps_no[] = {16,16, 20,20, 20,24, 24,22 };
static int stress_lengths_no[8] = {160,140, 200,200, 0,0, 250,270};
static int stress_lengths_no[8] = {160,140, 200,190, 0,0, 220,240};
tr = new Translator();
SetupTranslator(tr,stress_lengths_no,stress_amps_no);
+5 -3
View File
@@ -122,9 +122,10 @@
#define RULE_NOTVOWEL 25 // K
#define RULE_IFVERB 26 // V
#define RULE_LETTERGP 27 // L + letter group number
#define RULE_ALT1 28 // word has $alt attribute
#define RULE_SPELLING 31 // while spelling letter-by-letter
#define RULE_LAST_RULE 28
#define RULE_ALT1 28 // T word has $alt attribute
#define RULE_NOVOWELS 29 // X no vowels up to word boundary
#define RULE_SPELLING 31 // W while spelling letter-by-letter
#define RULE_LAST_RULE 31
#define LETTERGP_A 0
#define LETTERGP_B 1
@@ -258,6 +259,7 @@ typedef struct {
// bit9=stress last syllable if it doesn't end in vowel or "s" or "n" LANG=Spanish
// bit12= In a 2-syllable word, if one has primary stress then give the other secondary stress
// bit13= If there is only one syllable before the primary stress, give it a secondary stress
// bit16= Don't diminish consecutive syllables within a word.
int stress_flags;
int unstressed_wd1; // stress for $u word of 1 syllable
+13 -2
View File
@@ -373,10 +373,12 @@ void VowelChart(int control, char *fname)
static void FindPhonemesUsed(void)
{//===============================
void FindPhonemesUsed(void)
{//========================
int hash;
char *p;
char *start;
char *group;
char *next;
unsigned char c;
int count = 0;
@@ -386,15 +388,24 @@ static void FindPhonemesUsed(void)
p = translator->data_dictrules;
while(*p != 0)
{
if(*p == RULE_CONDITION)
p+=2;
if(*p == RULE_GROUP_END)
{
p++;
if(*p == 0) break;
}
if(*p == RULE_GROUP_START)
{
group = p;
p += (strlen(p)+1);
}
while((((c = *p) != RULE_PHONEMES)) && (c != 0)) p++;
count++;
if(c == RULE_PHONEMES)
{
start = p;
p++;
while(*p != 0)
{