Browse Source

Program restructure and tidy-up.

Change Translator from Class to Struct, so avoiding use of Classes in eSpeak.
Make more functions and variables "extern".


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@209 d46cf337-b52f-0410-862d-fd96e6ae7743
master
jonsd 16 years ago
parent
commit
b053a790df

+ 55
- 41
src/compiledict.cpp View File

static FILE *f_log = NULL; static FILE *f_log = NULL;
extern char *dir_dictionary; extern char *dir_dictionary;


int linenum;
static int linenum;
static int error_count; static int error_count;
static int transpose_offset; // transpose character range for LookupDictList() static int transpose_offset; // transpose character range for LookupDictList()
static int transpose_min; static int transpose_min;
static int text_mode = 0; static int text_mode = 0;
static int debug_flag = 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[] = { MNEM_TAB mnem_flags[] = {
// these in the first group put a value in bits0-3 of dictionary_flags // these in the first group put a value in bits0-3 of dictionary_flags
} }




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) static FILE *fopen_log(const char *fname,const char *access)
{//================================================== {//==================================================
// performs fopen, but produces error message to f_log if it fails // performs fopen, but produces error message to f_log if it fails






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 // Compile a line in the language_list file
unsigned char c; unsigned char c;
char *p; char *p;
{ {
// this assumes that the lower case char is the same length as the upper case char // 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() // 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) if(c2 == 0)
break; break;
if(iswupper(c2)) if(iswupper(c2))






void compile_dictlist_start(void)
{//==============================
static void compile_dictlist_start(void)
{//=====================================
// initialise dictionary list // initialise dictionary list
int ix; int ix;
char *p; char *p;
} }




void compile_dictlist_end(FILE *f_out)
{//===================================
static void compile_dictlist_end(FILE *f_out)
{//==========================================
// Write out the compiled dictionary list // Write out the compiled dictionary list
int hash; int hash;
int length; int length;






int compile_dictlist_file(const char *path, const char* filename)
{//==============================================================
static int compile_dictlist_file(const char *path, const char* filename)
{//=====================================================================
int length; int length;
int hash; int hash;
char *p; char *p;






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 #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 // 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 char *outbuf[5] = {rule_cond, rule_pre, rule_match, rule_post, rule_phonemes};
static int next_state[5] = {2,2,4,4,4}; static int next_state[5] = {2,2,4,4,4};






char *compile_rule(char *input)
{//============================
static char *compile_rule(char *input)
{//===================================
int ix; int ix;
unsigned char c; unsigned char c;
int wc; int wc;
len_name = strlen(group_name); len_name = strlen(group_name);
if((len_name > 0) && (memcmp(rule_match,group_name,len_name) != 0)) 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)) if((group_name[0] == '9') && IsDigit(wc))
{ {
// numeric group, rule_match starts with a digit, so OK // numeric group, rule_match starts with a digit, so OK




#ifdef OUTPUT_FORMAT #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 rule;
int ix; int ix;
unsigned char c; unsigned char c;




//#define LIST_GROUP_INFO //#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 ix;
int len1; int len1;
int len2; int len2;
if(strlen(group_name) > 2) 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); fprintf(f_log,"%5d: Group name longer than 2 bytes (UTF8)",linenum);
error_count++; error_count++;
ix = 0; ix = 0;
while((unsigned char)(*p) > 0x20) // not space or zero-byte while((unsigned char)(*p) > 0x20) // not space or zero-byte
{ {
p += utf8_in(&c,p,0);
p += utf8_in(&c,p);
replace1 += (c << ix); replace1 += (c << ix);
ix += 16; ix += 16;
} }
ix = 0; ix = 0;
while((unsigned char)(*p) > 0x20) while((unsigned char)(*p) > 0x20)
{ {
p += utf8_in(&c,p,0);
p += utf8_in(&c,p);
replace2 += (c << ix); replace2 += (c << ix);
ix += 16; ix += 16;
} }







int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname_err, int flags) 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 // fname: space to write the filename in case of error


compile_dictlist_start(); 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"); compile_dictlist_file(path,"roots");
if(translator->langopts.listx) if(translator->langopts.listx)
{ {
Write4Bytes(f_out,offset_rules); Write4Bytes(f_out,offset_rules);
fclose(f_out); fclose(f_out);


translator->LoadDictionary(dict_name,0);
LoadDictionary(translator, dict_name, 0);


return(error_count); return(error_count);
} // end of compile_dictionary } // end of compile_dictionary

+ 404
- 384
src/dictionary.cpp
File diff suppressed because it is too large
View File


+ 1
- 1
src/event.cpp View File

} }
//> //>
//<event_display //<event_display
void event_display(espeak_EVENT* event)
static void event_display(espeak_EVENT* event)
{ {
ENTER("event_display"); ENTER("event_display");



+ 8
- 7
src/extras.cpp View File

#include "translate.h" #include "translate.h"
#include "options.h" #include "options.h"


extern char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes


//****************************************************************************************************** //******************************************************************************************************


// convert word to lower-case // convert word to lower-case
for(ix=0, p=&word2[1];;) for(ix=0, p=&word2[1];;)
{ {
ix += utf8_in(&c,&word[ix],0);
ix += utf8_in(&c,&word[ix]);
c = towlower(c); c = towlower(c);
p += utf8_out(c,p); p += utf8_out(c,p);
if(c == 0) if(c == 0)


// translate // translate
memset(&winfo,0,sizeof(winfo)); memset(&winfo,0,sizeof(winfo));
translator->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) if(strcmp(phonemes,pronounce2) == 0)
{ {


// translate // translate
memset(&winfo,0,sizeof(winfo)); 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 // find the stress position in the translation
max_stress = 0; max_stress = 0;
check_root = 0; check_root = 0;


ph = phoneme_tab[phonPAUSE]; 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]; ph = phoneme_tab[(unsigned int)*p];
if(ph == NULL) if(ph == NULL)
n_chars = 0; n_chars = 0;
for(k=0; k<ix; ) for(k=0; k<ix; )
{ {
k += utf8_in(&wc,&buf[k],0);
k += utf8_in(&wc,&buf[k]);
wc = towlower(wc); // convert to lower case wc = towlower(wc); // convert to lower case
if(iswalpha(wc)) if(iswalpha(wc))
{ {

+ 1
- 1
src/fifo.cpp View File



//<sleep_until_start_request_or_inactivity //<sleep_until_start_request_or_inactivity


int sleep_until_start_request_or_inactivity()
static int sleep_until_start_request_or_inactivity()
{ {
SHOW_TIME("fifo > sleep_until_start_request_or_inactivity > ENTER"); SHOW_TIME("fifo > sleep_until_start_request_or_inactivity > ENTER");
int a_start_is_required=0; int a_start_is_required=0;

+ 22
- 22
src/intonation.cpp View File

short pitch2; short pitch2;
} SYLLABLE; } SYLLABLE;


SYLLABLE *syllable_tab;
static SYLLABLE *syllable_tab;




static int tone_pitch_env; /* used to return pitch envelope */ static int tone_pitch_env; /* used to return pitch envelope */






void Translator::CalcPitches_Tone(int clause_tone)
{//===============================================
static void CalcPitches_Tone(Translator *tr, int clause_tone)
{//==========================================================
// clause_tone: 0=. 1=, 2=?, 3=! 4=none // clause_tone: 0=. 1=, 2=?, 3=! 4=none
PHONEME_LIST *p; PHONEME_LIST *p;
int ix; int ix;
phoneme_list[final_stressed].tone = 7; phoneme_list[final_stressed].tone = 7;


// language specific, changes to tones // language specific, changes to tones
if(translator_name == L('v','i'))
if(tr->translator_name == L('v','i'))
{ {
// LANG=vi // LANG=vi
p = &phoneme_list[final_stressed]; p = &phoneme_list[final_stressed];
if(p->tone_ph == 0) 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
} }




tph = phoneme_tab[tone_ph]; tph = phoneme_tab[tone_ph];


// Mandarin // Mandarin
if(translator_name == L('z','h'))
if(tr->translator_name == L('z','h'))
{ {
if(tone_ph == 0) if(tone_ph == 0)
{ {
if(pause || tone_promoted) 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; tone_promoted = 1;
} }
else else
{ {
tone_ph = LookupPh("11"); // default tone 5
tone_ph = PhonemeCode2('1','1'); // default tone 5
} }


p->tone_ph = tone_ph; p->tone_ph = tone_ph;
if(prevw_tph->mnemonic == 0x343132) // [214] if(prevw_tph->mnemonic == 0x343132) // [214]
{ {
if(tph->mnemonic == 0x343132) // [214] if(tph->mnemonic == 0x343132) // [214]
prev_p->tone_ph = LookupPh("35");
prev_p->tone_ph = PhonemeCode2('3','5');
else else
prev_p->tone_ph = LookupPh("21");
prev_p->tone_ph = PhonemeCode2('2','1');
} }
if((prev_tph->mnemonic == 0x3135) && (tph->mnemonic == 0x3135)) // [51] + [51] 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 if(tph->mnemonic == 0x3131) // [11] Tone 5
{ {
// tone 5, change its level depending on the previous tone (across word boundaries) // tone 5, change its level depending on the previous tone (across word boundaries)
if(prevw_tph->mnemonic == 0x3535) if(prevw_tph->mnemonic == 0x3535)
p->tone_ph = LookupPh("22");
p->tone_ph = PhonemeCode2('2','2');
if(prevw_tph->mnemonic == 0x3533) if(prevw_tph->mnemonic == 0x3533)
p->tone_ph = LookupPh("33");
p->tone_ph = PhonemeCode2('3','3');
if(prevw_tph->mnemonic == 0x343132) if(prevw_tph->mnemonic == 0x343132)
p->tone_ph = LookupPh("44");
p->tone_ph = PhonemeCode2('4','4');


// tone 5 is unstressed (shorter) // tone 5 is unstressed (shorter)
p->tone = 1; // diminished stress p->tone = 1; // diminished stress






void Translator::CalcPitches(int clause_type)
{//==========================================
void CalcPitches(Translator *tr, int clause_type)
{//==============================================
// clause_type: 0=. 1=, 2=?, 3=! 4=none // clause_type: 0=. 1=, 2=?, 3=! 4=none
PHONEME_LIST *p; PHONEME_LIST *p;
SYLLABLE *syl; SYLLABLE *syl;






if(langopts.tone_language == 1)
if(tr->langopts.tone_language == 1)
{ {
CalcPitches_Tone(clause_type);
CalcPitches_Tone(tr,clause_type);
return; return;
} }




option = langopts.intonation_group;
option = tr->langopts.intonation_group;
if(option >= INTONATION_TYPES) if(option >= INTONATION_TYPES)
option = 0; 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) if(clause_type == 4)
no_tonic = 1; /* incomplete clause, used for abbreviations such as Mr. Dr. Mrs. */ no_tonic = 1; /* incomplete clause, used for abbreviations such as Mr. Dr. Mrs. */

+ 3
- 3
src/klatt.cpp View File

*/ */




int parwave(klatt_frame_ptr frame)
static int parwave(klatt_frame_ptr frame)
{ {
double temp; double temp;
double outbypas; double outbypas;
to zero. to zero.
*/ */


void reset_resonators()
static void reset_resonators()
{ {
int r_ix; int r_ix;


} }
} }


void parwave_init()
static void parwave_init()
{ {
kt_globals.FLPhz = (950 * kt_globals.samrate) / 10000; kt_globals.FLPhz = (950 * kt_globals.samrate) / 10000;
kt_globals.BLPhz = (630 * kt_globals.samrate) / 10000; kt_globals.BLPhz = (630 * kt_globals.samrate) / 10000;

+ 171
- 171
src/numbers.cpp View File

} ACCENTS; } ACCENTS;


// these are tokens to look up in the *_list file. // these are tokens to look up in the *_list file.
ACCENTS accents_tab[] = {
static ACCENTS accents_tab[] = {
{"_lig", 1}, {"_lig", 1},
{"_smc", 1}, // smallcap {"_smc", 1}, // smallcap
{"_tur", 1}, // turned {"_tur", 1}, // turned




// characters U+00e0 to U+017f // 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_GRAVE,0), // U+00e0
LETTER('a',M_ACUTE,0), LETTER('a',M_ACUTE,0),
LETTER('a',M_CIRCUMFLEX,0), LETTER('a',M_CIRCUMFLEX,0),




// characters U+0250 to U+029F // 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('a',M_TURNED,0), // U+250
LETTER(L_ALPHA,0,0), LETTER(L_ALPHA,0,0),
LETTER(L_ALPHA,M_TURNED,0), LETTER(L_ALPHA,M_TURNED,0),
LIGATURE('t','s',M_CURL), 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; int len;
char single_letter[10]; char single_letter[10];


single_letter[len+2] = ' '; single_letter[len+2] = ' ';
single_letter[len+3] = 0; 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] = ' '; 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]); 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 // lookup the character in the accents table
int accent_data = 0; int accent_data = 0;
int accent1 = 0; int accent1 = 0;
} }




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(accent2 != 0)
{ {
if(Lookup(accents_tab[accent2].name, ph_accent2) == 0)
if(Lookup(tr, accents_tab[accent2].name, ph_accent2) == 0)
{ {
// break; // break;
} }
if(letter2 != 0) if(letter2 != 0)
{ {
//ligature //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); sprintf(ph_buf,"%s%c%s%c%s%s",ph_accent1, phonPAUSE_VSHORT, ph_letter1, phonSTRESS_P, ph_letter2, ph_accent2);
} }
else else
if(accent1 == 0) if(accent1 == 0)
strcpy(ph_buf, ph_letter1); strcpy(ph_buf, ph_letter1);
else 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); sprintf(ph_buf,"%s%c%c%s", ph_accent1, phonPAUSE_VSHORT, phonSTRESS_P, ph_letter1);
else else
sprintf(ph_buf,"%c%s%c%s%c", phonSTRESS_2, ph_letter1, phonPAUSE_VSHORT, ph_accent1, phonPAUSE_VSHORT); sprintf(ph_buf,"%c%s%c%s%c", phonSTRESS_2, ph_letter1, phonPAUSE_VSHORT, ph_accent1, phonPAUSE_VSHORT);






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; int len;
unsigned char *p; unsigned char *p;
static char single_letter[10] = {0,0}; static char single_letter[10] = {0,0};
if(next_byte == -1) if(next_byte == -1)
{ {
// speaking normal text, not individual characters // speaking normal text, not individual characters
if(Lookup(&single_letter[2],ph_buf1) != 0)
if(Lookup(tr, &single_letter[2], ph_buf1) != 0)
return; return;


single_letter[1] = '_'; 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 return; // the character is specified as _* so ignore it when speaking normal text


// check whether this character is specified for English // check whether this character is specified for English
SetTranslator2("en"); 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 // yes, switch to English and re-translate the word
sprintf(ph_buf1,"%c",phonSWITCH); sprintf(ph_buf1,"%c",phonSWITCH);
{ {
// lookup space as _&32 etc. // lookup space as _&32 etc.
sprintf(&single_letter[1],"_#%d ",letter); sprintf(&single_letter[1],"_#%d ",letter);
Lookup(&single_letter[1],ph_buf1);
Lookup(tr, &single_letter[1], ph_buf1);
return; return;
} }


dict_flags[1] = 0; dict_flags[1] = 0;
ptr = &single_letter[1]; ptr = &single_letter[1];
if(Lookup(&single_letter[1],ph_buf3) == 0)
if(Lookup(tr, &single_letter[1], ph_buf3) == 0)
{ {
single_letter[1] = ' '; 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) if(ph_buf3[0] == 0)
{ {
LookupAccentedLetter(letter, ph_buf3);
LookupAccentedLetter(tr, letter, ph_buf3);
} }


if(ph_buf3[0] == 0) if(ph_buf3[0] == 0)






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 // get pronunciation for an isolated letter
// return number of bytes used by the letter // return number of bytes used by the letter
ph_buf[0] = 0; ph_buf[0] = 0;
capital[0] = 0; capital[0] = 0;


n_bytes = utf8_in(&letter,word,0);
n_bytes = utf8_in(&letter,word);


if((letter & 0xfff00) == 0x0e000) if((letter & 0xfff00) == 0x0e000)
{ {
// include CAPITAL information // include CAPITAL information
if(iswupper(letter)) if(iswupper(letter))
{ {
Lookup("_cap",capital);
Lookup(tr, "_cap", capital);
} }
} }
letter = towlower2(letter); letter = towlower2(letter);


LookupLetter(letter, word[n_bytes], ph_buf);
LookupLetter(tr, letter, word[n_bytes], ph_buf);


if(ph_buf[0] == phonSWITCH) if(ph_buf[0] == phonSWITCH)
{ {
return(0); 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 // speak as English, check whether there is a translation for this character
SetTranslator2("en"); SetTranslator2("en");
save_option_phonemes = option_phonemes; save_option_phonemes = option_phonemes;
option_phonemes = 0; 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 SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table
option_phonemes = save_option_phonemes; option_phonemes = save_option_phonemes;


{ {
// character name not found // character name not found
if(iswalpha(letter)) if(iswalpha(letter))
Lookup("_?A",ph_buf);
Lookup(tr, "_?A", ph_buf);


if((ph_buf[0]==0) && !iswspace(letter)) if((ph_buf[0]==0) && !iswspace(letter))
Lookup("_??",ph_buf);
Lookup(tr, "_??", ph_buf);


if(ph_buf[0] != 0) if(ph_buf[0] != 0)
{ {
{ {
pbuf += strlen(pbuf); pbuf += strlen(pbuf);
*pbuf++ = phonPAUSE_VSHORT; *pbuf++ = phonPAUSE_VSHORT;
LookupLetter(*p2, 0, pbuf);
LookupLetter(tr, *p2, 0, pbuf);
} }
} }
} }


len = strlen(phonemes); len = strlen(phonemes);
if(langopts.accents & 2)
if(tr->langopts.accents & 2)
sprintf(ph_buf2,"%c%s%s",0xff,ph_buf,capital); sprintf(ph_buf2,"%c%s%s",0xff,ph_buf,capital);
else else
sprintf(ph_buf2,"%c%s%s",0xff,capital,ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress() sprintf(ph_buf2,"%c%s%s",0xff,capital,ph_buf); // the 0xff marker will be removed or replaced in SetSpellingStress()






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. // Individual letter names, reduce the stress of some.
int ix; int ix;
unsigned int c; unsigned int c;
{ {
count++; count++;


if(langopts.spelling_stress == 1)
if(tr->langopts.spelling_stress == 1)
{ {
// stress on initial letter when spelling // stress on initial letter when spelling
if(count > 1) if(count > 1)






int Translator::TranslateRoman(char *word, char *ph_out)
int TranslateRoman(Translator *tr, char *word, char *ph_out)
{//===================================================== {//=====================================================
int c; int c;
char *p; char *p;
if(acc < 2) if(acc < 2)
return(0); return(0);


if(acc > langopts.max_roman)
if(acc > tr->langopts.max_roman)
return(0); 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]; p = &ph_out[0];


if((langopts.numbers & NUM_ROMAN_AFTER) == 0)
if((tr->langopts.numbers & NUM_ROMAN_AFTER) == 0)
{ {
strcpy(ph_out,ph_roman); strcpy(ph_out,ph_roman);
p = &ph_out[strlen(ph_out)]; p = &ph_out[strlen(ph_out)];
} }


sprintf(number_chars," %d ",acc); 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); strcat(ph_out,ph_roman);
return(1); return(1);
} // end of TranslateRoman } // end of TranslateRoman




int Translator::LookupNum2(int value, int control, char *ph_out)
{//=============================================================
static const char *M_Variant(int value)
{//====================================
// returns M, or perhaps MA for some cases
if(((value % 100)>20) || ((value % 100)<10)) // but not teens, 10 to 19
{
if ((translator->langopts.numbers2 & 0x40) &&
((value % 10)>=2) &&
((value % 10)<=4))
{
// for Polish language - two forms of plural!
return("0MA");
}

if((translator->langopts.numbers2 & 0x80) &&
((value % 10)==1))
{
return("1MA");
}

}
return("0M");
}


static int LookupThousands(Translator *tr, int value, int thousandplex, char *ph_out)
{//==================================================================================
int found;
char string[12];
char ph_of[12];
char ph_thousands[40];

ph_of[0] = 0;

// first look fora match with the exact value of thousands
sprintf(string,"_%dM%d",value,thousandplex);

if((found = Lookup(tr, string, ph_thousands)) == 0)
{
if((value % 100) >= 20)
{
Lookup(tr, "_0of", ph_of);
}

sprintf(string,"_%s%d",M_Variant(value),thousandplex);

if(Lookup(tr, string, ph_thousands) == 0)
{
// repeat "thousand" if higher order names are not available
sprintf(string,"_%dM1",value);
if((found = Lookup(tr, string, ph_thousands)) == 0)
Lookup(tr, "_0M1", ph_thousands);
}
}
sprintf(ph_out,"%s%s",ph_of,ph_thousands);
return(found);
}


static int LookupNum2(Translator *tr, int value, int control, char *ph_out)
{//========================================================================
// Lookup a 2 digit number // Lookup a 2 digit number
// control bit 0: use special form of '1' // control bit 0: use special form of '1'
// control bit 2: use feminine form of '2' // control bit 2: use feminine form of '2'


if((value == 1) && (control & 1)) if((value == 1) && (control & 1))
{ {
if(Lookup("_1a",ph_out) != 0)
if(Lookup(tr, "_1a", ph_out) != 0)
return(0); return(0);
} }
// is there a special pronunciation for this 2-digit number // is there a special pronunciation for this 2-digit number
if(control & 4) if(control & 4)
{ {
sprintf(string,"_%df",value); sprintf(string,"_%df",value);
found = Lookup(string,ph_digits);
found = Lookup(tr, string, ph_digits);
} }
if(found == 0) if(found == 0)
{ {
sprintf(string,"_%d",value); sprintf(string,"_%d",value);
found = Lookup(string,ph_digits);
found = Lookup(tr, string, ph_digits);
} }


// no, speak as tens+units // no, speak as tens+units
if((control & 2) && (value < 10)) if((control & 2) && (value < 10))
{ {
// speak leading zero // speak leading zero
Lookup("_0",ph_tens);
Lookup(tr, "_0", ph_tens);
} }
else else
{ {
if((value % 10) == 0) if((value % 10) == 0)
{ {
sprintf(string,"_%d0",value / 10); sprintf(string,"_%d0",value / 10);
found = Lookup(string,ph_tens);
found = Lookup(tr, string, ph_tens);
} }
if(!found) if(!found)
{ {
sprintf(string,"_%dX",value / 10); sprintf(string,"_%dX",value / 10);
Lookup(string,ph_tens);
Lookup(tr, string, ph_tens);
} }


if((value % 10) == 0) if((value % 10) == 0)
{ {
// is there a variant form of this number? // is there a variant form of this number?
sprintf(string,"_%df",units); sprintf(string,"_%df",units);
found = Lookup(string,ph_digits);
found = Lookup(tr, string, ph_digits);
} }
if(found == 0) if(found == 0)
{ {
sprintf(string,"_%d",units); sprintf(string,"_%d",units);
Lookup(string,ph_digits);
Lookup(tr, string, ph_digits);
} }
} }


if(langopts.numbers & 0x30)
if(tr->langopts.numbers & 0x30)
{ {
Lookup("_0and",ph_and);
if(langopts.numbers & 0x10)
Lookup(tr, "_0and", ph_and);
if(tr->langopts.numbers & 0x10)
sprintf(ph_out,"%s%s%s",ph_digits,ph_and,ph_tens); sprintf(ph_out,"%s%s%s",ph_digits,ph_and,ph_tens);
else else
sprintf(ph_out,"%s%s%s",ph_tens,ph_and,ph_digits); sprintf(ph_out,"%s%s%s",ph_tens,ph_and,ph_digits);
} }
else else
{ {
if(langopts.numbers & 0x200)
if(tr->langopts.numbers & 0x200)
{ {
// remove vowel from the end of tens if units starts with a vowel (LANG=Italian) // remove vowel from the end of tens if units starts with a vowel (LANG=Italian)
if((ix = strlen(ph_tens)-1) >= 0) if((ix = strlen(ph_tens)-1) >= 0)
sprintf(ph_out,"%s%s",ph_tens,ph_digits); sprintf(ph_out,"%s%s",ph_tens,ph_digits);
} }


if(langopts.numbers & 0x100)
if(tr->langopts.numbers & 0x100)
{ {
// only one primary stress // only one primary stress
found = 0; found = 0;
} // end of LookupNum2 } // end of LookupNum2




int Translator::LookupNum3(int value, char *ph_out, int suppress_null, int thousandplex, int prev_thousands)
{//=========================================================================================================
static int LookupNum3(Translator *tr, int value, char *ph_out, int suppress_null, int thousandplex, int prev_thousands)
{//====================================================================================================================
// Translate a 3 digit number // Translate a 3 digit number
int found; int found;
int hundreds; int hundreds;
ph_thousands[0] = 0; ph_thousands[0] = 0;
ph_thousand_and[0] = 0; ph_thousand_and[0] = 0;


Lookup("_0C",ph_100);
Lookup(tr, "_0C", ph_100);


if(((langopts.numbers & 0x0800) != 0) && (hundreds == 19))
if(((tr->langopts.numbers & 0x0800) != 0) && (hundreds == 19))
{ {
// speak numbers such as 1984 as years: nineteen-eighty-four // speak numbers such as 1984 as years: nineteen-eighty-four
// ph_100[0] = 0; // don't say "hundred", we also need to surpess "and" // ph_100[0] = 0; // don't say "hundred", we also need to surpess "and"
{ {
ph_digits[0] = 0; ph_digits[0] = 0;


if(LookupThousands(hundreds / 10, thousandplex+1, ph_10T) == 0)
if(LookupThousands(tr, hundreds / 10, thousandplex+1, ph_10T) == 0)
{ {
x = 0; x = 0;
if(langopts.numbers2 & (1 << (thousandplex+1)))
if(tr->langopts.numbers2 & (1 << (thousandplex+1)))
x = 4; x = 4;
LookupNum2(hundreds/10, x, ph_digits);
LookupNum2(tr, hundreds/10, x, ph_digits);
} }


if(langopts.numbers2 & 0x200)
if(tr->langopts.numbers2 & 0x200)
sprintf(ph_thousands,"%s%s%c",ph_10T,ph_digits,phonPAUSE_NOLINK); // say "thousands" before its number, not after sprintf(ph_thousands,"%s%s%c",ph_10T,ph_digits,phonPAUSE_NOLINK); // say "thousands" before its number, not after
else else
sprintf(ph_thousands,"%s%s%c",ph_digits,ph_10T,phonPAUSE_NOLINK); sprintf(ph_thousands,"%s%s%c",ph_digits,ph_10T,phonPAUSE_NOLINK);
ph_digits[0] = 0; ph_digits[0] = 0;
if(hundreds > 0) if(hundreds > 0)
{ {
if((langopts.numbers & 0x100000) && (prev_thousands || (ph_thousands[0] != 0)))
if((tr->langopts.numbers & 0x100000) && (prev_thousands || (ph_thousands[0] != 0)))
{ {
Lookup("_0and",ph_thousand_and);
Lookup(tr, "_0and", ph_thousand_and);
} }


suppress_null = 1; suppress_null = 1;
if((value % 1000) == 100) if((value % 1000) == 100)
{ {
// is there a special pronunciation for exactly 100 ? // is there a special pronunciation for exactly 100 ?
found = Lookup("_1C0",ph_digits);
found = Lookup(tr, "_1C0", ph_digits);
} }
if(!found) if(!found)
{ {
sprintf(string,"_%dC",hundreds); sprintf(string,"_%dC",hundreds);
found = Lookup(string,ph_digits); // is there a specific pronunciation for n-hundred ?
found = Lookup(tr, string, ph_digits); // is there a specific pronunciation for n-hundred ?
} }


if(found) if(found)
} }
else else
{ {
if((hundreds > 1) || ((langopts.numbers & 0x400) == 0))
if((hundreds > 1) || ((tr->langopts.numbers & 0x400) == 0))
{ {
LookupNum2(hundreds,0,ph_digits);
LookupNum2(tr, hundreds, 0, ph_digits);
} }
} }
} }
} }


ph_hundred_and[0] = 0; ph_hundred_and[0] = 0;
if((langopts.numbers & 0x40) && ((value % 100) != 0))
if((tr->langopts.numbers & 0x40) && ((value % 100) != 0))
{ {
if((value > 100) || (prev_thousands && (thousandplex==0))) if((value > 100) || (prev_thousands && (thousandplex==0)))
{ {
Lookup("_0and",ph_hundred_and);
Lookup(tr, "_0and", ph_hundred_and);
} }
} }


if(value == 0) if(value == 0)
{ {
if(suppress_null == 0) if(suppress_null == 0)
Lookup("_0",buf2);
Lookup(tr, "_0", buf2);
} }
else else
{ {
x = 1; // allow "eins" for 1 rather than "ein" x = 1; // allow "eins" for 1 rather than "ein"
else else
{ {
if(langopts.numbers2 & (1 << thousandplex))
if(tr->langopts.numbers2 & (1 << thousandplex))
x = 4; // use variant (feminine) for before thousands and millions x = 4; // use variant (feminine) for before thousands and millions
} }


if(LookupNum2(value,x,buf2) != 0)
if(LookupNum2(tr, value, x, buf2) != 0)
{ {
if(langopts.numbers & 0x80)
if(tr->langopts.numbers & 0x80)
ph_hundred_and[0] = 0; // don't put 'and' after 'hundred' if there's 'and' between tens and units ph_hundred_and[0] = 0; // don't put 'and' after 'hundred' if there's 'and' between tens and units
} }
} }






static const char *M_Variant(int value)
{//====================================
// returns M, or perhaps MA for some cases
if(((value % 100)>20) || ((value % 100)<10)) // but not teens, 10 to 19
{
if ((translator->langopts.numbers2 & 0x40) &&
((value % 10)>=2) &&
((value % 10)<=4))
{
// for Polish language - two forms of plural!
return("0MA");
}

if((translator->langopts.numbers2 & 0x80) &&
((value % 10)==1))
{
return("1MA");
}

}
return("0M");
}


int Translator::LookupThousands(int value, int thousandplex, char *ph_out)
{//=======================================================================
int found;
char string[12];
char ph_of[12];
char ph_thousands[40];

ph_of[0] = 0;

// first look fora match with the exact value of thousands
sprintf(string,"_%dM%d",value,thousandplex);

if((found = Lookup(string,ph_thousands)) == 0)
{
if((value % 100) >= 20)
{
Lookup("_0of",ph_of);
}

sprintf(string,"_%s%d",M_Variant(value),thousandplex);

if(Lookup(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);
}
}
sprintf(ph_out,"%s%s",ph_of,ph_thousands);
return(found);
}


int Translator::TranslateNumber_1(char *word, char *ph_out, unsigned int *flags, int wflags)
{//=========================================================================================
static int TranslateNumber_1(Translator *tr, char *word, char *ph_out, unsigned int *flags, int wflags)
{//====================================================================================================
// Number translation with various options // Number translation with various options
// the "word" may be up to 4 digits // the "word" may be up to 4 digits
// "words" of 3 digits may be preceded by another number "word" for thousands or millions // "words" of 3 digits may be preceded by another number "word" for thousands or millions
ph_buf2[0] = 0; ph_buf2[0] = 0;


// is there a previous thousands part (as a previous "word") ? // 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; prev_thousands = 1;
} }
else else
if((langopts.thousands_sep == ' ') || (langopts.numbers & 0x1000))
if((tr->langopts.thousands_sep == ' ') || (tr->langopts.numbers & 0x1000))
{ {
// thousands groups can be separated by spaces // thousands groups can be separated by spaces
if((n_digits == 3) && isdigit(word[-2])) if((n_digits == 3) && isdigit(word[-2]))
} }
} }


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])) if((n_digits == 2) && (word[3] == ':') && isdigit(word[5]) && isspace(word[7]))
{ {
} }
} }


if((langopts.numbers & 0x1000) && (word[n_digits] == ' '))
if((tr->langopts.numbers & 0x1000) && (word[n_digits] == ' '))
thousands_inc = 1; thousands_inc = 1;
else else
if(word[n_digits] == langopts.thousands_sep)
if(word[n_digits] == tr->langopts.thousands_sep)
thousands_inc = 2; thousands_inc = 2;


if(thousands_inc > 0) if(thousands_inc > 0)
while(isdigit(word[ix]) && isdigit(word[ix+1]) && isdigit(word[ix+2])) while(isdigit(word[ix]) && isdigit(word[ix+1]) && isdigit(word[ix+2]))
{ {
thousandplex++; thousandplex++;
if(word[ix+3] == langopts.thousands_sep)
if(word[ix+3] == tr->langopts.thousands_sep)
ix += (3 + thousands_inc); ix += (3 + thousands_inc);
else else
break; break;
suppress_null = 1; 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 // this "word" ends with a decimal point
Lookup("_dpt",ph_append);
Lookup(tr, "_dpt", ph_append);
decimal_point = 1; decimal_point = 1;
} }
else else
{ {
if((thousandplex > 0) && (value < 1000)) 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 // found an exact match for N thousand
value = 0; value = 0;
if((thousandplex > 1) && prev_thousands && (prev_value > 0)) if((thousandplex > 1) && prev_thousands && (prev_value > 0))
{ {
sprintf(string,"_%s%d",M_Variant(value),thousandplex+1); 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 // speak this thousandplex if there was no word for the previous thousandplex
sprintf(string,"_0M%d",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)) 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 sprintf(ph_out,"%s%s%s",ph_append,ph_buf2,ph_buf); // say "thousands" before its number
else else
sprintf(ph_out,"%s%s%s",ph_buf2,ph_buf,ph_append); sprintf(ph_out,"%s%s%s",ph_buf2,ph_buf,ph_append);
if(decimal_count > 1) if(decimal_count > 1)
{ {
max_decimal_count = 2; max_decimal_count = 2;
switch(langopts.numbers & 0xe000)
switch(tr->langopts.numbers & 0xe000)
{ {
case 0x8000: case 0x8000:
max_decimal_count = 5; max_decimal_count = 5;
// French/Polish decimal fraction // French/Polish decimal fraction
while(word[n_digits] == '0') while(word[n_digits] == '0')
{ {
Lookup("_0",buf1);
Lookup(tr, "_0", buf1);
strcat(ph_out,buf1); strcat(ph_out,buf1);
decimal_count--; decimal_count--;
n_digits++; n_digits++;
} }
if((decimal_count <= max_decimal_count) && isdigit(word[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); strcat(ph_out,buf1);
n_digits += decimal_count; n_digits += decimal_count;
} }
// Italian decimal fractions // Italian decimal fractions
if((decimal_count < 4) || ((decimal_count==4) && (word[n_digits] != '0'))) 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); strcat(ph_out,buf1);
if(word[n_digits]=='0') if(word[n_digits]=='0')
{ {
// decimal part has leading zeros, so add a "hundredths" or "thousandths" suffix // decimal part has leading zeros, so add a "hundredths" or "thousandths" suffix
sprintf(string,"_0Z%d",decimal_count); sprintf(string,"_0Z%d",decimal_count);
Lookup(string,buf1);
Lookup(tr, string, buf1);
strcat(ph_out,buf1); strcat(ph_out,buf1);
} }
n_digits += decimal_count; n_digits += decimal_count;
// Romanian decimal fractions // Romanian decimal fractions
if((decimal_count <= 4) && (word[n_digits] != '0')) 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); strcat(ph_out,buf1);
n_digits += decimal_count; n_digits += decimal_count;
} }
while(isdigit(c = word[n_digits]) && (strlen(ph_out) < (N_WORD_PHONEMES - 10))) while(isdigit(c = word[n_digits]) && (strlen(ph_out) < (N_WORD_PHONEMES - 10)))
{ {
value = word[n_digits++] - '0'; value = word[n_digits++] - '0';
LookupNum2(value, 1, buf1);
LookupNum2(tr, value, 1, buf1);
strcat(ph_out,buf1); strcat(ph_out,buf1);
} }


// something after the decimal part ? // something after the decimal part ?
if(Lookup("_dpt2",buf1))
if(Lookup(tr, "_dpt2", buf1))
strcat(ph_out,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); strcat(ph_out,buf1);
} }
else else
char *p; char *p;
p = &word[n_digits+1]; 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)) if(!iswalpha(next_char))
strcat(ph_out,str_pause); // don't add pause for 100s, 6th, etc. strcat(ph_out,str_pause); // don't add pause for 100s, 6th, etc.






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) if(option_sayas == SAYAS_DIGITS1)
return(0); // speak digits individually 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); return(0);
} // end of TranslateNumber } // end of TranslateNumber

+ 8
- 2
src/phoneme.h View File

extern REPLACE_PHONEMES replace_phonemes[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); char *EncodePhonemes(char *p, char *outptr, unsigned char *bad_phoneme);
void DecodePhonemes(const char *inptr, char *outptr); void DecodePhonemes(const char *inptr, char *outptr);
const char *PhonemeTabName(void);
int LookupPh(const char *string);

extern const char *WordToString(unsigned int word); extern const char *WordToString(unsigned int word);


extern PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS];
extern int phoneme_tab_number;

+ 44
- 34
src/phonemelist.cpp View File

const unsigned char pause_phonemes[8] = {0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG}; 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 // Called for each phoneme in the phoneme list, to allow a language to make changes
// ph The current phoneme // ph The current phoneme

if(tr->translator_name == L('r','u'))
return(ChangePhonemes_ru(tr, phlist, n_ph, index, ph, ch));

return(0); 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 // Copy the phonemes list and perform any substitutions that are required for the
// current voice // current voice
int ix; int ix;
if((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE))) if((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE)))
word_end = 1; // this phoneme is the end of a word 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 // this language does changes to phonemes after translation


ch.vowel_this = syllable; ch.vowel_this = syllable;
ch.vowel_stressed = syllable_stressed; 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 // check whether a Voice has specified that we should replace this phoneme






void Translator::MakePhonemeList(int post_pause, int start_sentence)
{//============================================================================================
void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
{//=====================================================================


int ix=0; int ix=0;
int j; int j;
PHONEME_LIST2 *plist2 = &ph_list2_null; PHONEME_LIST2 *plist2 = &ph_list2_null;
PHONEME_LIST2 *plist2_inserted = NULL; PHONEME_LIST2 *plist2_inserted = NULL;


plist2 = ph_list2;
phlist = phoneme_list; 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 ? // is the last word of the clause unstressed ?
max_stress = 0; 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 // 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; break;
} }
if(max_stress < 4) if(max_stress < 4)
// the last word is unstressed, look for a previous word that can be stressed // the last word is unstressed, look for a previous word that can be stressed
while(--j >= 0) 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; break;
} }
if(ph_list2[j].stress >= 4)
if(plist2[j].stress >= 4)
{ {
// found a stressed syllable, so stop looking // found a stressed syllable, so stop looking
break; break;
} }
} }


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 // set consonant clusters to all voiced or all unvoiced
// Regressive // Regressive


for(j=n_ph_list2-1; j>=0; j--) 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) if(ph == NULL)
continue; continue;


else else
if((voicing==2) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING)) 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 else
else else
if((voicing==1) && ((ph->phflags & phALTERNATIVE)==phSWITCHVOICING)) 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 else
voicing = 0; voicing = 0;
} }
} }
if((regression & 0x4) && (ph_list2[j].sourceix))
if((regression & 0x4) && (plist2[j].sourceix))
{ {
// stop propagation at a word boundary // stop propagation at a word boundary
voicing = 0; voicing = 0;
} }
} }


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 // transfer all the phonemes of the clause into phoneme_list
ph = phoneme_tab[phonPAUSE]; ph = phoneme_tab[phonPAUSE];
switched_language = 0; switched_language = 0;


for(j=0; insert_ph || ((j<n_ph_list2) && (ix < N_PHONEME_LIST-3)); j++)
for(j=0; insert_ph || ((j < n_ph_list2) && (ix < N_PHONEME_LIST-3)); j++)
{ {
prev = ph; prev = ph;


{ {
// in a sequence of unstressed syllables, reduce alternate syllables to 'diminished' // in a sequence of unstressed syllables, reduce alternate syllables to 'diminished'
// stress. But not for the last phoneme of a stressed word // stress. But not for the last phoneme of a stressed word
if((langopts.stress_flags & 0x2) || ((word_stress > 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 // An unstressed final vowel of a stressed word
unstress_count=1; // try again for next syllable unstress_count=1; // try again for next syllable
plist2->synthflags &= ~SFLAG_SYLLABLE; 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'))) if((ph->mnemonic == 't') && (plist2->sourceix == 0) && ((prev->type == phVOWEL) || (prev->mnemonic == 'n')))
{ {
} }




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 reduce_level;
int stress_level; int stress_level;
if(stress_level < reduce_level) if(stress_level < reduce_level)
reduce =1; 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 // don't reduce the most stressed syllable in an unstressed word
reduce = 0; reduce = 0;
{ {
int x; 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 // add a pause after a word which ends in a consonant
insert_ph = phonPAUSE_NOLINK; insert_ph = phonPAUSE_NOLINK;


if(next->type == phVOWEL) 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 // break before a word which starts with a vowel
if(x == 0xc) if(x == 0xc)
insert_ph = phonPAUSE_VSHORT; 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 // adjacent vowels over a word boundary
if(x == 2) if(x == 2)
insert_ph = phonPAUSE_VSHORT; 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 // pause before a words which starts with a stressed vowel
insert_ph = phonPAUSE_SHORT; insert_ph = phonPAUSE_SHORT;


if(plist2 != plist2_inserted) 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))) if((x > 1) || ((insert_ph != phonPAUSE_SHORT) && (insert_ph != phonPAUSE_NOLINK)))
{ {
} }
} }
else 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 // This phoneme can be linked to a following vowel by inserting a linking phoneme
if(next->type == phVOWEL) if(next->type == phVOWEL)

+ 54
- 52
src/readclause.cpp View File

#define N_XML_BUF 256 #define N_XML_BUF 256




const char *xmlbase = ""; // base URL from <speak>
static const char *xmlbase = ""; // base URL from <speak>


int namedata_ix=0;
int n_namedata = 0;
static int namedata_ix=0;
static int n_namedata = 0;
char *namedata = NULL; char *namedata = NULL;




FILE *f_input = NULL;
int ungot_char2 = 0;
static FILE *f_input = NULL;
static int ungot_char2 = 0;
char *p_textinput; char *p_textinput;
wchar_t *p_wchar_input; 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 <sub> ... </sub> 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 <sub> ... </sub> 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 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_stop = ".:!?"; // pitch fall if followed by space
static const char *punct_close = ")]}>;'\""; // always pitch fall unless followed by alnum static const char *punct_close = ")]}>;'\""; // always pitch fall unless followed by alnum
static const char *tone_punct_off = "\001T"; static const char *tone_punct_off = "\001T";


// punctuations symbols that can end a clause // punctuations symbols that can end a clause
const unsigned short punct_chars[] = {',','.','?','!',':',';',
static const unsigned short punct_chars[] = {',','.','?','!',':',';',
0x2013, // en-dash 0x2013, // en-dash
0x2014, // em-dash 0x2014, // em-dash
0x2026, // elipsis 0x2026, // elipsis
} SSML_STACK; } SSML_STACK;


#define N_SSML_STACK 20 #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 #define N_PARAM_STACK 20
int n_param_stack;
static int n_param_stack;
PARAM_STACK param_stack[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] = { const int param_defaults[N_SPEECH_PARAM] = {
0, // silence (internal use) 0, // silence (internal use)
} }




const char *WordToString2(unsigned int word)
{//========================================
static const char *WordToString2(unsigned int word)
{//================================================
// Convert a language mnemonic word into a string // Convert a language mnemonic word into a string
int ix; int ix;
static char buf[5]; static char buf[5];
} }




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]; unsigned int flags[2];
char phonemes[55]; char phonemes[55];
char phonemes2[55]; char phonemes2[55];
char *string1 = (char *)string; 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); DecodePhonemes(phonemes,phonemes2);
sprintf(text_out,"[[%s]]",phonemes2); sprintf(text_out,"[[%s]]",phonemes2);
option_phoneme_input |= 2; option_phoneme_input |= 2;
} }




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 // Find the phoneme string (in ascii) to speak the name of character c
// Used for punctuation characters and symbols // Used for punctuation characters and symbols


single_letter[2+ix]=0; single_letter[2+ix]=0;


string = &single_letter[1]; string = &single_letter[1];
if(LookupDictList(&string, phonemes, flags, 0, NULL) == 0)
if(LookupDictList(tr, &string, phonemes, flags, 0, NULL) == 0)
{ {
// try _* then * // try _* then *
string = &single_letter[2]; 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 // now try the rules
single_letter[1] = ' '; 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 // not found, try English
SetTranslator2("en"); SetTranslator2("en");
string = &single_letter[1]; string = &single_letter[1];
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]; string = &single_letter[2];
translator2->LookupDictList(&string, phonemes, flags, 0, NULL);
LookupDictList(translator2, &string, phonemes, flags, 0, NULL);
} }
if(phonemes[0]) if(phonemes[0])
{ {
{ {
if(lang_name) if(lang_name)
{ {
translator2->SetWordStress(phonemes,flags[0],-1,0);
SetWordStress(translator2, phonemes, flags[0], -1, 0);
DecodePhonemes(phonemes,phonemes2); 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 SelectPhonemeTable(voice->phoneme_tab_ix); // revert to original phoneme table
} }
else else
{ {
SetWordStress(phonemes,flags[0],-1,0);
SetWordStress(tr, phonemes, flags[0], -1, 0);
DecodePhonemes(phonemes,phonemes2); DecodePhonemes(phonemes,phonemes2);
sprintf(buf,"[[%s]] ",phonemes2); sprintf(buf,"[[%s]] ",phonemes2);
} }






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 // announce punctuation names
// c1: the punctuation character // c1: the punctuation character
// c2: the following character // c2: the following character
found = 1; found = 1;
} }
else else
if((punctname = LookupCharName(c1)) != NULL)
if((punctname = LookupCharName(tr, c1)) != NULL)
{ {
found = 1; found = 1;
if(bufix==0) if(bufix==0)
static char ignore_if_self_closing[] = {0,1,1,1,1,0,0,0,0,1,1,0,1,0,1,0,0}; 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}, {"speak", SSML_SPEAK},
{"voice", SSML_VOICE}, {"voice", SSML_VOICE},
{"prosody", SSML_PROSODY}, {"prosody", SSML_PROSODY},
} // end of attr_prosody_value } // 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 // Add the name to the namedata and return its position
int ix; int ix;
int len; int len;
} // end of ProcessSsmlTag } // end of ProcessSsmlTag




MNEM_TAB xml_char_mnemonics[] = {
static MNEM_TAB xml_char_mnemonics[] = {
{"gt",'>'}, {"gt",'>'},
{"lt",'<'}, {"lt",'<'},
{"amp", '&'}, {"amp", '&'},
{NULL,-1}}; {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. /* Find the end of the current clause.
Write the clause into buf Write the clause into buf


clear_skipping_text = 0; 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; end_of_input = 0;
*tone_type = 0; *tone_type = 0;


{ {
char *p_word; char *p_word;
if(translator_name == 0x6a626f)
if(tr->translator_name == 0x6a626f)
{ {
// language jbo : lojban // language jbo : lojban
// treat "i" or ".i" as end-of-sentence // treat "i" or ".i" as end-of-sentence


if(iswupper(c1)) if(iswupper(c1))
{ {
clause_upper_count++;
tr->clause_upper_count++;
if((option_capitals == 2) && (sayas_mode == 0) && !iswupper(cprev)) if((option_capitals == 2) && (sayas_mode == 0) && !iswupper(cprev))
{ {
char text_buf[40]; char text_buf[40];
char text_buf2[30]; 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); sprintf(text_buf,"%s%s%s",tone_punct_on,text_buf2,tone_punct_off);
j = strlen(text_buf); j = strlen(text_buf);
} }
else else
if(iswalpha(c1)) if(iswalpha(c1))
clause_lower_count++;
tr->clause_lower_count++;


if(option_phoneme_input) if(option_phoneme_input)
{ {
// if a list of allowed punctuation has been set up, check whether the character is in it // 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((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); return(terminator);
} }
} }
if((nl_count==0) && (c1 == '.')) 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 // dot after a number indicates an ordinal number
c2 = ' '; c2 = ' ';
{//================= {//=================
int param; int param;


ungot_char = 0;

n_ssml_stack =1; n_ssml_stack =1;
n_param_stack = 1; n_param_stack = 1;
ssml_stack[0].tag_type = 0; ssml_stack[0].tag_type = 0;

+ 18
- 18
src/setlengths.cpp View File

} }




void Translator::CalcLengths()
{//===========================
void CalcLengths(Translator *tr)
{//==============================
int ix; int ix;
int ix2; int ix2;
PHONEME_LIST *prev; PHONEME_LIST *prev;
if(prev->type == phSTOP) if(prev->type == phSTOP)
p->prepause = 60; p->prepause = 60;


if((langopts.word_gap & 0x10) && (p->newword))
if((tr->langopts.word_gap & 0x10) && (p->newword))
p->prepause = 60; p->prepause = 60;


if(p->ph->phflags & phLENGTHENSTOP) if(p->ph->phflags & phLENGTHENSTOP)
p->prepause += 30; p->prepause += 30;


if(p->synthflags & SFLAG_LENGTHEN) if(p->synthflags & SFLAG_LENGTHEN)
p->prepause += langopts.long_stop;
p->prepause += tr->langopts.long_stop;
break; break;


case phVFRICATIVE: case phVFRICATIVE:
else else
p->length = 256; p->length = 256;


if((langopts.word_gap & 0x10) && (p->newword))
if((tr->langopts.word_gap & 0x10) && (p->newword))
p->prepause = 30; p->prepause = 30;


break; break;
p->prepause = 0; 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; p->prepause = 20;


break; break;


case phLIQUID: case phLIQUID:
case phNASAL: case phNASAL:
p->amp = stress_amps[1]; // unless changed later
p->amp = tr->stress_amps[1]; // unless changed later
p->length = 256; // TEMPORARY p->length = 256; // TEMPORARY
min_drop = 0; min_drop = 0;
if(stress > 7) stress = 7; if(stress > 7) stress = 7;


if(pre_sonorant) if(pre_sonorant)
p->amp = stress_amps[stress]-1;
p->amp = tr->stress_amps[stress]-1;
else else
p->amp = stress_amps[stress];
p->amp = tr->stress_amps[stress];


if(emphasized) if(emphasized)
p->amp = 25; p->amp = 25;
if(ix >= (n_phoneme_list-3)) if(ix >= (n_phoneme_list-3))
{ {
// last phoneme of a clause, limit its amplitude // 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 ? // is the last syllable of a word ?


if(more_syllables==0) 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 // 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 else
length_mod = len; length_mod = len;
} }
else 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)) if((next->type == phNASAL) && (next2->type == phSTOP || next2->type == phVSTOP) && (next3->ph->phflags & phFORTIS))
length_mod -= 15; length_mod -= 15;
length_mod += 20; 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; length_mod = (length_mod * len)/128;


{ {
// this is the last syllable in the clause, lengthen it - more for short vowels // this is the last syllable in the clause, lengthen it - more for short vowels
len = p->ph->std_length; 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 len=200; // don't lengthen short vowels more than long vowels at end-of-clause
length_mod = length_mod * (256 + (280 - len)/3)/256; length_mod = length_mod * (256 + (280 - len)/3)/256;
} }

+ 1
- 1
src/speak_lib.cpp View File

int letter; int letter;
int ix; int ix;


ix = utf8_in(&letter,key,0);
ix = utf8_in(&letter,key);
if(key[ix] == 0) if(key[ix] == 0)
{ {
// a single character // a single character

+ 1
- 3
src/speak_riscos.cpp View File

option_linelength = 0; option_linelength = 0;
option_phonemes = 0; option_phonemes = 0;
option_waveout = 0; option_waveout = 0;
option_harmonic1 = 8;
option_multibyte = 0; // auto option_multibyte = 0; // auto
option_capitals = 0; option_capitals = 0;
option_punctuation = 0; option_punctuation = 0;
option_phonemes = 0; option_phonemes = 0;
option_waveout = 0; option_waveout = 0;
option_quiet = 0; option_quiet = 0;
option_harmonic1 = 8;
option_multibyte = 0; // auto option_multibyte = 0; // auto
option_capitals = 0; option_capitals = 0;
option_punctuation = 0; option_punctuation = 0;
{ {
RiscosCloseSound(); RiscosCloseSound();
RemoveCallback(); RemoveCallback();
delete translator;
DeleteTranslator(translator);
FreePhData(); FreePhData();
} /* end of terminate_module */ } /* end of terminate_module */



+ 11
- 11
src/synth_mbrola.cpp View File

#endif // USE_MBROLA_LIB #endif // USE_MBROLA_LIB




MBROLA_TAB *mbrola_tab = NULL;
int mbrola_control = 0;
static MBROLA_TAB *mbrola_tab = NULL;
static int mbrola_control = 0;






} // end of LoadMbrolaTable } // 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 // Look up a phoneme in the mbrola phoneme name translation table
// It may give none, 1, or 2 mbrola phonemes // It may give none, 1, or 2 mbrola phonemes
int mnem = ph->mnemonic; int mnem = ph->mnemonic;




#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
int MbrolaSynth(char *p_mbrola)
{//============================
static int MbrolaSynth(char *p_mbrola)
{//===================================
// p_mbrola is a string of mbrola pho lines - Windows // p_mbrola is a string of mbrola pho lines - Windows
int len; int len;
int finished; int finished;
} // end of SynthMbrola } // end of SynthMbrola
#else #else


int MbrolaSynth(char *p_mbrola)
{//============================
static int MbrolaSynth(char *p_mbrola)
{//===================================
// p_mbrola is a string of mbrola pho lines - Linux // p_mbrola is a string of mbrola pho lines - Linux


// This is wrong // This is wrong


#ifdef TEST_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) int MbrolaFill(int fill_zeros)

+ 19
- 19
src/synthdata.cpp View File



int n_phoneme_tables; int n_phoneme_tables;
PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS]; 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_ix; // a wavefile to play along with the synthesis
int wavefile_amp; int wavefile_amp;
int vowel_transition0; int vowel_transition0;
int vowel_transition1; 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); 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) static int ReadPhFile(char **ptr, const char *fname)
{//================================================= {//=================================================
} }




int LookupPh(const char *string)
{//=============================
int PhonemeCode(unsigned int mnem)
{//===============================
int ix;

for(ix=0; ix<n_phoneme_tab; ix++)
{
if(phoneme_tab[ix] == NULL)
continue;
if(phoneme_tab[ix]->mnemonic == mnem)
return(phoneme_tab[ix]->code);
}
return(0);
}


int LookupPhonemeString(const char *string)
{//========================================
int ix; int ix;
unsigned char c; unsigned char c;
unsigned int mnem; unsigned int mnem;
mnem |= (c << (ix*8)); mnem |= (c << (ix*8));
} }


for(ix=0; ix<n_phoneme_tab; ix++)
{
if(phoneme_tab[ix] == NULL)
continue;
if(phoneme_tab[ix]->mnemonic == mnem)
return(ix);
}
return(0);
return(PhonemeCode(mnem));
} }







static unsigned int LookupSound2(int index, unsigned int other_phcode, int control) static unsigned int LookupSound2(int index, unsigned int other_phcode, int control)
{//================================================================================ {//================================================================================
// control=1 get formant transition data only // control=1 get formant transition data only
if(*match_level == 0) if(*match_level == 0)
seq_len_adjust = FormantTransition2(frames,nf,vowel_transition0,vowel_transition1,prev_ph,which); seq_len_adjust = FormantTransition2(frames,nf,vowel_transition0,vowel_transition1,prev_ph,which);
} }
// FormantTransitions(frames,nf,this_ph,other_ph,which);
} }


nf1 = nf - 1; nf1 = nf - 1;

+ 7
- 10
src/synthesize.cpp View File

} }





void SynthesizeInit() void SynthesizeInit()
{//================== {//==================
last_pitch_cmd = 0; last_pitch_cmd = 0;
} }




