[1.39.36]

*_list files: add attribute $max3 to limit repetitions of a symbol to 3.
-v command option, if the voice-name is not found, lookup using it as a language name.
Windows: allow longer path names for espeak-data.
-m option: Ignore text within <script> and <style> tags.
Reduce default pitch to 80-117.
WavegenCloseSound() check if there remain items to be spoken and re-open the sound channel.
Reduce voicing before voiced plosives.
Corrections to mbrola translation for lang=hi.


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@205 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
jonsd
2008-12-03 16:57:41 +00:00
parent 04fa12b60c
commit f90a4e369e
67 changed files with 1236 additions and 985 deletions
+3 -1
View File
@@ -297,7 +297,8 @@ static keywtab_t keywords[] = {
{"f4", 0x300000a},
{"paus", 0x300000b},
{"colr=",0x300000c},
{"amp=", 0x300000d},
{"amp=", 0x300000d}, // set rms of 1st frame as fraction of rms of 2nd frame (1/30ths)
{"", -1}
};
@@ -1286,6 +1287,7 @@ void Compile::VowelTransition(int which, unsigned int *trans)
vcolour = NextItem(tNUMBER);
break;
case 13:
// set rms of 1st frame as fraction of rms of 2nd frame (1/30ths)
rms = (Range(NextItem(tNUMBER), 1, 0, 31) & 0x1f) | 0x20;
flags |= 1;
break;
+1
View File
@@ -90,6 +90,7 @@ MNEM_TAB mnem_flags[] = {
{"$alt2", 21},
{"$max3", 27}, // limit to 3 repetitions
{"$brk", 28}, // a shorter $pause
{"$text", 29}, // word translates to replcement text, not phonemes
+51 -1
View File
@@ -684,6 +684,7 @@ int Translator::IsLetterGroup(char *word, int group, int pre)
// match the word against a list of utf-8 strings
char *p;
char *w;
int len;
p = letterGroups[group];
if(p == NULL)
@@ -691,14 +692,26 @@ int Translator::IsLetterGroup(char *word, int group, int pre)
while(*p != RULE_GROUP_END)
{
w = word;
if(pre)
{
len = strlen(p);
w = word - len + 1;
}
else
{
w = word;
}
while(*p == *w)
{
w++;
p++;
}
if(*p == 0)
{
if(pre)
return(len);
return(w-word); // matched a complete string
}
while(*p++ != 0); // skip to end of string
}
@@ -1023,6 +1036,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int
unsigned char vowel_stress[N_WORD_PHONEMES/2];
char syllable_weight[N_WORD_PHONEMES/2];
char vowel_length[N_WORD_PHONEMES/2];
unsigned char phonetic[N_WORD_PHONEMES];
static char consonant_types[16] = {0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0};
@@ -1079,6 +1093,7 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int
// long vowel, increase syllable weight
weight++;
}
vowel_length[ix] = weight;
if(lengthened) p++; // advance over phonLENGTHEN
@@ -1150,6 +1165,14 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int
}
}
}
if(langopts.stress_flags & 0x80000)
{
// stress on last syllable if it has a long vowel, but previous syllable has a short vowel
if(vowel_length[vowel_count - 1] > vowel_length[vowel_count - 2])
{
stressed_syllable = vowel_count - 1;
}
}
if(vowel_stress[stressed_syllable] == 1)
{
@@ -2547,6 +2570,10 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char
}
p += (wc_bytes-1);
}
else
{
phonemes_repeat_count = 0;
}
}
}
@@ -2590,6 +2617,7 @@ int Translator::TranslateRules(char *p_start, char *phonemes, int ph_size, char
// any language specific changes ?
ApplySpecialAttribute(phonemes,dict_flags0);
memcpy(p_start,word_copy,strlen(word_copy));
return(0);
} /* end of TranslateRules */
@@ -3127,6 +3155,28 @@ int Translator::LookupDictList(char **wordptr, char *ph_out, unsigned int *flags
found = LookupDict2(word, word1, ph_out, flags, end_flags, wtab);
if(flags[0] & FLAG_MAX3)
{
if(strcmp(ph_out, phonemes_repeat) == 0)
{
phonemes_repeat_count++;
if(phonemes_repeat_count > 3)
{
ph_out[0] = 0;
}
}
else
{
strncpy0(phonemes_repeat, ph_out, sizeof(phonemes_repeat));
phonemes_repeat_count = 1;
}
}
else
{
phonemes_repeat_count = 0;
}
if((found == 0) && (flags[1] & FLAG_ACCENT))
{
int letter;
+10 -4
View File
@@ -324,7 +324,7 @@ int main (int argc, char **argv)
FILE *f_text=NULL;
char *p_text=NULL;
FILE *f_phonemes_out = stderr;
FILE *f_phonemes_out = stdout;
char *data_path = NULL; // use default path for espeak-data
int option_index = 0;
@@ -345,7 +345,8 @@ int main (int argc, char **argv)
int option_linelength = 0;
int option_waveout = 0;
char filename[120];
espeak_VOICE voice_select;
char filename[200];
char voicename[40];
char voice_mbrola[20];
char dictname[40];
@@ -529,8 +530,13 @@ int main (int argc, char **argv)
if(espeak_SetVoiceByName(voicename) != EE_OK)
{
fprintf(stderr,"%svoice '%s'\n",err_load,voicename);
exit(2);
memset(&voice_select,0,sizeof(voice_select));
voice_select.languages = voicename;
if(espeak_SetVoiceByProperties(&voice_select) != EE_OK)
{
fprintf(stderr,"%svoice '%s'\n",err_load,voicename);
exit(2);
}
}
if(flag_compile)
+30 -9
View File
@@ -79,8 +79,6 @@ const unsigned short punct_chars[] = {',','.','?','!',':',';',
0x037e, // Greek question mark (looks like semicolon)
0x0387, // Greek semicolon, ano teleia
0x0964, // Devanagari Danda (fullstop)
0x3001, // ideograph comma
0x3002, // ideograph period
0x0589, // Armenian period
0x055d, // Armenian comma
@@ -88,6 +86,17 @@ const unsigned short punct_chars[] = {',','.','?','!',':',';',
0x055e, // Armenian question
0x055b, // Armenian emphasis mark
0x1362, // Ethiopic period
0x1363,
0x1364,
0x1365,
0x1366,
0x1367,
0x1368,
0x3001, // ideograph comma
0x3002, // ideograph period
0xff01, // fullwidth exclamation
0xff0c, // fullwidth comma
0xff0e, // fullwidth period
@@ -109,8 +118,6 @@ static const unsigned int punct_attributes [] = { 0,
CLAUSE_QUESTION, // Greek question mark
CLAUSE_SEMICOLON, // Greek semicolon
CLAUSE_PERIOD+0x8000, // Devanagari Danda (fullstop)
CLAUSE_COMMA+0x8000, // ideograph comma
CLAUSE_PERIOD+0x8000, // ideograph period
CLAUSE_PERIOD+0x8000, // Armenian period
CLAUSE_COMMA, // Armenian comma
@@ -118,6 +125,17 @@ static const unsigned int punct_attributes [] = { 0,
CLAUSE_QUESTION + PUNCT_IN_WORD, // Armenian question
CLAUSE_PERIOD + PUNCT_IN_WORD, // Armenian emphasis mark
CLAUSE_PERIOD, // Ethiopic period
CLAUSE_COMMA, // Ethiopic comma
CLAUSE_SEMICOLON, // Ethiopic semicolon
CLAUSE_COLON, // Ethiopic colon
CLAUSE_COLON, // Ethiopic preface colon
CLAUSE_QUESTION, // Ethiopic question mark
CLAUSE_PERIOD, // Ethiopic paragraph
CLAUSE_COMMA+0x8000, // ideograph comma
CLAUSE_PERIOD+0x8000, // ideograph period
CLAUSE_EXCLAMATION+0x8000, // fullwidth
CLAUSE_COMMA+0x8000,
CLAUSE_PERIOD+0x8000,
@@ -865,7 +883,7 @@ int Translator::AnnouncePunctuation(int c1, int c2, char *buf, int bufix)
#define SSML_AUDIO 11
#define SSML_EMPHASIS 12
#define SSML_BREAK 13
#define SSML_METADATA 14
#define SSML_IGNORE_TEXT 14
#define HTML_BREAK 15
#define SSML_CLOSE 0x10 // for a closing tag, OR this with the tag type
@@ -887,7 +905,7 @@ MNEM_TAB ssmltags[] = {
{"audio", SSML_AUDIO},
{"emphasis", SSML_EMPHASIS},
{"break", SSML_BREAK},
{"metadata", SSML_METADATA},
{"metadata", SSML_IGNORE_TEXT},
{"br", HTML_BREAK},
{"li", HTML_BREAK},
@@ -898,6 +916,8 @@ MNEM_TAB ssmltags[] = {
{"h3", SSML_PARAGRAPH},
{"h4", SSML_PARAGRAPH},
{"hr", SSML_PARAGRAPH},
{"script", SSML_IGNORE_TEXT},
{"style", SSML_IGNORE_TEXT},
{NULL,0}};
@@ -911,6 +931,7 @@ static const char *VoiceFromStack()
SSML_STACK *sp;
const char *v_id;
int voice_name_specified;
int voice_found;
espeak_VOICE voice_select;
char voice_name[40];
char language[40];
@@ -952,7 +973,7 @@ static const char *VoiceFromStack()
voice_select.name = voice_name;
voice_select.languages = language;
v_id = SelectVoice(&voice_select);
v_id = SelectVoice(&voice_select, &voice_found);
if(v_id == NULL)
return("default");
return(v_id);
@@ -1625,12 +1646,12 @@ static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int &outix, int n_outb
}
break;
case SSML_METADATA:
case SSML_IGNORE_TEXT:
ignore_text = 1;
break;
case SSML_SUB + SSML_CLOSE:
case SSML_METADATA + SSML_CLOSE:
case SSML_IGNORE_TEXT + SSML_CLOSE:
ignore_text = 0;
break;
+12 -5
View File
@@ -447,7 +447,7 @@ static void StopSpeak(int unused)
static int optional_argument;
static const char *arg_opts = "afklpsvw"; // which options have arguments
static char *opt_string="";
#define no_argument 0
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#endif
@@ -494,7 +494,8 @@ int main (int argc, char **argv)
int flag_stdin = 0;
int flag_compile = 0;
int pitch_adjustment = 50;
char filename[120];
espeak_VOICE voice_select;
char filename[200];
char voicename[40];
char dictname[40];
@@ -510,10 +511,11 @@ int main (int argc, char **argv)
option_endpause = 1;
option_phoneme_input = 1;
option_multibyte = espeakCHARS_AUTO; // auto
f_trans = stderr;
f_trans = stdout;
#ifdef NEED_GETOPT
optind = 1;
opt_string = "";
while(optind < argc)
{
int len;
@@ -735,8 +737,13 @@ int main (int argc, char **argv)
if(SetVoiceByName(voicename) != EE_OK)
{
fprintf(stderr,"%svoice '%s'\n",err_load,voicename);
exit(2);
memset(&voice_select,0,sizeof(voice_select));
voice_select.languages = voicename;
if(SetVoiceByProperties(&voice_select) != EE_OK)
{
fprintf(stderr,"%svoice '%s'\n",err_load,voicename);
exit(2);
}
}
SetParameter(espeakRATE,speed,0);
+7 -4
View File
@@ -911,10 +911,12 @@ ESPEAK_API espeak_ERROR espeak_Char(wchar_t character)
ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name)
{//===================================================
{//============================================================
ENTER("espeak_SetVoiceByName");
#ifdef USE_ASYNC
//#ifdef USE_ASYNC
// I don't think there's a need to queue change voice requests
#ifdef deleted
espeak_ERROR a_error;
if(synchronous_mode)
@@ -937,10 +939,11 @@ ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name)
ESPEAK_API espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_selector)
{//=====================================================================
{//==============================================================================
ENTER("espeak_SetVoiceByProperties");
#ifdef USE_ASYNC
//#ifdef USE_ASYNC
#ifdef deleted
espeak_ERROR a_error;
if(synchronous_mode)
+1 -1
View File
@@ -35,7 +35,7 @@
#include "translate.h"
#include "wave.h"
const char *version_string = "1.39.29 23.Nov.08";
const char *version_string = "1.39.36 03.Dec.08";
const int version_phdata = 0x013900;
int option_device_number = -1;
+31 -21
View File
@@ -123,7 +123,7 @@ Translator *SelectTranslator(const char *name)
int name2 = 0;
Translator *tr;
static const unsigned char stress_amps_sk[8] = {16,16, 20,20, 20,24, 24,22 };
static const unsigned char stress_amps_sk[8] = {17,17, 20,20, 20,24, 24,22 };
static const short stress_lengths_sk[8] = {190,190, 210,210, 0,0, 210,210};
// convert name string into a word of up to 4 characters, for the switch()
@@ -198,10 +198,9 @@ Translator *SelectTranslator(const char *name)
case L('d','a'): // Danish
{
static const unsigned char stress_amps_da[] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_da[8] = {160,140, 200,200, 0,0, 220,210};
tr = new Translator();
SetupTranslator(tr,stress_lengths_da,stress_amps_da);
SetupTranslator(tr,stress_lengths_da,NULL);
tr->langopts.stress_rule = 0;
SetLetterVowel(tr,'y');
@@ -365,6 +364,16 @@ Translator *SelectTranslator(const char *name)
}
break;
#ifdef deleted
case L('g','a'): // Irish Gaelic
{
tr = new Translator();
tr->langopts.stress_rule = 1;
}
break;
#endif
case L('h','i'): // Hindi
case L('n','e'): // Nepali
{
@@ -390,7 +399,7 @@ Translator *SelectTranslator(const char *name)
case L('b','s'): // Bosnian
case L('s','r'): // Serbian
{
static const unsigned char stress_amps_hr[8] = {16,16, 20,20, 20,24, 24,22 };
static const unsigned char stress_amps_hr[8] = {17,17, 20,20, 20,24, 24,22 };
static const short stress_lengths_hr[8] = {180,160, 200,200, 0,0, 220,230};
static const short stress_lengths_sr[8] = {160,150, 200,200, 0,0, 250,260};
@@ -476,12 +485,11 @@ SetLengthMods(tr,3); // all equal
case L('i','s'): // Icelandic
{
static const unsigned char stress_amps_is[] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_is[8] = {180,160, 200,200, 0,0, 240,250};
static const wchar_t is_lettergroup_B[] = {'c','f','h','k','p','t','x',0xfe,0}; // voiceless conants, including 'þ' ?? 's'
tr = new Translator();
SetupTranslator(tr,stress_lengths_is,stress_amps_is);
SetupTranslator(tr,stress_lengths_is,NULL);
tr->langopts.stress_rule = 0;
tr->langopts.stress_flags = 0x10;
tr->langopts.param[LOPT_IT_LENGTHEN] = 0x11; // remove lengthen indicator from unstressed vowels
@@ -499,8 +507,8 @@ SetLengthMods(tr,3); // all equal
case L('i','t'): // Italian
{
static const short stress_lengths_it[8] = {150, 140, 180, 180, 0, 0, 270, 320};
static const unsigned char stress_amps_it[8] = {15,14, 19,19, 20,24, 24,22 };
static const short stress_lengths_it[8] = {150, 140, 170, 170, 0, 0, 300, 330};
static const unsigned char stress_amps_it[8] = {15,14, 19,19, 20,22, 22,20 };
tr = new Translator();
SetupTranslator(tr,stress_lengths_it,stress_amps_it);
@@ -606,7 +614,7 @@ SetLengthMods(tr,3); // all equal
{
static wchar_t vowels_cyrillic[] = {0x440, // also include 'р' [R]
0x430,0x435,0x438,0x439,0x43e,0x443,0x44b,0x44d,0x44e,0x44f,0x450,0x451,0x456,0x457,0x45d,0x45e,0};
static const unsigned char stress_amps_mk[8] = {16,16, 20,20, 20,24, 24,22 };
static const unsigned char stress_amps_mk[8] = {17,17, 20,20, 20,24, 24,22 };
static const short stress_lengths_mk[8] = {180,160, 200,200, 0,0, 220,230};
tr = new Translator();
@@ -639,10 +647,9 @@ SetLengthMods(tr,3); // all equal
case L('n','o'): // Norwegian
{
static const unsigned char stress_amps_no[] = {16,16, 20,20, 20,24, 24,22 };
static const short stress_lengths_no[8] = {160,140, 200,200, 0,0, 220,210};
tr = new Translator();
SetupTranslator(tr,stress_lengths_no,stress_amps_no);
SetupTranslator(tr,stress_lengths_no,NULL);
tr->langopts.stress_rule = 0;
SetLetterVowel(tr,'y');
@@ -652,12 +659,13 @@ SetLengthMods(tr,3); // all equal
case L('o','m'):
{
static const unsigned char stress_amps_om[] = {16,16, 20,20, 20,24, 24,22 };
static const unsigned char stress_amps_om[] = {18,15, 20,20, 20,22, 22,22 };
static const short stress_lengths_om[8] = {200,200, 200,200, 0,0, 200,200};
tr = new Translator();
SetupTranslator(tr,stress_lengths_om,stress_amps_om);
tr->langopts.stress_rule = 3;
tr->langopts.stress_rule = 2;
tr->langopts.stress_flags = 0x16 + 0x80000;
}
break;
@@ -766,11 +774,13 @@ SetLengthMods(tr,3); // all equal
case L('s','q'): // Albanian
{
static const short stress_lengths_sq[8] = {170, 170, 170, 170, 0, 0, 250, 270};
static const unsigned char stress_amps_sq[8] = {17,12, 17,17, 20,20, 24,22 };
static const short stress_lengths_sq[8] = {150, 150, 180, 180, 0, 0, 300, 300};
static const unsigned char stress_amps_sq[8] = {16,12, 16,16, 20,20, 21,19 };
tr = new Translator();
SetupTranslator(tr,stress_lengths_sq,stress_amps_sq);
tr->langopts.stress_flags = 0x4 + 0x10;
tr->langopts.stress_rule = 2;
tr->langopts.stress_flags = 0x16 + 0x100;
SetLetterVowel(tr,'y');
tr->langopts.numbers = 0x69 + 0x8000;
}
@@ -879,8 +889,8 @@ SetLengthMods(tr,3); // all equal
case L('v','i'): // Vietnamese
{
static const short stress_lengths_vi[8] = {150, 150, 180, 180, 210, 220, 220, 280};
static const unsigned char stress_amps_vi[] = {16,16, 16,16, 24,24, 24,22 };
static const short stress_lengths_vi[8] = {150, 150, 180, 180, 210, 230, 230, 240};
static const unsigned char stress_amps_vi[] = {16,16, 16,16, 22,22, 22,22 };
static wchar_t vowels_vi[] = {
0x61, 0xe0, 0xe1, 0x1ea3, 0xe3, 0x1ea1, // a
0x103, 0x1eb1, 0x1eaf, 0x1eb3, 0x1eb5, 0x1eb7, // ă
@@ -900,12 +910,12 @@ SetLengthMods(tr,3); // all equal
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
tr->langopts.stress_rule = 0;
tr->langopts.word_gap = 0x20; // length of a final vowel is less dependent on the next consonant
tr->langopts.vowel_pause = 4;
tr->langopts.word_gap = 0x21; // length of a final vowel is less dependent on the next consonant, don't merge consonant with next word
// tr->langopts.vowel_pause = 4;
tr->letter_groups[0] = vowels_vi;
// tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
tr->langopts.tone_language = 1; // Tone language, use CalcPitches_Tone() rather than CalcPitches()
tr->langopts.unstressed_wd1 = 2;
tr->langopts.numbers = 0x0049;
}
break;
+2 -1
View File
@@ -412,7 +412,7 @@ int IsSpace(unsigned int c)
Translator::Translator()
{//=====================
int ix;
static const unsigned char stress_amps2[] = {16,16, 20,20, 20,24, 24,21 };
static const unsigned char stress_amps2[] = {17,17, 20,20, 20,24, 24,21 };
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 punct_in_word[2] = {'\'', 0}; // allow hyphen within words
@@ -2111,6 +2111,7 @@ void *Translator::TranslateClause(FILE *f_text, const void *vp_input, int *tone_
expect_verb_s=0;
end_stressed_vowel=0;
prev_dict_flags = 0;
phonemes_repeat_count = 0;
sbuf[0] = 0;
sbuf[1] = ' ';
+4 -1
View File
@@ -56,7 +56,7 @@
#define FLAG_ALT_TRANS 0x100000 // language specific
#define FLAG_ALT2_TRANS 0x200000 // language specific
#define FLAG_MAX3 0x08000000 // limit to 3 repeats
#define FLAG_PAUSE1 0x10000000 // shorter prepause
#define FLAG_TEXTMODE 0x20000000 // word translates to replacement text, not phonemes
#define BITNUM_FLAG_TEXTMODE 29
@@ -314,6 +314,7 @@ typedef struct {
// bit16= Don't diminish consecutive syllables within a word.
// bit17= "priority" stress reduces other primary stress to "unstressed" not "secondary"
// bit18= don't lengthen short vowels more than long vowels at end-of-clause
// bit19=stress on final syllable if it has a long vowel, but previous syllable has a short vowel
int stress_flags;
int unstressed_wd1; // stress for $u word of 1 syllable
@@ -416,6 +417,8 @@ public:
char phon_out[300];
char word_phonemes[N_WORD_PHONEMES]; // a word translated into phoneme codes
char phonemes_repeat[20];
int phonemes_repeat_count;
unsigned char stress_amps[8];
unsigned char stress_amps_r[8];
+1 -1
View File
@@ -71,7 +71,7 @@ extern USHORT voice_pcnt[N_PEAKS+1][3];
extern voice_t *voice;
extern int tone_points[12];
const char *SelectVoice(espeak_VOICE *voice_select);
const char *SelectVoice(espeak_VOICE *voice_select, int *found);
espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name);
voice_t *LoadVoice(const char *voice_name, int control);
voice_t *LoadVoiceVariant(const char *voice_name, int variant);
+15 -6
View File
@@ -365,8 +365,11 @@ void VoiceReset(int tone_only)
static int breath_widths[N_PEAKS] = {0,200,200,400,400,400,600,600,600};
// default is: pitch 82,118
voice->pitch_base = 0x49000; // default, 73 << 12;
voice->pitch_range = 0x0f30; // default = 0x1000
// voice->pitch_base = 0x49000; // default, 73 << 12;
// voice->pitch_range = 0x0f30; // default = 0x1000
voice->pitch_base = 0x47000;
voice->pitch_range = 3996;
voice->formant_factor = 256;
voice->echo_delay = 0;
@@ -1122,7 +1125,7 @@ static int ScoreVoice(espeak_VOICE *voice_spec, const char *spec_language, int s
matching_parts += matching; // number of parts which match
if(matching_parts == 0)
break; // no matching parts for this language
continue; // no matching parts for this language
x = 5;
// reduce the score if not all parts of the required language match
@@ -1301,8 +1304,8 @@ espeak_VOICE *SelectVoiceByName(espeak_VOICE **voices, const char *name)
char const *SelectVoice(espeak_VOICE *voice_select)
{//================================================
char const *SelectVoice(espeak_VOICE *voice_select, int *found)
{//============================================================
// Returns a path within espeak-voices, with a possible +variant suffix
// variant is an output-only parameter
int nv; // number of candidates
@@ -1323,6 +1326,7 @@ char const *SelectVoice(espeak_VOICE *voice_select)
static espeak_VOICE voice_variants[N_VOICE_VARIANTS];
static char voice_id[50];
*found = 1;
memcpy(&voice_select2,voice_select,sizeof(voice_select2));
if(n_voices_list == 0)
@@ -1366,6 +1370,7 @@ char const *SelectVoice(espeak_VOICE *voice_select)
if(nv == 0)
{
// no matching voice, choose the default
*found = 0;
if((voices[0] = SelectVoiceByName(voices_list,"default")) != NULL)
nv = 1;
}
@@ -1639,8 +1644,12 @@ espeak_ERROR SetVoiceByName(const char *name)
espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector)
{//============================================================
const char *voice_id;
int voice_found;
voice_id = SelectVoice(voice_selector);
voice_id = SelectVoice(voice_selector, &voice_found);
if(voice_found == 0)
return(EE_NOT_FOUND);
LoadVoiceVariant(voice_id,0);
DoVoiceChange(voice);
+30 -40
View File
@@ -59,7 +59,7 @@ voice_t *wvoice;
FILE *f_log = NULL;
int option_waveout = 0;
int option_harmonic1 = 11; // 10
int option_harmonic1 = 10; // 10
int option_log_frames = 0;
static int flutter_amp = 64;
@@ -252,7 +252,7 @@ static const unsigned char Flutter_tab[N_FLUTTER] = {
};
// waveform shape table for HF peaks, formants 6,7,8
#define N_WAVEMULT 512
#define N_WAVEMULT 128
static int wavemult_offset=0;
static int wavemult_max=0;
@@ -266,32 +266,8 @@ static unsigned char wavemult[N_WAVEMULT] = {
218,213,207,201,194,188,181,174,166,159,152,144,136,128,121,113,
105, 98, 90, 83, 76, 69, 62, 55, 49, 43, 37, 32, 27, 22, 18, 14,
11, 8, 5, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// set from y = pow(2,x) * 128, x=-1 to 1
unsigned char pitch_adjust_tab[MAX_PITCH_VALUE+1] = {
@@ -662,24 +638,31 @@ int WavegenOpenSound()
}
int WavegenCloseSound()
{//====================
PaError active;
// check whether speaking has finished, and close the stream
// if(pa_stream != NULL)
if((pa_stream != NULL) && (WcmdqUsed() == 0)) // TEST, also check that queue is empty
if(pa_stream != NULL)
{
#if USE_PORTAUDIO == 18
active = Pa_StreamActive(pa_stream);
#else
active = Pa_IsStreamActive(pa_stream);
#endif
if(active == 0)
if(WcmdqUsed() == 0) // also check that the queue is empty
{
Pa_CloseStream(pa_stream);
pa_stream = NULL;
return(1);
if(active == 0)
{
Pa_CloseStream(pa_stream);
pa_stream = NULL;
return(1);
}
}
else
{
WavegenOpenSound(); // still items in the queue, shouldn't be closed
}
}
return(0);
@@ -901,13 +884,20 @@ int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control)
}
}
// increase bass, up to the F1 peak
h=1;
x = peaks[1].height * 24;
for(f=pitch; f<peaks[1].freq; f+=pitch)
{
int y;
int h2;
// increase bass
y = peaks[1].height * 10; // addition as a multiple of 1/256s
h2 = (1000<<16)/pitch; // decrease until 1000Hz
x = y/h2;
h = 1;
while(y > 0)
{
htab[h++] += x;
htab[h++] += y;
y -= x;
}
}
// find the nearest harmonic for HF peaks where we don't use shape
for(; pk<N_PEAKS; pk++)
@@ -1255,8 +1245,8 @@ int Wavegen()
if((ix = amp_ix>>8) > 127) ix = 127;
amp = amplitude_env[ix];
amplitude2 = (amplitude2 * amp)/255;
if(amp < 255)
modulation_type = 7;
// if(amp < 255)
// modulation_type = 7;
}
// introduce roughness into the sound by reducing the amplitude of