@@ -31,7 +31,7 @@ | |||
#include "speak_lib.h" | |||
#include "espeak_ng.h" | |||
extern void strncpy0(char *to,const char *from, int size); | |||
extern void strncpy0(char *to, const char *from, int size); | |||
extern int utf8_in(int *c, const char *buf); | |||
extern int GetFileLength(const char *filename); | |||
@@ -132,59 +132,50 @@ void DisplayVoices(FILE *f_out, char *language) | |||
const espeak_VOICE **voices; | |||
espeak_VOICE voice_select; | |||
static char genders[4] = {'-','M','F','-'}; | |||
static char genders[4] = { '-', 'M', 'F', '-' }; | |||
if((language != NULL) && (language[0] != 0)) | |||
{ | |||
if ((language != NULL) && (language[0] != 0)) { | |||
// display only voices for the specified language, in order of priority | |||
voice_select.languages = language; | |||
voice_select.age = 0; | |||
voice_select.gender = 0; | |||
voice_select.name = NULL; | |||
voices = espeak_ListVoices(&voice_select); | |||
} | |||
else | |||
{ | |||
} else { | |||
voices = espeak_ListVoices(NULL); | |||
} | |||
fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Languages\n"); | |||
fprintf(f_out, "Pty Language Age/Gender VoiceName File Other Languages\n"); | |||
for(ix=0; (v = voices[ix]) != NULL; ix++) | |||
{ | |||
for (ix = 0; (v = voices[ix]) != NULL; ix++) { | |||
count = 0; | |||
p = v->languages; | |||
while(*p != 0) | |||
{ | |||
while (*p != 0) { | |||
len = strlen(p+1); | |||
lang_name = p+1; | |||
if(v->age == 0) | |||
strcpy(age_buf," "); | |||
if (v->age == 0) | |||
strcpy(age_buf, " "); | |||
else | |||
sprintf(age_buf,"%3d",v->age); | |||
sprintf(age_buf, "%3d", v->age); | |||
if(count==0) | |||
{ | |||
for(j=0; j < sizeof(buf); j++) | |||
{ | |||
if (count == 0) { | |||
for (j = 0; j < sizeof(buf); j++) { | |||
// replace spaces in the name | |||
if((c = v->name[j]) == ' ') | |||
if ((c = v->name[j]) == ' ') | |||
c = '_'; | |||
if((buf[j] = c) == 0) | |||
if ((buf[j] = c) == 0) | |||
break; | |||
} | |||
fprintf(f_out,"%2d %-12s%s%c %-20s %-13s ", | |||
p[0],lang_name,age_buf,genders[v->gender],buf,v->identifier); | |||
} | |||
else | |||
{ | |||
fprintf(f_out,"(%s %d)",lang_name,p[0]); | |||
fprintf(f_out, "%2d %-12s%s%c %-20s %-13s ", | |||
p[0], lang_name, age_buf, genders[v->gender], buf, v->identifier); | |||
} else { | |||
fprintf(f_out, "(%s %d)", lang_name, p[0]); | |||
} | |||
count++; | |||
p += len+2; | |||
} | |||
fputc('\n',f_out); | |||
fputc('\n', f_out); | |||
} | |||
} | |||
@@ -196,9 +187,8 @@ static void Write4Bytes(FILE *f, int value) | |||
// Write 4 bytes to a file, least significant first | |||
int ix; | |||
for(ix=0; ix<4; ix++) | |||
{ | |||
fputc(value & 0xff,f); | |||
for (ix = 0; ix < 4; ix++) { | |||
fputc(value & 0xff, f); | |||
value = value >> 8; | |||
} | |||
} | |||
@@ -208,37 +198,35 @@ static void Write4Bytes(FILE *f, int value) | |||
int OpenWavFile(char *path, int rate) | |||
{ | |||
static unsigned char wave_hdr[44] = { | |||
'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ', | |||
0x10,0,0,0,1,0,1,0, 9,0x3d,0,0,0x12,0x7a,0,0, | |||
2,0,0x10,0,'d','a','t','a', 0x00,0xf0,0xff,0x7f | |||
'R', 'I', 'F', 'F', 0x24, 0xf0, 0xff, 0x7f, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', | |||
0x10, 0, 0, 0, 1, 0, 1, 0, 9, 0x3d, 0, 0, 0x12, 0x7a, 0, 0, | |||
2, 0, 0x10, 0, 'd', 'a', 't', 'a', 0x00, 0xf0, 0xff, 0x7f | |||
}; | |||
if(path == NULL) | |||
return(2); | |||
if (path == NULL) | |||
return (2); | |||
while(isspace(*path)) path++; | |||
while (isspace(*path)) path++; | |||
f_wavfile = NULL; | |||
if(path[0] != 0) | |||
{ | |||
if(strcmp(path,"stdout")==0) | |||
if (path[0] != 0) { | |||
if (strcmp(path, "stdout") == 0) | |||
f_wavfile = stdout; | |||
else | |||
f_wavfile = fopen(path,"wb"); | |||
f_wavfile = fopen(path, "wb"); | |||
} | |||
if(f_wavfile == NULL) | |||
{ | |||
fprintf(stderr,"Can't write to: '%s'\n",path); | |||
return(1); | |||
if (f_wavfile == NULL) { | |||
fprintf(stderr, "Can't write to: '%s'\n", path); | |||
return (1); | |||
} | |||
fwrite(wave_hdr,1,24,f_wavfile); | |||
Write4Bytes(f_wavfile,rate); | |||
Write4Bytes(f_wavfile,rate * 2); | |||
fwrite(&wave_hdr[32],1,12,f_wavfile); | |||
return(0); | |||
fwrite(wave_hdr, 1, 24, f_wavfile); | |||
Write4Bytes(f_wavfile, rate); | |||
Write4Bytes(f_wavfile, rate * 2); | |||
fwrite(&wave_hdr[32], 1, 12, f_wavfile); | |||
return (0); | |||
} | |||
@@ -247,17 +235,17 @@ static void CloseWavFile() | |||
{ | |||
unsigned int pos; | |||
if((f_wavfile==NULL) || (f_wavfile == stdout)) | |||
if ((f_wavfile == NULL) || (f_wavfile == stdout)) | |||
return; | |||
fflush(f_wavfile); | |||
pos = ftell(f_wavfile); | |||
fseek(f_wavfile,4,SEEK_SET); | |||
Write4Bytes(f_wavfile,pos - 8); | |||
fseek(f_wavfile, 4, SEEK_SET); | |||
Write4Bytes(f_wavfile, pos - 8); | |||
fseek(f_wavfile,40,SEEK_SET); | |||
Write4Bytes(f_wavfile,pos - 44); | |||
fseek(f_wavfile, 40, SEEK_SET); | |||
Write4Bytes(f_wavfile, pos - 44); | |||
fclose(f_wavfile); | |||
f_wavfile = NULL; | |||
@@ -269,27 +257,20 @@ static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) | |||
{ | |||
char fname[210]; | |||
if(quiet) return(0); // -q quiet mode | |||
if (quiet) return (0); // -q quiet mode | |||
if(wav == NULL) | |||
{ | |||
if (wav == NULL) { | |||
CloseWavFile(); | |||
return(0); | |||
return (0); | |||
} | |||
while(events->type != 0) | |||
{ | |||
if(events->type == espeakEVENT_SAMPLERATE) | |||
{ | |||
while (events->type != 0) { | |||
if (events->type == espeakEVENT_SAMPLERATE) { | |||
samplerate = events->id.number; | |||
samples_split = samples_split_seconds * samplerate; | |||
} | |||
else | |||
if(events->type == espeakEVENT_SENTENCE) | |||
{ | |||
} else if (events->type == espeakEVENT_SENTENCE) { | |||
// start a new WAV file when the limit is reached, at this sentence boundary | |||
if((samples_split > 0) && (samples_total > samples_split)) | |||
{ | |||
if ((samples_split > 0) && (samples_total > samples_split)) { | |||
CloseWavFile(); | |||
samples_total = 0; | |||
wavefile_count++; | |||
@@ -298,27 +279,22 @@ static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) | |||
events++; | |||
} | |||
if(f_wavfile == NULL) | |||
{ | |||
if(samples_split > 0) | |||
{ | |||
sprintf(fname,"%s_%.2d%s",wavefile,wavefile_count+1,filetype); | |||
if(OpenWavFile(fname, samplerate) != 0) | |||
return(1); | |||
} | |||
else | |||
{ | |||
if(OpenWavFile(wavefile, samplerate) != 0) | |||
return(1); | |||
if (f_wavfile == NULL) { | |||
if (samples_split > 0) { | |||
sprintf(fname, "%s_%.2d%s", wavefile, wavefile_count+1, filetype); | |||
if (OpenWavFile(fname, samplerate) != 0) | |||
return (1); | |||
} else { | |||
if (OpenWavFile(wavefile, samplerate) != 0) | |||
return (1); | |||
} | |||
} | |||
if(numsamples > 0) | |||
{ | |||
if (numsamples > 0) { | |||
samples_total += numsamples; | |||
fwrite(wav,numsamples*2,1,f_wavfile); | |||
fwrite(wav, numsamples*2, 1, f_wavfile); | |||
} | |||
return(0); | |||
return (0); | |||
} | |||
@@ -343,42 +319,41 @@ struct option { | |||
int optind; | |||
static int optional_argument; | |||
static const char *arg_opts = "abfgklpsvw"; // which options have arguments | |||
static char *opt_string=""; | |||
static char *opt_string = ""; | |||
#define no_argument 0 | |||
#define required_argument 1 | |||
#define optional_argument 2 | |||
#endif | |||
int main (int argc, char **argv) | |||
int main(int argc, char **argv) | |||
{ | |||
static struct option long_options[] = | |||
{ | |||
{"help", no_argument, 0, 'h'}, | |||
{"stdin", no_argument, 0, 0x100}, | |||
{"compile-debug", optional_argument, 0, 0x101}, | |||
{"compile", optional_argument, 0, 0x102}, | |||
{"punct", optional_argument, 0, 0x103}, | |||
{"voices", optional_argument, 0, 0x104}, | |||
{"stdout", no_argument, 0, 0x105}, | |||
{"split", optional_argument, 0, 0x106}, | |||
{"path", required_argument, 0, 0x107}, | |||
{"phonout", required_argument, 0, 0x108}, | |||
{"pho", no_argument, 0, 0x109}, | |||
{"ipa", optional_argument, 0, 0x10a}, | |||
{"version", no_argument, 0, 0x10b}, | |||
{"sep", optional_argument, 0, 0x10c}, | |||
{"tie", optional_argument, 0, 0x10d}, | |||
{"compile-mbrola", optional_argument, 0, 0x10e}, | |||
{"compile-intonations", no_argument, 0, 0x10f}, | |||
{"compile-phonemes", no_argument, 0, 0x110}, | |||
{0, 0, 0, 0} | |||
static struct option long_options[] = { | |||
{ "help", no_argument, 0, 'h' }, | |||
{ "stdin", no_argument, 0, 0x100 }, | |||
{ "compile-debug", optional_argument, 0, 0x101 }, | |||
{ "compile", optional_argument, 0, 0x102 }, | |||
{ "punct", optional_argument, 0, 0x103 }, | |||
{ "voices", optional_argument, 0, 0x104 }, | |||
{ "stdout", no_argument, 0, 0x105 }, | |||
{ "split", optional_argument, 0, 0x106 }, | |||
{ "path", required_argument, 0, 0x107 }, | |||
{ "phonout", required_argument, 0, 0x108 }, | |||
{ "pho", no_argument, 0, 0x109 }, | |||
{ "ipa", optional_argument, 0, 0x10a }, | |||
{ "version", no_argument, 0, 0x10b }, | |||
{ "sep", optional_argument, 0, 0x10c }, | |||
{ "tie", optional_argument, 0, 0x10d }, | |||
{ "compile-mbrola", optional_argument, 0, 0x10e }, | |||
{ "compile-intonations", no_argument, 0, 0x10f }, | |||
{ "compile-phonemes", no_argument, 0, 0x110 }, | |||
{ 0, 0, 0, 0 } | |||
}; | |||
static const char* err_load = "Failed to read "; | |||
static const char *err_load = "Failed to read "; | |||
FILE *f_text=NULL; | |||
char *p_text=NULL; | |||
FILE *f_text = NULL; | |||
char *p_text = NULL; | |||
FILE *f_phonemes_out = stdout; | |||
char *data_path = NULL; // use default path for espeak-data | |||
@@ -417,15 +392,13 @@ int main (int argc, char **argv) | |||
#ifdef NEED_GETOPT | |||
optind = 1; | |||
opt_string = ""; | |||
while(optind < argc) | |||
{ | |||
while (optind < argc) { | |||
int len; | |||
char *p; | |||
if((c = *opt_string) == 0) | |||
{ | |||
if ((c = *opt_string) == 0) { | |||
opt_string = argv[optind]; | |||
if(opt_string[0] != '-') | |||
if (opt_string[0] != '-') | |||
break; | |||
optind++; | |||
@@ -435,45 +408,36 @@ int main (int argc, char **argv) | |||
opt_string++; | |||
p = optarg2 = opt_string; | |||
if(c == '-') | |||
{ | |||
if(p[0] == 0) | |||
if (c == '-') { | |||
if (p[0] == 0) | |||
break; // -- means don't interpret further - as commands | |||
opt_string=""; | |||
for(ix=0;; ix++) | |||
{ | |||
if(long_options[ix].name == 0) | |||
opt_string = ""; | |||
for (ix = 0;; ix++) { | |||
if (long_options[ix].name == 0) | |||
break; | |||
len = strlen(long_options[ix].name); | |||
if(memcmp(long_options[ix].name,p,len)==0) | |||
{ | |||
if (memcmp(long_options[ix].name, p, len) == 0) { | |||
c = long_options[ix].val; | |||
optarg2 = NULL; | |||
if((long_options[ix].has_arg != 0) && (p[len]=='=')) | |||
{ | |||
if ((long_options[ix].has_arg != 0) && (p[len] == '=')) { | |||
optarg2 = &p[len+1]; | |||
} | |||
break; | |||
} | |||
} | |||
} | |||
else | |||
if(strchr(arg_opts,c) != NULL) | |||
{ | |||
opt_string=""; | |||
if(optarg2[0]==0) | |||
{ | |||
} else if (strchr(arg_opts, c) != NULL) { | |||
opt_string = ""; | |||
if (optarg2[0] == 0) { | |||
// the option's value is in the next argument | |||
optarg2 = argv[optind++]; | |||
} | |||
} | |||
#else | |||
while(true) | |||
{ | |||
c = getopt_long (argc, argv, "a:b:f:g:hk:l:mp:qs:v:w:xXz", | |||
long_options, &option_index); | |||
while (true) { | |||
c = getopt_long(argc, argv, "a:b:f:g:hk:l:mp:qs:v:w:xXz", | |||
long_options, &option_index); | |||
/* Detect the end of the options. */ | |||
if (c == -1) | |||
@@ -485,7 +449,7 @@ int main (int argc, char **argv) | |||
{ | |||
case 'b': | |||
// input character encoding, 8bit, 16bit, UTF8 | |||
if((sscanf(optarg2,"%d",&value) == 1) && (value <= 4)) | |||
if ((sscanf(optarg2, "%d", &value) == 1) && (value <= 4)) | |||
synth_flags |= value; | |||
else | |||
synth_flags |= espeakCHARS_8BIT; | |||
@@ -523,7 +487,7 @@ int main (int argc, char **argv) | |||
break; | |||
case 'f': | |||
strncpy0(filename,optarg2,sizeof(filename)); | |||
strncpy0(filename, optarg2, sizeof(filename)); | |||
break; | |||
case 'l': | |||
@@ -543,12 +507,12 @@ int main (int argc, char **argv) | |||
break; | |||
case 'v': | |||
strncpy0(voicename,optarg2,sizeof(voicename)); | |||
strncpy0(voicename, optarg2, sizeof(voicename)); | |||
break; | |||
case 'w': | |||
option_waveout = 1; | |||
strncpy0(wavefile,optarg2,sizeof(filename)); | |||
strncpy0(wavefile, optarg2, sizeof(filename)); | |||
break; | |||
case 'z': // remove pause from the end of a sentence | |||
@@ -561,34 +525,33 @@ int main (int argc, char **argv) | |||
case 0x105: // --stdout | |||
option_waveout = 1; | |||
strcpy(wavefile,"stdout"); | |||
strcpy(wavefile, "stdout"); | |||
break; | |||
case 0x101: // --compile-debug | |||
case 0x102: // --compile | |||
strncpy0(voicename,optarg2,sizeof(voicename)); | |||
strncpy0(voicename, optarg2, sizeof(voicename)); | |||
flag_compile = c; | |||
quiet = 1; | |||
break; | |||
case 0x103: // --punct | |||
option_punctuation = 1; | |||
if(optarg2 != NULL) | |||
{ | |||
if (optarg2 != NULL) { | |||
ix = 0; | |||
while((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++; | |||
while ((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++; | |||
option_punctlist[N_PUNCTLIST-1] = 0; | |||
option_punctuation = 2; | |||
} | |||
break; | |||
case 0x104: // --voices | |||
espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,0,data_path,0); | |||
DisplayVoices(stdout,optarg2); | |||
espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0); | |||
DisplayVoices(stdout, optarg2); | |||
exit(0); | |||
case 0x106: // -- split | |||
if(optarg2 == NULL) | |||
if (optarg2 == NULL) | |||
samples_split_seconds = 30 * 60; // default 30 minutes | |||
else | |||
samples_split_seconds = atoi(optarg2) * 60; | |||
@@ -599,9 +562,8 @@ int main (int argc, char **argv) | |||
break; | |||
case 0x108: // --phonout | |||
if((f_phonemes_out = fopen(optarg2,"w")) == NULL) | |||
{ | |||
fprintf(stderr,"Can't write to: %s\n",optarg2); | |||
if ((f_phonemes_out = fopen(optarg2, "w")) == NULL) { | |||
fprintf(stderr, "Can't write to: %s\n", optarg2); | |||
} | |||
break; | |||
@@ -611,10 +573,9 @@ int main (int argc, char **argv) | |||
case 0x10a: // --ipa | |||
phoneme_options |= espeakPHONEMES_IPA; | |||
if(optarg2 != NULL) | |||
{ | |||
if (optarg2 != NULL) { | |||
// deprecated and obsolete | |||
switch(atoi(optarg2)) | |||
switch (atoi(optarg2)) | |||
{ | |||
case 1: | |||
phonemes_separator = '_'; | |||
@@ -638,36 +599,36 @@ int main (int argc, char **argv) | |||
case 0x10c: // --sep | |||
phoneme_options |= espeakPHONEMES_SHOW; | |||
if(optarg2 == 0) | |||
if (optarg2 == 0) | |||
phonemes_separator = ' '; | |||
else | |||
utf8_in(&phonemes_separator, optarg2); | |||
if(phonemes_separator == 'z') | |||
if (phonemes_separator == 'z') | |||
phonemes_separator = 0x200c; // ZWNJ | |||
break; | |||
case 0x10d: // --tie | |||
phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE); | |||
if(optarg2 == 0) | |||
if (optarg2 == 0) | |||
phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
else | |||
utf8_in(&phonemes_separator, optarg2); | |||
if(phonemes_separator == 'z') | |||
if (phonemes_separator == 'z') | |||
phonemes_separator = 0x200d; // ZWJ | |||
break; | |||
case 0x10e: // --compile-mbrola | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0); | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0); | |||
espeak_ng_CompileMbrolaVoice(optarg2, stdout); | |||
exit(0); | |||
case 0x10f: // --compile-intonations | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,espeakINITIALIZE_PATH_ONLY); | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY); | |||
espeak_ng_CompileIntonation(stdout); | |||
exit(0); | |||
case 0x110: // --compile-phonemes | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,espeakINITIALIZE_PATH_ONLY); | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, espeakINITIALIZE_PATH_ONLY); | |||
espeak_ng_CompilePhonemeData(22050, stdout); | |||
exit(0); | |||
@@ -677,167 +638,135 @@ int main (int argc, char **argv) | |||
} | |||
if(option_waveout || quiet) | |||
{ | |||
if (option_waveout || quiet) { | |||
// writing to a file (or no output), we can use synchronous mode | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,0,data_path,0); | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0); | |||
samples_split = samplerate * samples_split_seconds; | |||
espeak_SetSynthCallback(SynthCallback); | |||
if(samples_split) | |||
{ | |||
if (samples_split) { | |||
char *extn; | |||
extn = strrchr(wavefile,'.'); | |||
if((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) | |||
{ | |||
strcpy(filetype,extn); | |||
extn = strrchr(wavefile, '.'); | |||
if ((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) { | |||
strcpy(filetype, extn); | |||
*extn = 0; | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
// play the sound output | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0); | |||
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0); | |||
} | |||
if(voicename[0] == 0) | |||
strcpy(voicename,"default"); | |||
if (voicename[0] == 0) | |||
strcpy(voicename, "default"); | |||
if(espeak_SetVoiceByName(voicename) != EE_OK) | |||
{ | |||
memset(&voice_select,0,sizeof(voice_select)); | |||
if (espeak_SetVoiceByName(voicename) != EE_OK) { | |||
memset(&voice_select, 0, sizeof(voice_select)); | |||
voice_select.languages = voicename; | |||
if(espeak_SetVoiceByProperties(&voice_select) != EE_OK) | |||
{ | |||
fprintf(stderr,"%svoice '%s'\n",err_load,voicename); | |||
if (espeak_SetVoiceByProperties(&voice_select) != EE_OK) { | |||
fprintf(stderr, "%svoice '%s'\n", err_load, voicename); | |||
exit(2); | |||
} | |||
} | |||
if(flag_compile) | |||
{ | |||
if (flag_compile) { | |||
// This must be done after the voice is set | |||
espeak_CompileDictionary("", stderr, flag_compile & 0x1); | |||
exit(0); | |||
} | |||
// set any non-default values of parameters. This must be done after espeak_Initialize() | |||
if(speed > 0) | |||
espeak_SetParameter(espeakRATE,speed,0); | |||
if(volume >= 0) | |||
espeak_SetParameter(espeakVOLUME,volume,0); | |||
if(pitch >= 0) | |||
espeak_SetParameter(espeakPITCH,pitch,0); | |||
if(option_capitals >= 0) | |||
espeak_SetParameter(espeakCAPITALS,option_capitals,0); | |||
if(option_punctuation >= 0) | |||
espeak_SetParameter(espeakPUNCTUATION,option_punctuation,0); | |||
if(wordgap >= 0) | |||
espeak_SetParameter(espeakWORDGAP,wordgap,0); | |||
if(option_linelength > 0) | |||
espeak_SetParameter(espeakLINELENGTH,option_linelength,0); | |||
if(option_punctuation == 2) | |||
if (speed > 0) | |||
espeak_SetParameter(espeakRATE, speed, 0); | |||
if (volume >= 0) | |||
espeak_SetParameter(espeakVOLUME, volume, 0); | |||
if (pitch >= 0) | |||
espeak_SetParameter(espeakPITCH, pitch, 0); | |||
if (option_capitals >= 0) | |||
espeak_SetParameter(espeakCAPITALS, option_capitals, 0); | |||
if (option_punctuation >= 0) | |||
espeak_SetParameter(espeakPUNCTUATION, option_punctuation, 0); | |||
if (wordgap >= 0) | |||
espeak_SetParameter(espeakWORDGAP, wordgap, 0); | |||
if (option_linelength > 0) | |||
espeak_SetParameter(espeakLINELENGTH, option_linelength, 0); | |||
if (option_punctuation == 2) | |||
espeak_SetPunctuationList(option_punctlist); | |||
espeak_SetPhonemeTrace(phoneme_options | (phonemes_separator << 8), f_phonemes_out); | |||
if(filename[0]==0) | |||
{ | |||
if((optind < argc) && (flag_stdin == 0)) | |||
{ | |||
if (filename[0] == 0) { | |||
if ((optind < argc) && (flag_stdin == 0)) { | |||
// there's a non-option parameter, and no -f or --stdin | |||
// use it as text | |||
p_text = argv[optind]; | |||
} | |||
else | |||
{ | |||
} else { | |||
f_text = stdin; | |||
if(flag_stdin == 0) | |||
{ | |||
if (flag_stdin == 0) { | |||
flag_stdin = 2; | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
filesize = GetFileLength(filename); | |||
f_text = fopen(filename,"r"); | |||
f_text = fopen(filename, "r"); | |||
} | |||
if((f_text == NULL) && (p_text == NULL)) | |||
{ | |||
fprintf(stderr,"%sfile '%s'\n",err_load,filename); | |||
if ((f_text == NULL) && (p_text == NULL)) { | |||
fprintf(stderr, "%sfile '%s'\n", err_load, filename); | |||
exit(1); | |||
} | |||
if(p_text != NULL) | |||
{ | |||
if (p_text != NULL) { | |||
int size; | |||
size = strlen(p_text); | |||
espeak_Synth(p_text,size+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL); | |||
} | |||
else | |||
if(flag_stdin) | |||
{ | |||
espeak_Synth(p_text, size+1, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL); | |||
} else if (flag_stdin) { | |||
int max = 1000; | |||
p_text = (char *)malloc(max); | |||
if(flag_stdin == 2) | |||
{ | |||
if (flag_stdin == 2) { | |||
// line by line input on stdin | |||
while(fgets(p_text,max,stdin) != NULL) | |||
{ | |||
while (fgets(p_text, max, stdin) != NULL) { | |||
p_text[max-1] = 0; | |||
espeak_Synth(p_text,max,0,POS_CHARACTER,0,synth_flags,NULL,NULL); | |||
espeak_Synth(p_text, max, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL); | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
// bulk input on stdin | |||
ix = 0; | |||
while(!feof(stdin)) | |||
{ | |||
while (!feof(stdin)) { | |||
p_text[ix++] = fgetc(stdin); | |||
if(ix >= (max-1)) | |||
{ | |||
if (ix >= (max-1)) { | |||
max += 1000; | |||
p_text = (char *)realloc(p_text,max); | |||
p_text = (char *)realloc(p_text, max); | |||
} | |||
} | |||
if(ix > 0) | |||
{ | |||
if (ix > 0) { | |||
p_text[ix-1] = 0; | |||
espeak_Synth(p_text,ix+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL); | |||
espeak_Synth(p_text, ix+1, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL); | |||
} | |||
} | |||
} | |||
else | |||
if(f_text != NULL) | |||
{ | |||
if((p_text = (char *)malloc(filesize+1)) == NULL) | |||
{ | |||
fprintf(stderr,"Failed to allocate memory %d bytes",filesize); | |||
} else if (f_text != NULL) { | |||
if ((p_text = (char *)malloc(filesize+1)) == NULL) { | |||
fprintf(stderr, "Failed to allocate memory %d bytes", filesize); | |||
exit(3); | |||
} | |||
fread(p_text,1,filesize,f_text); | |||
p_text[filesize]=0; | |||
espeak_Synth(p_text,filesize+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL); | |||
fread(p_text, 1, filesize, f_text); | |||
p_text[filesize] = 0; | |||
espeak_Synth(p_text, filesize+1, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL); | |||
fclose(f_text); | |||
} | |||
if(espeak_Synchronize() != EE_OK) | |||
{ | |||
if (espeak_Synchronize() != EE_OK) { | |||
fprintf(stderr, "espeak_Synchronize() failed, maybe error when opening output device\n"); | |||
exit(4); | |||
} | |||
if(f_phonemes_out != stdout) | |||
if (f_phonemes_out != stdout) | |||
fclose(f_phonemes_out); // needed for WinCE | |||
return(0); | |||
return (0); | |||
} |
@@ -48,17 +48,16 @@ static unsigned int StringToWord(const char *string) | |||
unsigned char c; | |||
unsigned int word; | |||
if(string==NULL) | |||
return(0); | |||
if (string == NULL) | |||
return (0); | |||
word = 0; | |||
for(ix=0; ix<4; ix++) | |||
{ | |||
if(string[ix]==0) break; | |||
for (ix = 0; ix < 4; ix++) { | |||
if (string[ix] == 0) break; | |||
c = string[ix]; | |||
word |= (c << (ix*8)); | |||
} | |||
return(word); | |||
return (word); | |||
} | |||
#pragma GCC visibility push(default) | |||
@@ -82,34 +81,29 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
int mbrola_ctrl = 20; // volume in 1/16 ths | |||
MBROLA_TAB data[N_PHONEME_TAB]; | |||
strcpy(buf,filepath); | |||
if((f_in = fopen(buf,"r")) == NULL) | |||
{ | |||
strcpy(buf, filepath); | |||
if ((f_in = fopen(buf, "r")) == NULL) { | |||
fprintf(log, "Can't read: %s\n", filepath); | |||
return ENE_READ_ERROR; | |||
} | |||
while(fgets(buf,sizeof(phoneme),f_in) != NULL) | |||
{ | |||
while (fgets(buf, sizeof(phoneme), f_in) != NULL) { | |||
buf[sizeof(phoneme)-1] = 0; | |||
if((p = strstr(buf,"//")) != NULL) | |||
if ((p = strstr(buf, "//")) != NULL) | |||
*p = 0; // truncate line at comment | |||
if(memcmp(buf,"volume",6)==0) | |||
{ | |||
if (memcmp(buf, "volume", 6) == 0) { | |||
mbrola_ctrl = atoi(&buf[6]); | |||
continue; | |||
} | |||
n = sscanf(buf,"%d %s %s %d %s %s",&control,phoneme,phoneme2,&percent,name1,name2); | |||
if(n >= 5) | |||
{ | |||
n = sscanf(buf, "%d %s %s %d %s %s", &control, phoneme, phoneme2, &percent, name1, name2); | |||
if (n >= 5) { | |||
data[count].name = StringToWord(phoneme); | |||
if(strcmp(phoneme2,"NULL")==0) | |||
if (strcmp(phoneme2, "NULL") == 0) | |||
data[count].next_phoneme = 0; | |||
else | |||
if(strcmp(phoneme2,"VWL")==0) | |||
else if (strcmp(phoneme2, "VWL") == 0) | |||
data[count].next_phoneme = 2; | |||
else | |||
data[count].next_phoneme = StringToWord(phoneme2); | |||
@@ -117,9 +111,9 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
data[count].mbr_name2 = 0; | |||
data[count].percent = percent; | |||
data[count].control = control; | |||
if(strcmp(name1,"NULL")!=0) | |||
if (strcmp(name1, "NULL") != 0) | |||
data[count].mbr_name = StringToWord(name1); | |||
if(n == 6) | |||
if (n == 6) | |||
data[count].mbr_name2 = StringToWord(name2); | |||
count++; | |||
@@ -127,10 +121,9 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
} | |||
fclose(f_in); | |||
strcpy(mbrola_voice,basename(filepath)); | |||
sprintf(buf,"%s/mbrola_ph/%s_phtrans",path_home,mbrola_voice); | |||
if((f_out = fopen(buf,"wb")) == NULL) | |||
{ | |||
strcpy(mbrola_voice, basename(filepath)); | |||
sprintf(buf, "%s/mbrola_ph/%s_phtrans", path_home, mbrola_voice); | |||
if ((f_out = fopen(buf, "wb")) == NULL) { | |||
fprintf(log, "Can't write to: %s\n", buf); | |||
return ENE_WRITE_ERROR; | |||
} | |||
@@ -139,8 +132,7 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log) | |||
Write4Bytes(f_out, mbrola_ctrl); | |||
pw_end = (int *)(&data[count+1]); | |||
for(pw = (int *)data; pw < pw_end; pw++) | |||
{ | |||
for (pw = (int *)data; pw < pw_end; pw++) { | |||
Write4Bytes(f_out, *pw); | |||
} | |||
fclose(f_out); |
@@ -27,29 +27,27 @@ | |||
#include <sys/time.h> | |||
#include <unistd.h> | |||
static FILE* fd_log=NULL; | |||
static const char* FILENAME="/tmp/espeak.log"; | |||
static FILE *fd_log = NULL; | |||
static const char *FILENAME = "/tmp/espeak.log"; | |||
void debug_init() | |||
{ | |||
if((fd_log = fopen(FILENAME,"a")) != NULL) | |||
if ((fd_log = fopen(FILENAME, "a")) != NULL) | |||
setvbuf(fd_log, NULL, _IONBF, 0); | |||
} | |||
void debug_enter(const char* text) | |||
void debug_enter(const char *text) | |||
{ | |||
struct timeval tv; | |||
gettimeofday(&tv, NULL); | |||
if (!fd_log) | |||
{ | |||
if (!fd_log) { | |||
debug_init(); | |||
} | |||
if (fd_log) | |||
{ | |||
fprintf(fd_log, "%03d.%03dms > ENTER %s\n",(int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text); | |||
if (fd_log) { | |||
fprintf(fd_log, "%03d.%03dms > ENTER %s\n", (int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text); | |||
} | |||
} | |||
@@ -58,30 +56,26 @@ void debug_show(const char *format, ...) | |||
{ | |||
va_list args; | |||
va_start(args, format); | |||
if (!fd_log) | |||
{ | |||
if (!fd_log) { | |||
debug_init(); | |||
} | |||
if (fd_log) | |||
{ | |||
if (fd_log) { | |||
vfprintf(fd_log, format, args); | |||
} | |||
va_end(args); | |||
} | |||
void debug_time(const char* text) | |||
void debug_time(const char *text) | |||
{ | |||
struct timeval tv; | |||
gettimeofday(&tv, NULL); | |||
if (!fd_log) | |||
{ | |||
if (!fd_log) { | |||
debug_init(); | |||
} | |||
if (fd_log) | |||
{ | |||
fprintf(fd_log, "%03d.%03dms > %s\n",(int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text); | |||
if (fd_log) { | |||
fprintf(fd_log, "%03d.%03dms > %s\n", (int)(tv.tv_sec%1000), (int)(tv.tv_usec/1000), text); | |||
} | |||
} | |||
@@ -27,18 +27,18 @@ extern "C" | |||
#ifdef DEBUG_ENABLED | |||
#define ENTER(text) debug_enter(text) | |||
#define SHOW(format,...) debug_show(format,__VA_ARGS__); | |||
#define SHOW(format, ...) debug_show(format, __VA_ARGS__); | |||
#define SHOW_TIME(text) debug_time(text); | |||
extern void debug_enter(const char* text); | |||
extern void debug_show(const char* format,...); | |||
extern void debug_time(const char* text); | |||
extern void debug_enter(const char *text); | |||
extern void debug_show(const char *format, ...); | |||
extern void debug_time(const char *text); | |||
#else | |||
#ifdef NO_VARIADIC_MACROS | |||
#define SHOW(format) // VC6 doesn't allow "..." | |||
#else | |||
#define SHOW(format,...) | |||
#define SHOW(format, ...) | |||
#endif | |||
#define SHOW_TIME(text) | |||
#define ENTER(text) |
@@ -27,24 +27,22 @@ | |||
#include "debug.h" | |||
static unsigned int my_current_text_id=0; | |||
static unsigned int my_current_text_id = 0; | |||
t_espeak_command* create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void* user_data) | |||
t_espeak_command *create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void *user_data) | |||
{ | |||
ENTER("create_espeak_text"); | |||
int a_error=1; | |||
void* a_text = NULL; | |||
t_espeak_text* data = NULL; | |||
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); | |||
int a_error = 1; | |||
void *a_text = NULL; | |||
t_espeak_text *data = NULL; | |||
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command)); | |||
if (!text || !size || !a_command) | |||
{ | |||
if (!text || !size || !a_command) { | |||
goto text_error; | |||
} | |||
a_text = malloc( size+1 ); | |||
if (!a_text) | |||
{ | |||
a_text = malloc(size+1); | |||
if (!a_text) { | |||
goto text_error; | |||
} | |||
memcpy(a_text, text, size); | |||
@@ -60,20 +58,17 @@ t_espeak_command* create_espeak_text(const void *text, size_t size, unsigned int | |||
data->end_position = end_position; | |||
data->flags = flags; | |||
data->user_data = user_data; | |||
a_error=0; | |||
a_error = 0; | |||
SHOW("ET_TEXT malloc text=%x, command=%x (uid=%d)\n", a_text, a_command, data->unique_identifier); | |||
text_error: | |||
if (a_error) | |||
{ | |||
if (a_text) | |||
{ | |||
free (a_text); | |||
if (a_error) { | |||
if (a_text) { | |||
free(a_text); | |||
} | |||
if (a_command) | |||
{ | |||
free (a_command); | |||
if (a_command) { | |||
free(a_command); | |||
} | |||
a_command = NULL; | |||
} | |||
@@ -83,15 +78,14 @@ text_error: | |||
return a_command; | |||
} | |||
t_espeak_command* create_espeak_terminated_msg(unsigned int unique_identifier, void* user_data) | |||
t_espeak_command *create_espeak_terminated_msg(unsigned int unique_identifier, void *user_data) | |||
{ | |||
ENTER("create_espeak_terminated_msg"); | |||
int a_error=1; | |||
t_espeak_terminated_msg* data = NULL; | |||
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); | |||
int a_error = 1; | |||
t_espeak_terminated_msg *data = NULL; | |||
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command)); | |||
if (!a_command) | |||
{ | |||
if (!a_command) { | |||
goto msg_error; | |||
} | |||
@@ -100,16 +94,14 @@ t_espeak_command* create_espeak_terminated_msg(unsigned int unique_identifier, v | |||
data = &(a_command->u.my_terminated_msg); | |||
data->unique_identifier = unique_identifier; | |||
data->user_data = user_data; | |||
a_error=0; | |||
a_error = 0; | |||
SHOW("ET_TERMINATED_MSG command=%x (uid=%d, user_data=0x%x)\n", a_command, unique_identifier, (int)user_data); | |||
msg_error: | |||
if (a_error) | |||
{ | |||
if (a_command) | |||
{ | |||
free (a_command); | |||
if (a_error) { | |||
if (a_command) { | |||
free(a_command); | |||
} | |||
a_command = NULL; | |||
} | |||
@@ -120,28 +112,26 @@ msg_error: | |||
} | |||
t_espeak_command* create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void* user_data) | |||
t_espeak_command *create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void *user_data) | |||
{ | |||
ENTER("create_espeak_mark"); | |||
int a_error=1; | |||
void* a_text = NULL; | |||
int a_error = 1; | |||
void *a_text = NULL; | |||
char *a_index_mark = NULL; | |||
t_espeak_mark* data = NULL; | |||
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); | |||
t_espeak_mark *data = NULL; | |||
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command)); | |||
if (!text || !size || !index_mark || !a_command) | |||
{ | |||
if (!text || !size || !index_mark || !a_command) { | |||
goto mark_error; | |||
} | |||
a_text = malloc( size ); | |||
if (!a_text) | |||
{ | |||
a_text = malloc(size); | |||
if (!a_text) { | |||
goto mark_error; | |||
} | |||
memcpy(a_text, text, size); | |||
a_index_mark = strdup( index_mark); | |||
a_index_mark = strdup(index_mark); | |||
a_command->type = ET_MARK; | |||
a_command->state = CS_UNDEFINED; | |||
@@ -153,23 +143,19 @@ t_espeak_command* create_espeak_mark(const void *text, size_t size, const char * | |||
data->end_position = end_position; | |||
data->flags = flags; | |||
data->user_data = user_data; | |||
a_error=0; | |||
a_error = 0; | |||
mark_error: | |||
if (a_error) | |||
{ | |||
if (a_text) | |||
{ | |||
free (a_text); | |||
if (a_error) { | |||
if (a_text) { | |||
free(a_text); | |||
} | |||
if (a_command) | |||
{ | |||
free (a_command); | |||
if (a_command) { | |||
free(a_command); | |||
} | |||
a_command = NULL; | |||
if (a_index_mark) | |||
{ | |||
free (a_index_mark); | |||
if (a_index_mark) { | |||
free(a_index_mark); | |||
} | |||
} | |||
@@ -178,14 +164,13 @@ mark_error: | |||
return a_command; | |||
} | |||
t_espeak_command* create_espeak_key(const char *key_name, void *user_data) | |||
t_espeak_command *create_espeak_key(const char *key_name, void *user_data) | |||
{ | |||
ENTER("create_espeak_key"); | |||
int a_error=1; | |||
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); | |||
int a_error = 1; | |||
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command)); | |||
if (!key_name || !a_command) | |||
{ | |||
if (!key_name || !a_command) { | |||
goto key_error; | |||
} | |||
@@ -193,15 +178,13 @@ t_espeak_command* create_espeak_key(const char *key_name, void *user_data) | |||
a_command->state = CS_UNDEFINED; | |||
a_command->u.my_key.user_data = user_data; | |||
a_command->u.my_key.unique_identifier = ++my_current_text_id; | |||
a_command->u.my_key.key_name = strdup( key_name); | |||
a_error=0; | |||
a_command->u.my_key.key_name = strdup(key_name); | |||
a_error = 0; | |||
key_error: | |||
if (a_error) | |||
{ | |||
if (a_command) | |||
{ | |||
free (a_command); | |||
if (a_error) { | |||
if (a_command) { | |||
free(a_command); | |||
} | |||
a_command = NULL; | |||
} | |||
@@ -211,13 +194,12 @@ key_error: | |||
return a_command; | |||
} | |||
t_espeak_command* create_espeak_char(wchar_t character, void* user_data) | |||
t_espeak_command *create_espeak_char(wchar_t character, void *user_data) | |||
{ | |||
ENTER("create_espeak_char"); | |||
int a_error=1; | |||
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); | |||
if (!a_command) | |||
{ | |||
int a_error = 1; | |||
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command)); | |||
if (!a_command) { | |||
goto char_error; | |||
} | |||
@@ -226,14 +208,12 @@ t_espeak_command* create_espeak_char(wchar_t character, void* user_data) | |||
a_command->u.my_char.user_data = user_data; | |||
a_command->u.my_char.unique_identifier = ++my_current_text_id; | |||
a_command->u.my_char.character = character; | |||
a_error=0; | |||
a_error = 0; | |||
char_error: | |||
if (a_error) | |||
{ | |||
if (a_command) | |||
{ | |||
free (a_command); | |||
if (a_error) { | |||
if (a_command) { | |||
free(a_command); | |||
} | |||
a_command = NULL; | |||
} | |||
@@ -243,14 +223,13 @@ char_error: | |||
return a_command; | |||
} | |||
t_espeak_command* create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative) | |||
t_espeak_command *create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative) | |||
{ | |||
ENTER("create_espeak_parameter"); | |||
int a_error=1; | |||
t_espeak_parameter* data = NULL; | |||
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); | |||
if (!a_command) | |||
{ | |||
int a_error = 1; | |||
t_espeak_parameter *data = NULL; | |||
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command)); | |||
if (!a_command) { | |||
goto param_error; | |||
} | |||
@@ -260,14 +239,12 @@ t_espeak_command* create_espeak_parameter(espeak_PARAMETER parameter, int value, | |||
data->parameter = parameter; | |||
data->value = value; | |||
data->relative = relative; | |||
a_error=0; | |||
a_error = 0; | |||
param_error: | |||
if (a_error) | |||
{ | |||
if (a_command) | |||
{ | |||
free (a_command); | |||
if (a_error) { | |||
if (a_command) { | |||
free(a_command); | |||
} | |||
a_command = NULL; | |||
} | |||
@@ -277,14 +254,13 @@ param_error: | |||
return a_command; | |||
} | |||
t_espeak_command* create_espeak_punctuation_list(const wchar_t *punctlist) | |||
t_espeak_command *create_espeak_punctuation_list(const wchar_t *punctlist) | |||
{ | |||
ENTER("create_espeak_punctuation_list"); | |||
int a_error=1; | |||
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); | |||
int a_error = 1; | |||
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command)); | |||
if (!punctlist || !a_command) | |||
{ | |||
if (!punctlist || !a_command) { | |||
goto list_error; | |||
} | |||
@@ -293,19 +269,17 @@ t_espeak_command* create_espeak_punctuation_list(const wchar_t *punctlist) | |||
{ | |||
size_t len = (wcslen(punctlist) + 1)*sizeof(wchar_t); | |||
wchar_t* a_list = (wchar_t*)malloc(len); | |||
wchar_t *a_list = (wchar_t *)malloc(len); | |||
memcpy(a_list, punctlist, len); | |||
a_command->u.my_punctuation_list = a_list; | |||
} | |||
a_error=0; | |||
a_error = 0; | |||
list_error: | |||
if (a_error) | |||
{ | |||
if (a_command) | |||
{ | |||
free (a_command); | |||
if (a_error) { | |||
if (a_command) { | |||
free(a_command); | |||
} | |||
a_command = NULL; | |||
} | |||
@@ -315,29 +289,26 @@ list_error: | |||
return a_command; | |||
} | |||
t_espeak_command* create_espeak_voice_name(const char *name) | |||
t_espeak_command *create_espeak_voice_name(const char *name) | |||
{ | |||
ENTER("create_espeak_voice_name"); | |||
int a_error=1; | |||
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); | |||
int a_error = 1; | |||
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command)); | |||
if (!name || !a_command) | |||
{ | |||
if (!name || !a_command) { | |||
goto name_error; | |||
} | |||
a_command->type = ET_VOICE_NAME; | |||
a_command->state = CS_UNDEFINED; | |||
a_command->u.my_voice_name = strdup( name); | |||
a_error=0; | |||
a_command->u.my_voice_name = strdup(name); | |||
a_error = 0; | |||
name_error: | |||
if (a_error) | |||
{ | |||
if (a_command) | |||
{ | |||
free (a_command); | |||
if (a_error) { | |||
if (a_command) { | |||
free(a_command); | |||
} | |||
a_command = NULL; | |||
} | |||
@@ -347,47 +318,41 @@ name_error: | |||
return a_command; | |||
} | |||
t_espeak_command* create_espeak_voice_spec(espeak_VOICE *voice) | |||
t_espeak_command *create_espeak_voice_spec(espeak_VOICE *voice) | |||
{ | |||
ENTER("create_espeak_voice_spec"); | |||
int a_error=1; | |||
t_espeak_command* a_command = (t_espeak_command*)malloc(sizeof(t_espeak_command)); | |||
int a_error = 1; | |||
t_espeak_command *a_command = (t_espeak_command *)malloc(sizeof(t_espeak_command)); | |||
if (!voice || !a_command) | |||
{ | |||
if (!voice || !a_command) { | |||
goto spec_error; | |||
} | |||
a_command->type = ET_VOICE_SPEC; | |||
a_command->state = CS_UNDEFINED; | |||
{ | |||
espeak_VOICE* data = &(a_command->u.my_voice_spec); | |||
espeak_VOICE *data = &(a_command->u.my_voice_spec); | |||
memcpy(data, voice, sizeof(espeak_VOICE)); | |||
if (voice->name) | |||
{ | |||
if (voice->name) { | |||
data->name = strdup(voice->name); | |||
} | |||
if (voice->languages) | |||
{ | |||
if (voice->languages) { | |||
data->languages = strdup(voice->languages); | |||
} | |||
if (voice->identifier) | |||
{ | |||
if (voice->identifier) { | |||
data->identifier = strdup(voice->identifier); | |||
} | |||
a_error=0; | |||
a_error = 0; | |||
} | |||
spec_error: | |||
if (a_error) | |||
{ | |||
if (a_command) | |||
{ | |||
free (a_command); | |||
if (a_error) { | |||
if (a_command) { | |||
free(a_command); | |||
} | |||
a_command = NULL; | |||
} | |||
@@ -397,30 +362,26 @@ spec_error: | |||
return a_command; | |||
} | |||
int delete_espeak_command( t_espeak_command* the_command) | |||
int delete_espeak_command(t_espeak_command *the_command) | |||
{ | |||
ENTER("delete_espeak_command"); | |||
int a_status = 0; | |||
if (the_command) | |||
{ | |||
switch(the_command->type) | |||
if (the_command) { | |||
switch (the_command->type) | |||
{ | |||
case ET_TEXT: | |||
if (the_command->u.my_text.text) | |||
{ | |||
if (the_command->u.my_text.text) { | |||
SHOW("delete_espeak_command > ET_TEXT free text=%x, command=%x, uid=%d\n", the_command->u.my_text.text, the_command, the_command->u.my_text.unique_identifier); | |||
free(the_command->u.my_text.text); | |||
} | |||
break; | |||
case ET_MARK: | |||
if (the_command->u.my_mark.text) | |||
{ | |||
if (the_command->u.my_mark.text) { | |||
free(the_command->u.my_mark.text); | |||
} | |||
if (the_command->u.my_mark.index_mark) | |||
{ | |||
free((void*)(the_command->u.my_mark.index_mark)); | |||
if (the_command->u.my_mark.index_mark) { | |||
free((void *)(the_command->u.my_mark.index_mark)); | |||
} | |||
break; | |||
@@ -430,20 +391,18 @@ int delete_espeak_command( t_espeak_command* the_command) | |||
// it must be processed here for informing the calling program | |||
// that its message is finished. | |||
// This can be important for cleaning the related user data. | |||
t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg); | |||
if (the_command->state == CS_PENDING) | |||
{ | |||
t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg); | |||
if (the_command->state == CS_PENDING) { | |||
the_command->state = CS_PROCESSED; | |||
SHOW("delete_espeak_command > ET_TERMINATED_MSG callback (command=0x%x, uid=%d) \n", the_command, data->unique_identifier); | |||
sync_espeak_terminated_msg( data->unique_identifier, data->user_data); | |||
sync_espeak_terminated_msg(data->unique_identifier, data->user_data); | |||
} | |||
} | |||
break; | |||
case ET_KEY: | |||
if (the_command->u.my_key.key_name) | |||
{ | |||
free((void*)(the_command->u.my_key.key_name)); | |||
if (the_command->u.my_key.key_name) { | |||
free((void *)(the_command->u.my_key.key_name)); | |||
} | |||
break; | |||
@@ -453,35 +412,30 @@ int delete_espeak_command( t_espeak_command* the_command) | |||
break; | |||
case ET_PUNCTUATION_LIST: | |||
if (the_command->u.my_punctuation_list) | |||
{ | |||
free((void*)(the_command->u.my_punctuation_list)); | |||
if (the_command->u.my_punctuation_list) { | |||
free((void *)(the_command->u.my_punctuation_list)); | |||
} | |||
break; | |||
case ET_VOICE_NAME: | |||
if (the_command->u.my_voice_name) | |||
{ | |||
free((void*)(the_command->u.my_voice_name)); | |||
if (the_command->u.my_voice_name) { | |||
free((void *)(the_command->u.my_voice_name)); | |||
} | |||
break; | |||
case ET_VOICE_SPEC: | |||
{ | |||
espeak_VOICE* data = &(the_command->u.my_voice_spec); | |||
espeak_VOICE *data = &(the_command->u.my_voice_spec); | |||
if (data->name) | |||
{ | |||
if (data->name) { | |||
free((void *)data->name); | |||
} | |||
if (data->languages) | |||
{ | |||
if (data->languages) { | |||
free((void *)data->languages); | |||
} | |||
if (data->identifier) | |||
{ | |||
if (data->identifier) { | |||
free((void *)data->identifier); | |||
} | |||
} | |||
@@ -497,49 +451,48 @@ int delete_espeak_command( t_espeak_command* the_command) | |||
return a_status; | |||
} | |||
void process_espeak_command( t_espeak_command* the_command) | |||
void process_espeak_command(t_espeak_command *the_command) | |||
{ | |||
ENTER("process_espeak_command"); | |||
SHOW("command=0x%x\n", the_command); | |||
if (the_command == NULL) | |||
{ | |||
if (the_command == NULL) { | |||
return; | |||
} | |||
the_command->state = CS_PROCESSED; | |||
switch(the_command->type) | |||
switch (the_command->type) | |||
{ | |||
case ET_TEXT: | |||
{ | |||
t_espeak_text* data = &(the_command->u.my_text); | |||
sync_espeak_Synth( data->unique_identifier, data->text, data->size, | |||
data->position, data->position_type, | |||
data->end_position, data->flags, data->user_data); | |||
t_espeak_text *data = &(the_command->u.my_text); | |||
sync_espeak_Synth(data->unique_identifier, data->text, data->size, | |||
data->position, data->position_type, | |||
data->end_position, data->flags, data->user_data); | |||
} | |||
break; | |||
case ET_MARK: | |||
{ | |||
t_espeak_mark* data = &(the_command->u.my_mark); | |||
sync_espeak_Synth_Mark( data->unique_identifier, data->text, data->size, | |||
data->index_mark, data->end_position, data->flags, | |||
data->user_data); | |||
t_espeak_mark *data = &(the_command->u.my_mark); | |||
sync_espeak_Synth_Mark(data->unique_identifier, data->text, data->size, | |||
data->index_mark, data->end_position, data->flags, | |||
data->user_data); | |||
} | |||
break; | |||
case ET_TERMINATED_MSG: | |||
{ | |||
t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg); | |||
sync_espeak_terminated_msg( data->unique_identifier, data->user_data); | |||
t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg); | |||
sync_espeak_terminated_msg(data->unique_identifier, data->user_data); | |||
} | |||
break; | |||
case ET_KEY: | |||
{ | |||
const char* data = the_command->u.my_key.key_name; | |||
const char *data = the_command->u.my_key.key_name; | |||
sync_espeak_Key(data); | |||
} | |||
break; | |||
@@ -547,34 +500,34 @@ void process_espeak_command( t_espeak_command* the_command) | |||
case ET_CHAR: | |||
{ | |||
const wchar_t data = the_command->u.my_char.character; | |||
sync_espeak_Char( data); | |||
sync_espeak_Char(data); | |||
} | |||
break; | |||
case ET_PARAMETER: | |||
{ | |||
t_espeak_parameter* data = &(the_command->u.my_param); | |||
SetParameter( data->parameter, data->value, data->relative); | |||
t_espeak_parameter *data = &(the_command->u.my_param); | |||
SetParameter(data->parameter, data->value, data->relative); | |||
} | |||
break; | |||
case ET_PUNCTUATION_LIST: | |||
{ | |||
const wchar_t* data = the_command->u.my_punctuation_list; | |||
sync_espeak_SetPunctuationList( data); | |||
const wchar_t *data = the_command->u.my_punctuation_list; | |||
sync_espeak_SetPunctuationList(data); | |||
} | |||
break; | |||
case ET_VOICE_NAME: | |||
{ | |||
const char* data = the_command->u.my_voice_name; | |||
SetVoiceByName( data); | |||
const char *data = the_command->u.my_voice_name; | |||
SetVoiceByName(data); | |||
} | |||
break; | |||
case ET_VOICE_SPEC: | |||
{ | |||
espeak_VOICE* data = &(the_command->u.my_voice_spec); | |||
espeak_VOICE *data = &(the_command->u.my_voice_spec); | |||
SetVoiceByProperties(data); | |||
} | |||
break; | |||
@@ -585,44 +538,43 @@ void process_espeak_command( t_espeak_command* the_command) | |||
} | |||
} | |||
void display_espeak_command( t_espeak_command* the_command) | |||
void display_espeak_command(t_espeak_command *the_command) | |||
{ | |||
ENTER("display_espeak_command"); | |||
#ifdef DEBUG_ENABLED | |||
if (the_command == NULL) | |||
{ | |||
SHOW("display_espeak_command > command=%s\n","NULL"); | |||
if (the_command == NULL) { | |||
SHOW("display_espeak_command > command=%s\n", "NULL"); | |||
return; | |||
} | |||
SHOW("display_espeak_command > state=%d\n",the_command->state); | |||
SHOW("display_espeak_command > state=%d\n", the_command->state); | |||
switch(the_command->type) | |||
switch (the_command->type) | |||
{ | |||
case ET_TEXT: | |||
{ | |||
t_espeak_text* data = &(the_command->u.my_text); | |||
SHOW("display_espeak_command > (0x%x) uid=%d, TEXT=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char*)data->text, (int)(data->user_data)); | |||
t_espeak_text *data = &(the_command->u.my_text); | |||
SHOW("display_espeak_command > (0x%x) uid=%d, TEXT=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char *)data->text, (int)(data->user_data)); | |||
} | |||
break; | |||
case ET_MARK: | |||
{ | |||
t_espeak_mark* data = &(the_command->u.my_mark); | |||
SHOW("display_espeak_command > (0x%x) uid=%d, MARK=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char*)data->text, (int)(data->user_data)); | |||
t_espeak_mark *data = &(the_command->u.my_mark); | |||
SHOW("display_espeak_command > (0x%x) uid=%d, MARK=%s, user_data=0x%x\n", the_command, data->unique_identifier, (char *)data->text, (int)(data->user_data)); | |||
} | |||
break; | |||
case ET_KEY: | |||
{ | |||
const char* data = the_command->u.my_key.key_name; | |||
const char *data = the_command->u.my_key.key_name; | |||
SHOW("display_espeak_command > (0x%x) KEY=%c\n", the_command, data); | |||
} | |||
break; | |||
case ET_TERMINATED_MSG: | |||
{ | |||
t_espeak_terminated_msg* data = &(the_command->u.my_terminated_msg); | |||
t_espeak_terminated_msg *data = &(the_command->u.my_terminated_msg); | |||
SHOW("display_espeak_command > (0x%x) TERMINATED_MSG uid=%d, user_data=0x%x, state=%d\n", | |||
the_command, data->unique_identifier, data->user_data, | |||
@@ -639,7 +591,7 @@ void display_espeak_command( t_espeak_command* the_command) | |||
case ET_PARAMETER: | |||
{ | |||
t_espeak_parameter* data = &(the_command->u.my_param); | |||
t_espeak_parameter *data = &(the_command->u.my_param); | |||
SHOW("display_espeak_command > (0x%x) PARAMETER=%d, value=%d, relative=%d\n", | |||
the_command, data->parameter, data->value, data->relative); | |||
} | |||
@@ -647,15 +599,15 @@ void display_espeak_command( t_espeak_command* the_command) | |||
case ET_PUNCTUATION_LIST: | |||
{ | |||
const wchar_t* data = the_command->u.my_punctuation_list; | |||
sync_espeak_SetPunctuationList( data); | |||
SHOW("display_espeak_command > (0x%x) PUNCTLIST=%s\n", the_command, (char*)data); | |||
const wchar_t *data = the_command->u.my_punctuation_list; | |||
sync_espeak_SetPunctuationList(data); | |||
SHOW("display_espeak_command > (0x%x) PUNCTLIST=%s\n", the_command, (char *)data); | |||
} | |||
break; | |||
case ET_VOICE_NAME: | |||
{ | |||
const char* data = the_command->u.my_voice_name; | |||
const char *data = the_command->u.my_voice_name; | |||
SHOW("display_espeak_command > (0x%x) VOICE_NAME=%s\n", the_command, data); | |||
} | |||
break; |
@@ -29,8 +29,7 @@ extern "C" | |||
{ | |||
#endif | |||
typedef enum | |||
{ | |||
typedef enum { | |||
ET_TEXT, | |||
ET_MARK, | |||
ET_KEY, | |||
@@ -42,78 +41,69 @@ typedef enum | |||
ET_TERMINATED_MSG | |||
} t_espeak_type; | |||
typedef struct | |||
{ | |||
typedef struct { | |||
unsigned int unique_identifier; | |||
void* text; | |||
void *text; | |||
size_t size; | |||
unsigned int position; | |||
espeak_POSITION_TYPE position_type; | |||
unsigned int end_position; | |||
unsigned int flags; | |||
void* user_data; | |||
void *user_data; | |||
} t_espeak_text; | |||
typedef struct | |||
{ | |||
typedef struct { | |||
unsigned int unique_identifier; | |||
void* text; | |||
void *text; | |||
size_t size; | |||
const char* index_mark; | |||
const char *index_mark; | |||
unsigned int end_position; | |||
unsigned int flags; | |||
void* user_data; | |||
void *user_data; | |||
} t_espeak_mark; | |||
typedef struct | |||
{ | |||
typedef struct { | |||
unsigned int unique_identifier; | |||
void* user_data; | |||
void *user_data; | |||
wchar_t character; | |||
} t_espeak_character; | |||
typedef struct | |||
{ | |||
typedef struct { | |||
unsigned int unique_identifier; | |||
void* user_data; | |||
const char* key_name; | |||
void *user_data; | |||
const char *key_name; | |||
} t_espeak_key; | |||
typedef struct | |||
{ | |||
typedef struct { | |||
unsigned int unique_identifier; | |||
void* user_data; | |||
void *user_data; | |||
} t_espeak_terminated_msg; | |||
typedef struct | |||
{ | |||
typedef struct { | |||
espeak_PARAMETER parameter; | |||
int value; | |||
int relative; | |||
} t_espeak_parameter; | |||
typedef enum | |||
{ | |||
typedef enum { | |||
CS_UNDEFINED, // The command has just been created | |||
CS_PENDING, // stored in the fifo | |||
CS_PROCESSED // processed | |||
} t_command_state; | |||
typedef struct | |||
{ | |||
typedef struct { | |||
t_espeak_type type; | |||
t_command_state state; | |||
union command | |||
{ | |||
union command { | |||
t_espeak_text my_text; | |||
t_espeak_mark my_mark; | |||
t_espeak_key my_key; | |||
t_espeak_character my_char; | |||
t_espeak_parameter my_param; | |||
const wchar_t* my_punctuation_list; | |||
const wchar_t *my_punctuation_list; | |||
const char *my_voice_name; | |||
espeak_VOICE my_voice_spec; | |||
t_espeak_terminated_msg my_terminated_msg; | |||
@@ -121,37 +111,37 @@ typedef struct | |||
} t_espeak_command; | |||
t_espeak_command* create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void* user_data); | |||
t_espeak_command *create_espeak_text(const void *text, size_t size, unsigned int position, espeak_POSITION_TYPE position_type, unsigned int end_position, unsigned int flags, void *user_data); | |||
t_espeak_command* create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void* user_data); | |||
t_espeak_command *create_espeak_mark(const void *text, size_t size, const char *index_mark, unsigned int end_position, unsigned int flags, void *user_data); | |||
t_espeak_command* create_espeak_terminated_msg(unsigned int unique_identifier, void* user_data); | |||
t_espeak_command *create_espeak_terminated_msg(unsigned int unique_identifier, void *user_data); | |||
t_espeak_command* create_espeak_key(const char *key_name, void *user_data); | |||
t_espeak_command *create_espeak_key(const char *key_name, void *user_data); | |||
t_espeak_command* create_espeak_char(wchar_t character, void *user_data); | |||
t_espeak_command *create_espeak_char(wchar_t character, void *user_data); | |||
t_espeak_command* create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative); | |||
t_espeak_command *create_espeak_parameter(espeak_PARAMETER parameter, int value, int relative); | |||
t_espeak_command* create_espeak_punctuation_list(const wchar_t *punctlist); | |||
t_espeak_command *create_espeak_punctuation_list(const wchar_t *punctlist); | |||
t_espeak_command* create_espeak_voice_name(const char *name); | |||
t_espeak_command *create_espeak_voice_name(const char *name); | |||
t_espeak_command* create_espeak_voice_spec(espeak_VOICE *voice_spec); | |||
t_espeak_command *create_espeak_voice_spec(espeak_VOICE *voice_spec); | |||
void process_espeak_command( t_espeak_command* the_command); | |||
void process_espeak_command(t_espeak_command *the_command); | |||
int delete_espeak_command( t_espeak_command* the_command); | |||
int delete_espeak_command(t_espeak_command *the_command); | |||
void display_espeak_command(t_espeak_command* the_command); | |||
void display_espeak_command(t_espeak_command *the_command); | |||
espeak_ERROR sync_espeak_Synth(unsigned int unique_identifier, const void *text, size_t size, | |||
unsigned int position, espeak_POSITION_TYPE position_type, | |||
unsigned int end_position, unsigned int flags, void* user_data); | |||
unsigned int end_position, unsigned int flags, void *user_data); | |||
espeak_ERROR sync_espeak_Synth_Mark(unsigned int unique_identifier, const void *text, size_t size, | |||
const char *index_mark, unsigned int end_position, | |||
unsigned int flags, void* user_data); | |||
unsigned int flags, void *user_data); | |||
void sync_espeak_Key(const char *key); | |||
void sync_espeak_Char(wchar_t character); | |||
void sync_espeak_SetPunctuationList(const wchar_t *punctlist); | |||
@@ -162,11 +152,11 @@ espeak_ERROR SetVoiceByName(const char *name); | |||
espeak_ERROR SetVoiceByProperties(espeak_VOICE *voice_selector); | |||
void SetParameter(int parameter, int value, int relative); | |||
int sync_espeak_terminated_msg(unsigned int unique_identifier, void* user_data); | |||
int sync_espeak_terminated_msg(unsigned int unique_identifier, void *user_data); | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
//> | |||
// > | |||
#endif |
@@ -47,29 +47,28 @@ static sem_t my_sem_stop_is_acknowledged; | |||
static pthread_t my_thread; | |||
static bool thread_inited; | |||
static t_espeak_callback* my_callback = NULL; | |||
static int my_event_is_running=0; | |||
static t_espeak_callback *my_callback = NULL; | |||
static int my_event_is_running = 0; | |||
enum {MIN_TIMEOUT_IN_MS=10, | |||
ACTIVITY_TIMEOUT=50, // in ms, check that the stream is active | |||
MAX_ACTIVITY_CHECK=6}; | |||
enum { MIN_TIMEOUT_IN_MS = 10, | |||
ACTIVITY_TIMEOUT = 50, // in ms, check that the stream is active | |||
MAX_ACTIVITY_CHECK = 6 }; | |||
typedef struct t_node | |||
{ | |||
void* data; | |||
typedef struct t_node { | |||
void *data; | |||
struct t_node *next; | |||
} node; | |||
static node* head=NULL; | |||
static node* tail=NULL; | |||
static int node_counter=0; | |||
static espeak_ERROR push(void* data); | |||
static void* pop(); | |||
static node *head = NULL; | |||
static node *tail = NULL; | |||
static int node_counter = 0; | |||
static espeak_ERROR push(void *data); | |||
static void *pop(); | |||
static void init(); | |||
static void* polling_thread(void*); | |||
static void *polling_thread(void *); | |||
void event_set_callback(t_espeak_callback* SynthCallback) | |||
void event_set_callback(t_espeak_callback *SynthCallback) | |||
{ | |||
my_callback = SynthCallback; | |||
} | |||
@@ -78,10 +77,10 @@ void event_init(void) | |||
{ | |||
ENTER("event_init"); | |||
my_event_is_running=0; | |||
my_event_is_running = 0; | |||
// security | |||
pthread_mutex_init( &my_mutex, (const pthread_mutexattr_t *)NULL); | |||
pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL); | |||
init(); | |||
assert(-1 != sem_init(&my_sem_start_is_required, 0, 0)); | |||
@@ -90,30 +89,26 @@ void event_init(void) | |||
pthread_attr_t a_attrib; | |||
if (pthread_attr_init (&a_attrib) == 0 | |||
&& pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) == 0) | |||
{ | |||
if (pthread_attr_init(&a_attrib) == 0 | |||
&& pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) == 0) { | |||
thread_inited = (0 == pthread_create(&my_thread, | |||
&a_attrib, | |||
polling_thread, | |||
(void*)NULL)); | |||
(void *)NULL)); | |||
} | |||
assert(thread_inited); | |||
pthread_attr_destroy(&a_attrib); | |||
} | |||
static void event_display(espeak_EVENT* event) | |||
static void event_display(espeak_EVENT *event) | |||
{ | |||
ENTER("event_display"); | |||
#ifdef DEBUG_ENABLED | |||
if (event==NULL) | |||
{ | |||
SHOW("event_display > event=%s\n","NULL"); | |||
} | |||
else | |||
{ | |||
static const char* label[] = { | |||
if (event == NULL) { | |||
SHOW("event_display > event=%s\n", "NULL"); | |||
} else { | |||
static const char *label[] = { | |||
"LIST_TERMINATED", | |||
"WORD", | |||
"SENTENCE", | |||
@@ -126,38 +121,35 @@ static void event_display(espeak_EVENT* event) | |||
"??" | |||
}; | |||
SHOW("event_display > event=0x%x\n",event); | |||
SHOW("event_display > type=%s\n",label[event->type]); | |||
SHOW("event_display > uid=%d\n",event->unique_identifier); | |||
SHOW("event_display > text_position=%d\n",event->text_position); | |||
SHOW("event_display > length=%d\n",event->length); | |||
SHOW("event_display > audio_position=%d\n",event->audio_position); | |||
SHOW("event_display > sample=%d\n",event->sample); | |||
SHOW("event_display > user_data=0x%x\n",event->user_data); | |||
SHOW("event_display > event=0x%x\n", event); | |||
SHOW("event_display > type=%s\n", label[event->type]); | |||
SHOW("event_display > uid=%d\n", event->unique_identifier); | |||
SHOW("event_display > text_position=%d\n", event->text_position); | |||
SHOW("event_display > length=%d\n", event->length); | |||
SHOW("event_display > audio_position=%d\n", event->audio_position); | |||
SHOW("event_display > sample=%d\n", event->sample); | |||
SHOW("event_display > user_data=0x%x\n", event->user_data); | |||
} | |||
#endif | |||
} | |||
static espeak_EVENT* event_copy (espeak_EVENT* event) | |||
static espeak_EVENT *event_copy(espeak_EVENT *event) | |||
{ | |||
ENTER("event_copy"); | |||
if (event==NULL) | |||
{ | |||
if (event == NULL) { | |||
return NULL; | |||
} | |||
espeak_EVENT* a_event=(espeak_EVENT*)malloc(sizeof(espeak_EVENT)); | |||
if (a_event) | |||
{ | |||
espeak_EVENT *a_event = (espeak_EVENT *)malloc(sizeof(espeak_EVENT)); | |||
if (a_event) { | |||
memcpy(a_event, event, sizeof(espeak_EVENT)); | |||
switch(event->type) | |||
switch (event->type) | |||
{ | |||
case espeakEVENT_MARK: | |||
case espeakEVENT_PLAY: | |||
if (event->id.name) | |||
{ | |||
if (event->id.name) { | |||
a_event->id.name = strdup(event->id.name); | |||
} | |||
break; | |||
@@ -181,21 +173,20 @@ static espeak_EVENT* event_copy (espeak_EVENT* event) | |||
// * Last call: event->type = espeakEVENT_MSG_TERMINATED | |||
// | |||
static void event_notify(espeak_EVENT* event) | |||
static void event_notify(espeak_EVENT *event) | |||
{ | |||
ENTER("event_notify"); | |||
static unsigned int a_old_uid = 0; | |||
espeak_EVENT events[2]; | |||
memcpy(&events[0],event,sizeof(espeak_EVENT)); // the event parameter in the callback function should be an array of eventd | |||
memcpy(&events[1],event,sizeof(espeak_EVENT)); | |||
memcpy(&events[0], event, sizeof(espeak_EVENT)); // the event parameter in the callback function should be an array of eventd | |||
memcpy(&events[1], event, sizeof(espeak_EVENT)); | |||
events[1].type = espeakEVENT_LIST_TERMINATED; // ... terminated by an event type=0 | |||
if (event && my_callback) | |||
{ | |||
if (event && my_callback) { | |||
event_display(event); | |||
switch(event->type) | |||
switch (event->type) | |||
{ | |||
case espeakEVENT_SENTENCE: | |||
my_callback(NULL, 0, events); | |||
@@ -208,8 +199,7 @@ static void event_notify(espeak_EVENT* event) | |||
case espeakEVENT_END: | |||
case espeakEVENT_PHONEME: | |||
{ | |||
if (a_old_uid != event->unique_identifier) | |||
{ | |||
if (a_old_uid != event->unique_identifier) { | |||
espeak_EVENT_TYPE a_new_type = events[0].type; | |||
events[0].type = espeakEVENT_SENTENCE; | |||
my_callback(NULL, 0, events); | |||
@@ -229,18 +219,17 @@ static void event_notify(espeak_EVENT* event) | |||
} | |||
} | |||
static int event_delete(espeak_EVENT* event) | |||
static int event_delete(espeak_EVENT *event) | |||
{ | |||
ENTER("event_delete"); | |||
event_display(event); | |||
if(event==NULL) | |||
{ | |||
if (event == NULL) { | |||
return 0; | |||
} | |||
switch(event->type) | |||
switch (event->type) | |||
{ | |||
case espeakEVENT_MSG_TERMINATED: | |||
event_notify(event); | |||
@@ -248,9 +237,8 @@ static int event_delete(espeak_EVENT* event) | |||
case espeakEVENT_MARK: | |||
case espeakEVENT_PLAY: | |||
if(event->id.name) | |||
{ | |||
free((void*)(event->id.name)); | |||
if (event->id.name) { | |||
free((void *)(event->id.name)); | |||
} | |||
break; | |||
@@ -262,27 +250,24 @@ static int event_delete(espeak_EVENT* event) | |||
return 1; | |||
} | |||
espeak_ERROR event_declare (espeak_EVENT* event) | |||
espeak_ERROR event_declare(espeak_EVENT *event) | |||
{ | |||
ENTER("event_declare"); | |||
event_display(event); | |||
if (!event) | |||
{ | |||
if (!event) { | |||
return EE_INTERNAL_ERROR; | |||
} | |||
int a_status = pthread_mutex_lock(&my_mutex); | |||
espeak_ERROR a_error = EE_OK; | |||
if (!a_status) | |||
{ | |||
if (!a_status) { | |||
SHOW_TIME("event_declare > locked\n"); | |||
espeak_EVENT* a_event = event_copy(event); | |||
espeak_EVENT *a_event = event_copy(event); | |||
a_error = push(a_event); | |||
if (a_error != EE_OK) | |||
{ | |||
if (a_error != EE_OK) { | |||
event_delete(a_event); | |||
} | |||
SHOW_TIME("event_declare > unlocking\n"); | |||
@@ -292,15 +277,14 @@ espeak_ERROR event_declare (espeak_EVENT* event) | |||
SHOW_TIME("event_declare > post my_sem_start_is_required\n"); | |||
sem_post(&my_sem_start_is_required); | |||
if (a_status != 0) | |||
{ | |||
if (a_status != 0) { | |||
a_error = EE_INTERNAL_ERROR; | |||
} | |||
return a_error; | |||
} | |||
espeak_ERROR event_clear_all () | |||
espeak_ERROR event_clear_all() | |||
{ | |||
ENTER("event_clear_all"); | |||
@@ -308,33 +292,26 @@ espeak_ERROR event_clear_all () | |||
int a_event_is_running = 0; | |||
SHOW_TIME("event_stop > locked\n"); | |||
if (a_status != 0) | |||
{ | |||
if (a_status != 0) { | |||
return EE_INTERNAL_ERROR; | |||
} | |||
if (my_event_is_running) | |||
{ | |||
if (my_event_is_running) { | |||
SHOW_TIME("event_stop > post my_sem_stop_is_required\n"); | |||
sem_post(&my_sem_stop_is_required); | |||
a_event_is_running = 1; | |||
} | |||
else | |||
{ | |||
} else { | |||
init(); // clear pending events | |||
} | |||
SHOW_TIME("event_stop > unlocking\n"); | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
if (a_status != 0) | |||
{ | |||
if (a_status != 0) { | |||
return EE_INTERNAL_ERROR; | |||
} | |||
if (a_event_is_running) | |||
{ | |||
if (a_event_is_running) { | |||
SHOW_TIME("event_stop > wait for my_sem_stop_is_acknowledged\n"); | |||
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) | |||
{ | |||
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) { | |||
continue; // Restart when interrupted by handler | |||
} | |||
SHOW_TIME("event_stop > get my_sem_stop_is_acknowledged\n"); | |||
@@ -349,12 +326,12 @@ static int sleep_until_timeout_or_stop_request(uint32_t time_in_ms) | |||
{ | |||
ENTER("sleep_until_timeout_or_stop_request"); | |||
int a_stop_is_required=0; | |||
int a_stop_is_required = 0; | |||
struct timespec ts; | |||
struct timeval tv; | |||
int err=0; | |||
int err = 0; | |||
clock_gettime2( &ts); | |||
clock_gettime2(&ts); | |||
#ifdef DEBUG_ENABLED | |||
struct timespec to; | |||
@@ -362,26 +339,24 @@ static int sleep_until_timeout_or_stop_request(uint32_t time_in_ms) | |||
to.tv_nsec = ts.tv_nsec; | |||
#endif | |||
add_time_in_ms( &ts, time_in_ms); | |||
add_time_in_ms(&ts, time_in_ms); | |||
SHOW("polling_thread > sleep_until_timeout_or_stop_request > start sem_timedwait from %d.%09lu to %d.%09lu \n", | |||
to.tv_sec, to.tv_nsec, | |||
ts.tv_sec, ts.tv_nsec); | |||
while ((err = sem_timedwait(&my_sem_stop_is_required, &ts)) == -1 | |||
&& errno == EINTR) | |||
{ | |||
&& errno == EINTR) { | |||
continue; // Restart when interrupted by handler | |||
} | |||
assert (gettimeofday(&tv, NULL) != -1); | |||
assert(gettimeofday(&tv, NULL) != -1); | |||
SHOW("polling_thread > sleep_until_timeout_or_stop_request > stop sem_timedwait %d.%09lu \n", | |||
tv.tv_sec, tv.tv_usec*1000); | |||
if (err == 0) | |||
{ | |||
SHOW("polling_thread > sleep_until_timeout_or_stop_request > %s\n","stop required!"); | |||
a_stop_is_required=1; // stop required | |||
if (err == 0) { | |||
SHOW("polling_thread > sleep_until_timeout_or_stop_request > %s\n", "stop required!"); | |||
a_stop_is_required = 1; // stop required | |||
} | |||
return a_stop_is_required; | |||
} | |||
@@ -390,22 +365,20 @@ static int sleep_until_timeout_or_stop_request(uint32_t time_in_ms) | |||
// If the stream is opened but the audio samples are not played, | |||
// a timeout is started. | |||
static int get_remaining_time(uint32_t sample, uint32_t* time_in_ms, int* stop_is_required) | |||
static int get_remaining_time(uint32_t sample, uint32_t *time_in_ms, int *stop_is_required) | |||
{ | |||
ENTER("get_remaining_time"); | |||
int err = 0; | |||
*stop_is_required = 0; | |||
int i=0; | |||
int i = 0; | |||
for (i=0; i < MAX_ACTIVITY_CHECK && (*stop_is_required == 0); i++) | |||
{ | |||
err = wave_get_remaining_time( sample, time_in_ms); | |||
for (i = 0; i < MAX_ACTIVITY_CHECK && (*stop_is_required == 0); i++) { | |||
err = wave_get_remaining_time(sample, time_in_ms); | |||
if (err || wave_is_busy(NULL) || (*time_in_ms == 0)) | |||
{ // if err, stream not available: quit | |||
// if wave is busy, time_in_ms is known: quit | |||
// if wave is not busy but remaining time == 0, event is reached: quit | |||
if (err || wave_is_busy(NULL) || (*time_in_ms == 0)) { // if err, stream not available: quit | |||
// if wave is busy, time_in_ms is known: quit | |||
// if wave is not busy but remaining time == 0, event is reached: quit | |||
break; | |||
} | |||
@@ -422,19 +395,18 @@ static int get_remaining_time(uint32_t sample, uint32_t* time_in_ms, int* stop_i | |||
// | |||
// wait for the close of stream | |||
*stop_is_required = sleep_until_timeout_or_stop_request( ACTIVITY_TIMEOUT); | |||
*stop_is_required = sleep_until_timeout_or_stop_request(ACTIVITY_TIMEOUT); | |||
} | |||
return err; | |||
} | |||
static void* polling_thread(void*p) | |||
static void *polling_thread(void *p) | |||
{ | |||
ENTER("polling_thread"); | |||
while(1) | |||
{ | |||
int a_stop_is_required=0; | |||
while (1) { | |||
int a_stop_is_required = 0; | |||
SHOW_TIME("polling_thread > locking\n"); | |||
int a_status = pthread_mutex_lock(&my_mutex); | |||
@@ -445,8 +417,7 @@ static void* polling_thread(void*p) | |||
SHOW_TIME("polling_thread > wait for my_sem_start_is_required\n"); | |||
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR) | |||
{ | |||
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR) { | |||
continue; // Restart when interrupted by handler | |||
} | |||
@@ -458,29 +429,25 @@ static void* polling_thread(void*p) | |||
pthread_mutex_unlock(&my_mutex); | |||
SHOW_TIME("polling_thread > unlocked\n"); | |||
a_stop_is_required=0; | |||
a_stop_is_required = 0; | |||
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); // NOTE: may set a_stop_is_required to -1 | |||
if ((a_status==0) && (a_stop_is_required > 0)) | |||
{ | |||
if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
SHOW("polling_thread > stop required (%d)\n", __LINE__); | |||
while(0 == sem_trywait(&my_sem_stop_is_required)) | |||
{ | |||
}; | |||
} | |||
else | |||
{ | |||
a_stop_is_required=0; | |||
while (0 == sem_trywait(&my_sem_stop_is_required)) { | |||
} | |||
; | |||
} else { | |||
a_stop_is_required = 0; | |||
} | |||
// In this loop, my_event_is_running = 1 | |||
while (head && (a_stop_is_required <= 0)) | |||
{ | |||
while (head && (a_stop_is_required <= 0)) { | |||
SHOW_TIME("polling_thread > check head\n"); | |||
while(0 == sem_trywait(&my_sem_start_is_required)) | |||
{ | |||
}; | |||
while (0 == sem_trywait(&my_sem_start_is_required)) { | |||
} | |||
; | |||
espeak_EVENT* event = (espeak_EVENT*)(head->data); | |||
espeak_EVENT *event = (espeak_EVENT *)(head->data); | |||
assert(event); | |||
uint32_t time_in_ms = 0; | |||
@@ -488,54 +455,43 @@ static void* polling_thread(void*p) | |||
int err = get_remaining_time((uint32_t)event->sample, | |||
&time_in_ms, | |||
&a_stop_is_required); | |||
if (a_stop_is_required > 0) | |||
{ | |||
if (a_stop_is_required > 0) { | |||
break; | |||
} | |||
else if (err != 0) | |||
{ | |||
} else if (err != 0) { | |||
// No available time: the event is deleted. | |||
SHOW("polling_thread > %s\n","audio device down"); | |||
SHOW("polling_thread > %s\n", "audio device down"); | |||
a_status = pthread_mutex_lock(&my_mutex); | |||
SHOW_TIME("polling_thread > locked\n"); | |||
event_delete( (espeak_EVENT*)pop()); | |||
event_delete((espeak_EVENT *)pop()); | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
SHOW_TIME("polling_thread > unlocked\n"); | |||
} | |||
else if (time_in_ms==0) | |||
{ // the event is already reached. | |||
if (my_callback) | |||
{ | |||
} else if (time_in_ms == 0) { // the event is already reached. | |||
if (my_callback) { | |||
event_notify(event); | |||
// the user_data (and the type) are cleaned to be sure | |||
// that MSG_TERMINATED is called twice (at delete time too). | |||
event->type=espeakEVENT_LIST_TERMINATED; | |||
event->user_data=NULL; | |||
event->type = espeakEVENT_LIST_TERMINATED; | |||
event->user_data = NULL; | |||
} | |||
a_status = pthread_mutex_lock(&my_mutex); | |||
SHOW_TIME("polling_thread > locked\n"); | |||
event_delete( (espeak_EVENT*)pop()); | |||
event_delete((espeak_EVENT *)pop()); | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
SHOW_TIME("polling_thread > unlocked\n"); | |||
a_stop_is_required=0; | |||
a_stop_is_required = 0; | |||
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); | |||
if ((a_status==0) && (a_stop_is_required > 0)) | |||
{ | |||
if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
SHOW("polling_thread > stop required (%d)\n", __LINE__); | |||
while(0 == sem_trywait(&my_sem_stop_is_required)) | |||
{ | |||
}; | |||
} | |||
else | |||
{ | |||
a_stop_is_required=0; | |||
while (0 == sem_trywait(&my_sem_stop_is_required)) { | |||
} | |||
; | |||
} else { | |||
a_stop_is_required = 0; | |||
} | |||
} | |||
else | |||
{ // The event will be notified soon: sleep until timeout or stop request | |||
} else { // The event will be notified soon: sleep until timeout or stop request | |||
a_stop_is_required = sleep_until_timeout_or_stop_request(time_in_ms); | |||
} | |||
} | |||
@@ -546,28 +502,23 @@ static void* polling_thread(void*p) | |||
SHOW_TIME("polling_thread > my_event_is_running = 0\n"); | |||
my_event_is_running = 0; | |||
if(a_stop_is_required <= 0) | |||
{ | |||
if (a_stop_is_required <= 0) { | |||
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); | |||
if ((a_status==0) && (a_stop_is_required > 0)) | |||
{ | |||
if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
SHOW("polling_thread > stop required (%d)\n", __LINE__); | |||
while(0 == sem_trywait(&my_sem_stop_is_required)) | |||
{ | |||
}; | |||
} | |||
else | |||
{ | |||
a_stop_is_required=0; | |||
while (0 == sem_trywait(&my_sem_stop_is_required)) { | |||
} | |||
; | |||
} else { | |||
a_stop_is_required = 0; | |||
} | |||
} | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
SHOW_TIME("polling_thread > unlocked\n"); | |||
if (a_stop_is_required > 0) | |||
{ | |||
SHOW("polling_thread > %s\n","stop required!"); | |||
if (a_stop_is_required > 0) { | |||
SHOW("polling_thread > %s\n", "stop required!"); | |||
// no mutex required since the stop command is synchronous | |||
// and waiting for my_sem_stop_is_acknowledged | |||
init(); | |||
@@ -581,39 +532,33 @@ static void* polling_thread(void*p) | |||
return NULL; | |||
} | |||
enum {MAX_NODE_COUNTER=1000}; | |||
enum { MAX_NODE_COUNTER = 1000 }; | |||
static espeak_ERROR push(void* the_data) | |||
static espeak_ERROR push(void *the_data) | |||
{ | |||
ENTER("event > push"); | |||
assert((!head && !tail) || (head && tail)); | |||
if (the_data == NULL) | |||
{ | |||
if (the_data == NULL) { | |||
SHOW("event > push > event=0x%x\n", NULL); | |||
return EE_INTERNAL_ERROR; | |||
} | |||
if (node_counter >= MAX_NODE_COUNTER) | |||
{ | |||
if (node_counter >= MAX_NODE_COUNTER) { | |||
SHOW("event > push > %s\n", "EE_BUFFER_FULL"); | |||
return EE_BUFFER_FULL; | |||
} | |||
node *n = (node *)malloc(sizeof(node)); | |||
if (n == NULL) | |||
{ | |||
if (n == NULL) { | |||
return EE_INTERNAL_ERROR; | |||
} | |||
if (head == NULL) | |||
{ | |||
if (head == NULL) { | |||
head = n; | |||
tail = n; | |||
} | |||
else | |||
{ | |||
} else { | |||
tail->next = n; | |||
tail = n; | |||
} | |||
@@ -622,30 +567,28 @@ static espeak_ERROR push(void* the_data) | |||
tail->data = the_data; | |||
node_counter++; | |||
SHOW("event > push > counter=%d (uid=%d)\n",node_counter,((espeak_EVENT*)the_data)->unique_identifier); | |||
SHOW("event > push > counter=%d (uid=%d)\n", node_counter, ((espeak_EVENT *)the_data)->unique_identifier); | |||
return EE_OK; | |||
} | |||
static void* pop() | |||
static void *pop() | |||
{ | |||
ENTER("event > pop"); | |||
void* the_data = NULL; | |||
void *the_data = NULL; | |||
assert((!head && !tail) || (head && tail)); | |||
if (head != NULL) | |||
{ | |||
node* n = head; | |||
if (head != NULL) { | |||
node *n = head; | |||
the_data = n->data; | |||
head = n->next; | |||
free(n); | |||
node_counter--; | |||
SHOW("event > pop > event=0x%x (counter=%d, uid=%d)\n",the_data, node_counter,((espeak_EVENT*)the_data)->unique_identifier); | |||
SHOW("event > pop > event=0x%x (counter=%d, uid=%d)\n", the_data, node_counter, ((espeak_EVENT *)the_data)->unique_identifier); | |||
} | |||
if(head == NULL) | |||
{ | |||
if (head == NULL) { | |||
tail = NULL; | |||
} | |||
@@ -657,8 +600,8 @@ static void init() | |||
{ | |||
ENTER("event > init"); | |||
while (event_delete( (espeak_EVENT*)pop() )) | |||
{} | |||
while (event_delete((espeak_EVENT *)pop())) { | |||
} | |||
node_counter = 0; | |||
} | |||
@@ -667,10 +610,9 @@ void event_terminate() | |||
{ | |||
ENTER("event_terminate"); | |||
if (thread_inited) | |||
{ | |||
if (thread_inited) { | |||
pthread_cancel(my_thread); | |||
pthread_join(my_thread,NULL); | |||
pthread_join(my_thread, NULL); | |||
pthread_mutex_destroy(&my_mutex); | |||
sem_destroy(&my_sem_start_is_required); | |||
sem_destroy(&my_sem_stop_is_required); |
@@ -51,13 +51,13 @@ extern "C" | |||
// the callback will be called when the event actually occurs. | |||
// The callback is detailled in speak_lib.h . | |||
void event_init(void); | |||
void event_set_callback(t_espeak_callback* cb); | |||
void event_set_callback(t_espeak_callback *cb); | |||
// Clear any pending event. | |||
// | |||
// Return: EE_OK: operation achieved | |||
// EE_INTERNAL_ERROR. | |||
espeak_ERROR event_clear_all (); | |||
espeak_ERROR event_clear_all(); | |||
// Declare a future event | |||
// | |||
@@ -65,7 +65,7 @@ espeak_ERROR event_clear_all (); | |||
// EE_BUFFER_FULL: the event can not be buffered; | |||
// you may try after a while to call the function again. | |||
// EE_INTERNAL_ERROR. | |||
espeak_ERROR event_declare (espeak_EVENT* event); | |||
espeak_ERROR event_declare(espeak_EVENT *event); | |||
// Terminate the event component. | |||
// Last function to be called. |
@@ -52,35 +52,34 @@ static pthread_t my_thread; | |||
static sem_t my_sem_start_is_required; | |||
static sem_t my_sem_stop_is_acknowledged; | |||
static void* say_thread(void*); | |||
static void *say_thread(void *); | |||
static espeak_ERROR push(t_espeak_command* the_command); | |||
static t_espeak_command* pop(); | |||
static espeak_ERROR push(t_espeak_command *the_command); | |||
static t_espeak_command *pop(); | |||
static void init(int process_parameters); | |||
static int node_counter=0; | |||
enum {MAX_NODE_COUNTER=400, | |||
INACTIVITY_TIMEOUT=50, // in ms, check that the stream is inactive | |||
MAX_INACTIVITY_CHECK=2}; | |||
static int node_counter = 0; | |||
enum { MAX_NODE_COUNTER = 400, | |||
INACTIVITY_TIMEOUT = 50, // in ms, check that the stream is inactive | |||
MAX_INACTIVITY_CHECK = 2 }; | |||
void fifo_init() | |||
{ | |||
ENTER("fifo_init"); | |||
// security | |||
pthread_mutex_init( &my_mutex, (const pthread_mutexattr_t *)NULL); | |||
pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL); | |||
init(0); | |||
assert(-1 != sem_init(&my_sem_start_is_required, 0, 0)); | |||
assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0)); | |||
pthread_attr_t a_attrib; | |||
if (pthread_attr_init (&a_attrib) | |||
if (pthread_attr_init(&a_attrib) | |||
|| pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) | |||
|| pthread_create( &my_thread, | |||
&a_attrib, | |||
say_thread, | |||
(void*)NULL)) | |||
{ | |||
|| pthread_create(&my_thread, | |||
&a_attrib, | |||
say_thread, | |||
(void *)NULL)) { | |||
assert(0); | |||
} | |||
@@ -88,44 +87,39 @@ void fifo_init() | |||
// leave once the thread is actually started | |||
SHOW_TIME("fifo > wait for my_sem_stop_is_acknowledged\n"); | |||
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) | |||
{ | |||
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) { | |||
continue; // Restart when interrupted by handler | |||
} | |||
SHOW_TIME("fifo > get my_sem_stop_is_acknowledged\n"); | |||
} | |||
espeak_ERROR fifo_add_command (t_espeak_command* the_command) | |||
espeak_ERROR fifo_add_command(t_espeak_command *the_command) | |||
{ | |||
ENTER("fifo_add_command"); | |||
int a_status = pthread_mutex_lock(&my_mutex); | |||
espeak_ERROR a_error = EE_OK; | |||
if (!a_status) | |||
{ | |||
if (!a_status) { | |||
SHOW_TIME("fifo_add_command > locked\n"); | |||
a_error = push(the_command); | |||
SHOW_TIME("fifo_add_command > unlocking\n"); | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
} | |||
if (!a_status && !my_command_is_running && (a_error == EE_OK)) | |||
{ | |||
if (!a_status && !my_command_is_running && (a_error == EE_OK)) { | |||
// quit when command is actually started | |||
// (for possible forthcoming 'end of command' checks) | |||
SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n"); | |||
sem_post(&my_sem_start_is_required); | |||
int val=1; | |||
while (val > 0) | |||
{ | |||
int val = 1; | |||
while (val > 0) { | |||
usleep(50000); // TBD: event? | |||
sem_getvalue(&my_sem_start_is_required, &val); | |||
} | |||
} | |||
if (a_status != 0) | |||
{ | |||
if (a_status != 0) { | |||
a_error = EE_INTERNAL_ERROR; | |||
} | |||
@@ -133,24 +127,20 @@ espeak_ERROR fifo_add_command (t_espeak_command* the_command) | |||
return a_error; | |||
} | |||
espeak_ERROR fifo_add_commands (t_espeak_command* command1, t_espeak_command* command2) | |||
espeak_ERROR fifo_add_commands(t_espeak_command *command1, t_espeak_command *command2) | |||
{ | |||
ENTER("fifo_add_command"); | |||
int a_status = pthread_mutex_lock(&my_mutex); | |||
espeak_ERROR a_error = EE_OK; | |||
if (!a_status) | |||
{ | |||
if (!a_status) { | |||
SHOW_TIME("fifo_add_commands > locked\n"); | |||
if (node_counter+1 >= MAX_NODE_COUNTER) | |||
{ | |||
if (node_counter+1 >= MAX_NODE_COUNTER) { | |||
SHOW("push > %s\n", "EE_BUFFER_FULL"); | |||
a_error = EE_BUFFER_FULL; | |||
} | |||
else | |||
{ | |||
} else { | |||
push(command1); | |||
push(command2); | |||
} | |||
@@ -158,22 +148,19 @@ espeak_ERROR fifo_add_commands (t_espeak_command* command1, t_espeak_command* co | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
} | |||
if (!a_status && !my_command_is_running && (a_error == EE_OK)) | |||
{ | |||
if (!a_status && !my_command_is_running && (a_error == EE_OK)) { | |||
// quit when one command is actually started | |||
// (for possible forthcoming 'end of command' checks) | |||
SHOW_TIME("fifo_add_command > post my_sem_start_is_required\n"); | |||
sem_post(&my_sem_start_is_required); | |||
int val=1; | |||
while (val > 0) | |||
{ | |||
int val = 1; | |||
while (val > 0) { | |||
usleep(50000); // TBD: event? | |||
sem_getvalue(&my_sem_start_is_required, &val); | |||
} | |||
} | |||
if (a_status != 0) | |||
{ | |||
if (a_status != 0) { | |||
a_error = EE_INTERNAL_ERROR; | |||
} | |||
@@ -181,36 +168,31 @@ espeak_ERROR fifo_add_commands (t_espeak_command* command1, t_espeak_command* co | |||
return a_error; | |||
} | |||
espeak_ERROR fifo_stop () | |||
espeak_ERROR fifo_stop() | |||
{ | |||
ENTER("fifo_stop"); | |||
int a_command_is_running = 0; | |||
int a_status = pthread_mutex_lock(&my_mutex); | |||
SHOW_TIME("fifo_stop > locked\n"); | |||
if (a_status != 0) | |||
{ | |||
if (a_status != 0) { | |||
return EE_INTERNAL_ERROR; | |||
} | |||
if (my_command_is_running) | |||
{ | |||
if (my_command_is_running) { | |||
a_command_is_running = 1; | |||
my_stop_is_required = 1; | |||
SHOW_TIME("fifo_stop > my_stop_is_required = 1\n"); | |||
} | |||
SHOW_TIME("fifo_stop > unlocking\n"); | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
if (a_status != 0) | |||
{ | |||
if (a_status != 0) { | |||
return EE_INTERNAL_ERROR; | |||
} | |||
if (a_command_is_running) | |||
{ | |||
if (a_command_is_running) { | |||
SHOW_TIME("fifo_stop > wait for my_sem_stop_is_acknowledged\n"); | |||
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) | |||
{ | |||
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) { | |||
continue; // Restart when interrupted by handler | |||
} | |||
SHOW_TIME("fifo_stop > get my_sem_stop_is_acknowledged\n"); | |||
@@ -223,16 +205,16 @@ espeak_ERROR fifo_stop () | |||
return EE_OK; | |||
} | |||
int fifo_is_busy () | |||
int fifo_is_busy() | |||
{ | |||
SHOW("fifo_is_busy > aResult = %d\n",my_command_is_running); | |||
SHOW("fifo_is_busy > aResult = %d\n", my_command_is_running); | |||
return my_command_is_running; | |||
} | |||
static int sleep_until_start_request_or_inactivity() | |||
{ | |||
SHOW_TIME("fifo > sleep_until_start_request_or_inactivity > ENTER"); | |||
int a_start_is_required=0; | |||
int a_start_is_required = 0; | |||
// Wait for the start request (my_sem_start_is_required). | |||
// Besides this, if the audio stream is still busy, | |||
@@ -240,23 +222,19 @@ static int sleep_until_start_request_or_inactivity() | |||
// The end of the stream is confirmed by several checks | |||
// for filtering underflow. | |||
// | |||
int i=0; | |||
while((i<= MAX_INACTIVITY_CHECK) && !a_start_is_required) | |||
{ | |||
if (wave_is_busy( NULL) ) | |||
{ | |||
int i = 0; | |||
while ((i <= MAX_INACTIVITY_CHECK) && !a_start_is_required) { | |||
if (wave_is_busy(NULL)) { | |||
i = 0; | |||
} | |||
else | |||
{ | |||
} else { | |||
i++; | |||
} | |||
int err=0; | |||
int err = 0; | |||
struct timespec ts; | |||
struct timeval tv; | |||
clock_gettime2( &ts); | |||
clock_gettime2(&ts); | |||
#ifdef DEBUG_ENABLED | |||
struct timespec to; | |||
@@ -264,24 +242,22 @@ static int sleep_until_start_request_or_inactivity() | |||
to.tv_nsec = ts.tv_nsec; | |||
#endif | |||
add_time_in_ms( &ts, INACTIVITY_TIMEOUT); | |||
add_time_in_ms(&ts, INACTIVITY_TIMEOUT); | |||
SHOW("fifo > sleep_until_start_request_or_inactivity > start sem_timedwait (start_is_required) from %d.%09lu to %d.%09lu \n", | |||
to.tv_sec, to.tv_nsec, | |||
ts.tv_sec, ts.tv_nsec); | |||
while ((err = sem_timedwait(&my_sem_start_is_required, &ts)) == -1 | |||
&& errno == EINTR) | |||
{ | |||
&& errno == EINTR) { | |||
continue; | |||
} | |||
assert (gettimeofday(&tv, NULL) != -1); | |||
assert(gettimeofday(&tv, NULL) != -1); | |||
SHOW("fifo > sleep_until_start_request_or_inactivity > stop sem_timedwait (start_is_required, err=%d) %d.%09lu \n", err, | |||
tv.tv_sec, tv.tv_usec*1000); | |||
if (err==0) | |||
{ | |||
if (err == 0) { | |||
a_start_is_required = 1; | |||
} | |||
} | |||
@@ -298,38 +274,35 @@ static void close_stream() | |||
// my_stop_is_required = 1; | |||
int a_status = pthread_mutex_lock(&my_mutex); | |||
assert (!a_status); | |||
assert(!a_status); | |||
int a_stop_is_required = my_stop_is_required; | |||
if (!a_stop_is_required) | |||
{ | |||
if (!a_stop_is_required) { | |||
my_command_is_running = 1; | |||
} | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
if (!a_stop_is_required) | |||
{ | |||
if (!a_stop_is_required) { | |||
wave_close(NULL); | |||
int a_status = pthread_mutex_lock(&my_mutex); | |||
assert (!a_status); | |||
assert(!a_status); | |||
my_command_is_running = 0; | |||
a_stop_is_required = my_stop_is_required; | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
if (a_stop_is_required) | |||
{ | |||
if (a_stop_is_required) { | |||
// acknowledge the stop request | |||
SHOW_TIME("fifo > close_stream > post my_sem_stop_is_acknowledged\n"); | |||
int a_status = sem_post(&my_sem_stop_is_acknowledged); | |||
assert( a_status != -1); | |||
assert(a_status != -1); | |||
} | |||
} | |||
SHOW_TIME("fifo > close_stream > LEAVE\n"); | |||
} | |||
static void* say_thread(void*p) | |||
static void *say_thread(void *p) | |||
{ | |||
ENTER("say_thread"); | |||
@@ -338,27 +311,22 @@ static void* say_thread(void*p) | |||
// announce that thread is started | |||
sem_post(&my_sem_stop_is_acknowledged); | |||
int look_for_inactivity=0; | |||
int look_for_inactivity = 0; | |||
while(1) | |||
{ | |||
while (1) { | |||
SHOW_TIME("say_thread > wait for my_sem_start_is_required\n"); | |||
int a_start_is_required = 0; | |||
if (look_for_inactivity) | |||
{ | |||
if (look_for_inactivity) { | |||
a_start_is_required = sleep_until_start_request_or_inactivity(); | |||
if (!a_start_is_required) | |||
{ | |||
if (!a_start_is_required) { | |||
close_stream(); | |||
} | |||
} | |||
look_for_inactivity = 1; | |||
if (!a_start_is_required) | |||
{ | |||
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR) | |||
{ | |||
if (!a_start_is_required) { | |||
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR) { | |||
continue; // Restart when interrupted by handler | |||
} | |||
} | |||
@@ -367,62 +335,55 @@ static void* say_thread(void*p) | |||
SHOW_TIME("say_thread > my_command_is_running = 1\n"); | |||
my_command_is_running = 1; | |||
while( my_command_is_running) | |||
{ | |||
while (my_command_is_running) { | |||
SHOW_TIME("say_thread > locking\n"); | |||
int a_status = pthread_mutex_lock(&my_mutex); | |||
assert (!a_status); | |||
t_espeak_command* a_command = (t_espeak_command*)pop(); | |||
assert(!a_status); | |||
t_espeak_command *a_command = (t_espeak_command *)pop(); | |||
if (a_command == NULL) | |||
{ | |||
if (a_command == NULL) { | |||
SHOW_TIME("say_thread > text empty (talking=0) \n"); | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
SHOW_TIME("say_thread > unlocked\n"); | |||
SHOW_TIME("say_thread > my_command_is_running = 0\n"); | |||
my_command_is_running = 0; | |||
} | |||
else | |||
{ | |||
} else { | |||
display_espeak_command(a_command); | |||
// purge start semaphore | |||
SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); | |||
while(0 == sem_trywait(&my_sem_start_is_required)) | |||
{ | |||
}; | |||
while (0 == sem_trywait(&my_sem_start_is_required)) { | |||
} | |||
; | |||
if (my_stop_is_required) | |||
{ | |||
if (my_stop_is_required) { | |||
SHOW_TIME("say_thread > my_command_is_running = 0\n"); | |||
my_command_is_running = 0; | |||
} | |||
SHOW_TIME("say_thread > unlocking\n"); | |||
a_status = pthread_mutex_unlock(&my_mutex); | |||
if (my_command_is_running) | |||
{ | |||
if (my_command_is_running) { | |||
process_espeak_command(a_command); | |||
} | |||
delete_espeak_command(a_command); | |||
} | |||
} | |||
if (my_stop_is_required) | |||
{ | |||
if (my_stop_is_required) { | |||
// no mutex required since the stop command is synchronous | |||
// and waiting for my_sem_stop_is_acknowledged | |||
init(1); | |||
// purge start semaphore | |||
SHOW_TIME("say_thread > purge my_sem_start_is_required\n"); | |||
while(0==sem_trywait(&my_sem_start_is_required)) | |||
{ | |||
}; | |||
while (0 == sem_trywait(&my_sem_start_is_required)) { | |||
} | |||
; | |||
// acknowledge the stop request | |||
SHOW_TIME("say_thread > post my_sem_stop_is_acknowledged\n"); | |||
int a_status = sem_post(&my_sem_stop_is_acknowledged); | |||
assert( a_status != -1); | |||
assert(a_status != -1); | |||
} | |||
// and wait for the next start | |||
SHOW_TIME("say_thread > wait for my_sem_start_is_required\n"); | |||
@@ -433,50 +394,43 @@ static void* say_thread(void*p) | |||
int fifo_is_command_enabled() | |||
{ | |||
SHOW("ENTER fifo_is_command_enabled=%d\n",(int)(0 == my_stop_is_required)); | |||
SHOW("ENTER fifo_is_command_enabled=%d\n", (int)(0 == my_stop_is_required)); | |||
return (0 == my_stop_is_required); | |||
} | |||
typedef struct t_node | |||
{ | |||
t_espeak_command* data; | |||
typedef struct t_node { | |||
t_espeak_command *data; | |||
struct t_node *next; | |||
} node; | |||
static node* head=NULL; | |||
static node* tail=NULL; | |||
static node *head = NULL; | |||
static node *tail = NULL; | |||
static espeak_ERROR push(t_espeak_command* the_command) | |||
static espeak_ERROR push(t_espeak_command *the_command) | |||
{ | |||
ENTER("fifo > push"); | |||
assert((!head && !tail) || (head && tail)); | |||
if (the_command == NULL) | |||
{ | |||
if (the_command == NULL) { | |||
SHOW("push > command=0x%x\n", NULL); | |||
return EE_INTERNAL_ERROR; | |||
} | |||
if (node_counter >= MAX_NODE_COUNTER) | |||
{ | |||
if (node_counter >= MAX_NODE_COUNTER) { | |||
SHOW("push > %s\n", "EE_BUFFER_FULL"); | |||
return EE_BUFFER_FULL; | |||
} | |||
node *n = (node *)malloc(sizeof(node)); | |||
if (n == NULL) | |||
{ | |||
if (n == NULL) { | |||
return EE_INTERNAL_ERROR; | |||
} | |||
if (head == NULL) | |||
{ | |||
if (head == NULL) { | |||
head = n; | |||
tail = n; | |||
} | |||
else | |||
{ | |||
} else { | |||
tail->next = n; | |||
tail = n; | |||
} | |||
@@ -485,7 +439,7 @@ static espeak_ERROR push(t_espeak_command* the_command) | |||
tail->data = the_command; | |||
node_counter++; | |||
SHOW("push > counter=%d\n",node_counter); | |||
SHOW("push > counter=%d\n", node_counter); | |||
the_command->state = CS_PENDING; | |||
display_espeak_command(the_command); | |||
@@ -493,25 +447,23 @@ static espeak_ERROR push(t_espeak_command* the_command) | |||
return EE_OK; | |||
} | |||
static t_espeak_command* pop() | |||
static t_espeak_command *pop() | |||
{ | |||
ENTER("fifo > pop"); | |||
t_espeak_command* the_command = NULL; | |||
t_espeak_command *the_command = NULL; | |||
assert((!head && !tail) || (head && tail)); | |||
if (head != NULL) | |||
{ | |||
node* n = head; | |||
if (head != NULL) { | |||
node *n = head; | |||
the_command = n->data; | |||
head = n->next; | |||
free(n); | |||
node_counter--; | |||
SHOW("pop > command=0x%x (counter=%d)\n",the_command, node_counter); | |||
SHOW("pop > command=0x%x (counter=%d)\n", the_command, node_counter); | |||
} | |||
if(head == NULL) | |||
{ | |||
if (head == NULL) { | |||
tail = NULL; | |||
} | |||
@@ -526,8 +478,7 @@ static void init(int process_parameters) | |||
ENTER("fifo > init"); | |||
c = pop(); | |||
while (c != NULL) { | |||
if (process_parameters && (c->type == ET_PARAMETER || c->type == ET_VOICE_NAME || c->type == ET_VOICE_SPEC)) | |||
{ | |||
if (process_parameters && (c->type == ET_PARAMETER || c->type == ET_VOICE_NAME || c->type == ET_VOICE_SPEC)) { | |||
process_espeak_command(c); | |||
} | |||
delete_espeak_command(c); | |||
@@ -541,7 +492,7 @@ void fifo_terminate() | |||
ENTER("fifo_terminate"); | |||
pthread_cancel(my_thread); | |||
pthread_join(my_thread,NULL); | |||
pthread_join(my_thread, NULL); | |||
pthread_mutex_destroy(&my_mutex); | |||
sem_destroy(&my_sem_start_is_required); | |||
sem_destroy(&my_sem_stop_is_acknowledged); |
@@ -43,7 +43,7 @@ void fifo_init(); | |||
// EE_BUFFER_FULL: the command can not be buffered; | |||
// you may try after a while to call the function again. | |||
// EE_INTERNAL_ERROR. | |||
espeak_ERROR fifo_add_command (t_espeak_command* c); | |||
espeak_ERROR fifo_add_command(t_espeak_command *c); | |||
// Add two espeak commands in a single transaction. | |||
// | |||
@@ -54,16 +54,16 @@ espeak_ERROR fifo_add_command (t_espeak_command* c); | |||
// EE_BUFFER_FULL: at least one command can not be buffered; | |||
// you may try after a while to call the function again. | |||
// EE_INTERNAL_ERROR. | |||
espeak_ERROR fifo_add_commands (t_espeak_command* c1, t_espeak_command* c2); | |||
espeak_ERROR fifo_add_commands(t_espeak_command *c1, t_espeak_command *c2); | |||
// The current running command must be stopped and the awaiting commands are cleared. | |||
// Return: EE_OK: operation achieved | |||
// EE_INTERNAL_ERROR. | |||
espeak_ERROR fifo_stop (); | |||
espeak_ERROR fifo_stop(); | |||
// Is there a running command? | |||
// Returns 1 if yes; 0 otherwise. | |||
int fifo_is_busy (); | |||
int fifo_is_busy(); | |||
// Terminate the fifo component. | |||
// Last function to be called. |
@@ -43,8 +43,7 @@ typedef long flag; | |||
/* Resonator Structure */ | |||
typedef struct | |||
{ | |||
typedef struct { | |||
double a; | |||
double b; | |||
double c; | |||
@@ -57,8 +56,7 @@ typedef struct | |||
/* Structure for Klatt Globals */ | |||
typedef struct | |||
{ | |||
typedef struct { | |||
flag synthesis_model; /* cascade-parallel or all-parallel */ | |||
flag outsl; /* Output waveform selector */ | |||
long samrate; /* Number of output samples per second */ | |||
@@ -136,8 +134,7 @@ typedef struct | |||
#define F_NP 9 // nasal pole formant | |||
typedef struct | |||
{ | |||
typedef struct { | |||
int F0hz10; /* Voicing fund freq in Hz */ | |||
int AVdb; /* Amp of voicing in dB, 0 to 70 */ | |||
int Fhz[10]; // formant Hz, F_NZ to F6 to F_NP | |||
@@ -156,7 +153,7 @@ typedef struct | |||
int AVpdb; /* Amp of voicing, par in dB, 0 to 70 */ | |||
int Gain0; /* Overall gain, 60 dB is unity, 0 to 60 */ | |||
int AVdb_tmp; //copy of AVdb, which is changed within parwave() | |||
int AVdb_tmp; // copy of AVdb, which is changed within parwave() | |||
int Fhz_next[10]; // Fhz for the next chunk, so we can do interpolation of resonator (a,b,c) parameters | |||
int Bhz_next[10]; | |||
} klatt_frame_t, *klatt_frame_ptr; |
@@ -287,7 +287,7 @@ static int mbrola_has_errors(void) | |||
char *buf_ptr, *lf; | |||
buf_ptr = buffer; | |||
for (;; ) { | |||
for (;;) { | |||
result = read(mbr_error_fd, buf_ptr, | |||
sizeof(buffer) - (buf_ptr - buffer) - 1); | |||
if (result == -1) { | |||
@@ -514,7 +514,7 @@ int init_MBR(const char *voice_path) | |||
} | |||
mbr_samplerate = wavhdr[24] + (wavhdr[25]<<8) + | |||
(wavhdr[26]<<16) + (wavhdr[27]<<24); | |||
//log("mbrowrap: voice samplerate = %d", mbr_samplerate); | |||
// log("mbrowrap: voice samplerate = %d", mbr_samplerate); | |||
/* remember the voice path for setVolumeRatio_MBR() */ | |||
if (mbr_voice_path != voice_path) { |
@@ -160,9 +160,9 @@ typedef struct { | |||
#define PH(c1,c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name | |||
#define PH3(c1,c2,c3) (c3<<16)+(c2<<8)+c1 | |||
#define PhonemeCode2(c1,c2) PhonemeCode((c2<<8)+c1) | |||
#define PH(c1, c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name | |||
#define PH3(c1, c2, c3) (c3<<16)+(c2<<8)+c1 | |||
#define PhonemeCode2(c1, c2) PhonemeCode((c2<<8)+c1) | |||
int LookupPhonemeString(const char *string); | |||
int PhonemeCode(unsigned int mnem); | |||
@@ -33,7 +33,7 @@ | |||
#include "translate.h" | |||
const unsigned char pause_phonemes[8] = {0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG}; | |||
const unsigned char pause_phonemes[8] = { 0, phonPAUSE_VSHORT, phonPAUSE_SHORT, phonPAUSE, phonPAUSE_LONG, phonGLOTTALSTOP, phonPAUSE_LONG, phonPAUSE_LONG }; | |||
extern int n_ph_list2; | |||
@@ -51,59 +51,54 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) | |||
int n_plist_out = 0; | |||
int word_end; | |||
PHONEME_LIST2 *plist2; | |||
PHONEME_TAB *next=NULL; | |||
PHONEME_TAB *next = NULL; | |||
for(ix=0; (ix < n_ph_list2) && (n_plist_out < N_PHONEME_LIST); ix++) | |||
{ | |||
for (ix = 0; (ix < n_ph_list2) && (n_plist_out < N_PHONEME_LIST); ix++) { | |||
plist2 = &ph_list2[ix]; | |||
// don't do any substitution if the language has been temporarily changed | |||
if(!(plist2->synthflags & SFLAG_SWITCHED_LANG)) | |||
{ | |||
if(ix < (n_ph_list2 -1)) | |||
if (!(plist2->synthflags & SFLAG_SWITCHED_LANG)) { | |||
if (ix < (n_ph_list2 -1)) | |||
next = phoneme_tab[ph_list2[ix+1].phcode]; | |||
word_end = 0; | |||
if((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE))) | |||
if ((plist2+1)->sourceix || ((next != 0) && (next->type == phPAUSE))) | |||
word_end = 1; // this phoneme is the end of a word | |||
// check whether a Voice has specified that we should replace this phoneme | |||
for(k=0; k<n_replace_phonemes; k++) | |||
{ | |||
if(plist2->phcode == replace_phonemes[k].old_ph) | |||
{ | |||
for (k = 0; k < n_replace_phonemes; k++) { | |||
if (plist2->phcode == replace_phonemes[k].old_ph) { | |||
replace_flags = replace_phonemes[k].type; | |||
if((replace_flags & 1) && (word_end == 0)) | |||
if ((replace_flags & 1) && (word_end == 0)) | |||
continue; // this replacement only occurs at the end of a word | |||
if((replace_flags & 2) && ((plist2->stresslevel & 0x7) > 3)) | |||
if ((replace_flags & 2) && ((plist2->stresslevel & 0x7) > 3)) | |||
continue; // this replacement doesn't occur in stressed syllables | |||
if((replace_flags & 4) && (plist2->sourceix == 0)) | |||
if ((replace_flags & 4) && (plist2->sourceix == 0)) | |||
continue; // this replacement only occurs at the start of a word | |||
// substitute the replacement phoneme | |||
plist2->phcode = replace_phonemes[k].new_ph; | |||
if((plist2->stresslevel > 1) && (phoneme_tab[plist2->phcode]->phflags & phUNSTRESSED)) | |||
if ((plist2->stresslevel > 1) && (phoneme_tab[plist2->phcode]->phflags & phUNSTRESSED)) | |||
plist2->stresslevel = 0; // the replacement must be unstressed | |||
break; | |||
} | |||
} | |||
if(plist2->phcode == 0) | |||
{ | |||
if (plist2->phcode == 0) { | |||
continue; // phoneme has been replaced by NULL, so don't copy it | |||
} | |||
} | |||
// copy phoneme into the output list | |||
memcpy(&plist_out[n_plist_out],plist2,sizeof(PHONEME_LIST2)); | |||
memcpy(&plist_out[n_plist_out], plist2, sizeof(PHONEME_LIST2)); | |||
plist_out[n_plist_out].ph = phoneme_tab[plist2->phcode]; | |||
plist_out[n_plist_out].type = plist_out[n_plist_out].ph->type; | |||
n_plist_out++; | |||
} | |||
return(n_plist_out); | |||
return (n_plist_out); | |||
} | |||
@@ -111,7 +106,7 @@ static int SubstitutePhonemes(Translator *tr, PHONEME_LIST *plist_out) | |||
void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
{ | |||
int ix=0; | |||
int ix = 0; | |||
int j; | |||
int insert_ph = 0; | |||
PHONEME_LIST *phlist; | |||
@@ -146,26 +141,21 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
// is the last word of the clause unstressed ? | |||
max_stress = 0; | |||
for(j = n_ph_list2-3; j>=0; j--) | |||
{ | |||
for (j = n_ph_list2-3; j >= 0; j--) { | |||
// start with the last phoneme (before the terminating pauses) and move backwards | |||
if((plist2[j].stresslevel & 0x7f) > max_stress) | |||
if ((plist2[j].stresslevel & 0x7f) > max_stress) | |||
max_stress = plist2[j].stresslevel & 0x7f; | |||
if(plist2[j].sourceix != 0) | |||
if (plist2[j].sourceix != 0) | |||
break; | |||
} | |||
if(max_stress < 4) | |||
{ | |||
if (max_stress < 4) { | |||
// the last word is unstressed, look for a previous word that can be stressed | |||
while(--j >= 0) | |||
{ | |||
if(plist2[j].synthflags & SFLAG_PROMOTE_STRESS) // dictionary flags indicated that this stress can be promoted | |||
{ | |||
while (--j >= 0) { | |||
if (plist2[j].synthflags & SFLAG_PROMOTE_STRESS) { // dictionary flags indicated that this stress can be promoted | |||
plist2[j].stresslevel = 4; // promote to stressed | |||
break; | |||
} | |||
if(plist2[j].stresslevel >= 4) | |||
{ | |||
if (plist2[j].stresslevel >= 4) { | |||
// found a stressed syllable, so stop looking | |||
break; | |||
} | |||
@@ -175,32 +165,25 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
// look for switch of phoneme tables | |||
delete_count = 0; | |||
current_phoneme_tab = tr->phoneme_tab_ix; | |||
for(j = 0; j < n_ph_list2; j++) | |||
{ | |||
if(current_phoneme_tab != tr->phoneme_tab_ix) | |||
{ | |||
for (j = 0; j < n_ph_list2; j++) { | |||
if (current_phoneme_tab != tr->phoneme_tab_ix) { | |||
plist2[j].synthflags |= SFLAG_SWITCHED_LANG; | |||
} | |||
if(delete_count > 0) | |||
{ | |||
if (delete_count > 0) { | |||
memcpy(&plist2[j-delete_count], &plist2[j], sizeof(plist2[0])); | |||
} | |||
if(plist2[j].phcode == phonSWITCH) | |||
{ | |||
if((!(plist2[j].synthflags & SFLAG_EMBEDDED)) && ( | |||
(plist2[j].tone_ph == current_phoneme_tab) || | |||
(plist2[j+1].phcode == phonSWITCH) || | |||
((plist2[j+1].phcode == phonPAUSE) && (plist2[j+2].phcode == phonSWITCH)) | |||
)) | |||
{ | |||
if (plist2[j].phcode == phonSWITCH) { | |||
if ((!(plist2[j].synthflags & SFLAG_EMBEDDED)) && ( | |||
(plist2[j].tone_ph == current_phoneme_tab) || | |||
(plist2[j+1].phcode == phonSWITCH) || | |||
((plist2[j+1].phcode == phonPAUSE) && (plist2[j+2].phcode == phonSWITCH)) | |||
)) { | |||
// delete this phonSWITCH if it's switching to the current phoneme table, or | |||
// delete this phonSWITCH if its followed by another phonSWITCH | |||
delete_count++; | |||
} | |||
else | |||
{ | |||
} else { | |||
current_phoneme_tab = plist2[j].tone_ph; | |||
} | |||
} | |||
@@ -208,95 +191,71 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
} | |||
n_ph_list2 -= delete_count; | |||
if((regression = tr->langopts.param[LOPT_REGRESSIVE_VOICING]) != 0) | |||
{ | |||
if ((regression = tr->langopts.param[LOPT_REGRESSIVE_VOICING]) != 0) { | |||
// set consonant clusters to all voiced or all unvoiced | |||
// Regressive | |||
int type; | |||
int stop_propagation = 0; | |||
voicing = 0; | |||
for(j=n_ph_list2-1; j>=0; j--) | |||
{ | |||
for (j = n_ph_list2-1; j >= 0; j--) { | |||
ph = phoneme_tab[plist2[j].phcode]; | |||
if(ph == NULL) | |||
if (ph == NULL) | |||
continue; | |||
if(plist2[j].synthflags & SFLAG_SWITCHED_LANG) | |||
{ | |||
if (plist2[j].synthflags & SFLAG_SWITCHED_LANG) { | |||
stop_propagation = 0; | |||
voicing = 0; | |||
if(regression & 0x100) | |||
if (regression & 0x100) | |||
voicing = 1; // word-end devoicing | |||
continue; | |||
} | |||
type = ph->type; | |||
if(regression & 0x2) | |||
{ | |||
if (regression & 0x2) { | |||
// [v] amd [v;] don't cause regression, or [R^] | |||
if(((ph->mnemonic & 0xff) == 'v') || ((ph->mnemonic & 0xff)== 'R')) | |||
{ | |||
if (((ph->mnemonic & 0xff) == 'v') || ((ph->mnemonic & 0xff) == 'R')) { | |||
stop_propagation = 1; | |||
if(regression & 0x10) | |||
if (regression & 0x10) | |||
voicing = 0; | |||
} | |||
} | |||
if((type==phSTOP) || type==(phFRICATIVE)) | |||
{ | |||
if((voicing==0) && (regression & 0xf)) | |||
{ | |||
if ((type == phSTOP) || type == (phFRICATIVE)) { | |||
if ((voicing == 0) && (regression & 0xf)) { | |||
voicing = 1; | |||
} | |||
else if((voicing==2) && (ph->end_type != 0)) // use end_type field for voicing_switch for consonants | |||
{ | |||
} else if ((voicing == 2) && (ph->end_type != 0)) { // use end_type field for voicing_switch for consonants | |||
plist2[j].phcode = ph->end_type; // change to voiced equivalent | |||
} | |||
} | |||
else if((type==phVSTOP) || type==(phVFRICATIVE)) | |||
{ | |||
if((voicing==0) && (regression & 0xf)) | |||
{ | |||
} else if ((type == phVSTOP) || type == (phVFRICATIVE)) { | |||
if ((voicing == 0) && (regression & 0xf)) { | |||
voicing = 2; | |||
} | |||
else if((voicing==1) && (ph->end_type != 0)) | |||
{ | |||
} else if ((voicing == 1) && (ph->end_type != 0)) { | |||
plist2[j].phcode = ph->end_type; // change to unvoiced equivalent | |||
} | |||
} | |||
else | |||
{ | |||
if(regression & 0x8) | |||
{ | |||
} else { | |||
if (regression & 0x8) { | |||
// LANG=Polish, propagate through liquids and nasals | |||
if((type == phPAUSE) || (type == phVOWEL)) | |||
if ((type == phPAUSE) || (type == phVOWEL)) | |||
voicing = 0; | |||
} | |||
else | |||
{ | |||
} else { | |||
voicing = 0; | |||
} | |||
} | |||
if(stop_propagation) | |||
{ | |||
if (stop_propagation) { | |||
voicing = 0; | |||
stop_propagation = 0; | |||
} | |||
if(plist2[j].sourceix) | |||
{ | |||
if(regression & 0x04) | |||
{ | |||
if (plist2[j].sourceix) { | |||
if (regression & 0x04) { | |||
// stop propagation at a word boundary | |||
voicing = 0; | |||
} | |||
if(regression & 0x100) | |||
{ | |||
if (regression & 0x100) { | |||
// devoice word-final consonants, unless propagating voiced | |||
if(voicing == 0) | |||
{ | |||
if (voicing == 0) { | |||
voicing = 1; | |||
} | |||
} | |||
@@ -304,35 +263,29 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
} | |||
} | |||
n_ph_list3 = SubstitutePhonemes(tr,ph_list3) - 2; | |||
n_ph_list3 = SubstitutePhonemes(tr, ph_list3) - 2; | |||
for(j=0; (j < n_ph_list3) && (ix < N_PHONEME_LIST-3); ) | |||
{ | |||
if(ph_list3[j].sourceix) | |||
{ | |||
for (j = 0; (j < n_ph_list3) && (ix < N_PHONEME_LIST-3);) { | |||
if (ph_list3[j].sourceix) { | |||
// start of a word | |||
int k; | |||
int nextw; | |||
word_stress = 0; | |||
// find the highest stress level in this word | |||
for(nextw=j; nextw < n_ph_list3; ) | |||
{ | |||
if(ph_list3[nextw].stresslevel > word_stress) | |||
for (nextw = j; nextw < n_ph_list3;) { | |||
if (ph_list3[nextw].stresslevel > word_stress) | |||
word_stress = ph_list3[nextw].stresslevel; | |||
nextw++; | |||
if(ph_list3[nextw].sourceix) | |||
if (ph_list3[nextw].sourceix) | |||
break; // start of the next word | |||
} | |||
for(k=j; k<nextw; k++) | |||
{ | |||
for (k = j; k < nextw; k++) { | |||
ph_list3[k].wordstress = word_stress; | |||
} | |||
j = nextw; | |||
} | |||
else | |||
{ | |||
} else { | |||
j++; | |||
} | |||
} | |||
@@ -342,14 +295,12 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
ph_list3[0].ph = ph; | |||
word_start = 1; | |||
for(j=0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) | |||
{ | |||
for (j = 0; insert_ph || ((j < n_ph_list3) && (ix < N_PHONEME_LIST-3)); j++) { | |||
plist3 = &ph_list3[j]; | |||
inserted = 0; | |||
deleted = 0; | |||
if(insert_ph != 0) | |||
{ | |||
if (insert_ph != 0) { | |||
// we have a (linking) phoneme which we need to insert here | |||
next = phoneme_tab[plist3->phcode]; // this phoneme, i.e. after the insert | |||
@@ -357,20 +308,16 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
// That's OK because we don't look backwards from plist3 *** but CountVowelPosition() and isAfterStress does !!! | |||
j--; | |||
plist3 = plist3_inserted = &ph_list3[j]; | |||
if(j > 0) | |||
{ | |||
if (j > 0) { | |||
// move all previous phonemes in the word back one place | |||
int k; | |||
if(word_start > 0) | |||
{ | |||
if (word_start > 0) { | |||
k = word_start; | |||
word_start--; | |||
} | |||
else | |||
{ | |||
} else { | |||
k = 2; // No more space, don't loose the start of word mark at ph_list2[word_start] | |||
} | |||
for(; k<=j; k++) | |||
for (; k <= j; k++) | |||
memcpy(&ph_list3[k-1], &ph_list3[k], sizeof(*plist3)); | |||
} | |||
memset(&plist3[0], 0, sizeof(*plist3)); | |||
@@ -379,18 +326,15 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
plist3->ph = ph; | |||
insert_ph = 0; | |||
inserted = 1; // don't insert the same phoneme repeatedly | |||
} | |||
else | |||
{ | |||
} else { | |||
// otherwise get the next phoneme from the list | |||
if(plist3->sourceix != 0) | |||
if (plist3->sourceix != 0) | |||
word_start = j; | |||
ph = phoneme_tab[plist3->phcode]; | |||
plist3[0].ph = ph; | |||
if(plist3->phcode == phonSWITCH) | |||
{ | |||
if (plist3->phcode == phonSWITCH) { | |||
// change phoneme table | |||
SelectPhonemeTable(plist3->tone_ph); | |||
} | |||
@@ -398,20 +342,18 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
plist3[1].ph = next; | |||
} | |||
if(ph == NULL) continue; | |||
if (ph == NULL) continue; | |||
InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata); | |||
if((alternative = phdata.pd_param[pd_CHANGE_NEXTPHONEME]) > 0) | |||
{ | |||
if ((alternative = phdata.pd_param[pd_CHANGE_NEXTPHONEME]) > 0) { | |||
ph_list3[j+1].ph = phoneme_tab[alternative]; | |||
ph_list3[j+1].phcode = alternative; | |||
ph_list3[j+1].type = phoneme_tab[alternative]->type; | |||
next = phoneme_tab[alternative]; | |||
} | |||
if(((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0) && (inserted == 0)) | |||
{ | |||
if (((alternative = phdata.pd_param[pd_INSERTPHONEME]) > 0) && (inserted == 0)) { | |||
// PROBLEM: if we insert a phoneme before a vowel then we loose the stress. | |||
PHONEME_TAB *ph2; | |||
ph2 = ph; | |||
@@ -421,13 +363,11 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
plist3->ph = ph; | |||
plist3->phcode = alternative; | |||
if(ph->type == phVOWEL) | |||
{ | |||
if (ph->type == phVOWEL) { | |||
plist3->synthflags |= SFLAG_SYLLABLE; | |||
if(ph2->type != phVOWEL) | |||
if (ph2->type != phVOWEL) | |||
plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
} | |||
else | |||
} else | |||
plist3->synthflags &= ~SFLAG_SYLLABLE; | |||
// re-interpret the changed phoneme | |||
@@ -435,27 +375,21 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
InterpretPhoneme(tr, 0x100, plist3, &phdata, &worddata); | |||
} | |||
if((alternative = phdata.pd_param[pd_CHANGEPHONEME]) > 0) | |||
{ | |||
if ((alternative = phdata.pd_param[pd_CHANGEPHONEME]) > 0) { | |||
PHONEME_TAB *ph2; | |||
ph2 = ph; | |||
ph = phoneme_tab[alternative]; | |||
plist3->ph = ph; | |||
plist3->phcode = alternative; | |||
if(alternative == 1) | |||
{ | |||
if (alternative == 1) { | |||
deleted = 1; // NULL phoneme, discard | |||
} | |||
else | |||
{ | |||
if(ph->type == phVOWEL) | |||
{ | |||
} else { | |||
if (ph->type == phVOWEL) { | |||
plist3->synthflags |= SFLAG_SYLLABLE; | |||
if(ph2->type != phVOWEL) | |||
if (ph2->type != phVOWEL) | |||
plist3->stresslevel = 0; // change from non-vowel to vowel, make sure it's unstressed | |||
} | |||
else | |||
} else | |||
plist3->synthflags &= ~SFLAG_SYLLABLE; | |||
// re-interpret the changed phoneme | |||
@@ -464,64 +398,48 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
} | |||
} | |||
if((ph->type == phVOWEL) && (deleted == 0)) | |||
{ | |||
if ((ph->type == phVOWEL) && (deleted == 0)) { | |||
PHONEME_LIST *p; | |||
// Check for consecutive unstressed syllables, even across word boundaries. | |||
// Do this after changing phonemes according to stress level. | |||
if(plist3->stresslevel <= 1) | |||
{ | |||
if (plist3->stresslevel <= 1) { | |||
// an unstressed vowel | |||
unstress_count++; | |||
if(tr->langopts.stress_flags & 0x08) | |||
{ | |||
if (tr->langopts.stress_flags & 0x08) { | |||
// change sequences of consecutive unstressed vowels in unstressed words to diminished stress (TEST) | |||
for(p=plist3+1; p->type != phPAUSE; p++) | |||
{ | |||
if(p->type == phVOWEL) | |||
{ | |||
if(p->stresslevel <= 1) | |||
{ | |||
if(plist3->wordstress < 4) | |||
for (p = plist3+1; p->type != phPAUSE; p++) { | |||
if (p->type == phVOWEL) { | |||
if (p->stresslevel <= 1) { | |||
if (plist3->wordstress < 4) | |||
plist3->stresslevel = 0; | |||
if(p->wordstress < 4) | |||
if (p->wordstress < 4) | |||
p->stresslevel = 0; | |||
} | |||
break; | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
if((unstress_count > 1) && ((unstress_count & 1)==0)) | |||
{ | |||
} else { | |||
if ((unstress_count > 1) && ((unstress_count & 1) == 0)) { | |||
// in a sequence of unstressed syllables, reduce alternate syllables to 'diminished' | |||
// stress. But not for the last phoneme of a stressed word | |||
if((tr->langopts.stress_flags & S_NO_DIM) || ((word_stress > 3) && ((plist3+1)->sourceix!=0))) | |||
{ | |||
if ((tr->langopts.stress_flags & S_NO_DIM) || ((word_stress > 3) && ((plist3+1)->sourceix != 0))) { | |||
// An unstressed final vowel of a stressed word | |||
unstress_count=1; // try again for next syllable | |||
} | |||
else | |||
{ | |||
unstress_count = 1; // try again for next syllable | |||
} else { | |||
plist3->stresslevel = 0; // change stress to 'diminished' | |||
} | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
unstress_count = 0; | |||
} | |||
} | |||
if((plist3+1)->synthflags & SFLAG_LENGTHEN) | |||
{ | |||
static char types_double[] = {phFRICATIVE,phVFRICATIVE,phNASAL,phLIQUID,0}; | |||
if((j > 0) && (strchr(types_double,next->type))) | |||
{ | |||
if ((plist3+1)->synthflags & SFLAG_LENGTHEN) { | |||
static char types_double[] = { phFRICATIVE, phVFRICATIVE, phNASAL, phLIQUID, 0 }; | |||
if ((j > 0) && (strchr(types_double, next->type))) { | |||
// lengthen this consonant by doubling it | |||
// BUT, can't insert a phoneme at position plist3[0] because it crashes PrevPh() | |||
insert_ph = next->code; | |||
@@ -529,59 +447,48 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
} | |||
} | |||
if((plist3+1)->sourceix != 0) | |||
{ | |||
if ((plist3+1)->sourceix != 0) { | |||
int x; | |||
if(tr->langopts.vowel_pause && (ph->type != phPAUSE)) | |||
{ | |||
if (tr->langopts.vowel_pause && (ph->type != phPAUSE)) { | |||
if((ph->type != phVOWEL) && (tr->langopts.vowel_pause & 0x200)) | |||
{ | |||
if ((ph->type != phVOWEL) && (tr->langopts.vowel_pause & 0x200)) { | |||
// add a pause after a word which ends in a consonant | |||
insert_ph = phonPAUSE_NOLINK; | |||
} | |||
if(next->type == phVOWEL) | |||
{ | |||
if((x = tr->langopts.vowel_pause & 0x0c) != 0) | |||
{ | |||
if (next->type == phVOWEL) { | |||
if ((x = tr->langopts.vowel_pause & 0x0c) != 0) { | |||
// break before a word which starts with a vowel | |||
if(x == 0xc) | |||
if (x == 0xc) | |||
insert_ph = phonPAUSE_NOLINK; | |||
else | |||
insert_ph = phonPAUSE_VSHORT; | |||
} | |||
if((ph->type == phVOWEL) && ((x = tr->langopts.vowel_pause & 0x03) != 0)) | |||
{ | |||
if ((ph->type == phVOWEL) && ((x = tr->langopts.vowel_pause & 0x03) != 0)) { | |||
// adjacent vowels over a word boundary | |||
if(x == 2) | |||
if (x == 2) | |||
insert_ph = phonPAUSE_SHORT; | |||
else | |||
insert_ph = phonPAUSE_VSHORT; | |||
} | |||
if(((plist3+1)->stresslevel >= 4) && (tr->langopts.vowel_pause & 0x100)) | |||
{ | |||
if (((plist3+1)->stresslevel >= 4) && (tr->langopts.vowel_pause & 0x100)) { | |||
// pause before a words which starts with a stressed vowel | |||
insert_ph = phonPAUSE_SHORT; | |||
} | |||
} | |||
} | |||
if((plist3 != plist3_inserted) && (ix > 0)) | |||
{ | |||
if((x = (tr->langopts.word_gap & 0x7)) != 0) | |||
{ | |||
if((x > 1) || ((insert_ph != phonPAUSE_SHORT) && (insert_ph != phonPAUSE_NOLINK))) | |||
{ | |||
if ((plist3 != plist3_inserted) && (ix > 0)) { | |||
if ((x = (tr->langopts.word_gap & 0x7)) != 0) { | |||
if ((x > 1) || ((insert_ph != phonPAUSE_SHORT) && (insert_ph != phonPAUSE_NOLINK))) { | |||
// don't reduce the pause | |||
insert_ph = pause_phonemes[x]; | |||
} | |||
} | |||
if(option_wordgap > 0) | |||
{ | |||
if (option_wordgap > 0) { | |||
insert_ph = phonPAUSE_LONG; | |||
} | |||
} | |||
@@ -590,13 +497,11 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
next2 = phoneme_tab[plist3[2].phcode]; | |||
plist3[2].ph = next2; | |||
if((insert_ph == 0) && (phdata.pd_param[pd_APPENDPHONEME] != 0)) | |||
{ | |||
if ((insert_ph == 0) && (phdata.pd_param[pd_APPENDPHONEME] != 0)) { | |||
insert_ph = phdata.pd_param[pd_APPENDPHONEME]; | |||
} | |||
if(deleted == 0) | |||
{ | |||
if (deleted == 0) { | |||
phlist[ix].ph = ph; | |||
phlist[ix].type = ph->type; | |||
phlist[ix].env = PITCHfall; // default, can be changed in the "intonation" module | |||
@@ -607,31 +512,25 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
phlist[ix].sourceix = 0; | |||
phlist[ix].phcode = ph->code; | |||
if(plist3->sourceix != 0) | |||
{ | |||
if (plist3->sourceix != 0) { | |||
phlist[ix].sourceix = plist3->sourceix; | |||
phlist[ix].newword = 1; // this phoneme is the start of a word | |||
if(start_sentence) | |||
{ | |||
if (start_sentence) { | |||
phlist[ix].newword = 5; // start of sentence + start of word | |||
start_sentence = 0; | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
phlist[ix].newword = 0; | |||
} | |||
phlist[ix].length = phdata.pd_param[i_SET_LENGTH]*2; | |||
if((ph->code == phonPAUSE_LONG) && (option_wordgap > 0) && (plist3[1].sourceix != 0)) | |||
{ | |||
if ((ph->code == phonPAUSE_LONG) && (option_wordgap > 0) && (plist3[1].sourceix != 0)) { | |||
phlist[ix].ph = phoneme_tab[phonPAUSE_SHORT]; | |||
phlist[ix].length = option_wordgap*14; // 10mS per unit at the default speed | |||
} | |||
if(ph->type==phVOWEL || ph->type==phLIQUID || ph->type==phNASAL || ph->type==phVSTOP || ph->type==phVFRICATIVE || (ph->phflags & phPREVOICE)) | |||
{ | |||
if (ph->type == phVOWEL || ph->type == phLIQUID || ph->type == phNASAL || ph->type == phVSTOP || ph->type == phVFRICATIVE || (ph->phflags & phPREVOICE)) { | |||
phlist[ix].length = 128; // length_mod | |||
phlist[ix].env = PITCHfall; | |||
} | |||
@@ -655,7 +554,7 @@ void MakePhonemeList(Translator *tr, int post_pause, int start_sentence) | |||
phlist[ix].phcode = phonPAUSE; | |||
phlist[ix].type = phPAUSE; | |||
phlist[ix].length = 0; | |||
phlist[ix].sourceix=0; | |||
phlist[ix].sourceix = 0; | |||
phlist[ix].synthflags = 0; | |||
phlist[ix++].ph = phoneme_tab[phonPAUSE_SHORT]; | |||
@@ -102,9 +102,9 @@ static unsigned char speed_lookup[] = { | |||
// speed_factor1 adjustments for speeds 350 to 374: pauses | |||
static unsigned char pause_factor_350[] = { | |||
22,22,22,22,22,22,22,21,21,21, // 350 | |||
21,20,20,19,19,18,17,16,15,15, // 360 | |||
15,15,15,15,15 | |||
22, 22, 22, 22, 22, 22, 22, 21, 21, 21, // 350 | |||
21, 20, 20, 19, 19, 18, 17, 16, 15, 15, // 360 | |||
15, 15, 15, 15, 15 | |||
}; // 370 | |||
// wav_factor adjustments for speeds 350 to 450 | |||
@@ -157,36 +157,31 @@ void SetSpeed(int control) | |||
speed.min_pause = 5; | |||
wpm = embedded_value[EMBED_S]; | |||
if(control == 2) | |||
if (control == 2) | |||
wpm = embedded_value[EMBED_S2]; | |||
wpm_value = wpm; | |||
if(voice->speed_percent > 0) | |||
{ | |||
if (voice->speed_percent > 0) { | |||
wpm = (wpm * voice->speed_percent)/100; | |||
} | |||
if(control & 2) | |||
{ | |||
if (control & 2) { | |||
DoSonicSpeed(1 * 1024); | |||
} | |||
if((wpm_value >= 450) || ((wpm_value > speed.fast_settings[0]) && (wpm > 350))) | |||
{ | |||
if ((wpm_value >= 450) || ((wpm_value > speed.fast_settings[0]) && (wpm > 350))) { | |||
wpm2 = wpm; | |||
wpm = 175; | |||
// set special eSpeak speed parameters for Sonic use | |||
// The eSpeak output will be speeded up by at least x2 | |||
x = 73; | |||
if(control & 1) | |||
{ | |||
if (control & 1) { | |||
speed1 = (x * voice->speedf1)/256; | |||
speed2 = (x * voice->speedf2)/256; | |||
speed3 = (x * voice->speedf3)/256; | |||
} | |||
if(control & 2) | |||
{ | |||
if (control & 2) { | |||
sonic = ((double)wpm2)/wpm; | |||
DoSonicSpeed((int)(sonic * 1024)); | |||
speed.pause_factor = 85; | |||
@@ -200,71 +195,61 @@ void SetSpeed(int control) | |||
return; | |||
} | |||
if(wpm > 450) | |||
if (wpm > 450) | |||
wpm = 450; | |||
if(wpm > 360) | |||
{ | |||
if (wpm > 360) { | |||
speed.loud_consonants = (wpm - 360) / 8; | |||
} | |||
wpm2 = wpm; | |||
if(wpm > 359) wpm2 = 359; | |||
if(wpm < 80) wpm2 = 80; | |||
if (wpm > 359) wpm2 = 359; | |||
if (wpm < 80) wpm2 = 80; | |||
x = speed_lookup[wpm2-80]; | |||
if(wpm >= 380) | |||
if (wpm >= 380) | |||
x = 7; | |||
if(wpm >= 400) | |||
if (wpm >= 400) | |||
x = 6; | |||
if(control & 1) | |||
{ | |||
if (control & 1) { | |||
// set speed factors for different syllable positions within a word | |||
// these are used in CalcLengths() | |||
speed1 = (x * voice->speedf1)/256; | |||
speed2 = (x * voice->speedf2)/256; | |||
speed3 = (x * voice->speedf3)/256; | |||
if(x <= 7) | |||
{ | |||
if (x <= 7) { | |||
speed1 = x; | |||
speed2 = speed3 = x - 1; | |||
} | |||
} | |||
if(control & 2) | |||
{ | |||
if (control & 2) { | |||
// these are used in synthesis file | |||
if(wpm > 350) | |||
{ | |||
if (wpm > 350) { | |||
speed.lenmod_factor = 85 - (wpm - 350) / 3; | |||
speed.lenmod2_factor = 60 - (wpm - 350) / 8; | |||
} | |||
else | |||
if(wpm > 250) | |||
{ | |||
} else if (wpm > 250) { | |||
speed.lenmod_factor = 110 - (wpm - 250)/4; | |||
speed.lenmod2_factor = 110 - (wpm - 250)/2; | |||
} | |||
s1 = (x * voice->speedf1)/256; | |||
if(wpm >= 170) | |||
if (wpm >= 170) | |||
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
else | |||
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
if(wpm >= 350) | |||
{ | |||
if (wpm >= 350) { | |||
speed.wav_factor = wav_factor_350[wpm-350]; | |||
} | |||
if(wpm >= 390) | |||
{ | |||
if (wpm >= 390) { | |||
speed.min_sample_len = 450 - (wpm - 400)/2; | |||
if(wpm > 440) | |||
if (wpm > 440) | |||
speed.min_sample_len = 420 - (wpm - 440); | |||
} | |||
@@ -274,30 +259,19 @@ void SetSpeed(int control) | |||
speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
speed.clause_pause_factor = 0; | |||
if(wpm > 430) | |||
{ | |||
if (wpm > 430) { | |||
speed.pause_factor = 12; | |||
} | |||
else | |||
if(wpm > 400) | |||
{ | |||
} else if (wpm > 400) { | |||
speed.pause_factor = 13; | |||
} | |||
else | |||
if(wpm > 374) | |||
{ | |||
} else if (wpm > 374) { | |||
speed.pause_factor = 14; | |||
} | |||
else | |||
if(wpm > 350) | |||
{ | |||
} else if (wpm > 350) { | |||
speed.pause_factor = pause_factor_350[wpm - 350]; | |||
} | |||
if(speed.clause_pause_factor == 0) | |||
{ | |||
if (speed.clause_pause_factor == 0) { | |||
// restrict the reduction of pauses between clauses | |||
if((speed.clause_pause_factor = speed.pause_factor) < 16) | |||
if ((speed.clause_pause_factor = speed.pause_factor) < 16) | |||
speed.clause_pause_factor = 16; | |||
} | |||
} | |||
@@ -319,108 +293,86 @@ void SetSpeed(int control) | |||
speed.lenmod2_factor = 100; | |||
wpm = embedded_value[EMBED_S]; | |||
if(control == 2) | |||
if (control == 2) | |||
wpm = embedded_value[EMBED_S2]; | |||
if(voice->speed_percent > 0) | |||
{ | |||
if (voice->speed_percent > 0) { | |||
wpm = (wpm * voice->speed_percent)/100; | |||
} | |||
if(wpm > 450) | |||
if (wpm > 450) | |||
wpm = 450; | |||
if(wpm > 360) | |||
{ | |||
if (wpm > 360) { | |||
speed.loud_consonants = (wpm - 360) / 8; | |||
} | |||
wpm2 = wpm; | |||
if(wpm > 359) wpm2 = 359; | |||
if(wpm < 80) wpm2 = 80; | |||
if (wpm > 359) wpm2 = 359; | |||
if (wpm < 80) wpm2 = 80; | |||
x = speed_lookup[wpm2-80]; | |||
if(wpm >= 380) | |||
if (wpm >= 380) | |||
x = 7; | |||
if(wpm >= 400) | |||
if (wpm >= 400) | |||
x = 6; | |||
if(control & 1) | |||
{ | |||
if (control & 1) { | |||
// set speed factors for different syllable positions within a word | |||
// these are used in CalcLengths() | |||
speed1 = (x * voice->speedf1)/256; | |||
speed2 = (x * voice->speedf2)/256; | |||
speed3 = (x * voice->speedf3)/256; | |||
if(x <= 7) | |||
{ | |||
if (x <= 7) { | |||
speed1 = x; | |||
speed2 = speed3 = x - 1; | |||
} | |||
} | |||
if(control & 2) | |||
{ | |||
if (control & 2) { | |||
// these are used in synthesis file | |||
if(wpm > 350) | |||
{ | |||
if (wpm > 350) { | |||
speed.lenmod_factor = 85 - (wpm - 350) / 3; | |||
speed.lenmod2_factor = 60 - (wpm - 350) / 8; | |||
} | |||
else | |||
if(wpm > 250) | |||
{ | |||
} else if (wpm > 250) { | |||
speed.lenmod_factor = 110 - (wpm - 250)/4; | |||
speed.lenmod2_factor = 110 - (wpm - 250)/2; | |||
} | |||
s1 = (x * voice->speedf1)/256; | |||
if(wpm >= 170) | |||
if (wpm >= 170) | |||
speed.wav_factor = 110 + (150*s1)/128; // reduced speed adjustment, used for playing recorded sounds | |||
else | |||
speed.wav_factor = 128 + (128*s1)/130; // = 215 at 170 wpm | |||
if(wpm >= 350) | |||
{ | |||
if (wpm >= 350) { | |||
speed.wav_factor = wav_factor_350[wpm-350]; | |||
} | |||
if(wpm >= 390) | |||
{ | |||
if (wpm >= 390) { | |||
speed.min_sample_len = 450 - (wpm - 400)/2; | |||
if(wpm > 440) | |||
if (wpm > 440) | |||
speed.min_sample_len = 420 - (wpm - 440); | |||
} | |||
speed.pause_factor = (256 * s1)/115; // full speed adjustment, used for pause length | |||
speed.clause_pause_factor = 0; | |||
if(wpm > 430) | |||
{ | |||
if (wpm > 430) { | |||
speed.pause_factor = 12; | |||
} | |||
else | |||
if(wpm > 400) | |||
{ | |||
} else if (wpm > 400) { | |||
speed.pause_factor = 13; | |||
} | |||
else | |||
if(wpm > 374) | |||
{ | |||
} else if (wpm > 374) { | |||
speed.pause_factor = 14; | |||
} | |||
else | |||
if(wpm > 350) | |||
{ | |||
} else if (wpm > 350) { | |||
speed.pause_factor = pause_factor_350[wpm - 350]; | |||
} | |||
if(speed.clause_pause_factor == 0) | |||
{ | |||
if (speed.clause_pause_factor == 0) { | |||
// restrict the reduction of pauses between clauses | |||
if((speed.clause_pause_factor = speed.pause_factor) < 16) | |||
if ((speed.clause_pause_factor = speed.pause_factor) < 16) | |||
speed.clause_pause_factor = 16; | |||
} | |||
} | |||
@@ -437,10 +389,8 @@ void SetParameter(int parameter, int value, int relative) | |||
int new_value = value; | |||
int default_value; | |||
if(relative) | |||
{ | |||
if(parameter < 5) | |||
{ | |||
if (relative) { | |||
if (parameter < 5) { | |||
default_value = param_defaults[parameter]; | |||
new_value = default_value + (default_value * value)/100; | |||
} | |||
@@ -448,7 +398,7 @@ void SetParameter(int parameter, int value, int relative) | |||
param_stack[0].parameter[parameter] = new_value; | |||
saved_parameters[parameter] = new_value; | |||
switch(parameter) | |||
switch (parameter) | |||
{ | |||
case espeakRATE: | |||
embedded_value[EMBED_S] = new_value; | |||
@@ -462,13 +412,13 @@ void SetParameter(int parameter, int value, int relative) | |||
break; | |||
case espeakPITCH: | |||
if(new_value > 99) new_value = 99; | |||
if(new_value < 0) new_value = 0; | |||
if (new_value > 99) new_value = 99; | |||
if (new_value < 0) new_value = 0; | |||
embedded_value[EMBED_P] = new_value; | |||
break; | |||
case espeakRANGE: | |||
if(new_value > 99) new_value = 99; | |||
if (new_value > 99) new_value = 99; | |||
embedded_value[EMBED_R] = new_value; | |||
break; | |||
@@ -481,7 +431,7 @@ void SetParameter(int parameter, int value, int relative) | |||
break; | |||
case espeakINTONATION: | |||
if((new_value & 0xff) != 0) | |||
if ((new_value & 0xff) != 0) | |||
translator->langopts.intonation_group = new_value & 0xff; | |||
option_tone_flags = new_value; | |||
break; | |||
@@ -502,13 +452,12 @@ static void DoEmbedded2(int *embix) | |||
do { | |||
word = embedded_list[(*embix)++]; | |||
if((word & 0x1f) == EMBED_S) | |||
{ | |||
if ((word & 0x1f) == EMBED_S) { | |||
// speed | |||
SetEmbedded(word & 0x7f, word >> 8); // adjusts embedded_value[EMBED_S] | |||
SetSpeed(1); | |||
} | |||
} while((word & 0x80) == 0); | |||
} while ((word & 0x80) == 0); | |||
} | |||
@@ -525,9 +474,9 @@ void CalcLengths(Translator *tr) | |||
int stress; | |||
int type; | |||
static int more_syllables=0; | |||
int pre_sonorant=0; | |||
int pre_voiced=0; | |||
static int more_syllables = 0; | |||
int pre_sonorant = 0; | |||
int pre_voiced = 0; | |||
int last_pitch = 0; | |||
int pitch_start; | |||
int length_mod; | |||
@@ -540,11 +489,10 @@ void CalcLengths(Translator *tr) | |||
int pitch1; | |||
int emphasized; | |||
int tone_mod; | |||
unsigned char *pitch_env=NULL; | |||
unsigned char *pitch_env = NULL; | |||
PHONEME_DATA phdata_tone; | |||
for(ix=1; ix<n_phoneme_list; ix++) | |||
{ | |||
for (ix = 1; ix < n_phoneme_list; ix++) { | |||
prev = &phoneme_list[ix-1]; | |||
p = &phoneme_list[ix]; | |||
stress = p->stresslevel & 0x7; | |||
@@ -552,16 +500,15 @@ void CalcLengths(Translator *tr) | |||
next = &phoneme_list[ix+1]; | |||
if(p->synthflags & SFLAG_EMBEDDED) | |||
{ | |||
if (p->synthflags & SFLAG_EMBEDDED) { | |||
DoEmbedded2(&embedded_ix); | |||
} | |||
type = p->type; | |||
if(p->synthflags & SFLAG_SYLLABLE) | |||
if (p->synthflags & SFLAG_SYLLABLE) | |||
type = phVOWEL; | |||
switch(type) | |||
switch (type) | |||
{ | |||
case phPAUSE: | |||
last_pitch = 0; | |||
@@ -569,109 +516,91 @@ void CalcLengths(Translator *tr) | |||
case phSTOP: | |||
last_pitch = 0; | |||
if(prev->type == phFRICATIVE) | |||
if (prev->type == phFRICATIVE) | |||
p->prepause = 25; | |||
else | |||
if((more_syllables > 0) || (stress < 4)) | |||
else if ((more_syllables > 0) || (stress < 4)) | |||
p->prepause = 48; | |||
else | |||
p->prepause = 60; | |||
if(prev->type == phSTOP) | |||
if (prev->type == phSTOP) | |||
p->prepause = 60; | |||
if((tr->langopts.word_gap & 0x10) && (p->newword)) | |||
if ((tr->langopts.word_gap & 0x10) && (p->newword)) | |||
p->prepause = 60; | |||
if(p->ph->phflags & phLENGTHENSTOP) | |||
if (p->ph->phflags & phLENGTHENSTOP) | |||
p->prepause += 30; | |||
if(p->synthflags & SFLAG_LENGTHEN) | |||
if (p->synthflags & SFLAG_LENGTHEN) | |||
p->prepause += tr->langopts.long_stop; | |||
break; | |||
case phVFRICATIVE: | |||
case phFRICATIVE: | |||
if(p->newword) | |||
{ | |||
if((prev->type == phVOWEL) && (p->ph->phflags & phNOPAUSE)) | |||
{ | |||
} | |||
else | |||
{ | |||
if (p->newword) { | |||
if ((prev->type == phVOWEL) && (p->ph->phflags & phNOPAUSE)) { | |||
} else { | |||
p->prepause = 15; | |||
} | |||
} | |||
if(next->type==phPAUSE && prev->type==phNASAL && !(p->ph->phflags&phFORTIS)) | |||
if (next->type == phPAUSE && prev->type == phNASAL && !(p->ph->phflags&phFORTIS)) | |||
p->prepause = 25; | |||
if(prev->ph->phflags & phBRKAFTER) | |||
if (prev->ph->phflags & phBRKAFTER) | |||
p->prepause = 30; | |||
if((tr->langopts.word_gap & 0x10) && (p->newword)) | |||
if ((tr->langopts.word_gap & 0x10) && (p->newword)) | |||
p->prepause = 30; | |||
if((p->ph->phflags & phSIBILANT) && next->type==phSTOP && !next->newword) | |||
{ | |||
if(prev->type == phVOWEL) | |||
if ((p->ph->phflags & phSIBILANT) && next->type == phSTOP && !next->newword) { | |||
if (prev->type == phVOWEL) | |||
p->length = 200; // ?? should do this if it's from a prefix | |||
else | |||
p->length = 150; | |||
} | |||
else | |||
} else | |||
p->length = 256; | |||
if(type == phVFRICATIVE) | |||
{ | |||
if(next->type==phVOWEL) | |||
{ | |||
if (type == phVFRICATIVE) { | |||
if (next->type == phVOWEL) { | |||
pre_voiced = 1; | |||
} | |||
if((prev->type==phVOWEL) || (prev->type == phLIQUID)) | |||
{ | |||
if ((prev->type == phVOWEL) || (prev->type == phLIQUID)) { | |||
p->length = (255 + prev->length)/2; | |||
} | |||
} | |||
break; | |||
case phVSTOP: | |||
if(prev->type==phVFRICATIVE || prev->type==phFRICATIVE || (prev->ph->phflags & phSIBILANT) || (prev->type == phLIQUID)) | |||
if (prev->type == phVFRICATIVE || prev->type == phFRICATIVE || (prev->ph->phflags & phSIBILANT) || (prev->type == phLIQUID)) | |||
p->prepause = 30; | |||
if(next->type==phVOWEL || next->type==phLIQUID) | |||
{ | |||
if((next->type==phVOWEL) || !next->newword) | |||
if (next->type == phVOWEL || next->type == phLIQUID) { | |||
if ((next->type == phVOWEL) || !next->newword) | |||
pre_voiced = 1; | |||
p->prepause = 40; | |||
if(prev->type == phVOWEL) | |||
{ | |||
if (prev->type == phVOWEL) { | |||
p->prepause = 0; // use murmur instead to link from the preceding vowel | |||
} | |||
else | |||
if(prev->type == phPAUSE) | |||
{ | |||
} else if (prev->type == phPAUSE) { | |||
// reduce by the length of the preceding pause | |||
if(prev->length < p->prepause) | |||
if (prev->length < p->prepause) | |||
p->prepause -= prev->length; | |||
else | |||
p->prepause = 0; | |||
} | |||
else | |||
if(p->newword==0) | |||
{ | |||
if(prev->type==phLIQUID) | |||
} else if (p->newword == 0) { | |||
if (prev->type == phLIQUID) | |||
p->prepause = 20; | |||
if(prev->type==phNASAL) | |||
if (prev->type == phNASAL) | |||
p->prepause = 12; | |||
if(prev->type==phSTOP && !(prev->ph->phflags & phFORTIS)) | |||
if (prev->type == phSTOP && !(prev->ph->phflags & phFORTIS)) | |||
p->prepause = 0; | |||
} | |||
} | |||
if((tr->langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20)) | |||
if ((tr->langopts.word_gap & 0x10) && (p->newword) && (p->prepause < 20)) | |||
p->prepause = 20; | |||
break; | |||
@@ -682,49 +611,36 @@ void CalcLengths(Translator *tr) | |||
p->length = 256; // TEMPORARY | |||
min_drop = 0; | |||
if(p->newword) | |||
{ | |||
if(prev->type==phLIQUID) | |||
if (p->newword) { | |||
if (prev->type == phLIQUID) | |||
p->prepause = 25; | |||
if(prev->type==phVOWEL) | |||
{ | |||
if(!(p->ph->phflags & phNOPAUSE)) | |||
if (prev->type == phVOWEL) { | |||
if (!(p->ph->phflags & phNOPAUSE)) | |||
p->prepause = 12; | |||
} | |||
} | |||
if(next->type==phVOWEL) | |||
{ | |||
if (next->type == phVOWEL) { | |||
pre_sonorant = 1; | |||
} | |||
else | |||
{ | |||
} else { | |||
p->pitch2 = last_pitch; | |||
if((prev->type==phVOWEL) || (prev->type == phLIQUID)) | |||
{ | |||
if ((prev->type == phVOWEL) || (prev->type == phLIQUID)) { | |||
p->length = prev->length; | |||
if(p->type == phLIQUID) | |||
{ | |||
if (p->type == phLIQUID) { | |||
p->length = speed1; | |||
} | |||
if(next->type == phVSTOP) | |||
{ | |||
if (next->type == phVSTOP) { | |||
p->length = (p->length * 160)/100; | |||
} | |||
if(next->type == phVFRICATIVE) | |||
{ | |||
if (next->type == phVFRICATIVE) { | |||
p->length = (p->length * 120)/100; | |||
} | |||
} | |||
else | |||
{ | |||
for(ix2=ix; ix2<n_phoneme_list; ix2++) | |||
{ | |||
if(phoneme_list[ix2].type == phVOWEL) | |||
{ | |||
} else { | |||
for (ix2 = ix; ix2 < n_phoneme_list; ix2++) { | |||
if (phoneme_list[ix2].type == phVOWEL) { | |||
p->pitch2 = phoneme_list[ix2].pitch2; | |||
break; | |||
} | |||
@@ -732,8 +648,7 @@ void CalcLengths(Translator *tr) | |||
} | |||
p->pitch1 = p->pitch2-16; | |||
if(p->pitch2 < 16) | |||
{ | |||
if (p->pitch2 < 16) { | |||
p->pitch1 = 0; | |||
} | |||
p->env = PITCHfall; | |||
@@ -746,49 +661,44 @@ void CalcLengths(Translator *tr) | |||
next2 = &phoneme_list[ix+2]; | |||
next3 = &phoneme_list[ix+3]; | |||
if(stress > 7) stress = 7; | |||
if (stress > 7) stress = 7; | |||
if(stress <= 1) | |||
{ | |||
if (stress <= 1) { | |||
stress = stress ^ 1; // swap diminished and unstressed (until we swap stress_amps,stress_lengths in tr_languages) | |||
} | |||
if(pre_sonorant) | |||
if (pre_sonorant) | |||
p->amp = tr->stress_amps[stress]-1; | |||
else | |||
p->amp = tr->stress_amps[stress]; | |||
if(emphasized) | |||
if (emphasized) | |||
p->amp = 25; | |||
if(ix >= (n_phoneme_list-3)) | |||
{ | |||
if (ix >= (n_phoneme_list-3)) { | |||
// last phoneme of a clause, limit its amplitude | |||
if(p->amp > tr->langopts.param[LOPT_MAXAMP_EOC]) | |||
if (p->amp > tr->langopts.param[LOPT_MAXAMP_EOC]) | |||
p->amp = tr->langopts.param[LOPT_MAXAMP_EOC]; | |||
} | |||
// is the last syllable of a word ? | |||
more_syllables=0; | |||
more_syllables = 0; | |||
end_of_clause = 0; | |||
for(p2 = p+1; p2->newword== 0; p2++) | |||
{ | |||
if((p2->type == phVOWEL) && !(p2->ph->phflags & phNONSYLLABIC)) | |||
for (p2 = p+1; p2->newword == 0; p2++) { | |||
if ((p2->type == phVOWEL) && !(p2->ph->phflags & phNONSYLLABIC)) | |||
more_syllables++; | |||
if(p2->ph->code == phonPAUSE_CLAUSE) | |||
if (p2->ph->code == phonPAUSE_CLAUSE) | |||
end_of_clause = 2; | |||
} | |||
if(p2->ph->code == phonPAUSE_CLAUSE) | |||
if (p2->ph->code == phonPAUSE_CLAUSE) | |||
end_of_clause = 2; | |||
if((p2->newword & 2) && (more_syllables==0)) | |||
{ | |||
if ((p2->newword & 2) && (more_syllables == 0)) { | |||
end_of_clause = 2; | |||
} | |||
// calc length modifier | |||
if((next->ph->code == phonPAUSE_VSHORT) && (next2->type == phPAUSE)) | |||
{ | |||
if ((next->ph->code == phonPAUSE_VSHORT) && (next2->type == phPAUSE)) { | |||
// if PAUSE_VSHORT is followed by a pause, then use that | |||
next = next2; | |||
next2 = next3; | |||
@@ -796,101 +706,84 @@ void CalcLengths(Translator *tr) | |||
} | |||
next2type = next2->ph->length_mod; | |||
if(more_syllables==0) | |||
{ | |||
if(next->newword || next2->newword) | |||
{ | |||
if (more_syllables == 0) { | |||
if (next->newword || next2->newword) { | |||
// don't use 2nd phoneme over a word boundary, unless it's a pause | |||
if(next2type != 1) | |||
if (next2type != 1) | |||
next2type = 0; | |||
} | |||
len = tr->langopts.length_mods0[next2type *10+ next->ph->length_mod]; | |||
if((next->newword) && (tr->langopts.word_gap & 0x20)) | |||
{ | |||
if ((next->newword) && (tr->langopts.word_gap & 0x20)) { | |||
// consider as a pause + first phoneme of the next word | |||
length_mod = (len + tr->langopts.length_mods0[next->ph->length_mod *10+ 1])/2; | |||
} | |||
else | |||
} else | |||
length_mod = len; | |||
} | |||
else | |||
{ | |||
} else { | |||
length_mod = tr->langopts.length_mods[next2type *10+ next->ph->length_mod]; | |||
if((next->type == phNASAL) && (next2->type == phSTOP || next2->type == phVSTOP) && (next3->ph->phflags & phFORTIS)) | |||
if ((next->type == phNASAL) && (next2->type == phSTOP || next2->type == phVSTOP) && (next3->ph->phflags & phFORTIS)) | |||
length_mod -= 15; | |||
} | |||
if(more_syllables==0) | |||
if (more_syllables == 0) | |||
length_mod *= speed1; | |||
else | |||
if(more_syllables==1) | |||
else if (more_syllables == 1) | |||
length_mod *= speed2; | |||
else | |||
length_mod *= speed3; | |||
length_mod = length_mod / 128; | |||
if(length_mod < 8) | |||
if (length_mod < 8) | |||
length_mod = 8; // restrict how much lengths can be reduced | |||
if(stress >= 7) | |||
{ | |||
if (stress >= 7) { | |||
// tonic syllable, include a constant component so it doesn't decrease directly with speed | |||
length_mod += tr->langopts.lengthen_tonic; | |||
if(emphasized) | |||
if (emphasized) | |||
length_mod += (tr->langopts.lengthen_tonic/2); | |||
} | |||
else | |||
if(emphasized) | |||
{ | |||
} else if (emphasized) { | |||
length_mod += tr->langopts.lengthen_tonic; | |||
} | |||
if((len = tr->stress_lengths[stress]) == 0) | |||
if ((len = tr->stress_lengths[stress]) == 0) | |||
len = tr->stress_lengths[6]; | |||
length_mod = length_mod * len; | |||
if(p->tone_ph != 0) | |||
{ | |||
if((tone_mod = phoneme_tab[p->tone_ph]->std_length) > 0) | |||
{ | |||
if (p->tone_ph != 0) { | |||
if ((tone_mod = phoneme_tab[p->tone_ph]->std_length) > 0) { | |||
// a tone phoneme specifies a percentage change to the length | |||
length_mod = (length_mod * tone_mod) / 100; | |||
} | |||
} | |||
if((end_of_clause == 2) && !(tr->langopts.stress_flags & S_NO_EOC_LENGTHEN)) | |||
{ | |||
if ((end_of_clause == 2) && !(tr->langopts.stress_flags & S_NO_EOC_LENGTHEN)) { | |||
// this is the last syllable in the clause, lengthen it - more for short vowels | |||
len = (p->ph->std_length * 2); | |||
if(tr->langopts.stress_flags & S_EO_CLAUSE1) | |||
len=200; // don't lengthen short vowels more than long vowels at end-of-clause | |||
if (tr->langopts.stress_flags & S_EO_CLAUSE1) | |||
len = 200; // don't lengthen short vowels more than long vowels at end-of-clause | |||
length_mod = length_mod * (256 + (280 - len)/3)/256; | |||
} | |||
if(length_mod > tr->langopts.max_lengthmod*speed1) | |||
{ | |||
//limit the vowel length adjustment for some languages | |||
if (length_mod > tr->langopts.max_lengthmod*speed1) { | |||
// limit the vowel length adjustment for some languages | |||
length_mod = (tr->langopts.max_lengthmod*speed1); | |||
} | |||
length_mod = length_mod / 128; | |||
if(p->type != phVOWEL) | |||
{ | |||
if (p->type != phVOWEL) { | |||
length_mod = 256; // syllabic consonant | |||
min_drop = 16; | |||
} | |||
p->length = length_mod; | |||
if(p->env >= (N_ENVELOPE_DATA-1)) | |||
{ | |||
fprintf(stderr,"espeak: Bad intonation data\n"); | |||
if (p->env >= (N_ENVELOPE_DATA-1)) { | |||
fprintf(stderr, "espeak: Bad intonation data\n"); | |||
p->env = 0; | |||
} | |||
@@ -898,73 +791,61 @@ void CalcLengths(Translator *tr) | |||
// set last-pitch | |||
env2 = p->env + 1; // version for use with preceding semi-vowel | |||
if(p->tone_ph != 0) | |||
{ | |||
if (p->tone_ph != 0) { | |||
InterpretPhoneme2(p->tone_ph, &phdata_tone); | |||
pitch_env = GetEnvelope(phdata_tone.pitch_env); | |||
} | |||
else | |||
{ | |||
} else { | |||
pitch_env = envelope_data[env2]; | |||
} | |||
pitch_start = p->pitch1 + ((p->pitch2-p->pitch1)*pitch_env[0])/256; | |||
if(pre_sonorant || pre_voiced) | |||
{ | |||
if (pre_sonorant || pre_voiced) { | |||
// set pitch for pre-vocalic part | |||
if(pitch_start == 255) | |||
if (pitch_start == 255) | |||
last_pitch = pitch_start; // pitch is not set | |||
if(pitch_start - last_pitch > 16) | |||
if (pitch_start - last_pitch > 16) | |||
last_pitch = pitch_start - 16; | |||
prev->pitch1 = last_pitch; | |||
prev->pitch2 = pitch_start; | |||
if(last_pitch < pitch_start) | |||
{ | |||
if (last_pitch < pitch_start) { | |||
prev->env = PITCHrise; | |||
p->env = env2; | |||
} | |||
else | |||
{ | |||
} else { | |||
prev->env = PITCHfall; | |||
} | |||
prev->length = length_mod; | |||
prev->amp = p->amp; | |||
if((prev->type != phLIQUID) && (prev->amp > 18)) | |||
if ((prev->type != phLIQUID) && (prev->amp > 18)) | |||
prev->amp = 18; | |||
} | |||
// vowel & post-vocalic part | |||
next->synthflags &= ~SFLAG_SEQCONTINUE; | |||
if(next->type == phNASAL && next2->type != phVOWEL) | |||
if (next->type == phNASAL && next2->type != phVOWEL) | |||
next->synthflags |= SFLAG_SEQCONTINUE; | |||
if(next->type == phLIQUID) | |||
{ | |||
if (next->type == phLIQUID) { | |||
next->synthflags |= SFLAG_SEQCONTINUE; | |||
if(next2->type == phVOWEL) | |||
{ | |||
if (next2->type == phVOWEL) { | |||
next->synthflags &= ~SFLAG_SEQCONTINUE; | |||
} | |||
if(next2->type != phVOWEL) | |||
{ | |||
if(next->ph->mnemonic == ('/'*256+'r')) | |||
{ | |||
if (next2->type != phVOWEL) { | |||
if (next->ph->mnemonic == ('/'*256+'r')) { | |||
next->synthflags &= ~SFLAG_SEQCONTINUE; | |||
} | |||
} | |||
} | |||
if((min_drop > 0) && ((p->pitch2 - p->pitch1) < min_drop)) | |||
{ | |||
if ((min_drop > 0) && ((p->pitch2 - p->pitch1) < min_drop)) { | |||
pitch1 = p->pitch2 - min_drop; | |||
if(pitch1 < 0) | |||
if (pitch1 < 0) | |||
pitch1 = 0; | |||
p->pitch1 = pitch1; | |||
} |
@@ -48,54 +48,53 @@ int pk_select; | |||
#define PEAKSHAPEW 256 | |||
static int default_freq[N_PEAKS] = | |||
{200,500,1200,3000,3500,4000,6900,7800,9000}; | |||
{ 200, 500, 1200, 3000, 3500, 4000, 6900, 7800, 9000 }; | |||
static int default_width[N_PEAKS] = | |||
{750,500,550,550,600,700,700,700,700}; | |||
{ 750, 500, 550, 550, 600, 700, 700, 700, 700 }; | |||
static int default_klt_bw[N_PEAKS] = | |||
{89,90,140,260,260,260,500,500,500}; | |||
{ 89, 90, 140, 260, 260, 260, 500, 500, 500 }; | |||
static double read_double(FILE *stream) | |||
{ | |||
unsigned char bytes[10]; | |||
fread(bytes,sizeof(char),10,stream); | |||
fread(bytes, sizeof(char), 10, stream); | |||
return ConvertFromIeeeExtended(bytes); | |||
} | |||
float polint(float xa[],float ya[],int n,float x) | |||
float polint(float xa[], float ya[], int n, float x) | |||
{ | |||
// General polinomial interpolation routine, xa[1...n] ya[1...n] | |||
int i,m,ns=1; | |||
float den,dif,dift,ho,hp,w; | |||
int i, m, ns = 1; | |||
float den, dif, dift, ho, hp, w; | |||
float y; // result | |||
float c[9],d[9]; | |||
float c[9], d[9]; | |||
dif=fabs(x-xa[1]); | |||
dif = fabs(x-xa[1]); | |||
for(i=1; i<=n; i++) { | |||
if((dift=fabs(x-xa[i])) < dif) { | |||
ns=i; | |||
dif=dift; | |||
for (i = 1; i <= n; i++) { | |||
if ((dift = fabs(x-xa[i])) < dif) { | |||
ns = i; | |||
dif = dift; | |||
} | |||
c[i]=ya[i]; | |||
d[i]=ya[i]; | |||
c[i] = ya[i]; | |||
d[i] = ya[i]; | |||
} | |||
y=ya[ns--]; | |||
for(m=1; m<n; m++) { | |||
for(i=1; i<=n-m; i++) { | |||
ho=xa[i]-x; | |||
hp=xa[i+m]-x; | |||
w=c[i+1]-d[i]; | |||
if((den=ho-hp) == 0.0) | |||
{ | |||
return(ya[2]); // two input xa are identical | |||
y = ya[ns--]; | |||
for (m = 1; m < n; m++) { | |||
for (i = 1; i <= n-m; i++) { | |||
ho = xa[i]-x; | |||
hp = xa[i+m]-x; | |||
w = c[i+1]-d[i]; | |||
if ((den = ho-hp) == 0.0) { | |||
return (ya[2]); // two input xa are identical | |||
} | |||
den=w/den; | |||
d[i]=hp*den; | |||
c[i]=ho*den; | |||
den = w/den; | |||
d[i] = hp*den; | |||
c[i] = ho*den; | |||
} | |||
y += ((2*ns < (n-m) ? c[ns+1] : d[ns--])); | |||
} | |||
return(y); | |||
return (y); | |||
} | |||
@@ -115,8 +114,7 @@ static SpectFrame *SpectFrameCreate() | |||
frame->amp_adjust = 100; | |||
frame->length_adjust = 0; | |||
for(ix=0; ix<N_PEAKS; ix++) | |||
{ | |||
for (ix = 0; ix < N_PEAKS; ix++) { | |||
frame->formants[ix].freq = 0; | |||
frame->peaks[ix].pkfreq = default_freq[ix]; | |||
frame->peaks[ix].pkheight = 0; | |||
@@ -136,7 +134,7 @@ static SpectFrame *SpectFrameCreate() | |||
static void SpectFrameDestroy(SpectFrame *frame) | |||
{ | |||
if(frame->spect != NULL) | |||
if (frame->spect != NULL) | |||
free(frame->spect); | |||
free(frame); | |||
} | |||
@@ -153,61 +151,54 @@ int LoadFrame(SpectFrame *frame, FILE *stream, int file_format_type) | |||
frame->pitch = read_double(stream); | |||
frame->length = read_double(stream); | |||
frame->dx = read_double(stream); | |||
fread(&frame->nx,sizeof(short),1,stream); | |||
fread(&frame->markers,sizeof(short),1,stream); | |||
fread(&frame->amp_adjust,sizeof(short),1,stream); | |||
if(file_format_type == 2) | |||
{ | |||
fread(&ix,sizeof(short),1,stream); // spare | |||
fread(&ix,sizeof(short),1,stream); // spare | |||
fread(&frame->nx, sizeof(short), 1, stream); | |||
fread(&frame->markers, sizeof(short), 1, stream); | |||
fread(&frame->amp_adjust, sizeof(short), 1, stream); | |||
if (file_format_type == 2) { | |||
fread(&ix, sizeof(short), 1, stream); // spare | |||
fread(&ix, sizeof(short), 1, stream); // spare | |||
} | |||
for(ix=0; ix<N_PEAKS; ix++) | |||
{ | |||
fread(&frame->formants[ix].freq,sizeof(short),1,stream); | |||
fread(&frame->formants[ix].bandw,sizeof(short),1,stream); | |||
fread(&frame->peaks[ix].pkfreq,sizeof(short),1,stream); | |||
fread(&frame->peaks[ix].pkheight,sizeof(short),1,stream); | |||
fread(&frame->peaks[ix].pkwidth,sizeof(short),1,stream); | |||
fread(&frame->peaks[ix].pkright,sizeof(short),1,stream); | |||
if(frame->peaks[ix].pkheight > 0) | |||
for (ix = 0; ix < N_PEAKS; ix++) { | |||
fread(&frame->formants[ix].freq, sizeof(short), 1, stream); | |||
fread(&frame->formants[ix].bandw, sizeof(short), 1, stream); | |||
fread(&frame->peaks[ix].pkfreq, sizeof(short), 1, stream); | |||
fread(&frame->peaks[ix].pkheight, sizeof(short), 1, stream); | |||
fread(&frame->peaks[ix].pkwidth, sizeof(short), 1, stream); | |||
fread(&frame->peaks[ix].pkright, sizeof(short), 1, stream); | |||
if (frame->peaks[ix].pkheight > 0) | |||
frame->keyframe = 1; | |||
if(file_format_type == 2) | |||
{ | |||
fread(&frame->peaks[ix].klt_bw,sizeof(short),1,stream); | |||
fread(&frame->peaks[ix].klt_ap,sizeof(short),1,stream); | |||
fread(&frame->peaks[ix].klt_bp,sizeof(short),1,stream); | |||
if (file_format_type == 2) { | |||
fread(&frame->peaks[ix].klt_bw, sizeof(short), 1, stream); | |||
fread(&frame->peaks[ix].klt_ap, sizeof(short), 1, stream); | |||
fread(&frame->peaks[ix].klt_bp, sizeof(short), 1, stream); | |||
} | |||
} | |||
if(file_format_type > 0) | |||
{ | |||
for(ix=0; ix<N_KLATTP2; ix++) | |||
{ | |||
fread(frame->klatt_param + ix,sizeof(short),1,stream); | |||
if (file_format_type > 0) { | |||
for (ix = 0; ix < N_KLATTP2; ix++) { | |||
fread(frame->klatt_param + ix, sizeof(short), 1, stream); | |||
} | |||
} | |||
spect_data = malloc(sizeof(USHORT) * frame->nx); | |||
if(spect_data == NULL) | |||
{ | |||
fprintf(stderr,"Failed to allocate memory\n"); | |||
return(1); | |||
if (spect_data == NULL) { | |||
fprintf(stderr, "Failed to allocate memory\n"); | |||
return (1); | |||
} | |||
frame->max_y = 0; | |||
for(ix=0; ix<frame->nx; ix++) | |||
{ | |||
fread(&x,sizeof(short),1,stream); | |||
for (ix = 0; ix < frame->nx; ix++) { | |||
fread(&x, sizeof(short), 1, stream); | |||
spect_data[ix] = x; | |||
if(x > frame->max_y) frame->max_y = x; | |||
if (x > frame->max_y) frame->max_y = x; | |||
} | |||
frame->spect = spect_data; | |||
return(0); | |||
return (0); | |||
} | |||
@@ -215,14 +206,13 @@ int LoadFrame(SpectFrame *frame, FILE *stream, int file_format_type) | |||
double GetFrameRms(SpectFrame *frame, int seq_amplitude) | |||
{ | |||
int h; | |||
float total=0; | |||
float total = 0; | |||
int maxh; | |||
int height; | |||
int htab[400]; | |||
wavegen_peaks_t wpeaks[9]; | |||
for(h=0; h<9; h++) | |||
{ | |||
for (h = 0; h < 9; h++) { | |||
height = (frame->peaks[h].pkheight * seq_amplitude * frame->amp_adjust)/10000; | |||
wpeaks[h].height = height << 8; | |||
@@ -231,13 +221,12 @@ double GetFrameRms(SpectFrame *frame, int seq_amplitude) | |||
wpeaks[h].right = frame->peaks[h].pkright << 16; | |||
} | |||
maxh = PeaksToHarmspect(wpeaks,90<<16,htab,0); | |||
for(h=1; h<maxh; h++) | |||
{ | |||
maxh = PeaksToHarmspect(wpeaks, 90<<16, htab, 0); | |||
for (h = 1; h < maxh; h++) { | |||
total += ((htab[h] * htab[h]) >> 10); | |||
} | |||
frame->rms = sqrt(total) / 7.25; | |||
return(frame->rms); | |||
return (frame->rms); | |||
} | |||
@@ -266,11 +255,9 @@ SpectSeq *SpectSeqCreate() | |||
void SpectSeqDestroy(SpectSeq *spect) | |||
{ | |||
int ix; | |||
if(spect->frames != NULL) | |||
{ | |||
for(ix=0; ix<spect->numframes; ix++) | |||
{ | |||
if(spect->frames[ix] != NULL) | |||
if (spect->frames != NULL) { | |||
for (ix = 0; ix < spect->numframes; ix++) { | |||
if (spect->frames[ix] != NULL) | |||
SpectFrameDestroy(spect->frames[ix]); | |||
} | |||
free(spect->frames); | |||
@@ -283,13 +270,12 @@ void SpectSeqDestroy(SpectSeq *spect) | |||
static float GetFrameLength(SpectSeq *spect, int frame) | |||
{ | |||
int ix; | |||
float adjust=0; | |||
float adjust = 0; | |||
if(frame >= spect->numframes-1) return(0); | |||
if (frame >= spect->numframes-1) return (0); | |||
for(ix=frame+1; ix<spect->numframes-1; ix++) | |||
{ | |||
if(spect->frames[ix]->keyframe) break; // reached next keyframe | |||
for (ix = frame+1; ix < spect->numframes-1; ix++) { | |||
if (spect->frames[ix]->keyframe) break; // reached next keyframe | |||
adjust += spect->frames[ix]->length_adjust; | |||
} | |||
return ((spect->frames[ix]->time - spect->frames[frame]->time) * 1000.0 + adjust); | |||
@@ -302,65 +288,50 @@ int LoadSpectSeq(SpectSeq *spect, const char *filename) | |||
short n, temp; | |||
int ix; | |||
uint32_t id1, id2, name_len; | |||
int set_max_y=0; | |||
int set_max_y = 0; | |||
float time_offset; | |||
FILE *stream = fopen(filename, "rb"); | |||
if(stream == NULL) | |||
{ | |||
if (stream == NULL) { | |||
fprintf(stderr, "Failed to open: '%s'", filename); | |||
return(0); | |||
return (0); | |||
} | |||
fread(&id1,sizeof(uint32_t),1,stream); | |||
fread(&id2,sizeof(uint32_t),1,stream); | |||
fread(&id1, sizeof(uint32_t), 1, stream); | |||
fread(&id2, sizeof(uint32_t), 1, stream); | |||
if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEQ)) | |||
{ | |||
if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEQ)) { | |||
spect->file_format = 0; // eSpeak formants | |||
} | |||
else | |||
if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEK)) | |||
{ | |||
} else if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEK)) { | |||
spect->file_format = 1; // formants for Klatt synthesizer | |||
} | |||
else | |||
if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSQ2)) | |||
{ | |||
} else if ((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSQ2)) { | |||
spect->file_format = 2; // formants for Klatt synthesizer | |||
} | |||
else | |||
{ | |||
} else { | |||
fprintf(stderr, "Unsupported spectral file format.\n"); | |||
fclose(stream); | |||
return(1); | |||
return (1); | |||
} | |||
fread(&name_len,sizeof(uint32_t),1,stream); | |||
if (name_len > 0) | |||
{ | |||
fread(&name_len, sizeof(uint32_t), 1, stream); | |||
if (name_len > 0) { | |||
spect->name = (char *)malloc(name_len); | |||
fread(spect->name,sizeof(char),name_len,stream); | |||
} | |||
else | |||
fread(spect->name, sizeof(char), name_len, stream); | |||
} else | |||
spect->name = NULL; | |||
fread(&n,sizeof(short),1,stream); | |||
fread(&spect->amplitude,sizeof(short),1,stream); | |||
fread(&spect->max_y,sizeof(short),1,stream); | |||
fread(&temp,sizeof(short),1,stream); // unused | |||
fread(&n, sizeof(short), 1, stream); | |||
fread(&spect->amplitude, sizeof(short), 1, stream); | |||
fread(&spect->max_y, sizeof(short), 1, stream); | |||
fread(&temp, sizeof(short), 1, stream); // unused | |||
if(n==0) | |||
{ | |||
if (n == 0) { | |||
fclose(stream); | |||
return(0); | |||
return (0); | |||
} | |||
if(spect->frames != NULL) | |||
{ | |||
for(ix=0; ix<spect->numframes; ix++) | |||
{ | |||
if(spect->frames[ix] != NULL) | |||
if (spect->frames != NULL) { | |||
for (ix = 0; ix < spect->numframes; ix++) { | |||
if (spect->frames[ix] != NULL) | |||
SpectFrameDestroy(spect->frames[ix]); | |||
} | |||
free(spect->frames); | |||
@@ -369,52 +340,48 @@ int LoadSpectSeq(SpectSeq *spect, const char *filename) | |||
spect->numframes = 0; | |||
spect->max_x = 3000; | |||
if(spect->max_y == 0) | |||
{ | |||
if (spect->max_y == 0) { | |||
set_max_y = 1; | |||
spect->max_y = 1; | |||
} | |||
for(ix = 0; ix < n; ix++) | |||
{ | |||
for (ix = 0; ix < n; ix++) { | |||
SpectFrame *frame = SpectFrameCreate(); | |||
if(LoadFrame(frame, stream, spect->file_format) != 0) | |||
{ | |||
if (LoadFrame(frame, stream, spect->file_format) != 0) { | |||
free(frame); | |||
break; | |||
} | |||
spect->frames[spect->numframes++] = frame; | |||
if(set_max_y && (frame->max_y > spect->max_y)) | |||
if (set_max_y && (frame->max_y > spect->max_y)) | |||
spect->max_y = frame->max_y; | |||
if(frame->nx * frame->dx > spect->max_x) spect->max_x = (int)(frame->nx * frame->dx); | |||
if (frame->nx * frame->dx > spect->max_x) spect->max_x = (int)(frame->nx * frame->dx); | |||
} | |||
spect->max_x = 9000; // disable auto-xscaling | |||
frame_width = (int)((FRAME_WIDTH*spect->max_x)/MAX_DISPLAY_FREQ); | |||
if(frame_width > FRAME_WIDTH) frame_width = FRAME_WIDTH; | |||
if (frame_width > FRAME_WIDTH) frame_width = FRAME_WIDTH; | |||
// start times from zero | |||
time_offset = spect->frames[0]->time; | |||
for(ix=0; ix<spect->numframes; ix++) | |||
for (ix = 0; ix < spect->numframes; ix++) | |||
spect->frames[ix]->time -= time_offset; | |||
spect->pitch1 = spect->pitchenv.pitch1; | |||
spect->pitch2 = spect->pitchenv.pitch2; | |||
spect->duration = (int)(spect->frames[spect->numframes-1]->time * 1000); | |||
if(spect->max_y < 400) | |||
if (spect->max_y < 400) | |||
spect->max_y = 200; | |||
else | |||
spect->max_y = 29000; // disable auto height scaling | |||
for(ix=0; ix<spect->numframes; ix++) | |||
{ | |||
if(spect->frames[ix]->keyframe) | |||
spect->frames[ix]->length_adjust = spect->frames[ix]->length - GetFrameLength(spect,ix); | |||
for (ix = 0; ix < spect->numframes; ix++) { | |||
if (spect->frames[ix]->keyframe) | |||
spect->frames[ix]->length_adjust = spect->frames[ix]->length - GetFrameLength(spect, ix); | |||
} | |||
fclose(stream); | |||
return(0); | |||
return (0); | |||
} |
@@ -87,8 +87,7 @@ typedef struct { | |||
} peak_t; | |||
typedef struct | |||
{ | |||
typedef struct { | |||
int keyframe; | |||
short amp_adjust; | |||
float length_adjust; | |||
@@ -111,8 +110,7 @@ typedef struct | |||
double GetFrameRms(SpectFrame *frame, int amp); | |||
typedef struct | |||
{ | |||
typedef struct { | |||
int numframes; | |||
short amplitude; | |||
int spare; |
@@ -86,7 +86,7 @@ int LookupMnem(MNEM_TAB *table, const char *string); | |||
extern char path_home[N_PATH_HOME]; // this is the espeak-data directory | |||
extern void strncpy0(char *to,const char *from, int size); | |||
extern void strncpy0(char *to, const char *from, int size); | |||
int GetFileLength(const char *filename); | |||
char *Alloc(int size); | |||
void Free(void *ptr); |
@@ -54,8 +54,8 @@ typedef void (WINAPI *PROCVI)(int); | |||
typedef void (WINAPI *PROCVF)(float); | |||
typedef int (WINAPI *PROCIV)(); | |||
typedef int (WINAPI *PROCIC)(char *); | |||
typedef int (WINAPI *PROCISI)(short *,int); | |||
typedef char* (WINAPI *PROCVCI)(char *,int); | |||
typedef int (WINAPI *PROCISI)(short *, int); | |||
typedef char * (WINAPI *PROCVCI)(char *, int); | |||
PROCIC init_MBR; | |||
PROCIC write_MBR; | |||
@@ -76,31 +76,30 @@ HINSTANCE hinstDllMBR = NULL; | |||
BOOL load_MBR() | |||
{ | |||
if(hinstDllMBR != NULL) | |||
if (hinstDllMBR != NULL) | |||
return TRUE; // already loaded | |||
if ((hinstDllMBR=LoadLibraryA("mbrola.dll")) == 0) | |||
if ((hinstDllMBR = LoadLibraryA("mbrola.dll")) == 0) | |||
return FALSE; | |||
init_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"init_MBR"); | |||
write_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"write_MBR"); | |||
flush_MBR =(PROCIV) GetProcAddress(hinstDllMBR,"flush_MBR"); | |||
read_MBR =(PROCISI) GetProcAddress(hinstDllMBR,"read_MBR"); | |||
close_MBR =(PROCVV) GetProcAddress(hinstDllMBR,"close_MBR"); | |||
reset_MBR =(PROCVV) GetProcAddress(hinstDllMBR,"reset_MBR"); | |||
lastError_MBR =(PROCIV) GetProcAddress(hinstDllMBR,"lastError_MBR"); | |||
lastErrorStr_MBR =(PROCVCI) GetProcAddress(hinstDllMBR,"lastErrorStr_MBR"); | |||
setNoError_MBR =(PROCVI) GetProcAddress(hinstDllMBR,"setNoError_MBR"); | |||
setVolumeRatio_MBR =(PROCVF) GetProcAddress(hinstDllMBR,"setVolumeRatio_MBR"); | |||
init_MBR = (PROCIC)GetProcAddress(hinstDllMBR, "init_MBR"); | |||
write_MBR = (PROCIC)GetProcAddress(hinstDllMBR, "write_MBR"); | |||
flush_MBR = (PROCIV)GetProcAddress(hinstDllMBR, "flush_MBR"); | |||
read_MBR = (PROCISI)GetProcAddress(hinstDllMBR, "read_MBR"); | |||
close_MBR = (PROCVV)GetProcAddress(hinstDllMBR, "close_MBR"); | |||
reset_MBR = (PROCVV)GetProcAddress(hinstDllMBR, "reset_MBR"); | |||
lastError_MBR = (PROCIV)GetProcAddress(hinstDllMBR, "lastError_MBR"); | |||
lastErrorStr_MBR = (PROCVCI)GetProcAddress(hinstDllMBR, "lastErrorStr_MBR"); | |||
setNoError_MBR = (PROCVI)GetProcAddress(hinstDllMBR, "setNoError_MBR"); | |||
setVolumeRatio_MBR = (PROCVF)GetProcAddress(hinstDllMBR, "setVolumeRatio_MBR"); | |||
return TRUE; | |||
} | |||
void unload_MBR() | |||
{ | |||
if (hinstDllMBR) | |||
{ | |||
FreeLibrary (hinstDllMBR); | |||
hinstDllMBR=NULL; | |||
if (hinstDllMBR) { | |||
FreeLibrary(hinstDllMBR); | |||
hinstDllMBR = NULL; | |||
} | |||
} | |||
@@ -125,79 +124,72 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int | |||
mbrola_delay = 0; | |||
mbr_name_prefix = 0; | |||
if(mbrola_voice == NULL) | |||
{ | |||
if (mbrola_voice == NULL) { | |||
samplerate = samplerate_native; | |||
SetParameter(espeakVOICETYPE,0,0); | |||
return(EE_OK); | |||
SetParameter(espeakVOICETYPE, 0, 0); | |||
return (EE_OK); | |||
} | |||
sprintf(path,"%s/mbrola/%s",path_home,mbrola_voice); | |||
sprintf(path, "%s/mbrola/%s", path_home, mbrola_voice); | |||
#ifdef PLATFORM_POSIX | |||
// if not found, then also look in | |||
// usr/share/mbrola/xx, /usr/share/mbrola/xx/xx, /usr/share/mbrola/voices/xx | |||
if(GetFileLength(path) <= 0) | |||
{ | |||
sprintf(path,"/usr/share/mbrola/%s",mbrola_voice); | |||
if (GetFileLength(path) <= 0) { | |||
sprintf(path, "/usr/share/mbrola/%s", mbrola_voice); | |||
if(GetFileLength(path) <= 0) | |||
{ | |||
sprintf(path,"/usr/share/mbrola/%s/%s",mbrola_voice,mbrola_voice); | |||
if (GetFileLength(path) <= 0) { | |||
sprintf(path, "/usr/share/mbrola/%s/%s", mbrola_voice, mbrola_voice); | |||
if(GetFileLength(path) <= 0) | |||
{ | |||
sprintf(path,"/usr/share/mbrola/voices/%s",mbrola_voice); | |||
if (GetFileLength(path) <= 0) { | |||
sprintf(path, "/usr/share/mbrola/voices/%s", mbrola_voice); | |||
} | |||
} | |||
} | |||
close_MBR(); | |||
#endif | |||
#ifdef PLATFORM_WINDOWS | |||
if(load_MBR() == FALSE) // load mbrola.dll | |||
{ | |||
if (load_MBR() == FALSE) { // load mbrola.dll | |||
fprintf(stderr, "Can't load mbrola.dll\n"); | |||
return(EE_INTERNAL_ERROR); | |||
return (EE_INTERNAL_ERROR); | |||
} | |||
#endif | |||
if(init_MBR(path) != 0) // initialise the required mbrola voice | |||
return(EE_NOT_FOUND); | |||
if (init_MBR(path) != 0) // initialise the required mbrola voice | |||
return (EE_NOT_FOUND); | |||
setNoError_MBR(1); // don't stop on phoneme errors | |||
// read eSpeak's mbrola phoneme translation data, eg. en1_phtrans | |||
sprintf(path,"%s/mbrola_ph/%s",path_home,phtrans); | |||
sprintf(path, "%s/mbrola_ph/%s", path_home, phtrans); | |||
size = GetFileLength(path); | |||
if((f_in = fopen(path,"rb")) == NULL) { | |||
if ((f_in = fopen(path, "rb")) == NULL) { | |||
close_MBR(); | |||
return(EE_NOT_FOUND); | |||
return (EE_NOT_FOUND); | |||
} | |||
if((mbrola_tab = (MBROLA_TAB *)realloc(mbrola_tab,size)) == NULL) | |||
{ | |||
if ((mbrola_tab = (MBROLA_TAB *)realloc(mbrola_tab, size)) == NULL) { | |||
fclose(f_in); | |||
close_MBR(); | |||
return(EE_INTERNAL_ERROR); | |||
return (EE_INTERNAL_ERROR); | |||
} | |||
mbrola_control = Read4Bytes(f_in); | |||
pw = (int *)mbrola_tab; | |||
for(ix=4; ix<size; ix+=4) | |||
{ | |||
for (ix = 4; ix < size; ix += 4) { | |||
*pw++ = Read4Bytes(f_in); | |||
} | |||
size = fread(mbrola_tab,1,size,f_in); | |||
size = fread(mbrola_tab, 1, size, f_in); | |||
fclose(f_in); | |||
setVolumeRatio_MBR((float)(mbrola_control & 0xff) /16.0f); | |||
samplerate = *srate = getFreq_MBR(); | |||
if(*srate == 22050) | |||
SetParameter(espeakVOICETYPE,0,0); | |||
if (*srate == 22050) | |||
SetParameter(espeakVOICETYPE, 0, 0); | |||
else | |||
SetParameter(espeakVOICETYPE,1,0); | |||
strcpy(mbrola_name,mbrola_voice); | |||
SetParameter(espeakVOICETYPE, 1, 0); | |||
strcpy(mbrola_name, mbrola_voice); | |||
mbrola_delay = 1000; // improve synchronization of events | |||
return(EE_OK); | |||
return (EE_OK); | |||
} | |||
@@ -219,60 +211,50 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev | |||
// bit 5 only in stressed syllable | |||
// bit 6 only at the end of a word | |||
*name2=0; | |||
*split=0; | |||
*control=0; | |||
*name2 = 0; | |||
*split = 0; | |||
*control = 0; | |||
mnem = ph->mnemonic; | |||
pr = mbrola_tab; | |||
while(pr->name != 0) | |||
{ | |||
if(mnem == pr->name) | |||
{ | |||
if(pr->next_phoneme == 0) | |||
while (pr->name != 0) { | |||
if (mnem == pr->name) { | |||
if (pr->next_phoneme == 0) | |||
found = 1; | |||
else | |||
if((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN)) | |||
{ | |||
else if ((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN)) { | |||
found = 1; | |||
} | |||
else | |||
{ | |||
if(pr->control & 2) | |||
} else { | |||
if (pr->control & 2) | |||
other_ph = ph_prev; | |||
else | |||
if((pr->control & 8) && ((plist+1)->newword)) | |||
else if ((pr->control & 8) && ((plist+1)->newword)) | |||
other_ph = phoneme_tab[phPAUSE]; // don't match the next phoneme over a word boundary | |||
else | |||
other_ph = ph_next; | |||
if((pr->next_phoneme == other_ph->mnemonic) || | |||
((pr->next_phoneme == 2) && (other_ph->type == phVOWEL)) || | |||
((pr->next_phoneme == '_') && (other_ph->type == phPAUSE))) | |||
{ | |||
if ((pr->next_phoneme == other_ph->mnemonic) || | |||
((pr->next_phoneme == 2) && (other_ph->type == phVOWEL)) || | |||
((pr->next_phoneme == '_') && (other_ph->type == phPAUSE))) { | |||
found = 1; | |||
} | |||
} | |||
if((pr->control & 4) && (plist->newword == 0)) // only at start of word | |||
if ((pr->control & 4) && (plist->newword == 0)) // only at start of word | |||
found = 0; | |||
if((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word | |||
if ((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word | |||
found = 0; | |||
if((pr->control & 0x20) && (plist->stresslevel < plist->wordstress)) | |||
if ((pr->control & 0x20) && (plist->stresslevel < plist->wordstress)) | |||
found = 0; // only in stressed syllables | |||
if(found) | |||
{ | |||
if (found) { | |||
*name2 = pr->mbr_name2; | |||
*split = pr->percent; | |||
*control = pr->control; | |||
if(pr->control & 0x10) | |||
{ | |||
if (pr->control & 0x10) { | |||
mbr_name_prefix = pr->mbr_name; | |||
return(0); | |||
return (0); | |||
} | |||
mnem = pr->mbr_name; | |||
break; | |||
@@ -282,12 +264,11 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev | |||
pr++; | |||
} | |||
if(mbr_name_prefix != 0) | |||
{ | |||
if (mbr_name_prefix != 0) { | |||
mnem = (mnem << 8) | (mbr_name_prefix & 0xff); | |||
} | |||
mbr_name_prefix = 0; | |||
return(mnem); | |||
return (mnem); | |||
} | |||
@@ -298,12 +279,12 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
int ix; | |||
int pitch_base; | |||
int pitch_range; | |||
int p1,p2,p_end; | |||
int p1, p2, p_end; | |||
unsigned char *pitch_env; | |||
int max = -1; | |||
int min = 999; | |||
int y_max=0; | |||
int y_min=0; | |||
int y_max = 0; | |||
int y_min = 0; | |||
int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s) | |||
int y2; | |||
int y[4]; | |||
@@ -319,19 +300,16 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
env_split = (split * 128)/100; | |||
if(env_split < 0) | |||
if (env_split < 0) | |||
env_split = 0-env_split; | |||
// find max and min in the pitch envelope | |||
for(x=0; x<128; x++) | |||
{ | |||
if(pitch_env[x] > max) | |||
{ | |||
for (x = 0; x < 128; x++) { | |||
if (pitch_env[x] > max) { | |||
max = pitch_env[x]; | |||
y_max = x; | |||
} | |||
if(pitch_env[x] < min) | |||
{ | |||
if (pitch_env[x] < min) { | |||
min = pitch_env[x]; | |||
y_min = x; | |||
} | |||
@@ -339,12 +317,10 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
// set an additional pitch point half way through the phoneme. | |||
// but look for a maximum or a minimum and use that instead | |||
y[2] = 64; | |||
if((y_max > 0) && (y_max < 127)) | |||
{ | |||
if ((y_max > 0) && (y_max < 127)) { | |||
y[2] = y_max; | |||
} | |||
if((y_min > 0) && (y_min < 127)) | |||
{ | |||
if ((y_min > 0) && (y_min < 127)) { | |||
y[2] = y_min; | |||
} | |||
y[1] = y[2] / 2; | |||
@@ -355,56 +331,44 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final) | |||
p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base; | |||
if(split >= 0) | |||
{ | |||
sprintf(buf," 0 %d",p1/4096); | |||
strcat(output,buf); | |||
if (split >= 0) { | |||
sprintf(buf, " 0 %d", p1/4096); | |||
strcat(output, buf); | |||
} | |||
// don't use intermediate pitch points for linear rise and fall | |||
if(env > 1) | |||
{ | |||
for(ix=1; ix<4; ix++) | |||
{ | |||
if (env > 1) { | |||
for (ix = 1; ix < 4; ix++) { | |||
p2 = ((pitch_env[y[ix]]*pitch_range)>>8) + pitch_base; | |||
if(split > 0) | |||
{ | |||
if (split > 0) { | |||
y2 = (y[ix] * env100)/env_split; | |||
} | |||
else | |||
if(split < 0) | |||
{ | |||
} else if (split < 0) { | |||
y2 = ((y[ix]-env_split) * env100)/env_split; | |||
} | |||
else | |||
{ | |||
} else { | |||
y2 = (y[ix] * env100)/128; | |||
} | |||
if((y2 > 0) && (y2 <= env100)) | |||
{ | |||
sprintf(buf," %d %d",y2,p2/4096); | |||
strcat(output,buf); | |||
if ((y2 > 0) && (y2 <= env100)) { | |||
sprintf(buf, " %d %d", y2, p2/4096); | |||
strcat(output, buf); | |||
} | |||
} | |||
} | |||
p_end = p_end/4096; | |||
if(split <= 0) | |||
{ | |||
sprintf(buf," %d %d",env100,p_end); | |||
strcat(output,buf); | |||
if (split <= 0) { | |||
sprintf(buf, " %d %d", env100, p_end); | |||
strcat(output, buf); | |||
} | |||
if(env100 < 100) | |||
{ | |||
sprintf(buf," %d %d",100,p_end); | |||
strcat(output,buf); | |||
if (env100 < 100) { | |||
sprintf(buf, " %d %d", 100, p_end); | |||
strcat(output, buf); | |||
} | |||
strcat(output,"\n"); | |||
strcat(output, "\n"); | |||
if(final) | |||
sprintf(output,"\t100 %d\n",p_end); | |||
return(output); | |||
if (final) | |||
sprintf(output, "\t100 %d\n", p_end); | |||
return (output); | |||
} | |||
@@ -441,8 +405,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
word_count = 0; | |||
} | |||
while (phix < n_phonemes) | |||
{ | |||
while (phix < n_phonemes) { | |||
if (WcmdqFree() < MIN_WCMDQ) | |||
return 1; | |||
@@ -454,47 +417,42 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
ph_prev = plist[phix-1].ph; | |||
ph_next = plist[phix+1].ph; | |||
if(p->synthflags & SFLAG_EMBEDDED) | |||
{ | |||
if (p->synthflags & SFLAG_EMBEDDED) { | |||
DoEmbedded(&embedded_ix, p->sourceix); | |||
} | |||
if(p->newword & 4) | |||
if (p->newword & 4) | |||
DoMarker(espeakEVENT_SENTENCE, (p->sourceix & 0x7ff) + clause_start_char, 0, count_sentences); | |||
if(p->newword & 1) | |||
if (p->newword & 1) | |||
DoMarker(espeakEVENT_WORD, (p->sourceix & 0x7ff) + clause_start_char, p->sourceix >> 11, clause_start_word + word_count++); | |||
name = GetMbrName(p,ph,ph_prev,ph_next,&name2,&len_percent,&control); | |||
if(control & 1) | |||
name = GetMbrName(p, ph, ph_prev, ph_next, &name2, &len_percent, &control); | |||
if (control & 1) | |||
phix++; | |||
if(name == 0) { | |||
if (name == 0) { | |||
phix++; | |||
continue; // ignore this phoneme | |||
} | |||
if((ph->type == phPAUSE) && (name == ph->mnemonic)) | |||
{ | |||
if ((ph->type == phPAUSE) && (name == ph->mnemonic)) { | |||
// a pause phoneme, which has not been changed by the translation | |||
name = '_'; | |||
len = (p->length * speed.pause_factor)/256; | |||
if(len == 0) | |||
if (len == 0) | |||
len = 1; | |||
} | |||
else | |||
} else | |||
len = (80 * speed.wav_factor)/256; | |||
if(ph->code != phonEND_WORD) | |||
{ | |||
if (ph->code != phonEND_WORD) { | |||
char phoneme_name[16]; | |||
WritePhMnemonic(phoneme_name, p->ph, p, option_phoneme_events & espeakINITIALIZE_PHONEME_IPA, NULL); | |||
DoPhonemeMarker(espeakEVENT_PHONEME, (p->sourceix & 0x7ff) + clause_start_char, 0, phoneme_name); | |||
} | |||
ptr += sprintf(ptr,"%s\t",WordToString(name)); | |||
ptr += sprintf(ptr, "%s\t", WordToString(name)); | |||
if(name2 == '_') | |||
{ | |||
if (name2 == '_') { | |||
// add a pause after this phoneme | |||
pause = len_percent; | |||
name2 = 0; | |||
@@ -503,48 +461,45 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
done = 0; | |||
final_pitch = ""; | |||
switch(ph->type) | |||
switch (ph->type) | |||
{ | |||
case phVOWEL: | |||
len = ph->std_length; | |||
if(p->synthflags & SFLAG_LENGTHEN) | |||
if (p->synthflags & SFLAG_LENGTHEN) | |||
len += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol | |||
if(ph_next->type == phPAUSE) | |||
if (ph_next->type == phPAUSE) | |||
len += 50; // lengthen vowels before a pause | |||
len = (len * p->length)/256; | |||
if(name2 == 0) | |||
{ | |||
char *pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,0); | |||
ptr += sprintf(ptr,"%d\t%s", len, pitch); | |||
} | |||
else | |||
{ | |||
if (name2 == 0) { | |||
char *pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 0); | |||
ptr += sprintf(ptr, "%d\t%s", len, pitch); | |||
} else { | |||
char *pitch; | |||
pitch = WritePitch(p->env,p->pitch1,p->pitch2,len_percent,0); | |||
pitch = WritePitch(p->env, p->pitch1, p->pitch2, len_percent, 0); | |||
len1 = (len * len_percent)/100; | |||
ptr += sprintf(ptr,"%d\t%s", len1, pitch); | |||
ptr += sprintf(ptr, "%d\t%s", len1, pitch); | |||
pitch = WritePitch(p->env,p->pitch1,p->pitch2,-len_percent,0); | |||
ptr += sprintf(ptr,"%s\t%d\t%s", WordToString(name2), len-len1, pitch); | |||
pitch = WritePitch(p->env, p->pitch1, p->pitch2, -len_percent, 0); | |||
ptr += sprintf(ptr, "%s\t%d\t%s", WordToString(name2), len-len1, pitch); | |||
} | |||
done = 1; | |||
break; | |||
case phSTOP: | |||
released = 0; | |||
if(next->type==phVOWEL) released = 1; | |||
if(next->type==phLIQUID && !next->newword) released = 1; | |||
if (next->type == phVOWEL) released = 1; | |||
if (next->type == phLIQUID && !next->newword) released = 1; | |||
if(released == 0) | |||
if (released == 0) | |||
p->synthflags |= SFLAG_NEXT_PAUSE; | |||
InterpretPhoneme(NULL, 0, p, &phdata, NULL); | |||
len = DoSample3(&phdata, 0, -1); | |||
len = (len * 1000)/samplerate; // convert to mS | |||
len += PauseLength(p->prepause,1); | |||
len += PauseLength(p->prepause, 1); | |||
break; | |||
case phVSTOP: | |||
@@ -554,7 +509,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
case phFRICATIVE: | |||
len = 0; | |||
InterpretPhoneme(NULL, 0, p, &phdata, NULL); | |||
if(p->synthflags & SFLAG_LENGTHEN) | |||
if (p->synthflags & SFLAG_LENGTHEN) | |||
len = DoSample3(&phdata, p->length, -1); // play it twice for [s:] etc. | |||
len += DoSample3(&phdata, p->length, -1); | |||
@@ -562,52 +517,44 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
break; | |||
case phNASAL: | |||
if(next->type != phVOWEL) | |||
{ | |||
if (next->type != phVOWEL) { | |||
memset(&fmtp, 0, sizeof(fmtp)); | |||
InterpretPhoneme(NULL, 0, p, &phdata, NULL); | |||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT]; | |||
len = DoSpect2(p->ph, 0, &fmtp, p, -1); | |||
len = (len * 1000)/samplerate; | |||
if(next->type == phPAUSE) | |||
if (next->type == phPAUSE) | |||
len += 50; | |||
final_pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,1); | |||
final_pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 1); | |||
} | |||
break; | |||
case phLIQUID: | |||
if(next->type == phPAUSE) | |||
{ | |||
if (next->type == phPAUSE) { | |||
len += 50; | |||
final_pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,1); | |||
final_pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 1); | |||
} | |||
break; | |||
} | |||
if(!done) | |||
{ | |||
if(name2 != 0) | |||
{ | |||
if (!done) { | |||
if (name2 != 0) { | |||
len1 = (len * len_percent)/100; | |||
ptr += sprintf(ptr,"%d\n%s\t",len1,WordToString(name2)); | |||
ptr += sprintf(ptr, "%d\n%s\t", len1, WordToString(name2)); | |||
len -= len1; | |||
} | |||
ptr += sprintf(ptr,"%d%s\n",len,final_pitch); | |||
ptr += sprintf(ptr, "%d%s\n", len, final_pitch); | |||
} | |||
if(pause) | |||
{ | |||
len += PauseLength(pause,0); | |||
ptr += sprintf(ptr,"_ \t%d\n",PauseLength(pause,0)); | |||
if (pause) { | |||
len += PauseLength(pause, 0); | |||
ptr += sprintf(ptr, "_ \t%d\n", PauseLength(pause, 0)); | |||
pause = 0; | |||
} | |||
if(f_mbrola) | |||
{ | |||
fwrite(mbr_buf,1,(ptr-mbr_buf),f_mbrola); // write .pho to a file | |||
} | |||
else | |||
{ | |||
if (f_mbrola) { | |||
fwrite(mbr_buf, 1, (ptr-mbr_buf), f_mbrola); // write .pho to a file | |||
} else { | |||
int res = write_MBR(mbr_buf); | |||
if (res < 0) | |||
return 0; /* don't get stuck on error */ | |||
@@ -621,8 +568,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr | |||
phix++; | |||
} | |||
if(!f_mbrola) | |||
{ | |||
if (!f_mbrola) { | |||
flush_MBR(); | |||
// flush the mbrola output buffer | |||
@@ -639,11 +585,10 @@ int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
{ | |||
FILE *f_mbrola = NULL; | |||
if(*n_ph == 0) | |||
return(0); | |||
if (*n_ph == 0) | |||
return (0); | |||
if(option_phonemes & espeakPHONEMES_MBROLA) | |||
{ | |||
if (option_phonemes & espeakPHONEMES_MBROLA) { | |||
// send mbrola data to a file, not to the mbrola library | |||
f_mbrola = f_trans; | |||
} | |||
@@ -675,14 +620,13 @@ int MbrolaFill(int length, int resume, int amplitude) | |||
if (result <= 0) | |||
return 0; | |||
for(ix=0; ix < result; ix++) | |||
{ | |||
for (ix = 0; ix < result; ix++) { | |||
value16 = out_ptr[0] + (out_ptr[1] << 8); | |||
value = value16 * amplitude; | |||
value = value / 40; // adjust this constant to give a suitable amplitude for mbrola voices | |||
if(value > 0x7fff) | |||
if (value > 0x7fff) | |||
value = 0x7fff; | |||
if(value < -0x8000) | |||
if (value < -0x8000) | |||
value = 0x8000; | |||
out_ptr[0] = value; | |||
out_ptr[1] = value >> 8; | |||
@@ -706,17 +650,17 @@ void MbrolaReset(void) | |||
espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate) | |||
{ | |||
return(EE_INTERNAL_ERROR); | |||
return (EE_INTERNAL_ERROR); | |||
} | |||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume) | |||
{ | |||
return(0); | |||
return (0); | |||
} | |||
int MbrolaFill(int length, int resume, int amplitude) | |||
{ | |||
return(0); | |||
return (0); | |||
} | |||
void MbrolaReset(void) |
@@ -490,7 +490,7 @@ int WavegenOpenSound(); | |||
int WavegenCloseSound(); | |||
int WavegenInitSound(); | |||
void WavegenInit(int rate, int wavemult_fact); | |||
float polint(float xa[],float ya[],int n,float x); | |||
float polint(float xa[], float ya[], int n, float x); | |||
int WavegenFill(int fill_zeros); | |||
void MarkerEvent(int type, unsigned int char_position, int value, int value2, unsigned char *out_ptr); | |||
@@ -536,7 +536,7 @@ int SelectPhonemeTableName(const char *name); | |||
void Write4Bytes(FILE *f, int value); | |||
int Read4Bytes(FILE *f); | |||
int Reverse4Bytes(int word); | |||
int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name,int flags); | |||
int CompileDictionary(const char *dsource, const char *dict_name, FILE *log, char *err_name, int flags); | |||
#define ENV_LEN 128 // length of pitch envelopes | |||
@@ -555,7 +555,7 @@ extern unsigned char *out_start; | |||
extern unsigned char *out_end; | |||
extern int event_list_ix; | |||
extern espeak_EVENT *event_list; | |||
extern t_espeak_callback* synth_callback; | |||
extern t_espeak_callback *synth_callback; | |||
extern const char *version_string; | |||
extern const int version_phdata; | |||
extern double sonicSpeed; |
@@ -22,7 +22,7 @@ extern "C" | |||
{ | |||
#endif | |||
#define L(c1,c2) (c1<<8)+c2 // combine two characters into an integer for translator name | |||
#define L(c1, c2) (c1<<8)+c2 // combine two characters into an integer for translator name | |||
#define CTRL_EMBEDDED 0x01 // control character at the start of an embedded command | |||
#define REPLACED_E 'E' // 'e' replaced by silent e | |||
@@ -252,7 +252,7 @@ extern "C" | |||
// match 1 pre 2 post 0 - use common phoneme string | |||
// match 1 pre 2 post 3 0 - empty phoneme string | |||
typedef const char * constcharptr; | |||
typedef const char *constcharptr; | |||
typedef struct { | |||
int points; | |||
@@ -601,8 +601,7 @@ typedef struct { | |||
typedef struct | |||
{ | |||
typedef struct { | |||
LANGUAGE_OPTIONS langopts; | |||
int translator_name; | |||
@@ -723,8 +722,8 @@ extern unsigned char *p_textinput; | |||
extern wchar_t *p_wchar_input; | |||
extern int dictionary_skipwords; | |||
extern int (* uri_callback)(int, const char *, const char *); | |||
extern int (* phoneme_callback)(const char *); | |||
extern int (*uri_callback)(int, const char *, const char *); | |||
extern int (*phoneme_callback)(const char *); | |||
extern void SetLengthMods(Translator *tr, int value); | |||
void LoadConfig(void); | |||
@@ -733,8 +732,8 @@ int utf8_in(int *c, const char *buf); | |||
int utf8_in2(int *c, const char *buf, int backwards); | |||
int utf8_out(unsigned int c, char *buf); | |||
int utf8_nbytes(const char *buf); | |||
int lookupwchar(const unsigned short *list,int c); | |||
int lookupwchar2(const unsigned short *list,int c); | |||
int lookupwchar(const unsigned short *list, int c); | |||
int lookupwchar2(const unsigned short *list, int c); | |||
int Eof(void); | |||
char *strchr_w(const char *s, int c); | |||
int IsBracket(int c); |
@@ -32,15 +32,15 @@ extern "C" | |||
extern int option_device_number; | |||
extern int wave_init(int samplerate); | |||
extern void* wave_open(const char* the_api); | |||
extern void *wave_open(const char *the_api); | |||
extern size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize); | |||
extern int wave_close(void* theHandler); | |||
extern void wave_flush(void* theHandler); | |||
extern int wave_is_busy(void* theHandler); | |||
extern size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize); | |||
extern int wave_close(void *theHandler); | |||
extern void wave_flush(void *theHandler); | |||
extern int wave_is_busy(void *theHandler); | |||
extern void wave_terminate(); | |||
extern uint32_t wave_get_read_position(void* theHandler); | |||
extern uint32_t wave_get_write_position(void* theHandler); | |||
extern uint32_t wave_get_read_position(void *theHandler); | |||
extern uint32_t wave_get_write_position(void *theHandler); | |||
// Supply the remaining time in ms before the sample is played | |||
// (or 0 if the event has been already played). | |||
@@ -48,12 +48,12 @@ extern uint32_t wave_get_write_position(void* theHandler); | |||
// time: supplied value in ms | |||
// | |||
// return 0 if ok or -1 otherwise (stream not opened). | |||
extern int wave_get_remaining_time(uint32_t sample, uint32_t* time); | |||
extern int wave_get_remaining_time(uint32_t sample, uint32_t *time); | |||
// set the callback which informs if the output is still enabled. | |||
// Helpful if a new sample is waiting for free space whereas sound must be stopped. | |||
typedef int (t_wave_callback)(void); | |||
extern void wave_set_callback_is_output_enabled(t_wave_callback* cb); | |||
extern void wave_set_callback_is_output_enabled(t_wave_callback *cb); | |||
// general functions |
@@ -48,7 +48,7 @@ | |||
#include "wave.h" | |||
#include "debug.h" | |||
enum {ONE_BILLION=1000000000}; | |||
enum { ONE_BILLION = 1000000000 }; | |||
enum { | |||
/* return value */ | |||
@@ -59,7 +59,7 @@ enum { | |||
#ifdef USE_PULSEAUDIO | |||
static t_wave_callback* my_callback_is_output_enabled=NULL; | |||
static t_wave_callback *my_callback_is_output_enabled = NULL; | |||
#define SAMPLE_RATE 22050 | |||
#define ESPEAK_FORMAT PA_SAMPLE_S16LE | |||
@@ -126,7 +126,7 @@ static int wave_samplerate; | |||
SHOW("Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \ | |||
goto label; \ | |||
} \ | |||
} while(0); | |||
} while (0); | |||
#define CHECK_CONNECTED(retval) \ | |||
do { \ | |||
@@ -154,7 +154,8 @@ static void context_state_cb(pa_context *c, void *userdata) { | |||
ENTER(__FUNCTION__); | |||
assert(c); | |||
switch (pa_context_get_state(c)) { | |||
switch (pa_context_get_state(c)) | |||
{ | |||
case PA_CONTEXT_READY: | |||
case PA_CONTEXT_TERMINATED: | |||
case PA_CONTEXT_FAILED: | |||
@@ -169,11 +170,12 @@ static void context_state_cb(pa_context *c, void *userdata) { | |||
} | |||
} | |||
static void stream_state_cb(pa_stream *s, void * userdata) { | |||
static void stream_state_cb(pa_stream *s, void *userdata) { | |||
ENTER(__FUNCTION__); | |||
assert(s); | |||
switch (pa_stream_get_state(s)) { | |||
switch (pa_stream_get_state(s)) | |||
{ | |||
case PA_STREAM_READY: | |||
case PA_STREAM_FAILED: | |||
@@ -192,7 +194,7 @@ static void stream_success_cb(pa_stream *s, int success, void *userdata) { | |||
assert(s); | |||
if (userdata) | |||
*(int*) userdata = success; | |||
*(int *)userdata = success; | |||
pa_threaded_mainloop_signal(mainloop, 0); | |||
} | |||
@@ -202,7 +204,7 @@ static void context_success_cb(pa_context *c, int success, void *userdata) { | |||
assert(c); | |||
if (userdata) | |||
*(int*) userdata = success; | |||
*(int *)userdata = success; | |||
pa_threaded_mainloop_signal(mainloop, 0); | |||
} | |||
@@ -231,7 +233,7 @@ static int pulse_free(void) { | |||
pa_threaded_mainloop_lock(mainloop); | |||
CHECK_DEAD_GOTO(fail, 1); | |||
if ((l = pa_stream_writable_size(stream)) == (size_t) -1) { | |||
if ((l = pa_stream_writable_size(stream)) == (size_t)-1) { | |||
SHOW("pa_stream_writable_size() failed: %s", pa_strerror(pa_context_errno(context))); | |||
l = 0; | |||
goto fail; | |||
@@ -271,7 +273,7 @@ fail: | |||
do_trigger = !!l; | |||
SHOW("pulse_free: %d (ret)\n", (int)l); | |||
return (int) l; | |||
return (int)l; | |||
} | |||
static int pulse_playing(const pa_timing_info *the_timing_info) { | |||
@@ -285,11 +287,10 @@ static int pulse_playing(const pa_timing_info *the_timing_info) { | |||
pa_threaded_mainloop_lock(mainloop); | |||
for (;; ) { | |||
for (;;) { | |||
CHECK_DEAD_GOTO(fail, 1); | |||
if ((i = pa_stream_get_timing_info(stream))) | |||
{ | |||
if ((i = pa_stream_get_timing_info(stream))) { | |||
break; | |||
} | |||
if (pa_context_errno(context) != PA_ERR_NODATA) { | |||
@@ -301,7 +302,7 @@ static int pulse_playing(const pa_timing_info *the_timing_info) { | |||
} | |||
r = i->playing; | |||
memcpy((void*)the_timing_info, (void*)i, sizeof(pa_timing_info)); | |||
memcpy((void *)the_timing_info, (void *)i, sizeof(pa_timing_info)); | |||
fail: | |||
pa_threaded_mainloop_unlock(mainloop); | |||
@@ -309,7 +310,7 @@ fail: | |||
return r; | |||
} | |||
static void pulse_write(void* ptr, int length) { | |||
static void pulse_write(void *ptr, int length) { | |||
ENTER(__FUNCTION__); | |||
@@ -360,8 +361,7 @@ static int drain(void) { | |||
if (!success) { | |||
SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context))); | |||
} | |||
else { | |||
} else { | |||
ret = PULSE_OK; | |||
} | |||
@@ -420,7 +420,7 @@ static int pulse_open() | |||
assert(!stream); | |||
assert(!connected); | |||
pthread_mutex_init( &pulse_mutex, (const pthread_mutexattr_t *)NULL); | |||
pthread_mutex_init(&pulse_mutex, (const pthread_mutexattr_t *)NULL); | |||
ss.format = ESPEAK_FORMAT; | |||
ss.rate = wave_samplerate; | |||
@@ -431,7 +431,7 @@ static int pulse_open() | |||
SHOW_TIME("pa_threaded_mainloop_new (call)"); | |||
if (!(mainloop = pa_threaded_mainloop_new())) { | |||
SHOW("Failed to allocate main loop\n",""); | |||
SHOW("Failed to allocate main loop\n", ""); | |||
goto fail; | |||
} | |||
@@ -439,7 +439,7 @@ static int pulse_open() | |||
SHOW_TIME("pa_context_new (call)"); | |||
if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "eSpeak"))) { | |||
SHOW("Failed to allocate context\n",""); | |||
SHOW("Failed to allocate context\n", ""); | |||
goto unlock_and_fail; | |||
} | |||
@@ -455,7 +455,7 @@ static int pulse_open() | |||
SHOW_TIME("pa_threaded_mainloop_start (call)"); | |||
if (pa_threaded_mainloop_start(mainloop) < 0) { | |||
SHOW("Failed to start main loop",""); | |||
SHOW("Failed to start main loop", ""); | |||
goto unlock_and_fail; | |||
} | |||
@@ -558,8 +558,7 @@ fail: | |||
pa_threaded_mainloop_free(mainloop); | |||
mainloop = NULL; | |||
} | |||
} | |||
else { | |||
} else { | |||
pulse_close(); | |||
} | |||
@@ -569,12 +568,12 @@ fail: | |||
} | |||
void wave_flush(void* theHandler) | |||
void wave_flush(void *theHandler) | |||
{ | |||
ENTER("wave_flush"); | |||
} | |||
void wave_set_callback_is_output_enabled(t_wave_callback* cb) | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
{ | |||
my_callback_is_output_enabled = cb; | |||
} | |||
@@ -589,52 +588,47 @@ int wave_init(int srate) | |||
return pulse_open() == PULSE_OK; | |||
} | |||
void* wave_open(const char* the_api) | |||
void *wave_open(const char *the_api) | |||
{ | |||
ENTER("wave_open"); | |||
return((void*)1); | |||
return ((void *)1); | |||
} | |||
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) | |||
size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) | |||
{ | |||
ENTER("wave_write"); | |||
size_t bytes_to_write = theSize; | |||
char* aBuffer=theMono16BitsWaveBuffer; | |||
char *aBuffer = theMono16BitsWaveBuffer; | |||
assert(stream); | |||
size_t aTotalFreeMem=0; | |||
size_t aTotalFreeMem = 0; | |||
pthread_mutex_lock(&pulse_mutex); | |||
while (1) | |||
{ | |||
while (1) { | |||
if (my_callback_is_output_enabled | |||
&& (0==my_callback_is_output_enabled())) | |||
{ | |||
&& (0 == my_callback_is_output_enabled())) { | |||
SHOW_TIME("wave_write > my_callback_is_output_enabled: no!"); | |||
theSize=0; | |||
theSize = 0; | |||
goto terminate; | |||
} | |||
aTotalFreeMem = pulse_free(); | |||
if (aTotalFreeMem >= bytes_to_write) | |||
{ | |||
if (aTotalFreeMem >= bytes_to_write) { | |||
SHOW("wave_write > aTotalFreeMem(%d) >= bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write); | |||
break; | |||
} | |||
// TBD: check if really helpful | |||
if (aTotalFreeMem >= MAXLENGTH*2) | |||
{ | |||
if (aTotalFreeMem >= MAXLENGTH*2) { | |||
aTotalFreeMem = MAXLENGTH*2; | |||
} | |||
SHOW("wave_write > wait: aTotalFreeMem(%d) < bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write); | |||
// 500: threshold for avoiding too many calls to pulse_write | |||
if (aTotalFreeMem>500) | |||
{ | |||
if (aTotalFreeMem > 500) { | |||
pulse_write(aBuffer, aTotalFreeMem); | |||
bytes_to_write -= aTotalFreeMem; | |||
aBuffer += aTotalFreeMem; | |||
@@ -652,7 +646,7 @@ terminate: | |||
return theSize; | |||
} | |||
int wave_close(void* theHandler) | |||
int wave_close(void *theHandler) | |||
{ | |||
SHOW_TIME("wave_close > ENTER"); | |||
static int aStopStreamCount = 0; | |||
@@ -660,15 +654,13 @@ int wave_close(void* theHandler) | |||
// Avoid race condition by making sure this function only | |||
// gets called once at a time | |||
aStopStreamCount++; | |||
if (aStopStreamCount != 1) | |||
{ | |||
if (aStopStreamCount != 1) { | |||
SHOW_TIME("wave_close > LEAVE (stopStreamCount)"); | |||
return 0; | |||
} | |||
int a_status = pthread_mutex_lock(&pulse_mutex); | |||
if (a_status) | |||
{ | |||
if (a_status) { | |||
SHOW("Error: pulse_mutex lock=%d (%s)\n", a_status, __FUNCTION__); | |||
aStopStreamCount = 0; // last action | |||
return PULSE_ERROR; | |||
@@ -683,13 +675,13 @@ int wave_close(void* theHandler) | |||
return PULSE_OK; | |||
} | |||
int wave_is_busy(void* theHandler) | |||
int wave_is_busy(void *theHandler) | |||
{ | |||
SHOW_TIME("wave_is_busy"); | |||
pa_timing_info a_timing_info; | |||
int active = pulse_playing(&a_timing_info); | |||
SHOW("wave_is_busy: %d\n",active); | |||
SHOW("wave_is_busy: %d\n", active); | |||
return active; | |||
} | |||
@@ -698,7 +690,7 @@ void wave_terminate() | |||
ENTER("wave_terminate"); | |||
int a_status; | |||
pthread_mutex_t* a_mutex = NULL; | |||
pthread_mutex_t *a_mutex = NULL; | |||
a_mutex = &pulse_mutex; | |||
a_status = pthread_mutex_lock(a_mutex); | |||
@@ -709,7 +701,7 @@ void wave_terminate() | |||
pthread_mutex_destroy(a_mutex); | |||
} | |||
uint32_t wave_get_read_position(void* theHandler) | |||
uint32_t wave_get_read_position(void *theHandler) | |||
{ | |||
pa_timing_info a_timing_info; | |||
pulse_playing(&a_timing_info); | |||
@@ -717,7 +709,7 @@ uint32_t wave_get_read_position(void* theHandler) | |||
return a_timing_info.read_index; | |||
} | |||
uint32_t wave_get_write_position(void* theHandler) | |||
uint32_t wave_get_write_position(void *theHandler) | |||
{ | |||
pa_timing_info a_timing_info; | |||
pulse_playing(&a_timing_info); | |||
@@ -725,27 +717,23 @@ uint32_t wave_get_write_position(void* theHandler) | |||
return a_timing_info.write_index; | |||
} | |||
int wave_get_remaining_time(uint32_t sample, uint32_t* time) | |||
int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
{ | |||
double a_time=0; | |||
double a_time = 0; | |||
if (!time || !stream) | |||
{ | |||
SHOW("event get_remaining_time> %s\n","audio device not available"); | |||
if (!time || !stream) { | |||
SHOW("event get_remaining_time> %s\n", "audio device not available"); | |||
return -1; | |||
} | |||
pa_timing_info a_timing_info; | |||
pulse_playing(&a_timing_info); | |||
if (sample > a_timing_info.read_index) | |||
{ | |||
if (sample > a_timing_info.read_index) { | |||
// TBD: take in account time suplied by portaudio V18 API | |||
a_time = sample - a_timing_info.read_index; | |||
a_time = 0.5 + (a_time * 1000.0) / wave_samplerate; | |||
} | |||
else | |||
{ | |||
} else { | |||
a_time = 0; | |||
} | |||
@@ -767,38 +755,38 @@ void *wave_test_get_write_buffer() | |||
int wave_init(return 1; ) { | |||
} | |||
void* wave_open(const char* the_api) { | |||
void *wave_open(const char *the_api) { | |||
return (void *)1; | |||
} | |||
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) { | |||
size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) { | |||
return theSize; | |||
} | |||
int wave_close(void* theHandler) { | |||
int wave_close(void *theHandler) { | |||
return 0; | |||
} | |||
int wave_is_busy(void* theHandler) { | |||
int wave_is_busy(void *theHandler) { | |||
return 0; | |||
} | |||
void wave_terminate() { | |||
} | |||
uint32_t wave_get_read_position(void* theHandler) { | |||
uint32_t wave_get_read_position(void *theHandler) { | |||
return 0; | |||
} | |||
uint32_t wave_get_write_position(void* theHandler) { | |||
uint32_t wave_get_write_position(void *theHandler) { | |||
return 0; | |||
} | |||
void wave_flush(void* theHandler) { | |||
void wave_flush(void *theHandler) { | |||
} | |||
typedef int (t_wave_callback)(void); | |||
void wave_set_callback_is_output_enabled(t_wave_callback* cb) { | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
} | |||
extern void* wave_test_get_write_buffer() { | |||
extern void *wave_test_get_write_buffer() { | |||
return NULL; | |||
} | |||
int wave_get_remaining_time(uint32_t sample, uint32_t* time) | |||
int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
{ | |||
if (!time) return(-1); | |||
if (!time) return (-1); | |||
*time = (uint32_t)0; | |||
return 0; | |||
} | |||
@@ -811,26 +799,23 @@ void clock_gettime2(struct timespec *ts) | |||
{ | |||
struct timeval tv; | |||
if (!ts) | |||
{ | |||
if (!ts) { | |||
return; | |||
} | |||
assert (gettimeofday(&tv, NULL) != -1); | |||
assert(gettimeofday(&tv, NULL) != -1); | |||
ts->tv_sec = tv.tv_sec; | |||
ts->tv_nsec = tv.tv_usec*1000; | |||
} | |||
void add_time_in_ms(struct timespec *ts, int time_in_ms) | |||
{ | |||
if (!ts) | |||
{ | |||
if (!ts) { | |||
return; | |||
} | |||
uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms; | |||
while(t_ns >= ONE_BILLION) | |||
{ | |||
while (t_ns >= ONE_BILLION) { | |||
SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns); | |||
ts->tv_sec += 1; | |||
t_ns -= ONE_BILLION; |
@@ -35,13 +35,13 @@ | |||
#include "wave.h" | |||
#include "debug.h" | |||
enum {ONE_BILLION=1000000000}; | |||
enum { ONE_BILLION = 1000000000 }; | |||
#define SAMPLE_RATE 22050 | |||
#define SAMPLE_SIZE 16 | |||
#ifdef USE_SADA | |||
static t_wave_callback* my_callback_is_output_enabled=NULL; | |||
static t_wave_callback *my_callback_is_output_enabled = NULL; | |||
static const char *sun_audio_device = "/dev/audio"; | |||
static int sun_audio_fd = -1; | |||
@@ -59,7 +59,7 @@ static uint32_t total_samples_skipped; | |||
// The last known playing index after a call to wave_close. | |||
// | |||
static uint32_t last_play_position=0; | |||
static uint32_t last_play_position = 0; | |||
static uint32_t wave_samplerate; | |||
@@ -100,7 +100,7 @@ int wave_init(int srate) { | |||
SHOW("wave_init() sun_audio_fd: %d\n", sun_audio_fd); | |||
if (sun_audio_fd < 0) { | |||
return(0); | |||
return (0); | |||
} | |||
ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo); | |||
@@ -113,9 +113,9 @@ int wave_init(int srate) { | |||
if (ioctl(sun_audio_fd, AUDIO_SETINFO, &ainfo) == -1) { | |||
SHOW("wave_init() failed to set audio params: %s\n", strerror(errno)); | |||
close(sun_audio_fd); | |||
return(0); | |||
return (0); | |||
} | |||
return(1); | |||
return (1); | |||
} | |||
// wave_open | |||
@@ -140,10 +140,10 @@ int wave_init(int srate) { | |||
// sun_audio_fd opened in wave_init, which is passed in as theHandler | |||
// parameter in all other methods | |||
// | |||
void* wave_open(const char* the_api) | |||
void *wave_open(const char *the_api) | |||
{ | |||
ENTER("wave_open"); | |||
return((void*) sun_audio_fd); | |||
return ((void *)sun_audio_fd); | |||
} | |||
// wave_write | |||
@@ -172,13 +172,13 @@ void* wave_open(const char* the_api) | |||
// | |||
// the number of bytes (not 16-bit samples) sent | |||
// | |||
size_t wave_write(void* theHandler, | |||
char* theMono16BitsWaveBuffer, | |||
size_t wave_write(void *theHandler, | |||
char *theMono16BitsWaveBuffer, | |||
size_t theSize) | |||
{ | |||
size_t num; | |||
ENTER("wave_write"); | |||
if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) { | |||
if (my_callback_is_output_enabled && (0 == my_callback_is_output_enabled())) { | |||
SHOW_TIME("wave_write > my_callback_is_output_enabled: no!"); | |||
return 0; | |||
} | |||
@@ -191,8 +191,7 @@ size_t wave_write(void* theHandler, | |||
char *out_end; | |||
out_ptr = (char *)theMono16BitsWaveBuffer; | |||
out_end = out_ptr + theSize; | |||
while(out_ptr < out_end) | |||
{ | |||
while (out_ptr < out_end) { | |||
c = out_ptr[0]; | |||
out_ptr[0] = out_ptr[1]; | |||
out_ptr[1] = c; | |||
@@ -201,7 +200,7 @@ size_t wave_write(void* theHandler, | |||
} | |||
#endif | |||
num = write((int) theHandler, theMono16BitsWaveBuffer, theSize); | |||
num = write((int)theHandler, theMono16BitsWaveBuffer, theSize); | |||
// Keep track of the total number of samples sent -- we use this in | |||
// wave_get_read_position and also use it to help calculate the | |||
@@ -246,11 +245,11 @@ size_t wave_write(void* theHandler, | |||
// | |||
// The result of the ioctl call (non-0 means failure) | |||
// | |||
int wave_close(void* theHandler) | |||
int wave_close(void *theHandler) | |||
{ | |||
int ret; | |||
audio_info_t ainfo; | |||
int audio_fd = (int) theHandler; | |||
int audio_fd = (int)theHandler; | |||
if (!audio_fd) { | |||
audio_fd = sun_audio_fd; | |||
} | |||
@@ -291,7 +290,7 @@ int wave_close(void* theHandler) | |||
// | |||
// A non-0 value if audio is being played | |||
// | |||
int wave_is_busy(void* theHandler) | |||
int wave_is_busy(void *theHandler) | |||
{ | |||
uint32_t time; | |||
if (total_samples_sent >= 1) { | |||
@@ -335,7 +334,7 @@ void wave_terminate() | |||
// | |||
// theHandler: the audio device file descriptor | |||
// | |||
void wave_flush(void* theHandler) | |||
void wave_flush(void *theHandler) | |||
{ | |||
ENTER("wave_flush"); | |||
SHOW_TIME("wave_flush > LEAVE"); | |||
@@ -353,7 +352,7 @@ void wave_flush(void* theHandler) | |||
// | |||
// cb: the callback to call from wave_write | |||
// | |||
void wave_set_callback_is_output_enabled(t_wave_callback* cb) | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
{ | |||
my_callback_is_output_enabled = cb; | |||
} | |||
@@ -393,11 +392,11 @@ void *wave_test_get_write_buffer() | |||
// The total number of 16-bit samples played by the audio system | |||
// so far. | |||
// | |||
uint32_t wave_get_read_position(void* theHandler) | |||
uint32_t wave_get_read_position(void *theHandler) | |||
{ | |||
audio_info_t ainfo; | |||
ENTER("wave_get_read_position"); | |||
ioctl((int) theHandler, AUDIO_GETINFO, &ainfo); | |||
ioctl((int)theHandler, AUDIO_GETINFO, &ainfo); | |||
SHOW("wave_get_read_position: %d\n", ainfo.play.samples); | |||
SHOW_TIME("wave_get_read_position > LEAVE"); | |||
return ainfo.play.samples; | |||
@@ -429,7 +428,7 @@ uint32_t wave_get_read_position(void* theHandler) | |||
// the index wraps back to 0. We don't handle that wrapping, so | |||
// the behavior after 54 hours of play time is undefined.]]] | |||
// | |||
uint32_t wave_get_write_position(void* theHandler) | |||
uint32_t wave_get_write_position(void *theHandler) | |||
{ | |||
ENTER("wave_get_write_position"); | |||
SHOW("wave_get_write_position: %d\n", total_samples_sent); | |||
@@ -464,15 +463,15 @@ uint32_t wave_get_write_position(void* theHandler) | |||
// Time in milliseconds before the sample is played or 0 if the sample | |||
// is currently playing or has already been played. | |||
// | |||
int wave_get_remaining_time(uint32_t sample, uint32_t* time) | |||
int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
{ | |||
uint32_t a_time=0; | |||
uint32_t a_time = 0; | |||
uint32_t actual_index; | |||
audio_info_t ainfo; | |||
ENTER("wave_get_remaining_time"); | |||
if (!time) { | |||
return(-1); | |||
return (-1); | |||
SHOW_TIME("wave_get_remaining_time > LEAVE"); | |||
} | |||
@@ -487,7 +486,7 @@ int wave_get_remaining_time(uint32_t sample, uint32_t* time) | |||
*time = 0; | |||
} else { | |||
a_time = ((actual_index - ainfo.play.samples) * 1000) / wave_samplerate; | |||
*time = (uint32_t) a_time; | |||
*time = (uint32_t)a_time; | |||
} | |||
SHOW("wave_get_remaining_time for %d: %d\n", sample, *time); | |||
SHOW_TIME("wave_get_remaining_time > LEAVE"); | |||
@@ -499,38 +498,38 @@ int wave_get_remaining_time(uint32_t sample, uint32_t* time) | |||
init wave_init() { | |||
return 1; | |||
} | |||
void* wave_open(const char* the_api) { | |||
void *wave_open(const char *the_api) { | |||
return (void *)1; | |||
} | |||
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) { | |||
size_t wave_write(void *theHandler, char *theMono16BitsWaveBuffer, size_t theSize) { | |||
return theSize; | |||
} | |||
int wave_close(void* theHandler) { | |||
int wave_close(void *theHandler) { | |||
return 0; | |||
} | |||
int wave_is_busy(void* theHandler) { | |||
int wave_is_busy(void *theHandler) { | |||
return 0; | |||
} | |||
void wave_terminate() { | |||
} | |||
uint32_t wave_get_read_position(void* theHandler) { | |||
uint32_t wave_get_read_position(void *theHandler) { | |||
return 0; | |||
} | |||
uint32_t wave_get_write_position(void* theHandler) { | |||
uint32_t wave_get_write_position(void *theHandler) { | |||
return 0; | |||
} | |||
void wave_flush(void* theHandler) { | |||
void wave_flush(void *theHandler) { | |||
} | |||
typedef int (t_wave_callback)(void); | |||
void wave_set_callback_is_output_enabled(t_wave_callback* cb) { | |||
void wave_set_callback_is_output_enabled(t_wave_callback *cb) { | |||
} | |||
extern void* wave_test_get_write_buffer() { | |||
extern void *wave_test_get_write_buffer() { | |||
return NULL; | |||
} | |||
int wave_get_remaining_time(uint32_t sample, uint32_t* time) | |||
int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
{ | |||
if (!time) return(-1); | |||
if (!time) return (-1); | |||
*time = (uint32_t)0; | |||
return 0; | |||
} | |||
@@ -541,26 +540,23 @@ void clock_gettime2(struct timespec *ts) | |||
{ | |||
struct timeval tv; | |||
if (!ts) | |||
{ | |||
if (!ts) { | |||
return; | |||
} | |||
assert (gettimeofday(&tv, NULL) != -1); | |||
assert(gettimeofday(&tv, NULL) != -1); | |||
ts->tv_sec = tv.tv_sec; | |||
ts->tv_nsec = tv.tv_usec*1000; | |||
} | |||
void add_time_in_ms(struct timespec *ts, int time_in_ms) | |||
{ | |||
if (!ts) | |||
{ | |||
if (!ts) { | |||
return; | |||
} | |||
uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms; | |||
while(t_ns >= ONE_BILLION) | |||
{ | |||
while (t_ns >= ONE_BILLION) { | |||
SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns); | |||
ts->tv_sec += 1; | |||
t_ns -= ONE_BILLION; |
@@ -145,59 +145,50 @@ void DisplayVoices(FILE *f_out, char *language) | |||
const espeak_VOICE **voices; | |||
espeak_VOICE voice_select; | |||
static char genders[4] = {'-','M','F','-'}; | |||
static char genders[4] = { '-', 'M', 'F', '-' }; | |||
if((language != NULL) && (language[0] != 0)) | |||
{ | |||
if ((language != NULL) && (language[0] != 0)) { | |||
// display only voices for the specified language, in order of priority | |||
voice_select.languages = language; | |||
voice_select.age = 0; | |||
voice_select.gender = 0; | |||
voice_select.name = NULL; | |||
voices = espeak_ListVoices(&voice_select); | |||
} | |||
else | |||
{ | |||
} else { | |||
voices = espeak_ListVoices(NULL); | |||
} | |||
fprintf(f_out,"Pty Language Age/Gender VoiceName File Other Languages\n"); | |||
fprintf(f_out, "Pty Language Age/Gender VoiceName File Other Languages\n"); | |||
for(ix=0; (v = voices[ix]) != NULL; ix++) | |||
{ | |||
for (ix = 0; (v = voices[ix]) != NULL; ix++) { | |||
count = 0; | |||
p = v->languages; | |||
while(*p != 0) | |||
{ | |||
while (*p != 0) { | |||
len = strlen(p+1); | |||
lang_name = p+1; | |||
if(v->age == 0) | |||
strcpy(age_buf," "); | |||
if (v->age == 0) | |||
strcpy(age_buf, " "); | |||
else | |||
sprintf(age_buf,"%3d",v->age); | |||
sprintf(age_buf, "%3d", v->age); | |||
if(count==0) | |||
{ | |||
for(j=0; j < sizeof(buf); j++) | |||
{ | |||
if (count == 0) { | |||
for (j = 0; j < sizeof(buf); j++) { | |||
// replace spaces in the name | |||
if((c = v->name[j]) == ' ') | |||
if ((c = v->name[j]) == ' ') | |||
c = '_'; | |||
if((buf[j] = c) == 0) | |||
if ((buf[j] = c) == 0) | |||
break; | |||
} | |||
fprintf(f_out,"%2d %-12s%s%c %-20s %-13s ", | |||
p[0],lang_name,age_buf,genders[v->gender],buf,v->identifier); | |||
} | |||
else | |||
{ | |||
fprintf(f_out,"(%s %d)",lang_name,p[0]); | |||
fprintf(f_out, "%2d %-12s%s%c %-20s %-13s ", | |||
p[0], lang_name, age_buf, genders[v->gender], buf, v->identifier); | |||
} else { | |||
fprintf(f_out, "(%s %d)", lang_name, p[0]); | |||
} | |||
count++; | |||
p += len+2; | |||
} | |||
fputc('\n',f_out); | |||
fputc('\n', f_out); | |||
} | |||
} | |||
@@ -207,40 +198,36 @@ static int OpenWaveFile(const char *path, int rate) | |||
// Set the length of 0x7ffff000 for --stdout | |||
// This will be changed to the correct length for -w (write to file) | |||
static unsigned char wave_hdr[44] = { | |||
'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ', | |||
0x10,0,0,0,1,0,1,0, 9,0x3d,0,0,0x12,0x7a,0,0, | |||
2,0,0x10,0,'d','a','t','a', 0x00,0xf0,0xff,0x7f | |||
'R', 'I', 'F', 'F', 0x24, 0xf0, 0xff, 0x7f, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', | |||
0x10, 0, 0, 0, 1, 0, 1, 0, 9, 0x3d, 0, 0, 0x12, 0x7a, 0, 0, | |||
2, 0, 0x10, 0, 'd', 'a', 't', 'a', 0x00, 0xf0, 0xff, 0x7f | |||
}; | |||
if(path == NULL) | |||
return(2); | |||
if (path == NULL) | |||
return (2); | |||
while(isspace(*path)) path++; | |||
while (isspace(*path)) path++; | |||
f_wave = NULL; | |||
if(path[0] != 0) | |||
{ | |||
if(strcmp(path,"stdout")==0) | |||
{ | |||
if (path[0] != 0) { | |||
if (strcmp(path, "stdout") == 0) { | |||
#ifdef PLATFORM_WINDOWS | |||
// prevent Windows adding 0x0d before 0x0a bytes | |||
_setmode(_fileno(stdout), _O_BINARY); | |||
#endif | |||
f_wave = stdout; | |||
} | |||
else | |||
f_wave = fopen(path,"wb"); | |||
} else | |||
f_wave = fopen(path, "wb"); | |||
} | |||
if(f_wave != NULL) | |||
{ | |||
fwrite(wave_hdr,1,24,f_wave); | |||
Write4Bytes(f_wave,rate); | |||
Write4Bytes(f_wave,rate * 2); | |||
fwrite(&wave_hdr[32],1,12,f_wave); | |||
return(0); | |||
if (f_wave != NULL) { | |||
fwrite(wave_hdr, 1, 24, f_wave); | |||
Write4Bytes(f_wave, rate); | |||
Write4Bytes(f_wave, rate * 2); | |||
fwrite(&wave_hdr[32], 1, 12, f_wave); | |||
return (0); | |||
} | |||
return(1); | |||
return (1); | |||
} | |||
@@ -250,17 +237,17 @@ static void CloseWaveFile() | |||
{ | |||
unsigned int pos; | |||
if((f_wave == NULL) || (f_wave == stdout)) | |||
if ((f_wave == NULL) || (f_wave == stdout)) | |||
return; | |||
fflush(f_wave); | |||
pos = ftell(f_wave); | |||
fseek(f_wave,4,SEEK_SET); | |||
Write4Bytes(f_wave,pos - 8); | |||
fseek(f_wave, 4, SEEK_SET); | |||
Write4Bytes(f_wave, pos - 8); | |||
fseek(f_wave,40,SEEK_SET); | |||
Write4Bytes(f_wave,pos - 44); | |||
fseek(f_wave, 40, SEEK_SET); | |||
Write4Bytes(f_wave, pos - 44); | |||
fclose(f_wave); | |||
@@ -282,32 +269,28 @@ static int WavegenFile(void) | |||
finished = WavegenFill(0); | |||
if(quiet) | |||
return(finished); | |||
if (quiet) | |||
return (finished); | |||
if(f_wave == NULL) | |||
{ | |||
sprintf(fname,"%s_%.2d%s",wavefile,++wavefile_count,filetype); | |||
if(OpenWaveFile(fname, samplerate) != 0) | |||
return(1); | |||
if (f_wave == NULL) { | |||
sprintf(fname, "%s_%.2d%s", wavefile, ++wavefile_count, filetype); | |||
if (OpenWaveFile(fname, samplerate) != 0) | |||
return (1); | |||
} | |||
if(end_of_sentence) | |||
{ | |||
if (end_of_sentence) { | |||
end_of_sentence = 0; | |||
if((samples_split > 0 ) && (samples_total > samples_split)) | |||
{ | |||
if ((samples_split > 0 ) && (samples_total > samples_split)) { | |||
CloseWaveFile(); | |||
samples_total = 0; | |||
} | |||
} | |||
if(f_wave != NULL) | |||
{ | |||
if (f_wave != NULL) { | |||
samples_total += (out_ptr - wav_outbuf)/2; | |||
fwrite(wav_outbuf, 1, out_ptr - wav_outbuf, f_wave); | |||
} | |||
return(finished); | |||
return (finished); | |||
} | |||
@@ -315,9 +298,8 @@ static int WavegenFile(void) | |||
static void init_path(char *argv0, char *path_specified) | |||
{ | |||
if(path_specified) | |||
{ | |||
sprintf(path_home,"%s/espeak-data",path_specified); | |||
if (path_specified) { | |||
sprintf(path_home, "%s/espeak-data", path_specified); | |||
return; | |||
} | |||
@@ -329,18 +311,16 @@ static void init_path(char *argv0, char *path_specified) | |||
char *env; | |||
unsigned char buf[sizeof(path_home)-12]; | |||
if(((env = getenv("ESPEAK_DATA_PATH")) != NULL) && ((strlen(env)+12) < sizeof(path_home))) | |||
{ | |||
sprintf(path_home,"%s\\espeak-data",env); | |||
if(GetFileLength(path_home) == -2) | |||
if (((env = getenv("ESPEAK_DATA_PATH")) != NULL) && ((strlen(env)+12) < sizeof(path_home))) { | |||
sprintf(path_home, "%s\\espeak-data", env); | |||
if (GetFileLength(path_home) == -2) | |||
return; // an espeak-data directory exists in the directory specified by environment variable | |||
} | |||
strcpy(path_home,argv0); | |||
if((p = strrchr(path_home,'\\')) != NULL) | |||
{ | |||
strcpy(&p[1],"espeak-data"); | |||
if(GetFileLength(path_home) == -2) | |||
strcpy(path_home, argv0); | |||
if ((p = strrchr(path_home, '\\')) != NULL) { | |||
strcpy(&p[1], "espeak-data"); | |||
if (GetFileLength(path_home) == -2) | |||
return; // an espeak-data directory exists in the same directory as the espeak program | |||
} | |||
@@ -351,23 +331,21 @@ static void init_path(char *argv0, char *path_specified) | |||
var_type = REG_SZ; | |||
RegQueryValueEx(RegKey, "path", 0, &var_type, buf, &size); | |||
sprintf(path_home,"%s\\espeak-data",buf); | |||
sprintf(path_home, "%s\\espeak-data", buf); | |||
#else | |||
#ifdef PLATFORM_DOS | |||
strcpy(path_home,PATH_ESPEAK_DATA); | |||
strcpy(path_home, PATH_ESPEAK_DATA); | |||
#else | |||
char *env; | |||
if((env = getenv("ESPEAK_DATA_PATH")) != NULL) | |||
{ | |||
snprintf(path_home,sizeof(path_home),"%s/espeak-data",env); | |||
if(GetFileLength(path_home) == -2) | |||
if ((env = getenv("ESPEAK_DATA_PATH")) != NULL) { | |||
snprintf(path_home, sizeof(path_home), "%s/espeak-data", env); | |||
if (GetFileLength(path_home) == -2) | |||
return; // an espeak-data directory exists | |||
} | |||
snprintf(path_home,sizeof(path_home),"%s/espeak-data",getenv("HOME")); | |||
if(access(path_home,R_OK) != 0) | |||
{ | |||
strcpy(path_home,PATH_ESPEAK_DATA); | |||
snprintf(path_home, sizeof(path_home), "%s/espeak-data", getenv("HOME")); | |||
if (access(path_home, R_OK) != 0) { | |||
strcpy(path_home, PATH_ESPEAK_DATA); | |||
} | |||
#endif | |||
#endif | |||
@@ -384,35 +362,31 @@ static int initialise(void) | |||
// to something other than the default "C". Then, not only Latin1 but also the | |||
// other characters give the correct results with iswalpha() etc. | |||
#ifdef PLATFORM_RISCOS | |||
setlocale(LC_CTYPE,"ISO8859-1"); | |||
setlocale(LC_CTYPE, "ISO8859-1"); | |||
#else | |||
if(setlocale(LC_CTYPE,"en_US.UTF-8") == NULL) | |||
{ | |||
if(setlocale(LC_CTYPE,"UTF-8") == NULL) | |||
setlocale(LC_CTYPE,""); | |||
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) { | |||
if (setlocale(LC_CTYPE, "UTF-8") == NULL) | |||
setlocale(LC_CTYPE, ""); | |||
} | |||
#endif | |||
if((result = LoadPhData(&srate)) != 1) | |||
{ | |||
if(result == -1) | |||
{ | |||
fprintf(stderr,"Failed to load espeak-data\n"); | |||
if ((result = LoadPhData(&srate)) != 1) { | |||
if (result == -1) { | |||
fprintf(stderr, "Failed to load espeak-data\n"); | |||
exit(1); | |||
} | |||
else | |||
fprintf(stderr,"Wrong version of espeak-data 0x%x (expects 0x%x) at %s\n",result,version_phdata,path_home); | |||
} else | |||
fprintf(stderr, "Wrong version of espeak-data 0x%x (expects 0x%x) at %s\n", result, version_phdata, path_home); | |||
} | |||
WavegenInit(srate,0); | |||
WavegenInit(srate, 0); | |||
LoadConfig(); | |||
SetVoiceStack(NULL, ""); | |||
SynthesizeInit(); | |||
for(param=0; param<N_SPEECH_PARAM; param++) | |||
for (param = 0; param < N_SPEECH_PARAM; param++) | |||
param_stack[0].parameter[param] = param_defaults[param]; | |||
return(0); | |||
return (0); | |||
} | |||
@@ -427,44 +401,43 @@ struct option { | |||
int optind; | |||
static int optional_argument; | |||
static const char *arg_opts = "abfgklpsvw"; // which options have arguments | |||
static char *opt_string=""; | |||
static char *opt_string = ""; | |||
#define no_argument 0 | |||
#define required_argument 1 | |||
#define optional_argument 2 | |||
#endif | |||
int main (int argc, char **argv) | |||
int main(int argc, char **argv) | |||
{ | |||
static struct option long_options[] = | |||
{ | |||
{"help", no_argument, 0, 'h'}, | |||
{"stdin", no_argument, 0, 0x100}, | |||
{"compile-debug", optional_argument, 0, 0x101}, | |||
{"compile", optional_argument, 0, 0x102}, | |||
{"punct", optional_argument, 0, 0x103}, | |||
{"voices", optional_argument, 0, 0x104}, | |||
{"stdout", no_argument, 0, 0x105}, | |||
{"split", optional_argument, 0, 0x106}, | |||
{"path", required_argument, 0, 0x107}, | |||
{"phonout", required_argument, 0, 0x108}, | |||
{"pho", no_argument, 0, 0x109}, | |||
{"ipa", optional_argument, 0, 0x10a}, | |||
{"version", no_argument, 0, 0x10b}, | |||
{"sep", optional_argument, 0, 0x10c}, | |||
{"tie", optional_argument, 0, 0x10d}, | |||
{0, 0, 0, 0} | |||
static struct option long_options[] = { | |||
{ "help", no_argument, 0, 'h' }, | |||
{ "stdin", no_argument, 0, 0x100 }, | |||
{ "compile-debug", optional_argument, 0, 0x101 }, | |||
{ "compile", optional_argument, 0, 0x102 }, | |||
{ "punct", optional_argument, 0, 0x103 }, | |||
{ "voices", optional_argument, 0, 0x104 }, | |||
{ "stdout", no_argument, 0, 0x105 }, | |||
{ "split", optional_argument, 0, 0x106 }, | |||
{ "path", required_argument, 0, 0x107 }, | |||
{ "phonout", required_argument, 0, 0x108 }, | |||
{ "pho", no_argument, 0, 0x109 }, | |||
{ "ipa", optional_argument, 0, 0x10a }, | |||
{ "version", no_argument, 0, 0x10b }, | |||
{ "sep", optional_argument, 0, 0x10c }, | |||
{ "tie", optional_argument, 0, 0x10d }, | |||
{ 0, 0, 0, 0 } | |||
}; | |||
static const char *err_load = "Failed to read "; | |||
FILE *f_text=NULL; | |||
const char *p_text=NULL; | |||
FILE *f_text = NULL; | |||
const char *p_text = NULL; | |||
char *data_path = NULL; // use default path for espeak-data | |||
int option_index = 0; | |||
int c; | |||
int value; | |||
int speed=175; | |||
int speed = 175; | |||
int ix; | |||
char *optarg2; | |||
int amp = 100; // default | |||
@@ -495,15 +468,13 @@ int main (int argc, char **argv) | |||
#ifdef NEED_GETOPT | |||
optind = 1; | |||
opt_string = ""; | |||
while(optind < argc) | |||
{ | |||
while (optind < argc) { | |||
int len; | |||
char *p; | |||
if((c = *opt_string) == 0) | |||
{ | |||
if ((c = *opt_string) == 0) { | |||
opt_string = argv[optind]; | |||
if(opt_string[0] != '-') | |||
if (opt_string[0] != '-') | |||
break; | |||
optind++; | |||
@@ -513,45 +484,36 @@ int main (int argc, char **argv) | |||
opt_string++; | |||
p = optarg2 = opt_string; | |||
if(c == '-') | |||
{ | |||
if(p[0] == 0) | |||
if (c == '-') { | |||
if (p[0] == 0) | |||
break; // -- means don't interpret further - as commands | |||
opt_string=""; | |||
for(ix=0;; ix++) | |||
{ | |||
if(long_options[ix].name == 0) | |||
opt_string = ""; | |||
for (ix = 0;; ix++) { | |||
if (long_options[ix].name == 0) | |||
break; | |||
len = strlen(long_options[ix].name); | |||
if(memcmp(long_options[ix].name,p,len)==0) | |||
{ | |||
if (memcmp(long_options[ix].name, p, len) == 0) { | |||
c = long_options[ix].val; | |||
optarg2 = NULL; | |||
if((long_options[ix].has_arg != 0) && (p[len]=='=')) | |||
{ | |||
if ((long_options[ix].has_arg != 0) && (p[len] == '=')) { | |||
optarg2 = &p[len+1]; | |||
} | |||
break; | |||
} | |||
} | |||
} | |||
else | |||
if(strchr(arg_opts,c) != NULL) | |||
{ | |||
opt_string=""; | |||
if(optarg2[0]==0) | |||
{ | |||
} else if (strchr(arg_opts, c) != NULL) { | |||
opt_string = ""; | |||
if (optarg2[0] == 0) { | |||
// the option's value is in the next argument | |||
optarg2 = argv[optind++]; | |||
} | |||
} | |||
#else | |||
while(true) | |||
{ | |||
c = getopt_long (argc, argv, "a:b:f:g:hk:l:p:qs:v:w:xXmz", // NOTE: also change arg_opts to indicate which commands have a numeric value | |||
long_options, &option_index); | |||
while (true) { | |||
c = getopt_long(argc, argv, "a:b:f:g:hk:l:p:qs:v:w:xXmz", // NOTE: also change arg_opts to indicate which commands have a numeric value | |||
long_options, &option_index); | |||
/* Detect the end of the options. */ | |||
if (c == -1) | |||
@@ -564,13 +526,13 @@ int main (int argc, char **argv) | |||
case 'b': | |||
// input character encoding, 8bit, 16bit, UTF8 | |||
option_multibyte = espeakCHARS_8BIT; | |||
if((sscanf(optarg2,"%d",&value) == 1) && (value <= 4)) | |||
option_multibyte= value; | |||
if ((sscanf(optarg2, "%d", &value) == 1) && (value <= 4)) | |||
option_multibyte = value; | |||
break; | |||
case 'h': | |||
init_path(argv[0],data_path); | |||
printf("\nspeak text-to-speech: %s Data at: %s\n%s",version_string,path_home,help_text); | |||
init_path(argv[0], data_path); | |||
printf("\nspeak text-to-speech: %s Data at: %s\n%s", version_string, path_home, help_text); | |||
exit(0); | |||
case 'k': | |||
@@ -591,7 +553,7 @@ int main (int argc, char **argv) | |||
case 'p': | |||
pitch_adjustment = atoi(optarg2); | |||
if(pitch_adjustment > 99) pitch_adjustment = 99; | |||
if (pitch_adjustment > 99) pitch_adjustment = 99; | |||
break; | |||
case 'q': | |||
@@ -599,7 +561,7 @@ int main (int argc, char **argv) | |||
break; | |||
case 'f': | |||
strncpy0(filename,optarg2,sizeof(filename)); | |||
strncpy0(filename, optarg2, sizeof(filename)); | |||
break; | |||
case 'l': | |||
@@ -621,12 +583,12 @@ int main (int argc, char **argv) | |||
break; | |||
case 'v': | |||
strncpy0(voicename,optarg2,sizeof(voicename)); | |||
strncpy0(voicename, optarg2, sizeof(voicename)); | |||
break; | |||
case 'w': | |||
option_waveout = 1; | |||
strncpy0(wavefile,optarg2,sizeof(wavefile)); | |||
strncpy0(wavefile, optarg2, sizeof(wavefile)); | |||
break; | |||
case 'z': | |||
@@ -639,34 +601,33 @@ int main (int argc, char **argv) | |||
case 0x105: // --stdout | |||
option_waveout = 1; | |||
strcpy(wavefile,"stdout"); | |||
strcpy(wavefile, "stdout"); | |||
break; | |||
case 0x101: // --compile-debug | |||
case 0x102: // --compile | |||
if(optarg2 != NULL) | |||
strncpy0(voicename,optarg2,sizeof(voicename)); | |||
if (optarg2 != NULL) | |||
strncpy0(voicename, optarg2, sizeof(voicename)); | |||
flag_compile = c; | |||
break; | |||
case 0x103: // --punct | |||
option_punctuation = 1; | |||
if(optarg2 != NULL) | |||
{ | |||
if (optarg2 != NULL) { | |||
ix = 0; | |||
while((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++; | |||
while ((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++; | |||
option_punctlist[N_PUNCTLIST-1] = 0; | |||
option_punctuation = 2; | |||
} | |||
break; | |||
case 0x104: // --voices | |||
init_path(argv[0],data_path); | |||
DisplayVoices(stdout,optarg2); | |||
init_path(argv[0], data_path); | |||
DisplayVoices(stdout, optarg2); | |||
exit(0); | |||
case 0x106: // -- split | |||
if(optarg2 == NULL) | |||
if (optarg2 == NULL) | |||
samples_split = 30; // default 30 minutes | |||
else | |||
samples_split = atoi(optarg2); | |||
@@ -677,9 +638,8 @@ int main (int argc, char **argv) | |||
break; | |||
case 0x108: // --phonout | |||
if((f_trans = fopen(optarg2,"w")) == NULL) | |||
{ | |||
fprintf(stderr,"Can't write to: %s\n",optarg2); | |||
if ((f_trans = fopen(optarg2, "w")) == NULL) { | |||
fprintf(stderr, "Can't write to: %s\n", optarg2); | |||
f_trans = stderr; | |||
} | |||
break; | |||
@@ -690,10 +650,9 @@ int main (int argc, char **argv) | |||
case 0x10a: // --ipa | |||
phoneme_options |= espeakPHONEMES_IPA; | |||
if(optarg2 != NULL) | |||
{ | |||
if (optarg2 != NULL) { | |||
// deprecated and obsolete | |||
switch(atoi(optarg2)) | |||
switch (atoi(optarg2)) | |||
{ | |||
case 1: | |||
phonemes_separator = '_'; | |||
@@ -712,27 +671,27 @@ int main (int argc, char **argv) | |||
break; | |||
case 0x10b: // --version | |||
init_path(argv[0],data_path); | |||
printf("speak text-to-speech: %s Data at: %s\n",version_string,path_home); | |||
init_path(argv[0], data_path); | |||
printf("speak text-to-speech: %s Data at: %s\n", version_string, path_home); | |||
exit(0); | |||
case 0x10c: // --sep | |||
phoneme_options |= espeakPHONEMES_SHOW; | |||
if(optarg2 == 0) | |||
if (optarg2 == 0) | |||
phonemes_separator = ' '; | |||
else | |||
utf8_in(&phonemes_separator, optarg2); | |||
if(phonemes_separator == 'z') | |||
if (phonemes_separator == 'z') | |||
phonemes_separator = 0x200c; // ZWNJ | |||
break; | |||
case 0x10d: // --tie | |||
phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE); | |||
if(optarg2 == 0) | |||
if (optarg2 == 0) | |||
phonemes_separator = 0x0361; // default: combining-double-inverted-breve | |||
else | |||
utf8_in(&phonemes_separator, optarg2); | |||
if(phonemes_separator == 'z') | |||
if (phonemes_separator == 'z') | |||
phonemes_separator = 0x200d; // ZWJ | |||
break; | |||
@@ -741,154 +700,127 @@ int main (int argc, char **argv) | |||
} | |||
} | |||
init_path(argv[0],data_path); | |||
init_path(argv[0], data_path); | |||
initialise(); | |||
if(voicename[0] == 0) | |||
strcpy(voicename,"default"); | |||
if (voicename[0] == 0) | |||
strcpy(voicename, "default"); | |||
if(SetVoiceByName(voicename) != EE_OK) | |||
{ | |||
memset(&voice_select,0,sizeof(voice_select)); | |||
if (SetVoiceByName(voicename) != EE_OK) { | |||
memset(&voice_select, 0, sizeof(voice_select)); | |||
voice_select.languages = voicename; | |||
if(SetVoiceByProperties(&voice_select) != EE_OK) | |||
{ | |||
fprintf(stderr,"%svoice '%s'\n",err_load,voicename); | |||
if (SetVoiceByProperties(&voice_select) != EE_OK) { | |||
fprintf(stderr, "%svoice '%s'\n", err_load, voicename); | |||
exit(2); | |||
} | |||
} | |||
if(flag_compile) | |||
{ | |||
if (flag_compile) { | |||
#ifdef PLATFORM_DOS | |||
char path_dsource[sizeof(path_home)+20]; | |||
strcpy(path_dsource,path_home); | |||
strcpy(path_dsource, path_home); | |||
path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
strcat(path_dsource,"dictsource\\"); | |||
CompileDictionary(path_dsource,dictionary_name,NULL,NULL, flag_compile & 0x1); | |||
strcat(path_dsource, "dictsource\\"); | |||
CompileDictionary(path_dsource, dictionary_name, NULL, NULL, flag_compile & 0x1); | |||
#else | |||
#ifdef PLATFORM_WINDOWS | |||
char path_dsource[sizeof(path_home)+20]; | |||
strcpy(path_dsource,path_home); | |||
strcpy(path_dsource, path_home); | |||
path_dsource[strlen(path_home)-11] = 0; // remove "espeak-data" from the end | |||
strcat(path_dsource,"dictsource\\"); | |||
CompileDictionary(path_dsource,dictionary_name,NULL,NULL, flag_compile & 0x1); | |||
strcat(path_dsource, "dictsource\\"); | |||
CompileDictionary(path_dsource, dictionary_name, NULL, NULL, flag_compile & 0x1); | |||
#else | |||
CompileDictionary(NULL,dictionary_name,NULL,NULL, flag_compile & 0x1); | |||
CompileDictionary(NULL, dictionary_name, NULL, NULL, flag_compile & 0x1); | |||
#endif | |||
#endif | |||
exit(0); | |||
} | |||
SetParameter(espeakRATE,speed,0); | |||
SetParameter(espeakVOLUME,amp,0); | |||
SetParameter(espeakCAPITALS,option_capitals,0); | |||
SetParameter(espeakPUNCTUATION,option_punctuation,0); | |||
SetParameter(espeakWORDGAP,wordgap,0); | |||
SetParameter(espeakRATE, speed, 0); | |||
SetParameter(espeakVOLUME, amp, 0); | |||
SetParameter(espeakCAPITALS, option_capitals, 0); | |||
SetParameter(espeakPUNCTUATION, option_punctuation, 0); | |||
SetParameter(espeakWORDGAP, wordgap, 0); | |||
option_phonemes = phoneme_options | (phonemes_separator << 8); | |||
if(pitch_adjustment != 50) | |||
{ | |||
SetParameter(espeakPITCH,pitch_adjustment,0); | |||
if (pitch_adjustment != 50) { | |||
SetParameter(espeakPITCH, pitch_adjustment, 0); | |||
} | |||
DoVoiceChange(voice); | |||
if(filename[0]==0) | |||
{ | |||
if((optind < argc) && (flag_stdin == 0)) | |||
{ | |||
if (filename[0] == 0) { | |||
if ((optind < argc) && (flag_stdin == 0)) { | |||
// there's a non-option parameter, and no -f or --stdin | |||
// use it as text | |||
p_text = argv[optind]; | |||
} | |||
else | |||
{ | |||
} else { | |||
f_text = stdin; | |||
if(flag_stdin == 0) | |||
if (flag_stdin == 0) | |||
option_linelength = -1; // single input lines on stdin | |||
} | |||
} | |||
else | |||
{ | |||
f_text = fopen(filename,"r"); | |||
} else { | |||
f_text = fopen(filename, "r"); | |||
} | |||
if((f_text == NULL) && (p_text == NULL)) | |||
{ | |||
fprintf(stderr,"%sfile '%s'\n",err_load,filename); | |||
if ((f_text == NULL) && (p_text == NULL)) { | |||
fprintf(stderr, "%sfile '%s'\n", err_load, filename); | |||
exit(1); | |||
} | |||
if(option_waveout || quiet) | |||
{ | |||
if(quiet) | |||
{ | |||
if (option_waveout || quiet) { | |||
if (quiet) { | |||
// no sound output | |||
OpenWaveFile(NULL,samplerate); | |||
OpenWaveFile(NULL, samplerate); | |||
option_waveout = 1; | |||
} | |||
else | |||
{ | |||
} else { | |||
// write sound output to a WAV file | |||
samples_split = (samplerate * samples_split) * 60; | |||
if(samples_split) | |||
{ | |||
if (samples_split) { | |||
// don't open the wav file until we start generating speech | |||
char *extn; | |||
extn = strrchr(wavefile,'.'); | |||
if((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) | |||
{ | |||
strcpy(filetype,extn); | |||
extn = strrchr(wavefile, '.'); | |||
if ((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) { | |||
strcpy(filetype, extn); | |||
*extn = 0; | |||
} | |||
} | |||
else | |||
if(OpenWaveFile(wavefile,samplerate) != 0) | |||
{ | |||
fprintf(stderr,"Can't write to output file '%s'\n'",wavefile); | |||
} else if (OpenWaveFile(wavefile, samplerate) != 0) { | |||
fprintf(stderr, "Can't write to output file '%s'\n'", wavefile); | |||
exit(3); | |||
} | |||
} | |||
InitText(0); | |||
SpeakNextClause(f_text,p_text,0); | |||
SpeakNextClause(f_text, p_text, 0); | |||
ix = 1; | |||
for(;; ) | |||
{ | |||
if(WavegenFile() != 0) | |||
{ | |||
if(ix == 0) | |||
for (;;) { | |||
if (WavegenFile() != 0) { | |||
if (ix == 0) | |||
break; // finished, wavegen command queue is empty | |||
} | |||
if(Generate(phoneme_list,&n_phoneme_list,1)==0) | |||
{ | |||
ix = SpeakNextClause(NULL,NULL,1); | |||
if (Generate(phoneme_list, &n_phoneme_list, 1) == 0) { | |||
ix = SpeakNextClause(NULL, NULL, 1); | |||
} | |||
} | |||
CloseWaveFile(); | |||
} | |||
else | |||
{ | |||
} else { | |||
WavegenInitSound(); | |||
InitText(0); | |||
SpeakNextClause(f_text,p_text,0); | |||
SpeakNextClause(f_text, p_text, 0); | |||
if(option_quiet) | |||
{ | |||
while(SpeakNextClause(NULL,NULL,1) != 0); | |||
return(0); | |||
if (option_quiet) { | |||
while (SpeakNextClause(NULL, NULL, 1) != 0) ; | |||
return (0); | |||
} | |||
speaking = 1; | |||
while(speaking) | |||
{ | |||
while (speaking) { | |||
// NOTE: if nanosleep() isn't recognised on your system, try replacing | |||
// this by sleep(1); | |||
#ifdef PLATFORM_WINDOWS | |||
@@ -899,17 +831,17 @@ int main (int argc, char **argv) | |||
struct timespec remaining; | |||
period.tv_sec = 0; | |||
period.tv_nsec = 300000000; // 0.3 sec | |||
nanosleep(&period,&remaining); | |||
nanosleep(&period, &remaining); | |||
#else | |||
sleep(1); | |||
#endif | |||
#endif | |||
if(SynthOnTimer() != 0) | |||
if (SynthOnTimer() != 0) | |||
speaking = 0; | |||
} | |||
} | |||
if((f_trans != stdout) && (f_trans != stderr)) | |||
if ((f_trans != stdout) && (f_trans != stderr)) | |||
fclose(f_trans); // needed for WinCe | |||
return(0); | |||
return (0); | |||
} |