int VowelCloseness(frame_t *fr)
{//============================
static int VowelCloseness(frame_t *fr)
{//===================================
// return a value 0-3 depending on the vowel's f1 // return a value 0-3 depending on the vowel's f1
int f1; int f1;


} }




void SwitchDictionary()
{//====================
}



int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
{//============================================================ {//============================================================


// read the next clause from the input text file, translate it, and generate // read the next clause from the input text file, translate it, and generate
// entries in the wavegen command queue // 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) if(option_phonemes > 0)
{ {
fprintf(f_trans,"%s\n",translator->phon_out); fprintf(f_trans,"%s\n",translator->phon_out);

+ 1
- 1
src/synthesize.h View File

espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int srate); espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int srate);
void SetParameter(int parameter, int value, int relative); void SetParameter(int parameter, int value, int relative);
void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola); 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 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 DoSpect(PHONEME_TAB *this_ph, PHONEME_TAB *prev_ph, PHONEME_TAB *next_ph,
int which, PHONEME_LIST *plist, int modulation); int which, PHONEME_LIST *plist, int modulation);

+ 0
- 117
src/tr_english.cpp View File



#include "StdAfx.h" #include "StdAfx.h"


#include <stdio.h>
#include <ctype.h>
#include <wctype.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>

#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 */






