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

#include "speak_lib.h" #include "speak_lib.h"
#include "espeak_ng.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 utf8_in(int *c, const char *buf);
extern int GetFileLength(const char *filename); extern int GetFileLength(const char *filename);


const espeak_VOICE **voices; const espeak_VOICE **voices;
espeak_VOICE voice_select; 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 // display only voices for the specified language, in order of priority
voice_select.languages = language; voice_select.languages = language;
voice_select.age = 0; voice_select.age = 0;
voice_select.gender = 0; voice_select.gender = 0;
voice_select.name = NULL; voice_select.name = NULL;
voices = espeak_ListVoices(&voice_select); voices = espeak_ListVoices(&voice_select);
}
else
{
} else {
voices = espeak_ListVoices(NULL); 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; count = 0;
p = v->languages; p = v->languages;
while(*p != 0)
{
while (*p != 0) {
len = strlen(p+1); len = strlen(p+1);
lang_name = p+1; lang_name = p+1;


if(v->age == 0)
strcpy(age_buf," ");
if (v->age == 0)
strcpy(age_buf, " ");
else 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 // replace spaces in the name
if((c = v->name[j]) == ' ')
if ((c = v->name[j]) == ' ')
c = '_'; c = '_';
if((buf[j] = c) == 0)
if ((buf[j] = c) == 0)
break; 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++; count++;
p += len+2; p += len+2;
} }
fputc('\n',f_out);
fputc('\n', f_out);
} }
} }


// Write 4 bytes to a file, least significant first // Write 4 bytes to a file, least significant first
int ix; 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; value = value >> 8;
} }
} }
int OpenWavFile(char *path, int rate) int OpenWavFile(char *path, int rate)
{ {
static unsigned char wave_hdr[44] = { 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; f_wavfile = NULL;
if(path[0] != 0)
{
if(strcmp(path,"stdout")==0)
if (path[0] != 0) {
if (strcmp(path, "stdout") == 0)
f_wavfile = stdout; f_wavfile = stdout;
else 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);
} }




{ {
unsigned int pos; unsigned int pos;


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


fflush(f_wavfile); fflush(f_wavfile);
pos = ftell(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); fclose(f_wavfile);
f_wavfile = NULL; f_wavfile = NULL;
{ {
char fname[210]; char fname[210];


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


if(wav == NULL)
{
if (wav == NULL) {
CloseWavFile(); 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; samplerate = events->id.number;
samples_split = samples_split_seconds * samplerate; 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 // 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(); CloseWavFile();
samples_total = 0; samples_total = 0;
wavefile_count++; wavefile_count++;
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; samples_total += numsamples;
fwrite(wav,numsamples*2,1,f_wavfile);
fwrite(wav, numsamples*2, 1, f_wavfile);
} }
return(0);
return (0);
} }




int optind; int optind;
static int optional_argument; static int optional_argument;
static const char *arg_opts = "abfgklpsvw"; // which options have arguments static const char *arg_opts = "abfgklpsvw"; // which options have arguments
static char *opt_string="";
static char *opt_string = "";
#define no_argument 0 #define no_argument 0
#define required_argument 1 #define required_argument 1
#define optional_argument 2 #define optional_argument 2
#endif #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; FILE *f_phonemes_out = stdout;
char *data_path = NULL; // use default path for espeak-data char *data_path = NULL; // use default path for espeak-data


#ifdef NEED_GETOPT #ifdef NEED_GETOPT
optind = 1; optind = 1;
opt_string = ""; opt_string = "";
while(optind < argc)
{
while (optind < argc) {
int len; int len;
char *p; char *p;


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


optind++; optind++;
opt_string++; opt_string++;
p = optarg2 = 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 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; break;
len = strlen(long_options[ix].name); 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; c = long_options[ix].val;
optarg2 = NULL; optarg2 = NULL;


if((long_options[ix].has_arg != 0) && (p[len]=='='))
{
if ((long_options[ix].has_arg != 0) && (p[len] == '=')) {
optarg2 = &p[len+1]; optarg2 = &p[len+1];
} }
break; 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 // the option's value is in the next argument
optarg2 = argv[optind++]; optarg2 = argv[optind++];
} }
} }
#else #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. */ /* Detect the end of the options. */
if (c == -1) if (c == -1)
{ {
case 'b': case 'b':
// input character encoding, 8bit, 16bit, UTF8 // 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; synth_flags |= value;
else else
synth_flags |= espeakCHARS_8BIT; synth_flags |= espeakCHARS_8BIT;
break; break;


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


case 'l': case 'l':
break; break;


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


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


case 'z': // remove pause from the end of a sentence case 'z': // remove pause from the end of a sentence


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


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


case 0x103: // --punct case 0x103: // --punct
option_punctuation = 1; option_punctuation = 1;
if(optarg2 != NULL)
{
if (optarg2 != NULL) {
ix = 0; 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_punctlist[N_PUNCTLIST-1] = 0;
option_punctuation = 2; option_punctuation = 2;
} }
break; break;


case 0x104: // --voices 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); exit(0);


case 0x106: // -- split case 0x106: // -- split
if(optarg2 == NULL)
if (optarg2 == NULL)
samples_split_seconds = 30 * 60; // default 30 minutes samples_split_seconds = 30 * 60; // default 30 minutes
else else
samples_split_seconds = atoi(optarg2) * 60; samples_split_seconds = atoi(optarg2) * 60;
break; break;


case 0x108: // --phonout 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; break;




case 0x10a: // --ipa case 0x10a: // --ipa
phoneme_options |= espeakPHONEMES_IPA; phoneme_options |= espeakPHONEMES_IPA;
if(optarg2 != NULL)
{
if (optarg2 != NULL) {
// deprecated and obsolete // deprecated and obsolete
switch(atoi(optarg2))
switch (atoi(optarg2))
{ {
case 1: case 1:
phonemes_separator = '_'; phonemes_separator = '_';


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


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


case 0x10e: // --compile-mbrola 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); espeak_ng_CompileMbrolaVoice(optarg2, stdout);
exit(0); exit(0);


case 0x10f: // --compile-intonations 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); espeak_ng_CompileIntonation(stdout);
exit(0); exit(0);


case 0x110: // --compile-phonemes 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); espeak_ng_CompilePhonemeData(22050, stdout);
exit(0); exit(0);


} }




if(option_waveout || quiet)
{
if (option_waveout || quiet) {
// writing to a file (or no output), we can use synchronous mode // 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; samples_split = samplerate * samples_split_seconds;


espeak_SetSynthCallback(SynthCallback); espeak_SetSynthCallback(SynthCallback);
if(samples_split)
{
if (samples_split) {
char *extn; 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; *extn = 0;
} }
} }
}
else
{
} else {
// play the sound output // 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; 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); exit(2);
} }
} }


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


// set any non-default values of parameters. This must be done after espeak_Initialize() // 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_SetPunctuationList(option_punctlist);




espeak_SetPhonemeTrace(phoneme_options | (phonemes_separator << 8), f_phonemes_out); 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 // there's a non-option parameter, and no -f or --stdin
// use it as text // use it as text
p_text = argv[optind]; p_text = argv[optind];
}
else
{
} else {
f_text = stdin; f_text = stdin;
if(flag_stdin == 0)
{
if (flag_stdin == 0) {
flag_stdin = 2; flag_stdin = 2;
} }
} }
}
else
{
} else {
filesize = GetFileLength(filename); 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); exit(1);
} }




if(p_text != NULL)
{
if (p_text != NULL) {
int size; int size;
size = strlen(p_text); 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; int max = 1000;
p_text = (char *)malloc(max); p_text = (char *)malloc(max);


if(flag_stdin == 2)
{
if (flag_stdin == 2) {
// line by line input on stdin // 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; 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 // bulk input on stdin
ix = 0; ix = 0;
while(!feof(stdin))
{
while (!feof(stdin)) {
p_text[ix++] = fgetc(stdin); p_text[ix++] = fgetc(stdin);
if(ix >= (max-1))
{
if (ix >= (max-1)) {
max += 1000; 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; 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); 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); 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"); fprintf(stderr, "espeak_Synchronize() failed, maybe error when opening output device\n");
exit(4); exit(4);
} }


if(f_phonemes_out != stdout)
if (f_phonemes_out != stdout)
fclose(f_phonemes_out); // needed for WinCE 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

unsigned char c; unsigned char c;
unsigned int word; unsigned int word;


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


word = 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]; c = string[ix];
word |= (c << (ix*8)); word |= (c << (ix*8));
} }
return(word);
return (word);
} }


#pragma GCC visibility push(default) #pragma GCC visibility push(default)
int mbrola_ctrl = 20; // volume in 1/16 ths int mbrola_ctrl = 20; // volume in 1/16 ths
MBROLA_TAB data[N_PHONEME_TAB]; 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); fprintf(log, "Can't read: %s\n", filepath);
return ENE_READ_ERROR; 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; buf[sizeof(phoneme)-1] = 0;


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


if(memcmp(buf,"volume",6)==0)
{
if (memcmp(buf, "volume", 6) == 0) {
mbrola_ctrl = atoi(&buf[6]); mbrola_ctrl = atoi(&buf[6]);
continue; 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); data[count].name = StringToWord(phoneme);
if(strcmp(phoneme2,"NULL")==0)
if (strcmp(phoneme2, "NULL") == 0)
data[count].next_phoneme = 0; data[count].next_phoneme = 0;
else
if(strcmp(phoneme2,"VWL")==0)
else if (strcmp(phoneme2, "VWL") == 0)
data[count].next_phoneme = 2; data[count].next_phoneme = 2;
else else
data[count].next_phoneme = StringToWord(phoneme2); data[count].next_phoneme = StringToWord(phoneme2);
data[count].mbr_name2 = 0; data[count].mbr_name2 = 0;
data[count].percent = percent; data[count].percent = percent;
data[count].control = control; data[count].control = control;
if(strcmp(name1,"NULL")!=0)
if (strcmp(name1, "NULL") != 0)
data[count].mbr_name = StringToWord(name1); data[count].mbr_name = StringToWord(name1);
if(n == 6)
if (n == 6)
data[count].mbr_name2 = StringToWord(name2); data[count].mbr_name2 = StringToWord(name2);


count++; count++;
} }
fclose(f_in); 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); fprintf(log, "Can't write to: %s\n", buf);
return ENE_WRITE_ERROR; return ENE_WRITE_ERROR;
} }
Write4Bytes(f_out, mbrola_ctrl); Write4Bytes(f_out, mbrola_ctrl);


pw_end = (int *)(&data[count+1]); 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); Write4Bytes(f_out, *pw);
} }
fclose(f_out); fclose(f_out);

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

#include <sys/time.h> #include <sys/time.h>
#include <unistd.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() void debug_init()
{ {
if((fd_log = fopen(FILENAME,"a")) != NULL)
if ((fd_log = fopen(FILENAME, "a")) != NULL)
setvbuf(fd_log, NULL, _IONBF, 0); setvbuf(fd_log, NULL, _IONBF, 0);
} }


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


gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);


if (!fd_log)
{
if (!fd_log) {
debug_init(); 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);
} }
} }


{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
if (!fd_log)
{
if (!fd_log) {
debug_init(); debug_init();
} }
if (fd_log)
{
if (fd_log) {
vfprintf(fd_log, format, args); vfprintf(fd_log, format, args);
} }
va_end(args); va_end(args);
} }


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


gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);


if (!fd_log)
{
if (!fd_log) {
debug_init(); 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



#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
#define ENTER(text) debug_enter(text) #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); #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 #else


#ifdef NO_VARIADIC_MACROS #ifdef NO_VARIADIC_MACROS
#define SHOW(format) // VC6 doesn't allow "..." #define SHOW(format) // VC6 doesn't allow "..."
#else #else
#define SHOW(format,...)
#define SHOW(format, ...)
#endif #endif
#define SHOW_TIME(text) #define SHOW_TIME(text)
#define ENTER(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



#include "debug.h" #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"); 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; goto text_error;
} }


a_text = malloc( size+1 );
if (!a_text)
{
a_text = malloc(size+1);
if (!a_text) {
goto text_error; goto text_error;
} }
memcpy(a_text, text, size); memcpy(a_text, text, size);
data->end_position = end_position; data->end_position = end_position;
data->flags = flags; data->flags = flags;
data->user_data = user_data; 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); SHOW("ET_TEXT malloc text=%x, command=%x (uid=%d)\n", a_text, a_command, data->unique_identifier);


text_error: 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; a_command = NULL;
} }
return a_command; 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"); 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; goto msg_error;
} }


data = &(a_command->u.my_terminated_msg); data = &(a_command->u.my_terminated_msg);
data->unique_identifier = unique_identifier; data->unique_identifier = unique_identifier;
data->user_data = user_data; 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); SHOW("ET_TERMINATED_MSG command=%x (uid=%d, user_data=0x%x)\n", a_command, unique_identifier, (int)user_data);


