mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-03 14:17:12 +00:00
[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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user