Fixes: #1549 A bunch of `#ifdef` stuff cleanups, including: - Check header presence with `__has_include` instead of autoconf's `HAVE_XXX` macro - Standartization of defines: consistent naming, define to 1 and check with `#if` instead of `#ifdef` - Compile MBROLA-related code only if configured `--with-mbrola` - Compile tests with flags that match configuration (including async, klatt, speechplayer, mbrola) - Fix for API test when compiled with asyncmaster
all-local: \ | all-local: \ | ||||
espeak-ng-data/phontab \ | espeak-ng-data/phontab \ | ||||
dictionaries \ | dictionaries | ||||
mbrola | |||||
uninstall-hook: | uninstall-hook: | ||||
rm -rf $(DESTDIR)$(DATADIR) | rm -rf $(DESTDIR)$(DATADIR) | ||||
src/libespeak-ng/common.c \ | src/libespeak-ng/common.c \ | ||||
src/libespeak-ng/compiledata.c \ | src/libespeak-ng/compiledata.c \ | ||||
src/libespeak-ng/compiledict.c \ | src/libespeak-ng/compiledict.c \ | ||||
src/libespeak-ng/compilembrola.c \ | |||||
src/libespeak-ng/dictionary.c \ | src/libespeak-ng/dictionary.c \ | ||||
src/libespeak-ng/encoding.c \ | src/libespeak-ng/encoding.c \ | ||||
src/libespeak-ng/error.c \ | src/libespeak-ng/error.c \ | ||||
src/libespeak-ng/ssml.c \ | src/libespeak-ng/ssml.c \ | ||||
src/libespeak-ng/synthdata.c \ | src/libespeak-ng/synthdata.c \ | ||||
src/libespeak-ng/synthesize.c \ | src/libespeak-ng/synthesize.c \ | ||||
src/libespeak-ng/synth_mbrola.c \ | |||||
src/libespeak-ng/translate.c \ | src/libespeak-ng/translate.c \ | ||||
src/libespeak-ng/translateword.c \ | src/libespeak-ng/translateword.c \ | ||||
src/libespeak-ng/tr_languages.c \ | src/libespeak-ng/tr_languages.c \ | ||||
src/ucd-tools/src/include/ucd/ucd.h | src/ucd-tools/src/include/ucd/ucd.h | ||||
if OPT_KLATT | if OPT_KLATT | ||||
src_libespeak_ng_la_CFLAGS += -DINCLUDE_KLATT | AM_CFLAGS += -DUSE_KLATT=1 | ||||
src_libespeak_ng_la_SOURCES += src/libespeak-ng/klatt.c | src_libespeak_ng_la_SOURCES += src/libespeak-ng/klatt.c | ||||
endif | endif | ||||
if OPT_SPEECHPLAYER | if OPT_SPEECHPLAYER | ||||
src_libespeak_ng_la_CFLAGS += -DINCLUDE_SPEECHPLAYER | AM_CFLAGS += -DUSE_SPEECHPLAYER=1 | ||||
src_libespeak_ng_la_SOURCES += src/libespeak-ng/sPlayer.c | src_libespeak_ng_la_SOURCES += src/libespeak-ng/sPlayer.c | ||||
src_libespeak_ng_la_SOURCES += src/speechPlayer/src/frame.cpp | src_libespeak_ng_la_SOURCES += src/speechPlayer/src/frame.cpp | ||||
src_libespeak_ng_la_SOURCES += src/speechPlayer/src/speechPlayer.cpp | src_libespeak_ng_la_SOURCES += src/speechPlayer/src/speechPlayer.cpp | ||||
endif | endif | ||||
if OPT_MBROLA | if OPT_MBROLA | ||||
src_libespeak_ng_la_CFLAGS += -DINCLUDE_MBROLA | AM_CFLAGS += -DUSE_MBROLA=1 | ||||
src_libespeak_ng_la_SOURCES += src/libespeak-ng/mbrowrap.c | src_libespeak_ng_la_SOURCES += \ | ||||
src/libespeak-ng/mbrowrap.c \ | |||||
src/libespeak-ng/synth_mbrola.c \ | |||||
src/libespeak-ng/compilembrola.c | |||||
endif | endif | ||||
if OPT_ASYNC | if OPT_ASYNC | ||||
src_libespeak_ng_la_CFLAGS += -DUSE_ASYNC | AM_CFLAGS += -DUSE_ASYNC=1 | ||||
src_libespeak_ng_la_SOURCES += \ | src_libespeak_ng_la_SOURCES += \ | ||||
src/libespeak-ng/espeak_command.c \ | src/libespeak-ng/espeak_command.c \ | ||||
src/libespeak-ng/event.c \ | src/libespeak-ng/event.c \ | ||||
${PCAUDIOLIB_CFLAGS} ${AM_CFLAGS} | ${PCAUDIOLIB_CFLAGS} ${AM_CFLAGS} | ||||
src_libespeak_ng_test_la_SOURCES = $(src_libespeak_ng_la_SOURCES) | src_libespeak_ng_test_la_SOURCES = $(src_libespeak_ng_la_SOURCES) | ||||
if OPT_KLATT | |||||
src_libespeak_ng_test_la_CFLAGS += -DINCLUDE_KLATT | |||||
endif | |||||
if OPT_SPEECHPLAYER | |||||
src_libespeak_ng_test_la_CFLAGS += -DINCLUDE_SPEECHPLAYER | |||||
endif | |||||
check_PROGRAMS += tests/encoding.test | check_PROGRAMS += tests/encoding.test | ||||
tests_encoding_test_LDADD = src/libespeak-ng.la | tests_encoding_test_LDADD = src/libespeak-ng.la | ||||
##### mbrola: | ##### mbrola: | ||||
if OPT_MBROLA | |||||
PHSOURCE_MBROLA = \ | PHSOURCE_MBROLA = \ | ||||
$(wildcard phsource/mbrola/*) | $(wildcard phsource/mbrola/*) | ||||
ESPEAK_DATA_PATH=$(CURDIR) src/espeak-ng --compile-mbrola=phsource/mbrola/$* | ESPEAK_DATA_PATH=$(CURDIR) src/espeak-ng --compile-mbrola=phsource/mbrola/$* | ||||
EXTRA_DIST += $(PHSOURCE_MBROLA) | EXTRA_DIST += $(PHSOURCE_MBROLA) | ||||
all-local: mbrola | |||||
endif |
"\t Compile pronunciation rules and dictionary from the current\n" | "\t Compile pronunciation rules and dictionary from the current\n" | ||||
"\t directory, including line numbers for use with -X.\n" | "\t directory, including line numbers for use with -X.\n" | ||||
"\t <voice name> specifies the language\n" | "\t <voice name> specifies the language\n" | ||||
#if USE_MBROLA | |||||
"--compile-mbrola=<voice name>\n" | "--compile-mbrola=<voice name>\n" | ||||
"\t Compile an MBROLA voice\n" | "\t Compile an MBROLA voice\n" | ||||
#endif | |||||
"--compile-intonations\n" | "--compile-intonations\n" | ||||
"\t Compile the intonation data\n" | "\t Compile the intonation data\n" | ||||
"--compile-phonemes=<phsource-dir>\n" | "--compile-phonemes=<phsource-dir>\n" | ||||
f_wavfile = NULL; | f_wavfile = NULL; | ||||
if (path[0] != 0) { | if (path[0] != 0) { | ||||
if (strcmp(path, "stdout") == 0) { | if (strcmp(path, "stdout") == 0) { | ||||
#ifdef PLATFORM_WINDOWS | #if PLATFORM_WINDOWS | ||||
// prevent Windows adding 0x0d before 0x0a bytes | // prevent Windows adding 0x0d before 0x0a bytes | ||||
_setmode(_fileno(stdout), _O_BINARY); | _setmode(_fileno(stdout), _O_BINARY); | ||||
#endif | #endif | ||||
{ "version", no_argument, 0, 0x10b }, | { "version", no_argument, 0, 0x10b }, | ||||
{ "sep", optional_argument, 0, 0x10c }, | { "sep", optional_argument, 0, 0x10c }, | ||||
{ "tie", optional_argument, 0, 0x10d }, | { "tie", optional_argument, 0, 0x10d }, | ||||
#if USE_MBROLA | |||||
{ "compile-mbrola", optional_argument, 0, 0x10e }, | { "compile-mbrola", optional_argument, 0, 0x10e }, | ||||
#endif | |||||
{ "compile-intonations", no_argument, 0, 0x10f }, | { "compile-intonations", no_argument, 0, 0x10f }, | ||||
{ "compile-phonemes", optional_argument, 0, 0x110 }, | { "compile-phonemes", optional_argument, 0, 0x110 }, | ||||
{ "load", no_argument, 0, 0x111 }, | { "load", no_argument, 0, 0x111 }, | ||||
if (phonemes_separator == 'z') | if (phonemes_separator == 'z') | ||||
phonemes_separator = 0x200d; // ZWJ | phonemes_separator = 0x200d; // ZWJ | ||||
break; | break; | ||||
#if USE_MBROLA | |||||
case 0x10e: // --compile-mbrola | case 0x10e: // --compile-mbrola | ||||
{ | { | ||||
espeak_ng_InitializePath(data_path); | espeak_ng_InitializePath(data_path); | ||||
} | } | ||||
return EXIT_SUCCESS; | return EXIT_SUCCESS; | ||||
} | } | ||||
#endif | |||||
case 0x10f: // --compile-intonations | case 0x10f: // --compile-intonations | ||||
{ | { | ||||
espeak_ng_InitializePath(data_path); | espeak_ng_InitializePath(data_path); |
#define ENDIAN_H_COMPAT_SHIM | #define ENDIAN_H_COMPAT_SHIM | ||||
#pragma once | #pragma once | ||||
#if defined(HAVE_ENDIAN_H) | #if __has_include_next(<endian.h>) | ||||
# pragma GCC system_header // Silence "warning: #include_next is a GCC extension" | # pragma GCC system_header // Silence "warning: #include_next is a GCC extension" | ||||
# include_next <endian.h> | # include_next <endian.h> | ||||
#elif defined(HAVE_SYS_ENDIAN_H) | #elif __has_include(<sys/endian.h>) | ||||
# include <sys/endian.h> | # include <sys/endian.h> | ||||
# if !defined(be16toh) | # if !defined(be16toh) | ||||
# define be16toh(x) betoh16(x) | # define be16toh(x) betoh16(x) |
#ifndef GETOPT_H_COMPAT_SHIM | #ifndef GETOPT_H_COMPAT_SHIM | ||||
#define GETOPT_H_COMPAT_SHIM | #define GETOPT_H_COMPAT_SHIM | ||||
#if defined(HAVE_GETOPT_H) | #if __has_include_next(<getopt.h>) | ||||
#pragma GCC system_header // Silence "warning: #include_next is a GCC extension" | #pragma GCC system_header // Silence "warning: #include_next is a GCC extension" | ||||
#include_next <getopt.h> | #include_next <getopt.h> | ||||
#else | #else |
#pragma GCC system_header // Silence "warning: #include_next is a GCC extension" | #pragma GCC system_header // Silence "warning: #include_next is a GCC extension" | ||||
#if defined(HAVE_STDINT_H) || !defined(HAVE_INTTYPES_H) | #if __has_include(<stdint.h>) || !__has_include(<inttypes.h>) | ||||
#include_next <stdint.h> | #include_next <stdint.h> | ||||
#else | #else | ||||
#include_next <inttypes.h> | #include_next <inttypes.h> |
#ifndef UNISTD_H_COMPAT_SHIM | #ifndef UNISTD_H_COMPAT_SHIM | ||||
#define UNISTD_H_COMPAT_SHIM | #define UNISTD_H_COMPAT_SHIM | ||||
#if defined(HAVE_UNISTD_H) | #if __has_include_next(<unistd.h>) | ||||
#pragma GCC system_header // Silence "warning: #include_next is a GCC extension" | #pragma GCC system_header // Silence "warning: #include_next is a GCC extension" | ||||
#include_next <unistd.h> | #include_next <unistd.h> | ||||
#endif | #endif |
#include "espeak_command.h" | #include "espeak_command.h" | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
static unsigned int my_current_text_id = 0; | static unsigned int my_current_text_id = 0; | ||||
static bool my_terminate_is_required = 0; | static bool my_terminate_is_required = 0; | ||||
// my_thread: polls the audio duration and compares it to the duration of the first event. | // my_thread: polls the audio duration and compares it to the duration of the first event. | ||||
static pthread_t my_thread; | static pthread_t my_thread; | ||||
static bool thread_inited; | static bool thread_inited = false; | ||||
static t_espeak_callback *my_callback = NULL; | static t_espeak_callback *my_callback = NULL; | ||||
static bool my_event_is_running = false; | static bool my_event_is_running = false; |
#include "fifo.h" | #include "fifo.h" | ||||
#include "event.h" | #include "event.h" | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
// my_mutex: protects my_thread_is_talking, | // my_mutex: protects my_thread_is_talking, | ||||
// my_stop_is_required, and the command fifo | // my_stop_is_required, and the command fifo | ||||
static t_espeak_command *pop(void); | static t_espeak_command *pop(void); | ||||
static void init(int process_parameters); | static void init(int process_parameters); | ||||
static int node_counter = 0; | static int node_counter = 0; | ||||
static bool thread_inited = false; | |||||
enum { | enum { | ||||
MAX_NODE_COUNTER = 400, | MAX_NODE_COUNTER = 400, | ||||
(void *)NULL)) { | (void *)NULL)) { | ||||
assert(0); | assert(0); | ||||
} | } | ||||
thread_inited = true; | |||||
pthread_attr_destroy(&a_attrib); | pthread_attr_destroy(&a_attrib); | ||||
espeak_ng_STATUS fifo_add_commands(t_espeak_command *command1, t_espeak_command *command2) | espeak_ng_STATUS fifo_add_commands(t_espeak_command *command1, t_espeak_command *command2) | ||||
{ | { | ||||
espeak_ng_STATUS status; | espeak_ng_STATUS status; | ||||
if (!thread_inited) { | |||||
return ENS_NOT_INITIALIZED; | |||||
} | |||||
if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | ||||
return status; | return status; | ||||
espeak_ng_STATUS fifo_stop() | espeak_ng_STATUS fifo_stop() | ||||
{ | { | ||||
if (!thread_inited) return ENS_OK; | |||||
espeak_ng_STATUS status; | espeak_ng_STATUS status; | ||||
if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) | ||||
return status; | return status; | ||||
int fifo_is_busy() | int fifo_is_busy() | ||||
{ | { | ||||
return my_command_is_running; | if (!thread_inited) return false; | ||||
pthread_mutex_lock(&my_mutex); | |||||
bool running = my_command_is_running; | |||||
pthread_mutex_unlock(&my_mutex); | |||||
return running; | |||||
} | } | ||||
static int sleep_until_start_request_or_inactivity() | static int sleep_until_start_request_or_inactivity() | ||||
void fifo_terminate() | void fifo_terminate() | ||||
{ | { | ||||
if (!thread_inited) return; | |||||
pthread_mutex_lock(&my_mutex); | pthread_mutex_lock(&my_mutex); | ||||
my_terminate_is_required = true; | my_terminate_is_required = true; | ||||
pthread_mutex_unlock(&my_mutex); | pthread_mutex_unlock(&my_mutex); | ||||
pthread_cond_signal(&my_cond_start_is_required); | pthread_cond_signal(&my_cond_start_is_required); | ||||
pthread_join(my_thread, NULL); | pthread_join(my_thread, NULL); | ||||
my_terminate_is_required = false; | my_terminate_is_required = false; | ||||
thread_inited = false; | |||||
pthread_mutex_destroy(&my_mutex); | pthread_mutex_destroy(&my_mutex); | ||||
pthread_cond_destroy(&my_cond_start_is_required); | pthread_cond_destroy(&my_cond_start_is_required); |
#include "common.h" // for espeak_rand | #include "common.h" // for espeak_rand | ||||
#include "synthesize.h" // for frame_t, WGEN_DATA, STEPSIZE, N_KLATTP, echo... | #include "synthesize.h" // for frame_t, WGEN_DATA, STEPSIZE, N_KLATTP, echo... | ||||
#include "voice.h" // for voice_t, N_PEAKS | #include "voice.h" // for voice_t, N_PEAKS | ||||
#ifdef INCLUDE_SPEECHPLAYER | #if USE_SPEECHPLAYER | ||||
#include "sPlayer.h" | #include "sPlayer.h" | ||||
#endif | #endif | ||||
{ | { | ||||
int r_ix; | int r_ix; | ||||
#ifdef INCLUDE_SPEECHPLAYER | #if USE_SPEECHPLAYER | ||||
KlattResetSP(); | KlattResetSP(); | ||||
#endif | #endif | ||||
void KlattFini(void) | void KlattFini(void) | ||||
{ | { | ||||
#ifdef INCLUDE_SPEECHPLAYER | #if USE_SPEECHPLAYER | ||||
KlattFiniSP(); | KlattFiniSP(); | ||||
#endif | #endif | ||||
} | } | ||||
int Wavegen_Klatt(int length, int resume, frame_t *fr1, frame_t *fr2, WGEN_DATA *wdata, voice_t *wvoice) | int Wavegen_Klatt(int length, int resume, frame_t *fr1, frame_t *fr2, WGEN_DATA *wdata, voice_t *wvoice) | ||||
{ | { | ||||
#ifdef INCLUDE_SPEECHPLAYER | #if USE_SPEECHPLAYER | ||||
if(wvoice->klattv[0] == 6) | if(wvoice->klattv[0] == 6) | ||||
return Wavegen_KlattSP(wdata, wvoice, length, resume, fr1, fr2); | return Wavegen_KlattSP(wdata, wvoice, length, resume, fr1, fr2); | ||||
#endif | #endif | ||||
int ix; | int ix; | ||||
#ifdef INCLUDE_SPEECHPLAYER | #if USE_SPEECHPLAYER | ||||
KlattInitSP(); | KlattInitSP(); | ||||
#endif | #endif | ||||
#include "readclause.h" | #include "readclause.h" | ||||
#include "common.h" // for GetFileLength, strncpy0 | #include "common.h" // for GetFileLength, strncpy0 | ||||
#include "config.h" // for HAVE_MKSTEMP | |||||
#include "dictionary.h" // for LookupDictList, DecodePhonemes, Set... | #include "dictionary.h" // for LookupDictList, DecodePhonemes, Set... | ||||
#include "error.h" // for create_file_error_context | #include "error.h" // for create_file_error_context | ||||
#include "phoneme.h" // for phonSWITCH | #include "phoneme.h" // for phonSWITCH |
speed.min_pause = 5; | speed.min_pause = 5; | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
int wpm_value = wpm; | int wpm_value = wpm; | ||||
if (voice->speed_percent > 0) | if (voice->speed_percent > 0) |
fclose(f); | fclose(f); | ||||
f = NULL; | f = NULL; | ||||
#ifdef HAVE_MKSTEMP | #if HAVE_MKSTEMP | ||||
strcpy(fname_temp, "/tmp/espeakXXXXXX"); | strcpy(fname_temp, "/tmp/espeakXXXXXX"); | ||||
int fd_temp; | int fd_temp; | ||||
if ((fd_temp = mkstemp(fname_temp)) >= 0) | if ((fd_temp = mkstemp(fname_temp)) >= 0) |
#include <unistd.h> | #include <unistd.h> | ||||
#include <wchar.h> | #include <wchar.h> | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
#include <pcaudiolib/audio.h> | #include <pcaudiolib/audio.h> | ||||
#endif | #endif | ||||
static int event_list_ix = 0; | static int event_list_ix = 0; | ||||
static int n_event_list; | static int n_event_list; | ||||
static long count_samples; | static long count_samples; | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
static struct audio_object *my_audio = NULL; | static struct audio_object *my_audio = NULL; | ||||
#endif | #endif | ||||
void cancel_audio(void) | void cancel_audio(void) | ||||
{ | { | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | ||||
audio_object_flush(my_audio); | audio_object_flush(my_audio); | ||||
} | } | ||||
static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event) | static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event) | ||||
{ | { | ||||
int a_wave_can_be_played = 1; | int a_wave_can_be_played = 1; | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
if ((my_mode & ENOUTPUT_MODE_SYNCHRONOUS) == 0) | if ((my_mode & ENOUTPUT_MODE_SYNCHRONOUS) == 0) | ||||
a_wave_can_be_played = fifo_is_command_enabled(); | a_wave_can_be_played = fifo_is_command_enabled(); | ||||
#endif | #endif | ||||
voice_samplerate = event->id.number; | voice_samplerate = event->id.number; | ||||
if (out_samplerate != voice_samplerate) { | if (out_samplerate != voice_samplerate) { | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
if (out_samplerate != 0) { | if (out_samplerate != 0) { | ||||
// sound was previously open with a different sample rate | // sound was previously open with a different sample rate | ||||
audio_object_close(my_audio); | audio_object_close(my_audio); | ||||
out_samplerate = 0; | out_samplerate = 0; | ||||
#ifdef HAVE_SLEEP | |||||
sleep(1); | |||||
#endif | |||||
} | } | ||||
#endif | #endif | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
int error = audio_object_open(my_audio, AUDIO_OBJECT_FORMAT_S16LE, voice_samplerate, 1); | int error = audio_object_open(my_audio, AUDIO_OBJECT_FORMAT_S16LE, voice_samplerate, 1); | ||||
if (error != 0) { | if (error != 0) { | ||||
fprintf(stderr, "error: %s\n", audio_object_strerror(my_audio, error)); | fprintf(stderr, "error: %s\n", audio_object_strerror(my_audio, error)); | ||||
} | } | ||||
#endif | #endif | ||||
out_samplerate = voice_samplerate; | out_samplerate = voice_samplerate; | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
if ((my_mode & ENOUTPUT_MODE_SYNCHRONOUS) == 0) | if ((my_mode & ENOUTPUT_MODE_SYNCHRONOUS) == 0) | ||||
event_init(); | event_init(); | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
if (out_samplerate == 0) { | if (out_samplerate == 0) { | ||||
int error = audio_object_open(my_audio, AUDIO_OBJECT_FORMAT_S16LE, voice_samplerate, 1); | int error = audio_object_open(my_audio, AUDIO_OBJECT_FORMAT_S16LE, voice_samplerate, 1); | ||||
if (error != 0) { | if (error != 0) { | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
if (outbuf && length && a_wave_can_be_played) { | if (outbuf && length && a_wave_can_be_played) { | ||||
int error = audio_object_write(my_audio, (char *)outbuf, 2*length); | int error = audio_object_write(my_audio, (char *)outbuf, 2*length); | ||||
if (error != 0) | if (error != 0) | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
while (event && a_wave_can_be_played) { | while (event && a_wave_can_be_played) { | ||||
// TBD: some event are filtered here but some insight might be given | // TBD: some event are filtered here but some insight might be given | ||||
// TBD: in synthesise.cpp for avoiding to create WORDs with size=0. | // TBD: in synthesise.cpp for avoiding to create WORDs with size=0. | ||||
return finished; | return finished; | ||||
} | } | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
int sync_espeak_terminated_msg(uint32_t unique_identifier, void *user_data) | int sync_espeak_terminated_msg(uint32_t unique_identifier, void *user_data) | ||||
{ | { | ||||
ESPEAK_NG_API espeak_ng_STATUS espeak_ng_InitializeOutput(espeak_ng_OUTPUT_MODE output_mode, int buffer_length, const char *device) | ESPEAK_NG_API espeak_ng_STATUS espeak_ng_InitializeOutput(espeak_ng_OUTPUT_MODE output_mode, int buffer_length, const char *device) | ||||
{ | { | ||||
(void)device; // unused if HAVE_PCAUDIOLIB_AUDIO_H is not defined | (void)device; // unused if USE_LIBPCAUDIO is not defined | ||||
my_mode = output_mode; | my_mode = output_mode; | ||||
out_samplerate = 0; | out_samplerate = 0; | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
if (((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) && (my_audio == NULL)) | if (((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) && (my_audio == NULL)) | ||||
my_audio = create_audio_device_object(device, "eSpeak", "Text-to-Speech"); | my_audio = create_audio_device_object(device, "eSpeak", "Text-to-Speech"); | ||||
#endif | #endif | ||||
#if USE_ASYNC | |||||
if ((my_mode & ENOUTPUT_MODE_SYNCHRONOUS) == 0) fifo_init(); | |||||
#endif | |||||
// Don't allow buffer be smaller than safe minimum | // Don't allow buffer be smaller than safe minimum | ||||
if (buffer_length < min_buffer_length) | if (buffer_length < min_buffer_length) | ||||
if (check_data_path(path, 1)) | if (check_data_path(path, 1)) | ||||
return; | return; | ||||
#ifdef PLATFORM_WINDOWS | #if PLATFORM_WINDOWS | ||||
HKEY RegKey; | HKEY RegKey; | ||||
unsigned long size; | unsigned long size; | ||||
unsigned long var_type; | unsigned long var_type; | ||||
SetParameter(espeakPUNCTUATION, option_punctuation, 0); | SetParameter(espeakPUNCTUATION, option_punctuation, 0); | ||||
SetParameter(espeakWORDGAP, 0, 0); | SetParameter(espeakWORDGAP, 0, 0); | ||||
#ifdef USE_ASYNC | |||||
fifo_init(); | |||||
#endif | |||||
option_phonemes = 0; | option_phonemes = 0; | ||||
option_phoneme_events = 0; | option_phoneme_events = 0; | ||||
ep->text_position = char_position & 0xffffff; | ep->text_position = char_position & 0xffffff; | ||||
ep->length = char_position >> 24; | ep->length = char_position >> 24; | ||||
#if !USE_MBROLA | |||||
static const int mbrola_delay = 0; | |||||
#endif | |||||
time = ((double)(count_samples + mbrola_delay + (out_ptr - out_start)/2)*1000.0)/samplerate; | time = ((double)(count_samples + mbrola_delay + (out_ptr - out_start)/2)*1000.0)/samplerate; | ||||
ep->audio_position = (int)time; | ep->audio_position = (int)time; | ||||
ep->sample = (count_samples + mbrola_delay + (out_ptr - out_start)/2); | ep->sample = (count_samples + mbrola_delay + (out_ptr - out_start)/2); | ||||
end_character_position = end_position; | end_character_position = end_position; | ||||
espeak_ng_STATUS aStatus = Synthesize(unique_identifier, text, flags); | espeak_ng_STATUS aStatus = Synthesize(unique_identifier, text, flags); | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | ||||
int error = (aStatus == ENS_SPEECH_STOPPED) | int error = (aStatus == ENS_SPEECH_STOPPED) | ||||
? audio_object_flush(my_audio) | ? audio_object_flush(my_audio) | ||||
ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback *SynthCallback) | ESPEAK_API void espeak_SetSynthCallback(t_espeak_callback *SynthCallback) | ||||
{ | { | ||||
synth_callback = SynthCallback; | synth_callback = SynthCallback; | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
event_set_callback(synth_callback); | event_set_callback(synth_callback); | ||||
#endif | #endif | ||||
} | } | ||||
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | ||||
return sync_espeak_Synth(0, text, position, position_type, end_position, flags, user_data); | return sync_espeak_Synth(0, text, position, position_type, end_position, flags, user_data); | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
// Create the text command | // Create the text command | ||||
t_espeak_command *c1 = create_espeak_text(text, size, position, position_type, end_position, flags, user_data); | t_espeak_command *c1 = create_espeak_text(text, size, position, position_type, end_position, flags, user_data); | ||||
if (c1) { | if (c1) { | ||||
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | ||||
return sync_espeak_Synth_Mark(0, text, index_mark, end_position, flags, user_data); | return sync_espeak_Synth_Mark(0, text, index_mark, end_position, flags, user_data); | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
// Create the mark command | // Create the mark command | ||||
t_espeak_command *c1 = create_espeak_mark(text, size, index_mark, end_position, | t_espeak_command *c1 = create_espeak_mark(text, size, index_mark, end_position, | ||||
flags, user_data); | flags, user_data); | ||||
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | ||||
return sync_espeak_Key(key_name); | return sync_espeak_Key(key_name); | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
t_espeak_command *c = create_espeak_key(key_name, NULL); | t_espeak_command *c = create_espeak_key(key_name, NULL); | ||||
espeak_ng_STATUS status = fifo_add_command(c); | espeak_ng_STATUS status = fifo_add_command(c); | ||||
if (status != ENS_OK) | if (status != ENS_OK) | ||||
{ | { | ||||
// is there a system resource of character names per language? | // is there a system resource of character names per language? | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | ||||
return sync_espeak_Char(character); | return sync_espeak_Char(character); | ||||
ESPEAK_NG_API espeak_ng_STATUS espeak_ng_SetParameter(espeak_PARAMETER parameter, int value, int relative) | ESPEAK_NG_API espeak_ng_STATUS espeak_ng_SetParameter(espeak_PARAMETER parameter, int value, int relative) | ||||
{ | { | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) | ||||
return SetParameter(parameter, value, relative); | return SetParameter(parameter, value, relative); | ||||
{ | { | ||||
// Set the list of punctuation which are spoken for "some". | // Set the list of punctuation which are spoken for "some". | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) { | if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) { | ||||
sync_espeak_SetPunctuationList(punctlist); | sync_espeak_SetPunctuationList(punctlist); | ||||
return ENS_OK; | return ENS_OK; | ||||
ESPEAK_NG_API espeak_ng_STATUS espeak_ng_Cancel(void) | ESPEAK_NG_API espeak_ng_STATUS espeak_ng_Cancel(void) | ||||
{ | { | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
fifo_stop(); | fifo_stop(); | ||||
event_clear_all(); | event_clear_all(); | ||||
#endif | #endif | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) | if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) | ||||
audio_object_flush(my_audio); | audio_object_flush(my_audio); | ||||
#endif | #endif | ||||
ESPEAK_API int espeak_IsPlaying(void) | ESPEAK_API int espeak_IsPlaying(void) | ||||
{ | { | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
return fifo_is_busy(); | return fifo_is_busy(); | ||||
#else | #else | ||||
return 0; | return 0; | ||||
ESPEAK_NG_API espeak_ng_STATUS espeak_ng_Synchronize(void) | ESPEAK_NG_API espeak_ng_STATUS espeak_ng_Synchronize(void) | ||||
{ | { | ||||
espeak_ng_STATUS berr = err; | espeak_ng_STATUS berr = err; | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
while (espeak_IsPlaying()) | while (espeak_IsPlaying()) | ||||
usleep(20000); | usleep(20000); | ||||
#endif | #endif | ||||
ESPEAK_NG_API espeak_ng_STATUS espeak_ng_Terminate(void) | ESPEAK_NG_API espeak_ng_STATUS espeak_ng_Terminate(void) | ||||
{ | { | ||||
#ifdef USE_ASYNC | #if USE_ASYNC | ||||
fifo_stop(); | fifo_stop(); | ||||
fifo_terminate(); | fifo_terminate(); | ||||
event_terminate(); | event_terminate(); | ||||
#endif | #endif | ||||
if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | ||||
#ifdef HAVE_PCAUDIOLIB_AUDIO_H | #if USE_LIBPCAUDIO | ||||
audio_object_close(my_audio); | audio_object_close(my_audio); | ||||
audio_object_destroy(my_audio); | audio_object_destroy(my_audio); | ||||
my_audio = NULL; | my_audio = NULL; |
#endif | #endif | ||||
#ifndef MAKE_MEM_UNDEFINED | #ifndef MAKE_MEM_UNDEFINED | ||||
# ifdef HAVE_VALGRIND_MEMCHECK_H | # if __has_include(<valgrind/memcheck.h>) | ||||
# include <valgrind/memcheck.h> | # include <valgrind/memcheck.h> | ||||
# define MAKE_MEM_UNDEFINED(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len) | # define MAKE_MEM_UNDEFINED(addr, len) VALGRIND_MAKE_MEM_UNDEFINED(addr, len) | ||||
# else | # else | ||||
#if defined(_WIN32) || defined(_WIN64) // Windows | #if defined(_WIN32) || defined(_WIN64) // Windows | ||||
#define PLATFORM_WINDOWS | #define PLATFORM_WINDOWS 1 | ||||
#define PATHSEP '\\' | #define PATHSEP '\\' | ||||
#define N_PATH_HOME_DEF 230 | #define N_PATH_HOME_DEF 230 | ||||
#define NO_VARIADIC_MACROS | #define NO_VARIADIC_MACROS | ||||
#else | #else | ||||
#define PLATFORM_POSIX | #define PLATFORM_POSIX 1 | ||||
#define PATHSEP '/' | #define PATHSEP '/' | ||||
#define N_PATH_HOME_DEF 160 | #define N_PATH_HOME_DEF 160 | ||||
#define USE_NANOSLEEP | #define USE_NANOSLEEP |
int wpm = speech_parameters[espeakRATE]; | int wpm = speech_parameters[espeakRATE]; | ||||
espeak_SetParameter(espeakRATE, wpm, 0); | espeak_SetParameter(espeakRATE, wpm, 0); | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
if (wpm >= espeakRATE_MAXIMUM) { | if (wpm >= espeakRATE_MAXIMUM) { | ||||
// Compensate speedup with libsonic, see function SetSpeed() | // Compensate speedup with libsonic, see function SetSpeed() | ||||
double sonic = ((double)wpm)/espeakRATE_NORMAL; | double sonic = ((double)wpm)/espeakRATE_NORMAL; |
int mbrola_delay; | int mbrola_delay; | ||||
char mbrola_name[20]; | char mbrola_name[20]; | ||||
#ifdef INCLUDE_MBROLA | #if USE_MBROLA | ||||
#if defined(_WIN32) || defined(_WIN64) | #if defined(_WIN32) || defined(_WIN64) | ||||
#include <windows.h> | #include <windows.h> | ||||
return ENS_MBROLA_NOT_FOUND; | return ENS_MBROLA_NOT_FOUND; | ||||
sprintf(path, "%s/mbrola/%s", path_home, mbrola_voice); | sprintf(path, "%s/mbrola/%s", path_home, mbrola_voice); | ||||
#ifdef PLATFORM_POSIX | #if PLATFORM_POSIX | ||||
// if not found, then also look in | // if not found, then also look in | ||||
// usr/share/mbrola/xx, /usr/share/mbrola/xx/xx, /usr/share/mbrola/voices/xx | // usr/share/mbrola/xx, /usr/share/mbrola/xx/xx, /usr/share/mbrola/voices/xx | ||||
if (GetFileLength(path) <= 0) { | if (GetFileLength(path) <= 0) { |
{ | { | ||||
case 1: // PreVoicing | case 1: // PreVoicing | ||||
return control & 1; | return control & 1; | ||||
#if USE_KLATT | |||||
case 2: // KlattSynth | case 2: // KlattSynth | ||||
return voice->klattv[0] != 0; | return voice->klattv[0] != 0; | ||||
#endif | |||||
#if USE_MBROLA | |||||
case 3: // MbrolaSynth | case 3: // MbrolaSynth | ||||
return mbrola_name[0] != 0; | return mbrola_name[0] != 0; | ||||
#endif | |||||
} | } | ||||
} | } | ||||
return false; | return false; |
} | } | ||||
} | } | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
void DoSonicSpeed(int value) | void DoSonicSpeed(int value) | ||||
{ | { | ||||
// value, multiplier * 1024 | // value, multiplier * 1024 | ||||
if (option_phoneme_events & espeakINITIALIZE_PHONEME_IPA) | if (option_phoneme_events & espeakINITIALIZE_PHONEME_IPA) | ||||
use_ipa = 1; | use_ipa = 1; | ||||
#if USE_MBROLA | |||||
if (mbrola_name[0] != 0) | if (mbrola_name[0] != 0) | ||||
return MbrolaGenerate(phoneme_list, n_ph, resume); | return MbrolaGenerate(phoneme_list, n_ph, resume); | ||||
#endif | |||||
if (resume == false) { | if (resume == false) { | ||||
ix = 1; | ix = 1; |
void Write4Bytes(FILE *f, int value); | void Write4Bytes(FILE *f, int value); | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
void DoSonicSpeed(int value); | void DoSonicSpeed(int value); | ||||
#endif | #endif | ||||
if (tone_only == 0) { | if (tone_only == 0) { | ||||
n_replace_phonemes = 0; | n_replace_phonemes = 0; | ||||
#if USE_MBROLA | |||||
LoadMbrolaTable(NULL, NULL, 0); | LoadMbrolaTable(NULL, NULL, 0); | ||||
#endif | |||||
} | } | ||||
// probably unnecessary, but removing this would break tests | // probably unnecessary, but removing this would break tests | ||||
sscanf(p, "%d", &voice->speed_percent); | sscanf(p, "%d", &voice->speed_percent); | ||||
SetSpeed(3); | SetSpeed(3); | ||||
break; | break; | ||||
#if USE_MBROLA | |||||
case V_MBROLA: | case V_MBROLA: | ||||
{ | { | ||||
int srate = 16000; | int srate = 16000; | ||||
voice->samplerate = srate; | voice->samplerate = srate; | ||||
} | } | ||||
break; | break; | ||||
#endif | |||||
#if USE_KLATT | |||||
case V_KLATT: | case V_KLATT: | ||||
voice->klattv[0] = 1; // default source: IMPULSIVE | voice->klattv[0] = 1; // default source: IMPULSIVE | ||||
Read8Numbers(p, voice->klattv); | Read8Numbers(p, voice->klattv); | ||||
voice->klattv[KLATT_Kopen] -= 40; | voice->klattv[KLATT_Kopen] -= 40; | ||||
break; | break; | ||||
#endif | |||||
case V_FAST: | case V_FAST: | ||||
sscanf(p, "%d", &speed.fast_settings); | sscanf(p, "%d", &speed.fast_settings); | ||||
SetSpeed(3); | SetSpeed(3); | ||||
{ | { | ||||
char fname[sizeof(path_home)+100]; | char fname[sizeof(path_home)+100]; | ||||
#ifdef PLATFORM_WINDOWS | #if PLATFORM_WINDOWS | ||||
WIN32_FIND_DATAA FindFileData; | WIN32_FIND_DATAA FindFileData; | ||||
HANDLE hFind = INVALID_HANDLE_VALUE; | HANDLE hFind = INVALID_HANDLE_VALUE; | ||||
#include "synthesize.h" // for WGEN_DATA, RESONATOR, frame_t | #include "synthesize.h" // for WGEN_DATA, RESONATOR, frame_t | ||||
#include "mbrola.h" // for MbrolaFill, MbrolaReset, mbrola... | #include "mbrola.h" // for MbrolaFill, MbrolaReset, mbrola... | ||||
#ifdef INCLUDE_KLATT | #if USE_KLATT | ||||
#include "klatt.h" | #include "klatt.h" | ||||
#endif | #endif | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
#include "sonic.h" | #include "sonic.h" | ||||
#endif | #endif | ||||
const int embedded_default[N_EMBEDDED_VALUES] = { 0, 50, espeakRATE_NORMAL, 100, 50, 0, 0, 0, espeakRATE_NORMAL, 0, 0, 0, 0, 0, 0 }; | const int embedded_default[N_EMBEDDED_VALUES] = { 0, 50, espeakRATE_NORMAL, 100, 50, 0, 0, 0, espeakRATE_NORMAL, 0, 0, 0, 0, 0, 0 }; | ||||
static int embedded_max[N_EMBEDDED_VALUES] = { 0, 0x7fff, 750, 300, 99, 99, 99, 0, 750, 0, 0, 0, 0, 4, 0 }; | static int embedded_max[N_EMBEDDED_VALUES] = { 0, 0x7fff, 750, 300, 99, 99, 99, 0, 750, 0, 0, 0, 0, 4, 0 }; | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
static sonicStream sonicSpeedupStream = NULL; | static sonicStream sonicSpeedupStream = NULL; | ||||
static double sonicSpeed = 1.0; | static double sonicSpeed = 1.0; | ||||
#endif | #endif | ||||
wcmdq_head = 0; | wcmdq_head = 0; | ||||
wcmdq_tail = 0; | wcmdq_tail = 0; | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
if (sonicSpeedupStream != NULL) { | if (sonicSpeedupStream != NULL) { | ||||
sonicDestroyStream(sonicSpeedupStream); | sonicDestroyStream(sonicSpeedupStream); | ||||
sonicSpeedupStream = NULL; | sonicSpeedupStream = NULL; | ||||
} | } | ||||
#endif | #endif | ||||
#if USE_MBROLA | |||||
if (mbrola_name[0] != 0) | if (mbrola_name[0] != 0) | ||||
MbrolaReset(); | MbrolaReset(); | ||||
#endif | |||||
} | } | ||||
int WcmdqFree() | int WcmdqFree() | ||||
pk_shape = pk_shape2; | pk_shape = pk_shape2; | ||||
#ifdef INCLUDE_KLATT | #if USE_KLATT | ||||
KlattInit(); | KlattInit(); | ||||
#endif | #endif | ||||
} | } | ||||
void WavegenFini(void) | void WavegenFini(void) | ||||
{ | { | ||||
#ifdef INCLUDE_KLATT | #if USE_KLATT | ||||
KlattFini(); | KlattFini(); | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
// apply main peaks, formants 0 to 5 | // apply main peaks, formants 0 to 5 | ||||
#ifdef USE_ASSEMBLER_1 | |||||
// use an optimised routine for this loop, if available | |||||
total += AddSineWaves(waveph, h_switch_sign, maxh, harmspect); // call an assembler code routine | |||||
#else | |||||
theta = waveph; | theta = waveph; | ||||
for (h = 1; h <= h_switch_sign; h++) { | for (h = 1; h <= h_switch_sign; h++) { | ||||
theta += waveph; | theta += waveph; | ||||
h++; | h++; | ||||
} | } | ||||
#endif | |||||
if (voicing != 64) | if (voicing != 64) | ||||
total = (total >> 6) * voicing; | total = (total >> 6) * voicing; | ||||
echo_complete -= length; | echo_complete -= length; | ||||
wdata.n_mix_wavefile = 0; | wdata.n_mix_wavefile = 0; | ||||
wdata.amplitude_fmt = 100; | wdata.amplitude_fmt = 100; | ||||
#ifdef INCLUDE_KLATT | #if USE_KLATT | ||||
KlattReset(1); | KlattReset(1); | ||||
#endif | #endif | ||||
result = PlaySilence(length, resume); | result = PlaySilence(length, resume); | ||||
case WCMD_WAVE: | case WCMD_WAVE: | ||||
echo_complete = echo_length; | echo_complete = echo_length; | ||||
wdata.n_mix_wavefile = 0; | wdata.n_mix_wavefile = 0; | ||||
#ifdef INCLUDE_KLATT | #if USE_KLATT | ||||
KlattReset(1); | KlattReset(1); | ||||
#endif | #endif | ||||
result = PlayWave(length, resume, (unsigned char *)q[2], q[3] & 0xff, q[3] >> 8); | result = PlayWave(length, resume, (unsigned char *)q[2], q[3] & 0xff, q[3] >> 8); | ||||
echo_complete = echo_length; | echo_complete = echo_length; | ||||
result = Wavegen(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3], wvoice); | result = Wavegen(length & 0xffff, q[1] >> 16, resume, (frame_t *)q[2], (frame_t *)q[3], wvoice); | ||||
break; | break; | ||||
#ifdef INCLUDE_KLATT | #if USE_KLATT | ||||
case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file | case WCMD_KLATT2: // as WCMD_SPECT but stop any concurrent wave file | ||||
wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | wdata.n_mix_wavefile = 0; // ... and drop through to WCMD_SPECT case | ||||
case WCMD_KLATT: | case WCMD_KLATT: | ||||
case WCMD_EMBEDDED: | case WCMD_EMBEDDED: | ||||
SetEmbedded(q[1], q[2]); | SetEmbedded(q[1], q[2]); | ||||
break; | break; | ||||
#if USE_MBROLA | |||||
case WCMD_MBROLA_DATA: | case WCMD_MBROLA_DATA: | ||||
if (wvoice != NULL) | if (wvoice != NULL) | ||||
result = MbrolaFill(length, resume, (general_amplitude * wvoice->voicing)/64); | result = MbrolaFill(length, resume, (general_amplitude * wvoice->voicing)/64); | ||||
break; | break; | ||||
#endif | |||||
case WCMD_FMT_AMPLITUDE: | case WCMD_FMT_AMPLITUDE: | ||||
if ((wdata.amplitude_fmt = q[1]) == 0) | if ((wdata.amplitude_fmt = q[1]) == 0) | ||||
wdata.amplitude_fmt = 100; // percentage, but value=0 means 100% | wdata.amplitude_fmt = 100; // percentage, but value=0 means 100% | ||||
break; | break; | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
case WCMD_SONIC_SPEED: | case WCMD_SONIC_SPEED: | ||||
sonicSpeed = (double)q[1] / 1024; | sonicSpeed = (double)q[1] / 1024; | ||||
if (sonicSpeedupStream && (sonicSpeed <= 1.0)) { | if (sonicSpeedupStream && (sonicSpeed <= 1.0)) { | ||||
return 0; | return 0; | ||||
} | } | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
// Speed up the audio samples with libsonic. | // Speed up the audio samples with libsonic. | ||||
static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text) | static int SpeedUp(short *outbuf, int length_in, int length_out, int end_of_text) | ||||
{ | { | ||||
int WavegenFill(void) | int WavegenFill(void) | ||||
{ | { | ||||
int finished; | int finished; | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
unsigned char *p_start; | unsigned char *p_start; | ||||
p_start = out_ptr; | p_start = out_ptr; | ||||
finished = WavegenFill2(); | finished = WavegenFill2(); | ||||
#if HAVE_SONIC_H | #if USE_LIBSONIC | ||||
if (sonicSpeed > 1.0) { | if (sonicSpeed > 1.0) { | ||||
int length; | int length; | ||||
int max_length; | int max_length; |
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "en") == 0); | assert(strcmp(translator->dictionary_name, "en") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(p_decoder == NULL); | assert(p_decoder == NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_NOT_FOUND); | int res = espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL); | ||||
#if USE_ASYNC | |||||
assert(res == EE_OK); | |||||
#else | |||||
assert(res == EE_NOT_FOUND); | |||||
#endif | |||||
assert(translator == NULL); | assert(translator == NULL); | ||||
assert(p_decoder == NULL); | assert(p_decoder == NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_ng_Synthesize(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == ENS_OK); | assert(espeak_ng_Synthesize(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == ENS_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "en") == 0); | assert(strcmp(translator->dictionary_name, "en") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(p_decoder == NULL); | assert(p_decoder == NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_ng_Synthesize(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == ENS_VOICE_NOT_FOUND); | int res = espeak_ng_Synthesize(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL); | ||||
#if USE_ASYNC | |||||
assert(res == EE_OK); | |||||
#else | |||||
assert(res == ENS_VOICE_NOT_FOUND); | |||||
#endif | |||||
assert(translator == NULL); | assert(translator == NULL); | ||||
assert(p_decoder == NULL); | assert(p_decoder == NULL); | ||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_ng_Synchronize() == ENS_OK); | ||||
assert(translator == NULL); | assert(translator == NULL); | ||||
assert(p_decoder == NULL); | assert(p_decoder == NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "en") == 0); | assert(strcmp(translator->dictionary_name, "en") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "en") == 0); | assert(strcmp(translator->dictionary_name, "en") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "de") == 0); | assert(strcmp(translator->dictionary_name, "de") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "en") == 0); | assert(strcmp(translator->dictionary_name, "en") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "en") == 0); | assert(strcmp(translator->dictionary_name, "en") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "en") == 0); | assert(strcmp(translator->dictionary_name, "en") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "en") == 0); | assert(strcmp(translator->dictionary_name, "en") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "mk") == 0); | assert(strcmp(translator->dictionary_name, "mk") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
const char *test = "One two three."; | const char *test = "One two three."; | ||||
assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | assert(espeak_Synth(test, strlen(test)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL) == EE_OK); | ||||
#if !USE_ASYNC | |||||
assert(translator != NULL); | assert(translator != NULL); | ||||
assert(strcmp(translator->dictionary_name, "en") == 0); | assert(strcmp(translator->dictionary_name, "en") == 0); | ||||
assert(p_decoder != NULL); | assert(p_decoder != NULL); | ||||
#endif | |||||
assert(espeak_Synchronize() == EE_OK); | assert(espeak_Synchronize() == EE_OK); | ||||
assert(translator != NULL); | assert(translator != NULL); | ||||
espeak_ng_InitializePath(NULL); | espeak_ng_InitializePath(NULL); | ||||
espeak_ng_ERROR_CONTEXT context = NULL; | espeak_ng_ERROR_CONTEXT context = NULL; | ||||
assert(espeak_ng_Initialize(&context) == ENS_OK); | assert(espeak_ng_Initialize(&context) == ENS_OK); | ||||
assert(espeak_ng_InitializeOutput(ENOUTPUT_MODE_SYNCHRONOUS, 0, NULL) == ENS_OK); | assert(espeak_ng_InitializeOutput(0, 0, NULL) == ENS_OK); | ||||
espeak_SetSynthCallback(_test_espeak_ng_phoneme_events_cb); | espeak_SetSynthCallback(_test_espeak_ng_phoneme_events_cb); | ||||
assert(espeak_ng_SetPhonemeEvents(enabled, ipa) == ENS_OK); | assert(espeak_ng_SetPhonemeEvents(enabled, ipa) == ENS_OK); | ||||