msg_error: msg_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
} }
a_command = NULL; a_command = NULL;
} }


} }


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"); 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; 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; goto mark_error;
} }


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


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


a_command->type = ET_MARK; a_command->type = ET_MARK;
a_command->state = CS_UNDEFINED; a_command->state = CS_UNDEFINED;
data->end_position = end_position; data->end_position = end_position;
data->flags = flags; data->flags = flags;
data->user_data = user_data; data->user_data = user_data;
a_error=0;
a_error = 0;


mark_error: 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; a_command = NULL;
if (a_index_mark)
{
free (a_index_mark);
if (a_index_mark) {
free(a_index_mark);
} }
} }


return a_command; 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"); 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; goto key_error;
} }


a_command->state = CS_UNDEFINED; a_command->state = CS_UNDEFINED;
a_command->u.my_key.user_data = user_data; 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.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: key_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
} }
a_command = NULL; a_command = NULL;
} }
return a_command; 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"); 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; goto char_error;
} }


a_command->u.my_char.user_data = 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.unique_identifier = ++my_current_text_id;
a_command->u.my_char.character = character; a_command->u.my_char.character = character;
a_error=0;
a_error = 0;


char_error: char_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
} }
a_command = NULL; a_command = NULL;
} }
return a_command; 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"); 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; goto param_error;
} }


data->parameter = parameter; data->parameter = parameter;
data->value = value; data->value = value;
data->relative = relative; data->relative = relative;
a_error=0;
a_error = 0;


param_error: param_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
} }
a_command = NULL; a_command = NULL;
} }
return a_command; 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"); 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; goto list_error;
} }




{ {
size_t len = (wcslen(punctlist) + 1)*sizeof(wchar_t); 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); memcpy(a_list, punctlist, len);
a_command->u.my_punctuation_list = a_list; a_command->u.my_punctuation_list = a_list;
} }


a_error=0;
a_error = 0;


list_error: list_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
} }
a_command = NULL; a_command = NULL;
} }
return a_command; 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"); 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; goto name_error;
} }


a_command->type = ET_VOICE_NAME; a_command->type = ET_VOICE_NAME;
a_command->state = CS_UNDEFINED; 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: name_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
} }
a_command = NULL; a_command = NULL;
} }
return a_command; 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"); 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; goto spec_error;
} }


a_command->type = ET_VOICE_SPEC; a_command->type = ET_VOICE_SPEC;
a_command->state = CS_UNDEFINED; 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)); memcpy(data, voice, sizeof(espeak_VOICE));


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


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


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


a_error=0;
a_error = 0;
} }


spec_error: spec_error:
if (a_error)
{
if (a_command)
{
free (a_command);
if (a_error) {
if (a_command) {
free(a_command);
} }
a_command = NULL; a_command = NULL;
} }
return a_command; 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"); ENTER("delete_espeak_command");
int a_status = 0; int a_status = 0;
if (the_command)
{
switch(the_command->type)
if (the_command) {
switch (the_command->type)
{ {
case ET_TEXT: 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); 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); free(the_command->u.my_text.text);
} }
break; break;


case ET_MARK: case ET_MARK:
if (the_command->u.my_mark.text)
{
if (the_command->u.my_mark.text) {
free(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; break;


// it must be processed here for informing the calling program // it must be processed here for informing the calling program
// that its message is finished. // that its message is finished.
// This can be important for cleaning the related user data. // 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; the_command->state = CS_PROCESSED;
SHOW("delete_espeak_command > ET_TERMINATED_MSG callback (command=0x%x, uid=%d) \n", the_command, data->unique_identifier); 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; break;


case ET_KEY: 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; break;


break; break;


case ET_PUNCTUATION_LIST: 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; break;


case ET_VOICE_NAME: 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; break;


case ET_VOICE_SPEC: 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); free((void *)data->name);
} }


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


if (data->identifier)
{
if (data->identifier) {
free((void *)data->identifier); free((void *)data->identifier);
} }
} }
return a_status; 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"); ENTER("process_espeak_command");


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


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


the_command->state = CS_PROCESSED; the_command->state = CS_PROCESSED;


switch(the_command->type)
switch (the_command->type)
{ {
case ET_TEXT: 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; break;


case ET_MARK: 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; break;


case ET_TERMINATED_MSG: 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; break;


case ET_KEY: 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); sync_espeak_Key(data);
} }
break; break;
case ET_CHAR: case ET_CHAR:
{ {
const wchar_t data = the_command->u.my_char.character; const wchar_t data = the_command->u.my_char.character;
sync_espeak_Char( data);
sync_espeak_Char(data);
} }
break; break;


case ET_PARAMETER: 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; break;


case ET_PUNCTUATION_LIST: 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; break;


case ET_VOICE_NAME: 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; break;


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


void display_espeak_command( t_espeak_command* the_command)
void display_espeak_command(t_espeak_command *the_command)
{ {
ENTER("display_espeak_command"); ENTER("display_espeak_command");
#ifdef DEBUG_ENABLED #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; 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: 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; break;


case ET_MARK: 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; break;


case ET_KEY: 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); SHOW("display_espeak_command > (0x%x) KEY=%c\n", the_command, data);
} }
break; break;


case ET_TERMINATED_MSG: 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", 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, the_command, data->unique_identifier, data->user_data,


case ET_PARAMETER: 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", SHOW("display_espeak_command > (0x%x) PARAMETER=%d, value=%d, relative=%d\n",
the_command, data->parameter, data->value, data->relative); the_command, data->parameter, data->value, data->relative);
} }


case ET_PUNCTUATION_LIST: 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; break;


case ET_VOICE_NAME: 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); SHOW("display_espeak_command > (0x%x) VOICE_NAME=%s\n", the_command, data);
} }
break; break;

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

{ {
#endif #endif


typedef enum
{
typedef enum {
ET_TEXT, ET_TEXT,
ET_MARK, ET_MARK,
ET_KEY, ET_KEY,
ET_TERMINATED_MSG ET_TERMINATED_MSG
} t_espeak_type; } t_espeak_type;


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


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


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


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




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




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


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


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


union command
{
union command {
t_espeak_text my_text; t_espeak_text my_text;
t_espeak_mark my_mark; t_espeak_mark my_mark;
t_espeak_key my_key; t_espeak_key my_key;
t_espeak_character my_char; t_espeak_character my_char;
t_espeak_parameter my_param; t_espeak_parameter my_param;
const wchar_t* my_punctuation_list;
const wchar_t *my_punctuation_list;
const char *my_voice_name; const char *my_voice_name;
espeak_VOICE my_voice_spec; espeak_VOICE my_voice_spec;
t_espeak_terminated_msg my_terminated_msg; t_espeak_terminated_msg my_terminated_msg;
} t_espeak_command; } 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, 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 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, espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size,
const char *index_mark, unsigned int end_position, 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_Key(const char *key);
void sync_espeak_Char(wchar_t character); void sync_espeak_Char(wchar_t character);
void sync_espeak_SetPunctuationList(const wchar_t *punctlist); void sync_espeak_SetPunctuationList(const wchar_t *punctlist);
espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector); espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector);
void SetParameter(int parameter, int value, int relative); 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 #ifdef __cplusplus
} }
#endif #endif


//>
// >
#endif #endif

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

static pthread_t my_thread; static pthread_t my_thread;
static bool thread_inited; 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; struct t_node *next;
} node; } 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 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; my_callback = SynthCallback;
} }
{ {
ENTER("event_init"); ENTER("event_init");


my_event_is_running=0;
my_event_is_running = 0;


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


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


pthread_attr_t a_attrib; 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, thread_inited = (0 == pthread_create(&my_thread,
&a_attrib, &a_attrib,
polling_thread, polling_thread,
(void*)NULL));
(void *)NULL));
} }
assert(thread_inited); assert(thread_inited);
pthread_attr_destroy(&a_attrib); pthread_attr_destroy(&a_attrib);
} }


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


#ifdef DEBUG_ENABLED #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", "LIST_TERMINATED",
"WORD", "WORD",
"SENTENCE", "SENTENCE",
"??" "??"
}; };


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 #endif
} }


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


if (event==NULL)
{
if (event == NULL) {
return 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)); memcpy(a_event, event, sizeof(espeak_EVENT));


switch(event->type)
switch (event->type)
{ {
case espeakEVENT_MARK: case espeakEVENT_MARK:
case espeakEVENT_PLAY: case espeakEVENT_PLAY:
if (event->id.name)
{
if (event->id.name) {
a_event->id.name = strdup(event->id.name); a_event->id.name = strdup(event->id.name);
} }
break; break;
// * Last call: event->type = espeakEVENT_MSG_TERMINATED // * Last call: event->type = espeakEVENT_MSG_TERMINATED
// //


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


espeak_EVENT events[2]; 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 events[1].type = espeakEVENT_LIST_TERMINATED; // ... terminated by an event type=0


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


switch(event->type)
switch (event->type)
{ {
case espeakEVENT_SENTENCE: case espeakEVENT_SENTENCE:
my_callback(NULL, 0, events); my_callback(NULL, 0, events);
case espeakEVENT_END: case espeakEVENT_END:
case espeakEVENT_PHONEME: 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; espeak_EVENT_TYPE a_new_type = events[0].type;
events[0].type = espeakEVENT_SENTENCE; events[0].type = espeakEVENT_SENTENCE;
my_callback(NULL, 0, events); my_callback(NULL, 0, events);
} }
} }


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


event_display(event); event_display(event);


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


switch(event->type)
switch (event->type)
{ {
case espeakEVENT_MSG_TERMINATED: case espeakEVENT_MSG_TERMINATED:
event_notify(event); event_notify(event);


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


return 1; return 1;
} }


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


event_display(event); event_display(event);


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


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


if (!a_status)
{
if (!a_status) {
SHOW_TIME("event_declare > locked\n"); 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); a_error = push(a_event);
if (a_error != EE_OK)
{
if (a_error != EE_OK) {
event_delete(a_event); event_delete(a_event);
} }
SHOW_TIME("event_declare > unlocking\n"); SHOW_TIME("event_declare > unlocking\n");
SHOW_TIME("event_declare > post my_sem_start_is_required\n"); SHOW_TIME("event_declare > post my_sem_start_is_required\n");
sem_post(&my_sem_start_is_required); sem_post(&my_sem_start_is_required);


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


return a_error; return a_error;
} }


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


int a_event_is_running = 0; int a_event_is_running = 0;


SHOW_TIME("event_stop > locked\n"); SHOW_TIME("event_stop > locked\n");
if (a_status != 0)
{
if (a_status != 0) {
return EE_INTERNAL_ERROR; 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"); SHOW_TIME("event_stop > post my_sem_stop_is_required\n");
sem_post(&my_sem_stop_is_required); sem_post(&my_sem_stop_is_required);
a_event_is_running = 1; a_event_is_running = 1;
}
else
{
} else {
init(); // clear pending events init(); // clear pending events
} }
SHOW_TIME("event_stop > unlocking\n"); SHOW_TIME("event_stop > unlocking\n");
a_status = pthread_mutex_unlock(&my_mutex); a_status = pthread_mutex_unlock(&my_mutex);
if (a_status != 0)
{
if (a_status != 0) {
return EE_INTERNAL_ERROR; 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"); 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 continue; // Restart when interrupted by handler
} }
SHOW_TIME("event_stop > get my_sem_stop_is_acknowledged\n"); SHOW_TIME("event_stop > get my_sem_stop_is_acknowledged\n");
{ {
ENTER("sleep_until_timeout_or_stop_request"); ENTER("sleep_until_timeout_or_stop_request");


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


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


#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
struct timespec to; struct timespec to;
to.tv_nsec = ts.tv_nsec; to.tv_nsec = ts.tv_nsec;
#endif #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", 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, to.tv_sec, to.tv_nsec,
ts.tv_sec, ts.tv_nsec); ts.tv_sec, ts.tv_nsec);


while ((err = sem_timedwait(&my_sem_stop_is_required, &ts)) == -1 while ((err = sem_timedwait(&my_sem_stop_is_required, &ts)) == -1
&& errno == EINTR)
{
&& errno == EINTR) {
continue; // Restart when interrupted by handler 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", SHOW("polling_thread > sleep_until_timeout_or_stop_request > stop sem_timedwait %d.%09lu \n",
tv.tv_sec, tv.tv_usec*1000); 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; return a_stop_is_required;
} }
// If the stream is opened but the audio samples are not played, // If the stream is opened but the audio samples are not played,
// a timeout is started. // 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"); ENTER("get_remaining_time");


int err = 0; int err = 0;
*stop_is_required = 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; break;
} }


// //
// wait for the close of stream // 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; return err;
} }


static void* polling_thread(void*p)
static void *polling_thread(void *p)
{ {
ENTER("polling_thread"); 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"); SHOW_TIME("polling_thread > locking\n");
int a_status = pthread_mutex_lock(&my_mutex); int a_status = pthread_mutex_lock(&my_mutex);


SHOW_TIME("polling_thread > wait for my_sem_start_is_required\n"); 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 continue; // Restart when interrupted by handler
} }