+ 170
- 91
src/tr_languages.cpp View File

#include "phoneme.h" #include "phoneme.h"
#include "synthesize.h" #include "synthesize.h"
#include "translate.h" #include "translate.h"
#include "tr_languages.h"






#define OFFSET_MALAYALAM 0xd00 #define OFFSET_MALAYALAM 0xd00
#define OFFSET_KOREAN 0x1100 #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; ix<sizeof(tr->letter_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[] = static const unsigned int replace_cyrillic_latin[] =
{0x430,'a', {0x430,'a',
while(*name != 0) while(*name != 0)
name2 = (name2 << 8) + *name++; name2 = (name2 << 8) + *name++;


tr = NewTranslator();


switch(name2) switch(name2)
{ {
case L('a','f'): case L('a','f'):
{ {
static const short stress_lengths_af[8] = {170,140, 220,220, 0, 0, 250,270}; static const short stress_lengths_af[8] = {170,140, 220,220, 0, 0, 250,270};
tr = new Translator();
SetupTranslator(tr,stress_lengths_af,NULL); SetupTranslator(tr,stress_lengths_af,NULL);


tr->langopts.stress_rule = 0; tr->langopts.stress_rule = 0;
static const short stress_lengths_bn[8] = {180, 180, 210, 210, 0, 0, 230, 240}; 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 }; 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); SetupTranslator(tr,stress_lengths_bn,stress_amps_bn);
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable


static const short stress_lengths_cy[8] = {170,220, 180,180, 0, 0, 250,270}; 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 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); SetupTranslator(tr,stress_lengths_cy,stress_amps_cy);


tr->charset_a0 = charsets[14]; // ISO-8859-14 tr->charset_a0 = charsets[14]; // ISO-8859-14
case L('d','a'): // Danish case L('d','a'): // Danish
{ {
static const short stress_lengths_da[8] = {160,140, 200,200, 0,0, 220,210}; static const short stress_lengths_da[8] = {160,140, 200,200, 0,0, 220,210};
tr = new Translator();
SetupTranslator(tr,stress_lengths_da,NULL); SetupTranslator(tr,stress_lengths_da,NULL);


tr->langopts.stress_rule = 0; tr->langopts.stress_rule = 0;
case L('d','e'): case L('d','e'):
{ {
static const short stress_lengths_de[8] = {150,130, 190,190, 0, 0, 260,275}; 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.stress_rule = 0;
tr->langopts.word_gap = 0x8; // don't use linking phonemes tr->langopts.word_gap = 0x8; // don't use linking phonemes
tr->langopts.vowel_pause = 0x30; tr->langopts.vowel_pause = 0x30;
break; break;


case L('e','n'): 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; break;


case L('e','l'): // Greek case L('e','l'): // Greek
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 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}; // σ static const wchar_t el_char_apostrophe[] = {0x3c3,0}; // σ


tr = new Translator();
SetupTranslator(tr,stress_lengths_el,stress_amps_el); SetupTranslator(tr,stress_lengths_el,stress_amps_el);


tr->charset_a0 = charsets[7]; // ISO-8859-7 tr->charset_a0 = charsets[7]; // ISO-8859-7
static const unsigned char stress_amps_eo[] = {16,14, 20,20, 20,22, 22,21 }; 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}; static const wchar_t eo_char_apostrophe[2] = {'l',0};
tr = new Translator();
SetupTranslator(tr,stress_lengths_eo,stress_amps_eo); SetupTranslator(tr,stress_lengths_eo,stress_amps_eo);


tr->charset_a0 = charsets[3]; // ISO-8859-3 tr->charset_a0 = charsets[3]; // ISO-8859-3
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 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 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); SetupTranslator(tr,stress_lengths_es,stress_amps_es);


tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
static const unsigned char stress_amps_fi[8] = {18,16, 22,22, 20,22, 22,22 }; 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}; 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); SetupTranslator(tr,stress_lengths_fi,stress_amps_fi);


tr->langopts.stress_rule = 0; tr->langopts.stress_rule = 0;
static const short stress_lengths_fr[8] = {190, 170, 190, 200, 0, 0, 235, 240}; 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 }; 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); SetupTranslator(tr,stress_lengths_fr,stress_amps_fr);
tr->langopts.stress_rule = 3; // stress on final syllable tr->langopts.stress_rule = 3; // stress on final syllable
tr->langopts.stress_flags = 0x0024; // don't use secondary stress tr->langopts.stress_flags = 0x0024; // don't use secondary stress
#ifdef deleted #ifdef deleted
case L('g','a'): // Irish Gaelic case L('g','a'): // Irish Gaelic
{ {
tr = new Translator();

tr->langopts.stress_rule = 1; tr->langopts.stress_rule = 1;
} }
break; break;
static const short stress_lengths_hi[8] = {190, 190, 210, 210, 0, 0, 230, 250}; 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 }; 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); SetupTranslator(tr,stress_lengths_hi,stress_amps_hi);
tr->charset_a0 = charsets[19]; // ISCII tr->charset_a0 = charsets[19]; // ISCII
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
static const short stress_lengths_hr[8] = {180,160, 200,200, 0,0, 220,230}; 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}; static const short stress_lengths_sr[8] = {160,150, 200,200, 0,0, 250,260};


