mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-10-31 13:38:47 +00:00
Merge branch 'master' of https://github.com/espeak-ng/espeak-ng
This commit is contained in:
+2
-1
@@ -41,8 +41,9 @@ libespeak-ng.a
|
||||
libespeak-ng.la
|
||||
libespeak-ng.so*
|
||||
|
||||
# programs
|
||||
# build output
|
||||
|
||||
*.html
|
||||
*.exe
|
||||
|
||||
src/espeak-ng
|
||||
|
||||
+10
-3
@@ -50,15 +50,22 @@ distclean-local:
|
||||
rm -rf espeak-data/phondata-manifest
|
||||
rm -f espeak-data/*_dict
|
||||
|
||||
##### documentation:
|
||||
|
||||
%.html: %.md _layouts/webpage.html
|
||||
cat $< | sed -e 's/\.md)/.html)/g' | kramdown --template _layouts/webpage.html > $@
|
||||
|
||||
docs: README.html
|
||||
|
||||
docs/speak_lib.h: src/include/espeak-ng/speak_lib.h
|
||||
cp $< $@
|
||||
|
||||
##### build targets:
|
||||
|
||||
libespeak_ng_includedir = $(includedir)/espeak-ng
|
||||
libespeak_ng_include_HEADERS = \
|
||||
src/include/espeak-ng/speak_lib.h
|
||||
|
||||
docs/speak_lib.h: src/include/espeak-ng/speak_lib.h
|
||||
cp $< $@
|
||||
|
||||
lib_LTLIBRARIES += src/libespeak-ng.la
|
||||
|
||||
src_libespeak_ng_la_LDFLAGS = -version-info $(SHARED_VERSION) -lpthread -lm
|
||||
|
||||
@@ -39,31 +39,52 @@ Optionally, you need:
|
||||
2. the portaudio development library to enable portaudio output;
|
||||
3. the sonic development library to enable sonic audio speed up support.
|
||||
|
||||
To build the documentation, you need:
|
||||
|
||||
1. the `kramdown` markdown processor.
|
||||
|
||||
### Debian
|
||||
|
||||
Core dependencies:
|
||||
|
||||
| Dependency | Install |
|
||||
|---------------|------------------------------------------------------------------|
|
||||
| autotools | `sudo apt-get install make autoconf automake libtool pkg-config` |
|
||||
| c11 compiler | `sudo apt-get install gcc` |
|
||||
| pulseaudio | `sudo apt-get install libpulse-dev` |
|
||||
| portaudio | `sudo apt-get install libportaudio-dev` |
|
||||
| sonic | `sudo apt-get install libsonic-dev` |
|
||||
|
||||
Optional dependencies:
|
||||
|
||||
| Dependency | Install |
|
||||
|------------|-----------------------------------------|
|
||||
| pulseaudio | `sudo apt-get install libpulse-dev` |
|
||||
| portaudio | `sudo apt-get install libportaudio-dev` |
|
||||
| sonic | `sudo apt-get install libsonic-dev` |
|
||||
|
||||
Documentation dependencies:
|
||||
|
||||
| Dependency | Install |
|
||||
|---------------|--------------------------------------|
|
||||
| kramdown | `sudo apt-get install ruby-kramdown` |
|
||||
|
||||
Cross-compiling for windows:
|
||||
|
||||
| Dependency | Install |
|
||||
|-------------------------|--------------------------------------------------------|
|
||||
| 32-bit Windows compiler | `sudo apt-get install mingw-w64-i686-dev` |
|
||||
| 64-bit Windows compiler | `sudo apt-get install mingw-w64-x86-64-dev` |
|
||||
| Dependency | Install |
|
||||
|-------------------------|---------------------------------------------|
|
||||
| 32-bit Windows compiler | `sudo apt-get install mingw-w64-i686-dev` |
|
||||
| 64-bit Windows compiler | `sudo apt-get install mingw-w64-x86-64-dev` |
|
||||
|
||||
## Building
|
||||
|
||||
The `espeak-ng` and `speak-ng` programs, along with the espeak-ng voices, can
|
||||
be built via the standard autotools commands:
|
||||
|
||||
$ ./autogen.sh
|
||||
$ ./configure --prefix=/usr
|
||||
$ make
|
||||
./autogen.sh
|
||||
./configure --prefix=/usr
|
||||
make
|
||||
|
||||
The documentation can be built by running:
|
||||
|
||||
make doc
|
||||
|
||||
### Audio Output Configuration
|
||||
|
||||
@@ -134,7 +155,7 @@ __NOTE:__ This currently fails to build `espeak-ng.exe`, but does build
|
||||
|
||||
Before installing, you can test the built espeak-ng using the following command:
|
||||
|
||||
$ ESPEAK_DATA_PATH=`pwd` LD_LIBRARY_PATH=src:${LD_LIBRARY_PATH} src/espeak-ng ...
|
||||
ESPEAK_DATA_PATH=`pwd` LD_LIBRARY_PATH=src:${LD_LIBRARY_PATH} src/espeak-ng ...
|
||||
|
||||
The `ESPEAK_DATA_PATH` variable needs to be set to use the espeak-ng data from
|
||||
the source tree. Otherwise, espeak-ng will look in `$(HOME)` or
|
||||
@@ -149,7 +170,7 @@ version).
|
||||
|
||||
You can install eSpeak NG by running the following command:
|
||||
|
||||
$ sudo make LIBDIR=/usr/lib/x86_64-linux-gnu install
|
||||
sudo make LIBDIR=/usr/lib/x86_64-linux-gnu install
|
||||
|
||||
The `LIBDIR` path may be different to the one on your system (the above
|
||||
is for 64-bit Debian/Ubuntu releases that use the multi-arch package
|
||||
@@ -158,19 +179,19 @@ structure -- that is, Debian Wheezy or later).
|
||||
You can find out where espeak-ng is installed to on your system if you
|
||||
already have an espeak-ng install by running:
|
||||
|
||||
$ find /usr/lib | grep libespeak-ng
|
||||
find /usr/lib | grep libespeak-ng
|
||||
|
||||
## Building Voices
|
||||
|
||||
If you are modifying a language's phoneme, voice or dictionary files, you
|
||||
can just build that voice by running:
|
||||
|
||||
$ make <lang-code>
|
||||
make <lang-code>
|
||||
|
||||
For example, if you add entries in the `dictsource/en_extra` file, you can
|
||||
run:
|
||||
|
||||
$ make en
|
||||
make en
|
||||
|
||||
to build an English voice file with those changes in without rebuilding
|
||||
all the voices. This will make it easier to spot errors.
|
||||
@@ -206,7 +227,7 @@ These early releases have been checked into the historical branch,
|
||||
with the 1.24.02 release as the last entry. This makes it possible
|
||||
to use the replace functionality of git to see the earlier history:
|
||||
|
||||
$ git replace 8d59235f 63c1c019
|
||||
git replace 8d59235f 63c1c019
|
||||
|
||||
__NOTE:__ The source releases contain the `big_endian`, `espeak-edit`,
|
||||
`praat-mod`, `riskos`, `windows_dll` and `windows_sapi` folders. These
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1"/>
|
||||
<meta name="robots" content="all"/>
|
||||
<style type="text/css">
|
||||
body
|
||||
{
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
*:first-child
|
||||
{
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
code, pre
|
||||
{
|
||||
font-family: monospace;
|
||||
background: #F7F7F7;
|
||||
color: navy;
|
||||
}
|
||||
|
||||
code
|
||||
{
|
||||
font-size: 85%;
|
||||
padding: 0.2em;
|
||||
}
|
||||
|
||||
pre
|
||||
{
|
||||
margin-left: 3em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
th
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
border: 0;
|
||||
border-bottom: 1px solid #BBB;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<%= @body %>
|
||||
</body>
|
||||
</html>
|
||||
+183
-254
@@ -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;
|
||||
}
|
||||
|
||||
+941
-1251
File diff suppressed because it is too large
Load Diff
+513
-715
File diff suppressed because it is too large
Load Diff
@@ -48,17 +48,16 @@ static unsigned int StringToWord(const char *string)
|
||||
unsigned char c;
|
||||
unsigned int word;
|
||||
|
||||
if(string==NULL)
|
||||
return(0);
|
||||
if (string == NULL)
|
||||
return 0;
|
||||
|
||||
word = 0;
|
||||
for(ix=0; ix<4; ix++)
|
||||
{
|
||||
if(string[ix]==0) break;
|
||||
for (ix = 0; ix < 4; ix++) {
|
||||
if (string[ix] == 0) break;
|
||||
c = string[ix];
|
||||
word |= (c << (ix*8));
|
||||
}
|
||||
return(word);
|
||||
return word;
|
||||
}
|
||||
|
||||
#pragma GCC visibility push(default)
|
||||
@@ -82,34 +81,29 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log)
|
||||
int mbrola_ctrl = 20; // volume in 1/16 ths
|
||||
MBROLA_TAB data[N_PHONEME_TAB];
|
||||
|
||||
strcpy(buf,filepath);
|
||||
if((f_in = fopen(buf,"r")) == NULL)
|
||||
{
|
||||
strcpy(buf, filepath);
|
||||
if ((f_in = fopen(buf, "r")) == NULL) {
|
||||
fprintf(log, "Can't read: %s\n", filepath);
|
||||
return ENE_READ_ERROR;
|
||||
}
|
||||
|
||||
while(fgets(buf,sizeof(phoneme),f_in) != NULL)
|
||||
{
|
||||
while (fgets(buf, sizeof(phoneme), f_in) != NULL) {
|
||||
buf[sizeof(phoneme)-1] = 0;
|
||||
|
||||
if((p = strstr(buf,"//")) != NULL)
|
||||
if ((p = strstr(buf, "//")) != NULL)
|
||||
*p = 0; // truncate line at comment
|
||||
|
||||
if(memcmp(buf,"volume",6)==0)
|
||||
{
|
||||
if (memcmp(buf, "volume", 6) == 0) {
|
||||
mbrola_ctrl = atoi(&buf[6]);
|
||||
continue;
|
||||
}
|
||||
|
||||
n = sscanf(buf,"%d %s %s %d %s %s",&control,phoneme,phoneme2,&percent,name1,name2);
|
||||
if(n >= 5)
|
||||
{
|
||||
n = sscanf(buf, "%d %s %s %d %s %s", &control, phoneme, phoneme2, &percent, name1, name2);
|
||||
if (n >= 5) {
|
||||
data[count].name = StringToWord(phoneme);
|
||||
if(strcmp(phoneme2,"NULL")==0)
|
||||
if (strcmp(phoneme2, "NULL") == 0)
|
||||
data[count].next_phoneme = 0;
|
||||
else
|
||||
if(strcmp(phoneme2,"VWL")==0)
|
||||
else if (strcmp(phoneme2, "VWL") == 0)
|
||||
data[count].next_phoneme = 2;
|
||||
else
|
||||
data[count].next_phoneme = StringToWord(phoneme2);
|
||||
@@ -117,9 +111,9 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log)
|
||||
data[count].mbr_name2 = 0;
|
||||
data[count].percent = percent;
|
||||
data[count].control = control;
|
||||
if(strcmp(name1,"NULL")!=0)
|
||||
if (strcmp(name1, "NULL") != 0)
|
||||
data[count].mbr_name = StringToWord(name1);
|
||||
if(n == 6)
|
||||
if (n == 6)
|
||||
data[count].mbr_name2 = StringToWord(name2);
|
||||
|
||||
count++;
|
||||
@@ -127,10 +121,9 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log)
|
||||
}
|
||||
fclose(f_in);
|
||||
|
||||
strcpy(mbrola_voice,basename(filepath));
|
||||
sprintf(buf,"%s/mbrola_ph/%s_phtrans",path_home,mbrola_voice);
|
||||
if((f_out = fopen(buf,"wb")) == NULL)
|
||||
{
|
||||
strcpy(mbrola_voice, basename(filepath));
|
||||
sprintf(buf, "%s/mbrola_ph/%s_phtrans", path_home, mbrola_voice);
|
||||
if ((f_out = fopen(buf, "wb")) == NULL) {
|
||||
fprintf(log, "Can't write to: %s\n", buf);
|
||||
return ENE_WRITE_ERROR;
|
||||
}
|
||||
@@ -139,8 +132,7 @@ espeak_ng_STATUS espeak_ng_CompileMbrolaVoice(const char *filepath, FILE *log)
|
||||
Write4Bytes(f_out, mbrola_ctrl);
|
||||
|
||||
pw_end = (int *)(&data[count+1]);
|
||||
for(pw = (int *)data; pw < pw_end; pw++)
|
||||
{
|
||||
for (pw = (int *)data; pw < pw_end; pw++) {
|
||||
Write4Bytes(f_out, *pw);
|
||||
}
|
||||
fclose(f_out);
|
||||
|
||||
+13
-19
@@ -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)
|
||||
|
||||
+802
-1294
File diff suppressed because it is too large
Load Diff
+155
-203
@@ -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
|
||||
|
||||
+139
-197
@@ -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))
|
||||
{
|
||||
};
|
||||
while (0 == sem_trywait(&my_sem_stop_is_required)) {
|
||||
}
|
||||
;
|
||||
} else {
|
||||
a_stop_is_required = 0;
|
||||
}
|
||||
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.
|
||||
|
||||
+96
-145
@@ -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));
|
||||
return (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.
|
||||
|
||||
+240
-374
File diff suppressed because it is too large
Load Diff
+176
-265
@@ -49,34 +49,34 @@ static int sample_count;
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define getrandom(min,max) ((rand()%(int)(((max)+1)-(min)))+(min))
|
||||
#define getrandom(min, max) ((rand()%(int)(((max)+1)-(min)))+(min))
|
||||
#else
|
||||
#define getrandom(min,max) ((rand()%(long)(((max)+1)-(min)))+(min))
|
||||
#define getrandom(min, max) ((rand()%(long)(((max)+1)-(min)))+(min))
|
||||
#endif
|
||||
|
||||
|
||||
/* function prototypes for functions private to this file */
|
||||
|
||||
static void flutter(klatt_frame_ptr);
|
||||
static double sampled_source (int);
|
||||
static double impulsive_source (void);
|
||||
static double natural_source (void);
|
||||
static void pitch_synch_par_reset (klatt_frame_ptr);
|
||||
static double gen_noise (double);
|
||||
static double DBtoLIN (long);
|
||||
static void frame_init (klatt_frame_ptr);
|
||||
static void setabc (long,long,resonator_ptr);
|
||||
static void setzeroabc (long,long,resonator_ptr);
|
||||
static double sampled_source(int);
|
||||
static double impulsive_source(void);
|
||||
static double natural_source(void);
|
||||
static void pitch_synch_par_reset(klatt_frame_ptr);
|
||||
static double gen_noise(double);
|
||||
static double DBtoLIN(long);
|
||||
static void frame_init(klatt_frame_ptr);
|
||||
static void setabc(long, long, resonator_ptr);
|
||||
static void setzeroabc(long, long, resonator_ptr);
|
||||
|
||||
static klatt_frame_t kt_frame;
|
||||
static klatt_global_t kt_globals;
|
||||
|
||||
#define NUMBER_OF_SAMPLES 100
|
||||
|
||||
static int scale_wav_tab[] = {45,38,45,45,55}; // scale output from different voicing sources
|
||||
static int scale_wav_tab[] = { 45, 38, 45, 45, 55 }; // scale output from different voicing sources
|
||||
|
||||
// For testing, this can be overwritten in KlattInit()
|
||||
static short natural_samples2[256]= {
|
||||
static short natural_samples2[256] = {
|
||||
2583, 2516, 2450, 2384, 2319, 2254, 2191, 2127,
|
||||
2067, 2005, 1946, 1890, 1832, 1779, 1726, 1675,
|
||||
1626, 1579, 1533, 1491, 1449, 1409, 1372, 1336,
|
||||
@@ -110,15 +110,14 @@ static short natural_samples2[256]= {
|
||||
-1680, -1732, -1783, -1839, -1894, -1952, -2010, -2072,
|
||||
-2133, -2196, -2260, -2325, -2390, -2456, -2522, -2589,
|
||||
};
|
||||
static short natural_samples[100]=
|
||||
{
|
||||
-310,-400,530,356,224,89,23,-10,-58,-16,461,599,536,701,770,
|
||||
605,497,461,560,404,110,224,131,104,-97,155,278,-154,-1165,
|
||||
-598,737,125,-592,41,11,-247,-10,65,92,80,-304,71,167,-1,122,
|
||||
233,161,-43,278,479,485,407,266,650,134,80,236,68,260,269,179,
|
||||
53,140,275,293,296,104,257,152,311,182,263,245,125,314,140,44,
|
||||
203,230,-235,-286,23,107,92,-91,38,464,443,176,98,-784,-2449,
|
||||
-1891,-1045,-1600,-1462,-1384,-1261,-949,-730
|
||||
static short natural_samples[100] = {
|
||||
-310, -400, 530, 356, 224, 89, 23, -10, -58, -16, 461, 599, 536, 701, 770,
|
||||
605, 497, 461, 560, 404, 110, 224, 131, 104, -97, 155, 278, -154, -1165,
|
||||
-598, 737, 125, -592, 41, 11, -247, -10, 65, 92, 80, -304, 71, 167, -1, 122,
|
||||
233, 161, -43, 278, 479, 485, 407, 266, 650, 134, 80, 236, 68, 260, 269, 179,
|
||||
53, 140, 275, 293, 296, 104, 257, 152, 311, 182, 263, 245, 125, 314, 140, 44,
|
||||
203, 230, -235, -286, 23, 107, 92, -91, 38, 464, 443, 176, 98, -784, -2449,
|
||||
-1891, -1045, -1600, -1462, -1384, -1261, -949, -730
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -132,7 +131,7 @@ static double resonator(resonator_ptr r, double input)
|
||||
{
|
||||
double x;
|
||||
|
||||
x = (double) ((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2);
|
||||
x = (double)((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2);
|
||||
r->p2 = (double)r->p1;
|
||||
r->p1 = (double)x;
|
||||
|
||||
@@ -143,7 +142,7 @@ static double resonator2(resonator_ptr r, double input)
|
||||
{
|
||||
double x;
|
||||
|
||||
x = (double) ((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2);
|
||||
x = (double)((double)r->a * (double)input + (double)r->b * (double)r->p1 + (double)r->c * (double)r->p2);
|
||||
r->p2 = (double)r->p1;
|
||||
r->p1 = (double)x;
|
||||
|
||||
@@ -185,15 +184,15 @@ static void flutter(klatt_frame_ptr frame)
|
||||
{
|
||||
static int time_count;
|
||||
double delta_f0;
|
||||
double fla,flb,flc,fld,fle;
|
||||
double fla, flb, flc, fld, fle;
|
||||
|
||||
fla = (double) kt_globals.f0_flutter / 50;
|
||||
flb = (double) kt_globals.original_f0 / 100;
|
||||
fla = (double)kt_globals.f0_flutter / 50;
|
||||
flb = (double)kt_globals.original_f0 / 100;
|
||||
flc = sin(PI*12.7*time_count); // because we are calling flutter() more frequently, every 2.9mS
|
||||
fld = sin(PI*7.1*time_count);
|
||||
fle = sin(PI*4.7*time_count);
|
||||
delta_f0 = fla * flb * (flc + fld + fle) * 10;
|
||||
frame->F0hz10 = frame->F0hz10 + (long) delta_f0;
|
||||
frame->F0hz10 = frame->F0hz10 + (long)delta_f0;
|
||||
time_count++;
|
||||
}
|
||||
|
||||
@@ -217,40 +216,34 @@ static double sampled_source(int source_num)
|
||||
double temp_diff;
|
||||
short *samples;
|
||||
|
||||
if(source_num == 0)
|
||||
{
|
||||
if (source_num == 0) {
|
||||
samples = natural_samples;
|
||||
kt_globals.num_samples = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
samples = natural_samples2;
|
||||
kt_globals.num_samples = 256;
|
||||
}
|
||||
|
||||
if(kt_globals.T0!=0)
|
||||
{
|
||||
ftemp = (double) kt_globals.nper;
|
||||
if (kt_globals.T0 != 0) {
|
||||
ftemp = (double)kt_globals.nper;
|
||||
ftemp = ftemp / kt_globals.T0;
|
||||
ftemp = ftemp * kt_globals.num_samples;
|
||||
itemp = (int) ftemp;
|
||||
itemp = (int)ftemp;
|
||||
|
||||
temp_diff = ftemp - (double) itemp;
|
||||
temp_diff = ftemp - (double)itemp;
|
||||
|
||||
current_value = samples[itemp];
|
||||
next_value = samples[itemp+1];
|
||||
|
||||
diff_value = (double) next_value - (double) current_value;
|
||||
diff_value = (double)next_value - (double)current_value;
|
||||
diff_value = diff_value * temp_diff;
|
||||
|
||||
result = samples[itemp] + diff_value;
|
||||
result = result * kt_globals.sample_factor;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -286,8 +279,7 @@ static int parwave(klatt_frame_ptr frame)
|
||||
|
||||
/* MAIN LOOP, for each output sample of current frame: */
|
||||
|
||||
for (kt_globals.ns=0; kt_globals.ns<kt_globals.nspfr; kt_globals.ns++)
|
||||
{
|
||||
for (kt_globals.ns = 0; kt_globals.ns < kt_globals.nspfr; kt_globals.ns++) {
|
||||
/* Get low-passed random number for aspiration and frication noise */
|
||||
noise = gen_noise(noise);
|
||||
|
||||
@@ -296,9 +288,8 @@ static int parwave(klatt_frame_ptr frame)
|
||||
second half of glottal period) if voicing simultaneously present.
|
||||
*/
|
||||
|
||||
if (kt_globals.nper > kt_globals.nmod)
|
||||
{
|
||||
noise *= (double) 0.5;
|
||||
if (kt_globals.nper > kt_globals.nmod) {
|
||||
noise *= (double)0.5;
|
||||
}
|
||||
|
||||
/* Compute frication noise */
|
||||
@@ -310,9 +301,8 @@ static int parwave(klatt_frame_ptr frame)
|
||||
period of female voice.
|
||||
*/
|
||||
|
||||
for (n4=0; n4<4; n4++)
|
||||
{
|
||||
switch(kt_globals.glsource)
|
||||
for (n4 = 0; n4 < 4; n4++) {
|
||||
switch (kt_globals.glsource)
|
||||
{
|
||||
case IMPULSIVE:
|
||||
voice = impulsive_source();
|
||||
@@ -329,8 +319,7 @@ static int parwave(klatt_frame_ptr frame)
|
||||
}
|
||||
|
||||
/* Reset period when counter 'nper' reaches T0 */
|
||||
if (kt_globals.nper >= kt_globals.T0)
|
||||
{
|
||||
if (kt_globals.nper >= kt_globals.T0) {
|
||||
kt_globals.nper = 0;
|
||||
pitch_synch_par_reset(frame);
|
||||
}
|
||||
@@ -340,7 +329,7 @@ static int parwave(klatt_frame_ptr frame)
|
||||
to samrate samples/sec. Resonator f=.09*samrate, bw=.06*samrate
|
||||
*/
|
||||
|
||||
voice = resonator(&(kt_globals.rsn[RLP]),voice);
|
||||
voice = resonator(&(kt_globals.rsn[RLP]), voice);
|
||||
|
||||
/* Increment counter that keeps track of 4*samrate samples per sec */
|
||||
kt_globals.nper++;
|
||||
@@ -361,8 +350,7 @@ static int parwave(klatt_frame_ptr frame)
|
||||
*/
|
||||
|
||||
|
||||
if (kt_globals.nper < kt_globals.nopen)
|
||||
{
|
||||
if (kt_globals.nper < kt_globals.nopen) {
|
||||
voice += kt_globals.amp_breth * kt_globals.nrand;
|
||||
}
|
||||
|
||||
@@ -381,19 +369,18 @@ static int parwave(klatt_frame_ptr frame)
|
||||
Nasal antiresonator, then formants FNP, F5, F4, F3, F2, F1
|
||||
*/
|
||||
|
||||
out=0;
|
||||
if(kt_globals.synthesis_model != ALL_PARALLEL)
|
||||
{
|
||||
casc_next_in = antiresonator2(&(kt_globals.rsn[Rnz]),glotout);
|
||||
casc_next_in = resonator(&(kt_globals.rsn[Rnpc]),casc_next_in);
|
||||
casc_next_in = resonator(&(kt_globals.rsn[R8c]),casc_next_in);
|
||||
casc_next_in = resonator(&(kt_globals.rsn[R7c]),casc_next_in);
|
||||
casc_next_in = resonator(&(kt_globals.rsn[R6c]),casc_next_in);
|
||||
casc_next_in = resonator2(&(kt_globals.rsn[R5c]),casc_next_in);
|
||||
casc_next_in = resonator2(&(kt_globals.rsn[R4c]),casc_next_in);
|
||||
casc_next_in = resonator2(&(kt_globals.rsn[R3c]),casc_next_in);
|
||||
casc_next_in = resonator2(&(kt_globals.rsn[R2c]),casc_next_in);
|
||||
out = resonator2(&(kt_globals.rsn[R1c]),casc_next_in);
|
||||
out = 0;
|
||||
if (kt_globals.synthesis_model != ALL_PARALLEL) {
|
||||
casc_next_in = antiresonator2(&(kt_globals.rsn[Rnz]), glotout);
|
||||
casc_next_in = resonator(&(kt_globals.rsn[Rnpc]), casc_next_in);
|
||||
casc_next_in = resonator(&(kt_globals.rsn[R8c]), casc_next_in);
|
||||
casc_next_in = resonator(&(kt_globals.rsn[R7c]), casc_next_in);
|
||||
casc_next_in = resonator(&(kt_globals.rsn[R6c]), casc_next_in);
|
||||
casc_next_in = resonator2(&(kt_globals.rsn[R5c]), casc_next_in);
|
||||
casc_next_in = resonator2(&(kt_globals.rsn[R4c]), casc_next_in);
|
||||
casc_next_in = resonator2(&(kt_globals.rsn[R3c]), casc_next_in);
|
||||
casc_next_in = resonator2(&(kt_globals.rsn[R2c]), casc_next_in);
|
||||
out = resonator2(&(kt_globals.rsn[R1c]), casc_next_in);
|
||||
}
|
||||
|
||||
/* Excite parallel F1 and FNP by voicing waveform */
|
||||
@@ -406,22 +393,21 @@ static int parwave(klatt_frame_ptr frame)
|
||||
voicing waveform.
|
||||
*/
|
||||
|
||||
out += resonator(&(kt_globals.rsn[R1p]),sourc);
|
||||
out += resonator(&(kt_globals.rsn[Rnpp]),sourc);
|
||||
out += resonator(&(kt_globals.rsn[R1p]), sourc);
|
||||
out += resonator(&(kt_globals.rsn[Rnpp]), sourc);
|
||||
|
||||
sourc = frics + par_glotout - glotlast;
|
||||
glotlast = par_glotout;
|
||||
|
||||
for(ix=R2p; ix<=R6p; ix++)
|
||||
{
|
||||
out = resonator(&(kt_globals.rsn[ix]),sourc) - out;
|
||||
for (ix = R2p; ix <= R6p; ix++) {
|
||||
out = resonator(&(kt_globals.rsn[ix]), sourc) - out;
|
||||
}
|
||||
|
||||
outbypas = kt_globals.amp_bypas * sourc;
|
||||
|
||||
out = outbypas - out;
|
||||
|
||||
out = resonator(&(kt_globals.rsn[Rout]),out);
|
||||
out = resonator(&(kt_globals.rsn[Rout]), out);
|
||||
temp = (int)(out * wdata.amplitude * kt_globals.amp_gain0); /* Convert back to integer */
|
||||
|
||||
|
||||
@@ -432,17 +418,13 @@ static int parwave(klatt_frame_ptr frame)
|
||||
int sample;
|
||||
|
||||
z2 = 0;
|
||||
if(wdata.mix_wavefile_ix < wdata.n_mix_wavefile)
|
||||
{
|
||||
if(wdata.mix_wave_scale == 0)
|
||||
{
|
||||
if (wdata.mix_wavefile_ix < wdata.n_mix_wavefile) {
|
||||
if (wdata.mix_wave_scale == 0) {
|
||||
// a 16 bit sample
|
||||
c = wdata.mix_wavefile[wdata.mix_wavefile_ix+1];
|
||||
sample = wdata.mix_wavefile[wdata.mix_wavefile_ix] + (c * 256);
|
||||
wdata.mix_wavefile_ix += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// a 8 bit sample, scaled
|
||||
sample = (signed char)wdata.mix_wavefile[wdata.mix_wavefile_ix++] * wdata.mix_wave_scale;
|
||||
}
|
||||
@@ -453,23 +435,20 @@ static int parwave(klatt_frame_ptr frame)
|
||||
}
|
||||
|
||||
// if fadeout is set, fade to zero over 64 samples, to avoid clicks at end of synthesis
|
||||
if(kt_globals.fadeout > 0)
|
||||
{
|
||||
if (kt_globals.fadeout > 0) {
|
||||
kt_globals.fadeout--;
|
||||
temp = (temp * kt_globals.fadeout) / 64;
|
||||
}
|
||||
|
||||
value = (int)temp + ((echo_buf[echo_tail++]*echo_amp) >> 8);
|
||||
if(echo_tail >= N_ECHO_BUF)
|
||||
echo_tail=0;
|
||||
if (echo_tail >= N_ECHO_BUF)
|
||||
echo_tail = 0;
|
||||
|
||||
if (value < -32768)
|
||||
{
|
||||
if (value < -32768) {
|
||||
value = -32768;
|
||||
}
|
||||
|
||||
if (value > 32767)
|
||||
{
|
||||
if (value > 32767) {
|
||||
value = 32767;
|
||||
}
|
||||
|
||||
@@ -477,16 +456,15 @@ static int parwave(klatt_frame_ptr frame)
|
||||
*out_ptr++ = value >> 8;
|
||||
|
||||
echo_buf[echo_head++] = value;
|
||||
if(echo_head >= N_ECHO_BUF)
|
||||
if (echo_head >= N_ECHO_BUF)
|
||||
echo_head = 0;
|
||||
|
||||
sample_count++;
|
||||
if(out_ptr >= out_end)
|
||||
{
|
||||
return(1);
|
||||
if (out_ptr >= out_end) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -497,34 +475,30 @@ void KlattReset(int control)
|
||||
{
|
||||
int r_ix;
|
||||
|
||||
if(control == 2)
|
||||
{
|
||||
//Full reset
|
||||
if (control == 2) {
|
||||
// Full reset
|
||||
kt_globals.FLPhz = (950 * kt_globals.samrate) / 10000;
|
||||
kt_globals.BLPhz = (630 * kt_globals.samrate) / 10000;
|
||||
kt_globals.minus_pi_t = -PI / kt_globals.samrate;
|
||||
kt_globals.two_pi_t = -2.0 * kt_globals.minus_pi_t;
|
||||
setabc(kt_globals.FLPhz,kt_globals.BLPhz,&(kt_globals.rsn[RLP]));
|
||||
setabc(kt_globals.FLPhz, kt_globals.BLPhz, &(kt_globals.rsn[RLP]));
|
||||
|
||||
}
|
||||
|
||||
if(control > 0)
|
||||
{
|
||||
if (control > 0) {
|
||||
kt_globals.nper = 0;
|
||||
kt_globals.T0 = 0;
|
||||
kt_globals.nopen = 0;
|
||||
kt_globals.nmod = 0;
|
||||
|
||||
for(r_ix=RGL; r_ix < N_RSN; r_ix++)
|
||||
{
|
||||
for (r_ix = RGL; r_ix < N_RSN; r_ix++) {
|
||||
kt_globals.rsn[r_ix].p1 = 0;
|
||||
kt_globals.rsn[r_ix].p2 = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(r_ix=0; r_ix <= R6p; r_ix++)
|
||||
{
|
||||
for (r_ix = 0; r_ix <= R6p; r_ix++) {
|
||||
kt_globals.rsn[r_ix].p1 = 0;
|
||||
kt_globals.rsn[r_ix].p2 = 0;
|
||||
}
|
||||
@@ -540,15 +514,14 @@ void KlattReset(int control)
|
||||
static void frame_init(klatt_frame_ptr frame)
|
||||
{
|
||||
double amp_par[7];
|
||||
static double amp_par_factor[7] = {0.6, 0.4, 0.15, 0.06, 0.04, 0.022, 0.03};
|
||||
static double amp_par_factor[7] = { 0.6, 0.4, 0.15, 0.06, 0.04, 0.022, 0.03 };
|
||||
long Gain0_tmp;
|
||||
int ix;
|
||||
|
||||
kt_globals.original_f0 = frame->F0hz10 / 10;
|
||||
|
||||
frame->AVdb_tmp = frame->AVdb - 7;
|
||||
if (frame->AVdb_tmp < 0)
|
||||
{
|
||||
if (frame->AVdb_tmp < 0) {
|
||||
frame->AVdb_tmp = 0;
|
||||
}
|
||||
|
||||
@@ -557,28 +530,24 @@ static void frame_init(klatt_frame_ptr frame)
|
||||
kt_globals.par_amp_voice = DBtoLIN(frame->AVpdb);
|
||||
kt_globals.amp_bypas = DBtoLIN(frame->AB) * 0.05;
|
||||
|
||||
for(ix=0; ix <= 6; ix++)
|
||||
{
|
||||
for (ix = 0; ix <= 6; ix++) {
|
||||
// parallel amplitudes F1 to F6, and parallel nasal pole
|
||||
amp_par[ix] = DBtoLIN(frame->Ap[ix]) * amp_par_factor[ix];
|
||||
}
|
||||
|
||||
Gain0_tmp = frame->Gain0 - 3;
|
||||
if (Gain0_tmp <= 0)
|
||||
{
|
||||
if (Gain0_tmp <= 0) {
|
||||
Gain0_tmp = 57;
|
||||
}
|
||||
kt_globals.amp_gain0 = DBtoLIN(Gain0_tmp) / kt_globals.scale_wav;
|
||||
|
||||
/* Set coefficients of variable cascade resonators */
|
||||
for(ix=1; ix<=9; ix++)
|
||||
{
|
||||
for (ix = 1; ix <= 9; ix++) {
|
||||
// formants 1 to 8, plus nasal pole
|
||||
setabc(frame->Fhz[ix],frame->Bhz[ix],&(kt_globals.rsn[ix]));
|
||||
setabc(frame->Fhz[ix], frame->Bhz[ix], &(kt_globals.rsn[ix]));
|
||||
|
||||
if(ix <= 5)
|
||||
{
|
||||
setabc(frame->Fhz_next[ix],frame->Bhz_next[ix],&(kt_globals.rsn_next[ix]));
|
||||
if (ix <= 5) {
|
||||
setabc(frame->Fhz_next[ix], frame->Bhz_next[ix], &(kt_globals.rsn_next[ix]));
|
||||
|
||||
kt_globals.rsn[ix].a_inc = (kt_globals.rsn_next[ix].a - kt_globals.rsn[ix].a) / 64.0;
|
||||
kt_globals.rsn[ix].b_inc = (kt_globals.rsn_next[ix].b - kt_globals.rsn[ix].b) / 64.0;
|
||||
@@ -587,8 +556,8 @@ static void frame_init(klatt_frame_ptr frame)
|
||||
}
|
||||
|
||||
// nasal zero anti-resonator
|
||||
setzeroabc(frame->Fhz[F_NZ],frame->Bhz[F_NZ],&(kt_globals.rsn[Rnz]));
|
||||
setzeroabc(frame->Fhz_next[F_NZ],frame->Bhz_next[F_NZ],&(kt_globals.rsn_next[Rnz]));
|
||||
setzeroabc(frame->Fhz[F_NZ], frame->Bhz[F_NZ], &(kt_globals.rsn[Rnz]));
|
||||
setzeroabc(frame->Fhz_next[F_NZ], frame->Bhz_next[F_NZ], &(kt_globals.rsn_next[Rnz]));
|
||||
kt_globals.rsn[F_NZ].a_inc = (kt_globals.rsn_next[F_NZ].a - kt_globals.rsn[F_NZ].a) / 64.0;
|
||||
kt_globals.rsn[F_NZ].b_inc = (kt_globals.rsn_next[F_NZ].b - kt_globals.rsn[F_NZ].b) / 64.0;
|
||||
kt_globals.rsn[F_NZ].c_inc = (kt_globals.rsn_next[F_NZ].c - kt_globals.rsn[F_NZ].c) / 64.0;
|
||||
@@ -596,15 +565,14 @@ static void frame_init(klatt_frame_ptr frame)
|
||||
|
||||
/* Set coefficients of parallel resonators, and amplitude of outputs */
|
||||
|
||||
for(ix=0; ix<=6; ix++)
|
||||
{
|
||||
setabc(frame->Fhz[ix],frame->Bphz[ix],&(kt_globals.rsn[Rparallel+ix]));
|
||||
for (ix = 0; ix <= 6; ix++) {
|
||||
setabc(frame->Fhz[ix], frame->Bphz[ix], &(kt_globals.rsn[Rparallel+ix]));
|
||||
kt_globals.rsn[Rparallel+ix].a *= amp_par[ix];
|
||||
}
|
||||
|
||||
/* output low-pass filter */
|
||||
|
||||
setabc((long)0.0,(long)(kt_globals.samrate/2),&(kt_globals.rsn[Rout]));
|
||||
setabc((long)0.0, (long)(kt_globals.samrate/2), &(kt_globals.rsn[Rout]));
|
||||
|
||||
}
|
||||
|
||||
@@ -622,19 +590,16 @@ static void frame_init(klatt_frame_ptr frame)
|
||||
|
||||
static double impulsive_source()
|
||||
{
|
||||
static double doublet[] = {0.0,13000000.0,-13000000.0};
|
||||
static double doublet[] = { 0.0, 13000000.0, -13000000.0 };
|
||||
static double vwave;
|
||||
|
||||
if (kt_globals.nper < 3)
|
||||
{
|
||||
if (kt_globals.nper < 3) {
|
||||
vwave = doublet[kt_globals.nper];
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
vwave = 0.0;
|
||||
}
|
||||
|
||||
return(resonator(&(kt_globals.rsn[RGL]),vwave));
|
||||
return resonator(&(kt_globals.rsn[RGL]), vwave);
|
||||
}
|
||||
|
||||
|
||||
@@ -651,18 +616,15 @@ static double natural_source()
|
||||
double lgtemp;
|
||||
static double vwave;
|
||||
|
||||
if (kt_globals.nper < kt_globals.nopen)
|
||||
{
|
||||
if (kt_globals.nper < kt_globals.nopen) {
|
||||
kt_globals.pulse_shape_a -= kt_globals.pulse_shape_b;
|
||||
vwave += kt_globals.pulse_shape_a;
|
||||
lgtemp=vwave * 0.028;
|
||||
lgtemp = vwave * 0.028;
|
||||
|
||||
return(lgtemp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return lgtemp;
|
||||
} else {
|
||||
vwave = 0.0;
|
||||
return(0.0);
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,26 +669,24 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame)
|
||||
long temp;
|
||||
double temp1;
|
||||
static long skew;
|
||||
static short B0[224] =
|
||||
{
|
||||
1200,1142,1088,1038, 991, 948, 907, 869, 833, 799, 768, 738, 710, 683, 658,
|
||||
static short B0[224] = {
|
||||
1200, 1142, 1088, 1038, 991, 948, 907, 869, 833, 799, 768, 738, 710, 683, 658,
|
||||
634, 612, 590, 570, 551, 533, 515, 499, 483, 468, 454, 440, 427, 415, 403,
|
||||
391, 380, 370, 360, 350, 341, 332, 323, 315, 307, 300, 292, 285, 278, 272,
|
||||
265, 259, 253, 247, 242, 237, 231, 226, 221, 217, 212, 208, 204, 199, 195,
|
||||
192, 188, 184, 180, 177, 174, 170, 167, 164, 161, 158, 155, 153, 150, 147,
|
||||
145, 142, 140, 137, 135, 133, 131, 128, 126, 124, 122, 120, 119, 117, 115,
|
||||
113,111, 110, 108, 106, 105, 103, 102, 100, 99, 97, 96, 95, 93, 92, 91, 90,
|
||||
113, 111, 110, 108, 106, 105, 103, 102, 100, 99, 97, 96, 95, 93, 92, 91, 90,
|
||||
88, 87, 86, 85, 84, 83, 82, 80, 79, 78, 77, 76, 75, 75, 74, 73, 72, 71,
|
||||
70, 69, 68, 68, 67, 66, 65, 64, 64, 63, 62, 61, 61, 60, 59, 59, 58, 57,
|
||||
57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48,
|
||||
47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 41, 41, 40, 40,
|
||||
39, 39, 38, 38, 38, 38, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34,33,
|
||||
39, 39, 38, 38, 38, 38, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 33,
|
||||
33, 33, 33, 32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29, 29, 29,
|
||||
28, 28, 28, 28, 27, 27
|
||||
};
|
||||
|
||||
if (frame->F0hz10 > 0)
|
||||
{
|
||||
if (frame->F0hz10 > 0) {
|
||||
/* T0 is 4* the number of samples in one pitch period */
|
||||
|
||||
kt_globals.T0 = (40 * kt_globals.samrate) / frame->F0hz10;
|
||||
@@ -737,8 +697,7 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame)
|
||||
/* Duration of period before amplitude modulation */
|
||||
|
||||
kt_globals.nmod = kt_globals.T0;
|
||||
if (frame->AVdb_tmp > 0)
|
||||
{
|
||||
if (frame->AVdb_tmp > 0) {
|
||||
kt_globals.nmod >>= 1;
|
||||
}
|
||||
|
||||
@@ -750,18 +709,15 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame)
|
||||
|
||||
kt_globals.nopen = 4 * frame->Kopen;
|
||||
|
||||
if ((kt_globals.glsource == IMPULSIVE) && (kt_globals.nopen > 263))
|
||||
{
|
||||
if ((kt_globals.glsource == IMPULSIVE) && (kt_globals.nopen > 263)) {
|
||||
kt_globals.nopen = 263;
|
||||
}
|
||||
|
||||
if (kt_globals.nopen >= (kt_globals.T0-1))
|
||||
{
|
||||
if (kt_globals.nopen >= (kt_globals.T0-1)) {
|
||||
kt_globals.nopen = kt_globals.T0 - 2;
|
||||
}
|
||||
|
||||
if (kt_globals.nopen < 40)
|
||||
{
|
||||
if (kt_globals.nopen < 40) {
|
||||
/* F0 max = 1000 Hz */
|
||||
kt_globals.nopen = 40;
|
||||
}
|
||||
@@ -776,7 +732,7 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame)
|
||||
|
||||
temp = kt_globals.samrate / kt_globals.nopen;
|
||||
|
||||
setabc((long)0,temp,&(kt_globals.rsn[RGL]));
|
||||
setabc((long)0, temp, &(kt_globals.rsn[RGL]));
|
||||
|
||||
/* Make gain at F1 about constant */
|
||||
|
||||
@@ -790,25 +746,19 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame)
|
||||
|
||||
|
||||
temp = kt_globals.T0 - kt_globals.nopen;
|
||||
if (frame->Kskew > temp)
|
||||
{
|
||||
if (frame->Kskew > temp) {
|
||||
frame->Kskew = temp;
|
||||
}
|
||||
if (skew >= 0)
|
||||
{
|
||||
if (skew >= 0) {
|
||||
skew = frame->Kskew;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
skew = -frame->Kskew;
|
||||
}
|
||||
|
||||
/* Add skewness to closed portion of voicing period */
|
||||
kt_globals.T0 = kt_globals.T0 + skew;
|
||||
skew = -skew;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
kt_globals.T0 = 4; /* Default for f0 undefined */
|
||||
kt_globals.amp_voice = 0.0;
|
||||
kt_globals.nmod = kt_globals.T0;
|
||||
@@ -819,18 +769,14 @@ static void pitch_synch_par_reset(klatt_frame_ptr frame)
|
||||
|
||||
/* Reset these pars pitch synchronously or at update rate if f0=0 */
|
||||
|
||||
if ((kt_globals.T0 != 4) || (kt_globals.ns == 0))
|
||||
{
|
||||
if ((kt_globals.T0 != 4) || (kt_globals.ns == 0)) {
|
||||
/* Set one-pole low-pass filter that tilts glottal source */
|
||||
|
||||
kt_globals.decay = (0.033 * frame->TLTdb);
|
||||
|
||||
if (kt_globals.decay > 0.0)
|
||||
{
|
||||
if (kt_globals.decay > 0.0) {
|
||||
kt_globals.onemd = 1.0 - kt_globals.decay;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
kt_globals.onemd = 1.0;
|
||||
}
|
||||
}
|
||||
@@ -901,8 +847,7 @@ static void setzeroabc(long int f, long int bw, resonator_ptr rp)
|
||||
* INF, causing an audible sound spike when triggered (e.g. apiration with the
|
||||
* nasal register set to f=0, bw=0).
|
||||
*/
|
||||
if (rp->a != 0)
|
||||
{
|
||||
if (rp->a != 0) {
|
||||
/* Now convert to antiresonator coefficients (a'=1/a, b'=b/a, c'=c/a) */
|
||||
rp->a = 1.0 / rp->a;
|
||||
rp->c *= -rp->a;
|
||||
@@ -925,13 +870,13 @@ static double gen_noise(double noise)
|
||||
long temp;
|
||||
static double nlast;
|
||||
|
||||
temp = (long) getrandom(-8191,8191);
|
||||
kt_globals.nrand = (long) temp;
|
||||
temp = (long)getrandom(-8191, 8191);
|
||||
kt_globals.nrand = (long)temp;
|
||||
|
||||
noise = kt_globals.nrand + (0.75 * nlast);
|
||||
nlast = noise;
|
||||
|
||||
return(noise);
|
||||
return noise;
|
||||
}
|
||||
|
||||
|
||||
@@ -956,8 +901,7 @@ static double gen_noise(double noise)
|
||||
|
||||
static double DBtoLIN(long dB)
|
||||
{
|
||||
static short amptable[88] =
|
||||
{
|
||||
static short amptable[88] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7,
|
||||
8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 25, 28, 32,
|
||||
35, 40, 45, 51, 57, 64, 71, 80, 90, 101, 114, 128,
|
||||
@@ -969,12 +913,11 @@ static double DBtoLIN(long dB)
|
||||
26214, 29491, 32767
|
||||
};
|
||||
|
||||
if ((dB < 0) || (dB > 87))
|
||||
{
|
||||
return(0);
|
||||
if ((dB < 0) || (dB > 87)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return((double)(amptable[dB]) * 0.001);
|
||||
return (double)(amptable[dB]) * 0.001;
|
||||
}
|
||||
|
||||
|
||||
@@ -998,28 +941,23 @@ int Wavegen_Klatt(int resume)
|
||||
int ix;
|
||||
int fade;
|
||||
|
||||
if(resume==0)
|
||||
{
|
||||
if (resume == 0) {
|
||||
sample_count = 0;
|
||||
}
|
||||
|
||||
while(sample_count < nsamples)
|
||||
{
|
||||
while (sample_count < nsamples) {
|
||||
kt_frame.F0hz10 = (wdata.pitch * 10) / 4096;
|
||||
|
||||
// formants F6,F7,F8 are fixed values for cascade resonators, set in KlattInit()
|
||||
// but F6 is used for parallel resonator
|
||||
// F0 is used for the nasal zero
|
||||
for(ix=0; ix < 6; ix++)
|
||||
{
|
||||
for (ix = 0; ix < 6; ix++) {
|
||||
kt_frame.Fhz[ix] = peaks[ix].freq;
|
||||
if(ix < 4)
|
||||
{
|
||||
if (ix < 4) {
|
||||
kt_frame.Bhz[ix] = peaks[ix].bw;
|
||||
}
|
||||
}
|
||||
for(ix=1; ix < 7; ix++)
|
||||
{
|
||||
for (ix = 1; ix < 7; ix++) {
|
||||
kt_frame.Ap[ix] = peaks[ix].ap;
|
||||
}
|
||||
|
||||
@@ -1034,8 +972,7 @@ int Wavegen_Klatt(int resume)
|
||||
kt_frame.Kopen = klattp[KLATT_Kopen];
|
||||
|
||||
// advance formants
|
||||
for(pk=0; pk<N_PEAKS; pk++)
|
||||
{
|
||||
for (pk = 0; pk < N_PEAKS; pk++) {
|
||||
peaks[pk].freq1 += peaks[pk].freq_inc;
|
||||
peaks[pk].freq = (int)peaks[pk].freq1;
|
||||
peaks[pk].bw1 += peaks[pk].bw_inc;
|
||||
@@ -1047,41 +984,36 @@ int Wavegen_Klatt(int resume)
|
||||
}
|
||||
|
||||
// advance other parameters
|
||||
for(ix=0; ix < N_KLATTP; ix++)
|
||||
{
|
||||
for (ix = 0; ix < N_KLATTP; ix++) {
|
||||
klattp1[ix] += klattp_inc[ix];
|
||||
klattp[ix] = (int)klattp1[ix];
|
||||
}
|
||||
|
||||
for(ix=0; ix<=6; ix++)
|
||||
{
|
||||
for (ix = 0; ix <= 6; ix++) {
|
||||
kt_frame.Fhz_next[ix] = peaks[ix].freq;
|
||||
if(ix < 4)
|
||||
{
|
||||
if (ix < 4) {
|
||||
kt_frame.Bhz_next[ix] = peaks[ix].bw;
|
||||
}
|
||||
}
|
||||
|
||||
// advance the pitch
|
||||
wdata.pitch_ix += wdata.pitch_inc;
|
||||
if((ix = wdata.pitch_ix>>8) > 127) ix = 127;
|
||||
if ((ix = wdata.pitch_ix>>8) > 127) ix = 127;
|
||||
x = wdata.pitch_env[ix] * wdata.pitch_range;
|
||||
wdata.pitch = (x>>8) + wdata.pitch_base;
|
||||
|
||||
kt_globals.nspfr = (nsamples - sample_count);
|
||||
if(kt_globals.nspfr > STEPSIZE)
|
||||
if (kt_globals.nspfr > STEPSIZE)
|
||||
kt_globals.nspfr = STEPSIZE;
|
||||
|
||||
frame_init(&kt_frame); /* get parameters for next frame of speech */
|
||||
|
||||
if(parwave(&kt_frame) == 1)
|
||||
{
|
||||
return(1); // output buffer is full
|
||||
if (parwave(&kt_frame) == 1) {
|
||||
return 1; // output buffer is full
|
||||
}
|
||||
}
|
||||
|
||||
if(end_wave > 0)
|
||||
{
|
||||
if (end_wave > 0) {
|
||||
fade = 64; // not followd by formant synthesis
|
||||
|
||||
// fade out to avoid a click
|
||||
@@ -1089,13 +1021,12 @@ int Wavegen_Klatt(int resume)
|
||||
end_wave = 0;
|
||||
sample_count -= fade;
|
||||
kt_globals.nspfr = fade;
|
||||
if(parwave(&kt_frame) == 1)
|
||||
{
|
||||
return(1); // output buffer is full
|
||||
if (parwave(&kt_frame) == 1) {
|
||||
return 1; // output buffer is full
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1108,10 +1039,8 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v
|
||||
frame_t *fr3;
|
||||
static frame_t prev_fr;
|
||||
|
||||
if(wvoice != NULL)
|
||||
{
|
||||
if((wvoice->klattv[0] > 0) && (wvoice->klattv[0] <=4 ))
|
||||
{
|
||||
if (wvoice != NULL) {
|
||||
if ((wvoice->klattv[0] > 0) && (wvoice->klattv[0] <= 4 )) {
|
||||
kt_globals.glsource = wvoice->klattv[0];
|
||||
kt_globals.scale_wav = scale_wav_tab[kt_globals.glsource];
|
||||
}
|
||||
@@ -1119,28 +1048,22 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v
|
||||
}
|
||||
|
||||
end_wave = 0;
|
||||
if(control & 2)
|
||||
{
|
||||
if (control & 2) {
|
||||
end_wave = 1; // fadeout at the end
|
||||
}
|
||||
if(control & 1)
|
||||
{
|
||||
if (control & 1) {
|
||||
end_wave = 1;
|
||||
for(qix=wcmdq_head+1;; qix++)
|
||||
{
|
||||
if(qix >= N_WCMDQ) qix = 0;
|
||||
if(qix == wcmdq_tail) break;
|
||||
for (qix = wcmdq_head+1;; qix++) {
|
||||
if (qix >= N_WCMDQ) qix = 0;
|
||||
if (qix == wcmdq_tail) break;
|
||||
|
||||
cmd = wcmdq[qix][0];
|
||||
if(cmd==WCMD_KLATT)
|
||||
{
|
||||
if (cmd == WCMD_KLATT) {
|
||||
end_wave = 0; // next wave generation is from another spectrum
|
||||
|
||||
fr3 = (frame_t *)wcmdq[qix][2];
|
||||
for(ix=1; ix<6; ix++)
|
||||
{
|
||||
if(fr3->ffreq[ix] != fr2->ffreq[ix])
|
||||
{
|
||||
for (ix = 1; ix < 6; ix++) {
|
||||
if (fr3->ffreq[ix] != fr2->ffreq[ix]) {
|
||||
// there is a discontinuity in formants
|
||||
end_wave = 2;
|
||||
break;
|
||||
@@ -1148,35 +1071,28 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v
|
||||
}
|
||||
break;
|
||||
}
|
||||
if((cmd==WCMD_WAVE) || (cmd==WCMD_PAUSE))
|
||||
if ((cmd == WCMD_WAVE) || (cmd == WCMD_PAUSE))
|
||||
break; // next is not from spectrum, so continue until end of wave cycle
|
||||
}
|
||||
}
|
||||
|
||||
if(control & 1)
|
||||
{
|
||||
for(ix=1; ix<6; ix++)
|
||||
{
|
||||
if(prev_fr.ffreq[ix] != fr1->ffreq[ix])
|
||||
{
|
||||
if (control & 1) {
|
||||
for (ix = 1; ix < 6; ix++) {
|
||||
if (prev_fr.ffreq[ix] != fr1->ffreq[ix]) {
|
||||
// Discontinuity in formants.
|
||||
// end_wave was set in SetSynth_Klatt() to fade out the previous frame
|
||||
KlattReset(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
memcpy(&prev_fr,fr2,sizeof(prev_fr));
|
||||
memcpy(&prev_fr, fr2, sizeof(prev_fr));
|
||||
}
|
||||
|
||||
for(ix=0; ix<N_KLATTP; ix++)
|
||||
{
|
||||
if((ix >= 5) && ((fr1->frflags & FRFLAG_KLATT) == 0))
|
||||
{
|
||||
for (ix = 0; ix < N_KLATTP; ix++) {
|
||||
if ((ix >= 5) && ((fr1->frflags & FRFLAG_KLATT) == 0)) {
|
||||
klattp1[ix] = klattp[ix] = 0;
|
||||
klattp_inc[ix] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
klattp1[ix] = klattp[ix] = fr1->klattp[ix];
|
||||
klattp_inc[ix] = (double)((fr2->klattp[ix] - klattp[ix]) * STEPSIZE)/length;
|
||||
}
|
||||
@@ -1184,15 +1100,13 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v
|
||||
|
||||
nsamples = length;
|
||||
|
||||
for(ix=1; ix < 6; ix++)
|
||||
{
|
||||
for (ix = 1; ix < 6; ix++) {
|
||||
peaks[ix].freq1 = (fr1->ffreq[ix] * v->freq[ix] / 256.0) + v->freqadd[ix];
|
||||
peaks[ix].freq = (int)peaks[ix].freq1;
|
||||
next = (fr2->ffreq[ix] * v->freq[ix] / 256.0) + v->freqadd[ix];
|
||||
peaks[ix].freq_inc = ((next - peaks[ix].freq1) * STEPSIZE) / length;
|
||||
|
||||
if(ix < 4)
|
||||
{
|
||||
if (ix < 4) {
|
||||
// klatt bandwidth for f1, f2, f3 (others are fixed)
|
||||
peaks[ix].bw1 = fr1->bw[ix] * 2;
|
||||
peaks[ix].bw = (int)peaks[ix].bw1;
|
||||
@@ -1203,12 +1117,12 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v
|
||||
|
||||
// nasal zero frequency
|
||||
peaks[0].freq1 = fr1->klattp[KLATT_FNZ] * 2;
|
||||
if(peaks[0].freq1 == 0)
|
||||
if (peaks[0].freq1 == 0)
|
||||
peaks[0].freq1 = kt_frame.Fhz[F_NP]; // if no nasal zero, set it to same freq as nasal pole
|
||||
|
||||
peaks[0].freq = (int)peaks[0].freq1;
|
||||
next = fr2->klattp[KLATT_FNZ] * 2;
|
||||
if(next == 0)
|
||||
if (next == 0)
|
||||
next = kt_frame.Fhz[F_NP];
|
||||
|
||||
peaks[0].freq_inc = ((next - peaks[0].freq1) * STEPSIZE) / length;
|
||||
@@ -1217,11 +1131,9 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v
|
||||
peaks[0].bw = 89;
|
||||
peaks[0].bw_inc = 0;
|
||||
|
||||
if(fr1->frflags & FRFLAG_KLATT)
|
||||
{
|
||||
if (fr1->frflags & FRFLAG_KLATT) {
|
||||
// the frame contains additional parameters for parallel resonators
|
||||
for(ix=1; ix < 7; ix++)
|
||||
{
|
||||
for (ix = 1; ix < 7; ix++) {
|
||||
peaks[ix].bp1 = fr1->klatt_bp[ix] * 4; // parallel bandwidth
|
||||
peaks[ix].bp = (int)peaks[ix].bp1;
|
||||
next = fr2->klatt_bp[ix] * 4;
|
||||
@@ -1238,10 +1150,10 @@ void SetSynth_Klatt(int length, int modn, frame_t *fr1, frame_t *fr2, voice_t *v
|
||||
|
||||
int Wavegen_Klatt2(int length, int modulation, int resume, frame_t *fr1, frame_t *fr2)
|
||||
{
|
||||
if(resume==0)
|
||||
if (resume == 0)
|
||||
SetSynth_Klatt(length, modulation, fr1, fr2, wvoice, 1);
|
||||
|
||||
return(Wavegen_Klatt(resume));
|
||||
return Wavegen_Klatt(resume);
|
||||
}
|
||||
|
||||
|
||||
@@ -1249,14 +1161,14 @@ int Wavegen_Klatt2(int length, int modulation, int resume, frame_t *fr1, frame_t
|
||||
void KlattInit()
|
||||
{
|
||||
|
||||
static short formant_hz[10] = {280,688,1064,2806,3260,3700,6500,7000,8000,280};
|
||||
static short bandwidth[10] = {89,160,70,160,200,200,500,500,500,89};
|
||||
static short parallel_amp[10] = { 0,59,59,59,59,59,59,0,0,0};
|
||||
static short parallel_bw[10] = {59,59,89,149,200,200,500,0,0,0};
|
||||
static short formant_hz[10] = { 280, 688, 1064, 2806, 3260, 3700, 6500, 7000, 8000, 280 };
|
||||
static short bandwidth[10] = { 89, 160, 70, 160, 200, 200, 500, 500, 500, 89 };
|
||||
static short parallel_amp[10] = { 0, 59, 59, 59, 59, 59, 59, 0, 0, 0 };
|
||||
static short parallel_bw[10] = { 59, 59, 89, 149, 200, 200, 500, 0, 0, 0 };
|
||||
|
||||
int ix;
|
||||
|
||||
sample_count=0;
|
||||
sample_count = 0;
|
||||
|
||||
kt_globals.synthesis_model = CASCADE_PARALLEL;
|
||||
kt_globals.samrate = 22050;
|
||||
@@ -1273,8 +1185,7 @@ void KlattInit()
|
||||
KlattReset(2);
|
||||
|
||||
// set default values for frame parameters
|
||||
for(ix=0; ix<=9; ix++)
|
||||
{
|
||||
for (ix = 0; ix <= 9; ix++) {
|
||||
kt_frame.Fhz[ix] = formant_hz[ix];
|
||||
kt_frame.Bhz[ix] = bandwidth[ix];
|
||||
kt_frame.Ap[ix] = parallel_amp[ix];
|
||||
@@ -1288,7 +1199,7 @@ void KlattInit()
|
||||
kt_frame.Kopen = 40; // 40
|
||||
kt_frame.Aturb = 0;
|
||||
kt_frame.TLTdb = 0;
|
||||
kt_frame.AF =50;
|
||||
kt_frame.AF = 50;
|
||||
kt_frame.Kskew = 0;
|
||||
kt_frame.AB = 0;
|
||||
kt_frame.AVpdb = 0;
|
||||
|
||||
@@ -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) {
|
||||
@@ -381,7 +381,7 @@ static int mbrola_is_idle(void)
|
||||
p = (char *)memchr(buffer, ')', sizeof(buffer));
|
||||
if (!p || (unsigned)(p - buffer) >= sizeof(buffer) - 2)
|
||||
return 0;
|
||||
return (p[1] == ' ' && p[2] == 'S');
|
||||
return p[1] == ' ' && p[2] == 'S';
|
||||
}
|
||||
|
||||
static ssize_t receive_from_mbrola(void *buffer, size_t bufsize)
|
||||
@@ -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) {
|
||||
|
||||
+676
-970
File diff suppressed because it is too large
Load Diff
@@ -160,9 +160,9 @@ typedef struct {
|
||||
|
||||
|
||||
|
||||
#define PH(c1,c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name
|
||||
#define PH3(c1,c2,c3) (c3<<16)+(c2<<8)+c1
|
||||
#define PhonemeCode2(c1,c2) PhonemeCode((c2<<8)+c1)
|
||||
#define PH(c1, c2) (c2<<8)+c1 // combine two characters into an integer for phoneme name
|
||||
#define PH3(c1, c2, c3) (c3<<16)+(c2<<8)+c1
|
||||
#define PhonemeCode2(c1, c2) PhonemeCode((c2<<8)+c1)
|
||||
int LookupPhonemeString(const char *string);
|
||||
int PhonemeCode(unsigned int mnem);
|
||||
|
||||
|
||||
+123
-224
@@ -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];
|
||||
|
||||
|
||||
+859
-1171
File diff suppressed because it is too large
Load Diff
+165
-284
@@ -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;
|
||||
}
|
||||
|
||||
+221
-308
File diff suppressed because it is too large
Load Diff
+105
-138
@@ -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);
|
||||
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
|
||||
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,16 +270,15 @@ 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);
|
||||
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);
|
||||
|
||||
+148
-204
@@ -54,8 +54,8 @@ typedef void (WINAPI *PROCVI)(int);
|
||||
typedef void (WINAPI *PROCVF)(float);
|
||||
typedef int (WINAPI *PROCIV)();
|
||||
typedef int (WINAPI *PROCIC)(char *);
|
||||
typedef int (WINAPI *PROCISI)(short *,int);
|
||||
typedef char* (WINAPI *PROCVCI)(char *,int);
|
||||
typedef int (WINAPI *PROCISI)(short *, int);
|
||||
typedef char * (WINAPI *PROCVCI)(char *, int);
|
||||
|
||||
PROCIC init_MBR;
|
||||
PROCIC write_MBR;
|
||||
@@ -76,31 +76,30 @@ HINSTANCE hinstDllMBR = NULL;
|
||||
|
||||
BOOL load_MBR()
|
||||
{
|
||||
if(hinstDllMBR != NULL)
|
||||
if (hinstDllMBR != NULL)
|
||||
return TRUE; // already loaded
|
||||
|
||||
if ((hinstDllMBR=LoadLibraryA("mbrola.dll")) == 0)
|
||||
if ((hinstDllMBR = LoadLibraryA("mbrola.dll")) == 0)
|
||||
return FALSE;
|
||||
init_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"init_MBR");
|
||||
write_MBR =(PROCIC) GetProcAddress(hinstDllMBR,"write_MBR");
|
||||
flush_MBR =(PROCIV) GetProcAddress(hinstDllMBR,"flush_MBR");
|
||||
read_MBR =(PROCISI) GetProcAddress(hinstDllMBR,"read_MBR");
|
||||
close_MBR =(PROCVV) GetProcAddress(hinstDllMBR,"close_MBR");
|
||||
reset_MBR =(PROCVV) GetProcAddress(hinstDllMBR,"reset_MBR");
|
||||
lastError_MBR =(PROCIV) GetProcAddress(hinstDllMBR,"lastError_MBR");
|
||||
lastErrorStr_MBR =(PROCVCI) GetProcAddress(hinstDllMBR,"lastErrorStr_MBR");
|
||||
setNoError_MBR =(PROCVI) GetProcAddress(hinstDllMBR,"setNoError_MBR");
|
||||
setVolumeRatio_MBR =(PROCVF) GetProcAddress(hinstDllMBR,"setVolumeRatio_MBR");
|
||||
init_MBR = (PROCIC)GetProcAddress(hinstDllMBR, "init_MBR");
|
||||
write_MBR = (PROCIC)GetProcAddress(hinstDllMBR, "write_MBR");
|
||||
flush_MBR = (PROCIV)GetProcAddress(hinstDllMBR, "flush_MBR");
|
||||
read_MBR = (PROCISI)GetProcAddress(hinstDllMBR, "read_MBR");
|
||||
close_MBR = (PROCVV)GetProcAddress(hinstDllMBR, "close_MBR");
|
||||
reset_MBR = (PROCVV)GetProcAddress(hinstDllMBR, "reset_MBR");
|
||||
lastError_MBR = (PROCIV)GetProcAddress(hinstDllMBR, "lastError_MBR");
|
||||
lastErrorStr_MBR = (PROCVCI)GetProcAddress(hinstDllMBR, "lastErrorStr_MBR");
|
||||
setNoError_MBR = (PROCVI)GetProcAddress(hinstDllMBR, "setNoError_MBR");
|
||||
setVolumeRatio_MBR = (PROCVF)GetProcAddress(hinstDllMBR, "setVolumeRatio_MBR");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void unload_MBR()
|
||||
{
|
||||
if (hinstDllMBR)
|
||||
{
|
||||
FreeLibrary (hinstDllMBR);
|
||||
hinstDllMBR=NULL;
|
||||
if (hinstDllMBR) {
|
||||
FreeLibrary(hinstDllMBR);
|
||||
hinstDllMBR = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,79 +124,72 @@ espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int
|
||||
mbrola_delay = 0;
|
||||
mbr_name_prefix = 0;
|
||||
|
||||
if(mbrola_voice == NULL)
|
||||
{
|
||||
if (mbrola_voice == NULL) {
|
||||
samplerate = samplerate_native;
|
||||
SetParameter(espeakVOICETYPE,0,0);
|
||||
return(EE_OK);
|
||||
SetParameter(espeakVOICETYPE, 0, 0);
|
||||
return EE_OK;
|
||||
}
|
||||
|
||||
sprintf(path,"%s/mbrola/%s",path_home,mbrola_voice);
|
||||
sprintf(path, "%s/mbrola/%s", path_home, mbrola_voice);
|
||||
#ifdef PLATFORM_POSIX
|
||||
// if not found, then also look in
|
||||
// usr/share/mbrola/xx, /usr/share/mbrola/xx/xx, /usr/share/mbrola/voices/xx
|
||||
if(GetFileLength(path) <= 0)
|
||||
{
|
||||
sprintf(path,"/usr/share/mbrola/%s",mbrola_voice);
|
||||
if (GetFileLength(path) <= 0) {
|
||||
sprintf(path, "/usr/share/mbrola/%s", mbrola_voice);
|
||||
|
||||
if(GetFileLength(path) <= 0)
|
||||
{
|
||||
sprintf(path,"/usr/share/mbrola/%s/%s",mbrola_voice,mbrola_voice);
|
||||
if (GetFileLength(path) <= 0) {
|
||||
sprintf(path, "/usr/share/mbrola/%s/%s", mbrola_voice, mbrola_voice);
|
||||
|
||||
if(GetFileLength(path) <= 0)
|
||||
{
|
||||
sprintf(path,"/usr/share/mbrola/voices/%s",mbrola_voice);
|
||||
if (GetFileLength(path) <= 0) {
|
||||
sprintf(path, "/usr/share/mbrola/voices/%s", mbrola_voice);
|
||||
}
|
||||
}
|
||||
}
|
||||
close_MBR();
|
||||
#endif
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
if(load_MBR() == FALSE) // load mbrola.dll
|
||||
{
|
||||
if (load_MBR() == FALSE) { // load mbrola.dll
|
||||
fprintf(stderr, "Can't load mbrola.dll\n");
|
||||
return(EE_INTERNAL_ERROR);
|
||||
return EE_INTERNAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(init_MBR(path) != 0) // initialise the required mbrola voice
|
||||
return(EE_NOT_FOUND);
|
||||
if (init_MBR(path) != 0) // initialise the required mbrola voice
|
||||
return EE_NOT_FOUND;
|
||||
|
||||
setNoError_MBR(1); // don't stop on phoneme errors
|
||||
|
||||
// read eSpeak's mbrola phoneme translation data, eg. en1_phtrans
|
||||
sprintf(path,"%s/mbrola_ph/%s",path_home,phtrans);
|
||||
sprintf(path, "%s/mbrola_ph/%s", path_home, phtrans);
|
||||
size = GetFileLength(path);
|
||||
if((f_in = fopen(path,"rb")) == NULL) {
|
||||
if ((f_in = fopen(path, "rb")) == NULL) {
|
||||
close_MBR();
|
||||
return(EE_NOT_FOUND);
|
||||
return EE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if((mbrola_tab = (MBROLA_TAB *)realloc(mbrola_tab,size)) == NULL)
|
||||
{
|
||||
if ((mbrola_tab = (MBROLA_TAB *)realloc(mbrola_tab, size)) == NULL) {
|
||||
fclose(f_in);
|
||||
close_MBR();
|
||||
return(EE_INTERNAL_ERROR);
|
||||
return EE_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
mbrola_control = Read4Bytes(f_in);
|
||||
pw = (int *)mbrola_tab;
|
||||
for(ix=4; ix<size; ix+=4)
|
||||
{
|
||||
for (ix = 4; ix < size; ix += 4) {
|
||||
*pw++ = Read4Bytes(f_in);
|
||||
}
|
||||
size = fread(mbrola_tab,1,size,f_in);
|
||||
size = fread(mbrola_tab, 1, size, f_in);
|
||||
fclose(f_in);
|
||||
|
||||
setVolumeRatio_MBR((float)(mbrola_control & 0xff) /16.0f);
|
||||
samplerate = *srate = getFreq_MBR();
|
||||
if(*srate == 22050)
|
||||
SetParameter(espeakVOICETYPE,0,0);
|
||||
if (*srate == 22050)
|
||||
SetParameter(espeakVOICETYPE, 0, 0);
|
||||
else
|
||||
SetParameter(espeakVOICETYPE,1,0);
|
||||
strcpy(mbrola_name,mbrola_voice);
|
||||
SetParameter(espeakVOICETYPE, 1, 0);
|
||||
strcpy(mbrola_name, mbrola_voice);
|
||||
mbrola_delay = 1000; // improve synchronization of events
|
||||
return(EE_OK);
|
||||
return EE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,60 +211,50 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev
|
||||
// bit 5 only in stressed syllable
|
||||
// bit 6 only at the end of a word
|
||||
|
||||
*name2=0;
|
||||
*split=0;
|
||||
*control=0;
|
||||
*name2 = 0;
|
||||
*split = 0;
|
||||
*control = 0;
|
||||
mnem = ph->mnemonic;
|
||||
|
||||
pr = mbrola_tab;
|
||||
while(pr->name != 0)
|
||||
{
|
||||
if(mnem == pr->name)
|
||||
{
|
||||
if(pr->next_phoneme == 0)
|
||||
while (pr->name != 0) {
|
||||
if (mnem == pr->name) {
|
||||
if (pr->next_phoneme == 0)
|
||||
found = 1;
|
||||
else
|
||||
if((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN))
|
||||
{
|
||||
else if ((pr->next_phoneme == ':') && (plist->synthflags & SFLAG_LENGTHEN)) {
|
||||
found = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pr->control & 2)
|
||||
} else {
|
||||
if (pr->control & 2)
|
||||
other_ph = ph_prev;
|
||||
else
|
||||
if((pr->control & 8) && ((plist+1)->newword))
|
||||
else if ((pr->control & 8) && ((plist+1)->newword))
|
||||
other_ph = phoneme_tab[phPAUSE]; // don't match the next phoneme over a word boundary
|
||||
else
|
||||
other_ph = ph_next;
|
||||
|
||||
if((pr->next_phoneme == other_ph->mnemonic) ||
|
||||
((pr->next_phoneme == 2) && (other_ph->type == phVOWEL)) ||
|
||||
((pr->next_phoneme == '_') && (other_ph->type == phPAUSE)))
|
||||
{
|
||||
if ((pr->next_phoneme == other_ph->mnemonic) ||
|
||||
((pr->next_phoneme == 2) && (other_ph->type == phVOWEL)) ||
|
||||
((pr->next_phoneme == '_') && (other_ph->type == phPAUSE))) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if((pr->control & 4) && (plist->newword == 0)) // only at start of word
|
||||
if ((pr->control & 4) && (plist->newword == 0)) // only at start of word
|
||||
found = 0;
|
||||
|
||||
if((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word
|
||||
if ((pr->control & 0x40) && (plist[1].newword == 0)) // only at the end of a word
|
||||
found = 0;
|
||||
|
||||
if((pr->control & 0x20) && (plist->stresslevel < plist->wordstress))
|
||||
if ((pr->control & 0x20) && (plist->stresslevel < plist->wordstress))
|
||||
found = 0; // only in stressed syllables
|
||||
|
||||
if(found)
|
||||
{
|
||||
if (found) {
|
||||
*name2 = pr->mbr_name2;
|
||||
*split = pr->percent;
|
||||
*control = pr->control;
|
||||
|
||||
if(pr->control & 0x10)
|
||||
{
|
||||
if (pr->control & 0x10) {
|
||||
mbr_name_prefix = pr->mbr_name;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
mnem = pr->mbr_name;
|
||||
break;
|
||||
@@ -282,12 +264,11 @@ static int GetMbrName(PHONEME_LIST *plist, PHONEME_TAB *ph, PHONEME_TAB *ph_prev
|
||||
pr++;
|
||||
}
|
||||
|
||||
if(mbr_name_prefix != 0)
|
||||
{
|
||||
if (mbr_name_prefix != 0) {
|
||||
mnem = (mnem << 8) | (mbr_name_prefix & 0xff);
|
||||
}
|
||||
mbr_name_prefix = 0;
|
||||
return(mnem);
|
||||
return mnem;
|
||||
}
|
||||
|
||||
|
||||
@@ -298,12 +279,12 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final)
|
||||
int ix;
|
||||
int pitch_base;
|
||||
int pitch_range;
|
||||
int p1,p2,p_end;
|
||||
int p1, p2, p_end;
|
||||
unsigned char *pitch_env;
|
||||
int max = -1;
|
||||
int min = 999;
|
||||
int y_max=0;
|
||||
int y_min=0;
|
||||
int y_max = 0;
|
||||
int y_min = 0;
|
||||
int env100 = 80; // apply the pitch change only over this proportion of the mbrola phoneme(s)
|
||||
int y2;
|
||||
int y[4];
|
||||
@@ -319,19 +300,16 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final)
|
||||
|
||||
|
||||
env_split = (split * 128)/100;
|
||||
if(env_split < 0)
|
||||
if (env_split < 0)
|
||||
env_split = 0-env_split;
|
||||
|
||||
// find max and min in the pitch envelope
|
||||
for(x=0; x<128; x++)
|
||||
{
|
||||
if(pitch_env[x] > max)
|
||||
{
|
||||
for (x = 0; x < 128; x++) {
|
||||
if (pitch_env[x] > max) {
|
||||
max = pitch_env[x];
|
||||
y_max = x;
|
||||
}
|
||||
if(pitch_env[x] < min)
|
||||
{
|
||||
if (pitch_env[x] < min) {
|
||||
min = pitch_env[x];
|
||||
y_min = x;
|
||||
}
|
||||
@@ -339,12 +317,10 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final)
|
||||
// set an additional pitch point half way through the phoneme.
|
||||
// but look for a maximum or a minimum and use that instead
|
||||
y[2] = 64;
|
||||
if((y_max > 0) && (y_max < 127))
|
||||
{
|
||||
if ((y_max > 0) && (y_max < 127)) {
|
||||
y[2] = y_max;
|
||||
}
|
||||
if((y_min > 0) && (y_min < 127))
|
||||
{
|
||||
if ((y_min > 0) && (y_min < 127)) {
|
||||
y[2] = y_min;
|
||||
}
|
||||
y[1] = y[2] / 2;
|
||||
@@ -355,56 +331,44 @@ static char *WritePitch(int env, int pitch1, int pitch2, int split, int final)
|
||||
p_end = ((pitch_env[127]*pitch_range)>>8) + pitch_base;
|
||||
|
||||
|
||||
if(split >= 0)
|
||||
{
|
||||
sprintf(buf," 0 %d",p1/4096);
|
||||
strcat(output,buf);
|
||||
if (split >= 0) {
|
||||
sprintf(buf, " 0 %d", p1/4096);
|
||||
strcat(output, buf);
|
||||
}
|
||||
|
||||
// don't use intermediate pitch points for linear rise and fall
|
||||
if(env > 1)
|
||||
{
|
||||
for(ix=1; ix<4; ix++)
|
||||
{
|
||||
if (env > 1) {
|
||||
for (ix = 1; ix < 4; ix++) {
|
||||
p2 = ((pitch_env[y[ix]]*pitch_range)>>8) + pitch_base;
|
||||
|
||||
if(split > 0)
|
||||
{
|
||||
if (split > 0) {
|
||||
y2 = (y[ix] * env100)/env_split;
|
||||
}
|
||||
else
|
||||
if(split < 0)
|
||||
{
|
||||
} else if (split < 0) {
|
||||
y2 = ((y[ix]-env_split) * env100)/env_split;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
y2 = (y[ix] * env100)/128;
|
||||
}
|
||||
if((y2 > 0) && (y2 <= env100))
|
||||
{
|
||||
sprintf(buf," %d %d",y2,p2/4096);
|
||||
strcat(output,buf);
|
||||
if ((y2 > 0) && (y2 <= env100)) {
|
||||
sprintf(buf, " %d %d", y2, p2/4096);
|
||||
strcat(output, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p_end = p_end/4096;
|
||||
if(split <= 0)
|
||||
{
|
||||
sprintf(buf," %d %d",env100,p_end);
|
||||
strcat(output,buf);
|
||||
if (split <= 0) {
|
||||
sprintf(buf, " %d %d", env100, p_end);
|
||||
strcat(output, buf);
|
||||
}
|
||||
if(env100 < 100)
|
||||
{
|
||||
sprintf(buf," %d %d",100,p_end);
|
||||
strcat(output,buf);
|
||||
if (env100 < 100) {
|
||||
sprintf(buf, " %d %d", 100, p_end);
|
||||
strcat(output, buf);
|
||||
}
|
||||
strcat(output,"\n");
|
||||
strcat(output, "\n");
|
||||
|
||||
if(final)
|
||||
sprintf(output,"\t100 %d\n",p_end);
|
||||
return(output);
|
||||
if (final)
|
||||
sprintf(output, "\t100 %d\n", p_end);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@@ -441,8 +405,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
|
||||
word_count = 0;
|
||||
}
|
||||
|
||||
while (phix < n_phonemes)
|
||||
{
|
||||
while (phix < n_phonemes) {
|
||||
if (WcmdqFree() < MIN_WCMDQ)
|
||||
return 1;
|
||||
|
||||
@@ -454,47 +417,42 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
|
||||
ph_prev = plist[phix-1].ph;
|
||||
ph_next = plist[phix+1].ph;
|
||||
|
||||
if(p->synthflags & SFLAG_EMBEDDED)
|
||||
{
|
||||
if (p->synthflags & SFLAG_EMBEDDED) {
|
||||
DoEmbedded(&embedded_ix, p->sourceix);
|
||||
}
|
||||
|
||||
if(p->newword & 4)
|
||||
if (p->newword & 4)
|
||||
DoMarker(espeakEVENT_SENTENCE, (p->sourceix & 0x7ff) + clause_start_char, 0, count_sentences);
|
||||
if(p->newword & 1)
|
||||
if (p->newword & 1)
|
||||
DoMarker(espeakEVENT_WORD, (p->sourceix & 0x7ff) + clause_start_char, p->sourceix >> 11, clause_start_word + word_count++);
|
||||
|
||||
name = GetMbrName(p,ph,ph_prev,ph_next,&name2,&len_percent,&control);
|
||||
if(control & 1)
|
||||
name = GetMbrName(p, ph, ph_prev, ph_next, &name2, &len_percent, &control);
|
||||
if (control & 1)
|
||||
phix++;
|
||||
|
||||
if(name == 0) {
|
||||
if (name == 0) {
|
||||
phix++;
|
||||
continue; // ignore this phoneme
|
||||
}
|
||||
|
||||
if((ph->type == phPAUSE) && (name == ph->mnemonic))
|
||||
{
|
||||
if ((ph->type == phPAUSE) && (name == ph->mnemonic)) {
|
||||
// a pause phoneme, which has not been changed by the translation
|
||||
name = '_';
|
||||
len = (p->length * speed.pause_factor)/256;
|
||||
if(len == 0)
|
||||
if (len == 0)
|
||||
len = 1;
|
||||
}
|
||||
else
|
||||
} else
|
||||
len = (80 * speed.wav_factor)/256;
|
||||
|
||||
if(ph->code != phonEND_WORD)
|
||||
{
|
||||
if (ph->code != phonEND_WORD) {
|
||||
char phoneme_name[16];
|
||||
WritePhMnemonic(phoneme_name, p->ph, p, option_phoneme_events & espeakINITIALIZE_PHONEME_IPA, NULL);
|
||||
DoPhonemeMarker(espeakEVENT_PHONEME, (p->sourceix & 0x7ff) + clause_start_char, 0, phoneme_name);
|
||||
}
|
||||
|
||||
ptr += sprintf(ptr,"%s\t",WordToString(name));
|
||||
ptr += sprintf(ptr, "%s\t", WordToString(name));
|
||||
|
||||
if(name2 == '_')
|
||||
{
|
||||
if (name2 == '_') {
|
||||
// add a pause after this phoneme
|
||||
pause = len_percent;
|
||||
name2 = 0;
|
||||
@@ -503,48 +461,45 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
|
||||
done = 0;
|
||||
final_pitch = "";
|
||||
|
||||
switch(ph->type)
|
||||
switch (ph->type)
|
||||
{
|
||||
case phVOWEL:
|
||||
len = ph->std_length;
|
||||
if(p->synthflags & SFLAG_LENGTHEN)
|
||||
if (p->synthflags & SFLAG_LENGTHEN)
|
||||
len += phoneme_tab[phonLENGTHEN]->std_length; // phoneme was followed by an extra : symbol
|
||||
|
||||
if(ph_next->type == phPAUSE)
|
||||
if (ph_next->type == phPAUSE)
|
||||
len += 50; // lengthen vowels before a pause
|
||||
len = (len * p->length)/256;
|
||||
|
||||
if(name2 == 0)
|
||||
{
|
||||
char *pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,0);
|
||||
ptr += sprintf(ptr,"%d\t%s", len, pitch);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name2 == 0) {
|
||||
char *pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 0);
|
||||
ptr += sprintf(ptr, "%d\t%s", len, pitch);
|
||||
} else {
|
||||
char *pitch;
|
||||
|
||||
pitch = WritePitch(p->env,p->pitch1,p->pitch2,len_percent,0);
|
||||
pitch = WritePitch(p->env, p->pitch1, p->pitch2, len_percent, 0);
|
||||
len1 = (len * len_percent)/100;
|
||||
ptr += sprintf(ptr,"%d\t%s", len1, pitch);
|
||||
ptr += sprintf(ptr, "%d\t%s", len1, pitch);
|
||||
|
||||
pitch = WritePitch(p->env,p->pitch1,p->pitch2,-len_percent,0);
|
||||
ptr += sprintf(ptr,"%s\t%d\t%s", WordToString(name2), len-len1, pitch);
|
||||
pitch = WritePitch(p->env, p->pitch1, p->pitch2, -len_percent, 0);
|
||||
ptr += sprintf(ptr, "%s\t%d\t%s", WordToString(name2), len-len1, pitch);
|
||||
}
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
case phSTOP:
|
||||
released = 0;
|
||||
if(next->type==phVOWEL) released = 1;
|
||||
if(next->type==phLIQUID && !next->newword) released = 1;
|
||||
if (next->type == phVOWEL) released = 1;
|
||||
if (next->type == phLIQUID && !next->newword) released = 1;
|
||||
|
||||
if(released == 0)
|
||||
if (released == 0)
|
||||
p->synthflags |= SFLAG_NEXT_PAUSE;
|
||||
InterpretPhoneme(NULL, 0, p, &phdata, NULL);
|
||||
len = DoSample3(&phdata, 0, -1);
|
||||
|
||||
len = (len * 1000)/samplerate; // convert to mS
|
||||
len += PauseLength(p->prepause,1);
|
||||
len += PauseLength(p->prepause, 1);
|
||||
break;
|
||||
|
||||
case phVSTOP:
|
||||
@@ -554,7 +509,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
|
||||
case phFRICATIVE:
|
||||
len = 0;
|
||||
InterpretPhoneme(NULL, 0, p, &phdata, NULL);
|
||||
if(p->synthflags & SFLAG_LENGTHEN)
|
||||
if (p->synthflags & SFLAG_LENGTHEN)
|
||||
len = DoSample3(&phdata, p->length, -1); // play it twice for [s:] etc.
|
||||
len += DoSample3(&phdata, p->length, -1);
|
||||
|
||||
@@ -562,52 +517,44 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
|
||||
break;
|
||||
|
||||
case phNASAL:
|
||||
if(next->type != phVOWEL)
|
||||
{
|
||||
if (next->type != phVOWEL) {
|
||||
memset(&fmtp, 0, sizeof(fmtp));
|
||||
InterpretPhoneme(NULL, 0, p, &phdata, NULL);
|
||||
fmtp.fmt_addr = phdata.sound_addr[pd_FMT];
|
||||
len = DoSpect2(p->ph, 0, &fmtp, p, -1);
|
||||
len = (len * 1000)/samplerate;
|
||||
if(next->type == phPAUSE)
|
||||
if (next->type == phPAUSE)
|
||||
len += 50;
|
||||
final_pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,1);
|
||||
final_pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case phLIQUID:
|
||||
if(next->type == phPAUSE)
|
||||
{
|
||||
if (next->type == phPAUSE) {
|
||||
len += 50;
|
||||
final_pitch = WritePitch(p->env,p->pitch1,p->pitch2,0,1);
|
||||
final_pitch = WritePitch(p->env, p->pitch1, p->pitch2, 0, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(!done)
|
||||
{
|
||||
if(name2 != 0)
|
||||
{
|
||||
if (!done) {
|
||||
if (name2 != 0) {
|
||||
len1 = (len * len_percent)/100;
|
||||
ptr += sprintf(ptr,"%d\n%s\t",len1,WordToString(name2));
|
||||
ptr += sprintf(ptr, "%d\n%s\t", len1, WordToString(name2));
|
||||
len -= len1;
|
||||
}
|
||||
ptr += sprintf(ptr,"%d%s\n",len,final_pitch);
|
||||
ptr += sprintf(ptr, "%d%s\n", len, final_pitch);
|
||||
}
|
||||
|
||||
if(pause)
|
||||
{
|
||||
len += PauseLength(pause,0);
|
||||
ptr += sprintf(ptr,"_ \t%d\n",PauseLength(pause,0));
|
||||
if (pause) {
|
||||
len += PauseLength(pause, 0);
|
||||
ptr += sprintf(ptr, "_ \t%d\n", PauseLength(pause, 0));
|
||||
pause = 0;
|
||||
}
|
||||
|
||||
if(f_mbrola)
|
||||
{
|
||||
fwrite(mbr_buf,1,(ptr-mbr_buf),f_mbrola); // write .pho to a file
|
||||
}
|
||||
else
|
||||
{
|
||||
if (f_mbrola) {
|
||||
fwrite(mbr_buf, 1, (ptr-mbr_buf), f_mbrola); // write .pho to a file
|
||||
} else {
|
||||
int res = write_MBR(mbr_buf);
|
||||
if (res < 0)
|
||||
return 0; /* don't get stuck on error */
|
||||
@@ -621,8 +568,7 @@ int MbrolaTranslate(PHONEME_LIST *plist, int n_phonemes, int resume, FILE *f_mbr
|
||||
phix++;
|
||||
}
|
||||
|
||||
if(!f_mbrola)
|
||||
{
|
||||
if (!f_mbrola) {
|
||||
flush_MBR();
|
||||
|
||||
// flush the mbrola output buffer
|
||||
@@ -639,11 +585,10 @@ int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
{
|
||||
FILE *f_mbrola = NULL;
|
||||
|
||||
if(*n_ph == 0)
|
||||
return(0);
|
||||
if (*n_ph == 0)
|
||||
return 0;
|
||||
|
||||
if(option_phonemes & espeakPHONEMES_MBROLA)
|
||||
{
|
||||
if (option_phonemes & espeakPHONEMES_MBROLA) {
|
||||
// send mbrola data to a file, not to the mbrola library
|
||||
f_mbrola = f_trans;
|
||||
}
|
||||
@@ -675,14 +620,13 @@ int MbrolaFill(int length, int resume, int amplitude)
|
||||
if (result <= 0)
|
||||
return 0;
|
||||
|
||||
for(ix=0; ix < result; ix++)
|
||||
{
|
||||
for (ix = 0; ix < result; ix++) {
|
||||
value16 = out_ptr[0] + (out_ptr[1] << 8);
|
||||
value = value16 * amplitude;
|
||||
value = value / 40; // adjust this constant to give a suitable amplitude for mbrola voices
|
||||
if(value > 0x7fff)
|
||||
if (value > 0x7fff)
|
||||
value = 0x7fff;
|
||||
if(value < -0x8000)
|
||||
if (value < -0x8000)
|
||||
value = 0x8000;
|
||||
out_ptr[0] = value;
|
||||
out_ptr[1] = value >> 8;
|
||||
@@ -706,17 +650,17 @@ void MbrolaReset(void)
|
||||
|
||||
espeak_ERROR LoadMbrolaTable(const char *mbrola_voice, const char *phtrans, int *srate)
|
||||
{
|
||||
return(EE_INTERNAL_ERROR);
|
||||
return EE_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
int MbrolaGenerate(PHONEME_LIST *phoneme_list, int *n_ph, int resume)
|
||||
{
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MbrolaFill(int length, int resume, int amplitude)
|
||||
{
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MbrolaReset(void)
|
||||
|
||||
+270
-403
File diff suppressed because it is too large
Load Diff
+399
-625
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
+464
-514
File diff suppressed because it is too large
Load Diff
+775
-1221
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
+463
-623
File diff suppressed because it is too large
Load Diff
+236
-325
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
+336
-469
File diff suppressed because it is too large
Load Diff
+199
-267
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user