pthread_mutex_unlock(&my_mutex); pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n"); 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 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__); 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 // 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"); 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); assert(event);


uint32_t time_in_ms = 0; uint32_t time_in_ms = 0;
int err = get_remaining_time((uint32_t)event->sample, int err = get_remaining_time((uint32_t)event->sample,
&time_in_ms, &time_in_ms,
&a_stop_is_required); &a_stop_is_required);
if (a_stop_is_required > 0)
{
if (a_stop_is_required > 0) {
break; break;
}
else if (err != 0)
{
} else if (err != 0) {
// No available time: the event is deleted. // 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); a_status = pthread_mutex_lock(&my_mutex);
SHOW_TIME("polling_thread > locked\n"); SHOW_TIME("polling_thread > locked\n");
event_delete( (espeak_EVENT*)pop());
event_delete((espeak_EVENT *)pop());
a_status = pthread_mutex_unlock(&my_mutex); a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n"); 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); event_notify(event);
// the user_data (and the type) are cleaned to be sure // the user_data (and the type) are cleaned to be sure
// that MSG_TERMINATED is called twice (at delete time too). // 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); a_status = pthread_mutex_lock(&my_mutex);
SHOW_TIME("polling_thread > locked\n"); SHOW_TIME("polling_thread > locked\n");
event_delete( (espeak_EVENT*)pop());
event_delete((espeak_EVENT *)pop());
a_status = pthread_mutex_unlock(&my_mutex); a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n"); 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); 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__); 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); a_stop_is_required = sleep_until_timeout_or_stop_request(time_in_ms);
} }
} }
SHOW_TIME("polling_thread > my_event_is_running = 0\n"); SHOW_TIME("polling_thread > my_event_is_running = 0\n");
my_event_is_running = 0; 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); 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__); 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); a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n"); 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 // no mutex required since the stop command is synchronous
// and waiting for my_sem_stop_is_acknowledged // and waiting for my_sem_stop_is_acknowledged
init(); init();
return NULL; 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"); ENTER("event > push");


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


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


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


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


if (head == NULL)
{
if (head == NULL) {
head = n; head = n;
tail = n; tail = n;
}
else
{
} else {
tail->next = n; tail->next = n;
tail = n; tail = n;
} }
tail->data = the_data; tail->data = the_data;


node_counter++; 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; return EE_OK;
} }


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


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


if (head != NULL)
{
node* n = head;
if (head != NULL) {
node *n = head;
the_data = n->data; the_data = n->data;
head = n->next; head = n->next;
free(n); free(n);
node_counter--; 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; tail = NULL;
} }


{ {
ENTER("event > init"); ENTER("event > init");


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


node_counter = 0; node_counter = 0;
} }
{ {
ENTER("event_terminate"); ENTER("event_terminate");


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

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

// the callback will be called when the event actually occurs. // the callback will be called when the event actually occurs.
// The callback is detailled in speak_lib.h . // The callback is detailled in speak_lib.h .
void event_init(void); void event_init(void);
void event_set_callback(t_espeak_callback* cb);
void event_set_callback(t_espeak_callback *cb);


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


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


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

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

static sem_t my_sem_start_is_required; static sem_t my_sem_start_is_required;
static sem_t my_sem_stop_is_acknowledged; 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 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() void fifo_init()
{ {
ENTER("fifo_init"); ENTER("fifo_init");


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


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


pthread_attr_t a_attrib; 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_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); assert(0);
} }




// leave once the thread is actually started // leave once the thread is actually started
SHOW_TIME("fifo > wait for my_sem_stop_is_acknowledged\n"); 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 continue; // Restart when interrupted by handler
} }
SHOW_TIME("fifo > get my_sem_stop_is_acknowledged\n"); 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"); ENTER("fifo_add_command");


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


if (!a_status)
{
if (!a_status) {
SHOW_TIME("fifo_add_command > locked\n"); SHOW_TIME("fifo_add_command > locked\n");
a_error = push(the_command); a_error = push(the_command);
SHOW_TIME("fifo_add_command > unlocking\n"); SHOW_TIME("fifo_add_command > unlocking\n");
a_status = pthread_mutex_unlock(&my_mutex); 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 // quit when command is actually started
// (for possible forthcoming 'end of command' checks) // (for possible forthcoming 'end of command' checks)
SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n"); SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n");
sem_post(&my_sem_start_is_required); sem_post(&my_sem_start_is_required);
int val=1;
while (val > 0)
{
int val = 1;
while (val > 0) {
usleep(50000); // TBD: event? usleep(50000); // TBD: event?
sem_getvalue(&my_sem_start_is_required, &val); sem_getvalue(&my_sem_start_is_required, &val);
} }
} }


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


return a_error; 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"); ENTER("fifo_add_command");


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


if (!a_status)
{
if (!a_status) {
SHOW_TIME("fifo_add_commands > locked\n"); 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"); SHOW("push > %s\n", "EE_BUFFER_FULL");
a_error = EE_BUFFER_FULL; a_error = EE_BUFFER_FULL;
}
else
{
} else {
push(command1); push(command1);
push(command2); push(command2);
} }
a_status = pthread_mutex_unlock(&my_mutex); 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 // quit when one command is actually started
// (for possible forthcoming 'end of command' checks) // (for possible forthcoming 'end of command' checks)
SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n"); SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n");
sem_post(&my_sem_start_is_required); sem_post(&my_sem_start_is_required);
int val=1;
while (val > 0)
{
int val = 1;
while (val > 0) {
usleep(50000); // TBD: event? usleep(50000); // TBD: event?
sem_getvalue(&my_sem_start_is_required, &val); sem_getvalue(&my_sem_start_is_required, &val);
} }
} }


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


return a_error; return a_error;
} }


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


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


if (my_command_is_running)
{
if (my_command_is_running) {
a_command_is_running = 1; a_command_is_running = 1;
my_stop_is_required = 1; my_stop_is_required = 1;
SHOW_TIME("fifo_stop > my_stop_is_required = 1\n"); SHOW_TIME("fifo_stop > my_stop_is_required = 1\n");
} }
SHOW_TIME("fifo_stop > unlocking\n"); SHOW_TIME("fifo_stop > unlocking\n");
a_status = pthread_mutex_unlock(&my_mutex); a_status = pthread_mutex_unlock(&my_mutex);
if (a_status != 0)
{
if (a_status != 0) {
return EE_INTERNAL_ERROR; 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"); 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 continue; // Restart when interrupted by handler
} }
SHOW_TIME("fifo_stop > get my_sem_stop_is_acknowledged\n"); SHOW_TIME("fifo_stop > get my_sem_stop_is_acknowledged\n");
return EE_OK; 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; return my_command_is_running;
} }


static int sleep_until_start_request_or_inactivity() static int sleep_until_start_request_or_inactivity()
{ {
SHOW_TIME("fifo > sleep_until_start_request_or_inactivity > ENTER"); 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). // Wait for the start request (my_sem_start_is_required).
// Besides this, if the audio stream is still busy, // Besides this, if the audio stream is still busy,
// The end of the stream is confirmed by several checks // The end of the stream is confirmed by several checks
// for filtering underflow. // 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; i = 0;
}
else
{
} else {
i++; i++;
} }


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


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


#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
struct timespec to; struct timespec to;
to.tv_nsec = ts.tv_nsec; to.tv_nsec = ts.tv_nsec;
#endif #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", 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, to.tv_sec, to.tv_nsec,
ts.tv_sec, ts.tv_nsec); ts.tv_sec, ts.tv_nsec);


while ((err = sem_timedwait(&my_sem_start_is_required, &ts)) == -1 while ((err = sem_timedwait(&my_sem_start_is_required, &ts)) == -1
&& errno == EINTR)
{
&& errno == EINTR) {
continue; 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, 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); tv.tv_sec, tv.tv_usec*1000);


if (err==0)
{
if (err == 0) {
a_start_is_required = 1; a_start_is_required = 1;
} }
} }
// my_stop_is_required = 1; // my_stop_is_required = 1;


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


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


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


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


if (a_stop_is_required)
{
if (a_stop_is_required) {
// acknowledge the stop request // acknowledge the stop request
SHOW_TIME("fifo > close_stream > post my_sem_stop_is_acknowledged\n"); SHOW_TIME("fifo > close_stream > post my_sem_stop_is_acknowledged\n");
int a_status = sem_post(&my_sem_stop_is_acknowledged); 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"); SHOW_TIME("fifo > close_stream > LEAVE\n");
} }


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


// announce that thread is started // announce that thread is started
sem_post(&my_sem_stop_is_acknowledged); 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"); SHOW_TIME("say_thread > wait for my_sem_start_is_required\n");


int a_start_is_required = 0; int a_start_is_required = 0;
if (look_for_inactivity)
{
if (look_for_inactivity) {
a_start_is_required = sleep_until_start_request_or_inactivity(); a_start_is_required = sleep_until_start_request_or_inactivity();
if (!a_start_is_required)
{
if (!a_start_is_required) {
close_stream(); close_stream();
} }
} }
look_for_inactivity = 1; 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 continue; // Restart when interrupted by handler
} }
} }
SHOW_TIME("say_thread > my_command_is_running = 1\n"); SHOW_TIME("say_thread > my_command_is_running = 1\n");
my_command_is_running = 1; my_command_is_running = 1;


while( my_command_is_running)
{
while (my_command_is_running) {
SHOW_TIME("say_thread > locking\n"); SHOW_TIME("say_thread > locking\n");
int a_status = pthread_mutex_lock(&my_mutex); 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"); SHOW_TIME("say_thread > text empty (talking=0) \n");
a_status = pthread_mutex_unlock(&my_mutex); a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("say_thread > unlocked\n"); SHOW_TIME("say_thread > unlocked\n");
SHOW_TIME("say_thread > my_command_is_running = 0\n"); SHOW_TIME("say_thread > my_command_is_running = 0\n");
my_command_is_running = 0; my_command_is_running = 0;
}
else
{
} else {
display_espeak_command(a_command); display_espeak_command(a_command);
// purge start semaphore // purge start semaphore
SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); 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"); SHOW_TIME("say_thread > my_command_is_running = 0\n");
my_command_is_running = 0; my_command_is_running = 0;
} }
SHOW_TIME("say_thread > unlocking\n"); SHOW_TIME("say_thread > unlocking\n");
a_status = pthread_mutex_unlock(&my_mutex); a_status = pthread_mutex_unlock(&my_mutex);


if (my_command_is_running)
{
if (my_command_is_running) {
process_espeak_command(a_command); process_espeak_command(a_command);
} }
delete_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 // no mutex required since the stop command is synchronous
// and waiting for my_sem_stop_is_acknowledged // and waiting for my_sem_stop_is_acknowledged
init(1); init(1);


// purge start semaphore // purge start semaphore
SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); 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 // acknowledge the stop request
SHOW_TIME("say_thread > post my_sem_stop_is_acknowledged\n"); SHOW_TIME("say_thread > post my_sem_stop_is_acknowledged\n");
int a_status = sem_post(&my_sem_stop_is_acknowledged); int a_status = sem_post(&my_sem_stop_is_acknowledged);
assert( a_status != -1);
assert(a_status != -1);
} }
// and wait for the next start // and wait for the next start
SHOW_TIME("say_thread > wait for my_sem_start_is_required\n"); SHOW_TIME("say_thread > wait for my_sem_start_is_required\n");


int fifo_is_command_enabled() 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); 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; struct t_node *next;
} node; } 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"); ENTER("fifo > push");


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


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


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


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


if (head == NULL)
{
if (head == NULL) {
head = n; head = n;
tail = n; tail = n;
}
else
{
} else {
tail->next = n; tail->next = n;
tail = n; tail = n;
} }
tail->data = the_command; tail->data = the_command;


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


the_command->state = CS_PENDING; the_command->state = CS_PENDING;
display_espeak_command(the_command); display_espeak_command(the_command);
return EE_OK; return EE_OK;
} }


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


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


if (head != NULL)
{
node* n = head;
if (head != NULL) {
node *n = head;
the_command = n->data; the_command = n->data;
head = n->next; head = n->next;
free(n); free(n);
node_counter--; 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; tail = NULL;
} }


ENTER("fifo > init"); ENTER("fifo > init");
c = pop(); c = pop();
while (c != NULL) { 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); process_espeak_command(c);
} }
delete_espeak_command(c); delete_espeak_command(c);
ENTER("fifo_terminate"); ENTER("fifo_terminate");


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

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

