diff --git a/dictsource/en_rules b/dictsource/en_rules index 91398b00..a9a81941 100644 --- a/dictsource/en_rules +++ b/dictsource/en_rules @@ -4242,6 +4242,7 @@ rea (C% r,i:@ _) rea (dC r,i:@ rea (gen rI2eI + _) re (au@P2 ,ri: re (ck rE reckon rEk@n reco (g rEk@ diff --git a/docs/commands.html b/docs/commands.html index a0f2d5b1..6685dbd9 100644 --- a/docs/commands.html +++ b/docs/commands.html @@ -3,7 +3,6 @@ eSpeak Speech Synthesizer - @@ -151,16 +150,20 @@ shown on stdout. --stdout
Writes the speech output to stdout as it is produced, rather than speaking it. The data starts with a WAV file header which indicates the sample rate and format of the data. The length field is set to zero because the length of the data is unknown when the header is produced.

-

--compile[=<voice name>]
+
--compile [=<voice name>]
Compile the pronunciation rule and dictionary lookup data from their source files in the current directory. The Voice determines which language's files are compiled. For example, if it's an English voice, then en_rules, en_list, and en_extra (if present), are compiled to replace en_dict in the speak-data directory. If no Voice is specified then the default Voice is used.

-

--punct[="<characters>"]
+
--compile-debug [=<voice name>]
+
+The same as --compile, but source line numbers from the *_rules file are included. These are included in the rules trace when the -X option is used. +

+

--punct [="<characters>"]
Speaks the names of punctuation characters when they are encountered in the text. If <characters> are given, then only those listed punctuation characters are spoken, eg. --punct=".,;?"

---voices[=<language code>]
+--voices [=<language code>]
Lists the available voices.
If =<language code> is present then only those voices which are suitable for that language are listed.
--voices=variant lists the voice variants (voice modifiers). diff --git a/platforms/windows/windows_sapi/ttsengobj.cpp b/platforms/windows/windows_sapi/ttsengobj.cpp index bafe9070..a4c52273 100755 --- a/platforms/windows/windows_sapi/ttsengobj.cpp +++ b/platforms/windows/windows_sapi/ttsengobj.cpp @@ -767,7 +767,7 @@ int FAR PASCAL CompileDictionary(const char *voice, const char *path_log) sprintf(fname,"%s/",path_install); espeak_SetVoiceByName(voice); - espeak_CompileDictionary(fname,f_log3); + espeak_CompileDictionary(fname,f_log3,0); fclose(f_log3); return(0); diff --git a/src/compiledata.cpp b/src/compiledata.cpp index 138b8806..8935f496 100755 --- a/src/compiledata.cpp +++ b/src/compiledata.cpp @@ -77,7 +77,7 @@ extern int Read4Bytes(FILE *f); extern void MakeVowelLists(void); extern void FindPhonemesUsed(void); extern void DrawEnvelopes(); -extern int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname); +extern int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname, int flags); static int markers_used[8]; @@ -1952,10 +1952,16 @@ void Compile::Report(void) fprintf(f_report," [%s] %s",WordToString(prev_mnemonic = list[ix]->ph_mnemonic), phoneme_tab_list2[prev_table = list[ix]->ph_table].name); fputc('\n',f_report); - - free(list[ix]); } + + for(ix=0; ix 0) + if((err = CompileDictionary(path_dsource, dictname,log,NULL,0)) > 0) { report = report + dictstr + wxString::Format(_T(" %d, "),err); errors += err; diff --git a/src/compiledict.cpp b/src/compiledict.cpp index c25edabd..406e5c84 100755 --- a/src/compiledict.cpp +++ b/src/compiledict.cpp @@ -46,6 +46,7 @@ static int transpose_offset; // transpose character range for LookupDictList() static int transpose_min; static int transpose_max; static int text_mode = 0; +static int debug_flag = 0; int hash_counts[N_HASH_DICT]; char *hash_chains[N_HASH_DICT]; @@ -943,6 +944,15 @@ char *compile_rule(char *input) } strcpy(&output[len],rule_match); len += strlen(rule_match); + + if(debug_flag) + { + output[len] = RULE_LINENUM; + output[len+1] = (linenum % 255) + 1; + output[len+2] = (linenum / 255) + 1; + len+=3; + } + if(rule_cond[0] != 0) { ix = -1; @@ -1437,9 +1447,10 @@ static int compile_dictrules(FILE *f_in, FILE *f_out, char *fname_temp) -int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *fname_err) -{//========================================================================================== +int 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 +// flags: bit 0: include source line number information, for debug purposes. FILE *f_in; FILE *f_out; @@ -1451,6 +1462,7 @@ int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, cha char path[sizeof(path_home)+40]; // path_dsource+20 error_count = 0; + debug_flag = flags & 1; if(dsource == NULL) dsource = ""; diff --git a/src/dictionary.cpp b/src/dictionary.cpp index 6f398501..cd296313 100755 --- a/src/dictionary.cpp +++ b/src/dictionary.cpp @@ -1455,6 +1455,7 @@ char *Translator::DecodeRule(const char *group, char *rule) int match_type; int finished=0; int value; + int linenum=0; int flags; int suffix_char; int condition_num=0; @@ -1476,7 +1477,7 @@ char *Translator::DecodeRule(const char *group, char *rule) { rb = *rule++; - if(rb <= 5) + if(rb <= RULE_LINENUM) { switch(rb) { @@ -1501,6 +1502,11 @@ char *Translator::DecodeRule(const char *group, char *rule) /* conditional rule, next byte gives condition number */ condition_num = *rule++; break; + case RULE_LINENUM: + value = (rule[1] & 0xff) - 1; + linenum = (rule[0] & 0xff) - 1 + (value * 255); + rule+=2; + break; } continue; } @@ -1557,10 +1563,15 @@ char *Translator::DecodeRule(const char *group, char *rule) *p = 0; p = output; + if(linenum > 0) + { + sprintf(p,"%5d:\t",linenum); + p += 7; + } if(condition_num > 0) { - sprintf(output,"?%d ",condition_num); - p = &output[strlen(output)]; + sprintf(p,"?%d ",condition_num); + p = &p[strlen(p)]; } if((ix = strlen(buf_pre)) > 0) { @@ -1727,7 +1738,7 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec { rb = *rule++; - if(rb <= 5) + if(rb <= RULE_LINENUM) { switch(rb) { @@ -1779,6 +1790,9 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec if(!failed) match.points++; // add one point for a matched conditional rule break; + case RULE_LINENUM: + rule+=2; + break; } continue; } @@ -2173,7 +2187,7 @@ void Translator::MatchRule(char *word[], const char *group, char *rule, MatchRec if(group_length > 1) pts += 35; // to account for an extra letter matching DecodePhonemes(match.phonemes,decoded_phonemes); - fprintf(f_trans,"%3d %s [%s]\n",pts,DecodeRule(group,rule_start),decoded_phonemes); + fprintf(f_trans,"%3d\t%s [%s]\n",pts,DecodeRule(group,rule_start),decoded_phonemes); } #endif diff --git a/src/espeak.cpp b/src/espeak.cpp index b07184e8..e6d37243 100644 --- a/src/espeak.cpp +++ b/src/espeak.cpp @@ -274,10 +274,11 @@ int main (int argc, char **argv) We distinguish them by their indices. */ {"help", no_argument, 0, 'h'}, {"stdin", no_argument, 0, 0x100}, - {"stdout", no_argument, 0, 0x101}, + {"compile-debug", optional_argument, 0, 0x101}, {"compile", optional_argument, 0, 0x102}, {"punct", optional_argument, 0, 0x103}, {"voices", optional_argument, 0, 0x104}, + {"stdout", no_argument, 0, 0x105}, {0, 0, 0, 0} }; @@ -402,14 +403,15 @@ int main (int argc, char **argv) flag_stdin = 1; break; - case 0x101: // --stdout + case 0x105: // --stdout option_waveout = 1; strcpy(wavefile,"stdout"); break; + case 0x101: // --compile-debug case 0x102: // --compile strncpy0(voicename,optarg,sizeof(voicename)); - flag_compile = 1; + flag_compile = c; quiet = 1; break; @@ -466,7 +468,7 @@ int main (int argc, char **argv) if(flag_compile) { // This must be done after the voice is set - espeak_CompileDictionary("",stderr); + espeak_CompileDictionary("", stderr, flag_compile & 0x1); exit(0); } diff --git a/src/espeakedit.cpp b/src/espeakedit.cpp index d51c074e..aa1dc644 100755 --- a/src/espeakedit.cpp +++ b/src/espeakedit.cpp @@ -186,6 +186,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame) EVT_MENU(MENU_PATH4, MyFrame::OnOptions) EVT_MENU(MENU_COMPILE_PH, MyFrame::OnTools) EVT_MENU(MENU_COMPILE_DICT, MyFrame::OnTools) + EVT_MENU(MENU_COMPILE_DICT_DEBUG, MyFrame::OnTools) EVT_MENU(MENU_COMPILE_MBROLA, MyFrame::OnTools) EVT_MENU(MENU_CLOSE_ALL, MyFrame::OnQuit) EVT_MENU(MENU_QUIT, MyFrame::OnQuit) @@ -431,6 +432,7 @@ void MyFrame::OnTools(wxCommandEvent& event) {//========================================= int err; FILE *log; + int debug_flag=0; char fname_log[sizeof(path_dsource)+12]; char err_fname[sizeof(path_home)+15]; @@ -465,11 +467,13 @@ void MyFrame::OnTools(wxCommandEvent& event) CompileMbrola(); break; + case MENU_COMPILE_DICT_DEBUG: + debug_flag =1; // and drop through to next case case MENU_COMPILE_DICT: sprintf(fname_log,"%s%s",path_dsource,"dict_log"); log = fopen(fname_log,"w"); - if((err = CompileDictionary(path_dsource,dictionary_name,log,err_fname)) < 0) + if((err = CompileDictionary(path_dsource,dictionary_name,log,err_fname,debug_flag)) < 0) { wxLogError(_T("Can't access file:\n")+wxString(err_fname,wxConvLocal)); diff --git a/src/intonation.cpp b/src/intonation.cpp index 0a1a8179..4afde5fd 100755 --- a/src/intonation.cpp +++ b/src/intonation.cpp @@ -910,7 +910,7 @@ void Translator::CalcPitches(int clause_type) option = langopts.intonation_group; - if(option > INTONATION_TYPES) + if(option >= INTONATION_TYPES) option = 0; group_tone = punct_to_tone[option][clause_type]; @@ -952,6 +952,18 @@ void Translator::CalcPitches(int clause_type) if(syl->stress == 6) { + // reduce the stress of the previous stressed syllable + for(ix=st_ix-1; ix>=st_start && ix>=(st_ix-3); ix--) + { + if(syllable_tab[ix].stress == 6) + break; + if(syllable_tab[ix].stress == 4) + { + syllable_tab[ix].stress = 3; + break; + } + } + // are the next primary syllables also emphasized ? for(ix=st_ix+1; ixAppend(MENU_COMPILE_PH, _("Compile &phoneme data")); data_menu->Append(MENU_COMPILE_DICT, _("Compile &dictionary")); + data_menu->Append(MENU_COMPILE_DICT_DEBUG, _("Compile dictionary (&debug)")); data_menu->Append(MENU_COMPILE_MBROLA, _("Compile &mbrola phonemes list")); // OPTIONS MENU diff --git a/src/prosodydisplay.cpp b/src/prosodydisplay.cpp index b7332e5c..468a44ec 100755 --- a/src/prosodydisplay.cpp +++ b/src/prosodydisplay.cpp @@ -120,6 +120,7 @@ void ProsodyDisplay::SelectPh(int index) {//===================================== // A phoneme has been selected PHONEME_LIST *p; + const char *emphasized; char buf[120]; if(index < 0) return; @@ -127,8 +128,12 @@ void ProsodyDisplay::SelectPh(int index) p = &phlist[index]; if((p == NULL) || (p->ph == NULL)) return; - sprintf(buf,"Stress %d Amp %2d LenMod %2d Pitch %3d %3d [env=%d] Flags %.2x ", - p->tone,p->amp,p->length,p->pitch1,p->pitch2,p->env,p->ph->phflags); + emphasized = ""; + if(p->tone & 8) + emphasized = "*"; + + sprintf(buf,"Stress %s%d Amp %2d LenMod %2d Pitch %3d %3d [env=%d] Flags %.2x ", + emphasized,p->tone&0x7,p->amp,p->length,p->pitch1,p->pitch2,p->env,p->ph->phflags); wxLogStatus(wxString(buf,wxConvLocal)); } diff --git a/src/readclause.cpp b/src/readclause.cpp index ad791ed9..29c2aae2 100644 --- a/src/readclause.cpp +++ b/src/readclause.cpp @@ -845,7 +845,7 @@ static void ProcessParamStack(char *outbuf, int &outix) int value; char buf[20]; int new_parameters[N_SPEECH_PARAM]; - static char cmd_letter[N_SPEECH_PARAM] = {0, 'S','A','P','R', 0, 0, 'F'}; // embedded command letters + static char cmd_letter[N_SPEECH_PARAM] = {0, 'S','A','P','R', 0, 0, 0, 0, 0, 0, 0, 'F'}; // embedded command letters for(param=0; param 0) && (wmark < 8)) } } - if((wflags & FLAG_ALL_UPPER) && (word_length > 1) && (clause_lower_count > 3) && iswalpha(first_char)) + if((wflags & FLAG_ALL_UPPER) && (word_length > 1)&& iswalpha(first_char)) { if((option_tone_flags & OPTION_EMPHASIZE_ALLCAPS) && !(dictionary_flags[0] & FLAG_ABBREV)) { @@ -708,7 +708,7 @@ if((wmark > 0) && (wmark < 8)) emphasize_allcaps = FLAG_EMPHASIZED; } else - if(!found && !(dictionary_flags[0] & FLAG_SKIPWORDS) && (word_length<4) && (clause_upper_count <= clause_lower_count)) + if(!found && !(dictionary_flags[0] & FLAG_SKIPWORDS) && (word_length<4) && (clause_lower_count > 3) && (clause_upper_count <= clause_lower_count)) { // An upper case word in a lower case clause. This could be an abbreviation. spell_word = 1; @@ -1023,12 +1023,21 @@ strcpy(phonemes2,phonemes); strcat(word_phonemes,end_phonemes); } + if(wflags & FLAG_LAST_WORD) + { + // don't use $brk pause before the last word of a sentence + // (but allow it for emphasis, see below + dictionary_flags[0] &= ~FLAG_PAUSE1; + } + if(wflags & FLAG_EMPHASIZED) { // A word is indicated in the source text as stressed // Give it stress level 6 (for the intonation module) ChangeWordStress(this,word_phonemes,6); - dictionary_flags[0] |= FLAG_PAUSE1; // precede by short pause + +// if(!(wflags & FLAG_LAST_WORD)) // ?? omit pre-pause if it's the last word in the sentence? + dictionary_flags[0] |= FLAG_PAUSE1; // precede by short pause } else if(wtab[dictionary_skipwords].flags & FLAG_LAST_WORD) @@ -1335,7 +1344,7 @@ int Translator::TranslateWord2(char *word, WORD_TAB *wtab, int pre_pause, int ne } } - if(!(word_flags & FLAG_LAST_WORD) && !(word_flags & FLAG_HYPHEN)) + if(!(word_flags & FLAG_HYPHEN)) { if(flags & FLAG_PAUSE1) { diff --git a/src/translate.h b/src/translate.h index 6236238e..51c1a719 100755 --- a/src/translate.h +++ b/src/translate.h @@ -120,6 +120,7 @@ #define RULE_CONDITION 5 // followed by condition number (byte) #define RULE_GROUP_START 6 #define RULE_GROUP_END 7 +#define RULE_LINENUM 8 // next 2 bytes give a line number, for debugging purposes #define RULE_SPACE 32 // ascii space #define RULE_SYLLABLE 9 @@ -549,7 +550,7 @@ extern int (* phoneme_callback)(const char *); extern void SetLengthMods(Translator *tr, int value); Translator *SelectTranslator(const char *name); -int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name); +int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name,int flags); void LoadConfig(void); int PhonemeCode(unsigned int mnem); void ChangeWordStress(Translator *tr, char *word, int new_stress); diff --git a/src/vowelchart.cpp b/src/vowelchart.cpp index 89151b0f..043b8ed3 100644 --- a/src/vowelchart.cpp +++ b/src/vowelchart.cpp @@ -388,6 +388,8 @@ void FindPhonemesUsed(void) { if(*p == RULE_CONDITION) p+=2; + if(*p == RULE_LINENUM) + p+=3; if(*p == RULE_GROUP_END) { p++;