Browse Source

Reformat the code using the uncrustify program.

master
Reece H. Dunn 9 years ago
parent
commit
12e0bb122b
40 changed files with 8948 additions and 12757 deletions
  1. 183
    254
      src/espeak-ng.c
  2. 959
    1269
      src/libespeak-ng/compiledata.c
  3. 515
    717
      src/libespeak-ng/compiledict.c
  4. 20
    28
      src/libespeak-ng/compilembrola.c
  5. 13
    19
      src/libespeak-ng/debug.c
  6. 5
    5
      src/libespeak-ng/debug.h
  7. 804
    1296
      src/libespeak-ng/dictionary.c
  8. 155
    203
      src/libespeak-ng/espeak_command.c
  9. 36
    46
      src/libespeak-ng/espeak_command.h
  10. 139
    197
      src/libespeak-ng/event.c
  11. 3
    3
      src/libespeak-ng/event.h
  12. 95
    144
      src/libespeak-ng/fifo.c
  13. 4
    4
      src/libespeak-ng/fifo.h
  14. 241
    375
      src/libespeak-ng/intonation.c
  15. 176
    265
      src/libespeak-ng/klatt.c
  16. 4
    7
      src/libespeak-ng/klatt.h
  17. 2
    2
      src/libespeak-ng/mbrowrap.c
  18. 679
    973
      src/libespeak-ng/numbers.c
  19. 3
    3
      src/libespeak-ng/phoneme.h
  20. 123
    224
      src/libespeak-ng/phonemelist.c
  21. 878
    1190
      src/libespeak-ng/readclause.c
  22. 165
    284
      src/libespeak-ng/setlengths.c
  23. 220
    307
      src/libespeak-ng/speak_lib.c
  24. 105
    138
      src/libespeak-ng/spect.c
  25. 2
    4
      src/libespeak-ng/spect.h
  26. 1
    1
      src/libespeak-ng/speech.h
  27. 148
    204
      src/libespeak-ng/synth_mbrola.c
  28. 270
    403
      src/libespeak-ng/synthdata.c
  29. 399
    625
      src/libespeak-ng/synthesize.c
  30. 3
    3
      src/libespeak-ng/synthesize.h
  31. 466
    516
      src/libespeak-ng/tr_languages.c
  32. 775
    1221
      src/libespeak-ng/translate.c
  33. 7
    8
      src/libespeak-ng/translate.h
  34. 466
    626
      src/libespeak-ng/voices.c
  35. 237
    326
      src/libespeak-ng/wave.c
  36. 9
    9
      src/libespeak-ng/wave.h
  37. 64
    79
      src/libespeak-ng/wave_pulse.c
  38. 40
    44
      src/libespeak-ng/wave_sada.c
  39. 335
    468
      src/libespeak-ng/wavegen.c
  40. 199
    267
      src/speak-ng.c

+ 183
- 254
src/espeak-ng.c View File

@@ -31,7 +31,7 @@
#include "speak_lib.h"
#include "espeak_ng.h"

extern void strncpy0(char *to,const char *from, int size);
extern void strncpy0(char *to, const char *from, int size);
extern int utf8_in(int *c, const char *buf);
extern int GetFileLength(const char *filename);

@@ -132,59 +132,50 @@ void DisplayVoices(FILE *f_out, char *language)
const espeak_VOICE **voices;
espeak_VOICE voice_select;

static char genders[4] = {'-','M','F','-'};
static char genders[4] = { '-', 'M', 'F', '-' };