// EE_BUFFER_FULL: the command can not be buffered; // EE_BUFFER_FULL: the command can not be buffered;
// you may try after a while to call the function again. // you may try after a while to call the function again.
// EE_INTERNAL_ERROR. // 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. // Add two espeak commands in a single transaction.
// //
// EE_BUFFER_FULL: at least one command can not be buffered; // EE_BUFFER_FULL: at least one command can not be buffered;
// you may try after a while to call the function again. // you may try after a while to call the function again.
// EE_INTERNAL_ERROR. // 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. // The current running command must be stopped and the awaiting commands are cleared.
// Return: EE_OK: operation achieved // Return: EE_OK: operation achieved
// EE_INTERNAL_ERROR. // EE_INTERNAL_ERROR.
espeak_ERROR fifo_stop ();
espeak_ERROR fifo_stop();


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


// Terminate the fifo component. // Terminate the fifo component.
// Last function to be called. // 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



/* Resonator Structure */ /* Resonator Structure */


typedef struct
{
typedef struct {
double a; double a;
double b; double b;
double c; double c;


/* Structure for Klatt Globals */ /* Structure for Klatt Globals */


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




typedef struct
{
typedef struct {
int F0hz10; /* Voicing fund freq in Hz */ int F0hz10; /* Voicing fund freq in Hz */
int AVdb; /* Amp of voicing in dB, 0 to 70 */ int AVdb; /* Amp of voicing in dB, 0 to 70 */
int Fhz[10]; // formant Hz, F_NZ to F6 to F_NP int Fhz[10]; // formant Hz, F_NZ to F6 to F_NP
int AVpdb; /* Amp of voicing, par in dB, 0 to 70 */ int AVpdb; /* Amp of voicing, par in dB, 0 to 70 */
int Gain0; /* Overall gain, 60 dB is unity, 0 to 60 */ 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 Fhz_next[10]; // Fhz for the next chunk, so we can do interpolation of resonator (a,b,c) parameters
int Bhz_next[10]; int Bhz_next[10];
} klatt_frame_t, *klatt_frame_ptr; } klatt_frame_t, *klatt_frame_ptr;

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

char *buf_ptr, *lf; char *buf_ptr, *lf;


buf_ptr = buffer; buf_ptr = buffer;
for (;; ) {
for (;;) {
result = read(mbr_error_fd, buf_ptr, result = read(mbr_error_fd, buf_ptr,
sizeof(buffer) - (buf_ptr - buffer) - 1); sizeof(buffer) - (buf_ptr - buffer) - 1);
if (result == -1) { if (result == -1) {
} }
mbr_samplerate = wavhdr[24] + (wavhdr[25]<<8) + mbr_samplerate = wavhdr[24] + (wavhdr[25]<<8) +
(wavhdr[26]<<16) + (wavhdr[27]<<24); (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() */ /* remember the voice path for setVolumeRatio_MBR() */
if (mbr_voice_path != voice_path) { 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







#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 LookupPhonemeString(const char *string);
int PhonemeCode(unsigned int mnem); int PhonemeCode(unsigned int mnem);



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

#include "translate.h" #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; extern int n_ph_list2;
int n_plist_out = 0; int n_plist_out = 0;
int word_end; int word_end;
PHONEME_LIST2 *plist2; 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]; plist2 = &ph_list2[ix];


// don't do any substitution if the language has been temporarily changed // 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]; next = phoneme_tab[ph_list2[ix+1].phcode];


word_end = 0; 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 word_end = 1; // this phoneme is the end of a word


// check whether a Voice has specified that we should replace this phoneme // 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; 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 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 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 continue; // this replacement only occurs at the start of a word


// substitute the replacement phoneme // substitute the replacement phoneme
plist2->phcode = replace_phonemes[k].new_ph; 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 plist2->stresslevel = 0; // the replacement must be unstressed
break; break;
} }
} }


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


// copy phoneme into the output list // 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].ph = phoneme_tab[plist2->phcode];
plist_out[n_plist_out].type = plist_out[n_plist_out].ph->type; plist_out[n_plist_out].type = plist_out[n_plist_out].ph->type;
n_plist_out++; n_plist_out++;
} }
return(n_plist_out);
return (n_plist_out);
} }




void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) void MakePhonemeList(Translator *tr, int post_pause, int start_sentence)
{ {


int ix=0;
int ix = 0;
int j; int j;
int insert_ph = 0; int insert_ph = 0;
PHONEME_LIST *phlist; PHONEME_LIST *phlist;


// is the last word of the clause unstressed ? // is the last word of the clause unstressed ?
max_stress = 0; 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 // 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; max_stress = plist2[j].stresslevel & 0x7f;
if(plist2[j].sourceix != 0)
if (plist2[j].sourceix != 0)
break; break;
} }
if(max_stress < 4)
{
if (max_stress < 4) {
// the last word is unstressed, look for a previous word that can be stressed // 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 plist2[j].stresslevel = 4; // promote to stressed
break; break;
} }
if(plist2[j].stresslevel >= 4)
{
if (plist2[j].stresslevel >= 4) {
// found a stressed syllable, so stop looking // found a stressed syllable, so stop looking
break; break;
} }
// look for switch of phoneme tables // look for switch of phoneme tables
delete_count = 0; delete_count = 0;
current_phoneme_tab = tr->phoneme_tab_ix; 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; plist2[j].synthflags |= SFLAG_SWITCHED_LANG;
} }


if(delete_count > 0)
{
if (delete_count > 0) {
memcpy(&plist2[j-delete_count], &plist2[j], sizeof(plist2[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 it's switching to the current phoneme table, or
// delete this phonSWITCH if its followed by another phonSWITCH // delete this phonSWITCH if its followed by another phonSWITCH
delete_count++; delete_count++;
}
else
{
} else {
current_phoneme_tab = plist2[j].tone_ph; current_phoneme_tab = plist2[j].tone_ph;
} }
} }
} }
n_ph_list2 -= delete_count; 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 // set consonant clusters to all voiced or all unvoiced
// Regressive // Regressive
int type; int type;
int stop_propagation = 0; int stop_propagation = 0;
voicing = 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]; ph = phoneme_tab[plist2[j].phcode];
if(ph == NULL)
if (ph == NULL)
continue; continue;


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


type = ph->type; type = ph->type;


if(regression & 0x2)
{
if (regression & 0x2) {
// [v] amd [v;] don't cause regression, or [R^] // [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; stop_propagation = 1;
if(regression & 0x10)
if (regression & 0x10)
voicing = 0; voicing = 0;
} }
} }


if((type==phSTOP) || type==(phFRICATIVE))
{
if((voicing==0) && (regression & 0xf))
{
if ((type == phSTOP) || type == (phFRICATIVE)) {
if ((voicing == 0) && (regression & 0xf)) {
voicing = 1; 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 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; 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 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 // LANG=Polish, propagate through liquids and nasals
if((type == phPAUSE) || (type == phVOWEL))
if ((type == phPAUSE) || (type == phVOWEL))
voicing = 0; voicing = 0;
}
else
{
} else {
voicing = 0; voicing = 0;
} }
} }
if(stop_propagation)
{
if (stop_propagation) {
voicing = 0; voicing = 0;
stop_propagation = 0; stop_propagation = 0;
} }


if(plist2[j].sourceix)
{
if(regression & 0x04)
{
if (plist2[j].sourceix) {
if (regression & 0x04) {
// stop propagation at a word boundary // stop propagation at a word boundary
voicing = 0; voicing = 0;
} }
if(regression & 0x100)
{
if (regression & 0x100) {
// devoice word-final consonants, unless propagating voiced // devoice word-final consonants, unless propagating voiced
if(voicing == 0)
{
if (voicing == 0) {
voicing = 1; voicing = 1;
} }
} }
} }
} }


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 // start of a word
int k; int k;
int nextw; int nextw;
word_stress = 0; word_stress = 0;


// find the highest stress level in this word // 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; word_stress = ph_list3[nextw].stresslevel;


nextw++; nextw++;
if(ph_list3[nextw].sourceix)
if (ph_list3[nextw].sourceix)
break; // start of the next word break; // start of the next word
} }
for(k=j; k<nextw; k++)
{
for (k = j; k < nextw; k++) {
ph_list3[k].wordstress = word_stress; ph_list3[k].wordstress = word_stress;
} }
j = nextw; j = nextw;
}
else
{
} else {
j++; j++;
} }
} }
ph_list3[0].ph = ph; ph_list3[0].ph = ph;
word_start = 1; 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]; plist3 = &ph_list3[j];


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


// That's OK because we don't look backwards from plist3 *** but CountVowelPosition() and isAfterStress does !!! // That's OK because we don't look backwards from plist3 *** but CountVowelPosition() and isAfterStress does !!!
j--; j--;
plist3 = plist3_inserted = &ph_list3[j]; plist3 = plist3_inserted = &ph_list3[j];
if(j > 0)
{
if (j > 0) {
// move all previous phonemes in the word back one place // move all previous phonemes in the word back one place
int k; int k;
if(word_start > 0)
{
if (word_start > 0) {
k = word_start; k = word_start;
word_start--; word_start--;
}
else
{
} else {
k = 2; // No more space, don't loose the start of word mark at ph_list2[word_start] 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)); memcpy(&ph_list3[k-1], &ph_list3[k], sizeof(*plist3));
} }
memset(&plist3[0], 0, sizeof(*plist3)); memset(&plist3[0], 0, sizeof(*plist3));
plist3->ph = ph; plist3->ph = ph;
insert_ph = 0; insert_ph = 0;
inserted = 1; // don't insert the same phoneme repeatedly inserted = 1; // don't insert the same phoneme repeatedly
}
else
{
} else {
// otherwise get the next phoneme from the list // otherwise get the next phoneme from the list
if(plist3->sourceix != 0)
if (plist3->sourceix != 0)
word_start = j; word_start = j;


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


if(plist3->phcode == phonSWITCH)
{
if (plist3->phcode == phonSWITCH) {
// change phoneme table // change phoneme table
SelectPhonemeTable(plist3->tone_ph); SelectPhonemeTable(plist3->tone_ph);
} }
plist3[1].ph = next; plist3[1].ph = next;
} }


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


InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata); 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].ph = phoneme_tab[alternative];
ph_list3[j+1].phcode = alternative; ph_list3[j+1].phcode = alternative;
ph_list3[j+1].type = phoneme_tab[alternative]->type; ph_list3[j+1].type = phoneme_tab[alternative]->type;
next = phoneme_tab[alternative]; 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. // PROBLEM: if we insert a phoneme before a vowel then we loose the stress.
PHONEME_TAB *ph2; PHONEME_TAB *ph2;
ph2 = ph; ph2 = ph;
plist3->ph = ph; plist3->ph = ph;
plist3->phcode = alternative; plist3->phcode = alternative;


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


// re-interpret the changed phoneme // re-interpret the changed phoneme
InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata); 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; PHONEME_TAB *ph2;
ph2 = ph; ph2 = ph;
ph = phoneme_tab[alternative]; ph = phoneme_tab[alternative];
plist3->ph = ph; plist3->ph = ph;
plist3->phcode = alternative; plist3->phcode = alternative;


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


// re-interpret the changed phoneme // re-interpret the changed phoneme
} }
} }


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


// Check for consecutive unstressed syllables, even across word boundaries. // Check for consecutive unstressed syllables, even across word boundaries.
// Do this after changing phonemes according to stress level. // Do this after changing phonemes according to stress level.
if(plist3->stresslevel <= 1)
{
if (plist3->stresslevel <= 1) {
// an unstressed vowel // an unstressed vowel
unstress_count++; 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) // 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; plist3->stresslevel = 0;
if(p->wordstress < 4)
if (p->wordstress < 4)
p->stresslevel = 0; p->stresslevel = 0;
} }
break; 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' // in a sequence of unstressed syllables, reduce alternate syllables to 'diminished'
// stress. But not for the last phoneme of a stressed word // 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 // 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' plist3->stresslevel = 0; // change stress to 'diminished'
} }
} }
} }
}
else
{
} else {
unstress_count = 0; 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 // lengthen this consonant by doubling it
// BUT, can't insert a phoneme at position plist3[0] because it crashes PrevPh() // BUT, can't insert a phoneme at position plist3[0] because it crashes PrevPh()
insert_ph = next->code; insert_ph = next->code;
} }
} }


if((plist3+1)->sourceix != 0)
{
if ((plist3+1)->sourceix != 0) {
int x; 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 // add a pause after a word which ends in a consonant
insert_ph = phonPAUSE_NOLINK; 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 // break before a word which starts with a vowel
if(x == 0xc)
if (x == 0xc)
insert_ph = phonPAUSE_NOLINK; insert_ph = phonPAUSE_NOLINK;
else else
insert_ph = phonPAUSE_VSHORT; 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 // adjacent vowels over a word boundary
if(x == 2)
if (x == 2)
insert_ph = phonPAUSE_SHORT; insert_ph = phonPAUSE_SHORT;
else else
insert_ph = phonPAUSE_VSHORT; 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 // pause before a words which starts with a stressed vowel
insert_ph = phonPAUSE_SHORT; 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 // don't reduce the pause
insert_ph = pause_phonemes[x]; insert_ph = pause_phonemes[x];
} }
} }
if(option_wordgap > 0)
{
if (option_wordgap > 0) {
insert_ph = phonPAUSE_LONG; insert_ph = phonPAUSE_LONG;
} }
} }
next2 = phoneme_tab[plist3[2].phcode]; next2 = phoneme_tab[plist3[2].phcode];
plist3[2].ph = next2; 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]; insert_ph = phdata.pd_param[pd_APPENDPHONEME];
} }


