Browse Source

[1.29.24] Fixed problem where espeak_GetCurrentVoice() gave a newline character after the voice name.


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@110 d46cf337-b52f-0410-862d-fd96e6ae7743
master
jonsd 17 years ago
parent
commit
363753f388

+ 4
- 4
dictsource/dict_phonemes View File

@@ -337,10 +337,10 @@ Dictionary zh_dict
i i. i[ iou o o- ou u
uai y

f j k kh l m n N
p ph R R2 R3 s s. S;
t th ts ts. ts. tS; tS; tsh
v w x z z.
: f j k kh l m n
N p ph R R2 R3 s s.
S; t th ts ts. ts. tS; tS;
tsh v w x z z.


Dictionary hbs_dict

+ 3
- 3
dictsource/en_list View File

@@ -1344,7 +1344,7 @@ peculiar pI2kju:lI3
pedalo pEd@loU
pejorative p@dZ0r@tIv
penal pi:n@L
?4 penchant p0nS0n
penchant p0nS0n
peninsula p@n'InsjUl@
penis pi:nI2s
perfectly p3:fEktlI2
@@ -1388,8 +1388,8 @@ politer p@l'aIt3
politic p0l@tIk
poll poUl
polls poUlz
penchant p0nS0n
portend po@t'End
posse p0sI
postage poUstIdZ
practise praktIs
prayer pre@
@@ -2631,11 +2631,11 @@ also $verbf
already O:lr,EdI2 $verbf $strend2

not ,n0t $verbextend $only $strend
not n0t $capital $abbrev // don't spell "NOT"; speak it with stress
(not have) n0ta2v $pastf $u1
(not have) n0thav $pastf $atend
(not have to) ,n0thavt@5 $pastf $strend
(not a) ,n0t@ $nounf
not n0t $allcaps $verbextend // don't spell "NOT"; speak it with stress
only oUnlI2 $verbextend

any ,EnI2 $nounf $only

+ 1
- 1
dictsource/en_rules View File

@@ -1484,7 +1484,7 @@
de (lph dE
_) de (lt dE
delu (g dElju:
de (lv dE
de (lv+ dE
de (ma dI2
de (mea dI2
de (men dI2

+ 1
- 0
dictsource/hu_rules View File

@@ -308,6 +308,7 @@ vörösmar) ty ti
nehé) z (sé z
pén) z z
szá) z (sz z
tí) z (sz z
tű) z (sz z
ví) z (sz z
tor) z (szülött z

+ 1
- 1
dictsource/zh_list View File

@@ -1,5 +1,5 @@

_?? @11 // unrecognized character
_?? @:11 // unrecognized character

//numbers
_0 liN35

+ 1
- 1
phsource/phonemes View File

@@ -72,7 +72,7 @@ endphoneme

phoneme '' // Primary stress (priority)
stress
length 5
length 6
endphoneme

phoneme = // Place stress on previous vowel

+ 16
- 11
src/compiledict.cpp View File

@@ -78,7 +78,6 @@ MNEM_TAB mnem_flags[] = {
{"$unstressend",13}, /* reduce stress at end of clause */
{"$atend", 14}, /* use this pronunciation if at end of clause */

{"$capital", 15}, /* use this pronunciation if initial letter is upper case */
{"$dot", 16}, /* ignore '.' after this word (abbreviation) */
{"$abbrev", 17}, /* use this pronuciation rather than split into letters */
{"$stem", 18}, // must have a suffix
@@ -87,17 +86,23 @@ MNEM_TAB mnem_flags[] = {
{"$double", 19}, // IT double the initial consonant of next word
{"$alt", 20}, // use alternative pronunciation
{"$alt2", 21},

{"$verbf", 22}, /* verb follows */
{"$verbsf", 23}, /* verb follows, allow -s suffix */
{"$nounf", 24}, /* noun follows */
{"$verb", 25}, /* use this pronunciation when its a verb */
{"$past", 26}, /* use this pronunciation when its past tense */
{"$pastf", 27}, /* past tense follows */
{"$verbextend",28}, /* extend influence of 'verb follows' */

{"$brk", 28}, // a shorter $pause
{"$text", 29}, // word translates to replcement text, not phonemes
{"$brk", 30}, // a shorter $pause

// flags in dictionary word 2
{"$verbf", 0x20}, /* verb follows */
{"$verbsf", 0x21}, /* verb follows, allow -s suffix */
{"$nounf", 0x22}, /* noun follows */
{"$pastf", 0x23}, /* past tense follows */
{"$verb", 0x24}, /* use this pronunciation when its a verb */
{"$noun", 0x25}, /* use this pronunciation when its a noun */
{"$past", 0x26}, /* use this pronunciation when its past tense */
{"$verbextend",0x28}, /* extend influence of 'verb follows' */
{"$capital", 0x29}, /* use this pronunciation if initial letter is upper case */
{"$allcaps", 0x2a}, /* use this pronunciation if initial letter is upper case */

// doesn't set dictionary_flags
{"$?", 100}, // conditional rule, followed by byte giving the condition number

@@ -455,7 +460,7 @@ static char nullstring[] = {0};
}
else
{
dict_line[length++] = 40 + multiple_words;
dict_line[length++] = 80 + multiple_words;
ix = multiple_string_end - multiple_string;
memcpy(&dict_line[length],multiple_string,ix);
length += ix;

+ 86
- 47
src/dictionary.cpp View File

@@ -752,9 +752,9 @@ void SetLetterBitsRange(Translator *tr, int group, int first, int last)



static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char *vowel_stress, int &vowel_count, int &stressed_syllable)
{//======================================================================================================================================
static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char *vowel_stress, int &vowel_count, int &stressed_syllable, int control)
{//====================================================================================================================================================
// control = 1, set stress to 1 for forced unstressed vowels
unsigned char phcode;
PHONEME_TAB *ph;
unsigned char *ph_out = phonemes;
@@ -825,7 +825,7 @@ static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char
max_stress = stress;
}

if((stress == 0) && (ph->phflags & phUNSTRESSED))
if((stress == 0) && (control & 1) && (ph->phflags & phUNSTRESSED))
vowel_stress[count] = 1; /* weak vowel, must be unstressed */

count++;
@@ -836,7 +836,7 @@ static int GetVowelStress(Translator *tr, unsigned char *phonemes, unsigned char
{
// previous consonant phoneme is syllablic
vowel_stress[count] = (char)stress;
if(stress == 0)
if((stress == 0) && (control & 1))
vowel_stress[count++] = 1; // syllabic consonant, usually unstressed
}

@@ -900,14 +900,14 @@ void ChangeWordStress(Translator *tr, char *word, int new_stress)
unsigned char vowel_stress[N_WORD_PHONEMES/2];

strcpy((char *)phonetic,word);
max_stress = GetVowelStress(tr, phonetic,vowel_stress,vowel_count,stressed_syllable);
max_stress = GetVowelStress(tr, phonetic, vowel_stress, vowel_count, stressed_syllable, 0);

if(new_stress >= 4)
{
// promote to primary stress
for(ix=1; ix<vowel_count; ix++)
{
if(vowel_stress[ix] == max_stress)
if(vowel_stress[ix] >= max_stress)
{
vowel_stress[ix] = new_stress;
break;
@@ -919,7 +919,7 @@ void ChangeWordStress(Translator *tr, char *word, int new_stress)
// remove primary stress
for(ix=1; ix<vowel_count; ix++)
{
if(vowel_stress[ix] > new_stress)
if(vowel_stress[ix] > new_stress) // >= allows for diminished stress (=1)
vowel_stress[ix] = new_stress;
}
}
@@ -1013,7 +1013,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int
unstressed_word = 1;
}

max_stress = GetVowelStress(this,phonetic,vowel_stress,vowel_count,stressed_syllable);
max_stress = GetVowelStress(this, phonetic, vowel_stress, vowel_count, stressed_syllable, 1);

// heavy or light syllables
ix = 1;
@@ -2598,18 +2598,18 @@ int TransposeAlphabet(char *text, int offset, int min, int max)



char *print_dflags(int flags)
{//==========================
char *print_dflags(unsigned int *flags)
{//====================================
static char buf[20];

sprintf(buf,"%s 0x%x",LookupMnem(mnem_flags,(flags & 0xf)+0x40), flags);
sprintf(buf,"%s 0x%x/%x",LookupMnem(mnem_flags,(flags[0] & 0xf)+0x40), flags[0], flags[1]);
return(buf);
}



const char *Translator::LookupDict2(const char *word, const char *word2, char *phonetic, unsigned int *flags, int end_flags)
//====================================================================================================================
const char *Translator::LookupDict2(const char *word, const char *word2, char *phonetic, unsigned int *flags, int end_flags, WORD_TAB *wtab)
//==========================================================================================================================================
/* Find an entry in the word_dict file for a specified word.
Returns NULL if no match, else returns 'word_end'

@@ -2628,9 +2628,12 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p
int wlen;
unsigned char flag;
unsigned int dictionary_flags;
unsigned int dictionary_flags2;
int condition_failed=0;
int n_chars;
int no_phonemes;
int skipwords;
int ix;
const char *word_end;
const char *word1;
char word_buf[N_WORD_BYTES];
@@ -2675,6 +2678,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p
word_end = word2;

dictionary_flags = 0;
dictionary_flags2 = 0;
no_phonemes = p[1] & 0x80;

p += ((p[1] & 0x3f) + 2);
@@ -2713,32 +2717,48 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p
}
}
else
if(flag > 64)
if(flag > 80)
{
// stressed syllable information, put in bits 0-3
dictionary_flags = (dictionary_flags & ~0xf) | (flag & 0xf);
if((flag & 0xc) == 0xc)
dictionary_flags |= FLAG_STRESS_END;
}
else
if(flag > 40)
{
// flags 41 to 50 match more than one word
// flags 81 to 90 match more than one word
// This comes after the other flags
n_chars = next - p;
if(memcmp(word2,p,n_chars)==0)
skipwords = flag - 80;

// don't use the contraction if any of the words are emphasized
for(ix=0; ix <= skipwords; ix++)
{
dictionary_flags |= FLAG_SKIPWORDS;
dictionary_skipwords = (flag - 40);
p = next;
word_end = word2 + n_chars;
if((wtab != NULL) && (wtab[ix].flags & FLAG_EMPHASIZED))
{
condition_failed = 1;
}
}
else

if(memcmp(word2,p,n_chars) != 0)
condition_failed = 1;

if(condition_failed)
{
p = next;
condition_failed = 1;
break;
}

dictionary_flags |= FLAG_SKIPWORDS;
dictionary_skipwords = skipwords;
p = next;
word_end = word2 + n_chars;
}
else
if(flag > 64)
{
// stressed syllable information, put in bits 0-3
dictionary_flags = (dictionary_flags & ~0xf) | (flag & 0xf);
if((flag & 0xc) == 0xc)
dictionary_flags |= FLAG_STRESS_END;
}
else
if(flag >= 32)
{
dictionary_flags2 |= (1L << (flag-32));
}
else
{
@@ -2775,13 +2795,20 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p
}
}

if(dictionary_flags & FLAG_CAPITAL)
if(dictionary_flags2 & FLAG_CAPITAL)
{
if(!(word_flags & FLAG_FIRST_UPPER))
{
continue;
}
}
if(dictionary_flags2 & FLAG_ALLCAPS)
{
if(!(word_flags & FLAG_ALL_UPPER))
{
continue;
}
}

if((dictionary_flags & FLAG_ATEND) && (word_end < clause_end))
{
@@ -2789,7 +2816,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p
continue;
}

if(dictionary_flags & FLAG_VERB)
if(dictionary_flags2 & FLAG_VERB)
{
// this is a verb-form pronunciation

@@ -2804,7 +2831,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p
continue;
}
}
if(dictionary_flags & FLAG_PAST)
if(dictionary_flags2 & FLAG_PAST)
{
if(!expect_past)
{
@@ -2813,21 +2840,33 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p
continue;
}
}
if(dictionary_flags2 & FLAG_NOUN)
{
if(!expect_noun)
{
/* don't use the 'noun' pronunciation unless we are
expecting a noun */
continue;
}
}

if(flags != NULL)
*flags = dictionary_flags;
{
flags[0] = dictionary_flags | FLAG_FOUND_ATTRIBUTES;
flags[1] = dictionary_flags2;
}

if(phoneme_len == 0)
{
if(option_phonemes == 2)
{
fprintf(f_trans,"Flags: %s %s\n",word1,print_dflags(*flags));
fprintf(f_trans,"Flags: %s %s\n",word1,print_dflags(flags));
}
return(0); // no phoneme translation found here, only flags. So use rules
}

if(flags != NULL)
*flags |= FLAG_FOUND; // this flag indicates word was found in dictionary
flags[0] |= FLAG_FOUND; // this flag indicates word was found in dictionary
if(option_phonemes == 2)
{
@@ -2837,7 +2876,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p

DecodePhonemes(phonetic,ph_decoded);
if(flags != NULL)
flags1 = *flags;
flags1 = flags[0];

if((dictionary_flags & FLAG_TEXTMODE) == 0)
textmode = 0;
@@ -2847,7 +2886,7 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p
if(textmode == translator->langopts.textmode)
{
// only show this line if the word translates to phonemes, not replacement text
fprintf(f_trans,"Found: %s [%s] %s\n",word1,ph_decoded,print_dflags(flags1));
fprintf(f_trans,"Found: %s [%s] %s\n",word1,ph_decoded,print_dflags(flags));
}
}
return(word_end);
@@ -2858,8 +2897,8 @@ const char *Translator::LookupDict2(const char *word, const char *word2, char *p



int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags, int end_flags)
//==============================================================================================
int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab)
//==============================================================================================================
/* Lookup a specified word in the word dictionary.
Returns phonetic data in 'phonetic' and bits in 'flags'

@@ -2895,7 +2934,7 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags
nbytes = utf8_in(&c2,word2,0);
memcpy(&word[length],word2,nbytes);
word[length+nbytes] = 0;
found = LookupDict2(word,word2,ph_out,flags,end_flags);
found = LookupDict2(word, word2, ph_out, flags, end_flags, wtab);
if(found)
{
*flags = *flags & ~(7 << 5) | (length << 5);
@@ -2911,7 +2950,7 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags
}
word[length] = 0;

found = LookupDict2(word,word1,ph_out,flags,end_flags);
found = LookupDict2(word, word1, ph_out, flags, end_flags, wtab);

if(found == 0)
{
@@ -2923,14 +2962,14 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags
{
// try removing an 'e' which has been added by RemoveEnding
word[length-1] = 0;
found = LookupDict2(word,word1,ph_out,flags,end_flags);
found = LookupDict2(word, word1, ph_out, flags, end_flags, wtab);
}
else
if((end_flags & SUFX_D) && (word[length-1] == word[length-2]))
{
// try removing a double letter
word[length-1] = 0;
found = LookupDict2(word,word1,ph_out,flags,end_flags);
found = LookupDict2(word, word1, ph_out, flags, end_flags, wtab);
}
}

@@ -2977,9 +3016,9 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags

int Translator::Lookup(const char *word, char *ph_out)
{//===================================================
unsigned int flags;
unsigned int flags[2];
char *word1 = (char *)word;
return(LookupDictList(&word1,ph_out,&flags,0));
return(LookupDictList(&word1, ph_out, flags, 0, NULL));
}



+ 58
- 65
src/intonation.cpp View File

@@ -228,7 +228,7 @@ unsigned char *envelope_data[16] = {
/* all pitches given in Hz above pitch_base */

// pitch change during the main part of the clause
static int drops_0[8] = {0x400,0x400,0x700,0x700,0x700,0xa00,0x0e00,0x0e00};
static int drops_0[8] = {0x400,0x400,0x700,0x700,0x700,0xa00,0x1800,0x0e00};
static int drops_1[8] = {0x400,0x400,0x600,0x600,0xc00,0xc00,0x0e00,0x0e00};
static int drops_2[8] = {0x400,0x400,0x600,0x600,-0x800,0xc00,0x0e00,0x0e00};

@@ -241,6 +241,9 @@ typedef struct {
unsigned char tonic_max1;
unsigned char tonic_min1;

unsigned char emph_level;
unsigned char emph_next;

unsigned char pre_start;
unsigned char pre_end;

@@ -260,16 +263,19 @@ typedef struct {

static TONE_TABLE tone_table[N_TONE_TABLE] = {
{PITCHfall, 30, 5, PITCHfall, 30, 7, // statement
12, 10,
20, 25, 34, 22, drops_0, 3, 3, 12, 8, 0},

{PITCHfrise, 38,10, PITCHfrise2, 36,10, // comma, or question
30, 20,
20, 25, 34, 20, drops_0, 3, 3, 15, 25, 0},

{PITCHdrop, 38, 1, PITCHdrop, 42,25, // exclamation
30, 20,
20, 25, 34, 22, drops_0, 3, 3, 12, 8, 0},


#ifdef deleted
{PITCHfall, 30, 5, PITCHfall, 30, 7, // statement
20, 25, 34, 22, drops_1, 3, 3, 12, 8, 0},

@@ -301,23 +307,23 @@ static TONE_TABLE tone_table[N_TONE_TABLE] = {

{PITCHfall, 36, 6, PITCHfall, 36, 8,
30, 20, 18, 34, drops_0, 3, 3, 12, 8, 0},
#endif
};



/* indexed by stress */
static int min_drop[] = {0x300,0x300,0x300,0x300,0x300,0x500,0xc00,0xc00};
static int min_drop[] = {0x300,0x300,0x400,0x400,0x900,0x900,0x900,0x900};




#define SECONDARY 3
#define PRIMARY 4
#define PRIMARY_STRESSED 5
#define PRIMARY_MARKED 6
#define BODY_RESET 7
#define FIRST_TONE 8 /* first of the tone types */
#define PRIMARY_LAST 7


static int number_pre;
@@ -335,15 +341,13 @@ static void count_pitch_vowels()
{
int ix;
int stress;
int stage=0; /* 0=pre, 1=body, 2=tail */
int max_stress = 0;
int max_stress_posn = 0;
int tone_type_marker = 0;
int marked_stress_count = 0;

number_pre=0; /* number of vowels before 1st primary stress */
number_body=0;
number_tail=0; /* number between tonic syllable and next primary */
number_pre = -1; /* number of vowels before 1st primary stress */
number_body = 0;
number_tail = 0; /* number between tonic syllable and next primary */
last_primary = 0;
for(ix=vowel_ix; ix<vowel_ix_top; ix++)
{
@@ -355,65 +359,31 @@ static void count_pitch_vowels()
}
if(stress >= PRIMARY)
{
if(stress > PRIMARY)
{
marked_stress_count++;
}
if(number_pre < 0)
number_pre = ix;

last_primary = ix;
}

switch(stage)
{
case 0:
if(stress < PRIMARY)
number_pre++;
else
{
stage = 1;
ix = ix-1;
}
break;
}

case 1:
if(stress >= FIRST_TONE)
{
tone_type_marker = stress;
tone_posn = ix;
stage = 2;
}
break;
if(number_pre < 0)
number_pre = 0;

case 2:
if(stress < PRIMARY)
number_tail++;
else
stage = 3;
break;
}
}
number_tail = vowel_ix_top - max_stress_posn - 1;
tone_posn = max_stress_posn;
tone_posn = last_primary;

if(no_tonic)
{
tone_posn = vowel_ix_top;
}
else
if((tone_type_marker >= FIRST_TONE) && (tone_type_marker < (N_TONE_TABLE + FIRST_TONE)))
{
tone_type = tone_type_marker - FIRST_TONE;
}
else
// if((last_primary - max_stress_posn) > 2)
{
/* no tonic syllable found, use highest stress */
vowel_tab[max_stress_posn] = FIRST_TONE;
number_tail = vowel_ix_top - max_stress_posn - 1;
tone_posn = max_stress_posn;
if(vowel_tab[last_primary] < PRIMARY_MARKED)
vowel_tab[last_primary] = PRIMARY_LAST;
}

if(marked_stress_count > 1)
annotation = 1;
else
annotation = 0;
} /* end of count_pitch_vowels */


@@ -429,9 +399,9 @@ static int count_increments(int ix, int end_ix, int min_stress)
while(ix < end_ix)
{
stress = vowel_tab[ix++] & 0x3f;
if(stress >= BODY_RESET)
break;
else
// if(stress >= PRIMARY_MARKED)
// break;
if(stress >= min_stress)
count++;
}
@@ -494,9 +464,10 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_TABLE *t, int min_stress)
int n_primary=0;
int initial;
int overflow=0;
int marking=0;
int *drops;

static char overflow_tab[5] = {0, 5, 3, 1, 0};
static char overflow_tab[5] = {0, 20, 12, 4, 0};

drops = t->body_drops;
@@ -505,11 +476,13 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_TABLE *t, int min_stress)
{
stress = vowel_tab[ix] & 0x3f;

if(stress == BODY_RESET)
initial = 1;
// if(stress == PRIMARY_MARKED)
// initial = 1; // reset the intonation pattern

if(initial || (stress >= min_stress))
{
// a primary stress

if(initial)
{
initial = 0;
@@ -535,14 +508,34 @@ static int calc_pitch_segment(int ix, int end_ix, TONE_TABLE *t, int min_stress)
pitch += increment;
else
{
pitch = (t->body_end << 8) - (increment * overflow_tab[overflow++])/4;
pitch = (t->body_end << 8) - (increment * overflow_tab[overflow++])/16;
if(overflow > 4) overflow = 0;
}
}

if(stress == PRIMARY_MARKED)
{
pitch = (t->emph_level << 8);
marking = 2;
n_primary = marking+1; // move into overflow region
}
else
if(marking > 0)
{
marking--;
pitch = (t->emph_next << 8);
}


n_primary--;
}

if(((annotation==0) && (stress >= PRIMARY)) || (stress >= PRIMARY_MARKED))
if((annotation==0) && (stress >= PRIMARY))
{
vowel_tab[ix] = PRIMARY_STRESSED;
set_pitch(ix,pitch,drops[stress]);
}
if(stress >= PRIMARY_MARKED)
{
vowel_tab[ix] = PRIMARY_MARKED;
set_pitch(ix,pitch,drops[stress]);

+ 3
- 3
src/readclause.cpp View File

@@ -460,15 +460,15 @@ static void UngetC(int c)

const char *Translator::LookupSpecial(const char *string)
{//======================================================
unsigned int flags;
unsigned int flags[2];
char phonemes[55];
char phonemes2[55];
static char buf[60];
char *string1 = (char *)string;

if(LookupDictList(&string1,phonemes,&flags,0))
if(LookupDictList(&string1,phonemes,flags,0,NULL))
{
SetWordStress(phonemes,flags,-1,0);
SetWordStress(phonemes,flags[0],-1,0);
DecodePhonemes(phonemes,phonemes2);
sprintf(buf,"[[%s]] ",phonemes2);
option_phoneme_input = 1;

+ 5
- 2
src/setlengths.cpp View File

@@ -499,13 +499,16 @@ void Translator::CalcLengths()
if(length_mod < 8)
length_mod = 8; // restrict how much lengths can be reduced

if(stress >= 7)
if(stress >= 6)
{
// tonic syllable, include a constant component so it doesn't decrease directly with speed
length_mod += 20;
}
length_mod = (length_mod * stress_lengths[stress])/128;
if((len = stress_lengths[stress]) == 0)
len = stress_lengths[6];

length_mod = (length_mod * len)/128;

if(end_of_clause == 2)
{

+ 5
- 0
src/speak.cpp View File

@@ -630,6 +630,11 @@ int main (int argc, char **argv)
exit(1);
}

{
espeak_VOICE *v;
v = espeak_GetCurrentVoice();
printf("Voice id='%s' name='%s' langs={%x %x %x %x}\n",v->identifier,v->name,v->languages[0],v->languages[1],v->languages[2],v->languages[3]);
}
if(option_waveout || quiet)
{
if(quiet)

+ 2
- 2
src/synthdata.cpp View File

@@ -35,8 +35,8 @@
#include "translate.h"
#include "wave.h"

const char *version_string = "1.29.23 01.Dec.07";
const int version_phdata = 0x012901;
const char *version_string = "1.29.24 12.Dec.07";
const int version_phdata = 0x012924;

int option_device_number = -1;


+ 1
- 1
src/tr_english.cpp View File

@@ -37,7 +37,7 @@
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};
static const short stress_lengths2[8] = {182,140, 220,220, 248,248, 275,275};

memcpy(stress_lengths,stress_lengths2,sizeof(stress_lengths));
langopts.stress_rule = 0;

+ 42
- 43
src/tr_languages.cpp View File

@@ -111,8 +111,8 @@ Translator *SelectTranslator(const char *name)

case L('c','y'): // Welsh
{
static const short stress_lengths_cy[8] = {170,230, 190,190, 0, 0, 250,270};
static const unsigned char stress_amps_cy[8] = {16,15, 18,18, 0,0, 24,22 }; // 'diminished' is used to mark a quieter, final unstressed syllable
static const short stress_lengths_cy[8] = {170,230, 190,190, 250, 250, 270,270};
static const unsigned char stress_amps_cy[8] = {16,15, 18,18, 20,24, 24,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable

tr = new Translator();
SetupTranslator(tr,stress_lengths_cy,stress_amps_cy);
@@ -136,7 +136,7 @@ Translator *SelectTranslator(const char *name)

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, 260, 260, 275,275};
tr = new Translator();
tr->langopts.stress_rule = 0;
tr->langopts.word_gap = 0x8; // don't use linking phonemes
@@ -156,8 +156,8 @@ Translator *SelectTranslator(const char *name)
case L('e','l'): // Greek
case L_grc: // Ancient Greek
{
static const short stress_lengths_el[8] = {155, 180, 210, 210, 0, 0, 270, 300};
static const unsigned char stress_amps_el[8] = {15,12, 20,20, 20,24, 24,22 }; // 'diminished' is used to mark a quieter, final unstressed syllable
static const short stress_lengths_el[8] = {155, 180, 210, 210, 270, 270, 300, 300};
static const unsigned char stress_amps_el[8] = {15,12, 20,20, 20,24, 24,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable

// character codes offset by 0x380
static const char el_vowels[] = {0x10,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x35,0x37,0x39,0x3f,0x45,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0};
@@ -199,8 +199,8 @@ Translator *SelectTranslator(const char *name)

case L('e','o'):
{
static const short stress_lengths_eo[8] = {145, 180, 200, 190, 0, 0, 300, 320};
static const unsigned char stress_amps_eo[] = {16,14, 20,20, 20,24, 24,22 };
static const short stress_lengths_eo[8] = {145, 180, 200, 190, 300, 300, 320, 320};
static const unsigned char stress_amps_eo[] = {16,14, 20,20, 20,24, 24,21 };
static const wchar_t eo_char_apostrophe[2] = {'l',0};
tr = new Translator();
@@ -222,8 +222,8 @@ Translator *SelectTranslator(const char *name)

case L('e','s'): // Spanish
{
static const short stress_lengths_es[8] = {170, 200, 180, 180, 0, 0, 220, 250};
static const unsigned char stress_amps_es[8] = {16,12, 18,18, 20,22, 22,22 }; // 'diminished' is used to mark a quieter, final unstressed syllable
static const short stress_lengths_es[8] = {170, 200, 180, 180, 220, 220, 250, 250};
static const unsigned char stress_amps_es[8] = {16,12, 18,18, 20,22, 22,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable

tr = new Translator();
SetupTranslator(tr,stress_lengths_es,stress_amps_es);
@@ -245,8 +245,8 @@ Translator *SelectTranslator(const char *name)

case L('f','i'): // Finnish
{
static const unsigned char stress_amps_fi[8] = {18,16, 22,22, 20,22, 22,22 };
static const short stress_lengths_fi[8] = {150,170, 200,200, 0,0, 210,250};
static const short stress_lengths_fi[8] = {150,170, 200,200, 210,210, 250,240};
static const unsigned char stress_amps_fi[8] = {18,16, 22,22, 20,22, 22,21 };

tr = new Translator();
SetupTranslator(tr,stress_lengths_fi,stress_amps_fi);
@@ -267,7 +267,7 @@ Translator *SelectTranslator(const char *name)

case L('f','r'): // french
{
static const short stress_lengths_fr[8] = {190, 170, 190, 200, 0, 0, 235, 235};
static const short stress_lengths_fr[8] = {190, 170, 190, 200, 235, 235, 235, 235};
static const unsigned char stress_amps_fr[8] = {16,14, 20,20, 20,24, 24,22 };

tr = new Translator();
@@ -284,8 +284,8 @@ Translator *SelectTranslator(const char *name)
case L('h','i'):
{
static const char dev_consonants2[] = {0x02,0x03,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f};
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,24, 24,22 };
static const short stress_lengths_hi[8] = {190, 190, 210, 210, 230, 230, 250, 250};
static const unsigned char stress_amps_hi[8] = {17,14, 20,19, 20,24, 24,21 };

tr = new Translator();
SetupTranslator(tr,stress_lengths_hi,stress_amps_hi);
@@ -312,8 +312,8 @@ Translator *SelectTranslator(const char *name)
case L('b','s'): // Bosnian
case L('s','r'): // Serbian
{
static const unsigned char stress_amps_hr[8] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_hr[8] = {180,160, 200,200, 0,0, 220,230};
static const unsigned char stress_amps_hr[8] = {16,16, 20,20, 20,24, 24,21 };
static const short stress_lengths_hr[8] = {180,160, 200,200, 220,220, 230,230};

tr = new Translator();
SetupTranslator(tr,stress_lengths_hr,stress_amps_hr);
@@ -337,8 +337,8 @@ Translator *SelectTranslator(const char *name)

case L('h','u'): // Hungarian
{
static const unsigned char stress_amps_hu[8] = {17,17, 19,19, 20,24, 24,22 };
static const short stress_lengths_hu[8] = {185,195, 195,190, 0,0, 210,220};
static const unsigned char stress_amps_hu[8] = {17,17, 19,19, 20,24, 24,21 };
static const short stress_lengths_hu[8] = {185,195, 195,190, 210,210, 220,220};

tr = new Translator();
SetupTranslator(tr,stress_lengths_hu,stress_amps_hu);
@@ -361,8 +361,8 @@ SetLengthMods(tr,3); // all equal

case L('i','s'): // Icelandic
{
static const unsigned char stress_amps_is[] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_is[8] = {180,160, 200,200, 0,0, 240,250};
static const unsigned char stress_amps_is[] = {16,16, 20,20, 20,24, 24,21 };
static const short stress_lengths_is[8] = {180,160, 200,200, 240,240, 250,250};
static const wchar_t is_lettergroup_B[] = {'c','f','h','k','p','t','x',0xfe,0}; // voiceless conants, including 'þ' ?? 's'

tr = new Translator();
@@ -384,8 +384,8 @@ SetLengthMods(tr,3); // all equal

case L('i','t'): // Italian
{
static const short stress_lengths_it[8] = {150, 140, 180, 180, 0, 0, 270, 320};
static const unsigned char stress_amps_it[8] = {15,14, 19,19, 20,24, 24,22 };
static const short stress_lengths_it[8] = {150, 140, 180, 180, 270, 270, 320, 320};
static const unsigned char stress_amps_it[8] = {15,14, 19,19, 20,24, 24,21 };

tr = new Translator();
SetupTranslator(tr,stress_lengths_it,stress_amps_it);
@@ -421,8 +421,8 @@ SetLengthMods(tr,3); // all equal
{
static wchar_t vowels_cyrillic[] = {0x440, // also include 'р' [R]
0x430,0x435,0x438,0x439,0x43e,0x443,0x44b,0x44d,0x44e,0x44f,0x450,0x451,0x456,0x457,0x45d,0x45e,0};
static const unsigned char stress_amps_mk[8] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_mk[8] = {180,160, 200,200, 0,0, 220,230};
static const unsigned char stress_amps_mk[8] = {16,16, 20,20, 20,24, 24,21 };
static const short stress_lengths_mk[8] = {180,160, 200,200, 220,220, 230,230};

tr = new Translator();
SetupTranslator(tr,stress_lengths_mk,stress_amps_mk);
@@ -438,7 +438,7 @@ SetLengthMods(tr,3); // all equal

case L('n','l'): // Dutch
{
static const short stress_lengths_nl[8] = {160,135, 210,210, 0, 0, 260,280};
static const short stress_lengths_nl[8] = {160,135, 210,210, 260, 260, 280,280};
tr = new Translator();

tr->langopts.stress_rule = 0;
@@ -454,8 +454,8 @@ SetLengthMods(tr,3); // all equal

case L('n','o'): // Norwegian
{
static const unsigned char stress_amps_no[] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_no[8] = {160,140, 200,190, 0,0, 220,240};
static const short stress_lengths_no[8] = {160,140, 200,190, 220,220, 240,240};
static const unsigned char stress_amps_no[] = {16,16, 20,20, 20,24, 24,21 };
tr = new Translator();
SetupTranslator(tr,stress_lengths_no,stress_amps_no);

@@ -467,8 +467,8 @@ SetLengthMods(tr,3); // all equal

case L('p','l'): // Polish
{
static const short stress_lengths_pl[8] = {160, 180, 175, 175, 0, 0, 260, 290};
static const unsigned char stress_amps_pl[8] = {17,14, 19,19, 20,24, 24,22 }; // 'diminished' is used to mark a quieter, final unstressed syllable
static const short stress_lengths_pl[8] = {160, 180, 175, 175, 260, 260, 290, 290};
static const unsigned char stress_amps_pl[8] = {17,14, 19,19, 20,24, 24,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable

tr = new Translator();
SetupTranslator(tr,stress_lengths_pl,stress_amps_pl);
@@ -487,8 +487,8 @@ SetLengthMods(tr,3); // all equal

case L('p','t'): // Portuguese
{
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,24, 24,22 }; // 'diminished' is used to mark a quieter, final unstressed syllable
static const short stress_lengths_pt[8] = {180, 125, 210, 210, 270, 270, 295, 295};
static const unsigned char stress_amps_pt[8] = {16,13, 19,19, 20,24, 24,21 }; // 'diminished' is used to mark a quieter, final unstressed syllable
tr = new Translator();
SetupTranslator(tr,stress_lengths_pt,stress_amps_pt);
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
@@ -504,8 +504,8 @@ SetLengthMods(tr,3); // all equal

case L('r','o'): // Romanian
{
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,22 };
static const short stress_lengths_ro[8] = {170, 170, 180, 180, 240, 240, 260, 260};
static const unsigned char stress_amps_ro[8] = {15,13, 18,18, 20,22, 22,21 };

tr = new Translator();
SetupTranslator(tr,stress_lengths_ro,stress_amps_ro);
@@ -526,8 +526,8 @@ SetLengthMods(tr,3); // all equal
case L('s','k'): // Slovak
case L('c','s'): // Czech
{
static const short stress_lengths_sk[8] = {190,190, 210,210, 210,210, 210,210};
static const unsigned char stress_amps_sk[8] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_sk[8] = {190,190, 210,210, 0,0, 210,210};
static const char *sk_voiced = "bdgjlmnrvwzaeiouy";

tr = new Translator();
@@ -560,21 +560,20 @@ SetLengthMods(tr,3); // all equal

case L('s','v'): // Swedish
{
static const short stress_lengths_sv[8] = {160,135, 220,220, 250,250, 250,280};
static const unsigned char stress_amps_sv[] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_sv[8] = {160,135, 220,220, 0,0, 250,280};
tr = new Translator();
SetupTranslator(tr,stress_lengths_sv,stress_amps_sv);

tr->langopts.stress_rule = 0;
SetLetterVowel(tr,'y');
// SetLetterBits(tr,6,"eiyäö"); // soft vowels NOTE accented letters don't work in SetLetterBits
tr->langopts.numbers = 0x1109;
}
break;

case L('s','w'): // Swahili
{
static const short stress_lengths_sw[8] = {160, 170, 200, 200, 0, 0, 320, 340};
static const short stress_lengths_sw[8] = {150, 160, 190, 190, 300, 300, 320, 320};
static const unsigned char stress_amps_sw[] = {16,12, 19,19, 20,24, 24,22 };
tr = new Translator();
@@ -592,8 +591,8 @@ SetLengthMods(tr,3); // all equal

case L('t','r'): // Turkish
{
static const unsigned char stress_amps_tr[8] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_tr[8] = {180,150, 200,180, 0,0, 230,270};
static const short stress_lengths_tr[8] = {180,150, 200,180, 230,230, 270,270};
static const unsigned char stress_amps_tr[8] = {16,16, 20,20, 20,24, 24,21 };

tr = new Translator();
SetupTranslator(tr,stress_lengths_tr,stress_amps_tr);
@@ -608,7 +607,7 @@ SetLengthMods(tr,3); // all equal

case L('v','i'): // Vietnamese
{
static const short stress_lengths_vi[8] = {150, 150, 180, 180, 210, 220, 220, 280};
static const short stress_lengths_vi[8] = {150, 150, 180, 180, 220, 220, 280, 280};
static const unsigned char stress_amps_vi[] = {16,16, 16,16, 24,24, 24,22 };
static wchar_t vowels_vi[] = {
0x61, 0xe0, 0xe1, 0x1ea3, 0xe3, 0x1ea1, // a
@@ -642,7 +641,7 @@ SetLengthMods(tr,3); // all equal
case L('z','h'):
case L_zhy:
{
static const short stress_lengths_zh[8] = {230,150, 230,230, 230,0, 230,250};
static const short stress_lengths_zh[8] = {230,150, 230,230, 230,230, 250,250};
static const unsigned char stress_amps_zh[] = {22,16, 22,22, 22,22, 22,22 };

tr = new Translator;
@@ -691,8 +690,8 @@ SetLengthMods(tr,3); // all equal

Translator_Russian::Translator_Russian() : Translator()
{//===================================
static const short stress_lengths_ru[8] = {150,140, 220,220, 260,260, 280,280};
static const unsigned char stress_amps_ru[] = {16,16, 18,18, 20,24, 24,22 };
static const short stress_lengths_ru[8] = {150,140, 220,220, 0,0, 260,280};


// character codes offset by 0x420
@@ -945,7 +944,7 @@ Translator_Afrikaans::Translator_Afrikaans() : Translator()
{//=========================================
// Initialise options for this language

static const short stress_lengths2[8] = {170,140, 220,220, 0, 0, 250,270};
static const short stress_lengths2[8] = {170,140, 220,220, 250, 250, 270,270};
langopts.stress_rule = 0;
langopts.vowel_pause = 0x30;
langopts.param[LOPT_DIERESES] = 1;

+ 104
- 61
src/translate.cpp View File

@@ -52,7 +52,9 @@ int option_capitals = 0;
int option_punctuation = 0;
int option_sayas = 0;
int option_sayas2 = 0; // used in translate_clause()
int option_emphasis = 0;
int option_emphasis = 0; // 0=normal, 1=normal, 2=weak, 3=moderate, 4=strong
int word_emphasis = 0; // set if emphasis level 3 or 4
int option_emphasize_allcaps = 0;
int option_ssml = 0;
int option_phoneme_input = 1; // allow [[phonemes]] in input
int option_phoneme_variants = 0; // 0= don't display phoneme variant mnemonics
@@ -394,7 +396,7 @@ Translator::Translator()
{//=====================
int ix;
static const unsigned char stress_amps2[] = {16,16, 20,20, 20,24, 24,21 };
static const short stress_lengths2[8] = {182,140, 220,220, 220,240, 260,280};
static const short stress_lengths2[8] = {182,140, 220,220, 250,260, 280,280};
static const wchar_t empty_wstring[1] = {0};

charset_a0 = charsets[1]; // ISO-8859-1, this is for when the input is not utf8
@@ -595,8 +597,8 @@ int Translator::TranslateWord(char *word1, int next_pause, WORD_TAB *wtab)
int word_length;
int ix;
int posn;
unsigned int dictionary_flags=0;
unsigned int dictionary_flags2=0;
unsigned int dictionary_flags[2];
unsigned int dictionary_flags2[2];
int end_type=0;
int prefix_type=0;
char *wordx;
@@ -616,6 +618,7 @@ int Translator::TranslateWord(char *word1, int next_pause, WORD_TAB *wtab)
int prefix_flags = 0;
int confirm_prefix;
int spell_word;
int emphasize_allcaps = 0;
int wflags = wtab->flags;
int wmark = wtab->wmark;

@@ -625,6 +628,12 @@ int Translator::TranslateWord(char *word1, int next_pause, WORD_TAB *wtab)
static char word_iz[4] = {0,'i','z',0};
static char word_ss[4] = {0,'s','s',0};

dictionary_flags[0] = 0;
dictionary_flags[1] = 0;
dictionary_flags2[0] = 0;
dictionary_flags2[1] = 0;
dictionary_skipwords = 0;

prefix_phonemes[0] = 0;
end_phonemes[0] = 0;
ph_limit = &phonemes[N_WORD_PHONEMES];
@@ -649,7 +658,7 @@ int Translator::TranslateWord(char *word1, int next_pause, WORD_TAB *wtab)
else
{
spell_word = 0;
found = LookupDictList(&word1,phonemes,&dictionary_flags,FLAG_ALLOW_TEXTMODE | wflags << 16); // the original word
found = LookupDictList(&word1, phonemes, dictionary_flags, FLAG_ALLOW_TEXTMODE, wtab); // the original word

if(phonemes[0] == phonSWITCH)
{
@@ -661,10 +670,10 @@ int Translator::TranslateWord(char *word1, int next_pause, WORD_TAB *wtab)
if((wmark > 0) && (wmark < 8))
{
// the stressed syllable has been specified in the text (TESTING)
dictionary_flags = (dictionary_flags & ~0xf) | wmark;
dictionary_flags[0] = (dictionary_flags[0] & ~0xf) | wmark;
}

if(!found && (dictionary_flags & FLAG_ABBREV))
if(!found && (dictionary_flags[0] & FLAG_ABBREV))
{
// the word has $abbrev flag, but no pronunciation specified. Speak as individual letters
spell_word = 1;
@@ -676,7 +685,7 @@ if((wmark > 0) && (wmark < 8))
if(word_phonemes[0] == phonSWITCH)
return(0);

found = TranslateNumber(word1,phonemes,&dictionary_flags,wflags);
found = TranslateNumber(word1,phonemes,dictionary_flags,wflags);
}

if(!found & ((word_flags & FLAG_UPPERS) != FLAG_FIRST_UPPER))
@@ -686,15 +695,23 @@ if((wmark > 0) && (wmark < 8))
if((langopts.numbers & NUM_ROMAN) || ((langopts.numbers & NUM_ROMAN_UC) && (word_flags & FLAG_ALL_UPPER)))
{
if((found = TranslateRoman(word1,phonemes)) != 0)
dictionary_flags |= FLAG_ABBREV; // don't spell capital Roman numbers as individual letters
dictionary_flags[0] |= FLAG_ABBREV; // prevent emphasis if capitals
}
}

if((wflags & FLAG_ALL_UPPER) && (clause_upper_count <= clause_lower_count) &&
!(dictionary_flags & (FLAG_ABBREV | FLAG_SKIPWORDS)) && (word_length>1) && (word_length<4) && iswalpha(first_char))
if((wflags & FLAG_ALL_UPPER) && (word_length > 1) && (clause_lower_count > 3) && iswalpha(first_char))
{
// An upper case word in a lower case clause. This could be an abbreviation.
spell_word = 1;
if((option_emphasize_allcaps) && !(dictionary_flags[0] & FLAG_ABBREV))
{
// emphasize words which are in capitals
emphasize_allcaps = FLAG_EMPHASIZED;
}
else
if(!found && !(dictionary_flags[0] & FLAG_SKIPWORDS) && (word_length<4) && (clause_upper_count <= clause_lower_count))
{
// An upper case word in a lower case clause. This could be an abbreviation.
spell_word = 1;
}
}
}

@@ -733,6 +750,7 @@ if((wmark > 0) && (wmark < 8))
char *p;
// This word looks "unpronouncable", so speak letters individually until we
// find a remainder that we can pronounce.
emphasize_allcaps = 0;
wordx += TranslateLetter(wordx,phonemes,0);
if(phonemes[0] == phonSWITCH)
{
@@ -763,7 +781,7 @@ if((wmark > 0) && (wmark < 8))
{
// Translate the stem
unpron_length = strlen(phonemes);
end_type = TranslateRules(wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags, dictionary_flags);
end_type = TranslateRules(wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags, dictionary_flags[0]);

if(phonemes[0] == phonSWITCH)
{
@@ -788,11 +806,11 @@ if((wmark > 0) && (wmark < 8))

// remove any standard suffix and confirm that the prefix is still recognised
phonemes2[0] = 0;
end2 = TranslateRules(wordx, phonemes2, N_WORD_PHONEMES, end_phonemes2, wflags|FLAG_NO_PREFIX|FLAG_NO_TRACE, dictionary_flags);
end2 = TranslateRules(wordx, phonemes2, N_WORD_PHONEMES, end_phonemes2, wflags|FLAG_NO_PREFIX|FLAG_NO_TRACE, dictionary_flags[0]);
if(end2)
{
RemoveEnding(wordx,end2,word_copy);
end_type = TranslateRules(wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags|FLAG_NO_TRACE, dictionary_flags);
end_type = TranslateRules(wordx, phonemes, N_WORD_PHONEMES, end_phonemes, wflags|FLAG_NO_TRACE, dictionary_flags[0]);
memcpy(wordx,word_copy,strlen(word_copy));
if((end_type & SUFX_P) == 0)
{
@@ -832,14 +850,17 @@ if((wmark > 0) && (wmark < 8))
confirm_prefix = 1;

end_type = 0;
found = LookupDictList(&wordx,phonemes,&dictionary_flags2,SUFX_P | (wflags << 16)); // without prefix
if(dictionary_flags==0)
dictionary_flags = dictionary_flags2;
found = LookupDictList(&wordx, phonemes, dictionary_flags2, SUFX_P, wtab); // without prefix
if(dictionary_flags[0]==0)
{
dictionary_flags[0] = dictionary_flags2[0];
dictionary_flags[1] = dictionary_flags2[1];
}
else
prefix_flags = 1;
if(found == 0)
{
end_type = TranslateRules(wordx, phonemes, N_WORD_PHONEMES, end_phonemes, 0, dictionary_flags);
end_type = TranslateRules(wordx, phonemes, N_WORD_PHONEMES, end_phonemes, 0, dictionary_flags[0]);

if(phonemes[0] == phonSWITCH)
{
@@ -866,19 +887,22 @@ strcpy(phonemes2,phonemes);
{
// lookup the stem without the prefix removed
wordx[-1] = c_temp;
found = LookupDictList(&word1,phonemes_ptr,&dictionary_flags2,end_flags | (wflags << 16)); // include prefix, but not suffix
found = LookupDictList(&word1, phonemes_ptr, dictionary_flags2, end_flags, wtab); // include prefix, but not suffix
wordx[-1] = ' ';
if(dictionary_flags==0)
dictionary_flags = dictionary_flags2;
if(dictionary_flags[0]==0)
{
dictionary_flags[0] = dictionary_flags2[0];
dictionary_flags[1] = dictionary_flags2[1];
}
if(found)
prefix_phonemes[0] = 0; // matched whole word, don't need prefix now

if((found==0) && (dictionary_flags2 != 0))
if((found==0) && (dictionary_flags2[0] != 0))
prefix_flags = 1;
}
if(found == 0)
{
found = LookupDictList(&wordx,phonemes_ptr,&dictionary_flags2,end_flags | (wflags << 16)); // without prefix and suffix
found = LookupDictList(&wordx, phonemes_ptr, dictionary_flags2, end_flags, wtab); // without prefix and suffix
if(phonemes_ptr[0] == phonSWITCH)
{
// change to another language in order to translate this word
@@ -886,8 +910,11 @@ strcpy(phonemes2,phonemes);
strcpy(word_phonemes,phonemes_ptr);
return(0);
}
if(dictionary_flags==0)
dictionary_flags = dictionary_flags2;
if(dictionary_flags[0]==0)
{
dictionary_flags[0] = dictionary_flags2[0];
dictionary_flags[1] = dictionary_flags2[1];
}
}
if(found == 0)
{
@@ -897,14 +924,14 @@ strcpy(phonemes2,phonemes);
strcpy(phonemes,phonemes2);

// language specific changes
ApplySpecialAttribute(phonemes,dictionary_flags);
ApplySpecialAttribute(phonemes,dictionary_flags[0]);
}
else
{
if(end_flags & FLAG_SUFX)
TranslateRules(wordx, phonemes, N_WORD_PHONEMES, NULL,wflags | FLAG_SUFFIX_REMOVED, dictionary_flags);
TranslateRules(wordx, phonemes, N_WORD_PHONEMES, NULL,wflags | FLAG_SUFFIX_REMOVED, dictionary_flags[0]);
else
TranslateRules(wordx, phonemes, N_WORD_PHONEMES, NULL,wflags,dictionary_flags);
TranslateRules(wordx, phonemes, N_WORD_PHONEMES, NULL,wflags,dictionary_flags[0]);

if(phonemes[0] == phonSWITCH)
{
@@ -940,6 +967,8 @@ strcpy(phonemes2,phonemes);
TranslateRules(&word_iz[1], phonemes, N_WORD_PHONEMES, NULL, 0, 0);
}

wflags |= emphasize_allcaps;


/* determine stress pattern for this word */
/******************************************/
@@ -951,7 +980,7 @@ strcpy(phonemes2,phonemes);
{
char *p;
// German, keep a secondary stress on the stem
SetWordStress(phonemes,dictionary_flags,3,0);
SetWordStress(phonemes,dictionary_flags[0],3,0);

// reduce all but the first primary stress
ix=0;
@@ -967,22 +996,22 @@ strcpy(phonemes2,phonemes);
}
strcpy(word_phonemes,prefix_phonemes);
strcat(word_phonemes,phonemes);
SetWordStress(word_phonemes,dictionary_flags,-1,0);
SetWordStress(word_phonemes,dictionary_flags[0],-1,0);
}
else
{
// stress position affects the whole word, including prefix
strcpy(word_phonemes,prefix_phonemes);
strcat(word_phonemes,phonemes);
SetWordStress(word_phonemes,dictionary_flags,-1,prev_last_stress);
SetWordStress(word_phonemes,dictionary_flags[0],-1,prev_last_stress);
}
}
else
{
if(prefix_phonemes[0] == 0)
SetWordStress(phonemes,dictionary_flags,-1,prev_last_stress);
SetWordStress(phonemes,dictionary_flags[0],-1,prev_last_stress);
else
SetWordStress(phonemes,dictionary_flags,-1,0);
SetWordStress(phonemes,dictionary_flags[0],-1,0);
strcpy(word_phonemes,prefix_phonemes);
strcat(word_phonemes,phonemes);
}
@@ -993,26 +1022,23 @@ strcpy(phonemes2,phonemes);
strcat(word_phonemes,end_phonemes);
}

// if(next_pause > 2)
ix = ((dictionary_flags >> 5) & 7); // dictionary indicates skip next word(s)
if(wtab[ix].flags & FLAG_LAST_WORD)
{
// the word has attribute to stress or unstress when at end of clause
if(dictionary_flags & (FLAG_STRESS_END | FLAG_STRESS_END2))
ChangeWordStress(this,word_phonemes,4);
// SetWordStress(word_phonemes,0,4,prev_last_stress);
else
if(dictionary_flags & FLAG_UNSTRESS_END)
ChangeWordStress(this,word_phonemes,3);
// SetWordStress(word_phonemes,0,3,prev_last_stress);
}
if(wflags & FLAG_STRESSED_WORD)
if(wflags & FLAG_EMPHASIZED)
{
// A word is indicated in the source text as stressed

// we need to improve the intonation module to deal better with a clauses tonic
// stress being early in the clause, before enabling this
//SetWordStress(word_phonemes,0,5,prev_last_stress);
ChangeWordStress(this,word_phonemes,6);
}
else
if(wtab[dictionary_skipwords].flags & FLAG_LAST_WORD)
{
// the word has attribute to stress or unstress when at end of clause
if(dictionary_flags[0] & (FLAG_STRESS_END | FLAG_STRESS_END2))
ChangeWordStress(this,word_phonemes,4);
else
if(dictionary_flags[0] & FLAG_UNSTRESS_END)
ChangeWordStress(this,word_phonemes,3);
}

// dictionary flags for this word give a clue about which alternative pronunciations of
@@ -1024,56 +1050,63 @@ strcpy(phonemes2,phonemes);
expect_verb_s = 2;
}

if(dictionary_flags & FLAG_PASTF)
if(dictionary_flags[1] & FLAG_PASTF)
{
/* expect perfect tense in next two words */
expect_past = 3;
expect_verb = 0;
expect_noun = 0;
}
else
if(dictionary_flags & FLAG_VERBF)
if(dictionary_flags[1] & FLAG_VERBF)
{
/* expect a verb in the next word */
expect_verb = 2;
expect_verb_s = 0; /* verb won't have -s suffix */
expect_noun = 0;
}
else
if(dictionary_flags & FLAG_VERBSF)
if(dictionary_flags[1] & FLAG_VERBSF)
{
// expect a verb, must have a -s suffix
expect_verb = 0;
expect_verb_s = 2;
expect_past = 0;
expect_noun = 0;
}
else
if(dictionary_flags & FLAG_NOUNF)
if(dictionary_flags[1] & FLAG_NOUNF)
{
/* not expecting a verb next */
expect_noun = 3;
expect_verb = 0;
expect_verb_s = 0;
expect_past = 0;
}

if((wordx[0] != 0) && (!(dictionary_flags & FLAG_VERB_EXT)))
if((wordx[0] != 0) && (!(dictionary_flags[1] & FLAG_VERB_EXT)))
{
if(expect_verb > 0)
expect_verb -= 1;
expect_verb--;

if(expect_verb_s > 0)
expect_verb_s -= 1;
expect_verb_s--;

if(expect_noun >0)
expect_noun--;

if(expect_past > 0)
expect_past -= 1;
expect_past--;
}

if((word_length == 1) && iswalpha(first_char) && (first_char != 'i'))
{
// English Specific !!!!
// any single letter before a dot is an abbreviation, except 'I'
dictionary_flags |= FLAG_DOT;
dictionary_flags[0] |= FLAG_DOT;
}

return(dictionary_flags);
return(dictionary_flags[0]);
} // end of TranslateWord


@@ -1565,12 +1598,20 @@ static int EmbeddedCommand(unsigned int &source_index)
option_sayas2 = value;
count_sayas_digits = 0;
}
if(cmd == EMBED_F)
{
if(value >= 3)
word_emphasis = FLAG_EMPHASIZED;
else
word_emphasis = 0;
}

embedded_list[embedded_ix++] = cmd + sign + (value << 8);
return(1);
} // end of EmbeddedCommand



int SubstituteChar(Translator *tr, unsigned int c, unsigned int next_in, int *insert)
{//==================================================================================
int ix;
@@ -1752,6 +1793,7 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_
word_flags = 0;
next_word_flags = 0;
expect_verb=0;
expect_noun=0;
expect_past=0;
expect_verb_s=0;
end_stressed_vowel=0;
@@ -2144,7 +2186,7 @@ if((c == '/') && (langopts.testing & 2) && IsDigit09(next_in) && IsAlpha(prev_ou
embedded_count = 0;
}
words[word_count].pre_pause = pre_pause;
words[word_count].flags |= (all_upper_case | word_flags);
words[word_count].flags |= (all_upper_case | word_flags | word_emphasis);
words[word_count].wmark = word_mark;

if(pre_pause > 0)
@@ -2342,6 +2384,7 @@ void InitText(int control)
option_sayas = 0;
option_sayas2 = 0;
option_emphasis = 0;
word_emphasis = 0;

InitText2();


+ 26
- 16
src/translate.h View File

@@ -32,7 +32,7 @@
#define N_LETTER_GROUPS 20


/* flags from word dictionary */
/* dictionary flags, word 1 */
// bits 0-3 stressed syllable, 7=unstressed
#define FLAG_SKIPWORDS 0x80
#define FLAG_PREPAUSE 0x100
@@ -47,7 +47,6 @@
#define FLAG_UNSTRESS_END 0x2000 /* reduce stress at end of clause */
#define FLAG_ATEND 0x4000 /* use this pronunciation if at end of clause */

#define FLAG_CAPITAL 0x8000 /* pronunciation if initial letter is upper case */
#define FLAG_DOT 0x10000 /* ignore '.' after word (abbreviation) */
#define FLAG_ABBREV 0x20000 // spell as letters, even with a vowel, OR use specified pronunciation rather than split into letters
#define FLAG_STEM 0x40000 // must have a suffix
@@ -56,19 +55,27 @@
#define FLAG_ALT_TRANS 0x100000 // language specific
#define FLAG_ALT2_TRANS 0x200000 // language specific

#define FLAG_VERBF 0x400000 /* verb follows */
#define FLAG_VERBSF 0x800000 /* verb follows, may have -s suffix */
#define FLAG_NOUNF 0x1000000 /* noun follows */
#define FLAG_VERB 0x2000000 /* pronunciation for verb */
#define FLAG_PAST 0x4000000 /* pronunciation for past tense */
#define FLAG_PASTF 0x8000000 /* past tense follows */
#define FLAG_VERB_EXT 0x10000000 /* extend the 'verb follows' */

#define FLAG_PAUSE1 0x10000000 // shorter prepause
#define FLAG_TEXTMODE 0x20000000 // word translates to replacement text, not phonemes
#define BITNUM_FLAG_TEXTMODE 29

#define FLAG_PAUSE1 0x40000000 // shorter prepause
#define FLAG_FOUND 0x80000000 /* pronunciation was found in the dictionary list */
#define FLAG_FOUND_ATTRIBUTES 0x40000000 // word was found in the dictionary list (has attributes)
#define FLAG_FOUND 0x80000000 // pronunciation was found in the dictionary list

// dictionary flags, word 2
#define FLAG_VERBF 0x1 /* verb follows */
#define FLAG_VERBSF 0x2 /* verb follows, may have -s suffix */
#define FLAG_NOUNF 0x4 /* noun follows */
#define FLAG_PASTF 0x8 /* past tense follows */
#define FLAG_VERB 0x10 /* pronunciation for verb */
#define FLAG_NOUN 0x20 /* pronunciation for noun */
#define FLAG_PAST 0x40 /* pronunciation for past tense */
#define FLAG_VERB_EXT 0x100 /* extend the 'verb follows' */
#define FLAG_CAPITAL 0x200 /* pronunciation if initial letter is upper case */
#define FLAG_ALLCAPS 0x400 // only if the word is all capitals



// wordflags, flags in source word
#define FLAG_ALL_UPPER 0x1 /* no lower case letters in the word */
@@ -77,15 +84,17 @@
#define FLAG_HAS_PLURAL 0x4 /* upper-case word with s or 's lower-case ending */
#define FLAG_PHONEMES 0x8 /* word is phonemes */
#define FLAG_LAST_WORD 0x10 /* last word in clause */
#define FLAG_STRESSED_WORD 0x20 /* this word has explicit stress */
//#define FLAG_STRESSED_WORD 0x20 /* this word has explicit stress */
#define FLAG_EMBEDDED 0x40 /* word is preceded by embedded commands */
#define FLAG_HYPHEN 0x80
#define FLAG_NOSPACE 0x100 // word is not seperated from previous word by a space
#define FLAG_DONT_SWITCH_TRANSLATOR 0x1000
#define FLAG_SUFFIX_REMOVED 0x2000
#define FLAG_HYPHEN_AFTER 0x4000
#define FLAG_NO_PREFIX 0x8000
#define FLAG_NO_TRACE 0x10000
#define FLAG_EMPHASIZED 0x8000

#define FLAG_NO_TRACE 0x10000 // passed to TranslateRules() to suppress dictionary lookup printout
#define FLAG_NO_PREFIX 0x20000

// prefix/suffix flags (bits 8 to 14, bits 16 to 22) don't use 0x8000, 0x800000
#define SUFX_E 0x0100 // e may have been added
@@ -394,7 +403,7 @@ private:
int ReadClause(FILE *f_in, char *buf, unsigned short *charix, int n_buf);
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);
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);
const char *LookupCharName(int c);
int LookupNum2(int value, int control, char *ph_out);
@@ -424,7 +433,7 @@ protected:
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);
int LookupDictList(char **wordptr, char *ph_out, unsigned int *flags, int end_flags, WORD_TAB *wtab);
int Lookup(const char *word, char *ph_out);

@@ -448,6 +457,7 @@ protected:
int expect_verb;
int expect_past; // expect past tense
int expect_verb_s;
int expect_noun;
int word_flags; // word is all upper case
int prev_last_stress;
int prepause_timeout;

+ 21
- 7
src/voices.cpp View File

@@ -161,6 +161,25 @@ const char *variant_lists[3] = {variants_either, variants_male, variants_female}
voice_t voicedata;
voice_t *voice = &voicedata;

char *fgets_strip(char *buf, int size, FILE *f_in)
{//===============================================
// strip trailing spaces, and truncate lines at // comment
int len;
char *p;

if(fgets(buf,size,f_in) == NULL)
return(NULL);

len = strlen(buf);
while((--len > 0) && isspace(buf[len]))
buf[len] = 0;

if((p = strstr(buf,"//")) != NULL)
*p = 0;

return(buf);
}


void SetToneAdjust(voice_t *voice, int *tone_pts)
{//==============================================
@@ -257,10 +276,8 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*lea
vgender[0] = 0;
age = 0;

while(fgets(linebuf,sizeof(linebuf),f_in) != NULL)
while(fgets_strip(linebuf,sizeof(linebuf),f_in) != NULL)
{
linebuf[strlen(linebuf)-1] = 0;

if(memcmp(linebuf,"name",4)==0)
{
p = &linebuf[4];
@@ -571,11 +588,8 @@ voice_t *LoadVoice(const char *vname, int control)
SelectPhonemeTableName(phonemes_name); // set up phoneme_tab


while((f_voice != NULL) && (fgets(buf,sizeof(buf),f_voice) != NULL))
while((f_voice != NULL) && (fgets_strip(buf,sizeof(buf),f_voice) != NULL))
{
if((p = strstr(buf,"//")) != NULL)
*p = 0;

// isolate the attribute name
for(p=buf; (*p != 0) && !isspace(*p); p++);
*p++ = 0;

+ 1
- 1
src/wavegen.cpp View File

@@ -787,7 +787,7 @@ int GetAmplitude(void)
int amp;

// normal, none, reduced, moderate, strong
static const unsigned char amp_emphasis[5] = {16, 16, 8, 24, 32};
static const unsigned char amp_emphasis[5] = {16, 16, 8, 16, 26};

amp = (embedded_value[EMBED_A])*60/100;
general_amplitude = amp * amp_emphasis[embedded_value[EMBED_F]] / 16;

Loading…
Cancel
Save