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-fd96e6ae7743master
| 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 |
| &) 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 |
| #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 | ||||
| */ | */ |
| 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) |
| 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 | ||||
| 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 | |||||
| } | } | ||||
| } | } | ||||
| 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) |
| 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) |
| #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; |
| 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; |
| 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; |
| 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]; |
| // 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; |
| { | { | ||||
| 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); |
| 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; |