Browse Source

[1.29.25] <emphasis> tag now changes the intonation to emphasize the specified word.

option_emphasize_allcaps in translate.cpp, if set will emphasize words which are all-capitals.
Changed intonation.cpp.
Added an intonation for sentences which end in an exclamation mark.


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

+ 6
- 1
dictsource/en_list View File

genre Z0nr@ genre Z0nr@
genuine dZEnju:In genuine dZEnju:In
geyser gi:z3 geyser gi:z3
gibbon gIb@n
gig gIg gig gIg
gigantic dZaIg'antIk gigantic dZaIg'antIk
gibbon gIb@n
gilead g'IlIad gilead g'IlIad
gimme gImI
giraffe dZI2raaf giraffe dZI2raaf
goin ,goUIn $only // for goin' goin ,goUIn $only // for goin'
goodbye $2 goodbye $2
?!3 rather rA:D3 ?!3 rather rA:D3
ratio reISI2oU ratio reISI2oU
rationale raS@n'al rationale raS@n'al
ravenous rav@n@s
ravine r@vi:n ravine r@vi:n
rawest rO:@st rawest rO:@st
re r,i: re r,i:
reign reIn reign reIn
rein reIn rein reIn
reined reInd reined reInd
reining reInIN
reindeer reIndi@ reindeer reIndi@
reinvent ri:Inv'Ent reinvent ri:Inv'Ent
refinery rI2faIn@rI2 refinery rI2faIn@rI2
(to to) %tU_t@5 $verbf (to to) %tU_t@5 $verbf
(to and fro) tu:@ndfr'oU (to and fro) tu:@ndfr'oU
to tu: $u $atend to tu: $u $atend
to tu: $allcaps




at at $nounf $only $u at at $nounf $only $u
has haz $only $atend has haz $only $atend
(has been) %haz%bIn $pastf (has been) %haz%bIn $pastf
(has to) haztU $atend (has to) haztU $atend
has haz $allcaps
hath %haT $pastf $only hath %haT $pastf $only
had %had $pastf $strend2 $only had %had $pastf $strend2 $only
(had been) %had%bIn $pastf (had been) %had%bIn $pastf

+ 3
- 1
dictsource/en_rules View File

