[1.31.03]

lang=en-r: change to phoneme [t#] (reduced "t")
Added "consonants" attribute to voice files.
Minor change to intonation types 2 and 3.
lang=zh: adjust tone levels
lang=fr: adjust stressAmp, adjust consonant strengths.
Platform RISC_OS. Disable the "breath" attribute in voices because floating point is not allowed in callbacks.
Platform RISC_OS. Implement ListVoices()


git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@132 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
jonsd
2008-01-27 11:26:03 +00:00
parent 0d2fa52994
commit e69ec3a676
43 changed files with 619 additions and 291 deletions
+1 -1
View File
@@ -177,7 +177,7 @@ int Translator::LoadDictionary(const char *name, int no_error)
length = pw[1];
if(size <= (N_HASH_DICT + sizeof(int)*2))
{
fprintf(stderr,"Empty dictionary: '%s\n",fname);
fprintf(stderr,"Empty _dict file: '%s\n",fname);
return(2);
}
if((pw[0] != N_HASH_DICT) || (length <= 0) || (length > 0x8000000))
+21 -13
View File
@@ -247,7 +247,8 @@ static int drops_0[8] = {0x400,0x400,0x700,0x700,0x700,0xa00,0x1800,0x0e00};
static short oflow[] = {0, 20, 12, 4, 0};
static short oflow_emf[] = {5, 24, 15, 10, 5};
static short oflow_less[] = {1, 17, 10, 5, 1};
static short oflow_less[] = {3, 19, 12, 7, 2};
static short oflow_test2[] = {20, 0, 20, 0, 20};
static short back_emf[] = {35, 32, 0};
typedef struct {
@@ -278,7 +279,7 @@ typedef struct {
unsigned char tail_shape;
} TONE_TABLE;
#define N_TONE_TABLE 11
#define N_TONE_TABLE 13
static TONE_TABLE tone_table[N_TONE_TABLE] = {
{PITCHfall, 30, 5, PITCHfall, 30, 8, // 0 statement
@@ -297,14 +298,14 @@ static TONE_TABLE tone_table[N_TONE_TABLE] = {
20, 25, 34, 22, drops_0, 3, 3, 5, oflow, NULL, 15, 5, 0},
{PITCHfall, 28, 6, PITCHfall, 28, 10, // 5 statement, less intonation
20, 25, 30, 22, drops_0, 4, 3, 5, oflow_less, NULL, 12, 6, 0},
{PITCHfall, 28, 5, PITCHfall, 28, 9, // 5 statement, less intonation
20, 25, 32, 24, drops_0, 4, 3, 5, oflow_less, NULL, 12, 7, 0},
{PITCHfrise2, 33,11, PITCHfall, 28,10, // 6 comma, less intonation
20, 25, 30, 22, drops_0, 4, 3, 5, oflow_less, NULL, 9,14, 0},
{PITCHfrise2, 32,8, PITCHfrise2, 28,9, // 6 comma, less intonation
20, 25, 32, 24, drops_0, 4, 3, 5, oflow_less, NULL, 10,16, 0},
{PITCHfrise2, 28, 7, PITCHfall, 28, 12, // 7 comma, less intonation, less rise
20, 25, 30, 22, drops_0, 4, 3, 5, oflow_less, NULL, 14, 8, 0},
{PITCHfrise2, 28, 7, PITCHfall, 29, 14, // 7 comma, less intonation, less rise
20, 25, 32, 24, drops_0, 4, 3, 5, oflow_less, NULL, 14, 8, 0},
{PITCHrise, 30, 20, PITCHfall, 19, 14, // 8 pitch raises at end of sentence
20, 25, 34, 22, drops_0, 3, 3, 5, oflow, NULL, 24, 30, 0},
@@ -315,6 +316,12 @@ static TONE_TABLE tone_table[N_TONE_TABLE] = {
{PITCHfrise, 39, 15, PITCHfall, 28, 14, // 10 question
20, 25, 34, 22, drops_0, 3, 3, 5, oflow, NULL, 20, 36, 0},
{PITCHfall, 28, 6, PITCHfall, 28, 10, // 11 test
20, 25, 24, 22, drops_0, 3, 3, 5, oflow_less, NULL, 12, 6, 0},
{PITCHfall, 35, 9, PITCHfall, 35, 12, // 12 test
19, 26, 36, 20, drops_0, 2, 4, 5, oflow_test2, NULL, 16, 10, 0},
};
@@ -327,8 +334,9 @@ unsigned char punctuation_to_tone[INTONATION_TYPES][PUNCT_INTONATIONS] = {
{5,7,1,0,0,4},
{8,9,10,3,0,0},
{8,8,10,3,0,0},
{0,1,2,3,0,4},
{0,1,2,3,0,0} };
{11,11,11,11,0,0}, // 6 test
{12,12,12,12,0,0}
};
@@ -738,10 +746,10 @@ void Translator::CalcPitches_Tone(int clause_tone)
PHONEME_TAB *prev2_tph; // 2 tones previous
PHONEME_LIST *prev_p;
int pitch_adjust = 10; // pitch gradient through the clause - inital value
int pitch_adjust = 0; // pitch gradient through the clause - inital value
int pitch_decrement = 0; // decrease by this for each stressed syllable
int pitch_low = 10; // until it drops to this
int pitch_high = 10; // then reset to this
int pitch_low = 0; // until it drops to this
int pitch_high = 0; // then reset to this
p = &phoneme_list[0];
+6 -2
View File
@@ -1759,7 +1759,7 @@ f_input = f_in; // for GetC etc
c2 = GetC();
}
while(!Eof())
while(!Eof() || (ungot_char != 0))
{
if(!iswalnum(c1))
{
@@ -1791,7 +1791,7 @@ f_input = f_in; // for GetC etc
if((option_ssml) && (phoneme_mode==0))
{
if((c1 == '&') && ((c2=='#') || isalpha(c2)))
if((c1 == '&') && ((c2=='#') || ((c2 >= 'a') && (c2 <= 'z'))))
{
n_xml_buf = 0;
c1 = c2;
@@ -1818,6 +1818,10 @@ f_input = f_in; // for GetC etc
{
c1 = j;
}
else
{
c1 = '&';
}
}
if((sayas_mode == 0x14) && (c1 <= 0x20))
{
+119 -12
View File
@@ -76,6 +76,7 @@ char textbuffile[L_tmpnam];
int sample_rate_index; // current value
int current_voice_num=0;
int n_voice_files = 0;
int n_voice_variant_files = 0;
// output sound buffer, 2 bytes per sample
static unsigned short SoundBuf[4096];
@@ -84,7 +85,9 @@ static int callback_inhibit = 0;
static int more_text=0;
#define N_VOICE_NAMES 60
static char *voice_names[40];
#define N_VOICE_VARIANT_NAMES 30
static char *voice_names[N_VOICE_NAMES];
static char *voice_variant_names[N_VOICE_VARIANT_NAMES];
#define N_STATIC_BUF 8000
static char static_buf[N_STATIC_BUF];
@@ -127,9 +130,9 @@ static const char *help_text =
"--punct=\"<characters>\"\n"
"\t Speak the names of punctuation characters during speaking. If\n"
"\t =<characters> is omitted, all punctuation is spoken.\n"
//"--voices=<langauge>\n"
//"\t List the available voices for the specified language.\n"
//"\t If <language> is omitted, then list all voices.\n"
"--voices=<langauge>\n"
"\t List the available voices for the specified language.\n"
"\t If <language> is omitted, then list all voices.\n"
"-k <integer>\n"
"\t Indicate capital letters with: 1=sound, 2=the word \"capitals\",\n"
"\t higher values = a pitch increase (try -k20).\n";
@@ -169,6 +172,7 @@ int GetFileLength(const char *filename)
void ReadVoiceNames2(char *directory)
{//==================================
int len;
int path_len;
int *type;
char *p;
_kernel_swi_regs regs;
@@ -184,6 +188,8 @@ void ReadVoiceNames2(char *directory)
regs.r[5] = sizeof(buf);
regs.r[6] = 0;
path_len = strlen(directory);
while(regs.r[3] > 0)
{
error = _kernel_swi(0x0c+os_X,&regs,&regs); /* OS_GBPB 10, read directory entries */
@@ -202,11 +208,25 @@ void ReadVoiceNames2(char *directory)
}
else
{
p = Alloc(len+1);
p = (char *)malloc(len+1);
strcpy(p,&buf[20]);
voice_names[n_voice_files++] = p;
if(n_voice_files >= (N_VOICE_NAMES-1))
break;
if(strcmp(&directory[path_len-3],".!v")==0)
{
if(n_voice_variant_files >= (N_VOICE_VARIANT_NAMES-1))
continue;
voice_variant_names[n_voice_variant_files++] = p;
}
else
{
if(n_voice_files >= (N_VOICE_NAMES-1))
continue;
voice_names[n_voice_files++] = p;
if(strcmp(p,"en")==0)
{
voice_names[n_voice_files++] = "en+f2";
}
}
}
}
}
@@ -216,13 +236,15 @@ void ReadVoiceNames()
{//===================
char directory[sizeof(path_home)+10];
for(n_voice_files=0; n_voice_files<N_VOICE_NAMES; n_voice_files++)
voice_names[n_voice_files] = NULL;
n_voice_files = 0;
n_voice_variant_files = 0;
sprintf(directory,"%s.voices",path_home);
ReadVoiceNames2(directory);
voice_names[n_voice_files] = NULL;
voice_variant_names[n_voice_variant_files] = NULL;
}
@@ -557,10 +579,13 @@ void set_say_options(int reg2, int reg3)
void jsd_swi_functions(int *r)
/****************************/
{
espeak_VOICE voice_select;
switch(r[0])
{
case 0: /* major version */
r[0] = 3;
r[0] = 4;
r[1] = 331;
break;
case 1: /* register user */
@@ -579,6 +604,7 @@ void jsd_swi_functions(int *r)
case 5: /* get table of voice names */
r[0] = (int)voice_names;
r[1] = (int)voice_variant_names;
break;
case 6: /* update voice data, r1 = voice_number */
@@ -594,6 +620,15 @@ void jsd_swi_functions(int *r)
// init_voice((char *)r[1]);
break;
case 8:
// list voices, r[1] contains optional language name (or "variant")
voice_select.languages = (char *)r[1];
voice_select.age = 0;
voice_select.gender = 0;
voice_select.name = NULL;
r[0] = (int)espeak_ListVoices(&voice_select);
break;
default:
r[0] = 0;
r[1] = 0;
@@ -709,6 +744,72 @@ void PitchAdjust(int pitch_adjustment)
void DisplayVoices(FILE *f_out, char *language)
{//============================================
int ix;
const char *p;
int len;
int count;
int scores = 0;
const espeak_VOICE *v;
const char *lang_name;
char age_buf[12];
const espeak_VOICE **voices;
espeak_VOICE voice_select;
static char genders[4] = {' ','M','F',' '};
if(language[0] == '=')
{
// display only voices for the specified language, in order of priority
voice_select.languages = &language[1];
voice_select.age = 0;
voice_select.gender = 0;
voice_select.name = NULL;
voices = espeak_ListVoices(&voice_select);
scores = 1;
}
else
{
voices = espeak_ListVoices(NULL);
}
fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Langs\n");
for(ix=0; (v = voices[ix]) != NULL; ix++)
{
count = 0;
p = v->languages;
while(*p != 0)
{
len = strlen(p+1);
lang_name = p+1;
if(v->age == 0)
strcpy(age_buf," ");
else
sprintf(age_buf,"%3d",v->age);
if(count==0)
{
fprintf(f_out,"%2d %-12s%s%c %-17s %-11s ",
p[0],lang_name,age_buf,genders[v->gender],v->name,v->identifier);
}
else
{
fprintf(f_out,"(%s %d)",lang_name,p[0]);
}
count++;
p += len+2;
}
// if(scores)
// fprintf(f_out,"%3d ",v->score);
fputc('\n',f_out);
}
} // end of DisplayVoices
char *param_string(char **argp)
{//============================
char *p;
@@ -860,6 +961,12 @@ void command_line(char *arg_string, int wait)
return;
}
else
if(memcmp(command,"voices",6)==0)
{
DisplayVoices(stdout,&command[6]);
return;
}
else
if(strcmp(command,"help")==0)
{
printf("\nspeak text-to-speech: %s\n%s",version_string,help_text);
+1 -1
View File
@@ -35,7 +35,7 @@
#include "translate.h"
#include "wave.h"
const char *version_string = "1.31.01 23.Jan.08";
const char *version_string = "1.31.03 26.Jan.08";
const int version_phdata = 0x013100;
int option_device_number = -1;
+6 -1
View File
@@ -269,7 +269,7 @@ Translator *SelectTranslator(const char *name)
case L('f','r'): // french
{
static const short stress_lengths_fr[8] = {190, 170, 190, 200, 0, 0, 235, 235};
static const unsigned char stress_amps_fr[8] = {16,14, 20,20, 20,24, 24,22 };
static const unsigned char stress_amps_fr[8] = {18,16, 20,20, 20,22, 22,22 };
tr = new Translator();
SetupTranslator(tr,stress_lengths_fr,stress_amps_fr);
@@ -421,6 +421,11 @@ SetLengthMods(tr,3); // all equal
}
break;
case L('j','a'): // TEST
tr = new Translator();
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
break;
case L_jbo: // Lojban
{
static const short stress_lengths_jbo[8] = {185,170, 200,200, 0,0, 290,300};
+2
View File
@@ -38,6 +38,8 @@ typedef struct {
int peak_shape; // alternative shape for formant peaks (0=standard 1=squarer)
int voicing; // 100% = 64, level of formant-synthesized sound
int formant_factor; // adjust nominal formant frequencies by this because of the voice's pitch (256ths)
int consonant_amp; // amplitude of unvoiced consonants
int consonant_ampv; // amplitude of the noise component of voiced consonants
// parameters used by Wavegen
short freq[N_PEAKS]; // 100% = 256
+65 -5
View File
@@ -29,7 +29,9 @@
#ifdef PLATFORM_WINDOWS
#include "windows.h"
#else
#ifndef PLATFORM_RISCOS
#ifdef PLATFORM_RISCOS
#include "kernel.h"
#else
#include "dirent.h"
#endif
#endif
@@ -103,7 +105,7 @@ espeak_VOICE voice_selected;
// these need a phoneme table to have been specified
#define V_REPLACE 28
#define V_CONSONANTS 29
typedef struct {
@@ -141,6 +143,7 @@ static keywtab_t keyword_tab[] = {
{"numbers", V_NUMBERS},
{"option", V_OPTION},
{"mbrola", V_MBROLA},
{"consonants", V_CONSONANTS},
// these just set a value in langopts.param[]
{"l_dieresis", 0x100+LOPT_DIERESES},
@@ -368,6 +371,9 @@ void VoiceReset(int tone_only)
voice->n_harmonic_peaks = 5;
voice->peak_shape = 1;
voice->voicing = 64;
voice->consonant_amp = 100;
voice->consonant_ampv = 100;
#ifdef PLATFORM_RISCOS
voice->roughness = 1;
#else
@@ -836,6 +842,10 @@ voice_t *LoadVoice(const char *vname, int control)
voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
break;
case V_CONSONANTS:
value = sscanf(p,"%d %d",&voice->consonant_amp, &voice->consonant_ampv);
break;
case V_MBROLA:
{
int srate = 16000;
@@ -937,8 +947,10 @@ char *ExtractVoiceVariantName(char *vname, int variant_num)
char *p;
static char variant_name[20];
char variant_prefix[5];
variant_name[0] = 0;
sprintf(variant_prefix,"!v%c",PATHSEP);
if(vname != NULL)
{
@@ -953,7 +965,7 @@ char *ExtractVoiceVariantName(char *vname, int variant_num)
else
{
// voice variant name, not number
strcpy(variant_name,"!v/");
strcpy(variant_name,variant_prefix);
strncpy0(&variant_name[3],p,sizeof(variant_name)-3);
}
}
@@ -962,9 +974,9 @@ char *ExtractVoiceVariantName(char *vname, int variant_num)
if(variant_num > 0)
{
if(variant_num < 10)
sprintf(variant_name,"!v/m%d",variant_num); // male
sprintf(variant_name,"%sm%d",variant_prefix, variant_num); // male
else
sprintf(variant_name,"!v/f%d",variant_num-10); // female
sprintf(variant_name,"%sf%d",variant_prefix, variant_num-10); // female
}
return(variant_name);
@@ -1409,6 +1421,54 @@ void GetVoices(const char *path)
char fname[sizeof(path_home)+100];
#ifdef PLATFORM_RISCOS
int len;
int *type;
char *p;
_kernel_swi_regs regs;
_kernel_oserror *error;
char buf[80];
char directory2[sizeof(path_home)+100];
regs.r[0] = 10;
regs.r[1] = (int)path;
regs.r[2] = (int)buf;
regs.r[3] = 1;
regs.r[4] = 0;
regs.r[5] = sizeof(buf);
regs.r[6] = 0;
while(regs.r[3] > 0)
{
error = _kernel_swi(0x0c+0x20000,&regs,&regs); /* OS_GBPB 10, read directory entries */
if((error != NULL) || (regs.r[3] == 0))
{
break;
}
type = (int *)(&buf[16]);
len = strlen(&buf[20]);
sprintf(fname,"%s.%s",path,&buf[20]);
if(*type == 2)
{
// a sub-directory
GetVoices(fname);
}
else
{
// a regular line, add it to the voices list
if((f_voice = fopen(fname,"r")) == NULL)
continue;
// pass voice file name within the voices directory
voice_data = ReadVoiceFile(f_voice, fname+len_path_voices, &buf[20]);
fclose(f_voice);
if(voice_data != NULL)
{
voices_list[n_voices_list++] = voice_data;
}
}
}
#else
#ifdef PLATFORM_WINDOWS
WIN32_FIND_DATA FindFileData;
+18 -10
View File
@@ -748,12 +748,6 @@ void WavegenInit(int rate, int wavemult_fact)
for(ix=0; ix<N_EMBEDDED_VALUES; ix++)
embedded_value[ix] = embedded_default[ix];
if(rate <= 11000)
{
// adjust some parameters for telephony with low sample rates
consonant_amp = 50;
option_harmonic1 = 6;
}
// set up window to generate a spread of harmonics from a
// single peak for HF peaks
@@ -1011,7 +1005,7 @@ static void AdvanceParameters()
} // end of AdvanceParameters
#ifndef PLATFORM_RISCOS
static double resonator(RESONATOR *r, double input)
{//================================================
double x;
@@ -1055,11 +1049,12 @@ static void setresonator(RESONATOR *rp, int freq, int bwidth, int init)
// a = 1.0 - b - c
rp->a = 1.0 - rp->b - rp->c;
} // end if setresonator
#endif
void InitBreath(void)
{//==================
#ifndef PLATFORM_RISCOS
int ix;
minus_pi_t = -PI / samplerate;
@@ -1069,12 +1064,14 @@ void InitBreath(void)
{
setresonator(&rbreath[ix],2000,200,1);
}
#endif
} // end of InitBreath
void SetBreath()
{//=============
#ifndef PLATFORM_RISCOS
int pk;
if(wvoice->breath[0] == 0)
@@ -1089,15 +1086,17 @@ void SetBreath()
setresonator(&rbreath[pk], peaks[pk].freq >> 16, wvoice->breathw[pk],0);
}
}
#endif
} // end of SetBreath
int ApplyBreath(void)
{//==================
int value = 0;
#ifndef PLATFORM_RISCOS
int noise;
int ix;
int amp;
int value = 0;
// use two random numbers, for alternate formants
noise = (rand() & 0x3fff) - 0x2000;
@@ -1110,6 +1109,7 @@ int ApplyBreath(void)
value += int(resonator(&rbreath[ix],noise) * amp);
}
}
#endif
return (value);
}
@@ -1320,10 +1320,12 @@ int Wavegen()
total = (total >> 6) * voicing;
}
#ifndef PLATFORM_RISCOS
if(wvoice->breath[0])
{
total += ApplyBreath();
}
#endif
// mix with sampled wave if required
z2 = 0;
@@ -1558,6 +1560,12 @@ void WavegenSetVoice(voice_t *v)
else
pk_shape = pk_shape2;
consonant_amp = (v->consonant_amp * 26) /100;
if(samplerate <= 11000)
{
consonant_amp = consonant_amp*2; // emphasize consonants at low sample rates
option_harmonic1 = 6;
}
WavegenSetEcho();
}
@@ -1571,7 +1579,7 @@ static void SetAmplitude(int length, unsigned char *amp_env, int value)
amp_inc = (256 * ENV_LEN * STEPSIZE)/length;
amplitude = (value * general_amplitude)/16;
amplitude_v = amplitude * 15; // for wave mixed with voiced sounds
amplitude_v = (amplitude * wvoice->consonant_ampv * 15)/100; // for wave mixed with voiced sounds
amplitude_env = amp_env;
}