tr = new Translator();

if(name2 == L('s','r')) if(name2 == L('s','r'))
SetupTranslator(tr,stress_lengths_sr,stress_amps_hr); SetupTranslator(tr,stress_lengths_sr,stress_amps_hr);
else else
static const unsigned char stress_amps_hu[8] = {17,17, 19,19, 20,22, 22,21 }; 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}; 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); SetupTranslator(tr,stress_lengths_hu,stress_amps_hu);
tr->charset_a0 = charsets[2]; // ISO-8859-2 tr->charset_a0 = charsets[2]; // ISO-8859-2


static const char hy_vowels[] = {0x31, 0x35, 0x37, 0x38, 0x3b, 0x48, 0x55, 0}; 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, 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}; 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); SetupTranslator(tr,stress_lengths_hy,NULL);
tr->langopts.stress_rule = 3; // default stress on final syllable tr->langopts.stress_rule = 3; // default stress on final syllable


{ {
static const short stress_lengths_id[8] = {160, 200, 180, 180, 0, 0, 220, 240}; 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 }; 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); SetupTranslator(tr,stress_lengths_id,stress_amps_id);
tr->langopts.stress_rule = 2; tr->langopts.stress_rule = 2;
tr->langopts.numbers = 0x1009 + NUM_ROMAN; tr->langopts.numbers = 0x1009 + NUM_ROMAN;
static const short stress_lengths_is[8] = {180,160, 200,200, 0,0, 240,250}; 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' 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); SetupTranslator(tr,stress_lengths_is,NULL);
tr->langopts.stress_rule = 0; tr->langopts.stress_rule = 0;
tr->langopts.stress_flags = 0x10; tr->langopts.stress_flags = 0x10;
static const short stress_lengths_it[8] = {150, 140, 170, 170, 0, 0, 300, 330}; 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 }; 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); SetupTranslator(tr,stress_lengths_it,stress_amps_it);


tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
} }
break; 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 case L_jbo: // Lojban
{ {
static const short stress_lengths_jbo[8] = {145,145, 170,160, 0,0, 330,350}; 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) 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); SetupTranslator(tr,stress_lengths_jbo,NULL);
tr->langopts.stress_rule = 2; 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 tr->langopts.vowel_pause = 0x20c; // pause before a word which starts with a vowel, or after a word which ends in a consonant
{ {
static const char ko_ivowels[] = {0x63,0x64,0x67,0x68,0x6d,0x72,0x74,0x75,0}; // y and i vowels 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 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; tr->letter_bits_offset = OFFSET_KOREAN;
memset(tr->letter_bits,0,sizeof(tr->letter_bits)); memset(tr->letter_bits,0,sizeof(tr->letter_bits));
static const unsigned char stress_amps_ku[8] = {18,18, 20,20, 20,22, 22,21 }; 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}; 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); SetupTranslator(tr,stress_lengths_ku,stress_amps_ku);
tr->charset_a0 = charsets[9]; // ISO-8859-9 - Latin5 tr->charset_a0 = charsets[9]; // ISO-8859-9 - Latin5




case L('l','a'): //Latin case L('l','a'): //Latin
{ {
tr = new Translator();
tr->charset_a0 = charsets[4]; // ISO-8859-4, includes a,e,i,o,u-macron tr->charset_a0 = charsets[4]; // ISO-8859-4, includes a,e,i,o,u-macron
tr->langopts.stress_rule = 2; tr->langopts.stress_rule = 2;
tr->langopts.stress_flags = 0x20; tr->langopts.stress_flags = 0x20;
{ {
static const unsigned char stress_amps_lv[8] = {17,13, 20,20, 20,22, 22,21 }; 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}; 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); SetupTranslator(tr,stress_lengths_lv,stress_amps_lv);


tr->langopts.stress_rule = 0; tr->langopts.stress_rule = 0;
static const unsigned char stress_amps_mk[8] = {17,17, 20,20, 20,22, 22,21 }; 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}; 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); SetupTranslator(tr,stress_lengths_mk,stress_amps_mk);
tr->charset_a0 = charsets[5]; // ISO-8859-5 tr->charset_a0 = charsets[5]; // ISO-8859-5
tr->letter_groups[0] = vowels_cyrillic; tr->letter_groups[0] = vowels_cyrillic;
case L('n','l'): // Dutch case L('n','l'): // Dutch
{ {
static const short stress_lengths_nl[8] = {160,135, 210,210, 0, 0, 260,280}; 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.stress_rule = 0;
tr->langopts.vowel_pause = 1; tr->langopts.vowel_pause = 1;
case L('n','o'): // Norwegian case L('n','o'): // Norwegian
{ {
static const short stress_lengths_no[8] = {160,140, 200,200, 0,0, 220,210}; 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; tr->langopts.stress_rule = 0;
SetLetterVowel(tr,'y'); SetLetterVowel(tr,'y');
tr->langopts.numbers = 0x11849; tr->langopts.numbers = 0x11849;
{ {
static const unsigned char stress_amps_om[] = {18,15, 20,20, 20,22, 22,22 }; 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}; 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_rule = 2;
tr->langopts.stress_flags = 0x16 + 0x80000; tr->langopts.stress_flags = 0x16 + 0x80000;
} }
static const short stress_lengths_pl[8] = {160, 190, 175, 175, 0, 0, 200, 210}; 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 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); SetupTranslator(tr,stress_lengths_pl,stress_amps_pl);


tr->charset_a0 = charsets[2]; // ISO-8859-2 tr->charset_a0 = charsets[2]; // ISO-8859-2
{ {
static const short stress_lengths_pt[8] = {180, 125, 210, 210, 0, 0, 270, 295}; static const short stress_lengths_pt[8] = {180, 125, 210, 210, 0, 0, 270, 295};
static const unsigned char stress_amps_pt[8] = {16,13, 19,19, 20,22, 22,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable static const 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); SetupTranslator(tr,stress_lengths_pt,stress_amps_pt);
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable


static const short stress_lengths_ro[8] = {170, 170, 180, 180, 0, 0, 240, 260}; 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 }; 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); SetupTranslator(tr,stress_lengths_ro,stress_amps_ro);


tr->langopts.stress_rule = 2; tr->langopts.stress_rule = 2;
break; break;


case L('r','u'): // Russian case L('r','u'): // Russian
tr = new Translator_Russian();
Translator_Russian(tr);
break; break;


case L('r','w'): // Kiryarwanda case L('r','w'): // Kiryarwanda
{ {
tr = new Translator();
tr->langopts.stress_rule = 2; tr->langopts.stress_rule = 2;
tr->langopts.stress_flags = 0x16; tr->langopts.stress_flags = 0x16;
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
{ {
static const char *sk_voiced = "bdgjlmnrvwzaeiouy"; static const char *sk_voiced = "bdgjlmnrvwzaeiouy";


tr = new Translator();
SetupTranslator(tr,stress_lengths_sk,stress_amps_sk); SetupTranslator(tr,stress_lengths_sk,stress_amps_sk);
tr->charset_a0 = charsets[2]; // ISO-8859-2 tr->charset_a0 = charsets[2]; // ISO-8859-2


{ {
static const short stress_lengths_sq[8] = {150, 150, 180, 180, 0, 0, 300, 300}; 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 }; 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); SetupTranslator(tr,stress_lengths_sq,stress_amps_sq);


tr->langopts.stress_rule = 2; tr->langopts.stress_rule = 2;
{ {
static const unsigned char stress_amps_sv[] = {16,16, 20,20, 20,22, 22,21 }; 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}; 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); SetupTranslator(tr,stress_lengths_sv,stress_amps_sv);


tr->langopts.stress_rule = 0; tr->langopts.stress_rule = 0;
SetLetterVowel(tr,'y'); SetLetterVowel(tr,'y');
// SetLetterBits(tr,6,"eiyäö"); // soft vowels NOTE accented letters don't work in SetLetterBits
tr->langopts.numbers = 0x1909; tr->langopts.numbers = 0x1909;
tr->langopts.accents = 1; tr->langopts.accents = 1;
} }
{ {
static const short stress_lengths_sw[8] = {160, 170, 200, 200, 0, 0, 320, 340}; 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 }; 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); SetupTranslator(tr,stress_lengths_sw,stress_amps_sw);
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable


static const short stress_lengths_ta[8] = {200, 200, 210, 210, 0, 0, 230, 230}; 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 }; 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); SetupTranslator(tr,stress_lengths_ta,stress_amps_ta);
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable


static const short stress_lengths_th[8] = {230,150, 230,230, 230,0, 230,250}; 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 }; 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); SetupTranslator(tr,stress_lengths_th,stress_amps_th);


