diff options
Diffstat (limited to 'src/espeak.c')
-rw-r--r-- | src/espeak.c | 130 |
1 files changed, 75 insertions, 55 deletions
diff --git a/src/espeak.c b/src/espeak.c index 265a243..f49cd6d 100644 --- a/src/espeak.c +++ b/src/espeak.c @@ -21,67 +21,99 @@ #include <glib.h> #include <gio/gio.h> #include <espeak/speak_lib.h> +#include <gst/gst.h> -struct Espeak +#include "spin.h" +#include "espeak.h" + +struct _Espeak { - GOutputStream *buffer; + Econtext *context; + guint rate; + guint pitch; + const gchar *voice; }; -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static GOutputStream *buffer = NULL; -static gint sample_rate = 0; -static const espeak_VOICE **voices = NULL; +static gint espeak_sample_rate = 0; +static const espeak_VOICE **espeak_voices = NULL; +static GOutputStream *espeak_buffer = NULL; static gint -read_cb(short * data, int numsamples, espeak_EVENT * events) +synth_cb(short * data, int numsamples, espeak_EVENT * events) { if (data == NULL) return 0; if (numsamples > 0) - g_output_stream_write(buffer, data, numsamples*2, NULL, NULL); + g_output_stream_write(espeak_buffer, data, numsamples*2, NULL, NULL); + + GST_DEBUG("numsamples=%d data_size=%ld", numsamples*2, + g_memory_output_stream_get_data_size(G_MEMORY_OUTPUT_STREAM( + espeak_buffer))); return 0; } static void +synth(const gchar *text, GMemoryOutputStream *sound, gpointer self_) +{ + Espeak *self = (Espeak*)self_; + + espeak_SetParameter(espeakPITCH, self->pitch, 0); + espeak_SetParameter(espeakRATE, self->rate, 0); + espeak_SetVoiceByName(self->voice); + espeak_buffer = G_OUTPUT_STREAM(sound); + + espeak_Synth(text, strlen(text)+1, 0, POS_WORD, 0, espeakCHARS_UTF8, + NULL, NULL); +} + +static void init() { static volatile gsize initialized = 0; - pthread_mutex_lock(&mutex); if (initialized == 0) { ++initialized; - sample_rate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 4096, NULL, 0); - espeak_SetSynthCallback(read_cb); - voices = espeak_ListVoices(NULL); + espeak_sample_rate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 4096, + NULL, 0); + espeak_SetSynthCallback(synth_cb); + espeak_voices = espeak_ListVoices(NULL); + spin_init(synth); } - pthread_mutex_unlock(&mutex); } -struct Espeak* +Espeak* espeak_new() { init(); - if (sample_rate == EE_INTERNAL_ERROR) - return NULL; + Espeak *self = g_new0(Espeak, 1); + self->context = spin_new(self); + self->pitch = ESPEAK_DEFAULT_PITCH; + self->rate = ESPEAK_DEFAULT_RATE; + self->voice = ESPEAK_DEFAULT_VOICE; - struct Espeak *es = g_new(struct Espeak, 1); - es->buffer = g_memory_output_stream_new(NULL, 0, realloc, free); + return self; +} - return es; +void +espeak_unref(Espeak *self) +{ + spin_unref(self->context); + memset(self, 0, sizeof(Espeak)); + g_free(self); } gint -espeak_sample_rate() +espeak_get_sample_rate() { - return sample_rate; + return espeak_sample_rate; } gchar** -espeak_voices() +espeak_get_voices() { gsize count = 0; const espeak_VOICE **i; @@ -89,52 +121,40 @@ espeak_voices() init(); - for (i = voices; *i; ++i) ++count; + for (i = espeak_voices; *i; ++i) ++count; out = j = g_new0(gchar*, count); - for (i = voices; *i; ++i) + for (i = espeak_voices; *i; ++i) *j++ = g_strconcat((*i)->name, ":", (*i)->languages+1, NULL); return out; } -gboolean -espeak_say(struct Espeak *es, const gchar *text, const gchar *voice, - guint pitch, guint rate) +void +espeak_set_pitch(Espeak *self, guint value) { - g_seekable_seek(G_SEEKABLE(es->buffer), 0, G_SEEK_SET, NULL, NULL); - - pthread_mutex_lock(&mutex); - buffer = es->buffer; - espeak_SetParameter(espeakPITCH, pitch, 0); - espeak_SetParameter(espeakRATE, rate, 0); - espeak_SetVoiceByName(voice); - gint status = espeak_Synth(text, strlen(text)+1, 0, POS_WORD, 0, - espeakCHARS_AUTO, NULL, NULL); - buffer = NULL; - pthread_mutex_unlock(&mutex); - - if (status != EE_OK) - return FALSE; - - return TRUE; + self->pitch = value; } -gpointer -espeak_hear(struct Espeak *es, goffset offset, guint *size) +void +espeak_set_rate(Espeak *self, guint value) { - GMemoryOutputStream *mb = (GMemoryOutputStream*)es->buffer; - - gpointer out = g_memory_output_stream_get_data(mb) + offset; - *size = MIN(g_memory_output_stream_get_data_size(mb) - offset, *size); + self->rate = value; +} - return out; +void +espeak_set_voice(Espeak *self, const gchar *value) +{ + self->voice = value; } void -espeak_unref(struct Espeak *es) +espeak_say(Espeak *self, const gchar *text) +{ + spin_in(self->context, text); +} + +gpointer +espeak_hear(Espeak *self, gsize size) { - g_output_stream_close(es->buffer, NULL, NULL); - g_object_unref(es->buffer); - es->buffer = 0; - g_free(es); + return spin_out(self->context, &size); } |