if(deleted == 0)
{
if (deleted == 0) {
phlist[ix].ph = ph; phlist[ix].ph = ph;
phlist[ix].type = ph->type; phlist[ix].type = ph->type;
phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module
phlist[ix].sourceix = 0; phlist[ix].sourceix = 0;
phlist[ix].phcode = ph->code; phlist[ix].phcode = ph->code;


if(plist3->sourceix != 0)
{
if (plist3->sourceix != 0) {
phlist[ix].sourceix = plist3->sourceix; phlist[ix].sourceix = plist3->sourceix;
phlist[ix].newword = 1; // this phoneme is the start of a word 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 phlist[ix].newword = 5; // start of sentence + start of word
start_sentence = 0; start_sentence = 0;
} }
}
else
{
} else {
phlist[ix].newword = 0; phlist[ix].newword = 0;
} }


phlist[ix].length = phdata.pd_param[i_SET_LENGTH]*2; 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].ph = phoneme_tab[phonPAUSE_SHORT];
phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed 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].length = 128; // length_mod
phlist[ix].env = PITCHfall; phlist[ix].env = PITCHfall;
} }
phlist[ix].phcode = phonPAUSE; phlist[ix].phcode = phonPAUSE;
phlist[ix].type = phPAUSE; phlist[ix].type = phPAUSE;
phlist[ix].length = 0; phlist[ix].length = 0;
phlist[ix].sourceix=0;
phlist[ix].sourceix = 0;
phlist[ix].synthflags = 0; phlist[ix].synthflags = 0;
phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT]; 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



// speed_factor1 adjustments for speeds 350 to 374: pauses // speed_factor1 adjustments for speeds 350 to 374: pauses
static unsigned char pause_factor_350[] = { 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 }; // 370


// wav_factor adjustments for speeds 350 to 450 // wav_factor adjustments for speeds 350 to 450
speed.min_pause = 5; speed.min_pause = 5;


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


wpm_value = wpm; wpm_value = wpm;


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


if(control & 2)
{
if (control & 2) {
DoSonicSpeed(1 * 1024); 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; wpm2 = wpm;
wpm = 175; wpm = 175;


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


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


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


wpm2 = wpm; 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]; x = speed_lookup[wpm2-80];


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


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


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


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


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


s1 = (x * voice->speedf1)/256; 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 speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
else else
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm 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]; speed.wav_factor = wav_factor_350[wpm-350];
} }


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


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


if(wpm > 430)
{
if (wpm > 430) {
speed.pause_factor = 12; speed.pause_factor = 12;
}
else
if(wpm > 400)
{
} else if (wpm > 400) {
speed.pause_factor = 13; speed.pause_factor = 13;
}
else
if(wpm > 374)
{
} else if (wpm > 374) {
speed.pause_factor = 14; speed.pause_factor = 14;
}
else
if(wpm > 350)
{
} else if (wpm > 350) {
speed.pause_factor = pause_factor_350[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 // 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; speed.clause_pause_factor = 16;
} }
} }
speed.lenmod2_factor = 100; speed.lenmod2_factor = 100;


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


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


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


wpm2 = wpm; 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]; x = speed_lookup[wpm2-80];


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


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


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


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


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


s1 = (x * voice->speedf1)/256; 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 speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds
else else
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm 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]; speed.wav_factor = wav_factor_350[wpm-350];
} }


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


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


if(wpm > 430)
{
if (wpm > 430) {
speed.pause_factor = 12; speed.pause_factor = 12;
}
else
if(wpm > 400)
{
} else if (wpm > 400) {
speed.pause_factor = 13; speed.pause_factor = 13;
}
else
if(wpm > 374)
{
} else if (wpm > 374) {
speed.pause_factor = 14; speed.pause_factor = 14;
}
else
if(wpm > 350)
{
} else if (wpm > 350) {
speed.pause_factor = pause_factor_350[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 // 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; speed.clause_pause_factor = 16;
} }
} }
int new_value = value; int new_value = value;
int default_value; int default_value;


if(relative)
{
if(parameter < 5)
{
if (relative) {
if (parameter < 5) {
default_value = param_defaults[parameter]; default_value = param_defaults[parameter];
new_value = default_value + (default_value * value)/100; new_value = default_value + (default_value * value)/100;
} }
param_stack[0].parameter[parameter] = new_value; param_stack[0].parameter[parameter] = new_value;
saved_parameters[parameter] = new_value; saved_parameters[parameter] = new_value;


switch(parameter)
switch (parameter)
{ {
case espeakRATE: case espeakRATE:
embedded_value[EMBED_S] = new_value; embedded_value[EMBED_S] = new_value;
break; break;


case espeakPITCH: 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; embedded_value[EMBED_P] = new_value;
break; break;


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


break; break;


case espeakINTONATION: case espeakINTONATION:
if((new_value & 0xff) != 0)
if ((new_value & 0xff) != 0)
translator->langopts.intonation_group = new_value & 0xff; translator->langopts.intonation_group = new_value & 0xff;
option_tone_flags = new_value; option_tone_flags = new_value;
break; break;
do { do {
word = embedded_list[(*embix)++]; word = embedded_list[(*embix)++];


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






int stress; int stress;
int type; 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 last_pitch = 0;
int pitch_start; int pitch_start;
int length_mod; int length_mod;
int pitch1; int pitch1;
int emphasized; int emphasized;
int tone_mod; int tone_mod;
unsigned char *pitch_env=NULL;
unsigned char *pitch_env = NULL;
PHONEME_DATA phdata_tone; 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]; prev = &phoneme_list[ix-1];
p = &phoneme_list[ix]; p = &phoneme_list[ix];
stress = p->stresslevel & 0x7; stress = p->stresslevel & 0x7;


next = &phoneme_list[ix+1]; next = &phoneme_list[ix+1];


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


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


switch(type)
switch (type)
{ {
case phPAUSE: case phPAUSE:
last_pitch = 0; last_pitch = 0;


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


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


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


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


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


case phVFRICATIVE: case phVFRICATIVE:
case phFRICATIVE: 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; 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; p->prepause = 25;


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


if((tr->langopts.word_gap & 0x10) && (p->newword))
if ((tr->langopts.word_gap & 0x10) && (p->newword))
p->prepause = 30; 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 p->length = 200; // ?? should do this if it's from a prefix
else else
p->length = 150; p->length = 150;
}
else
} else
p->length = 256; p->length = 256;


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


case phVSTOP: 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; 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; pre_voiced = 1;


p->prepause = 40; p->prepause = 40;


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


if(prev->type==phSTOP && !(prev->ph->phflags & phFORTIS))
if (prev->type == phSTOP && !(prev->ph->phflags & phFORTIS))
p->prepause = 0; 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; p->prepause = 20;


break; break;
p->length = 256; // TEMPORARY p->length = 256; // TEMPORARY
min_drop = 0; min_drop = 0;


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


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


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


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


if(next->type == phVSTOP)
{
if (next->type == phVSTOP) {
p->length = (p->length * 160)/100; p->length = (p->length * 160)/100;
} }
if(next->type == phVFRICATIVE)
{
if (next->type == phVFRICATIVE) {
p->length = (p->length * 120)/100; 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; p->pitch2 = phoneme_list[ix2].pitch2;
break; break;
} }
} }


p->pitch1 = p->pitch2-16; p->pitch1 = p->pitch2-16;
if(p->pitch2 < 16)
{
if (p->pitch2 < 16) {
p->pitch1 = 0; p->pitch1 = 0;
} }
p->env = PITCHfall; p->env = PITCHfall;
next2 = &phoneme_list[ix+2]; next2 = &phoneme_list[ix+2];
next3 = &phoneme_list[ix+3]; 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) 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; p->amp = tr->stress_amps[stress]-1;
else else
p->amp = tr->stress_amps[stress]; p->amp = tr->stress_amps[stress];


if(emphasized)
if (emphasized)
p->amp = 25; p->amp = 25;


if(ix >= (n_phoneme_list-3))
{
if (ix >= (n_phoneme_list-3)) {
// last phoneme of a clause, limit its amplitude // last phoneme of a clause, limit its amplitude
if(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]; p->amp = tr->langopts.param[LOPT_MAXAMP_EOC];
} }


// is the last syllable of a word ? // is the last syllable of a word ?
more_syllables=0;
more_syllables = 0;
end_of_clause = 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++; more_syllables++;


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


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


// calc length modifier // 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 // if PAUSE_VSHORT is followed by a pause, then use that
next = next2; next = next2;
next2 = next3; next2 = next3;
} }


next2type = next2->ph->length_mod; 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 // don't use 2nd phoneme over a word boundary, unless it's a pause
if(next2type != 1)
if (next2type != 1)
next2type = 0; next2type = 0;
} }


len = tr->langopts.length_mods0[next2type *10+ next->ph->length_mod]; 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 // consider as a pause + first phoneme of the next word
length_mod = (len + tr->langopts.length_mods0[next->ph->length_mod *10+ 1])/2; length_mod = (len + tr->langopts.length_mods0[next->ph->length_mod *10+ 1])/2;
}
else
} else
length_mod = len; length_mod = len;
}
else
{
} else {
length_mod = tr->langopts.length_mods[next2type *10+ next->ph->length_mod]; 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; length_mod -= 15;
} }


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


length_mod = length_mod / 128; length_mod = length_mod / 128;


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


if(stress >= 7)
{
if (stress >= 7) {
// tonic syllable, include a constant component so it doesn't decrease directly with speed // tonic syllable, include a constant component so it doesn't decrease directly with speed
length_mod += tr->langopts.lengthen_tonic; length_mod += tr->langopts.lengthen_tonic;
if(emphasized)
if (emphasized)
length_mod += (tr->langopts.lengthen_tonic/2); length_mod += (tr->langopts.lengthen_tonic/2);
}
else
if(emphasized)
{
} else if (emphasized) {
length_mod += tr->langopts.lengthen_tonic; 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]; len = tr->stress_lengths[6];


length_mod = length_mod * len; 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 // a tone phoneme specifies a percentage change to the length
length_mod = (length_mod * tone_mod) / 100; 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 // this is the last syllable in the clause, lengthen it - more for short vowels
len = (p->ph->std_length * 2); 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; 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 = (tr->langopts.max_lengthmod*speed1);
} }


length_mod = length_mod / 128; length_mod = length_mod / 128;


if(p->type != phVOWEL)
{
if (p->type != phVOWEL) {
length_mod = 256; // syllabic consonant length_mod = 256; // syllabic consonant
min_drop = 16; min_drop = 16;
} }
p->length = length_mod; 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; p->env = 0;
} }


// set last-pitch // set last-pitch
env2 = p->env + 1; // version for use with preceding semi-vowel 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); InterpretPhoneme2(p->tone_ph, &phdata_tone);
pitch_env = GetEnvelope(phdata_tone.pitch_env); pitch_env = GetEnvelope(phdata_tone.pitch_env);
}
else
{
} else {
pitch_env = envelope_data[env2]; pitch_env = envelope_data[env2];
} }


pitch_start = p->pitch1 + ((p->pitch2-p->pitch1)*pitch_env[0])/256; 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 // set pitch for pre-vocalic part
if(pitch_start == 255)
if (pitch_start == 255)
last_pitch = pitch_start; // pitch is not set 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; last_pitch = pitch_start - 16;


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


prev->length = length_mod; prev->length = length_mod;


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


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


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


if(next2->type == phVOWEL)
{
if (next2->type == phVOWEL) {
next->synthflags &= ~SFLAG_SEQCONTINUE; 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; 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; pitch1 = p->pitch2 - min_drop;
if(pitch1 < 0)
if (pitch1 < 0)
pitch1 = 0; pitch1 = 0;
p->pitch1 = pitch1; 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

#define PEAKSHAPEW 256 #define PEAKSHAPEW 256


static int default_freq[N_PEAKS] = 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] = 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] = 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) static double read_double(FILE *stream)
{ {
unsigned char bytes[10]; unsigned char bytes[10];
fread(bytes,sizeof(char),10,stream);
fread(bytes, sizeof(char), 10, stream);
return ConvertFromIeeeExtended(bytes); 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] // 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 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--])); y += ((2*ns < (n-m) ? c[ns+1] : d[ns--]));
} }
return(y);
return (y);
} }




frame->amp_adjust = 100; frame->amp_adjust = 100;
frame->length_adjust = 0; frame->length_adjust = 0;


