mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-11 16:39:15 +00:00
[1.39.48]
Fix lettergroups: Sort items to longest first. Lang en-us: Use rhotic [3] in place of [@] when [r] follows. Voice files: add attribute "fast-test" to experiment with faster talking speeds. git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@212 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
+6
-2
@@ -69,6 +69,7 @@
|
||||
#define tBEFORENOTVOWEL 19
|
||||
#define tBEFORENOTVOWEL2 20
|
||||
#define tSWITCHVOICING 21
|
||||
#define tBEFORE_R 22
|
||||
|
||||
#define tLINKOUT 23
|
||||
#define tVOWELIN 24
|
||||
@@ -83,7 +84,7 @@
|
||||
#define tSTRESSTYPE 32
|
||||
|
||||
|
||||
static const int flags_alternative[] = {phBEFOREVOWEL,phBEFOREVOWELPAUSE,phBEFORENOTVOWEL,phBEFORENOTVOWEL2,phSWITCHVOICING};
|
||||
static const int flags_alternative[] = {phBEFOREVOWEL,phBEFOREVOWELPAUSE,phBEFORENOTVOWEL,phBEFORENOTVOWEL2,phSWITCHVOICING,phBEFORE_R};
|
||||
|
||||
extern void MakeVowelLists(void);
|
||||
extern void FindPhonemesUsed(void);
|
||||
@@ -243,6 +244,7 @@ static keywtab_t keywords[] = {
|
||||
{"beforevowelpause", tBEFOREVOWELPAUSE},
|
||||
{"beforenotvowel",tBEFORENOTVOWEL},
|
||||
{"beforenotvowel2",tBEFORENOTVOWEL2},
|
||||
{"before_r",tBEFORE_R},
|
||||
{"linkout",tLINKOUT},
|
||||
{"switchvoicing",tSWITCHVOICING},
|
||||
{"vowelin",tVOWELIN},
|
||||
@@ -263,6 +265,7 @@ static keywtab_t keywords[] = {
|
||||
{"palatal", 0x2000000+phPALATAL},
|
||||
{"long", 0x2000000+phLONG},
|
||||
{"brkafter", 0x2000000+phBRKAFTER},
|
||||
{"rhotic", 0x2000000+phRHOTIC},
|
||||
{"nonsyllabic",0x2000000+phNONSYLLABIC},
|
||||
{"lengthenstop",0x2000000+phLENGTHENSTOP},
|
||||
|
||||
@@ -1465,6 +1468,7 @@ int Compile::CPhoneme()
|
||||
case tBEFORENOTVOWEL:
|
||||
case tBEFORENOTVOWEL2:
|
||||
case tSWITCHVOICING:
|
||||
case tBEFORE_R:
|
||||
ph->phflags |= flags_alternative[item - tBEFOREVOWEL];
|
||||
if((phcode = NextItem(tPHONEMEMNEM)) == -1)
|
||||
phcode = LookupPhoneme(item_string,1);
|
||||
@@ -1813,7 +1817,7 @@ int LoadEnvelope2(FILE *f, const char *fname)
|
||||
n = sscanf(line_buf,"%f %f %d",&env_x[n_points],&env_y[n_points],&env_lin[n_points]);
|
||||
if(n >= 2)
|
||||
{
|
||||
env_x[n_points] *= 1.28; // convert range 0-100 to 0-128
|
||||
env_x[n_points] *= (float)1.28; // convert range 0-100 to 0-128
|
||||
n_points++;
|
||||
}
|
||||
}
|
||||
|
||||
+33
-4
@@ -1271,7 +1271,16 @@ static void output_rule_group(FILE *f_out, int n_rules, char **rules, char *name
|
||||
static int compile_lettergroup(char *input, FILE *f_out)
|
||||
{//=====================================================
|
||||
char *p;
|
||||
char *p_start;
|
||||
int group;
|
||||
int ix;
|
||||
int n_items;
|
||||
int length;
|
||||
int max_length = 0;
|
||||
|
||||
#define N_LETTERGP_ITEMS 200
|
||||
char *items[N_LETTERGP_ITEMS];
|
||||
char item_length[N_LETTERGP_ITEMS];
|
||||
|
||||
p = input;
|
||||
if(!isdigit(p[0]) || !isdigit(p[1]))
|
||||
@@ -1296,18 +1305,38 @@ static int compile_lettergroup(char *input, FILE *f_out)
|
||||
fputc(group + 'A', f_out);
|
||||
letterGroupsDefined[group] = 1;
|
||||
|
||||
for(;;)
|
||||
n_items = 0;
|
||||
while(n_items < N_LETTERGP_ITEMS)
|
||||
{
|
||||
while(isspace2(*p)) p++;
|
||||
if(*p == 0)
|
||||
break;
|
||||
|
||||
|
||||
items[n_items] = p_start = p;
|
||||
while((*p & 0xff) > ' ')
|
||||
{
|
||||
fputc(*p++, f_out);
|
||||
p++;
|
||||
}
|
||||
fputc(0,f_out);
|
||||
*p++ = 0;
|
||||
length = p - p_start;
|
||||
if(length > max_length)
|
||||
max_length = length;
|
||||
item_length[n_items++] = length;
|
||||
}
|
||||
|
||||
// write out the items, longest first
|
||||
while(max_length > 1)
|
||||
{
|
||||
for(ix=0; ix < n_items; ix++)
|
||||
{
|
||||
if(item_length[ix] == max_length)
|
||||
{
|
||||
fwrite(items[ix],1,max_length,f_out);
|
||||
}
|
||||
}
|
||||
max_length--;
|
||||
}
|
||||
|
||||
fputc(RULE_GROUP_END,f_out);
|
||||
|
||||
return(0);
|
||||
|
||||
+4
-1
@@ -829,7 +829,10 @@ static const char *M_Variant(int value)
|
||||
{//====================================
|
||||
// returns M, or perhaps MA for some cases
|
||||
|
||||
if(((value % 100)>20) || ((value % 100)<10)) // but not teens, 10 to 19
|
||||
if((translator->langopts.numbers2 & 0x100) && (value >= 2) && (value <= 4))
|
||||
return("0MA"); // Czech, Slovak
|
||||
else
|
||||
if(((value % 100) < 10) || ((value % 100) > 20)) // but not teens, 10 to 19
|
||||
{
|
||||
if ((translator->langopts.numbers2 & 0x40) &&
|
||||
((value % 10)>=2) &&
|
||||
|
||||
@@ -55,10 +55,12 @@
|
||||
#define phBEFORENOTVOWEL 0x0c00
|
||||
#define phBEFORENOTVOWEL2 0x1000
|
||||
#define phSWITCHVOICING 0x0800
|
||||
#define phBEFORE_R 0x1400
|
||||
|
||||
#define phNONSYLLABIC 0x100000 // don't count this vowel as a syllable when finding the stress position
|
||||
#define phLONG 0x200000
|
||||
#define phLENGTHENSTOP 0x400000 // make the pre-pause slightly longer
|
||||
#define phRHOTIC 0x800000
|
||||
|
||||
// fixed phoneme code numbers, these can be used from the program code
|
||||
#define phonCONTROL 1
|
||||
|
||||
@@ -427,6 +427,13 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
|
||||
if(next->type == phVOWEL)
|
||||
alternative = ph->alternative_ph;
|
||||
break;
|
||||
|
||||
case phBEFORE_R:
|
||||
if(next->phflags & phRHOTIC)
|
||||
{
|
||||
alternative = ph->alternative_ph;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ph->phflags & phBEFOREPAUSE)
|
||||
|
||||
+1
-1
@@ -1750,7 +1750,7 @@ static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int &outix, int n_outb
|
||||
}
|
||||
if((attr2 = GetSsmlAttribute(px,"time")) != NULL)
|
||||
{
|
||||
value = (attrnumber(attr2,0,1) * 25) / speed_factor1; // compensate for speaking speed to keep constant pause length
|
||||
value = (attrnumber(attr2,0,1) * 25) / speed.speed_factor1; // compensate for speaking speed to keep constant pause length
|
||||
|
||||
if(terminator == 0)
|
||||
terminator = CLAUSE_NONE;
|
||||
|
||||
+21
-9
@@ -136,24 +136,37 @@ void SetSpeed(int control)
|
||||
{
|
||||
// these are used in synthesis file
|
||||
s1 = (x * voice->speedf1)/256;
|
||||
speed_factor1 = (256 * s1)/115; // full speed adjustment, used for pause length
|
||||
if(speed_factor1 < 15)
|
||||
speed_factor1 = 15;
|
||||
speed.speed_factor1 = (256 * s1)/115; // full speed adjustment, used for pause length
|
||||
if(speed.speed_factor1 < 15)
|
||||
speed.speed_factor1 = 15;
|
||||
if(wpm >= 170)
|
||||
// speed_factor2 = 100 + (166*s1)/128; // reduced speed adjustment, used for playing recorded sounds
|
||||
speed_factor2 = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
|
||||
speed.speed_factor2 = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
|
||||
else
|
||||
speed_factor2 = 128 + (128*s1)/130; // = 215 at 170 wpm
|
||||
speed.speed_factor2 = 128 + (128*s1)/130; // = 215 at 170 wpm
|
||||
|
||||
if(wpm2 > 369)
|
||||
{
|
||||
if(wpm2 > 390)
|
||||
wpm2 = 390;
|
||||
speed_factor2 = faster[wpm2 - 370];
|
||||
speed.speed_factor2 = faster[wpm2 - 370];
|
||||
}
|
||||
}
|
||||
|
||||
speed_min_sample_len = 450;
|
||||
speed.min_sample_len = 450;
|
||||
speed.speed_factor3 = 110; // controls the effect of FRFLAG_LEN_MOD reduce length change
|
||||
|
||||
if(wpm2 >= 370)
|
||||
{
|
||||
// TESTING
|
||||
// use experimental fast settings if they have been specified in the Voice
|
||||
if(speed.fast_settings[0] > 0)
|
||||
speed.speed_factor1 = speed.fast_settings[0];
|
||||
if(speed.fast_settings[1] > 0)
|
||||
speed.speed_factor2 = speed.fast_settings[1];
|
||||
if(speed.fast_settings[2] > 0)
|
||||
speed.speed_factor3 = speed.fast_settings[2];
|
||||
}
|
||||
} // end of SetSpeed
|
||||
|
||||
|
||||
@@ -528,8 +541,7 @@ void CalcLengths(Translator *tr)
|
||||
length_mod *= speed3;
|
||||
|
||||
length_mod = length_mod / 128;
|
||||
// if(length_mod < 9)
|
||||
// length_mod = 9; // restrict how much lengths can be reduced
|
||||
|
||||
if(length_mod < 8)
|
||||
length_mod = 8; // restrict how much lengths can be reduced
|
||||
|
||||
|
||||
@@ -597,13 +597,13 @@ void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola)
|
||||
{
|
||||
// a pause phoneme, which has not been changed by the translation
|
||||
name = '_';
|
||||
len = (p->length * speed_factor1)/256;
|
||||
len = (p->length * speed.speed_factor1)/256;
|
||||
// if(len == 0) continue;
|
||||
if(len == 0)
|
||||
len = 1;
|
||||
}
|
||||
else
|
||||
len = (80 * speed_factor2)/256;
|
||||
len = (80 * speed.speed_factor2)/256;
|
||||
|
||||
#ifdef USE_MBROLA_LIB
|
||||
MbrolaMarker(espeakEVENT_PHONEME, (p->sourceix & 0x7ff) + clause_start_char, 0, ph->mnemonic);
|
||||
@@ -664,7 +664,7 @@ void MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, FILE *f_mbrola)
|
||||
break;
|
||||
|
||||
case phVSTOP:
|
||||
len = (80 * speed_factor2)/256;
|
||||
len = (80 * speed.speed_factor2)/256;
|
||||
break;
|
||||
|
||||
case phFRICATIVE:
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.39.42 17.Dec.08";
|
||||
const char *version_string = "1.39.48 19.Dec.08";
|
||||
const int version_phdata = 0x013900;
|
||||
|
||||
int option_device_number = -1;
|
||||
|
||||
+6
-8
@@ -45,9 +45,7 @@ PHONEME_LIST phoneme_list[N_PHONEME_LIST];
|
||||
int mbrola_delay;
|
||||
char mbrola_name[20];
|
||||
|
||||
int speed_factor1;
|
||||
int speed_factor2;
|
||||
int speed_min_sample_len;
|
||||
SPEED_FACTORS speed;
|
||||
|
||||
static int last_pitch_cmd;
|
||||
static int last_amp_cmd;
|
||||
@@ -192,9 +190,9 @@ int PauseLength(int pause, int control)
|
||||
int len;
|
||||
|
||||
if(control == 0)
|
||||
len = (pause * speed_factor1)/256;
|
||||
len = (pause * speed.speed_factor1)/256;
|
||||
else
|
||||
len = (pause * speed_factor2)/256;
|
||||
len = (pause * speed.speed_factor2)/256;
|
||||
|
||||
if(len < 5) len = 5; // mS, limit the amount to which pauses can be shortened
|
||||
return(len);
|
||||
@@ -253,8 +251,8 @@ static int DoSample2(int index, int which, int length_mod, int amp)
|
||||
length = length1;
|
||||
|
||||
|
||||
length = (length * speed_factor2)/256;
|
||||
min_length = speed_min_sample_len;
|
||||
length = (length * speed.speed_factor2)/256;
|
||||
min_length = speed.min_sample_len;
|
||||
if(format==0)
|
||||
min_length *= 2;
|
||||
|
||||
@@ -982,7 +980,7 @@ if(which==1)
|
||||
length_factor = length_mod;
|
||||
if(frame1->frflags & FRFLAG_LEN_MOD) // reduce effect of length mod
|
||||
{
|
||||
length_factor = (length_mod*4 + 256*3)/7;
|
||||
length_factor = (length_mod*(256-speed.speed_factor3) + 256*speed.speed_factor3)/256;
|
||||
}
|
||||
len = (frame_length * samplerate)/1000;
|
||||
len = (len * length_factor)/256;
|
||||
|
||||
+9
-3
@@ -213,6 +213,14 @@ typedef struct {
|
||||
int control;
|
||||
} MBROLA_TAB;
|
||||
|
||||
typedef struct {
|
||||
int speed_factor1;
|
||||
int speed_factor2;
|
||||
int speed_factor3;
|
||||
int min_sample_len;
|
||||
int fast_settings[8];
|
||||
} SPEED_FACTORS;
|
||||
|
||||
|
||||
// phoneme table
|
||||
extern PHONEME_TAB *phoneme_tab[N_PHONEME_TAB];
|
||||
@@ -304,9 +312,7 @@ int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, cha
|
||||
|
||||
extern unsigned char *envelope_data[18];
|
||||
extern int formant_rate[]; // max rate of change of each formant
|
||||
extern int speed_factor1;
|
||||
extern int speed_factor2;
|
||||
extern int speed_min_sample_len;
|
||||
extern SPEED_FACTORS speed;
|
||||
|
||||
extern long count_samples;
|
||||
extern int outbuf_size;
|
||||
|
||||
@@ -282,7 +282,7 @@ Translator *SelectTranslator(const char *name)
|
||||
SetLetterBitsRange(tr,LETTERGP_F,0x3e,0x4c); // vowel signs, but not virama
|
||||
|
||||
tr->langopts.numbers = 0x1;
|
||||
tr->langopts.numbers2 = 0x100;
|
||||
tr->langopts.numbers2 = NUM2_100000;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -849,13 +849,13 @@ SetLengthMods(tr,3); // all equal
|
||||
tr->langopts.param[LOPT_COMBINE_WORDS] = 4; // combine some prepositions with the following word
|
||||
|
||||
tr->langopts.numbers = 0x0401 + 0x4000 + NUM_ROMAN;
|
||||
tr->langopts.numbers2 = 0x40;
|
||||
tr->langopts.numbers2 = 0x100;
|
||||
tr->langopts.thousands_sep = 0; //no thousands separator
|
||||
tr->langopts.decimal_sep = ',';
|
||||
|
||||
if(name2 == L('c','s'))
|
||||
{
|
||||
tr->langopts.numbers2 = 0x48; // variant numbers before milliards
|
||||
tr->langopts.numbers2 = 0x108; // variant numbers before milliards
|
||||
}
|
||||
|
||||
SetLetterVowel(tr,'y');
|
||||
|
||||
+4
-3
@@ -349,14 +349,15 @@ typedef struct {
|
||||
// bit21= say "roman" after the number, not before
|
||||
int numbers;
|
||||
|
||||
#define NUM2_100000 0x100 // numbers for 100,000 and 10,000,000
|
||||
#define NUM2_100000a 0x500 // numbers for 100,000 and 1,000,000
|
||||
#define NUM2_100000 0x800 // numbers for 100,000 and 10,000,000
|
||||
#define NUM2_100000a 0xc00 // numbers for 100,000 and 1,000,000
|
||||
// bits 1-4 use variant form of numbers before thousands,millions,etc.
|
||||
// bit6=(LANG=pl) two forms of plural, M or MA
|
||||
// bit7=(LANG-ru) use MB for 1 thousand, million, etc
|
||||
// bit8=(LANG=hi) special word for 100,000 and 10,000,000
|
||||
// bit8=(LANG=cs,sk) two forms of plural, M or MA
|
||||
// bit9=(LANG=rw) say "thousand" and "million" before its number, not after
|
||||
// bit10=(LANG=sw) special word for 100,000 and 1,000,000
|
||||
// bit11=(LANG=hi) special word for 100,000 and 10,000,000
|
||||
int numbers2;
|
||||
|
||||
int max_roman;
|
||||
|
||||
+40
-31
@@ -69,44 +69,46 @@ static int len_path_voices;
|
||||
espeak_VOICE voice_selected;
|
||||
|
||||
|
||||
|
||||
#define V_NAME 1
|
||||
#define V_LANGUAGE 2
|
||||
#define V_GENDER 3
|
||||
#define V_TRANSLATOR 4
|
||||
#define V_PHONEMES 5
|
||||
#define V_DICTIONARY 6
|
||||
enum {
|
||||
V_NAME = 1,
|
||||
V_LANGUAGE,
|
||||
V_GENDER,
|
||||
V_TRANSLATOR,
|
||||
V_PHONEMES,
|
||||
V_DICTIONARY,
|
||||
|
||||
// these affect voice quality, are independent of language
|
||||
#define V_FORMANT 7
|
||||
#define V_PITCH 8
|
||||
#define V_ECHO 9
|
||||
#define V_FLUTTER 10
|
||||
#define V_ROUGHNESS 11
|
||||
#define V_CLARITY 12
|
||||
#define V_TONE 13
|
||||
#define V_VOICING 14
|
||||
#define V_BREATH 15
|
||||
#define V_BREATHW 16
|
||||
V_FORMANT,
|
||||
V_PITCH,
|
||||
V_ECHO,
|
||||
V_FLUTTER,
|
||||
V_ROUGHNESS,
|
||||
V_CLARITY,
|
||||
V_TONE,
|
||||
V_VOICING,
|
||||
V_BREATH,
|
||||
V_BREATHW,
|
||||
|
||||
// these override defaults set by the translator
|
||||
#define V_WORDGAP 17
|
||||
#define V_INTONATION 18
|
||||
#define V_STRESSLENGTH 19
|
||||
#define V_STRESSAMP 20
|
||||
#define V_STRESSADD 21
|
||||
#define V_DICTRULES 22
|
||||
#define V_STRESSRULE 23
|
||||
#define V_CHARSET 24
|
||||
#define V_NUMBERS 25
|
||||
#define V_OPTION 26
|
||||
V_WORDGAP,
|
||||
V_INTONATION,
|
||||
V_STRESSLENGTH,
|
||||
V_STRESSAMP,
|
||||
V_STRESSADD,
|
||||
V_DICTRULES,
|
||||
V_STRESSRULE,
|
||||
V_CHARSET,
|
||||
V_NUMBERS,
|
||||
V_OPTION,
|
||||
|
||||
#define V_MBROLA 27
|
||||
#define V_KLATT 28
|
||||
V_MBROLA,
|
||||
V_KLATT,
|
||||
V_FAST,
|
||||
|
||||
// these need a phoneme table to have been specified
|
||||
#define V_REPLACE 29
|
||||
#define V_CONSONANTS 30
|
||||
V_REPLACE,
|
||||
V_CONSONANTS
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -147,6 +149,7 @@ static keywtab_t keyword_tab[] = {
|
||||
{"mbrola", V_MBROLA},
|
||||
{"consonants", V_CONSONANTS},
|
||||
{"klatt", V_KLATT},
|
||||
{"fast_test", V_FAST},
|
||||
|
||||
// these just set a value in langopts.param[]
|
||||
{"l_dieresis", 0x100+LOPT_DIERESES},
|
||||
@@ -385,6 +388,7 @@ void VoiceReset(int tone_only)
|
||||
voice->consonant_amp = 100;
|
||||
voice->consonant_ampv = 100;
|
||||
memset(voice->klatt,0,sizeof(voice->klatt));
|
||||
memset(speed.fast_settings,0,sizeof(speed.fast_settings));
|
||||
|
||||
#ifdef PLATFORM_RISCOS
|
||||
voice->roughness = 1;
|
||||
@@ -880,6 +884,11 @@ voice_t *LoadVoice(const char *vname, int control)
|
||||
voice->klatt[KLATT_Kopen] -= 40;
|
||||
break;
|
||||
|
||||
case V_FAST:
|
||||
Read8Numbers(p,speed.fast_settings);
|
||||
SetSpeed(2);
|
||||
break;
|
||||
|
||||
default:
|
||||
if((key & 0xff00) == 0x100)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user