diff --git a/src/mod/asr_tts/mod_flite/Makefile b/src/mod/asr_tts/mod_flite/Makefile new file mode 100644 index 0000000000..0a75105eae --- /dev/null +++ b/src/mod/asr_tts/mod_flite/Makefile @@ -0,0 +1,5 @@ +LOCAL_CFLAGS=-I/usr/local/include +LOCAL_LDFLAGS=-L/usr/local/lib -lflite_cmu_us_kal -lflite_cmu_us_kal16 -lflite_usenglish -lflite_cmulex -lflite -lm + +BASE=../../../.. +include $(BASE)/build/modmake.rules diff --git a/src/mod/asr_tts/mod_flite/mod_flite.c b/src/mod/asr_tts/mod_flite/mod_flite.c new file mode 100644 index 0000000000..a9eca6346a --- /dev/null +++ b/src/mod/asr_tts/mod_flite/mod_flite.c @@ -0,0 +1,206 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005/2006, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Brian West + * + * + * mod_flite.c -- Flite Interface + * + * + */ + +#include +#include + +cst_voice *register_cmu_us_kal(void); +void unregister_cmu_us_kal(cst_voice * v); + +cst_voice *register_cmu_us_kal16(void); +void unregister_cmu_us_kal16(cst_voice * v); + +SWITCH_MODULE_LOAD_FUNCTION(mod_flite_load); +SWITCH_MODULE_DEFINITION(mod_flite, mod_flite_load, NULL, NULL); +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_flite_shutdown); + +static struct { + cst_voice *v8; + cst_voice *v16; +} globals; + + +struct flite_data { + cst_voice *v; + cst_wave *w; + switch_buffer_t *audio_buffer; +}; +typedef struct flite_data flite_t; + +#define free_wave(w) if (w) {delete_wave(w) ; w = NULL; } +#define FLITE_BLOCK_SIZE 1024 * 32 + +static switch_status_t flite_speech_open(switch_speech_handle_t *sh, const char *voice_name, int rate, switch_speech_flag_t *flags) +{ + + flite_t *flite = switch_core_alloc(sh->memory_pool, sizeof(*flite)); + + if (rate == 8000) { + flite->v = globals.v8; + } else if (rate == 16000) { + flite->v = globals.v16; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid rate %d. Only 8000 and 16000 are supported.\n", rate); + } + + if (flite->v) { + sh->private_info = flite; + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + +static switch_status_t flite_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags) +{ + flite_t *flite = (flite_t *) sh->private_info; + + if (flite->audio_buffer) { + switch_buffer_destroy(&flite->audio_buffer); + } + + free_wave(flite->w); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t flite_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags) +{ + + flite_t *flite = (flite_t *) sh->private_info; + + flite->w = flite_text_to_wave(text, flite->v); + + return SWITCH_STATUS_SUCCESS; +} + +static void flite_speech_flush_tts(switch_speech_handle_t *sh) +{ + flite_t *flite = (flite_t *) sh->private_info; + + if (flite->audio_buffer) { + switch_buffer_zero(flite->audio_buffer); + } + free_wave(flite->w); +} + +static switch_status_t flite_speech_read_tts(switch_speech_handle_t *sh, void *data, size_t *datalen, uint32_t *rate, switch_speech_flag_t *flags) +{ + size_t bytes_read; + flite_t *flite = (flite_t *) sh->private_info; + + if (!flite->audio_buffer) { + int32_t len; + + if (flite->w) { + len = flite->w->num_samples * 2; + } else { + len = FLITE_BLOCK_SIZE; + } + + switch_buffer_create_dynamic(&flite->audio_buffer, FLITE_BLOCK_SIZE, len, 0); + switch_assert(flite->audio_buffer); + } + + if (flite->w) { + switch_buffer_write(flite->audio_buffer, flite->w->samples, flite->w->num_samples * 2); + free_wave(flite->w); + } + + if ((bytes_read = switch_buffer_read(flite->audio_buffer, data, *datalen))) { + *datalen = bytes_read; + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + +static void flite_text_param_tts(switch_speech_handle_t *sh, char *param, const char *val) +{ + +} + +static void flite_numeric_param_tts(switch_speech_handle_t *sh, char *param, int val) +{ + +} + +static void flite_float_param_tts(switch_speech_handle_t *sh, char *param, double val) +{ + +} + +SWITCH_MODULE_LOAD_FUNCTION(mod_flite_load) +{ + switch_speech_interface_t *speech_interface; + + flite_init(); + globals.v8 = register_cmu_us_kal(); + globals.v16 = register_cmu_us_kal16(); + + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + speech_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_SPEECH_INTERFACE); + speech_interface->interface_name = "flite"; + speech_interface->speech_open = flite_speech_open; + speech_interface->speech_close = flite_speech_close; + speech_interface->speech_feed_tts = flite_speech_feed_tts; + speech_interface->speech_read_tts = flite_speech_read_tts; + speech_interface->speech_flush_tts = flite_speech_flush_tts; + speech_interface->speech_text_param_tts = flite_text_param_tts; + speech_interface->speech_numeric_param_tts = flite_numeric_param_tts; + speech_interface->speech_float_param_tts = flite_float_param_tts; + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_flite_shutdown) +{ + unregister_cmu_us_kal(globals.v8); + unregister_cmu_us_kal(globals.v16); + + return SWITCH_STATUS_UNLOAD; +} + + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab: + */