freeswitch/src/mod/asr_tts/mod_flite/mod_flite.c

202 lines
5.4 KiB
C

/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
*
* 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 <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Brian West <brian@freeswitch.org>
*
* mod_flite.c -- Flite Interface
*
*/
#include <switch.h>
#include <flite.h>
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:
*/