[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:
jonsd
2010-05-21 23:21:06 +00:00
parent 19b774ffc6
commit cec2c415da
113 changed files with 13695 additions and 5592 deletions
+280 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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");
}
}
}
+8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+9 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}