mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-01 21:58:52 +00:00
[1.32]
Fix: espeak --stdout, set a (large) data size. espeak --voices. Include mbrola voices only if a language is specified. git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@156 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
+103
-35
@@ -37,6 +37,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <pulse/pulseaudio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifndef PLATFORM_WINDOWS
|
||||
#include <unistd.h>
|
||||
@@ -48,6 +49,18 @@
|
||||
|
||||
enum {ONE_BILLION=1000000000};
|
||||
|
||||
enum {
|
||||
// /* 100ms.
|
||||
// If a greater value is set (several seconds),
|
||||
// please update _pulse_timeout_start accordingly */
|
||||
// PULSE_TIMEOUT_IN_USEC = 100000,
|
||||
|
||||
/* return value */
|
||||
PULSE_OK = 0,
|
||||
PULSE_ERROR = -1,
|
||||
PULSE_NO_CONNECTION = -2
|
||||
};
|
||||
|
||||
#ifdef USE_PULSEAUDIO
|
||||
|
||||
static t_wave_callback* my_callback_is_output_enabled=NULL;
|
||||
@@ -62,6 +75,8 @@ static t_wave_callback* my_callback_is_output_enabled=NULL;
|
||||
#define MINREQ 880
|
||||
#define FRAGSIZE 0
|
||||
|
||||
static pthread_mutex_t pulse_mutex;
|
||||
|
||||
static pa_context *context = NULL;
|
||||
static pa_stream *stream = NULL;
|
||||
static pa_threaded_mainloop *mainloop = NULL;
|
||||
@@ -81,7 +96,7 @@ if (!mainloop || \
|
||||
!context || pa_context_get_state(context) != PA_CONTEXT_READY || \
|
||||
!stream || pa_stream_get_state(stream) != PA_STREAM_READY) { \
|
||||
if (warn) \
|
||||
printf("Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \
|
||||
SHOW("Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \
|
||||
goto label; \
|
||||
} \
|
||||
} while(0);
|
||||
@@ -91,6 +106,11 @@ do { \
|
||||
if (!connected) return retval; \
|
||||
} while (0);
|
||||
|
||||
#define CHECK_CONNECTED_NO_RETVAL(id) \
|
||||
do { \
|
||||
if (!connected){ SHOW("CHECK_CONNECTED_NO_RETVAL: !pulse_connected\n", ""); return; } \
|
||||
} while (0);
|
||||
|
||||
//>
|
||||
|
||||
|
||||
@@ -136,7 +156,7 @@ static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t
|
||||
return;
|
||||
|
||||
if (!(o = pa_context_get_sink_input_info(c, index, info_cb, NULL))) {
|
||||
printf("pa_context_get_sink_input_info() failed: %s\n", pa_strerror(pa_context_errno(c)));
|
||||
SHOW("pa_context_get_sink_input_info() failed: %s\n", pa_strerror(pa_context_errno(c)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -365,20 +385,21 @@ fail:
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
}
|
||||
|
||||
static void drain(void) {
|
||||
static int drain(void) {
|
||||
pa_operation *o = NULL;
|
||||
int success = 0;
|
||||
int ret = PULSE_ERROR;
|
||||
|
||||
ENTER(__FUNCTION__);
|
||||
|
||||
CHECK_CONNECTED();
|
||||
CHECK_CONNECTED(ret);
|
||||
|
||||
pa_threaded_mainloop_lock(mainloop);
|
||||
CHECK_DEAD_GOTO(fail, 0);
|
||||
|
||||
SHOW_TIME("pa_stream_drain (call)");
|
||||
if (!(o = pa_stream_drain(stream, stream_success_cb, &success))) {
|
||||
printf("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
|
||||
SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -389,8 +410,12 @@ static void drain(void) {
|
||||
}
|
||||
SHOW_TIME("pa_threaded_mainloop_wait (ret)");
|
||||
|
||||
if (!success)
|
||||
printf("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
|
||||
if (!success) {
|
||||
SHOW("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
|
||||
}
|
||||
else {
|
||||
ret = PULSE_OK;
|
||||
}
|
||||
|
||||
fail:
|
||||
SHOW_TIME("pa_operation_unref (call)");
|
||||
@@ -399,6 +424,8 @@ fail:
|
||||
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
SHOW_TIME("drain (ret)");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -413,12 +440,7 @@ static void pulse_close(void) {
|
||||
if (mainloop)
|
||||
pa_threaded_mainloop_stop(mainloop);
|
||||
|
||||
if (stream) {
|
||||
SHOW_TIME("pa_stream_disconnect (call)");
|
||||
pa_stream_disconnect(stream);
|
||||
pa_stream_unref(stream);
|
||||
stream = NULL;
|
||||
}
|
||||
connected = 0;
|
||||
|
||||
if (context) {
|
||||
SHOW_TIME("pa_context_disconnect (call)");
|
||||
@@ -443,12 +465,15 @@ static int pulse_open()
|
||||
pa_sample_spec ss;
|
||||
pa_operation *o = NULL;
|
||||
int success;
|
||||
int ret = PULSE_ERROR;
|
||||
|
||||
assert(!mainloop);
|
||||
assert(!context);
|
||||
assert(!stream);
|
||||
assert(!connected);
|
||||
|
||||
pthread_mutex_init( &pulse_mutex, (const pthread_mutexattr_t *)NULL);
|
||||
|
||||
ss.format = ESPEAK_FORMAT;
|
||||
ss.rate = SAMPLE_RATE;
|
||||
ss.channels = ESPEAK_CHANNEL;
|
||||
@@ -464,7 +489,7 @@ static int pulse_open()
|
||||
|
||||
SHOW_TIME("pa_threaded_mainloop_new (call)");
|
||||
if (!(mainloop = pa_threaded_mainloop_new())) {
|
||||
printf("Failed to allocate main loop\n");
|
||||
SHOW("Failed to allocate main loop\n","");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -472,7 +497,7 @@ static int pulse_open()
|
||||
|
||||
SHOW_TIME("pa_context_new (call)");
|
||||
if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "eSpeak"))) {
|
||||
printf("Failed to allocate context\n");
|
||||
SHOW("Failed to allocate context\n","");
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
@@ -481,13 +506,14 @@ static int pulse_open()
|
||||
|
||||
SHOW_TIME("pa_context_connect (call)");
|
||||
if (pa_context_connect(context, NULL, (pa_context_flags_t)0, NULL) < 0) {
|
||||
printf("Failed to connect to server: %s", pa_strerror(pa_context_errno(context)));
|
||||
SHOW("Failed to connect to server: %s", pa_strerror(pa_context_errno(context)));
|
||||
ret = PULSE_NO_CONNECTION;
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
SHOW_TIME("pa_threaded_mainloop_start (call)");
|
||||
if (pa_threaded_mainloop_start(mainloop) < 0) {
|
||||
printf("Failed to start main loop");
|
||||
SHOW("Failed to start main loop","");
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
@@ -496,13 +522,16 @@ static int pulse_open()
|
||||
pa_threaded_mainloop_wait(mainloop);
|
||||
|
||||
if (pa_context_get_state(context) != PA_CONTEXT_READY) {
|
||||
printf("Failed to connect to server: %s", pa_strerror(pa_context_errno(context)));
|
||||
SHOW("Failed to connect to server: %s", pa_strerror(pa_context_errno(context)));
|
||||
ret = PULSE_NO_CONNECTION;
|
||||
if (mainloop)
|
||||
pa_threaded_mainloop_stop(mainloop);
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
SHOW_TIME("pa_stream_new");
|
||||
if (!(stream = pa_stream_new(context, "unknown", &ss, NULL))) {
|
||||
printf("Failed to create stream: %s", pa_strerror(pa_context_errno(context)));
|
||||
SHOW("Failed to create stream: %s", pa_strerror(pa_context_errno(context)));
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
@@ -522,7 +551,7 @@ static int pulse_open()
|
||||
|
||||
SHOW_TIME("pa_connect_playback");
|
||||
if (pa_stream_connect_playback(stream, NULL, &a_attr, (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE), &volume, NULL) < 0) {
|
||||
printf("Failed to connect stream: %s", pa_strerror(pa_context_errno(context)));
|
||||
SHOW("Failed to connect stream: %s", pa_strerror(pa_context_errno(context)));
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
@@ -531,14 +560,14 @@ static int pulse_open()
|
||||
pa_threaded_mainloop_wait(mainloop);
|
||||
|
||||
if (pa_stream_get_state(stream) != PA_STREAM_READY) {
|
||||
printf("Failed to connect stream: %s", pa_strerror(pa_context_errno(context)));
|
||||
SHOW("Failed to connect stream: %s", pa_strerror(pa_context_errno(context)));
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
/* Now subscribe to events */
|
||||
SHOW_TIME("pa_context_subscribe");
|
||||
if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) {
|
||||
printf("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context)));
|
||||
SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context)));
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
@@ -550,7 +579,7 @@ static int pulse_open()
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
printf("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context)));
|
||||
SHOW("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context)));
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
@@ -558,7 +587,7 @@ static int pulse_open()
|
||||
|
||||
/* Now request the initial stream info */
|
||||
if (!(o = pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_cb, NULL))) {
|
||||
printf("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context)));
|
||||
SHOW("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context)));
|
||||
goto unlock_and_fail;
|
||||
}
|
||||
|
||||
@@ -569,7 +598,7 @@ static int pulse_open()
|
||||
}
|
||||
|
||||
/* if (!volume_valid) { */
|
||||
/* printf("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); */
|
||||
/* SHOW("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context))); */
|
||||
/* goto unlock_and_fail; */
|
||||
/* } */
|
||||
|
||||
@@ -583,7 +612,9 @@ static int pulse_open()
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
SHOW_TIME("pulse_open (ret true)");
|
||||
|
||||
return true;
|
||||
// return true;
|
||||
return PULSE_OK;
|
||||
|
||||
|
||||
unlock_and_fail:
|
||||
|
||||
@@ -594,13 +625,29 @@ unlock_and_fail:
|
||||
|
||||
fail:
|
||||
|
||||
// pulse_close();
|
||||
|
||||
if (ret == PULSE_NO_CONNECTION) {
|
||||
if (context) {
|
||||
SHOW_TIME("pa_context_disconnect (call)");
|
||||
pa_context_disconnect(context);
|
||||
pa_context_unref(context);
|
||||
context = NULL;
|
||||
}
|
||||
|
||||
if (mainloop) {
|
||||
SHOW_TIME("pa_threaded_mainloop_free (call)");
|
||||
pa_threaded_mainloop_free(mainloop);
|
||||
mainloop = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pulse_close();
|
||||
}
|
||||
|
||||
SHOW_TIME("pulse_open (ret false)");
|
||||
|
||||
return false;
|
||||
|
||||
|
||||
SHOW_TIME("pulse_open (ret false)");
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@@ -661,13 +708,16 @@ size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSiz
|
||||
|
||||
size_t aTotalFreeMem=0;
|
||||
|
||||
pthread_mutex_lock(&pulse_mutex);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (my_callback_is_output_enabled
|
||||
&& (0==my_callback_is_output_enabled()))
|
||||
{
|
||||
SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
|
||||
return 0;
|
||||
theSize=0;
|
||||
goto terminate;
|
||||
}
|
||||
|
||||
aTotalFreeMem = pulse_free();
|
||||
@@ -698,9 +748,10 @@ size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSiz
|
||||
|
||||
pulse_write(aBuffer, bytes_to_write);
|
||||
|
||||
|
||||
terminate:
|
||||
pthread_mutex_unlock(&pulse_mutex);
|
||||
SHOW("wave_write: theSize=%d", theSize);
|
||||
SHOW_TIME("wave_write > LEAVE");
|
||||
|
||||
return theSize;
|
||||
}
|
||||
|
||||
@@ -711,9 +762,18 @@ int wave_close(void* theHandler)
|
||||
{
|
||||
SHOW_TIME("wave_close > ENTER");
|
||||
|
||||
int a_status = pthread_mutex_lock(&pulse_mutex);
|
||||
if (a_status) {
|
||||
SHOW("Error: pulse_mutex lock=%d (%s)\n", a_status, __FUNCTION__);
|
||||
return PULSE_ERROR;
|
||||
}
|
||||
|
||||
drain();
|
||||
|
||||
return 0;
|
||||
pthread_mutex_unlock(&pulse_mutex);
|
||||
SHOW_TIME("wave_close (ret)");
|
||||
|
||||
return PULSE_OK;
|
||||
}
|
||||
|
||||
//>
|
||||
@@ -738,8 +798,16 @@ void wave_terminate()
|
||||
|
||||
// Pa_Terminate();
|
||||
|
||||
int a_status;
|
||||
pthread_mutex_t* a_mutex = NULL;
|
||||
a_mutex = &pulse_mutex;
|
||||
a_status = pthread_mutex_lock(a_mutex);
|
||||
|
||||
pulse_close();
|
||||
|
||||
SHOW_TIME("unlock mutex");
|
||||
a_status = pthread_mutex_unlock(a_mutex);
|
||||
pthread_mutex_destroy(a_mutex);
|
||||
}
|
||||
|
||||
//>
|
||||
|
||||
Reference in New Issue
Block a user