lang=hr: Recognize Roman numbers only when all-capitals. lang=en: Change to word-final [I] (phoneme [i]). git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@84 d46cf337-b52f-0410-862d-fd96e6ae7743master
.group | .group | ||||
// non-ascii characters with specified pronunciations | // non-ascii characters with specified pronunciations | ||||
é eI | |||||
_) é I2 | |||||
ä E | |||||
ë E | |||||
ï i: | |||||
ö 3: | |||||
?5 ö VR | |||||
ü u: | |||||
ç s | |||||
ß s | |||||
_) ß (_ b'i:t@_ | |||||
č tS | |||||
š S | |||||
ş S | |||||
ž Z | |||||
þ T | |||||
ð D | |||||
é eI | |||||
_) é I2 | |||||
ê E: | |||||
ä E | |||||
ë E | |||||
ï i: | |||||
ö 3: | |||||
?5 ö VR | |||||
ü u: | |||||
ç s | |||||
ß s | |||||
_) ß (_ b'i:t@_ | |||||
č tS | |||||
š S | |||||
ş S | |||||
ž Z | |||||
þ T | |||||
ð D | |||||
\\ bakstroUk | \\ bakstroUk |
?2 _0M4 b'ilijOna | ?2 _0M4 b'ilijOna | ||||
?2 _1M4 b'ilijOn | ?2 _1M4 b'ilijOn | ||||
_dpt _:z'a*Ez_ | _dpt _:z'a*Ez_ | ||||
_roman @-*'imsko | |||||
// not Roman numerals | // not Roman numerals | ||||
vi ti | |||||
// vi vi // not needed if only all-capitals are spoken as Roman numbers | |||||
// Abbreviations | // Abbreviations |
[Setup] | [Setup] | ||||
AppName=eSpeak | AppName=eSpeak | ||||
AppVerName=eSpeak version 1.29.02 | |||||
AppVerName=eSpeak version 1.29.03 | |||||
DefaultDirName={pf}\eSpeak | DefaultDirName={pf}\eSpeak | ||||
DefaultGroupName=eSpeak | DefaultGroupName=eSpeak | ||||
case lang1 of | case lang1 of | ||||
'af': value := $436; | 'af': value := $436; | ||||
'bs': value := $141a; | |||||
'bs': value := $41a; // should be $141a but Jaws crashes on startup | |||||
'cs': value := $405; | 'cs': value := $405; | ||||
'cy': value := $452; | 'cy': value := $452; | ||||
'de': value := $407; | 'de': value := $407; |
//=== ISpTTSEngine Implementation ============================================ | //=== ISpTTSEngine Implementation ============================================ | ||||
// | // | ||||
#define L(c1,c2) (c1<<8)+c2 // combine two characters into an integer | |||||
static char *phoneme_names_en[] = { | |||||
NULL,NULL,NULL," ",NULL,NULL,NULL,NULL,"'",",", | |||||
"A:","a","V","0","aU","@","aI", | |||||
"b","tS","d","D","E","3:","eI", | |||||
"f","g","h","I","i:","dZ","k", | |||||
"l","m","n","N","oU","OI","p", | |||||
"r","s","S","t","T","U","u:", | |||||
"v","w","j","z","Z", | |||||
NULL | |||||
}; | |||||
int CTTSEngObj::WritePhonemes(SPPHONEID *phons, wchar_t *pW) | |||||
{//========================================================= | |||||
int ph; | |||||
int ix=2; | |||||
int skip=0; | |||||
int maxph = 49; | |||||
char *p; | |||||
int j; | |||||
int lang; | |||||
char **phoneme_names; | |||||
char phbuf[200]; | |||||
espeak_VOICE *voice; | |||||
voice = espeak_GetCurrentVoice(); | |||||
lang = (voice->languages[1] << 8) + (voice->languages[2]); | |||||
phoneme_names = phoneme_names_en; | |||||
maxph = 0; | |||||
if(lang == L('e','n')) | |||||
{ | |||||
phoneme_names = phoneme_names_en; | |||||
maxph = 49; | |||||
} | |||||
if(maxph == 0) | |||||
return(0); | |||||
strcpy(phbuf,"[["); | |||||
while(((ph = *phons++) != 0) && (ix < (sizeof(phbuf) - 3))) | |||||
{ | |||||
if(skip) | |||||
{ | |||||
skip = 0; | |||||
continue; | |||||
} | |||||
if(ph > maxph) | |||||
continue; | |||||
p = phoneme_names[phons[0]]; // look at the phoneme after this one | |||||
if(p != NULL) | |||||
{ | |||||
if(p[0] == '\'') | |||||
{ | |||||
phbuf[ix++] = '\''; // primary stress, put before the vowel, not after | |||||
skip=1; | |||||
} | |||||
if(p[0] == ',') | |||||
{ | |||||
phbuf[ix++] = ','; // secondary stress | |||||
skip=1; | |||||
} | |||||
} | |||||
p = phoneme_names[ph]; // look at this phoneme | |||||
if(p != NULL) | |||||
{ | |||||
strcpy(&phbuf[ix],p); | |||||
ix += strlen(p); | |||||
} | |||||
} | |||||
strcpy(&phbuf[ix],"]]"); | |||||
ix += 2; | |||||
if(pW != NULL) | |||||
{ | |||||
for(j=0; j<=ix; j++) | |||||
{ | |||||
pW[j] = phbuf[j]; | |||||
} | |||||
} | |||||
return(strlen(phbuf)); | |||||
} | |||||
int CTTSEngObj::ProcessFragList(const SPVTEXTFRAG* pTextFragList, wchar_t *pW_start, ISpTTSEngineSite* pOutputSite, int *n_text) | int CTTSEngObj::ProcessFragList(const SPVTEXTFRAG* pTextFragList, wchar_t *pW_start, ISpTTSEngineSite* pOutputSite, int *n_text) | ||||
{//============================================================================================================================= | |||||
{//============================================================================================================================ | |||||
int action; | int action; | ||||
int control; | int control; | ||||
CheckActions(pOutputSite); | CheckActions(pOutputSite); | ||||
sayas = 0; | sayas = 0; | ||||
state = &pTextFragList->State; | |||||
switch(action) | switch(action) | ||||
{ | { | ||||
} | } | ||||
// first set the volume, rate, pitch | // first set the volume, rate, pitch | ||||
state = &pTextFragList->State; | |||||
volume = (state->Volume * master_volume)/100; | volume = (state->Volume * master_volume)/100; | ||||
speed = ConvertRate(state->RateAdj); | speed = ConvertRate(state->RateAdj); | ||||
pitch = ConvertPitch(state->PitchAdj.MiddleAdj); | pitch = ConvertPitch(state->PitchAdj.MiddleAdj); | ||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case SPVA_Pronounce: | |||||
total += WritePhonemes(state->pPhoneIds, pW); | |||||
if(pW != NULL) | |||||
{ | |||||
pW += total; | |||||
} | |||||
break; | |||||
} | } | ||||
*pW = 0; | *pW = 0; | ||||
} | } | ||||
*n_text = frag_count; | *n_text = frag_count; | ||||
return(total); | return(total); | ||||
} // end of ProcessFragList | } // end of ProcessFragList | ||||
if(size > 0) | if(size > 0) | ||||
{ | { | ||||
espeak_Synth(TextBuf,0,0,POS_CHARACTER,0,espeakCHARS_WCHAR | espeakKEEP_NAMEDATA,NULL,NULL); | |||||
espeak_Synth(TextBuf,0,0,POS_CHARACTER,0,espeakCHARS_WCHAR | espeakKEEP_NAMEDATA | espeakPHONEMES,NULL,NULL); | |||||
} | } | ||||
} | } | ||||
return hr; | return hr; |
} | } | ||||
length += n_flag_codes; | length += n_flag_codes; | ||||
if((multiple_string != NULL) && (multiple_words > 0) && (multiple_words <= 4)) | |||||
if((multiple_string != NULL) && (multiple_words > 0)) | |||||
{ | { | ||||
dict_line[length++] = 40 + multiple_words; | |||||
ix = multiple_string_end - multiple_string; | |||||
memcpy(&dict_line[length],multiple_string,ix); | |||||
length += ix; | |||||
if(multiple_words > 10) | |||||
{ | |||||
fprintf(f_log,"%5d: Two many parts in a multi-word entry: %d\n",linenum,multiple_words); | |||||
} | |||||
else | |||||
{ | |||||
dict_line[length++] = 40 + multiple_words; | |||||
ix = multiple_string_end - multiple_string; | |||||
memcpy(&dict_line[length],multiple_string,ix); | |||||
length += ix; | |||||
} | |||||
} | } | ||||
dict_line[0] = length; | dict_line[0] = length; | ||||
#include "translate.h" | #include "translate.h" | ||||
int dictionary_skipwords; | |||||
char dictionary_name[40]; | char dictionary_name[40]; | ||||
extern MNEM_TAB mnem_flags[]; | extern MNEM_TAB mnem_flags[]; | ||||
else | else | ||||
if(flag > 40) | if(flag > 40) | ||||
{ | { | ||||
// flags 41,42,or 43 match more than one word | |||||
// flags 41 to 50 match more than one word | |||||
// This comes after the other flags | // This comes after the other flags | ||||
n_chars = next - p; | n_chars = next - p; | ||||
if(memcmp(word2,p,n_chars)==0) | if(memcmp(word2,p,n_chars)==0) | ||||
{ | { | ||||
dictionary_flags |= ((flag-40) << 5); // set (bits 5-7) to 1,2,or 3 | |||||
dictionary_flags |= FLAG_SKIPWORDS; | |||||
dictionary_skipwords = (flag - 40); | |||||
p = next; | p = next; | ||||
word_end = word2 + n_chars; | word_end = word2 + n_chars; | ||||
} | } |
static char *roman_numbers = "ixcmvld"; | static char *roman_numbers = "ixcmvld"; | ||||
static int roman_values[] = {1,10,100,1000,5,50,500}; | static int roman_values[] = {1,10,100,1000,5,50,500}; | ||||
if((langopts.numbers & NUM_ROMAN) == 0) | |||||
return(0); | |||||
acc = 0; | acc = 0; | ||||
prev = 0; | prev = 0; | ||||
subtract = 0x7fff; | subtract = 0x7fff; |
#include "translate.h" | #include "translate.h" | ||||
#include "wave.h" | #include "wave.h" | ||||
const char *version_string = "1.29.02 10.Sep.07"; | |||||
const char *version_string = "1.29.04 11.Sep.07"; | |||||
const int version_phdata = 0x012901; | const int version_phdata = 0x012901; | ||||
int option_device_number = -1; | int option_device_number = -1; | ||||
{//================================================================================ | {//================================================================================ | ||||
// control=1 get formant transition data only | // control=1 get formant transition data only | ||||
int code; | |||||
unsigned int code; | |||||
unsigned int value, value2; | unsigned int value, value2; | ||||
while((value = phoneme_index[index++]) != 0) | while((value = phoneme_index[index++]) != 0) | ||||
} | } | ||||
break; | break; | ||||
case 1: | case 1: | ||||
if(control==0) | |||||
seq_len_adjust = value2 >> 8; | |||||
if(control==0) | |||||
{ | |||||
seq_len_adjust = value2 >> 8; | |||||
} | |||||
break; | break; | ||||
case 2: | case 2: | ||||
if(control==0) | |||||
seq_len_adjust = -(value2 >> 8); | |||||
if(control==0) | |||||
{ | |||||
seq_len_adjust = value2 >> 8; | |||||
seq_len_adjust = -seq_len_adjust; | |||||
} | |||||
break; | break; | ||||
case 3: | case 3: | ||||
if(control==0) | if(control==0) |
tr->langopts.max_initial_consonants = 5; | tr->langopts.max_initial_consonants = 5; | ||||
tr->langopts.spelling_stress = 1; | tr->langopts.spelling_stress = 1; | ||||
tr->langopts.numbers = 0x1c0d + 0x4000 + NUM_ROMAN; | |||||
tr->langopts.numbers = 0x1c0d + 0x4000 + NUM_ROMAN_UC; | |||||
tr->langopts.numbers2 = 0x4a; // variant numbers before thousands,milliards | tr->langopts.numbers2 = 0x4a; // variant numbers before thousands,milliards | ||||
tr->langopts.replace_chars = replace_cyrillic; | tr->langopts.replace_chars = replace_cyrillic; | ||||
tr->langopts.replacement_chars = replace_cyrillic_latin; | tr->langopts.replacement_chars = replace_cyrillic_latin; |
if(!found & ((word_flags & FLAG_UPPERS) != FLAG_FIRST_UPPER)) | if(!found & ((word_flags & FLAG_UPPERS) != FLAG_FIRST_UPPER)) | ||||
{ | { | ||||
// either all upper or all lower case | // either all upper or all lower case | ||||
if((found = TranslateRoman(word,phonemes)) != 0) | |||||
dictionary_flags |= FLAG_ABBREV; // don't spell capital Roman numbers as individual letters | |||||
if((langopts.numbers & NUM_ROMAN) || ((langopts.numbers & NUM_ROMAN_UC) && (word_flags & FLAG_ALL_UPPER))) | |||||
{ | |||||
if((found = TranslateRoman(word,phonemes)) != 0) | |||||
dictionary_flags |= FLAG_ABBREV; // don't spell capital Roman numbers as individual letters | |||||
} | |||||
} | } | ||||
if((wflags & FLAG_ALL_UPPER) && (clause_upper_count <= clause_lower_count) && | if((wflags & FLAG_ALL_UPPER) && (clause_upper_count <= clause_lower_count) && | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
flags |= FLAG_SKIPWORDS_1; | |||||
flags |= FLAG_SKIPWORDS; | |||||
dictionary_skipwords = 1; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
int ix; | int ix; | ||||
unsigned int word; | unsigned int word; | ||||
unsigned int new_c, c2; | |||||
unsigned int new_c, c2, c_lower; | |||||
int upper_case = 0; | int upper_case = 0; | ||||
static int ignore_next = 0; | static int ignore_next = 0; | ||||
// there is a list of character codes to be substituted with alternative codes | // there is a list of character codes to be substituted with alternative codes | ||||
if(iswupper(c)) | |||||
if(iswupper(c_lower = c)) | |||||
{ | { | ||||
c = towlower(c); | |||||
c_lower = towlower(c); | |||||
upper_case = 1; | upper_case = 1; | ||||
} | } | ||||
new_c = 0; | new_c = 0; | ||||
for(ix=0; (word = langopts.replace_chars[ix]) != 0; ix++) | for(ix=0; (word = langopts.replace_chars[ix]) != 0; ix++) | ||||
{ | { | ||||
if(c == (word & 0xffff)) | |||||
if(c_lower == (word & 0xffff)) | |||||
{ | { | ||||
if((word >> 16) == 0) | if((word >> 16) == 0) | ||||
{ | { | ||||
else | else | ||||
{ | { | ||||
dict_flags = TranslateWord2(word, &words[ix], words[ix].pre_pause, words[ix+1].pre_pause); | dict_flags = TranslateWord2(word, &words[ix], words[ix].pre_pause, words[ix+1].pre_pause); | ||||
ix += ((dict_flags >> 5) & 7); // dictionary indicates skip next word(s) | |||||
if(dict_flags & FLAG_SKIPWORDS) | |||||
ix += dictionary_skipwords; // dictionary indicates skip next word(s) | |||||
if((dict_flags & FLAG_DOT) && (ix == word_count-1) && (terminator == CLAUSE_PERIOD)) | if((dict_flags & FLAG_DOT) && (ix == word_count-1) && (terminator == CLAUSE_PERIOD)) | ||||
{ | { |
/* flags from word dictionary */ | /* flags from word dictionary */ | ||||
// bits 0-3 stressed syllable, 7=unstressed | // bits 0-3 stressed syllable, 7=unstressed | ||||
#define FLAG_SKIPWORDS 0xe0 /* bits 5,6,7 number of words to skip */ | |||||
#define FLAG_SKIPWORDS_1 0x20 | |||||
#define FLAG_SKIPWORDS 0x80 | |||||
#define FLAG_PREPAUSE 0x100 | #define FLAG_PREPAUSE 0x100 | ||||
#define FLAG_ONLY 0x200 | #define FLAG_ONLY 0x200 | ||||
#define BITNUM_FLAG_ONLY 9 // bit 9 is set | #define BITNUM_FLAG_ONLY 9 // bit 9 is set | ||||
unsigned char *length_mods; | unsigned char *length_mods; | ||||
unsigned char *length_mods0; | unsigned char *length_mods0; | ||||
#define NUM_ROMAN 0x20000 | |||||
#define NUM_ROMAN 0x20000 | |||||
#define NUM_ROMAN_UC 0x40000 | |||||
// bits0-1=which numbers routine to use. | // bits0-1=which numbers routine to use. | ||||
// bit2= thousands separator must be space | // bit2= thousands separator must be space | ||||
// bit3= , decimal separator, not . | // bit3= , decimal separator, not . | ||||
// bits13-15 post-decimal-digits 0=single digits, 1=(LANG=it) 2=(LANG=pl) 3=(LANG=ro) | // bits13-15 post-decimal-digits 0=single digits, 1=(LANG=it) 2=(LANG=pl) 3=(LANG=ro) | ||||
// bit16=dot after number indicates ordinal | // bit16=dot after number indicates ordinal | ||||
// bit17=recognize roman numbers | // bit17=recognize roman numbers | ||||
// bit18=Roman numbers only if upper case | |||||
int numbers; | int numbers; | ||||
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 ungot_char; | ||||
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); |