&) hold (_$4 hoUld &) hold (_$4 hoUld
holme hoUm holme hoUm
_) h (our _) h (our
_) h (ono
_) h (onor
_) h (onou
hone (st 0nI hone (st 0nI
_) horri h0rI _) horri h0rI
_) horse hO@s _) horse hO@s
n) o (ta oU n) o (ta oU
n) o (tor oU n) o (tor oU
r) o (ta oU r) o (ta oU
r) o (to oU
t) o (ta oU t) o (ta oU
piv) o (t @ piv) o (t @
o (tat oU o (tat oU

+ 21
- 21
platforms/windows/windows_dll/src/speak_lib.h View File

#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
int espeak_Initialize(espeak_AUDIO_OUTPUT output, int buflength, const char *path, int options);
ESPEAK_API int espeak_Initialize(espeak_AUDIO_OUTPUT output, int buflength, const char *path, int options);
/* Must be called before any synthesis functions are called. /* Must be called before any synthesis functions are called.
output: the audio data can either be played by eSpeak or passed back by the SynthCallback function. output: the audio data can either be played by eSpeak or passed back by the SynthCallback function.


#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
void espeak_SetSynthCallback(t_espeak_callback* SynthCallback);
ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback* SynthCallback);
/* Must be called before any synthesis functions are called. /* Must be called before any synthesis functions are called.
This specifies a function in the calling program which is called when a buffer of This specifies a function in the calling program which is called when a buffer of
speech sound data has been produced. speech sound data has been produced.
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
void espeak_SetUriCallback(int (*UriCallback)(int, const char*, const char*));
ESPEAK_API void espeak_SetUriCallback(int (*UriCallback)(int, const char*, const char*));
/* This function may be called before synthesis functions are used, in order to deal with /* This function may be called before synthesis functions are used, in order to deal with
<audio> tags. It specifies a callback function which is called when an <audio> element is <audio> tags. It specifies a callback function which is called when an <audio> element is
encountered and allows the calling program to indicate whether the sound file which encountered and allows the calling program to indicate whether the sound file which
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_Synth(const void *text,
ESPEAK_API espeak_ERROR espeak_Synth(const void *text,
size_t size, size_t size,
unsigned int position, unsigned int position,
espeak_POSITION_TYPE position_type, espeak_POSITION_TYPE position_type,
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_Synth_Mark(const void *text,
ESPEAK_API espeak_ERROR espeak_Synth_Mark(const void *text,
size_t size, size_t size,
const char *index_mark, const char *index_mark,
unsigned int end_position, unsigned int end_position,
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_Key(const char *key_name);
ESPEAK_API espeak_ERROR espeak_Key(const char *key_name);
/* Speak the name of a keyboard key. /* Speak the name of a keyboard key.
Currently this just speaks the "key_name" as given Currently this just speaks the "key_name" as given


#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_Char(wchar_t character);
ESPEAK_API espeak_ERROR espeak_Char(wchar_t character);
/* Speak the name of the given character /* Speak the name of the given character


Return: EE_OK: operation achieved Return: EE_OK: operation achieved
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative);
ESPEAK_API espeak_ERROR espeak_SetParameter(espeak_PARAMETER parameter, int value, int relative);
/* Sets the value of the specified parameter. /* Sets the value of the specified parameter.
relative=0 Sets the absolute value of the parameter. relative=0 Sets the absolute value of the parameter.
relative=1 Sets a relative value of the parameter. relative=1 Sets a relative value of the parameter.
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
int espeak_GetParameter(espeak_PARAMETER parameter, int current);
ESPEAK_API int espeak_GetParameter(espeak_PARAMETER parameter, int current);
/* current=0 Returns the default value of the specified parameter. /* current=0 Returns the default value of the specified parameter.
current=1 Returns the current value of the specified parameter, as set by SetParameter() current=1 Returns the current value of the specified parameter, as set by SetParameter()
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist);
ESPEAK_API espeak_ERROR espeak_SetPunctuationList(const wchar_t *punctlist);
/* Specified a list of punctuation characters whose names are to be spoken when the /* Specified a list of punctuation characters whose names are to be spoken when the
value of the Punctuation parameter is set to "some". value of the Punctuation parameter is set to "some".


#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
void espeak_SetPhonemeTrace(int value, FILE *stream);
ESPEAK_API void espeak_SetPhonemeTrace(int value, FILE *stream);
/* Controls the output of phoneme symbols for the text /* Controls the output of phoneme symbols for the text
value=0 No phoneme output (default) value=0 No phoneme output (default)
value=1 Output the translated phoneme symbols for the text value=1 Output the translated phoneme symbols for the text
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
void espeak_CompileDictionary(const char *path, FILE *log);
ESPEAK_API void espeak_CompileDictionary(const char *path, FILE *log);
/* Compile pronunciation dictionary for a language which corresponds to the currently /* Compile pronunciation dictionary for a language which corresponds to the currently
selected voice. The required voice should be selected before calling this function. selected voice. The required voice should be selected before calling this function.


#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec);
ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec);
/* Reads the voice files from espeak-data/voices and creates an array of espeak_VOICE pointers. /* Reads the voice files from espeak-data/voices and creates an array of espeak_VOICE pointers.
The list is terminated by a NULL pointer The list is terminated by a NULL pointer


#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_SetVoiceByName(const char *name);
ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name);
/* Searches for a voice with a matching "name" field. Language is not considered. /* Searches for a voice with a matching "name" field. Language is not considered.
"name" is a UTF8 string. "name" is a UTF8 string.


#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_spec);
ESPEAK_API espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_spec);
/* An espeak_VOICE structure is used to pass criteria to select a voice. Any of the following /* An espeak_VOICE structure is used to pass criteria to select a voice. Any of the following
fields may be set: fields may be set:


#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_VOICE *espeak_GetCurrentVoice(void);
ESPEAK_API espeak_VOICE *espeak_GetCurrentVoice(void);
/* Returns the espeak_VOICE data for the currently selected voice. /* Returns the espeak_VOICE data for the currently selected voice.
This is not affected by temporary voice changes caused by SSML elements such as <voice> and <s> This is not affected by temporary voice changes caused by SSML elements such as <voice> and <s>
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_Cancel(void);
ESPEAK_API espeak_ERROR espeak_Cancel(void);
/* Stop immediately synthesis and audio output of the current text. When this /* Stop immediately synthesis and audio output of the current text. When this
function returns, the audio output is fully stopped and the synthesizer is ready to function returns, the audio output is fully stopped and the synthesizer is ready to
synthesize a new message. synthesize a new message.
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
int espeak_IsPlaying(void);
ESPEAK_API int espeak_IsPlaying(void);
/* Returns 1 if audio is played, 0 otherwise. /* Returns 1 if audio is played, 0 otherwise.
*/ */


#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_Synchronize(void);
ESPEAK_API espeak_ERROR espeak_Synchronize(void);
/* This function returns when all data have been spoken. /* This function returns when all data have been spoken.
Return: EE_OK: operation achieved Return: EE_OK: operation achieved
EE_INTERNAL_ERROR. EE_INTERNAL_ERROR.
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
espeak_ERROR espeak_Terminate(void);
ESPEAK_API espeak_ERROR espeak_Terminate(void);
/* last function to be called. /* last function to be called.
Return: EE_OK: operation achieved Return: EE_OK: operation achieved
EE_INTERNAL_ERROR. EE_INTERNAL_ERROR.
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
const char *espeak_Info(void* ptr);
ESPEAK_API const char *espeak_Info(void* ptr);
/* Returns the version number string. /* Returns the version number string.
The parameter is for future use, and should be set to NULL The parameter is for future use, and should be set to NULL
*/ */

+ 3
- 0
src/extras.cpp View File

espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,100,NULL,0); espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,100,NULL,0);
memset(&voicespec,0,sizeof(voicespec)); memset(&voicespec,0,sizeof(voicespec));
voicespec.languages = "de"; voicespec.languages = "de";
voicespec.gender = 2;

espeak_SetVoiceByProperties(&voicespec); espeak_SetVoiceByProperties(&voicespec);
newvoice = espeak_GetCurrentVoice(); newvoice = espeak_GetCurrentVoice();
x = 1; x = 1;
//CharsetToUnicode("ISO-8859-4"); //CharsetToUnicode("ISO-8859-4");
//CharsetToUnicode("ISCII"); //CharsetToUnicode("ISCII");



return; return;


if(control==2) if(control==2)

+ 218
- 295
src/intonation.cpp View File

provide a more flexible intonation system. provide a more flexible intonation system.
*/ */


static int tone_pitch_env; /* used to return pitch envelope */
typedef struct {
char stress;
char env;
char flags; //bit 0=pitch rising, bit1=emnphasized
short pitch1;
short pitch2;
} SYLLABLE;

SYLLABLE syllable_tab[N_PHONEME_LIST];




static int vowel_ix;
static int vowel_ix_top;
static int *vowel_tab;
static int tone_pitch_env; /* used to return pitch envelope */





/* Pitch data for tone types */ /* Pitch data for tone types */
unsigned char tonic_max1; unsigned char tonic_max1;
unsigned char tonic_min1; unsigned char tonic_min1;


unsigned char emph_level;
unsigned char emph_next;

unsigned char pre_start; unsigned char pre_start;
unsigned char pre_end; unsigned char pre_end;


#define N_TONE_TABLE 15 #define N_TONE_TABLE 15


static TONE_TABLE tone_table[N_TONE_TABLE] = { 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},
{PITCHfall, 30, 5, PITCHfall, 30, 8, // statement
20, 25, 34, 22, drops_0, 3, 3, 12, 7, 0},


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

{PITCHfrise, 39,10, PITCHfrise2, 36,10, // question
20, 25, 34, 20, drops_0, 3, 3, 15, 29, 0},


{PITCHdrop, 38, 1, PITCHdrop, 42,25, // exclamation
30, 20,
20, 25, 34, 22, drops_0, 3, 3, 12, 8, 0},
{PITCHfall, 36, 0, PITCHfall, 40, 30, // statement, emphatic
20, 25, 34, 22, drops_0, 3, 3, 20, 4, 0},




#ifdef deleted #ifdef deleted




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








#define SECONDARY 3 #define SECONDARY 3
#define PRIMARY 4 #define PRIMARY 4
#define PRIMARY_STRESSED 5
#define PRIMARY_MARKED 6
#define PRIMARY_STRESSED 6
#define PRIMARY_LAST 7 #define PRIMARY_LAST 7




static int number_body; static int number_body;
static int number_tail; static int number_tail;
static int last_primary; static int last_primary;
static int tone_type;
static int tone_posn; static int tone_posn;
static int annotation;
static int tone_posn2;
static int no_tonic; static int no_tonic;




static void count_pitch_vowels()
/******************************/
static void count_pitch_vowels(int start, int end, int clause_end)
/****************************************************************/
{ {
int ix; int ix;
int stress; int stress;
int max_stress = 0; int max_stress = 0;
int max_stress_posn = 0;
int max_stress_posn = 0; // last syllable ot the highest stress
int max_stress_posn2 = 0; // penuntimate syllable of the highest stress
int last2_primary;


number_pre = -1; /* number of vowels before 1st primary stress */ number_pre = -1; /* number of vowels before 1st primary stress */
number_body = 0; number_body = 0;
number_tail = 0; /* number between tonic syllable and next primary */ number_tail = 0; /* number between tonic syllable and next primary */
last_primary = 0; last_primary = 0;
last2_primary = 0;
for(ix=vowel_ix; ix<vowel_ix_top; ix++)
for(ix=start; ix<end; ix++)
{ {
stress = vowel_tab[ix] & 0x3f; /* marked stress level */
stress = syllable_tab[ix].stress; /* marked stress level */

if(stress >= max_stress) if(stress >= max_stress)
{ {
max_stress = stress;
if(stress > max_stress)
{
max_stress_posn2 = ix;
}
else
{
max_stress_posn2 = max_stress_posn;
}
max_stress_posn = ix; max_stress_posn = ix;
max_stress = stress;
} }
if(stress >= PRIMARY) if(stress >= PRIMARY)
{ {
if(number_pre < 0) if(number_pre < 0)
number_pre = ix;
number_pre = ix - start;


last_primary = ix; last_primary = ix;
} }
if(number_pre < 0) if(number_pre < 0)
number_pre = 0; number_pre = 0;


number_tail = vowel_ix_top - max_stress_posn - 1;
number_tail = end - max_stress_posn - 1;
tone_posn = max_stress_posn; tone_posn = max_stress_posn;
tone_posn = last_primary;
tone_posn2 = max_stress_posn2;


if(no_tonic) if(no_tonic)
{ {
tone_posn = vowel_ix_top;
tone_posn = tone_posn2 = end-1;
} }
else else
// if((last_primary - max_stress_posn) > 2)
if(end == clause_end)
{ {
if(vowel_tab[last_primary] < PRIMARY_MARKED)
vowel_tab[last_primary] = PRIMARY_LAST;
syllable_tab[last_primary].stress = PRIMARY_LAST;
} }
} /* end of count_pitch_vowels */ } /* end of count_pitch_vowels */




while(ix < end_ix) while(ix < end_ix)
{ {
stress = vowel_tab[ix++] & 0x3f;
stress = syllable_tab[ix++].stress;
// if(stress >= PRIMARY_MARKED) // if(stress >= PRIMARY_MARKED)
// break; // break;








static void set_pitch(int ix, int base, int drop)
/***********************************************/
// Set the pitch of a vowel in vowel_tab. Base & drop are Hz * 256
static void set_pitch(SYLLABLE *syl, int base, int drop)
/******************************************************/
// Set the pitch of a vowel in syllable_tab. Base & drop are Hz * 256
{ {
int pitch1, pitch2; int pitch1, pitch2;
int flags = 0; int flags = 0;
int pitch_range2 = 148; int pitch_range2 = 148;
int pitch_base2 = 72; int pitch_base2 = 72;


// fprintf(f_log,"base=%3d,drop=%3d ",base>>8,drop>>8);

// pitch_range2 = pitch_range + 20;
// pitch_base2 = pitch_base - (128-72);

if(base < 0) base = 0; if(base < 0) base = 0;


pitch2 = ((base * pitch_range2 ) >> 15) + pitch_base2; pitch2 = ((base * pitch_range2 ) >> 15) + pitch_base2;


if(drop < 0) if(drop < 0)
{ {
flags = 0x80;
flags = 1;
drop = -drop; drop = -drop;
} }


pitch1 = pitch2 + ((drop * pitch_range2) >> 15); pitch1 = pitch2 + ((drop * pitch_range2) >> 15);
//x = (pitch1 - pitch2) / 4; // TEST
//pitch1 -= x;
//pitch2 += x;


if(pitch1 > 511) pitch1 = 511; if(pitch1 > 511) pitch1 = 511;
if(pitch2 > 511) pitch2 = 511; if(pitch2 > 511) pitch2 = 511;


// fprintf(f_log," %d p1=%3d p2=%3d %x\n",vowel_tab[ix] & 0x3f,pitch1,pitch2,flags);
vowel_tab[ix] = (vowel_tab[ix] & 0x3f) + flags
+ (pitch1 << 8) + (pitch2 << 17);

syl->pitch1 = pitch1;
syl->pitch2 = pitch2;
syl->flags |= flags;
} /* end of set_pitch */ } /* end of set_pitch */






static int calc_pitch_segment(int ix, int end_ix, TONE_TABLE *t, int min_stress)
/******************************************************************************/
static int calc_pitch_segment(int ix, int end_ix, TONE_TABLE *t, int min_stress, int continuing)
/**********************************************************************************************/
/* Calculate pitches until next RESET or tonic syllable, or end. /* Calculate pitches until next RESET or tonic syllable, or end.
Increment pitch if stress is >= min_stress. Increment pitch if stress is >= min_stress.
Used for tonic segment */ Used for tonic segment */
int n_primary=0; int n_primary=0;
int initial; int initial;
int overflow=0; int overflow=0;
int marking=0;
int *drops; int *drops;
short *overflow_tab;
SYLLABLE *syl;


static char overflow_tab[5] = {0, 20, 12, 4, 0};
static short overflow_tab1[5] = {0, 20, 12, 4, 0};
static short continue_tab[5] = {-14, 16, 10, 4, 0};


drops = t->body_drops; drops = t->body_drops;
initial = 1;

if(continuing)
{
initial =0;
overflow = 0;
overflow_tab = continue_tab;
increment = (t->body_end - t->body_start) << 8;
increment = increment / (t->body_max_steps -1);
}
else
{
overflow_tab = overflow_tab1;
initial = 1;
}

while(ix < end_ix) while(ix < end_ix)
{ {
stress = vowel_tab[ix] & 0x3f;
syl = &syllable_tab[ix];
stress = syl->stress;


// if(stress == PRIMARY_MARKED) // if(stress == PRIMARY_MARKED)
// initial = 1; // reset the intonation pattern // initial = 1; // reset the intonation pattern
else else
{ {
pitch = (t->body_end << 8) - (increment * overflow_tab[overflow++])/16; pitch = (t->body_end << 8) - (increment * overflow_tab[overflow++])/16;
if(overflow > 4) overflow = 0;
if(overflow > 4)
{
overflow = 0;
overflow_tab = overflow_tab1;
}
} }
} }


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--; n_primary--;
} }


if((annotation==0) && (stress >= PRIMARY))
{
vowel_tab[ix] = PRIMARY_STRESSED;
set_pitch(ix,pitch,drops[stress]);
}
if(stress >= PRIMARY_MARKED)
if(stress >= PRIMARY)
{ {
vowel_tab[ix] = PRIMARY_MARKED;
set_pitch(ix,pitch,drops[stress]);
syl->stress = PRIMARY_STRESSED;
set_pitch(syl,pitch,drops[stress]);
} }
else else
if(stress >= SECONDARY) if(stress >= SECONDARY)
{ {
/* use secondary stress for unmarked word stress, if no annotation */
set_pitch(ix,pitch,drops[stress]);
set_pitch(syl,pitch,drops[stress]);
} }
else else
{ {
/* unstressed, drop pitch if preceded by PRIMARY */ /* unstressed, drop pitch if preceded by PRIMARY */
if((vowel_tab[ix-1] & 0x3f) >= SECONDARY)
set_pitch(ix,pitch - (t->body_lower_u << 8), drops[stress]);
if((syllable_tab[ix-1].stress & 0x3f) >= SECONDARY)
set_pitch(syl,pitch - (t->body_lower_u << 8), drops[stress]);
else else
set_pitch(ix,pitch,drops[stress]);
set_pitch(syl,pitch,drops[stress]);
} }


ix++; ix++;








static int calc_pitch_segment2(int ix, int end_ix, int start_p, int end_p, int min_stress) static int calc_pitch_segment2(int ix, int end_ix, int start_p, int end_p, int min_stress)
/****************************************************************************************/ /****************************************************************************************/
/* Linear pitch rise/fall, change pitch at min_stress or stronger /* Linear pitch rise/fall, change pitch at min_stress or stronger
int increment; int increment;
int n_increments; int n_increments;
int drop; int drop;
SYLLABLE *syl;


if(ix >= end_ix) if(ix >= end_ix)
return(ix); return(ix);
pitch = start_p << 8; pitch = start_p << 8;
while(ix < end_ix) while(ix < end_ix)
{ {
stress = vowel_tab[ix] & 0x3f;
syl = &syllable_tab[ix];
stress = syl->stress;


if(increment > 0) if(increment > 0)
{ {
set_pitch(ix,pitch,-increment);
set_pitch(syl,pitch,-increment);
pitch += increment; pitch += increment;
} }
else else
drop = min_drop[stress]; drop = min_drop[stress];
pitch += increment; pitch += increment;
set_pitch(ix,pitch,drop);
set_pitch(syl,pitch,drop);
} }
ix++; ix++;






static int calc_pitches(int *syllable_tab, int num, int sentence_tone)
/********************************************************************/
static int calc_pitches(int start, int end, int group_tone)
/**********************************************************/
/* Calculate pitch values for the vowels in this tone group */ /* Calculate pitch values for the vowels in this tone group */
{ {
int ix; int ix;
TONE_TABLE *t; TONE_TABLE *t;
int drop; int drop;
int continuing = 0;

if(start > 0)
continuing = 1;


t = &tone_table[tone_type];
ix = vowel_ix;
t = &tone_table[group_tone];
ix = start;


/* vowels before the first primary stress */ /* vowels before the first primary stress */
/******************************************/ /******************************************/


if(number_pre > 0) if(number_pre > 0)
{ {
ix = calc_pitch_segment2(ix,ix+number_pre,t->pre_start,t->pre_end, 0);
ix = calc_pitch_segment2(ix, ix+number_pre, t->pre_start, t->pre_end, 0);
} }


/* body of tonic segment */ /* body of tonic segment */
/*************************/ /*************************/


if(annotation)
ix = calc_pitch_segment(ix,tone_posn, t, PRIMARY_MARKED);
else
ix = calc_pitch_segment(ix,tone_posn, t, PRIMARY);
if(option_tone2 & 1)
{
static int count=0;
count++;
//if(count & 1)
tone_posn = tone_posn2; // TEST put tone on the penultimate stressed word
}
ix = calc_pitch_segment(ix,tone_posn, t, PRIMARY, continuing);
if(no_tonic) if(no_tonic)
return(0); return(0);
{ {
tone_pitch_env = t->pitch_env0; tone_pitch_env = t->pitch_env0;
drop = t->tonic_max0 - t->tonic_min0; drop = t->tonic_max0 - t->tonic_min0;
set_pitch(ix++,t->tonic_min0 << 8,drop << 8);
set_pitch(&syllable_tab[ix++],t->tonic_min0 << 8,drop << 8);
} }
else else
{ {
tone_pitch_env = t->pitch_env1; tone_pitch_env = t->pitch_env1;
drop = t->tonic_max1 - t->tonic_min1; drop = t->tonic_max1 - t->tonic_min1;
set_pitch(ix++,t->tonic_min1 << 8,drop << 8);
set_pitch(&syllable_tab[ix++],t->tonic_min1 << 8,drop << 8);
} }


syllable_tab[tone_posn].env = tone_pitch_env;
if(syllable_tab[tone_posn].stress == PRIMARY)
syllable_tab[tone_posn].stress = PRIMARY_STRESSED;


/* tail, after the tonic syllable */ /* tail, after the tonic syllable */
/**********************************/ /**********************************/
calc_pitch_segment2(ix,vowel_ix_top,t->tail_start,t->tail_end,0);
calc_pitch_segment2(ix, end, t->tail_start, t->tail_end, 0);


return(tone_pitch_env); return(tone_pitch_env);
} /* end of calc_pitches */ } /* end of calc_pitches */






static int calc_pitch_segmentX(int ix, int end_ix, TONE_TABLE *t, int min_stress)
/******************************************************************************/
/* Calculate pitches until next RESET or tonic syllable, or end.
Increment pitch if stress is >= min_stress.
Used for tonic segment */
// EXPERIMENTAL VERSION
{
int stress;
int pitch=0;
int n_primary;
int initial;
int *drops;

int prev_stress=0;
int n_unstressed;
int j;

drops = t->body_drops; // pitch fall or raise for each stress value

n_primary = count_increments(ix,end_ix,min_stress)-1; // number if primary stress in the clause -1
initial = 1;
while(ix < end_ix) // for each syllable
{
for(j=ix; j<end_ix; j++)
{
// how many unstressed syllables before the next primary stress ?
if((vowel_tab[j] & 0x3f) > SECONDARY)
break;
}
n_unstressed = (j - ix - 1);

stress = vowel_tab[ix] & 0x3f; // stress value of this syllable

pitch = 0x1000; // set a base pitch
pitch += ((n_primary % 3) * 0x0500); // some variety. add an offset that changes after each primary stress

if(stress >= PRIMARY)
{
vowel_tab[ix] = PRIMARY_MARKED;
set_pitch(ix,pitch+0x100, -0x0900);
n_primary--;
}
// else
// if(stress >= SECONDARY)
// {
// set_pitch(ix,pitch,drops[stress]);
// }
else
{
if(ix > 0)
prev_stress = vowel_tab[ix-1] & 0x3f; // stress level of previous syllable

if(prev_stress >= PRIMARY)
{
// an unstressed syllable which follows a primary stress syllable
set_pitch(ix,pitch+0x0200, 0x0800);
}
else
{
stress = 0; // treat secondary stress the same as unstressed ??

set_pitch(ix,pitch + n_unstressed*0x300, drops[stress]);
}
n_unstressed--;
}
ix++;
}
return(ix);
} /* end of calc_pitch_segmentX */



static int calc_pitchesX(int *syllable_tab, int num, int sentence_tone)
/********************************************************************/
/* Calculate pitch values for the vowels in this tone group */
// EXPERMENTAL VERSION of calc_pitches()
{
int ix;
TONE_TABLE *t;
int drop;

t = &tone_table[tone_type];
ix = vowel_ix;


/* body of tonic segment */
/*************************/

if(annotation)
ix = calc_pitch_segmentX(ix,tone_posn, t, PRIMARY_MARKED);
else
ix = calc_pitch_segmentX(ix,tone_posn, t, PRIMARY);
if(no_tonic)
return(0);

/* tonic syllable */
/******************/
if(number_tail == 0)
{
tone_pitch_env = t->pitch_env0;
drop = t->tonic_max0 - t->tonic_min0;
set_pitch(ix++,t->tonic_min0 << 8,drop << 8);
}
else
{
tone_pitch_env = t->pitch_env1;
drop = t->tonic_max1 - t->tonic_min1;
set_pitch(ix++,t->tonic_min1 << 8,drop << 8);
}


/* tail, after the tonic syllable */
/**********************************/
calc_pitch_segment2(ix,vowel_ix_top,t->tail_start,t->tail_end,0);

return(tone_pitch_env);
} /* end of calc_pitchesX */




void Translator::CalcPitches_Tone(int clause_tone) void Translator::CalcPitches_Tone(int clause_tone)
{//=============================================== {//===============================================
p->pitch2 = pitch_adjust + phoneme_tab[tone_ph]->end_type; p->pitch2 = pitch_adjust + phoneme_tab[tone_ph]->end_type;
} }
} }


} // end of Translator::CalcPitches_Tone } // end of Translator::CalcPitches_Tone