if((language != NULL) && (language[0] != 0))
{
if ((language != NULL) && (language[0] != 0)) {
// display only voices for the specified language, in order of priority
voice_select.languages = language;
voice_select.age = 0;
voice_select.gender = 0;
voice_select.name = NULL;
voices = espeak_ListVoices(&voice_select);
}
else
{
} else {
voices = espeak_ListVoices(NULL);
}

fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Languages\n");
fprintf(f_out, "Pty Language Age/Gender VoiceName File Other Languages\n");

for(ix=0; (v = voices[ix]) != NULL; ix++)
{
for (ix = 0; (v = voices[ix]) != NULL; ix++) {
count = 0;
p = v->languages;
while(*p != 0)
{
while (*p != 0) {
len = strlen(p+1);
lang_name = p+1;

if(v->age == 0)
strcpy(age_buf," ");
if (v->age == 0)
strcpy(age_buf, " ");
else
sprintf(age_buf,"%3d",v->age);
sprintf(age_buf, "%3d", v->age);

if(count==0)
{
for(j=0; j < sizeof(buf); j++)
{
if (count == 0) {
for (j = 0; j < sizeof(buf); j++) {
// replace spaces in the name
if((c = v->name[j]) == ' ')
if ((c = v->name[j]) == ' ')
c = '_';
if((buf[j] = c) == 0)
if ((buf[j] = c) == 0)
break;
}
fprintf(f_out,"%2d %-12s%s%c %-20s %-13s ",
p[0],lang_name,age_buf,genders[v->gender],buf,v->identifier);
}
else
{
fprintf(f_out,"(%s %d)",lang_name,p[0]);
fprintf(f_out, "%2d %-12s%s%c %-20s %-13s ",
p[0], lang_name, age_buf, genders[v->gender], buf, v->identifier);
} else {
fprintf(f_out, "(%s %d)", lang_name, p[0]);
}
count++;
p += len+2;
}
fputc('\n',f_out);
fputc('\n', f_out);
}
}

@@ -196,9 +187,8 @@ static void Write4Bytes(FILE *f, int value)
// Write 4 bytes to a file, least significant first
int ix;

for(ix=0; ix<4; ix++)
{
fputc(value & 0xff,f);
for (ix = 0; ix < 4; ix++) {
fputc(value & 0xff, f);
value = value >> 8;
}
}
@@ -208,37 +198,35 @@ static void Write4Bytes(FILE *f, int value)
int OpenWavFile(char *path, int rate)
{
static unsigned char wave_hdr[44] = {
'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ',
0x10,0,0,0,1,0,1,0, 9,0x3d,0,0,0x12,0x7a,0,0,
2,0,0x10,0,'d','a','t','a', 0x00,0xf0,0xff,0x7f
'R', 'I', 'F', 'F', 0x24, 0xf0, 0xff, 0x7f, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ',
0x10, 0, 0, 0, 1, 0, 1, 0, 9, 0x3d, 0, 0, 0x12, 0x7a, 0, 0,
2, 0, 0x10, 0, 'd', 'a', 't', 'a', 0x00, 0xf0, 0xff, 0x7f
};

if(path == NULL)
return(2);
if (path == NULL)
return (2);

while(isspace(*path)) path++;
while (isspace(*path)) path++;

f_wavfile = NULL;
if(path[0] != 0)
{
if(strcmp(path,"stdout")==0)
if (path[0] != 0) {
if (strcmp(path, "stdout") == 0)
f_wavfile = stdout;
else
f_wavfile = fopen(path,"wb");
f_wavfile = fopen(path, "wb");
}

if(f_wavfile == NULL)
{
fprintf(stderr,"Can't write to: '%s'\n",path);
return(1);
if (f_wavfile == NULL) {
fprintf(stderr, "Can't write to: '%s'\n", path);
return (1);
}


fwrite(wave_hdr,1,24,f_wavfile);
Write4Bytes(f_wavfile,rate);
Write4Bytes(f_wavfile,rate * 2);
fwrite(&wave_hdr[32],1,12,f_wavfile);
return(0);
fwrite(wave_hdr, 1, 24, f_wavfile);
Write4Bytes(f_wavfile, rate);
Write4Bytes(f_wavfile, rate * 2);
fwrite(&wave_hdr[32], 1, 12, f_wavfile);
return (0);
}


@@ -247,17 +235,17 @@ static void CloseWavFile()
{
unsigned int pos;

if((f_wavfile==NULL) || (f_wavfile == stdout))
if ((f_wavfile == NULL) || (f_wavfile == stdout))
return;

fflush(f_wavfile);
pos = ftell(f_wavfile);

fseek(f_wavfile,4,SEEK_SET);
Write4Bytes(f_wavfile,pos - 8);
fseek(f_wavfile, 4, SEEK_SET);
Write4Bytes(f_wavfile, pos - 8);

fseek(f_wavfile,40,SEEK_SET);
Write4Bytes(f_wavfile,pos - 44);
fseek(f_wavfile, 40, SEEK_SET);
Write4Bytes(f_wavfile, pos - 44);

fclose(f_wavfile);
f_wavfile = NULL;
@@ -269,27 +257,20 @@ static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events)
{
char fname[210];

if(quiet) return(0); // -q quiet mode
if (quiet) return (0); // -q quiet mode

if(wav == NULL)
{
if (wav == NULL) {
CloseWavFile();
return(0);
return (0);
}

while(events->type != 0)
{
if(events->type == espeakEVENT_SAMPLERATE)
{
while (events->type != 0) {
if (events->type == espeakEVENT_SAMPLERATE) {
samplerate = events->id.number;
samples_split = samples_split_seconds * samplerate;
}
else
if(events->type == espeakEVENT_SENTENCE)
{
} else if (events->type == espeakEVENT_SENTENCE) {
// start a new WAV file when the limit is reached, at this sentence boundary
if((samples_split > 0) && (samples_total > samples_split))
{
if ((samples_split > 0) && (samples_total > samples_split)) {
CloseWavFile();
samples_total = 0;
wavefile_count++;
@@ -298,27 +279,22 @@ static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events)
events++;
}

if(f_wavfile == NULL)
{
if(samples_split > 0)
{
sprintf(fname,"%s_%.2d%s",wavefile,wavefile_count+1,filetype);
if(OpenWavFile(fname, samplerate) != 0)
return(1);
}
else
{
if(OpenWavFile(wavefile, samplerate) != 0)
return(1);
if (f_wavfile == NULL) {
if (samples_split > 0) {
sprintf(fname, "%s_%.2d%s", wavefile, wavefile_count+1, filetype);
if (OpenWavFile(fname, samplerate) != 0)
return (1);
} else {
if (OpenWavFile(wavefile, samplerate) != 0)
return (1);
}
}

if(numsamples > 0)
{
if (numsamples > 0) {
samples_total += numsamples;
fwrite(wav,numsamples*2,1,f_wavfile);
fwrite(wav, numsamples*2, 1, f_wavfile);
}
return(0);
return (0);
}


@@ -343,42 +319,41 @@ struct option {
int optind;
static int optional_argument;
static const char *arg_opts = "abfgklpsvw"; // which options have arguments
static char *opt_string="";
static char *opt_string = "";
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#endif

int main (int argc, char **argv)
int main(int argc, char **argv)
{
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"stdin", no_argument, 0, 0x100},
{"compile-debug", optional_argument, 0, 0x101},
{"compile", optional_argument, 0, 0x102},
{"punct", optional_argument, 0, 0x103},
{"voices", optional_argument, 0, 0x104},
{"stdout", no_argument, 0, 0x105},
{"split", optional_argument, 0, 0x106},
{"path", required_argument, 0, 0x107},
{"phonout", required_argument, 0, 0x108},
{"pho", no_argument, 0, 0x109},
{"ipa", optional_argument, 0, 0x10a},
{"version", no_argument, 0, 0x10b},
{"sep", optional_argument, 0, 0x10c},
{"tie", optional_argument, 0, 0x10d},
{"compile-mbrola", optional_argument, 0, 0x10e},
{"compile-intonations", no_argument, 0, 0x10f},
{"compile-phonemes", no_argument, 0, 0x110},
{0, 0, 0, 0}
static struct option long_options[] = {
{ "help", no_argument, 0, 'h' },
{ "stdin", no_argument, 0, 0x100 },
{ "compile-debug", optional_argument, 0, 0x101 },
{ "compile", optional_argument, 0, 0x102 },
{ "punct", optional_argument, 0, 0x103 },
{ "voices", optional_argument, 0, 0x104 },
{ "stdout", no_argument, 0, 0x105 },
{ "split", optional_argument, 0, 0x106 },
{ "path", required_argument, 0, 0x107 },
{ "phonout", required_argument, 0, 0x108 },
{ "pho", no_argument, 0, 0x109 },
{ "ipa", optional_argument, 0, 0x10a },
{ "version", no_argument, 0, 0x10b },
{ "sep", optional_argument, 0, 0x10c },
{ "tie", optional_argument, 0, 0x10d },
{ "compile-mbrola", optional_argument, 0, 0x10e },
{ "compile-intonations", no_argument, 0, 0x10f },
{ "compile-phonemes", no_argument, 0, 0x110 },
{ 0, 0, 0, 0 }
};

static const char* err_load = "Failed to read ";
static const char *err_load = "Failed to read ";


FILE *f_text=NULL;
char *p_text=NULL;
FILE *f_text = NULL;
char *p_text = NULL;
FILE *f_phonemes_out = stdout;
char *data_path = NULL; // use default path for espeak-data

@@ -417,15 +392,13 @@ int main (int argc, char **argv)
#ifdef NEED_GETOPT
optind = 1;
opt_string = "";
while(optind < argc)
{
while (optind < argc) {
int len;
char *p;

if((c = *opt_string) == 0)
{
if ((c = *opt_string) == 0) {
opt_string = argv[optind];
if(opt_string[0] != '-')
if (opt_string[0] != '-')
break;

optind++;
@@ -435,45 +408,36 @@ int main (int argc, char **argv)
opt_string++;
p = optarg2 = opt_string;

if(c == '-')
{
if(p[0] == 0)
if (c == '-') {
if (p[0] == 0)
break; // -- means don't interpret further - as commands

opt_string="";
for(ix=0;; ix++)
{
if(long_options[ix].name == 0)
opt_string = "";
for (ix = 0;; ix++) {
if (long_options[ix].name == 0)
break;
len = strlen(long_options[ix].name);
if(memcmp(long_options[ix].name,p,len)==0)
{
if (memcmp(long_options[ix].name, p, len) == 0) {
c = long_options[ix].val;
optarg2 = NULL;

if((long_options[ix].has_arg != 0) && (p[len]=='='))
{
if ((long_options[ix].has_arg != 0) && (p[len] == '=')) {
optarg2 = &p[len+1];
}
break;
}
}
}
else
if(strchr(arg_opts,c) != NULL)
{
opt_string="";
if(optarg2[0]==0)
{
} else if (strchr(arg_opts, c) != NULL) {
opt_string = "";
if (optarg2[0] == 0) {
// the option's value is in the next argument
optarg2 = argv[optind++];
}
}
#else
while(true)
{
c = getopt_long (argc, argv, "a:b:f:g:hk:l:mp:qs:v:w:xXz",
long_options, &option_index);
while (true) {
c = getopt_long(argc, argv, "a:b:f:g:hk:l:mp:qs:v:w:xXz",
long_options, &option_index);

/* Detect the end of the options. */
if (c == -1)
@@ -485,7 +449,7 @@ int main (int argc, char **argv)
{
case 'b':
// input character encoding, 8bit, 16bit, UTF8
if((sscanf(optarg2,"%d",&value) == 1) && (value <= 4))
if ((sscanf(optarg2, "%d", &value) == 1) && (value <= 4))
synth_flags |= value;
else
synth_flags |= espeakCHARS_8BIT;
@@ -523,7 +487,7 @@ int main (int argc, char **argv)
break;

case 'f':
strncpy0(filename,optarg2,sizeof(filename));
strncpy0(filename, optarg2, sizeof(filename));
break;

case 'l':
@@ -543,12 +507,12 @@ int main (int argc, char **argv)
break;

case 'v':
strncpy0(voicename,optarg2,sizeof(voicename));
strncpy0(voicename, optarg2, sizeof(voicename));
break;

case 'w':
option_waveout = 1;
strncpy0(wavefile,optarg2,sizeof(filename));
strncpy0(wavefile, optarg2, sizeof(filename));
break;

case 'z': // remove pause from the end of a sentence
@@ -561,34 +525,33 @@ int main (int argc, char **argv)

case 0x105: // --stdout
option_waveout = 1;
strcpy(wavefile,"stdout");
strcpy(wavefile, "stdout");
break;

case 0x101: // --compile-debug
case 0x102: // --compile
strncpy0(voicename,optarg2,sizeof(voicename));
strncpy0(voicename, optarg2, sizeof(voicename));
flag_compile = c;
quiet = 1;
break;

case 0x103: // --punct
option_punctuation = 1;
if(optarg2 != NULL)
{
if (optarg2 != NULL) {
ix = 0;
while((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++;
while ((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++;
option_punctlist[N_PUNCTLIST-1] = 0;
option_punctuation = 2;
}
break;

case 0x104: // --voices
espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,0,data_path,0);
DisplayVoices(stdout,optarg2);
espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0);
DisplayVoices(stdout, optarg2);
exit(0);

case 0x106: // -- split
if(optarg2 == NULL)
if (optarg2 == NULL)
samples_split_seconds = 30 * 60; // default 30 minutes
else
samples_split_seconds = atoi(optarg2) * 60;
@@ -599,9 +562,8 @@ int main (int argc, char **argv)
break;

case 0x108: // --phonout
if((f_phonemes_out = fopen(optarg2,"w")) == NULL)
{
fprintf(stderr,"Can't write to: %s\n",optarg2);
if ((f_phonemes_out = fopen(optarg2, "w")) == NULL) {
fprintf(stderr, "Can't write to: %s\n", optarg2);
}
break;

@@ -611,10 +573,9 @@ int main (int argc, char **argv)

case 0x10a: // --ipa
phoneme_options |= espeakPHONEMES_IPA;
if(optarg2 != NULL)
{
if (optarg2 != NULL) {
// deprecated and obsolete
switch(atoi(optarg2))
switch (atoi(optarg2))
{
case 1:
phonemes_separator = '_';
@@ -638,36 +599,36 @@ int main (int argc, char **argv)

case 0x10c: // --sep
phoneme_options |= espeakPHONEMES_SHOW;
if(optarg2 == 0)
if (optarg2 == 0)
phonemes_separator = ' ';
else
utf8_in(&phonemes_separator, optarg2);
if(phonemes_separator == 'z')
if (phonemes_separator == 'z')
phonemes_separator = 0x200c; // ZWNJ
break;

case 0x10d: // --tie
phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE);
if(optarg2 == 0)
if (optarg2 == 0)
phonemes_separator = 0x0361; // default: combining-double-inverted-breve
else
utf8_in(&phonemes_separator, optarg2);
if(phonemes_separator == 'z')
if (phonemes_separator == 'z')
phonemes_separator = 0x200d; // ZWJ
break;

case 0x10e: // --compile-mbrola
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0);
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0);
espeak_ng_CompileMbrolaVoice(optarg2, stdout);
exit(0);

case 0x10f: // --compile-intonations
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,espeakINITIALIZE_PATH_ONLY);
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY);
espeak_ng_CompileIntonation(stdout);
exit(0);

case 0x110: // --compile-phonemes
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,espeakINITIALIZE_PATH_ONLY);
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY);
espeak_ng_CompilePhonemeData(22050, stdout);
exit(0);

@@ -677,167 +638,135 @@ int main (int argc, char **argv)
}


if(option_waveout || quiet)
{
if (option_waveout || quiet) {
// writing to a file (or no output), we can use synchronous mode
samplerate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,0,data_path,0);
samplerate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0);
samples_split = samplerate * samples_split_seconds;

espeak_SetSynthCallback(SynthCallback);
if(samples_split)
{
if (samples_split) {
char *extn;
extn = strrchr(wavefile,'.');
if((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4))
{
strcpy(filetype,extn);
extn = strrchr(wavefile, '.');
if ((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) {
strcpy(filetype, extn);
*extn = 0;
}
}
}
else
{
} else {
// play the sound output
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0);
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0);
}


if(voicename[0] == 0)
strcpy(voicename,"default");
if (voicename[0] == 0)
strcpy(voicename, "default");

if(espeak_SetVoiceByName(voicename) != EE_OK)
{
memset(&voice_select,0,sizeof(voice_select));
if (espeak_SetVoiceByName(voicename) != EE_OK) {
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);
if (espeak_SetVoiceByProperties(&voice_select) != EE_OK) {
fprintf(stderr, "%svoice '%s'\n", err_load, voicename);
exit(2);
}
}

if(flag_compile)
{
if (flag_compile) {
// This must be done after the voice is set
espeak_CompileDictionary("", stderr, flag_compile & 0x1);
exit(0);
}

// set any non-default values of parameters. This must be done after espeak_Initialize()
if(speed > 0)
espeak_SetParameter(espeakRATE,speed,0);
if(volume >= 0)
espeak_SetParameter(espeakVOLUME,volume,0);
if(pitch >= 0)
espeak_SetParameter(espeakPITCH,pitch,0);
if(option_capitals >= 0)
espeak_SetParameter(espeakCAPITALS,option_capitals,0);
if(option_punctuation >= 0)
espeak_SetParameter(espeakPUNCTUATION,option_punctuation,0);
if(wordgap >= 0)
espeak_SetParameter(espeakWORDGAP,wordgap,0);
if(option_linelength > 0)
espeak_SetParameter(espeakLINELENGTH,option_linelength,0);
if(option_punctuation == 2)
if (speed > 0)
espeak_SetParameter(espeakRATE, speed, 0);
if (volume >= 0)
espeak_SetParameter(espeakVOLUME, volume, 0);
if (pitch >= 0)
espeak_SetParameter(espeakPITCH, pitch, 0);
if (option_capitals >= 0)
espeak_SetParameter(espeakCAPITALS, option_capitals, 0);
if (option_punctuation >= 0)
espeak_SetParameter(espeakPUNCTUATION, option_punctuation, 0);
if (wordgap >= 0)
espeak_SetParameter(espeakWORDGAP, wordgap, 0);
if (option_linelength > 0)
espeak_SetParameter(espeakLINELENGTH, option_linelength, 0);
if (option_punctuation == 2)
espeak_SetPunctuationList(option_punctlist);


espeak_SetPhonemeTrace(phoneme_options | (phonemes_separator << 8), f_phonemes_out);

if(filename[0]==0)
{
if((optind < argc) && (flag_stdin == 0))
{
if (filename[0] == 0) {
if ((optind < argc) && (flag_stdin == 0)) {
// there's a non-option parameter, and no -f or --stdin
// use it as text
p_text = argv[optind];
}
else
{
} else {
f_text = stdin;
if(flag_stdin == 0)
{
if (flag_stdin == 0) {
flag_stdin = 2;
}
}
}
else
{
} else {
filesize = GetFileLength(filename);
f_text = fopen(filename,"r");
f_text = fopen(filename, "r");
}

if((f_text == NULL) && (p_text == NULL))
{
fprintf(stderr,"%sfile '%s'\n",err_load,filename);
if ((f_text == NULL) && (p_text == NULL)) {
fprintf(stderr, "%sfile '%s'\n", err_load, filename);
exit(1);
}


if(p_text != NULL)
{
if (p_text != NULL) {
int size;
size = strlen(p_text);
espeak_Synth(p_text,size+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL);
}
else
if(flag_stdin)
{
espeak_Synth(p_text, size+1, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL);
} else if (flag_stdin) {
int max = 1000;
p_text = (char *)malloc(max);

if(flag_stdin == 2)
{
if (flag_stdin == 2) {
// line by line input on stdin
while(fgets(p_text,max,stdin) != NULL)
{
while (fgets(p_text, max, stdin) != NULL) {
p_text[max-1] = 0;
espeak_Synth(p_text,max,0,POS_CHARACTER,0,synth_flags,NULL,NULL);
espeak_Synth(p_text, max, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL);

}
}
else
{
} else {
// bulk input on stdin
ix = 0;
while(!feof(stdin))
{
while (!feof(stdin)) {
p_text[ix++] = fgetc(stdin);
if(ix >= (max-1))
{
if (ix >= (max-1)) {
max += 1000;
p_text = (char *)realloc(p_text,max);
p_text = (char *)realloc(p_text, max);
}
}
if(ix > 0)
{
if (ix > 0) {
p_text[ix-1] = 0;
espeak_Synth(p_text,ix+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL);
espeak_Synth(p_text, ix+1, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL);
}
}
}
else
if(f_text != NULL)
{
if((p_text = (char *)malloc(filesize+1)) == NULL)
{
fprintf(stderr,"Failed to allocate memory %d bytes",filesize);
} else if (f_text != NULL) {
if ((p_text = (char *)malloc(filesize+1)) == NULL) {
fprintf(stderr, "Failed to allocate memory %d bytes", filesize);
exit(3);
}

fread(p_text,1,filesize,f_text);
p_text[filesize]=0;
espeak_Synth(p_text,filesize+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL);
fread(p_text, 1, filesize, f_text);
p_text[filesize] = 0;
espeak_Synth(p_text, filesize+1, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL);
fclose(f_text);
}

if(espeak_Synchronize() != EE_OK)
{
if (espeak_Synchronize() != EE_OK) {
fprintf(stderr, "espeak_Synchronize() failed, maybe error when opening output device\n");
exit(4);
}

if(f_phonemes_out != stdout)
if (f_phonemes_out != stdout)
fclose(f_phonemes_out); // needed for WinCE
return(0);
return (0);
}

+ 959
- 1269
src/libespeak-ng/compiledata.c
File diff suppressed because it is too large
View File


+ 515
- 717
src/libespeak-ng/compiledict.c
File diff suppressed because it is too large
View File


+ 20
- 28
src/libespeak-ng/compilembrola.c View File

@@ -48,17 +48,16 @@ static unsigned int StringToWord(const char *string)
unsigned char c;
unsigned int word;

if(string==NULL)
return(0);
if (string == NULL)
return (0);

word = 0;
for(ix=0; ix<4; ix++)
{
if(string[ix]==0) break;
for (ix = 0; ix < 4; ix++) {
if (string[ix] == 0) break;
c = string[ix];
word |= (c << (ix*8));
}
return(word);
return (word);
}

#pragma GCC visibility push(default)
@@ -82,34 +81,29 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log)
int mbrola_ctrl = 20; // volume in 1/16 ths
MBROLA_TAB data[N_PHONEME_TAB];

strcpy(buf,filepath);
if((f_in = fopen(buf,"r")) == NULL)
{
strcpy(buf, filepath);
if ((f_in = fopen(buf, "r")) == NULL) {
fprintf(log, "Can't read: %s\n", filepath);
return ENE_READ_ERROR;
}

while(fgets(buf,sizeof(phoneme),f_in) != NULL)
{
while (fgets(buf, sizeof(phoneme), f_in) != NULL) {
buf[sizeof(phoneme)-1] = 0;

if((p = strstr(buf,"//")) != NULL)
if ((p = strstr(buf, "//")) != NULL)
*p = 0; // truncate line at comment

if(memcmp(buf,"volume",6)==0)
{
if (memcmp(buf, "volume", 6) == 0) {
mbrola_ctrl = atoi(&buf[6]);
continue;
}

n = sscanf(buf,"%d %s %s %d %s %s",&control,phoneme,phoneme2,&percent,name1,name2);
if(n >= 5)
{
n = sscanf(buf, "%d %s %s %d %s %s", &control, phoneme, phoneme2, &percent, name1, name2);
if (n >= 5) {
data[count].name = StringToWord(phoneme);
if(strcmp(phoneme2,"NULL")==0)
if (strcmp(phoneme2, "NULL") == 0)
data[count].next_phoneme = 0;
else
if(strcmp(phoneme2,"VWL")==0)
else if (strcmp(phoneme2, "VWL") == 0)
data[count].next_phoneme = 2;
else
data[count].next_phoneme = StringToWord(phoneme2);
@@ -117,9 +111,9 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log)
data[count].mbr_name2 = 0;
data[count].percent = percent;
data[count].control = control;
if(strcmp(name1,"NULL")!=0)
if (strcmp(name1, "NULL") != 0)
data[count].mbr_name = StringToWord(name1);
if(n == 6)
if (n == 6)
data[count].mbr_name2 = StringToWord(name2);

count++;
@@ -127,10 +121,9 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log)
}
fclose(f_in);

strcpy(mbrola_voice,basename(filepath));
sprintf(buf,"%s/mbrola_ph/%s_phtrans",path_home,mbrola_voice);
if((f_out = fopen(buf,"wb")) == NULL)
{
strcpy(mbrola_voice, basename(filepath));
sprintf(buf, "%s/mbrola_ph/%s_phtrans", path_home, mbrola_voice);
if ((f_out = fopen(buf, "wb")) == NULL) {
fprintf(log, "Can't write to: %s\n", buf);
return ENE_WRITE_ERROR;
}
@@ -139,8 +132,7 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log)
Write4Bytes(f_out, mbrola_ctrl);

pw_end = (int *)(&data[count+1]);
for(pw = (int *)data; pw < pw_end; pw++)
{
for (pw = (int *)data; pw < pw_end; pw++) {
Write4Bytes(f_out, *pw);
}
fclose(f_out);

+ 13
- 19
src/libespeak-ng/debug.c View File

@@ -27,29 +27,27 @@
#include <sys/time.h>
#include <unistd.h>

static FILE* fd_log=NULL;
static const char* FILENAME="/tmp/espeak.log";
static FILE *fd_log = NULL;
static const char *FILENAME = "/tmp/espeak.log";

void debug_init()
{
if((fd_log = fopen(FILENAME,"a")) != NULL)
if ((fd_log = fopen(FILENAME, "a")) != NULL)
setvbuf(fd_log, NULL, _IONBF, 0);
}

void debug_enter(const char* text)
void debug_enter(const char *text)
{
struct timeval tv;

gettimeofday(&tv, NULL);

if (!fd_log)
{
if (!fd_log) {
debug_init();
}

if (fd_log)
{
fprintf(fd_log, "%03d.%03dms > ENTER %s\n",(int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text);
if (fd_log) {
fprintf(fd_log, "%03d.%03dms > ENTER %s\n", (int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text);
}
}

@@ -58,30 +56,26 @@ void debug_show(const char *format, ...)
{
va_list args;
va_start(args, format);
if (!fd_log)
{
if (!fd_log) {
debug_init();
}
if (fd_log)
{
if (fd_log) {
vfprintf(fd_log, format, args);
}
va_end(args);
}

void debug_time(const char* text)
void debug_time(const char *text)
{
struct timeval tv;

gettimeofday(&tv, NULL);

if (!fd_log)
{
if (!fd_log) {
debug_init();
}
if (fd_log)
{
fprintf(fd_log, "%03d.%03dms > %s\n",(int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text);
if (fd_log) {
fprintf(fd_log, "%03d.%03dms > %s\n", (int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text);
}
}


+ 5
- 5
src/libespeak-ng/debug.h View File

@@ -27,18 +27,18 @@ extern "C"

#ifdef DEBUG_ENABLED
#define ENTER(text) debug_enter(text)
#define SHOW(format,...) debug_show(format,__VA_ARGS__);
#define SHOW(format, ...) debug_show(format, __VA_ARGS__);
#define SHOW_TIME(text) debug_time(text);
extern void debug_enter(const char* text);
extern void debug_show(const char* format,...);
extern void debug_time(const char* text);
extern void debug_enter(const char *text);
extern void debug_show(const char *format, ...);
extern void debug_time(const char *text);

#else

#ifdef NO_VARIADIC_MACROS
#define SHOW(format) // VC6 doesn't allow "..."
#else
#define SHOW(format,...)
#define SHOW(format, ...)
#endif
#define SHOW_TIME(text)
#define ENTER(text)

+ 804
- 1296
src/libespeak-ng/dictionary.c
File diff suppressed because it is too large
View File


+ 155
- 203
src/libespeak-ng/espeak_command.c View File

@@ -27,24 +27,22 @@

#include "debug.h"

static unsigned int my_current_text_id=0;
static unsigned int my_current_text_id = 0;

t_espeak_command* create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void* user_data)
t_espeak_command *create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void *user_data)
{
ENTER("create_espeak_text");
int a_error=1;
void* a_text = NULL;
t_espeak_text* data = NULL;
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
int a_error = 1;
void *a_text = NULL;
t_espeak_text *data = NULL;
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command));

if (!text || !size || !a_command)
{
if (!text || !size || !a_command) {
goto text_error;
}

a_text = malloc( size+1 );
if (!a_text)
{
a_text = malloc(size+1);
if (!a_text) {
goto text_error;
}
memcpy(a_text, text, size);
@@ -60,20 +58,17 @@ t_espeak_command* create_espeak_text(const void *text, size_t size, unsigned int
data->end_position = end_position;
data->flags = flags;
data->user_data = user_data;
a_error=0;
a_error = 0;

SHOW("ET_TEXT malloc text=%x, command=%x (uid=%d)\n", a_text, a_command, data->unique_identifier);

text_error:
if (a_error)
{
if (a_text)
{
free (a_text);
if (a_error) {
if (a_text) {
free(a_text);
}
if (a_command)
{
free (a_command);
if (a_command) {
free(a_command);
}
a_command = NULL;
}
@@ -83,15 +78,14 @@ text_error:
return a_command;
}

t_espeak_command* create_espeak_terminated_msg(unsigned int unique_identifier, void* user_data)
t_espeak_command *create_espeak_terminated_msg(unsigned int unique_identifier, void *user_data)
{
ENTER("create_espeak_terminated_msg");
int a_error=1;
t_espeak_terminated_msg* data = NULL;
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
int a_error = 1;
t_espeak_terminated_msg *data = NULL;
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command));

if (!a_command)
{
if (!a_command) {
goto msg_error;
}

@@ -100,16 +94,14 @@ t_espeak_command* create_espeak_terminated_msg(unsigned int unique_identifier, v
data = &(a_command->u.my_terminated_msg);
data->unique_identifier = unique_identifier;
data->user_data = user_data;
a_error=0;
a_error = 0;

SHOW("ET_TERMINATED_MSG command=%x (uid=%d, user_data=0x%x)\n", a_command, unique_identifier, (int)user_data);

msg_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
}
a_command = NULL;
}
@@ -120,28 +112,26 @@ msg_error:

}

t_espeak_command* create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void* user_data)
t_espeak_command *create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void *user_data)
{
ENTER("create_espeak_mark");
int a_error=1;
void* a_text = NULL;
int a_error = 1;
void *a_text = NULL;
char *a_index_mark = NULL;
t_espeak_mark* data = NULL;
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
t_espeak_mark *data = NULL;
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command));

if (!text || !size || !index_mark || !a_command)
{
if (!text || !size || !index_mark || !a_command) {
goto mark_error;
}

a_text = malloc( size );
if (!a_text)
{
a_text = malloc(size);
if (!a_text) {
goto mark_error;
}
memcpy(a_text, text, size);

a_index_mark = strdup( index_mark);
a_index_mark = strdup(index_mark);

a_command->type = ET_MARK;
a_command->state = CS_UNDEFINED;
@@ -153,23 +143,19 @@ t_espeak_command* create_espeak_mark(const void *text, size_t size, const char *
data->end_position = end_position;
data->flags = flags;
data->user_data = user_data;
a_error=0;
a_error = 0;

mark_error:
if (a_error)
{
if (a_text)
{
free (a_text);
if (a_error) {
if (a_text) {
free(a_text);
}
if (a_command)
{
free (a_command);
if (a_command) {
free(a_command);
}
a_command = NULL;
if (a_index_mark)
{
free (a_index_mark);
if (a_index_mark) {
free(a_index_mark);
}
}

@@ -178,14 +164,13 @@ mark_error:
return a_command;
}

t_espeak_command* create_espeak_key(const char *key_name, void *user_data)
t_espeak_command *create_espeak_key(const char *key_name, void *user_data)
{
ENTER("create_espeak_key");
int a_error=1;
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
int a_error = 1;
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command));

if (!key_name || !a_command)
{
if (!key_name || !a_command) {
goto key_error;
}

@@ -193,15 +178,13 @@ t_espeak_command* create_espeak_key(const char *key_name, void *user_data)
a_command->state = CS_UNDEFINED;
a_command->u.my_key.user_data = user_data;
a_command->u.my_key.unique_identifier = ++my_current_text_id;
a_command->u.my_key.key_name = strdup( key_name);
a_error=0;
a_command->u.my_key.key_name = strdup(key_name);
a_error = 0;

key_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
}
a_command = NULL;
}
@@ -211,13 +194,12 @@ key_error:
return a_command;
}

t_espeak_command* create_espeak_char(wchar_t character, void* user_data)
t_espeak_command *create_espeak_char(wchar_t character, void *user_data)
{
ENTER("create_espeak_char");
int a_error=1;
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
if (!a_command)
{
int a_error = 1;
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command));
if (!a_command) {
goto char_error;
}

@@ -226,14 +208,12 @@ t_espeak_command* create_espeak_char(wchar_t character, void* user_data)
a_command->u.my_char.user_data = user_data;
a_command->u.my_char.unique_identifier = ++my_current_text_id;
a_command->u.my_char.character = character;
a_error=0;
a_error = 0;

char_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
}
a_command = NULL;
}
@@ -243,14 +223,13 @@ char_error:
return a_command;
}

t_espeak_command* create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative)
t_espeak_command *create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative)
{
ENTER("create_espeak_parameter");
int a_error=1;
t_espeak_parameter* data = NULL;
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
if (!a_command)
{
int a_error = 1;
t_espeak_parameter *data = NULL;
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command));
if (!a_command) {
goto param_error;
}

@@ -260,14 +239,12 @@ t_espeak_command* create_espeak_parameter(espeak_PARAMETER parameter, int value,
data->parameter = parameter;
data->value = value;
data->relative = relative;
a_error=0;
a_error = 0;

param_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
}
a_command = NULL;
}
@@ -277,14 +254,13 @@ param_error:
return a_command;
}

t_espeak_command* create_espeak_punctuation_list(const wchar_t *punctlist)
t_espeak_command *create_espeak_punctuation_list(const wchar_t *punctlist)
{
ENTER("create_espeak_punctuation_list");
int a_error=1;
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
int a_error = 1;
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command));

if (!punctlist || !a_command)
{
if (!punctlist || !a_command) {
goto list_error;
}

@@ -293,19 +269,17 @@ t_espeak_command* create_espeak_punctuation_list(const wchar_t *punctlist)

{
size_t len = (wcslen(punctlist) + 1)*sizeof(wchar_t);
wchar_t* a_list = (wchar_t*)malloc(len);
wchar_t *a_list = (wchar_t *)malloc(len);
memcpy(a_list, punctlist, len);
a_command->u.my_punctuation_list = a_list;
}

a_error=0;
a_error = 0;

list_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
}
a_command = NULL;
}
@@ -315,29 +289,26 @@ list_error:
return a_command;
}

t_espeak_command* create_espeak_voice_name(const char *name)
t_espeak_command *create_espeak_voice_name(const char *name)
{
ENTER("create_espeak_voice_name");

int a_error=1;
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
int a_error = 1;
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command));

if (!name || !a_command)
{
if (!name || !a_command) {
goto name_error;
}

a_command->type = ET_VOICE_NAME;
a_command->state = CS_UNDEFINED;
a_command->u.my_voice_name = strdup( name);
a_error=0;
a_command->u.my_voice_name = strdup(name);
a_error = 0;

name_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
}
a_command = NULL;
}
@@ -347,47 +318,41 @@ name_error:
return a_command;
}

t_espeak_command* create_espeak_voice_spec(espeak_VOICE *voice)
t_espeak_command *create_espeak_voice_spec(espeak_VOICE *voice)
{
ENTER("create_espeak_voice_spec");
int a_error=1;
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command));
int a_error = 1;
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command));

if (!voice || !a_command)
{
if (!voice || !a_command) {
goto spec_error;
}

a_command->type = ET_VOICE_SPEC;
a_command->state = CS_UNDEFINED;
{
espeak_VOICE* data = &(a_command->u.my_voice_spec);
espeak_VOICE *data = &(a_command->u.my_voice_spec);
memcpy(data, voice, sizeof(espeak_VOICE));

if (voice->name)
{
if (voice->name) {
data->name = strdup(voice->name);
}

if (voice->languages)
{
if (voice->languages) {
data->languages = strdup(voice->languages);
}

if (voice->identifier)
{
if (voice->identifier) {
data->identifier = strdup(voice->identifier);
}

a_error=0;
a_error = 0;
}

spec_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
}
a_command = NULL;
}
@@ -397,30 +362,26 @@ spec_error:
return a_command;
}

int delete_espeak_command( t_espeak_command* the_command)
int delete_espeak_command(t_espeak_command *the_command)
{
ENTER("delete_espeak_command");
int a_status = 0;
if (the_command)
{
switch(the_command->type)
if (the_command) {
switch (the_command->type)
{
case ET_TEXT:
if (the_command->u.my_text.text)
{
if (the_command->u.my_text.text) {
SHOW("delete_espeak_command > ET_TEXT free text=%x, command=%x, uid=%d\n", the_command->u.my_text.text, the_command, the_command->u.my_text.unique_identifier);
free(the_command->u.my_text.text);
}
break;

case ET_MARK:
if (the_command->u.my_mark.text)
{
if (the_command->u.my_mark.text) {
free(the_command->u.my_mark.text);
}
if (the_command->u.my_mark.index_mark)
{
free((void*)(the_command->u.my_mark.index_mark));
if (the_command->u.my_mark.index_mark) {
free((void *)(the_command->u.my_mark.index_mark));
}
break;

@@ -430,20 +391,18 @@ int delete_espeak_command( t_espeak_command* the_command)
// it must be processed here for informing the calling program
// that its message is finished.
// This can be important for cleaning the related user data.
t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg);
if (the_command->state == CS_PENDING)
{
t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg);
if (the_command->state == CS_PENDING) {
the_command->state = CS_PROCESSED;
SHOW("delete_espeak_command > ET_TERMINATED_MSG callback (command=0x%x, uid=%d) \n", the_command, data->unique_identifier);
sync_espeak_terminated_msg( data->unique_identifier, data->user_data);
sync_espeak_terminated_msg(data->unique_identifier, data->user_data);
}
}
break;

case ET_KEY:
if (the_command->u.my_key.key_name)
{
free((void*)(the_command->u.my_key.key_name));
if (the_command->u.my_key.key_name) {
free((void *)(the_command->u.my_key.key_name));
}
break;

@@ -453,35 +412,30 @@ int delete_espeak_command( t_espeak_command* the_command)
break;

case ET_PUNCTUATION_LIST:
if (the_command->u.my_punctuation_list)
{
free((void*)(the_command->u.my_punctuation_list));
if (the_command->u.my_punctuation_list) {
free((void *)(the_command->u.my_punctuation_list));
}
break;

case ET_VOICE_NAME:
if (the_command->u.my_voice_name)
{
free((void*)(the_command->u.my_voice_name));
if (the_command->u.my_voice_name) {
free((void *)(the_command->u.my_voice_name));
}
break;

case ET_VOICE_SPEC:
{
espeak_VOICE* data = &(the_command->u.my_voice_spec);
espeak_VOICE *data = &(the_command->u.my_voice_spec);

if (data->name)
{
if (data->name) {
free((void *)data->name);
}

if (data->languages)
{
if (data->languages) {
free((void *)data->languages);
}

if (data->identifier)
{
if (data->identifier) {
free((void *)data->identifier);
}
}
@@ -497,49 +451,48 @@ int delete_espeak_command( t_espeak_command* the_command)
return a_status;
}

void process_espeak_command( t_espeak_command* the_command)
void process_espeak_command(t_espeak_command *the_command)
{
ENTER("process_espeak_command");

SHOW("command=0x%x\n", the_command);

if (the_command == NULL)
{
if (the_command == NULL) {
return;
}

the_command->state = CS_PROCESSED;

switch(the_command->type)
switch (the_command->type)
{
case ET_TEXT:
{
t_espeak_text* data = &(the_command->u.my_text);
sync_espeak_Synth( data->unique_identifier, data->text, data->size,
data->position, data->position_type,
data->end_position, data->flags, data->user_data);
t_espeak_text *data = &(the_command->u.my_text);
sync_espeak_Synth(data->unique_identifier, data->text, data->size,
data->position, data->position_type,
data->end_position, data->flags, data->user_data);
}
break;

case ET_MARK:
{
t_espeak_mark* data = &(the_command->u.my_mark);
sync_espeak_Synth_Mark( data->unique_identifier, data->text, data->size,
data->index_mark, data->end_position, data->flags,
data->user_data);
t_espeak_mark *data = &(the_command->u.my_mark);
sync_espeak_Synth_Mark(data->unique_identifier, data->text, data->size,
data->index_mark, data->end_position, data->flags,
data->user_data);
}
break;

case ET_TERMINATED_MSG:
{
t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg);
sync_espeak_terminated_msg( data->unique_identifier, data->user_data);
t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg);
sync_espeak_terminated_msg(data->unique_identifier, data->user_data);
}
break;

case ET_KEY:
{
const char* data = the_command->u.my_key.key_name;
const char *data = the_command->u.my_key.key_name;
sync_espeak_Key(data);
}
break;
@@ -547,34 +500,34 @@ void process_espeak_command( t_espeak_command* the_command)
case ET_CHAR:
{
const wchar_t data = the_command->u.my_char.character;
sync_espeak_Char( data);
sync_espeak_Char(data);
}
break;

case ET_PARAMETER:
{
t_espeak_parameter* data = &(the_command->u.my_param);
SetParameter( data->parameter, data->value, data->relative);
t_espeak_parameter *data = &(the_command->u.my_param);
SetParameter(data->parameter, data->value, data->relative);
}
break;

case ET_PUNCTUATION_LIST:
{
const wchar_t* data = the_command->u.my_punctuation_list;
sync_espeak_SetPunctuationList( data);
const wchar_t *data = the_command->u.my_punctuation_list;
sync_espeak_SetPunctuationList(data);
}
break;

case ET_VOICE_NAME:
{
const char* data = the_command->u.my_voice_name;
SetVoiceByName( data);
const char *data = the_command->u.my_voice_name;
SetVoiceByName(data);
}
break;

case ET_VOICE_SPEC:
{
espeak_VOICE* data = &(the_command->u.my_voice_spec);
espeak_VOICE *data = &(the_command->u.my_voice_spec);
SetVoiceByProperties(data);
}
break;
@@ -585,44 +538,43 @@ void process_espeak_command( t_espeak_command* the_command)
}
}

void display_espeak_command( t_espeak_command* the_command)
void display_espeak_command(t_espeak_command *the_command)
{
ENTER("display_espeak_command");
#ifdef DEBUG_ENABLED
if (the_command == NULL)
{
SHOW("display_espeak_command > command=%s\n","NULL");
if (the_command == NULL) {
SHOW("display_espeak_command > command=%s\n", "NULL");
return;
}

SHOW("display_espeak_command > state=%d\n",the_command->state);
SHOW("display_espeak_command > state=%d\n", the_command->state);

switch(the_command->type)
switch (the_command->type)
{
case ET_TEXT:
{
t_espeak_text* data = &(the_command->u.my_text);
SHOW("display_espeak_command > (0x%x) uid=%d, TEXT=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char*)data->text, (int)(data->user_data));
t_espeak_text *data = &(the_command->u.my_text);
SHOW("display_espeak_command > (0x%x) uid=%d, TEXT=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char *)data->text, (int)(data->user_data));
}
break;

case ET_MARK:
{
t_espeak_mark* data = &(the_command->u.my_mark);
SHOW("display_espeak_command > (0x%x) uid=%d, MARK=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char*)data->text, (int)(data->user_data));
t_espeak_mark *data = &(the_command->u.my_mark);
SHOW("display_espeak_command > (0x%x) uid=%d, MARK=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char *)data->text, (int)(data->user_data));
}
break;

case ET_KEY:
{
const char* data = the_command->u.my_key.key_name;
const char *data = the_command->u.my_key.key_name;
SHOW("display_espeak_command > (0x%x) KEY=%c\n", the_command, data);
}
break;

case ET_TERMINATED_MSG:
{
t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg);
t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg);

SHOW("display_espeak_command > (0x%x) TERMINATED_MSG uid=%d, user_data=0x%x, state=%d\n",
the_command, data->unique_identifier, data->user_data,
@@ -639,7 +591,7 @@ void display_espeak_command( t_espeak_command* the_command)

case ET_PARAMETER:
{
t_espeak_parameter* data = &(the_command->u.my_param);
t_espeak_parameter *data = &(the_command->u.my_param);
SHOW("display_espeak_command > (0x%x) PARAMETER=%d, value=%d, relative=%d\n",
the_command, data->parameter, data->value, data->relative);
}
@@ -647,15 +599,15 @@ void display_espeak_command( t_espeak_command* the_command)

case ET_PUNCTUATION_LIST:
{
const wchar_t* data = the_command->u.my_punctuation_list;
sync_espeak_SetPunctuationList( data);
SHOW("display_espeak_command > (0x%x) PUNCTLIST=%s\n", the_command, (char*)data);
const wchar_t *data = the_command->u.my_punctuation_list;
sync_espeak_SetPunctuationList(data);
SHOW("display_espeak_command > (0x%x) PUNCTLIST=%s\n", the_command, (char *)data);
}
break;

case ET_VOICE_NAME:
{
const char* data = the_command->u.my_voice_name;
const char *data = the_command->u.my_voice_name;
SHOW("display_espeak_command > (0x%x) VOICE_NAME=%s\n", the_command, data);
}
break;

+ 36
- 46
src/libespeak-ng/espeak_command.h View File

@@ -29,8 +29,7 @@ extern "C"
{
#endif

typedef enum
{
typedef enum {
ET_TEXT,
ET_MARK,
ET_KEY,
@@ -42,78 +41,69 @@ typedef enum
ET_TERMINATED_MSG
} t_espeak_type;

typedef struct
{
typedef struct {
unsigned int unique_identifier;
void* text;
void *text;
size_t size;
unsigned int position;
espeak_POSITION_TYPE position_type;
unsigned int end_position;
unsigned int flags;
void* user_data;
void *user_data;
} t_espeak_text;

typedef struct
{
typedef struct {
unsigned int unique_identifier;
void* text;
void *text;
size_t size;
const char* index_mark;
const char *index_mark;
unsigned int end_position;
unsigned int flags;
void* user_data;
void *user_data;
} t_espeak_mark;

typedef struct
{
typedef struct {
unsigned int unique_identifier;
void* user_data;
void *user_data;
wchar_t character;
} t_espeak_character;

typedef struct
{
typedef struct {
unsigned int unique_identifier;
void* user_data;
const char* key_name;
void *user_data;
const char *key_name;
} t_espeak_key;


typedef struct
{
typedef struct {
unsigned int unique_identifier;
void* user_data;
void *user_data;
} t_espeak_terminated_msg;


typedef struct
{
typedef struct {
espeak_PARAMETER parameter;
int value;
int relative;
} t_espeak_parameter;

typedef enum
{
typedef enum {
CS_UNDEFINED, // The command has just been created
CS_PENDING, // stored in the fifo
CS_PROCESSED // processed
} t_command_state;

typedef struct
{
typedef struct {
t_espeak_type type;
t_command_state state;

union command
{
union command {
t_espeak_text my_text;
t_espeak_mark my_mark;
t_espeak_key my_key;
t_espeak_character my_char;
t_espeak_parameter my_param;
const wchar_t* my_punctuation_list;
const wchar_t *my_punctuation_list;
const char *my_voice_name;
espeak_VOICE my_voice_spec;
t_espeak_terminated_msg my_terminated_msg;
@@ -121,37 +111,37 @@ typedef struct
} t_espeak_command;


t_espeak_command* create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void* user_data);
t_espeak_command *create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void *user_data);

t_espeak_command* create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void* user_data);
t_espeak_command *create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void *user_data);

t_espeak_command* create_espeak_terminated_msg(unsigned int unique_identifier, void* user_data);
t_espeak_command *create_espeak_terminated_msg(unsigned int unique_identifier, void *user_data);

t_espeak_command* create_espeak_key(const char *key_name, void *user_data);
t_espeak_command *create_espeak_key(const char *key_name, void *user_data);

t_espeak_command* create_espeak_char(wchar_t character, void *user_data);
t_espeak_command *create_espeak_char(wchar_t character, void *user_data);

t_espeak_command* create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative);
t_espeak_command *create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative);

t_espeak_command* create_espeak_punctuation_list(const wchar_t *punctlist);
t_espeak_command *create_espeak_punctuation_list(const wchar_t *punctlist);

t_espeak_command* create_espeak_voice_name(const char *name);
t_espeak_command *create_espeak_voice_name(const char *name);

t_espeak_command* create_espeak_voice_spec(espeak_VOICE *voice_spec);
t_espeak_command *create_espeak_voice_spec(espeak_VOICE *voice_spec);

void process_espeak_command( t_espeak_command* the_command);
void process_espeak_command(t_espeak_command *the_command);

int delete_espeak_command( t_espeak_command* the_command);
int delete_espeak_command(t_espeak_command *the_command);

void display_espeak_command(t_espeak_command* the_command);
void display_espeak_command(t_espeak_command *the_command);


espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size,
unsigned int position, espeak_POSITION_TYPE position_type,
unsigned int end_position, unsigned int flags, void* user_data);
unsigned int end_position, unsigned int flags, void *user_data);
espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size,
const char *index_mark, unsigned int end_position,
unsigned int flags, void* user_data);
unsigned int flags, void *user_data);
void sync_espeak_Key(const char *key);
void sync_espeak_Char(wchar_t character);
void sync_espeak_SetPunctuationList(const wchar_t *punctlist);
@@ -162,11 +152,11 @@ espeak_ERROR SetVoiceByName(const char *name);
espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector);
void SetParameter(int parameter, int value, int relative);

int sync_espeak_terminated_msg(unsigned int unique_identifier, void* user_data);
int sync_espeak_terminated_msg(unsigned int unique_identifier, void *user_data);

#ifdef __cplusplus
}
#endif

//>
// >
#endif

+ 139
- 197
src/libespeak-ng/event.c View File

@@ -47,29 +47,28 @@ static sem_t my_sem_stop_is_acknowledged;
static pthread_t my_thread;
static bool thread_inited;

static t_espeak_callback* my_callback = NULL;
static int my_event_is_running=0;
static t_espeak_callback *my_callback = NULL;
static int my_event_is_running = 0;

enum {MIN_TIMEOUT_IN_MS=10,
ACTIVITY_TIMEOUT=50, // in ms, check that the stream is active
MAX_ACTIVITY_CHECK=6};
enum { MIN_TIMEOUT_IN_MS = 10,
ACTIVITY_TIMEOUT = 50, // in ms, check that the stream is active
MAX_ACTIVITY_CHECK = 6 };


typedef struct t_node
{
void* data;
typedef struct t_node {
void *data;
struct t_node *next;
} node;

static node* head=NULL;
static node* tail=NULL;
static int node_counter=0;
static espeak_ERROR push(void* data);
static void* pop();
static node *head = NULL;
static node *tail = NULL;
static int node_counter = 0;
static espeak_ERROR push(void *data);
static void *pop();
static void init();
static void* polling_thread(void*);
static void *polling_thread(void *);

void event_set_callback(t_espeak_callback* SynthCallback)
void event_set_callback(t_espeak_callback *SynthCallback)
{
my_callback = SynthCallback;
}
@@ -78,10 +77,10 @@ void event_init(void)
{
ENTER("event_init");

my_event_is_running=0;
my_event_is_running = 0;

// security
pthread_mutex_init( &my_mutex, (const pthread_mutexattr_t *)NULL);
pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL);
init();

assert(-1 != sem_init(&my_sem_start_is_required, 0, 0));
@@ -90,30 +89,26 @@ void event_init(void)

pthread_attr_t a_attrib;

if (pthread_attr_init (&a_attrib) == 0
&& pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) == 0)
{
if (pthread_attr_init(&a_attrib) == 0
&& pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) == 0) {
thread_inited = (0 == pthread_create(&my_thread,
&a_attrib,
polling_thread,
(void*)NULL));
(void *)NULL));
}
assert(thread_inited);
pthread_attr_destroy(&a_attrib);
}

static void event_display(espeak_EVENT* event)
static void event_display(espeak_EVENT *event)
{
ENTER("event_display");

#ifdef DEBUG_ENABLED
if (event==NULL)
{
SHOW("event_display > event=%s\n","NULL");
}
else
{
static const char* label[] = {
if (event == NULL) {
SHOW("event_display > event=%s\n", "NULL");
} else {
static const char *label[] = {
"LIST_TERMINATED",
"WORD",
"SENTENCE",
@@ -126,38 +121,35 @@ static void event_display(espeak_EVENT* event)
"??"
};

SHOW("event_display > event=0x%x\n",event);
SHOW("event_display > type=%s\n",label[event->type]);
SHOW("event_display > uid=%d\n",event->unique_identifier);
SHOW("event_display > text_position=%d\n",event->text_position);
SHOW("event_display > length=%d\n",event->length);
SHOW("event_display > audio_position=%d\n",event->audio_position);
SHOW("event_display > sample=%d\n",event->sample);
SHOW("event_display > user_data=0x%x\n",event->user_data);
SHOW("event_display > event=0x%x\n", event);
SHOW("event_display > type=%s\n", label[event->type]);
SHOW("event_display > uid=%d\n", event->unique_identifier);
SHOW("event_display > text_position=%d\n", event->text_position);
SHOW("event_display > length=%d\n", event->length);
SHOW("event_display > audio_position=%d\n", event->audio_position);
SHOW("event_display > sample=%d\n", event->sample);
SHOW("event_display > user_data=0x%x\n", event->user_data);
}
#endif
}

static espeak_EVENT* event_copy (espeak_EVENT* event)
static espeak_EVENT *event_copy(espeak_EVENT *event)
{
ENTER("event_copy");

if (event==NULL)
{
if (event == NULL) {
return NULL;
}

espeak_EVENT* a_event=(espeak_EVENT*)malloc(sizeof(espeak_EVENT));
if (a_event)
{
espeak_EVENT *a_event = (espeak_EVENT *)malloc(sizeof(espeak_EVENT));
if (a_event) {
memcpy(a_event, event, sizeof(espeak_EVENT));

switch(event->type)
switch (event->type)
{
case espeakEVENT_MARK:
case espeakEVENT_PLAY:
if (event->id.name)
{
if (event->id.name) {
a_event->id.name = strdup(event->id.name);
}
break;
@@ -181,21 +173,20 @@ static espeak_EVENT* event_copy (espeak_EVENT* event)
// * Last call: event->type = espeakEVENT_MSG_TERMINATED
//

static void event_notify(espeak_EVENT* event)
static void event_notify(espeak_EVENT *event)
{
ENTER("event_notify");
static unsigned int a_old_uid = 0;

espeak_EVENT events[2];
memcpy(&events[0],event,sizeof(espeak_EVENT)); // the event parameter in the callback function should be an array of eventd
memcpy(&events[1],event,sizeof(espeak_EVENT));
memcpy(&events[0], event, sizeof(espeak_EVENT)); // the event parameter in the callback function should be an array of eventd
memcpy(&events[1], event, sizeof(espeak_EVENT));
events[1].type = espeakEVENT_LIST_TERMINATED; // ... terminated by an event type=0

if (event && my_callback)
{
if (event && my_callback) {
event_display(event);

switch(event->type)
switch (event->type)
{
case espeakEVENT_SENTENCE:
my_callback(NULL, 0, events);
@@ -208,8 +199,7 @@ static void event_notify(espeak_EVENT* event)
case espeakEVENT_END:
case espeakEVENT_PHONEME:
{
if (a_old_uid != event->unique_identifier)
{
if (a_old_uid != event->unique_identifier) {
espeak_EVENT_TYPE a_new_type = events[0].type;
events[0].type = espeakEVENT_SENTENCE;
my_callback(NULL, 0, events);
@@ -229,18 +219,17 @@ static void event_notify(espeak_EVENT* event)
}
}

static int event_delete(espeak_EVENT* event)
static int event_delete(espeak_EVENT *event)
{
ENTER("event_delete");

event_display(event);

if(event==NULL)
{
if (event == NULL) {
return 0;
}

switch(event->type)
switch (event->type)
{
case espeakEVENT_MSG_TERMINATED:
event_notify(event);
@@ -248,9 +237,8 @@ static int event_delete(espeak_EVENT* event)

case espeakEVENT_MARK:
case espeakEVENT_PLAY:
if(event->id.name)
{
free((void*)(event->id.name));
if (event->id.name) {
free((void *)(event->id.name));
}
break;

@@ -262,27 +250,24 @@ static int event_delete(espeak_EVENT* event)
return 1;
}

espeak_ERROR event_declare (espeak_EVENT* event)
espeak_ERROR event_declare(espeak_EVENT *event)
{
ENTER("event_declare");

event_display(event);

if (!event)
{
if (!event) {
return EE_INTERNAL_ERROR;
}

int a_status = pthread_mutex_lock(&my_mutex);
espeak_ERROR a_error = EE_OK;

if (!a_status)
{
if (!a_status) {
SHOW_TIME("event_declare > locked\n");
espeak_EVENT* a_event = event_copy(event);
espeak_EVENT *a_event = event_copy(event);
a_error = push(a_event);
if (a_error != EE_OK)
{
if (a_error != EE_OK) {
event_delete(a_event);
}
SHOW_TIME("event_declare > unlocking\n");
@@ -292,15 +277,14 @@ espeak_ERROR event_declare (espeak_EVENT* event)
SHOW_TIME("event_declare > post my_sem_start_is_required\n");
sem_post(&my_sem_start_is_required);

if (a_status != 0)
{
if (a_status != 0) {
a_error = EE_INTERNAL_ERROR;
}

return a_error;
}

espeak_ERROR event_clear_all ()
espeak_ERROR event_clear_all()
{
ENTER("event_clear_all");

@@ -308,33 +292,26 @@ espeak_ERROR event_clear_all ()
int a_event_is_running = 0;

SHOW_TIME("event_stop > locked\n");
if (a_status != 0)
{
if (a_status != 0) {
return EE_INTERNAL_ERROR;
}

if (my_event_is_running)
{
if (my_event_is_running) {
SHOW_TIME("event_stop > post my_sem_stop_is_required\n");
sem_post(&my_sem_stop_is_required);
a_event_is_running = 1;
}
else
{
} else {
init(); // clear pending events
}
SHOW_TIME("event_stop > unlocking\n");
a_status = pthread_mutex_unlock(&my_mutex);
if (a_status != 0)
{
if (a_status != 0) {
return EE_INTERNAL_ERROR;
}

if (a_event_is_running)
{
if (a_event_is_running) {
SHOW_TIME("event_stop > wait for my_sem_stop_is_acknowledged\n");
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR)
{
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) {
continue; // Restart when interrupted by handler
}
SHOW_TIME("event_stop > get my_sem_stop_is_acknowledged\n");
@@ -349,12 +326,12 @@ static int sleep_until_timeout_or_stop_request(uint32_t time_in_ms)
{
ENTER("sleep_until_timeout_or_stop_request");

int a_stop_is_required=0;
int a_stop_is_required = 0;
struct timespec ts;
struct timeval tv;
int err=0;
int err = 0;

clock_gettime2( &ts);
clock_gettime2(&ts);

#ifdef DEBUG_ENABLED
struct timespec to;
@@ -362,26 +339,24 @@ static int sleep_until_timeout_or_stop_request(uint32_t time_in_ms)
to.tv_nsec = ts.tv_nsec;
#endif

add_time_in_ms( &ts, time_in_ms);
add_time_in_ms(&ts, time_in_ms);

SHOW("polling_thread > sleep_until_timeout_or_stop_request > start sem_timedwait from %d.%09lu to %d.%09lu \n",
to.tv_sec, to.tv_nsec,
ts.tv_sec, ts.tv_nsec);

while ((err = sem_timedwait(&my_sem_stop_is_required, &ts)) == -1
&& errno == EINTR)
{
&& errno == EINTR) {
continue; // Restart when interrupted by handler
}

assert (gettimeofday(&tv, NULL) != -1);
assert(gettimeofday(&tv, NULL) != -1);
SHOW("polling_thread > sleep_until_timeout_or_stop_request > stop sem_timedwait %d.%09lu \n",
tv.tv_sec, tv.tv_usec*1000);

if (err == 0)
{
SHOW("polling_thread > sleep_until_timeout_or_stop_request > %s\n","stop required!");
a_stop_is_required=1; // stop required
if (err == 0) {
SHOW("polling_thread > sleep_until_timeout_or_stop_request > %s\n", "stop required!");
a_stop_is_required = 1; // stop required
}
return a_stop_is_required;
}
@@ -390,22 +365,20 @@ static int sleep_until_timeout_or_stop_request(uint32_t time_in_ms)
// If the stream is opened but the audio samples are not played,
// a timeout is started.

static int get_remaining_time(uint32_t sample, uint32_t* time_in_ms, int* stop_is_required)
static int get_remaining_time(uint32_t sample, uint32_t *time_in_ms, int *stop_is_required)
{
ENTER("get_remaining_time");

int err = 0;
*stop_is_required = 0;
int i=0;
int i = 0;

for (i=0; i < MAX_ACTIVITY_CHECK && (*stop_is_required == 0); i++)
{
err = wave_get_remaining_time( sample, time_in_ms);
for (i = 0; i < MAX_ACTIVITY_CHECK && (*stop_is_required == 0); i++) {
err = wave_get_remaining_time(sample, time_in_ms);

if (err || wave_is_busy(NULL) || (*time_in_ms == 0))
{ // if err, stream not available: quit
// if wave is busy, time_in_ms is known: quit
// if wave is not busy but remaining time == 0, event is reached: quit
if (err || wave_is_busy(NULL) || (*time_in_ms == 0)) { // if err, stream not available: quit
// if wave is busy, time_in_ms is known: quit
// if wave is not busy but remaining time == 0, event is reached: quit
break;
}

@@ -422,19 +395,18 @@ static int get_remaining_time(uint32_t sample, uint32_t* time_in_ms, int* stop_i
//
// wait for the close of stream

*stop_is_required = sleep_until_timeout_or_stop_request( ACTIVITY_TIMEOUT);
*stop_is_required = sleep_until_timeout_or_stop_request(ACTIVITY_TIMEOUT);
}

return err;
}

static void* polling_thread(void*p)
static void *polling_thread(void *p)
{
ENTER("polling_thread");

while(1)
{
int a_stop_is_required=0;
while (1) {
int a_stop_is_required = 0;

SHOW_TIME("polling_thread > locking\n");
int a_status = pthread_mutex_lock(&my_mutex);
@@ -445,8 +417,7 @@ static void* polling_thread(void*p)

SHOW_TIME("polling_thread > wait for my_sem_start_is_required\n");

while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR)
{
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR) {
continue; // Restart when interrupted by handler
}

@@ -458,29 +429,25 @@ static void* polling_thread(void*p)
pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n");

a_stop_is_required=0;
a_stop_is_required = 0;
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); // NOTE: may set a_stop_is_required to -1
if ((a_status==0) && (a_stop_is_required > 0))
{
if ((a_status == 0) && (a_stop_is_required > 0)) {
SHOW("polling_thread > stop required (%d)\n", __LINE__);
while(0 == sem_trywait(&my_sem_stop_is_required))
{
};
}
else
{
a_stop_is_required=0;
while (0 == sem_trywait(&my_sem_stop_is_required)) {
}
;
} else {
a_stop_is_required = 0;
}

// In this loop, my_event_is_running = 1
while (head && (a_stop_is_required <= 0))
{
while (head && (a_stop_is_required <= 0)) {
SHOW_TIME("polling_thread > check head\n");
while(0 == sem_trywait(&my_sem_start_is_required))
{
};
while (0 == sem_trywait(&my_sem_start_is_required)) {
}
;

espeak_EVENT* event = (espeak_EVENT*)(head->data);
espeak_EVENT *event = (espeak_EVENT *)(head->data);
assert(event);

uint32_t time_in_ms = 0;
@@ -488,54 +455,43 @@ static void* polling_thread(void*p)
int err = get_remaining_time((uint32_t)event->sample,
&time_in_ms,
&a_stop_is_required);
if (a_stop_is_required > 0)
{
if (a_stop_is_required > 0) {
break;
}
else if (err != 0)
{
} else if (err != 0) {
// No available time: the event is deleted.
SHOW("polling_thread > %s\n","audio device down");
SHOW("polling_thread > %s\n", "audio device down");
a_status = pthread_mutex_lock(&my_mutex);
SHOW_TIME("polling_thread > locked\n");
event_delete( (espeak_EVENT*)pop());
event_delete((espeak_EVENT *)pop());
a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n");
}
else if (time_in_ms==0)
{ // the event is already reached.
if (my_callback)
{
} else if (time_in_ms == 0) { // the event is already reached.
if (my_callback) {
event_notify(event);
// the user_data (and the type) are cleaned to be sure
// that MSG_TERMINATED is called twice (at delete time too).
event->type=espeakEVENT_LIST_TERMINATED;
event->user_data=NULL;
event->type = espeakEVENT_LIST_TERMINATED;
event->user_data = NULL;
}

a_status = pthread_mutex_lock(&my_mutex);
SHOW_TIME("polling_thread > locked\n");
event_delete( (espeak_EVENT*)pop());
event_delete((espeak_EVENT *)pop());
a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n");

a_stop_is_required=0;
a_stop_is_required = 0;
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required);

if ((a_status==0) && (a_stop_is_required > 0))
{
if ((a_status == 0) && (a_stop_is_required > 0)) {
SHOW("polling_thread > stop required (%d)\n", __LINE__);
while(0 == sem_trywait(&my_sem_stop_is_required))
{
};
}
else
{
a_stop_is_required=0;
while (0 == sem_trywait(&my_sem_stop_is_required)) {
}
;
} else {
a_stop_is_required = 0;
}
}
else
{ // The event will be notified soon: sleep until timeout or stop request
} else { // The event will be notified soon: sleep until timeout or stop request
a_stop_is_required = sleep_until_timeout_or_stop_request(time_in_ms);
}
}
@@ -546,28 +502,23 @@ static void* polling_thread(void*p)
SHOW_TIME("polling_thread > my_event_is_running = 0\n");
my_event_is_running = 0;

if(a_stop_is_required <= 0)
{
if (a_stop_is_required <= 0) {
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required);
if ((a_status==0) && (a_stop_is_required > 0))
{
if ((a_status == 0) && (a_stop_is_required > 0)) {
SHOW("polling_thread > stop required (%d)\n", __LINE__);
while(0 == sem_trywait(&my_sem_stop_is_required))
{
};
}
else
{
a_stop_is_required=0;
while (0 == sem_trywait(&my_sem_stop_is_required)) {
}
;
} else {
a_stop_is_required = 0;
}
}

a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n");

if (a_stop_is_required > 0)
{
SHOW("polling_thread > %s\n","stop required!");
if (a_stop_is_required > 0) {
SHOW("polling_thread > %s\n", "stop required!");
// no mutex required since the stop command is synchronous
// and waiting for my_sem_stop_is_acknowledged
init();
@@ -581,39 +532,33 @@ static void* polling_thread(void*p)
return NULL;
}

enum {MAX_NODE_COUNTER=1000};
enum { MAX_NODE_COUNTER = 1000 };

static espeak_ERROR push(void* the_data)
static espeak_ERROR push(void *the_data)
{
ENTER("event > push");

assert((!head && !tail) || (head && tail));

if (the_data == NULL)
{
if (the_data == NULL) {
SHOW("event > push > event=0x%x\n", NULL);
return EE_INTERNAL_ERROR;
}

if (node_counter >= MAX_NODE_COUNTER)
{
if (node_counter >= MAX_NODE_COUNTER) {
SHOW("event > push > %s\n", "EE_BUFFER_FULL");
return EE_BUFFER_FULL;
}

node *n = (node *)malloc(sizeof(node));
if (n == NULL)
{
if (n == NULL) {
return EE_INTERNAL_ERROR;
}

if (head == NULL)
{
if (head == NULL) {
head = n;
tail = n;
}
else
{
} else {
tail->next = n;
tail = n;
}
@@ -622,30 +567,28 @@ static espeak_ERROR push(void* the_data)
tail->data = the_data;

node_counter++;
SHOW("event > push > counter=%d (uid=%d)\n",node_counter,((espeak_EVENT*)the_data)->unique_identifier);
SHOW("event > push > counter=%d (uid=%d)\n", node_counter, ((espeak_EVENT *)the_data)->unique_identifier);

return EE_OK;
}

static void* pop()
static void *pop()
{
ENTER("event > pop");
void* the_data = NULL;
void *the_data = NULL;

assert((!head && !tail) || (head && tail));

if (head != NULL)
{
node* n = head;
if (head != NULL) {
node *n = head;
the_data = n->data;
head = n->next;
free(n);
node_counter--;
SHOW("event > pop > event=0x%x (counter=%d, uid=%d)\n",the_data, node_counter,((espeak_EVENT*)the_data)->unique_identifier);
SHOW("event > pop > event=0x%x (counter=%d, uid=%d)\n", the_data, node_counter, ((espeak_EVENT *)the_data)->unique_identifier);
}

if(head == NULL)
{
if (head == NULL) {
tail = NULL;
}

@@ -657,8 +600,8 @@ static void init()
{
ENTER("event > init");

while (event_delete( (espeak_EVENT*)pop() ))
{}
while (event_delete((espeak_EVENT *)pop())) {
}

node_counter = 0;
}
@@ -667,10 +610,9 @@ void event_terminate()
{
ENTER("event_terminate");

if (thread_inited)
{
if (thread_inited) {
pthread_cancel(my_thread);
pthread_join(my_thread,NULL);
pthread_join(my_thread, NULL);
pthread_mutex_destroy(&my_mutex);
sem_destroy(&my_sem_start_is_required);
sem_destroy(&my_sem_stop_is_required);

+ 3
- 3
src/libespeak-ng/event.h View File

@@ -51,13 +51,13 @@ extern "C"
// the callback will be called when the event actually occurs.
// The callback is detailled in speak_lib.h .
void event_init(void);
void event_set_callback(t_espeak_callback* cb);
void event_set_callback(t_espeak_callback *cb);

// Clear any pending event.
//
// Return: EE_OK: operation achieved
// EE_INTERNAL_ERROR.
espeak_ERROR event_clear_all ();
espeak_ERROR event_clear_all();

// Declare a future event
//
@@ -65,7 +65,7 @@ espeak_ERROR event_clear_all ();
// EE_BUFFER_FULL: the event can not be buffered;
// you may try after a while to call the function again.
// EE_INTERNAL_ERROR.
espeak_ERROR event_declare (espeak_EVENT* event);
espeak_ERROR event_declare(espeak_EVENT *event);

// Terminate the event component.
// Last function to be called.

+ 95
- 144
src/libespeak-ng/fifo.c View File

@@ -52,35 +52,34 @@ static pthread_t my_thread;
static sem_t my_sem_start_is_required;
static sem_t my_sem_stop_is_acknowledged;

static void* say_thread(void*);
static void *say_thread(void *);

static espeak_ERROR push(t_espeak_command* the_command);
static t_espeak_command* pop();
static espeak_ERROR push(t_espeak_command *the_command);
static t_espeak_command *pop();
static void init(int process_parameters);
static int node_counter=0;
enum {MAX_NODE_COUNTER=400,
INACTIVITY_TIMEOUT=50, // in ms, check that the stream is inactive
MAX_INACTIVITY_CHECK=2};
static int node_counter = 0;
enum { MAX_NODE_COUNTER = 400,
INACTIVITY_TIMEOUT = 50, // in ms, check that the stream is inactive
MAX_INACTIVITY_CHECK = 2 };

void fifo_init()
{
ENTER("fifo_init");

// security
pthread_mutex_init( &my_mutex, (const pthread_mutexattr_t *)NULL);
pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL);
init(0);

assert(-1 != sem_init(&my_sem_start_is_required, 0, 0));
assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0));

pthread_attr_t a_attrib;
if (pthread_attr_init (&a_attrib)
if (pthread_attr_init(&a_attrib)
|| pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE)
|| pthread_create( &my_thread,
&a_attrib,
say_thread,
(void*)NULL))
{
|| pthread_create(&my_thread,
&a_attrib,
say_thread,
(void *)NULL)) {
assert(0);
}

@@ -88,44 +87,39 @@ void fifo_init()

// leave once the thread is actually started
SHOW_TIME("fifo > wait for my_sem_stop_is_acknowledged\n");
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR)
{
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) {
continue; // Restart when interrupted by handler
}
SHOW_TIME("fifo > get my_sem_stop_is_acknowledged\n");
}

espeak_ERROR fifo_add_command (t_espeak_command* the_command)
espeak_ERROR fifo_add_command(t_espeak_command *the_command)
{
ENTER("fifo_add_command");

int a_status = pthread_mutex_lock(&my_mutex);
espeak_ERROR a_error = EE_OK;

if (!a_status)
{
if (!a_status) {
SHOW_TIME("fifo_add_command > locked\n");
a_error = push(the_command);
SHOW_TIME("fifo_add_command > unlocking\n");
a_status = pthread_mutex_unlock(&my_mutex);
}

if (!a_status && !my_command_is_running && (a_error == EE_OK))
{
if (!a_status && !my_command_is_running && (a_error == EE_OK)) {
// quit when command is actually started
// (for possible forthcoming 'end of command' checks)
SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n");
sem_post(&my_sem_start_is_required);
int val=1;
while (val > 0)
{
int val = 1;
while (val > 0) {
usleep(50000); // TBD: event?
sem_getvalue(&my_sem_start_is_required, &val);
}
}

if (a_status != 0)
{
if (a_status != 0) {
a_error = EE_INTERNAL_ERROR;
}

@@ -133,24 +127,20 @@ espeak_ERROR fifo_add_command (t_espeak_command* the_command)
return a_error;
}

espeak_ERROR fifo_add_commands (t_espeak_command* command1, t_espeak_command* command2)
espeak_ERROR fifo_add_commands(t_espeak_command *command1, t_espeak_command *command2)
{
ENTER("fifo_add_command");

int a_status = pthread_mutex_lock(&my_mutex);
espeak_ERROR a_error = EE_OK;

if (!a_status)
{
if (!a_status) {
SHOW_TIME("fifo_add_commands > locked\n");

if (node_counter+1 >= MAX_NODE_COUNTER)
{
if (node_counter+1 >= MAX_NODE_COUNTER) {
SHOW("push > %s\n", "EE_BUFFER_FULL");
a_error = EE_BUFFER_FULL;
}
else
{
} else {
push(command1);
push(command2);
}
@@ -158,22 +148,19 @@ espeak_ERROR fifo_add_commands (t_espeak_command* command1, t_espeak_command* co
a_status = pthread_mutex_unlock(&my_mutex);
}

if (!a_status && !my_command_is_running && (a_error == EE_OK))
{
if (!a_status && !my_command_is_running && (a_error == EE_OK)) {
// quit when one command is actually started
// (for possible forthcoming 'end of command' checks)
SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n");
sem_post(&my_sem_start_is_required);
int val=1;
while (val > 0)
{
int val = 1;
while (val > 0) {
usleep(50000); // TBD: event?
sem_getvalue(&my_sem_start_is_required, &val);
}
}

if (a_status != 0)
{
if (a_status != 0) {
a_error = EE_INTERNAL_ERROR;
}

@@ -181,36 +168,31 @@ espeak_ERROR fifo_add_commands (t_espeak_command* command1, t_espeak_command* co
return a_error;
}

espeak_ERROR fifo_stop ()
espeak_ERROR fifo_stop()
{
ENTER("fifo_stop");

int a_command_is_running = 0;
int a_status = pthread_mutex_lock(&my_mutex);
SHOW_TIME("fifo_stop > locked\n");
if (a_status != 0)
{
if (a_status != 0) {
return EE_INTERNAL_ERROR;
}

if (my_command_is_running)
{
if (my_command_is_running) {
a_command_is_running = 1;
my_stop_is_required = 1;
SHOW_TIME("fifo_stop > my_stop_is_required = 1\n");
}
SHOW_TIME("fifo_stop > unlocking\n");
a_status = pthread_mutex_unlock(&my_mutex);
if (a_status != 0)
{
if (a_status != 0) {
return EE_INTERNAL_ERROR;
}

if (a_command_is_running)
{
if (a_command_is_running) {
SHOW_TIME("fifo_stop > wait for my_sem_stop_is_acknowledged\n");
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR)
{
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) {
continue; // Restart when interrupted by handler
}
SHOW_TIME("fifo_stop > get my_sem_stop_is_acknowledged\n");
@@ -223,16 +205,16 @@ espeak_ERROR fifo_stop ()
return EE_OK;
}

int fifo_is_busy ()
int fifo_is_busy()
{
SHOW("fifo_is_busy > aResult = %d\n",my_command_is_running);
SHOW("fifo_is_busy > aResult = %d\n", my_command_is_running);
return my_command_is_running;
}

static int sleep_until_start_request_or_inactivity()
{
SHOW_TIME("fifo > sleep_until_start_request_or_inactivity > ENTER");
int a_start_is_required=0;
int a_start_is_required = 0;

// Wait for the start request (my_sem_start_is_required).
// Besides this, if the audio stream is still busy,
@@ -240,23 +222,19 @@ static int sleep_until_start_request_or_inactivity()
// The end of the stream is confirmed by several checks
// for filtering underflow.
//
int i=0;
while((i<= MAX_INACTIVITY_CHECK) && !a_start_is_required)
{
if (wave_is_busy( NULL) )
{
int i = 0;
while ((i <= MAX_INACTIVITY_CHECK) && !a_start_is_required) {
if (wave_is_busy(NULL)) {
i = 0;
}
else
{
} else {
i++;
}

int err=0;
int err = 0;
struct timespec ts;
struct timeval tv;

clock_gettime2( &ts);
clock_gettime2(&ts);

#ifdef DEBUG_ENABLED
struct timespec to;
@@ -264,24 +242,22 @@ static int sleep_until_start_request_or_inactivity()
to.tv_nsec = ts.tv_nsec;
#endif

add_time_in_ms( &ts, INACTIVITY_TIMEOUT);
add_time_in_ms(&ts, INACTIVITY_TIMEOUT);

SHOW("fifo > sleep_until_start_request_or_inactivity > start sem_timedwait (start_is_required) from %d.%09lu to %d.%09lu \n",
to.tv_sec, to.tv_nsec,
ts.tv_sec, ts.tv_nsec);

while ((err = sem_timedwait(&my_sem_start_is_required, &ts)) == -1
&& errno == EINTR)
{
&& errno == EINTR) {
continue;
}

assert (gettimeofday(&tv, NULL) != -1);
assert(gettimeofday(&tv, NULL) != -1);
SHOW("fifo > sleep_until_start_request_or_inactivity > stop sem_timedwait (start_is_required, err=%d) %d.%09lu \n", err,
tv.tv_sec, tv.tv_usec*1000);

if (err==0)
{
if (err == 0) {
a_start_is_required = 1;
}
}
@@ -298,38 +274,35 @@ static void close_stream()
// my_stop_is_required = 1;

int a_status = pthread_mutex_lock(&my_mutex);
assert (!a_status);
assert(!a_status);
int a_stop_is_required = my_stop_is_required;
if (!a_stop_is_required)
{
if (!a_stop_is_required) {
my_command_is_running = 1;
}
a_status = pthread_mutex_unlock(&my_mutex);

if (!a_stop_is_required)
{
if (!a_stop_is_required) {
wave_close(NULL);

int a_status = pthread_mutex_lock(&my_mutex);
assert (!a_status);
assert(!a_status);
my_command_is_running = 0;

a_stop_is_required = my_stop_is_required;
a_status = pthread_mutex_unlock(&my_mutex);

if (a_stop_is_required)
{
if (a_stop_is_required) {
// acknowledge the stop request
SHOW_TIME("fifo > close_stream > post my_sem_stop_is_acknowledged\n");
int a_status = sem_post(&my_sem_stop_is_acknowledged);
assert( a_status != -1);
assert(a_status != -1);
}
}

SHOW_TIME("fifo > close_stream > LEAVE\n");
}

static void* say_thread(void*p)
static void *say_thread(void *p)
{
ENTER("say_thread");

@@ -338,27 +311,22 @@ static void* say_thread(void*p)
// announce that thread is started
sem_post(&my_sem_stop_is_acknowledged);

int look_for_inactivity=0;
int look_for_inactivity = 0;

while(1)
{
while (1) {
SHOW_TIME("say_thread > wait for my_sem_start_is_required\n");

int a_start_is_required = 0;
if (look_for_inactivity)
{
if (look_for_inactivity) {
a_start_is_required = sleep_until_start_request_or_inactivity();
if (!a_start_is_required)
{
if (!a_start_is_required) {
close_stream();
}
}
look_for_inactivity = 1;

if (!a_start_is_required)
{
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR)
{
if (!a_start_is_required) {
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR) {
continue; // Restart when interrupted by handler
}
}
@@ -367,62 +335,55 @@ static void* say_thread(void*p)
SHOW_TIME("say_thread > my_command_is_running = 1\n");
my_command_is_running = 1;

while( my_command_is_running)
{
while (my_command_is_running) {
SHOW_TIME("say_thread > locking\n");
int a_status = pthread_mutex_lock(&my_mutex);
assert (!a_status);
t_espeak_command* a_command = (t_espeak_command*)pop();
assert(!a_status);
t_espeak_command *a_command = (t_espeak_command *)pop();

if (a_command == NULL)
{
if (a_command == NULL) {
SHOW_TIME("say_thread > text empty (talking=0) \n");
a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("say_thread > unlocked\n");
SHOW_TIME("say_thread > my_command_is_running = 0\n");
my_command_is_running = 0;
}
else
{
} else {
display_espeak_command(a_command);
// purge start semaphore
SHOW_TIME("say_thread > purge my_sem_start_is_required\n");
while(0 == sem_trywait(&my_sem_start_is_required))
{
};
while (0 == sem_trywait(&my_sem_start_is_required)) {
}
;

if (my_stop_is_required)
{
if (my_stop_is_required) {
SHOW_TIME("say_thread > my_command_is_running = 0\n");
my_command_is_running = 0;
}
SHOW_TIME("say_thread > unlocking\n");
a_status = pthread_mutex_unlock(&my_mutex);

if (my_command_is_running)
{
if (my_command_is_running) {
process_espeak_command(a_command);
}
delete_espeak_command(a_command);
}
}

if (my_stop_is_required)
{
if (my_stop_is_required) {
// no mutex required since the stop command is synchronous
// and waiting for my_sem_stop_is_acknowledged
init(1);

// purge start semaphore
SHOW_TIME("say_thread > purge my_sem_start_is_required\n");
while(0==sem_trywait(&my_sem_start_is_required))
{
};
while (0 == sem_trywait(&my_sem_start_is_required)) {
}
;

// acknowledge the stop request
SHOW_TIME("say_thread > post my_sem_stop_is_acknowledged\n");
int a_status = sem_post(&my_sem_stop_is_acknowledged);
assert( a_status != -1);
assert(a_status != -1);
}
// and wait for the next start
SHOW_TIME("say_thread > wait for my_sem_start_is_required\n");
@@ -433,50 +394,43 @@ static void* say_thread(void*p)

int fifo_is_command_enabled()
{
SHOW("ENTER fifo_is_command_enabled=%d\n",(int)(0 == my_stop_is_required));
SHOW("ENTER fifo_is_command_enabled=%d\n", (int)(0 == my_stop_is_required));
return (0 == my_stop_is_required);
}

typedef struct t_node
{
t_espeak_command* data;
typedef struct t_node {
t_espeak_command *data;
struct t_node *next;
} node;

static node* head=NULL;
static node* tail=NULL;
static node *head = NULL;
static node *tail = NULL;

static espeak_ERROR push(t_espeak_command* the_command)
static espeak_ERROR push(t_espeak_command *the_command)
{
ENTER("fifo > push");

assert((!head && !tail) || (head && tail));

if (the_command == NULL)
{
if (the_command == NULL) {
SHOW("push > command=0x%x\n", NULL);
return EE_INTERNAL_ERROR;
}

if (node_counter >= MAX_NODE_COUNTER)
{
if (node_counter >= MAX_NODE_COUNTER) {
SHOW("push > %s\n", "EE_BUFFER_FULL");
return EE_BUFFER_FULL;
}

node *n = (node *)malloc(sizeof(node));
if (n == NULL)
{
if (n == NULL) {
return EE_INTERNAL_ERROR;
}

if (head == NULL)
{
if (head == NULL) {
head = n;
tail = n;
}
else
{
} else {
tail->next = n;
tail = n;
}
@@ -485,7 +439,7 @@ static espeak_ERROR push(t_espeak_command* the_command)
tail->data = the_command;

node_counter++;
SHOW("push > counter=%d\n",node_counter);
SHOW("push > counter=%d\n", node_counter);

the_command->state = CS_PENDING;
display_espeak_command(the_command);
@@ -493,25 +447,23 @@ static espeak_ERROR push(t_espeak_command* the_command)
return EE_OK;
}

static t_espeak_command* pop()
static t_espeak_command *pop()
{
ENTER("fifo > pop");
t_espeak_command* the_command = NULL;
t_espeak_command *the_command = NULL;

assert((!head && !tail) || (head && tail));

if (head != NULL)
{
node* n = head;
if (head != NULL) {
node *n = head;
the_command = n->data;
head = n->next;
free(n);
node_counter--;
SHOW("pop > command=0x%x (counter=%d)\n",the_command, node_counter);
SHOW("pop > command=0x%x (counter=%d)\n", the_command, node_counter);
}

if(head == NULL)
{
if (head == NULL) {
tail = NULL;
}

@@ -526,8 +478,7 @@ static void init(int process_parameters)
ENTER("fifo > init");
c = pop();
while (c != NULL) {
if (process_parameters && (c->type == ET_PARAMETER || c->type == ET_VOICE_NAME || c->type == ET_VOICE_SPEC))
{
if (process_parameters && (c->type == ET_PARAMETER || c->type == ET_VOICE_NAME || c->type == ET_VOICE_SPEC)) {
process_espeak_command(c);
}
delete_espeak_command(c);
@@ -541,7 +492,7 @@ void fifo_terminate()
ENTER("fifo_terminate");

pthread_cancel(my_thread);
pthread_join(my_thread,NULL);
pthread_join(my_thread, NULL);
pthread_mutex_destroy(&my_mutex);
sem_destroy(&my_sem_start_is_required);
sem_destroy(&my_sem_stop_is_acknowledged);

+ 4
- 4
src/libespeak-ng/fifo.h View File

@@ -43,7 +43,7 @@ void fifo_init();
// EE_BUFFER_FULL: the command can not be buffered;
// you may try after a while to call the function again.
// EE_INTERNAL_ERROR.
espeak_ERROR fifo_add_command (t_espeak_command* c);
espeak_ERROR fifo_add_command(t_espeak_command *c);

// Add two espeak commands in a single transaction.
//
@@ -54,16 +54,16 @@ espeak_ERROR fifo_add_command (t_espeak_command* c);
// EE_BUFFER_FULL: at least one command can not be buffered;
// you may try after a while to call the function again.
// EE_INTERNAL_ERROR.
espeak_ERROR fifo_add_commands (t_espeak_command* c1, t_espeak_command* c2);
espeak_ERROR fifo_add_commands(t_espeak_command *c1, t_espeak_command *c2);

// The current running command must be stopped and the awaiting commands are cleared.
// Return: EE_OK: operation achieved
// EE_INTERNAL_ERROR.
espeak_ERROR fifo_stop ();
espeak_ERROR fifo_stop();

// Is there a running command?
// Returns 1 if yes; 0 otherwise.
int fifo_is_busy ();
int fifo_is_busy();

// Terminate the fifo component.
// Last function to be called.

+ 241
- 375
src/libespeak-ng/intonation.c
File diff suppressed because it is too large
View File


+ 176
- 265
src/libespeak-ng/klatt.c
File diff suppressed because it is too large
View File


+ 4
- 7
src/libespeak-ng/klatt.h View File

@@ -43,8 +43,7 @@ typedef long flag;

/* Resonator Structure */

typedef struct
{
typedef struct {
double a;
double b;
double c;
@@ -57,8 +56,7 @@ typedef struct

/* Structure for Klatt Globals */

typedef struct
{
typedef struct {
flag synthesis_model; /* cascade-parallel or all-parallel */
flag outsl; /* Output waveform selector */
long samrate; /* Number of output samples per second */
@@ -136,8 +134,7 @@ typedef struct
#define F_NP 9 // nasal pole formant


typedef struct
{
typedef struct {
int F0hz10; /* Voicing fund freq in Hz */
int AVdb; /* Amp of voicing in dB, 0 to 70 */
int Fhz[10]; // formant Hz, F_NZ to F6 to F_NP
@@ -156,7 +153,7 @@ typedef struct
int AVpdb; /* Amp of voicing, par in dB, 0 to 70 */
int Gain0; /* Overall gain, 60 dB is unity, 0 to 60 */

int AVdb_tmp; //copy of AVdb, which is changed within parwave()
int AVdb_tmp; // copy of AVdb, which is changed within parwave()
int Fhz_next[10]; // Fhz for the next chunk, so we can do interpolation of resonator (a,b,c) parameters
int Bhz_next[10];
} klatt_frame_t, *klatt_frame_ptr;

+ 2
- 2
src/libespeak-ng/mbrowrap.c View File

@@ -287,7 +287,7 @@ static int mbrola_has_errors(void)
char *buf_ptr, *lf;

buf_ptr = buffer;
for (;; ) {
for (;;) {
result = read(mbr_error_fd, buf_ptr,
sizeof(buffer) - (buf_ptr - buffer) - 1);
if (result == -1) {
@@ -514,7 +514,7 @@ int init_MBR(const char *voice_path)
}
mbr_samplerate = wavhdr[24] + (wavhdr[25]<<8) +
(wavhdr[26]<<16) + (wavhdr[27]<<24);
//log("mbrowrap: voice samplerate = %d", mbr_samplerate);
// log("mbrowrap: voice samplerate = %d", mbr_samplerate);

/* remember the voice path for setVolumeRatio_MBR() */
if (mbr_voice_path != voice_path) {

+ 679
- 973
src/libespeak-ng/numbers.c
File diff suppressed because it is too large
View File


+ 3
- 3
src/libespeak-ng/phoneme.h View File

@@ -160,9 +160,9 @@ typedef struct {



#define PH(c1,c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name
#define PH3(c1,c2,c3) (c3<<16)+(c2<<8)+c1
#define PhonemeCode2(c1,c2) PhonemeCode((c2<<8)+c1)
#define PH(c1, c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name
#define PH3(c1, c2, c3) (c3<<16)+(c2<<8)+c1
#define PhonemeCode2(c1, c2) PhonemeCode((c2<<8)+c1)
int LookupPhonemeString(const char *string);
int PhonemeCode(unsigned int mnem);


+ 123
- 224
src/libespeak-ng/phonemelist.c View File

@@ -33,7 +33,7 @@
#include "translate.h"


const unsigned char pause_phonemes[8] = {0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG};
const unsigned char pause_phonemes[8] = { 0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG };


extern int n_ph_list2;
@@ -51,59 +51,54 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out)
int n_plist_out = 0;
int word_end;
PHONEME_LIST2 *plist2;
PHONEME_TAB *next=NULL;
PHONEME_TAB *next = NULL;

for(ix=0; (ix < n_ph_list2) && (n_plist_out < N_PHONEME_LIST); ix++)
{
for (ix = 0; (ix < n_ph_list2) && (n_plist_out < N_PHONEME_LIST); ix++) {
plist2 = &ph_list2[ix];

// don't do any substitution if the language has been temporarily changed
if(!(plist2->synthflags & SFLAG_SWITCHED_LANG))
{
if(ix < (n_ph_list2 -1))
if (!(plist2->synthflags & SFLAG_SWITCHED_LANG)) {
if (ix < (n_ph_list2 -1))
next = phoneme_tab[ph_list2[ix+1].phcode];

word_end = 0;
if((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE)))
if ((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE)))
word_end = 1; // this phoneme is the end of a word

// check whether a Voice has specified that we should replace this phoneme
for(k=0; k<n_replace_phonemes; k++)
{
if(plist2->phcode == replace_phonemes[k].old_ph)
{
for (k = 0; k < n_replace_phonemes; k++) {
if (plist2->phcode == replace_phonemes[k].old_ph) {
replace_flags = replace_phonemes[k].type;

if((replace_flags & 1) && (word_end == 0))
if ((replace_flags & 1) && (word_end == 0))
continue; // this replacement only occurs at the end of a word

if((replace_flags & 2) && ((plist2->stresslevel & 0x7) > 3))
if ((replace_flags & 2) && ((plist2->stresslevel & 0x7) > 3))
continue; // this replacement doesn't occur in stressed syllables

if((replace_flags & 4) && (plist2->sourceix == 0))
if ((replace_flags & 4) && (plist2->sourceix == 0))
continue; // this replacement only occurs at the start of a word

// substitute the replacement phoneme
plist2->phcode = replace_phonemes[k].new_ph;
if((plist2->stresslevel > 1) && (phoneme_tab[plist2->phcode]->phflags & phUNSTRESSED))
if ((plist2->stresslevel > 1) && (phoneme_tab[plist2->phcode]->phflags & phUNSTRESSED))
plist2->stresslevel = 0; // the replacement must be unstressed
break;
}
}

if(plist2->phcode == 0)
{
if (plist2->phcode == 0) {
continue; // phoneme has been replaced by NULL, so don't copy it
}
}

// copy phoneme into the output list
memcpy(&plist_out[n_plist_out],plist2,sizeof(PHONEME_LIST2));
memcpy(&plist_out[n_plist_out], plist2, sizeof(PHONEME_LIST2));
plist_out[n_plist_out].ph = phoneme_tab[plist2->phcode];
plist_out[n_plist_out].type = plist_out[n_plist_out].ph->type;
n_plist_out++;
}
return(n_plist_out);
return (n_plist_out);
}


@@ -111,7 +106,7 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out)
void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
{

int ix=0;
int ix = 0;
int j;
int insert_ph = 0;
PHONEME_LIST *phlist;
@@ -146,26 +141,21 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)

// is the last word of the clause unstressed ?
max_stress = 0;
for(j = n_ph_list2-3; j>=0; j--)
{
for (j = n_ph_list2-3; j >= 0; j--) {
// start with the last phoneme (before the terminating pauses) and move backwards
if((plist2[j].stresslevel & 0x7f) > max_stress)
if ((plist2[j].stresslevel & 0x7f) > max_stress)
max_stress = plist2[j].stresslevel & 0x7f;
if(plist2[j].sourceix != 0)
if (plist2[j].sourceix != 0)
break;
}
if(max_stress < 4)
{
if (max_stress < 4) {
// the last word is unstressed, look for a previous word that can be stressed
while(--j >= 0)
{
if(plist2[j].synthflags & SFLAG_PROMOTE_STRESS) // dictionary flags indicated that this stress can be promoted
{
while (--j >= 0) {
if (plist2[j].synthflags & SFLAG_PROMOTE_STRESS) { // dictionary flags indicated that this stress can be promoted
plist2[j].stresslevel = 4; // promote to stressed
break;
}
if(plist2[j].stresslevel >= 4)
{
if (plist2[j].stresslevel >= 4) {
// found a stressed syllable, so stop looking
break;
}
@@ -175,32 +165,25 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
// look for switch of phoneme tables
delete_count = 0;
current_phoneme_tab = tr->phoneme_tab_ix;
for(j = 0; j < n_ph_list2; j++)
{
if(current_phoneme_tab != tr->phoneme_tab_ix)
{
for (j = 0; j < n_ph_list2; j++) {
if (current_phoneme_tab != tr->phoneme_tab_ix) {
plist2[j].synthflags |= SFLAG_SWITCHED_LANG;
}

if(delete_count > 0)
{
if (delete_count > 0) {
memcpy(&plist2[j-delete_count], &plist2[j], sizeof(plist2[0]));
}

if(plist2[j].phcode == phonSWITCH)
{
if((!(plist2[j].synthflags & SFLAG_EMBEDDED)) && (
(plist2[j].tone_ph == current_phoneme_tab) ||
(plist2[j+1].phcode == phonSWITCH) ||
((plist2[j+1].phcode == phonPAUSE) && (plist2[j+2].phcode == phonSWITCH))
))
{
if (plist2[j].phcode == phonSWITCH) {
if ((!(plist2[j].synthflags & SFLAG_EMBEDDED)) && (
(plist2[j].tone_ph == current_phoneme_tab) ||
(plist2[j+1].phcode == phonSWITCH) ||
((plist2[j+1].phcode == phonPAUSE) && (plist2[j+2].phcode == phonSWITCH))
)) {
// delete this phonSWITCH if it's switching to the current phoneme table, or
// delete this phonSWITCH if its followed by another phonSWITCH
delete_count++;
}
else
{
} else {
current_phoneme_tab = plist2[j].tone_ph;
}
}
@@ -208,95 +191,71 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
}
n_ph_list2 -= delete_count;

if((regression = tr->langopts.param[LOPT_REGRESSIVE_VOICING]) != 0)
{
if ((regression = tr->langopts.param[LOPT_REGRESSIVE_VOICING]) != 0) {
// set consonant clusters to all voiced or all unvoiced
// Regressive
int type;
int stop_propagation = 0;
voicing = 0;

for(j=n_ph_list2-1; j>=0; j--)
{
for (j = n_ph_list2-1; j >= 0; j--) {
ph = phoneme_tab[plist2[j].phcode];
if(ph == NULL)
if (ph == NULL)
continue;

if(plist2[j].synthflags & SFLAG_SWITCHED_LANG)
{
if (plist2[j].synthflags & SFLAG_SWITCHED_LANG) {
stop_propagation = 0;
voicing = 0;
if(regression & 0x100)
if (regression & 0x100)
voicing = 1; // word-end devoicing
continue;
}

type = ph->type;

if(regression & 0x2)
{
if (regression & 0x2) {
// [v] amd [v;] don't cause regression, or [R^]
if(((ph->mnemonic & 0xff) == 'v') || ((ph->mnemonic & 0xff)== 'R'))
{
if (((ph->mnemonic & 0xff) == 'v') || ((ph->mnemonic & 0xff) == 'R')) {
stop_propagation = 1;
if(regression & 0x10)
if (regression & 0x10)
voicing = 0;
}
}

if((type==phSTOP) || type==(phFRICATIVE))
{
if((voicing==0) && (regression & 0xf))
{
if ((type == phSTOP) || type == (phFRICATIVE)) {
if ((voicing == 0) && (regression & 0xf)) {
voicing = 1;
}
else if((voicing==2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants
{
} else if ((voicing == 2) && (ph->end_type != 0)) { // use end_type field for voicing_switch for consonants
plist2[j].phcode = ph->end_type; // change to voiced equivalent
}
}
else if((type==phVSTOP) || type==(phVFRICATIVE))
{
if((voicing==0) && (regression & 0xf))
{
} else if ((type == phVSTOP) || type == (phVFRICATIVE)) {
if ((voicing == 0) && (regression & 0xf)) {
voicing = 2;
}
else if((voicing==1) && (ph->end_type != 0))
{
} else if ((voicing == 1) && (ph->end_type != 0)) {
plist2[j].phcode = ph->end_type; // change to unvoiced equivalent
}
}
else
{
if(regression & 0x8)
{
} else {
if (regression & 0x8) {
// LANG=Polish, propagate through liquids and nasals
if((type == phPAUSE) || (type == phVOWEL))
if ((type == phPAUSE) || (type == phVOWEL))
voicing = 0;
}
else
{
} else {
voicing = 0;
}
}
if(stop_propagation)
{
if (stop_propagation) {
voicing = 0;
stop_propagation = 0;
}

if(plist2[j].sourceix)
{
if(regression & 0x04)
{
if (plist2[j].sourceix) {
if (regression & 0x04) {
// stop propagation at a word boundary
voicing = 0;
}
if(regression & 0x100)
{
if (regression & 0x100) {
// devoice word-final consonants, unless propagating voiced
if(voicing == 0)
{
if (voicing == 0) {
voicing = 1;
}
}
@@ -304,35 +263,29 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
}
}

n_ph_list3 = SubstitutePhonemes(tr,ph_list3) - 2;
n_ph_list3 = SubstitutePhonemes(tr, ph_list3) - 2;

for(j=0; (j < n_ph_list3) && (ix < N_PHONEME_LIST-3); )
{
if(ph_list3[j].sourceix)
{
for (j = 0; (j < n_ph_list3) && (ix < N_PHONEME_LIST-3);) {
if (ph_list3[j].sourceix) {
// start of a word
int k;
int nextw;
word_stress = 0;

// find the highest stress level in this word
for(nextw=j; nextw < n_ph_list3; )
{
if(ph_list3[nextw].stresslevel > word_stress)
for (nextw = j; nextw < n_ph_list3;) {
if (ph_list3[nextw].stresslevel > word_stress)
word_stress = ph_list3[nextw].stresslevel;

nextw++;
if(ph_list3[nextw].sourceix)
if (ph_list3[nextw].sourceix)
break; // start of the next word
}
for(k=j; k<nextw; k++)
{
for (k = j; k < nextw; k++) {
ph_list3[k].wordstress = word_stress;
}
j = nextw;
}
else
{
} else {
j++;
}
}
@@ -342,14 +295,12 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
ph_list3[0].ph = ph;
word_start = 1;

for(j=0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++)
{
for (j = 0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) {
plist3 = &ph_list3[j];

inserted = 0;
deleted = 0;
if(insert_ph != 0)
{
if (insert_ph != 0) {
// we have a (linking) phoneme which we need to insert here
next = phoneme_tab[plist3->phcode]; // this phoneme, i.e. after the insert

@@ -357,20 +308,16 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
// That's OK because we don't look backwards from plist3 *** but CountVowelPosition() and isAfterStress does !!!
j--;
plist3 = plist3_inserted = &ph_list3[j];
if(j > 0)
{
if (j > 0) {
// move all previous phonemes in the word back one place
int k;
if(word_start > 0)
{
if (word_start > 0) {
k = word_start;
word_start--;
}
else
{
} else {
k = 2; // No more space, don't loose the start of word mark at ph_list2[word_start]
}
for(; k<=j; k++)
for (; k <= j; k++)
memcpy(&ph_list3[k-1], &ph_list3[k], sizeof(*plist3));
}
memset(&plist3[0], 0, sizeof(*plist3));
@@ -379,18 +326,15 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
plist3->ph = ph;
insert_ph = 0;
inserted = 1; // don't insert the same phoneme repeatedly
}
else
{
} else {
// otherwise get the next phoneme from the list
if(plist3->sourceix != 0)
if (plist3->sourceix != 0)
word_start = j;

ph = phoneme_tab[plist3->phcode];
plist3[0].ph = ph;

if(plist3->phcode == phonSWITCH)
{
if (plist3->phcode == phonSWITCH) {
// change phoneme table
SelectPhonemeTable(plist3->tone_ph);
}
@@ -398,20 +342,18 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
plist3[1].ph = next;
}

if(ph == NULL) continue;
if (ph == NULL) continue;

InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata);

if((alternative = phdata.pd_param[pd_CHANGE_NEXTPHONEME]) > 0)
{
if ((alternative = phdata.pd_param[pd_CHANGE_NEXTPHONEME]) > 0) {
ph_list3[j+1].ph = phoneme_tab[alternative];
ph_list3[j+1].phcode = alternative;
ph_list3[j+1].type = phoneme_tab[alternative]->type;
next = phoneme_tab[alternative];
}

if(((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0) && (inserted == 0))
{
if (((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0) && (inserted == 0)) {
// PROBLEM: if we insert a phoneme before a vowel then we loose the stress.
PHONEME_TAB *ph2;
ph2 = ph;
@@ -421,13 +363,11 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
plist3->ph = ph;
plist3->phcode = alternative;

if(ph->type == phVOWEL)
{
if (ph->type == phVOWEL) {
plist3->synthflags |= SFLAG_SYLLABLE;
if(ph2->type != phVOWEL)
if (ph2->type != phVOWEL)
plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed
}
else
} else
plist3->synthflags &= ~SFLAG_SYLLABLE;

// re-interpret the changed phoneme
@@ -435,27 +375,21 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata);
}

if((alternative = phdata.pd_param[pd_CHANGEPHONEME]) > 0)
{
if ((alternative = phdata.pd_param[pd_CHANGEPHONEME]) > 0) {
PHONEME_TAB *ph2;
ph2 = ph;
ph = phoneme_tab[alternative];
plist3->ph = ph;
plist3->phcode = alternative;

if(alternative == 1)
{
if (alternative == 1) {
deleted = 1; // NULL phoneme, discard
}
else
{
if(ph->type == phVOWEL)
{
} else {
if (ph->type == phVOWEL) {
plist3->synthflags |= SFLAG_SYLLABLE;
if(ph2->type != phVOWEL)
if (ph2->type != phVOWEL)
plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed
}
else
} else
plist3->synthflags &= ~SFLAG_SYLLABLE;

// re-interpret the changed phoneme
@@ -464,64 +398,48 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
}
}

if((ph->type == phVOWEL) && (deleted == 0))
{
if ((ph->type == phVOWEL) && (deleted == 0)) {
PHONEME_LIST *p;

// Check for consecutive unstressed syllables, even across word boundaries.
// Do this after changing phonemes according to stress level.
if(plist3->stresslevel <= 1)
{
if (plist3->stresslevel <= 1) {
// an unstressed vowel
unstress_count++;

if(tr->langopts.stress_flags & 0x08)
{
if (tr->langopts.stress_flags & 0x08) {
// change sequences of consecutive unstressed vowels in unstressed words to diminished stress (TEST)
for(p=plist3+1; p->type != phPAUSE; p++)
{
if(p->type == phVOWEL)
{
if(p->stresslevel <= 1)
{
if(plist3->wordstress < 4)
for (p = plist3+1; p->type != phPAUSE; p++) {
if (p->type == phVOWEL) {
if (p->stresslevel <= 1) {
if (plist3->wordstress < 4)
plist3->stresslevel = 0;
if(p->wordstress < 4)
if (p->wordstress < 4)
p->stresslevel = 0;
}
break;
}
}
}
else
{
if((unstress_count > 1) && ((unstress_count & 1)==0))
{
} else {
if ((unstress_count > 1) && ((unstress_count & 1) == 0)) {
// in a sequence of unstressed syllables, reduce alternate syllables to 'diminished'
// stress. But not for the last phoneme of a stressed word
if((tr->langopts.stress_flags & S_NO_DIM) || ((word_stress > 3) && ((plist3+1)->sourceix!=0)))
{
if ((tr->langopts.stress_flags & S_NO_DIM) || ((word_stress > 3) && ((plist3+1)->sourceix != 0))) {
// An unstressed final vowel of a stressed word
unstress_count=1; // try again for next syllable
}
else
{
unstress_count = 1; // try again for next syllable
} else {
plist3->stresslevel = 0; // change stress to 'diminished'
}
}
}
}
else
{
} else {
unstress_count = 0;
}
}

if((plist3+1)->synthflags & SFLAG_LENGTHEN)
{
static char types_double[] = {phFRICATIVE,phVFRICATIVE,phNASAL,phLIQUID,0};
if((j > 0) && (strchr(types_double,next->type)))
{
if ((plist3+1)->synthflags & SFLAG_LENGTHEN) {
static char types_double[] = { phFRICATIVE, phVFRICATIVE, phNASAL, phLIQUID, 0 };
if ((j > 0) && (strchr(types_double, next->type))) {
// lengthen this consonant by doubling it
// BUT, can't insert a phoneme at position plist3[0] because it crashes PrevPh()
insert_ph = next->code;
@@ -529,59 +447,48 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
}
}

if((plist3+1)->sourceix != 0)
{
if ((plist3+1)->sourceix != 0) {
int x;

if(tr->langopts.vowel_pause && (ph->type != phPAUSE))
{
if (tr->langopts.vowel_pause && (ph->type != phPAUSE)) {

if((ph->type != phVOWEL) && (tr->langopts.vowel_pause & 0x200))
{
if ((ph->type != phVOWEL) && (tr->langopts.vowel_pause & 0x200)) {
// add a pause after a word which ends in a consonant
insert_ph = phonPAUSE_NOLINK;
}

if(next->type == phVOWEL)
{
if((x = tr->langopts.vowel_pause & 0x0c) != 0)
{
if (next->type == phVOWEL) {
if ((x = tr->langopts.vowel_pause & 0x0c) != 0) {
// break before a word which starts with a vowel
if(x == 0xc)
if (x == 0xc)
insert_ph = phonPAUSE_NOLINK;
else
insert_ph = phonPAUSE_VSHORT;
}

if((ph->type == phVOWEL) && ((x = tr->langopts.vowel_pause & 0x03) != 0))
{
if ((ph->type == phVOWEL) && ((x = tr->langopts.vowel_pause & 0x03) != 0)) {
// adjacent vowels over a word boundary
if(x == 2)
if (x == 2)
insert_ph = phonPAUSE_SHORT;
else
insert_ph = phonPAUSE_VSHORT;
}

if(((plist3+1)->stresslevel >= 4) && (tr->langopts.vowel_pause & 0x100))
{
if (((plist3+1)->stresslevel >= 4) && (tr->langopts.vowel_pause & 0x100)) {
// pause before a words which starts with a stressed vowel
insert_ph = phonPAUSE_SHORT;
}
}
}

if((plist3 != plist3_inserted) && (ix > 0))
{
if((x = (tr->langopts.word_gap & 0x7)) != 0)
{
if((x > 1) || ((insert_ph != phonPAUSE_SHORT) && (insert_ph != phonPAUSE_NOLINK)))
{
if ((plist3 != plist3_inserted) && (ix > 0)) {
if ((x = (tr->langopts.word_gap & 0x7)) != 0) {
if ((x > 1) || ((insert_ph != phonPAUSE_SHORT) && (insert_ph != phonPAUSE_NOLINK))) {
// don't reduce the pause
insert_ph = pause_phonemes[x];
}
}
if(option_wordgap > 0)
{
if (option_wordgap > 0) {
insert_ph = phonPAUSE_LONG;
}
}
@@ -590,13 +497,11 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
next2 = phoneme_tab[plist3[2].phcode];
plist3[2].ph = next2;

if((insert_ph == 0) && (phdata.pd_param[pd_APPENDPHONEME] != 0))
{
if ((insert_ph == 0) && (phdata.pd_param[pd_APPENDPHONEME] != 0)) {
insert_ph = phdata.pd_param[pd_APPENDPHONEME];
}

if(deleted == 0)
{
if (deleted == 0) {
phlist[ix].ph = ph;
phlist[ix].type = ph->type;
phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module
@@ -607,31 +512,25 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
phlist[ix].sourceix = 0;
phlist[ix].phcode = ph->code;

if(plist3->sourceix != 0)
{
if (plist3->sourceix != 0) {
phlist[ix].sourceix = plist3->sourceix;
phlist[ix].newword = 1; // this phoneme is the start of a word

if(start_sentence)
{
if (start_sentence) {
phlist[ix].newword = 5; // start of sentence + start of word
start_sentence = 0;
}
}
else
{
} else {
phlist[ix].newword = 0;
}

phlist[ix].length = phdata.pd_param[i_SET_LENGTH]*2;
if((ph->code == phonPAUSE_LONG) && (option_wordgap > 0) && (plist3[1].sourceix != 0))
{
if ((ph->code == phonPAUSE_LONG) && (option_wordgap > 0) && (plist3[1].sourceix != 0)) {
phlist[ix].ph = phoneme_tab[phonPAUSE_SHORT];
phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed
}

if(ph->type==phVOWEL || ph->type==phLIQUID || ph->type==phNASAL || ph->type==phVSTOP || ph->type==phVFRICATIVE || (ph->phflags & phPREVOICE))
{
if (ph->type == phVOWEL || ph->type == phLIQUID || ph->type == phNASAL || ph->type == phVSTOP || ph->type == phVFRICATIVE || (ph->phflags & phPREVOICE)) {
phlist[ix].length = 128; // length_mod
phlist[ix].env = PITCHfall;
}
@@ -655,7 +554,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
phlist[ix].phcode = phonPAUSE;
phlist[ix].type = phPAUSE;
phlist[ix].length = 0;
phlist[ix].sourceix=0;
phlist[ix].sourceix = 0;
phlist[ix].synthflags = 0;
phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT];


+ 878
- 1190
src/libespeak-ng/readclause.c
File diff suppressed because it is too large
View File


+ 165
- 284
src/libespeak-ng/setlengths.c View File

@@ -102,9 +102,9 @@ static unsigned char speed_lookup[] = {

// speed_factor1 adjustments for speeds 350 to 374: pauses
static unsigned char pause_factor_350[] = {
22,22,22,22,22,22,22,21,21,21, // 350
21,20,20,19,19,18,17,16,15,15, // 360
15,15,15,15,15
22, 22, 22, 22, 22, 22, 22, 21, 21, 21, // 350
21, 20, 20, 19, 19, 18, 17, 16, 15, 15, // 360
15, 15, 15, 15, 15
}; // 370

// wav_factor adjustments for speeds 350 to 450
@@ -157,36 +157,31 @@ void SetSpeed(int control)
speed.min_pause = 5;

wpm = embedded_value[EMBED_S];
if(control == 2)
if (control == 2)
wpm = embedded_value[EMBED_S2];

wpm_value = wpm;

if(voice->speed_percent > 0)
{
if (voice->speed_percent > 0) {
wpm = (wpm * voice->speed_percent)/100;
}

if(control & 2)
{
if (control & 2) {
DoSonicSpeed(1 * 1024);
}
if((wpm_value >= 450) || ((wpm_value > speed.fast_settings[0]) && (wpm > 350)))
{
if ((wpm_value >= 450) || ((wpm_value > speed.fast_settings[0]) && (wpm > 350))) {
wpm2 = wpm;
wpm = 175;

// set special eSpeak speed parameters for Sonic use
// The eSpeak output will be speeded up by at least x2
x = 73;
if(control & 1)
{
if (control & 1) {
speed1 = (x * voice->speedf1)/256;
speed2 = (x * voice->speedf2)/256;
speed3 = (x * voice->speedf3)/256;
}
if(control & 2)
{
if (control & 2) {
sonic = ((double)wpm2)/wpm;
DoSonicSpeed((int)(sonic * 1024));
speed.pause_factor = 85;
@@ -200,71 +195,61 @@ void SetSpeed(int control)
return;
}

if(wpm > 450)
if (wpm > 450)
wpm = 450;

if(wpm > 360)
{
if (wpm > 360) {
speed.loud_consonants = (wpm - 360) / 8;
}

wpm2 = wpm;
if(wpm > 359) wpm2 = 359;
if(wpm < 80) wpm2 = 80;
if (wpm > 359) wpm2 = 359;
if (wpm < 80) wpm2 = 80;
x = speed_lookup[wpm2-80];

if(wpm >= 380)
if (wpm >= 380)
x = 7;
if(wpm >= 400)
if (wpm >= 400)
x = 6;

if(control & 1)
{
if (control & 1) {
// set speed factors for different syllable positions within a word
// these are used in CalcLengths()
speed1 = (x * voice->speedf1)/256;
speed2 = (x * voice->speedf2)/256;
speed3 = (x * voice->speedf3)/256;

if(x <= 7)
{
if (x <= 7) {
speed1 = x;
speed2 = speed3 = x - 1;
}
}

if(control & 2)
{
if (control & 2) {
// these are used in synthesis file

if(wpm > 350)
{
if (wpm > 350) {
speed.lenmod_factor = 85 - (wpm - 350) / 3;
speed.lenmod2_factor = 60 - (wpm - 350) / 8;
}
else
if(wpm > 250)
{
} else if (wpm > 250) {
speed.lenmod_factor = 110 - (wpm - 250)/4;
speed.lenmod2_factor = 110 - (wpm - 250)/2;
}

s1 = (x * voice->speedf1)/256;

if(wpm >= 170)
if (wpm >= 170)
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
else
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm

if(wpm >= 350)
{
if (wpm >= 350) {
speed.wav_factor = wav_factor_350[wpm-350];
}

if(wpm >= 390)
{
if (wpm >= 390) {
speed.min_sample_len = 450 - (wpm - 400)/2;
if(wpm > 440)
if (wpm > 440)
speed.min_sample_len = 420 - (wpm - 440);
}

@@ -274,30 +259,19 @@ void SetSpeed(int control)
speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length
speed.clause_pause_factor = 0;

if(wpm > 430)
{
if (wpm > 430) {
speed.pause_factor = 12;
}
else
if(wpm > 400)
{
} else if (wpm > 400) {
speed.pause_factor = 13;
}
else
if(wpm > 374)
{
} else if (wpm > 374) {
speed.pause_factor = 14;
}
else
if(wpm > 350)
{
} else if (wpm > 350) {
speed.pause_factor = pause_factor_350[wpm - 350];
}

if(speed.clause_pause_factor == 0)
{
if (speed.clause_pause_factor == 0) {
// restrict the reduction of pauses between clauses
if((speed.clause_pause_factor = speed.pause_factor) < 16)
if ((speed.clause_pause_factor = speed.pause_factor) < 16)
speed.clause_pause_factor = 16;
}
}
@@ -319,108 +293,86 @@ void SetSpeed(int control)
speed.lenmod2_factor = 100;

wpm = embedded_value[EMBED_S];
if(control == 2)
if (control == 2)
wpm = embedded_value[EMBED_S2];

if(voice->speed_percent > 0)
{
if (voice->speed_percent > 0) {
wpm = (wpm * voice->speed_percent)/100;
}
if(wpm > 450)
if (wpm > 450)
wpm = 450;

if(wpm > 360)
{
if (wpm > 360) {
speed.loud_consonants = (wpm - 360) / 8;
}

wpm2 = wpm;
if(wpm > 359) wpm2 = 359;
if(wpm < 80) wpm2 = 80;
if (wpm > 359) wpm2 = 359;
if (wpm < 80) wpm2 = 80;
x = speed_lookup[wpm2-80];

if(wpm >= 380)
if (wpm >= 380)
x = 7;
if(wpm >= 400)
if (wpm >= 400)
x = 6;

if(control & 1)
{
if (control & 1) {
// set speed factors for different syllable positions within a word
// these are used in CalcLengths()
speed1 = (x * voice->speedf1)/256;
speed2 = (x * voice->speedf2)/256;
speed3 = (x * voice->speedf3)/256;

if(x <= 7)
{
if (x <= 7) {
speed1 = x;
speed2 = speed3 = x - 1;
}
}

if(control & 2)
{
if (control & 2) {
// these are used in synthesis file

if(wpm > 350)
{
if (wpm > 350) {
speed.lenmod_factor = 85 - (wpm - 350) / 3;
speed.lenmod2_factor = 60 - (wpm - 350) / 8;
}
else
if(wpm > 250)
{
} else if (wpm > 250) {
speed.lenmod_factor = 110 - (wpm - 250)/4;
speed.lenmod2_factor = 110 - (wpm - 250)/2;
}

s1 = (x * voice->speedf1)/256;

if(wpm >= 170)
if (wpm >= 170)
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
else
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm

if(wpm >= 350)
{
if (wpm >= 350) {
speed.wav_factor = wav_factor_350[wpm-350];
}

if(wpm >= 390)
{
if (wpm >= 390) {
speed.min_sample_len = 450 - (wpm - 400)/2;
if(wpm > 440)
if (wpm > 440)
speed.min_sample_len = 420 - (wpm - 440);
}

speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length
speed.clause_pause_factor = 0;

if(wpm > 430)
{
if (wpm > 430) {
speed.pause_factor = 12;
}
else
if(wpm > 400)
{
} else if (wpm > 400) {
speed.pause_factor = 13;
}
else
if(wpm > 374)
{
} else if (wpm > 374) {
speed.pause_factor = 14;
}
else
if(wpm > 350)
{
} else if (wpm > 350) {
speed.pause_factor = pause_factor_350[wpm - 350];
}

if(speed.clause_pause_factor == 0)
{
if (speed.clause_pause_factor == 0) {
// restrict the reduction of pauses between clauses
if((speed.clause_pause_factor = speed.pause_factor) < 16)
if ((speed.clause_pause_factor = speed.pause_factor) < 16)
speed.clause_pause_factor = 16;
}
}
@@ -437,10 +389,8 @@ void SetParameter(int parameter, int value, int relative)
int new_value = value;
int default_value;

if(relative)
{
if(parameter < 5)
{
if (relative) {
if (parameter < 5) {
default_value = param_defaults[parameter];
new_value = default_value + (default_value * value)/100;
}
@@ -448,7 +398,7 @@ void SetParameter(int parameter, int value, int relative)
param_stack[0].parameter[parameter] = new_value;
saved_parameters[parameter] = new_value;

switch(parameter)
switch (parameter)
{
case espeakRATE:
embedded_value[EMBED_S] = new_value;
@@ -462,13 +412,13 @@ void SetParameter(int parameter, int value, int relative)
break;

case espeakPITCH:
if(new_value > 99) new_value = 99;
if(new_value < 0) new_value = 0;
if (new_value > 99) new_value = 99;
if (new_value < 0) new_value = 0;
embedded_value[EMBED_P] = new_value;
break;

case espeakRANGE:
if(new_value > 99) new_value = 99;
if (new_value > 99) new_value = 99;
embedded_value[EMBED_R] = new_value;
break;

@@ -481,7 +431,7 @@ void SetParameter(int parameter, int value, int relative)
break;

case espeakINTONATION:
if((new_value & 0xff) != 0)
if ((new_value & 0xff) != 0)
translator->langopts.intonation_group = new_value & 0xff;
option_tone_flags = new_value;
break;
@@ -502,13 +452,12 @@ static void DoEmbedded2(int *embix)
do {
word = embedded_list[(*embix)++];

if((word & 0x1f) == EMBED_S)
{
if ((word & 0x1f) == EMBED_S) {
// speed
SetEmbedded(word & 0x7f, word >> 8); // adjusts embedded_value[EMBED_S]
SetSpeed(1);
}
} while((word & 0x80) == 0);
} while ((word & 0x80) == 0);
}


@@ -525,9 +474,9 @@ void CalcLengths(Translator *tr)

int stress;
int type;
static int more_syllables=0;
int pre_sonorant=0;
int pre_voiced=0;
static int more_syllables = 0;
int pre_sonorant = 0;
int pre_voiced = 0;
int last_pitch = 0;
int pitch_start;
int length_mod;
@@ -540,11 +489,10 @@ void CalcLengths(Translator *tr)
int pitch1;
int emphasized;
int tone_mod;
unsigned char *pitch_env=NULL;
unsigned char *pitch_env = NULL;
PHONEME_DATA phdata_tone;

for(ix=1; ix<n_phoneme_list; ix++)
{
for (ix = 1; ix < n_phoneme_list; ix++) {
prev = &phoneme_list[ix-1];
p = &phoneme_list[ix];
stress = p->stresslevel & 0x7;
@@ -552,16 +500,15 @@ void CalcLengths(Translator *tr)

next = &phoneme_list[ix+1];

if(p->synthflags & SFLAG_EMBEDDED)
{
if (p->synthflags & SFLAG_EMBEDDED) {
DoEmbedded2(&embedded_ix);
}

type = p->type;
if(p->synthflags & SFLAG_SYLLABLE)
if (p->synthflags & SFLAG_SYLLABLE)
type = phVOWEL;

switch(type)
switch (type)
{
case phPAUSE:
last_pitch = 0;
@@ -569,109 +516,91 @@ void CalcLengths(Translator *tr)

case phSTOP:
last_pitch = 0;
if(prev->type == phFRICATIVE)
if (prev->type == phFRICATIVE)
p->prepause = 25;
else
if((more_syllables > 0) || (stress < 4))
else if ((more_syllables > 0) || (stress < 4))
p->prepause = 48;
else
p->prepause = 60;

if(prev->type == phSTOP)
if (prev->type == phSTOP)
p->prepause = 60;

if((tr->langopts.word_gap & 0x10) && (p->newword))
if ((tr->langopts.word_gap & 0x10) && (p->newword))
p->prepause = 60;

if(p->ph->phflags & phLENGTHENSTOP)
if (p->ph->phflags & phLENGTHENSTOP)
p->prepause += 30;

if(p->synthflags & SFLAG_LENGTHEN)
if (p->synthflags & SFLAG_LENGTHEN)
p->prepause += tr->langopts.long_stop;
break;

case phVFRICATIVE:
case phFRICATIVE:
if(p->newword)
{
if((prev->type == phVOWEL) && (p->ph->phflags & phNOPAUSE))
{
}
else
{
if (p->newword) {
if ((prev->type == phVOWEL) && (p->ph->phflags & phNOPAUSE)) {
} else {
p->prepause = 15;
}
}

if(next->type==phPAUSE && prev->type==phNASAL && !(p->ph->phflags&phFORTIS))
if (next->type == phPAUSE && prev->type == phNASAL && !(p->ph->phflags&phFORTIS))
p->prepause = 25;

if(prev->ph->phflags & phBRKAFTER)
if (prev->ph->phflags & phBRKAFTER)
p->prepause = 30;

if((tr->langopts.word_gap & 0x10) && (p->newword))
if ((tr->langopts.word_gap & 0x10) && (p->newword))
p->prepause = 30;

if((p->ph->phflags & phSIBILANT) && next->type==phSTOP && !next->newword)
{
if(prev->type == phVOWEL)
if ((p->ph->phflags & phSIBILANT) && next->type == phSTOP && !next->newword) {
if (prev->type == phVOWEL)
p->length = 200; // ?? should do this if it's from a prefix
else
p->length = 150;
}
else
} else
p->length = 256;

if(type == phVFRICATIVE)
{
if(next->type==phVOWEL)
{
if (type == phVFRICATIVE) {
if (next->type == phVOWEL) {
pre_voiced = 1;
}
if((prev->type==phVOWEL) || (prev->type == phLIQUID))
{
if ((prev->type == phVOWEL) || (prev->type == phLIQUID)) {
p->length = (255 + prev->length)/2;
}
}
break;

case phVSTOP:
if(prev->type==phVFRICATIVE || prev->type==phFRICATIVE || (prev->ph->phflags & phSIBILANT) || (prev->type == phLIQUID))
if (prev->type == phVFRICATIVE || prev->type == phFRICATIVE || (prev->ph->phflags & phSIBILANT) || (prev->type == phLIQUID))
p->prepause = 30;

if(next->type==phVOWEL || next->type==phLIQUID)
{
if((next->type==phVOWEL) || !next->newword)
if (next->type == phVOWEL || next->type == phLIQUID) {
if ((next->type == phVOWEL) || !next->newword)
pre_voiced = 1;

p->prepause = 40;

if(prev->type == phVOWEL)
{
if (prev->type == phVOWEL) {
p->prepause = 0; // use murmur instead to link from the preceding vowel
}
else
if(prev->type == phPAUSE)
{
} else if (prev->type == phPAUSE) {
// reduce by the length of the preceding pause
if(prev->length < p->prepause)
if (prev->length < p->prepause)
p->prepause -= prev->length;
else
p->prepause = 0;
}
else
if(p->newword==0)
{
if(prev->type==phLIQUID)
} else if (p->newword == 0) {
if (prev->type == phLIQUID)
p->prepause = 20;
if(prev->type==phNASAL)
if (prev->type == phNASAL)
p->prepause = 12;

if(prev->type==phSTOP && !(prev->ph->phflags & phFORTIS))
if (prev->type == phSTOP && !(prev->ph->phflags & phFORTIS))
p->prepause = 0;
}
}
if((tr->langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20))
if ((tr->langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20))
p->prepause = 20;

break;
@@ -682,49 +611,36 @@ void CalcLengths(Translator *tr)
p->length = 256; // TEMPORARY
min_drop = 0;

if(p->newword)
{
if(prev->type==phLIQUID)
if (p->newword) {
if (prev->type == phLIQUID)
p->prepause = 25;
if(prev->type==phVOWEL)
{
if(!(p->ph->phflags & phNOPAUSE))
if (prev->type == phVOWEL) {
if (!(p->ph->phflags & phNOPAUSE))
p->prepause = 12;
}
}

if(next->type==phVOWEL)
{
if (next->type == phVOWEL) {
pre_sonorant = 1;
}
else
{
} else {
p->pitch2 = last_pitch;

if((prev->type==phVOWEL) || (prev->type == phLIQUID))
{
if ((prev->type == phVOWEL) || (prev->type == phLIQUID)) {
p->length = prev->length;

if(p->type == phLIQUID)
{
if (p->type == phLIQUID) {
p->length = speed1;
}

if(next->type == phVSTOP)
{
if (next->type == phVSTOP) {
p->length = (p->length * 160)/100;
}
if(next->type == phVFRICATIVE)
{
if (next->type == phVFRICATIVE) {
p->length = (p->length * 120)/100;
}
}
else
{
for(ix2=ix; ix2<n_phoneme_list; ix2++)
{
if(phoneme_list[ix2].type == phVOWEL)
{
} else {
for (ix2 = ix; ix2 < n_phoneme_list; ix2++) {
if (phoneme_list[ix2].type == phVOWEL) {
p->pitch2 = phoneme_list[ix2].pitch2;
break;
}
@@ -732,8 +648,7 @@ void CalcLengths(Translator *tr)
}

p->pitch1 = p->pitch2-16;
if(p->pitch2 < 16)
{
if (p->pitch2 < 16) {
p->pitch1 = 0;
}
p->env = PITCHfall;
@@ -746,49 +661,44 @@ void CalcLengths(Translator *tr)
next2 = &phoneme_list[ix+2];
next3 = &phoneme_list[ix+3];

if(stress > 7) stress = 7;
if (stress > 7) stress = 7;

if(stress <= 1)
{
if (stress <= 1) {
stress = stress ^ 1; // swap diminished and unstressed (until we swap stress_amps,stress_lengths in tr_languages)
}
if(pre_sonorant)
if (pre_sonorant)
p->amp = tr->stress_amps[stress]-1;
else
p->amp = tr->stress_amps[stress];

if(emphasized)
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
if(p->amp > tr->langopts.param[LOPT_MAXAMP_EOC])
if (p->amp > tr->langopts.param[LOPT_MAXAMP_EOC])
p->amp = tr->langopts.param[LOPT_MAXAMP_EOC];
}

// is the last syllable of a word ?
more_syllables=0;
more_syllables = 0;
end_of_clause = 0;
for(p2 = p+1; p2->newword== 0; p2++)
{
if((p2->type == phVOWEL) && !(p2->ph->phflags & phNONSYLLABIC))
for (p2 = p+1; p2->newword == 0; p2++) {
if ((p2->type == phVOWEL) && !(p2->ph->phflags & phNONSYLLABIC))
more_syllables++;

if(p2->ph->code == phonPAUSE_CLAUSE)
if (p2->ph->code == phonPAUSE_CLAUSE)
end_of_clause = 2;
}
if(p2->ph->code == phonPAUSE_CLAUSE)
if (p2->ph->code == phonPAUSE_CLAUSE)
end_of_clause = 2;

if((p2->newword & 2) && (more_syllables==0))
{
if ((p2->newword & 2) && (more_syllables == 0)) {
end_of_clause = 2;
}

// calc length modifier
if((next->ph->code == phonPAUSE_VSHORT) && (next2->type == phPAUSE))
{
if ((next->ph->code == phonPAUSE_VSHORT) && (next2->type == phPAUSE)) {
// if PAUSE_VSHORT is followed by a pause, then use that
next = next2;
next2 = next3;
@@ -796,101 +706,84 @@ void CalcLengths(Translator *tr)
}

next2type = next2->ph->length_mod;
if(more_syllables==0)
{
if(next->newword || next2->newword)
{
if (more_syllables == 0) {
if (next->newword || next2->newword) {
// don't use 2nd phoneme over a word boundary, unless it's a pause
if(next2type != 1)
if (next2type != 1)
next2type = 0;
}

len = tr->langopts.length_mods0[next2type *10+ next->ph->length_mod];

if((next->newword) && (tr->langopts.word_gap & 0x20))
{
if ((next->newword) && (tr->langopts.word_gap & 0x20)) {
// consider as a pause + first phoneme of the next word
length_mod = (len + tr->langopts.length_mods0[next->ph->length_mod *10+ 1])/2;
}
else
} else
length_mod = len;
}
else
{
} else {
length_mod = tr->langopts.length_mods[next2type *10+ next->ph->length_mod];

if((next->type == phNASAL) && (next2->type == phSTOP || next2->type == phVSTOP) && (next3->ph->phflags & phFORTIS))
if ((next->type == phNASAL) && (next2->type == phSTOP || next2->type == phVSTOP) && (next3->ph->phflags & phFORTIS))
length_mod -= 15;
}

if(more_syllables==0)
if (more_syllables == 0)
length_mod *= speed1;
else
if(more_syllables==1)
else if (more_syllables == 1)
length_mod *= speed2;
else
length_mod *= speed3;

length_mod = length_mod / 128;

if(length_mod < 8)
if (length_mod < 8)
length_mod = 8; // restrict how much lengths can be reduced

if(stress >= 7)
{
if (stress >= 7) {
// tonic syllable, include a constant component so it doesn't decrease directly with speed
length_mod += tr->langopts.lengthen_tonic;
if(emphasized)
if (emphasized)
length_mod += (tr->langopts.lengthen_tonic/2);
}
else
if(emphasized)
{
} else if (emphasized) {
length_mod += tr->langopts.lengthen_tonic;
}

if((len = tr->stress_lengths[stress]) == 0)
if ((len = tr->stress_lengths[stress]) == 0)
len = tr->stress_lengths[6];

length_mod = length_mod * len;

if(p->tone_ph != 0)
{
if((tone_mod = phoneme_tab[p->tone_ph]->std_length) > 0)
{
if (p->tone_ph != 0) {
if ((tone_mod = phoneme_tab[p->tone_ph]->std_length) > 0) {
// a tone phoneme specifies a percentage change to the length
length_mod = (length_mod * tone_mod) / 100;
}
}


if((end_of_clause == 2) && !(tr->langopts.stress_flags & S_NO_EOC_LENGTHEN))
{
if ((end_of_clause == 2) && !(tr->langopts.stress_flags & S_NO_EOC_LENGTHEN)) {
// this is the last syllable in the clause, lengthen it - more for short vowels
len = (p->ph->std_length * 2);
if(tr->langopts.stress_flags & S_EO_CLAUSE1)
len=200; // don't lengthen short vowels more than long vowels at end-of-clause
if (tr->langopts.stress_flags & S_EO_CLAUSE1)
len = 200; // don't lengthen short vowels more than long vowels at end-of-clause
length_mod = length_mod * (256 + (280 - len)/3)/256;
}

if(length_mod > tr->langopts.max_lengthmod*speed1)
{
//limit the vowel length adjustment for some languages
if (length_mod > tr->langopts.max_lengthmod*speed1) {
// limit the vowel length adjustment for some languages
length_mod = (tr->langopts.max_lengthmod*speed1);
}

length_mod = length_mod / 128;

if(p->type != phVOWEL)
{
if (p->type != phVOWEL) {
length_mod = 256; // syllabic consonant
min_drop = 16;
}
p->length = length_mod;

if(p->env >= (N_ENVELOPE_DATA-1))
{
fprintf(stderr,"espeak: Bad intonation data\n");
if (p->env >= (N_ENVELOPE_DATA-1)) {
fprintf(stderr, "espeak: Bad intonation data\n");
p->env = 0;
}

@@ -898,73 +791,61 @@ void CalcLengths(Translator *tr)
// set last-pitch
env2 = p->env + 1; // version for use with preceding semi-vowel

if(p->tone_ph != 0)
{
if (p->tone_ph != 0) {
InterpretPhoneme2(p->tone_ph, &phdata_tone);
pitch_env = GetEnvelope(phdata_tone.pitch_env);
}
else
{
} else {
pitch_env = envelope_data[env2];
}

pitch_start = p->pitch1 + ((p->pitch2-p->pitch1)*pitch_env[0])/256;

if(pre_sonorant || pre_voiced)
{
if (pre_sonorant || pre_voiced) {
// set pitch for pre-vocalic part
if(pitch_start == 255)
if (pitch_start == 255)
last_pitch = pitch_start; // pitch is not set

if(pitch_start - last_pitch > 16)
if (pitch_start - last_pitch > 16)
last_pitch = pitch_start - 16;

prev->pitch1 = last_pitch;
prev->pitch2 = pitch_start;
if(last_pitch < pitch_start)
{
if (last_pitch < pitch_start) {
prev->env = PITCHrise;
p->env = env2;
}
else
{
} else {
prev->env = PITCHfall;
}

prev->length = length_mod;

prev->amp = p->amp;
if((prev->type != phLIQUID) && (prev->amp > 18))
if ((prev->type != phLIQUID) && (prev->amp > 18))
prev->amp = 18;
}

// vowel & post-vocalic part
next->synthflags &= ~SFLAG_SEQCONTINUE;
if(next->type == phNASAL && next2->type != phVOWEL)
if (next->type == phNASAL && next2->type != phVOWEL)
next->synthflags |= SFLAG_SEQCONTINUE;

if(next->type == phLIQUID)
{
if (next->type == phLIQUID) {
next->synthflags |= SFLAG_SEQCONTINUE;

if(next2->type == phVOWEL)
{
if (next2->type == phVOWEL) {
next->synthflags &= ~SFLAG_SEQCONTINUE;
}

if(next2->type != phVOWEL)
{
if(next->ph->mnemonic == ('/'*256+'r'))
{
if (next2->type != phVOWEL) {
if (next->ph->mnemonic == ('/'*256+'r')) {
next->synthflags &= ~SFLAG_SEQCONTINUE;
}
}
}

if((min_drop > 0) && ((p->pitch2 - p->pitch1) < min_drop))
{
if ((min_drop > 0) && ((p->pitch2 - p->pitch1) < min_drop)) {
pitch1 = p->pitch2 - min_drop;
if(pitch1 < 0)
if (pitch1 < 0)
pitch1 = 0;
p->pitch1 = pitch1;
}

+ 220
- 307
src/libespeak-ng/speak_lib.c
File diff suppressed because it is too large
View File


+ 105
- 138
src/libespeak-ng/spect.c View File

@@ -48,54 +48,53 @@ int pk_select;
#define PEAKSHAPEW 256

static int default_freq[N_PEAKS] =
{200,500,1200,3000,3500,4000,6900,7800,9000};
{ 200, 500, 1200, 3000, 3500, 4000, 6900, 7800, 9000 };
static int default_width[N_PEAKS] =
{750,500,550,550,600,700,700,700,700};
{ 750, 500, 550, 550, 600, 700, 700, 700, 700 };
static int default_klt_bw[N_PEAKS] =
{89,90,140,260,260,260,500,500,500};
{ 89, 90, 140, 260, 260, 260, 500, 500, 500 };

static double read_double(FILE *stream)
{
unsigned char bytes[10];
fread(bytes,sizeof(char),10,stream);
fread(bytes, sizeof(char), 10, stream);
return ConvertFromIeeeExtended(bytes);
}

float polint(float xa[],float ya[],int n,float x)
float polint(float xa[], float ya[], int n, float x)
{
// General polinomial interpolation routine, xa[1...n] ya[1...n]
int i,m,ns=1;
float den,dif,dift,ho,hp,w;
int i, m, ns = 1;
float den, dif, dift, ho, hp, w;
float y; // result
float c[9],d[9];
float c[9], d[9];

dif=fabs(x-xa[1]);
dif = fabs(x-xa[1]);

for(i=1; i<=n; i++) {
if((dift=fabs(x-xa[i])) < dif) {
ns=i;
dif=dift;
for (i = 1; i <= n; i++) {
if ((dift = fabs(x-xa[i])) < dif) {
ns = i;
dif = dift;
}
c[i]=ya[i];
d[i]=ya[i];
c[i] = ya[i];
d[i] = ya[i];
}
y=ya[ns--];
for(m=1; m<n; m++) {
for(i=1; i<=n-m; i++) {
ho=xa[i]-x;
hp=xa[i+m]-x;
w=c[i+1]-d[i];
if((den=ho-hp) == 0.0)
{
return(ya[2]); // two input xa are identical
y = ya[ns--];
for (m = 1; m < n; m++) {
for (i = 1; i <= n-m; i++) {
ho = xa[i]-x;
hp = xa[i+m]-x;
w = c[i+1]-d[i];
if ((den = ho-hp) == 0.0) {
return (ya[2]); // two input xa are identical
}
den=w/den;
d[i]=hp*den;
c[i]=ho*den;
den = w/den;
d[i] = hp*den;
c[i] = ho*den;
}
y += ((2*ns < (n-m) ? c[ns+1] : d[ns--]));
}
return(y);
return (y);
}


@@ -115,8 +114,7 @@ static SpectFrame *SpectFrameCreate()
frame->amp_adjust = 100;
frame->length_adjust = 0;

for(ix=0; ix<N_PEAKS; ix++)
{
for (ix = 0; ix < N_PEAKS; ix++) {
frame->formants[ix].freq = 0;
frame->peaks[ix].pkfreq = default_freq[ix];
frame->peaks[ix].pkheight = 0;
@@ -136,7 +134,7 @@ static SpectFrame *SpectFrameCreate()

static void SpectFrameDestroy(SpectFrame *frame)
{
if(frame->spect != NULL)
if (frame->spect != NULL)
free(frame->spect);
free(frame);
}
@@ -153,61 +151,54 @@ int LoadFrame(SpectFrame *frame, FILE *stream, int file_format_type)
frame->pitch = read_double(stream);
frame->length = read_double(stream);
frame->dx = read_double(stream);
fread(&frame->nx,sizeof(short),1,stream);
fread(&frame->markers,sizeof(short),1,stream);
fread(&frame->amp_adjust,sizeof(short),1,stream);

if(file_format_type == 2)
{
fread(&ix,sizeof(short),1,stream); // spare
fread(&ix,sizeof(short),1,stream); // spare
fread(&frame->nx, sizeof(short), 1, stream);
fread(&frame->markers, sizeof(short), 1, stream);
fread(&frame->amp_adjust, sizeof(short), 1, stream);

if (file_format_type == 2) {
fread(&ix, sizeof(short), 1, stream); // spare
fread(&ix, sizeof(short), 1, stream); // spare
}

for(ix=0; ix<N_PEAKS; ix++)
{
fread(&frame->formants[ix].freq,sizeof(short),1,stream);
fread(&frame->formants[ix].bandw,sizeof(short),1,stream);
fread(&frame->peaks[ix].pkfreq,sizeof(short),1,stream);
fread(&frame->peaks[ix].pkheight,sizeof(short),1,stream);
fread(&frame->peaks[ix].pkwidth,sizeof(short),1,stream);
fread(&frame->peaks[ix].pkright,sizeof(short),1,stream);
if(frame->peaks[ix].pkheight > 0)
for (ix = 0; ix < N_PEAKS; ix++) {
fread(&frame->formants[ix].freq, sizeof(short), 1, stream);
fread(&frame->formants[ix].bandw, sizeof(short), 1, stream);
fread(&frame->peaks[ix].pkfreq, sizeof(short), 1, stream);
fread(&frame->peaks[ix].pkheight, sizeof(short), 1, stream);
fread(&frame->peaks[ix].pkwidth, sizeof(short), 1, stream);
fread(&frame->peaks[ix].pkright, sizeof(short), 1, stream);
if (frame->peaks[ix].pkheight > 0)
frame->keyframe = 1;

if(file_format_type == 2)
{
fread(&frame->peaks[ix].klt_bw,sizeof(short),1,stream);
fread(&frame->peaks[ix].klt_ap,sizeof(short),1,stream);
fread(&frame->peaks[ix].klt_bp,sizeof(short),1,stream);
if (file_format_type == 2) {
fread(&frame->peaks[ix].klt_bw, sizeof(short), 1, stream);
fread(&frame->peaks[ix].klt_ap, sizeof(short), 1, stream);
fread(&frame->peaks[ix].klt_bp, sizeof(short), 1, stream);
}
}

if(file_format_type > 0)
{
for(ix=0; ix<N_KLATTP2; ix++)
{
fread(frame->klatt_param + ix,sizeof(short),1,stream);
if (file_format_type > 0) {
for (ix = 0; ix < N_KLATTP2; ix++) {
fread(frame->klatt_param + ix, sizeof(short), 1, stream);
}
}

spect_data = malloc(sizeof(USHORT) * frame->nx);

if(spect_data == NULL)
{
fprintf(stderr,"Failed to allocate memory\n");
return(1);
if (spect_data == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
return (1);
}

frame->max_y = 0;
for(ix=0; ix<frame->nx; ix++)
{
fread(&x,sizeof(short),1,stream);
for (ix = 0; ix < frame->nx; ix++) {
fread(&x, sizeof(short), 1, stream);
spect_data[ix] = x;
if(x > frame->max_y) frame->max_y = x;
if (x > frame->max_y) frame->max_y = x;
}
frame->spect = spect_data;

return(0);
return (0);
}


@@ -215,14 +206,13 @@ int LoadFrame(SpectFrame *frame, FILE *stream, int file_format_type)
double GetFrameRms(SpectFrame *frame, int seq_amplitude)
{
int h;
float total=0;
float total = 0;
int maxh;
int height;
int htab[400];
wavegen_peaks_t wpeaks[9];

for(h=0; h<9; h++)
{
for (h = 0; h < 9; h++) {
height = (frame->peaks[h].pkheight * seq_amplitude * frame->amp_adjust)/10000;
wpeaks[h].height = height << 8;

@@ -231,13 +221,12 @@ double GetFrameRms(SpectFrame *frame, int seq_amplitude)
wpeaks[h].right = frame->peaks[h].pkright << 16;
}

maxh = PeaksToHarmspect(wpeaks,90<<16,htab,0);
for(h=1; h<maxh; h++)
{
maxh = PeaksToHarmspect(wpeaks, 90<<16, htab, 0);
for (h = 1; h < maxh; h++) {
total += ((htab[h] * htab[h]) >> 10);
}
frame->rms = sqrt(total) / 7.25;
return(frame->rms);
return (frame->rms);
}


@@ -266,11 +255,9 @@ SpectSeq *SpectSeqCreate()
void SpectSeqDestroy(SpectSeq *spect)
{
int ix;
if(spect->frames != NULL)
{
for(ix=0; ix<spect->numframes; ix++)
{
if(spect->frames[ix] != NULL)
if (spect->frames != NULL) {
for (ix = 0; ix < spect->numframes; ix++) {
if (spect->frames[ix] != NULL)
SpectFrameDestroy(spect->frames[ix]);
}
free(spect->frames);
@@ -283,13 +270,12 @@ void SpectSeqDestroy(SpectSeq *spect)
static float GetFrameLength(SpectSeq *spect, int frame)
{
int ix;
float adjust=0;
float adjust = 0;

if(frame >= spect->numframes-1) return(0);
if (frame >= spect->numframes-1) return (0);

for(ix=frame+1; ix<spect->numframes-1; ix++)
{
if(spect->frames[ix]->keyframe) break; // reached next keyframe
for (ix = frame+1; ix < spect->numframes-1; ix++) {
if (spect->frames[ix]->keyframe) break; // reached next keyframe
adjust += spect->frames[ix]->length_adjust;
}
return ((spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust);
@@ -302,65 +288,50 @@ int LoadSpectSeq(SpectSeq *spect, const char *filename)
short n, temp;
int ix;
uint32_t id1, id2, name_len;
int set_max_y=0;
int set_max_y = 0;
float time_offset;

FILE *stream = fopen(filename, "rb");
if(stream == NULL)
{
if (stream == NULL) {
fprintf(stderr, "Failed to open: '%s'", filename);
return(0);
return (0);
}

fread(&id1,sizeof(uint32_t),1,stream);
fread(&id2,sizeof(uint32_t),1,stream);
fread(&id1, sizeof(uint32_t), 1, stream);
fread(&id2, sizeof(uint32_t), 1, stream);

if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEQ))
{
if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEQ)) {
spect->file_format = 0; // eSpeak formants
}
else
if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEK))
{
} else if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEK)) {
spect->file_format = 1; // formants for Klatt synthesizer
}
else
if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSQ2))
{
} else if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSQ2)) {
spect->file_format = 2; // formants for Klatt synthesizer
}
else
{
} else {
fprintf(stderr, "Unsupported spectral file format.\n");
fclose(stream);
return(1);
return (1);
}

fread(&name_len,sizeof(uint32_t),1,stream);
if (name_len > 0)
{
fread(&name_len, sizeof(uint32_t), 1, stream);
if (name_len > 0) {
spect->name = (char *)malloc(name_len);
fread(spect->name,sizeof(char),name_len,stream);
}
else
fread(spect->name, sizeof(char), name_len, stream);
} else
spect->name = NULL;

fread(&n,sizeof(short),1,stream);
fread(&spect->amplitude,sizeof(short),1,stream);
fread(&spect->max_y,sizeof(short),1,stream);
fread(&temp,sizeof(short),1,stream); // unused
fread(&n, sizeof(short), 1, stream);
fread(&spect->amplitude, sizeof(short), 1, stream);
fread(&spect->max_y, sizeof(short), 1, stream);
fread(&temp, sizeof(short), 1, stream); // unused

if(n==0)
{
if (n == 0) {
fclose(stream);
return(0);
return (0);
}

if(spect->frames != NULL)
{
for(ix=0; ix<spect->numframes; ix++)
{
if(spect->frames[ix] != NULL)
if (spect->frames != NULL) {
for (ix = 0; ix < spect->numframes; ix++) {
if (spect->frames[ix] != NULL)
SpectFrameDestroy(spect->frames[ix]);
}
free(spect->frames);
@@ -369,52 +340,48 @@ int LoadSpectSeq(SpectSeq *spect, const char *filename)

spect->numframes = 0;
spect->max_x = 3000;
if(spect->max_y == 0)
{
if (spect->max_y == 0) {
set_max_y = 1;
spect->max_y = 1;
}
for(ix = 0; ix < n; ix++)
{
for (ix = 0; ix < n; ix++) {
SpectFrame *frame = SpectFrameCreate();

if(LoadFrame(frame, stream, spect->file_format) != 0)
{
if (LoadFrame(frame, stream, spect->file_format) != 0) {
free(frame);
break;
}

spect->frames[spect->numframes++] = frame;

if(set_max_y && (frame->max_y > spect->max_y))
if (set_max_y && (frame->max_y > spect->max_y))
spect->max_y = frame->max_y;
if(frame->nx * frame->dx > spect->max_x) spect->max_x = (int)(frame->nx * frame->dx);
if (frame->nx * frame->dx > spect->max_x) spect->max_x = (int)(frame->nx * frame->dx);
}
spect->max_x = 9000; // disable auto-xscaling

frame_width = (int)((FRAME_WIDTH*spect->max_x)/MAX_DISPLAY_FREQ);
if(frame_width > FRAME_WIDTH) frame_width = FRAME_WIDTH;
if (frame_width > FRAME_WIDTH) frame_width = FRAME_WIDTH;


// start times from zero
time_offset = spect->frames[0]->time;
for(ix=0; ix<spect->numframes; ix++)
for (ix = 0; ix < spect->numframes; ix++)
spect->frames[ix]->time -= time_offset;

spect->pitch1 = spect->pitchenv.pitch1;
spect->pitch2 = spect->pitchenv.pitch2;
spect->duration = (int)(spect->frames[spect->numframes-1]->time * 1000);

if(spect->max_y < 400)
if (spect->max_y < 400)
spect->max_y = 200;
else
spect->max_y = 29000; // disable auto height scaling

for(ix=0; ix<spect->numframes; ix++)
{
if(spect->frames[ix]->keyframe)
spect->frames[ix]->length_adjust = spect->frames[ix]->length - GetFrameLength(spect,ix);
for (ix = 0; ix < spect->numframes; ix++) {
if (spect->frames[ix]->keyframe)
spect->frames[ix]->length_adjust = spect->frames[ix]->length - GetFrameLength(spect, ix);
}
fclose(stream);
return(0);
return (0);
}

+ 2
- 4
src/libespeak-ng/spect.h View File

@@ -87,8 +87,7 @@ typedef struct {
} peak_t;


typedef struct
{
typedef struct {
int keyframe;
short amp_adjust;
float length_adjust;
@@ -111,8 +110,7 @@ typedef struct

double GetFrameRms(SpectFrame *frame, int amp);

typedef struct
{
typedef struct {
int numframes;
short amplitude;
int spare;

+ 1
- 1
src/libespeak-ng/speech.h View File

@@ -86,7 +86,7 @@ int LookupMnem(MNEM_TAB *table, const char *string);

extern char path_home[N_PATH_HOME]; // this is the espeak-data directory

extern void strncpy0(char *to,const char *from, int size);
extern void strncpy0(char *to, const char *from, int size);
int GetFileLength(const char *filename);
char *Alloc(int size);
void Free(void *ptr);

+ 148
- 204
src/libespeak-ng/synth_mbrola.c View File

@@ -54,8 +54,8 @@ typedef void (WINAPI *PROCVI)(int);
typedef void (WINAPI *PROCVF)(float);
typedef int (WINAPI *PROCIV)();
typedef int (WINAPI *PROCIC)(char *);
typedef int (WINAPI *PROCISI)(short *,int);
typedef char* (WINAPI *PROCVCI)(char *,int);
typedef int (WINAPI *PROCISI)(short *, int);
typedef char * (WINAPI *PROCVCI)(char *, int);

PROCIC init_MBR;
PROCIC write_MBR;
@@ -76,31 +76,30 @@ HINSTANCE hinstDllMBR = NULL;

BOOL load_MBR()
{
if(hinstDllMBR != NULL)
if (hinstDllMBR != NULL)
return TRUE; // already loaded

if ((hinstDllMBR=LoadLibraryA("mbrola.dll")) == 0)
if ((hinstDllMBR = LoadLibraryA("mbrola.dll")) == 0)
return FALSE;
init_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"init_MBR");
write_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"write_MBR");
flush_MBR =(PROCIV) GetProcAddress(hinstDllMBR,"flush_MBR");
read_MBR =(PROCISI) GetProcAddress(hinstDllMBR,"read_MBR");
close_MBR =(PROCVV) GetProcAddress(hinstDllMBR,"close_MBR");
reset_MBR =(PROCVV) GetProcAddress(hinstDllMBR,"reset_MBR");
lastError_MBR =(PROCIV) GetProcAddress(hinstDllMBR,"lastError_MBR");
lastErrorStr_MBR =(PROCVCI) GetProcAddress(hinstDllMBR,"lastErrorStr_MBR");
setNoError_MBR =(PROCVI) GetProcAddress(hinstDllMBR,"setNoError_MBR");
setVolumeRatio_MBR =(PROCVF) GetProcAddress(hinstDllMBR,"setVolumeRatio_MBR");
init_MBR = (PROCIC)GetProcAddress(hinstDllMBR, "init_MBR");
write_MBR = (PROCIC)GetProcAddress(hinstDllMBR, "write_MBR");
flush_MBR = (PROCIV)GetProcAddress(hinstDllMBR, "flush_MBR");
read_MBR = (PROCISI)GetProcAddress(hinstDllMBR, "read_MBR");
close_MBR = (PROCVV)GetProcAddress(hinstDllMBR, "close_MBR");
reset_MBR = (PROCVV)GetProcAddress(hinstDllMBR, "reset_MBR");
lastError_MBR = (PROCIV)GetProcAddress(hinstDllMBR, "lastError_MBR");
lastErrorStr_MBR = (PROCVCI)GetProcAddress(hinstDllMBR, "lastErrorStr_MBR");
setNoError_MBR = (PROCVI)GetProcAddress(hinstDllMBR, "setNoError_MBR");
setVolumeRatio_MBR = (PROCVF)GetProcAddress(hinstDllMBR, "setVolumeRatio_MBR");
return TRUE;
}


void unload_MBR()
{
if (hinstDllMBR)
{
FreeLibrary (hinstDllMBR);
hinstDllMBR=NULL;
if (hinstDllMBR) {
FreeLibrary(hinstDllMBR);
hinstDllMBR = NULL;
}
}

@@ -125,79 +124,72 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int
mbrola_delay = 0;
mbr_name_prefix = 0;

if(mbrola_voice == NULL)
{
if (mbrola_voice == NULL) {
samplerate = samplerate_native;
SetParameter(espeakVOICETYPE,0,0);
return(EE_OK);
SetParameter(espeakVOICETYPE, 0, 0);
return (EE_OK);
}

sprintf(path,"%s/mbrola/%s",path_home,mbrola_voice);
sprintf(path, "%s/mbrola/%s", path_home, mbrola_voice);
#ifdef PLATFORM_POSIX
// if not found, then also look in
// usr/share/mbrola/xx, /usr/share/mbrola/xx/xx, /usr/share/mbrola/voices/xx
if(GetFileLength(path) <= 0)
{
sprintf(path,"/usr/share/mbrola/%s",mbrola_voice);
if (GetFileLength(path) <= 0) {
sprintf(path, "/usr/share/mbrola/%s", mbrola_voice);

if(GetFileLength(path) <= 0)
{
sprintf(path,"/usr/share/mbrola/%s/%s",mbrola_voice,mbrola_voice);
if (GetFileLength(path) <= 0) {
sprintf(path, "/usr/share/mbrola/%s/%s", mbrola_voice, mbrola_voice);

if(GetFileLength(path) <= 0)
{
sprintf(path,"/usr/share/mbrola/voices/%s",mbrola_voice);
if (GetFileLength(path) <= 0) {
sprintf(path, "/usr/share/mbrola/voices/%s", mbrola_voice);
}
}
}
close_MBR();
#endif
#ifdef PLATFORM_WINDOWS
if(load_MBR() == FALSE) // load mbrola.dll
{
if (load_MBR() == FALSE) { // load mbrola.dll
fprintf(stderr, "Can't load mbrola.dll\n");
return(EE_INTERNAL_ERROR);
return (EE_INTERNAL_ERROR);
}
#endif

if(init_MBR(path) != 0) // initialise the required mbrola voice
return(EE_NOT_FOUND);
if (init_MBR(path) != 0) // initialise the required mbrola voice
return (EE_NOT_FOUND);

setNoError_MBR(1); // don't stop on phoneme errors

// read eSpeak's mbrola phoneme translation data, eg. en1_phtrans
sprintf(path,"%s/mbrola_ph/%s",path_home,phtrans);
sprintf(path, "%s/mbrola_ph/%s", path_home, phtrans);
size = GetFileLength(path);
if((f_in = fopen(path,"rb")) == NULL) {
if ((f_in = fopen(path, "rb")) == NULL) {
close_MBR();
return(EE_NOT_FOUND);
return (EE_NOT_FOUND);
}

if((mbrola_tab = (MBROLA_TAB *)realloc(mbrola_tab,size)) == NULL)
{
if ((mbrola_tab = (MBROLA_TAB *)realloc(mbrola_tab, size)) == NULL) {
fclose(f_in);
close_MBR();
return(EE_INTERNAL_ERROR);
return (EE_INTERNAL_ERROR);
}

mbrola_control = Read4Bytes(f_in);
pw = (int *)mbrola_tab;
for(ix=4; ix<size; ix+=4)
{
for (ix = 4; ix < size; ix += 4) {
*pw++ = Read4Bytes(f_in);
}
size = fread(mbrola_tab,1,size,f_in);
size = fread(mbrola_tab, 1, size, f_in);
fclose(f_in);

setVolumeRatio_MBR((float)(mbrola_control & 0xff) /16.0f);
samplerate = *srate = getFreq_MBR();
if(*srate == 22050)
SetParameter(espeakVOICETYPE,0,0);
if (*srate == 22050)
SetParameter(espeakVOICETYPE, 0, 0);
else
SetParameter(espeakVOICETYPE,1,0);
strcpy(mbrola_name,mbrola_voice);
SetParameter(espeakVOICETYPE, 1, 0);
strcpy(mbrola_name, mbrola_voice);
mbrola_delay = 1000; // improve synchronization of events
return(EE_OK);
return (EE_OK);
}


@@ -219,60 +211,50 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev
// bit 5 only in stressed syllable
// bit 6 only at the end of a word

*name2=0;
*split=0;
*control=0;
*name2 = 0;
*split = 0;
*control = 0;
mnem = ph->mnemonic;

pr = mbrola_tab;
while(pr->name != 0)
{
if(mnem == pr->name)
{
if(pr->next_phoneme == 0)
while (pr->name != 0) {
if (mnem == pr->name) {
if (pr->next_phoneme == 0)
found = 1;
else
if((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN))
{
else if ((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN)) {
found = 1;
}
else
{
if(pr->control & 2)
} else {
if (pr->control & 2)
other_ph = ph_prev;
else
if((pr->control & 8) && ((plist+1)->newword))
else if ((pr->control & 8) && ((plist+1)->newword))
other_ph = phoneme_tab[phPAUSE]; // don't match the next phoneme over a word boundary
else
other_ph = ph_next;

if((pr->next_phoneme == other_ph->mnemonic) ||
((pr->next_phoneme == 2) && (other_ph->type == phVOWEL)) ||
((pr->next_phoneme == '_') && (other_ph->type == phPAUSE)))
{
if ((pr->next_phoneme == other_ph->mnemonic) ||
((pr->next_phoneme == 2) && (other_ph->type == phVOWEL)) ||
((pr->next_phoneme == '_') && (other_ph->type == phPAUSE))) {
found = 1;
}
}

if((pr->control & 4) && (plist->newword == 0)) // only at start of word
if ((pr->control & 4) && (plist->newword == 0)) // only at start of word
found = 0;

if((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word
if ((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word
found = 0;

if((pr->control & 0x20) && (plist->stresslevel < plist->wordstress))
if ((pr->control & 0x20) && (plist->stresslevel < plist->wordstress))
found = 0; // only in stressed syllables

if(found)
{
if (found) {
*name2 = pr->mbr_name2;
*split = pr->percent;
*control = pr->control;

if(pr->control & 0x10)
{
if (pr->control & 0x10) {
mbr_name_prefix = pr->mbr_name;
return(0);
return (0);
}
mnem = pr->mbr_name;
break;
@@ -282,12 +264,11 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev
pr++;
}

if(mbr_name_prefix != 0)
{
if (mbr_name_prefix != 0) {
mnem = (mnem << 8) | (mbr_name_prefix & 0xff);
}
mbr_name_prefix = 0;
return(mnem);
return (mnem);
}


@@ -298,12 +279,12 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final)
int ix;
int pitch_base;
int pitch_range;
int p1,p2,p_end;
int p1, p2, p_end;
unsigned char *pitch_env;
int max = -1;
int min = 999;
int y_max=0;
int y_min=0;
int y_max = 0;
int y_min = 0;
int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s)
int y2;
int y[4];
@@ -319,19 +300,16 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final)


env_split = (split * 128)/100;
if(env_split < 0)
if (env_split < 0)
env_split = 0-env_split;

// find max and min in the pitch envelope
for(x=0; x<128; x++)
{
if(pitch_env[x] > max)
{
for (x = 0; x < 128; x++) {
if (pitch_env[x] > max) {
max = pitch_env[x];
y_max = x;
}
if(pitch_env[x] < min)
{
if (pitch_env[x] < min) {
min = pitch_env[x];
y_min = x;
}
@@ -339,12 +317,10 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final)
// set an additional pitch point half way through the phoneme.
// but look for a maximum or a minimum and use that instead
y[2] = 64;
if((y_max > 0) && (y_max < 127))
{
if ((y_max > 0) && (y_max < 127)) {
y[2] = y_max;
}
if((y_min > 0) && (y_min < 127))
{
if ((y_min > 0) && (y_min < 127)) {
y[2] = y_min;
}
y[1] = y[2] / 2;
@@ -355,56 +331,44 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final)
p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base;


if(split >= 0)
{
sprintf(buf," 0 %d",p1/4096);
strcat(output,buf);
if (split >= 0) {
sprintf(buf, " 0 %d", p1/4096);
strcat(output, buf);
}

// don't use intermediate pitch points for linear rise and fall
if(env > 1)
{
for(ix=1; ix<4; ix++)
{
if (env > 1) {
for (ix = 1; ix < 4; ix++) {
p2 = ((pitch_env[y[ix]]*pitch_range)>>8) + pitch_base;

if(split > 0)
{
if (split > 0) {
y2 = (y[ix] * env100)/env_split;
}
else
if(split < 0)
{
} else if (split < 0) {
y2 = ((y[ix]-env_split) * env100)/env_split;
}
else
{
} else {
y2 = (y[ix] * env100)/128;
}
if((y2 > 0) && (y2 <= env100))
{
sprintf(buf," %d %d",y2,p2/4096);
strcat(output,buf);
if ((y2 > 0) && (y2 <= env100)) {
sprintf(buf, " %d %d", y2, p2/4096);
strcat(output, buf);
}
}
}

p_end = p_end/4096;
if(split <= 0)
{
sprintf(buf," %d %d",env100,p_end);
strcat(output,buf);
if (split <= 0) {
sprintf(buf, " %d %d", env100, p_end);
strcat(output, buf);
}
if(env100 < 100)
{
sprintf(buf," %d %d",100,p_end);
strcat(output,buf);
if (env100 < 100) {
sprintf(buf, " %d %d", 100, p_end);
strcat(output, buf);
}
strcat(output,"\n");
strcat(output, "\n");

if(final)
sprintf(output,"\t100 %d\n",p_end);
return(output);
if (final)
sprintf(output, "\t100 %d\n", p_end);
return (output);
}


@@ -441,8 +405,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
word_count = 0;
}

while (phix < n_phonemes)
{
while (phix < n_phonemes) {
if (WcmdqFree() < MIN_WCMDQ)
return 1;

@@ -454,47 +417,42 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
ph_prev = plist[phix-1].ph;
ph_next = plist[phix+1].ph;

if(p->synthflags & SFLAG_EMBEDDED)
{
if (p->synthflags & SFLAG_EMBEDDED) {
DoEmbedded(&embedded_ix, p->sourceix);
}

if(p->newword & 4)
if (p->newword & 4)
DoMarker(espeakEVENT_SENTENCE, (p->sourceix & 0x7ff) + clause_start_char, 0, count_sentences);
if(p->newword & 1)
if (p->newword & 1)
DoMarker(espeakEVENT_WORD, (p->sourceix & 0x7ff) + clause_start_char, p->sourceix >> 11, clause_start_word + word_count++);

name = GetMbrName(p,ph,ph_prev,ph_next,&name2,&len_percent,&control);
if(control & 1)
name = GetMbrName(p, ph, ph_prev, ph_next, &name2, &len_percent, &control);
if (control & 1)
phix++;

if(name == 0) {
if (name == 0) {
phix++;
continue; // ignore this phoneme
}

if((ph->type == phPAUSE) && (name == ph->mnemonic))
{
if ((ph->type == phPAUSE) && (name == ph->mnemonic)) {
// a pause phoneme, which has not been changed by the translation
name = '_';
len = (p->length * speed.pause_factor)/256;
if(len == 0)
if (len == 0)
len = 1;
}
else
} else
len = (80 * speed.wav_factor)/256;

if(ph->code != phonEND_WORD)
{
if (ph->code != phonEND_WORD) {
char phoneme_name[16];
WritePhMnemonic(phoneme_name, p->ph, p, option_phoneme_events & espeakINITIALIZE_PHONEME_IPA, NULL);
DoPhonemeMarker(espeakEVENT_PHONEME, (p->sourceix & 0x7ff) + clause_start_char, 0, phoneme_name);
}

ptr += sprintf(ptr,"%s\t",WordToString(name));
ptr += sprintf(ptr, "%s\t", WordToString(name));

if(name2 == '_')
{
if (name2 == '_') {
// add a pause after this phoneme
pause = len_percent;
name2 = 0;
@@ -503,48 +461,45 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
done = 0;
final_pitch = "";

switch(ph->type)
switch (ph->type)
{
case phVOWEL:
len = ph->std_length;
if(p->synthflags & SFLAG_LENGTHEN)
if (p->synthflags & SFLAG_LENGTHEN)
len += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol

if(ph_next->type == phPAUSE)
if (ph_next->type == phPAUSE)
len += 50; // lengthen vowels before a pause
len = (len * p->length)/256;

if(name2 == 0)
{
char *pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,0);
ptr += sprintf(ptr,"%d\t%s", len, pitch);
}
else
{
if (name2 == 0) {
char *pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 0);
ptr += sprintf(ptr, "%d\t%s", len, pitch);
} else {
char *pitch;

pitch = WritePitch(p->env,p->pitch1,p->pitch2,len_percent,0);
pitch = WritePitch(p->env, p->pitch1, p->pitch2, len_percent, 0);
len1 = (len * len_percent)/100;
ptr += sprintf(ptr,"%d\t%s", len1, pitch);
ptr += sprintf(ptr, "%d\t%s", len1, pitch);

pitch = WritePitch(p->env,p->pitch1,p->pitch2,-len_percent,0);
ptr += sprintf(ptr,"%s\t%d\t%s", WordToString(name2), len-len1, pitch);
pitch = WritePitch(p->env, p->pitch1, p->pitch2, -len_percent, 0);
ptr += sprintf(ptr, "%s\t%d\t%s", WordToString(name2), len-len1, pitch);
}
done = 1;
break;

case phSTOP:
released = 0;
if(next->type==phVOWEL) released = 1;
if(next->type==phLIQUID && !next->newword) released = 1;
if (next->type == phVOWEL) released = 1;
if (next->type == phLIQUID && !next->newword) released = 1;

if(released == 0)
if (released == 0)
p->synthflags |= SFLAG_NEXT_PAUSE;
InterpretPhoneme(NULL, 0, p, &phdata, NULL);
len = DoSample3(&phdata, 0, -1);

len = (len * 1000)/samplerate; // convert to mS
len += PauseLength(p->prepause,1);
len += PauseLength(p->prepause, 1);
break;

case phVSTOP:
@@ -554,7 +509,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
case phFRICATIVE:
len = 0;
InterpretPhoneme(NULL, 0, p, &phdata, NULL);
if(p->synthflags & SFLAG_LENGTHEN)
if (p->synthflags & SFLAG_LENGTHEN)
len = DoSample3(&phdata, p->length, -1); // play it twice for [s:] etc.
len += DoSample3(&phdata, p->length, -1);

@@ -562,52 +517,44 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
break;

case phNASAL:
if(next->type != phVOWEL)
{
if (next->type != phVOWEL) {
memset(&fmtp, 0, sizeof(fmtp));
InterpretPhoneme(NULL, 0, p, &phdata, NULL);
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
len = DoSpect2(p->ph, 0, &fmtp, p, -1);
len = (len * 1000)/samplerate;
if(next->type == phPAUSE)
if (next->type == phPAUSE)
len += 50;
final_pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,1);
final_pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 1);
}
break;

case phLIQUID:
if(next->type == phPAUSE)
{
if (next->type == phPAUSE) {
len += 50;
final_pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,1);
final_pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 1);
}
break;
}

if(!done)
{
if(name2 != 0)
{
if (!done) {
if (name2 != 0) {
len1 = (len * len_percent)/100;
ptr += sprintf(ptr,"%d\n%s\t",len1,WordToString(name2));
ptr += sprintf(ptr, "%d\n%s\t", len1, WordToString(name2));
len -= len1;
}
ptr += sprintf(ptr,"%d%s\n",len,final_pitch);
ptr += sprintf(ptr, "%d%s\n", len, final_pitch);
}

if(pause)
{
len += PauseLength(pause,0);
ptr += sprintf(ptr,"_ \t%d\n",PauseLength(pause,0));
if (pause) {
len += PauseLength(pause, 0);
ptr += sprintf(ptr, "_ \t%d\n", PauseLength(pause, 0));
pause = 0;
}

if(f_mbrola)
{
fwrite(mbr_buf,1,(ptr-mbr_buf),f_mbrola); // write .pho to a file
}
else
{
if (f_mbrola) {
fwrite(mbr_buf, 1, (ptr-mbr_buf), f_mbrola); // write .pho to a file
} else {
int res = write_MBR(mbr_buf);
if (res < 0)
return 0; /* don't get stuck on error */
@@ -621,8 +568,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
phix++;
}

if(!f_mbrola)
{
if (!f_mbrola) {
flush_MBR();

// flush the mbrola output buffer
@@ -639,11 +585,10 @@ int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
{
FILE *f_mbrola = NULL;

if(*n_ph == 0)
return(0);
if (*n_ph == 0)
return (0);

if(option_phonemes & espeakPHONEMES_MBROLA)
{
if (option_phonemes & espeakPHONEMES_MBROLA) {
// send mbrola data to a file, not to the mbrola library
f_mbrola = f_trans;
}
@@ -675,14 +620,13 @@ int MbrolaFill(int length, int resume, int amplitude)
if (result <= 0)
return 0;

for(ix=0; ix < result; ix++)
{
for (ix = 0; ix < result; ix++) {
value16 = out_ptr[0] + (out_ptr[1] << 8);
value = value16 * amplitude;
value = value / 40; // adjust this constant to give a suitable amplitude for mbrola voices
if(value > 0x7fff)
if (value > 0x7fff)
value = 0x7fff;
if(value < -0x8000)
if (value < -0x8000)
value = 0x8000;
out_ptr[0] = value;
out_ptr[1] = value >> 8;
@@ -706,17 +650,17 @@ void MbrolaReset(void)

espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate)
{
return(EE_INTERNAL_ERROR);
return (EE_INTERNAL_ERROR);
}

int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
{
return(0);
return (0);
}

int MbrolaFill(int length, int resume, int amplitude)
{
return(0);
return (0);
}

void MbrolaReset(void)

+ 270
- 403
src/libespeak-ng/synthdata.c
File diff suppressed because it is too large
View File


+ 399
- 625
src/libespeak-ng/synthesize.c
File diff suppressed because it is too large
View File


+ 3
- 3
src/libespeak-ng/synthesize.h View File

@@ -490,7 +490,7 @@ int WavegenOpenSound();
int WavegenCloseSound();
int WavegenInitSound();
void WavegenInit(int rate, int wavemult_fact);
float polint(float xa[],float ya[],int n,float x);
float polint(float xa[], float ya[], int n, float x);
int WavegenFill(int fill_zeros);
void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr);

@@ -536,7 +536,7 @@ int SelectPhonemeTableName(const char *name);
void Write4Bytes(FILE *f, int value);
int Read4Bytes(FILE *f);
int Reverse4Bytes(int word);
int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name,int flags);
int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name, int flags);


#define ENV_LEN 128 // length of pitch envelopes
@@ -555,7 +555,7 @@ extern unsigned char *out_start;
extern unsigned char *out_end;
extern int event_list_ix;
extern espeak_EVENT *event_list;
extern t_espeak_callback* synth_callback;
extern t_espeak_callback *synth_callback;
extern const char *version_string;
extern const int version_phdata;
extern double sonicSpeed;

+ 466
- 516
src/libespeak-ng/tr_languages.c
File diff suppressed because it is too large
View File


+ 775
- 1221
src/libespeak-ng/translate.c
File diff suppressed because it is too large
View File


+ 7
- 8
src/libespeak-ng/translate.h View File

@@ -22,7 +22,7 @@ extern "C"
{
#endif

#define L(c1,c2) (c1<<8)+c2 // combine two characters into an integer for translator name
#define L(c1, c2) (c1<<8)+c2 // combine two characters into an integer for translator name

#define CTRL_EMBEDDED 0x01 // control character at the start of an embedded command
#define REPLACED_E 'E' // 'e' replaced by silent e
@@ -252,7 +252,7 @@ extern "C"
// match 1 pre 2 post 0 - use common phoneme string
// match 1 pre 2 post 3 0 - empty phoneme string

typedef const char * constcharptr;
typedef const char *constcharptr;

typedef struct {
int points;
@@ -601,8 +601,7 @@ typedef struct {



typedef struct
{
typedef struct {

LANGUAGE_OPTIONS langopts;
int translator_name;
@@ -723,8 +722,8 @@ extern unsigned char *p_textinput;
extern wchar_t *p_wchar_input;
extern int dictionary_skipwords;

extern int (* uri_callback)(int, const char *, const char *);
extern int (* phoneme_callback)(const char *);
extern int (*uri_callback)(int, const char *, const char *);
extern int (*phoneme_callback)(const char *);
extern void SetLengthMods(Translator *tr, int value);

void LoadConfig(void);
@@ -733,8 +732,8 @@ int utf8_in(int *c, const char *buf);
int utf8_in2(int *c, const char *buf, int backwards);
int utf8_out(unsigned int c, char *buf);
int utf8_nbytes(const char *buf);
int lookupwchar(const unsigned short *list,int c);
int lookupwchar2(const unsigned short *list,int c);
int lookupwchar(const unsigned short *list, int c);
int lookupwchar2(const unsigned short *list, int c);
int Eof(void);
char *strchr_w(const char *s, int c);
int IsBracket(int c);

+ 466
- 626
src/libespeak-ng/voices.c
File diff suppressed because it is too large
View File


+ 237
- 326
src/libespeak-ng/wave.c
File diff suppressed because it is too large
View File


+ 9
- 9
src/libespeak-ng/wave.h View File

@@ -32,15 +32,15 @@ extern "C"
extern int option_device_number;

extern int wave_init(int samplerate);
extern void* wave_open(const char* the_api);
extern void *wave_open(const char *the_api);

extern size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize);
extern int wave_close(void* theHandler);
extern void wave_flush(void* theHandler);
extern int wave_is_busy(void* theHandler);
extern size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize);
extern int wave_close(void *theHandler);
extern void wave_flush(void *theHandler);
extern int wave_is_busy(void *theHandler);
extern void wave_terminate();
extern uint32_t wave_get_read_position(void* theHandler);
extern uint32_t wave_get_write_position(void* theHandler);
extern uint32_t wave_get_read_position(void *theHandler);
extern uint32_t wave_get_write_position(void *theHandler);

// Supply the remaining time in ms before the sample is played
// (or 0 if the event has been already played).
@@ -48,12 +48,12 @@ extern uint32_t wave_get_write_position(void* theHandler);
// time: supplied value in ms
//
// return 0 if ok or -1 otherwise (stream not opened).
extern int wave_get_remaining_time(uint32_t sample, uint32_t* time);
extern int wave_get_remaining_time(uint32_t sample, uint32_t *time);

// set the callback which informs if the output is still enabled.
// Helpful if a new sample is waiting for free space whereas sound must be stopped.
typedef int (t_wave_callback)(void);
extern void wave_set_callback_is_output_enabled(t_wave_callback* cb);
extern void wave_set_callback_is_output_enabled(t_wave_callback *cb);


// general functions

+ 64
- 79
src/libespeak-ng/wave_pulse.c View File

@@ -48,7 +48,7 @@
#include "wave.h"
#include "debug.h"

enum {ONE_BILLION=1000000000};
enum { ONE_BILLION = 1000000000 };

enum {
/* return value */
@@ -59,7 +59,7 @@ enum {

#ifdef USE_PULSEAUDIO

static t_wave_callback* my_callback_is_output_enabled=NULL;
static t_wave_callback *my_callback_is_output_enabled = NULL;

#define SAMPLE_RATE 22050
#define ESPEAK_FORMAT PA_SAMPLE_S16LE
@@ -126,7 +126,7 @@ static int wave_samplerate;
SHOW("Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \
goto label; \
} \
} while(0);
} while (0);

#define CHECK_CONNECTED(retval) \
do { \
@@ -154,7 +154,8 @@ static void context_state_cb(pa_context *c, void *userdata) {
ENTER(__FUNCTION__);
assert(c);

switch (pa_context_get_state(c)) {
switch (pa_context_get_state(c))
{
case PA_CONTEXT_READY:
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
@@ -169,11 +170,12 @@ static void context_state_cb(pa_context *c, void *userdata) {
}
}

static void stream_state_cb(pa_stream *s, void * userdata) {
static void stream_state_cb(pa_stream *s, void *userdata) {
ENTER(__FUNCTION__);
assert(s);

switch (pa_stream_get_state(s)) {
switch (pa_stream_get_state(s))
{

case PA_STREAM_READY:
case PA_STREAM_FAILED:
@@ -192,7 +194,7 @@ static void stream_success_cb(pa_stream *s, int success, void *userdata) {
assert(s);

if (userdata)
*(int*) userdata = success;
*(int *)userdata = success;

pa_threaded_mainloop_signal(mainloop, 0);
}
@@ -202,7 +204,7 @@ static void context_success_cb(pa_context *c, int success, void *userdata) {
assert(c);

if (userdata)
*(int*) userdata = success;
*(int *)userdata = success;

pa_threaded_mainloop_signal(mainloop, 0);
}
@@ -231,7 +233,7 @@ static int pulse_free(void) {
pa_threaded_mainloop_lock(mainloop);
CHECK_DEAD_GOTO(fail, 1);

if ((l = pa_stream_writable_size(stream)) == (size_t) -1) {
if ((l = pa_stream_writable_size(stream)) == (size_t)-1) {
SHOW("pa_stream_writable_size() failed: %s", pa_strerror(pa_context_errno(context)));
l = 0;
goto fail;
@@ -271,7 +273,7 @@ fail:

do_trigger = !!l;
SHOW("pulse_free: %d (ret)\n", (int)l);
return (int) l;
return (int)l;
}

static int pulse_playing(const pa_timing_info *the_timing_info) {
@@ -285,11 +287,10 @@ static int pulse_playing(const pa_timing_info *the_timing_info) {

pa_threaded_mainloop_lock(mainloop);

for (;; ) {
for (;;) {
CHECK_DEAD_GOTO(fail, 1);

if ((i = pa_stream_get_timing_info(stream)))
{
if ((i = pa_stream_get_timing_info(stream))) {
break;
}
if (pa_context_errno(context) != PA_ERR_NODATA) {
@@ -301,7 +302,7 @@ static int pulse_playing(const pa_timing_info *the_timing_info) {
}

r = i->playing;
memcpy((void*)the_timing_info, (void*)i, sizeof(pa_timing_info));
memcpy((void *)the_timing_info, (void *)i, sizeof(pa_timing_info));

fail:
pa_threaded_mainloop_unlock(mainloop);
@@ -309,7 +310,7 @@ fail:
return r;
}

static void pulse_write(void* ptr, int length) {
static void pulse_write(void *ptr, int length) {
ENTER(__FUNCTION__);


@@ -360,8 +361,7 @@ static int drain(void) {

if (!success) {
SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
}
else {
} else {
ret = PULSE_OK;
}

@@ -420,7 +420,7 @@ static int pulse_open()
assert(!stream);
assert(!connected);

pthread_mutex_init( &pulse_mutex, (const pthread_mutexattr_t *)NULL);
pthread_mutex_init(&pulse_mutex, (const pthread_mutexattr_t *)NULL);

ss.format = ESPEAK_FORMAT;
ss.rate = wave_samplerate;
@@ -431,7 +431,7 @@ static int pulse_open()

SHOW_TIME("pa_threaded_mainloop_new (call)");
if (!(mainloop = pa_threaded_mainloop_new())) {
SHOW("Failed to allocate main loop\n","");
SHOW("Failed to allocate main loop\n", "");
goto fail;
}

@@ -439,7 +439,7 @@ static int pulse_open()

SHOW_TIME("pa_context_new (call)");
if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "eSpeak"))) {
SHOW("Failed to allocate context\n","");
SHOW("Failed to allocate context\n", "");
goto unlock_and_fail;
}

@@ -455,7 +455,7 @@ static int pulse_open()

SHOW_TIME("pa_threaded_mainloop_start (call)");
if (pa_threaded_mainloop_start(mainloop) < 0) {
SHOW("Failed to start main loop","");
SHOW("Failed to start main loop", "");
goto unlock_and_fail;
}

@@ -558,8 +558,7 @@ fail:
pa_threaded_mainloop_free(mainloop);
mainloop = NULL;
}
}
else {
} else {
pulse_close();
}

@@ -569,12 +568,12 @@ fail:

}

void wave_flush(void* theHandler)
void wave_flush(void *theHandler)
{
ENTER("wave_flush");
}

void wave_set_callback_is_output_enabled(t_wave_callback* cb)
void wave_set_callback_is_output_enabled(t_wave_callback *cb)
{
my_callback_is_output_enabled = cb;
}
@@ -589,52 +588,47 @@ int wave_init(int srate)
return pulse_open() == PULSE_OK;
}

void* wave_open(const char* the_api)
void *wave_open(const char *the_api)
{
ENTER("wave_open");
return((void*)1);
return ((void *)1);
}

size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize)
size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize)
{
ENTER("wave_write");
size_t bytes_to_write = theSize;
char* aBuffer=theMono16BitsWaveBuffer;
char *aBuffer = theMono16BitsWaveBuffer;

assert(stream);

size_t aTotalFreeMem=0;
size_t aTotalFreeMem = 0;

pthread_mutex_lock(&pulse_mutex);

while (1)
{
while (1) {
if (my_callback_is_output_enabled
&& (0==my_callback_is_output_enabled()))
{
&& (0 == my_callback_is_output_enabled())) {
SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
theSize=0;
theSize = 0;
goto terminate;
}

aTotalFreeMem = pulse_free();
if (aTotalFreeMem >= bytes_to_write)
{
if (aTotalFreeMem >= bytes_to_write) {
SHOW("wave_write > aTotalFreeMem(%d) >= bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write);
break;
}

// TBD: check if really helpful
if (aTotalFreeMem >= MAXLENGTH*2)
{
if (aTotalFreeMem >= MAXLENGTH*2) {
aTotalFreeMem = MAXLENGTH*2;
}

SHOW("wave_write > wait: aTotalFreeMem(%d) < bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write);

// 500: threshold for avoiding too many calls to pulse_write
if (aTotalFreeMem>500)
{
if (aTotalFreeMem > 500) {
pulse_write(aBuffer, aTotalFreeMem);
bytes_to_write -= aTotalFreeMem;
aBuffer += aTotalFreeMem;
@@ -652,7 +646,7 @@ terminate:
return theSize;
}

int wave_close(void* theHandler)
int wave_close(void *theHandler)
{
SHOW_TIME("wave_close > ENTER");
static int aStopStreamCount = 0;
@@ -660,15 +654,13 @@ int wave_close(void* theHandler)
// Avoid race condition by making sure this function only
// gets called once at a time
aStopStreamCount++;
if (aStopStreamCount != 1)
{
if (aStopStreamCount != 1) {
SHOW_TIME("wave_close > LEAVE (stopStreamCount)");
return 0;
}

int a_status = pthread_mutex_lock(&pulse_mutex);
if (a_status)
{
if (a_status) {
SHOW("Error: pulse_mutex lock=%d (%s)\n", a_status, __FUNCTION__);
aStopStreamCount = 0; // last action
return PULSE_ERROR;
@@ -683,13 +675,13 @@ int wave_close(void* theHandler)
return PULSE_OK;
}

int wave_is_busy(void* theHandler)
int wave_is_busy(void *theHandler)
{
SHOW_TIME("wave_is_busy");

pa_timing_info a_timing_info;
int active = pulse_playing(&a_timing_info);
SHOW("wave_is_busy: %d\n",active);
SHOW("wave_is_busy: %d\n", active);
return active;
}

@@ -698,7 +690,7 @@ void wave_terminate()
ENTER("wave_terminate");

int a_status;
pthread_mutex_t* a_mutex = NULL;
pthread_mutex_t *a_mutex = NULL;
a_mutex = &pulse_mutex;
a_status = pthread_mutex_lock(a_mutex);

@@ -709,7 +701,7 @@ void wave_terminate()
pthread_mutex_destroy(a_mutex);
}

uint32_t wave_get_read_position(void* theHandler)
uint32_t wave_get_read_position(void *theHandler)
{
pa_timing_info a_timing_info;
pulse_playing(&a_timing_info);
@@ -717,7 +709,7 @@ uint32_t wave_get_read_position(void* theHandler)
return a_timing_info.read_index;
}

uint32_t wave_get_write_position(void* theHandler)
uint32_t wave_get_write_position(void *theHandler)
{
pa_timing_info a_timing_info;
pulse_playing(&a_timing_info);
@@ -725,27 +717,23 @@ uint32_t wave_get_write_position(void* theHandler)
return a_timing_info.write_index;
}

int wave_get_remaining_time(uint32_t sample, uint32_t* time)
int wave_get_remaining_time(uint32_t sample, uint32_t *time)
{
double a_time=0;
double a_time = 0;

if (!time || !stream)
{
SHOW("event get_remaining_time> %s\n","audio device not available");
if (!time || !stream) {
SHOW("event get_remaining_time> %s\n", "audio device not available");
return -1;
}

pa_timing_info a_timing_info;
pulse_playing(&a_timing_info);

if (sample > a_timing_info.read_index)
{
if (sample > a_timing_info.read_index) {
// TBD: take in account time suplied by portaudio V18 API
a_time = sample - a_timing_info.read_index;
a_time = 0.5 + (a_time * 1000.0) / wave_samplerate;
}
else
{
} else {
a_time = 0;
}

@@ -767,38 +755,38 @@ void *wave_test_get_write_buffer()

int wave_init(return 1; ) {
}
void* wave_open(const char* the_api) {
void *wave_open(const char *the_api) {
return (void *)1;
}
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {
size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) {
return theSize;
}
int wave_close(void* theHandler) {
int wave_close(void *theHandler) {
return 0;
}
int wave_is_busy(void* theHandler) {
int wave_is_busy(void *theHandler) {
return 0;
}
void wave_terminate() {
}
uint32_t wave_get_read_position(void* theHandler) {
uint32_t wave_get_read_position(void *theHandler) {
return 0;
}
uint32_t wave_get_write_position(void* theHandler) {
uint32_t wave_get_write_position(void *theHandler) {
return 0;
}
void wave_flush(void* theHandler) {
void wave_flush(void *theHandler) {
}
typedef int (t_wave_callback)(void);
void wave_set_callback_is_output_enabled(t_wave_callback* cb) {
void wave_set_callback_is_output_enabled(t_wave_callback *cb) {
}
extern void* wave_test_get_write_buffer() {
extern void *wave_test_get_write_buffer() {
return NULL;
}

int wave_get_remaining_time(uint32_t sample, uint32_t* time)
int wave_get_remaining_time(uint32_t sample, uint32_t *time)
{
if (!time) return(-1);
if (!time) return (-1);
*time = (uint32_t)0;
return 0;
}
@@ -811,26 +799,23 @@ void clock_gettime2(struct timespec *ts)
{
struct timeval tv;

if (!ts)
{
if (!ts) {
return;
}

assert (gettimeofday(&tv, NULL) != -1);
assert(gettimeofday(&tv, NULL) != -1);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec*1000;
}

void add_time_in_ms(struct timespec *ts, int time_in_ms)
{
if (!ts)
{
if (!ts) {
return;
}

uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms;
while(t_ns >= ONE_BILLION)
{
while (t_ns >= ONE_BILLION) {
SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns);
ts->tv_sec += 1;
t_ns -= ONE_BILLION;

+ 40
- 44
src/libespeak-ng/wave_sada.c View File

@@ -35,13 +35,13 @@
#include "wave.h"
#include "debug.h"

enum {ONE_BILLION=1000000000};
enum { ONE_BILLION = 1000000000 };
#define SAMPLE_RATE 22050
#define SAMPLE_SIZE 16

#ifdef USE_SADA

static t_wave_callback* my_callback_is_output_enabled=NULL;
static t_wave_callback *my_callback_is_output_enabled = NULL;

static const char *sun_audio_device = "/dev/audio";
static int sun_audio_fd = -1;
@@ -59,7 +59,7 @@ static uint32_t total_samples_skipped;

// The last known playing index after a call to wave_close.
//
static uint32_t last_play_position=0;
static uint32_t last_play_position = 0;

static uint32_t wave_samplerate;

@@ -100,7 +100,7 @@ int wave_init(int srate) {
SHOW("wave_init() sun_audio_fd: %d\n", sun_audio_fd);

if (sun_audio_fd < 0) {
return(0);
return (0);
}

ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo);
@@ -113,9 +113,9 @@ int wave_init(int srate) {
if (ioctl(sun_audio_fd, AUDIO_SETINFO, &ainfo) == -1) {
SHOW("wave_init() failed to set audio params: %s\n", strerror(errno));
close(sun_audio_fd);
return(0);
return (0);
}
return(1);
return (1);
}

// wave_open
@@ -140,10 +140,10 @@ int wave_init(int srate) {
// sun_audio_fd opened in wave_init, which is passed in as theHandler
// parameter in all other methods
//
void* wave_open(const char* the_api)
void *wave_open(const char *the_api)
{
ENTER("wave_open");
return((void*) sun_audio_fd);
return ((void *)sun_audio_fd);
}

// wave_write
@@ -172,13 +172,13 @@ void* wave_open(const char* the_api)
//
// the number of bytes (not 16-bit samples) sent
//
size_t wave_write(void* theHandler,
char* theMono16BitsWaveBuffer,
size_t wave_write(void *theHandler,
char *theMono16BitsWaveBuffer,
size_t theSize)
{
size_t num;
ENTER("wave_write");
if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) {
if (my_callback_is_output_enabled && (0 == my_callback_is_output_enabled())) {
SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
return 0;
}
@@ -191,8 +191,7 @@ size_t wave_write(void* theHandler,
char *out_end;
out_ptr = (char *)theMono16BitsWaveBuffer;
out_end = out_ptr + theSize;
while(out_ptr < out_end)
{
while (out_ptr < out_end) {
c = out_ptr[0];
out_ptr[0] = out_ptr[1];
out_ptr[1] = c;
@@ -201,7 +200,7 @@ size_t wave_write(void* theHandler,
}
#endif

num = write((int) theHandler, theMono16BitsWaveBuffer, theSize);
num = write((int)theHandler, theMono16BitsWaveBuffer, theSize);

// Keep track of the total number of samples sent -- we use this in
// wave_get_read_position and also use it to help calculate the
@@ -246,11 +245,11 @@ size_t wave_write(void* theHandler,
//
// The result of the ioctl call (non-0 means failure)
//
int wave_close(void* theHandler)
int wave_close(void *theHandler)
{
int ret;
audio_info_t ainfo;
int audio_fd = (int) theHandler;
int audio_fd = (int)theHandler;
if (!audio_fd) {
audio_fd = sun_audio_fd;
}
@@ -291,7 +290,7 @@ int wave_close(void* theHandler)
//
// A non-0 value if audio is being played
//
int wave_is_busy(void* theHandler)
int wave_is_busy(void *theHandler)
{
uint32_t time;
if (total_samples_sent >= 1) {
@@ -335,7 +334,7 @@ void wave_terminate()
//
// theHandler: the audio device file descriptor
//
void wave_flush(void* theHandler)
void wave_flush(void *theHandler)
{
ENTER("wave_flush");
SHOW_TIME("wave_flush > LEAVE");
@@ -353,7 +352,7 @@ void wave_flush(void* theHandler)
//
// cb: the callback to call from wave_write
//
void wave_set_callback_is_output_enabled(t_wave_callback* cb)
void wave_set_callback_is_output_enabled(t_wave_callback *cb)
{
my_callback_is_output_enabled = cb;
}
@@ -393,11 +392,11 @@ void *wave_test_get_write_buffer()
// The total number of 16-bit samples played by the audio system
// so far.
//
uint32_t wave_get_read_position(void* theHandler)
uint32_t wave_get_read_position(void *theHandler)
{
audio_info_t ainfo;
ENTER("wave_get_read_position");
ioctl((int) theHandler, AUDIO_GETINFO, &ainfo);
ioctl((int)theHandler, AUDIO_GETINFO, &ainfo);
SHOW("wave_get_read_position: %d\n", ainfo.play.samples);
SHOW_TIME("wave_get_read_position > LEAVE");
return ainfo.play.samples;
@@ -429,7 +428,7 @@ uint32_t wave_get_read_position(void* theHandler)
// the index wraps back to 0. We don't handle that wrapping, so
// the behavior after 54 hours of play time is undefined.]]]
//
uint32_t wave_get_write_position(void* theHandler)
uint32_t wave_get_write_position(void *theHandler)
{
ENTER("wave_get_write_position");
SHOW("wave_get_write_position: %d\n", total_samples_sent);
@@ -464,15 +463,15 @@ uint32_t wave_get_write_position(void* theHandler)
// Time in milliseconds before the sample is played or 0 if the sample
// is currently playing or has already been played.
//
int wave_get_remaining_time(uint32_t sample, uint32_t* time)
int wave_get_remaining_time(uint32_t sample, uint32_t *time)
{
uint32_t a_time=0;
uint32_t a_time = 0;
uint32_t actual_index;

audio_info_t ainfo;
ENTER("wave_get_remaining_time");
if (!time) {
return(-1);
return (-1);
SHOW_TIME("wave_get_remaining_time > LEAVE");
}

@@ -487,7 +486,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t* time)
*time = 0;
} else {
a_time = ((actual_index - ainfo.play.samples) * 1000) / wave_samplerate;
*time = (uint32_t) a_time;
*time = (uint32_t)a_time;
}
SHOW("wave_get_remaining_time for %d: %d\n", sample, *time);
SHOW_TIME("wave_get_remaining_time > LEAVE");
@@ -499,38 +498,38 @@ int wave_get_remaining_time(uint32_t sample, uint32_t* time)
init wave_init() {
return 1;
}
void* wave_open(const char* the_api) {
void *wave_open(const char *the_api) {
return (void *)1;
}
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {
size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) {
return theSize;
}
int wave_close(void* theHandler) {
int wave_close(void *theHandler) {
return 0;
}
int wave_is_busy(void* theHandler) {
int wave_is_busy(void *theHandler) {
return 0;
}
void wave_terminate() {
}
uint32_t wave_get_read_position(void* theHandler) {
uint32_t wave_get_read_position(void *theHandler) {
return 0;
}
uint32_t wave_get_write_position(void* theHandler) {
uint32_t wave_get_write_position(void *theHandler) {
return 0;
}
void wave_flush(void* theHandler) {
void wave_flush(void *theHandler) {
}
typedef int (t_wave_callback)(void);
void wave_set_callback_is_output_enabled(t_wave_callback* cb) {
void wave_set_callback_is_output_enabled(t_wave_callback *cb) {
}
extern void* wave_test_get_write_buffer() {
extern void *wave_test_get_write_buffer() {
return NULL;
}

int wave_get_remaining_time(uint32_t sample, uint32_t* time)
int wave_get_remaining_time(uint32_t sample, uint32_t *time)
{
if (!time) return(-1);
if (!time) return (-1);
*time = (uint32_t)0;
return 0;
}
@@ -541,26 +540,23 @@ void clock_gettime2(struct timespec *ts)
{
struct timeval tv;

if (!ts)
{
if (!ts) {
return;
}

assert (gettimeofday(&tv, NULL) != -1);
assert(gettimeofday(&tv, NULL) != -1);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec*1000;
}

void add_time_in_ms(struct timespec *ts, int time_in_ms)
{
if (!ts)
{
if (!ts) {
return;
}

uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms;
while(t_ns >= ONE_BILLION)
{
while (t_ns >= ONE_BILLION) {
SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns);
ts->tv_sec += 1;
t_ns -= ONE_BILLION;

+ 335
- 468
src/libespeak-ng/wavegen.c
File diff suppressed because it is too large
View File


+ 199
- 267
src/speak-ng.c View File

@@ -145,59 +145,50 @@ void DisplayVoices(FILE *f_out, char *language)
const espeak_VOICE **voices;
espeak_VOICE voice_select;

static char genders[4] = {'-','M','F','-'};
static char genders[4] = { '-', 'M', 'F', '-' };

if((language != NULL) && (language[0] != 0))
{
if ((language != NULL) && (language[0] != 0)) {
// display only voices for the specified language, in order of priority
voice_select.languages = language;
voice_select.age = 0;
voice_select.gender = 0;
voice_select.name = NULL;
voices = espeak_ListVoices(&voice_select);
}
else
{
} else {
voices = espeak_ListVoices(NULL);
}

fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Languages\n");
fprintf(f_out, "Pty Language Age/Gender VoiceName File Other Languages\n");

for(ix=0; (v = voices[ix]) != NULL; ix++)
{
for (ix = 0; (v = voices[ix]) != NULL; ix++) {
count = 0;
p = v->languages;
while(*p != 0)
{
while (*p != 0) {
len = strlen(p+1);
lang_name = p+1;

if(v->age == 0)
strcpy(age_buf," ");
if (v->age == 0)
strcpy(age_buf, " ");
else
sprintf(age_buf,"%3d",v->age);
sprintf(age_buf, "%3d", v->age);

if(count==0)
{
for(j=0; j < sizeof(buf); j++)
{
if (count == 0) {
for (j = 0; j < sizeof(buf); j++) {
// replace spaces in the name
if((c = v->name[j]) == ' ')
if ((c = v->name[j]) == ' ')
c = '_';
if((buf[j] = c) == 0)
if ((buf[j] = c) == 0)
break;
}
fprintf(f_out,"%2d %-12s%s%c %-20s %-13s ",
p[0],lang_name,age_buf,genders[v->gender],buf,v->identifier);
}
else
{
fprintf(f_out,"(%s %d)",lang_name,p[0]);
fprintf(f_out, "%2d %-12s%s%c %-20s %-13s ",
p[0], lang_name, age_buf, genders[v->gender], buf, v->identifier);
} else {
fprintf(f_out, "(%s %d)", lang_name, p[0]);
}
count++;
p += len+2;
}
fputc('\n',f_out);
fputc('\n', f_out);
}
}

@@ -207,40 +198,36 @@ static int OpenWaveFile(const char *path, int rate)
// Set the length of 0x7ffff000 for --stdout
// This will be changed to the correct length for -w (write to file)
static unsigned char wave_hdr[44] = {
'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ',
0x10,0,0,0,1,0,1,0, 9,0x3d,0,0,0x12,0x7a,0,0,
2,0,0x10,0,'d','a','t','a', 0x00,0xf0,0xff,0x7f
'R', 'I', 'F', 'F', 0x24, 0xf0, 0xff, 0x7f, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ',
0x10, 0, 0, 0, 1, 0, 1, 0, 9, 0x3d, 0, 0, 0x12, 0x7a, 0, 0,
2, 0, 0x10, 0, 'd', 'a', 't', 'a', 0x00, 0xf0, 0xff, 0x7f
};

if(path == NULL)
return(2);
if (path == NULL)
return (2);

while(isspace(*path)) path++;
while (isspace(*path)) path++;

f_wave = NULL;
if(path[0] != 0)
{
if(strcmp(path,"stdout")==0)
{
if (path[0] != 0) {
if (strcmp(path, "stdout") == 0) {
#ifdef PLATFORM_WINDOWS
// prevent Windows adding 0x0d before 0x0a bytes
_setmode(_fileno(stdout), _O_BINARY);
#endif
f_wave = stdout;
}
else
f_wave = fopen(path,"wb");
} else
f_wave = fopen(path, "wb");
}

if(f_wave != NULL)
{
fwrite(wave_hdr,1,24,f_wave);
Write4Bytes(f_wave,rate);
Write4Bytes(f_wave,rate * 2);
fwrite(&wave_hdr[32],1,12,f_wave);
return(0);
if (f_wave != NULL) {
fwrite(wave_hdr, 1, 24, f_wave);
Write4Bytes(f_wave, rate);
Write4Bytes(f_wave, rate * 2);
fwrite(&wave_hdr[32], 1, 12, f_wave);
return (0);
}
return(1);
return (1);
}


@@ -250,17 +237,17 @@ static void CloseWaveFile()
{
unsigned int pos;

if((f_wave == NULL) || (f_wave == stdout))
if ((f_wave == NULL) || (f_wave == stdout))
return;

fflush(f_wave);
pos = ftell(f_wave);

fseek(f_wave,4,SEEK_SET);
Write4Bytes(f_wave,pos - 8);
fseek(f_wave, 4, SEEK_SET);
Write4Bytes(f_wave, pos - 8);

fseek(f_wave,40,SEEK_SET);
Write4Bytes(f_wave,pos - 44);
fseek(f_wave, 40, SEEK_SET);
Write4Bytes(f_wave, pos - 44);


fclose(f_wave);
@@ -282,32 +269,28 @@ static int WavegenFile(void)

finished = WavegenFill(0);

if(quiet)
return(finished);
if (quiet)
return (finished);

if(f_wave == NULL)
{
sprintf(fname,"%s_%.2d%s",wavefile,++wavefile_count,filetype);
if(OpenWaveFile(fname, samplerate) != 0)
return(1);
if (f_wave == NULL) {
sprintf(fname, "%s_%.2d%s", wavefile, ++wavefile_count, filetype);
if (OpenWaveFile(fname, samplerate) != 0)
return (1);
}

if(end_of_sentence)
{
if (end_of_sentence) {
end_of_sentence = 0;
if((samples_split > 0 ) && (samples_total > samples_split))
{
if ((samples_split > 0 ) && (samples_total > samples_split)) {
CloseWaveFile();
samples_total = 0;
}
}

if(f_wave != NULL)
{
if (f_wave != NULL) {
samples_total += (out_ptr - wav_outbuf)/2;
fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave);
}
return(finished);
return (finished);
}


@@ -315,9 +298,8 @@ static int WavegenFile(void)
static void init_path(char *argv0, char *path_specified)
{

if(path_specified)
{
sprintf(path_home,"%s/espeak-data",path_specified);
if (path_specified) {
sprintf(path_home, "%s/espeak-data", path_specified);
return;
}

@@ -329,18 +311,16 @@ static void init_path(char *argv0, char *path_specified)
char *env;
unsigned char buf[sizeof(path_home)-12];

if(((env = getenv("ESPEAK_DATA_PATH")) != NULL) && ((strlen(env)+12) < sizeof(path_home)))
{
sprintf(path_home,"%s\\espeak-data",env);
if(GetFileLength(path_home) == -2)
if (((env = getenv("ESPEAK_DATA_PATH")) != NULL) && ((strlen(env)+12) < sizeof(path_home))) {
sprintf(path_home, "%s\\espeak-data", env);
if (GetFileLength(path_home) == -2)
return; // an espeak-data directory exists in the directory specified by environment variable
}

strcpy(path_home,argv0);
if((p = strrchr(path_home,'\\')) != NULL)
{
strcpy(&p[1],"espeak-data");
if(GetFileLength(path_home) == -2)
strcpy(path_home, argv0);
if ((p = strrchr(path_home, '\\')) != NULL) {
strcpy(&p[1], "espeak-data");
if (GetFileLength(path_home) == -2)
return; // an espeak-data directory exists in the same directory as the espeak program
}

@@ -351,23 +331,21 @@ static void init_path(char *argv0, char *path_specified)
var_type = REG_SZ;
RegQueryValueEx(RegKey, "path", 0, &var_type, buf, &size);

sprintf(path_home,"%s\\espeak-data",buf);
sprintf(path_home, "%s\\espeak-data", buf);
#else
#ifdef PLATFORM_DOS
strcpy(path_home,PATH_ESPEAK_DATA);
strcpy(path_home, PATH_ESPEAK_DATA);
#else
char *env;
if((env = getenv("ESPEAK_DATA_PATH")) != NULL)
{
snprintf(path_home,sizeof(path_home),"%s/espeak-data",env);
if(GetFileLength(path_home) == -2)
if ((env = getenv("ESPEAK_DATA_PATH")) != NULL) {
snprintf(path_home, sizeof(path_home), "%s/espeak-data", env);
if (GetFileLength(path_home) == -2)
return; // an espeak-data directory exists
}

snprintf(path_home,sizeof(path_home),"%s/espeak-data",getenv("HOME"));
if(access(path_home,R_OK) != 0)
{
strcpy(path_home,PATH_ESPEAK_DATA);
snprintf(path_home, sizeof(path_home), "%s/espeak-data", getenv("HOME"));
if (access(path_home, R_OK) != 0) {
strcpy(path_home, PATH_ESPEAK_DATA);
}
#endif
#endif
@@ -384,35 +362,31 @@ static int initialise(void)
// to something other than the default "C". Then, not only Latin1 but also the
// other characters give the correct results with iswalpha() etc.
#ifdef PLATFORM_RISCOS
setlocale(LC_CTYPE,"ISO8859-1");
setlocale(LC_CTYPE, "ISO8859-1");
#else
if(setlocale(LC_CTYPE,"en_US.UTF-8") == NULL)
{
if(setlocale(LC_CTYPE,"UTF-8") == NULL)
setlocale(LC_CTYPE,"");
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) {
if (setlocale(LC_CTYPE, "UTF-8") == NULL)
setlocale(LC_CTYPE, "");
}
#endif


if((result = LoadPhData(&srate)) != 1)
{
if(result == -1)
{
fprintf(stderr,"Failed to load espeak-data\n");
if ((result = LoadPhData(&srate)) != 1) {
if (result == -1) {
fprintf(stderr, "Failed to load espeak-data\n");
exit(1);
}
else
fprintf(stderr,"Wrong version of espeak-data 0x%x (expects 0x%x) at %s\n",result,version_phdata,path_home);
} else
fprintf(stderr, "Wrong version of espeak-data 0x%x (expects 0x%x) at %s\n", result, version_phdata, path_home);
}
WavegenInit(srate,0);
WavegenInit(srate, 0);
LoadConfig();
SetVoiceStack(NULL, "");
SynthesizeInit();

for(param=0; param<N_SPEECH_PARAM; param++)
for (param = 0; param < N_SPEECH_PARAM; param++)
param_stack[0].parameter[param] = param_defaults[param];

return(0);
return (0);
}


@@ -427,44 +401,43 @@ struct option {
int optind;
static int optional_argument;
static const char *arg_opts = "abfgklpsvw"; // which options have arguments
static char *opt_string="";
static char *opt_string = "";
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#endif

int main (int argc, char **argv)
int main(int argc, char **argv)
{
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"stdin", no_argument, 0, 0x100},
{"compile-debug", optional_argument, 0, 0x101},
{"compile", optional_argument, 0, 0x102},
{"punct", optional_argument, 0, 0x103},
{"voices", optional_argument, 0, 0x104},
{"stdout", no_argument, 0, 0x105},
{"split", optional_argument, 0, 0x106},
{"path", required_argument, 0, 0x107},
{"phonout", required_argument, 0, 0x108},
{"pho", no_argument, 0, 0x109},
{"ipa", optional_argument, 0, 0x10a},
{"version", no_argument, 0, 0x10b},
{"sep", optional_argument, 0, 0x10c},
{"tie", optional_argument, 0, 0x10d},
{0, 0, 0, 0}
static struct option long_options[] = {
{ "help", no_argument, 0, 'h' },
{ "stdin", no_argument, 0, 0x100 },
{ "compile-debug", optional_argument, 0, 0x101 },
{ "compile", optional_argument, 0, 0x102 },
{ "punct", optional_argument, 0, 0x103 },
{ "voices", optional_argument, 0, 0x104 },
{ "stdout", no_argument, 0, 0x105 },
{ "split", optional_argument, 0, 0x106 },
{ "path", required_argument, 0, 0x107 },
{ "phonout", required_argument, 0, 0x108 },
{ "pho", no_argument, 0, 0x109 },
{ "ipa", optional_argument, 0, 0x10a },
{ "version", no_argument, 0, 0x10b },
{ "sep", optional_argument, 0, 0x10c },
{ "tie", optional_argument, 0, 0x10d },
{ 0, 0, 0, 0 }
};

static const char *err_load = "Failed to read ";

FILE *f_text=NULL;
const char *p_text=NULL;
FILE *f_text = NULL;
const char *p_text = NULL;
char *data_path = NULL; // use default path for espeak-data

int option_index = 0;
int c;
int value;
int speed=175;
int speed = 175;
int ix;
char *optarg2;
int amp = 100; // default
@@ -495,15 +468,13 @@ int main (int argc, char **argv)
#ifdef NEED_GETOPT
optind = 1;
opt_string = "";
while(optind < argc)
{
while (optind < argc) {
int len;
char *p;

if((c = *opt_string) == 0)
{
if ((c = *opt_string) == 0) {
opt_string = argv[optind];
if(opt_string[0] != '-')
if (opt_string[0] != '-')
break;

optind++;
@@ -513,45 +484,36 @@ int main (int argc, char **argv)
opt_string++;
p = optarg2 = opt_string;

if(c == '-')
{
if(p[0] == 0)
if (c == '-') {
if (p[0] == 0)
break; // -- means don't interpret further - as commands

opt_string="";
for(ix=0;; ix++)
{
if(long_options[ix].name == 0)
opt_string = "";
for (ix = 0;; ix++) {
if (long_options[ix].name == 0)
break;
len = strlen(long_options[ix].name);
if(memcmp(long_options[ix].name,p,len)==0)
{
if (memcmp(long_options[ix].name, p, len) == 0) {
c = long_options[ix].val;
optarg2 = NULL;

if((long_options[ix].has_arg != 0) && (p[len]=='='))
{
if ((long_options[ix].has_arg != 0) && (p[len] == '=')) {
optarg2 = &p[len+1];
}
break;
}
}
}
else
if(strchr(arg_opts,c) != NULL)
{
opt_string="";
if(optarg2[0]==0)
{
} else if (strchr(arg_opts, c) != NULL) {
opt_string = "";
if (optarg2[0] == 0) {
// the option's value is in the next argument
optarg2 = argv[optind++];
}
}
#else
while(true)
{
c = getopt_long (argc, argv, "a:b:f:g:hk:l:p:qs:v:w:xXmz", // NOTE: also change arg_opts to indicate which commands have a numeric value
long_options, &option_index);
while (true) {
c = getopt_long(argc, argv, "a:b:f:g:hk:l:p:qs:v:w:xXmz", // NOTE: also change arg_opts to indicate which commands have a numeric value
long_options, &option_index);

/* Detect the end of the options. */
if (c == -1)
@@ -564,13 +526,13 @@ int main (int argc, char **argv)
case 'b':
// input character encoding, 8bit, 16bit, UTF8
option_multibyte = espeakCHARS_8BIT;
if((sscanf(optarg2,"%d",&value) == 1) && (value <= 4))
option_multibyte= value;
if ((sscanf(optarg2, "%d", &value) == 1) && (value <= 4))
option_multibyte = value;
break;

case 'h':
init_path(argv[0],data_path);
printf("\nspeak text-to-speech: %s Data at: %s\n%s",version_string,path_home,help_text);
init_path(argv[0], data_path);
printf("\nspeak text-to-speech: %s Data at: %s\n%s", version_string, path_home, help_text);
exit(0);

case 'k':
@@ -591,7 +553,7 @@ int main (int argc, char **argv)

case 'p':
pitch_adjustment = atoi(optarg2);
if(pitch_adjustment > 99) pitch_adjustment = 99;
if (pitch_adjustment > 99) pitch_adjustment = 99;
break;

case 'q':
@@ -599,7 +561,7 @@ int main (int argc, char **argv)
break;

case 'f':
strncpy0(filename,optarg2,sizeof(filename));
strncpy0(filename, optarg2, sizeof(filename));
break;

case 'l':
@@ -621,12 +583,12 @@ int main (int argc, char **argv)
break;

case 'v':
strncpy0(voicename,optarg2,sizeof(voicename));
strncpy0(voicename, optarg2, sizeof(voicename));
break;

case 'w':
option_waveout = 1;
strncpy0(wavefile,optarg2,sizeof(wavefile));
strncpy0(wavefile, optarg2, sizeof(wavefile));
break;

case 'z':
@@ -639,34 +601,33 @@ int main (int argc, char **argv)

case 0x105: // --stdout
option_waveout = 1;
strcpy(wavefile,"stdout");
strcpy(wavefile, "stdout");
break;

case 0x101: // --compile-debug
case 0x102: // --compile
if(optarg2 != NULL)
strncpy0(voicename,optarg2,sizeof(voicename));
if (optarg2 != NULL)
strncpy0(voicename, optarg2, sizeof(voicename));
flag_compile = c;
break;

case 0x103: // --punct
option_punctuation = 1;
if(optarg2 != NULL)
{
if (optarg2 != NULL) {
ix = 0;
while((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++;
while ((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++;
option_punctlist[N_PUNCTLIST-1] = 0;
option_punctuation = 2;
}
break;

case 0x104: // --voices
init_path(argv[0],data_path);
DisplayVoices(stdout,optarg2);
init_path(argv[0], data_path);
DisplayVoices(stdout, optarg2);
exit(0);

case 0x106: // -- split
if(optarg2 == NULL)
if (optarg2 == NULL)
samples_split = 30; // default 30 minutes
else
samples_split = atoi(optarg2);
@@ -677,9 +638,8 @@ int main (int argc, char **argv)
break;

case 0x108: // --phonout
if((f_trans = fopen(optarg2,"w")) == NULL)
{
fprintf(stderr,"Can't write to: %s\n",optarg2);
if ((f_trans = fopen(optarg2, "w")) == NULL) {
fprintf(stderr, "Can't write to: %s\n", optarg2);
f_trans = stderr;
}
break;
@@ -690,10 +650,9 @@ int main (int argc, char **argv)

case 0x10a: // --ipa
phoneme_options |= espeakPHONEMES_IPA;
if(optarg2 != NULL)
{
if (optarg2 != NULL) {
// deprecated and obsolete
switch(atoi(optarg2))
switch (atoi(optarg2))
{
case 1:
phonemes_separator = '_';
@@ -712,27 +671,27 @@ int main (int argc, char **argv)
break;

case 0x10b: // --version
init_path(argv[0],data_path);
printf("speak text-to-speech: %s Data at: %s\n",version_string,path_home);
init_path(argv[0], data_path);
printf("speak text-to-speech: %s Data at: %s\n", version_string, path_home);
exit(0);

case 0x10c: // --sep
phoneme_options |= espeakPHONEMES_SHOW;
if(optarg2 == 0)
if (optarg2 == 0)
phonemes_separator = ' ';
else
utf8_in(&phonemes_separator, optarg2);
if(phonemes_separator == 'z')
if (phonemes_separator == 'z')
phonemes_separator = 0x200c; // ZWNJ
break;

case 0x10d: // --tie
phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE);
if(optarg2 == 0)
if (optarg2 == 0)
phonemes_separator = 0x0361; // default: combining-double-inverted-breve
else
utf8_in(&phonemes_separator, optarg2);
if(phonemes_separator == 'z')
if (phonemes_separator == 'z')
phonemes_separator = 0x200d; // ZWJ
break;

@@ -741,154 +700,127 @@ int main (int argc, char **argv)
}
}

init_path(argv[0],data_path);
init_path(argv[0], data_path);
initialise();

if(voicename[0] == 0)
strcpy(voicename,"default");
if (voicename[0] == 0)
strcpy(voicename, "default");

if(SetVoiceByName(voicename) != EE_OK)
{
memset(&voice_select,0,sizeof(voice_select));
if (SetVoiceByName(voicename) != EE_OK) {
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);
if (SetVoiceByProperties(&voice_select) != EE_OK) {
fprintf(stderr, "%svoice '%s'\n", err_load, voicename);
exit(2);
}
}

if(flag_compile)
{
if (flag_compile) {
#ifdef PLATFORM_DOS
char path_dsource[sizeof(path_home)+20];
strcpy(path_dsource,path_home);
strcpy(path_dsource, path_home);
path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end
strcat(path_dsource,"dictsource\\");
CompileDictionary(path_dsource,dictionary_name,NULL,NULL, flag_compile & 0x1);
strcat(path_dsource, "dictsource\\");
CompileDictionary(path_dsource, dictionary_name, NULL, NULL, flag_compile & 0x1);
#else
#ifdef PLATFORM_WINDOWS
char path_dsource[sizeof(path_home)+20];
strcpy(path_dsource,path_home);
strcpy(path_dsource, path_home);
path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end
strcat(path_dsource,"dictsource\\");
CompileDictionary(path_dsource,dictionary_name,NULL,NULL, flag_compile & 0x1);
strcat(path_dsource, "dictsource\\");
CompileDictionary(path_dsource, dictionary_name, NULL, NULL, flag_compile & 0x1);
#else
CompileDictionary(NULL,dictionary_name,NULL,NULL, flag_compile & 0x1);
CompileDictionary(NULL, dictionary_name, NULL, NULL, flag_compile & 0x1);
#endif
#endif
exit(0);
}


SetParameter(espeakRATE,speed,0);
SetParameter(espeakVOLUME,amp,0);
SetParameter(espeakCAPITALS,option_capitals,0);
SetParameter(espeakPUNCTUATION,option_punctuation,0);
SetParameter(espeakWORDGAP,wordgap,0);
SetParameter(espeakRATE, speed, 0);
SetParameter(espeakVOLUME, amp, 0);
SetParameter(espeakCAPITALS, option_capitals, 0);
SetParameter(espeakPUNCTUATION, option_punctuation, 0);
SetParameter(espeakWORDGAP, wordgap, 0);

option_phonemes = phoneme_options | (phonemes_separator << 8);

if(pitch_adjustment != 50)
{
SetParameter(espeakPITCH,pitch_adjustment,0);
if (pitch_adjustment != 50) {
SetParameter(espeakPITCH, pitch_adjustment, 0);
}
DoVoiceChange(voice);

if(filename[0]==0)
{
if((optind < argc) && (flag_stdin == 0))
{
if (filename[0] == 0) {
if ((optind < argc) && (flag_stdin == 0)) {
// there's a non-option parameter, and no -f or --stdin
// use it as text
p_text = argv[optind];
}
else
{
} else {
f_text = stdin;
if(flag_stdin == 0)
if (flag_stdin == 0)
option_linelength = -1; // single input lines on stdin
}
}
else
{
f_text = fopen(filename,"r");
} else {
f_text = fopen(filename, "r");
}

if((f_text == NULL) && (p_text == NULL))
{
fprintf(stderr,"%sfile '%s'\n",err_load,filename);
if ((f_text == NULL) && (p_text == NULL)) {
fprintf(stderr, "%sfile '%s'\n", err_load, filename);
exit(1);
}

if(option_waveout || quiet)
{
if(quiet)
{
if (option_waveout || quiet) {
if (quiet) {
// no sound output
OpenWaveFile(NULL,samplerate);
OpenWaveFile(NULL, samplerate);
option_waveout = 1;
}
else
{
} else {
// write sound output to a WAV file
samples_split = (samplerate * samples_split) * 60;

if(samples_split)
{
if (samples_split) {
// don't open the wav file until we start generating speech
char *extn;
extn = strrchr(wavefile,'.');
if((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4))
{
strcpy(filetype,extn);
extn = strrchr(wavefile, '.');
if ((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) {
strcpy(filetype, extn);
*extn = 0;
}
}
else
if(OpenWaveFile(wavefile,samplerate) != 0)
{
fprintf(stderr,"Can't write to output file '%s'\n'",wavefile);
} else if (OpenWaveFile(wavefile, samplerate) != 0) {
fprintf(stderr, "Can't write to output file '%s'\n'", wavefile);
exit(3);
}
}

InitText(0);
SpeakNextClause(f_text,p_text,0);
SpeakNextClause(f_text, p_text, 0);

ix = 1;
for(;; )
{
if(WavegenFile() != 0)
{
if(ix == 0)
for (;;) {
if (WavegenFile() != 0) {
if (ix == 0)
break; // finished, wavegen command queue is empty
}

if(Generate(phoneme_list,&n_phoneme_list,1)==0)
{
ix = SpeakNextClause(NULL,NULL,1);
if (Generate(phoneme_list, &n_phoneme_list, 1) == 0) {
ix = SpeakNextClause(NULL, NULL, 1);
}
}

CloseWaveFile();
}
else
{
} else {
WavegenInitSound();

InitText(0);
SpeakNextClause(f_text,p_text,0);
SpeakNextClause(f_text, p_text, 0);

if(option_quiet)
{
while(SpeakNextClause(NULL,NULL,1) != 0);
return(0);
if (option_quiet) {
while (SpeakNextClause(NULL, NULL, 1) != 0) ;
return (0);
}

speaking = 1;
while(speaking)
{
while (speaking) {
// NOTE: if nanosleep() isn't recognised on your system, try replacing
// this by sleep(1);
#ifdef PLATFORM_WINDOWS
@@ -899,17 +831,17 @@ int main (int argc, char **argv)
struct timespec remaining;
period.tv_sec = 0;
period.tv_nsec = 300000000; // 0.3 sec
nanosleep(&period,&remaining);
nanosleep(&period, &remaining);
#else
sleep(1);
#endif
#endif
if(SynthOnTimer() != 0)
if (SynthOnTimer() != 0)
speaking = 0;
}
}

if((f_trans != stdout) && (f_trans != stderr))
if ((f_trans != stdout) && (f_trans != stderr))
fclose(f_trans); // needed for WinCe
return(0);
return (0);
}

Loading…
Cancel
Save