tr->langopts.stress_rule = 0; // stress on final syllable of a "word" tr->langopts.stress_rule = 0; // stress on final syllable of a "word"
static const unsigned char stress_amps_tr[8] = {18,18, 20,20, 20,22, 22,21 }; 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}; 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); SetupTranslator(tr,stress_lengths_tr,stress_amps_tr);
tr->charset_a0 = charsets[9]; // ISO-8859-9 - Latin5 tr->charset_a0 = charsets[9]; // ISO-8859-9 - Latin5


0x1b0, 0x1eeb, 0x1ee9, 0x1eed, 0x1eef, 0x1ef1, // ư 0x1b0, 0x1eeb, 0x1ee9, 0x1eed, 0x1eef, 0x1ef1, // ư
0x79, 0x1ef3, 0xfd, 0x1ef7, 0x1ef9, 0x1e, 0 }; // y 0x79, 0x1ef3, 0xfd, 0x1ef7, 0x1ef9, 0x1e, 0 }; // y


tr = new Translator();
SetupTranslator(tr,stress_lengths_vi,stress_amps_vi); SetupTranslator(tr,stress_lengths_vi,stress_amps_vi);
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable


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 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 }; 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); SetupTranslator(tr,stress_lengths_zh,stress_amps_zh);


tr->langopts.stress_rule = 3; // stress on final syllable of a "word" tr->langopts.stress_rule = 3; // stress on final syllable of a "word"
break; break;


