mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-01 05:46:19 +00:00
[1.43.31]
*_list files: added attribute $sentence. *_rules files: added attributes $w_alt, $p_alt. phoneme definitions: added attribute no_pause. -X command-line option: Show the matching of multiple-word entries in *_list files. espeakedit: Add menu option to compile the intonation data file (the data is not yet used). Start language: Bulgarian. lang=bg (Bulgarian): Add feature in espeakedit to make bg_listx from a lexicon of words which have stress position mark-up. espeakedit: Change the frame-length field from Spin Control to Text Control to allow better access from screen-readers. Language options: add an option to the Regressive Voicing option to de-voice the final consonant of words. Don't speak "dot" if an ellipsis is followed by a dot. Intonation: change the internal pitch unit to give finer control, and align with the values displayed in the espeakedit Prosody window. git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@243 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
+58
-182
@@ -18,8 +18,6 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#define LOG_TRANSLATE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
@@ -40,6 +38,7 @@ int dictionary_skipwords;
|
||||
char dictionary_name[40];
|
||||
|
||||
extern char *print_dictionary_flags(unsigned int *flags);
|
||||
extern char *DecodeRule(const char *group_chars, int group_length, char *rule);
|
||||
|
||||
// accented characters which indicate (in some languages) the start of a separate syllable
|
||||
//static const unsigned short diereses_list[7] = {L'ä',L'ë',L'ï',L'ö',L'ü',L'ÿ',0};
|
||||
@@ -106,8 +105,8 @@ static int reverse_word_bytes(int word)
|
||||
}
|
||||
|
||||
|
||||
int LookupMnem(MNEM_TAB *table, char *string)
|
||||
{//==========================================
|
||||
int LookupMnem(MNEM_TAB *table, const char *string)
|
||||
{//================================================
|
||||
while(table->mnem != NULL)
|
||||
{
|
||||
if(strcmp(string,table->mnem)==0)
|
||||
@@ -118,7 +117,6 @@ int LookupMnem(MNEM_TAB *table, char *string)
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================================
|
||||
// Read pronunciation rules and pronunciation lookup dictionary
|
||||
//
|
||||
@@ -1628,159 +1626,6 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
//=============================================================================================
|
||||
|
||||
|
||||
#ifdef LOG_TRANSLATE
|
||||
static char *DecodeRule(const char *group_chars, int group_length, char *rule)
|
||||
{//===========================================================================
|
||||
/* Convert compiled match template to ascii */
|
||||
|
||||
unsigned char rb;
|
||||
unsigned char c;
|
||||
char *p;
|
||||
int ix;
|
||||
int match_type;
|
||||
int finished=0;
|
||||
int value;
|
||||
int linenum=0;
|
||||
int flags;
|
||||
int suffix_char;
|
||||
int condition_num=0;
|
||||
char buf[60];
|
||||
char buf_pre[60];
|
||||
char suffix[20];
|
||||
static char output[60];
|
||||
|
||||
static char symbols[] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',
|
||||
'@','&','%','+','#','S','D','Z','A','L','!',' ','?','?','J','N','K','V','?','T','X','?','W'};
|
||||
|
||||
static char symbols_lg[] = {'A','B','C','H','F','G','Y'};
|
||||
|
||||
match_type = 0;
|
||||
buf_pre[0] = 0;
|
||||
|
||||
for(ix=0; ix<group_length; ix++)
|
||||
{
|
||||
buf[ix] = group_chars[ix];
|
||||
}
|
||||
buf[ix] = 0;
|
||||
|
||||
p = &buf[strlen(buf)];
|
||||
while(!finished)
|
||||
{
|
||||
rb = *rule++;
|
||||
|
||||
if(rb <= RULE_LINENUM)
|
||||
{
|
||||
switch(rb)
|
||||
{
|
||||
case 0:
|
||||
case RULE_PHONEMES:
|
||||
finished=1;
|
||||
break;
|
||||
case RULE_PRE:
|
||||
match_type = RULE_PRE;
|
||||
*p = 0;
|
||||
p = buf_pre;
|
||||
break;
|
||||
case RULE_POST:
|
||||
match_type = RULE_POST;
|
||||
*p = 0;
|
||||
strcat(buf," (");
|
||||
p = &buf[strlen(buf)];
|
||||
break;
|
||||
case RULE_PH_COMMON:
|
||||
break;
|
||||
case RULE_CONDITION:
|
||||
/* conditional rule, next byte gives condition number */
|
||||
condition_num = *rule++;
|
||||
break;
|
||||
case RULE_LINENUM:
|
||||
value = (rule[1] & 0xff) - 1;
|
||||
linenum = (rule[0] & 0xff) - 1 + (value * 255);
|
||||
rule+=2;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(rb == RULE_ENDING)
|
||||
{
|
||||
static const char *flag_chars = "ei vtfq t";
|
||||
flags = ((rule[0] & 0x7f)<< 8) + (rule[1] & 0x7f);
|
||||
suffix_char = 'S';
|
||||
if(flags & (SUFX_P >> 8))
|
||||
suffix_char = 'P';
|
||||
sprintf(suffix,"%c%d",suffix_char,rule[2] & 0x7f);
|
||||
rule += 3;
|
||||
for(ix=0;ix<9;ix++)
|
||||
{
|
||||
if(flags & 1)
|
||||
sprintf(&suffix[strlen(suffix)],"%c",flag_chars[ix]);
|
||||
flags = (flags >> 1);
|
||||
}
|
||||
strcpy(p,suffix);
|
||||
p += strlen(suffix);
|
||||
c = ' ';
|
||||
}
|
||||
else
|
||||
if(rb == RULE_LETTERGP)
|
||||
{
|
||||
c = symbols_lg[*rule++ - 'A'];
|
||||
}
|
||||
else
|
||||
if(rb == RULE_LETTERGP2)
|
||||
{
|
||||
value = *rule++ - 'A';
|
||||
p[0] = 'L';
|
||||
p[1] = (value / 10) + '0';
|
||||
c = (value % 10) + '0';
|
||||
|
||||
if(match_type == RULE_PRE)
|
||||
{
|
||||
p[0] = c;
|
||||
c = 'L';
|
||||
}
|
||||
p+=2;
|
||||
}
|
||||
else
|
||||
if(rb <= RULE_LAST_RULE)
|
||||
c = symbols[rb];
|
||||
else
|
||||
if(rb == RULE_SPACE)
|
||||
c = '_';
|
||||
else
|
||||
c = rb;
|
||||
*p++ = c;
|
||||
}
|
||||
*p = 0;
|
||||
|
||||
p = output;
|
||||
if(linenum > 0)
|
||||
{
|
||||
sprintf(p,"%5d:\t",linenum);
|
||||
p += 7;
|
||||
}
|
||||
if(condition_num > 0)
|
||||
{
|
||||
sprintf(p,"?%d ",condition_num);
|
||||
p = &p[strlen(p)];
|
||||
}
|
||||
if((ix = strlen(buf_pre)) > 0)
|
||||
{
|
||||
while(--ix >= 0)
|
||||
*p++ = buf_pre[ix];
|
||||
*p++ = ')';
|
||||
*p++ = ' ';
|
||||
}
|
||||
*p = 0;
|
||||
strcat(p,buf);
|
||||
ix = strlen(output);
|
||||
while(ix < 8)
|
||||
output[ix++]=' ';
|
||||
output[ix]=0;
|
||||
return(output);
|
||||
} /* end of decode_match */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void AppendPhonemes(Translator *tr, char *string, int size, const char *ph)
|
||||
@@ -1833,8 +1678,8 @@ void AppendPhonemes(Translator *tr, char *string, int size, const char *ph)
|
||||
|
||||
|
||||
|
||||
static void MatchRule(Translator *tr, char *word[], int group_length, char *rule, MatchRecord *match_out, int word_flags, int dict_flags)
|
||||
{//======================================================================================================================================
|
||||
static void MatchRule(Translator *tr, char *word[], char *word_start, int group_length, char *rule, MatchRecord *match_out, int word_flags, int dict_flags)
|
||||
{//========================================================================================================================================================
|
||||
/* Checks a specified word against dictionary rules.
|
||||
Returns with phoneme code string, or NULL if no match found.
|
||||
|
||||
@@ -1861,6 +1706,7 @@ static void MatchRule(Translator *tr, char *word[], int group_length, char *rule
|
||||
|
||||
char *rule_start; /* start of current match template */
|
||||
char *p;
|
||||
int ix;
|
||||
|
||||
int match_type; /* left, right, or consume */
|
||||
int failed;
|
||||
@@ -1874,6 +1720,7 @@ static void MatchRule(Translator *tr, char *word[], int group_length, char *rule
|
||||
int lg_pts;
|
||||
int n_bytes;
|
||||
int add_points;
|
||||
int command;
|
||||
|
||||
MatchRecord match;
|
||||
static MatchRecord best;
|
||||
@@ -1883,6 +1730,7 @@ static void MatchRule(Translator *tr, char *word[], int group_length, char *rule
|
||||
unsigned char condition_num;
|
||||
char *common_phonemes; /* common to a group of entries */
|
||||
char *group_chars;
|
||||
char word_buf[N_WORD_BYTES];
|
||||
|
||||
group_chars = *word;
|
||||
|
||||
@@ -2091,11 +1939,29 @@ static void MatchRule(Translator *tr, char *word[], int group_length, char *rule
|
||||
failed = 1;
|
||||
break;
|
||||
|
||||
case RULE_ALT1:
|
||||
if(dict_flags & FLAG_ALT_TRANS)
|
||||
add_points = 1;
|
||||
case RULE_DOLLAR:
|
||||
command = *rule++;
|
||||
if((command & 0xf0) == 0x10)
|
||||
{
|
||||
if(dict_flags & (1 << (BITNUM_FLAG_ALT + (command & 0xf))))
|
||||
add_points = 23;
|
||||
else
|
||||
failed = 1;
|
||||
}
|
||||
else
|
||||
failed = 1;
|
||||
if((command & 0xf0) == 0x20)
|
||||
{
|
||||
// make a copy of the word up to the post-match characters
|
||||
ix = *word - word_start + consumed + group_length + 1;
|
||||
memcpy(word_buf, word_start-1, ix);
|
||||
word_buf[ix] = ' ';
|
||||
word_buf[ix+1] = 0;
|
||||
|
||||
if(LookupFlags(tr, &word_buf[1]) & (1 << (BITNUM_FLAG_ALT + (command & 0xf))))
|
||||
add_points = 23;
|
||||
else
|
||||
failed = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
@@ -2403,7 +2269,6 @@ static void MatchRule(Translator *tr, char *word[], int group_length, char *rule
|
||||
total_consumed = consumed;
|
||||
}
|
||||
|
||||
#ifdef LOG_TRANSLATE
|
||||
if((option_phonemes == 2) && (match.points > 0) && ((word_flags & FLAG_NO_TRACE) == 0))
|
||||
{
|
||||
// show each rule that matches, and it's points score
|
||||
@@ -2417,7 +2282,6 @@ static void MatchRule(Translator *tr, char *word[], int group_length, char *rule
|
||||
DecodePhonemes(match.phonemes,decoded_phonemes);
|
||||
fprintf(f_trans,"%3d\t%s [%s]\n",pts,DecodeRule(group_chars, group_length, rule_start),decoded_phonemes);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -2425,13 +2289,11 @@ static void MatchRule(Translator *tr, char *word[], int group_length, char *rule
|
||||
while(*rule++ != 0);
|
||||
}
|
||||
|
||||
#ifdef LOG_TRANSLATE
|
||||
if((option_phonemes == 2) && ((word_flags & FLAG_NO_TRACE)==0))
|
||||
{
|
||||
if(group_length <= 1)
|
||||
fprintf(f_trans,"\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* advance input data pointer */
|
||||
total_consumed += group_length;
|
||||
@@ -2491,7 +2353,6 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
word_copy[ix] = 0;
|
||||
|
||||
|
||||
#ifdef LOG_TRANSLATE
|
||||
if((option_phonemes == 2) && ((word_flags & FLAG_NO_TRACE)==0))
|
||||
{
|
||||
char wordbuf[120];
|
||||
@@ -2504,7 +2365,6 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
wordbuf[ix] = 0;
|
||||
fprintf(f_trans,"Translate '%s'\n",wordbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
p = p_start;
|
||||
tr->word_vowel_count = 0;
|
||||
@@ -2548,7 +2408,7 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
{
|
||||
if(tr->groups3[ix] != NULL)
|
||||
{
|
||||
MatchRule(tr, &p, wc_bytes, tr->groups3[ix], &match1, word_flags, dict_flags0);
|
||||
MatchRule(tr, &p, p_start, wc_bytes, tr->groups3[ix], &match1, word_flags, dict_flags0);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
@@ -2568,12 +2428,12 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
found = 1;
|
||||
|
||||
p2 = p;
|
||||
MatchRule(tr, &p2, 2, tr->groups2[g], &match2, word_flags, dict_flags0);
|
||||
MatchRule(tr, &p2, p_start, 2, tr->groups2[g], &match2, word_flags, dict_flags0);
|
||||
if(match2.points > 0)
|
||||
match2.points += 35; /* to acount for 2 letters matching */
|
||||
|
||||
/* now see whether single letter chain gives a better match ? */
|
||||
MatchRule(tr, &p, 1, tr->groups1[c], &match1, word_flags, dict_flags0);
|
||||
MatchRule(tr, &p, p_start, 1, tr->groups1[c], &match1, word_flags, dict_flags0);
|
||||
|
||||
if(match2.points >= match1.points)
|
||||
{
|
||||
@@ -2589,11 +2449,11 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
{
|
||||
/* alphabetic, single letter chain */
|
||||
if(tr->groups1[c] != NULL)
|
||||
MatchRule(tr, &p, 1, tr->groups1[c], &match1, word_flags, dict_flags0);
|
||||
MatchRule(tr, &p, p_start, 1, tr->groups1[c], &match1, word_flags, dict_flags0);
|
||||
else
|
||||
{
|
||||
// no group for this letter, use default group
|
||||
MatchRule(tr, &p, 0, tr->groups1[0], &match1, word_flags, dict_flags0);
|
||||
MatchRule(tr, &p, p_start, 0, tr->groups1[0], &match1, word_flags, dict_flags0);
|
||||
|
||||
if((match1.points == 0) && ((option_sayas & 0x10) == 0))
|
||||
{
|
||||
@@ -3167,6 +3027,12 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
|
||||
continue;
|
||||
}
|
||||
|
||||
if((dictionary_flags2 & FLAG_SENTENCE) && !(tr->clause_terminator & CLAUSE_BIT_SENTENCE))
|
||||
{
|
||||
// only uis this clause is a sentence , i.e. terminator is {. ? !} not {, : :}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(dictionary_flags2 & FLAG_VERB)
|
||||
{
|
||||
// this is a verb-form pronunciation
|
||||
@@ -3243,7 +3109,18 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
|
||||
if(textmode == translator->langopts.textmode)
|
||||
{
|
||||
// only show this line if the word translates to phonemes, not replacement text
|
||||
fprintf(f_trans,"Found: %s [%s] %s\n",word1,ph_decoded,print_dictionary_flags(flags));
|
||||
if(dictionary_skipwords)
|
||||
{
|
||||
// matched more than one word
|
||||
memcpy(word_buf,word2,word_end-word2);
|
||||
word_buf[word_end-word2-1] = 0;
|
||||
fprintf(f_trans,"Found: '%s %s",word1,word_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(f_trans,"Found: '%s",word1);
|
||||
}
|
||||
fprintf(f_trans,"' [%s] %s\n",ph_decoded,print_dictionary_flags(flags));
|
||||
}
|
||||
}
|
||||
return(word_end);
|
||||
@@ -3541,12 +3418,11 @@ int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy)
|
||||
if(end_flags & FLAG_SUFX_E_ADDED)
|
||||
{
|
||||
utf8_out(tr->langopts.suffix_add_e, &word_end[1]);
|
||||
#ifdef LOG_TRANSLATE
|
||||
if(option_phonemes == 2)
|
||||
{
|
||||
fprintf(f_trans,"add e\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if(option_phonemes == 2)
|
||||
{
|
||||
fprintf(f_trans,"add e\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user