diff --git a/src/compiledict.cpp b/src/compiledict.cpp index 345aa331..90383868 100755 --- a/src/compiledict.cpp +++ b/src/compiledict.cpp @@ -40,7 +40,7 @@ int HashDictionary(const char *string); static FILE *f_log = NULL; extern char *dir_dictionary; -int linenum; +static int linenum; static int error_count; static int transpose_offset; // transpose character range for LookupDictList() static int transpose_min; @@ -48,9 +48,9 @@ static int transpose_max; static int text_mode = 0; static int debug_flag = 0; -int hash_counts[N_HASH_DICT]; -char *hash_chains[N_HASH_DICT]; -char letterGroupsDefined[N_LETTER_GROUPS]; +static int hash_counts[N_HASH_DICT]; +static char *hash_chains[N_HASH_DICT]; +static char letterGroupsDefined[N_LETTER_GROUPS]; MNEM_TAB mnem_flags[] = { // these in the first group put a value in bits0-3 of dictionary_flags @@ -136,6 +136,28 @@ 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) {//================================================== // performs fopen, but produces error message to f_log if it fails @@ -168,8 +190,8 @@ static const char *lookup_mnem(MNEM_TAB *table, int value) -int compile_line(char *linebuf, char *dict_line, int *hash) -{//======================================================== +static int compile_line(char *linebuf, char *dict_line, int *hash) +{//=============================================================== // Compile a line in the language_list file unsigned char c; char *p; @@ -448,7 +470,7 @@ step=1; // TEST { // this assumes that the lower case char is the same length as the upper case char // OK, except for Turkish "I", but use towlower() rather than towlower2() - ix = utf8_in(&c2,p,0); + ix = utf8_in(&c2,p); if(c2 == 0) break; if(iswupper(c2)) @@ -551,8 +573,8 @@ step=1; // TEST -void compile_dictlist_start(void) -{//============================== +static void compile_dictlist_start(void) +{//===================================== // initialise dictionary list int ix; char *p; @@ -573,8 +595,8 @@ void compile_dictlist_start(void) } -void compile_dictlist_end(FILE *f_out) -{//=================================== +static void compile_dictlist_end(FILE *f_out) +{//========================================== // Write out the compiled dictionary list int hash; int length; @@ -610,8 +632,8 @@ void compile_dictlist_end(FILE *f_out) -int compile_dictlist_file(const char *path, const char* filename) -{//============================================================== +static int compile_dictlist_file(const char *path, const char* filename) +{//===================================================================== int length; int hash; char *p; @@ -664,26 +686,19 @@ int compile_dictlist_file(const char *path, const char* filename) -char rule_cond[80]; -char rule_pre[80]; -char rule_post[80]; -char rule_match[80]; -char rule_phonemes[80]; -char group_name[LEN_GROUP_NAME+1]; +static char rule_cond[80]; +static char rule_pre[80]; +static char rule_post[80]; +static char rule_match[80]; +static char rule_phonemes[80]; +static char group_name[LEN_GROUP_NAME+1]; #define N_RULES 2000 // max rules for each group -int hexdigit(char c) -{//================= - if(isdigit(c)) - return(c - '0'); - return(tolower(c) - 'a' + 10); -} - -void copy_rule_string(char *string, int &state) -{//============================================ +static void copy_rule_string(char *string, int &state) +{//=================================================== // state 0: conditional, 1=pre, 2=match, 3=post, 4=phonemes static char *outbuf[5] = {rule_cond, rule_pre, rule_match, rule_post, rule_phonemes}; static int next_state[5] = {2,2,4,4,4}; @@ -892,8 +907,8 @@ void copy_rule_string(char *string, int &state) -char *compile_rule(char *input) -{//============================ +static char *compile_rule(char *input) +{//=================================== int ix; unsigned char c; int wc; @@ -990,7 +1005,7 @@ char *compile_rule(char *input) len_name = strlen(group_name); if((len_name > 0) && (memcmp(rule_match,group_name,len_name) != 0)) { - utf8_in(&wc,rule_match,0); + utf8_in(&wc,rule_match); if((group_name[0] == '9') && IsDigit(wc)) { // numeric group, rule_match starts with a digit, so OK @@ -1080,8 +1095,8 @@ static int __cdecl rgroup_sorter(RGROUP *a, RGROUP *b) #ifdef OUTPUT_FORMAT -void print_rule_group(FILE *f_out, int n_rules, char **rules, char *name) -{//====================================================================== +static void print_rule_group(FILE *f_out, int n_rules, char **rules, char *name) +{//============================================================================= int rule; int ix; unsigned char c; @@ -1187,8 +1202,8 @@ void print_rule_group(FILE *f_out, int n_rules, char **rules, char *name) //#define LIST_GROUP_INFO -void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name) -{//======================================================================= +static void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name) +{//============================================================================== int ix; int len1; int len2; @@ -1406,7 +1421,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) if(strlen(group_name) > 2) { - if(utf8_in(&c,group_name,0) < 2) + if(utf8_in(&c,group_name) < 2) { fprintf(f_log,"%5d: Group name longer than 2 bytes (UTF8)",linenum); error_count++; @@ -1442,7 +1457,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) ix = 0; while((unsigned char)(*p) > 0x20) // not space or zero-byte { - p += utf8_in(&c,p,0); + p += utf8_in(&c,p); replace1 += (c << ix); ix += 16; } @@ -1450,7 +1465,7 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) ix = 0; while((unsigned char)(*p) > 0x20) { - p += utf8_in(&c,p,0); + p += utf8_in(&c,p); replace2 += (c << ix); ix += 16; } @@ -1508,7 +1523,6 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) - int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname_err, int flags) {//===================================================================================================== // fname: space to write the filename in case of error @@ -1572,7 +1586,7 @@ int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, cha compile_dictlist_start(); - fprintf(f_log,"Using phonemetable: '%s'\n",PhonemeTabName()); + fprintf(f_log,"Using phonemetable: '%s'\n",phoneme_tab_list[phoneme_tab_number].name); compile_dictlist_file(path,"roots"); if(translator->langopts.listx) { @@ -1598,7 +1612,7 @@ int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, cha Write4Bytes(f_out,offset_rules); fclose(f_out); - translator->LoadDictionary(dict_name,0); + LoadDictionary(translator, dict_name, 0); return(error_count); } // end of compile_dictionary diff --git a/src/dictionary.cpp b/src/dictionary.cpp index 4652c350..23bd9c65 100755 --- a/src/dictionary.cpp +++ b/src/dictionary.cpp @@ -39,8 +39,7 @@ int dictionary_skipwords; char dictionary_name[40]; -extern MNEM_TAB mnem_flags[]; -extern PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS]; +extern char *print_dictionary_flags(unsigned int *flags); // 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}; @@ -118,17 +117,6 @@ int LookupMnem(MNEM_TAB *table, char *string) return(table->value); } -const char *LookupMnem(MNEM_TAB *table, int value) -{//=============================================== - while(table->mnem != NULL) - { - if(table->value == value) - return(table->mnem); - table++; - } - return(""); -} - //============================================================================================= @@ -137,9 +125,112 @@ const char *LookupMnem(MNEM_TAB *table, int value) //============================================================================================= +static void InitGroups(Translator *tr) +{//=================================== +/* Called after dictionary 1 is loaded, to set up table of entry points for translation rule chains + for single-letters and two-letter combinations +*/ -int Translator::LoadDictionary(const char *name, int no_error) -{//=========================================================== + int ix; + char *p; + char *p_name; + unsigned int *pw; + unsigned char c, c2; + int len; + + tr->n_groups2 = 0; + for(ix=0; ix<256; ix++) + { + tr->groups1[ix]=NULL; + tr->groups2_count[ix]=0; + tr->groups2_start[ix]=255; // indicates "not set" + } + memset(tr->letterGroups,0,sizeof(tr->letterGroups)); + + p = tr->data_dictrules; + while(*p != 0) + { + if(*p != RULE_GROUP_START) + { + fprintf(stderr,"Bad rules data in '%s_dict' at 0x%x\n",dictionary_name,(unsigned int)(p - tr->data_dictrules)); + break; + } + p++; + + if(p[0] == RULE_REPLACEMENTS) + { + pw = (unsigned int *)(((long)p+4) & ~3); // advance to next word boundary + tr->langopts.replace_chars = pw; + while(pw[0] != 0) + { + pw += 2; // find the end of the replacement list, each entry is 2 words. + } + p = (char *)(pw+1); + +#ifdef ARCH_BIG + pw = (unsigned int *)(tr->langopts.replace_chars); + while(*pw != 0) + { + *pw = reverse_word_bytes(*pw); + pw++; + *pw = reverse_word_bytes(*pw); + pw++; + } +#endif + continue; + } + + if(p[0] == RULE_LETTERGP2) + { + ix = p[1] - 'A'; + p += 2; + if((ix >= 0) && (ix < N_LETTER_GROUPS)) + { + tr->letterGroups[ix] = p; + } + } + else + { + len = strlen(p); + p_name = p; + c = p_name[0]; + + p += (len+1); + if(len == 1) + { + tr->groups1[c] = p; + } + else + if(len == 0) + { + tr->groups1[0] = p; + } + else + { + if(tr->groups2_start[c] == 255) + tr->groups2_start[c] = tr->n_groups2; + + tr->groups2_count[c]++; + tr->groups2[tr->n_groups2] = p; + c2 = p_name[1]; + tr->groups2_name[tr->n_groups2++] = (c + (c2 << 8)); + } + } + + // skip over all the rules in this group + while(*p != RULE_GROUP_END) + { + p += (strlen(p) + 1); + } + p++; + } + +} // end of InitGroups + + + +int LoadDictionary(Translator *tr, const char *name, int no_error) +{//=============================================================== int hash; char *p; int *pw; @@ -169,15 +260,15 @@ int Translator::LoadDictionary(const char *name, int no_error) return(1); } - if(data_dictlist != NULL) - Free(data_dictlist); + if(tr->data_dictlist != NULL) + Free(tr->data_dictlist); - data_dictlist = Alloc(size); - fread(data_dictlist,size,1,f); + tr->data_dictlist = Alloc(size); + fread(tr->data_dictlist,size,1,f); fclose(f); - pw = (int *)data_dictlist; + pw = (int *)(tr->data_dictlist); length = reverse_word_bytes(pw[1]); if(size <= (N_HASH_DICT + sizeof(int)*2)) @@ -192,21 +283,21 @@ int Translator::LoadDictionary(const char *name, int no_error) fprintf(stderr,"Bad data: '%s' (%x length=%x)\n",fname,reverse_word_bytes(pw[0]),length); return(2); } - data_dictrules = &data_dictlist[length]; + tr->data_dictrules = &(tr->data_dictlist[length]); // set up indices into data_dictrules - InitGroups(); - if(groups1[0] == NULL) + InitGroups(tr); + if(tr->groups1[0] == NULL) { fprintf(stderr,"Error in %s_rules, no default rule group\n",name); } // set up hash table for data_dictlist - p = &data_dictlist[8]; + p = &(tr->data_dictlist[8]); for(hash=0; hashdict_hashtab[hash] = p; while((length = *p) != 0) { p += length; @@ -218,109 +309,6 @@ int Translator::LoadDictionary(const char *name, int no_error) } // end of LoadDictionary -void Translator::InitGroups(void) -{//============================== -/* Called after dictionary 1 is loaded, to set up table of entry points for translation rule chains - for single-letters and two-letter combinations -*/ - - int ix; - char *p; - char *p_name; - unsigned int *pw; - unsigned char c, c2; - int len; - - n_groups2 = 0; - for(ix=0; ix<256; ix++) - { - groups1[ix]=NULL; - groups2_count[ix]=0; - groups2_start[ix]=255; // indicates "not set" - } - memset(letterGroups,0,sizeof(letterGroups)); - - p = data_dictrules; - while(*p != 0) - { - if(*p != RULE_GROUP_START) - { - fprintf(stderr,"Bad rules data in '%s_dict' at 0x%x\n",dictionary_name,(unsigned int)(p-data_dictrules)); - break; - } - p++; - - if(p[0] == RULE_REPLACEMENTS) - { - pw = (unsigned int *)(((long)p+4) & ~3); // advance to next word boundary - langopts.replace_chars = pw; - while(pw[0] != 0) - { - pw += 2; // find the end of the replacement list, each entry is 2 words. - } - p = (char *)(pw+1); - -#ifdef ARCH_BIG - pw = (unsigned int *)langopts.replace_chars; - while(*pw != 0) - { - *pw = reverse_word_bytes(*pw); - pw++; - *pw = reverse_word_bytes(*pw); - pw++; - } -#endif - continue; - } - - if(p[0] == RULE_LETTERGP2) - { - ix = p[1] - 'A'; - p += 2; - if((ix >= 0) && (ix < N_LETTER_GROUPS)) - { - letterGroups[ix] = p; - } - } - else - { - len = strlen(p); - p_name = p; - c = p_name[0]; - - p += (len+1); - if(len == 1) - { - groups1[c] = p; - } - else - if(len == 0) - { - groups1[0] = p; - } - else - { - if(groups2_start[c] == 255) - groups2_start[c] = n_groups2; - - groups2_count[c]++; - groups2[n_groups2] = p; - c2 = p_name[1]; - groups2_name[n_groups2++] = (c + (c2 << 8)); - } - } - - // skip over all the rules in this group - while(*p != RULE_GROUP_END) - { - p += (strlen(p) + 1); - } - p++; - } - -} // end of InitGroups - - int HashDictionary(const char *string) //==================================== /* Generate a hash code from the specified string @@ -514,8 +502,8 @@ void DecodePhonemes(const char *inptr, char *outptr) -void Translator::WriteMnemonic(int *ix, int mnem) -{//============================================== +static void WriteMnemonic(char *phon_out, int *ix, int mnem) +{//========================================================= unsigned char c; while((c = mnem & 0xff) != 0) @@ -529,8 +517,9 @@ void Translator::WriteMnemonic(int *ix, int mnem) } -void Translator::GetTranslatedPhonemeString(char *phon_out, int n_phon_out) -{//======================================================================== + +void GetTranslatedPhonemeString(char *phon_out, int n_phon_out) +{//============================================================ /* Can be called after a clause has been translated into phonemes, in order to display the clause in phoneme mnemonic form. */ @@ -559,16 +548,16 @@ void Translator::GetTranslatedPhonemeString(char *phon_out, int n_phon_out) phon_out[phon_out_ix++] = stress_chars[stress]; } } - WriteMnemonic(&phon_out_ix,plist->ph->mnemonic); + WriteMnemonic(phon_out, &phon_out_ix, plist->ph->mnemonic); if(plist->synthflags & SFLAG_LENGTHEN) { - WriteMnemonic(&phon_out_ix,phoneme_tab[phonLENGTHEN]->mnemonic); + WriteMnemonic(phon_out, &phon_out_ix, phoneme_tab[phonLENGTHEN]->mnemonic); } if((plist->synthflags & SFLAG_SYLLABLE) && (plist->type != phVOWEL)) { // syllablic consonant - WriteMnemonic(&phon_out_ix,phoneme_tab[phonSYLLABIC]->mnemonic); + WriteMnemonic(phon_out, &phon_out_ix, phoneme_tab[phonSYLLABIC]->mnemonic); } if(plist->ph->code == phonSWITCH) { @@ -583,7 +572,7 @@ void Translator::GetTranslatedPhonemeString(char *phon_out, int n_phon_out) else if(plist->tone_ph > 0) { - WriteMnemonic(&phon_out_ix,phoneme_tab[plist->tone_ph]->mnemonic); + WriteMnemonic(phon_out, &phon_out_ix, phoneme_tab[plist->tone_ph]->mnemonic); } } @@ -591,7 +580,7 @@ void Translator::GetTranslatedPhonemeString(char *phon_out, int n_phon_out) phon_out_ix = n_phon_out - 1; phon_out[phon_out_ix] = 0; } -} // end of Translator::GetTranslatedPhonemeString +} // end of GetTranslatedPhonemeString @@ -601,92 +590,15 @@ void Translator::GetTranslatedPhonemeString(char *phon_out, int n_phon_out) //============================================================================================= -#ifdef deleted -// this is the initials_bitmap for english -static unsigned char initials_bitmap[86] = { - 0x00, 0x00, 0x00, 0x00, 0x22, 0x08, 0x00, 0x88, // 0 - 0x20, 0x24, 0x20, 0x80, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x08, 0x00, 0x88, 0x22, 0x04, 0x00, // 16 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x88, 0x22, 0x04, 0x00, 0x02, 0x00, 0x00, // 32 - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x8a, 0x03, 0x00, 0x00, 0x40, 0x00, // 48 - 0x02, 0x00, 0x41, 0xca, 0x9b, 0x06, 0x20, 0x80, - 0x91, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, // 64 - 0x08, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, }; -#endif - -int Translator::Unpronouncable(char *word) -{//======================================= -/* Determines whether a word in 'unpronouncable', i.e. whether it should - be spoken as individual letters. - - This function may be language specific. This is a generic version. -*/ - - int c; - int c1=0; - int vowel_posn=9; - int index; - int count; - int apostrophe=0; - - if(langopts.param[LOPT_UNPRONOUNCABLE] == 1) - return(0); - - if((*word == ' ') || (*word == 0)) - return(0); - - index = 0; - count = 0; - for(;;) - { - index += utf8_in(&c,&word[index],0); - if((c==0) || (c==' ')) - break; - - if(count==0) - c1 = c; - count++; - - if(IsVowel(c)) - { - vowel_posn = count; // position of the first vowel - break; - } - - if(c == '\'') - apostrophe = 1; - else - if(!iswalpha(c)) - return(0); // letter (not vowel) outside a-z range or apostrophe, abort test - } - - if((vowel_posn < 9) && (langopts.param[LOPT_UNPRONOUNCABLE] == 2)) - return(0); // option means allow any word with a vowel - - if(c1 == langopts.param[LOPT_UNPRONOUNCABLE]) - vowel_posn--; // disregard this as the initial letter when counting - - if(vowel_posn > (langopts.max_initial_consonants+1)) - return(1); // no vowel, or no vowel in first four letters - -return(0); - -} /* end of Unpronounceable */ - - - -int Translator::IsLetterGroup(char *word, int group, int pre) -{//========================================================== +static int IsLetterGroup(Translator *tr, char *word, int group, int pre) +{//===================================================================== // match the word against a list of utf-8 strings char *p; char *w; int len=0; - p = letterGroups[group]; + p = tr->letterGroups[group]; if(p == NULL) return(0); @@ -719,13 +631,13 @@ int Translator::IsLetterGroup(char *word, int group, int pre) } -int Translator::IsLetter(int letter, int group) -{//============================================ +static int IsLetter(Translator *tr, int letter, int group) +{//======================================================= int letter2; - if(letter_groups[group] != NULL) + if(tr->letter_groups[group] != NULL) { - if(wcschr(letter_groups[group],letter)) + if(wcschr(tr->letter_groups[group],letter)) return(1); return(0); } @@ -733,9 +645,9 @@ int Translator::IsLetter(int letter, int group) if(group > 7) return(0); - if(letter_bits_offset > 0) + if(tr->letter_bits_offset > 0) { - if(((letter2 = (letter - letter_bits_offset)) > 0) && (letter2 < 0x80)) + if(((letter2 = (letter - tr->letter_bits_offset)) > 0) && (letter2 < 0x80)) letter = letter2; else return(0); @@ -743,62 +655,173 @@ int Translator::IsLetter(int letter, int group) else { if((letter >= 0xc0) && (letter <= 0x241)) - return(letter_bits[remove_accent[letter-0xc0]] & (1L << group)); + return(tr->letter_bits[remove_accent[letter-0xc0]] & (1L << group)); } if((letter >= 0) && (letter < 0x80)) - return(letter_bits[letter] & (1L << group)); + return(tr->letter_bits[letter] & (1L << group)); return(0); } -int Translator::IsVowel(int letter) -{//================================ - return(IsLetter(letter,0)); +static int IsVowel(Translator *tr, int letter) +{//=========================================== + return(IsLetter(tr, letter, 0)); } -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) -} -void ResetLetterBits(Translator *tr, int groups) -{//============================================= -// Clear all the specified groups - unsigned int ix; - unsigned int mask; - mask = ~groups; - for(ix=0; ixletter_bits); ix++) +static int Unpronouncable_en(Translator *tr, char *word) +{//===================================================== +/* Determines whether a word in 'unpronouncable', i.e. whether it should + be spoken as individual letters. + + This function is language specific. +*/ + + int c; + int vowel_posn=9; + int index; + int count; + int ix; + int apostrophe=0; + + static unsigned char initials_bitmap[86] = { + 0x00, 0x00, 0x00, 0x00, 0x22, 0x08, 0x00, 0x88, // 0 + 0x20, 0x24, 0x20, 0x80, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x08, 0x00, 0x88, 0x22, 0x04, 0x00, // 16 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x88, 0x22, 0x04, 0x00, 0x02, 0x00, 0x04, // 32 + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x8a, 0x03, 0x00, 0x00, 0x40, 0x00, // 48 + 0x02, 0x00, 0x41, 0xca, 0x9b, 0x06, 0x20, 0x80, + 0x91, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, // 64 + 0x08, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, }; + + + // words which we pass through to the dictionary, even though they look unpronouncable + static const char *exceptions[] = { + "'s ", "st ","nd ","rd ","th ",NULL }; + + if((*word == ' ') || (*word == 0)) + return(0); + + for(ix=0; exceptions[ix] != NULL; ix++) { - tr->letter_bits[ix] &= mask; + // Seemingly uncpronouncable words, but to be looked in the dictionary rules instead + if(memcmp(word,exceptions[ix],3)==0) + return(0); } -} - -void SetLetterBits(Translator *tr, int group, const char *string) -{//============================================================== - int bits; - unsigned char c; - - bits = (1L << group); - while((c = *string++) != 0) - tr->letter_bits[c] |= bits; -} - -void SetLetterBitsRange(Translator *tr, int group, int first, int last) -{//==================================================================== - int bits; - int ix; - - bits = (1L << group); - for(ix=first; ix<=last; ix++) + index=0; + count=0; + for(;;) { - tr->letter_bits[ix] |= bits; + index += utf8_in(&c,&word[index]); + count++; + + if((c==0) || (c==' ')) + break; + + if(IsVowel(tr, c) || (c == 'y')) + { + vowel_posn = count; + break; + } + + if(c == '\'') + apostrophe = 1; + else + if(!IsAlpha(c)) + return(0); // letter (not vowel) outside Latin character range or apostrophe, abort test } -} + if((vowel_posn > 5) || ((word[0]!='s') && (vowel_posn > 4))) + return(1); // no vowel, or no vowel in first four letters + + /* there is at least one vowel, is the initial letter combination valid ? */ + + if(vowel_posn < 3) + return(0); /* vowel in first two letters, OK */ + + if(apostrophe) + return(0); // first two letters not a-z, abort test + + index = (word[0]-'a') * 26 + (word[1]-'a'); + if(initials_bitmap[index >> 3] & (1L << (index & 7))) + return(0); + else + return(1); /****/ +} /* end of Unpronounceable */ + + + + +int Unpronouncable(Translator *tr, char *word) +{//=========================================== +/* Determines whether a word in 'unpronouncable', i.e. whether it should + be spoken as individual letters. + + This function may be language specific. This is a generic version. +*/ + + int c; + int c1=0; + int vowel_posn=9; + int index; + int count; + int apostrophe=0; + + if(tr->translator_name == L('e','n')) + { + return(Unpronouncable_en(tr,word)); + } + + if(tr->langopts.param[LOPT_UNPRONOUNCABLE] == 1) + return(0); + + if((*word == ' ') || (*word == 0)) + return(0); + + index = 0; + count = 0; + for(;;) + { + index += utf8_in(&c,&word[index]); + if((c==0) || (c==' ')) + break; + + if(count==0) + c1 = c; + count++; + + if(IsVowel(tr, c)) + { + vowel_posn = count; // position of the first vowel + break; + } + + if(c == '\'') + apostrophe = 1; + else + if(!iswalpha(c)) + return(0); // letter (not vowel) outside a-z range or apostrophe, abort test + } + + if((vowel_posn < 9) && (tr->langopts.param[LOPT_UNPRONOUNCABLE] == 2)) + return(0); // option means allow any word with a vowel + + if(c1 == tr->langopts.param[LOPT_UNPRONOUNCABLE]) + vowel_posn--; // disregard this as the initial letter when counting + + if(vowel_posn > (tr->langopts.max_initial_consonants+1)) + return(1); // no vowel, or no vowel in first four letters + +return(0); + +} /* end of Unpronounceable */ @@ -1000,8 +1023,8 @@ void ChangeWordStress(Translator *tr, char *word, int new_stress) -void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int tonic, int prev_stress) -{//=================================================================================================== +void SetWordStress(Translator *tr, char *output, unsigned int dictionary_flags, int tonic, int prev_stress) +{//======================================================================================================== /* Guess stress pattern of word. This is language specific 'dictionary_flags' has bits 0-3 position of stressed vowel (if > 0) @@ -1033,6 +1056,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int int post_tonic; int opt_length; int done; + int stressflags; unsigned char vowel_stress[N_WORD_PHONEMES/2]; char syllable_weight[N_WORD_PHONEMES/2]; @@ -1049,6 +1073,8 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int 3 secondary stress 4 main stress */ + stressflags = tr->langopts.stress_flags; + /* copy input string into internal buffer */ for(ix=0; ixlangopts.stress_rule) { case 8: // stress on first syllable, unless it is a light syllable @@ -1139,12 +1165,12 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int { stressed_syllable = vowel_count - 2; - if(langopts.stress_flags & 0x300) + if(stressflags & 0x300) { // LANG=Spanish, stress on last vowel if the word ends in a consonant other than 'n' or 's' if(phoneme_tab[final_ph]->type != phVOWEL) { - if(langopts.stress_flags & 0x100) + if(stressflags & 0x100) { stressed_syllable = vowel_count - 1; } @@ -1165,7 +1191,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int } } } - if(langopts.stress_flags & 0x80000) + if(stressflags & 0x80000) { // stress on last syllable if it has a long vowel, but previous syllable has a short vowel if(vowel_length[vowel_count - 1] > vowel_length[vowel_count - 2]) @@ -1186,7 +1212,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int else { stressed_syllable = 1; - if(langopts.stress_flags & 0x1) + if(stressflags & 0x1) max_stress = 3; // don't give full stress to monosyllables } @@ -1334,7 +1360,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int stress = 3; - if((langopts.stress_flags & 0x1000) && (vowel_count == 2)) + if((stressflags & 0x1000) && (vowel_count == 2)) { // Two syllable word, if one syllable has primary stress, then give the other secondary stress if(vowel_stress[1] == 4) @@ -1343,7 +1369,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int vowel_stress[1] = 3; } #if deleted - if((langopts.stress_flags & 0x2000) && (vowel_stress[1] == 0)) + if((stressflags & 0x2000) && (vowel_stress[1] == 0)) { // If there is only one syllable before the primary stress, give it a secondary stress if((vowel_count > 2) && (vowel_stress[2] >= 4)) @@ -1358,12 +1384,12 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int { if(vowel_stress[v] == 0) { - if((langopts.stress_flags & 0x10) && (stress < 4) && (v == vowel_count-1)) + if((stressflags & 0x10) && (stress < 4) && (v == vowel_count-1)) { // flag: don't give secondary stress to final vowel } else - if((langopts.stress_flags & 0x8000) && (done == 0)) + if((stressflags & 0x8000) && (done == 0)) { vowel_stress[v] = (char)stress; done =1; @@ -1374,10 +1400,10 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int { /* trochaic: give stress to vowel surrounded by unstressed vowels */ - if((stress == 3) && (langopts.stress_flags & 0x20)) + if((stress == 3) && (stressflags & 0x20)) continue; // don't use secondary stress - if((v > 1) && (langopts.stress_flags & 0x40) && (syllable_weight[v]==0) && (syllable_weight[v+1]>0)) + if((v > 1) && (stressflags & 0x40) && (syllable_weight[v]==0) && (syllable_weight[v+1]>0)) { // don't put secondary stress on a light syllable which is followed by a heavy syllable continue; @@ -1395,9 +1421,9 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int if((unstressed_word) && (tonic < 0)) { if(vowel_count <= 2) - tonic = langopts.unstressed_wd1; /* monosyllable - unstressed */ + tonic = tr->langopts.unstressed_wd1; /* monosyllable - unstressed */ else - tonic = langopts.unstressed_wd2; /* more than one syllable, used secondary stress as the main stress */ + tonic = tr->langopts.unstressed_wd2; /* more than one syllable, used secondary stress as the main stress */ } max_stress = 0; @@ -1433,7 +1459,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int ph = phoneme_tab[p[1]]; #ifdef deleted - int gap = langopts.word_gap & 0x700; + int gap = tr->langopts.word_gap & 0x700; if((gap) && (vowel_stress[1] >= 4) && (prev_stress >= 4)) { /* two primary stresses together, insert a short pause */ @@ -1441,11 +1467,11 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int } else #endif - if((langopts.vowel_pause & 0x30) && (ph->type == phVOWEL)) + if((tr->langopts.vowel_pause & 0x30) && (ph->type == phVOWEL)) { // word starts with a vowel - if((langopts.vowel_pause & 0x20) && (vowel_stress[1] >= 4)) + if((tr->langopts.vowel_pause & 0x20) && (vowel_stress[1] >= 4)) { *output++ = phonPAUSE_NOLINK; // not to be replaced by link } @@ -1468,7 +1494,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int if(ph->type == phPAUSE) { - prev_last_stress = 0; + tr->prev_last_stress = 0; } else if(((ph->type == phVOWEL) && !(ph->phflags & phNONSYLLABIC)) || (*p == phonSYLLABIC)) @@ -1476,20 +1502,20 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int // a vowel, or a consonant followed by a syllabic consonant marker v_stress = vowel_stress[v]; - prev_last_stress = v_stress; + tr->prev_last_stress = v_stress; if(vowel_stress[v-1] >= max_stress) post_tonic = 1; if(v_stress <= 1) { - if((v > 1) && (max_stress >= 4) && (langopts.stress_flags & 4) && (v == (vowel_count-1))) + if((v > 1) && (max_stress >= 4) && (stressflags & 4) && (v == (vowel_count-1))) { // option: mark unstressed final syllable as diminished v_stress = 1; } else - if((langopts.stress_flags & 2) || (v == 1) || (v == (vowel_count-1))) + if((stressflags & 2) || (v == 1) || (v == (vowel_count-1))) { // first or last syllable, or option 'don't set diminished stress' v_stress = 0; @@ -1503,7 +1529,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int else { // unstressed syllable within a word - if((vowel_stress[v-1] != 1) || ((langopts.stress_flags & 0x10000) == 0)) + if((vowel_stress[v-1] != 1) || ((stressflags & 0x10000) == 0)) { v_stress = 1; /* change from 0 (unstressed) to 1 (diminished stress) */ vowel_stress[v] = v_stress; @@ -1520,7 +1546,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int max_stress = vowel_stress[v]; } - if((*p == phonLENGTHEN) && ((opt_length = langopts.param[LOPT_IT_LENGTHEN]) != 0)) + if((*p == phonLENGTHEN) && ((opt_length = tr->langopts.param[LOPT_IT_LENGTHEN]) != 0)) { // remove lengthen indicator from non-stressed syllables int shorten=0; @@ -1565,7 +1591,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int #ifdef LOG_TRANSLATE -char *Translator::DecodeRule(const char *group, char *rule) +static char *DecodeRule(const char *group, char *rule) {//================================================== /* Convert compiled match template to ascii */ @@ -1713,8 +1739,8 @@ char *Translator::DecodeRule(const char *group, char *rule) -void Translator::AppendPhonemes(char *string, int size, const char *ph) -{//==================================================================== +void AppendPhonemes(Translator *tr, char *string, int size, const char *ph) +{//======================================================================== /* Add new phoneme string "ph" to "string" Keeps count of the number of vowel phonemes in the word, and whether these can be stressed syllables. These values can be used in translation rules @@ -1749,10 +1775,10 @@ void Translator::AppendPhonemes(char *string, int size, const char *ph) if(((phoneme_tab[c]->phflags & phUNSTRESSED) == 0) && (unstress_mark == 0)) { - word_stressed_count++; + tr->word_stressed_count++; } unstress_mark = 0; - word_vowel_count++; + tr->word_vowel_count++; } } } @@ -1763,8 +1789,8 @@ void Translator::AppendPhonemes(char *string, int size, const char *ph) -void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRecord *match_out, int word_flags, int dict_flags) -{//============================================================================================================================ +static void MatchRule(Translator *tr, char *word[], const char *group, 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. @@ -1901,13 +1927,13 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec if(condition_num >= 32) { // allow the rule only if the condition number is NOT set - if((dict_condition & (1L << (condition_num-32))) != 0) + if((tr->dict_condition & (1L << (condition_num-32))) != 0) failed = 1; } else { // allow the rule only if the condition number is set - if((dict_condition & (1L << condition_num)) == 0) + if((tr->dict_condition & (1L << condition_num)) == 0) failed = 1; } @@ -1946,14 +1972,14 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec if(distance_right > 18) distance_right = 19; last_letter = letter; - letter_xbytes = utf8_in(&letter_w,post_ptr,0)-1; + letter_xbytes = utf8_in(&letter_w,post_ptr)-1; letter = *post_ptr++; switch(rb) { case RULE_LETTERGP: letter_group = *rule++ - 'A'; - if(IsLetter(letter_w,letter_group)) + if(IsLetter(tr, letter_w, letter_group)) { lg_pts = 20; if(letter_group==2) @@ -1967,7 +1993,7 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec case RULE_LETTERGP2: // match against a list of utf-8 strings letter_group = *rule++ - 'A'; - if((n_bytes = IsLetterGroup(post_ptr-1,letter_group,0)) >0) + if((n_bytes = IsLetterGroup(tr, post_ptr-1,letter_group,0)) >0) { add_points = (20-distance_right); post_ptr += (n_bytes-1); @@ -1977,7 +2003,7 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec break; case RULE_NOTVOWEL: - if(!IsLetter(letter_w,0)) + if(!IsLetter(tr, letter_w,0)) { add_points = (20-distance_right); post_ptr += letter_xbytes; @@ -1993,7 +2019,7 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec post_ptr += letter_xbytes; } else - if(langopts.tone_numbers) + if(tr->langopts.tone_numbers) { // also match if there is no digit add_points = (20-distance_right); @@ -2050,13 +2076,13 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec vowel = 0; while(letter_w != RULE_SPACE) { - if((vowel==0) && IsLetter(letter_w,LETTERGP_VOWEL2)) + if((vowel==0) && IsLetter(tr, letter_w,LETTERGP_VOWEL2)) { // this is counting vowels which are separated by non-vowels syllable_count--; } - vowel = IsLetter(letter_w,LETTERGP_VOWEL2); - p += utf8_in(&letter_w,p,0); + vowel = IsLetter(tr, letter_w,LETTERGP_VOWEL2); + p += utf8_in(&letter_w,p); } if(syllable_count <= 0) add_points = (19-distance_right); @@ -2070,12 +2096,12 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec char *p = post_ptr + letter_xbytes; while(letter_w != RULE_SPACE) { - if(IsLetter(letter_w,LETTERGP_VOWEL2)) + if(IsLetter(tr, letter_w,LETTERGP_VOWEL2)) { failed = 1; break; } - p += utf8_in(&letter_w,p,0); + p += utf8_in(&letter_w,p); } if(!failed) add_points = (19-distance_right); @@ -2134,14 +2160,14 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec last_letter = *pre_ptr; pre_ptr--; - letter_xbytes = utf8_in(&letter_w,pre_ptr,1)-1; + letter_xbytes = utf8_in2(&letter_w,pre_ptr,1)-1; letter = *pre_ptr; switch(rb) { case RULE_LETTERGP: letter_group = *rule++ - 'A'; - if(IsLetter(letter_w,letter_group)) + if(IsLetter(tr, letter_w,letter_group)) { lg_pts = 20; if(letter_group==2) @@ -2155,7 +2181,7 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec case RULE_LETTERGP2: // match against a list of utf-8 strings letter_group = *rule++ - 'A'; - if((n_bytes = IsLetterGroup(pre_ptr-letter_xbytes,letter_group,1)) >0) + if((n_bytes = IsLetterGroup(tr, pre_ptr-letter_xbytes,letter_group,1)) >0) { add_points = (20-distance_right); pre_ptr -= (n_bytes-1); @@ -2165,7 +2191,7 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec break; case RULE_NOTVOWEL: - if(!IsLetter(letter_w,0)) + if(!IsLetter(tr, letter_w,0)) { add_points = (20-distance_left); pre_ptr -= letter_xbytes; @@ -2209,14 +2235,14 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec rule++; syllable_count++; /* number of syllables to match */ } - if(syllable_count <= word_vowel_count) + if(syllable_count <= tr->word_vowel_count) add_points = (19-distance_left); else failed = 1; break; case RULE_STRESSED: - if(word_stressed_count > 0) + if(tr->word_stressed_count > 0) add_points = 19; else failed = 1; @@ -2227,12 +2253,12 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec char *p = pre_ptr - letter_xbytes - 1; while(letter_w != RULE_SPACE) { - if(IsLetter(letter_w,LETTERGP_VOWEL2)) + if(IsLetter(tr, letter_w,LETTERGP_VOWEL2)) { failed = 1; break; } - p -= utf8_in(&letter_w,p,1); + p -= utf8_in2(&letter_w,p,1); } if(!failed) add_points = 3; @@ -2240,7 +2266,7 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec break; case RULE_IFVERB: - if(expect_verb) + if(tr->expect_verb) add_points = 1; else failed = 1; @@ -2349,11 +2375,11 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec -int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char *end_phonemes, int word_flags, unsigned int *dict_flags) +int TranslateRules(Translator *tr, char *p_start, char *phonemes, int ph_size, char *end_phonemes, int word_flags, unsigned int *dict_flags) {//===================================================================================================================================== /* Translate a word bounded by space characters Append the result to 'phonemes' and any standard prefix/suffix in 'end_phonemes' */ - + unsigned char c, c2; unsigned int c12; int wc=0; @@ -2378,7 +2404,7 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char char group_name[4]; - if(data_dictrules == NULL) + if(tr->data_dictrules == NULL) return(0); if(dict_flags != NULL) @@ -2410,8 +2436,8 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char #endif p = p_start; - word_vowel_count = 0; - word_stressed_count = 0; + tr->word_vowel_count = 0; + tr->word_stressed_count = 0; if(end_phonemes != NULL) end_phonemes[0] = 0; @@ -2419,12 +2445,12 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char while(((c = *p) != ' ') && (c != 0)) { wc_prev = wc; - wc_bytes = utf8_in(&wc,p,0); + wc_bytes = utf8_in(&wc,p); if(IsAlpha(wc)) any_alpha++; - n = groups2_count[c]; - if(IsDigit(wc) && ((langopts.tone_numbers == 0) || !any_alpha)) + n = tr->groups2_count[c]; + if(IsDigit(wc) && ((tr->langopts.tone_numbers == 0) || !any_alpha)) { // lookup the number in *_list not *_rules char string[8]; @@ -2432,19 +2458,15 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char string[0] = '_'; memcpy(&string[1],p,wc_bytes); string[1+wc_bytes] = 0; - Lookup(string,buf); + Lookup(tr, string,buf); if(++digit_count >= 2) { strcat(buf,str_pause); digit_count=0; } - AppendPhonemes(phonemes,ph_size,buf); + AppendPhonemes(tr,phonemes,ph_size,buf); p += wc_bytes; continue; - -// MatchRule(&p, "", groups1[(unsigned char)'9'],&match1,word_flags); -// if(match1.points == 0) -// p++; // not found, move on past this digit } else { @@ -2457,10 +2479,10 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char c2 = p[1]; c12 = c + (c2 << 8); /* 2 characters */ - g1 = groups2_start[c]; + g1 = tr->groups2_start[c]; for(g=g1; g < (g1+n); g++) { - if(groups2_name[g] == c12) + if(tr->groups2_name[g] == c12) { found = 1; @@ -2468,13 +2490,13 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char group_name[1] = c2; group_name[2] = 0; p2 = p; - MatchRule(&p2, group_name, groups2[g], &match2, word_flags, dict_flags0); + MatchRule(tr, &p2, group_name, tr->groups2[g], &match2, word_flags, dict_flags0); if(match2.points > 0) match2.points += 35; /* to acount for 2 letters matching */ /* now see whether single letter chain gives a better match ? */ group_name[1] = 0; - MatchRule(&p, group_name, groups1[c], &match1, word_flags, dict_flags0); + MatchRule(tr, &p, group_name, tr->groups1[c], &match1, word_flags, dict_flags0); if(match2.points >= match1.points) { @@ -2492,17 +2514,17 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char group_name[0] = c; group_name[1] = 0; - if(groups1[c] != NULL) - MatchRule(&p, group_name, groups1[c], &match1, word_flags, dict_flags0); + if(tr->groups1[c] != NULL) + MatchRule(tr, &p, group_name, tr->groups1[c], &match1, word_flags, dict_flags0); else { // no group for this letter, use default group - MatchRule(&p, "", groups1[0], &match1, word_flags, dict_flags0); + MatchRule(tr, &p, "", tr->groups1[0], &match1, word_flags, dict_flags0); if((match1.points == 0) && ((option_sayas & 0x10) == 0)) { // no match, try removing the accent and re-translating the word - n = utf8_in(&letter,p-1,0)-1; + n = utf8_in(&letter,p-1)-1; if((letter >= 0xc0) && (letter <= 0x241) && ((ix = remove_accent[letter-0xc0]) != 0)) { // within range of the remove_accent table @@ -2514,7 +2536,7 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char while((p[0] = p[n]) != ' ') p++; while(n-- > 0) *p++ = ' '; // replacement character must be no longer than original - if(langopts.param[LOPT_DIERESES] && (lookupwchar(diereses_list,letter) > 0)) + if(tr->langopts.param[LOPT_DIERESES] && (lookupwchar(diereses_list,letter) > 0)) { // vowel with dieresis, replace and continue from this point p = p2; @@ -2523,8 +2545,8 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char phonemes[0] = 0; // delete any phonemes which have been produced so far p = p_start; - word_vowel_count = 0; - word_stressed_count = 0; + tr->word_vowel_count = 0; + tr->word_stressed_count = 0; continue; // start again at the beginning of the word } } @@ -2533,7 +2555,7 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char { // ideograms // outside the range of the accent table, speak the unknown symbol sound - Lookup("_??",ph_buf); + Lookup(tr, "_??", ph_buf); match1.phonemes = ph_buf; match1.points = 1; p += (wc_bytes-1); @@ -2561,7 +2583,7 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char } else { - LookupLetter(wc, -1, ph_buf); + LookupLetter(tr, wc, -1, ph_buf); if(ph_buf[0]) { match1.phonemes = ph_buf; @@ -2572,7 +2594,7 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char } else { - phonemes_repeat_count = 0; + tr->phonemes_repeat_count = 0; } } } @@ -2610,12 +2632,12 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char } if(match1.del_fwd != NULL) *match1.del_fwd = REPLACED_E; - AppendPhonemes(phonemes,ph_size,match1.phonemes); + AppendPhonemes(tr,phonemes,ph_size,match1.phonemes); } } // any language specific changes ? - ApplySpecialAttribute(phonemes,dict_flags0); + ApplySpecialAttribute(tr,phonemes,dict_flags0); memcpy(p_start,word_copy,strlen(word_copy)); return(0); @@ -2623,8 +2645,8 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char -void Translator::ApplySpecialAttribute(char *phonemes, int dict_flags) -{//=================================================================== +void ApplySpecialAttribute(Translator *tr, char *phonemes, int dict_flags) +{//======================================================================= // Amend the translated phonemes according to an attribute which is specific for the language. int len; int ix; @@ -2637,37 +2659,37 @@ void Translator::ApplySpecialAttribute(char *phonemes, int dict_flags) len = strlen(phonemes); p_end = &phonemes[len-1]; - switch(translator_name) + switch(tr->translator_name) { case L('d','e'): - if(p_end[0] == LookupPh("i:")) + if(p_end[0] == PhonemeCode2('i',':')) { // words ends in ['i:], change to [=I@] p_end[-1] = phonSTRESS_PREV; - p_end[0] = LookupPh("I"); + p_end[0] = PhonemeCode('I'); p_end[1] = phonSCHWA; p_end[2] = 0; } break; case L('p','t'): - phoneme_1 = LookupPh("o"); + phoneme_1 = PhonemeCode('o'); for(ix=0; ix<(len-1); ix++) { if(phonemes[ix] == phoneme_1) { - phonemes[ix] = LookupPh("O"); + phonemes[ix] = PhonemeCode('O'); break; } } break; case L('r','o'): - if(p_end[0] == LookupPh("j")) + if(p_end[0] == PhonemeCode('j')) { // word end in [j], change to ['i] p_end[0] = phonSTRESS_P; - p_end[1] = LookupPh("i"); + p_end[1] = PhonemeCode('i'); p_end[2] = 0; } break; @@ -2733,7 +2755,7 @@ int TransposeAlphabet(char *text, int offset, int min, int max) int acc; do { - p += utf8_in(&c,p,0); + p += utf8_in(&c,p); if((c >= min) && (c <= max)) { *p2++ = c - offset; @@ -2789,18 +2811,10 @@ int TransposeAlphabet(char *text, int offset, int min, int max) -char *print_dflags(unsigned int *flags) -{//==================================== - static char buf[20]; - sprintf(buf,"%s 0x%x/%x",LookupMnem(mnem_flags,(flags[0] & 0xf)+0x40), flags[0], flags[1]); - return(buf); -} - - - -const char *Translator::LookupDict2(const char *word, const char *word2, char *phonetic, unsigned int *flags, int end_flags, WORD_TAB *wtab) -//========================================================================================================================================== +static const char *LookupDict2(Translator *tr, const char *word, const char *word2, + char *phonetic, unsigned int *flags, int end_flags, WORD_TAB *wtab) +//===================================================================================== /* Find an entry in the word_dict file for a specified word. Returns NULL if no match, else returns 'word_end' @@ -2827,13 +2841,19 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p int ix; const char *word_end; const char *word1; + int wflags = 0; char word_buf[N_WORD_BYTES]; + if(wtab != NULL) + { + wflags = wtab->flags; + } + word1 = word; - if(transpose_offset > 0) + if(tr->transpose_offset > 0) { strcpy(word_buf,word); - wlen = TransposeAlphabet(word_buf, transpose_offset, transpose_min, transpose_max); + wlen = TransposeAlphabet(word_buf, tr->transpose_offset, tr->transpose_min, tr->transpose_max); word = word_buf; } else @@ -2842,7 +2862,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p } hash = HashDictionary(word); - p = dict_hashtab[hash]; + p = tr->dict_hashtab[hash]; if(p == NULL) { @@ -2897,13 +2917,13 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p if(flag >= 132) { // fail if this condition is set - if((dict_condition & (1 << (flag-132))) != 0) + if((tr->dict_condition & (1 << (flag-132))) != 0) condition_failed = 1; } else { // allow only if this condition is set - if((dict_condition & (1 << (flag-100))) == 0) + if((tr->dict_condition & (1 << (flag-100))) == 0) condition_failed = 1; } } @@ -2918,7 +2938,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p // don't use the contraction if any of the words are emphasized for(ix=0; ix <= skipwords; ix++) { - if((wtab != NULL) && (wtab[ix].flags & FLAG_EMPHASIZED2)) + if(wflags & FLAG_EMPHASIZED2) { condition_failed = 1; } @@ -2988,27 +3008,27 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p if(dictionary_flags2 & FLAG_HYPHENATED) { - if(!(word_flags & FLAG_HYPHEN_AFTER)) + if(!(wflags & FLAG_HYPHEN_AFTER)) { continue; } } if(dictionary_flags2 & FLAG_CAPITAL) { - if(!(word_flags & FLAG_FIRST_UPPER)) + if(!(wflags & FLAG_FIRST_UPPER)) { continue; } } if(dictionary_flags2 & FLAG_ALLCAPS) { - if(!(word_flags & FLAG_ALL_UPPER)) + if(!(wflags & FLAG_ALL_UPPER)) { continue; } } - if((dictionary_flags & FLAG_ATEND) && (word_end < clause_end)) + if((dictionary_flags & FLAG_ATEND) && (word_end < tr->clause_end)) { // only use this pronunciation if it's the last word of the clause continue; @@ -3018,7 +3038,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p { // this is a verb-form pronunciation - if(expect_verb || (expect_verb_s && (end_flags & FLAG_SUFX_S))) + if(tr->expect_verb || (tr->expect_verb_s && (end_flags & FLAG_SUFX_S))) { // OK, we are expecting a verb } @@ -3031,7 +3051,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p } if(dictionary_flags2 & FLAG_PAST) { - if(!expect_past) + if(!tr->expect_past) { /* don't use the 'past' pronunciation unless we are expecting past tense */ @@ -3040,7 +3060,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p } if(dictionary_flags2 & FLAG_NOUN) { - if(!expect_noun) + if(!tr->expect_noun) { /* don't use the 'noun' pronunciation unless we are expecting a noun */ @@ -3058,7 +3078,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p { if(option_phonemes == 2) { - fprintf(f_trans,"Flags: %s %s\n",word1,print_dflags(flags)); + fprintf(f_trans,"Flags: %s %s\n",word1,print_dictionary_flags(flags)); } return(0); // no phoneme translation found here, only flags. So use rules } @@ -3084,7 +3104,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p 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_dflags(flags)); + fprintf(f_trans,"Found: %s [%s] %s\n",word1,ph_decoded,print_dictionary_flags(flags)); } } return(word_end); @@ -3095,8 +3115,8 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p -int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab) -//============================================================================================================== +int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab) +//================================================================================================================== /* Lookup a specified word in the word dictionary. Returns phonetic data in 'phonetic' and bits in 'flags' @@ -3135,7 +3155,7 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags } memcpy(&word[length],word2,nbytes); word[length+nbytes] = 0; - found = LookupDict2(word, word2, ph_out, flags, end_flags, wtab); + found = LookupDict2(tr, word, word2, ph_out, flags, end_flags, wtab); if(found) { // set the skip words flag @@ -3153,27 +3173,27 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags } word[length] = 0; - found = LookupDict2(word, word1, ph_out, flags, end_flags, wtab); + found = LookupDict2(tr, word, word1, ph_out, flags, end_flags, wtab); if(flags[0] & FLAG_MAX3) { - if(strcmp(ph_out, phonemes_repeat) == 0) + if(strcmp(ph_out, tr->phonemes_repeat) == 0) { - phonemes_repeat_count++; - if(phonemes_repeat_count > 3) + tr->phonemes_repeat_count++; + if(tr->phonemes_repeat_count > 3) { ph_out[0] = 0; } } else { - strncpy0(phonemes_repeat, ph_out, sizeof(phonemes_repeat)); - phonemes_repeat_count = 1; + strncpy0(tr->phonemes_repeat, ph_out, sizeof(tr->phonemes_repeat)); + tr->phonemes_repeat_count = 1; } } else { - phonemes_repeat_count = 0; + tr->phonemes_repeat_count = 0; } @@ -3182,8 +3202,8 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags int letter; word2 = word; if(*word2 == '_') word2++; - len = utf8_in(&letter, word2, 0); - LookupAccentedLetter(letter, ph_out); + len = utf8_in(&letter, word2); + LookupAccentedLetter(tr,letter, ph_out); found = word2 + len; } @@ -3197,21 +3217,21 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags { // try removing an 'e' which has been added by RemoveEnding word[length-1] = 0; - found = LookupDict2(word, word1, ph_out, flags, end_flags, wtab); + found = LookupDict2(tr, word, word1, ph_out, flags, end_flags, wtab); } else if((end_flags & SUFX_D) && (word[length-1] == word[length-2])) { // try removing a double letter word[length-1] = 0; - found = LookupDict2(word, word1, ph_out, flags, end_flags, wtab); + found = LookupDict2(tr, word, word1, ph_out, flags, end_flags, wtab); } } if(found) { // if textmode is the default, then words which have phonemes are marked. - if(langopts.textmode) + if(tr->langopts.textmode) *flags ^= FLAG_TEXTMODE; if(*flags & FLAG_TEXTMODE) @@ -3250,18 +3270,18 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags -int Translator::Lookup(const char *word, char *ph_out) +int Lookup(Translator *tr, const char *word, char *ph_out) {//=================================================== unsigned int flags[2]; flags[0] = flags[1] = 0; char *word1 = (char *)word; - return(LookupDictList(&word1, ph_out, flags, 0, NULL)); + return(LookupDictList(tr, &word1, ph_out, flags, 0, NULL)); } -int Translator::RemoveEnding(char *word, int end_type, char *word_copy) -{//==================================================================== +int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy) +{//======================================================================== /* Removes a standard suffix from a word, once it has been indicated by the dictionary rules. end_type: bits 0-6 number of letters bits 8-14 suffix flags @@ -3331,7 +3351,7 @@ int Translator::RemoveEnding(char *word, int end_type, char *word_copy) if(end_type & SUFX_E) { // add 'e' to end of stem - if(IsLetter(word_end[-1],LETTERGP_VOWEL2) && IsLetter(word_end[0],1)) + if(IsLetter(tr, word_end[-1],LETTERGP_VOWEL2) && IsLetter(tr, word_end[0],1)) { // vowel(incl.'y') + hard.consonant @@ -3371,8 +3391,8 @@ if(option_phonemes == 2) } } - if((end_type & SUFX_V) && (expect_verb==0)) - expect_verb = 1; // this suffix indicates the verb pronunciation + if((end_type & SUFX_V) && (tr->expect_verb==0)) + tr->expect_verb = 1; // this suffix indicates the verb pronunciation if((strcmp(ending,"s")==0) || (strcmp(ending,"es")==0)) diff --git a/src/event.cpp b/src/event.cpp index bcb75ef1..cc696272 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -109,7 +109,7 @@ void event_init(void) } //> //TranslateWord(&word2[1],0,&winfo); + TranslateWord(translator,&word2[1],0,&winfo); - DecodePhonemes2(translator->word_phonemes,phonemes); // also need to change some phoneme names + DecodePhonemes2(word_phonemes,phonemes); // also need to change some phoneme names if(strcmp(phonemes,pronounce2) == 0) { @@ -624,8 +625,8 @@ p_unicode = unicode; // translate memset(&winfo,0,sizeof(winfo)); - translator->TranslateWord(&word2[1],0,&winfo); - DecodePhonemes(translator->word_phonemes,phonemes); + TranslateWord(translator, &word2[1],0,&winfo); + DecodePhonemes(word_phonemes,phonemes); // find the stress position in the translation max_stress = 0; @@ -634,7 +635,7 @@ p_unicode = unicode; check_root = 0; ph = phoneme_tab[phonPAUSE]; - for(p=translator->word_phonemes; *p != 0; p++) + for(p=word_phonemes; *p != 0; p++) { ph = phoneme_tab[(unsigned int)*p]; if(ph == NULL) @@ -866,7 +867,7 @@ void CountWordFreq(wxString path, wcount **hashtab) n_chars = 0; for(k=0; k sleep_until_start_request_or_inactivity > ENTER"); int a_start_is_required=0; diff --git a/src/intonation.cpp b/src/intonation.cpp index e97f8d1f..6cc4f912 100755 --- a/src/intonation.cpp +++ b/src/intonation.cpp @@ -49,7 +49,7 @@ typedef struct { short pitch2; } SYLLABLE; -SYLLABLE *syllable_tab; +static SYLLABLE *syllable_tab; static int tone_pitch_env; /* used to return pitch envelope */ @@ -706,8 +706,8 @@ static int calc_pitches(int start, int end, int head_tone, int nucleus_tone) -void Translator::CalcPitches_Tone(int clause_tone) -{//=============================================== +static void CalcPitches_Tone(Translator *tr, int clause_tone) +{//========================================================== // clause_tone: 0=. 1=, 2=?, 3=! 4=none PHONEME_LIST *p; int ix; @@ -750,12 +750,12 @@ void Translator::CalcPitches_Tone(int clause_tone) phoneme_list[final_stressed].tone = 7; // language specific, changes to tones - if(translator_name == L('v','i')) + if(tr->translator_name == L('v','i')) { // LANG=vi p = &phoneme_list[final_stressed]; if(p->tone_ph == 0) - p->tone_ph = LookupPh("7"); // change default tone (tone 1) to falling tone at end of clause + p->tone_ph = PhonemeCode('7'); // change default tone (tone 1) to falling tone at end of clause } @@ -785,18 +785,18 @@ void Translator::CalcPitches_Tone(int clause_tone) tph = phoneme_tab[tone_ph]; // Mandarin - if(translator_name == L('z','h')) + if(tr->translator_name == L('z','h')) { if(tone_ph == 0) { if(pause || tone_promoted) { - tone_ph = LookupPh("55"); // no previous vowel, use tone 1 + tone_ph = PhonemeCode2('5','5'); // no previous vowel, use tone 1 tone_promoted = 1; } else { - tone_ph = LookupPh("11"); // default tone 5 + tone_ph = PhonemeCode2('1','1'); // default tone 5 } p->tone_ph = tone_ph; @@ -820,24 +820,24 @@ void Translator::CalcPitches_Tone(int clause_tone) if(prevw_tph->mnemonic == 0x343132) // [214] { if(tph->mnemonic == 0x343132) // [214] - prev_p->tone_ph = LookupPh("35"); + prev_p->tone_ph = PhonemeCode2('3','5'); else - prev_p->tone_ph = LookupPh("21"); + prev_p->tone_ph = PhonemeCode2('2','1'); } if((prev_tph->mnemonic == 0x3135) && (tph->mnemonic == 0x3135)) // [51] + [51] { - prev_p->tone_ph = LookupPh("53"); + prev_p->tone_ph = PhonemeCode2('5','3'); } if(tph->mnemonic == 0x3131) // [11] Tone 5 { // tone 5, change its level depending on the previous tone (across word boundaries) if(prevw_tph->mnemonic == 0x3535) - p->tone_ph = LookupPh("22"); + p->tone_ph = PhonemeCode2('2','2'); if(prevw_tph->mnemonic == 0x3533) - p->tone_ph = LookupPh("33"); + p->tone_ph = PhonemeCode2('3','3'); if(prevw_tph->mnemonic == 0x343132) - p->tone_ph = LookupPh("44"); + p->tone_ph = PhonemeCode2('4','4'); // tone 5 is unstressed (shorter) p->tone = 1; // diminished stress @@ -889,8 +889,8 @@ void Translator::CalcPitches_Tone(int clause_tone) -void Translator::CalcPitches(int clause_type) -{//========================================== +void CalcPitches(Translator *tr, int clause_type) +{//============================================== // clause_type: 0=. 1=, 2=?, 3=! 4=none PHONEME_LIST *p; SYLLABLE *syl; @@ -942,20 +942,20 @@ void Translator::CalcPitches(int clause_type) - if(langopts.tone_language == 1) + if(tr->langopts.tone_language == 1) { - CalcPitches_Tone(clause_type); + CalcPitches_Tone(tr,clause_type); return; } - option = langopts.intonation_group; + option = tr->langopts.intonation_group; if(option >= INTONATION_TYPES) option = 0; - group_tone = punct_to_tone[option][clause_type]; - group_tone_emph = punct_to_tone[option][5]; // emphatic form of statement - group_tone_comma = punct_to_tone[option][1]; // emphatic form of statement + group_tone = tr->punct_to_tone[option][clause_type]; + group_tone_emph = tr->punct_to_tone[option][5]; // emphatic form of statement + group_tone_comma = tr->punct_to_tone[option][1]; // emphatic form of statement if(clause_type == 4) no_tonic = 1; /* incomplete clause, used for abbreviations such as Mr. Dr. Mrs. */ diff --git a/src/klatt.cpp b/src/klatt.cpp index 1a9c480d..da0baaa0 100644 --- a/src/klatt.cpp +++ b/src/klatt.cpp @@ -223,7 +223,7 @@ Converts synthesis parameters to a waveform. */ -int parwave(klatt_frame_ptr frame) +static int parwave(klatt_frame_ptr frame) { double temp; double outbypas; @@ -489,7 +489,7 @@ Initialises all parameters used in parwave, sets resonator internal memory to zero. */ -void reset_resonators() +static void reset_resonators() { int r_ix; @@ -500,7 +500,7 @@ void reset_resonators() } } -void parwave_init() +static void parwave_init() { kt_globals.FLPhz = (950 * kt_globals.samrate) / 10000; kt_globals.BLPhz = (630 * kt_globals.samrate) / 10000; diff --git a/src/numbers.cpp b/src/numbers.cpp index f1e761a0..32963a12 100644 --- a/src/numbers.cpp +++ b/src/numbers.cpp @@ -71,7 +71,7 @@ int flags; } ACCENTS; // these are tokens to look up in the *_list file. -ACCENTS accents_tab[] = { +static ACCENTS accents_tab[] = { {"_lig", 1}, {"_smc", 1}, // smallcap {"_tur", 1}, // turned @@ -126,7 +126,7 @@ static const short non_ascii_tab[] = { // characters U+00e0 to U+017f -const unsigned short letter_accents_0e0[] = { +static const unsigned short letter_accents_0e0[] = { LETTER('a',M_GRAVE,0), // U+00e0 LETTER('a',M_ACUTE,0), LETTER('a',M_CIRCUMFLEX,0), @@ -291,7 +291,7 @@ LETTER('s',M_NAME,0), // long-s // U+17f // characters U+0250 to U+029F -const unsigned short letter_accents_250[] = { +static const unsigned short letter_accents_250[] = { LETTER('a',M_TURNED,0), // U+250 LETTER(L_ALPHA,0,0), LETTER(L_ALPHA,M_TURNED,0), @@ -383,8 +383,8 @@ LIGATURE('t','s',0), LIGATURE('t','s',M_CURL), }; -int Translator::LookupLetter2(unsigned int letter, char *ph_buf) -{//============================================================= +static int LookupLetter2(Translator *tr, unsigned int letter, char *ph_buf) +{//======================================================================== int len; char single_letter[10]; @@ -394,20 +394,20 @@ int Translator::LookupLetter2(unsigned int letter, char *ph_buf) single_letter[len+2] = ' '; single_letter[len+3] = 0; - if(Lookup(&single_letter[1],ph_buf) == 0) + if(Lookup(tr, &single_letter[1], ph_buf) == 0) { single_letter[1] = ' '; - if(Lookup(&single_letter[2],ph_buf) == 0) + if(Lookup(tr, &single_letter[2], ph_buf) == 0) { - TranslateRules(&single_letter[2], ph_buf, 20, NULL,0,NULL); + TranslateRules(tr, &single_letter[2], ph_buf, 20, NULL,0,NULL); } } return(ph_buf[0]); } -void Translator::LookupAccentedLetter(unsigned int letter, char *ph_buf) -{//===================================================================== +void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf) +{//========================================================================= // lookup the character in the accents table int accent_data = 0; int accent1 = 0; @@ -450,14 +450,14 @@ void Translator::LookupAccentedLetter(unsigned int letter, char *ph_buf) } - if(Lookup(accents_tab[accent1].name, ph_accent1) != 0) + if(Lookup(tr, accents_tab[accent1].name, ph_accent1) != 0) { - if(LookupLetter2(basic_letter, ph_letter1) != 0) + if(LookupLetter2(tr, basic_letter, ph_letter1) != 0) { if(accent2 != 0) { - if(Lookup(accents_tab[accent2].name, ph_accent2) == 0) + if(Lookup(tr, accents_tab[accent2].name, ph_accent2) == 0) { // break; } @@ -472,7 +472,7 @@ void Translator::LookupAccentedLetter(unsigned int letter, char *ph_buf) if(letter2 != 0) { //ligature - LookupLetter2(letter2, ph_letter2); + LookupLetter2(tr, letter2, ph_letter2); sprintf(ph_buf,"%s%c%s%c%s%s",ph_accent1, phonPAUSE_VSHORT, ph_letter1, phonSTRESS_P, ph_letter2, ph_accent2); } else @@ -480,7 +480,7 @@ void Translator::LookupAccentedLetter(unsigned int letter, char *ph_buf) if(accent1 == 0) strcpy(ph_buf, ph_letter1); else - if((langopts.accents & 1) || (accents_tab[accent1].flags & 1)) + if((tr->langopts.accents & 1) || (accents_tab[accent1].flags & 1)) sprintf(ph_buf,"%s%c%c%s", ph_accent1, phonPAUSE_VSHORT, phonSTRESS_P, ph_letter1); else sprintf(ph_buf,"%c%s%c%s%c", phonSTRESS_2, ph_letter1, phonPAUSE_VSHORT, ph_accent1, phonPAUSE_VSHORT); @@ -492,8 +492,8 @@ void Translator::LookupAccentedLetter(unsigned int letter, char *ph_buf) -void Translator::LookupLetter(unsigned int letter, int next_byte, char *ph_buf1) -{//============================================================================= +void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf1) +{//================================================================================= int len; unsigned char *p; static char single_letter[10] = {0,0}; @@ -509,16 +509,16 @@ void Translator::LookupLetter(unsigned int letter, int next_byte, char *ph_buf1) if(next_byte == -1) { // speaking normal text, not individual characters - if(Lookup(&single_letter[2],ph_buf1) != 0) + if(Lookup(tr, &single_letter[2], ph_buf1) != 0) return; single_letter[1] = '_'; - if(Lookup(&single_letter[1],ph_buf3) != 0) + if(Lookup(tr, &single_letter[1], ph_buf3) != 0) return; // the character is specified as _* so ignore it when speaking normal text // check whether this character is specified for English SetTranslator2("en"); - if(translator2->Lookup(&single_letter[2], ph_buf3) != 0) + if(Lookup(translator2, &single_letter[2], ph_buf3) != 0) { // yes, switch to English and re-translate the word sprintf(ph_buf1,"%c",phonSWITCH); @@ -531,7 +531,7 @@ void Translator::LookupLetter(unsigned int letter, int next_byte, char *ph_buf1) { // lookup space as _&32 etc. sprintf(&single_letter[1],"_#%d ",letter); - Lookup(&single_letter[1],ph_buf1); + Lookup(tr, &single_letter[1], ph_buf1); return; } @@ -545,18 +545,18 @@ void Translator::LookupLetter(unsigned int letter, int next_byte, char *ph_buf1) dict_flags[1] = 0; ptr = &single_letter[1]; - if(Lookup(&single_letter[1],ph_buf3) == 0) + if(Lookup(tr, &single_letter[1], ph_buf3) == 0) { single_letter[1] = ' '; - if(Lookup(&single_letter[2],ph_buf3) == 0) + if(Lookup(tr, &single_letter[2], ph_buf3) == 0) { - TranslateRules(&single_letter[2], ph_buf3, sizeof(ph_buf3), NULL,FLAG_NO_TRACE,NULL); + TranslateRules(tr, &single_letter[2], ph_buf3, sizeof(ph_buf3), NULL,FLAG_NO_TRACE,NULL); } } if(ph_buf3[0] == 0) { - LookupAccentedLetter(letter, ph_buf3); + LookupAccentedLetter(tr, letter, ph_buf3); } if(ph_buf3[0] == 0) @@ -583,7 +583,7 @@ void Translator::LookupLetter(unsigned int letter, int next_byte, char *ph_buf1) -int Translator::TranslateLetter(char *word, char *phonemes, int control, int word_length) +int TranslateLetter(Translator *tr, char *word, char *phonemes, int control, int word_length) {//====================================================================================== // get pronunciation for an isolated letter // return number of bytes used by the letter @@ -602,7 +602,7 @@ int Translator::TranslateLetter(char *word, char *phonemes, int control, int wor ph_buf[0] = 0; capital[0] = 0; - n_bytes = utf8_in(&letter,word,0); + n_bytes = utf8_in(&letter,word); if((letter & 0xfff00) == 0x0e000) { @@ -614,12 +614,12 @@ int Translator::TranslateLetter(char *word, char *phonemes, int control, int wor // include CAPITAL information if(iswupper(letter)) { - Lookup("_cap",capital); + Lookup(tr, "_cap", capital); } } letter = towlower2(letter); - LookupLetter(letter, word[n_bytes], ph_buf); + LookupLetter(tr, letter, word[n_bytes], ph_buf); if(ph_buf[0] == phonSWITCH) { @@ -627,13 +627,13 @@ int Translator::TranslateLetter(char *word, char *phonemes, int control, int wor return(0); } - if((ph_buf[0] == 0) && (translator_name != L('e','n'))) + if((ph_buf[0] == 0) && (tr->translator_name != L('e','n'))) { // speak as English, check whether there is a translation for this character SetTranslator2("en"); save_option_phonemes = option_phonemes; option_phonemes = 0; - translator2->LookupLetter(letter, word[n_bytes], ph_buf); + LookupLetter(translator2, letter, word[n_bytes], ph_buf); SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table option_phonemes = save_option_phonemes; @@ -648,10 +648,10 @@ int Translator::TranslateLetter(char *word, char *phonemes, int control, int wor { // character name not found if(iswalpha(letter)) - Lookup("_?A",ph_buf); + Lookup(tr, "_?A", ph_buf); if((ph_buf[0]==0) && !iswspace(letter)) - Lookup("_??",ph_buf); + Lookup(tr, "_??", ph_buf); if(ph_buf[0] != 0) { @@ -662,13 +662,13 @@ int Translator::TranslateLetter(char *word, char *phonemes, int control, int wor { pbuf += strlen(pbuf); *pbuf++ = phonPAUSE_VSHORT; - LookupLetter(*p2, 0, pbuf); + LookupLetter(tr, *p2, 0, pbuf); } } } len = strlen(phonemes); - if(langopts.accents & 2) + if(tr->langopts.accents & 2) sprintf(ph_buf2,"%c%s%s",0xff,ph_buf,capital); else sprintf(ph_buf2,"%c%s%s",0xff,capital,ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress() @@ -681,8 +681,8 @@ int Translator::TranslateLetter(char *word, char *phonemes, int control, int wor -void Translator::SetSpellingStress(char *phonemes, int control, int n_chars) -{//========================================================================= +void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars) +{//============================================================================= // Individual letter names, reduce the stress of some. int ix; unsigned int c; @@ -707,7 +707,7 @@ void Translator::SetSpellingStress(char *phonemes, int control, int n_chars) { count++; - if(langopts.spelling_stress == 1) + if(tr->langopts.spelling_stress == 1) { // stress on initial letter when spelling if(count > 1) @@ -745,7 +745,7 @@ void Translator::SetSpellingStress(char *phonemes, int control, int n_chars) -int Translator::TranslateRoman(char *word, char *ph_out) +int TranslateRoman(Translator *tr, char *word, char *ph_out) {//===================================================== int c; char *p; @@ -804,288 +804,27 @@ int Translator::TranslateRoman(char *word, char *ph_out) if(acc < 2) return(0); - if(acc > langopts.max_roman) + if(acc > tr->langopts.max_roman) return(0); - Lookup("_roman",ph_roman); // precede by "roman" if _rom is defined in *_list + Lookup(tr, "_roman",ph_roman); // precede by "roman" if _rom is defined in *_list p = &ph_out[0]; - if((langopts.numbers & NUM_ROMAN_AFTER) == 0) + if((tr->langopts.numbers & NUM_ROMAN_AFTER) == 0) { strcpy(ph_out,ph_roman); p = &ph_out[strlen(ph_out)]; } sprintf(number_chars," %d ",acc); - TranslateNumber(&number_chars[1],p,&flags,0); + TranslateNumber(tr, &number_chars[1], p, &flags, 0); - if(langopts.numbers & NUM_ROMAN_AFTER) + if(tr->langopts.numbers & NUM_ROMAN_AFTER) strcat(ph_out,ph_roman); return(1); } // end of TranslateRoman -int Translator::LookupNum2(int value, int control, char *ph_out) -{//============================================================= -// Lookup a 2 digit number -// control bit 0: use special form of '1' -// control bit 2: use feminine form of '2' - - int found; - int ix; - int units; - int used_and=0; - int next_phtype; - char string[12]; // for looking up entries in de_list - char ph_tens[50]; - char ph_digits[50]; - char ph_and[12]; - - if((value == 1) && (control & 1)) - { - if(Lookup("_1a",ph_out) != 0) - return(0); - } - // is there a special pronunciation for this 2-digit number - found = 0; - if(control & 4) - { - sprintf(string,"_%df",value); - found = Lookup(string,ph_digits); - } - if(found == 0) - { - sprintf(string,"_%d",value); - found = Lookup(string,ph_digits); - } - - // no, speak as tens+units - if((control & 2) && (value < 10)) - { - // speak leading zero - Lookup("_0",ph_tens); - } - else - { - if(found) - { - strcpy(ph_out,ph_digits); - return(0); - } - - if((value % 10) == 0) - { - sprintf(string,"_%d0",value / 10); - found = Lookup(string,ph_tens); - } - if(!found) - { - sprintf(string,"_%dX",value / 10); - Lookup(string,ph_tens); - } - - if((value % 10) == 0) - { - strcpy(ph_out,ph_tens); - return(0); - } - - found = 0; - units = (value % 10); - if(control & 4) - { - // is there a variant form of this number? - sprintf(string,"_%df",units); - found = Lookup(string,ph_digits); - } - if(found == 0) - { - sprintf(string,"_%d",units); - Lookup(string,ph_digits); - } - } - - if(langopts.numbers & 0x30) - { - Lookup("_0and",ph_and); - if(langopts.numbers & 0x10) - sprintf(ph_out,"%s%s%s",ph_digits,ph_and,ph_tens); - else - sprintf(ph_out,"%s%s%s",ph_tens,ph_and,ph_digits); - used_and = 1; - } - else - { - if(langopts.numbers & 0x200) - { - // remove vowel from the end of tens if units starts with a vowel (LANG=Italian) - if((ix = strlen(ph_tens)-1) >= 0) - { - if((next_phtype = phoneme_tab[(unsigned int)(ph_digits[0])]->type) == phSTRESS) - next_phtype = phoneme_tab[(unsigned int)(ph_digits[1])]->type; - - if((phoneme_tab[(unsigned int)(ph_tens[ix])]->type == phVOWEL) && (next_phtype == phVOWEL)) - ph_tens[ix] = 0; - } - } - sprintf(ph_out,"%s%s",ph_tens,ph_digits); - } - - if(langopts.numbers & 0x100) - { - // only one primary stress - found = 0; - for(ix=strlen(ph_out)-1; ix>=0; ix--) - { - if(ph_out[ix] == phonSTRESS_P) - { - if(found) - ph_out[ix] = phonSTRESS_3; - else - found = 1; - } - } - } - return(used_and); -} // end of LookupNum2 - - -int Translator::LookupNum3(int value, char *ph_out, int suppress_null, int thousandplex, int prev_thousands) -{//========================================================================================================= -// Translate a 3 digit number - int found; - int hundreds; - int x; - char string[12]; // for looking up entries in **_list - char buf1[100]; - char buf2[100]; - char ph_100[20]; - char ph_10T[20]; - char ph_digits[50]; - char ph_thousands[50]; - char ph_hundred_and[12]; - char ph_thousand_and[12]; - - hundreds = value / 100; - buf1[0] = 0; - - if(hundreds > 0) - { - ph_thousands[0] = 0; - ph_thousand_and[0] = 0; - - Lookup("_0C",ph_100); - - if(((langopts.numbers & 0x0800) != 0) && (hundreds == 19)) - { - // speak numbers such as 1984 as years: nineteen-eighty-four -// ph_100[0] = 0; // don't say "hundred", we also need to surpess "and" - } - else - if(hundreds >= 10) - { - ph_digits[0] = 0; - - if(LookupThousands(hundreds / 10, thousandplex+1, ph_10T) == 0) - { - x = 0; - if(langopts.numbers2 & (1 << (thousandplex+1))) - x = 4; - LookupNum2(hundreds/10, x, ph_digits); - } - - if(langopts.numbers2 & 0x200) - sprintf(ph_thousands,"%s%s%c",ph_10T,ph_digits,phonPAUSE_NOLINK); // say "thousands" before its number, not after - else - sprintf(ph_thousands,"%s%s%c",ph_digits,ph_10T,phonPAUSE_NOLINK); - - hundreds %= 10; - if(hundreds == 0) - ph_100[0] = 0; - suppress_null = 1; - } - - ph_digits[0] = 0; - if(hundreds > 0) - { - if((langopts.numbers & 0x100000) && (prev_thousands || (ph_thousands[0] != 0))) - { - Lookup("_0and",ph_thousand_and); - } - - suppress_null = 1; - - found = 0; - if((value % 1000) == 100) - { - // is there a special pronunciation for exactly 100 ? - found = Lookup("_1C0",ph_digits); - } - if(!found) - { - sprintf(string,"_%dC",hundreds); - found = Lookup(string,ph_digits); // is there a specific pronunciation for n-hundred ? - } - - if(found) - { - ph_100[0] = 0; - } - else - { - if((hundreds > 1) || ((langopts.numbers & 0x400) == 0)) - { - LookupNum2(hundreds,0,ph_digits); - } - } - } - - sprintf(buf1,"%s%s%s%s",ph_thousands,ph_thousand_and,ph_digits,ph_100); - } - - ph_hundred_and[0] = 0; - if((langopts.numbers & 0x40) && ((value % 100) != 0)) - { - if((value > 100) || (prev_thousands && (thousandplex==0))) - { - Lookup("_0and",ph_hundred_and); - } - } - - - buf2[0] = 0; - value = value % 100; - - if(value == 0) - { - if(suppress_null == 0) - Lookup("_0",buf2); - } - else - { - x = 0; - if(thousandplex==0) - x = 1; // allow "eins" for 1 rather than "ein" - else - { - if(langopts.numbers2 & (1 << thousandplex)) - x = 4; // use variant (feminine) for before thousands and millions - } - - if(LookupNum2(value,x,buf2) != 0) - { - if(langopts.numbers & 0x80) - ph_hundred_and[0] = 0; // don't put 'and' after 'hundred' if there's 'and' between tens and units - } - } - - sprintf(ph_out,"%s%s%s",buf1,ph_hundred_and,buf2); - - return(0); -} // end of LookupNum3 - - - static const char *M_Variant(int value) {//==================================== // returns M, or perhaps MA for some cases @@ -1111,8 +850,8 @@ static const char *M_Variant(int value) } -int Translator::LookupThousands(int value, int thousandplex, char *ph_out) -{//======================================================================= +static int LookupThousands(Translator *tr, int value, int thousandplex, char *ph_out) +{//================================================================================== int found; char string[12]; char ph_of[12]; @@ -1123,21 +862,21 @@ int Translator::LookupThousands(int value, int thousandplex, char *ph_out) // first look fora match with the exact value of thousands sprintf(string,"_%dM%d",value,thousandplex); - if((found = Lookup(string,ph_thousands)) == 0) + if((found = Lookup(tr, string, ph_thousands)) == 0) { if((value % 100) >= 20) { - Lookup("_0of",ph_of); + Lookup(tr, "_0of", ph_of); } sprintf(string,"_%s%d",M_Variant(value),thousandplex); - if(Lookup(string,ph_thousands) == 0) + if(Lookup(tr, string, ph_thousands) == 0) { // repeat "thousand" if higher order names are not available sprintf(string,"_%dM1",value); - if((found = Lookup(string,ph_thousands)) == 0) - Lookup("_0M1",ph_thousands); + if((found = Lookup(tr, string, ph_thousands)) == 0) + Lookup(tr, "_0M1", ph_thousands); } } sprintf(ph_out,"%s%s",ph_of,ph_thousands); @@ -1145,8 +884,269 @@ int Translator::LookupThousands(int value, int thousandplex, char *ph_out) } -int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, int wflags) -{//========================================================================================= +static int LookupNum2(Translator *tr, int value, int control, char *ph_out) +{//======================================================================== +// Lookup a 2 digit number +// control bit 0: use special form of '1' +// control bit 2: use feminine form of '2' + + int found; + int ix; + int units; + int used_and=0; + int next_phtype; + char string[12]; // for looking up entries in de_list + char ph_tens[50]; + char ph_digits[50]; + char ph_and[12]; + + if((value == 1) && (control & 1)) + { + if(Lookup(tr, "_1a", ph_out) != 0) + return(0); + } + // is there a special pronunciation for this 2-digit number + found = 0; + if(control & 4) + { + sprintf(string,"_%df",value); + found = Lookup(tr, string, ph_digits); + } + if(found == 0) + { + sprintf(string,"_%d",value); + found = Lookup(tr, string, ph_digits); + } + + // no, speak as tens+units + if((control & 2) && (value < 10)) + { + // speak leading zero + Lookup(tr, "_0", ph_tens); + } + else + { + if(found) + { + strcpy(ph_out,ph_digits); + return(0); + } + + if((value % 10) == 0) + { + sprintf(string,"_%d0",value / 10); + found = Lookup(tr, string, ph_tens); + } + if(!found) + { + sprintf(string,"_%dX",value / 10); + Lookup(tr, string, ph_tens); + } + + if((value % 10) == 0) + { + strcpy(ph_out,ph_tens); + return(0); + } + + found = 0; + units = (value % 10); + if(control & 4) + { + // is there a variant form of this number? + sprintf(string,"_%df",units); + found = Lookup(tr, string, ph_digits); + } + if(found == 0) + { + sprintf(string,"_%d",units); + Lookup(tr, string, ph_digits); + } + } + + if(tr->langopts.numbers & 0x30) + { + Lookup(tr, "_0and", ph_and); + if(tr->langopts.numbers & 0x10) + sprintf(ph_out,"%s%s%s",ph_digits,ph_and,ph_tens); + else + sprintf(ph_out,"%s%s%s",ph_tens,ph_and,ph_digits); + used_and = 1; + } + else + { + if(tr->langopts.numbers & 0x200) + { + // remove vowel from the end of tens if units starts with a vowel (LANG=Italian) + if((ix = strlen(ph_tens)-1) >= 0) + { + if((next_phtype = phoneme_tab[(unsigned int)(ph_digits[0])]->type) == phSTRESS) + next_phtype = phoneme_tab[(unsigned int)(ph_digits[1])]->type; + + if((phoneme_tab[(unsigned int)(ph_tens[ix])]->type == phVOWEL) && (next_phtype == phVOWEL)) + ph_tens[ix] = 0; + } + } + sprintf(ph_out,"%s%s",ph_tens,ph_digits); + } + + if(tr->langopts.numbers & 0x100) + { + // only one primary stress + found = 0; + for(ix=strlen(ph_out)-1; ix>=0; ix--) + { + if(ph_out[ix] == phonSTRESS_P) + { + if(found) + ph_out[ix] = phonSTRESS_3; + else + found = 1; + } + } + } + return(used_and); +} // end of LookupNum2 + + +static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int prev_thousands) +{//==================================================================================================================== +// Translate a 3 digit number + int found; + int hundreds; + int x; + char string[12]; // for looking up entries in **_list + char buf1[100]; + char buf2[100]; + char ph_100[20]; + char ph_10T[20]; + char ph_digits[50]; + char ph_thousands[50]; + char ph_hundred_and[12]; + char ph_thousand_and[12]; + + hundreds = value / 100; + buf1[0] = 0; + + if(hundreds > 0) + { + ph_thousands[0] = 0; + ph_thousand_and[0] = 0; + + Lookup(tr, "_0C", ph_100); + + if(((tr->langopts.numbers & 0x0800) != 0) && (hundreds == 19)) + { + // speak numbers such as 1984 as years: nineteen-eighty-four +// ph_100[0] = 0; // don't say "hundred", we also need to surpess "and" + } + else + if(hundreds >= 10) + { + ph_digits[0] = 0; + + if(LookupThousands(tr, hundreds / 10, thousandplex+1, ph_10T) == 0) + { + x = 0; + if(tr->langopts.numbers2 & (1 << (thousandplex+1))) + x = 4; + LookupNum2(tr, hundreds/10, x, ph_digits); + } + + if(tr->langopts.numbers2 & 0x200) + sprintf(ph_thousands,"%s%s%c",ph_10T,ph_digits,phonPAUSE_NOLINK); // say "thousands" before its number, not after + else + sprintf(ph_thousands,"%s%s%c",ph_digits,ph_10T,phonPAUSE_NOLINK); + + hundreds %= 10; + if(hundreds == 0) + ph_100[0] = 0; + suppress_null = 1; + } + + ph_digits[0] = 0; + if(hundreds > 0) + { + if((tr->langopts.numbers & 0x100000) && (prev_thousands || (ph_thousands[0] != 0))) + { + Lookup(tr, "_0and", ph_thousand_and); + } + + suppress_null = 1; + + found = 0; + if((value % 1000) == 100) + { + // is there a special pronunciation for exactly 100 ? + found = Lookup(tr, "_1C0", ph_digits); + } + if(!found) + { + sprintf(string,"_%dC",hundreds); + found = Lookup(tr, string, ph_digits); // is there a specific pronunciation for n-hundred ? + } + + if(found) + { + ph_100[0] = 0; + } + else + { + if((hundreds > 1) || ((tr->langopts.numbers & 0x400) == 0)) + { + LookupNum2(tr, hundreds, 0, ph_digits); + } + } + } + + sprintf(buf1,"%s%s%s%s",ph_thousands,ph_thousand_and,ph_digits,ph_100); + } + + ph_hundred_and[0] = 0; + if((tr->langopts.numbers & 0x40) && ((value % 100) != 0)) + { + if((value > 100) || (prev_thousands && (thousandplex==0))) + { + Lookup(tr, "_0and", ph_hundred_and); + } + } + + + buf2[0] = 0; + value = value % 100; + + if(value == 0) + { + if(suppress_null == 0) + Lookup(tr, "_0", buf2); + } + else + { + x = 0; + if(thousandplex==0) + x = 1; // allow "eins" for 1 rather than "ein" + else + { + if(tr->langopts.numbers2 & (1 << thousandplex)) + x = 4; // use variant (feminine) for before thousands and millions + } + + if(LookupNum2(tr, value, x, buf2) != 0) + { + if(tr->langopts.numbers & 0x80) + ph_hundred_and[0] = 0; // don't put 'and' after 'hundred' if there's 'and' between tens and units + } + } + + sprintf(ph_out,"%s%s%s",buf1,ph_hundred_and,buf2); + + return(0); +} // end of LookupNum3 + + + +static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, int wflags) +{//==================================================================================================== // 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 @@ -1180,12 +1180,12 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, ph_buf2[0] = 0; // is there a previous thousands part (as a previous "word") ? - if((n_digits == 3) && (word[-2] == langopts.thousands_sep) && isdigit(word[-3])) + if((n_digits == 3) && (word[-2] == tr->langopts.thousands_sep) && isdigit(word[-3])) { prev_thousands = 1; } else - if((langopts.thousands_sep == ' ') || (langopts.numbers & 0x1000)) + if((tr->langopts.thousands_sep == ' ') || (tr->langopts.numbers & 0x1000)) { // thousands groups can be separated by spaces if((n_digits == 3) && isdigit(word[-2])) @@ -1194,7 +1194,7 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, } } - if((word[0] == '0') && (prev_thousands == 0) && (word[1] != langopts.decimal_sep)) + if((word[0] == '0') && (prev_thousands == 0) && (word[1] != tr->langopts.decimal_sep)) { if((n_digits == 2) && (word[3] == ':') && isdigit(word[5]) && isspace(word[7])) { @@ -1206,10 +1206,10 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, } } - if((langopts.numbers & 0x1000) && (word[n_digits] == ' ')) + if((tr->langopts.numbers & 0x1000) && (word[n_digits] == ' ')) thousands_inc = 1; else - if(word[n_digits] == langopts.thousands_sep) + if(word[n_digits] == tr->langopts.thousands_sep) thousands_inc = 2; if(thousands_inc > 0) @@ -1221,7 +1221,7 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, while(isdigit(word[ix]) && isdigit(word[ix+1]) && isdigit(word[ix+2])) { thousandplex++; - if(word[ix+3] == langopts.thousands_sep) + if(word[ix+3] == tr->langopts.thousands_sep) ix += (3 + thousands_inc); else break; @@ -1233,10 +1233,10 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, suppress_null = 1; } - if((word[n_digits] == langopts.decimal_sep) && isdigit(word[n_digits+1])) + if((word[n_digits] == tr->langopts.decimal_sep) && isdigit(word[n_digits+1])) { // this "word" ends with a decimal point - Lookup("_dpt",ph_append); + Lookup(tr, "_dpt", ph_append); decimal_point = 1; } else @@ -1246,7 +1246,7 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, { if((thousandplex > 0) && (value < 1000)) { - if((suppress_null == 0) && (LookupThousands(value,thousandplex,ph_append))) + if((suppress_null == 0) && (LookupThousands(tr,value,thousandplex,ph_append))) { // found an exact match for N thousand value = 0; @@ -1259,21 +1259,21 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, if((thousandplex > 1) && prev_thousands && (prev_value > 0)) { sprintf(string,"_%s%d",M_Variant(value),thousandplex+1); - if(Lookup(string,buf1)==0) + if(Lookup(tr, string, buf1)==0) { // speak this thousandplex if there was no word for the previous thousandplex sprintf(string,"_0M%d",thousandplex); - Lookup(string,ph_append); + Lookup(tr, string, ph_append); } } if((ph_append[0] == 0) && (word[n_digits] == '.') && (thousandplex == 0)) { - Lookup("_.",ph_append); + Lookup(tr, "_.", ph_append); } - LookupNum3(value, ph_buf, suppress_null, thousandplex, prev_thousands); - if((thousandplex > 0) && (langopts.numbers2 & 0x200)) + LookupNum3(tr, value, ph_buf, suppress_null, thousandplex, prev_thousands); + if((thousandplex > 0) && (tr->langopts.numbers2 & 0x200)) sprintf(ph_out,"%s%s%s",ph_append,ph_buf2,ph_buf); // say "thousands" before its number else sprintf(ph_out,"%s%s%s",ph_buf2,ph_buf,ph_append); @@ -1290,7 +1290,7 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, if(decimal_count > 1) { max_decimal_count = 2; - switch(langopts.numbers & 0xe000) + switch(tr->langopts.numbers & 0xe000) { case 0x8000: max_decimal_count = 5; @@ -1298,14 +1298,14 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, // French/Polish decimal fraction while(word[n_digits] == '0') { - Lookup("_0",buf1); + Lookup(tr, "_0", buf1); strcat(ph_out,buf1); decimal_count--; n_digits++; } if((decimal_count <= max_decimal_count) && isdigit(word[n_digits])) { - LookupNum3(atoi(&word[n_digits]),buf1,0,0,0); + LookupNum3(tr, atoi(&word[n_digits]), buf1, 0,0,0); strcat(ph_out,buf1); n_digits += decimal_count; } @@ -1315,13 +1315,13 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, // Italian decimal fractions if((decimal_count < 4) || ((decimal_count==4) && (word[n_digits] != '0'))) { - LookupNum3(atoi(&word[n_digits]),buf1,0,0,0); + LookupNum3(tr, atoi(&word[n_digits]), buf1, 0,0,0); strcat(ph_out,buf1); if(word[n_digits]=='0') { // decimal part has leading zeros, so add a "hundredths" or "thousandths" suffix sprintf(string,"_0Z%d",decimal_count); - Lookup(string,buf1); + Lookup(tr, string, buf1); strcat(ph_out,buf1); } n_digits += decimal_count; @@ -1332,7 +1332,7 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, // Romanian decimal fractions if((decimal_count <= 4) && (word[n_digits] != '0')) { - LookupNum3(atoi(&word[n_digits]),buf1,0,0,0); + LookupNum3(tr, atoi(&word[n_digits]), buf1, 0,0,0); strcat(ph_out,buf1); n_digits += decimal_count; } @@ -1343,17 +1343,17 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, while(isdigit(c = word[n_digits]) && (strlen(ph_out) < (N_WORD_PHONEMES - 10))) { value = word[n_digits++] - '0'; - LookupNum2(value, 1, buf1); + LookupNum2(tr, value, 1, buf1); strcat(ph_out,buf1); } // something after the decimal part ? - if(Lookup("_dpt2",buf1)) + if(Lookup(tr, "_dpt2", buf1)) strcat(ph_out,buf1); - if((c == langopts.decimal_sep) && isdigit(word[n_digits+1])) + if((c == tr->langopts.decimal_sep) && isdigit(word[n_digits+1])) { - Lookup("_dpt",buf1); + Lookup(tr, "_dpt", buf1); strcat(ph_out,buf1); } else @@ -1367,9 +1367,9 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, char *p; p = &word[n_digits+1]; - p += utf8_in(&next_char,p,0); - if((langopts.numbers & NUM_NOPAUSE) && (next_char == ' ')) - utf8_in(&next_char,p,0); + p += utf8_in(&next_char,p); + if((tr->langopts.numbers & NUM_NOPAUSE) && (next_char == ' ')) + utf8_in(&next_char,p); if(!iswalpha(next_char)) strcat(ph_out,str_pause); // don't add pause for 100s, 6th, etc. @@ -1382,13 +1382,13 @@ int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, -int Translator::TranslateNumber(char *word1, char *ph_out, unsigned int *flags, int wflags) -{//======================================================================================= +int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, int wflags) +{//============================================================================================ if(option_sayas == SAYAS_DIGITS1) return(0); // speak digits individually - if((langopts.numbers & 0x3) == 1) - return(TranslateNumber_1(word1,ph_out,flags,wflags)); + if((tr->langopts.numbers & 0x3) == 1) + return(TranslateNumber_1(tr, word1, ph_out, flags, wflags)); return(0); } // end of TranslateNumber diff --git a/src/phoneme.h b/src/phoneme.h index 1294296d..8021e953 100755 --- a/src/phoneme.h +++ b/src/phoneme.h @@ -151,10 +151,16 @@ extern int n_replace_phonemes; extern REPLACE_PHONEMES replace_phonemes[N_REPLACE_PHONEMES]; +#define PH(c1,c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name +#define PH3(c1,c2,c3) (c3<<16)+(c2<<8)+c1 +#define PhonemeCode2(c1,c2) PhonemeCode((c2<<8)+c1) +int LookupPhonemeString(const char *string); +int PhonemeCode(unsigned int mnem); char *EncodePhonemes(char *p, char *outptr, unsigned char *bad_phoneme); void DecodePhonemes(const char *inptr, char *outptr); -const char *PhonemeTabName(void); -int LookupPh(const char *string); + extern const char *WordToString(unsigned int word); +extern PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS]; +extern int phoneme_tab_number; diff --git a/src/phonemelist.cpp b/src/phonemelist.cpp index 55a949c0..0c0fb902 100755 --- a/src/phonemelist.cpp +++ b/src/phonemelist.cpp @@ -33,16 +33,25 @@ const unsigned char pause_phonemes[8] = {0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG}; -int Translator::ChangePhonemes(PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) -{//====================================================================================================== +extern int n_ph_list2; +extern PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes + + + +static int ChangePhonemes(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) +{//================================================================================================================= // Called for each phoneme in the phoneme list, to allow a language to make changes // ph The current phoneme + + if(tr->translator_name == L('r','u')) + return(ChangePhonemes_ru(tr, phlist, n_ph, index, ph, ch)); + return(0); } -int Translator::SubstitutePhonemes(PHONEME_LIST2 *plist_out) -{//========================================================= +static int SubstitutePhonemes(Translator *tr, PHONEME_LIST2 *plist_out) +{//==================================================================== // Copy the phonemes list and perform any substitutions that are required for the // current voice int ix; @@ -77,7 +86,7 @@ int Translator::SubstitutePhonemes(PHONEME_LIST2 *plist_out) if((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE))) word_end = 1; // this phoneme is the end of a word - if(langopts.phoneme_change != 0) + if(tr->langopts.phoneme_change != 0) { // this language does changes to phonemes after translation @@ -134,7 +143,7 @@ int Translator::SubstitutePhonemes(PHONEME_LIST2 *plist_out) ch.vowel_this = syllable; ch.vowel_stressed = syllable_stressed; - ChangePhonemes(ph_list2, n_ph_list2, ix, phoneme_tab[ph_list2[ix].phcode], &ch); + ChangePhonemes(tr, ph_list2, n_ph_list2, ix, phoneme_tab[ph_list2[ix].phcode], &ch); } // check whether a Voice has specified that we should replace this phoneme @@ -172,8 +181,8 @@ int Translator::SubstitutePhonemes(PHONEME_LIST2 *plist_out) -void Translator::MakePhonemeList(int post_pause, int start_sentence) -{//============================================================================================ +void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) +{//===================================================================== int ix=0; int j; @@ -196,17 +205,18 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) PHONEME_LIST2 *plist2 = &ph_list2_null; PHONEME_LIST2 *plist2_inserted = NULL; + plist2 = ph_list2; phlist = phoneme_list; - end_sourceix = ph_list2[n_ph_list2-1].sourceix; + end_sourceix = plist2[n_ph_list2-1].sourceix; // is the last word of the clause unstressed ? max_stress = 0; - for(j=n_ph_list2-3; j>=0; j--) + for(j = n_ph_list2-3; j>=0; j--) { // start with the last phoneme (before the terminating pauses) and move forwards - if((ph_list2[j].stress & 0x7f) > max_stress) - max_stress = ph_list2[j].stress & 0x7f; - if(ph_list2[j].sourceix != 0) + if((plist2[j].stress & 0x7f) > max_stress) + max_stress = plist2[j].stress & 0x7f; + if(plist2[j].sourceix != 0) break; } if(max_stress < 4) @@ -214,12 +224,12 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) // the last word is unstressed, look for a previous word that can be stressed while(--j >= 0) { - if(ph_list2[j].synthflags & SFLAG_PROMOTE_STRESS) // dictionary flags indicated that this stress can be promoted + if(plist2[j].synthflags & SFLAG_PROMOTE_STRESS) // dictionary flags indicated that this stress can be promoted { - ph_list2[j].stress = 4; // promote to stressed + plist2[j].stress = 4; // promote to stressed break; } - if(ph_list2[j].stress >= 4) + if(plist2[j].stress >= 4) { // found a stressed syllable, so stop looking break; @@ -227,7 +237,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) } } - if((regression = langopts.param[LOPT_REGRESSIVE_VOICING]) != 0) + if((regression = tr->langopts.param[LOPT_REGRESSIVE_VOICING]) != 0) { // set consonant clusters to all voiced or all unvoiced // Regressive @@ -236,7 +246,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) for(j=n_ph_list2-1; j>=0; j--) { - ph = phoneme_tab[ph_list2[j].phcode]; + ph = phoneme_tab[plist2[j].phcode]; if(ph == NULL) continue; @@ -263,7 +273,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) else if((voicing==2) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING)) { - ph_list2[j].phcode = ph->alternative_ph; // change to voiced equivalent + plist2[j].phcode = ph->alternative_ph; // change to voiced equivalent } } else @@ -276,7 +286,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) else if((voicing==1) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING)) { - ph_list2[j].phcode = ph->alternative_ph; // change to unvoiced equivalent + plist2[j].phcode = ph->alternative_ph; // change to unvoiced equivalent } } else @@ -292,7 +302,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) voicing = 0; } } - if((regression & 0x4) && (ph_list2[j].sourceix)) + if((regression & 0x4) && (plist2[j].sourceix)) { // stop propagation at a word boundary voicing = 0; @@ -300,13 +310,13 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) } } - n_ph_list2 = SubstitutePhonemes(ph_list3) - 2; + n_ph_list2 = SubstitutePhonemes(tr,ph_list3) - 2; // transfer all the phonemes of the clause into phoneme_list ph = phoneme_tab[phonPAUSE]; switched_language = 0; - for(j=0; insert_ph || ((j 3) && ((plist2+1)->sourceix!=0))) + if((tr->langopts.stress_flags & 0x2) || ((word_stress > 3) && ((plist2+1)->sourceix!=0))) { // An unstressed final vowel of a stressed word unstress_count=1; // try again for next syllable @@ -444,7 +454,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) plist2->synthflags &= ~SFLAG_SYLLABLE; } - if(langopts.param[LOPT_REDUCE_T]) + if(tr->langopts.param[LOPT_REDUCE_T]) { if((ph->mnemonic == 't') && (plist2->sourceix == 0) && ((prev->type == phVOWEL) || (prev->mnemonic == 'n'))) { @@ -456,7 +466,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) } - while((ph->reduce_to != 0) && (!(plist2->synthflags & SFLAG_DICTIONARY) || (langopts.param[LOPT_REDUCE] & 1))) + while((ph->reduce_to != 0) && (!(plist2->synthflags & SFLAG_DICTIONARY) || (tr->langopts.param[LOPT_REDUCE] & 1))) { int reduce_level; int stress_level; @@ -486,7 +496,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) if(stress_level < reduce_level) reduce =1; - if((word_stress < 4) && (langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= word_stress)) + if((word_stress < 4) && (tr->langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= word_stress)) { // don't reduce the most stressed syllable in an unstressed word reduce = 0; @@ -516,10 +526,10 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) { int x; - if(langopts.vowel_pause && (ph->type != phPAUSE)) + if(tr->langopts.vowel_pause && (ph->type != phPAUSE)) { - if((ph->type != phVOWEL) && (langopts.vowel_pause & 0x200)) + if((ph->type != phVOWEL) && (tr->langopts.vowel_pause & 0x200)) { // add a pause after a word which ends in a consonant insert_ph = phonPAUSE_NOLINK; @@ -527,7 +537,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) if(next->type == phVOWEL) { - if((x = langopts.vowel_pause & 0x0c) != 0) + if((x = tr->langopts.vowel_pause & 0x0c) != 0) { // break before a word which starts with a vowel if(x == 0xc) @@ -536,7 +546,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) insert_ph = phonPAUSE_VSHORT; } - if((ph->type == phVOWEL) && ((x = langopts.vowel_pause & 0x03) != 0)) + if((ph->type == phVOWEL) && ((x = tr->langopts.vowel_pause & 0x03) != 0)) { // adjacent vowels over a word boundary if(x == 2) @@ -545,7 +555,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) insert_ph = phonPAUSE_VSHORT; } - if(((plist2+1)->stress >= 4) && (langopts.vowel_pause & 0x100)) + if(((plist2+1)->stress >= 4) && (tr->langopts.vowel_pause & 0x100)) { // pause before a words which starts with a stressed vowel insert_ph = phonPAUSE_SHORT; @@ -555,7 +565,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) if(plist2 != plist2_inserted) { - if((x = (langopts.word_gap & 0x7)) != 0) + if((x = (tr->langopts.word_gap & 0x7)) != 0) { if((x > 1) || ((insert_ph != phonPAUSE_SHORT) && (insert_ph != phonPAUSE_NOLINK))) { @@ -584,7 +594,7 @@ void Translator::MakePhonemeList(int post_pause, int start_sentence) } } else - if(((langopts.word_gap & 8)==0) || ((plist2+1)->sourceix == 0)) + if(((tr->langopts.word_gap & 8)==0) || ((plist2+1)->sourceix == 0)) { // This phoneme can be linked to a following vowel by inserting a linking phoneme if(next->type == phVOWEL) diff --git a/src/readclause.cpp b/src/readclause.cpp index 9372c352..582e8282 100644 --- a/src/readclause.cpp +++ b/src/readclause.cpp @@ -42,26 +42,26 @@ #define N_XML_BUF 256 -const char *xmlbase = ""; // base URL from +static const char *xmlbase = ""; // base URL from -int namedata_ix=0; -int n_namedata = 0; +static int namedata_ix=0; +static int n_namedata = 0; char *namedata = NULL; -FILE *f_input = NULL; -int ungot_char2 = 0; +static FILE *f_input = NULL; +static int ungot_char2 = 0; char *p_textinput; wchar_t *p_wchar_input; -int ungot_char; -const char *ungot_word = NULL; -int end_of_input; +static int ungot_char; +static const char *ungot_word = NULL; +static int end_of_input; -int ignore_text=0; // set during ... to ignore text which has been replaced by an alias -int clear_skipping_text = 0; // next clause should clear the skipping_text flag +static int ignore_text=0; // set during ... to ignore text which has been replaced by an alias +static int clear_skipping_text = 0; // next clause should clear the skipping_text flag int count_characters = 0; -int sayas_mode; -int ssml_ignore_l_angle = 0; +static int sayas_mode; +static int ssml_ignore_l_angle = 0; static const char *punct_stop = ".:!?"; // pitch fall if followed by space static const char *punct_close = ")]}>;'\""; // always pitch fall unless followed by alnum @@ -71,7 +71,7 @@ static const char *tone_punct_on = "\0016T"; // add reverberation, lower pitch static const char *tone_punct_off = "\001T"; // punctuations symbols that can end a clause -const unsigned short punct_chars[] = {',','.','?','!',':',';', +static const unsigned short punct_chars[] = {',','.','?','!',':',';', 0x2013, // en-dash 0x2014, // em-dash 0x2026, // elipsis @@ -159,17 +159,17 @@ typedef struct { } SSML_STACK; #define N_SSML_STACK 20 -int n_ssml_stack; -SSML_STACK ssml_stack[N_SSML_STACK]; +static int n_ssml_stack; +static SSML_STACK ssml_stack[N_SSML_STACK]; -char current_voice_id[40] = {0}; +static char current_voice_id[40] = {0}; #define N_PARAM_STACK 20 -int n_param_stack; +static int n_param_stack; PARAM_STACK param_stack[N_PARAM_STACK]; -int speech_parameters[N_SPEECH_PARAM]; // current values, from param_stack +static int speech_parameters[N_SPEECH_PARAM]; // current values, from param_stack const int param_defaults[N_SPEECH_PARAM] = { 0, // silence (internal use) @@ -511,8 +511,8 @@ static void UngetC(int c) } -const char *WordToString2(unsigned int word) -{//======================================== +static const char *WordToString2(unsigned int word) +{//================================================ // Convert a language mnemonic word into a string int ix; static char buf[5]; @@ -529,16 +529,16 @@ const char *WordToString2(unsigned int word) } -const char *Translator::LookupSpecial(const char *string, char* text_out) -{//====================================================================== +static const char *LookupSpecial(Translator *tr, const char *string, char* text_out) +{//================================================================================= unsigned int flags[2]; char phonemes[55]; char phonemes2[55]; char *string1 = (char *)string; - if(LookupDictList(&string1,phonemes,flags,0,NULL)) + if(LookupDictList(tr,&string1,phonemes,flags,0,NULL)) { - SetWordStress(phonemes,flags[0],-1,0); + SetWordStress(tr, phonemes, flags[0], -1, 0); DecodePhonemes(phonemes,phonemes2); sprintf(text_out,"[[%s]]",phonemes2); option_phoneme_input |= 2; @@ -548,8 +548,8 @@ const char *Translator::LookupSpecial(const char *string, char* text_out) } -const char *Translator::LookupCharName(int c) -{//========================================== +static const char *LookupCharName(Translator *tr, int c) +{//===================================================== // Find the phoneme string (in ascii) to speak the name of character c // Used for punctuation characters and symbols @@ -571,28 +571,28 @@ const char *Translator::LookupCharName(int c) single_letter[2+ix]=0; string = &single_letter[1]; - if(LookupDictList(&string, phonemes, flags, 0, NULL) == 0) + if(LookupDictList(tr, &string, phonemes, flags, 0, NULL) == 0) { // try _* then * string = &single_letter[2]; - if(LookupDictList(&string, phonemes, flags, 0, NULL) == 0) + if(LookupDictList(tr, &string, phonemes, flags, 0, NULL) == 0) { // now try the rules single_letter[1] = ' '; - TranslateRules(&single_letter[2], phonemes, sizeof(phonemes), NULL,0,NULL); + TranslateRules(tr, &single_letter[2], phonemes, sizeof(phonemes), NULL,0,NULL); } } - if((phonemes[0] == 0) && (translator_name != L('e','n'))) + if((phonemes[0] == 0) && (tr->translator_name != L('e','n'))) { // not found, try English SetTranslator2("en"); string = &single_letter[1]; single_letter[1] = '_'; - if(translator2->LookupDictList(&string, phonemes, flags, 0, NULL) == 0) + if(LookupDictList(translator2, &string, phonemes, flags, 0, NULL) == 0) { string = &single_letter[2]; - translator2->LookupDictList(&string, phonemes, flags, 0, NULL); + LookupDictList(translator2, &string, phonemes, flags, 0, NULL); } if(phonemes[0]) { @@ -608,14 +608,14 @@ const char *Translator::LookupCharName(int c) { if(lang_name) { - translator2->SetWordStress(phonemes,flags[0],-1,0); + SetWordStress(translator2, phonemes, flags[0], -1, 0); DecodePhonemes(phonemes,phonemes2); - sprintf(buf,"[[_^_%s %s _^_%s]]","en",phonemes2,WordToString2(translator_name)); + sprintf(buf,"[[_^_%s %s _^_%s]]","en",phonemes2,WordToString2(tr->translator_name)); SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table } else { - SetWordStress(phonemes,flags[0],-1,0); + SetWordStress(tr, phonemes, flags[0], -1, 0); DecodePhonemes(phonemes,phonemes2); sprintf(buf,"[[%s]] ",phonemes2); } @@ -789,8 +789,8 @@ static int LoadSoundFile2(const char *fname) -int Translator::AnnouncePunctuation(int c1, int c2, char *buf, int bufix) -{//====================================================================== +static int AnnouncePunctuation(Translator *tr, int c1, int c2, char *buf, int bufix) +{//================================================================================= // announce punctuation names // c1: the punctuation character // c2: the following character @@ -809,7 +809,7 @@ int Translator::AnnouncePunctuation(int c1, int c2, char *buf, int bufix) found = 1; } else - if((punctname = LookupCharName(c1)) != NULL) + if((punctname = LookupCharName(tr, c1)) != NULL) { found = 1; if(bufix==0) @@ -891,7 +891,7 @@ int Translator::AnnouncePunctuation(int c1, int c2, char *buf, int bufix) static char ignore_if_self_closing[] = {0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,0,0}; -MNEM_TAB ssmltags[] = { +static MNEM_TAB ssmltags[] = { {"speak", SSML_SPEAK}, {"voice", SSML_VOICE}, {"prosody", SSML_PROSODY}, @@ -1243,8 +1243,8 @@ static int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out) } // end of attr_prosody_value -int AddNameData(const char *name, int wide) -{//======================================== +static int AddNameData(const char *name, int wide) +{//=============================================== // Add the name to the namedata and return its position int ix; int len; @@ -1849,7 +1849,7 @@ terminator=0; // ?? Sentence intonation, but no pause ?? } // end of ProcessSsmlTag -MNEM_TAB xml_char_mnemonics[] = { +static MNEM_TAB xml_char_mnemonics[] = { {"gt",'>'}, {"lt",'<'}, {"amp", '&'}, @@ -1859,8 +1859,8 @@ MNEM_TAB xml_char_mnemonics[] = { {NULL,-1}}; -int Translator::ReadClause(FILE *f_in, char *buf, short *charix, int n_buf, int *tone_type) -{//======================================================================================== +int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int n_buf, int *tone_type) +{//============================================================================================ /* Find the end of the current clause. Write the clause into buf @@ -1903,8 +1903,8 @@ int Translator::ReadClause(FILE *f_in, char *buf, short *charix, int n_buf, int clear_skipping_text = 0; } - clause_upper_count = 0; - clause_lower_count = 0; + tr->clause_upper_count = 0; + tr->clause_lower_count = 0; end_of_input = 0; *tone_type = 0; @@ -2158,7 +2158,7 @@ f_input = f_in; // for GetC etc { char *p_word; - if(translator_name == 0x6a626f) + if(tr->translator_name == 0x6a626f) { // language jbo : lojban // treat "i" or ".i" as end-of-sentence @@ -2181,12 +2181,12 @@ f_input = f_in; // for GetC etc if(iswupper(c1)) { - clause_upper_count++; + tr->clause_upper_count++; if((option_capitals == 2) && (sayas_mode == 0) && !iswupper(cprev)) { char text_buf[40]; char text_buf2[30]; - if(LookupSpecial("_cap",text_buf2) != NULL) + if(LookupSpecial(tr, "_cap", text_buf2) != NULL) { sprintf(text_buf,"%s%s%s",tone_punct_on,text_buf2,tone_punct_off); j = strlen(text_buf); @@ -2200,7 +2200,7 @@ f_input = f_in; // for GetC etc } else if(iswalpha(c1)) - clause_lower_count++; + tr->clause_lower_count++; if(option_phoneme_input) { @@ -2256,7 +2256,7 @@ if(option_ssml) parag=1; // if a list of allowed punctuation has been set up, check whether the character is in it if((option_punctuation == 1) || (wcschr(option_punctlist,c1) != NULL)) { - if((terminator = AnnouncePunctuation(c1, c2, buf, ix)) >= 0) + if((terminator = AnnouncePunctuation(tr, c1, c2, buf, ix)) >= 0) return(terminator); } } @@ -2299,7 +2299,7 @@ if(option_ssml) parag=1; if((nl_count==0) && (c1 == '.')) { - if(iswdigit(cprev) && (langopts.numbers & 0x10000)) + if(iswdigit(cprev) && (tr->langopts.numbers & 0x10000)) { // dot after a number indicates an ordinal number c2 = ' '; @@ -2377,6 +2377,8 @@ void InitText2(void) {//================= int param; + ungot_char = 0; + n_ssml_stack =1; n_param_stack = 1; ssml_stack[0].tag_type = 0; diff --git a/src/setlengths.cpp b/src/setlengths.cpp index b94cbcc1..06784505 100755 --- a/src/setlengths.cpp +++ b/src/setlengths.cpp @@ -253,8 +253,8 @@ static void DoEmbedded2(int &embix) } -void Translator::CalcLengths() -{//=========================== +void CalcLengths(Translator *tr) +{//============================== int ix; int ix2; PHONEME_LIST *prev; @@ -318,14 +318,14 @@ void Translator::CalcLengths() if(prev->type == phSTOP) p->prepause = 60; - if((langopts.word_gap & 0x10) && (p->newword)) + if((tr->langopts.word_gap & 0x10) && (p->newword)) p->prepause = 60; if(p->ph->phflags & phLENGTHENSTOP) p->prepause += 30; if(p->synthflags & SFLAG_LENGTHEN) - p->prepause += langopts.long_stop; + p->prepause += tr->langopts.long_stop; break; case phVFRICATIVE: @@ -353,7 +353,7 @@ void Translator::CalcLengths() else p->length = 256; - if((langopts.word_gap & 0x10) && (p->newword)) + if((tr->langopts.word_gap & 0x10) && (p->newword)) p->prepause = 30; break; @@ -383,14 +383,14 @@ void Translator::CalcLengths() p->prepause = 0; } } - if((langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20)) + if((tr->langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20)) p->prepause = 20; break; case phLIQUID: case phNASAL: - p->amp = stress_amps[1]; // unless changed later + p->amp = tr->stress_amps[1]; // unless changed later p->length = 256; // TEMPORARY min_drop = 0; @@ -457,9 +457,9 @@ void Translator::CalcLengths() if(stress > 7) stress = 7; if(pre_sonorant) - p->amp = stress_amps[stress]-1; + p->amp = tr->stress_amps[stress]-1; else - p->amp = stress_amps[stress]; + p->amp = tr->stress_amps[stress]; if(emphasized) p->amp = 25; @@ -467,8 +467,8 @@ void Translator::CalcLengths() if(ix >= (n_phoneme_list-3)) { // last phoneme of a clause, limit its amplitude - if(p->amp > langopts.param[LOPT_MAXAMP_EOC]) - p->amp = langopts.param[LOPT_MAXAMP_EOC]; + if(p->amp > tr->langopts.param[LOPT_MAXAMP_EOC]) + p->amp = tr->langopts.param[LOPT_MAXAMP_EOC]; } // is the last syllable of a word ? @@ -501,19 +501,19 @@ void Translator::CalcLengths() if(more_syllables==0) { - len = langopts.length_mods0[next2->ph->length_mod *10+ next->ph->length_mod]; + len = tr->langopts.length_mods0[next2->ph->length_mod *10+ next->ph->length_mod]; - if((next->newword) && (langopts.word_gap & 0x20)) + if((next->newword) && (tr->langopts.word_gap & 0x20)) { // consider as a pause + first phoneme of the next word - length_mod = (len + langopts.length_mods0[next->ph->length_mod *10+ 1])/2; + length_mod = (len + tr->langopts.length_mods0[next->ph->length_mod *10+ 1])/2; } else length_mod = len; } else { - length_mod = langopts.length_mods[next2->ph->length_mod *10+ next->ph->length_mod]; + length_mod = tr->langopts.length_mods[next2->ph->length_mod *10+ next->ph->length_mod]; if((next->type == phNASAL) && (next2->type == phSTOP || next2->type == phVSTOP) && (next3->ph->phflags & phFORTIS)) length_mod -= 15; @@ -546,8 +546,8 @@ void Translator::CalcLengths() length_mod += 20; } - if((len = stress_lengths[stress]) == 0) - len = stress_lengths[6]; + if((len = tr->stress_lengths[stress]) == 0) + len = tr->stress_lengths[6]; length_mod = (length_mod * len)/128; @@ -564,7 +564,7 @@ void Translator::CalcLengths() { // this is the last syllable in the clause, lengthen it - more for short vowels len = p->ph->std_length; - if(langopts.stress_flags & 0x40000) + if(tr->langopts.stress_flags & 0x40000) len=200; // don't lengthen short vowels more than long vowels at end-of-clause length_mod = length_mod * (256 + (280 - len)/3)/256; } diff --git a/src/speak_lib.cpp b/src/speak_lib.cpp index f48096e9..1ff56c2b 100644 --- a/src/speak_lib.cpp +++ b/src/speak_lib.cpp @@ -618,7 +618,7 @@ void sync_espeak_Key(const char *key) int letter; int ix; - ix = utf8_in(&letter,key,0); + ix = utf8_in(&letter,key); if(key[ix] == 0) { // a single character diff --git a/src/speak_riscos.cpp b/src/speak_riscos.cpp index 26d23857..78ed6eb1 100644 --- a/src/speak_riscos.cpp +++ b/src/speak_riscos.cpp @@ -568,7 +568,6 @@ void set_say_options(int reg2, int reg3) option_linelength = 0; option_phonemes = 0; option_waveout = 0; - option_harmonic1 = 8; option_multibyte = 0; // auto option_capitals = 0; option_punctuation = 0; @@ -868,7 +867,6 @@ void command_line(char *arg_string, int wait) option_phonemes = 0; option_waveout = 0; option_quiet = 0; - option_harmonic1 = 8; option_multibyte = 0; // auto option_capitals = 0; option_punctuation = 0; @@ -1263,7 +1261,7 @@ void terminate_module(void) { RiscosCloseSound(); RemoveCallback(); - delete translator; + DeleteTranslator(translator); FreePhData(); } /* end of terminate_module */ diff --git a/src/synth_mbrola.cpp b/src/synth_mbrola.cpp index d5e87d67..301c5d5a 100755 --- a/src/synth_mbrola.cpp +++ b/src/synth_mbrola.cpp @@ -106,8 +106,8 @@ void unload_MBR() #endif // USE_MBROLA_LIB -MBROLA_TAB *mbrola_tab = NULL; -int mbrola_control = 0; +static MBROLA_TAB *mbrola_tab = NULL; +static int mbrola_control = 0; @@ -200,8 +200,8 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int } // end of LoadMbrolaTable -int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev, PHONEME_TAB *ph_next, int *name2, int *split, int *control) -{//============================================================================================================== +static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev, PHONEME_TAB *ph_next, int *name2, int *split, int *control) +{//========================================================================================================================================== // Look up a phoneme in the mbrola phoneme name translation table // It may give none, 1, or 2 mbrola phonemes int mnem = ph->mnemonic; @@ -431,8 +431,8 @@ static void MbrolaEmbedded(int &embix, int sourceix) #ifdef PLATFORM_WINDOWS -int MbrolaSynth(char *p_mbrola) -{//============================ +static int MbrolaSynth(char *p_mbrola) +{//=================================== // p_mbrola is a string of mbrola pho lines - Windows int len; int finished; @@ -472,8 +472,8 @@ int MbrolaSynth(char *p_mbrola) } // end of SynthMbrola #else -int MbrolaSynth(char *p_mbrola) -{//============================ +static int MbrolaSynth(char *p_mbrola) +{//=================================== // p_mbrola is a string of mbrola pho lines - Linux // This is wrong @@ -737,9 +737,9 @@ void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola) #ifdef TEST_MBROLA -PHONEME_LIST mbrola_phlist; -int mbrola_n_ph; -int mbrola_phix; +static PHONEME_LIST mbrola_phlist; +static int mbrola_n_ph; +static int mbrola_phix; int MbrolaFill(int fill_zeros) diff --git a/src/synthdata.cpp b/src/synthdata.cpp index 24604281..5d9c6b87 100755 --- a/src/synthdata.cpp +++ b/src/synthdata.cpp @@ -53,7 +53,7 @@ static unsigned char *phoneme_tab_data = NULL; int n_phoneme_tables; PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS]; -static int phoneme_tab_number = 0; +int phoneme_tab_number = 0; int wavefile_ix; // a wavefile to play along with the synthesis int wavefile_amp; @@ -65,15 +65,9 @@ int vowel_transition[4]; int vowel_transition0; int vowel_transition1; -void FormantTransitions(frameref_t *seq, int &n_frames, PHONEME_TAB *this_ph, PHONEME_TAB *other_ph, int which); int FormantTransition2(frameref_t *seq, int &n_frames, unsigned int data1, unsigned int data2, PHONEME_TAB *other_ph, int which); -const char *PhonemeTabName(void) -{//============================= - return(phoneme_tab_list[phoneme_tab_number].name); -} - static int ReadPhFile(char **ptr, const char *fname) {//================================================= @@ -173,8 +167,23 @@ void FreePhData(void) } -int LookupPh(const char *string) -{//============================= +int PhonemeCode(unsigned int mnem) +{//=============================== + int ix; + + for(ix=0; ixmnemonic == mnem) + return(phoneme_tab[ix]->code); + } + return(0); +} + + +int LookupPhonemeString(const char *string) +{//======================================== int ix; unsigned char c; unsigned int mnem; @@ -188,19 +197,11 @@ int LookupPh(const char *string) mnem |= (c << (ix*8)); } - for(ix=0; ixmnemonic == mnem) - return(ix); - } - return(0); + return(PhonemeCode(mnem)); } - static unsigned int LookupSound2(int index, unsigned int other_phcode, int control) {//================================================================================ // control=1 get formant transition data only @@ -456,7 +457,6 @@ frameref_t *LookupSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB if(*match_level == 0) seq_len_adjust = FormantTransition2(frames,nf,vowel_transition0,vowel_transition1,prev_ph,which); } -// FormantTransitions(frames,nf,this_ph,other_ph,which); } nf1 = nf - 1; diff --git a/src/synthesize.cpp b/src/synthesize.cpp index 70207d53..6a199da9 100755 --- a/src/synthesize.cpp +++ b/src/synthesize.cpp @@ -90,6 +90,7 @@ const char *WordToString(unsigned int word) } + void SynthesizeInit() {//================== last_pitch_cmd = 0; @@ -477,8 +478,8 @@ static void AdjustFormants(frame_t *fr, int target, int min, int max, int f1_adj } -int VowelCloseness(frame_t *fr) -{//============================ +static int VowelCloseness(frame_t *fr) +{//=================================== // return a value 0-3 depending on the vowel's f1 int f1; @@ -1108,10 +1109,6 @@ static void DoEmbedded(int &embix, int sourceix) } -void SwitchDictionary() -{//==================== -} - int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) {//============================================================ @@ -1599,12 +1596,12 @@ int SpeakNextClause(FILE *f_in, const void *text_in, int control) // read the next clause from the input text file, translate it, and generate // entries in the wavegen command queue - p_text = translator->TranslateClause(f_text,p_text,&clause_tone,&voice_change); + p_text = TranslateClause(translator, f_text, p_text, &clause_tone, &voice_change); - translator->CalcPitches(clause_tone); - translator->CalcLengths(); + CalcPitches(translator, clause_tone); + CalcLengths(translator); - translator->GetTranslatedPhonemeString(translator->phon_out,sizeof(translator->phon_out)); + GetTranslatedPhonemeString(translator->phon_out,sizeof(translator->phon_out)); if(option_phonemes > 0) { fprintf(f_trans,"%s\n",translator->phon_out); diff --git a/src/synthesize.h b/src/synthesize.h index 87c5b137..10089d8c 100755 --- a/src/synthesize.h +++ b/src/synthesize.h @@ -326,7 +326,7 @@ espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector); espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int srate); void SetParameter(int parameter, int value, int relative); void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola); -int MbrolaSynth(char *p_mbrola); +//int MbrolaSynth(char *p_mbrola); int DoSample(PHONEME_TAB *ph1, PHONEME_TAB *ph2, int which, int length_mod, int amp); int DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph, int which, PHONEME_LIST *plist, int modulation); diff --git a/src/tr_english.cpp b/src/tr_english.cpp index 75a1f2c6..6367df31 100644 --- a/src/tr_english.cpp +++ b/src/tr_english.cpp @@ -19,120 +19,3 @@ #include "StdAfx.h" -#include -#include -#include -#include -#include -#include - -#include "speak_lib.h" -#include "speech.h" -#include "phoneme.h" -#include "synthesize.h" -#include "translate.h" -#include "tr_languages.h" - - -Translator_English::Translator_English() : Translator() -{//=================================== -// static int stress_lengths2[8] = {182,140, 220,220, 220,240, 248,270}; - static const short stress_lengths2[8] = {182,140, 220,220, 0,0, 248,275}; - - memcpy(stress_lengths,stress_lengths2,sizeof(stress_lengths)); - langopts.stress_rule = 0; - - langopts.numbers = 0x841 + NUM_ROMAN; - langopts.param[LOPT_COMBINE_WORDS] = 2; // allow "mc" to cmbine with the following word -} - - - -static unsigned char initials_bitmap[86] = { - 0x00, 0x00, 0x00, 0x00, 0x22, 0x08, 0x00, 0x88, // 0 - 0x20, 0x24, 0x20, 0x80, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x08, 0x00, 0x88, 0x22, 0x04, 0x00, // 16 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x88, 0x22, 0x04, 0x00, 0x02, 0x00, 0x04, // 32 - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x8a, 0x03, 0x00, 0x00, 0x40, 0x00, // 48 - 0x02, 0x00, 0x41, 0xca, 0x9b, 0x06, 0x20, 0x80, - 0x91, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, // 64 - 0x08, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, }; - - - -int Translator_English::Unpronouncable(char *word) -{//=============================================== -/* Determines whether a word in 'unpronouncable', i.e. whether it should - be spoken as individual letters. - - This function is language specific. -*/ - - int c; - int vowel_posn=9; - int index; - int count; - int ix; - int apostrophe=0; - - // words which we pass through to the dictionary, even though they look unpronouncable - static const char *exceptions[] = { - "'s ", "st ","nd ","rd ","th ",NULL }; - - if((*word == ' ') || (*word == 0)) - return(0); - - for(ix=0; exceptions[ix] != NULL; ix++) - { - // Seemingly uncpronouncable words, but to be looked in the dictionary rules instead - if(memcmp(word,exceptions[ix],3)==0) - return(0); - } - - index=0; - count=0; - for(;;) - { - index += utf8_in(&c,&word[index],0); - count++; - - if((c==0) || (c==' ')) - break; - - if(IsVowel(c) || (c == 'y')) - { - vowel_posn = count; - break; - } - - if(c == '\'') - apostrophe = 1; - else - if(!IsAlpha(c)) - return(0); // letter (not vowel) outside Latin character range or apostrophe, abort test - } - if((vowel_posn > 5) || ((word[0]!='s') && (vowel_posn > 4))) - return(1); // no vowel, or no vowel in first four letters - - /* there is at least one vowel, is the initial letter combination valid ? */ - - if(vowel_posn < 3) - return(0); /* vowel in first two letters, OK */ - - if(apostrophe) - return(0); // first two letters not a-z, abort test - - index = (word[0]-'a') * 26 + (word[1]-'a'); - if(initials_bitmap[index >> 3] & (1L << (index & 7))) - return(0); - else - return(1); /****/ -} /* end of Unpronounceable */ - - - - - diff --git a/src/tr_languages.cpp b/src/tr_languages.cpp index 8e543f7e..9b7910bd 100644 --- a/src/tr_languages.cpp +++ b/src/tr_languages.cpp @@ -33,7 +33,6 @@ #include "phoneme.h" #include "synthesize.h" #include "translate.h" -#include "tr_languages.h" @@ -53,6 +52,123 @@ #define OFFSET_MALAYALAM 0xd00 #define OFFSET_KOREAN 0x1100 +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) +} + +static void ResetLetterBits(Translator *tr, int groups) +{//==================================================== +// Clear all the specified groups + unsigned int ix; + unsigned int mask; + + mask = ~groups; + + for(ix=0; ixletter_bits); ix++) + { + tr->letter_bits[ix] &= mask; + } +} + +static void SetLetterBits(Translator *tr, int group, const char *string) +{//===================================================================== + int bits; + unsigned char c; + + bits = (1L << group); + while((c = *string++) != 0) + tr->letter_bits[c] |= bits; +} + +static void SetLetterBitsRange(Translator *tr, int group, int first, int last) +{//=========================================================================== + int bits; + int ix; + + bits = (1L << group); + for(ix=first; ix<=last; ix++) + { + tr->letter_bits[ix] |= bits; + } +} + + +static Translator* NewTranslator(void) +{//=================================== + Translator *tr; + int ix; + static const unsigned char stress_amps2[] = {17,17, 20,20, 20,22, 22,20 }; + static const short stress_lengths2[8] = {182,140, 220,220, 220,240, 260,280}; + static const wchar_t empty_wstring[1] = {0}; + static const wchar_t punct_in_word[2] = {'\'', 0}; // allow hyphen within words + + tr = (Translator *)Alloc(sizeof(Translator)); + if(tr == NULL) + return(NULL); + + tr->charset_a0 = charsets[1]; // ISO-8859-1, this is for when the input is not utf8 + dictionary_name[0] = 0; + tr->dict_condition=0; + tr->data_dictrules = NULL; // language_1 translation rules file + tr->data_dictlist = NULL; // language_2 dictionary lookup file + + tr->transpose_offset = 0; + + // only need lower case + tr->letter_bits_offset = 0; + memset(tr->letter_bits,0,sizeof(tr->letter_bits)); + memset(tr->letter_groups,0,sizeof(tr->letter_groups)); + + // 0-5 sets of characters matched by A B C E F G in pronunciation rules + // these may be set differently for different languages + SetLetterBits(tr,0,"aeiou"); // A vowels, except y + SetLetterBits(tr,1,"bcdfgjklmnpqstvxz"); // B hard consonants, excluding h,r,w + SetLetterBits(tr,2,"bcdfghjklmnpqrstvwxz"); // C all consonants + SetLetterBits(tr,3,"hlmnr"); // H 'soft' consonants + SetLetterBits(tr,4,"cfhkpqstx"); // F voiceless consonants + SetLetterBits(tr,5,"bdgjlmnrvwyz"); // G voiced + SetLetterBits(tr,6,"eiy"); // Letter group Y, front vowels + SetLetterBits(tr,7,"aeiouy"); // vowels, including y + + + tr->char_plus_apostrophe = empty_wstring; + tr->punct_within_word = punct_in_word; + + for(ix=0; ix<8; ix++) + { + tr->stress_amps[ix] = stress_amps2[ix]; + tr->stress_amps_r[ix] = stress_amps2[ix] - 1; + tr->stress_lengths[ix] = stress_lengths2[ix]; + } + memset(&(tr->langopts),0,sizeof(tr->langopts)); + + tr->langopts.stress_rule = 2; + tr->langopts.unstressed_wd1 = 1; + tr->langopts.unstressed_wd2 = 3; + tr->langopts.param[LOPT_SONORANT_MIN] = 95; + tr->langopts.param[LOPT_MAXAMP_EOC] = 19; + tr->langopts.param[LOPT_UNPRONOUNCABLE] = 's'; // don't count this character at start of word + tr->langopts.max_initial_consonants = 3; + tr->langopts.replace_chars = NULL; + + SetLengthMods(tr,201); +// tr->langopts.length_mods = length_mods_en; +// tr->langopts.length_mods0 = length_mods_en0; + + tr->langopts.long_stop = 100; + + tr->langopts.max_roman = 49; + tr->langopts.thousands_sep = ','; + tr->langopts.decimal_sep = '.'; + + memcpy(tr->punct_to_tone, punctuation_to_tone, sizeof(tr->punct_to_tone)); + + return(tr); +} + static const unsigned int replace_cyrillic_latin[] = {0x430,'a', @@ -130,13 +246,13 @@ Translator *SelectTranslator(const char *name) while(*name != 0) name2 = (name2 << 8) + *name++; + tr = NewTranslator(); switch(name2) { case L('a','f'): { static const short stress_lengths_af[8] = {170,140, 220,220, 0, 0, 250,270}; - tr = new Translator(); SetupTranslator(tr,stress_lengths_af,NULL); tr->langopts.stress_rule = 0; @@ -155,7 +271,6 @@ Translator *SelectTranslator(const char *name) static const short stress_lengths_bn[8] = {180, 180, 210, 210, 0, 0, 230, 240}; static const unsigned char stress_amps_bn[8] = {18,18, 18,18, 20,20, 22,22 }; - tr = new Translator(); SetupTranslator(tr,stress_lengths_bn,stress_amps_bn); tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable @@ -175,7 +290,6 @@ Translator *SelectTranslator(const char *name) static const short stress_lengths_cy[8] = {170,220, 180,180, 0, 0, 250,270}; static const unsigned char stress_amps_cy[8] = {17,15, 18,18, 0,0, 22,20 }; // 'diminished' is used to mark a quieter, final unstressed syllable - tr = new Translator(); SetupTranslator(tr,stress_lengths_cy,stress_amps_cy); tr->charset_a0 = charsets[14]; // ISO-8859-14 @@ -199,7 +313,6 @@ Translator *SelectTranslator(const char *name) case L('d','a'): // Danish { static const short stress_lengths_da[8] = {160,140, 200,200, 0,0, 220,210}; - tr = new Translator(); SetupTranslator(tr,stress_lengths_da,NULL); tr->langopts.stress_rule = 0; @@ -212,7 +325,6 @@ Translator *SelectTranslator(const char *name) case L('d','e'): { static const short stress_lengths_de[8] = {150,130, 190,190, 0, 0, 260,275}; - tr = new Translator(); tr->langopts.stress_rule = 0; tr->langopts.word_gap = 0x8; // don't use linking phonemes tr->langopts.vowel_pause = 0x30; @@ -225,7 +337,14 @@ Translator *SelectTranslator(const char *name) break; case L('e','n'): - tr = new Translator_English(); + { + static const short stress_lengths_en[8] = {182,140, 220,220, 0,0, 248,275}; + SetupTranslator(tr,stress_lengths_en,NULL); + + tr->langopts.stress_rule = 0; + tr->langopts.numbers = 0x841 + NUM_ROMAN; + tr->langopts.param[LOPT_COMBINE_WORDS] = 2; // allow "mc" to cmbine with the following word + } break; case L('e','l'): // Greek @@ -241,7 +360,6 @@ Translator *SelectTranslator(const char *name) static const char el_consonants[]={0x32,0x33,0x34,0x36,0x38,0x3a,0x3b,0x3c,0x3d,0x3e,0x40,0x41,0x42,0x43,0x44,0x46,0x47,0x48,0}; static const wchar_t el_char_apostrophe[] = {0x3c3,0}; // σ - tr = new Translator(); SetupTranslator(tr,stress_lengths_el,stress_amps_el); tr->charset_a0 = charsets[7]; // ISO-8859-7 @@ -278,7 +396,6 @@ Translator *SelectTranslator(const char *name) static const unsigned char stress_amps_eo[] = {16,14, 20,20, 20,22, 22,21 }; static const wchar_t eo_char_apostrophe[2] = {'l',0}; - tr = new Translator(); SetupTranslator(tr,stress_lengths_eo,stress_amps_eo); tr->charset_a0 = charsets[3]; // ISO-8859-3 @@ -303,7 +420,6 @@ Translator *SelectTranslator(const char *name) static const unsigned char stress_amps_es[8] = {16,12, 18,18, 20,20, 20,20 }; // 'diminished' is used to mark a quieter, final unstressed syllable static const wchar_t ca_punct_within_word[] = {'\'',0xb7,0}; // ca: allow middle-dot within word - tr = new Translator(); SetupTranslator(tr,stress_lengths_es,stress_amps_es); tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable @@ -332,7 +448,6 @@ Translator *SelectTranslator(const char *name) static const unsigned char stress_amps_fi[8] = {18,16, 22,22, 20,22, 22,22 }; static const short stress_lengths_fi[8] = {150,180, 200,200, 0,0, 210,250}; - tr = new Translator(); SetupTranslator(tr,stress_lengths_fi,stress_amps_fi); tr->langopts.stress_rule = 0; @@ -353,7 +468,6 @@ Translator *SelectTranslator(const char *name) static const short stress_lengths_fr[8] = {190, 170, 190, 200, 0, 0, 235, 240}; static const unsigned char stress_amps_fr[8] = {18,16, 20,20, 20,22, 22,21 }; - tr = new Translator(); SetupTranslator(tr,stress_lengths_fr,stress_amps_fr); tr->langopts.stress_rule = 3; // stress on final syllable tr->langopts.stress_flags = 0x0024; // don't use secondary stress @@ -367,8 +481,6 @@ Translator *SelectTranslator(const char *name) #ifdef deleted case L('g','a'): // Irish Gaelic { - tr = new Translator(); - tr->langopts.stress_rule = 1; } break; @@ -380,7 +492,6 @@ Translator *SelectTranslator(const char *name) static const short stress_lengths_hi[8] = {190, 190, 210, 210, 0, 0, 230, 250}; static const unsigned char stress_amps_hi[8] = {17,14, 20,19, 20,22, 22,21 }; - tr = new Translator(); SetupTranslator(tr,stress_lengths_hi,stress_amps_hi); tr->charset_a0 = charsets[19]; // ISCII tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable @@ -403,8 +514,6 @@ Translator *SelectTranslator(const char *name) static const short stress_lengths_hr[8] = {180,160, 200,200, 0,0, 220,230}; static const short stress_lengths_sr[8] = {160,150, 200,200, 0,0, 250,260}; - tr = new Translator(); - if(name2 == L('s','r')) SetupTranslator(tr,stress_lengths_sr,stress_amps_hr); else @@ -433,7 +542,6 @@ Translator *SelectTranslator(const char *name) static const unsigned char stress_amps_hu[8] = {17,17, 19,19, 20,22, 22,21 }; static const short stress_lengths_hu[8] = {185,195, 195,190, 0,0, 210,220}; - tr = new Translator(); SetupTranslator(tr,stress_lengths_hu,stress_amps_hu); tr->charset_a0 = charsets[2]; // ISO-8859-2 @@ -458,7 +566,7 @@ SetLengthMods(tr,3); // all equal static const char hy_vowels[] = {0x31, 0x35, 0x37, 0x38, 0x3b, 0x48, 0x55, 0}; static const char hy_consonants[] = {0x32,0x33,0x34,0x36,0x39,0x3a,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x56,0}; - tr = new Translator(); + SetupTranslator(tr,stress_lengths_hy,NULL); tr->langopts.stress_rule = 3; // default stress on final syllable @@ -475,7 +583,7 @@ SetLengthMods(tr,3); // all equal { static const short stress_lengths_id[8] = {160, 200, 180, 180, 0, 0, 220, 240}; static const unsigned char stress_amps_id[8] = {16,18, 18,18, 20,22, 22,21 }; - tr = new Translator(); + SetupTranslator(tr,stress_lengths_id,stress_amps_id); tr->langopts.stress_rule = 2; tr->langopts.numbers = 0x1009 + NUM_ROMAN; @@ -489,7 +597,6 @@ SetLengthMods(tr,3); // all equal static const short stress_lengths_is[8] = {180,160, 200,200, 0,0, 240,250}; static const wchar_t is_lettergroup_B[] = {'c','f','h','k','p','t','x',0xfe,0}; // voiceless conants, including 'þ' ?? 's' - tr = new Translator(); SetupTranslator(tr,stress_lengths_is,NULL); tr->langopts.stress_rule = 0; tr->langopts.stress_flags = 0x10; @@ -511,7 +618,6 @@ SetLengthMods(tr,3); // all equal static const short stress_lengths_it[8] = {150, 140, 170, 170, 0, 0, 300, 330}; static const unsigned char stress_amps_it[8] = {15,14, 19,19, 20,22, 22,20 }; - tr = new Translator(); SetupTranslator(tr,stress_lengths_it,stress_amps_it); tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable @@ -528,16 +634,11 @@ SetLengthMods(tr,3); // all equal } break; - case L('j','a'): // TEST - tr = new Translator(); - tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words - break; - case L_jbo: // Lojban { static const short stress_lengths_jbo[8] = {145,145, 170,160, 0,0, 330,350}; static const wchar_t jbo_punct_within_word[] = {'.',',','\'',0x2c8,0}; // allow period and comma within a word, also stress marker (from LOPT_SYLLABLE_CAPS) - tr = new Translator(); + SetupTranslator(tr,stress_lengths_jbo,NULL); tr->langopts.stress_rule = 2; tr->langopts.vowel_pause = 0x20c; // pause before a word which starts with a vowel, or after a word which ends in a consonant @@ -552,7 +653,6 @@ SetLengthMods(tr,3); // all equal { static const char ko_ivowels[] = {0x63,0x64,0x67,0x68,0x6d,0x72,0x74,0x75,0}; // y and i vowels static const char ko_voiced[] = {0x02,0x05,0x06,0xab,0xaf,0xb7,0xbc,0}; // voiced consonants, l,m,n,N - tr = new Translator(); tr->letter_bits_offset = OFFSET_KOREAN; memset(tr->letter_bits,0,sizeof(tr->letter_bits)); @@ -571,7 +671,6 @@ SetLengthMods(tr,3); // all equal static const unsigned char stress_amps_ku[8] = {18,18, 20,20, 20,22, 22,21 }; static const short stress_lengths_ku[8] = {180,180, 190,180, 0,0, 230,240}; - tr = new Translator(); SetupTranslator(tr,stress_lengths_ku,stress_amps_ku); tr->charset_a0 = charsets[9]; // ISO-8859-9 - Latin5 @@ -584,7 +683,6 @@ SetLengthMods(tr,3); // all equal case L('l','a'): //Latin { - tr = new Translator(); tr->charset_a0 = charsets[4]; // ISO-8859-4, includes a,e,i,o,u-macron tr->langopts.stress_rule = 2; tr->langopts.stress_flags = 0x20; @@ -600,7 +698,7 @@ SetLengthMods(tr,3); // all equal { static const unsigned char stress_amps_lv[8] = {17,13, 20,20, 20,22, 22,21 }; static const short stress_lengths_lv[8] = {180,130, 210,210, 0,0, 210,210}; - tr = new Translator(); + SetupTranslator(tr,stress_lengths_lv,stress_amps_lv); tr->langopts.stress_rule = 0; @@ -618,7 +716,6 @@ SetLengthMods(tr,3); // all equal static const unsigned char stress_amps_mk[8] = {17,17, 20,20, 20,22, 22,21 }; static const short stress_lengths_mk[8] = {180,160, 200,200, 0,0, 220,230}; - tr = new Translator(); SetupTranslator(tr,stress_lengths_mk,stress_amps_mk); tr->charset_a0 = charsets[5]; // ISO-8859-5 tr->letter_groups[0] = vowels_cyrillic; @@ -633,7 +730,6 @@ SetLengthMods(tr,3); // all equal case L('n','l'): // Dutch { static const short stress_lengths_nl[8] = {160,135, 210,210, 0, 0, 260,280}; - tr = new Translator(); tr->langopts.stress_rule = 0; tr->langopts.vowel_pause = 1; @@ -649,9 +745,8 @@ SetLengthMods(tr,3); // all equal case L('n','o'): // Norwegian { static const short stress_lengths_no[8] = {160,140, 200,200, 0,0, 220,210}; - tr = new Translator(); - SetupTranslator(tr,stress_lengths_no,NULL); + SetupTranslator(tr,stress_lengths_no,NULL); tr->langopts.stress_rule = 0; SetLetterVowel(tr,'y'); tr->langopts.numbers = 0x11849; @@ -662,9 +757,8 @@ SetLengthMods(tr,3); // all equal { static const unsigned char stress_amps_om[] = {18,15, 20,20, 20,22, 22,22 }; static const short stress_lengths_om[8] = {200,200, 200,200, 0,0, 200,200}; - tr = new Translator(); - SetupTranslator(tr,stress_lengths_om,stress_amps_om); + SetupTranslator(tr,stress_lengths_om,stress_amps_om); tr->langopts.stress_rule = 2; tr->langopts.stress_flags = 0x16 + 0x80000; } @@ -675,7 +769,6 @@ SetLengthMods(tr,3); // all equal static const short stress_lengths_pl[8] = {160, 190, 175, 175, 0, 0, 200, 210}; static const unsigned char stress_amps_pl[8] = {17,13, 19,19, 20,22, 22,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable - tr = new Translator(); SetupTranslator(tr,stress_lengths_pl,stress_amps_pl); tr->charset_a0 = charsets[2]; // ISO-8859-2 @@ -694,7 +787,7 @@ SetLengthMods(tr,3); // all equal { static const short stress_lengths_pt[8] = {180, 125, 210, 210, 0, 0, 270, 295}; static const unsigned char stress_amps_pt[8] = {16,13, 19,19, 20,22, 22,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable - tr = new Translator(); + SetupTranslator(tr,stress_lengths_pt,stress_amps_pt); tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable @@ -712,7 +805,6 @@ SetLengthMods(tr,3); // all equal static const short stress_lengths_ro[8] = {170, 170, 180, 180, 0, 0, 240, 260}; static const unsigned char stress_amps_ro[8] = {15,13, 18,18, 20,22, 22,21 }; - tr = new Translator(); SetupTranslator(tr,stress_lengths_ro,stress_amps_ro); tr->langopts.stress_rule = 2; @@ -725,12 +817,11 @@ SetLengthMods(tr,3); // all equal break; case L('r','u'): // Russian - tr = new Translator_Russian(); + Translator_Russian(tr); break; case L('r','w'): // Kiryarwanda { - tr = new Translator(); tr->langopts.stress_rule = 2; tr->langopts.stress_flags = 0x16; tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable @@ -745,7 +836,6 @@ SetLengthMods(tr,3); // all equal { static const char *sk_voiced = "bdgjlmnrvwzaeiouy"; - tr = new Translator(); SetupTranslator(tr,stress_lengths_sk,stress_amps_sk); tr->charset_a0 = charsets[2]; // ISO-8859-2 @@ -777,7 +867,7 @@ SetLengthMods(tr,3); // all equal { static const short stress_lengths_sq[8] = {150, 150, 180, 180, 0, 0, 300, 300}; static const unsigned char stress_amps_sq[8] = {16,12, 16,16, 20,20, 21,19 }; - tr = new Translator(); + SetupTranslator(tr,stress_lengths_sq,stress_amps_sq); tr->langopts.stress_rule = 2; @@ -792,12 +882,10 @@ SetLengthMods(tr,3); // all equal { static const unsigned char stress_amps_sv[] = {16,16, 20,20, 20,22, 22,21 }; static const short stress_lengths_sv[8] = {160,135, 220,220, 0,0, 250,280}; - tr = new Translator(); SetupTranslator(tr,stress_lengths_sv,stress_amps_sv); tr->langopts.stress_rule = 0; SetLetterVowel(tr,'y'); -// SetLetterBits(tr,6,"eiyäö"); // soft vowels NOTE accented letters don't work in SetLetterBits tr->langopts.numbers = 0x1909; tr->langopts.accents = 1; } @@ -807,8 +895,7 @@ SetLengthMods(tr,3); // all equal { static const short stress_lengths_sw[8] = {160, 170, 200, 200, 0, 0, 320, 340}; static const unsigned char stress_amps_sw[] = {16,12, 19,19, 20,22, 22,21 }; - - tr = new Translator(); + SetupTranslator(tr,stress_lengths_sw,stress_amps_sw); tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable @@ -829,7 +916,6 @@ SetLengthMods(tr,3); // all equal static const short stress_lengths_ta[8] = {200, 200, 210, 210, 0, 0, 230, 230}; static const unsigned char stress_amps_ta[8] = {18,18, 18,18, 20,20, 22,22 }; - tr = new Translator(); SetupTranslator(tr,stress_lengths_ta,stress_amps_ta); tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable @@ -864,7 +950,6 @@ SetLengthMods(tr,3); // all equal static const short stress_lengths_th[8] = {230,150, 230,230, 230,0, 230,250}; static const unsigned char stress_amps_th[] = {22,16, 22,22, 22,22, 22,22 }; - tr = new Translator; SetupTranslator(tr,stress_lengths_th,stress_amps_th); tr->langopts.stress_rule = 0; // stress on final syllable of a "word" @@ -882,7 +967,6 @@ SetLengthMods(tr,3); // all equal static const unsigned char stress_amps_tr[8] = {18,18, 20,20, 20,22, 22,21 }; static const short stress_lengths_tr[8] = {190,190, 190,190, 0,0, 250,270}; - tr = new Translator(); SetupTranslator(tr,stress_lengths_tr,stress_amps_tr); tr->charset_a0 = charsets[9]; // ISO-8859-9 - Latin5 @@ -912,7 +996,6 @@ SetLengthMods(tr,3); // all equal 0x1b0, 0x1eeb, 0x1ee9, 0x1eed, 0x1eef, 0x1ef1, // ư 0x79, 0x1ef3, 0xfd, 0x1ef7, 0x1ef9, 0x1e, 0 }; // y - tr = new Translator(); SetupTranslator(tr,stress_lengths_vi,stress_amps_vi); tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable @@ -933,7 +1016,6 @@ SetLengthMods(tr,3); // all equal static const short stress_lengths_zh[8] = {230,150, 230,230, 230,0, 240,250}; // 1=tone5. end-of-sentence, 6=tone 1&4, 7=tone 2&3 static const unsigned char stress_amps_zh[] = {22,16, 22,22, 22,22, 22,22 }; - tr = new Translator; SetupTranslator(tr,stress_lengths_zh,stress_amps_zh); tr->langopts.stress_rule = 3; // stress on final syllable of a "word" @@ -953,7 +1035,6 @@ SetLengthMods(tr,3); // all equal break; default: - tr = new Translator(); break; } @@ -978,8 +1059,8 @@ SetLengthMods(tr,3); // all equal -Translator_Russian::Translator_Russian() : Translator() -{//=================================== +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}; @@ -993,40 +1074,38 @@ Translator_Russian::Translator_Russian() : Translator() 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) - SetupTranslator(this,stress_lengths_ru,stress_amps_ru); + SetupTranslator(tr,stress_lengths_ru,stress_amps_ru); - charset_a0 = charsets[18]; // KOI8-R - transpose_offset = 0x42f; // convert cyrillic from unicode into range 0x01 to 0x22 - transpose_min = 0x430; - transpose_max = 0x451; + 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; - letter_bits_offset = OFFSET_CYRILLIC; - memset(letter_bits,0,sizeof(letter_bits)); - SetLetterBits(this,0,ru_vowels); - SetLetterBits(this,1,ru_soft); - SetLetterBits(this,2,ru_consonants); - SetLetterBits(this,3,ru_hard); - SetLetterBits(this,4,ru_nothard); - SetLetterBits(this,5,ru_voiced); - SetLetterBits(this,6,ru_ivowels); - SetLetterBits(this,7,ru_vowels); + 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); - langopts.param[LOPT_UNPRONOUNCABLE] = 0x432; // [v] don't count this character at start of word - langopts.param[LOPT_REGRESSIVE_VOICING] = 1; - langopts.param[LOPT_REDUCE] = 2; - langopts.stress_rule = 5; - langopts.stress_flags = 0x0020; // waas 0x1010 + tr->langopts.param[LOPT_UNPRONOUNCABLE] = 0x432; // [v] don't count this character at start of word + tr->langopts.param[LOPT_REGRESSIVE_VOICING] = 1; + tr->langopts.param[LOPT_REDUCE] = 2; + tr->langopts.stress_rule = 5; + tr->langopts.stress_flags = 0x0020; // waas 0x1010 - langopts.numbers = 0x0409; - langopts.numbers2 = 0xc2; // variant numbers before thousands - langopts.phoneme_change = 1; - langopts.testing = 2; + tr->langopts.numbers = 0x0409; + tr->langopts.numbers2 = 0xc2; // variant numbers before thousands + tr->langopts.phoneme_change = 1; + tr->langopts.testing = 2; } // end of Translator_Russian -#define PH(c1,c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name -#define PY(c1,c2,c3) (c3<<16)+(c2<<8)+c1 /* typedef struct { @@ -1043,8 +1122,8 @@ typedef struct { #define RUSSIAN2 #ifdef RUSSIAN2 -int Translator_Russian::ChangePhonemes(PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) -{//============================================================================================================== +int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) +{//============================================================================================================= // Called for each phoneme in the phoneme list, to allow a language to make changes // ph The current phoneme @@ -1136,8 +1215,8 @@ PH('V','#'),PH('I','3'),PH('I','2'),PH('E','3')}; #else -int Translator_Russian::ChangePhonemes(PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) -{//=============================================================================================================== +int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch) +{//============================================================================================================= // Called for each phoneme in the phoneme list, to allow a language to make changes // flags: bit 0=1 last phoneme in a word // bit 1=1 this is the highest stressed vowel in the current word diff --git a/src/tr_languages.h b/src/tr_languages.h index 5eddb1f0..8ac318fe 100644 --- a/src/tr_languages.h +++ b/src/tr_languages.h @@ -18,28 +18,3 @@ ***************************************************************************/ - - - -class Translator_English: public Translator -{//======================================= - -public: - Translator_English(); - int Unpronouncable(char *word); -}; // end of class Translator_English - - - -class Translator_Russian: public Translator -{//======================================= - -public: - Translator_Russian(); -private: - int ChangePhonemes(PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch); - -}; // end of class Translator_Russian - - - diff --git a/src/translate.cpp b/src/translate.cpp index fdc5e706..fa169ba7 100755 --- a/src/translate.cpp +++ b/src/translate.cpp @@ -42,7 +42,6 @@ Translator *translator2 = NULL; // secondary translator for certain words static char translator2_language[20] = {0}; FILE *f_trans = NULL; // phoneme output text -int option_tone1 = 0; int option_tone2 = 0; int option_tone_flags = 0; // bit 8=emphasize allcaps, bit 9=emphasize penultimate stress int option_phonemes = 0; @@ -52,14 +51,14 @@ int option_endpause = 0; // suppress pause after end of text int option_capitals = 0; int option_punctuation = 0; int option_sayas = 0; -int option_sayas2 = 0; // used in translate_clause() -int option_emphasis = 0; // 0=normal, 1=normal, 2=weak, 3=moderate, 4=strong +static int option_sayas2 = 0; // used in translate_clause() +static int option_emphasis = 0; // 0=normal, 1=normal, 2=weak, 3=moderate, 4=strong int option_ssml = 0; int option_phoneme_input = 0; // allow [[phonemes]] in input int option_phoneme_variants = 0; // 0= don't display phoneme variant mnemonics int option_wordgap = 0; -int count_sayas_digits; +static int count_sayas_digits; int skip_sentences; int skip_words; int skip_characters; @@ -71,10 +70,17 @@ int count_words; int clause_start_char; int clause_start_word; int new_sentence; -int word_emphasis = 0; // set if emphasis level 3 or 4 +static int word_emphasis = 0; // set if emphasis level 3 or 4 + +static int prev_clause_pause=0; +static int max_clause_pause = 0; + + +// these were previously in translator class +char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes +int n_ph_list2; +PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes -int prev_clause_pause=0; -int max_clause_pause = 0; wchar_t option_punctlist[N_PUNCTLIST]={0}; @@ -332,7 +338,7 @@ static unsigned char length_mods_equal[100] = { 110,110,110,110,110,110,110,110,110, 110 }; // SPARE -unsigned char *length_mod_tabs[6] = { +static unsigned char *length_mod_tabs[6] = { length_mods_en, length_mods_en, // 1 length_mods_en0, // 2 @@ -409,75 +415,11 @@ int IsSpace(unsigned int c) } -Translator::Translator() -{//===================== - int ix; - static const unsigned char stress_amps2[] = {17,17, 20,20, 20,22, 22,20 }; - static const short stress_lengths2[8] = {182,140, 220,220, 220,240, 260,280}; - static const wchar_t empty_wstring[1] = {0}; - static const wchar_t punct_in_word[2] = {'\'', 0}; // allow hyphen within words - - charset_a0 = charsets[1]; // ISO-8859-1, this is for when the input is not utf8 - dictionary_name[0] = 0; - dict_condition=0; - data_dictrules = NULL; // language_1 translation rules file - data_dictlist = NULL; // language_2 dictionary lookup file - - transpose_offset = 0; - - // only need lower case - letter_bits_offset = 0; - memset(letter_bits,0,sizeof(letter_bits)); - memset(letter_groups,0,sizeof(letter_groups)); - - // 0-5 sets of characters matched by A B C E F G in pronunciation rules - // these may be set differently for different languages - SetLetterBits(this,0,"aeiou"); // A vowels, except y - SetLetterBits(this,1,"bcdfgjklmnpqstvxz"); // B hard consonants, excluding h,r,w - SetLetterBits(this,2,"bcdfghjklmnpqrstvwxz"); // C all consonants - SetLetterBits(this,3,"hlmnr"); // H 'soft' consonants - SetLetterBits(this,4,"cfhkpqstx"); // F voiceless consonants - SetLetterBits(this,5,"bdgjlmnrvwyz"); // G voiced - SetLetterBits(this,6,"eiy"); // Letter group Y, front vowels - SetLetterBits(this,7,"aeiouy"); // vowels, including y - - - char_plus_apostrophe = empty_wstring; - punct_within_word = punct_in_word; - - for(ix=0; ix<8; ix++) - { - stress_amps[ix] = stress_amps2[ix]; - stress_amps_r[ix] = stress_amps2[ix] - 1; - stress_lengths[ix] = stress_lengths2[ix]; - } - memset(&langopts,0,sizeof(langopts)); - - langopts.stress_rule = 2; - langopts.unstressed_wd1 = 1; - langopts.unstressed_wd2 = 3; - langopts.param[LOPT_SONORANT_MIN] = 95; - langopts.param[LOPT_MAXAMP_EOC] = 19; - langopts.param[LOPT_UNPRONOUNCABLE] = 's'; // don't count this character at start of word - langopts.max_initial_consonants = 3; - langopts.replace_chars = NULL; - - langopts.length_mods = length_mods_en; - langopts.length_mods0 = length_mods_en0; - langopts.long_stop = 100; - - langopts.max_roman = 49; - langopts.thousands_sep = ','; - langopts.decimal_sep = '.'; - - memcpy(punct_to_tone,punctuation_to_tone,sizeof(punct_to_tone)); -} - - -Translator::~Translator(void) -{//========================== - if(data_dictlist != NULL) - Free(data_dictlist); +void DeleteTranslator(Translator *tr) +{//================================== + if(tr->data_dictlist != NULL) + Free(tr->data_dictlist); + Free(tr); } @@ -554,8 +496,8 @@ int utf8_nbytes(const char *buf) } -int utf8_in(int *c, const char *buf, int backwards) -{//================================================ +int utf8_in2(int *c, const char *buf, int backwards) +{//================================================= // Read a unicode characater from a UTF8 string // Returns the number of UTF8 bytes used. // backwards: set if we are moving backwards through the UTF8 string @@ -598,6 +540,12 @@ int utf8_in(int *c, const char *buf, int backwards) } +int utf8_in(int *c, const char *buf) +{//================================= +// Read a unicode characater from a UTF8 string +// Returns the number of UTF8 bytes used. + return(utf8_in2(c,buf,0)); +} char *strchr_w(const char *s, int c) @@ -609,23 +557,10 @@ char *strchr_w(const char *s, int c) } -int PhonemeCode(unsigned int mnem) -{//=============================== - int ix; - - for(ix=0; ixmnemonic == mnem) - return(phoneme_tab[ix]->code); - } - return(phonSCHWA); -} - - -int Translator::TranslateWord(char *word1, int next_pause, WORD_TAB *wtab) -{//======================================================================= +int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab) +{//=========================================================================== // word1 is terminated by space (0x20) character int length; @@ -679,11 +614,11 @@ int Translator::TranslateWord(char *word1, int next_pause, WORD_TAB *wtab) // count the length of the word wordx = word1; - utf8_in(&first_char,wordx,0); + utf8_in(&first_char,wordx); word_length = 0; while((*wordx != 0) && (*wordx != ' ')) { - wordx += utf8_in(&last_char,wordx,0); + wordx += utf8_in(&last_char,wordx); word_length++; } @@ -703,11 +638,11 @@ int Translator::TranslateWord(char *word1, int next_pause, WORD_TAB *wtab) } else { - found = LookupDictList(&word1, phonemes, dictionary_flags, FLAG_ALLOW_TEXTMODE, wtab); // the original word + found = LookupDictList(tr, &word1, phonemes, dictionary_flags, FLAG_ALLOW_TEXTMODE, wtab); // the original word if(dictionary_flags[0] & FLAG_TEXTMODE) { stress_bits = dictionary_flags[0] & 0x7f; - found = LookupDictList(&word1, phonemes, dictionary_flags2, 0, wtab); // the text replacement + found = LookupDictList(tr, &word1, phonemes, dictionary_flags2, 0, wtab); // the text replacement if(dictionary_flags2[0]!=0) { dictionary_flags[0] = dictionary_flags2[0]; @@ -759,20 +694,20 @@ if((wmark > 0) && (wmark < 8)) if(!found && iswdigit(first_char)) { - Lookup("_0lang",word_phonemes); + Lookup(tr,"_0lang",word_phonemes); if(word_phonemes[0] == phonSWITCH) return(0); - found = TranslateNumber(word1,phonemes,dictionary_flags,wflags); + found = TranslateNumber(tr,word1,phonemes,dictionary_flags,wflags); } - if(!found & ((word_flags & FLAG_UPPERS) != FLAG_FIRST_UPPER)) + if(!found & ((wflags & FLAG_UPPERS) != FLAG_FIRST_UPPER)) { // either all upper or all lower case - if((langopts.numbers & NUM_ROMAN) || ((langopts.numbers & NUM_ROMAN_UC) && (word_flags & FLAG_ALL_UPPER))) + if((tr->langopts.numbers & NUM_ROMAN) || ((tr->langopts.numbers & NUM_ROMAN_UC) && (wflags & FLAG_ALL_UPPER))) { - if((found = TranslateRoman(word1,phonemes)) != 0) + if((found = TranslateRoman(tr, word1, phonemes)) != 0) dictionary_flags[0] |= FLAG_ABBREV; // prevent emphasis if capitals } } @@ -785,7 +720,8 @@ if((wmark > 0) && (wmark < 8)) emphasize_allcaps = FLAG_EMPHASIZED; } else - if(!found && !(dictionary_flags[0] & FLAG_SKIPWORDS) && (word_length<4) && (clause_lower_count > 3) && (clause_upper_count <= clause_lower_count)) + if(!found && !(dictionary_flags[0] & FLAG_SKIPWORDS) && (word_length<4) && (tr->clause_lower_count > 3) + && (tr->clause_upper_count <= tr->clause_lower_count)) { // An upper case word in a lower case clause. This could be an abbreviation. spell_word = 1; @@ -803,7 +739,7 @@ if((wmark > 0) && (wmark < 8)) while(*wordx != ' ') { - wordx += TranslateLetter(wordx, phonemes,spell_word, word_length); + wordx += TranslateLetter(tr,wordx, phonemes,spell_word, word_length); posn++; if(phonemes[0] == phonSWITCH) { @@ -814,7 +750,7 @@ if((wmark > 0) && (wmark < 8)) return(0); } } - SetSpellingStress(phonemes,spell_word,posn); + SetSpellingStress(tr,phonemes,spell_word,posn); } else if(found == 0) @@ -826,13 +762,13 @@ if((wmark > 0) && (wmark < 8)) length = 999; wordx = word1; - while(((length < 3) && (length > 0))|| (word_length > 1 && Unpronouncable(wordx))) + while(((length < 3) && (length > 0))|| (word_length > 1 && Unpronouncable(tr,wordx))) { char *p; // This word looks "unpronouncable", so speak letters individually until we // find a remainder that we can pronounce. emphasize_allcaps = 0; - wordx += TranslateLetter(wordx,phonemes,0, word_length); + wordx += TranslateLetter(tr,wordx,phonemes,0, word_length); posn++; if(phonemes[0] == phonSWITCH) { @@ -858,14 +794,14 @@ if((wmark > 0) && (wmark < 8)) if(length > 0) wordx[-1] = ' '; // prevent this affecting the pronunciation of the pronuncable part } - SetSpellingStress(phonemes,0,posn); + SetSpellingStress(tr,phonemes,0,posn); // anything left ? if(*wordx != ' ') { // Translate the stem unpron_length = strlen(phonemes); - end_type = TranslateRules(wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags, dictionary_flags); + end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags, dictionary_flags); if(phonemes[0] == phonSWITCH) { @@ -879,13 +815,13 @@ if((wmark > 0) && (wmark < 8)) int wc; // characters not recognised, speak them individually - utf8_in(&wc, wordx, 0); + utf8_in(&wc, wordx); if((word_length == 1) && IsAlpha(wc)) { posn = 0; while((*wordx != ' ') && (*wordx != 0)) { - wordx += TranslateLetter(wordx, phonemes, 4, word_length); + wordx += TranslateLetter(tr,wordx, phonemes, 4, word_length); posn++; if(phonemes[0] == phonSWITCH) { @@ -894,7 +830,7 @@ if((wmark > 0) && (wmark < 8)) return(0); } } - SetSpellingStress(phonemes,spell_word,posn); + SetSpellingStress(tr,phonemes,spell_word,posn); } } @@ -914,11 +850,11 @@ if((wmark > 0) && (wmark < 8)) // remove any standard suffix and confirm that the prefix is still recognised phonemes2[0] = 0; - end2 = TranslateRules(wordx, phonemes2, N_WORD_PHONEMES, end_phonemes2, wflags|FLAG_NO_PREFIX|FLAG_NO_TRACE, dictionary_flags); + end2 = TranslateRules(tr, wordx, phonemes2, N_WORD_PHONEMES, end_phonemes2, wflags|FLAG_NO_PREFIX|FLAG_NO_TRACE, dictionary_flags); if(end2) { - RemoveEnding(wordx,end2,word_copy); - end_type = TranslateRules(wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags|FLAG_NO_TRACE, dictionary_flags); + RemoveEnding(tr, wordx, end2, word_copy); + end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags|FLAG_NO_TRACE, dictionary_flags); memcpy(wordx,word_copy,strlen(word_copy)); if((end_type & SUFX_P) == 0) { @@ -942,7 +878,7 @@ if((wmark > 0) && (wmark < 8)) if(prefix_type & SUFX_V) { - expect_verb = 1; // use the verb form of the word + tr->expect_verb = 1; // use the verb form of the word } wordx[-1] = c_temp; @@ -985,10 +921,10 @@ if((wmark > 0) && (wmark < 8)) strncpy0(prefix_phonemes2,end_phonemes,sizeof(prefix_phonemes2)); wordpf = &prefix_chars[1]; - found = LookupDictList(&wordpf, phonemes, dictionary_flags, SUFX_P, wtab); // without prefix + found = LookupDictList(tr, &wordpf, phonemes, dictionary_flags, SUFX_P, wtab); // without prefix if(found == 0) { - end_type = TranslateRules(wordpf, phonemes, N_WORD_PHONEMES, end_phonemes, 0, dictionary_flags); + end_type = TranslateRules(tr, wordpf, phonemes, N_WORD_PHONEMES, end_phonemes, 0, dictionary_flags); sprintf(prefix_phonemes,"%s%s%s",phonemes,end_phonemes,prefix_phonemes2); } prefix_flags = 1; @@ -1000,7 +936,7 @@ if((wmark > 0) && (wmark < 8)) end_phonemes[0] = 0; end_type = 0; - found = LookupDictList(&wordx, phonemes, dictionary_flags2, SUFX_P, wtab); // without prefix + found = LookupDictList(tr, &wordx, phonemes, dictionary_flags2, SUFX_P, wtab); // without prefix if(dictionary_flags[0]==0) { dictionary_flags[0] = dictionary_flags2[0]; @@ -1010,7 +946,7 @@ if((wmark > 0) && (wmark < 8)) prefix_flags = 1; if(found == 0) { - end_type = TranslateRules(wordx, phonemes, N_WORD_PHONEMES, end_phonemes, 0, dictionary_flags); + end_type = TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, end_phonemes, 0, dictionary_flags); if(phonemes[0] == phonSWITCH) { @@ -1028,7 +964,7 @@ char phonemes2[N_WORD_PHONEMES]; strcpy(phonemes2,phonemes); // The word has a standard ending, re-translate without this ending - end_flags = RemoveEnding(wordx,end_type,word_copy); + end_flags = RemoveEnding(tr, wordx, end_type, word_copy); phonemes_ptr = &phonemes[unpron_length]; phonemes_ptr[0] = 0; @@ -1037,7 +973,7 @@ strcpy(phonemes2,phonemes); { // lookup the stem without the prefix removed wordx[-1] = c_temp; - found = LookupDictList(&word1, phonemes_ptr, dictionary_flags2, end_flags, wtab); // include prefix, but not suffix + found = LookupDictList(tr, &word1, phonemes_ptr, dictionary_flags2, end_flags, wtab); // include prefix, but not suffix wordx[-1] = ' '; if(dictionary_flags[0]==0) { @@ -1052,7 +988,7 @@ strcpy(phonemes2,phonemes); } if(found == 0) { - found = LookupDictList(&wordx, phonemes_ptr, dictionary_flags2, end_flags, wtab); // without prefix and suffix + found = LookupDictList(tr, &wordx, phonemes_ptr, dictionary_flags2, end_flags, wtab); // without prefix and suffix if(phonemes_ptr[0] == phonSWITCH) { // change to another language in order to translate this word @@ -1074,14 +1010,14 @@ strcpy(phonemes2,phonemes); strcpy(phonemes,phonemes2); // language specific changes - ApplySpecialAttribute(phonemes,dictionary_flags[0]); + ApplySpecialAttribute(tr,phonemes,dictionary_flags[0]); } else { if(end_flags & FLAG_SUFX) - TranslateRules(wordx, phonemes, N_WORD_PHONEMES, NULL,wflags | FLAG_SUFFIX_REMOVED, dictionary_flags); + TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, NULL,wflags | FLAG_SUFFIX_REMOVED, dictionary_flags); else - TranslateRules(wordx, phonemes, N_WORD_PHONEMES, NULL,wflags,dictionary_flags); + TranslateRules(tr, wordx, phonemes, N_WORD_PHONEMES, NULL,wflags,dictionary_flags); if(phonemes[0] == phonSWITCH) { @@ -1097,7 +1033,7 @@ strcpy(phonemes2,phonemes); if((end_type & SUFX_T) == 0) { // the default is to add the suffix and then determine the word's stress pattern - AppendPhonemes(phonemes, N_WORD_PHONEMES, end_phonemes); + AppendPhonemes(tr,phonemes, N_WORD_PHONEMES, end_phonemes); end_phonemes[0] = 0; } } @@ -1109,12 +1045,12 @@ strcpy(phonemes2,phonemes); { // s or 's suffix, append [s], [z] or [Iz] depending on previous letter if(last_char == 'f') - TranslateRules(&word_ss[1], phonemes, N_WORD_PHONEMES, NULL, 0, NULL); + TranslateRules(tr, &word_ss[1], phonemes, N_WORD_PHONEMES, NULL, 0, NULL); else if((last_char==0) || (strchr_w("hsx",last_char)==NULL)) - TranslateRules(&word_zz[1], phonemes, N_WORD_PHONEMES, NULL, 0, NULL); + TranslateRules(tr, &word_zz[1], phonemes, N_WORD_PHONEMES, NULL, 0, NULL); else - TranslateRules(&word_iz[1], phonemes, N_WORD_PHONEMES, NULL, 0, NULL); + TranslateRules(tr, &word_iz[1], phonemes, N_WORD_PHONEMES, NULL, 0, NULL); } wflags |= emphasize_allcaps; @@ -1126,11 +1062,11 @@ strcpy(phonemes2,phonemes); in a primary stress, and this one starts with one */ if(prefix_flags || (strchr(prefix_phonemes,phonSTRESS_P)!=NULL)) { - if((langopts.param[LOPT_PREFIXES]) || (prefix_type & SUFX_T)) + if((tr->langopts.param[LOPT_PREFIXES]) || (prefix_type & SUFX_T)) { char *p; // German, keep a secondary stress on the stem - SetWordStress(phonemes,dictionary_flags[0],3,0); + SetWordStress(tr, phonemes, dictionary_flags[0], 3, 0); // reduce all but the first primary stress ix=0; @@ -1146,22 +1082,22 @@ strcpy(phonemes2,phonemes); } strcpy(word_phonemes,prefix_phonemes); strcat(word_phonemes,phonemes); - SetWordStress(word_phonemes,dictionary_flags[0],-1,0); + SetWordStress(tr, word_phonemes, dictionary_flags[0], -1, 0); } else { // stress position affects the whole word, including prefix strcpy(word_phonemes,prefix_phonemes); strcat(word_phonemes,phonemes); - SetWordStress(word_phonemes,dictionary_flags[0],-1,prev_last_stress); + SetWordStress(tr, word_phonemes, dictionary_flags[0], -1, tr->prev_last_stress); } } else { if(prefix_phonemes[0] == 0) - SetWordStress(phonemes,dictionary_flags[0],-1,prev_last_stress); + SetWordStress(tr, phonemes, dictionary_flags[0], -1, tr->prev_last_stress); else - SetWordStress(phonemes,dictionary_flags[0],-1,0); + SetWordStress(tr, phonemes, dictionary_flags[0], -1, 0); strcpy(word_phonemes,prefix_phonemes); strcat(word_phonemes,phonemes); } @@ -1183,7 +1119,7 @@ strcpy(phonemes2,phonemes); { // A word is indicated in the source text as stressed // Give it stress level 6 (for the intonation module) - ChangeWordStress(this,word_phonemes,6); + ChangeWordStress(tr,word_phonemes,6); if(wflags & FLAG_EMPHASIZED) dictionary_flags[0] |= FLAG_PAUSE1; // precede by short pause @@ -1193,10 +1129,10 @@ strcpy(phonemes2,phonemes); { // the word has attribute to stress or unstress when at end of clause if(dictionary_flags[0] & (FLAG_STRESS_END | FLAG_STRESS_END2)) - ChangeWordStress(this,word_phonemes,4); + ChangeWordStress(tr,word_phonemes,4); else if(dictionary_flags[0] & FLAG_UNSTRESS_END) - ChangeWordStress(this,word_phonemes,3); + ChangeWordStress(tr,word_phonemes,3); } // dictionary flags for this word give a clue about which alternative pronunciations of @@ -1204,57 +1140,57 @@ strcpy(phonemes2,phonemes); if(end_type & SUFX_F) { // expect a verb form, with or without -s suffix - expect_verb = 2; - expect_verb_s = 2; + tr->expect_verb = 2; + tr->expect_verb_s = 2; } if(dictionary_flags[1] & FLAG_PASTF) { /* expect perfect tense in next two words */ - expect_past = 3; - expect_verb = 0; - expect_noun = 0; + tr->expect_past = 3; + tr->expect_verb = 0; + tr->expect_noun = 0; } else if(dictionary_flags[1] & FLAG_VERBF) { /* expect a verb in the next word */ - expect_verb = 2; - expect_verb_s = 0; /* verb won't have -s suffix */ - expect_noun = 0; + tr->expect_verb = 2; + tr->expect_verb_s = 0; /* verb won't have -s suffix */ + tr->expect_noun = 0; } else if(dictionary_flags[1] & FLAG_VERBSF) { // expect a verb, must have a -s suffix - expect_verb = 0; - expect_verb_s = 2; - expect_past = 0; - expect_noun = 0; + tr->expect_verb = 0; + tr->expect_verb_s = 2; + tr->expect_past = 0; + tr->expect_noun = 0; } else if(dictionary_flags[1] & FLAG_NOUNF) { /* not expecting a verb next */ - expect_noun = 3; - expect_verb = 0; - expect_verb_s = 0; - expect_past = 0; + tr->expect_noun = 3; + tr->expect_verb = 0; + tr->expect_verb_s = 0; + tr->expect_past = 0; } if((wordx[0] != 0) && (!(dictionary_flags[1] & FLAG_VERB_EXT))) { - if(expect_verb > 0) - expect_verb--; + if(tr->expect_verb > 0) + tr->expect_verb--; - if(expect_verb_s > 0) - expect_verb_s--; + if(tr->expect_verb_s > 0) + tr->expect_verb_s--; - if(expect_noun >0) - expect_noun--; + if(tr->expect_noun >0) + tr->expect_noun--; - if(expect_past > 0) - expect_past--; + if(tr->expect_past > 0) + tr->expect_past--; } if((word_length == 1) && iswalpha(first_char) && (first_char != 'i')) @@ -1301,7 +1237,7 @@ int SetTranslator2(const char *new_language) if((translator2 != NULL) && (strcmp(new_language,translator2_language) != 0)) { // we already have an alternative translator, but not for the required language, delete it - delete translator2; + DeleteTranslator(translator2); translator2 = NULL; } @@ -1310,7 +1246,7 @@ int SetTranslator2(const char *new_language) translator2 = SelectTranslator(new_language); strcpy(translator2_language,new_language); - if(translator2->LoadDictionary(new_language,0) != 0) + if(LoadDictionary(translator2, new_language, 0) != 0) { SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table new_phoneme_tab = -1; @@ -1323,8 +1259,8 @@ int SetTranslator2(const char *new_language) -int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int next_pause) -{//====================================================================================== +static int TranslateWord2(Translator *tr, char *word, WORD_TAB *wtab, int pre_pause, int next_pause) +{//================================================================================================= int flags=0; int stress; int next_stress; @@ -1350,6 +1286,7 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne int sylimit; // max. number of syllables in a word to be combined with a preceding preposition const char *new_language; unsigned char bad_phoneme[4]; + int word_flags; int word_copy_len; char word_copy[N_WORD_BYTES+1]; @@ -1396,8 +1333,8 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne } // after a $pause word attribute, ignore a $pause attribute on the next two words - if(prepause_timeout > 0) - prepause_timeout--; + if(tr->prepause_timeout > 0) + tr->prepause_timeout--; if((option_sayas & 0xf0) == 0x10) { @@ -1422,7 +1359,7 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne } } - p = (unsigned char *)translator->word_phonemes; + p = (unsigned char *)word_phonemes; if(word_flags & FLAG_PHONEMES) { // The input is in phoneme mnemonics, not language text @@ -1463,7 +1400,7 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne while(((c2 = word_copy[ix] = word[ix]) != ' ') && (c2 != 0) && (ix < N_WORD_BYTES)) ix++; word_copy_len = ix; - flags = translator->TranslateWord(word, next_pause, wtab); + flags = TranslateWord(translator, word, next_pause, wtab); if(flags & FLAG_SPELLWORD) { @@ -1472,7 +1409,7 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne return(flags); } - if((flags & FLAG_ALT2_TRANS) && ((sylimit = langopts.param[LOPT_COMBINE_WORDS]) > 0)) + if((flags & FLAG_ALT2_TRANS) && ((sylimit = tr->langopts.param[LOPT_COMBINE_WORDS]) > 0)) { char *p2; int ok = 1; @@ -1485,7 +1422,7 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne p2 = word; while(*p2 != ' ') p2++; - utf8_in(&c_word2, p2+1, 0); // first character of the next word; + utf8_in(&c_word2, p2+1); // first character of the next word; if(!iswalpha(c_word2)) { ok =0; @@ -1497,7 +1434,7 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne { // only if the second word has $alt attribute strcpy(ph_buf,word_phonemes); - flags2 = translator->TranslateWord(p2+1, 0, wtab+1); + flags2 = TranslateWord(translator, p2+1, 0, wtab+1); if((flags2 & FLAG_ALT_TRANS) == 0) { ok = 0; @@ -1515,12 +1452,12 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne if(ok) { *p2 = '-'; // replace next space by hyphen - flags = translator->TranslateWord(word, next_pause, wtab); // translate the combined word + flags = TranslateWord(translator, word, next_pause, wtab); // translate the combined word if(CountSyllables(p) > (sylimit & 0xf)) { // revert to separate words *p2 = ' '; - flags = translator->TranslateWord(word, next_pause, wtab); + flags = TranslateWord(translator, word, next_pause, wtab); } else { @@ -1544,8 +1481,8 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne if(switch_phonemes >= 0) { // re-translate the word using the new translator - flags = translator2->TranslateWord(word, next_pause, wtab); - strcpy((char *)p,translator2->word_phonemes); + flags = TranslateWord(translator2, word, next_pause, wtab); +// strcpy((char *)p,translator2->word_phonemes); if(p[0] == phonSWITCH) { // the second translator doesn't want to process this word @@ -1568,11 +1505,11 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne if(pre_pause < 1) pre_pause = 1; } - if((flags & FLAG_PREPAUSE) && (prepause_timeout == 0)) + if((flags & FLAG_PREPAUSE) && (tr->prepause_timeout == 0)) { // the word is marked in the dictionary list with $pause if(pre_pause < 4) pre_pause = 4; - prepause_timeout = 3; + tr->prepause_timeout = 3; } } @@ -1604,8 +1541,8 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne SetPlist2(&ph_list2[n_ph_list2++],phonPAUSE_NOLINK); pre_pause--; } - end_stressed_vowel = 0; // forget about the previous word - prev_dict_flags = 0; + tr->end_stressed_vowel = 0; // forget about the previous word + tr->prev_dict_flags = 0; } if((option_capitals==1) && (word_flags & FLAG_FIRST_UPPER)) @@ -1692,7 +1629,7 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne if(ph_code == phonX1) { // a language specific action - if(langopts.param[LOPT_IT_DOUBLING]) + if(tr->langopts.param[LOPT_IT_DOUBLING]) { flags |= FLAG_DOUBLING; } @@ -1730,10 +1667,10 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne } else { - if(first_phoneme && langopts.param[LOPT_IT_DOUBLING]) + if(first_phoneme && tr->langopts.param[LOPT_IT_DOUBLING]) { - if(((prev_dict_flags & FLAG_DOUBLING) && (langopts.param[LOPT_IT_DOUBLING] & 1)) || - (end_stressed_vowel && (langopts.param[LOPT_IT_DOUBLING] & 2))) + if(((tr->prev_dict_flags & FLAG_DOUBLING) && (tr->langopts.param[LOPT_IT_DOUBLING] & 1)) || + (tr->end_stressed_vowel && (tr->langopts.param[LOPT_IT_DOUBLING] & 2))) { // italian, double the initial consonant if the previous word ends with a // stressed vowel, or is marked with a flag @@ -1753,10 +1690,10 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne plist2->sourceix = source_ix; } - end_stressed_vowel = 0; + tr->end_stressed_vowel = 0; if((stress >= 4) && (phoneme_tab[ph_list2[n_ph_list2-1].phcode]->type == phVOWEL)) { - end_stressed_vowel = 1; // word ends with a stressed vowel + tr->end_stressed_vowel = 1; // word ends with a stressed vowel } if(switch_phonemes >= 0) @@ -1781,7 +1718,7 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne ph_list2[max_stress_ix].synthflags |= SFLAG_PROMOTE_STRESS; } - prev_dict_flags = flags; + tr->prev_dict_flags = flags; return(flags); } // end of TranslateWord2 @@ -1852,8 +1789,8 @@ static int EmbeddedCommand(unsigned int &source_index) -int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in, int *insert) -{//================================================================================== +static int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in, int *insert) +{//========================================================================================= int ix; unsigned int word; unsigned int new_c, c2, c_lower; @@ -1919,8 +1856,8 @@ int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in, int *in } -int Translator::TranslateChar(char *ptr, int prev_in, unsigned int c, unsigned int next_in, int *insert) -{//===================================================================================================== +static int TranslateChar(Translator *tr, char *ptr, int prev_in, unsigned int c, unsigned int next_in, int *insert) +{//================================================================================================================ // To allow language specific examination and replacement of characters int code; @@ -1938,12 +1875,12 @@ int Translator::TranslateChar(char *ptr, int prev_in, unsigned int c, unsigned i 0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71, 0x72,0x73,0x74,0x75 }; - switch(translator_name) + switch(tr->translator_name) { case L('a','f'): // look for 'n and replace by a special character (unicode: schwa) - utf8_in(&next2, &ptr[1], 0); + utf8_in(&next2, &ptr[1]); if(!iswalpha(prev_in)) { @@ -1987,12 +1924,12 @@ int Translator::TranslateChar(char *ptr, int prev_in, unsigned int c, unsigned i } break; } - return(SubstituteChar(this,c,next_in,insert)); + return(SubstituteChar(tr,c,next_in,insert)); } -void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_out, char **voice_change) -{//====================================================================================================== +void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *tone_out, char **voice_change) +{//========================================================================================================== int ix; int c; int cc; @@ -2026,7 +1963,6 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_ int n_digits; short charix[N_TR_SOURCE+1]; - WORD_TAB words[N_CLAUSE_WORDS]; int word_count=0; // index into words @@ -2036,6 +1972,7 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_ int tone; int tone2; + p_textinput = (char *)vp_input; p_wchar_input = (wchar_t *)vp_input; @@ -2049,7 +1986,7 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_ for(ix=0; ixReadClause(f_text, source, charix, N_TR_SOURCE, &tone2); + terminator = ReadClause(tr, f_text, source, charix, N_TR_SOURCE, &tone2); charix[N_TR_SOURCE] = count_characters; @@ -2099,19 +2036,20 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_ ph_list2[0].phcode = phonPAUSE_SHORT; n_ph_list2 = 1; - prev_last_stress = 0; - prepause_timeout = 0; + tr->prev_last_stress = 0; + tr->prepause_timeout = 0; + tr->expect_verb=0; + tr->expect_noun=0; + tr->expect_past=0; + tr->expect_verb_s=0; + tr->phonemes_repeat_count = 0; + tr->end_stressed_vowel=0; + tr->prev_dict_flags = 0; + word_count = 0; single_quoted = 0; word_flags = 0; next_word_flags = 0; - expect_verb=0; - expect_noun=0; - expect_past=0; - expect_verb_s=0; - end_stressed_vowel=0; - prev_dict_flags = 0; - phonemes_repeat_count = 0; sbuf[0] = 0; sbuf[1] = ' '; @@ -2137,9 +2075,9 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_ while(!finished && (ix < (int)sizeof(sbuf))&& (n_ph_list2 < N_PHONEME_LIST-4)) { prev_out2 = prev_out; - utf8_in(&prev_out,&sbuf[ix-1],1); // prev_out = sbuf[ix-1]; + utf8_in2(&prev_out,&sbuf[ix-1],1); // prev_out = sbuf[ix-1]; - if(langopts.tone_numbers && IsDigit09(prev_out) && IsAlpha(prev_out2)) + if(tr->langopts.tone_numbers && IsDigit09(prev_out) && IsAlpha(prev_out2)) { // tone numbers can be part of a word, consider them as alphabetic prev_out = 'a'; @@ -2153,7 +2091,7 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_ else if(source_index > 0) { - utf8_in(&prev_in,&source[source_index-1],1); // prev_in = source[source_index-1]; + utf8_in2(&prev_in,&source[source_index-1],1); // prev_in = source[source_index-1]; } prev_source_index = source_index; @@ -2165,10 +2103,10 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_ } else { - source_index += utf8_in(&cc,&source[source_index],0); // cc = source[source_index++]; + source_index += utf8_in(&cc,&source[source_index]); // cc = source[source_index++]; c = cc; } - utf8_in(&next_in,&source[source_index],0); + utf8_in(&next_in,&source[source_index]); if((c == CTRL_EMBEDDED) || (c == ctrl_embedded)) { @@ -2242,7 +2180,7 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_ // speak as words #ifdef deleted -if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_out)) +if((c == '/') && (tr->langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_out)) { // TESTING, explicit indication of stressed syllable by /2 after the word word_mark = next_in-'0'; @@ -2266,7 +2204,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou word_flags |= FLAG_FOCUS; } - c = TranslateChar(&source[source_index], prev_in,c, next_in, &char_inserted); // optional language specific function + c = TranslateChar(tr, &source[source_index], prev_in,c, next_in, &char_inserted); // optional language specific function if(c == 8) continue; // ignore this character @@ -2274,11 +2212,11 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou next_in = char_inserted; // allow certain punctuation within a word (usually only apostrophe) - if(!IsAlpha(c) && !IsSpace(c) && (wcschr(punct_within_word,c) == 0)) + if(!IsAlpha(c) && !IsSpace(c) && (wcschr(tr->punct_within_word,c) == 0)) { if(IsAlpha(prev_out)) { - if(langopts.tone_numbers && IsDigit09(c) && !IsDigit09(next_in)) + if(tr->langopts.tone_numbers && IsDigit09(c) && !IsDigit09(next_in)) { // allow a tone number as part of the word } @@ -2321,12 +2259,12 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou else if(IsAlpha(c)) { - if(!IsAlpha(prev_out) || (langopts.ideographs && ((c > 0x3040) || (prev_out > 0x3040)))) + if(!IsAlpha(prev_out) || (tr->langopts.ideographs && ((c > 0x3040) || (prev_out > 0x3040)))) { - if(wcschr(punct_within_word,prev_out) == 0) + if(wcschr(tr->punct_within_word,prev_out) == 0) letter_count = 0; // don't reset count for an apostrophy within a word - if((prev_out != ' ') && (wcschr(punct_within_word,prev_out) == 0)) + if((prev_out != ' ') && (wcschr(tr->punct_within_word,prev_out) == 0)) { // start of word, insert space if not one there already c = ' '; @@ -2353,7 +2291,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou { c = towlower2(c); - if(langopts.param[LOPT_SYLLABLE_CAPS]) + if(tr->langopts.param[LOPT_SYLLABLE_CAPS]) { if(syllable_marked == 0) { @@ -2442,7 +2380,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou single_quoted = 0; } else - if((wcschr(char_plus_apostrophe,prev_in) != 0) && (prev_out2 == ' ')) + if((wcschr(tr->char_plus_apostrophe,prev_in) != 0) && (prev_out2 == ' ')) { // consider single character plus apostrophe as a word single_quoted = 0; @@ -2484,13 +2422,13 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou else if(iswdigit(c)) { - if(langopts.tone_numbers && IsAlpha(prev_out) && !IsDigit(next_in)) + if(tr->langopts.tone_numbers && IsAlpha(prev_out) && !IsDigit(next_in)) { } else if((prev_out != ' ') && !iswdigit(prev_out)) { - if((prev_out != langopts.decimal_sep) || ((decimal_sep_count > 0) && (langopts.decimal_sep == ','))) + if((prev_out != tr->langopts.decimal_sep) || ((decimal_sep_count > 0) && (tr->langopts.decimal_sep == ','))) { c = ' '; space_inserted = 1; @@ -2592,7 +2530,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou word_count = 1; } - clause_end = &sbuf[ix-1]; + tr->clause_end = &sbuf[ix-1]; sbuf[ix] = 0; words[0].pre_pause = 0; // don't add extra pause at beginning of clause words[word_count].pre_pause = 8; @@ -2627,7 +2565,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou // digits should have been converted to Latin alphabet ('0' to '9') word = pw = &sbuf[words[ix].start]; - if(iswdigit(word[0]) && (langopts.numbers2 & NUM2_100000)) + if(iswdigit(word[0]) && (tr->langopts.numbers2 & NUM2_100000)) { // Languages with 100000 numbers. Remove thousands separators so that we can insert them again later pn = number_buf; @@ -2638,7 +2576,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou *pn++ = *pw++; } else - if((*pw == langopts.thousands_sep) && (pw[1] == ' ') && iswdigit(pw[2])) + if((*pw == tr->langopts.thousands_sep) && (pw[1] == ' ') && iswdigit(pw[2])) { pw += 2; ix++; // skip "word" @@ -2664,25 +2602,25 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou pn = &number_buf[1]; nx = n_digits; - if(langopts.numbers2 & NUM2_100000a) + if(tr->langopts.numbers2 & NUM2_100000a) break_numbers = break_numbers3; else - if(langopts.numbers2 & NUM2_100000) + if(tr->langopts.numbers2 & NUM2_100000) break_numbers = break_numbers2; else break_numbers = break_numbers1; while(pn < &number_buf[sizeof(number_buf)-3]) { - if(!isdigit(c = *pw++) && (c != langopts.decimal_sep)) + if(!isdigit(c = *pw++) && (c != tr->langopts.decimal_sep)) break; *pn++ = c; if((--nx > 0) && (break_numbers & (1 << nx))) { - if(langopts.thousands_sep != ' ') + if(tr->langopts.thousands_sep != ' ') { - *pn++ = langopts.thousands_sep; + *pn++ = tr->langopts.thousands_sep; } *pn++ = ' '; if(break_numbers & (1 << (nx-1))) @@ -2704,7 +2642,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou for(pw = &number_buf[1]; pw < pn;) { - TranslateWord2(pw, &words[ix], words[ix].pre_pause,0 ); + TranslateWord2(tr, pw, &words[ix], words[ix].pre_pause,0 ); while(*pw++ != ' '); words[ix].pre_pause = 0; words[ix].flags = 0; @@ -2712,7 +2650,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou } else { - dict_flags = TranslateWord2(word, &words[ix], words[ix].pre_pause, words[ix+1].pre_pause); + dict_flags = TranslateWord2(tr, word, &words[ix], words[ix].pre_pause, words[ix+1].pre_pause); if(dict_flags & FLAG_SPELLWORD) { @@ -2720,9 +2658,9 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou for(pw = word; *pw != ' ';) { memset(number_buf,' ',9); - nx = utf8_in(&c_temp, pw, 0); + nx = utf8_in(&c_temp, pw); memcpy(&number_buf[2],pw,nx); - TranslateWord2(&number_buf[2], &words[ix], 0, 0 ); + TranslateWord2(tr, &number_buf[2], &words[ix], 0, 0 ); pw += nx; } } @@ -2744,10 +2682,12 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou for(ix=0; ix<2; ix++) { // terminate the clause with 2 PAUSE phonemes - ph_list2[n_ph_list2+ix].phcode = phonPAUSE; - ph_list2[n_ph_list2+ix].stress = 0; - ph_list2[n_ph_list2+ix].sourceix = 0; - ph_list2[n_ph_list2+ix].synthflags = 0; + PHONEME_LIST2 *p2; + p2 = &ph_list2[n_ph_list2 + ix]; + p2->phcode = phonPAUSE; + p2->stress = 0; + p2->sourceix = 0; + p2->synthflags = 0; } n_ph_list2 += 2; @@ -2760,7 +2700,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou clause_pause = 10; } - MakePhonemeList(clause_pause, new_sentence); + MakePhonemeList(tr, clause_pause, new_sentence); if(embedded_count) // ???? is this needed { @@ -2814,7 +2754,6 @@ void InitText(int control) skipping_text = 0; new_sentence = 1; - ungot_char = 0; prev_clause_pause = 0; option_sayas = 0; diff --git a/src/translate.h b/src/translate.h index 103a4695..50ae91dc 100755 --- a/src/translate.h +++ b/src/translate.h @@ -397,18 +397,9 @@ typedef struct { #define NUM_SEP_SPACE 0x1000 // allow space as thousands separator (in addition to langopts.thousands_sep) #define NUM_DEC_IT 0x2000 // (LANG=it) speak post-decimal-point digits as a combined number not as single digits -class Translator +struct Translator {//============= -public: - Translator(); - virtual ~Translator(); - void *TranslateClause(FILE *f_text, const void *vp_input, int *tone, char **voice_change); - int TranslateWord(char *word, int next_pause, WORD_TAB *wtab); - int LoadDictionary(const char *name, int no_error); - virtual void CalcLengths(); - virtual void CalcPitches(int clause_tone); - void GetTranslatedPhonemeString(char *phon_out, int n_phon_out); - + LANGUAGE_OPTIONS langopts; int translator_name; int transpose_offset; @@ -416,7 +407,6 @@ public: int transpose_min; char phon_out[300]; - char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes char phonemes_repeat[20]; int phonemes_repeat_count; @@ -441,56 +431,8 @@ public: char *data_dictrules; // language_1 translation rules file char *data_dictlist; // language_2 dictionary lookup file char *dict_hashtab[N_HASH_DICT]; // hash table to index dictionary lookup file + char *letterGroups[N_LETTER_GROUPS]; - -private: - int TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int next_pause); - int TranslateLetter(char *letter, char *phonemes, int control, int word_length); - void SetSpellingStress(char *phonemes, int control, int n_chars); - void WriteMnemonic(int *ix, int mnem); - void MakePhonemeList(int post_pause, int new_sentence); - int SubstitutePhonemes(PHONEME_LIST2 *plist_out); - - int ReadClause(FILE *f_in, char *buf, short *charix, int n_buf, int *tone_type); - int AnnouncePunctuation(int c1, int c2, char *buf, int ix); - - const char *LookupDict2(const char *word, const char *word2, char *phonetic, unsigned int *flags, int end_flags, WORD_TAB *wtab); - const char *LookupSpecial(const char *string, char *text_out); - const char *LookupCharName(int c); - void LookupLetter(unsigned int letter, int next_byte, char *ph_buf); - int LookupLetter2(unsigned int letter, char *ph_buf); - void LookupAccentedLetter(unsigned int letter, char *ph_buf); - int LookupNum2(int value, int control, char *ph_out); - int LookupNum3(int value, char *ph_out, int suppress_null, int thousandplex, int prev_thousands); - int LookupThousands(int value, int thousandplex, char *ph_out); - int TranslateNumber_1(char *word1, char *ph_out, unsigned int *flags, int wflags); - int TranslateRoman(char *word, char *ph_out); - int TranslateChar(char *ptr, int prev_in, unsigned int c, unsigned int next_in, int *insert); - - void InitGroups(void); - void AppendPhonemes(char *string, int size, const char *ph); - char *DecodeRule(const char *group, char *rule); - void MatchRule(char *word[], const char *group, char *rule, MatchRecord *match_out, int end_flags, int dict_flags); - int TranslateRules(char *p, char *phonemes, int size, char *end_phonemes, int end_flags, unsigned int *dict_flags); - void ApplySpecialAttribute(char *phonemes, int dict_flags); - - int IsLetter(int letter, int group); - int IsLetterGroup(char *word, int group, int pre); - - void CalcPitches_Tone(int clause_tone); - -protected: - virtual int Unpronouncable(char *word); - virtual void SetWordStress(char *output, unsigned int dictionary_flags, int tonic, int prev_stress); - virtual int RemoveEnding(char *word, int end_type, char *word_copy); - virtual int TranslateNumber(char *word1, char *ph_out, unsigned int *flags, int wflags); - virtual int ChangePhonemes(PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch); - - int IsVowel(int letter); - int LookupDictList(char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab); - int Lookup(const char *word, char *ph_out); - - // groups1 and groups2 are indexes into data_dictrules, set up by InitGroups() // the two-letter rules for each letter must be consecutive in the language_rules source @@ -501,22 +443,13 @@ protected: unsigned char groups2_count[256]; // number of 2 letter groups for this initial letter unsigned char groups2_start[256]; // index into groups2 - char *letterGroups[N_LETTER_GROUPS]; - int n_ph_list2; - PHONEME_LIST2 ph_list2[N_PHONEME_LIST]; // first stage of text->phonemes - - int expect_verb; int expect_past; // expect past tense int expect_verb_s; int expect_noun; - int word_flags; // word is all upper case int prev_last_stress; - int prepause_timeout; - int end_stressed_vowel; // word ends with stressed vowel - int prev_dict_flags; // dictionary flags from previous word char *clause_end; int word_vowel_count; // number of vowels so far @@ -525,10 +458,12 @@ protected: int clause_upper_count; // number of upper case letters in the clause int clause_lower_count; // number of lower case letters in the clause + int prepause_timeout; + int end_stressed_vowel; // word ends with stressed vowel + int prev_dict_flags; // dictionary flags from previous word }; // end of class Translator -extern int option_tone1; extern int option_tone2; #define OPTION_EMPHASIZE_ALLCAPS 0x100 #define OPTION_EMPHASIZE_PENULTIMATE 0x200 @@ -538,7 +473,6 @@ extern int option_quiet; extern int option_phonemes; extern int option_phoneme_events; extern int option_linelength; // treat lines shorter than this as end-of-clause -extern int option_harmonic1; extern int option_multibyte; extern int option_capitals; extern int option_punctuation; @@ -569,9 +503,6 @@ extern char skip_marker[N_MARKER_LENGTH]; #define N_PUNCTLIST 60 extern wchar_t option_punctlist[N_PUNCTLIST]; // which punctuation characters to announce extern unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS]; -extern const unsigned short punct_chars[]; // punctuation chars fo end-of-clause - -extern int speech_parameters[]; extern Translator *translator; extern Translator *translator2; @@ -580,31 +511,23 @@ extern char dictionary_name[40]; extern char ctrl_embedded; // to allow an alternative CTRL for embedded commands extern char *p_textinput; extern wchar_t *p_wchar_input; -extern int ungot_char; extern int dictionary_skipwords; extern int (* uri_callback)(int, const char *, const char *); extern int (* phoneme_callback)(const char *); extern void SetLengthMods(Translator *tr, int value); -Translator *SelectTranslator(const char *name); -int SetTranslator2(const char *name); int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name,int flags); void LoadConfig(void); -int PhonemeCode(unsigned int mnem); -void ChangeWordStress(Translator *tr, char *word, int new_stress); int TransposeAlphabet(char *text, int offset, int min, int max); -int utf8_in(int *c, const char *buf, int backwards); +int utf8_in(int *c, const char *buf); +int utf8_in2(int *c, const char *buf, int backwards); int utf8_out(unsigned int c, char *buf); int utf8_nbytes(const char *buf); int lookupwchar(const unsigned short *list,int c); int Eof(void); char *strchr_w(const char *s, int c); int IsBracket(int c); -void ResetLetterBits(Translator *tr, int groups); -void SetLetterBits(Translator *tr, int group, const char *string); -void SetLetterBitsRange(Translator *tr, int group, int first, int last); -void SetLetterVowel(Translator *tr, int c); void InitNamedata(void); void InitText(int flags); void InitText2(void); @@ -612,6 +535,41 @@ int IsDigit(unsigned int c); int IsAlpha(unsigned int c); int isspace2(unsigned int c); int towlower2(unsigned int c); +void GetTranslatedPhonemeString(char *phon_out, int n_phon_out); + +Translator *SelectTranslator(const char *name); +int SetTranslator2(const char *name); +void DeleteTranslator(Translator *tr); +int Lookup(Translator *tr, const char *word, char *ph_out); + +int TranslateNumber(Translator *tr, char *word1, char *ph_out, unsigned int *flags, int wflags); +int TranslateRoman(Translator *tr, char *word, char *ph_out); + +void ChangeWordStress(Translator *tr, char *word, int new_stress); +void SetSpellingStress(Translator *tr, char *phonemes, int control, int n_chars); +int TranslateLetter(Translator *tr, char *letter, char *phonemes, int control, int word_length); +void LookupLetter(Translator *tr, unsigned int letter, int next_byte, char *ph_buf); +void LookupAccentedLetter(Translator *tr, unsigned int letter, char *ph_buf); + +int LoadDictionary(Translator *tr, const char *name, int no_error); +int LookupDictList(Translator *tr, char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab); + +void MakePhonemeList(Translator *tr, int post_pause, int new_sentence); +int ChangePhonemes_ru(Translator *tr, PHONEME_LIST2 *phlist, int n_ph, int index, PHONEME_TAB *ph, CHANGEPH *ch); +void ApplySpecialAttribute(Translator *tr, char *phonemes, int dict_flags); +void AppendPhonemes(Translator *tr, char *string, int size, const char *ph); + +void CalcLengths(Translator *tr); +void CalcPitches(Translator *tr, int clause_tone); + +int RemoveEnding(Translator *tr, char *word, int end_type, char *word_copy); +int Unpronouncable(Translator *tr, char *word); +void SetWordStress(Translator *tr, char *output, unsigned int dictionary_flags, int tonic, int prev_stress); +int TranslateRules(Translator *tr, char *p, char *phonemes, int size, char *end_phonemes, int end_flags, unsigned int *dict_flags); +int TranslateWord(Translator *tr, char *word1, int next_pause, WORD_TAB *wtab); +void *TranslateClause(Translator *tr, FILE *f_text, const void *vp_input, int *tone, char **voice_change); +int ReadClause(Translator *tr, FILE *f_in, char *buf, short *charix, int n_buf, int *tone_type); + void SetVoiceStack(espeak_VOICE *v); extern FILE *f_trans; // for logging diff --git a/src/transldlg.cpp b/src/transldlg.cpp index 679444b4..52c1eb84 100755 --- a/src/transldlg.cpp +++ b/src/transldlg.cpp @@ -423,11 +423,11 @@ void TranslDlg::OnCommand(wxCommandEvent& event) InitText(0); while((vp != NULL) && (n_ph_list < N_PH_LIST)) { - vp = translator->TranslateClause(NULL,vp,&clause_tone,NULL); - translator->CalcPitches(clause_tone); - translator->CalcLengths(); + vp = TranslateClause(translator,NULL,vp,&clause_tone,NULL); + CalcPitches(translator,clause_tone); + CalcLengths(translator); - translator->GetTranslatedPhonemeString(translator->phon_out,sizeof(translator->phon_out)); + GetTranslatedPhonemeString(translator->phon_out,sizeof(translator->phon_out)); if(clause_count++ > 0) strcat(phon_out," ||"); strcat(phon_out,translator->phon_out); diff --git a/src/voices.cpp b/src/voices.cpp index 073dc947..5411a039 100755 --- a/src/voices.cpp +++ b/src/voices.cpp @@ -164,11 +164,12 @@ const char variants_male[N_VOICE_VARIANTS] = {1,2,3,4,5,0}; const char variants_female[N_VOICE_VARIANTS] = {11,12,13,14,0}; const char *variant_lists[3] = {variants_either, variants_male, variants_female}; -voice_t voicedata; +static voice_t voicedata; voice_t *voice = &voicedata; -char *fgets_strip(char *buf, int size, FILE *f_in) -{//=============================================== + +static char *fgets_strip(char *buf, int size, FILE *f_in) +{//====================================================== // strip trailing spaces, and truncate lines at // comment int len; char *p; @@ -187,8 +188,8 @@ char *fgets_strip(char *buf, int size, FILE *f_in) } -void SetToneAdjust(voice_t *voice, int *tone_pts) -{//============================================== +static void SetToneAdjust(voice_t *voice, int *tone_pts) +{//===================================================== int ix; int pt; int y; @@ -420,7 +421,6 @@ SetToneAdjust(voice,tone_points); if(tone_only == 0) { n_replace_phonemes = 0; - option_tone1 = 0; option_quiet = 0; LoadMbrolaTable(NULL,NULL,0); } @@ -470,11 +470,11 @@ static void PhonemeReplacement(int type, char *p) if((n < 2) || (n_replace_phonemes >= N_REPLACE_PHONEMES)) return; - if((phon = LookupPh(phon_string1)) == 0) + if((phon = LookupPhonemeString(phon_string1)) == 0) return; // not recognised replace_phonemes[n_replace_phonemes].old_ph = phon; - replace_phonemes[n_replace_phonemes].new_ph = LookupPh(phon_string2); + replace_phonemes[n_replace_phonemes].new_ph = LookupPhonemeString(phon_string2); replace_phonemes[n_replace_phonemes++].type = flags; } // end of PhonemeReplacement @@ -581,7 +581,7 @@ voice_t *LoadVoice(const char *vname, int control) if(!tone_only && (translator != NULL)) { - delete translator; + DeleteTranslator(translator); translator = NULL; } @@ -672,7 +672,7 @@ voice_t *LoadVoice(const char *vname, int control) SelectPhonemeTableName(phonemes_name); if(new_translator != NULL) - delete new_translator; + DeleteTranslator(new_translator); new_translator = SelectTranslator(translator_name); langopts = &new_translator->langopts; @@ -704,7 +704,7 @@ voice_t *LoadVoice(const char *vname, int control) sscanf(p,"%s",translator_name); if(new_translator != NULL) - delete new_translator; + DeleteTranslator(new_translator); new_translator = SelectTranslator(translator_name); langopts = &new_translator->langopts; @@ -919,7 +919,7 @@ voice_t *LoadVoice(const char *vname, int control) fprintf(stderr,"Unknown phoneme table: '%s'\n",phonemes_name); } voice->phoneme_tab_ix = ix; - error = new_translator->LoadDictionary(new_dictionary, control & 4); + error = LoadDictionary(new_translator, new_dictionary, control & 4); if(dictionary_name[0]==0) return(NULL); // no dictionary loaded @@ -962,8 +962,8 @@ voice_t *LoadVoice(const char *vname, int control) } // end of LoadVoice -char *ExtractVoiceVariantName(char *vname, int variant_num) -{//======================================================== +static char *ExtractVoiceVariantName(char *vname, int variant_num) +{//=============================================================== // Remove any voice variant suffix (name or number) from a voice name // Returns the voice variant name @@ -1453,8 +1453,8 @@ char const *SelectVoice(espeak_VOICE *voice_select, int *found) -void GetVoices(const char *path) -{//============================= +static void GetVoices(const char *path) +{//==================================== FILE *f_voice; espeak_VOICE *voice_data; int ftype; diff --git a/src/vowelchart.cpp b/src/vowelchart.cpp index 9298b347..fde5bda0 100644 --- a/src/vowelchart.cpp +++ b/src/vowelchart.cpp @@ -43,7 +43,6 @@ extern wxString path_phsource; extern char *spects_data; extern int n_phoneme_tables; -extern PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS]; // size of the vowelchart png diff --git a/src/wavegen.cpp b/src/wavegen.cpp index 9a24bf91..f8946418 100755 --- a/src/wavegen.cpp +++ b/src/wavegen.cpp @@ -59,7 +59,7 @@ voice_t *wvoice; FILE *f_log = NULL; int option_waveout = 0; -int option_harmonic1 = 10; // 10 +static int option_harmonic1 = 10; // 10 int option_log_frames = 0; static int flutter_amp = 64; @@ -86,7 +86,7 @@ static int echo_amp = 0; static short echo_buf[N_ECHO_BUF]; static int voicing; -RESONATOR rbreath[N_PEAKS]; +static RESONATOR rbreath[N_PEAKS]; static int harm_sqrt_n = 0; @@ -535,7 +535,7 @@ static int WaveCallback(const void *inputBuffer, void *outputBuffer, /* This is a fixed version of Pa_OpenDefaultStream() for use if the version in portaudio V19 is broken */ -PaError Pa_OpenDefaultStream2( PaStream** stream, +static PaError Pa_OpenDefaultStream2( PaStream** stream, int inputChannelCount, int outputChannelCount, PaSampleFormat sampleFormat, @@ -1073,8 +1073,8 @@ void InitBreath(void) -void SetBreath() -{//============= +static void SetBreath() +{//==================== #ifndef PLATFORM_RISCOS int pk; @@ -1094,8 +1094,8 @@ void SetBreath() } // end of SetBreath -int ApplyBreath(void) -{//================== +static int ApplyBreath(void) +{//========================= int value = 0; #ifndef PLATFORM_RISCOS int noise;