void Translator::CalcPitches(int clause_tone)
void Translator::CalcPitches(int clause_type)
{//========================================== {//==========================================
// clause_tone: 0=. 1=, 2=?, 3=! 4=none
// clause_type: 0=. 1=, 2=?, 3=! 4=none
PHONEME_LIST *p; PHONEME_LIST *p;
SYLLABLE *syl;
int ix; int ix;
int x; int x;
int st_ix; int st_ix;
int tonic_ix=0;
int tonic_env;
int max_stress=0;
int n_st;
int option; int option;
int st_ix_changed = -1;
int syllable_tab[N_PHONEME_LIST];
int group_tone;
int group_tone_emph;
int ph_start=0;
int st_start;
int count;
int n_primary;
int count_primary;
int ph_end=n_phoneme_list;


if(langopts.intonation == 1) if(langopts.intonation == 1)
{ {
CalcPitches_Tone(clause_tone);
CalcPitches_Tone(clause_type);
return; return;
} }


st_ix=0;
p = &phoneme_list[0];


for(ix=0; ix<n_phoneme_list; ix++, p++)
option = option_tone1 & 0xf;
if(option > 4)
option = 0;

group_tone_emph = group_tone = punct_to_tone[option][clause_type];
group_tone_emph = punct_to_tone[option][3]; // emphatic form of statement

if(clause_type == 4)
no_tonic = 1; /* incomplete clause, used for abbreviations such as Mr. Dr. Mrs. */
else
no_tonic = 0;

n_st = 0;
n_primary = 0;
for(ix=0; ix<n_phoneme_list; ix++)
{ {
p = &phoneme_list[ix];
if(p->synthflags & SFLAG_SYLLABLE) if(p->synthflags & SFLAG_SYLLABLE)
{ {
syllable_tab[st_ix] = p->tone;

if(option_tone2 == 1)
{
// reduce number of full-stress words
if((p->tone == 4) && ((st_ix % 2) != 1))
{
syllable_tab[st_ix] = 3;
st_ix_changed = st_ix;
}
}
if(option_tone2 == 2)
{
// reduce all full-stress words, except last
if(p->tone == 4)
{
syllable_tab[st_ix] = 3;
st_ix_changed = st_ix;
}
}
syllable_tab[n_st].flags = 0;
syllable_tab[n_st++].stress = p->tone; // stress level


st_ix++;
if(p->tone >= max_stress)
{
max_stress = p->tone;
tonic_ix = ix;
}
if(p->tone >= 4)
n_primary++;
} }
} }
syllable_tab[n_st].stress = 0; // extra 0 entry at the end


if(st_ix_changed >= 0)
syllable_tab[st_ix_changed] = 4;
if(n_st == 0)
return; // nothing to do


if(st_ix == 0)
return; // no vowels, nothing to do
st_start = 0;
count_primary=0;
for(st_ix=0; st_ix<n_st; st_ix++)
{
syl = &syllable_tab[st_ix];


if(syl->stress >= 4)
count_primary++;


option = option_tone1 & 0xf;
if(option > 4)
option = 0;
if((syl->stress == 6) && (syllable_tab[st_ix+1].stress == 6))
{
syllable_tab[st_ix].flags = 2;
syl->stress = 4;
}
if(syl->stress == 6)
{
// an emphasized syllable, end the tone group after the next primary stress
syllable_tab[st_ix].flags = 2;


tone_type = punct_to_tone[option][clause_tone]; /* unless changed by count_pitch_vowels */
count = 0;
if((n_primary - count_primary) > 1)
count =1;


if(clause_tone == 4)
no_tonic = 1; /* incomplete clause, used for abbreviations such as Mr. Dr. Mrs. */
else
no_tonic = 0;
for(ix=st_ix+1; ix<n_st; ix++)
{
if(syllable_tab[ix].stress > 4)
break;
if(syllable_tab[ix].stress == 4)
{
count++;
if(count > 1)
break;
}
}


/* transfer vowel data from ph_list to syllable_tab */
vowel_tab = syllable_tab;
vowel_ix_top = st_ix;
count_pitch_vowels(st_start, ix, n_st);
if((ix < n_st) || (clause_type == 0))
calc_pitches(st_start, ix, group_tone_emph); // split into > 1 tone groups, use emphatic tone
else
calc_pitches(st_start, ix, group_tone);


count_pitch_vowels();
st_start = ix;
}
}


if((option_tone1 & 0xf0)== 0x10)
tonic_env = calc_pitchesX(syllable_tab,st_ix,clause_tone);
else
tonic_env = calc_pitches(syllable_tab,st_ix,clause_tone);
if(st_start < st_ix)
{
count_pitch_vowels(st_start, st_ix, n_st);
calc_pitches(st_start, st_ix, group_tone);
}


// unpack pitch data // unpack pitch data
st_ix=0; st_ix=0;
p = &phoneme_list[0];
for(ix=0; ix<n_phoneme_list; ix++, p++)
for(ix=ph_start; ix < ph_end; ix++)
{ {
p->tone = syllable_tab[st_ix] & 0x3f;
p = &phoneme_list[ix];
p->tone = syllable_tab[st_ix].stress;
if(p->synthflags & SFLAG_SYLLABLE) if(p->synthflags & SFLAG_SYLLABLE)
{ {
x = ((syllable_tab[st_ix] >> 8) & 0x1ff) - 72;
syl = &syllable_tab[st_ix];

x = syl->pitch1 - 72;
if(x < 0) x = 0; if(x < 0) x = 0;
p->pitch1 = x; p->pitch1 = x;


x = ((syllable_tab[st_ix] >> 17) & 0x1ff) - 72;
x = syl->pitch2 - 72;
if(x < 0) x = 0; if(x < 0) x = 0;
p->pitch2 = x; p->pitch2 = x;


p->env = PITCHfall; p->env = PITCHfall;
if(syllable_tab[st_ix] & 0x80)
if(syl->flags & 1)
{ {
// if(p->pitch1 > p->pitch2)
// p->env = PITCHfall;
// else
p->env = PITCHrise;
p->env = PITCHrise;
} }

if(p->pitch1 > p->pitch2) if(p->pitch1 > p->pitch2)
{ {
// swap so that pitch2 is the higher // swap so that pitch2 is the higher
p->pitch1 = p->pitch2; p->pitch1 = p->pitch2;
p->pitch2 = x; p->pitch2 = x;
} }
if(ix==tonic_ix) p->env = tonic_env;
if(p->tone > 5)
p->env = syl->env;

if(syl->flags & 2)
{
p->tone |= 8; // emphasized
}
st_ix++; st_ix++;
} }
} }

} // end of Translator::CalcPitches } // end of Translator::CalcPitches