for(ix=0; ix<N_PEAKS; ix++)
{
for (ix = 0; ix < N_PEAKS; ix++) {
frame->formants[ix].freq = 0; frame->formants[ix].freq = 0;
frame->peaks[ix].pkfreq = default_freq[ix]; frame->peaks[ix].pkfreq = default_freq[ix];
frame->peaks[ix].pkheight = 0; frame->peaks[ix].pkheight = 0;


static void SpectFrameDestroy(SpectFrame *frame) static void SpectFrameDestroy(SpectFrame *frame)
{ {
if(frame->spect != NULL)
if (frame->spect != NULL)
free(frame->spect); free(frame->spect);
free(frame); free(frame);
} }
frame->pitch = read_double(stream); frame->pitch = read_double(stream);
frame->length = read_double(stream); frame->length = read_double(stream);
frame->dx = 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; 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); 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; 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; 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; frame->spect = spect_data;


return(0);
return (0);
} }




double GetFrameRms(SpectFrame *frame, int seq_amplitude) double GetFrameRms(SpectFrame *frame, int seq_amplitude)
{ {
int h; int h;
float total=0;
float total = 0;
int maxh; int maxh;
int height; int height;
int htab[400]; int htab[400];
wavegen_peaks_t wpeaks[9]; 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; height = (frame->peaks[h].pkheight * seq_amplitude * frame->amp_adjust)/10000;
wpeaks[h].height = height << 8; wpeaks[h].height = height << 8;


wpeaks[h].right = frame->peaks[h].pkright << 16; 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); total += ((htab[h] * htab[h]) >> 10);
} }
frame->rms = sqrt(total) / 7.25; frame->rms = sqrt(total) / 7.25;
return(frame->rms);
return (frame->rms);
} }




void SpectSeqDestroy(SpectSeq *spect) void SpectSeqDestroy(SpectSeq *spect)
{ {
int ix; 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]); SpectFrameDestroy(spect->frames[ix]);
} }
free(spect->frames); free(spect->frames);
static float GetFrameLength(SpectSeq *spect, int frame) static float GetFrameLength(SpectSeq *spect, int frame)
{ {
int ix; 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; adjust += spect->frames[ix]->length_adjust;
} }
return ((spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust); return ((spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust);
short n, temp; short n, temp;
int ix; int ix;
uint32_t id1, id2, name_len; uint32_t id1, id2, name_len;
int set_max_y=0;
int set_max_y = 0;
float time_offset; float time_offset;


FILE *stream = fopen(filename, "rb"); FILE *stream = fopen(filename, "rb");
if(stream == NULL)
{
if (stream == NULL) {
fprintf(stderr, "Failed to open: '%s'", filename); 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 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 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 spect->file_format = 2; // formants for Klatt synthesizer
}
else
{
} else {
fprintf(stderr, "Unsupported spectral file format.\n"); fprintf(stderr, "Unsupported spectral file format.\n");
fclose(stream); 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); 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; 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); 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]); SpectFrameDestroy(spect->frames[ix]);
} }
free(spect->frames); free(spect->frames);


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


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


spect->frames[spect->numframes++] = frame; 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; 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 spect->max_x = 9000; // disable auto-xscaling


frame_width = (int)((FRAME_WIDTH*spect->max_x)/MAX_DISPLAY_FREQ); 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 // start times from zero
time_offset = spect->frames[0]->time; 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->frames[ix]->time -= time_offset;


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


if(spect->max_y < 400)
if (spect->max_y < 400)
spect->max_y = 200; spect->max_y = 200;
else else
spect->max_y = 29000; // disable auto height scaling 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); fclose(stream);
return(0);
return (0);
} }

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

} peak_t; } peak_t;




typedef struct
{
typedef struct {
int keyframe; int keyframe;
short amp_adjust; short amp_adjust;
float length_adjust; float length_adjust;


double GetFrameRms(SpectFrame *frame, int amp); double GetFrameRms(SpectFrame *frame, int amp);


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

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



extern char path_home[N_PATH_HOME]; // this is the espeak-data directory 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); int GetFileLength(const char *filename);
char *Alloc(int size); char *Alloc(int size);
void Free(void *ptr); void Free(void *ptr);

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

typedef void (WINAPI *PROCVF)(float); typedef void (WINAPI *PROCVF)(float);
typedef int (WINAPI *PROCIV)(); typedef int (WINAPI *PROCIV)();
typedef int (WINAPI *PROCIC)(char *); 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 init_MBR;
PROCIC write_MBR; PROCIC write_MBR;


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


if ((hinstDllMBR=LoadLibraryA("mbrola.dll")) == 0)
if ((hinstDllMBR = LoadLibraryA("mbrola.dll")) == 0)
return FALSE; 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; return TRUE;
} }




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


mbrola_delay = 0; mbrola_delay = 0;
mbr_name_prefix = 0; mbr_name_prefix = 0;


if(mbrola_voice == NULL)
{
if (mbrola_voice == NULL) {
samplerate = samplerate_native; 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 #ifdef PLATFORM_POSIX
// if not found, then also look in // if not found, then also look in
// usr/share/mbrola/xx, /usr/share/mbrola/xx/xx, /usr/share/mbrola/voices/xx // 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(); close_MBR();
#endif #endif
#ifdef PLATFORM_WINDOWS #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"); fprintf(stderr, "Can't load mbrola.dll\n");
return(EE_INTERNAL_ERROR);
return (EE_INTERNAL_ERROR);
} }
#endif #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 setNoError_MBR(1); // don't stop on phoneme errors


// read eSpeak's mbrola phoneme translation data, eg. en1_phtrans // 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); size = GetFileLength(path);
if((f_in = fopen(path,"rb")) == NULL) {
if ((f_in = fopen(path, "rb")) == NULL) {
close_MBR(); 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); fclose(f_in);
close_MBR(); close_MBR();
return(EE_INTERNAL_ERROR);
return (EE_INTERNAL_ERROR);
} }


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


setVolumeRatio_MBR((float)(mbrola_control & 0xff) /16.0f); setVolumeRatio_MBR((float)(mbrola_control & 0xff) /16.0f);
samplerate = *srate = getFreq_MBR(); samplerate = *srate = getFreq_MBR();
if(*srate == 22050)
SetParameter(espeakVOICETYPE,0,0);
if (*srate == 22050)
SetParameter(espeakVOICETYPE, 0, 0);
else 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 mbrola_delay = 1000; // improve synchronization of events
return(EE_OK);
return (EE_OK);
} }




// bit 5 only in stressed syllable // bit 5 only in stressed syllable
// bit 6 only at the end of a word // bit 6 only at the end of a word


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


pr = mbrola_tab; 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; found = 1;
else
if((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN))
{
else if ((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN)) {
found = 1; found = 1;
}
else
{
if(pr->control & 2)
} else {
if (pr->control & 2)
other_ph = ph_prev; 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 other_ph = phoneme_tab[phPAUSE]; // don't match the next phoneme over a word boundary
else else
other_ph = ph_next; 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; 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; 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; found = 0;


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


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


if(pr->control & 0x10)
{
if (pr->control & 0x10) {
mbr_name_prefix = pr->mbr_name; mbr_name_prefix = pr->mbr_name;
return(0);
return (0);
} }
mnem = pr->mbr_name; mnem = pr->mbr_name;
break; break;
pr++; pr++;
} }


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




int ix; int ix;
int pitch_base; int pitch_base;
int pitch_range; int pitch_range;
int p1,p2,p_end;
int p1, p2, p_end;
unsigned char *pitch_env; unsigned char *pitch_env;
int max = -1; int max = -1;
int min = 999; 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 env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s)
int y2; int y2;
int y[4]; int y[4];




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


// find max and min in the pitch envelope // 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]; max = pitch_env[x];
y_max = x; y_max = x;
} }
if(pitch_env[x] < min)
{
if (pitch_env[x] < min) {
min = pitch_env[x]; min = pitch_env[x];
y_min = x; y_min = x;
} }
// set an additional pitch point half way through the phoneme. // set an additional pitch point half way through the phoneme.
// but look for a maximum or a minimum and use that instead // but look for a maximum or a minimum and use that instead
y[2] = 64; y[2] = 64;
if((y_max > 0) && (y_max < 127))
{
if ((y_max > 0) && (y_max < 127)) {
y[2] = y_max; y[2] = y_max;
} }
if((y_min > 0) && (y_min < 127))
{
if ((y_min > 0) && (y_min < 127)) {
y[2] = y_min; y[2] = y_min;
} }
y[1] = y[2] / 2; y[1] = y[2] / 2;
p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base; 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 // 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; p2 = ((pitch_env[y[ix]]*pitch_range)>>8) + pitch_base;


if(split > 0)
{
if (split > 0) {
y2 = (y[ix] * env100)/env_split; y2 = (y[ix] * env100)/env_split;
}
else
if(split < 0)
{
} else if (split < 0) {
y2 = ((y[ix]-env_split) * env100)/env_split; y2 = ((y[ix]-env_split) * env100)/env_split;
}
else
{
} else {
y2 = (y[ix] * env100)/128; 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; 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);
} }




word_count = 0; word_count = 0;
} }


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


ph_prev = plist[phix-1].ph; ph_prev = plist[phix-1].ph;
ph_next = 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); 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); 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++); 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++; phix++;


if(name == 0) {
if (name == 0) {
phix++; phix++;
continue; // ignore this phoneme 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 // a pause phoneme, which has not been changed by the translation
name = '_'; name = '_';
len = (p->length * speed.pause_factor)/256; len = (p->length * speed.pause_factor)/256;
if(len == 0)
if (len == 0)
len = 1; len = 1;
}
else
} else
len = (80 * speed.wav_factor)/256; len = (80 * speed.wav_factor)/256;


if(ph->code != phonEND_WORD)
{
if (ph->code != phonEND_WORD) {
char phoneme_name[16]; char phoneme_name[16];
WritePhMnemonic(phoneme_name, p->ph, p, option_phoneme_events & espeakINITIALIZE_PHONEME_IPA, NULL); 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); 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 // add a pause after this phoneme
pause = len_percent; pause = len_percent;
name2 = 0; name2 = 0;
done = 0; done = 0;
final_pitch = ""; final_pitch = "";


switch(ph->type)
switch (ph->type)
{ {
case phVOWEL: case phVOWEL:
len = ph->std_length; 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 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 += 50; // lengthen vowels before a pause
len = (len * p->length)/256; 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; 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; 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; done = 1;
break; break;


case phSTOP: case phSTOP:
released = 0; 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; p->synthflags |= SFLAG_NEXT_PAUSE;
InterpretPhoneme(NULL, 0, p, &phdata, NULL); InterpretPhoneme(NULL, 0, p, &phdata, NULL);
len = DoSample3(&phdata, 0, -1); len = DoSample3(&phdata, 0, -1);


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


case phVSTOP: case phVSTOP:
case phFRICATIVE: case phFRICATIVE:
len = 0; len = 0;
InterpretPhoneme(NULL, 0, p, &phdata, NULL); 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); // play it twice for [s:] etc.
len += DoSample3(&phdata, p->length, -1); len += DoSample3(&phdata, p->length, -1);


break; break;


case phNASAL: case phNASAL:
if(next->type != phVOWEL)
{
if (next->type != phVOWEL) {
memset(&fmtp, 0, sizeof(fmtp)); memset(&fmtp, 0, sizeof(fmtp));
InterpretPhoneme(NULL, 0, p, &phdata, NULL); InterpretPhoneme(NULL, 0, p, &phdata, NULL);
fmtp.fmt_addr = phdata.sound_addr[pd_FMT]; fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
len = DoSpect2(p->ph, 0, &fmtp, p, -1); len = DoSpect2(p->ph, 0, &fmtp, p, -1);
len = (len * 1000)/samplerate; len = (len * 1000)/samplerate;
if(next->type == phPAUSE)
if (next->type == phPAUSE)
len += 50; 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; break;


case phLIQUID: case phLIQUID:
if(next->type == phPAUSE)
{
if (next->type == phPAUSE) {
len += 50; 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; break;
} }


if(!done)
{
if(name2 != 0)
{
if (!done) {
if (name2 != 0) {
len1 = (len * len_percent)/100; 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; 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; 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); int res = write_MBR(mbr_buf);
if (res < 0) if (res < 0)
return 0; /* don't get stuck on error */ return 0; /* don't get stuck on error */
phix++; phix++;
} }


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


// flush the mbrola output buffer // flush the mbrola output buffer
{ {
FILE *f_mbrola = NULL; 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 // send mbrola data to a file, not to the mbrola library
f_mbrola = f_trans; f_mbrola = f_trans;
} }
if (result <= 0) if (result <= 0)
return 0; return 0;


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


espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate) 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) int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
{ {
return(0);
return (0);
} }


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


void MbrolaReset(void) 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

int WavegenCloseSound(); int WavegenCloseSound();
int WavegenInitSound(); int WavegenInitSound();
void WavegenInit(int rate, int wavemult_fact); 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); int WavegenFill(int fill_zeros);
void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr); void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr);