default: default:
tr = new Translator();
break; break;
} }








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 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}; static const short stress_lengths_ru[8] = {150,140, 220,220, 0,0, 260,280};


static const char ru_voiced[] = {0x11,0x12,0x13,0x14,0x16,0x17,0}; // letter group G (voiced obstruents) static const char ru_voiced[] = {0x11,0x12,0x13,0x14,0x16,0x17,0}; // letter group G (voiced obstruents)
static const char ru_ivowels[] = {0x2c,0x15,0x31,0x18,0x2e,0x2f,0}; // letter group Y (iotated vowels & soft-sign) static const char ru_ivowels[] = {0x2c,0x15,0x31,0x18,0x2e,0x2f,0}; // letter group Y (iotated vowels & soft-sign)


SetupTranslator(this,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;
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);
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
langopts.numbers = 0x0409;
langopts.numbers2 = 0xc2; // variant numbers before thousands
langopts.phoneme_change = 1;
langopts.testing = 2;
SetupTranslator(tr,stress_lengths_ru,stress_amps_ru);
tr->charset_a0 = charsets[18]; // KOI8-R
tr->transpose_offset = 0x42f; // convert cyrillic from unicode into range 0x01 to 0x22
tr->transpose_min = 0x430;
tr->transpose_max = 0x451;
tr->letter_bits_offset = OFFSET_CYRILLIC;
memset(tr->letter_bits,0,sizeof(tr->letter_bits));
SetLetterBits(tr,0,ru_vowels);
SetLetterBits(tr,1,ru_soft);
SetLetterBits(tr,2,ru_consonants);
SetLetterBits(tr,3,ru_hard);
SetLetterBits(tr,4,ru_nothard);
SetLetterBits(tr,5,ru_voiced);
SetLetterBits(tr,6,ru_ivowels);
SetLetterBits(tr,7,ru_vowels);
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
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 } // 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 { typedef struct {
#define RUSSIAN2 #define RUSSIAN2
#ifdef 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 // Called for each phoneme in the phoneme list, to allow a language to make changes
// ph The current phoneme // ph The current phoneme


