mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-14 09:37:47 +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:
+280
-5
@@ -177,6 +177,35 @@ enum {
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
kTUNE = 1,
|
||||
kENDTUNE,
|
||||
kTUNE_PREHEAD,
|
||||
kTUNE_ONSET,
|
||||
kTUNE_HEAD,
|
||||
kTUNE_HEADEXTEND,
|
||||
kTUNE_HEADLAST,
|
||||
kTUNE_UNSTRESSED,
|
||||
kTUNE_NUCLEUS0,
|
||||
kTUNE_NUCLEUS1,
|
||||
kTUNE_SPLIT,
|
||||
};
|
||||
|
||||
static keywtab_t k_intonation[] = {
|
||||
{"tune", 0, kTUNE},
|
||||
{"endtune", 0, kENDTUNE},
|
||||
{"prehead", 0, kTUNE_PREHEAD},
|
||||
{"onset", 0, kTUNE_ONSET},
|
||||
{"head", 0, kTUNE_HEAD},
|
||||
{"headextend", 0, kTUNE_HEADEXTEND},
|
||||
{"headlast", 0, kTUNE_HEADLAST},
|
||||
{"unstressed",0, kTUNE_UNSTRESSED},
|
||||
{"nucleus0", 0, kTUNE_NUCLEUS0},
|
||||
{"nucleus1", 0, kTUNE_NUCLEUS1},
|
||||
{"split", 0, kTUNE_SPLIT},
|
||||
{NULL, 0, -1}
|
||||
};
|
||||
|
||||
static keywtab_t keywords[] = {
|
||||
{"vowel", tPHONEME_TYPE, phVOWEL},
|
||||
{"liquid", tPHONEME_TYPE, phLIQUID},
|
||||
@@ -271,6 +300,7 @@ static keywtab_t keywords[] = {
|
||||
{"rhotic", tPHONEME_FLAG, phRHOTIC},
|
||||
{"nonsyllabic",tPHONEME_FLAG, phNONSYLLABIC},
|
||||
{"lengthenstop",tPHONEME_FLAG, phLENGTHENSTOP},
|
||||
{"nopause", tPHONEME_FLAG, phNOPAUSE},
|
||||
|
||||
// voiced / unvoiced
|
||||
{"vcd", tPHONEME_FLAG, phVOICED},
|
||||
@@ -310,7 +340,7 @@ static keywtab_t keywords[] = {
|
||||
|
||||
|
||||
static keywtab_t *keyword_tabs[] = {
|
||||
keywords, k_conditions, k_properties };
|
||||
keywords, k_conditions, k_properties, k_intonation };
|
||||
|
||||
|
||||
static PHONEME_TAB *phoneme_out;
|
||||
@@ -621,6 +651,7 @@ enum {
|
||||
tKEYWORD,
|
||||
tCONDITION,
|
||||
tPROPERTIES,
|
||||
tINTONATION,
|
||||
};
|
||||
|
||||
int item_type;
|
||||
@@ -982,7 +1013,7 @@ static void error(const char *format, const char *string)
|
||||
|
||||
static void Error(const char *string)
|
||||
{//==================================
|
||||
error(string,NULL);
|
||||
error("%s",string);
|
||||
}
|
||||
|
||||
static FILE *fopen_log(FILE *f_log, const char *fname,const char *access)
|
||||
@@ -1149,6 +1180,15 @@ static void unget_char(unsigned int c)
|
||||
}
|
||||
|
||||
|
||||
int CheckNextChar()
|
||||
{//================
|
||||
int c;
|
||||
while(((c = get_char()) == ' ') || (c == '\t'));
|
||||
unget_char(c);
|
||||
return(c);
|
||||
} // end of CheckNextChar
|
||||
|
||||
|
||||
static int NextItem(int type)
|
||||
{//==========================
|
||||
int acc;
|
||||
@@ -1243,7 +1283,12 @@ static int NextItem(int type)
|
||||
p++;
|
||||
}
|
||||
if(!isdigit(*p))
|
||||
error("Expected a number",NULL);
|
||||
{
|
||||
if((type == tNUMBER) && (*p == '-'))
|
||||
error("Expected an unsigned number",NULL);
|
||||
else
|
||||
error("Expected a number",NULL);
|
||||
}
|
||||
while(isdigit(*p))
|
||||
{
|
||||
acc *= 10;
|
||||
@@ -1254,7 +1299,7 @@ static int NextItem(int type)
|
||||
}
|
||||
|
||||
|
||||
if((type >= tKEYWORD) && (type <= tPROPERTIES))
|
||||
if((type >= tKEYWORD) && (type <= tINTONATION))
|
||||
{
|
||||
pk = keyword_tabs[type-tKEYWORD];
|
||||
while(pk->mnem != NULL)
|
||||
@@ -3020,6 +3065,7 @@ static void CompilePhonemeFiles()
|
||||
} // end of CompilePhonemeFiles
|
||||
|
||||
|
||||
|
||||
static void CompilePhonemeData2(const char *source)
|
||||
{//================================================
|
||||
char fname[sizeof(path_source)+40];
|
||||
@@ -3110,7 +3156,7 @@ memset(markers_used,0,sizeof(markers_used));
|
||||
|
||||
if(gui_flag)
|
||||
{
|
||||
progress = new wxProgressDialog(_T("Phonemes"),_T(""),progress_max);
|
||||
progress = new wxProgressDialog(_T("Compiling"),_T(""),progress_max);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3260,6 +3306,235 @@ void CompileMbrola()
|
||||
|
||||
|
||||
|
||||
static const TUNE default_tune = {
|
||||
0, {0,0,0,0},
|
||||
{0, 40, 24, 8, 0, 0, 0, 0},
|
||||
46, 57, 255, 78, 50, 255,
|
||||
PITCHfall, 0,
|
||||
3, 5,
|
||||
7, 7, 0,
|
||||
PITCHfall, 64, 8,
|
||||
PITCHfall, 70, 18, 24, 12,
|
||||
PITCHfall, 70, 18, 24, 12,
|
||||
{0,0,0,0,0,0,0,0,0,0}
|
||||
};
|
||||
|
||||
TUNE new_tune;
|
||||
|
||||
#define N_TUNE_NAMES 100
|
||||
|
||||
static MNEM_TAB envelope_names[] = {
|
||||
{"fall", 0},
|
||||
{"rise", 1},
|
||||
{"fall_rise", 2},
|
||||
{"fall_rise2", 3},
|
||||
{"rise_fall", 4},
|
||||
{NULL, -1} };
|
||||
|
||||
|
||||
// env_fallrise3, env_fallrise3,
|
||||
// env_fallrise4, env_fallrise4,
|
||||
// env_fall2, env_fall2,
|
||||
// env_rise2, env_rise2,
|
||||
// env_risefallrise, env_risefallrise
|
||||
|
||||
int LookupEnvelope(const char *name)
|
||||
{//=================================
|
||||
return(LookupMnem(envelope_names, name));
|
||||
}
|
||||
|
||||
|
||||
void CompileIntonation()
|
||||
{//=====================
|
||||
int ix;
|
||||
char *p;
|
||||
char c;
|
||||
int keyword;
|
||||
int compiling_tune = 0;
|
||||
int n_tune_names = 0;
|
||||
int done_split;
|
||||
int n_tunes = 0;
|
||||
FILE *f_out;
|
||||
wxString report;
|
||||
|
||||
char name[5];
|
||||
unsigned int tune_names[N_TUNE_NAMES];
|
||||
char buf[sizeof(path_source)+120];
|
||||
|
||||
error_count = 0;
|
||||
|
||||
sprintf(buf,"%s%s",path_source,"error_intonation");
|
||||
if((f_errors = fopen(buf,"w")) == NULL)
|
||||
f_errors = stderr;
|
||||
|
||||
sprintf(buf,"%sintonation",path_source);
|
||||
f_in = fopen_log(f_errors, buf, "r");
|
||||
if(f_in == NULL)
|
||||
{
|
||||
fclose(f_errors);
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(buf,"%s/intonations",path_home);
|
||||
f_out = fopen_log(f_errors, buf, "w");
|
||||
if(f_out == NULL)
|
||||
{
|
||||
fclose(f_in);
|
||||
fclose(f_errors);
|
||||
return;
|
||||
}
|
||||
|
||||
// make a list of the tune names
|
||||
while(!feof(f_in))
|
||||
{
|
||||
if(fgets(buf,sizeof(buf),f_in) == NULL)
|
||||
break;
|
||||
|
||||
if((memcmp(buf,"tune",4)==0) && isspace(buf[4]))
|
||||
{
|
||||
p = &buf[5];
|
||||
while(isspace(*p)) p++;
|
||||
|
||||
ix = 0;
|
||||
while((ix < int(sizeof(name) - 1)) && !isspace(*p))
|
||||
{
|
||||
name[ix++] = *p++;
|
||||
}
|
||||
name[ix] = 0;
|
||||
tune_names[n_tune_names++] = StringToWord(name);
|
||||
|
||||
if(n_tune_names >= N_TUNE_NAMES)
|
||||
break;
|
||||
}
|
||||
}
|
||||
rewind(f_in);
|
||||
linenum = 1;
|
||||
|
||||
while(!feof(f_in))
|
||||
{
|
||||
keyword = NextItem(tINTONATION);
|
||||
|
||||
switch(keyword)
|
||||
{
|
||||
case kTUNE:
|
||||
if(compiling_tune)
|
||||
{
|
||||
}
|
||||
compiling_tune = 1;
|
||||
n_tunes++;
|
||||
done_split = 0;
|
||||
|
||||
memcpy(&new_tune, &default_tune, sizeof(TUNE));
|
||||
NextItem(tSTRING);
|
||||
new_tune.name = StringToWord(item_string);
|
||||
fprintf(f_errors,"tune %s\n",WordToString(new_tune.name));
|
||||
break;
|
||||
|
||||
case kENDTUNE:
|
||||
compiling_tune = 0;
|
||||
fwrite(&new_tune, 1, sizeof(new_tune), f_out);
|
||||
break;
|
||||
|
||||
case kTUNE_PREHEAD:
|
||||
new_tune.prehead_start = NextItem(tNUMBER);
|
||||
new_tune.prehead_end = NextItem(tNUMBER);
|
||||
break;
|
||||
|
||||
case kTUNE_HEAD:
|
||||
new_tune.head_max_steps = NextItem(tNUMBER);
|
||||
new_tune.head_start = NextItem(tNUMBER);
|
||||
new_tune.head_end = NextItem(tNUMBER);
|
||||
NextItem(tSTRING);
|
||||
if((ix = LookupEnvelope(item_string)) < 0)
|
||||
{
|
||||
error("Bad envelope name: '%s'",item_string);
|
||||
}
|
||||
break;
|
||||
|
||||
case kTUNE_HEADEXTEND:
|
||||
// up to 8 numbers
|
||||
for(ix=0; ix < int(sizeof(new_tune.headextend)); ix++)
|
||||
{
|
||||
if(!isdigit(c = CheckNextChar()) && (c != '-'))
|
||||
break;
|
||||
|
||||
new_tune.headextend[ix] = (NextItem(tSIGNEDNUMBER) * 64) / 100; // convert from percentage to 64ths
|
||||
}
|
||||
new_tune.n_headextend = ix; // number of values
|
||||
break;
|
||||
|
||||
case kTUNE_UNSTRESSED:
|
||||
new_tune.unstressed_start = NextItem(tSIGNEDNUMBER);
|
||||
new_tune.unstressed_end = NextItem(tSIGNEDNUMBER);
|
||||
break;
|
||||
|
||||
case kTUNE_NUCLEUS0:
|
||||
NextItem(tSTRING);
|
||||
if((ix = LookupEnvelope(item_string)) < 0)
|
||||
{
|
||||
error("Bad envelope name: '%s'",item_string);
|
||||
break;
|
||||
}
|
||||
new_tune.nucleus0_env = ix;
|
||||
new_tune.nucleus0_max = NextItem(tNUMBER);
|
||||
new_tune.nucleus0_min = NextItem(tNUMBER);
|
||||
break;
|
||||
|
||||
case kTUNE_NUCLEUS1:
|
||||
NextItem(tSTRING);
|
||||
if((ix = LookupEnvelope(item_string)) < 0)
|
||||
{
|
||||
error("Bad envelope name: '%s'",item_string);
|
||||
break;
|
||||
}
|
||||
new_tune.nucleus1_env = ix;
|
||||
new_tune.nucleus1_max = NextItem(tNUMBER);
|
||||
new_tune.nucleus1_min = NextItem(tNUMBER);
|
||||
new_tune.tail_start = NextItem(tNUMBER);
|
||||
new_tune.tail_end = NextItem(tNUMBER);
|
||||
|
||||
if(!done_split)
|
||||
{
|
||||
new_tune.split_nucleus_env = ix;
|
||||
new_tune.split_nucleus_max = new_tune.nucleus1_max;
|
||||
new_tune.split_nucleus_min = new_tune.nucleus1_min;
|
||||
new_tune.split_tail_start = new_tune.tail_start;
|
||||
new_tune.split_tail_end = new_tune.tail_end;
|
||||
}
|
||||
break;
|
||||
|
||||
case kTUNE_SPLIT:
|
||||
NextItem(tSTRING);
|
||||
if((ix = LookupEnvelope(item_string)) < 0)
|
||||
{
|
||||
error("Bad envelope name: '%s'",item_string);
|
||||
break;
|
||||
}
|
||||
new_tune.split_nucleus_env = ix;
|
||||
new_tune.split_nucleus_max = NextItem(tNUMBER);
|
||||
new_tune.split_nucleus_min = NextItem(tNUMBER);
|
||||
new_tune.split_tail_start = NextItem(tNUMBER);
|
||||
new_tune.split_tail_end = NextItem(tNUMBER);
|
||||
done_split = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Unexpected: '%s'",item_string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f_in);
|
||||
fclose(f_out);
|
||||
fclose(f_errors);
|
||||
|
||||
report.Printf(_T("Compiled %d intonation tunes: %d errors."),n_tunes, error_count);
|
||||
wxLogStatus(report);
|
||||
|
||||
} // end of CompileIntonation
|
||||
|
||||
|
||||
|
||||
void CompilePhonemeData()
|
||||
{
|
||||
CompilePhonemeData2("phonemes");
|
||||
|
||||
+215
-48
@@ -44,9 +44,6 @@ extern char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme
|
||||
|
||||
static int linenum;
|
||||
static int error_count;
|
||||
static int transpose_offset; // transpose character range for LookupDictList()
|
||||
static int transpose_min;
|
||||
static int transpose_max;
|
||||
static int text_mode = 0;
|
||||
static int debug_flag = 0;
|
||||
static int error_need_dictionary = 0;
|
||||
@@ -55,6 +52,15 @@ static int hash_counts[N_HASH_DICT];
|
||||
static char *hash_chains[N_HASH_DICT];
|
||||
static char letterGroupsDefined[N_LETTER_GROUPS];
|
||||
|
||||
MNEM_TAB mnem_rules[] = {
|
||||
{"w_alt2", 0x12},
|
||||
{"w_alt3", 0x13},
|
||||
{"w_alt", 0x11}, // note: put longer names before their sub-strings
|
||||
{"p_alt2", 0x22},
|
||||
{"p_alt3", 0x23},
|
||||
{"p_alt", 0x21},
|
||||
{NULL, -1} };
|
||||
|
||||
MNEM_TAB mnem_flags[] = {
|
||||
// these in the first group put a value in bits0-3 of dictionary_flags
|
||||
{"$1", 0x41}, // stress on 1st syllable
|
||||
@@ -89,9 +95,10 @@ MNEM_TAB mnem_flags[] = {
|
||||
// language specific
|
||||
{"$double", 19}, // IT double the initial consonant of next word
|
||||
{"$alt", 20}, // use alternative pronunciation
|
||||
{"$alt1", 20}, // synonym for $alt
|
||||
{"$alt2", 21},
|
||||
{"$combine", 22}, // Combine with the next word
|
||||
{"$alt3", 23},
|
||||
{"$alt3", 22},
|
||||
{"$combine", 23}, // 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
|
||||
@@ -112,6 +119,7 @@ MNEM_TAB mnem_flags[] = {
|
||||
{"$capital", 0x29}, /* use this pronunciation if initial letter is upper case */
|
||||
{"$allcaps", 0x2a}, /* use this pronunciation if initial letter is upper case */
|
||||
{"$accent", 0x2b}, // character name is base-character name + accent name
|
||||
{"$sentence",0x2d}, // only if this clause is a sentence (i.e. terminator is {. ? !} not {, ; :}
|
||||
|
||||
// doesn't set dictionary_flags
|
||||
{"$?", 100}, // conditional rule, followed by byte giving the condition number
|
||||
@@ -143,27 +151,6 @@ int isspace2(unsigned int c)
|
||||
}
|
||||
|
||||
|
||||
static const char *LookupMnem2(MNEM_TAB *table, int value)
|
||||
{//=======================================================
|
||||
while(table->mnem != NULL)
|
||||
{
|
||||
if(table->value == value)
|
||||
return(table->mnem);
|
||||
table++;
|
||||
}
|
||||
return("");
|
||||
}
|
||||
|
||||
|
||||
char *print_dictionary_flags(unsigned int *flags)
|
||||
{//==============================================
|
||||
static char buf[20];
|
||||
|
||||
sprintf(buf,"%s 0x%x/%x",LookupMnem2(mnem_flags,(flags[0] & 0xf)+0x40), flags[0], flags[1]);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static FILE *fopen_log(const char *fname,const char *access)
|
||||
{//==================================================
|
||||
@@ -179,9 +166,8 @@ static FILE *fopen_log(const char *fname,const char *access)
|
||||
}
|
||||
|
||||
|
||||
#ifdef OPT_FORMAT
|
||||
static const char *lookup_mnem(MNEM_TAB *table, int value)
|
||||
//========================================================
|
||||
const char *LookupMnemName(MNEM_TAB *table, const int value)
|
||||
//==========================================================
|
||||
/* Lookup a mnemonic string in a table, return its name */
|
||||
{
|
||||
while(table->mnem != NULL)
|
||||
@@ -190,9 +176,181 @@ static const char *lookup_mnem(MNEM_TAB *table, int value)
|
||||
return(table->mnem);
|
||||
table++;
|
||||
}
|
||||
return("??"); /* not found */
|
||||
} /* end of mnem */
|
||||
#endif
|
||||
return(""); /* not found */
|
||||
} /* end of LookupMnemValue */
|
||||
|
||||
|
||||
char *print_dictionary_flags(unsigned int *flags)
|
||||
{//==============================================
|
||||
static char buf[20];
|
||||
|
||||
sprintf(buf,"%s 0x%x/%x",LookupMnemName(mnem_flags,(flags[0] & 0xf)+0x40), flags[0], flags[1]);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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;
|
||||
const char *name;
|
||||
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_DOLLAR)
|
||||
{
|
||||
p[0] = '$';
|
||||
name = LookupMnemName(mnem_rules, *rule++);
|
||||
strcpy(&p[1],name);
|
||||
p += (strlen(name)+1);
|
||||
c = ' ';
|
||||
}
|
||||
else
|
||||
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 DecodeRule */
|
||||
|
||||
|
||||
|
||||
@@ -533,9 +691,9 @@ step=1; // TEST
|
||||
|
||||
len_word = strlen(word);
|
||||
|
||||
if(transpose_offset > 0)
|
||||
if(translator->transpose_offset > 0)
|
||||
{
|
||||
len_word = TransposeAlphabet(word, transpose_offset, transpose_min, transpose_max);
|
||||
len_word = TransposeAlphabet(word, translator->transpose_offset, translator->transpose_min, translator->transpose_max);
|
||||
}
|
||||
|
||||
*hash = HashDictionary(word);
|
||||
@@ -762,6 +920,7 @@ static void copy_rule_string(char *string, int &state)
|
||||
int sxflags;
|
||||
int value;
|
||||
int literal;
|
||||
MNEM_TAB *mr;
|
||||
|
||||
if(string[0] == 0) return;
|
||||
|
||||
@@ -858,7 +1017,8 @@ static void copy_rule_string(char *string, int &state)
|
||||
c = RULE_CAPITAL;
|
||||
break;
|
||||
case 'T':
|
||||
c = RULE_ALT1;
|
||||
output[ix++] = RULE_DOLLAR;
|
||||
c = 0x11;
|
||||
break;
|
||||
case 'W':
|
||||
c = RULE_SPELLING;
|
||||
@@ -899,10 +1059,28 @@ static void copy_rule_string(char *string, int &state)
|
||||
}
|
||||
break;
|
||||
|
||||
case '$': // obsolete, replaced by S
|
||||
fprintf(f_log,"%5d: $ now not allowed, use S for suffix",linenum);
|
||||
case '$':
|
||||
output[ix++] = RULE_DOLLAR;
|
||||
c = 0;
|
||||
mr = mnem_rules;
|
||||
while(mr->mnem != NULL)
|
||||
{
|
||||
len = strlen(mr->mnem);
|
||||
if(memcmp(p, mr->mnem, len) == 0)
|
||||
{
|
||||
c = mr->value;
|
||||
p += len;
|
||||
break;
|
||||
}
|
||||
mr++;
|
||||
}
|
||||
if(c == 0)
|
||||
{
|
||||
fprintf(f_log,"%5d: $ command not recognized\n",linenum);
|
||||
error_count++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
sxflags |= SUFX_P; // Prefix, now drop through to Suffix
|
||||
case 'S':
|
||||
@@ -1703,17 +1881,6 @@ int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, cha
|
||||
}
|
||||
sprintf(fname_temp,"%s%ctemp",path_home,PATHSEP);
|
||||
|
||||
transpose_offset = 0;
|
||||
|
||||
if(strcmp(dict_name,"ru") == 0)
|
||||
{
|
||||
// transpose cyrillic alphabet from unicode to iso8859-5
|
||||
// transpose_offset = 0x430-0xd0;
|
||||
transpose_offset = 0x42f; // range 0x01 to 0x22
|
||||
transpose_min = 0x430;
|
||||
transpose_max = 0x451;
|
||||
}
|
||||
|
||||
value = N_HASH_DICT;
|
||||
Write4Bytes(f_out,value);
|
||||
Write4Bytes(f_out,offset_rules);
|
||||
|
||||
+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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ extern void DictionarySort(const char *dictname);
|
||||
extern void init_z();
|
||||
extern void CompilePhonemeData(void);
|
||||
extern void CompileMbrola();
|
||||
extern void CompileIntonation();
|
||||
extern void InitSpectrumDisplay();
|
||||
extern void InitProsodyDisplay();
|
||||
extern void InitWaveDisplay();
|
||||
@@ -203,6 +204,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame)
|
||||
EVT_MENU(MENU_FORMAT_DICTIONARY, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_SORT_DICTIONARY, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_COMPILE_MBROLA, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_COMPILE_INTONATION, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_CLOSE_ALL, MyFrame::OnQuit)
|
||||
EVT_MENU(MENU_QUIT, MyFrame::OnQuit)
|
||||
EVT_MENU(MENU_SPEAK_TRANSLATE, MyFrame::OnSpeak)
|
||||
@@ -218,6 +220,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame)
|
||||
EVT_MENU(MENU_VOWELCHART2, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_VOWELCHART3, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_LEXICON_RU, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_LEXICON_BG, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_LEXICON_DE, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_LEXICON_IT, MyFrame::OnTools)
|
||||
EVT_MENU(MENU_LEXICON_IT2, MyFrame::OnTools)
|
||||
@@ -553,6 +556,7 @@ void MyFrame::OnTools(wxCommandEvent& event)
|
||||
break;
|
||||
|
||||
case MENU_LEXICON_RU:
|
||||
case MENU_LEXICON_BG:
|
||||
case MENU_LEXICON_DE:
|
||||
case MENU_LEXICON_IT:
|
||||
case MENU_LEXICON_IT2:
|
||||
@@ -566,6 +570,10 @@ void MyFrame::OnTools(wxCommandEvent& event)
|
||||
case MENU_COMPILE_MBROLA:
|
||||
CompileMbrola();
|
||||
break;
|
||||
|
||||
case MENU_COMPILE_INTONATION:
|
||||
CompileIntonation();
|
||||
break;
|
||||
|
||||
case MENU_COMPILE_DICT_DEBUG:
|
||||
debug_flag =1; // and drop through to next case
|
||||
|
||||
+202
-2
@@ -200,8 +200,6 @@ static const unsigned short KOI8_R[0x60] = {
|
||||
|
||||
|
||||
#define N_CHARS 34
|
||||
int *p_unicode;
|
||||
int unicode[80];
|
||||
#define PH(c1,c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name
|
||||
|
||||
|
||||
@@ -765,6 +763,202 @@ void Lexicon_De()
|
||||
}
|
||||
|
||||
|
||||
void Lexicon_Bg()
|
||||
{//==============
|
||||
// Bulgarian: compare stress markup in a list of words with lookup using bg_rules
|
||||
|
||||
char *p;
|
||||
char *pw;
|
||||
char *pw1;
|
||||
int cc;
|
||||
int vcount;
|
||||
int lex_stress;
|
||||
int input_length;
|
||||
int n_words=0;
|
||||
int n_wrong=0;
|
||||
int n_out=0;
|
||||
int n_stress;
|
||||
int max_stress;
|
||||
int max_stress_posn;
|
||||
int stress_first;
|
||||
int done;
|
||||
PHONEME_TAB *ph;
|
||||
|
||||
FILE *f_in;
|
||||
FILE *f_out;
|
||||
FILE *f_log;
|
||||
|
||||
char word[80];
|
||||
char word_in[80];
|
||||
char phonemes[N_WORD_PHONEMES];
|
||||
char buf[200];
|
||||
char fname[sizeof(path_dsource)+20];
|
||||
|
||||
static unsigned short bg_vowels[] = {0x430, 0x435, 0x438, 0x43e, 0x443, 0x44a, 0x44d, 0x44e, 0x44f, 0x450, 0x451, 0x45d, 0};
|
||||
|
||||
if(gui_flag == 0)
|
||||
return;
|
||||
|
||||
wxString s_fname = wxFileSelector(_T("List of UTF-8 words with Combining Grave Accent U+300 to indicate stress"),path_dir1,
|
||||
_T(""),_T(""),_T("*"),wxOPEN);
|
||||
if(s_fname.IsEmpty())
|
||||
return;
|
||||
strcpy(buf,s_fname.mb_str(wxConvLocal));
|
||||
path_dir1 = wxFileName(s_fname).GetPath();
|
||||
|
||||
if((f_in = fopen(buf,"r")) == NULL)
|
||||
{
|
||||
wxLogError(_T("Can't read file: ") + wxString(buf,wxConvLocal));
|
||||
return;
|
||||
}
|
||||
input_length = GetFileLength(buf);
|
||||
|
||||
sprintf(fname,"%s%c%s",path_dsource,PATHSEP,"bg_listx_1");
|
||||
if((f_out = fopen(fname,"w")) == NULL)
|
||||
{
|
||||
wxLogError(_T("Can't write to: ")+wxString(fname,wxConvLocal));
|
||||
fclose(f_in);
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(fname,"%s%c%s",path_dsource,PATHSEP,"bg_log");
|
||||
f_log = fopen(fname,"w");
|
||||
|
||||
LoadVoice("bg",0);
|
||||
progress = new wxProgressDialog(_T("Lexicon"),_T(""),input_length);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if((n_words & 0x3ff) == 0)
|
||||
{
|
||||
progress->Update(ftell(f_in));
|
||||
}
|
||||
|
||||
if(fgets(buf,sizeof(buf),f_in) == NULL)
|
||||
break;
|
||||
|
||||
if(isspace2(buf[0]))
|
||||
continue;
|
||||
|
||||
// convert from UTF-8 to Unicode
|
||||
word[0] = 0;
|
||||
word[1] = ' ';
|
||||
pw = &word[2];
|
||||
pw1 = word_in;
|
||||
p = buf;
|
||||
while(*p == ' ') p++;
|
||||
vcount = 0;
|
||||
lex_stress = 0;
|
||||
n_stress = 0;
|
||||
stress_first = 0;
|
||||
|
||||
// find the marked stress position
|
||||
for(;;)
|
||||
{
|
||||
p += utf8_in(&cc, p);
|
||||
if(iswspace(cc))
|
||||
break;
|
||||
if(cc == 0xfeff)
|
||||
continue; // ignore UTF-8 indication
|
||||
|
||||
pw1 += utf8_out(cc, pw1); // copy UTF-8 to 'word_in'
|
||||
|
||||
if(lookupwchar(bg_vowels, cc) != 0)
|
||||
vcount++;
|
||||
|
||||
if((cc == 0x300) || (cc == 0x450) || (cc == 0x45d))
|
||||
{
|
||||
// combining grave accent, of accented vowel character
|
||||
lex_stress = vcount;
|
||||
n_stress++;
|
||||
|
||||
if(vcount == 1)
|
||||
stress_first = 1;
|
||||
|
||||
if(cc == 0x300)
|
||||
continue; // discard combining accent
|
||||
if(cc == 0x450)
|
||||
cc = 0x435; // remove accent from vowel
|
||||
if(cc == 0x45d)
|
||||
cc = 0x438;
|
||||
}
|
||||
|
||||
pw += utf8_out(cc, pw); // copy UTF-8 to 'word'
|
||||
}
|
||||
*pw++ = ' ';
|
||||
*pw = 0;
|
||||
*pw1 = 0;
|
||||
|
||||
// translate
|
||||
TranslateWord(translator, &word[2],0, NULL);
|
||||
DecodePhonemes(word_phonemes,phonemes);
|
||||
|
||||
// find the stress position in the translation
|
||||
max_stress = 0;
|
||||
max_stress_posn = -1;
|
||||
vcount = 0;
|
||||
|
||||
ph = phoneme_tab[phonPAUSE];
|
||||
for(p=word_phonemes; *p != 0; p++)
|
||||
{
|
||||
ph = phoneme_tab[(unsigned int)*p];
|
||||
if(ph == NULL)
|
||||
continue;
|
||||
|
||||
if(ph->type == phVOWEL)
|
||||
vcount++;
|
||||
if(ph->type == phSTRESS)
|
||||
{
|
||||
if(ph->std_length > max_stress)
|
||||
{
|
||||
max_stress = ph->std_length;
|
||||
max_stress_posn = vcount+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done = 0;
|
||||
if((lex_stress != max_stress_posn) || (n_stress != 1))
|
||||
{
|
||||
if((vcount > 0) && (lex_stress > 0) && (lex_stress <= 7))
|
||||
{
|
||||
if((n_stress == 2) && (stress_first))
|
||||
{
|
||||
done = 1;
|
||||
fprintf(f_out,"%s\t$%d\n",&word[2],lex_stress);
|
||||
}
|
||||
if(n_stress == 1)
|
||||
{
|
||||
done = 1;
|
||||
fprintf(f_out,"%s\t$%d\n",&word[2],lex_stress);
|
||||
}
|
||||
}
|
||||
|
||||
if(done == 0)
|
||||
{
|
||||
n_wrong++;
|
||||
fprintf(f_out,"%s\t$text %s\n", &word[2], word_in);
|
||||
}
|
||||
|
||||
if(done)
|
||||
n_out++;
|
||||
}
|
||||
|
||||
n_words++;
|
||||
}
|
||||
|
||||
fclose(f_in);
|
||||
fclose(f_out);
|
||||
fclose(f_log);
|
||||
|
||||
|
||||
delete progress;
|
||||
sprintf(buf,"Lexicon: Input %d, Output %d, Failed %d",n_words,n_out,n_wrong);
|
||||
wxLogStatus(wxString(buf,wxConvLocal));
|
||||
} // end of Lexicon_Bg
|
||||
|
||||
|
||||
|
||||
void Lexicon_Ru()
|
||||
{//==============
|
||||
// compare stress markings in Russian RuLex file with lookup in ru_rules
|
||||
@@ -791,6 +985,9 @@ void Lexicon_Ru()
|
||||
int len;
|
||||
int check_root;
|
||||
|
||||
int *p_unicode;
|
||||
int unicode[80];
|
||||
|
||||
char word[80];
|
||||
char word2[80];
|
||||
int counts[20][20][10];
|
||||
@@ -1066,6 +1263,9 @@ void CompareLexicon(int id)
|
||||
case MENU_LEXICON_RU:
|
||||
Lexicon_Ru();
|
||||
break;
|
||||
case MENU_LEXICON_BG:
|
||||
Lexicon_Bg();
|
||||
break;
|
||||
case MENU_LEXICON_DE:
|
||||
Lexicon_De();
|
||||
break;
|
||||
|
||||
+22
-2
@@ -49,6 +49,7 @@ BEGIN_EVENT_TABLE(FormantDlg, wxPanel)
|
||||
// EVT_SPINCTRL(T_TIMEFRAME,FormantDlg::OnSpin)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
int use_spin_controls=0;
|
||||
|
||||
void FormantDlg::OnCommand(wxCommandEvent& event)
|
||||
{//=============================================
|
||||
@@ -181,7 +182,14 @@ FormantDlg::FormantDlg(wxWindow *parent) : wxPanel(parent,-1,wxDefaultPosition,w
|
||||
}
|
||||
|
||||
y=224;
|
||||
t_timeframe = new wxSpinCtrl(this,T_TIMEFRAME,_T(""), wxPoint(6,y+0), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Frame length"));
|
||||
if(use_spin_controls)
|
||||
{
|
||||
t_timeframe = new wxSpinCtrl(this,T_TIMEFRAME,_T(""), wxPoint(6,y+0), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Frame length"));
|
||||
}
|
||||
else
|
||||
{
|
||||
tt_timeframe = new wxTextCtrl(this,T_TIMEFRAME,_T(""), wxPoint(6,y+0), wxSize(52,24), wxTE_CENTRE,wxDefaultValidator,_T("Frame length"));
|
||||
}
|
||||
t_orig_frame = new wxStaticText(this,-1,_T("mS"),wxPoint(61,y+8));
|
||||
t_ampframe = new wxSpinCtrl(this,T_AMPFRAME,_T(""), wxPoint(104,y+0), wxSize(52,24), wxTE_CENTRE,0,500,0,_T("Frame amplitude"));
|
||||
t_lab[3] = new wxStaticText(this,-1,_T("% amp - Frame"),wxPoint(159,y+8));
|
||||
@@ -255,6 +263,12 @@ void FormantDlg::GetValues(SpectSeq *spectseq, int frame)
|
||||
return;
|
||||
sf = spectseq->frames[frame];
|
||||
|
||||
if(use_spin_controls == 0)
|
||||
{
|
||||
formantdlg->tt_timeframe->GetValue().ToLong(&num);
|
||||
sf->length_adjust = num - spectseq->GetFrameLength(frame,0,NULL);
|
||||
}
|
||||
|
||||
for(ix=0; ix < 8; ix++)
|
||||
{
|
||||
if(ix < 7)
|
||||
@@ -386,7 +400,13 @@ void FormantDlg::ShowFrame(SpectSeq *spectseq, int frame, int pk, int field)
|
||||
}
|
||||
|
||||
// find the time until the next keyframe
|
||||
SetSpinCtrl(t_timeframe,int(spectseq->GetFrameLength(frame,1,&original_mS)+0.5)); // round to nearest integer
|
||||
value.Printf(_T("%d"),int(spectseq->GetFrameLength(frame,1,&original_mS)+0.5)); // round to nearest integer
|
||||
|
||||
if(use_spin_controls)
|
||||
t_timeframe->SetValue(value);
|
||||
else
|
||||
tt_timeframe->SetValue(value);
|
||||
|
||||
value.Printf(_T("%d mS"),original_mS);
|
||||
t_orig_frame->SetLabel(value);
|
||||
value.Printf(_T("%3d"),sf->amp_adjust);
|
||||
|
||||
+98
-114
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include "speak_lib.h"
|
||||
@@ -45,8 +46,8 @@ typedef struct {
|
||||
char env;
|
||||
char flags; //bit 0=pitch rising, bit1=emnphasized, bit2=end of clause
|
||||
char nextph_type;
|
||||
short pitch1;
|
||||
short pitch2;
|
||||
unsigned char pitch1;
|
||||
unsigned char pitch2;
|
||||
} SYLLABLE;
|
||||
|
||||
static SYLLABLE *syllable_tab;
|
||||
@@ -61,10 +62,10 @@ static int tone_pitch_env; /* used to return pitch envelope */
|
||||
|
||||
|
||||
#define PITCHfall 0
|
||||
#define PITCHrise 1
|
||||
#define PITCHfrise 2 // and 3 must be for the varient preceded by 'r'
|
||||
#define PITCHfrise2 4 // and 5 must be the 'r' variant
|
||||
#define PITCHrisefall 6
|
||||
#define PITCHrise 2
|
||||
#define PITCHfrise 4 // and 3 must be for the variant preceded by 'r'
|
||||
#define PITCHfrise2 6 // and 5 must be the 'r' variant
|
||||
#define PITCHrisefall 8
|
||||
|
||||
/* 0 fall */
|
||||
unsigned char env_fall[128] = {
|
||||
@@ -191,9 +192,9 @@ static unsigned char env_risefallrise[128] = {
|
||||
|
||||
|
||||
|
||||
unsigned char *envelope_data[18] = {
|
||||
env_fall,
|
||||
env_rise,
|
||||
unsigned char *envelope_data[20] = {
|
||||
env_fall, env_fall,
|
||||
env_rise, env_rise,
|
||||
env_frise, env_r_frise,
|
||||
env_frise2, env_r_frise2,
|
||||
env_risefall, env_risefall,
|
||||
@@ -206,18 +207,17 @@ unsigned char *envelope_data[18] = {
|
||||
};
|
||||
|
||||
|
||||
/* all pitches given in Hz above pitch_base */
|
||||
|
||||
/* indexed by stress */
|
||||
static int min_drop[] = {6,7,9,9,20,20,20,25};
|
||||
|
||||
// pitch change during the main part of the clause
|
||||
static int drops_0[8] = {0x400,0x400,0x700,0x700,0x700,0xa00,0x1800,0x0e00};
|
||||
//static int drops_1[8] = {0x400,0x400,0x600,0x600,0xc00,0xc00,0x0e00,0x0e00};
|
||||
//static int drops_2[8] = {0x400,0x400,0x600,0x600,-0x800,0xc00,0x0e00,0x0e00};
|
||||
static int drops_0[8] = {9,9,16,16,16,23,55,32};
|
||||
|
||||
static short oflow[] = {0, 20, 12, 4, 0};
|
||||
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};
|
||||
// overflow table values are 64ths of the body pitch range (between body_start and body_end)
|
||||
static signed char oflow[] = {0, 40, 24, 8, 0};
|
||||
static signed char oflow_emf[] = {10, 52, 32, 20, 10};
|
||||
static signed char oflow_less[] = {6, 38, 24, 14, 4};
|
||||
|
||||
|
||||
#define N_TONE_HEAD_TABLE 13
|
||||
@@ -235,8 +235,8 @@ typedef struct {
|
||||
unsigned char body_max_steps;
|
||||
char body_lower_u;
|
||||
|
||||
char n_overflow;
|
||||
short *overflow;
|
||||
unsigned char n_overflow;
|
||||
signed char *overflow;
|
||||
} TONE_HEAD;
|
||||
|
||||
|
||||
@@ -259,38 +259,38 @@ typedef struct {
|
||||
#define T_EMPH 1
|
||||
|
||||
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, 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
|
||||
{20, 25, 32, 24, drops_0, 4, 3, 5, oflow_less}, // 7 comma, less intonation, less rise
|
||||
{20, 25, 34, 22, drops_0, 3, 3, 5, oflow}, // 8 pitch raises at end of sentence
|
||||
{20, 25, 34, 20, drops_0, 3, 3, 5, oflow}, // 9 comma
|
||||
{20, 25, 34, 22, drops_0, 3, 3, 5, oflow}, // 10 question
|
||||
{15, 18, 18, 14, drops_0, 3, 3, 5, oflow_less}, // 11 test
|
||||
{20, 25, 24, 22, drops_0, 3, 3, 5, oflow_less}, // 12 test
|
||||
{46, 57, 78, 50, drops_0, 3, 7, 5, oflow}, // 0 statement
|
||||
{46, 57, 78, 46, drops_0, 3, 7, 5, oflow}, // 1 comma
|
||||
{46, 57, 78, 46, drops_0, 3, 7, 5, oflow}, // 2 question
|
||||
{46, 57, 90, 50, drops_0, 3, 9, 5, oflow_emf}, // 3 exclamation
|
||||
{46, 57, 78, 50, drops_0, 3, 7, 5, oflow}, // 4 statement, emphatic
|
||||
{46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less}, // 5 statement, less intonation
|
||||
{46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less}, // 6 comma, less intonation
|
||||
{46, 57, 74, 55, drops_0, 4, 7, 5, oflow_less}, // 7 comma, less intonation, less rise
|
||||
{46, 57, 78, 50, drops_0, 3, 7, 5, oflow}, // 8 pitch raises at end of sentence
|
||||
{46, 57, 78, 46, drops_0, 3, 7, 5, oflow}, // 9 comma
|
||||
{46, 57, 78, 50, drops_0, 3, 7, 5, oflow}, // 10 question
|
||||
{34, 41, 41, 32, drops_0, 3, 7, 5, oflow_less}, // 11 test
|
||||
{46, 57, 55, 50, drops_0, 3, 7, 5, oflow_less}, // 12 test
|
||||
};
|
||||
|
||||
static TONE_NUCLEUS tone_nucleus_table[N_TONE_NUCLEUS_TABLE] = {
|
||||
{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
|
||||
{PITCHfall, 41, 4, PITCHfall, 41,35, NULL, 35, 4, T_EMPH}, // 3 exclamation
|
||||
{PITCHfall, 38, 2, PITCHfall, 42,30, NULL, 15, 5, 0}, // 4 statement, emphatic
|
||||
{PITCHfall, 28, 5, PITCHfall, 28, 9, NULL, 12, 7, 0}, // 5 statement, less intonation
|
||||
{PITCHfrise, 30, 8, PITCHfrise2, 30,10, NULL, 13, 20, 0}, // 6 comma, less intonation
|
||||
{PITCHfrise2, 28, 7, PITCHfall, 29,14, NULL, 14, 8, 0}, // 7 comma, less intonation, less rise
|
||||
{PITCHrise, 30,20, PITCHfall, 19,14, NULL, 20, 26, 0}, // 8 pitch raises at end of sentence
|
||||
{PITCHfrise, 35,11, PITCHfrise2, 32,10, NULL, 19, 24, 0}, // 9 comma
|
||||
{PITCHfrise, 39,15, PITCHfall, 28,14, NULL, 20, 36, 0}, // 10 question
|
||||
{PITCHfall, 28, 6, PITCHfall, 28,10, NULL, 12, 6, 0}, // 11 test
|
||||
{PITCHfall, 35, 9, PITCHfall, 35,12, NULL, 16, 10, 0}, // 12 test
|
||||
{PITCHfall, 64, 8, PITCHfall, 70,18, NULL, 24, 12, 0}, // 0 statement
|
||||
{PITCHfrise, 80,18, PITCHfrise2, 78,22, NULL, 34, 52, 0}, // 1 comma
|
||||
{PITCHfrise, 88,22, PITCHfrise2, 82,22, NULL, 34, 64, 0}, // 2 question
|
||||
{PITCHfall, 92, 8, PITCHfall, 92,80, NULL, 76, 8, T_EMPH}, // 3 exclamation
|
||||
|
||||
{PITCHfall, 86, 4, PITCHfall, 94,66, NULL, 34, 10, 0}, // 4 statement, emphatic
|
||||
{PITCHfall, 62,10, PITCHfall, 62,20, NULL, 28, 16, 0}, // 5 statement, less intonation
|
||||
{PITCHfrise, 68,18, PITCHfrise2, 68,22, NULL, 30, 44, 0}, // 6 comma, less intonation
|
||||
{PITCHfrise2, 64,16, PITCHfall, 66,32, NULL, 32, 18, 0}, // 7 comma, less intonation, less rise
|
||||
{PITCHrise, 68,46, PITCHfall, 42,32, NULL, 46, 58, 0}, // 8 pitch raises at end of sentence
|
||||
{PITCHfrise, 78,24, PITCHfrise2, 72,22, NULL, 42, 52, 0}, // 9 comma
|
||||
{PITCHfrise, 88,34, PITCHfall, 64,32, NULL, 46, 82, 0}, // 10 question
|
||||
{PITCHfall, 56,12, PITCHfall, 56,20, NULL, 24, 12, 0}, // 11 test
|
||||
{PITCHfall, 70,18, PITCHfall, 70,24, NULL, 32, 20, 0}, // 12 test
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* index by 0=. 1=, 2=?, 3=! 4=none, 5=emphasized */
|
||||
@@ -306,11 +306,8 @@ unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS] = {
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* indexed by stress */
|
||||
static int min_drop[] = {0x300,0x300,0x400,0x400,0x900,0x900,0x900,0xb00};
|
||||
|
||||
|
||||
int n_tunes = 0;
|
||||
TUNE *tunes = NULL;
|
||||
|
||||
|
||||
#define SECONDARY 3
|
||||
@@ -419,20 +416,17 @@ static int count_increments(int ix, int end_ix, int min_stress)
|
||||
|
||||
|
||||
|
||||
|
||||
static void set_pitch(SYLLABLE *syl, int base, int drop)
|
||||
/******************************************************/
|
||||
// Set the pitch of a vowel in syllable_tab. Base & drop are Hz * 256
|
||||
// Set the pitch of a vowel in syllable_tab
|
||||
{
|
||||
int pitch1, pitch2;
|
||||
int flags = 0;
|
||||
|
||||
/* adjust experimentally */
|
||||
int pitch_range2 = 148;
|
||||
int pitch_base2 = 72;
|
||||
|
||||
if(base < 0) base = 0;
|
||||
|
||||
pitch2 = ((base * pitch_range2 ) >> 15) + pitch_base2;
|
||||
pitch2 = base;
|
||||
|
||||
if(drop < 0)
|
||||
{
|
||||
@@ -440,10 +434,12 @@ static void set_pitch(SYLLABLE *syl, int base, int drop)
|
||||
drop = -drop;
|
||||
}
|
||||
|
||||
pitch1 = pitch2 + ((drop * pitch_range2) >> 15);
|
||||
pitch1 = pitch2 + drop;
|
||||
if(pitch1 < 0)
|
||||
pitch1 = 0;
|
||||
|
||||
if(pitch1 > 511) pitch1 = 511;
|
||||
if(pitch2 > 511) pitch2 = 511;
|
||||
if(pitch1 > 254) pitch1 = 254;
|
||||
if(pitch2 > 254) pitch2 = 254;
|
||||
|
||||
syl->pitch1 = pitch1;
|
||||
syl->pitch2 = pitch2;
|
||||
@@ -466,13 +462,17 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t
|
||||
int initial;
|
||||
int overflow=0;
|
||||
int n_overflow;
|
||||
int pitch_range;
|
||||
int pitch_range_abs;
|
||||
int *drops;
|
||||
short *overflow_tab;
|
||||
signed char *overflow_tab;
|
||||
SYLLABLE *syl;
|
||||
|
||||
static short continue_tab[5] = {-13, 16, 10, 4, 0};
|
||||
static signed char continue_tab[5] = {-26, 32, 20, 8, 0};
|
||||
|
||||
drops = th->body_drops;
|
||||
pitch_range = (th->body_end - th->body_start) << 8;
|
||||
pitch_range_abs = abs(pitch_range);
|
||||
|
||||
if(continuing)
|
||||
{
|
||||
@@ -480,8 +480,7 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t
|
||||
overflow = 0;
|
||||
n_overflow = 5;
|
||||
overflow_tab = continue_tab;
|
||||
increment = (th->body_end - th->body_start) << 8;
|
||||
increment = increment / (th->body_max_steps -1);
|
||||
increment = pitch_range / (th->body_max_steps -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -513,8 +512,7 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t
|
||||
|
||||
if(n_steps > 1)
|
||||
{
|
||||
increment = (th->body_end - th->body_start) << 8;
|
||||
increment = increment / (n_steps -1);
|
||||
increment = pitch_range / (n_steps -1);
|
||||
}
|
||||
else
|
||||
increment = 0;
|
||||
@@ -527,7 +525,7 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t
|
||||
pitch += increment;
|
||||
else
|
||||
{
|
||||
pitch = (th->body_end << 8) - (increment * overflow_tab[overflow++])/16;
|
||||
pitch = (th->body_end << 8) + (pitch_range_abs * overflow_tab[overflow++])/64;
|
||||
if(overflow >= n_overflow)
|
||||
{
|
||||
overflow = 0;
|
||||
@@ -548,20 +546,20 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t
|
||||
if(stress >= PRIMARY)
|
||||
{
|
||||
syl->stress = PRIMARY_STRESSED;
|
||||
set_pitch(syl,pitch,drops[stress]);
|
||||
set_pitch(syl,(pitch >> 8),drops[stress]);
|
||||
}
|
||||
else
|
||||
if(stress >= SECONDARY)
|
||||
{
|
||||
set_pitch(syl,pitch,drops[stress]);
|
||||
set_pitch(syl,(pitch >> 8),drops[stress]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unstressed, drop pitch if preceded by PRIMARY */
|
||||
if((syllable_tab[ix-1].stress & 0x3f) >= SECONDARY)
|
||||
set_pitch(syl,pitch - (th->body_lower_u << 8), drops[stress]);
|
||||
set_pitch(syl,(pitch >> 8) - th->body_lower_u, drops[stress]);
|
||||
else
|
||||
set_pitch(syl,pitch,drops[stress]);
|
||||
set_pitch(syl,(pitch >> 8),drops[stress]);
|
||||
}
|
||||
|
||||
ix++;
|
||||
@@ -571,13 +569,12 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_HEAD *th, TONE_NUCLEUS *t
|
||||
|
||||
|
||||
|
||||
static void SetPitchGradient(int start_ix, int end_ix, int start_pitch, int end_pitch)
|
||||
{//====================================================================================
|
||||
// Set a linear pitch change over a number of syllables.
|
||||
// Used for pre-head, unstressed syllables in the body, and the tail
|
||||
|
||||
|
||||
static int calc_pitch_segment2(int ix, int end_ix, int start_p, int end_p, int min_stress)
|
||||
/****************************************************************************************/
|
||||
/* Linear pitch rise/fall, change pitch at min_stress or stronger
|
||||
Used for pre-head and tail */
|
||||
{
|
||||
int ix;
|
||||
int stress;
|
||||
int pitch;
|
||||
int increment;
|
||||
@@ -585,49 +582,43 @@ static int calc_pitch_segment2(int ix, int end_ix, int start_p, int end_p, int m
|
||||
int drop;
|
||||
SYLLABLE *syl;
|
||||
|
||||
if(ix >= end_ix)
|
||||
return(ix);
|
||||
|
||||
n_increments = count_increments(ix,end_ix,min_stress);
|
||||
increment = (end_p - start_p) << 8;
|
||||
increment = (end_pitch - start_pitch) << 8;
|
||||
n_increments = end_ix - start_ix;
|
||||
|
||||
if(n_increments <= 0)
|
||||
return;
|
||||
|
||||
if(n_increments > 1)
|
||||
{
|
||||
increment = increment / n_increments;
|
||||
}
|
||||
|
||||
|
||||
pitch = start_p << 8;
|
||||
while(ix < end_ix)
|
||||
pitch = start_pitch << 8;
|
||||
|
||||
for(ix=start_ix; ix < end_ix; ix++)
|
||||
{
|
||||
syl = &syllable_tab[ix];
|
||||
stress = syl->stress;
|
||||
|
||||
if(increment > 0)
|
||||
{
|
||||
set_pitch(syl,pitch,-increment);
|
||||
set_pitch(syl,(pitch >> 8),-(increment >> 8));
|
||||
pitch += increment;
|
||||
}
|
||||
else
|
||||
{
|
||||
drop = -increment;
|
||||
drop = -(increment >> 8);
|
||||
if(drop < min_drop[stress])
|
||||
drop = min_drop[stress];
|
||||
|
||||
pitch += increment;
|
||||
|
||||
if(drop > 0x900)
|
||||
drop = 0x900;
|
||||
set_pitch(syl, pitch, drop);
|
||||
if(drop > 18)
|
||||
drop = 18;
|
||||
set_pitch(syl, (pitch >> 8), drop);
|
||||
}
|
||||
|
||||
ix++;
|
||||
}
|
||||
return(ix);
|
||||
} /* end of calc_pitch_segment2 */
|
||||
|
||||
|
||||
|
||||
} // end of SetPitchGradient
|
||||
|
||||
|
||||
|
||||
@@ -651,10 +642,8 @@ static int calc_pitches(int start, int end, int head_tone, int nucleus_tone)
|
||||
/* vowels before the first primary stress */
|
||||
/******************************************/
|
||||
|
||||
if(number_pre > 0)
|
||||
{
|
||||
ix = calc_pitch_segment2(ix, ix+number_pre, th->pre_start, th->pre_end, 0);
|
||||
}
|
||||
SetPitchGradient(ix, ix+number_pre, th->pre_start, th->pre_end);
|
||||
ix += number_pre;
|
||||
|
||||
/* body of tonic segment */
|
||||
/*************************/
|
||||
@@ -680,13 +669,13 @@ static int calc_pitches(int start, int end, int head_tone, int nucleus_tone)
|
||||
{
|
||||
tone_pitch_env = tn->pitch_env0;
|
||||
drop = tn->tonic_max0 - tn->tonic_min0;
|
||||
set_pitch(&syllable_tab[ix++],tn->tonic_min0 << 8,drop << 8);
|
||||
set_pitch(&syllable_tab[ix++],tn->tonic_min0, drop);
|
||||
}
|
||||
else
|
||||
{
|
||||
tone_pitch_env = tn->pitch_env1;
|
||||
drop = tn->tonic_max1 - tn->tonic_min1;
|
||||
set_pitch(&syllable_tab[ix++],tn->tonic_min1 << 8,drop << 8);
|
||||
set_pitch(&syllable_tab[ix++],tn->tonic_min1, drop);
|
||||
}
|
||||
|
||||
syllable_tab[tone_posn].env = tone_pitch_env;
|
||||
@@ -696,7 +685,7 @@ static int calc_pitches(int start, int end, int head_tone, int nucleus_tone)
|
||||
/* tail, after the tonic syllable */
|
||||
/**********************************/
|
||||
|
||||
calc_pitch_segment2(ix, end, tn->tail_start, tn->tail_end, 0);
|
||||
SetPitchGradient(ix, end, tn->tail_start, tn->tail_end);
|
||||
|
||||
return(tone_pitch_env);
|
||||
} /* end of calc_pitches */
|
||||
@@ -1057,13 +1046,8 @@ void CalcPitches(Translator *tr, int clause_type)
|
||||
{
|
||||
syl = &syllable_tab[st_ix];
|
||||
|
||||
x = syl->pitch1 - 72;
|
||||
if(x < 0) x = 0;
|
||||
p->pitch1 = x;
|
||||
|
||||
x = syl->pitch2 - 72;
|
||||
if(x < 0) x = 0;
|
||||
p->pitch2 = x;
|
||||
p->pitch1 = syl->pitch1;
|
||||
p->pitch2 = syl->pitch2;
|
||||
|
||||
p->env = PITCHfall;
|
||||
if(syl->flags & SYL_RISE)
|
||||
@@ -1099,6 +1083,6 @@ if(p->tone_ph)
|
||||
}
|
||||
}
|
||||
|
||||
} // end of Translator::CalcPitches
|
||||
} // end of CalcPitches
|
||||
|
||||
|
||||
|
||||
@@ -138,6 +138,7 @@ enum {
|
||||
MENU_FORMAT_DICTIONARY,
|
||||
MENU_SORT_DICTIONARY,
|
||||
MENU_COMPILE_MBROLA,
|
||||
MENU_COMPILE_INTONATION,
|
||||
|
||||
MENU_SPEAK_TRANSLATE,
|
||||
MENU_SPEAK_RULES,
|
||||
@@ -155,6 +156,7 @@ enum {
|
||||
MENU_VOWELCHART3,
|
||||
MENU_LEXICON,
|
||||
MENU_LEXICON_RU,
|
||||
MENU_LEXICON_BG,
|
||||
MENU_LEXICON_DE,
|
||||
MENU_LEXICON_IT,
|
||||
MENU_LEXICON_IT2,
|
||||
|
||||
+3
-1
@@ -88,6 +88,7 @@ wxMenuBar *MakeMenu(int type)
|
||||
data_menu->Append(MENU_COMPILE_DICT, _("Compile &dictionary"));
|
||||
data_menu->Append(MENU_COMPILE_DICT_DEBUG, _("Compile dictionary (debu&g)"));
|
||||
data_menu->Append(MENU_COMPILE_MBROLA, _("Compile &mbrola phonemes list..."));
|
||||
// data_menu->Append(MENU_COMPILE_INTONATION, _("Compile &intonation data"));
|
||||
data_menu->AppendSeparator();
|
||||
data_menu->Append(MENU_FORMAT_DICTIONARY, _("&Layout *_rules file"));
|
||||
data_menu->Append(MENU_SORT_DICTIONARY, _("&Sort *_rules file"));
|
||||
@@ -113,6 +114,7 @@ wxMenuBar *MakeMenu(int type)
|
||||
|
||||
lexicon_menu = new wxMenu;
|
||||
lexicon_menu->Append(MENU_LEXICON_RU, _("Russian (lexicon.dict)"));
|
||||
lexicon_menu->Append(MENU_LEXICON_BG, _("Bulgarian"));
|
||||
lexicon_menu->Append(MENU_LEXICON_DE, _("German"));
|
||||
lexicon_menu->Append(MENU_LEXICON_IT, _("Italian"));
|
||||
lexicon_menu->Append(MENU_LEXICON_IT2, _("Italian, pass 2"));
|
||||
@@ -120,7 +122,7 @@ wxMenuBar *MakeMenu(int type)
|
||||
tools_menu = new wxMenu;
|
||||
tools_menu->Append(MENU_VOWELCHART, _("Make &Vowels Chart"), vowelchart_menu);
|
||||
// tools_menu->Append(MENU_LOAD_WAV, _T("Analyse WAV file"));
|
||||
tools_menu->Append(MENU_LEXICON, _("Compare &Lexicon"), lexicon_menu);
|
||||
tools_menu->Append(MENU_LEXICON, _("Process &Lexicon"), lexicon_menu);
|
||||
tools_menu->Append(MENU_TO_UTF8, _("Convert file to &UTF8..."));
|
||||
tools_menu->Append(MENU_COUNT_WORDS, _("Count word &frequencies..."));
|
||||
tools_menu->Append(MENU_TEST , _("Test (temporary)"));
|
||||
|
||||
+57
-19
@@ -769,7 +769,11 @@ static int CheckDotOrdinal(Translator *tr, char *word, char *word_end, WORD_TAB
|
||||
{
|
||||
if(roman || !(wtab[1].flags & FLAG_FIRST_UPPER))
|
||||
{
|
||||
utf8_in(&c2, &word_end[2]);
|
||||
if(word_end[0] == '.')
|
||||
utf8_in(&c2, &word_end[2]);
|
||||
else
|
||||
utf8_in(&c2, &word_end[1]);
|
||||
|
||||
if((word_end[1] != 0) && ((c2 == 0) || (wtab[0].flags & FLAG_COMMA_AFTER) || IsAlpha(c2)))
|
||||
{
|
||||
// ordinal number is indicated by dot after the number
|
||||
@@ -810,6 +814,19 @@ if((tr->prev_dict_flags & FLAG_ALT_TRANS) && ((c2 == 0) || (wtab[0].flags & FLAG
|
||||
} // end of CheckDotOrdinal
|
||||
|
||||
|
||||
static int hu_number_e(const char *word)
|
||||
{//=====================================
|
||||
// lang-hu: variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt, att. ett
|
||||
|
||||
if((word[0] == 'a') || (word[0] == 'e'))
|
||||
{
|
||||
if((word[1] == ' ') || (word[1] == 'z') || ((word[1] == 't') && (word[2] == 't')))
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
} // end of hu_numnber_e
|
||||
|
||||
|
||||
|
||||
int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
|
||||
@@ -824,6 +841,7 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
|
||||
int repeat = 0;
|
||||
int n_digits = 0;
|
||||
char *word_start;
|
||||
int num_control = 0;
|
||||
unsigned int flags[2];
|
||||
char ph_roman[30];
|
||||
char number_chars[N_WORD_BYTES];
|
||||
@@ -895,18 +913,34 @@ int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab)
|
||||
|
||||
sprintf(number_chars," %d ",acc);
|
||||
|
||||
if(word[0] == '.')
|
||||
{
|
||||
// dot has not been removed. This implies that there was no space after it
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(CheckDotOrdinal(tr, word_start, word, wtab, 1))
|
||||
wtab[0].flags |= FLAG_ORDINAL;
|
||||
|
||||
if(tr->langopts.numbers & NUM_ROMAN_ORDINAL)
|
||||
{
|
||||
if((n_digits <= 1) && !(wtab[0].flags & FLAG_ORDINAL))
|
||||
return(0);
|
||||
wtab[0].flags |= FLAG_ORDINAL;
|
||||
if(tr->translator_name == L('h','u'))
|
||||
{
|
||||
if(!(wtab[0].flags & FLAG_ORDINAL))
|
||||
{
|
||||
if((wtab[0].flags & FLAG_HYPHEN_AFTER) && hu_number_e(word))
|
||||
{
|
||||
// should use the 'e' form of the number
|
||||
num_control |= 1;
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr->prev_dict_flags = 0;
|
||||
TranslateNumber(tr, &number_chars[2], p, flags, wtab);
|
||||
TranslateNumber(tr, &number_chars[2], p, flags, wtab, num_control);
|
||||
|
||||
if(tr->langopts.numbers & NUM_ROMAN_AFTER)
|
||||
strcat(ph_out,ph_roman);
|
||||
@@ -1319,11 +1353,11 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null
|
||||
tensunits = value % 100;
|
||||
buf1[0] = 0;
|
||||
|
||||
ph_thousands[0] = 0;
|
||||
ph_thousand_and[0] = 0;
|
||||
|
||||
if(hundreds > 0)
|
||||
{
|
||||
ph_thousands[0] = 0;
|
||||
ph_thousand_and[0] = 0;
|
||||
|
||||
found = 0;
|
||||
if(ordinal && (tensunits == 0))
|
||||
{
|
||||
@@ -1369,6 +1403,7 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null
|
||||
}
|
||||
|
||||
ph_digits[0] = 0;
|
||||
|
||||
if(hundreds > 0)
|
||||
{
|
||||
if((tr->langopts.numbers & NUM_AND_HUNDRED) && ((control & 1) || (ph_thousands[0] != 0)))
|
||||
@@ -1418,9 +1453,13 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null
|
||||
}
|
||||
|
||||
ph_hundred_and[0] = 0;
|
||||
if((tr->langopts.numbers & NUM_HUNDRED_AND) && (tensunits != 0))
|
||||
if(tensunits > 0)
|
||||
{
|
||||
if((value > 100) || ((control & 1) && (thousandplex==0)))
|
||||
if((tr->langopts.numbers & NUM_HUNDRED_AND) && ((value > 100) || ((control & 1) && (thousandplex==0))))
|
||||
{
|
||||
Lookup(tr, "_0and", ph_hundred_and);
|
||||
}
|
||||
if((tr->langopts.numbers & NUM_THOUSAND_AND) && (hundreds == 0) && ((control & 1) || (ph_thousands[0] != 0)))
|
||||
{
|
||||
Lookup(tr, "_0and", ph_hundred_and);
|
||||
}
|
||||
@@ -1461,8 +1500,8 @@ static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null
|
||||
} // end of LookupNum3
|
||||
|
||||
|
||||
static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, WORD_TAB *wtab)
|
||||
{//========================================================================================================
|
||||
static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control)
|
||||
{//=====================================================================================================================
|
||||
// Number translation with various options
|
||||
// the "word" may be up to 4 digits
|
||||
// "words" of 3 digits may be preceded by another number "word" for thousands or millions
|
||||
@@ -1501,7 +1540,7 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
n_digit_lookup = 0;
|
||||
buf_digit_lookup[0] = 0;
|
||||
digit_lookup = buf_digit_lookup;
|
||||
number_control = 0;
|
||||
number_control = control;
|
||||
|
||||
for(ix=0; isdigit(word[ix]); ix++) ;
|
||||
n_digits = ix;
|
||||
@@ -1639,9 +1678,8 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
|
||||
if(tr->translator_name == L('h','u'))
|
||||
{
|
||||
// variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (buit not a, e, az, ez, azt, ezt
|
||||
if((wtab[thousandplex].flags & FLAG_HYPHEN_AFTER) && (thousands_exact==1)
|
||||
&& ((word[suffix_ix] == 'a') || (word[suffix_ix] == 'e')) && ((c = word[suffix_ix+1]) != ' ') && (c != 'z'))
|
||||
// variant form of numbers when followed by hyphen and a suffix starting with 'a' or 'e' (but not a, e, az, ez, azt, ezt
|
||||
if((wtab[thousandplex].flags & FLAG_HYPHEN_AFTER) && (thousands_exact==1) && hu_number_e(&word[suffix_ix]))
|
||||
{
|
||||
number_control |= 1; // use _1e variant of number
|
||||
}
|
||||
@@ -1821,13 +1859,13 @@ static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned
|
||||
|
||||
|
||||
|
||||
int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab)
|
||||
{//================================================================================================
|
||||
int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control)
|
||||
{//=============================================================================================================
|
||||
if(option_sayas == SAYAS_DIGITS1)
|
||||
return(0); // speak digits individually
|
||||
|
||||
if(tr->langopts.numbers != 0)
|
||||
return(TranslateNumber_1(tr, word1, ph_out, flags, wtab));
|
||||
return(TranslateNumber_1(tr, word1, ph_out, flags, wtab, control));
|
||||
|
||||
return(0);
|
||||
} // end of TranslateNumber
|
||||
|
||||
+1
-1
@@ -192,7 +192,7 @@ void ConfigSave(int exit)
|
||||
wxFileConfig *pConfig = (wxFileConfig *)(wxConfigBase::Get());
|
||||
|
||||
#ifndef PLATFORM_WINDOWS
|
||||
pConfig->Write(_T("/samplerate"),samplerate);
|
||||
// pConfig->Write(_T("/samplerate"),samplerate);
|
||||
#endif
|
||||
pConfig->Write(_T("/spectload"),path_spectload);
|
||||
pConfig->Write(_T("/spectload2"),path_spectload2);
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#define phLONG 0x200000
|
||||
#define phLENGTHENSTOP 0x400000 // make the pre-pause slightly longer
|
||||
#define phRHOTIC 0x800000
|
||||
#define phNOPAUSE 0x1000000
|
||||
#define phLOCAL 0x80000000 // used during compilation
|
||||
|
||||
// fixed phoneme code numbers, these can be used from the program code
|
||||
|
||||
+20
-11
@@ -193,7 +193,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
|
||||
if((type==phSTOP) || type==(phFRICATIVE))
|
||||
{
|
||||
if(voicing==0)
|
||||
if((voicing==0) && (regression & 0xf))
|
||||
{
|
||||
voicing = 1;
|
||||
}
|
||||
@@ -206,7 +206,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
else
|
||||
if((type==phVSTOP) || type==(phVFRICATIVE))
|
||||
{
|
||||
if(voicing==0)
|
||||
if((voicing==0) && (regression & 0xf))
|
||||
{
|
||||
voicing = 2;
|
||||
}
|
||||
@@ -229,10 +229,19 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
voicing = 0;
|
||||
}
|
||||
}
|
||||
if((regression & 0x4) && (plist2[j].sourceix))
|
||||
if(plist2[j].sourceix)
|
||||
{
|
||||
// stop propagation at a word boundary
|
||||
voicing = 0;
|
||||
if(regression & 0x04)
|
||||
{
|
||||
// stop propagation at a word boundary
|
||||
voicing = 0;
|
||||
}
|
||||
if(regression & 0x10)
|
||||
{
|
||||
// devoice word-final consonants, unless propagating voiced
|
||||
if(voicing == 0)
|
||||
voicing = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -312,10 +321,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
|
||||
InterpretPhoneme(tr, 0x100, plist3, &phdata);
|
||||
|
||||
if((alternative = phdata.pd_param[pd_CHANGEPHONEME]) == 1)
|
||||
continue; // NULL phoneme, discard
|
||||
|
||||
if(alternative > 1)
|
||||
if((alternative = phdata.pd_param[pd_CHANGEPHONEME]) > 0)
|
||||
{
|
||||
PHONEME_TAB *ph2;
|
||||
ph2 = ph;
|
||||
@@ -323,6 +329,9 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
plist3->phcode = alternative;
|
||||
plist3->ph = ph;
|
||||
|
||||
if(alternative == 1)
|
||||
continue; // NULL phoneme, discard
|
||||
|
||||
if(ph->type == phVOWEL)
|
||||
{
|
||||
plist3->synthflags |= SFLAG_SYLLABLE;
|
||||
@@ -553,8 +562,8 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
|
||||
phlist[ix].prepause = 0;
|
||||
phlist[ix].amp = 20; // default, will be changed later
|
||||
phlist[ix].pitch1 = 0x400;
|
||||
phlist[ix].pitch2 = 0x400;
|
||||
phlist[ix].pitch1 = 255;
|
||||
phlist[ix].pitch2 = 255;
|
||||
ix++;
|
||||
}
|
||||
phlist[ix].newword = 2; // end of clause
|
||||
|
||||
+16
-13
@@ -56,7 +56,7 @@ ProsodyDisplay::ProsodyDisplay(wxWindow *parent, const wxPoint& pos, const wxSiz
|
||||
|
||||
linewidth = size.GetWidth();
|
||||
scalex = 0.5;
|
||||
scaley = double(LINESEP*6)/80.0;
|
||||
scaley = double(LINESEP*6)/160.0;
|
||||
selected_ph = -1;
|
||||
// SetBackgroundColour(* wxWHITE);
|
||||
|
||||
@@ -77,18 +77,18 @@ void InitProsodyDisplay()
|
||||
menu_envelopes = new wxMenu;
|
||||
// entries match those in envelope_data[] in intonation.cpp
|
||||
menu_envelopes->Append(0x100,_T("Fall"));
|
||||
menu_envelopes->Append(0x101,_T("Rise"));
|
||||
menu_envelopes->Append(0x102,_T("Fall-rise"));
|
||||
menu_envelopes->Append(0x103,_T("Fall-rise (R)"));
|
||||
menu_envelopes->Append(0x104,_T("Fall-rise 2"));
|
||||
menu_envelopes->Append(0x105,_T("Fall-rise 2(R)"));
|
||||
menu_envelopes->Append(0x106,_T("Rise-fall"));
|
||||
menu_envelopes->Append(0x102,_T("Rise"));
|
||||
menu_envelopes->Append(0x104,_T("Fall-rise"));
|
||||
menu_envelopes->Append(0x105,_T("Fall-rise (R)"));
|
||||
menu_envelopes->Append(0x106,_T("Fall-rise 2"));
|
||||
menu_envelopes->Append(0x107,_T("Fall-rise 2(R)"));
|
||||
menu_envelopes->Append(0x108,_T("Rise-fall"));
|
||||
|
||||
menu_envelopes->Append(0x108,_T("Fall-rise 3"));
|
||||
menu_envelopes->Append(0x10a,_T("Fall-rise 4"));
|
||||
menu_envelopes->Append(0x10c,_T("Fall 2"));
|
||||
menu_envelopes->Append(0x10e,_T("Rise 2"));
|
||||
menu_envelopes->Append(0x110,_T("Rise-fall-rise"));
|
||||
menu_envelopes->Append(0x10a,_T("Fall-rise 3"));
|
||||
menu_envelopes->Append(0x10c,_T("Fall-rise 4"));
|
||||
menu_envelopes->Append(0x10e,_T("Fall 2"));
|
||||
menu_envelopes->Append(0x110,_T("Rise 2"));
|
||||
menu_envelopes->Append(0x112,_T("Rise-fall-rise"));
|
||||
|
||||
menu_prosody = new wxMenu;
|
||||
menu_prosody->Append(1,_T("Pitch envelope"),menu_envelopes);
|
||||
@@ -129,6 +129,7 @@ void ProsodyDisplay::SelectPh(int index)
|
||||
// A phoneme has been selected
|
||||
PHONEME_LIST *p;
|
||||
const char *emphasized;
|
||||
int y1, y2;
|
||||
char buf[120];
|
||||
|
||||
if(index < 0) return;
|
||||
@@ -140,8 +141,10 @@ void ProsodyDisplay::SelectPh(int index)
|
||||
if(p->stresslevel & 8)
|
||||
emphasized = "*";
|
||||
|
||||
y1 = p->pitch1;
|
||||
y2 = p->pitch2;
|
||||
sprintf(buf,"Stress %s%d Amp %2d LenMod %2d Pitch %3d %3d [env=%d] Flags %.2x ",
|
||||
emphasized,p->stresslevel&0x7,p->amp,p->length,p->pitch1,p->pitch2,p->env,p->ph->phflags);
|
||||
emphasized,p->stresslevel&0x7,p->amp,p->length,y1,y2,p->env,p->ph->phflags);
|
||||
wxLogStatus(wxString(buf,wxConvLocal));
|
||||
}
|
||||
|
||||
|
||||
+14
-12
@@ -67,8 +67,6 @@ static int ssml_ignore_l_angle = 0;
|
||||
// alter tone for announce punctuation or capitals
|
||||
//static const char *tone_punct_on = "\0016T"; // add reverberation, lower pitch
|
||||
//static const char *tone_punct_off = "\001T\001P";
|
||||
static const char *tone_punct_on = ""; // add reverberation, lower pitch TEST apply no effect
|
||||
static const char *tone_punct_off = "";
|
||||
|
||||
// ignore these characters
|
||||
static const unsigned short chars_ignore[] = {
|
||||
@@ -122,7 +120,7 @@ static const unsigned int punct_attributes [] = { 0,
|
||||
CLAUSE_COMMA, CLAUSE_PERIOD, CLAUSE_QUESTION, CLAUSE_EXCLAMATION, CLAUSE_COLON, CLAUSE_SEMICOLON,
|
||||
CLAUSE_SEMICOLON, // en-dash
|
||||
CLAUSE_SEMICOLON, // em-dash
|
||||
CLAUSE_SEMICOLON + PUNCT_SAY_NAME, // elipsis
|
||||
CLAUSE_SEMICOLON + PUNCT_SAY_NAME | 0x8000, // elipsis
|
||||
|
||||
CLAUSE_QUESTION, // Greek question mark
|
||||
CLAUSE_SEMICOLON, // Greek semicolon
|
||||
@@ -887,24 +885,25 @@ static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output
|
||||
|
||||
if(punct_count==1)
|
||||
{
|
||||
sprintf(buf,"%s %s %s",tone_punct_on,punctname,tone_punct_off);
|
||||
// sprintf(buf,"%s %s %s",tone_punct_on,punctname,tone_punct_off);
|
||||
sprintf(buf,"%s",punctname);
|
||||
}
|
||||
else
|
||||
if(punct_count < 4)
|
||||
{
|
||||
sprintf(buf,"\001+10S%s",tone_punct_on);
|
||||
sprintf(buf,"\001+10S");
|
||||
while(punct_count-- > 0)
|
||||
{
|
||||
sprintf(buf2," %s",punctname);
|
||||
strcat(buf, buf2);
|
||||
}
|
||||
sprintf(buf2," %s\001-10S",tone_punct_off);
|
||||
sprintf(buf2," \001-10S");
|
||||
strcat(buf, buf2);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buf,"%s %s %d %s %s",
|
||||
tone_punct_on,punctname,punct_count,punctname,tone_punct_off);
|
||||
sprintf(buf,"%s %d %s",
|
||||
punctname,punct_count,punctname);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1082,7 +1081,7 @@ static void ProcessParamStack(char *outbuf, int &outix)
|
||||
int value;
|
||||
char buf[20];
|
||||
int new_parameters[N_SPEECH_PARAM];
|
||||
static char cmd_letter[N_SPEECH_PARAM] = {0, 'S','A','P','R', 0, 0, 0, 0, 0, 0, 0, 'F'}; // embedded command letters
|
||||
static char cmd_letter[N_SPEECH_PARAM] = {0, 'S','A','P','R', 0, 'C', 0, 0, 0, 0, 0, 'F'}; // embedded command letters
|
||||
|
||||
|
||||
for(param=0; param<N_SPEECH_PARAM; param++)
|
||||
@@ -2027,7 +2026,8 @@ int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int *charix
|
||||
int self_closing;
|
||||
int punct_data = 0;
|
||||
int is_end_clause;
|
||||
int announced_punctuation;
|
||||
int announced_punctuation = 0;
|
||||
int prev_announced_punctuation;
|
||||
int stressed_word = 0;
|
||||
int end_clause_after_tag = 0;
|
||||
int end_clause_index = 0;
|
||||
@@ -2354,7 +2354,7 @@ f_input = f_in; // for GetC etc
|
||||
char text_buf2[30];
|
||||
if(LookupSpecial(tr, "_cap", text_buf2) != NULL)
|
||||
{
|
||||
sprintf(text_buf,"%s%s%s",tone_punct_on,text_buf2,tone_punct_off);
|
||||
sprintf(text_buf,"%s",text_buf2);
|
||||
j = strlen(text_buf);
|
||||
if((ix + j) < n_buf)
|
||||
{
|
||||
@@ -2419,6 +2419,7 @@ if(option_ssml) parag=1;
|
||||
linelength = 0;
|
||||
}
|
||||
|
||||
prev_announced_punctuation = announced_punctuation;
|
||||
announced_punctuation = 0;
|
||||
|
||||
if((phoneme_mode==0) && (sayas_mode==0))
|
||||
@@ -2473,7 +2474,8 @@ if(option_ssml) parag=1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if((iswspace(c2) || (punct_data & 0x8000) || IsBracket(c2) || (c2=='?') || (c2=='-') || Eof()))
|
||||
if((iswspace(c2) || (punct_data & 0x8000) || IsBracket(c2) || (c2=='?') || Eof())) // don't check for '-' because if prevent recognizing ':-)'
|
||||
// if((iswspace(c2) || (punct_data & 0x8000) || IsBracket(c2) || (c2=='?') || (c2=='-') || Eof()))
|
||||
{
|
||||
// note: (c2='?') is for when a smart-quote has been replaced by '?'
|
||||
is_end_clause = 1;
|
||||
|
||||
+45
-40
@@ -295,6 +295,7 @@ void CalcLengths(Translator *tr)
|
||||
int end_of_clause;
|
||||
int embedded_ix = 0;
|
||||
int min_drop;
|
||||
int pitch1;
|
||||
int emphasized;
|
||||
int tone_mod;
|
||||
unsigned char *pitch_env=NULL;
|
||||
@@ -418,7 +419,10 @@ void CalcLengths(Translator *tr)
|
||||
if(prev->type==phLIQUID)
|
||||
p->prepause = 25;
|
||||
if(prev->type==phVOWEL)
|
||||
p->prepause = 12;
|
||||
{
|
||||
if(!(p->ph->phflags & phNOPAUSE))
|
||||
p->prepause = 12;
|
||||
}
|
||||
}
|
||||
|
||||
if(next->type==phVOWEL)
|
||||
@@ -426,43 +430,44 @@ void CalcLengths(Translator *tr)
|
||||
pre_sonorant = 1;
|
||||
}
|
||||
else
|
||||
if((prev->type==phVOWEL) || (prev->type == phLIQUID))
|
||||
{
|
||||
p->length = prev->length;
|
||||
p->pitch2 = last_pitch;
|
||||
if(p->pitch2 < 7)
|
||||
p->pitch2 = 7;
|
||||
p->pitch1 = p->pitch2 - 8;
|
||||
p->env = PITCHfall;
|
||||
pre_voiced = 0;
|
||||
|
||||
if(p->type == phLIQUID)
|
||||
{
|
||||
p->length = speed1;
|
||||
//p->pitch1 = p->pitch2 - 20; // post vocalic [r/]
|
||||
}
|
||||
|
||||
if(next->type == phVSTOP)
|
||||
if((prev->type==phVOWEL) || (prev->type == phLIQUID))
|
||||
{
|
||||
p->length = (p->length * 160)/100;
|
||||
}
|
||||
if(next->type == phVFRICATIVE)
|
||||
{
|
||||
p->length = (p->length * 120)/100;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->pitch2 = last_pitch;
|
||||
for(ix2=ix; ix2<n_phoneme_list; ix2++)
|
||||
{
|
||||
if(phoneme_list[ix2].type == phVOWEL)
|
||||
p->length = prev->length;
|
||||
|
||||
if(p->type == phLIQUID)
|
||||
{
|
||||
p->pitch2 = phoneme_list[ix2].pitch2;
|
||||
break;
|
||||
p->length = speed1;
|
||||
}
|
||||
|
||||
if(next->type == phVSTOP)
|
||||
{
|
||||
p->length = (p->length * 160)/100;
|
||||
}
|
||||
if(next->type == phVFRICATIVE)
|
||||
{
|
||||
p->length = (p->length * 120)/100;
|
||||
}
|
||||
}
|
||||
p->pitch1 = p->pitch2-8;
|
||||
else
|
||||
{
|
||||
for(ix2=ix; ix2<n_phoneme_list; ix2++)
|
||||
{
|
||||
if(phoneme_list[ix2].type == phVOWEL)
|
||||
{
|
||||
p->pitch2 = phoneme_list[ix2].pitch2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p->pitch1 = p->pitch2-16;
|
||||
if(p->pitch2 < 16)
|
||||
{
|
||||
p->pitch1 = 0;
|
||||
}
|
||||
p->env = PITCHfall;
|
||||
pre_voiced = 0;
|
||||
}
|
||||
@@ -602,14 +607,13 @@ if(stress <= 1)
|
||||
if(p->type != phVOWEL)
|
||||
{
|
||||
length_mod = 256; // syllabic consonant
|
||||
min_drop = 8;
|
||||
min_drop = 16;
|
||||
}
|
||||
p->length = length_mod;
|
||||
|
||||
// pre-vocalic part
|
||||
// set last-pitch
|
||||
env2 = p->env;
|
||||
if(env2 > 1) env2++; // version for use with preceding semi-vowel
|
||||
env2 = p->env + 1; // version for use with preceding semi-vowel
|
||||
|
||||
if(p->tone_ph != 0)
|
||||
{
|
||||
@@ -626,11 +630,11 @@ if(p->type != phVOWEL)
|
||||
if(pre_sonorant || pre_voiced)
|
||||
{
|
||||
// set pitch for pre-vocalic part
|
||||
if(pitch_start == 1024)
|
||||
if(pitch_start == 255)
|
||||
last_pitch = pitch_start; // pitch is not set
|
||||
|
||||
if(pitch_start - last_pitch > 8) // was 9
|
||||
last_pitch = pitch_start - 8;
|
||||
if(pitch_start - last_pitch > 16)
|
||||
last_pitch = pitch_start - 16;
|
||||
|
||||
prev->pitch1 = last_pitch;
|
||||
prev->pitch2 = pitch_start;
|
||||
@@ -677,9 +681,10 @@ if(p->type != phVOWEL)
|
||||
|
||||
if((min_drop > 0) && ((p->pitch2 - p->pitch1) < min_drop))
|
||||
{
|
||||
p->pitch1 = p->pitch2 - min_drop;
|
||||
if(p->pitch1 < 0)
|
||||
p->pitch1 = 0;
|
||||
pitch1 = p->pitch2 - min_drop;
|
||||
if(pitch1 < 0)
|
||||
pitch1 = 0;
|
||||
p->pitch1 = pitch1;
|
||||
}
|
||||
|
||||
last_pitch = p->pitch1 + ((p->pitch2-p->pitch1)*envelope_data[p->env][127])/256;
|
||||
|
||||
+2
-1
@@ -301,6 +301,7 @@ class FormantDlg : public wxPanel
|
||||
wxSpinCtrl *t_amplitude;
|
||||
wxSpinCtrl *t_ampframe;
|
||||
wxSpinCtrl *t_timeframe;
|
||||
wxTextCtrl *tt_timeframe;
|
||||
wxSpinCtrl *t_timeseq;
|
||||
wxStaticText *t_pitch;
|
||||
wxStaticText *t_orig_frame;
|
||||
@@ -394,4 +395,4 @@ extern void SetSpinCtrl(wxSpinCtrl *t, int value);
|
||||
extern int GetNumeric(wxTextCtrl *t);
|
||||
extern void SetNumeric(wxTextCtrl *t, int value);
|
||||
|
||||
|
||||
extern int use_spin_controls;
|
||||
|
||||
@@ -246,6 +246,7 @@ void SpectDisplay::RefreshDialogValues(int type)
|
||||
//{=============================================
|
||||
{
|
||||
int ix;
|
||||
long int value;
|
||||
SpectFrame *sf;
|
||||
|
||||
if(spectseq == NULL)
|
||||
@@ -255,7 +256,13 @@ void SpectDisplay::RefreshDialogValues(int type)
|
||||
|
||||
spectseq->amplitude = formantdlg->t_amplitude->GetValue();
|
||||
sf->amp_adjust = formantdlg->t_ampframe->GetValue();
|
||||
sf->length_adjust = formantdlg->t_timeframe->GetValue() - spectseq->GetFrameLength(sframe,0,NULL);
|
||||
|
||||
if(use_spin_controls)
|
||||
value = formantdlg->t_timeframe->GetValue();
|
||||
else
|
||||
formantdlg->tt_timeframe->GetValue().ToLong(&value);
|
||||
|
||||
sf->length_adjust = value - spectseq->GetFrameLength(sframe,0,NULL);
|
||||
|
||||
for(ix=0; ix < N_KLATTP; ix++)
|
||||
{
|
||||
@@ -268,7 +275,7 @@ void SpectDisplay::RefreshDialogValues(int type)
|
||||
Refresh();
|
||||
}
|
||||
else
|
||||
RefreshFrame(sframe);
|
||||
RefreshFrame(sframe); // frame amplitude
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ typedef struct {
|
||||
const char *mnem;
|
||||
int value;
|
||||
} MNEM_TAB;
|
||||
int LookupMnem(MNEM_TAB *table, char *string);
|
||||
int LookupMnem(MNEM_TAB *table, const char *string);
|
||||
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
|
||||
+23
-8
@@ -35,8 +35,8 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.43.14 29.Mar.10";
|
||||
const int version_phdata = 0x014300;
|
||||
const char *version_string = "1.43.31 21.May.10";
|
||||
const int version_phdata = 0x014317;
|
||||
|
||||
int option_device_number = -1;
|
||||
FILE *f_logespeak = NULL;
|
||||
@@ -71,8 +71,8 @@ int FormantTransition2(frameref_t *seq, int &n_frames, unsigned int data1, unsig
|
||||
|
||||
|
||||
|
||||
static char *ReadPhFile(void *ptr, const char *fname)
|
||||
{//==================================================
|
||||
static char *ReadPhFile(void *ptr, const char *fname, int *size)
|
||||
{//=============================================================
|
||||
FILE *f_in;
|
||||
char *p;
|
||||
unsigned int length;
|
||||
@@ -102,6 +102,8 @@ static char *ReadPhFile(void *ptr, const char *fname)
|
||||
}
|
||||
|
||||
fclose(f_in);
|
||||
if(size != NULL)
|
||||
*size = length;
|
||||
return(p);
|
||||
} // end of ReadPhFile
|
||||
|
||||
@@ -112,15 +114,19 @@ int LoadPhData()
|
||||
int n_phonemes;
|
||||
int version;
|
||||
int result = 1;
|
||||
int length;
|
||||
unsigned char *p;
|
||||
|
||||
if((phoneme_tab_data = (unsigned char *)ReadPhFile((void *)(phoneme_tab_data),"phontab")) == NULL)
|
||||
if((phoneme_tab_data = (unsigned char *)ReadPhFile((void *)(phoneme_tab_data),"phontab",NULL)) == NULL)
|
||||
return(-1);
|
||||
if((phoneme_index = (USHORT *)ReadPhFile((void *)(phoneme_index),"phonindex")) == NULL)
|
||||
if((phoneme_index = (USHORT *)ReadPhFile((void *)(phoneme_index),"phonindex",NULL)) == NULL)
|
||||
return(-1);
|
||||
if((spects_data = ReadPhFile((void *)(spects_data),"phondata")) == NULL)
|
||||
if((spects_data = ReadPhFile((void *)(spects_data),"phondata",NULL)) == NULL)
|
||||
return(-1);
|
||||
if((tunes = (TUNE *)ReadPhFile((void *)(tunes),"intonations",&length)) == NULL)
|
||||
return(-1);
|
||||
wavefile_data = (unsigned char *)spects_data;
|
||||
n_tunes = length / sizeof(TUNE);
|
||||
|
||||
// read the version number from the first 4 bytes of phondata
|
||||
version = 0;
|
||||
@@ -583,7 +589,7 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist,
|
||||
int instn2;
|
||||
PHONEME_TAB *ph;
|
||||
PHONEME_LIST *plist_this;
|
||||
static int ph_position[7] = {0, 1, 2, 3, 2, 0, 1};
|
||||
static int ph_position[7] = {0, 1, 2, 3, 2, 0, 1}; // prevPh, thisPh, nextPh, next2Ph, nextPhW, prevPhW, nextVowel
|
||||
|
||||
data = instn & 0xff;
|
||||
instn2 = instn >> 8;
|
||||
@@ -622,6 +628,15 @@ static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist,
|
||||
plist_this = plist;
|
||||
plist = &plist[which-1];
|
||||
|
||||
if(which == 0)
|
||||
{
|
||||
if(plist->phcode == 1)
|
||||
{
|
||||
// This is a NULL phoneme, a phoneme has been deleted so look at the previous phoneme
|
||||
plist = &plist[-1];
|
||||
}
|
||||
}
|
||||
|
||||
if(control & 0x100)
|
||||
{
|
||||
// change phonemes pass
|
||||
|
||||
+10
-4
@@ -162,11 +162,11 @@ static void DoPitch(unsigned char *env, int pitch1, int pitch2)
|
||||
|
||||
EndPitch(0);
|
||||
|
||||
if(pitch1 == 1024)
|
||||
if(pitch1 == 255)
|
||||
{
|
||||
// pitch was not set
|
||||
pitch1 = 24;
|
||||
pitch2 = 33;
|
||||
pitch1 = 55;
|
||||
pitch2 = 76;
|
||||
env = envelope_data[PITCHfall];
|
||||
}
|
||||
last_pitch_cmd = wcmdq_tail;
|
||||
@@ -1308,8 +1308,14 @@ int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
|
||||
if(p->newword)
|
||||
{
|
||||
if(translator->langopts.param[LOPT_WORD_MERGE] == 0)
|
||||
if(((p->type == phVOWEL) && (translator->langopts.param[LOPT_WORD_MERGE] & 1)) ||
|
||||
(p->ph->phflags & phNOPAUSE))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
last_frame = NULL;
|
||||
}
|
||||
|
||||
sourceix = (p->sourceix & 0x7ff) + clause_start_char;
|
||||
|
||||
|
||||
+50
-6
@@ -25,7 +25,7 @@
|
||||
#define STEPSIZE 64 // 2.9mS at 22 kHz sample rate
|
||||
|
||||
#define PITCHfall 0
|
||||
#define PITCHrise 1
|
||||
#define PITCHrise 2
|
||||
|
||||
// flags set for frames within a spectrum sequence
|
||||
#define FRFLAG_KLATT 0x01 // this frame includes extra data for Klatt synthesizer
|
||||
@@ -64,8 +64,9 @@
|
||||
#define EMBED_U 11 // audio uri
|
||||
#define EMBED_B 12 // break
|
||||
#define EMBED_F 13 // emphasis
|
||||
#define EMBED_C 14 // capital letter indication
|
||||
|
||||
#define N_EMBEDDED_VALUES 14
|
||||
#define N_EMBEDDED_VALUES 15
|
||||
extern int embedded_value[N_EMBEDDED_VALUES];
|
||||
extern int embedded_default[N_EMBEDDED_VALUES];
|
||||
|
||||
@@ -232,15 +233,15 @@ typedef struct {
|
||||
unsigned short sourceix; // ix into the original source text string, only set at the start of a word
|
||||
|
||||
PHONEME_TAB *ph;
|
||||
short length; // length_mod
|
||||
unsigned char env; // pitch envelope number
|
||||
unsigned char type;
|
||||
unsigned char prepause;
|
||||
unsigned char postpause;
|
||||
unsigned char amp;
|
||||
unsigned char newword; // bit 0=start of word, bit 1=end of clause, bit 2=start of sentence
|
||||
short length; // length_mod
|
||||
short pitch1; // pitch, 0-4095 within the Voice's pitch range
|
||||
short pitch2;
|
||||
unsigned char pitch1;
|
||||
unsigned char pitch2;
|
||||
} PHONEME_LIST;
|
||||
|
||||
|
||||
@@ -379,6 +380,49 @@ typedef struct {
|
||||
} SPEED_FACTORS;
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned int name;
|
||||
unsigned char flags[4];
|
||||
signed char headextend[8];
|
||||
|
||||
unsigned char prehead_start;
|
||||
unsigned char prehead_end;
|
||||
unsigned char onset;
|
||||
unsigned char head_start;
|
||||
unsigned char head_end;
|
||||
unsigned char head_last;
|
||||
|
||||
unsigned char stressed_env;
|
||||
unsigned char head_drops;
|
||||
unsigned char head_max_steps;
|
||||
unsigned char n_headextend;
|
||||
|
||||
char unstressed_start;
|
||||
char unstressed_end;
|
||||
char unstressed_shape;
|
||||
|
||||
unsigned char nucleus0_env; // pitch envelope, tonic syllable is at end, no tail
|
||||
unsigned char nucleus0_max;
|
||||
unsigned char nucleus0_min;
|
||||
|
||||
unsigned char nucleus1_env; // when followed by a tail
|
||||
unsigned char nucleus1_max;
|
||||
unsigned char nucleus1_min;
|
||||
unsigned char tail_start;
|
||||
unsigned char tail_end;
|
||||
|
||||
unsigned char split_nucleus_env;
|
||||
unsigned char split_nucleus_max;
|
||||
unsigned char split_nucleus_min;
|
||||
unsigned char split_tail_start;
|
||||
unsigned char split_tail_end;
|
||||
|
||||
unsigned char spare[10];
|
||||
} TUNE;
|
||||
|
||||
extern int n_tunes;
|
||||
extern TUNE *tunes;
|
||||
|
||||
// phoneme table
|
||||
extern PHONEME_TAB *phoneme_tab[N_PHONEME_TAB];
|
||||
|
||||
@@ -467,7 +511,7 @@ int Read4Bytes(FILE *f);
|
||||
int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name,int flags);
|
||||
|
||||
|
||||
extern unsigned char *envelope_data[18];
|
||||
extern unsigned char *envelope_data[20];
|
||||
extern int formant_rate[]; // max rate of change of each formant
|
||||
extern SPEED_FACTORS speed;
|
||||
|
||||
|
||||
+62
-27
@@ -39,7 +39,8 @@
|
||||
#define L_qa 0x716100
|
||||
#define L_grc 0x677263 // grc Ancient Greek
|
||||
#define L_jbo 0x6a626f // jbo Lojban
|
||||
#define L_pap 0x706170 // pap Papiamento
|
||||
#define L_pap 0x706170 // pap Papiamento]
|
||||
#define L_shs 0x736873 // shs Shuswap / Secwepemctsin
|
||||
#define L_zhy 0x7a6879 // zhy
|
||||
|
||||
// start of unicode pages for character sets
|
||||
@@ -57,6 +58,10 @@
|
||||
|
||||
static void Translator_Russian(Translator *tr);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void SetLetterVowel(Translator *tr, int c)
|
||||
{//==============================================
|
||||
tr->letter_bits[c] = (tr->letter_bits[c] & 0x40) | 0x81; // keep value for group 6 (front vowels e,i,y)
|
||||
@@ -216,6 +221,33 @@ static const unsigned int replace_cyrillic_latin[] =
|
||||
0x45c,0x107,
|
||||
0}; // ѓ ѕ ќ
|
||||
|
||||
static void SetCyrillicLetters(Translator *tr)
|
||||
{//===========================================
|
||||
// character codes offset by 0x420
|
||||
static const char ru_vowels[] = {0x10,0x15,0x31,0x18,0x1e,0x23,0x2b,0x2d,0x2e,0x2f,0};
|
||||
static const char ru_consonants[] = {0x11,0x12,0x13,0x14,0x16,0x17,0x19,0x1a,0x1b,0x1c,0x1d,0x1f,0x20,0x21,0x22,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2c,0};
|
||||
static const char ru_soft[] = {0x2c,0x19,0x27,0x29,0}; // letter group B [k ts; s;]
|
||||
static const char ru_hard[] = {0x2a,0x16,0x26,0x28,0}; // letter group H [S Z ts]
|
||||
static const char ru_nothard[] = {0x11,0x12,0x13,0x14,0x17,0x19,0x1a,0x1b,0x1c,0x1d,0x1f,0x20,0x21,0x22,0x24,0x25,0x27,0x29,0x2c,0};
|
||||
static const char ru_voiced[] = {0x11,0x12,0x13,0x14,0x16,0x17,0}; // letter group G (voiced obstruents)
|
||||
static const char ru_ivowels[] = {0x2c,0x2e,0x2f,0x31,0}; // letter group Y (iotated vowels & soft-sign)
|
||||
tr->charset_a0 = charsets[18]; // KOI8-R
|
||||
tr->transpose_offset = 0x42f; // convert cyrillic from unicode into range 0x01 to 0x22
|
||||
tr->transpose_min = 0x430;
|
||||
tr->transpose_max = 0x451;
|
||||
|
||||
tr->letter_bits_offset = OFFSET_CYRILLIC;
|
||||
memset(tr->letter_bits,0,sizeof(tr->letter_bits));
|
||||
SetLetterBits(tr,0,ru_vowels);
|
||||
SetLetterBits(tr,1,ru_soft);
|
||||
SetLetterBits(tr,2,ru_consonants);
|
||||
SetLetterBits(tr,3,ru_hard);
|
||||
SetLetterBits(tr,4,ru_nothard);
|
||||
SetLetterBits(tr,5,ru_voiced);
|
||||
SetLetterBits(tr,6,ru_ivowels);
|
||||
SetLetterBits(tr,7,ru_vowels);
|
||||
} // end of SetCyrillicLetters
|
||||
|
||||
|
||||
void SetIndicLetters(Translator *tr)
|
||||
{//=================================
|
||||
@@ -238,6 +270,7 @@ void SetIndicLetters(Translator *tr)
|
||||
tr->langopts.suffix_add_e = tr->letter_bits_offset + 0x4d; //virama
|
||||
}
|
||||
|
||||
|
||||
void SetupTranslator(Translator *tr, const short *lengths, const unsigned char *amps)
|
||||
{//==================================================================================
|
||||
if(lengths != NULL)
|
||||
@@ -284,6 +317,19 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
|
||||
break;
|
||||
|
||||
case L('b','g'): //Bulgarian
|
||||
{
|
||||
SetCyrillicLetters(tr);
|
||||
SetLetterVowel(tr,0x2a);
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 0x432; // [v] don't count this character at start of word
|
||||
tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x10;
|
||||
tr->langopts.param[LOPT_REDUCE] = 2;
|
||||
tr->langopts.stress_rule = STRESSPOSN_2R;
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_OMIT_1_HUNDRED | NUM_HUNDRED_AND | NUM_AND_UNITS | NUM_SINGLE_AND | NUM_ROMAN | NUM_ROMAN_ORDINAL | NUM_ROMAN_CAPITALS ;
|
||||
tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator
|
||||
}
|
||||
break;
|
||||
|
||||
case L('b','n'): // Bengali
|
||||
{
|
||||
static const short stress_lengths_bn[8] = {180, 180, 210, 210, 0, 0, 230, 240};
|
||||
@@ -601,6 +647,7 @@ Translator *SelectTranslator(const char *name)
|
||||
tr->langopts.numbers = NUM_DFRACTION_5 | NUM_ALLOW_SPACE | NUM_ROMAN | NUM_ROMAN_ORDINAL | NUM_ROMAN_CAPITALS | NUM_ORDINAL_DOT | NUM_OMIT_1_HUNDRED;
|
||||
tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator
|
||||
tr->langopts.decimal_sep = ',';
|
||||
tr->langopts.max_roman = 899;
|
||||
tr->langopts.min_roman = 1;
|
||||
SetLetterVowel(tr,'y');
|
||||
tr->langopts.spelling_stress = 1;
|
||||
@@ -917,6 +964,16 @@ SetLengthMods(tr,3); // all equal
|
||||
}
|
||||
break;
|
||||
|
||||
case L('s','l'): // Slovenian
|
||||
tr->charset_a0 = charsets[2]; // ISO-8859-2
|
||||
tr->langopts.stress_rule = STRESSPOSN_2R; // Temporary
|
||||
tr->langopts.stress_flags = 0x20;
|
||||
tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 0x13;
|
||||
tr->langopts.numbers = NUM_DECIMAL_COMMA | NUM_ALLOW_SPACE | NUM_SWAP_TENS | NUM_OMIT_1_HUNDRED | NUM_DFRACTION_2 | NUM_ORDINAL_DOT | NUM_ROMAN;
|
||||
tr->langopts.thousands_sep = ' '; // don't allow dot as thousands separator
|
||||
SetLetterVowel(tr,'r');
|
||||
break;
|
||||
|
||||
case L('s','q'): // Albanian
|
||||
{
|
||||
static const short stress_lengths_sq[8] = {150, 150, 180, 180, 0, 0, 300, 300};
|
||||
@@ -1127,38 +1184,16 @@ SetLengthMods(tr,3); // all equal
|
||||
|
||||
|
||||
|
||||
|
||||
static void Translator_Russian(Translator *tr)
|
||||
{//===========================================
|
||||
static const unsigned char stress_amps_ru[] = {16,16, 18,18, 20,24, 24,22 };
|
||||
static const short stress_lengths_ru[8] = {150,140, 220,220, 0,0, 260,280};
|
||||
|
||||
|
||||
// character codes offset by 0x420
|
||||
static const char ru_vowels[] = {0x10,0x15,0x31,0x18,0x1e,0x23,0x2b,0x2d,0x2e,0x2f,0};
|
||||
static const char ru_consonants[] = {0x11,0x12,0x13,0x14,0x16,0x17,0x19,0x1a,0x1b,0x1c,0x1d,0x1f,0x20,0x21,0x22,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2c,0};
|
||||
static const char ru_soft[] = {0x2c,0x19,0x27,0x29,0}; // letter group B [k ts; s;]
|
||||
static const char ru_hard[] = {0x2a,0x16,0x26,0x28,0}; // letter group H [S Z ts]
|
||||
static const char ru_nothard[] = {0x11,0x12,0x13,0x14,0x17,0x19,0x1a,0x1b,0x1c,0x1d,0x1f,0x20,0x21,0x22,0x24,0x25,0x27,0x29,0x2c,0};
|
||||
static const char ru_voiced[] = {0x11,0x12,0x13,0x14,0x16,0x17,0}; // letter group G (voiced obstruents)
|
||||
static const char ru_ivowels[] = {0x2c,0x15,0x31,0x18,0x2e,0x2f,0}; // letter group Y (iotated vowels & soft-sign)
|
||||
static const char ru_ivowels2[] = {0x2c,0x15,0x18,0x2e,0x2f,0}; // add more vowels to letter group Y (iotated vowels & soft-sign)
|
||||
|
||||
SetupTranslator(tr,stress_lengths_ru,stress_amps_ru);
|
||||
|
||||
tr->charset_a0 = charsets[18]; // KOI8-R
|
||||
tr->transpose_offset = 0x42f; // convert cyrillic from unicode into range 0x01 to 0x22
|
||||
tr->transpose_min = 0x430;
|
||||
tr->transpose_max = 0x451;
|
||||
|
||||
tr->letter_bits_offset = OFFSET_CYRILLIC;
|
||||
memset(tr->letter_bits,0,sizeof(tr->letter_bits));
|
||||
SetLetterBits(tr,0,ru_vowels);
|
||||
SetLetterBits(tr,1,ru_soft);
|
||||
SetLetterBits(tr,2,ru_consonants);
|
||||
SetLetterBits(tr,3,ru_hard);
|
||||
SetLetterBits(tr,4,ru_nothard);
|
||||
SetLetterBits(tr,5,ru_voiced);
|
||||
SetLetterBits(tr,6,ru_ivowels);
|
||||
SetLetterBits(tr,7,ru_vowels);
|
||||
SetCyrillicLetters(tr);
|
||||
SetLetterBits(tr,6,ru_ivowels2);
|
||||
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 0x432; // [v] don't count this character at start of word
|
||||
tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 1;
|
||||
|
||||
+30
-27
@@ -573,6 +573,26 @@ char *strchr_w(const char *s, int c)
|
||||
}
|
||||
|
||||
|
||||
static char *SpeakIndividualLetters(Translator *tr, char *word, char *phonemes, int spell_word)
|
||||
{//============================================================================================
|
||||
int posn = 0;
|
||||
|
||||
while((*word != ' ') && (*word != 0))
|
||||
{
|
||||
word += TranslateLetter(tr, word, phonemes, spell_word);
|
||||
posn++;
|
||||
if(phonemes[0] == phonSWITCH)
|
||||
{
|
||||
// change to another language in order to translate this word
|
||||
strcpy(word_phonemes,phonemes);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
SetSpellingStress(tr,phonemes,spell_word,posn);
|
||||
return(word);
|
||||
} // end of SpeakIndividualLetters
|
||||
|
||||
|
||||
|
||||
int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab)
|
||||
{//===========================================================================
|
||||
@@ -747,7 +767,7 @@ if((wmark > 0) && (wmark < 8))
|
||||
if(word_phonemes[0] == phonSWITCH)
|
||||
return(0);
|
||||
|
||||
found = TranslateNumber(tr,word1,phonemes,dictionary_flags,wtab);
|
||||
found = TranslateNumber(tr, word1, phonemes, dictionary_flags, wtab, 0);
|
||||
}
|
||||
|
||||
if(!found & ((wflags & FLAG_UPPERS) != FLAG_FIRST_UPPER))
|
||||
@@ -781,25 +801,15 @@ if((wmark > 0) && (wmark < 8))
|
||||
if(spell_word > 0)
|
||||
{
|
||||
// Speak as individual letters
|
||||
wordx = word1;
|
||||
posn = 0;
|
||||
phonemes[0] = 0;
|
||||
end_type = 0;
|
||||
|
||||
while(*wordx != ' ')
|
||||
if(SpeakIndividualLetters(tr, word1, phonemes, spell_word) == NULL)
|
||||
{
|
||||
wordx += TranslateLetter(tr,wordx, phonemes, spell_word);
|
||||
posn++;
|
||||
if(phonemes[0] == phonSWITCH)
|
||||
{
|
||||
// change to another language in order to translate this word
|
||||
strcpy(word_phonemes,phonemes);
|
||||
if(word_length > 1)
|
||||
return(FLAG_SPELLWORD); // a mixture of languages, retranslate as individual letters, separated by spaces
|
||||
return(0);
|
||||
}
|
||||
if(word_length > 1)
|
||||
return(FLAG_SPELLWORD); // a mixture of languages, retranslate as individual letters, separated by spaces
|
||||
return(0);
|
||||
}
|
||||
SetSpellingStress(tr,phonemes,spell_word,posn);
|
||||
}
|
||||
else
|
||||
if(found == 0)
|
||||
@@ -870,19 +880,10 @@ if((wmark > 0) && (wmark < 8))
|
||||
utf8_in(&wc, wordx);
|
||||
if((word_length == 1) && IsAlpha(wc))
|
||||
{
|
||||
posn = 0;
|
||||
while((*wordx != ' ') && (*wordx != 0))
|
||||
if((wordx = SpeakIndividualLetters(tr, wordx, phonemes, spell_word)) == NULL)
|
||||
{
|
||||
wordx += TranslateLetter(tr,wordx, phonemes, 4);
|
||||
posn++;
|
||||
if(phonemes[0] == phonSWITCH)
|
||||
{
|
||||
// change to another language in order to translate this word
|
||||
strcpy(word_phonemes,phonemes);
|
||||
return(0);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
SetSpellingStress(tr,phonemes,spell_word,posn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2114,7 +2115,7 @@ void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *t
|
||||
charix[charix_top+3] = 0;
|
||||
|
||||
clause_pause = (terminator & 0xfff) * 10; // mS
|
||||
tone = (terminator >> 12) & 0xf;
|
||||
tone = (terminator >> 12) & 0x7;
|
||||
if(tone2 != 0)
|
||||
{
|
||||
// override the tone type
|
||||
@@ -2143,6 +2144,7 @@ void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *t
|
||||
{
|
||||
max_clause_pause = clause_pause;
|
||||
}
|
||||
tr->clause_terminator = terminator;
|
||||
|
||||
if(new_sentence)
|
||||
{
|
||||
@@ -2440,6 +2442,7 @@ if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(pre
|
||||
c = ' '; // lower case followed by upper case, treat as new word
|
||||
space_inserted = 1;
|
||||
prev_in_save = c;
|
||||
// next_word_flags |= FLAG_NOSPACE; // problem: prevents FLAG_HAS_DOT being set
|
||||
}
|
||||
else
|
||||
if((c != ' ') && iswupper(prev_in) && iswlower(next_in))
|
||||
|
||||
+11
-5
@@ -52,10 +52,11 @@
|
||||
#define FLAG_STEM 0x40000 // must have a suffix
|
||||
|
||||
#define FLAG_DOUBLING 0x80000 // doubles the following consonant
|
||||
#define BITNUM_FLAG_ALT 19 // bit number of FLAG_ALT_TRANS - 1
|
||||
#define FLAG_ALT_TRANS 0x100000 // language specific
|
||||
#define FLAG_ALT2_TRANS 0x200000 // language specific
|
||||
#define FLAG_COMBINE 0x400000 // combine with the next word
|
||||
#define FLAG_ALT3_TRANS 0x800000 // language specific
|
||||
#define FLAG_ALT3_TRANS 0x400000 // language specific
|
||||
#define FLAG_COMBINE 0x800000 // 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
|
||||
@@ -81,6 +82,7 @@
|
||||
#define FLAG_ALLCAPS 0x400 // only if the word is all capitals
|
||||
#define FLAG_ACCENT 0x800 // character name is base-character name + accent name
|
||||
#define FLAG_HYPHENATED 0x1000 // multiple-words, but needs hyphen between parts 1 and 2
|
||||
#define FLAG_SENTENCE 0x2000 // only if the clause is a sentence
|
||||
#define BITNUM_FLAG_ALLCAPS 0x2a
|
||||
#define BITNUM_FLAG_HYPHENATED 0x2c
|
||||
|
||||
@@ -154,7 +156,7 @@
|
||||
#define RULE_NO_SUFFIX 24 // N
|
||||
#define RULE_NOTVOWEL 25 // K
|
||||
#define RULE_IFVERB 26 // V
|
||||
#define RULE_ALT1 28 // T word has $alt attribute
|
||||
#define RULE_DOLLAR 28 // $ commands
|
||||
#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
|
||||
@@ -257,6 +259,7 @@ extern const int param_defaults[N_SPEECH_PARAM];
|
||||
// bit 1=LANG=ru, don't propagate over [v]
|
||||
// bit 2=don't propagate acress word boundaries
|
||||
// bit 3=LANG=pl, propagate over liquids and nasals
|
||||
// bit 4=devoice word-final consonants
|
||||
#define LOPT_REGRESSIVE_VOICING 4
|
||||
|
||||
// 0=default, 1=no check, other allow this character as an extra initial letter (default is 's')
|
||||
@@ -268,7 +271,7 @@ extern const int param_defaults[N_SPEECH_PARAM];
|
||||
// increase this to prevent sonorants being shortened before shortened (eg. unstressed) vowels
|
||||
#define LOPT_SONORANT_MIN 7
|
||||
|
||||
// don't break vowels at word boundary
|
||||
// bit 0: don't break vowels at word boundary
|
||||
#define LOPT_WORD_MERGE 8
|
||||
|
||||
// max. amplitude for vowel at the end of a clause
|
||||
@@ -385,6 +388,7 @@ typedef struct {
|
||||
#define NUM_VIGESIMAL 0x400000
|
||||
#define NUM_ROMAN_ORDINAL 0x800000
|
||||
#define NUM_ROMAN_CAPITALS 0x1000000
|
||||
#define NUM_THOUSAND_AND 0x2000000
|
||||
|
||||
// bits0-1=which numbers routine to use.
|
||||
// bit2= thousands separator must be space
|
||||
@@ -408,6 +412,7 @@ typedef struct {
|
||||
// bit22= vigesimal number, if tens are not found
|
||||
// bit23=Roman numbers are ordinal numbers
|
||||
// bit24=Roman numbers must be capital letters
|
||||
// bit25='and' after thousands if there are no hundreds
|
||||
int numbers;
|
||||
|
||||
// bits 1-4 use variant form of numbers before thousands,millions,etc.
|
||||
@@ -526,6 +531,7 @@ struct Translator
|
||||
int prepause_timeout;
|
||||
int end_stressed_vowel; // word ends with stressed vowel
|
||||
int prev_dict_flags; // dictionary flags from previous word
|
||||
int clause_terminator;
|
||||
}; // end of class Translator
|
||||
|
||||
|
||||
@@ -608,7 +614,7 @@ 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 TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, WORD_TAB *wtab, int control);
|
||||
int TranslateRoman(Translator *tr, char *word, char *ph_out, WORD_TAB *wtab);
|
||||
|
||||
void ChangeWordStress(Translator *tr, char *word, int new_stress);
|
||||
|
||||
+4
-4
@@ -134,8 +134,8 @@ int wcmdq_head=0;
|
||||
int wcmdq_tail=0;
|
||||
|
||||
// pitch,speed,
|
||||
int embedded_default[N_EMBEDDED_VALUES] = {0,50,170,100,50, 0,0, 0,170,0,0,0,0,0};
|
||||
static int embedded_max[N_EMBEDDED_VALUES] = {0,0x7fff,600,300,99,99,99, 0,600,0,0,0,0,4};
|
||||
int embedded_default[N_EMBEDDED_VALUES] = {0,50,170,100,50, 0,0, 0,170,0,0,0,0,0,0};
|
||||
static int embedded_max[N_EMBEDDED_VALUES] = {0,0x7fff,600,300,99,99,99, 0,600,0,0,0,0,4,0};
|
||||
|
||||
#define N_CALLBACK_IX N_WAV_BUF-2 // adjust this delay to match display with the currently spoken word
|
||||
int current_source_index=0;
|
||||
@@ -1635,8 +1635,8 @@ void SetPitch2(voice_t *voice, int pitch1, int pitch2, int *pitch_base, int *pit
|
||||
// compensate for change in pitch when the range is narrowed or widened
|
||||
base -= (range - voice->pitch_range)*18;
|
||||
|
||||
*pitch_base = base + (pitch1 * range);
|
||||
*pitch_range = base + (pitch2 * range) - *pitch_base;
|
||||
*pitch_base = base + (pitch1 * range)/2;
|
||||
*pitch_range = base + (pitch2 * range)/2 - *pitch_base;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user