+ 7
- 1
src/readclause.cpp View File

int punct; int punct;
int any_alnum = 0; int any_alnum = 0;
int self_closing; int self_closing;
int punct_data;
const char *p; const char *p;
char buf2[40]; char buf2[40];
wchar_t xml_buf[N_XML_BUF+1]; wchar_t xml_buf[N_XML_BUF+1];
} }
} }
punct_data = punct_attributes[punct];
if(nl_count > 1) if(nl_count > 1)
{
if((punct_data == CLAUSE_QUESTION) || (punct_data == CLAUSE_EXCLAMATION))
return(punct_data + 35); // with a longer pause
return(CLAUSE_PARAGRAPH); return(CLAUSE_PARAGRAPH);
return(punct_attributes[punct]); // only recognise punctuation if followed by a blank or bracket/quote
}
return(punct_data); // only recognise punctuation if followed by a blank or bracket/quote
} }
} }



+ 14
- 4
src/setlengths.cpp View File

int end_of_clause; int end_of_clause;
int embedded_ix = 0; int embedded_ix = 0;
int min_drop; int min_drop;
int emphasized;
unsigned char *pitch_env=NULL; unsigned char *pitch_env=NULL;


for(ix=1; ix<n_phoneme_list; ix++) for(ix=1; ix<n_phoneme_list; ix++)
{ {
prev = &phoneme_list[ix-1]; prev = &phoneme_list[ix-1];
p = &phoneme_list[ix]; p = &phoneme_list[ix];
stress = p->tone & 0xf;
stress = p->tone & 0x7;
emphasized = p->tone & 0x8;


next = &phoneme_list[ix+1]; next = &phoneme_list[ix+1];


else else
p->amp = stress_amps[stress]; p->amp = stress_amps[stress];


if(emphasized)
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(length_mod < 8) if(length_mod < 8)
length_mod = 8; // restrict how much lengths can be reduced length_mod = 8; // restrict how much lengths can be reduced


if(stress >= 6)
if(stress >= 7)
{ {
// tonic syllable, include a constant component so it doesn't decrease directly with speed // tonic syllable, include a constant component so it doesn't decrease directly with speed
length_mod += 20; length_mod += 20;
} }
else
if(emphasized)
{
length_mod += 20;
}
if((len = stress_lengths[stress]) == 0) if((len = stress_lengths[stress]) == 0)
len = stress_lengths[6]; len = stress_lengths[6];
if(pre_sonorant || pre_voiced) if(pre_sonorant || pre_voiced)
{ {
// set pitch for pre-vocalic part // set pitch for pre-vocalic part
if(pitch_start - last_pitch > 9)
last_pitch = pitch_start - 9;
if(pitch_start - last_pitch > 8) // was 9
last_pitch = pitch_start - 8;
prev->pitch1 = last_pitch; prev->pitch1 = last_pitch;
prev->pitch2 = pitch_start; prev->pitch2 = pitch_start;
if(last_pitch < pitch_start) if(last_pitch < pitch_start)

+ 0
- 5
src/speak.cpp View File

exit(1); 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(option_waveout || quiet)
{ {
if(quiet) if(quiet)

+ 1
- 1
src/synthdata.cpp View File

#include "translate.h" #include "translate.h"
#include "wave.h" #include "wave.h"


const char *version_string = "1.29.24 12.Dec.07";
const char *version_string = "1.29.25 14.Dec.07";
const int version_phdata = 0x012924; const int version_phdata = 0x012924;


int option_device_number = -1; int option_device_number = -1;

+ 1
- 1
src/tr_english.cpp View File

Translator_English::Translator_English() : Translator() Translator_English::Translator_English() : Translator()
{//=================================== {//===================================
// static int stress_lengths2[8] = {182,140, 220,220, 220,240, 248,270}; // static int stress_lengths2[8] = {182,140, 220,220, 220,240, 248,270};
static const short stress_lengths2[8] = {182,140, 220,220, 248,248, 275,275};
static const short stress_lengths2[8] = {182,140, 220,220, 0,0, 248,275};


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

+ 43
- 42
src/tr_languages.cpp View File



case L('c','y'): // Welsh case L('c','y'): // Welsh
{ {
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
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


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_cy,stress_amps_cy); SetupTranslator(tr,stress_lengths_cy,stress_amps_cy);


case L('d','e'): case L('d','e'):
{ {
static const short stress_lengths_de[8] = {150,130, 190,190, 260, 260, 275,275};
static const short stress_lengths_de[8] = {150,130, 190,190, 0, 0, 260,275};
tr = new Translator(); 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
case L('e','l'): // Greek case L('e','l'): // Greek
case L_grc: // Ancient Greek case L_grc: // Ancient Greek
{ {
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
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


// character codes offset by 0x380 // 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}; 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};


case L('e','o'): case L('e','o'):
{ {
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 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 wchar_t eo_char_apostrophe[2] = {'l',0}; static const wchar_t eo_char_apostrophe[2] = {'l',0};
tr = new Translator(); tr = new Translator();


case L('e','s'): // Spanish case L('e','s'): // Spanish
{ {
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
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


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_es,stress_amps_es); SetupTranslator(tr,stress_lengths_es,stress_amps_es);


case L('f','i'): // Finnish case L('f','i'): // Finnish
{ {
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 };
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};


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_fi,stress_amps_fi); SetupTranslator(tr,stress_lengths_fi,stress_amps_fi);


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


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


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_hi,stress_amps_hi); SetupTranslator(tr,stress_lengths_hi,stress_amps_hi);
case L('b','s'): // Bosnian case L('b','s'): // Bosnian
case L('s','r'): // Serbian case L('s','r'): // Serbian
{ {
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};
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};


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_hr,stress_amps_hr); SetupTranslator(tr,stress_lengths_hr,stress_amps_hr);


case L('h','u'): // Hungarian case L('h','u'): // Hungarian
{ {
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};
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};


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_hu,stress_amps_hu); SetupTranslator(tr,stress_lengths_hu,stress_amps_hu);


case L('i','s'): // Icelandic case L('i','s'): // Icelandic
{ {
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 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 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(); tr = new Translator();


case L('i','t'): // Italian case L('i','t'): // Italian
{ {
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 };
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 };


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_it,stress_amps_it); SetupTranslator(tr,stress_lengths_it,stress_amps_it);
{ {
static wchar_t vowels_cyrillic[] = {0x440, // also include 'р' [R] 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}; 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,21 };
static const short stress_lengths_mk[8] = {180,160, 200,200, 220,220, 230,230};
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};


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_mk,stress_amps_mk); SetupTranslator(tr,stress_lengths_mk,stress_amps_mk);


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


tr->langopts.stress_rule = 0; tr->langopts.stress_rule = 0;


case L('n','o'): // Norwegian case L('n','o'): // Norwegian
{ {
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 };
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};
tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_no,stress_amps_no); SetupTranslator(tr,stress_lengths_no,stress_amps_no);




case L('p','l'): // Polish case L('p','l'): // Polish
{ {
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
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


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_pl,stress_amps_pl); SetupTranslator(tr,stress_lengths_pl,stress_amps_pl);


case L('p','t'): // Portuguese case L('p','t'): // Portuguese
{ {
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
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
tr = new Translator(); 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


case L('r','o'): // Romanian case L('r','o'): // Romanian
{ {
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 };
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 };


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_ro,stress_amps_ro); SetupTranslator(tr,stress_lengths_ro,stress_amps_ro);
case L('s','k'): // Slovak case L('s','k'): // Slovak
case L('c','s'): // Czech 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 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"; static const char *sk_voiced = "bdgjlmnrvwzaeiouy";


tr = new Translator(); tr = new Translator();


case L('s','v'): // Swedish 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 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(); 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 = 0x1109; tr->langopts.numbers = 0x1109;
} }
break; break;


case L('s','w'): // Swahili case L('s','w'): // Swahili
{ {
static const short stress_lengths_sw[8] = {150, 160, 190, 190, 300, 300, 320, 320};
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,24, 24,22 }; static const unsigned char stress_amps_sw[] = {16,12, 19,19, 20,24, 24,22 };
tr = new Translator(); tr = new Translator();


case L('t','r'): // Turkish case L('t','r'): // Turkish
{ {
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 };
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};


tr = new Translator(); tr = new Translator();
SetupTranslator(tr,stress_lengths_tr,stress_amps_tr); SetupTranslator(tr,stress_lengths_tr,stress_amps_tr);


case L('v','i'): // Vietnamese case L('v','i'): // Vietnamese
{ {
static const short stress_lengths_vi[8] = {150, 150, 180, 180, 220, 220, 280, 280};
static const short stress_lengths_vi[8] = {150, 150, 180, 180, 210, 220, 220, 280};
static const unsigned char stress_amps_vi[] = {16,16, 16,16, 24,24, 24,22 }; static const unsigned char stress_amps_vi[] = {16,16, 16,16, 24,24, 24,22 };
static wchar_t vowels_vi[] = { static wchar_t vowels_vi[] = {
0x61, 0xe0, 0xe1, 0x1ea3, 0xe3, 0x1ea1, // a 0x61, 0xe0, 0xe1, 0x1ea3, 0xe3, 0x1ea1, // a
case L('z','h'): case L('z','h'):
case L_zhy: case L_zhy:
{ {
static const short stress_lengths_zh[8] = {230,150, 230,230, 230,230, 250,250};
static const short stress_lengths_zh[8] = {230,150, 230,230, 230,0, 230,250};
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; tr = new Translator;


Translator_Russian::Translator_Russian() : Translator() 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 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 // character codes offset by 0x420
{//========================================= {//=========================================
// Initialise options for this language // Initialise options for this language


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

+ 11
- 13
src/translate.cpp View File

int option_sayas = 0; int option_sayas = 0;
int option_sayas2 = 0; // used in translate_clause() int option_sayas2 = 0; // used in translate_clause()
int option_emphasis = 0; // 0=normal, 1=normal, 2=weak, 3=moderate, 4=strong 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_emphasize_allcaps = 0;
int option_ssml = 0; int option_ssml = 0;
int option_phoneme_input = 1; // allow [[phonemes]] in input int option_phoneme_input = 1; // allow [[phonemes]] in input
int clause_start_char; int clause_start_char;
int clause_start_word; int clause_start_word;
int new_sentence; int new_sentence;
int word_emphasis = 0; // set if emphasis level 3 or 4


int prev_clause_pause=0; int prev_clause_pause=0;
int max_clause_pause = 0; int max_clause_pause = 0;


/* index by 0=. 1=, 2=?, 3=! 4=none */ /* index by 0=. 1=, 2=?, 3=! 4=none */
static unsigned char punctuation_to_tone[4][5] = { static unsigned char punctuation_to_tone[4][5] = {
{0,1,1,2,0},
{3,4,4,5,3},
{6,7,7,8,6},
{9,10,10,11,9} };

{0,1,2,3,0},
{0,1,2,3,0},
{0,1,2,3,0},
{0,1,2,3,0} };




void SetLengthMods(Translator *tr, int value) void SetLengthMods(Translator *tr, int value)
{//===================== {//=====================
int ix; int ix;
static const unsigned char stress_amps2[] = {16,16, 20,20, 20,24, 24,21 }; static const unsigned char stress_amps2[] = {16,16, 20,20, 20,24, 24,21 };
static const short stress_lengths2[8] = {182,140, 220,220, 250,260, 280,280};
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 empty_wstring[1] = {0};


charset_a0 = charsets[1]; // ISO-8859-1, this is for when the input is not utf8 charset_a0 = charsets[1]; // ISO-8859-1, this is for when the input is not utf8
langopts.decimal_sep = '.'; langopts.decimal_sep = '.';


memcpy(punct_to_tone,punctuation_to_tone,sizeof(punct_to_tone)); memcpy(punct_to_tone,punctuation_to_tone,sizeof(punct_to_tone));
punct_to_tone[0][3] = 0; // exclamation, use period until we can improve the exclamation intonation
// punct_to_tone[0][3] = 0; // exclamation, use period until we can improve the exclamation intonation
} }




if(wflags & FLAG_EMPHASIZED) if(wflags & FLAG_EMPHASIZED)
{ {
// A word is indicated in the source text as stressed // 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
// Give it stress level 6 (for the intonation module)
ChangeWordStress(this,word_phonemes,6); ChangeWordStress(this,word_phonemes,6);
dictionary_flags[0] |= FLAG_PAUSE1; // precede by short pause
} }
else else
if(wtab[dictionary_skipwords].flags & FLAG_LAST_WORD) if(wtab[dictionary_skipwords].flags & FLAG_LAST_WORD)
} }
} }


if((option_emphasis >= 3) && (pre_pause < 2))
pre_pause = 2;
if((option_emphasis >= 3) && (pre_pause < 1))
pre_pause = 1;
} }


plist2 = &ph_list2[n_ph_list2]; plist2 = &ph_list2[n_ph_list2];

+ 11
- 1
src/translate.h View File

// 1=remove [:] from unstressed syllables, 2= remove from unstressed or non-penultimate syllables // 1=remove [:] from unstressed syllables, 2= remove from unstressed or non-penultimate syllables
// bit 4=0, if stress < 4, bit 4=1, if not the highest stress in the word // bit 4=0, if stress < 4, bit 4=1, if not the highest stress in the word
#define LOPT_IT_LENGTHEN 2 #define LOPT_IT_LENGTHEN 2

// 1=german // 1=german
#define LOPT_PREFIXES 3 #define LOPT_PREFIXES 3

// non-zero, change voiced/unoiced to match last consonant in a cluster // non-zero, change voiced/unoiced to match last consonant in a cluster
// bit 1=LANG=ru, don't propagate over [v] // bit 1=LANG=ru, don't propagate over [v]
// bit 2=don't propagate acress word boundaries // bit 2=don't propagate acress word boundaries
// bit 3=LANG=pl, propagate over liquids and nasals // bit 3=LANG=pl, propagate over liquids and nasals
#define LOPT_REGRESSIVE_VOICING 4 #define LOPT_REGRESSIVE_VOICING 4

// 0=default, 1=no check, other allow this character as an extra initial letter (default is 's') // 0=default, 1=no check, other allow this character as an extra initial letter (default is 's')
#define LOPT_UNPRONOUNCABLE 5 #define LOPT_UNPRONOUNCABLE 5

// select length_mods tables, (length_mod_tab) + (length_mod_tab0 * 100) // select length_mods tables, (length_mod_tab) + (length_mod_tab0 * 100)
#define LOPT_LENGTH_MODS 6 #define LOPT_LENGTH_MODS 6

// increase this to prevent sonorants being shortened before shortened (eg. unstressed) vowels // increase this to prevent sonorants being shortened before shortened (eg. unstressed) vowels
#define LOPT_SONORANT_MIN 7 #define LOPT_SONORANT_MIN 7

// bit 0=Italian "syntactic doubling" of consoants in the word after a word marked with $double attribute // bit 0=Italian "syntactic doubling" of consoants in the word after a word marked with $double attribute
// bit 1=also after a word which ends with a stressed vowel // bit 1=also after a word which ends with a stressed vowel
#define LOPT_IT_DOUBLING 8 #define LOPT_IT_DOUBLING 8

// max. amplitude for vowel at the end of a clause // max. amplitude for vowel at the end of a clause
#define LOPT_MAXAMP_EOC 9 #define LOPT_MAXAMP_EOC 9

// bit 0=reduce even if phonemes are specified in the **_list file // bit 0=reduce even if phonemes are specified in the **_list file
// bit 1=don't reduce the strongest vowel in a word which is marked 'unstressed' // bit 1=don't reduce the strongest vowel in a word which is marked 'unstressed'
#define LOPT_REDUCE 10 #define LOPT_REDUCE 10

// LANG=cs,sk combine some prepositions with the following word, if the combination has N or fewer syllables // LANG=cs,sk combine some prepositions with the following word, if the combination has N or fewer syllables
// bits 0-3 N syllables // bits 0-3 N syllables
// bit 4=only if the second word has $alt attribute // bit 4=only if the second word has $alt attribute
// bit 5=not if the second word is end-of-sentence // bit 5=not if the second word is end-of-sentence
#define LOPT_COMBINE_WORDS 11 #define LOPT_COMBINE_WORDS 11

// change [t] when followed by unstressed vowel // change [t] when followed by unstressed vowel
#define LOPT_REDUCE_T 12 #define LOPT_REDUCE_T 12


char spelling_stress; // 0=default, 1=stress first letter char spelling_stress; // 0=default, 1=stress first letter
char tone_numbers; char tone_numbers;
char ideographs; // treat as separate words char ideographs; // treat as separate words
char textmode; // the meaning of FLAG_TEXTMODE is reversed
char textmode; // the meaning of FLAG_TEXTMODE is reversed (to save data when *_list file is compiled)
int testing; // testing options: bit 1= specify stressed syllable in the form: "outdoor/2" int testing; // testing options: bit 1= specify stressed syllable in the form: "outdoor/2"
const unsigned int *replace_chars; // characters to be substitutes const unsigned int *replace_chars; // characters to be substitutes
} LANGUAGE_OPTIONS; } LANGUAGE_OPTIONS;

+ 1
- 1
src/voices.cpp View File

{ {
variant_name = ExtractVoiceVariantName(NULL,vp->variant); variant_name = ExtractVoiceVariantName(NULL,vp->variant);
sprintf(voice_id,"%s+%s",vp->identifier,&variant_name[3]); sprintf(voice_id,"%s+%s",vp->identifier,&variant_name[3]);
return(variant_name);
return(voice_id);
} }


return(vp->identifier); return(vp->identifier);

+ 1
- 1
src/wavegen.cpp View File

int amp; int amp;


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


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

Loading…
Cancel
Save