mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-15 10:02:42 +00:00
[1.42.02]
git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@231 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
+38
-6
@@ -83,7 +83,6 @@ MNEM_TAB mnem_flags[] = {
|
||||
{"$unstressend",13}, /* reduce stress at end of clause */
|
||||
{"$atend", 14}, /* use this pronunciation if at end of clause */
|
||||
|
||||
{"$dot", 16}, /* ignore '.' after this word (abbreviation) */
|
||||
{"$abbrev", 17}, /* use this pronuciation rather than split into letters */
|
||||
{"$stem", 18}, // must have a suffix
|
||||
|
||||
@@ -93,6 +92,9 @@ MNEM_TAB mnem_flags[] = {
|
||||
{"$alt2", 21},
|
||||
{"$combine", 22}, // Combine with the next word
|
||||
|
||||
{"$dot", 24}, // ignore '.' after this word (abbreviation)
|
||||
{"$hasdot", 25}, // use this pronunciation if there is a dot after the word
|
||||
|
||||
{"$max3", 27}, // limit to 3 repetitions
|
||||
{"$brk", 28}, // a shorter $pause
|
||||
{"$text", 29}, // word translates to replcement text, not phonemes
|
||||
@@ -125,6 +127,7 @@ typedef struct {
|
||||
char name[LEN_GROUP_NAME+1];
|
||||
unsigned int start;
|
||||
unsigned int length;
|
||||
int group3_ix;
|
||||
} RGROUP;
|
||||
|
||||
|
||||
@@ -345,7 +348,7 @@ step=1; // TEST
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if((c == '-') && (word[0] != '_'))
|
||||
if((c == '-') && multiple_words)
|
||||
{
|
||||
if(isdigit(word[0]))
|
||||
{
|
||||
@@ -734,6 +737,7 @@ static char rule_post[80];
|
||||
static char rule_match[80];
|
||||
static char rule_phonemes[80];
|
||||
static char group_name[LEN_GROUP_NAME+1];
|
||||
static int group3_ix;
|
||||
|
||||
#define N_RULES 2000 // max rules for each group
|
||||
|
||||
@@ -1129,7 +1133,10 @@ static int __cdecl string_sorter(char **a, char **b)
|
||||
|
||||
static int __cdecl rgroup_sorter(RGROUP *a, RGROUP *b)
|
||||
{//===================================================
|
||||
// Sort long names before short names
|
||||
int ix;
|
||||
ix = strlen(b->name) - strlen(a->name);
|
||||
if(ix != 0) return(ix);
|
||||
ix = strcmp(a->name,b->name);
|
||||
if(ix != 0) return(ix);
|
||||
return(a->start-b->start);
|
||||
@@ -1401,6 +1408,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp)
|
||||
int n_rules=0;
|
||||
int count=0;
|
||||
int different;
|
||||
int wc;
|
||||
const char *prev_rgroup_name;
|
||||
unsigned int char_code;
|
||||
int compile_mode=0;
|
||||
@@ -1409,6 +1417,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp)
|
||||
char *rules[N_RULES];
|
||||
|
||||
int n_rgroups = 0;
|
||||
int n_groups3 = 0;
|
||||
RGROUP rgroup[N_RULE_GROUP2];
|
||||
|
||||
linenum = 0;
|
||||
@@ -1436,6 +1445,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp)
|
||||
if(n_rules > 0)
|
||||
{
|
||||
strcpy(rgroup[n_rgroups].name,group_name);
|
||||
rgroup[n_rgroups].group3_ix = group3_ix;
|
||||
rgroup[n_rgroups].start = ftell(f_temp);
|
||||
output_rule_group(f_temp,n_rules,rules,group_name);
|
||||
rgroup[n_rgroups].length = ftell(f_temp) - rgroup[n_rgroups].start;
|
||||
@@ -1481,7 +1491,8 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp)
|
||||
while((*p > ' ') && (ix < LEN_GROUP_NAME))
|
||||
group_name[ix++] = *p++;
|
||||
group_name[ix]=0;
|
||||
|
||||
group3_ix = 0;
|
||||
|
||||
if(sscanf(group_name,"0x%x",&char_code)==1)
|
||||
{
|
||||
// group character is given as a character code (max 16 bits)
|
||||
@@ -1494,8 +1505,19 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp)
|
||||
*p++ = char_code;
|
||||
*p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(translator->letter_bits_offset > 0)
|
||||
{
|
||||
utf8_in(&wc, group_name);
|
||||
if(((ix = (wc - translator->letter_bits_offset)) >= 0) && (ix < 128))
|
||||
{
|
||||
group3_ix = ix+1; // not zero
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen(group_name) > 2)
|
||||
if((group3_ix == 0) && (strlen(group_name) > 2))
|
||||
{
|
||||
if(utf8_in(&c,group_name) < 2)
|
||||
{
|
||||
@@ -1573,7 +1595,17 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp)
|
||||
if(gp > 0)
|
||||
fputc(RULE_GROUP_END,f_out);
|
||||
fputc(RULE_GROUP_START,f_out);
|
||||
fprintf(f_out, prev_rgroup_name = rgroup[gp].name);
|
||||
|
||||
if(rgroup[gp].group3_ix != 0)
|
||||
{
|
||||
n_groups3++;
|
||||
fputc(1,f_out);
|
||||
fputc(rgroup[gp].group3_ix, f_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(f_out, "%s", prev_rgroup_name = rgroup[gp].name);
|
||||
}
|
||||
fputc(0,f_out);
|
||||
}
|
||||
|
||||
@@ -1593,7 +1625,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp)
|
||||
fclose(f_temp);
|
||||
remove(fname_temp);
|
||||
|
||||
fprintf(f_log,"\t%d rules, %d groups\n\n",count,n_rgroups);
|
||||
fprintf(f_log,"\t%d rules, %d groups (%d)\n\n",count,n_rgroups,n_groups3);
|
||||
return(0);
|
||||
} // end of compile_dictrules
|
||||
|
||||
|
||||
+72
-59
@@ -36,6 +36,7 @@
|
||||
#include "translate.h"
|
||||
|
||||
|
||||
|
||||
int dictionary_skipwords;
|
||||
char dictionary_name[40];
|
||||
|
||||
@@ -146,6 +147,7 @@ static void InitGroups(Translator *tr)
|
||||
tr->groups2_start[ix]=255; // indicates "not set"
|
||||
}
|
||||
memset(tr->letterGroups,0,sizeof(tr->letterGroups));
|
||||
memset(tr->groups3,0,sizeof(tr->groups3));
|
||||
|
||||
p = tr->data_dictrules;
|
||||
while(*p != 0)
|
||||
@@ -194,7 +196,8 @@ static void InitGroups(Translator *tr)
|
||||
len = strlen(p);
|
||||
p_name = p;
|
||||
c = p_name[0];
|
||||
|
||||
c2 = p_name[1];
|
||||
|
||||
p += (len+1);
|
||||
if(len == 1)
|
||||
{
|
||||
@@ -206,13 +209,18 @@ static void InitGroups(Translator *tr)
|
||||
tr->groups1[0] = p;
|
||||
}
|
||||
else
|
||||
if(c == 1)
|
||||
{
|
||||
// index by offset from letter base
|
||||
tr->groups3[c2 - 1] = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tr->groups2_start[c] == 255)
|
||||
tr->groups2_start[c] = tr->n_groups2;
|
||||
|
||||
tr->groups2_count[c]++;
|
||||
tr->groups2[tr->n_groups2] = p;
|
||||
c2 = p_name[1];
|
||||
tr->groups2_name[tr->n_groups2++] = (c + (c2 << 8));
|
||||
}
|
||||
}
|
||||
@@ -1255,18 +1263,17 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
{
|
||||
/* no explicit stress - stress the final vowel */
|
||||
stressed_syllable = vowel_count - 1;
|
||||
if(max_stress == 0)
|
||||
|
||||
while(stressed_syllable > 0)
|
||||
{
|
||||
while(stressed_syllable > 0)
|
||||
// find the last vowel which is not unstressed
|
||||
if(vowel_stress[stressed_syllable] == 0)
|
||||
{
|
||||
if(vowel_stress[stressed_syllable] == 0)
|
||||
{
|
||||
vowel_stress[stressed_syllable] = 4;
|
||||
break;
|
||||
}
|
||||
else
|
||||
stressed_syllable--;
|
||||
vowel_stress[stressed_syllable] = 4;
|
||||
break;
|
||||
}
|
||||
else
|
||||
stressed_syllable--;
|
||||
}
|
||||
max_stress = 4;
|
||||
}
|
||||
@@ -1391,7 +1398,7 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
if(vowel_stress[2] == 4)
|
||||
vowel_stress[1] = 3;
|
||||
}
|
||||
#if deleted
|
||||
|
||||
if((stressflags & 0x2000) && (vowel_stress[1] == 0))
|
||||
{
|
||||
// If there is only one syllable before the primary stress, give it a secondary stress
|
||||
@@ -1400,7 +1407,6 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
vowel_stress[1] = 3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
done = 0;
|
||||
for(v=1; v<vowel_count; v++)
|
||||
@@ -1621,8 +1627,8 @@ void SetWordStress(Translator *tr, char *output, unsigned int *dictionary_flags,
|
||||
|
||||
|
||||
#ifdef LOG_TRANSLATE
|
||||
static char *DecodeRule(const char *group, char *rule)
|
||||
{//==================================================
|
||||
static char *DecodeRule(const char *group_chars, int group_length, char *rule)
|
||||
{//===========================================================================
|
||||
/* Convert compiled match template to ascii */
|
||||
|
||||
unsigned char rb;
|
||||
@@ -1648,7 +1654,13 @@ static char *DecodeRule(const char *group, char *rule)
|
||||
|
||||
match_type = 0;
|
||||
buf_pre[0] = 0;
|
||||
strcpy(buf,group);
|
||||
|
||||
for(ix=0; ix<group_length; ix++)
|
||||
{
|
||||
buf[ix] = group_chars[ix];
|
||||
}
|
||||
buf[ix] = 0;
|
||||
|
||||
p = &buf[strlen(buf)];
|
||||
while(!finished)
|
||||
{
|
||||
@@ -1819,8 +1831,8 @@ void AppendPhonemes(Translator *tr, char *string, int size, const char *ph)
|
||||
|
||||
|
||||
|
||||
static void MatchRule(Translator *tr, char *word[], const char *group, char *rule, MatchRecord *match_out, int word_flags, int dict_flags)
|
||||
{//=======================================================================================================================================
|
||||
static void MatchRule(Translator *tr, char *word[], 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.
|
||||
|
||||
@@ -1865,12 +1877,12 @@ static void MatchRule(Translator *tr, char *word[], const char *group, char *rul
|
||||
static MatchRecord best;
|
||||
|
||||
int total_consumed; /* letters consumed for best match */
|
||||
int group_length;
|
||||
|
||||
unsigned char condition_num;
|
||||
char *common_phonemes; /* common to a group of entries */
|
||||
char *group_chars;
|
||||
|
||||
|
||||
group_chars = *word;
|
||||
|
||||
if(rule == NULL)
|
||||
{
|
||||
@@ -1890,8 +1902,6 @@ static void MatchRule(Translator *tr, char *word[], const char *group, char *rul
|
||||
best.end_type = 0;
|
||||
best.del_fwd = NULL;
|
||||
|
||||
group_length = strlen(group);
|
||||
|
||||
/* search through dictionary rules */
|
||||
while(rule[0] != RULE_GROUP_END)
|
||||
{
|
||||
@@ -2372,7 +2382,7 @@ static void MatchRule(Translator *tr, char *word[], const char *group, char *rul
|
||||
if(group_length > 1)
|
||||
pts += 35; // to account for an extra letter matching
|
||||
DecodePhonemes(match.phonemes,decoded_phonemes);
|
||||
fprintf(f_trans,"%3d\t%s [%s]\n",pts,DecodeRule(group,rule_start),decoded_phonemes);
|
||||
fprintf(f_trans,"%3d\t%s [%s]\n",pts,DecodeRule(group_chars, group_length, rule_start),decoded_phonemes);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2411,7 +2421,7 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
Append the result to 'phonemes' and any standard prefix/suffix in 'end_phonemes' */
|
||||
|
||||
unsigned char c, c2;
|
||||
unsigned int c12;
|
||||
unsigned int c12, c123;
|
||||
int wc=0;
|
||||
int wc_prev;
|
||||
int wc_bytes;
|
||||
@@ -2432,8 +2442,6 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
char word_copy[N_WORD_BYTES];
|
||||
static const char str_pause[2] = {phonPAUSE_NOLINK,0};
|
||||
|
||||
char group_name[4];
|
||||
|
||||
if(tr->data_dictrules == NULL)
|
||||
return(0);
|
||||
|
||||
@@ -2502,12 +2510,22 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
{
|
||||
digit_count = 0;
|
||||
found = 0;
|
||||
|
||||
if(n > 0)
|
||||
|
||||
if(((ix = wc - tr->letter_bits_offset) >= 0) && (ix < 128))
|
||||
{
|
||||
if(tr->groups3[ix] != NULL)
|
||||
{
|
||||
MatchRule(tr, &p, wc_bytes, tr->groups3[ix], &match1, word_flags, dict_flags0);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found && (n > 0))
|
||||
{
|
||||
/* there are some 2 byte chains for this initial letter */
|
||||
c2 = p[1];
|
||||
c12 = c + (c2 << 8); /* 2 characters */
|
||||
c123 = c12 + (p[2] << 16);
|
||||
|
||||
g1 = tr->groups2_start[c];
|
||||
for(g=g1; g < (g1+n); g++)
|
||||
@@ -2516,17 +2534,13 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
{
|
||||
found = 1;
|
||||
|
||||
group_name[0] = c;
|
||||
group_name[1] = c2;
|
||||
group_name[2] = 0;
|
||||
p2 = p;
|
||||
MatchRule(tr, &p2, group_name, tr->groups2[g], &match2, word_flags, dict_flags0);
|
||||
MatchRule(tr, &p2, 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 ? */
|
||||
group_name[1] = 0;
|
||||
MatchRule(tr, &p, group_name, tr->groups1[c], &match1, word_flags, dict_flags0);
|
||||
MatchRule(tr, &p, 1, tr->groups1[c], &match1, word_flags, dict_flags0);
|
||||
|
||||
if(match2.points >= match1.points)
|
||||
{
|
||||
@@ -2541,15 +2555,12 @@ int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, c
|
||||
if(!found)
|
||||
{
|
||||
/* alphabetic, single letter chain */
|
||||
group_name[0] = c;
|
||||
group_name[1] = 0;
|
||||
|
||||
if(tr->groups1[c] != NULL)
|
||||
MatchRule(tr, &p, group_name, tr->groups1[c], &match1, word_flags, dict_flags0);
|
||||
MatchRule(tr, &p, 1, tr->groups1[c], &match1, word_flags, dict_flags0);
|
||||
else
|
||||
{
|
||||
// no group for this letter, use default group
|
||||
MatchRule(tr, &p, "", tr->groups1[0], &match1, word_flags, dict_flags0);
|
||||
MatchRule(tr, &p, 0, tr->groups1[0], &match1, word_flags, dict_flags0);
|
||||
|
||||
if((match1.points == 0) && ((option_sayas & 0x10) == 0))
|
||||
{
|
||||
@@ -2715,9 +2726,8 @@ void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags)
|
||||
|
||||
len = strlen(phonemes);
|
||||
|
||||
switch(tr->translator_name)
|
||||
if(tr->langopts.param[LOPT_ALT] & 2)
|
||||
{
|
||||
case L('i','t'):
|
||||
for(ix=0; ix<(len-1); ix++)
|
||||
{
|
||||
if(phonemes[ix] == phonSTRESS_P)
|
||||
@@ -2740,7 +2750,6 @@ void ApplySpecialAttribute2(Translator *tr, char *phonemes, int dict_flags)
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} // end of ApplySpecialAttribute2
|
||||
|
||||
@@ -2749,9 +2758,7 @@ void ApplySpecialAttribute(Translator *tr, char *phonemes, int dict_flags)
|
||||
{//=======================================================================
|
||||
// Amend the translated phonemes according to an attribute which is specific for the language.
|
||||
int len;
|
||||
int ix;
|
||||
char *p_end;
|
||||
int phoneme_1;
|
||||
|
||||
if((dict_flags & (FLAG_ALT_TRANS | FLAG_ALT2_TRANS)) == 0)
|
||||
return;
|
||||
@@ -2772,18 +2779,6 @@ void ApplySpecialAttribute(Translator *tr, char *phonemes, int dict_flags)
|
||||
}
|
||||
break;
|
||||
|
||||
case L('p','t'):
|
||||
phoneme_1 = PhonemeCode('o');
|
||||
for(ix=0; ix<(len-1); ix++)
|
||||
{
|
||||
if(phonemes[ix] == phoneme_1)
|
||||
{
|
||||
phonemes[ix] = PhonemeCode('O');
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case L('r','o'):
|
||||
if(p_end[0] == PhonemeCode('j'))
|
||||
{
|
||||
@@ -2961,6 +2956,7 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
|
||||
wlen = strlen(word);
|
||||
}
|
||||
|
||||
|
||||
hash = HashDictionary(word);
|
||||
p = tr->dict_hashtab[hash];
|
||||
|
||||
@@ -3127,6 +3123,11 @@ static const char *LookupDict2(Translator *tr, const char *word, const char *wor
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(dictionary_flags & FLAG_NEEDS_DOT)
|
||||
{
|
||||
if(!(wflags & FLAG_HAS_DOT))
|
||||
continue;
|
||||
}
|
||||
|
||||
if((dictionary_flags & FLAG_ATEND) && (word_end < tr->clause_end))
|
||||
{
|
||||
@@ -3267,7 +3268,7 @@ int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *f
|
||||
// set the skip words flag
|
||||
flags[0] |= FLAG_SKIPWORDS;
|
||||
dictionary_skipwords = length;
|
||||
return(flags[0]);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3367,7 +3368,7 @@ int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *f
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(flags[0]);
|
||||
return(1);
|
||||
}
|
||||
|
||||
ph_out[0] = 0;
|
||||
@@ -3384,6 +3385,17 @@ int Lookup(Translator *tr, const char *word, char *ph_out)
|
||||
return(LookupDictList(tr, &word1, ph_out, flags, 0, NULL));
|
||||
}
|
||||
|
||||
int LookupFlags(Translator *tr, const char *word)
|
||||
{//==============================================
|
||||
char buf[100];
|
||||
static unsigned int flags[2];
|
||||
|
||||
flags[0] = flags[1] = 0;
|
||||
char *word1 = (char *)word;
|
||||
LookupDictList(tr, &word1, buf, flags, 0, NULL);
|
||||
return(flags[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy)
|
||||
@@ -3410,7 +3422,8 @@ int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy)
|
||||
"ion", NULL };
|
||||
|
||||
static const char *add_e_additions[] = {
|
||||
"c", "rs", "ir", "ur", "ath", "ns", "lu", NULL };
|
||||
// "c", "rs", "ir", "ur", "ath", "ns", "lu", NULL };
|
||||
"c", "rs", "ir", "ur", "ath", "ns", "u", NULL };
|
||||
|
||||
for(word_end = word; *word_end != ' '; word_end++)
|
||||
{
|
||||
|
||||
+2
-1
@@ -266,6 +266,7 @@ wxSashLayoutWindow *win;
|
||||
|
||||
|
||||
ConfigInit();
|
||||
LoadConfig();
|
||||
WavegenInitSound();
|
||||
|
||||
if((result = LoadPhData()) != 1)
|
||||
@@ -320,7 +321,7 @@ void MyFrame::SetVoiceTitle(char *voice_name)
|
||||
{
|
||||
sprintf(buf,"Compile &dictionary '%s'",dictionary_name);
|
||||
data_menu->SetLabel(MENU_COMPILE_DICT, wxString(buf,wxConvLocal));
|
||||
sprintf(buf,"&Format '%s_rules' file",dictionary_name);
|
||||
sprintf(buf,"&Layout '%s_rules' file",dictionary_name);
|
||||
data_menu->SetLabel(MENU_FORMAT_DICTIONARY, wxString(buf,wxConvLocal));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -214,7 +214,7 @@ static int drops_0[8] = {0x400,0x400,0x700,0x700,0x700,0xa00,0x1800,0x0e00};
|
||||
//static int drops_2[8] = {0x400,0x400,0x600,0x600,-0x800,0xc00,0x0e00,0x0e00};
|
||||
|
||||
static short oflow[] = {0, 20, 12, 4, 0};
|
||||
static short oflow_emf[] = {5, 24, 15, 10, 5};
|
||||
static short oflow_emf[] = {5, 26, 16, 10, 5};
|
||||
static short oflow_less[] = {3, 19, 12, 7, 2};
|
||||
// static short oflow_test2[] = {20, 0, 20, 0, 20};
|
||||
// static short back_emf[] = {35, 32, 0};
|
||||
@@ -262,7 +262,7 @@ static TONE_HEAD tone_head_table[N_TONE_HEAD_TABLE] = {
|
||||
{20, 25, 34, 22, drops_0, 3, 3, 5, oflow}, // 0 statement
|
||||
{20, 25, 34, 20, drops_0, 3, 3, 5, oflow}, // 1 comma
|
||||
{20, 25, 34, 20, drops_0, 3, 3, 5, oflow}, // 2 question
|
||||
{20, 25, 36, 22, drops_0, 3, 4, 5, oflow_emf}, // 3 exclamation
|
||||
{20, 25, 39, 22, drops_0, 3, 4, 5, oflow_emf}, // 3 exclamation
|
||||
{20, 25, 34, 22, drops_0, 3, 3, 5, oflow}, // 4 statement, emphatic
|
||||
{20, 25, 32, 24, drops_0, 4, 3, 5, oflow_less}, // 5 statement, less intonation
|
||||
{20, 25, 32, 24, drops_0, 4, 3, 5, oflow_less}, // 6 comma, less intonation
|
||||
@@ -275,7 +275,7 @@ static TONE_HEAD tone_head_table[N_TONE_HEAD_TABLE] = {
|
||||
};
|
||||
|
||||
static TONE_NUCLEUS tone_nucleus_table[N_TONE_NUCLEUS_TABLE] = {
|
||||
{PITCHfall, 29, 4, PITCHfall, 32, 9, NULL, 12, 6, 0}, // 0 statement
|
||||
{PITCHfall, 29, 4, PITCHfall, 31, 8, NULL, 11, 6, 0}, // 0 statement
|
||||
{PITCHfrise, 35, 8, PITCHfrise2, 35,10, NULL, 15, 23, 0}, // 1 comma
|
||||
{PITCHfrise, 39,10, PITCHfrise2, 36,10, NULL, 15, 28, 0}, // 2 question
|
||||
// {PITCHfall, 41, 4, PITCHfall, 41,27, NULL, 16, 4, T_EMPH}, // 3 exclamation
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ wxMenuBar *MakeMenu(int type)
|
||||
data_menu->Append(MENU_COMPILE_DICT_DEBUG, _("Compile dictionary (debu&g)"));
|
||||
data_menu->Append(MENU_COMPILE_MBROLA, _("Compile &mbrola phonemes list..."));
|
||||
data_menu->AppendSeparator();
|
||||
data_menu->Append(MENU_FORMAT_DICTIONARY, _("&Format *_rules file"));
|
||||
data_menu->Append(MENU_FORMAT_DICTIONARY, _("&Layout *_rules file"));
|
||||
|
||||
// OPTIONS MENU
|
||||
paths_menu = new wxMenu;
|
||||
|
||||
+88
-46
@@ -67,6 +67,8 @@
|
||||
|
||||
static int n_digit_lookup;
|
||||
static char *digit_lookup;
|
||||
static int speak_missing_thousands;
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
@@ -589,8 +591,8 @@ void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_b
|
||||
|
||||
|
||||
|
||||
int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, int word_length)
|
||||
{//======================================================================================
|
||||
int TranslateLetter(Translator *tr, char *word, char *phonemes, int control)
|
||||
{//=========================================================================
|
||||
// get pronunciation for an isolated letter
|
||||
// return number of bytes used by the letter
|
||||
// control 2=say-as glyphs, 3-say-as chars
|
||||
@@ -755,27 +757,28 @@ void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars)
|
||||
static char ph_ordinal2[12];
|
||||
|
||||
|
||||
static int CheckDotOrdinal(Translator *tr, char *word, WORD_TAB *wtab, int lowercase)
|
||||
{//==================================================================================
|
||||
// nextupper: Next word must start with lower-case
|
||||
static int CheckDotOrdinal(Translator *tr, char *word, WORD_TAB *wtab, int roman)
|
||||
{//==============================================================================
|
||||
|
||||
int ordinal = 0;
|
||||
int c2;
|
||||
|
||||
if((tr->langopts.numbers & NUM_ORDINAL_DOT) && (word[0] == '.'))
|
||||
if((tr->langopts.numbers & NUM_ORDINAL_DOT) && ((word[0] == '.') || (wtab[0].flags & FLAG_HAS_DOT)) && !(wtab[1].flags & FLAG_NOSPACE))
|
||||
{
|
||||
if((lowercase==0) || !(wtab[1].flags & FLAG_FIRST_UPPER))
|
||||
if(roman || !(wtab[1].flags & FLAG_FIRST_UPPER))
|
||||
{
|
||||
utf8_in(&c2, &word[2]);
|
||||
if(IsAlpha(c2))
|
||||
if((word[1] != 0) && IsAlpha(c2))
|
||||
{
|
||||
// ordinal number is indicated by dot after the number
|
||||
// but not if the next word starts with an upper-case letter
|
||||
ordinal = 2;
|
||||
word[0] = ' ';
|
||||
if(tr->translator_name == L('h','u'))
|
||||
if(word[0] == '.')
|
||||
word[0] = ' ';
|
||||
|
||||
if((roman==0) && (tr->translator_name == L('h','u')))
|
||||
{
|
||||
// lang=hu don't treat dot as ordinal indicator if the next word is a month name ($alt)
|
||||
// lang=hu don't treat dot as ordinal indicator if the next word is a month name ($alt). It may have a suffix.
|
||||
if(TranslateWord(tr, &word[2], 0, NULL) & FLAG_ALT_TRANS)
|
||||
ordinal = 0;
|
||||
}
|
||||
@@ -799,7 +802,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
|
||||
int subtract;
|
||||
int repeat = 0;
|
||||
int n_digits = 0;
|
||||
unsigned int flags;
|
||||
unsigned int flags[2];
|
||||
char ph_roman[30];
|
||||
char number_chars[N_WORD_BYTES];
|
||||
|
||||
@@ -809,6 +812,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
|
||||
acc = 0;
|
||||
prev = 0;
|
||||
subtract = 0x7fff;
|
||||
ph_out[0] = 0;
|
||||
|
||||
if((tr->langopts.numbers & NUM_ROMAN_CAPITALS) && !(wtab[0].flags & FLAG_ALL_UPPER))
|
||||
return(0);
|
||||
@@ -861,12 +865,12 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
|
||||
if((tr->langopts.numbers & NUM_ROMAN_AFTER) == 0)
|
||||
{
|
||||
strcpy(ph_out,ph_roman);
|
||||
p = &ph_out[strlen(ph_out)];
|
||||
p = &ph_out[strlen(ph_roman)];
|
||||
}
|
||||
|
||||
sprintf(number_chars," %d ",acc);
|
||||
sprintf(number_chars," %d ",acc);
|
||||
|
||||
if(CheckDotOrdinal(tr, word, wtab, 0))
|
||||
if(CheckDotOrdinal(tr, word, wtab, 1))
|
||||
wtab[0].flags |= FLAG_ORDINAL;
|
||||
|
||||
if(tr->langopts.numbers & NUM_ROMAN_ORDINAL)
|
||||
@@ -876,8 +880,8 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
|
||||
wtab[0].flags |= FLAG_ORDINAL;
|
||||
}
|
||||
|
||||
|
||||
TranslateNumber(tr, &number_chars[1], p, &flags, wtab);
|
||||
tr->prev_dict_flags = 0;
|
||||
TranslateNumber(tr, &number_chars[2], p, flags, wtab);
|
||||
|
||||
if(tr->langopts.numbers & NUM_ROMAN_AFTER)
|
||||
strcat(ph_out,ph_roman);
|
||||
@@ -922,6 +926,7 @@ static int LookupThousands(Translator *tr, int value, int thousandplex, int thou
|
||||
char string[12];
|
||||
char ph_of[12];
|
||||
char ph_thousands[40];
|
||||
char ph_buf[40];
|
||||
|
||||
ph_of[0] = 0;
|
||||
|
||||
@@ -976,10 +981,24 @@ static int LookupThousands(Translator *tr, int value, int thousandplex, int thou
|
||||
|
||||
if(Lookup(tr, string, ph_thousands) == 0)
|
||||
{
|
||||
// repeat "thousand" if higher order names are not available
|
||||
sprintf(string,"_%dM1",value);
|
||||
if((found_value = Lookup(tr, string, ph_thousands)) == 0)
|
||||
Lookup(tr, "_0M1", ph_thousands);
|
||||
if(thousandplex > 3)
|
||||
{
|
||||
sprintf(string,"_0M%d", thousandplex-1);
|
||||
if(Lookup(tr, string, ph_buf) == 0)
|
||||
{
|
||||
// say "millions" if this name is not available and neither is the next lower
|
||||
Lookup(tr, "_0M2", ph_thousands);
|
||||
speak_missing_thousands = 3;
|
||||
}
|
||||
}
|
||||
if(ph_thousands[0] == 0)
|
||||
{
|
||||
// repeat "thousand" if higher order names are not available
|
||||
sprintf(string,"_%dM1",value);
|
||||
if((found_value = Lookup(tr, string, ph_thousands)) == 0)
|
||||
Lookup(tr, "_0M1", ph_thousands);
|
||||
speak_missing_thousands = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1015,6 +1034,9 @@ static int LookupNum2(Translator *tr, int value, int control, char *ph_out)
|
||||
|
||||
found = 0;
|
||||
ph_ordinal[0] = 0;
|
||||
ph_tens[0] = 0;
|
||||
ph_digits[0] = 0;
|
||||
ph_and[0] = 0;
|
||||
|
||||
if((control & 2) && (n_digit_lookup == 2))
|
||||
{
|
||||
@@ -1366,7 +1388,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
|
||||
int n_digits;
|
||||
int value;
|
||||
unsigned int ix;
|
||||
int ix;
|
||||
unsigned char c;
|
||||
int suppress_null = 0;
|
||||
int decimal_point = 0;
|
||||
@@ -1376,7 +1398,6 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
int prev_thousands = 0;
|
||||
int ordinal = 0;
|
||||
int this_value;
|
||||
static int prev_value;
|
||||
int decimal_count;
|
||||
int max_decimal_count;
|
||||
int decimal_mode;
|
||||
@@ -1394,16 +1415,48 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
static const char str_pause[2] = {phonPAUSE_NOLINK,0};
|
||||
|
||||
*flags = 0;
|
||||
n_digit_lookup = 0;
|
||||
buf_digit_lookup[0] = 0;
|
||||
digit_lookup = buf_digit_lookup;
|
||||
|
||||
for(ix=0; isdigit(word[ix]); ix++) ;
|
||||
n_digits = ix;
|
||||
value = this_value = atoi(word);
|
||||
|
||||
// is there a previous thousands part (as a previous "word") ?
|
||||
if((n_digits == 3) && (word[-2] == tr->langopts.thousands_sep) && isdigit(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) && isdigit(word[-2]))
|
||||
{
|
||||
prev_thousands = 1;
|
||||
}
|
||||
}
|
||||
if(prev_thousands == 0)
|
||||
{
|
||||
speak_missing_thousands = 0;
|
||||
}
|
||||
|
||||
|
||||
ph_ordinal2[0] = 0;
|
||||
ph_zeros[0] = 0;
|
||||
|
||||
ordinal = CheckDotOrdinal(tr, &word[ix], wtab, 1);
|
||||
if(prev_thousands || (word[0] != '0'))
|
||||
{
|
||||
// don't check for ordinal if the number has a leading zero
|
||||
ordinal = CheckDotOrdinal(tr, &word[ix], wtab, 0);
|
||||
}
|
||||
|
||||
if((word[ix] == '.') && !isdigit(word[ix+1]) && !isdigit(word[ix+2]) && !(wtab[1].flags & FLAG_NOSPACE))
|
||||
{
|
||||
// remove dot unless followed by another number
|
||||
word[ix] = 0;
|
||||
}
|
||||
|
||||
if(ordinal == 0)
|
||||
{
|
||||
@@ -1417,7 +1470,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
hyphen = 1;
|
||||
ix++;
|
||||
}
|
||||
while((word[ix] != 0) && (word[ix] != ' ') && (ix < (sizeof(suffix)-1)))
|
||||
while((word[ix] != 0) && (word[ix] != ' ') && (ix < int(sizeof(suffix)-1)))
|
||||
{
|
||||
*p++ = word[ix++];
|
||||
}
|
||||
@@ -1442,20 +1495,6 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
ph_append[0] = 0;
|
||||
ph_buf2[0] = 0;
|
||||
|
||||
// is there a previous thousands part (as a previous "word") ?
|
||||
if((n_digits == 3) && (word[-2] == tr->langopts.thousands_sep) && isdigit(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) && isdigit(word[-2]))
|
||||
{
|
||||
prev_thousands = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if((word[0] == '0') && (prev_thousands == 0) && (word[1] != ' ') && (word[1] != tr->langopts.decimal_sep))
|
||||
{
|
||||
@@ -1532,12 +1571,13 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
}
|
||||
}
|
||||
else
|
||||
if((thousandplex > 1) && prev_thousands && (prev_value > 0))
|
||||
|
||||
if(speak_missing_thousands == 1)
|
||||
{
|
||||
sprintf(string,"_%s%d",M_Variant(value),thousandplex+1);
|
||||
// speak this thousandplex if there was no word for the previous thousandplex
|
||||
sprintf(string,"_0M%d",thousandplex+1);
|
||||
if(Lookup(tr, string, buf1)==0)
|
||||
{
|
||||
// speak this thousandplex if there was no word for the previous thousandplex
|
||||
sprintf(string,"_0M%d",thousandplex);
|
||||
Lookup(tr, string, ph_append);
|
||||
}
|
||||
@@ -1548,8 +1588,6 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
Lookup(tr, "_.", ph_append);
|
||||
}
|
||||
|
||||
n_digit_lookup = 0;
|
||||
buf_digit_lookup[0] = 0;
|
||||
if(thousandplex == 0)
|
||||
{
|
||||
char *p2;
|
||||
@@ -1560,13 +1598,17 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
{
|
||||
p2 = p - 1;
|
||||
if(LookupDictList(tr, &p2, buf_digit_lookup, flags, FLAG_SUFX, wtab)) // lookup 2 digits
|
||||
{
|
||||
n_digit_lookup = 2;
|
||||
}
|
||||
}
|
||||
if((buf_digit_lookup[0] == 0) && (*p != '0'))
|
||||
{
|
||||
// not found, lookup only the last digit
|
||||
if(LookupDictList(tr, &p, buf_digit_lookup, flags, FLAG_SUFX, wtab)) // don't match '0', or entries with $only
|
||||
n_digit_lookup = 1;
|
||||
{
|
||||
n_digit_lookup = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1674,7 +1716,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
}
|
||||
|
||||
*flags |= FLAG_FOUND;
|
||||
prev_value = this_value;
|
||||
speak_missing_thousands--;
|
||||
return(1);
|
||||
} // end of TranslateNumber_1
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ extern const unsigned char pause_phonemes[8]; // 0, vshort, short, pause, long,
|
||||
|
||||
// place of articulation
|
||||
#define phPLACE 0xf0000
|
||||
#define phPLACE_blb 0x10000
|
||||
#define phPLACE_pla 0x60000
|
||||
|
||||
#define N_PHONEME_TABS 100 // number of phoneme tables
|
||||
|
||||
+99
-4
@@ -61,6 +61,7 @@ static int ignore_text=0; // set during <sub> ... </sub> to ignore text which
|
||||
static int clear_skipping_text = 0; // next clause should clear the skipping_text flag
|
||||
int count_characters = 0;
|
||||
static int sayas_mode;
|
||||
static int sayas_start;
|
||||
static int ssml_ignore_l_angle = 0;
|
||||
|
||||
// alter tone for announce punctuation or capitals
|
||||
@@ -1521,6 +1522,31 @@ static void SetProsodyParameter(int param_type, wchar_t *attr1, PARAM_STACK *sp)
|
||||
} // end of SetProsodyParemeter
|
||||
|
||||
|
||||
static int ReplaceKeyName(char *outbuf, int index, int &outix)
|
||||
{//===========================================================
|
||||
// Replace some key-names by single characters, so they can be pronounced in different languages
|
||||
MNEM_TAB keynames[] = {
|
||||
{"space ",0xe020},
|
||||
{"tab ", 0xe009},
|
||||
{"underscore ", 0xe05f},
|
||||
{"double-quote ", '"'},
|
||||
{NULL, 0}};
|
||||
|
||||
int ix;
|
||||
int letter;
|
||||
char *p;
|
||||
|
||||
p = &outbuf[index+1];
|
||||
|
||||
if((letter = LookupMnem(keynames, p)) != 0)
|
||||
{
|
||||
ix = utf8_out(letter, p);
|
||||
outix = index + ix + 1;
|
||||
return(letter);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int &outix, int n_outbuf, int self_closing)
|
||||
{//==================================================================================================
|
||||
@@ -1706,10 +1732,17 @@ static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int &outix, int n_outb
|
||||
strcpy(&outbuf[outix],buf);
|
||||
outix += strlen(buf);
|
||||
|
||||
sayas_start = outix;
|
||||
sayas_mode = value; // punctuation doesn't end clause during SAY-AS
|
||||
break;
|
||||
|
||||
case SSML_SAYAS + SSML_CLOSE:
|
||||
if(sayas_mode == SAYAS_KEY)
|
||||
{
|
||||
outbuf[outix] = 0;
|
||||
ReplaceKeyName(outbuf, sayas_start, outix);
|
||||
}
|
||||
|
||||
outbuf[outix++] = CTRL_EMBEDDED;
|
||||
outbuf[outix++] = 'Y';
|
||||
sayas_mode = 0;
|
||||
@@ -1971,6 +2004,8 @@ int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix
|
||||
int is_end_clause;
|
||||
int announced_punctuation;
|
||||
int stressed_word = 0;
|
||||
int end_clause_after_tag = 0;
|
||||
int end_clause_index = 0;
|
||||
const char *p;
|
||||
wchar_t xml_buf[N_XML_BUF+1];
|
||||
|
||||
@@ -1985,6 +2020,7 @@ int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix
|
||||
clear_skipping_text = 0;
|
||||
}
|
||||
|
||||
tr->phonemes_repeat_count = 0;
|
||||
tr->clause_upper_count = 0;
|
||||
tr->clause_lower_count = 0;
|
||||
end_of_input = 0;
|
||||
@@ -2150,6 +2186,9 @@ f_input = f_in; // for GetC etc
|
||||
|
||||
if(terminator != 0)
|
||||
{
|
||||
if(end_clause_after_tag)
|
||||
ix = end_clause_index;
|
||||
|
||||
buf[ix] = ' ';
|
||||
buf[ix++] = 0;
|
||||
|
||||
@@ -2333,6 +2372,9 @@ f_input = f_in; // for GetC etc
|
||||
// 2nd newline, assume paragraph
|
||||
UngetC(c2);
|
||||
|
||||
if(end_clause_after_tag)
|
||||
ix = end_clause_index; // delete clause-end punctiation
|
||||
|
||||
buf[ix] = ' ';
|
||||
buf[ix+1] = 0;
|
||||
if(parag > 3)
|
||||
@@ -2359,6 +2401,30 @@ if(option_ssml) parag=1;
|
||||
{
|
||||
is_end_clause = 0;
|
||||
|
||||
if(end_clause_after_tag)
|
||||
{
|
||||
// Because of an xml tag, we are waiting for the
|
||||
// next non-blank character to decide whether to end the clause
|
||||
// i.e. is dot followed by an upper-case letter?
|
||||
if(c1 == '\n')
|
||||
{
|
||||
// end_clause_after_tag &= ~CLAUSE_DOT;
|
||||
}
|
||||
|
||||
if(!iswspace(c1))
|
||||
{
|
||||
if(iswdigit(c1) || (IsAlpha(c1) && !iswlower(c1)))
|
||||
{
|
||||
UngetC(c2);
|
||||
ungot_char2 = c1;
|
||||
buf[end_clause_index] = ' '; // delete the end-clause punctuation
|
||||
buf[end_clause_index+1] = 0;
|
||||
return(end_clause_after_tag);
|
||||
}
|
||||
end_clause_after_tag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if((c1 == '.') && (c2 == '.'))
|
||||
{
|
||||
while((c_next = GetC()) == '.')
|
||||
@@ -2396,6 +2462,7 @@ if(option_ssml) parag=1;
|
||||
// if a list of allowed punctuation has been set up, check whether the character is in it
|
||||
if((option_punctuation == 1) || (wcschr(option_punctlist,c1) != NULL))
|
||||
{
|
||||
tr->phonemes_repeat_count = 0;
|
||||
if((terminator = AnnouncePunctuation(tr, c1, &c2, buf, &ix, is_end_clause)) >= 0)
|
||||
return(terminator);
|
||||
announced_punctuation = c1;
|
||||
@@ -2432,6 +2499,11 @@ if(option_ssml) parag=1;
|
||||
}
|
||||
}
|
||||
|
||||
if((c1 == '.') && (nl_count < 2))
|
||||
{
|
||||
punct_data |= CLAUSE_DOT;
|
||||
}
|
||||
|
||||
if(nl_count==0)
|
||||
{
|
||||
if(c1 == '.')
|
||||
@@ -2440,14 +2512,21 @@ if(option_ssml) parag=1;
|
||||
(iswdigit(cprev) || (IsRomanU(cprev) && (IsRomanU(cprev2) || iswspace(cprev2))))) // lang=hu
|
||||
{
|
||||
// dot after a number indicates an ordinal number
|
||||
if(!iswdigit(cprev) || iswlower(c_next) || (c_next == '<'))
|
||||
is_end_clause = 0; // only if followed by lower-case, (or if there is a XML tag)
|
||||
if(!iswdigit(cprev))
|
||||
{
|
||||
is_end_clause = 0; // Roman number followed by dot
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iswlower(c_next))
|
||||
is_end_clause = 0; // only if followed by lower-case, (or if there is a XML tag)
|
||||
}
|
||||
}
|
||||
else
|
||||
if(iswlower(c_next))
|
||||
{
|
||||
// next word has no capital letter, this dot is probably from an abbreviation
|
||||
c1 = ' ';
|
||||
// c1 = ' ';
|
||||
is_end_clause = 0;
|
||||
}
|
||||
if(any_alnum==0)
|
||||
@@ -2466,6 +2545,14 @@ if(option_ssml) parag=1;
|
||||
is_end_clause = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(is_end_clause && (c1 == '.') && (c_next == '<') && option_ssml)
|
||||
{
|
||||
// wait until after the end of the xml tag, then look for upper-case letter
|
||||
is_end_clause = 0;
|
||||
end_clause_index = ix;
|
||||
end_clause_after_tag = punct_data;
|
||||
}
|
||||
}
|
||||
|
||||
if(is_end_clause)
|
||||
@@ -2473,7 +2560,11 @@ if(option_ssml) parag=1;
|
||||
UngetC(c_next);
|
||||
buf[ix] = ' ';
|
||||
buf[ix+1] = 0;
|
||||
|
||||
|
||||
if(!IsAlpha(c_next))
|
||||
{
|
||||
punct_data &= ~CLAUSE_DOT;
|
||||
}
|
||||
if(nl_count > 1)
|
||||
{
|
||||
if((punct_data == CLAUSE_QUESTION) || (punct_data == CLAUSE_EXCLAMATION))
|
||||
@@ -2536,6 +2627,10 @@ if(option_ssml) parag=1;
|
||||
{
|
||||
ix += utf8_out(CHAR_EMPHASIS, &buf[ix]);
|
||||
}
|
||||
if(end_clause_after_tag)
|
||||
{
|
||||
ix = end_clause_index; // delete clause-end punctuation
|
||||
}
|
||||
buf[ix] = ' ';
|
||||
buf[ix+1] = 0;
|
||||
return(CLAUSE_EOF); // end of file
|
||||
|
||||
+2
-2
@@ -326,10 +326,10 @@ void CalcLengths(Translator *tr)
|
||||
case phSTOP:
|
||||
last_pitch = 0;
|
||||
if(prev->type == phFRICATIVE)
|
||||
p->prepause = 20;
|
||||
p->prepause = 25;
|
||||
else
|
||||
if((more_syllables > 0) || (stress < 4))
|
||||
p->prepause = 40;
|
||||
p->prepause = 48;
|
||||
else
|
||||
p->prepause = 60;
|
||||
|
||||
|
||||
+39
-1
@@ -47,6 +47,7 @@
|
||||
#include "wave.h"
|
||||
|
||||
unsigned char *outbuf=NULL;
|
||||
extern FILE *f_logespeak;
|
||||
extern espeak_VOICE voice_selected;
|
||||
|
||||
espeak_EVENT *event_list=NULL;
|
||||
@@ -713,7 +714,12 @@ ENTER("espeak_Initialize");
|
||||
init_path(path);
|
||||
initialise();
|
||||
select_output(output_type);
|
||||
|
||||
|
||||
if(f_logespeak)
|
||||
{
|
||||
fprintf(f_logespeak,"INIT mode %d options 0x%x\n",output_type,options);
|
||||
}
|
||||
|
||||
// buflength is in mS, allocate 2 bytes per sample
|
||||
if(buf_length == 0)
|
||||
buf_length = 200;
|
||||
@@ -763,6 +769,12 @@ ESPEAK_API espeak_ERROR espeak_Synth(const void *text, size_t size,
|
||||
SHOW("espeak_Synth > position=%d, position_type=%d, end_position=%d, flags=%d, user_data=0x%x, text=%s\n", position, position_type, end_position, flags, user_data, text);
|
||||
#endif
|
||||
|
||||
if(f_logespeak)
|
||||
{
|
||||
fprintf(f_logespeak,"\nSYNTH posn %d %d %d flags 0x%x\n%s\n",position,end_position,position_type,flags, (const char *)text);
|
||||
fflush(f_logespeak);
|
||||
}
|
||||
|
||||
espeak_ERROR a_error=EE_INTERNAL_ERROR;
|
||||
static unsigned int temp_identifier;
|
||||
|
||||
@@ -825,6 +837,12 @@ ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text, size_t size,
|
||||
espeak_ERROR a_error=EE_OK;
|
||||
static unsigned int temp_identifier;
|
||||
|
||||
if(f_logespeak)
|
||||
{
|
||||
fprintf(f_logespeak,"\nSYNTH MARK %s posn %d flags 0x%x\n%s\n",index_mark,end_position,flags, (const char *)text);
|
||||
}
|
||||
|
||||
|
||||
if (unique_identifier == NULL)
|
||||
{
|
||||
unique_identifier = &temp_identifier;
|
||||
@@ -875,6 +893,11 @@ ESPEAK_API espeak_ERROR espeak_Key(const char *key)
|
||||
ENTER("espeak_Key");
|
||||
// symbolic name, symbolicname_character - is there a system resource of symbolicnames per language
|
||||
|
||||
if(f_logespeak)
|
||||
{
|
||||
fprintf(f_logespeak,"\nKEY %s\n",key);
|
||||
}
|
||||
|
||||
espeak_ERROR a_error = EE_OK;
|
||||
|
||||
if(synchronous_mode)
|
||||
@@ -901,6 +924,11 @@ ESPEAK_API espeak_ERROR espeak_Char(wchar_t character)
|
||||
ENTER("espeak_Char");
|
||||
// is there a system resource of character names per language?
|
||||
|
||||
if(f_logespeak)
|
||||
{
|
||||
fprintf(f_logespeak,"\nCHAR U+%x\n",character);
|
||||
}
|
||||
|
||||
#ifdef USE_ASYNC
|
||||
espeak_ERROR a_error;
|
||||
|
||||
@@ -997,6 +1025,10 @@ ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int valu
|
||||
{//=============================================================================================
|
||||
ENTER("espeak_SetParameter");
|
||||
|
||||
if(f_logespeak)
|
||||
{
|
||||
fprintf(f_logespeak,"SETPARAM %d %d %d\n",parameter,value,relative);
|
||||
}
|
||||
#ifdef USE_ASYNC
|
||||
espeak_ERROR a_error;
|
||||
|
||||
@@ -1141,6 +1173,12 @@ ESPEAK_API espeak_ERROR espeak_Terminate(void)
|
||||
outbuf = NULL;
|
||||
FreePhData();
|
||||
|
||||
if(f_logespeak)
|
||||
{
|
||||
fclose(f_logespeak);
|
||||
f_logespeak = NULL;
|
||||
}
|
||||
|
||||
return EE_OK;
|
||||
} // end of espeak_Terminate
|
||||
|
||||
|
||||
+1
-1
@@ -507,7 +507,7 @@ const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec);
|
||||
The list is terminated by a NULL pointer
|
||||
|
||||
If voice_spec is NULL then all voices are listed.
|
||||
If voice spec is give, then only the voices which are compatible with the voice_spec
|
||||
If voice spec is given, then only the voices which are compatible with the voice_spec
|
||||
are listed, and they are listed in preference order.
|
||||
*/
|
||||
|
||||
|
||||
+14
-2
@@ -35,10 +35,12 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.41.32 09.Nov.09";
|
||||
const int version_phdata = 0x014118;
|
||||
const char *version_string = "1.42.02 30.Nov.09";
|
||||
const int version_phdata = 0x014200;
|
||||
|
||||
int option_device_number = -1;
|
||||
FILE *f_logespeak = NULL;
|
||||
int logging_type;
|
||||
|
||||
// copy the current phoneme table into here
|
||||
int n_phoneme_tab;
|
||||
@@ -640,6 +642,8 @@ void LoadConfig(void)
|
||||
char *p;
|
||||
char string[200];
|
||||
|
||||
logging_type = 0;
|
||||
|
||||
for(ix=0; ix<N_SOUNDICON_SLOTS; ix++)
|
||||
{
|
||||
soundicon_tab[ix].filename = NULL;
|
||||
@@ -654,6 +658,14 @@ void LoadConfig(void)
|
||||
|
||||
while(fgets(buf,sizeof(buf),f)!=NULL)
|
||||
{
|
||||
if(buf[0] == '/') continue;
|
||||
|
||||
if(memcmp(buf,"log",3)==0)
|
||||
{
|
||||
if(sscanf(&buf[4],"%d %s",&logging_type,string)==2)
|
||||
f_logespeak = fopen(string,"w");
|
||||
}
|
||||
else
|
||||
if(memcmp(buf,"tone",4)==0)
|
||||
{
|
||||
ReadTonePoints(&buf[5],tone_points);
|
||||
|
||||
+51
-12
@@ -876,36 +876,65 @@ int DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph,
|
||||
int ix;
|
||||
long *q;
|
||||
int len;
|
||||
int min;
|
||||
int match_level;
|
||||
int frame_length;
|
||||
int frame1_length;
|
||||
int frame2_length;
|
||||
int length_factor;
|
||||
int length_mod;
|
||||
int length_mod2; // reduced effect length_mod
|
||||
int total_len = 0;
|
||||
int len_adjust_factor = 256;
|
||||
static int wave_flag = 0;
|
||||
int wcmd_spect = WCMD_SPECT;
|
||||
|
||||
length_mod = plist->length;
|
||||
if(length_mod==0) length_mod=256;
|
||||
|
||||
if(which==1)
|
||||
{
|
||||
// limit the shortening of sonorants before shortened (eg. unstressed vowels)
|
||||
if((this_ph->type==phLIQUID) || (prev_ph->type==phLIQUID) || (prev_ph->type==phNASAL))
|
||||
length_mod2 = (length_mod*(256-speed.speed_factor3) + 256*speed.speed_factor3)/256;
|
||||
|
||||
if(which==1)
|
||||
{
|
||||
if(length_mod < (len = translator->langopts.param[LOPT_SONORANT_MIN]))
|
||||
// limit the shortening of sonorants before shortened (eg. unstressed vowels)
|
||||
if((this_ph->type==phLIQUID) || (prev_ph->type==phLIQUID) || (prev_ph->type==phNASAL))
|
||||
{
|
||||
length_mod = len;
|
||||
if(length_mod < (len = translator->langopts.param[LOPT_SONORANT_MIN]))
|
||||
{
|
||||
length_mod = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modn_flags = 0;
|
||||
frames = LookupSpect(this_ph,prev_ph,next_ph,which,&match_level,&n_frames, plist);
|
||||
if(frames == NULL)
|
||||
return(0); // not found
|
||||
|
||||
// if((which==2) && (this_ph->phflags & phLONG))
|
||||
if((which==2) && (this_ph->std_length >= 200))
|
||||
{
|
||||
// apply a minimum length for long vowels at fast speeds, to keep the distinction with short vowels
|
||||
total_len = 0;
|
||||
for(frameix=0; frameix<(n_frames-1); frameix++)
|
||||
{
|
||||
length_factor = length_mod;
|
||||
if(frames[frameix].frflags & FRFLAG_LEN_MOD) // reduce effect of length mod
|
||||
{
|
||||
length_factor = length_mod2;
|
||||
}
|
||||
len = (frames[frameix].length * samplerate)/1000;
|
||||
len = (len * length_factor)/256;
|
||||
total_len += len;
|
||||
}
|
||||
|
||||
min = translator->langopts.param[LOPT_MIN_LONG_VOWEL] * (samplerate)/1000;
|
||||
min = (min * length_mod2)/256;
|
||||
if(total_len < min)
|
||||
{
|
||||
len_adjust_factor = (min*256)/total_len;
|
||||
}
|
||||
}
|
||||
|
||||
frame1 = frames[0].frame;
|
||||
frame1_length = frames[0].length;
|
||||
if(voice->klattv[0])
|
||||
@@ -960,6 +989,7 @@ if(which==1)
|
||||
syllable_centre = wcmdq_tail;
|
||||
}
|
||||
|
||||
total_len = 0;
|
||||
frame_length = frame1_length;
|
||||
for(frameix=1; frameix<n_frames; frameix++)
|
||||
{
|
||||
@@ -978,10 +1008,11 @@ if(which==1)
|
||||
length_factor = length_mod;
|
||||
if(frame1->frflags & FRFLAG_LEN_MOD) // reduce effect of length mod
|
||||
{
|
||||
length_factor = (length_mod*(256-speed.speed_factor3) + 256*speed.speed_factor3)/256;
|
||||
length_factor = length_mod2;
|
||||
}
|
||||
len = (frame_length * samplerate)/1000;
|
||||
len = (len * length_factor)/256;
|
||||
len = (len * len_adjust_factor)/256;
|
||||
|
||||
if(modulation >= 0)
|
||||
{
|
||||
@@ -1210,8 +1241,16 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
|
||||
case phSTOP:
|
||||
released = 0;
|
||||
if(next->type==phVOWEL) released = 1;
|
||||
if(next->type==phLIQUID && !next->newword) released = 1;
|
||||
if(next->type==phVOWEL)
|
||||
{
|
||||
released = 1;
|
||||
}
|
||||
else
|
||||
if(!next->newword)
|
||||
{
|
||||
if(next->type==phLIQUID) released = 1;
|
||||
// if(((p->ph->phflags & phPLACE) == phPLACE_blb) && (next->ph->phflags & phSIBILANT)) released = 1;
|
||||
}
|
||||
|
||||
if(released)
|
||||
DoSample(p->ph,next->ph,2,0,0);
|
||||
@@ -1307,7 +1346,7 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
}
|
||||
}
|
||||
|
||||
if((next->type==phVOWEL) || ((next->type==phLIQUID)) && (next->newword==0)) // ?? test 14.Aug.2007
|
||||
if((next->type==phVOWEL) || ((next->type==phLIQUID) && (next->newword==0))) // ?? test 14.Aug.2007
|
||||
{
|
||||
StartSyllable();
|
||||
if(p->synthflags & SFLAG_LENGTHEN)
|
||||
|
||||
+28
-13
@@ -46,6 +46,7 @@
|
||||
#define OFFSET_GREEK 0x380
|
||||
#define OFFSET_CYRILLIC 0x420
|
||||
#define OFFSET_ARMENIAN 0x530
|
||||
#define OFFSET_ARABIC 0x600
|
||||
#define OFFSET_DEVANAGARI 0x900
|
||||
#define OFFSET_BENGALI 0x980
|
||||
#define OFFSET_GURMUKHI 0xa00
|
||||
@@ -156,6 +157,7 @@ static Translator* NewTranslator(void)
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 's'; // don't count this character at start of word
|
||||
tr->langopts.param[LOPT_BRACKET_PAUSE] = 4; // pause at bracket
|
||||
tr->langopts.param2[LOPT_BRACKET_PAUSE] = 2; // pauses when announcing bracket names
|
||||
tr->langopts.param[LOPT_MIN_LONG_VOWEL] = 40;
|
||||
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
|
||||
@@ -221,7 +223,9 @@ void SetIndicLetters(Translator *tr)
|
||||
static const char dev_consonants2[] = {0x02,0x03,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f};
|
||||
|
||||
memset(tr->letter_bits,0,sizeof(tr->letter_bits));
|
||||
SetLetterBitsRange(tr,LETTERGP_A,0x04,0x14); // vowel letters only
|
||||
SetLetterBitsRange(tr,LETTERGP_A,0x04,0x14); // vowel letters
|
||||
SetLetterBitsRange(tr,LETTERGP_A,0x3e,0x4d); // + vowel signs, and virama
|
||||
|
||||
SetLetterBitsRange(tr,LETTERGP_B,0x3e,0x4d); // vowel signs, and virama
|
||||
|
||||
SetLetterBitsRange(tr,LETTERGP_C,0x15,0x39); // the main consonant range
|
||||
@@ -274,6 +278,12 @@ Translator *SelectTranslator(const char *name)
|
||||
}
|
||||
break;
|
||||
|
||||
case L('a','r'): // Arabic
|
||||
case L('u','r'): // Urdu
|
||||
tr->letter_bits_offset = OFFSET_ARABIC;
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
|
||||
break;
|
||||
|
||||
case L('b','n'): // Bengali
|
||||
{
|
||||
static const short stress_lengths_bn[8] = {180, 180, 210, 210, 0, 0, 230, 240};
|
||||
@@ -463,13 +473,15 @@ Translator *SelectTranslator(const char *name)
|
||||
static const unsigned char stress_amps_eu[8] = {16,16, 18,18, 18,18, 18,18 };
|
||||
SetupTranslator(tr,stress_lengths_eu,stress_amps_eu);
|
||||
tr->langopts.stress_rule = STRESSPOSN_2L; // ?? second syllable ??
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS + NUM_DECIMAL_COMMA | NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_VIGESIMAL;
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_AND_UNITS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_VIGESIMAL;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case L('f','a'): // Farsi
|
||||
{
|
||||
tr->letter_bits_offset = OFFSET_ARABIC;
|
||||
tr->langopts.numbers = NUM_AND_UNITS | NUM_HUNDRED_AND;
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
|
||||
}
|
||||
break;
|
||||
@@ -486,6 +498,7 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.stress_flags = 0x56; // move secondary stress from light to a following heavy syllable
|
||||
tr->langopts.param[LOPT_IT_DOUBLING] = 1;
|
||||
tr->langopts.long_stop = 130;
|
||||
tr->langopts.param[LOPT_MIN_LONG_VOWEL] = 65;
|
||||
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA + NUM_ALLOW_SPACE;
|
||||
SetLetterVowel(tr,'y');
|
||||
@@ -506,7 +519,7 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.stress_flags = 0x0024; // don't use secondary stress
|
||||
tr->langopts.param[LOPT_IT_LENGTHEN] = 1; // remove lengthen indicator from unstressed syllables
|
||||
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS + NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_NOPAUSE | NUM_ROMAN | NUM_VIGESIMAL | NUM_DFRACTION_4;
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_NOPAUSE | NUM_ROMAN | NUM_VIGESIMAL | NUM_DFRACTION_4;
|
||||
SetLetterVowel(tr,'y');
|
||||
}
|
||||
break;
|
||||
@@ -558,7 +571,7 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.spelling_stress = 1;
|
||||
tr->langopts.accents = 1;
|
||||
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS + NUM_HUNDRED_AND | NUM_DECIMAL_COMMA | NUM_THOUS_SPACE | NUM_DFRACTION_2 | NUM_ROMAN_UC;
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_HUNDRED_AND | NUM_OMIT_1_HUNDRED | NUM_DECIMAL_COMMA | NUM_THOUS_SPACE | NUM_DFRACTION_2 | NUM_ROMAN_UC;
|
||||
tr->langopts.numbers2 = 0x4a; // variant numbers before thousands,milliards
|
||||
tr->langopts.replace_chars = replace_cyrillic_latin;
|
||||
|
||||
@@ -578,11 +591,11 @@ Translator *SelectTranslator(const char *name)
|
||||
|
||||
tr->langopts.vowel_pause = 0x20;
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.stress_flags = 0x8036 | STRS_HYPEN_UNSTRESS;
|
||||
tr->langopts.stress_flags = 0x8036 | S_HYPEN_UNSTRESS;
|
||||
tr->langopts.unstressed_wd1 = 2;
|
||||
tr->langopts.param[LOPT_IT_DOUBLING] = 1;
|
||||
tr->langopts.param[LOPT_ANNOUNCE_PUNCT] = 2; // don't break clause before announcing . ? !
|
||||
// tr->langopts.param[LOPT_COMBINE_WORDS] = 9; // combine some prepositions with the following word
|
||||
tr->langopts.param[LOPT_MIN_LONG_VOWEL] = 65;
|
||||
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_DFRACTION_5 | NUM_ROMAN | NUM_ROMAN_ORDINAL | NUM_ROMAN_CAPITALS | NUM_ORDINAL_DOT | NUM_OMIT_1_HUNDRED;
|
||||
tr->langopts.min_roman = 1;
|
||||
@@ -786,7 +799,7 @@ SetLengthMods(tr,3); // all equal
|
||||
SetupTranslator(tr,stress_lengths_no,NULL);
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
SetLetterVowel(tr,'y');
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_ALLOW_SPACE | NUM_1900 + NUM_ORDINAL_DOT;
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_HUNDRED_AND | NUM_ALLOW_SPACE | NUM_1900 | NUM_ORDINAL_DOT;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -822,18 +835,19 @@ SetLengthMods(tr,3); // all equal
|
||||
|
||||
case L('p','t'): // Portuguese
|
||||
{
|
||||
static const short stress_lengths_pt[8] = {180, 125, 210, 210, 0, 0, 270, 295};
|
||||
static const unsigned char stress_amps_pt[8] = {16,13, 19,19, 20,22, 22,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable
|
||||
static const short stress_lengths_pt[8] = {170, 115, 210, 240, 0, 0, 260, 280};
|
||||
static const unsigned char stress_amps_pt[8] = {16,11, 19,21, 20,22, 22,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable
|
||||
|
||||
SetupTranslator(tr,stress_lengths_pt,stress_amps_pt);
|
||||
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
|
||||
|
||||
tr->langopts.stress_rule = STRESSPOSN_1R; // stress on final syllable
|
||||
tr->langopts.stress_flags = 0x6 | 0x10 | 0x20000;
|
||||
tr->langopts.stress_flags = 0x6 | 0x10 | 0x2000 | 0x20000;
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_DFRACTION_2 | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_ROMAN;
|
||||
SetLetterVowel(tr,'y');
|
||||
ResetLetterBits(tr,0x2);
|
||||
SetLetterBits(tr,1,"bcdfgjkmnpqstvxz"); // B hard consonants, excluding h,l,r,w,y
|
||||
tr->langopts.param[LOPT_ALT] = 2; // call ApplySpecialAttributes2() if a word has $alt or $alt2
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -924,7 +938,7 @@ SetLengthMods(tr,3); // all equal
|
||||
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
SetLetterVowel(tr,'y');
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS + NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_1900;
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_1900;
|
||||
tr->langopts.accents = 1;
|
||||
}
|
||||
break;
|
||||
@@ -959,7 +973,7 @@ SetLengthMods(tr,3); // all equal
|
||||
|
||||
tr->langopts.stress_rule = STRESSPOSN_1L;
|
||||
tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable
|
||||
tr->langopts.break_numbers = 0x24a8; // 1000, 100,000 10,000,000
|
||||
tr->langopts.break_numbers = 0x14a8; // 1000, 100,000 10,000,000
|
||||
|
||||
if(name2 == L('t','a'))
|
||||
{
|
||||
@@ -1015,7 +1029,7 @@ SetLengthMods(tr,3); // all equal
|
||||
tr->langopts.stress_rule = 7; // stress on the last syllable, before any explicitly unstressed syllable
|
||||
tr->langopts.stress_flags = 0x20; //no automatic secondary stress
|
||||
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS + NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_DFRACTION_2;
|
||||
tr->langopts.numbers = NUM_SINGLE_STRESS | NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_DFRACTION_2;
|
||||
tr->langopts.max_initial_consonants = 2;
|
||||
}
|
||||
break;
|
||||
@@ -1093,6 +1107,7 @@ SetLengthMods(tr,3); // all equal
|
||||
{
|
||||
tr->langopts.thousands_sep = 0; // don't allow thousands separator, except space
|
||||
}
|
||||
|
||||
return(tr);
|
||||
} // end of SelectTranslator
|
||||
|
||||
|
||||
+96
-45
@@ -80,7 +80,11 @@ int pre_pause;
|
||||
|
||||
|
||||
// these were previously in translator class
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
char word_phonemes[N_WORD_PHONEMES*2]; // longer, because snprint() is not available
|
||||
#else
|
||||
char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes
|
||||
#endif
|
||||
int n_ph_list2;
|
||||
PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes
|
||||
|
||||
@@ -384,6 +388,9 @@ int IsAlpha(unsigned int c)
|
||||
return(0);
|
||||
}
|
||||
|
||||
if((c >= 0x64b) && (c <= 0x65e))
|
||||
return(1); // arabic vowel marks
|
||||
|
||||
if((c >= 0x300) && (c <= 0x36f))
|
||||
return(1); // combining accents
|
||||
|
||||
@@ -567,7 +574,6 @@ char *strchr_w(const char *s, int c)
|
||||
|
||||
|
||||
|
||||
|
||||
int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab)
|
||||
{//===========================================================================
|
||||
// word1 is terminated by space (0x20) character
|
||||
@@ -585,17 +591,16 @@ int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab)
|
||||
char *wordx;
|
||||
char phonemes[N_WORD_PHONEMES];
|
||||
char *ph_limit;
|
||||
char *phonemes_ptr;
|
||||
char prefix_phonemes[N_WORD_PHONEMES];
|
||||
char unpron_phonemes[N_WORD_PHONEMES];
|
||||
char end_phonemes[N_WORD_PHONEMES];
|
||||
char word_copy[N_WORD_BYTES];
|
||||
char prefix_chars[N_WORD_BYTES];
|
||||
char prefix_chars[41];
|
||||
int found=0;
|
||||
int end_flags;
|
||||
char c_temp; // save a character byte while we temporarily replace it with space
|
||||
int first_char;
|
||||
int last_char = 0;
|
||||
int unpron_length;
|
||||
int add_plural_suffix = 0;
|
||||
int prefix_flags = 0;
|
||||
int confirm_prefix;
|
||||
@@ -626,6 +631,8 @@ int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab)
|
||||
dictionary_flags2[1] = 0;
|
||||
dictionary_skipwords = 0;
|
||||
|
||||
phonemes[0] = 0;
|
||||
unpron_phonemes[0] = 0;
|
||||
prefix_phonemes[0] = 0;
|
||||
end_phonemes[0] = 0;
|
||||
ph_limit = &phonemes[N_WORD_PHONEMES];
|
||||
@@ -649,15 +656,22 @@ int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab)
|
||||
word_length++;
|
||||
}
|
||||
|
||||
// try an initial lookup in the dictionary list, we may find a pronunciation specified, or
|
||||
// we may just find some flags
|
||||
spell_word = 0;
|
||||
if(option_sayas == SAYAS_KEY)
|
||||
{
|
||||
if(word_length == 1)
|
||||
spell_word = 4;
|
||||
else
|
||||
{
|
||||
// is there a translation for this keyname ?
|
||||
word1--;
|
||||
*word1 = '_'; // prefix keyname with '_'
|
||||
found = LookupDictList(tr, &word1, phonemes, dictionary_flags, 0, wtab);
|
||||
}
|
||||
}
|
||||
|
||||
// try an initial lookup in the dictionary list, we may find a pronunciation specified, or
|
||||
// we may just find some flags
|
||||
if(option_sayas & 0x10)
|
||||
{
|
||||
// SAYAS_CHAR, SAYAS_GYLPH, or SAYAS_SINGLE_CHAR
|
||||
@@ -665,9 +679,10 @@ int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab)
|
||||
}
|
||||
else
|
||||
{
|
||||
found = LookupDictList(tr, &word1, phonemes, dictionary_flags, FLAG_ALLOW_TEXTMODE, wtab); // the original word
|
||||
if(!found)
|
||||
found = LookupDictList(tr, &word1, phonemes, dictionary_flags, FLAG_ALLOW_TEXTMODE, wtab); // the original word
|
||||
|
||||
if((dictionary_flags[0] & FLAG_DOT) && (wordx[1] == '.'))
|
||||
if((dictionary_flags[0] & (FLAG_ALLOW_DOT || FLAG_NEEDS_DOT)) && (wordx[1] == '.'))
|
||||
{
|
||||
wordx[1] = ' '; // remove a Dot after this word
|
||||
}
|
||||
@@ -773,7 +788,7 @@ if((wmark > 0) && (wmark < 8))
|
||||
|
||||
while(*wordx != ' ')
|
||||
{
|
||||
wordx += TranslateLetter(tr,wordx, phonemes,spell_word, word_length);
|
||||
wordx += TranslateLetter(tr,wordx, phonemes, spell_word);
|
||||
posn++;
|
||||
if(phonemes[0] == phonSWITCH)
|
||||
{
|
||||
@@ -802,13 +817,13 @@ if((wmark > 0) && (wmark < 8))
|
||||
// This word looks "unpronouncable", so speak letters individually until we
|
||||
// find a remainder that we can pronounce.
|
||||
emphasize_allcaps = 0;
|
||||
wordx += TranslateLetter(tr,wordx,phonemes,0, word_length);
|
||||
wordx += TranslateLetter(tr, wordx, unpron_phonemes, 0);
|
||||
posn++;
|
||||
if(phonemes[0] == phonSWITCH)
|
||||
{
|
||||
// change to another language in order to translate this word
|
||||
strcpy(word_phonemes,phonemes);
|
||||
if(strcmp(&phonemes[1],"en")==0)
|
||||
strcpy(word_phonemes,unpron_phonemes);
|
||||
if(strcmp(&unpron_phonemes[1],"en")==0)
|
||||
return(FLAG_SPELLWORD); // _^_en must have been set in TranslateLetter(), not *_rules
|
||||
return(0);
|
||||
}
|
||||
@@ -828,13 +843,12 @@ if((wmark > 0) && (wmark < 8))
|
||||
if(length > 0)
|
||||
wordx[-1] = ' '; // prevent this affecting the pronunciation of the pronuncable part
|
||||
}
|
||||
SetSpellingStress(tr,phonemes,0,posn);
|
||||
SetSpellingStress(tr,unpron_phonemes,0,posn);
|
||||
|
||||
// anything left ?
|
||||
if(*wordx != ' ')
|
||||
{
|
||||
// Translate the stem
|
||||
unpron_length = strlen(phonemes);
|
||||
end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags, dictionary_flags);
|
||||
|
||||
if(phonemes[0] == phonSWITCH)
|
||||
@@ -855,7 +869,7 @@ if((wmark > 0) && (wmark < 8))
|
||||
posn = 0;
|
||||
while((*wordx != ' ') && (*wordx != 0))
|
||||
{
|
||||
wordx += TranslateLetter(tr,wordx, phonemes, 4, word_length);
|
||||
wordx += TranslateLetter(tr,wordx, phonemes, 4);
|
||||
posn++;
|
||||
if(phonemes[0] == phonSWITCH)
|
||||
{
|
||||
@@ -1000,14 +1014,13 @@ strcpy(phonemes2,phonemes);
|
||||
// The word has a standard ending, re-translate without this ending
|
||||
end_flags = RemoveEnding(tr, wordx, end_type, word_copy);
|
||||
|
||||
phonemes_ptr = &phonemes[unpron_length];
|
||||
phonemes_ptr[0] = 0;
|
||||
phonemes[0] = 0;
|
||||
|
||||
if(prefix_phonemes[0] != 0)
|
||||
{
|
||||
// lookup the stem without the prefix removed
|
||||
wordx[-1] = c_temp;
|
||||
found = LookupDictList(tr, &word1, phonemes_ptr, dictionary_flags2, end_flags, wtab); // include prefix, but not suffix
|
||||
found = LookupDictList(tr, &word1, phonemes, dictionary_flags2, end_flags, wtab); // include prefix, but not suffix
|
||||
wordx[-1] = ' ';
|
||||
if(dictionary_flags[0]==0)
|
||||
{
|
||||
@@ -1022,12 +1035,12 @@ strcpy(phonemes2,phonemes);
|
||||
}
|
||||
if(found == 0)
|
||||
{
|
||||
found = LookupDictList(tr, &wordx, phonemes_ptr, dictionary_flags2, end_flags, wtab); // without prefix and suffix
|
||||
if(phonemes_ptr[0] == phonSWITCH)
|
||||
found = LookupDictList(tr, &wordx, phonemes, dictionary_flags2, end_flags, wtab); // without prefix and suffix
|
||||
if(phonemes[0] == phonSWITCH)
|
||||
{
|
||||
// change to another language in order to translate this word
|
||||
memcpy(wordx,word_copy,strlen(word_copy));
|
||||
strcpy(word_phonemes,phonemes_ptr);
|
||||
strcpy(word_phonemes,phonemes);
|
||||
return(0);
|
||||
}
|
||||
if(dictionary_flags[0]==0)
|
||||
@@ -1115,15 +1128,23 @@ strcpy(phonemes2,phonemes);
|
||||
*p = phonSTRESS_3;
|
||||
}
|
||||
}
|
||||
strcpy(word_phonemes,prefix_phonemes);
|
||||
strcat(word_phonemes,phonemes);
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
sprintf(word_phonemes, "%s%s%s", unpron_phonemes, prefix_phonemes, phonemes);
|
||||
#else
|
||||
snprintf(word_phonemes, sizeof(word_phonemes), "%s%s%s", unpron_phonemes, prefix_phonemes, phonemes);
|
||||
#endif
|
||||
word_phonemes[N_WORD_PHONEMES-1] = 0;
|
||||
SetWordStress(tr, word_phonemes, dictionary_flags, -1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// stress position affects the whole word, including prefix
|
||||
strcpy(word_phonemes,prefix_phonemes);
|
||||
strcat(word_phonemes,phonemes);
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
sprintf(word_phonemes, "%s%s%s", unpron_phonemes, prefix_phonemes, phonemes);
|
||||
#else
|
||||
snprintf(word_phonemes, sizeof(word_phonemes), "%s%s%s", unpron_phonemes, prefix_phonemes, phonemes);
|
||||
#endif
|
||||
word_phonemes[N_WORD_PHONEMES-1] = 0;
|
||||
SetWordStress(tr, word_phonemes, dictionary_flags, -1, tr->prev_last_stress);
|
||||
}
|
||||
}
|
||||
@@ -1133,14 +1154,20 @@ strcpy(phonemes2,phonemes);
|
||||
SetWordStress(tr, phonemes, dictionary_flags, -1, tr->prev_last_stress);
|
||||
else
|
||||
SetWordStress(tr, phonemes, dictionary_flags, -1, 0);
|
||||
strcpy(word_phonemes,prefix_phonemes);
|
||||
strcat(word_phonemes,phonemes);
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
sprintf(word_phonemes, "%s%s%s", unpron_phonemes, prefix_phonemes, phonemes);
|
||||
#else
|
||||
snprintf(word_phonemes, sizeof(word_phonemes), "%s%s%s", unpron_phonemes, prefix_phonemes, phonemes);
|
||||
#endif
|
||||
word_phonemes[N_WORD_PHONEMES-1] = 0;
|
||||
}
|
||||
|
||||
if(end_phonemes[0] != 0)
|
||||
{
|
||||
// a suffix had the SUFX_T option set, add the suffix after the stress pattern has been determined
|
||||
strcat(word_phonemes,end_phonemes);
|
||||
ix = strlen(word_phonemes);
|
||||
end_phonemes[N_WORD_PHONEMES-1-ix] = 0; // ensure no buffer overflow
|
||||
strcpy(&word_phonemes[ix], end_phonemes);
|
||||
}
|
||||
|
||||
if(wflags & FLAG_LAST_WORD)
|
||||
@@ -1150,7 +1177,7 @@ strcpy(phonemes2,phonemes);
|
||||
dictionary_flags[0] &= ~FLAG_PAUSE1;
|
||||
}
|
||||
|
||||
if((wflags & FLAG_HYPHEN) && (tr->langopts.stress_flags & STRS_HYPEN_UNSTRESS))
|
||||
if((wflags & FLAG_HYPHEN) && (tr->langopts.stress_flags & S_HYPEN_UNSTRESS))
|
||||
{
|
||||
ChangeWordStress(tr,word_phonemes,3);
|
||||
}
|
||||
@@ -1237,7 +1264,7 @@ strcpy(phonemes2,phonemes);
|
||||
{
|
||||
// English Specific !!!!
|
||||
// any single letter before a dot is an abbreviation, except 'I'
|
||||
dictionary_flags[0] |= FLAG_DOT;
|
||||
dictionary_flags[0] |= FLAG_ALLOW_DOT;
|
||||
}
|
||||
|
||||
if((tr->langopts.param[LOPT_ALT] & 2) && ((dictionary_flags[0] & (FLAG_ALT_TRANS | FLAG_ALT2_TRANS)) != 0))
|
||||
@@ -2186,12 +2213,10 @@ void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *t
|
||||
}
|
||||
}
|
||||
|
||||
if(option_sayas2 == SAYAS_KEY)
|
||||
if((option_sayas2 == SAYAS_KEY) && (c != ' '))
|
||||
{
|
||||
if(((c == '_') || (c == '-')) && IsAlpha(prev_in))
|
||||
{
|
||||
c = ' ';
|
||||
}
|
||||
if((prev_in == ' ') && (next_in == ' '))
|
||||
option_sayas2 = SAYAS_SINGLE_CHARS; // single character, speak its name
|
||||
c = towlower2(c);
|
||||
}
|
||||
|
||||
@@ -2231,7 +2256,7 @@ void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *t
|
||||
}
|
||||
}
|
||||
else
|
||||
if((option_sayas2 & 0x30) == 0)
|
||||
if((option_sayas2 & 0x10) == 0)
|
||||
{
|
||||
// speak as words
|
||||
|
||||
@@ -2325,6 +2350,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
// start of word, insert space if not one there already
|
||||
c = ' ';
|
||||
space_inserted = 1;
|
||||
next_word_flags |= FLAG_NOSPACE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2402,12 +2428,21 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
else
|
||||
if(c=='-')
|
||||
{
|
||||
if((IsAlpha(prev_in) || iswdigit(prev_in)) && IsAlpha(next_in))
|
||||
if(!IsSpace(prev_in) && IsAlpha(next_in))
|
||||
{
|
||||
// '-' between two letters is a hyphen, treat as a space
|
||||
word_flags |= FLAG_HYPHEN;
|
||||
words[word_count-1].flags |= FLAG_HYPHEN_AFTER;
|
||||
c = ' ';
|
||||
if(prev_out != ' ')
|
||||
{
|
||||
// previous 'word' not yet ended (not alpha or numeric), start new word now.
|
||||
c = ' ';
|
||||
space_inserted = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// '-' between two letters is a hyphen, treat as a space
|
||||
word_flags |= FLAG_HYPHEN;
|
||||
words[word_count-1].flags |= FLAG_HYPHEN_AFTER;
|
||||
c = ' ';
|
||||
}
|
||||
}
|
||||
else
|
||||
if((prev_in==' ') && (next_in==' '))
|
||||
@@ -2433,6 +2468,18 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
}
|
||||
}
|
||||
else
|
||||
if(c == '.')
|
||||
{
|
||||
if(!(words[word_count-1].flags & FLAG_NOSPACE) && IsAlpha(prev_in))
|
||||
{
|
||||
// dot after a word, with space following, probably an abbreviation
|
||||
words[word_count-1].flags |= FLAG_HAS_DOT;
|
||||
|
||||
if(IsSpace(next_in))
|
||||
c = ' '; // remove the dot if it's followed by a space, so that it's not pronounced
|
||||
}
|
||||
}
|
||||
else
|
||||
if(c == '\'')
|
||||
{
|
||||
if(iswalnum(prev_in) && IsAlpha(next_in))
|
||||
@@ -2604,9 +2651,14 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
words[0].pre_pause = 0; // don't add extra pause at beginning of clause
|
||||
words[word_count].pre_pause = 8;
|
||||
if(word_count > 0)
|
||||
{
|
||||
words[word_count-1].flags |= FLAG_LAST_WORD;
|
||||
if((terminator & CLAUSE_DOT) && !(words[word_count-1].flags & FLAG_NOSPACE))
|
||||
words[word_count-1].flags |= FLAG_HAS_DOT;
|
||||
}
|
||||
words[0].flags |= FLAG_FIRST_WORD;
|
||||
|
||||
|
||||
for(ix=0; ix<word_count; ix++)
|
||||
{
|
||||
int nx;
|
||||
@@ -2693,11 +2745,10 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
}
|
||||
}
|
||||
}
|
||||
word = pw;
|
||||
pw--;
|
||||
|
||||
// include the next few characters, in case there are an ordinal indicator or other suffix
|
||||
pn[0] = ' ';
|
||||
memcpy(pn+1, pw, 16);
|
||||
memcpy(pn, pw, 16);
|
||||
pn[16] = 0;
|
||||
|
||||
for(pw = &number_buf[1]; pw < pn;)
|
||||
@@ -2732,7 +2783,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
}
|
||||
}
|
||||
|
||||
if((dict_flags & FLAG_DOT) && (ix == word_count-1) && (terminator == CLAUSE_PERIOD))
|
||||
if((dict_flags & (FLAG_ALLOW_DOT | FLAG_NEEDS_DOT)) && (ix == word_count-1) && (terminator & CLAUSE_DOT))
|
||||
{
|
||||
// probably an abbreviation such as Mr. or B. rather than end of sentence
|
||||
clause_pause = 10;
|
||||
|
||||
+26
-7
@@ -48,7 +48,6 @@
|
||||
#define FLAG_ATEND 0x4000 /* use this pronunciation if at end of clause */
|
||||
#define FLAG_SPELLWORD 0x8000 // re-translate the word as individual letters, separated by spaces
|
||||
|
||||
#define FLAG_DOT 0x10000 /* ignore '.' after word (abbreviation) */
|
||||
#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
|
||||
|
||||
@@ -57,6 +56,9 @@
|
||||
#define FLAG_ALT2_TRANS 0x200000 // language specific
|
||||
#define FLAG_COMBINE 0x400000 // 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
|
||||
|
||||
#define FLAG_MAX3 0x08000000 // limit to 3 repeats
|
||||
#define FLAG_PAUSE1 0x10000000 // shorter prepause
|
||||
#define FLAG_TEXTMODE 0x20000000 // word translates to replacement text, not phonemes
|
||||
@@ -100,9 +102,10 @@
|
||||
#define FLAG_SUFFIX_REMOVED 0x2000
|
||||
#define FLAG_HYPHEN_AFTER 0x4000
|
||||
#define FLAG_ORDINAL 0x8000 // passed to TranslateNumber() to indicate an ordinal number
|
||||
#define FLAG_HAS_DOT 0x10000 // dot after this word
|
||||
|
||||
#define FLAG_NO_TRACE 0x10000 // passed to TranslateRules() to suppress dictionary lookup printout
|
||||
#define FLAG_NO_PREFIX 0x20000
|
||||
#define FLAG_NO_TRACE 0x10000000 // passed to TranslateRules() to suppress dictionary lookup printout
|
||||
#define FLAG_NO_PREFIX 0x20000000
|
||||
|
||||
// prefix/suffix flags (bits 8 to 14, bits 16 to 22) don't use 0x8000, 0x800000
|
||||
#define SUFX_E 0x0100 // e may have been added
|
||||
@@ -169,12 +172,14 @@
|
||||
// bit 16 used to distinguish otherwise identical types
|
||||
// bit 20= punctuation character can be inside a word (Armenian)
|
||||
// bit 21= speak the name of the punctuation character
|
||||
// bit 22= dot after the last word
|
||||
#define CLAUSE_BIT_SENTENCE 0x80000
|
||||
#define CLAUSE_BIT_CLAUSE 0x40000
|
||||
#define CLAUSE_BIT_VOICE 0x20000
|
||||
#define CLAUSE_BITS_INTONATION 0x7000
|
||||
#define PUNCT_IN_WORD 0x100000
|
||||
#define PUNCT_SAY_NAME 0x200000
|
||||
#define CLAUSE_DOT 0x400000
|
||||
|
||||
#define CLAUSE_NONE 0 + 0x04000
|
||||
#define CLAUSE_PARAGRAPH 70 + 0x80000
|
||||
@@ -215,9 +220,9 @@ typedef struct {
|
||||
|
||||
// used to mark words with the source[] buffer
|
||||
typedef struct{
|
||||
unsigned int flags;
|
||||
unsigned short start;
|
||||
unsigned short sourceix;
|
||||
unsigned short flags;
|
||||
unsigned char pre_pause;
|
||||
unsigned char wmark;
|
||||
unsigned char length;
|
||||
@@ -243,7 +248,7 @@ extern const int param_defaults[N_SPEECH_PARAM];
|
||||
|
||||
|
||||
|
||||
#define N_LOPTS 18
|
||||
#define N_LOPTS 19
|
||||
#define LOPT_DIERESES 1
|
||||
// 1=remove [:] from unstressed syllables, 2= remove from unstressed or non-penultimate syllables
|
||||
// bit 4=0, if stress < 4, bit 4=1, if not the highest stress in the word
|
||||
@@ -295,6 +300,7 @@ extern const int param_defaults[N_SPEECH_PARAM];
|
||||
#define LOPT_IT_DOUBLING 14
|
||||
|
||||
// Call ApplySpecialAttributes() if $alt or $alt2 is set for a word
|
||||
// bit 1: stressed syllable: $alt change [e],[o] to [E],[O], $alt2 change [E],[O] to [e],[o]
|
||||
#define LOPT_ALT 15
|
||||
|
||||
// pause for bracket (default=4), pause when annoucing bracket names (default=2)
|
||||
@@ -303,6 +309,9 @@ extern const int param_defaults[N_SPEECH_PARAM];
|
||||
// bit 1, don't break clause before annoucning . ? !
|
||||
#define LOPT_ANNOUNCE_PUNCT 17
|
||||
|
||||
// set minimum length for long vowels at fast speeds, to keep a distinction with short vowels
|
||||
#define LOPT_MIN_LONG_VOWEL 18
|
||||
|
||||
|
||||
// stress_rule
|
||||
#define STRESSPOSN_1L 0 // 1st syllable
|
||||
@@ -321,7 +330,15 @@ typedef struct {
|
||||
int vowel_pause;
|
||||
int stress_rule; // 1=first syllable, 2=penultimate, 3=last
|
||||
|
||||
#define STRS_HYPEN_UNSTRESS 0x100000
|
||||
#define S_NO_DIM 0x02
|
||||
#define S_FINAL_DIM 0x04
|
||||
#define S_FINAL_NO_2 0x10
|
||||
#define S_NO_AUTO_2 0x20
|
||||
#define S_2_TO_HEAVY 0x40
|
||||
#define S_2_SYL_2 0x1000
|
||||
#define S_INITIAL_2 0x2000
|
||||
#define S_NO_AUTO_DIM 0x10000
|
||||
#define S_HYPEN_UNSTRESS 0x100000
|
||||
// bit0=don't stress monosyllables, except at end of clause
|
||||
// bit1=don't set diminished stress,
|
||||
// bit2=mark unstressed final syllables as diminished
|
||||
@@ -487,6 +504,7 @@ struct Translator
|
||||
// the two-letter rules for each letter must be consecutive in the language_rules source
|
||||
|
||||
char *groups1[256]; // translation rule lists, index by single letter
|
||||
char *groups3[128]; // index by offset letter
|
||||
char *groups2[N_RULE_GROUP2]; // translation rule lists, indexed by two-letter pairs
|
||||
unsigned int groups2_name[N_RULE_GROUP2]; // the two letter pairs for groups2[]
|
||||
int n_groups2; // number of groups2[] entries used
|
||||
@@ -591,13 +609,14 @@ Translator *SelectTranslator(const char *name);
|
||||
int SetTranslator2(const char *name);
|
||||
void DeleteTranslator(Translator *tr);
|
||||
int Lookup(Translator *tr, const char *word, char *ph_out);
|
||||
int LookupFlags(Translator *tr, const char *word);
|
||||
|
||||
int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab);
|
||||
int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab);
|
||||
|
||||
void ChangeWordStress(Translator *tr, char *word, int new_stress);
|
||||
void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars);
|
||||
int TranslateLetter(Translator *tr, char *letter, char *phonemes, int control, int word_length);
|
||||
int TranslateLetter(Translator *tr, char *letter, char *phonemes, int control);
|
||||
void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf);
|
||||
void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf);
|
||||
|
||||
|
||||
+4
-3
@@ -116,6 +116,7 @@ enum {
|
||||
static MNEM_TAB options_tab[] = {
|
||||
{"reduce_t", LOPT_REDUCE_T},
|
||||
{"bracket", LOPT_BRACKET_PAUSE},
|
||||
{"fastLongVowel", LOPT_MIN_LONG_VOWEL},
|
||||
{NULL, -1} };
|
||||
|
||||
static MNEM_TAB keyword_tab[] = {
|
||||
@@ -373,9 +374,9 @@ void VoiceReset(int tone_only)
|
||||
|
||||
static int breath_widths[N_PEAKS] = {0,200,200,400,400,400,600,600,600};
|
||||
|
||||
// default is: pitch 78,120
|
||||
voice->pitch_base = 0x45000;
|
||||
voice->pitch_range = 4536;
|
||||
// default is: pitch 80,118
|
||||
voice->pitch_base = 0x47000;
|
||||
voice->pitch_range = 4104;
|
||||
// default is: pitch 80,117
|
||||
// voice->pitch_base = 0x47000;
|
||||
// voice->pitch_range = 3996;
|
||||
|
||||
Reference in New Issue
Block a user