提交 b8457503 authored 作者: Anthony Minessale's avatar Anthony Minessale

add transparent speech handle caching via cache_speech_handles=true variable and…

add transparent speech handle caching via cache_speech_handles=true variable and an app to clear a cached handle called clear_speech_cache

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5876 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 be921bed
...@@ -313,7 +313,7 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t ...@@ -313,7 +313,7 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t
SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session, SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session,
switch_speech_handle_t *sh, switch_speech_handle_t *sh,
switch_codec_t *codec, switch_timer_t *timer, char *text, switch_input_args_t *args); switch_codec_t *codec, switch_timer_t *timer, char *text, switch_input_args_t *args);
SWITCH_DECLARE(void) switch_ivr_clear_speech_cache(switch_core_session_t *session);
/*! /*!
\brief Speak given text with given tts engine \brief Speak given text with given tts engine
\param session the session to speak on \param session the session to speak on
......
...@@ -97,6 +97,8 @@ SWITCH_BEGIN_EXTERN_C ...@@ -97,6 +97,8 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_PATH_SEPARATOR "/" #define SWITCH_PATH_SEPARATOR "/"
#endif #endif
#define SWITCH_URL_SEPARATOR "://" #define SWITCH_URL_SEPARATOR "://"
#define SWITCH_CACHE_SPEECH_HANDLES_VARIABLE "cache_speech_handles"
#define SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME "__cache_speech_handles_obj__"
#define SWITCH_BYPASS_MEDIA_VARIABLE "bypass_media" #define SWITCH_BYPASS_MEDIA_VARIABLE "bypass_media"
#define SWITCH_ENDPOINT_DISPOSITION_VARIABLE "endpoint_disposition" #define SWITCH_ENDPOINT_DISPOSITION_VARIABLE "endpoint_disposition"
#define SWITCH_HOLD_MUSIC_VARIABLE "hold_music" #define SWITCH_HOLD_MUSIC_VARIABLE "hold_music"
......
...@@ -917,6 +917,10 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit ...@@ -917,6 +917,10 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
SWITCH_STANDARD_APP(clear_speech_cache_function)
{
switch_ivr_clear_speech_cache(session);
}
SWITCH_STANDARD_APP(speak_function) SWITCH_STANDARD_APP(speak_function)
{ {
...@@ -940,9 +944,24 @@ SWITCH_STANDARD_APP(speak_function) ...@@ -940,9 +944,24 @@ SWITCH_STANDARD_APP(speak_function)
mydata = switch_core_session_strdup(session, data); mydata = switch_core_session_strdup(session, data);
argc = switch_separate_string(mydata, '|', argv, sizeof(argv) / sizeof(argv[0])); argc = switch_separate_string(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
if (argc == 1) {
text = argv[0];
} else if (argc == 2) {
voice = argv[0];
text = argv[1];
} else {
engine = argv[0]; engine = argv[0];
voice = argv[1]; voice = argv[1];
text = argv[2]; text = argv[2];
}
if (!engine) {
engine = switch_channel_get_variable(channel, "tts_engine");
}
if (!voice) {
voice = switch_channel_get_variable(channel, "tts_voice");
}
if (!(engine && voice && text)) { if (!(engine && voice && text)) {
if (!engine) { if (!engine) {
...@@ -1322,6 +1341,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) ...@@ -1322,6 +1341,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "stop_displace_session", "Stop Displace File", "Stop Displacing to a file", stop_displace_session_function, "<path>", SAF_NONE); SWITCH_ADD_APP(app_interface, "stop_displace_session", "Stop Displace File", "Stop Displacing to a file", stop_displace_session_function, "<path>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "displace_session", "Displace File", DISPLACE_DESC, displace_session_function, "<path> [+time_limit_ms] [mux]", SAF_NONE); SWITCH_ADD_APP(app_interface, "displace_session", "Displace File", DISPLACE_DESC, displace_session_function, "<path> [+time_limit_ms] [mux]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "speak", "Speak text", SPEAK_DESC, speak_function, "<engine>|<voice>|<text>", SAF_NONE); SWITCH_ADD_APP(app_interface, "speak", "Speak text", SPEAK_DESC, speak_function, "<engine>|<voice>|<text>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "clear_speech_cache", "Clear Speech Handle Cache", "Clear Speech Handle Cache", clear_speech_cache_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "bridge", "Bridge Audio", "Bridge the audio between two sessions", audio_bridge_function, "<channel_url>", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "bridge", "Bridge Audio", "Bridge the audio between two sessions", audio_bridge_function, "<channel_url>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "system", "Execute a system command", "Execute a system command", system_session_function, "<command>", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "system", "Execute a system command", "Execute a system command", system_session_function, "<command>", SAF_SUPPORT_NOMEDIA);
......
...@@ -659,7 +659,7 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t * ...@@ -659,7 +659,7 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
switch_core_media_bug_remove_all(*session); switch_core_media_bug_remove_all(*session);
switch_buffer_destroy(&(*session)->raw_read_buffer); switch_buffer_destroy(&(*session)->raw_read_buffer);
switch_buffer_destroy(&(*session)->raw_write_buffer); switch_buffer_destroy(&(*session)->raw_write_buffer);
switch_ivr_clear_speech_cache(*session);
switch_channel_uninit((*session)->channel); switch_channel_uninit((*session)->channel);
pool = (*session)->pool; pool = (*session)->pool;
......
...@@ -1367,6 +1367,36 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session ...@@ -1367,6 +1367,36 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
} }
struct cached_speech_handle {
char tts_name[80];
char voice_name[80];
switch_speech_handle_t sh;
switch_codec_t codec;
switch_timer_t timer;
};
typedef struct cached_speech_handle cached_speech_handle_t;
SWITCH_DECLARE(void) switch_ivr_clear_speech_cache(switch_core_session_t *session)
{
cached_speech_handle_t *cache_obj = NULL;
switch_channel_t *channel;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
if ((cache_obj = switch_channel_get_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME))) {
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
if (cache_obj->timer.interval) {
switch_core_timer_destroy(&cache_obj->timer);
}
switch_core_speech_close(&cache_obj->sh, &flags);
switch_core_codec_destroy(&cache_obj->codec);
switch_channel_set_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME, NULL);
}
}
SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *session, SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *session,
char *tts_name, char *voice_name, char *text, switch_input_args_t *args) char *tts_name, char *voice_name, char *text, switch_input_args_t *args)
{ {
...@@ -1374,21 +1404,50 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses ...@@ -1374,21 +1404,50 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
uint32_t rate = 0; uint32_t rate = 0;
int interval = 0; int interval = 0;
switch_frame_t write_frame = { 0 }; switch_frame_t write_frame = { 0 };
switch_timer_t timer; switch_timer_t ltimer, *timer;
switch_core_thread_session_t thread_session; switch_core_thread_session_t thread_session;
switch_codec_t codec; switch_codec_t lcodec, *codec;
switch_memory_pool_t *pool = switch_core_session_get_pool(session); switch_memory_pool_t *pool = switch_core_session_get_pool(session);
char *codec_name; char *codec_name;
int stream_id = 0; int stream_id = 0;
switch_status_t status = SWITCH_STATUS_SUCCESS; switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_speech_handle_t sh; switch_speech_handle_t lsh, *sh;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE; switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
switch_codec_t *read_codec; switch_codec_t *read_codec;
char *timer_name; char *timer_name, *var;
cached_speech_handle_t *cache_obj = NULL;
int need_create = 1, need_alloc = 1;
channel = switch_core_session_get_channel(session); channel = switch_core_session_get_channel(session);
assert(channel != NULL); assert(channel != NULL);
sh = &lsh;
codec = &lcodec;
timer = &ltimer;
if ((var = switch_channel_get_variable(channel, SWITCH_CACHE_SPEECH_HANDLES_VARIABLE)) && switch_true(var)) {
if ((cache_obj = switch_channel_get_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME))) {
need_create = 0;
if (!strcasecmp(cache_obj->tts_name, tts_name)) {
need_alloc = 0;
} else {
switch_ivr_clear_speech_cache(session);
}
}
if (!cache_obj) {
cache_obj = switch_core_session_alloc(session, sizeof(*cache_obj));
}
if (need_alloc) {
switch_copy_string(cache_obj->tts_name, tts_name, sizeof(cache_obj->tts_name));
switch_copy_string(cache_obj->voice_name, voice_name, sizeof(cache_obj->voice_name));
switch_channel_set_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME, cache_obj);
}
sh = &cache_obj->sh;
codec = &cache_obj->codec;
timer = &cache_obj->timer;
}
timer_name = switch_channel_get_variable(channel, "timer_name"); timer_name = switch_channel_get_variable(channel, "timer_name");
switch_core_session_reset(session); switch_core_session_reset(session);
...@@ -1397,13 +1456,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses ...@@ -1397,13 +1456,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
rate = read_codec->implementation->samples_per_second; rate = read_codec->implementation->samples_per_second;
interval = read_codec->implementation->microseconds_per_frame / 1000; interval = read_codec->implementation->microseconds_per_frame / 1000;
memset(&sh, 0, sizeof(sh)); if (need_create) {
if (switch_core_speech_open(&sh, tts_name, voice_name, (uint32_t) rate, interval, memset(sh, 0, sizeof(*sh));
if (switch_core_speech_open(sh, tts_name, voice_name, (uint32_t) rate, interval,
&flags, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { &flags, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module!\n");
switch_core_session_reset(session); switch_core_session_reset(session);
if (cache_obj) {
switch_channel_set_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME, NULL);
}
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
} else if (cache_obj && strcasecmp(cache_obj->voice_name, voice_name)) {
switch_copy_string(cache_obj->voice_name, voice_name, sizeof(cache_obj->voice_name));
switch_core_speech_text_param_tts(sh, "voice", voice_name);
}
switch_channel_answer(channel); switch_channel_answer(channel);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name);
...@@ -1411,46 +1478,60 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses ...@@ -1411,46 +1478,60 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
codec_name = "L16"; codec_name = "L16";
if (switch_core_codec_init(&codec, if (need_create) {
if (switch_core_codec_init(codec,
codec_name, codec_name,
NULL, (int) rate, interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) { NULL, (int) rate, interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activated\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activated\n");
write_frame.codec = &codec;
} else { } else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activation Failed %s@%uhz 1 channel %dms\n", codec_name, rate, interval); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activation Failed %s@%uhz 1 channel %dms\n", codec_name, rate, interval);
flags = 0; flags = 0;
switch_core_speech_close(&sh, &flags); switch_core_speech_close(sh, &flags);
switch_core_session_reset(session); switch_core_session_reset(session);
if (cache_obj) {
switch_channel_set_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME, NULL);
}
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
}
write_frame.codec = codec;
if (timer_name) { if (timer_name) {
if (switch_core_timer_init(&timer, timer_name, interval, (int) sh.samples, pool) != SWITCH_STATUS_SUCCESS) { if (need_create) {
if (switch_core_timer_init(timer, timer_name, interval, (int) sh->samples, pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
switch_core_codec_destroy(write_frame.codec); switch_core_codec_destroy(write_frame.codec);
flags = 0; flags = 0;
switch_core_speech_close(&sh, &flags); switch_core_speech_close(sh, &flags);
switch_core_session_reset(session); switch_core_session_reset(session);
if (cache_obj) {
switch_channel_set_private(channel, SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME, NULL);
}
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
} }
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "setup timer success %u bytes per %d ms!\n", sh.samples * 2, interval); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "setup timer success %u bytes per %d ms!\n", sh->samples * 2, interval);
}
/* start a thread to absorb incoming audio */ /* start a thread to absorb incoming audio */
for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) { for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
switch_core_service_session(session, &thread_session, stream_id); switch_core_service_session(session, &thread_session, stream_id);
} }
} }
status = switch_ivr_speak_text_handle(session, &sh, write_frame.codec, timer_name ? &timer : NULL, text, args); status = switch_ivr_speak_text_handle(session, sh, write_frame.codec, timer_name ? timer : NULL, text, args);
flags = 0; flags = 0;
switch_core_speech_close(&sh, &flags);
switch_core_codec_destroy(&codec); if (!cache_obj) {
switch_core_speech_close(sh, &flags);
switch_core_codec_destroy(codec);
}
if (timer_name) { if (timer_name) {
/* End the audio absorbing thread */ /* End the audio absorbing thread */
switch_core_thread_session_end(&thread_session); switch_core_thread_session_end(&thread_session);
switch_core_timer_destroy(&timer); if (!cache_obj) {
switch_core_timer_destroy(timer);
}
} }
switch_core_session_reset(session); switch_core_session_reset(session);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论