#include <swift.h>
#include <switch.h>
+#define MY_BUF_LEN 1024 * 512
+
static const char modname[] = "mod_cepstral";
static swift_engine *engine;
cepstral_t *cepstral;
swift_event_t rv = SWIFT_SUCCESS;
void *buf = NULL;
- int len = 0;
+ int len = 0, i = 0;
cepstral = udata;
assert(cepstral != NULL);
+ if (!cepstral->port || cepstral->done || cepstral->done_gen) {
+ return SWIFT_UNKNOWN_ERROR;
+ }
+
/* Only proceed when we have success */
if (!SWIFT_FAILED((rv = swift_event_get_audio(event, &buf, &len)))) {
- switch_mutex_lock(cepstral->audio_lock);
-
- if (switch_buffer_write(cepstral->audio_buffer, buf, len) <= 0) {
- rv = SWIFT_UNKNOWN_ERROR;
+ while(!cepstral->done) {
+ switch_mutex_lock(cepstral->audio_lock);
+ if (switch_buffer_write(cepstral->audio_buffer, buf, len) > 0) {
+ switch_mutex_unlock(cepstral->audio_lock);
+ break;
+ }
+ switch_mutex_unlock(cepstral->audio_lock);
+ if (!cepstral->done) {
+ for (i = 0; i < 10; i++) {
+ switch_yield(10000);
+ if (cepstral->done) {
+ break;
+ }
+ }
+ }
+
}
- switch_mutex_unlock(cepstral->audio_lock);
} else {
cepstral->done = 1;
}
+ if (cepstral->done) {
+ rv = SWIFT_UNKNOWN_ERROR;
+ }
+
return rv;
}
return SWITCH_STATUS_MEMERR;
}
- if (switch_buffer_create(sh->memory_pool, &cepstral->audio_buffer, 1024 * 256) != SWITCH_STATUS_SUCCESS) {
+ if (switch_buffer_create(sh->memory_pool, &cepstral->audio_buffer, MY_BUF_LEN) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Write Buffer Failed!\n");
return SWITCH_STATUS_MEMERR;
}
cepstral = sh->private_info;
assert(cepstral != NULL);
+
+ cepstral->done = 1;
+ cepstral->done_gen = 1;
+ printf("CLOSE!!!\n");
+ swift_port_stop(cepstral->port, SWIFT_ASYNC_ANY, SWIFT_EVENT_NOW);
/* Close the Swift Port and Engine */
if (NULL != cepstral->port) swift_port_close(cepstral->port);
//if (NULL != cepstral->engine) swift_engine_close(cepstral->engine);
cepstral = sh->private_info;
assert(cepstral != NULL);
+ cepstral->done_gen = 0;
+ cepstral->done = 0;
+
+ cepstral->tts_stream = NULL;
+
swift_port_speak_text(cepstral->port, text, 0, NULL, &cepstral->tts_stream, NULL);
- //swift_port_speak_text(cepstral->port, text, 0, NULL, NULL, NULL);
-
return SWITCH_STATUS_FALSE;
}
+static void cepstral_speech_flush_tts(switch_speech_handle_t *sh)
+{
+ cepstral_t *cepstral;
+
+ cepstral = sh->private_info;
+ assert(cepstral != NULL);
+
+ cepstral->done_gen = 1;
+ cepstral->done = 1;
+ if (cepstral->audio_buffer) {
+ switch_mutex_lock(cepstral->audio_lock);
+ switch_buffer_zero(cepstral->audio_buffer);
+ switch_mutex_unlock(cepstral->audio_lock);
+ }
+ swift_port_stop(cepstral->port, SWIFT_ASYNC_ANY, SWIFT_EVENT_NOW);
+}
+
static switch_status_t cepstral_speech_read_tts(switch_speech_handle_t *sh,
void *data,
size_t *datalen,
while(!cepstral->done) {
if (!cepstral->done_gen) {
- int check = (SWIFT_STATUS_RUNNING == swift_port_status(cepstral->port, cepstral->tts_stream));
- if (!check) {
+ int check = swift_port_status(cepstral->port, cepstral->tts_stream);
+
+ if (!check == SWIFT_STATUS_RUNNING) {
cepstral->done_gen = 1;
}
}
+ switch_mutex_lock(cepstral->audio_lock);
used = switch_buffer_inuse(cepstral->audio_buffer);
-
+ switch_mutex_unlock(cepstral->audio_lock);
+
+
if (!used && cepstral->done_gen) {
+
+ status = SWITCH_STATUS_BREAK;
break;
}
-
/* wait for the right amount of data (unless there is no blocking flag) */
if (used < desired) {
/*.speech_feed_asr*/ NULL,
/*.speech_interpret_asr*/ NULL,
/*.speech_feed_tts*/ cepstral_speech_feed_tts,
- /*.speech_read_tts*/ cepstral_speech_read_tts
-
+ /*.speech_read_tts*/ cepstral_speech_read_tts,
+ /*.speech_flush_tts*/ cepstral_speech_flush_tts
};
static const switch_loadable_module_interface_t cepstral_module_interface = {
-SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *session,
- char *tts_name,
- char *voice_name,
- char *timer_name,
- uint32_t rate,
- switch_dtmf_callback_function_t dtmf_callback,
- char *text,
- void *buf,
- unsigned int buflen)
+SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session,
+ switch_speech_handle_t *sh,
+ switch_codec_t *codec,
+ switch_timer_t *timer,
+ switch_dtmf_callback_function_t dtmf_callback,
+ char *text,
+ void *buf,
+ unsigned int buflen)
{
switch_channel_t *channel;
short abuf[960];
char dtmf[128];
- int interval = 0;
- uint32_t samples = 0;
uint32_t len = 0;
switch_size_t ilen = 0;
switch_frame_t write_frame = {0};
- switch_timer_t timer;
- switch_core_thread_session_t thread_session;
- switch_codec_t codec;
- switch_memory_pool_t *pool = switch_core_session_get_pool(session);
- char *codec_name;
int x;
int stream_id;
int done = 0;
int lead_in_out = 10;
-
switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_speech_handle_t sh;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
-
-
- memset(&sh, 0, sizeof(sh));
+ uint32_t rate = 0, samples = 0;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
- if (switch_core_speech_open(&sh,
- tts_name,
- voice_name,
- (unsigned int)rate,
- &flags,
- switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module!\n");
- switch_core_session_reset(session);
+ if (!sh) {
return SWITCH_STATUS_FALSE;
}
-
+
switch_channel_answer(channel);
write_frame.data = abuf;
write_frame.buflen = sizeof(abuf);
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name);
-
- interval = 20;
- samples = (uint32_t)(rate / 50);
- len = samples * 2;
-
- codec_name = "L16";
-
- if (switch_core_codec_init(&codec,
- codec_name,
- (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");
- write_frame.codec = &codec;
- } else {
- 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;
- switch_core_speech_close(&sh, &flags);
- switch_core_session_reset(session);
- return SWITCH_STATUS_GENERR;
- }
-
- if (timer_name) {
- if (switch_core_timer_init(&timer, timer_name, interval, (int)samples, pool) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
- switch_core_codec_destroy(&codec);
- flags = 0;
- switch_core_speech_close(&sh, &flags);
- switch_core_session_reset(session);
- return SWITCH_STATUS_GENERR;
- }
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "setup timer success %u bytes per %d ms!\n", len, interval);
- }
+ samples = (uint32_t)(sh->rate / 50);
+ len = samples * 2;
flags = 0;
- switch_core_speech_feed_tts(&sh, text, &flags);
- write_frame.rate = rate;
+ switch_core_speech_feed_tts(sh, text, &flags);
+ write_frame.rate = sh->rate;
memset(write_frame.data, 0, len);
write_frame.datalen = len;
write_frame.samples = len / 2;
-
+ write_frame.codec = codec;
+
for( x = 0; !done && x < lead_in_out; x++) {
for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) {
}
}
- if (timer_name) {
- /* start a thread to absorb incoming audio */
- for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) {
- switch_core_service_session(session, &thread_session, stream_id);
- }
- }
-
ilen = len;
while(switch_channel_ready(channel)) {
- if (dtmf_callback || buf) {
-
-
- /*
- dtmf handler function you can hook up to be executed when a digit is dialed during playback
- if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
- */
- if (switch_channel_has_dtmf(channel)) {
- switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
- if (dtmf_callback) {
- status = dtmf_callback(session, dtmf, buf, buflen);
- } else {
- switch_copy_string((char *)buf, dtmf, buflen);
- status = SWITCH_STATUS_BREAK;
- }
- }
-
- if (status != SWITCH_STATUS_SUCCESS) {
- done = 1;
- break;
- }
- }
-
flags = SWITCH_SPEECH_FLAG_BLOCKING;
- status = switch_core_speech_read_tts(&sh,
+ status = switch_core_speech_read_tts(sh,
abuf,
&ilen,
&rate,
}
}
}
+ if (status == SWITCH_STATUS_BREAK) {
+ status = SWITCH_STATUS_SUCCESS;
+ }
done = 1;
}
- if (done || ilen <= 0) {
+ if (done) {
break;
}
break;
}
}
- if (timer_name) {
- if ((x = switch_core_timer_next(&timer)) < 0) {
+
+ if (dtmf_callback || buf) {
+ /*
+ dtmf handler function you can hook up to be executed when a digit is dialed during playback
+ if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
+ */
+ if (switch_channel_has_dtmf(channel)) {
+ switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+ if (dtmf_callback) {
+ status = dtmf_callback(session, dtmf, buf, buflen);
+ } else {
+ switch_copy_string((char *)buf, dtmf, buflen);
+ status = SWITCH_STATUS_BREAK;
+ }
+ }
+
+ if (status != SWITCH_STATUS_SUCCESS) {
+ done = 1;
+ break;
+ }
+ }
+
+ if (timer) {
+ if ((x = switch_core_timer_next(timer)) < 0) {
break;
}
} else { /* time off the channel (if you must) */
break;
}
}
- }
+ }
+
+
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done speaking text\n");
flags = 0;
+ switch_core_speech_flush_tts(sh);
+ return status;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *session,
+ char *tts_name,
+ char *voice_name,
+ char *timer_name,
+ uint32_t rate,
+ switch_dtmf_callback_function_t dtmf_callback,
+ char *text,
+ void *buf,
+ unsigned int buflen)
+{
+ switch_channel_t *channel;
+ int interval = 0;
+ uint32_t samples = 0;
+ uint32_t len = 0;
+ switch_frame_t write_frame = {0};
+ switch_timer_t timer;
+ switch_core_thread_session_t thread_session;
+ switch_codec_t codec;
+ switch_memory_pool_t *pool = switch_core_session_get_pool(session);
+ char *codec_name;
+ int stream_id;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_speech_handle_t sh;
+ switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
+
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+
+ memset(&sh, 0, sizeof(sh));
+ if (switch_core_speech_open(&sh,
+ tts_name,
+ voice_name,
+ (unsigned int)rate,
+ &flags,
+ switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module!\n");
+ switch_core_session_reset(session);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ switch_channel_answer(channel);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name);
+
+ interval = 20;
+ samples = (uint32_t)(rate / 50);
+ len = samples * 2;
+
+ codec_name = "L16";
+
+ if (switch_core_codec_init(&codec,
+ codec_name,
+ (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");
+ write_frame.codec = &codec;
+ } else {
+ 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;
+ switch_core_speech_close(&sh, &flags);
+ switch_core_session_reset(session);
+ return SWITCH_STATUS_GENERR;
+ }
+
+ if (timer_name) {
+ if (switch_core_timer_init(&timer, timer_name, interval, (int)samples, pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
+ switch_core_codec_destroy(&codec);
+ flags = 0;
+ switch_core_speech_close(&sh, &flags);
+
+ switch_core_session_reset(session);
+ return SWITCH_STATUS_GENERR;
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "setup timer success %u bytes per %d ms!\n", len, interval);
+
+ /* start a thread to absorb incoming audio */
+ 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_ivr_speak_text_handle(session, &sh, &codec, timer_name ? &timer : NULL, dtmf_callback, text, buf, buflen);
+ flags = 0;
switch_core_speech_close(&sh, &flags);
switch_core_codec_destroy(&codec);