#else #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 // Called for each phoneme in the phoneme list, to allow a language to make changes
// flags: bit 0=1 last phoneme in a word // flags: bit 0=1 last phoneme in a word
// bit 1=1 this is the highest stressed vowel in the current word // bit 1=1 this is the highest stressed vowel in the current word

+ 0
- 25
src/tr_languages.h View File

***************************************************************************/ ***************************************************************************/







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




+ 183
- 244
src/translate.cpp
File diff suppressed because it is too large
View File


+ 43
- 85
src/translate.h View File

#define NUM_SEP_SPACE 0x1000 // allow space as thousands separator (in addition to langopts.thousands_sep) #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 #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; LANGUAGE_OPTIONS langopts;
int translator_name; int translator_name;
int transpose_offset; int transpose_offset;
int transpose_min; int transpose_min;


char phon_out[300]; char phon_out[300];
char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes
char phonemes_repeat[20]; char phonemes_repeat[20];
int phonemes_repeat_count; int phonemes_repeat_count;


char *data_dictrules; // language_1 translation rules file char *data_dictrules; // language_1 translation rules file
char *data_dictlist; // language_2 dictionary lookup file char *data_dictlist; // language_2 dictionary lookup file
char *dict_hashtab[N_HASH_DICT]; // hash table to index 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() // 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 // the two-letter rules for each letter must be consecutive in the language_rules source
unsigned char groups2_count[256]; // number of 2 letter groups for this initial letter unsigned char groups2_count[256]; // number of 2 letter groups for this initial letter
unsigned char groups2_start[256]; // index into groups2 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_verb;
int expect_past; // expect past tense int expect_past; // expect past tense
int expect_verb_s; int expect_verb_s;
int expect_noun; int expect_noun;
int word_flags; // word is all upper case
int prev_last_stress; 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; char *clause_end;


int word_vowel_count; // number of vowels so far int word_vowel_count; // number of vowels so far
int clause_upper_count; // number of upper case letters in the clause 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 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 }; // end of class Translator




extern int option_tone1;
extern int option_tone2; extern int option_tone2;
#define OPTION_EMPHASIZE_ALLCAPS 0x100 #define OPTION_EMPHASIZE_ALLCAPS 0x100
#define OPTION_EMPHASIZE_PENULTIMATE 0x200 #define OPTION_EMPHASIZE_PENULTIMATE 0x200
extern int option_phonemes; extern int option_phonemes;
extern int option_phoneme_events; extern int option_phoneme_events;
extern int option_linelength; // treat lines shorter than this as end-of-clause extern int option_linelength; // treat lines shorter than this as end-of-clause
extern int option_harmonic1;
extern int option_multibyte; extern int option_multibyte;
extern int option_capitals; extern int option_capitals;
extern int option_punctuation; extern int option_punctuation;
#define N_PUNCTLIST 60 #define N_PUNCTLIST 60
extern wchar_t option_punctlist[N_PUNCTLIST]; // which punctuation characters to announce extern wchar_t option_punctlist[N_PUNCTLIST]; // which punctuation characters to announce
extern unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS]; 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 *translator;
extern Translator *translator2; extern Translator *translator2;
extern char ctrl_embedded; // to allow an alternative CTRL for embedded commands extern char ctrl_embedded; // to allow an alternative CTRL for embedded commands
extern char *p_textinput; extern char *p_textinput;
extern wchar_t *p_wchar_input; extern wchar_t *p_wchar_input;
extern int ungot_char;
extern int dictionary_skipwords; extern int dictionary_skipwords;


extern int (* uri_callback)(int, const char *, const char *); extern int (* uri_callback)(int, const char *, const char *);
extern int (* phoneme_callback)(const char *); extern int (* phoneme_callback)(const char *);
extern void SetLengthMods(Translator *tr, int value); 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); int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name,int flags);
void LoadConfig(void); 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 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_out(unsigned int c, char *buf);
int utf8_nbytes(const char *buf); int utf8_nbytes(const char *buf);
int lookupwchar(const unsigned short *list,int c); int lookupwchar(const unsigned short *list,int c);
int Eof(void); int Eof(void);
char *strchr_w(const char *s, int c); char *strchr_w(const char *s, int c);
int IsBracket(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 InitNamedata(void);
void InitText(int flags); void InitText(int flags);
void InitText2(void); void InitText2(void);
int IsAlpha(unsigned int c); int IsAlpha(unsigned int c);
int isspace2(unsigned int c); int isspace2(unsigned int c);
int towlower2(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); void SetVoiceStack(espeak_VOICE *v);


extern FILE *f_trans; // for logging extern FILE *f_trans; // for logging

+ 4
- 4
src/transldlg.cpp View File

InitText(0); InitText(0);
while((vp != NULL) && (n_ph_list < N_PH_LIST)) 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) if(clause_count++ > 0)
strcat(phon_out," ||"); strcat(phon_out," ||");
strcat(phon_out,translator->phon_out); strcat(phon_out,translator->phon_out);

+ 16
- 16
src/voices.cpp View File

const char variants_female[N_VOICE_VARIANTS] = {11,12,13,14,0}; const char variants_female[N_VOICE_VARIANTS] = {11,12,13,14,0};
const char *variant_lists[3] = {variants_either, variants_male, variants_female}; const char *variant_lists[3] = {variants_either, variants_male, variants_female};


voice_t voicedata;
static voice_t voicedata;
voice_t *voice = &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 // strip trailing spaces, and truncate lines at // comment
int len; int len;
char *p; char *p;
} }




void SetToneAdjust(voice_t *voice, int *tone_pts)
{//==============================================
static void SetToneAdjust(voice_t *voice, int *tone_pts)
{//=====================================================
int ix; int ix;
int pt; int pt;
int y; int y;
if(tone_only == 0) if(tone_only == 0)
{ {
n_replace_phonemes = 0; n_replace_phonemes = 0;
option_tone1 = 0;
option_quiet = 0; option_quiet = 0;
LoadMbrolaTable(NULL,NULL,0); LoadMbrolaTable(NULL,NULL,0);
} }
if((n < 2) || (n_replace_phonemes >= N_REPLACE_PHONEMES)) if((n < 2) || (n_replace_phonemes >= N_REPLACE_PHONEMES))
return; return;


if((phon = LookupPh(phon_string1)) == 0)
if((phon = LookupPhonemeString(phon_string1)) == 0)
return; // not recognised return; // not recognised


replace_phonemes[n_replace_phonemes].old_ph = phon; 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; replace_phonemes[n_replace_phonemes++].type = flags;
} // end of PhonemeReplacement } // end of PhonemeReplacement




if(!tone_only && (translator != NULL)) if(!tone_only && (translator != NULL))
{ {
delete translator;
DeleteTranslator(translator);
translator = NULL; translator = NULL;
} }


SelectPhonemeTableName(phonemes_name); SelectPhonemeTableName(phonemes_name);
if(new_translator != NULL) if(new_translator != NULL)
delete new_translator;
DeleteTranslator(new_translator);
new_translator = SelectTranslator(translator_name); new_translator = SelectTranslator(translator_name);
langopts = &new_translator->langopts; langopts = &new_translator->langopts;
sscanf(p,"%s",translator_name); sscanf(p,"%s",translator_name);


if(new_translator != NULL) if(new_translator != NULL)
delete new_translator;
DeleteTranslator(new_translator);


new_translator = SelectTranslator(translator_name); new_translator = SelectTranslator(translator_name);
langopts = &new_translator->langopts; langopts = &new_translator->langopts;
fprintf(stderr,"Unknown phoneme table: '%s'\n",phonemes_name); fprintf(stderr,"Unknown phoneme table: '%s'\n",phonemes_name);
} }
voice->phoneme_tab_ix = ix; 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) if(dictionary_name[0]==0)
return(NULL); // no dictionary loaded return(NULL); // no dictionary loaded


} // end of LoadVoice } // 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 // Remove any voice variant suffix (name or number) from a voice name
// Returns the voice variant name // Returns the voice variant name








void GetVoices(const char *path)
{//=============================
static void GetVoices(const char *path)
{//====================================
FILE *f_voice; FILE *f_voice;
espeak_VOICE *voice_data; espeak_VOICE *voice_data;
int ftype; int ftype;

+ 0
- 1
src/vowelchart.cpp View File



extern char *spects_data; extern char *spects_data;
extern int n_phoneme_tables; extern int n_phoneme_tables;
extern PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS];




// size of the vowelchart png // size of the vowelchart png

+ 7
- 7
src/wavegen.cpp View File



FILE *f_log = NULL; FILE *f_log = NULL;
int option_waveout = 0; int option_waveout = 0;
int option_harmonic1 = 10; // 10
static int option_harmonic1 = 10; // 10
int option_log_frames = 0; int option_log_frames = 0;
static int flutter_amp = 64; static int flutter_amp = 64;


static short echo_buf[N_ECHO_BUF]; static short echo_buf[N_ECHO_BUF];


static int voicing; static int voicing;
RESONATOR rbreath[N_PEAKS];
static RESONATOR rbreath[N_PEAKS];


static int harm_sqrt_n = 0; static int harm_sqrt_n = 0;


/* This is a fixed version of Pa_OpenDefaultStream() for use if the version in portaudio V19 /* This is a fixed version of Pa_OpenDefaultStream() for use if the version in portaudio V19
is broken */ is broken */


PaError Pa_OpenDefaultStream2( PaStream** stream,
static PaError Pa_OpenDefaultStream2( PaStream** stream,
int inputChannelCount, int inputChannelCount,
int outputChannelCount, int outputChannelCount,
PaSampleFormat sampleFormat, PaSampleFormat sampleFormat,






void SetBreath()
{//=============
static void SetBreath()
{//====================
#ifndef PLATFORM_RISCOS #ifndef PLATFORM_RISCOS
int pk; int pk;


} // end of SetBreath } // end of SetBreath




int ApplyBreath(void)
{//==================
static int ApplyBreath(void)
{//=========================
int value = 0; int value = 0;
#ifndef PLATFORM_RISCOS #ifndef PLATFORM_RISCOS
int noise; int noise;

Loading…
Cancel
Save