void Write4Bytes(FILE *f, int value); void Write4Bytes(FILE *f, int value);
int Read4Bytes(FILE *f); int Read4Bytes(FILE *f);
int Reverse4Bytes(int word); 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 #define ENV_LEN 128 // length of pitch envelopes
extern unsigned char *out_end; extern unsigned char *out_end;
extern int event_list_ix; extern int event_list_ix;
extern espeak_EVENT *event_list; extern espeak_EVENT *event_list;
extern t_espeak_callback* synth_callback;
extern t_espeak_callback *synth_callback;
extern const char *version_string; extern const char *version_string;
extern const int version_phdata; extern const int version_phdata;
extern double sonicSpeed; 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

{ {
#endif #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 CTRL_EMBEDDED 0x01 // control character at the start of an embedded command
#define REPLACED_E 'E' // 'e' replaced by silent e #define REPLACED_E 'E' // 'e' replaced by silent e
// match 1 pre 2 post 0 - use common phoneme string // match 1 pre 2 post 0 - use common phoneme string
// match 1 pre 2 post 3 0 - empty phoneme string // match 1 pre 2 post 3 0 - empty phoneme string


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


typedef struct { typedef struct {
int points; int points;






typedef struct
{
typedef struct {


LANGUAGE_OPTIONS langopts; LANGUAGE_OPTIONS langopts;
int translator_name; int translator_name;
extern wchar_t *p_wchar_input; extern wchar_t *p_wchar_input;
extern int dictionary_skipwords; 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); extern void SetLengthMods(Translator *tr, int value);


void LoadConfig(void); void LoadConfig(void);
int utf8_in2(int *c, const char *buf, int backwards); int utf8_in2(int *c, const char *buf, int backwards);
int utf8_out(unsigned int c, char *buf); int utf8_out(unsigned int c, char *buf);
int utf8_nbytes(const 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); int Eof(void);
char *strchr_w(const char *s, int c); char *strchr_w(const char *s, int c);
int IsBracket(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

extern int option_device_number; extern int option_device_number;


extern int wave_init(int samplerate); 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 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 // Supply the remaining time in ms before the sample is played
// (or 0 if the event has been already played). // (or 0 if the event has been already played).
// time: supplied value in ms // time: supplied value in ms
// //
// return 0 if ok or -1 otherwise (stream not opened). // 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. // 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. // Helpful if a new sample is waiting for free space whereas sound must be stopped.
typedef int (t_wave_callback)(void); 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 // general functions

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

#include "wave.h" #include "wave.h"
#include "debug.h" #include "debug.h"


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


enum { enum {
/* return value */ /* return value */


#ifdef USE_PULSEAUDIO #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 SAMPLE_RATE 22050
#define ESPEAK_FORMAT PA_SAMPLE_S16LE #define ESPEAK_FORMAT PA_SAMPLE_S16LE
SHOW("Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \ SHOW("Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \
goto label; \ goto label; \
} \ } \
} while(0);
} while (0);


#define CHECK_CONNECTED(retval) \ #define CHECK_CONNECTED(retval) \
do { \ do { \
ENTER(__FUNCTION__); ENTER(__FUNCTION__);
assert(c); assert(c);


switch (pa_context_get_state(c)) {
switch (pa_context_get_state(c))
{
case PA_CONTEXT_READY: case PA_CONTEXT_READY:
case PA_CONTEXT_TERMINATED: case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED: case PA_CONTEXT_FAILED:
} }
} }


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


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


case PA_STREAM_READY: case PA_STREAM_READY:
case PA_STREAM_FAILED: case PA_STREAM_FAILED:
assert(s); assert(s);


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


pa_threaded_mainloop_signal(mainloop, 0); pa_threaded_mainloop_signal(mainloop, 0);
} }
assert(c); assert(c);


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


pa_threaded_mainloop_signal(mainloop, 0); pa_threaded_mainloop_signal(mainloop, 0);
} }
pa_threaded_mainloop_lock(mainloop); pa_threaded_mainloop_lock(mainloop);
CHECK_DEAD_GOTO(fail, 1); 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))); SHOW("pa_stream_writable_size() failed: %s", pa_strerror(pa_context_errno(context)));
l = 0; l = 0;
goto fail; goto fail;


do_trigger = !!l; do_trigger = !!l;
SHOW("pulse_free: %d (ret)\n", (int)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) { static int pulse_playing(const pa_timing_info *the_timing_info) {


pa_threaded_mainloop_lock(mainloop); pa_threaded_mainloop_lock(mainloop);


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


if ((i = pa_stream_get_timing_info(stream)))
{
if ((i = pa_stream_get_timing_info(stream))) {
break; break;
} }
if (pa_context_errno(context) != PA_ERR_NODATA) { if (pa_context_errno(context) != PA_ERR_NODATA) {
} }


r = i->playing; 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: fail:
pa_threaded_mainloop_unlock(mainloop); pa_threaded_mainloop_unlock(mainloop);
return r; return r;
} }


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






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


assert(!stream); assert(!stream);
assert(!connected); 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.format = ESPEAK_FORMAT;
ss.rate = wave_samplerate; ss.rate = wave_samplerate;


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




SHOW_TIME("pa_context_new (call)"); SHOW_TIME("pa_context_new (call)");
if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "eSpeak"))) { 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; goto unlock_and_fail;
} }




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


pa_threaded_mainloop_free(mainloop); pa_threaded_mainloop_free(mainloop);
mainloop = NULL; mainloop = NULL;
} }
}
else {
} else {
pulse_close(); pulse_close();
} }




} }


void wave_flush(void* theHandler)
void wave_flush(void *theHandler)
{ {
ENTER("wave_flush"); 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; my_callback_is_output_enabled = cb;
} }
return pulse_open() == PULSE_OK; return pulse_open() == PULSE_OK;
} }


void* wave_open(const char* the_api)
void *wave_open(const char *the_api)
{ {
ENTER("wave_open"); 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"); ENTER("wave_write");
size_t bytes_to_write = theSize; size_t bytes_to_write = theSize;
char* aBuffer=theMono16BitsWaveBuffer;
char *aBuffer = theMono16BitsWaveBuffer;


assert(stream); assert(stream);


size_t aTotalFreeMem=0;
size_t aTotalFreeMem = 0;


pthread_mutex_lock(&pulse_mutex); pthread_mutex_lock(&pulse_mutex);


while (1)
{
while (1) {
if (my_callback_is_output_enabled 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!"); SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
theSize=0;
theSize = 0;
goto terminate; goto terminate;
} }


aTotalFreeMem = pulse_free(); 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); SHOW("wave_write > aTotalFreeMem(%d) >= bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write);
break; break;
} }


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


SHOW("wave_write > wait: aTotalFreeMem(%d) < bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write); 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 // 500: threshold for avoiding too many calls to pulse_write
if (aTotalFreeMem>500)
{
if (aTotalFreeMem > 500) {
pulse_write(aBuffer, aTotalFreeMem); pulse_write(aBuffer, aTotalFreeMem);
bytes_to_write -= aTotalFreeMem; bytes_to_write -= aTotalFreeMem;
aBuffer += aTotalFreeMem; aBuffer += aTotalFreeMem;
return theSize; return theSize;
} }


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


int a_status = pthread_mutex_lock(&pulse_mutex); 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__); SHOW("Error: pulse_mutex lock=%d (%s)\n", a_status, __FUNCTION__);
aStopStreamCount = 0; // last action aStopStreamCount = 0; // last action
return PULSE_ERROR; return PULSE_ERROR;
return PULSE_OK; return PULSE_OK;
} }


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


pa_timing_info a_timing_info; pa_timing_info a_timing_info;
int active = pulse_playing(&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; return active;
} }


ENTER("wave_terminate"); ENTER("wave_terminate");


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


pthread_mutex_destroy(a_mutex); 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; pa_timing_info a_timing_info;
pulse_playing(&a_timing_info); pulse_playing(&a_timing_info);
return a_timing_info.read_index; 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; pa_timing_info a_timing_info;
pulse_playing(&a_timing_info); pulse_playing(&a_timing_info);
return a_timing_info.write_index; 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; return -1;
} }


pa_timing_info a_timing_info; pa_timing_info a_timing_info;
pulse_playing(&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 // TBD: take in account time suplied by portaudio V18 API
a_time = sample - a_timing_info.read_index; a_time = sample - a_timing_info.read_index;
a_time = 0.5 + (a_time * 1000.0) / wave_samplerate; a_time = 0.5 + (a_time * 1000.0) / wave_samplerate;
}
else
{
} else {
a_time = 0; a_time = 0;
} }




int wave_init(return 1; ) { int wave_init(return 1; ) {
} }
void* wave_open(const char* the_api) {
void *wave_open(const char *the_api) {
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) {
return theSize; return theSize;
} }
int wave_close(void* theHandler) {
int wave_close(void *theHandler) {
return 0; return 0;
} }
int wave_is_busy(void* theHandler) {
int wave_is_busy(void *theHandler) {
return 0; return 0;
} }
void wave_terminate() { void wave_terminate() {
} }
uint32_t wave_get_read_position(void* theHandler) {
uint32_t wave_get_read_position(void *theHandler) {
return 0; return 0;
} }
uint32_t wave_get_write_position(void* theHandler) {
uint32_t wave_get_write_position(void *theHandler) {
return 0; return 0;
} }
void wave_flush(void* theHandler) {
void wave_flush(void *theHandler) {
} }
typedef int (t_wave_callback)(void); 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; 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; *time = (uint32_t)0;
return 0; return 0;
} }
{ {
struct timeval tv; struct timeval tv;


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


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


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


uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms; 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); SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns);
ts->tv_sec += 1; ts->tv_sec += 1;
t_ns -= ONE_BILLION; t_ns -= ONE_BILLION;

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

#include "wave.h" #include "wave.h"
#include "debug.h" #include "debug.h"


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


#ifdef USE_SADA #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 const char *sun_audio_device = "/dev/audio";
static int sun_audio_fd = -1; static int sun_audio_fd = -1;


// The last known playing index after a call to wave_close. // 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; static uint32_t wave_samplerate;


SHOW("wave_init() sun_audio_fd: %d\n", sun_audio_fd); SHOW("wave_init() sun_audio_fd: %d\n", sun_audio_fd);


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


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


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


// wave_write // wave_write
// //
// the number of bytes (not 16-bit samples) sent // 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 theSize)
{ {
size_t num; size_t num;
ENTER("wave_write"); 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!"); SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
return 0; return 0;
} }
char *out_end; char *out_end;
out_ptr = (char *)theMono16BitsWaveBuffer; out_ptr = (char *)theMono16BitsWaveBuffer;
out_end = out_ptr + theSize; out_end = out_ptr + theSize;
while(out_ptr < out_end)
{
while (out_ptr < out_end) {
c = out_ptr[0]; c = out_ptr[0];
out_ptr[0] = out_ptr[1]; out_ptr[0] = out_ptr[1];
out_ptr[1] = c; out_ptr[1] = c;
} }
#endif #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 // 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 // wave_get_read_position and also use it to help calculate the
// //
// The result of the ioctl call (non-0 means failure) // The result of the ioctl call (non-0 means failure)
// //
int wave_close(void* theHandler)
int wave_close(void *theHandler)
{ {
int ret; int ret;
audio_info_t ainfo; audio_info_t ainfo;
int audio_fd = (int) theHandler;
int audio_fd = (int)theHandler;
if (!audio_fd) { if (!audio_fd) {
audio_fd = sun_audio_fd; audio_fd = sun_audio_fd;
} }
// //
// A non-0 value if audio is being played // A non-0 value if audio is being played
// //
int wave_is_busy(void* theHandler)
int wave_is_busy(void *theHandler)
{ {
uint32_t time; uint32_t time;
if (total_samples_sent >= 1) { if (total_samples_sent >= 1) {
// //
// theHandler: the audio device file descriptor // theHandler: the audio device file descriptor
// //
void wave_flush(void* theHandler)
void wave_flush(void *theHandler)
{ {
ENTER("wave_flush"); ENTER("wave_flush");
SHOW_TIME("wave_flush > LEAVE"); SHOW_TIME("wave_flush > LEAVE");
// //
// cb: the callback to call from wave_write // 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; my_callback_is_output_enabled = cb;
} }
// The total number of 16-bit samples played by the audio system // The total number of 16-bit samples played by the audio system
// so far. // so far.
// //
uint32_t wave_get_read_position(void* theHandler)
uint32_t wave_get_read_position(void *theHandler)
{ {
audio_info_t ainfo; audio_info_t ainfo;
ENTER("wave_get_read_position"); 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("wave_get_read_position: %d\n", ainfo.play.samples);
SHOW_TIME("wave_get_read_position > LEAVE"); SHOW_TIME("wave_get_read_position > LEAVE");
return ainfo.play.samples; return ainfo.play.samples;
// the index wraps back to 0. We don't handle that wrapping, so // the index wraps back to 0. We don't handle that wrapping, so
// the behavior after 54 hours of play time is undefined.]]] // 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"); ENTER("wave_get_write_position");
SHOW("wave_get_write_position: %d\n", total_samples_sent); SHOW("wave_get_write_position: %d\n", total_samples_sent);
// Time in milliseconds before the sample is played or 0 if the sample // Time in milliseconds before the sample is played or 0 if the sample
// is currently playing or has already been played. // 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; uint32_t actual_index;


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


*time = 0; *time = 0;
} else { } else {
a_time = ((actual_index - ainfo.play.samples) * 1000) / wave_samplerate; 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("wave_get_remaining_time for %d: %d\n", sample, *time);
SHOW_TIME("wave_get_remaining_time > LEAVE"); SHOW_TIME("wave_get_remaining_time > LEAVE");
init wave_init() { init wave_init() {
return 1; return 1;
} }
void* wave_open(const char* the_api) {
void *wave_open(const char *the_api) {
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) {
return theSize; return theSize;
} }
int wave_close(void* theHandler) {
int wave_close(void *theHandler) {
return 0; return 0;
} }
int wave_is_busy(void* theHandler) {
int wave_is_busy(void *theHandler) {
return 0; return 0;
} }
void wave_terminate() { void wave_terminate() {
} }
uint32_t wave_get_read_position(void* theHandler) {
uint32_t wave_get_read_position(void *theHandler) {
return 0; return 0;
} }
uint32_t wave_get_write_position(void* theHandler) {
uint32_t wave_get_write_position(void *theHandler) {
return 0; return 0;
} }
void wave_flush(void* theHandler) {
void wave_flush(void *theHandler) {
} }
typedef int (t_wave_callback)(void); 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; 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; *time = (uint32_t)0;
return 0; return 0;
} }
{ {
struct timeval tv; struct timeval tv;


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


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


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


uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms; 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); SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns);
ts->tv_sec += 1; ts->tv_sec += 1;
t_ns -= ONE_BILLION; 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

const espeak_VOICE **voices; const espeak_VOICE **voices;
espeak_VOICE voice_select; 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 // display only voices for the specified language, in order of priority
voice_select.languages = language; voice_select.languages = language;
voice_select.age = 0; voice_select.age = 0;
voice_select.gender = 0; voice_select.gender = 0;
voice_select.name = NULL; voice_select.name = NULL;
voices = espeak_ListVoices(&voice_select); voices = espeak_ListVoices(&voice_select);
}
else
{
} else {
voices = espeak_ListVoices(NULL); 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; count = 0;
p = v->languages; p = v->languages;
while(*p != 0)
{
while (*p != 0) {
len = strlen(p+1); len = strlen(p+1);
lang_name = p+1; lang_name = p+1;


if(v->age == 0)
strcpy(age_buf," ");
if (v->age == 0)
strcpy(age_buf, " ");
else 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 // replace spaces in the name
if((c = v->name[j]) == ' ')
if ((c = v->name[j]) == ' ')
c = '_'; c = '_';
if((buf[j] = c) == 0)
if ((buf[j] = c) == 0)
break; 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++; count++;
p += len+2; p += len+2;
} }
fputc('\n',f_out);
fputc('\n', f_out);
} }
} }


// Set the length of 0x7ffff000 for --stdout // Set the length of 0x7ffff000 for --stdout
// This will be changed to the correct length for -w (write to file) // This will be changed to the correct length for -w (write to file)
static unsigned char wave_hdr[44] = { 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; f_wave = NULL;
if(path[0] != 0)
{
if(strcmp(path,"stdout")==0)
{
if (path[0] != 0) {
if (strcmp(path, "stdout") == 0) {
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
// prevent Windows adding 0x0d before 0x0a bytes // prevent Windows adding 0x0d before 0x0a bytes
_setmode(_fileno(stdout), _O_BINARY); _setmode(_fileno(stdout), _O_BINARY);
#endif #endif
f_wave = stdout; 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);
} }




{ {
unsigned int pos; unsigned int pos;


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


fflush(f_wave); fflush(f_wave);
pos = ftell(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); fclose(f_wave);


finished = WavegenFill(0); 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; end_of_sentence = 0;
if((samples_split > 0 ) && (samples_total > samples_split))
{
if ((samples_split > 0 ) && (samples_total > samples_split)) {
CloseWaveFile(); CloseWaveFile();
samples_total = 0; samples_total = 0;
} }
} }


if(f_wave != NULL)
{
if (f_wave != NULL) {
samples_total += (out_ptr - wav_outbuf)/2; samples_total += (out_ptr - wav_outbuf)/2;
fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave); fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave);
} }
return(finished);
return (finished);
} }




static void init_path(char *argv0, char *path_specified) 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; return;
} }


char *env; char *env;
unsigned char buf[sizeof(path_home)-12]; 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 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 return; // an espeak-data directory exists in the same directory as the espeak program
} }


var_type = REG_SZ; var_type = REG_SZ;
RegQueryValueEx(RegKey, "path", 0, &var_type, buf, &size); RegQueryValueEx(RegKey, "path", 0, &var_type, buf, &size);


sprintf(path_home,"%s\\espeak-data",buf);
sprintf(path_home, "%s\\espeak-data", buf);
#else #else
#ifdef PLATFORM_DOS #ifdef PLATFORM_DOS
strcpy(path_home,PATH_ESPEAK_DATA);
strcpy(path_home, PATH_ESPEAK_DATA);
#else #else
char *env; 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 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
#endif #endif
// to something other than the default "C". Then, not only Latin1 but also the // to something other than the default "C". Then, not only Latin1 but also the
// other characters give the correct results with iswalpha() etc. // other characters give the correct results with iswalpha() etc.
#ifdef PLATFORM_RISCOS #ifdef PLATFORM_RISCOS
setlocale(LC_CTYPE,"ISO8859-1");
setlocale(LC_CTYPE, "ISO8859-1");
#else #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 #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); 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(); LoadConfig();
SetVoiceStack(NULL, ""); SetVoiceStack(NULL, "");
SynthesizeInit(); 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]; param_stack[0].parameter[param] = param_defaults[param];


return(0);
return (0);
} }




int optind; int optind;
static int optional_argument; static int optional_argument;
static const char *arg_opts = "abfgklpsvw"; // which options have arguments static const char *arg_opts = "abfgklpsvw"; // which options have arguments
static char *opt_string="";
static char *opt_string = "";
#define no_argument 0 #define no_argument 0
#define required_argument 1 #define required_argument 1
#define optional_argument 2 #define optional_argument 2
#endif #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 "; 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 char *data_path = NULL; // use default path for espeak-data


int option_index = 0; int option_index = 0;
int c; int c;
int value; int value;
int speed=175;
int speed = 175;
int ix; int ix;
char *optarg2; char *optarg2;
int amp = 100; // default int amp = 100; // default
#ifdef NEED_GETOPT #ifdef NEED_GETOPT
optind = 1; optind = 1;
opt_string = ""; opt_string = "";
while(optind < argc)
{
while (optind < argc) {
int len; int len;
char *p; char *p;


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


optind++; optind++;
opt_string++; opt_string++;
p = optarg2 = 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 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; break;
len = strlen(long_options[ix].name); 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; c = long_options[ix].val;
optarg2 = NULL; optarg2 = NULL;


if((long_options[ix].has_arg != 0) && (p[len]=='='))
{
if ((long_options[ix].has_arg != 0) && (p[len] == '=')) {
optarg2 = &p[len+1]; optarg2 = &p[len+1];
} }
break; 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 // the option's value is in the next argument
optarg2 = argv[optind++]; optarg2 = argv[optind++];
} }
} }
#else #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. */ /* Detect the end of the options. */
if (c == -1) if (c == -1)
case 'b': case 'b':
// input character encoding, 8bit, 16bit, UTF8 // input character encoding, 8bit, 16bit, UTF8
option_multibyte = espeakCHARS_8BIT; 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; break;


case 'h': 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); exit(0);


case 'k': case 'k':


case 'p': case 'p':
pitch_adjustment = atoi(optarg2); pitch_adjustment = atoi(optarg2);
if(pitch_adjustment > 99) pitch_adjustment = 99;
if (pitch_adjustment > 99) pitch_adjustment = 99;
break; break;


case 'q': case 'q':
break; break;


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


case 'l': case 'l':
break; break;


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


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


case 'z': case 'z':


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


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


case 0x103: // --punct case 0x103: // --punct
option_punctuation = 1; option_punctuation = 1;
if(optarg2 != NULL)
{
if (optarg2 != NULL) {
ix = 0; 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_punctlist[N_PUNCTLIST-1] = 0;
option_punctuation = 2; option_punctuation = 2;
} }
break; break;


case 0x104: // --voices case 0x104: // --voices
init_path(argv[0],data_path);
DisplayVoices(stdout,optarg2);
init_path(argv[0], data_path);
DisplayVoices(stdout, optarg2);
exit(0); exit(0);


case 0x106: // -- split case 0x106: // -- split
if(optarg2 == NULL)
if (optarg2 == NULL)
samples_split = 30; // default 30 minutes samples_split = 30; // default 30 minutes
else else
samples_split = atoi(optarg2); samples_split = atoi(optarg2);
break; break;


case 0x108: // --phonout 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; f_trans = stderr;
} }
break; break;


case 0x10a: // --ipa case 0x10a: // --ipa
phoneme_options |= espeakPHONEMES_IPA; phoneme_options |= espeakPHONEMES_IPA;
if(optarg2 != NULL)
{
if (optarg2 != NULL) {
// deprecated and obsolete // deprecated and obsolete
switch(atoi(optarg2))
switch (atoi(optarg2))
{ {
case 1: case 1:
phonemes_separator = '_'; phonemes_separator = '_';
break; break;


case 0x10b: // --version 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); exit(0);


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


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


} }
} }


init_path(argv[0],data_path);
init_path(argv[0], data_path);
initialise(); 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; 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); exit(2);
} }
} }


if(flag_compile)
{
if (flag_compile) {
#ifdef PLATFORM_DOS #ifdef PLATFORM_DOS
char path_dsource[sizeof(path_home)+20]; 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 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 #else
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
char path_dsource[sizeof(path_home)+20]; 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 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 #else
CompileDictionary(NULL,dictionary_name,NULL,NULL, flag_compile & 0x1);
CompileDictionary(NULL, dictionary_name, NULL, NULL, flag_compile & 0x1);
#endif #endif
#endif #endif
exit(0); 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); 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); 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 // there's a non-option parameter, and no -f or --stdin
// use it as text // use it as text
p_text = argv[optind]; p_text = argv[optind];
}
else
{
} else {
f_text = stdin; f_text = stdin;
if(flag_stdin == 0)
if (flag_stdin == 0)
option_linelength = -1; // single input lines on stdin 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); exit(1);
} }


if(option_waveout || quiet)
{
if(quiet)
{
if (option_waveout || quiet) {
if (quiet) {
// no sound output // no sound output
OpenWaveFile(NULL,samplerate);
OpenWaveFile(NULL, samplerate);
option_waveout = 1; option_waveout = 1;
}
else
{
} else {
// write sound output to a WAV file // write sound output to a WAV file
samples_split = (samplerate * samples_split) * 60; samples_split = (samplerate * samples_split) * 60;


if(samples_split)
{
if (samples_split) {
// don't open the wav file until we start generating speech // don't open the wav file until we start generating speech
char *extn; 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; *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); exit(3);
} }
} }


InitText(0); InitText(0);
SpeakNextClause(f_text,p_text,0);
SpeakNextClause(f_text, p_text, 0);


ix = 1; ix = 1;
for(;; )
{
if(WavegenFile() != 0)
{
if(ix == 0)
for (;;) {
if (WavegenFile() != 0) {
if (ix == 0)
break; // finished, wavegen command queue is empty 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(); CloseWaveFile();
}
else
{
} else {
WavegenInitSound(); WavegenInitSound();


InitText(0); 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; speaking = 1;
while(speaking)
{
while (speaking) {
// NOTE: if nanosleep() isn't recognised on your system, try replacing // NOTE: if nanosleep() isn't recognised on your system, try replacing
// this by sleep(1); // this by sleep(1);
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
struct timespec remaining; struct timespec remaining;
period.tv_sec = 0; period.tv_sec = 0;
period.tv_nsec = 300000000; // 0.3 sec period.tv_nsec = 300000000; // 0.3 sec
nanosleep(&period,&remaining);
nanosleep(&period, &remaining);
#else #else
sleep(1); sleep(1);
#endif #endif
#endif #endif
if(SynthOnTimer() != 0)
if (SynthOnTimer() != 0)
speaking = 0; speaking = 0;
} }
} }


if((f_trans != stdout) && (f_trans != stderr))
if ((f_trans != stdout) && (f_trans != stderr))
fclose(f_trans); // needed for WinCe fclose(f_trans); // needed for WinCe
return(0);
return (0);
} }

Loading…
Cancel
Save