Finalization of speech detect interface and API

This changes the core to have the necessary tools to create
a speech detection interface.

It also changes the code in javascript (mod_spidermonkey)
there are a few api changes in how it handles callbacks

It also adds grammars as a system dir to store asr grammars




git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3291 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2006-11-09 05:39:04 +00:00
parent b942d8e044
commit 44fc26f7d4
20 changed files with 1996 additions and 540 deletions

View File

@ -0,0 +1,433 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
*
* 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 <anthmct@yahoo.com>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
*
*
* SpeechTools.jm Speech Detection Interface
*
*/
/* Constructor for Grammar Class (Class to identify a grammar entity) */
function Grammar(grammar_name, path, obj_path, min_score, confirm_score, halt) {
this.grammar_name = grammar_name;
this.path = path;
this.min_score = min_score;
this.confirm_score = confirm_score;
this.halt = halt;
this.obj_path = obj_path;
if (!this.min_score) {
this.min_score = 1;
}
if (!this.confirm_score) {
this.confirm_score = 400;
}
}
/* Constructor for SpeechDetect Class (Class to Detect Speech) */
function SpeechDetect(session, mod, ip) {
this.ip = ip;
this.session = session;
this.mod = mod;
this.grammar_name = undefined;
this.grammar_hash = new Array();
this.grammar_name = false;
this.audio_base = "";
this.audio_ext = ".wav";
this.tts_eng = false;
this.tts_voice = false;
this.AutoUnload = false;
this.debug = false;
/* Set the TTS info*/
this.setTTS = function (tts_eng, tts_voice) {
this.tts_eng = tts_eng;
this.tts_voice = tts_voice;
}
/* Set the audio base */
this.setAudioBase = function (audio_base) {
this.audio_base = audio_base;
}
/* Set the audio extension */
this.setAudioExt= function (audio_ext) {
this.audio_ext = audio_ext;
}
/* Add a grammar to be used*/
this.addGrammar = function(grammar_object) {
this.grammar_hash[grammar_object.grammar_name] = grammar_object;
}
/* Play an audio file */
this.streamFile = function(str) {
var rv;
if (!str) {
console_log("error", "No file specified!\n");
return;
}
files = str.split(",");
for( x = 0; x < files.length; x++) {
if (!files[x] || files[x] == "noop") {
continue;
}
this.session.streamFile(this.audio_base + files[x] + this.audio_ext);
}
}
/* Speak with TTS */
this.speak = function(str) {
return this.session.speak(this.tts_eng, this.tts_voice, str);
}
/* Set the current grammar */
this.setGrammar = function (grammar_name) {
var grammar_object = this.grammar_hash[grammar_name];
if (!grammar_object) {
console_log("error", "Missing Grammar!\n");
return false;
}
if (this.grammar_name) {
if (this.AutoUnload) {
console_log("debug", "Unloading grammar " + this.grammar_name + "\n");
this.session.execute("detect_speech", "nogrammar " + this.grammar_name);
}
if (grammar_object.path) {
this.session.execute("detect_speech", "grammar " + grammar_name + " " + grammar_object.path);
} else {
this.session.execute("detect_speech", "grammar " + grammar_name);
}
} else {
this.session.execute("detect_speech", this.mod + " " + grammar_name + " " + grammar_object.path + " " + this.ip);
}
this.grammar_name = grammar_name;
}
/* Pause speech detection */
this.pause = function() {
this.session.execute("detect_speech", "pause");
}
/* Resume speech detection */
this.resume = function() {
this.session.execute("detect_speech", "resume");
}
/* Stop speech detection */
this.stop = function() {
this.session.execute("detect_speech", "stop");
}
/* Callback function for streaming,TTS or bridged calls */
this.onInput = function(type, inputEvent, _this) {
if (type == "event") {
var speech_type = inputEvent.getHeader("Speech-Type");
var rv = new Array();
if (!_this.grammar_name) {
console_log("error", "No Grammar name!\n");
_this.session.hangup();
return;
}
var grammar_object = _this.grammar_hash[_this.grammar_name];
if (!grammar_object) {
console_log("error", "Can't find grammar for " + _this.grammar_name + "\n");
_this.session.hangup();
return;
}
if (speech_type == "begin-speaking") {
if (grammar_object.halt) {
return;
}
} else {
var body = inputEvent.getBody();
var interp = new XML(body);
_this.lastDetect = body;
if (_this.debug) {
console_log("debug", "----XML:\n" + body);
console_log("debug", "----Heard [" + interp.input + "]\n");
console_log("debug", "----Hit score " + interp.@score + "\n");
}
if (interp.@score < grammar_object.min_score) {
delete interp;
rv.push("_no_idea_");
return rv;
} else {
if (interp.@score < grammar_object.confirm_score) {
rv.push("_confirm_");
}
eval("xo = interp." + grammar_object.obj_path + ";");
for (x = 0; x < xo.length(); x++) {
rv.push(xo[x]);
}
delete interp;
return rv;
}
}
}
}
}
/* Constructor for SpeechObtainer Class (Class to collect data from a SpeechDetect Class) */
function SpeechObtainer(asr, req, wait_time) {
this.items = new Array();
this.collected_items = new Array();
this.index = 0;
this.collected_index = 0;
this.req = req;
this.tts_eng = undefined;
this.tts_voice = false;
this.asr = asr;
this.top_sound = false;
this.add_sound = false;
this.dup_sound = false;
this.bad_sound = false;
this.needConfirm = false;
this.grammar_name = false;
this.audio_base = asr.audio_base;
this.audio_ext = asr.audio_ext;
this.tts_eng = asr.tts_eng;
this.tts_voice = asr.tts_voice;
this.debug = asr.debug;
if (!req) {
req = 1;
}
if (!wait_time) {
wait_time = 5000;
}
this.waitTime = wait_time + 0;
/* Set the TTS info*/
this.setTTS = function (tts_eng, tts_voice) {
this.tts_eng = tts_eng;
this.tts_voice = tts_voice;
}
/* Set the audio base */
this.setAudioBase = function (audio_base) {
this.audio_base = audio_base;
}
/* Set the audio extension */
this.setAudioExt= function (audio_ext) {
this.audio_ext = audio_ext;
}
/* Set the grammar to use */
this.setGrammar = function (grammar_name, path, obj_path, min_score, confirm_score, halt) {
var grammar_object = new Grammar(grammar_name, path, obj_path, min_score, confirm_score, halt);
this.asr.addGrammar(grammar_object);
this.grammar_name = grammar_name;
}
/* Set the top audio file or tts for the collection */
this.setTopSound = function (top_sound) {
this.top_sound = top_sound;
}
/* Set the audio file or tts for misunderstood input */
this.setBadSound = function (bad_sound) {
this.bad_sound = bad_sound;
}
/* Set the audio file or tts for duplicate input */
this.setDupSound = function (dup_sound) {
this.dup_sound = dup_sound;
}
/* Set the audio file or tts for accepted input */
this.setAddSound = function (add_sound) {
this.add_sound = add_sound;
}
/* Add acceptable items (comma sep list)*/
this.addItem = function(item) {
ia = item.split(",");
var x;
for (x = 0; x < ia.length; x++) {
this.items[this.index++] = ia[x];
}
}
/* Add a regex */
this.addRegEx = function(item) {
this.items[this.index++] = item;
}
/* Reset the object and delete all collect items */
this.reset = function() {
this.collected_index = 0;
delete this.collected_items;
this.collected_items = new Array();
}
/* Stream a file, collecting input */
this.streamFile = function(str) {
var rv;
if (!str) {
console_log("error", "No file specified!\n");
return;
}
files = str.split(",");
for( x = 0; x < files.length; x++) {
if (!files[x] || files[x] == "noop") {
continue;
}
rv = this.asr.session.streamFile(this.audio_base + files[x] + this.audio_ext , "", this.asr.onInput, this.asr);
if (rv) {
break;
}
}
return rv;
}
/* Speak some text, collecting input */
this.speak = function(str) {
return this.asr.session.speak(this.tts_eng, this.tts_voice, str, this.asr.onInput, this.asr);
}
/* Process collected input */
this.react = function(say_str, play_str) {
var rv;
this.asr.resume();
if (this.tts_eng && this.tts_voice) {
rv = this.speak(say_str);
} else {
rv = this.streamFile(play_str);
}
if (!rv) {
rv = this.asr.session.collectInput(this.asr.onInput, this.asr, 500);
}
return rv;
}
/* Collect input */
this.run = function() {
var rv;
var hit;
var dup;
if (this.collected_index) {
this.reset();
}
if (!this.grammar_name) {
console_log("error", "No Grammar name!\n");
this.session.hangup();
return false;
}
this.asr.setGrammar(this.grammar_name);
while(this.asr.session.ready() && this.collected_index < this.req) {
var x;
this.needConfirm = false;
if (!rv) {
rv = this.react(this.top_sound, this.top_sound);
}
if (!rv) {
this.asr.resume();
rv = this.asr.session.collectInput(this.asr.onInput, this.asr, this.waitTime);
}
hit = false;
if (rv) {
for (y = 0; y < rv.length; y++) {
if (rv[y] == "_confirm_") {
this.needConfirm = true;
if (this.debug) {
console_log("debug", "----We need to confirm this one\n");
}
continue;
}
for(x = 0 ; x < this.index; x++) {
if (this.debug) {
console_log("debug", "----Testing " + rv[y] + " =~ [" + this.items[x] + "]\n");
}
var re = new RegExp(this.items[x]);
match = re.exec(rv[y]);
if (match) {
for (i = 0; i < match.length; i++) {
dup = false;
for(z = 0; z < this.collected_items.length; z++) {
if (this.collected_items[z] == match[i]) {
dup = true;
break;
}
}
if (dup) {
if (this.dup_sound) {
rv = this.react(this.dup_sound + " " + match[i], this.dup_sound + "," + match[i]);
}
} else {
if (this.debug) {
console_log("debug", "----Adding " + match[i] + "\n");
}
this.collected_items[this.collected_index++] = match[i];
hit = true;
if (this.add_sound) {
rv = this.react(this.add_sound + " " + match[i], this.add_sound + "," + match[i]);
}
}
}
}
}
}
}
if (!rv) {
rv = this.asr.session.collectInput(this.asr.onInput, this.asr, 500);
}
if (!rv && !hit && !dup) {
rv = this.react(this.bad_sound, this.bad_sound);
}
}
return this.collected_items;
}
}

View File

@ -124,5 +124,5 @@
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t

View File

@ -119,14 +119,21 @@ struct switch_core_port_allocator;
\param session the session to add the bug to
\param callback a callback for events
\param user_data arbitrary user data
\param flags flags to choose the stream
\param new_bug pointer to assign new bug to
\return SWITCH_STATUS_SUCCESS if the operation was a success
*/
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session,
switch_media_bug_callback_t callback,
void *user_data,
switch_media_bug_flag_t flags,
switch_media_bug_t **new_bug);
/*!
\brief Obtain private data from a media bug
\param session the session to obtain the private data from
\return the private data
*/
SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *bug);
/*!
\brief Remove a media bug from the session
@ -1060,7 +1067,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh)
\param module_name the speech module to use
\param voice_name the desired voice name
\param rate the sampling rate
\param flags asr/tts flags
\param flags tts flags
\param pool the pool to use (NULL for new pool)
\return SWITCH_STATUS_SUCCESS if the handle is opened
*/
@ -1070,28 +1077,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t *
unsigned int rate,
switch_speech_flag_t *flags,
switch_memory_pool_t *pool);
/*!
\brief Feed data to the ASR module
\param sh the speech handle to feed
\param data the buffer of audio data
\param len the in-use size of the buffer
\param rate the rate of the audio (in hz)
\param flags flags in/out for fine tuning
\return SWITCH_STATUS_SUCCESS with possible new flags on success
*/
SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_asr(switch_speech_handle_t *sh, void *data, unsigned int *len, int rate, switch_speech_flag_t *flags);
/*!
\brief Get text back from the ASR module
\param sh the speech handle to read
\param buf the buffer to insert the text into
\param buflen the max size of the buffer
\param flags flags in/out for fine tuning
\return SWITCH_STATUS_SUCCESS with possible new flags on success
*/
SWITCH_DECLARE(switch_status_t) switch_core_speech_interpret_asr(switch_speech_handle_t *sh, char *buf, unsigned int buflen, switch_speech_flag_t *flags);
/*!
\brief Feed text to the TTS module
\param sh the speech handle to feed
@ -1152,6 +1137,92 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_read_tts(switch_speech_handle
\return SWITCH_STATUS_SUCCESS if the file handle was closed
*/
SWITCH_DECLARE(switch_status_t) switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags);
/*!
\brief Open an asr handle
\param ah the asr handle to open
\param module_name the name of the asr module
\param codec the preferred codec
\param rate the preferred rate
\param dest the destination address
\param flags flags to influence behaviour
\param pool the pool to use (NULL for new pool)
\return SWITCH_STATUS_SUCCESS if the asr handle was opened
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_open(switch_asr_handle_t *ah,
char *module_name,
char *codec,
int rate,
char *dest,
switch_asr_flag_t *flags,
switch_memory_pool_t *pool);
/*!
\brief Close an asr handle
\param ah the handle to close
\param flags flags to influence behaviour
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
/*!
\brief Feed audio data to an asr handle
\param ah the handle to feed data to
\param data a pointer to the data
\param len the size in bytes of the data
\param flags flags to influence behaviour
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags);
/*!
\brief Check an asr handle for results
\param ah the handle to check
\param flags flags to influence behaviour
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
/*!
\brief Get results from an asr handle
\param ah the handle to get results from
\param xmlstr a pointer to dynamically allocate an xml result string to
\param flags flags to influence behaviour
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
/*!
\brief Load a grammar to an asr handle
\param ah the handle to load to
\param grammar the name of the grammar
\param path the path to the grammaar file
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, char *grammar, char *path);
/*!
\brief Unload a grammar from an asr handle
\param ah the handle to unload the grammar from
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, char *grammar);
/*!
\brief Pause detection on an asr handle
\param ah the handle to pause
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_pause(switch_asr_handle_t *ah);
/*!
\brief Resume detection on an asr handle
\param ah the handle to resume
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_resume(switch_asr_handle_t *ah);
///\}

View File

@ -69,12 +69,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session);
\param dtmf_callback code to execute if any dtmf is dialed during the recording
\param buf an object to maintain across calls
\param buflen the size of buf
\param timeout a timeout in milliseconds
\return SWITCH_STATUS_SUCCESS to keep the collection moving.
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session,
switch_input_callback_function_t dtmf_callback,
void *buf,
unsigned int buflen);
switch_input_callback_function_t dtmf_callback,
void *buf,
unsigned int buflen,
unsigned int timeout);
/*!
\brief Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up.
@ -95,6 +97,61 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess
char *terminator,
unsigned int timeout);
/*!
\brief Engage background Speech detection on a session
\param session the session to attach
\param mod_name the module name of the ASR library
\param grammar the grammar name
\param path the path to the grammar file
\param dest the destination address
\param ah an ASR handle to use (NULL to create one)
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session,
char *mod_name,
char *grammar,
char *path,
char *dest,
switch_asr_handle_t *ah);
/*!
\brief Stop background Speech detection on a session
\param session The session to stop detection on
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_stop_detect_speech(switch_core_session_t *session);
/*!
\brief Pause background Speech detection on a session
\param session The session to pause detection on
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_pause_detect_speech(switch_core_session_t *session);
/*!
\brief Resume background Speech detection on a session
\param session The session to resume detection on
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_resume_detect_speech(switch_core_session_t *session);
/*!
\brief Load a grammar on a background speech detection handle
\param session The session to change the grammar on
\param grammar the grammar name
\param path the grammar path
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *path);
/*!
\brief Unload a grammar on a background speech detection handle
\param session The session to change the grammar on
\param grammar the grammar name
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, char *grammar);
/*!
\brief Record a session to disk
\param session the session to record

View File

@ -75,6 +75,8 @@ struct switch_loadable_module_interface {
const switch_directory_interface_t *directory_interface;
/*! the table of chat interfaces the module has implmented */
const switch_chat_interface_t *chat_interface;
/*! the table of asr interfaces the module has implmented */
const switch_asr_interface_t *asr_interface;
};
/*!
@ -158,6 +160,13 @@ SWITCH_DECLARE(switch_file_interface_t *) switch_loadable_module_get_file_interf
*/
SWITCH_DECLARE(switch_speech_interface_t *) switch_loadable_module_get_speech_interface(char *name);
/*!
\brief Retrieve the asr interface by it's registered name
\param name the name of the asr interface
\return the desired asr interface
*/
SWITCH_DECLARE(switch_asr_interface_t *) switch_loadable_module_get_asr_interface(char *name);
/*!
\brief Retrieve the directory interface by it's registered name
\param name the name of the directory interface

View File

@ -315,6 +315,53 @@ struct switch_file_handle {
switch_buffer_t *audio_buffer;
};
/*! \brief Abstract interface to an asr module */
struct switch_asr_interface {
/*! the name of the interface */
const char *interface_name;
/*! function to open the asr interface */
switch_status_t (*asr_open)(switch_asr_handle_t *ah,
char *codec,
int rate,
char *dest,
switch_asr_flag_t *flags);
/*! function to load a grammar to the asr interface */
switch_status_t (*asr_load_grammar)(switch_asr_handle_t *ah, char *grammar, char *path);
/*! function to unload a grammar to the asr interface */
switch_status_t (*asr_unload_grammar)(switch_asr_handle_t *ah, char *grammar);
/*! function to close the asr interface */
switch_status_t (*asr_close)(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
/*! function to feed audio to the ASR*/
switch_status_t (*asr_feed)(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags);
/*! function to resume the ASR*/
switch_status_t (*asr_resume)(switch_asr_handle_t *ah);
/*! function to pause the ASR*/
switch_status_t (*asr_pause)(switch_asr_handle_t *ah);
/*! function to read results from the ASR*/
switch_status_t (*asr_check_results)(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
/*! function to read results from the ASR*/
switch_status_t (*asr_get_results)(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
const struct switch_asr_interface *next;
};
/*! an abstract representation of an asr speech interface. */
struct switch_asr_handle {
/*! the interface of the module that implemented the current speech interface */
const switch_asr_interface_t *asr_interface;
/*! flags to control behaviour */
uint32_t flags;
/*! The Name*/
char *name;
/*! The Codec*/
char *codec;
/*! The Rate*/
uint32_t rate;
char *grammar;
/*! the handle's memory pool */
switch_memory_pool_t *memory_pool;
/*! private data for the format module to store handle specific info */
void *private_info;
};
/*! \brief Abstract interface to a speech module */
struct switch_speech_interface {
@ -328,10 +375,6 @@ struct switch_speech_interface {
/*! function to close the speech interface */
switch_status_t (*speech_close)(switch_speech_handle_t *, switch_speech_flag_t *flags);
/*! function to feed audio to the ASR*/
switch_status_t (*speech_feed_asr)(switch_speech_handle_t *sh, void *data, unsigned int *len, int rate, switch_speech_flag_t *flags);
/*! function to read text from the ASR*/
switch_status_t (*speech_interpret_asr)(switch_speech_handle_t *sh, char *buf, unsigned int buflen, switch_speech_flag_t *flags);
/*! function to feed text to the TTS*/
switch_status_t (*speech_feed_tts)(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags);
/*! function to read audio from the TTS*/
switch_status_t (*speech_read_tts)(switch_speech_handle_t *sh,

View File

@ -72,6 +72,10 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_HTDOCS_DIR SWITCH_PREFIX_DIR SWITCH_PATH_SEPARATOR "htdocs"
#endif
#ifndef SWITCH_GRAMMAR_DIR
#define SWITCH_GRAMMAR_DIR SWITCH_PREFIX_DIR SWITCH_PATH_SEPARATOR "grammar"
#endif
#define SWITCH_R_SDP_VARIABLE "_switch_r_sdp_"
#define SWITCH_L_SDP_VARIABLE "_switch_l_sdp_"
#define SWITCH_B_SDP_VARIABLE "_switch_m_sdp_"
@ -82,7 +86,7 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_LOCAL_MEDIA_PORT_VARIABLE "_local_media_port_"
#define SWITCH_REMOTE_MEDIA_IP_VARIABLE "_remote_media_ip_"
#define SWITCH_REMOTE_MEDIA_PORT_VARIABLE "_remote_media_port_"
#define SWITCH_SPEECH_KEY "_speech_"
#define SWITCH_BITS_PER_BYTE 8
typedef uint8_t switch_byte_t;
@ -132,6 +136,7 @@ struct switch_directories {
char *script_dir;
char *temp_dir;
char *htdocs_dir;
char *grammar_dir;
};
typedef struct switch_directories switch_directories;
@ -313,6 +318,7 @@ typedef enum {
SWITCH_STATUS_SOCKERR - A socket error
SWITCH_STATUS_MORE_DATA - Need More Data
SWITCH_STATUS_NOTFOUND - Not Found
SWITCH_STATUS_UNLOAD - Unload
</pre>
*/
typedef enum {
@ -330,7 +336,8 @@ typedef enum {
SWITCH_STATUS_BREAK,
SWITCH_STATUS_SOCKERR,
SWITCH_STATUS_MORE_DATA,
SWITCH_STATUS_NOTFOUND
SWITCH_STATUS_NOTFOUND,
SWITCH_STATUS_UNLOAD
} switch_status_t;
@ -522,26 +529,42 @@ typedef enum {
\enum switch_speech_flag_t
\brief Speech related flags
<pre>
SWITCH_SPEECH_FLAG_TTS = (1 << 0) - Interface can/should convert text to speech.
SWITCH_SPEECH_FLAG_ASR = (1 << 1) - Interface can/should convert audio to text.
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 2) - Interface is has text to read.
SWITCH_SPEECH_FLAG_PEEK = (1 << 3) - Read data but do not erase it.
SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 4) - Free interface's pool on destruction.
SWITCH_SPEECH_FLAG_BLOCKING = (1 << 5) - Indicate that a blocking call is desired
SWITCH_SPEECH_FLAG_PAUSE = (1 << 6) - Pause toggle for playback
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 0) - Interface is has text to read.
SWITCH_SPEECH_FLAG_PEEK = (1 << 1) - Read data but do not erase it.
SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 2) - Free interface's pool on destruction.
SWITCH_SPEECH_FLAG_BLOCKING = (1 << 3) - Indicate that a blocking call is desired
SWITCH_SPEECH_FLAG_PAUSE = (1 << 4) - Pause toggle for playback
</pre>
*/
typedef enum {
SWITCH_SPEECH_FLAG_TTS = (1 << 0),
SWITCH_SPEECH_FLAG_ASR = (1 << 1),
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 2),
SWITCH_SPEECH_FLAG_PEEK = (1 << 3),
SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 4),
SWITCH_SPEECH_FLAG_BLOCKING = (1 << 5),
SWITCH_SPEECH_FLAG_PAUSE = (1 << 6)
SWITCH_SPEECH_FLAG_NONE = 0,
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 0),
SWITCH_SPEECH_FLAG_PEEK = (1 << 1),
SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 2),
SWITCH_SPEECH_FLAG_BLOCKING = (1 << 3),
SWITCH_SPEECH_FLAG_PAUSE = (1 << 4)
} switch_speech_flag_t;
/*!
\enum switch_asr_flag_t
\brief Asr related flags
<pre>
SWITCH_ASR_FLAG_DATA = (1 << 0) - Interface has data
SWITCH_ASR_FLAG_FREE_POOL = (1 << 1) - Pool needs to be freed
SWITCH_ASR_FLAG_CLOSED = (1 << 2) - Interface has been closed
SWITCH_ASR_FLAG_FIRE_EVENTS = (1 << 3) - Fire all speech events
SWITCH_ASR_FLAG_AUTO_RESUME = (1 << 4) - Auto Resume
</pre>
*/
typedef enum {
SWITCH_ASR_FLAG_NONE = 0,
SWITCH_ASR_FLAG_DATA = (1 << 0),
SWITCH_ASR_FLAG_FREE_POOL = (1 << 1),
SWITCH_ASR_FLAG_CLOSED = (1 << 2),
SWITCH_ASR_FLAG_FIRE_EVENTS = (1 << 3),
SWITCH_ASR_FLAG_AUTO_RESUME = (1 << 4)
} switch_asr_flag_t;
/*!
\enum switch_directory_flag_t
@ -584,6 +607,21 @@ typedef enum {
SWITCH_TIMER_FLAG_FREE_POOL = (1 << 0),
} switch_timer_flag_t;
/*!
\enum switch_timer_flag_t
\brief Timer related flags
<pre>
SMBF_READ_STREAM - Include the Read Stream
SMBF_WRITE_STREAM - Include the Write Stream
</pre>
*/
typedef enum {
SMBF_BOTH = 0,
SMBF_READ_STREAM = (1 << 0),
SMBF_WRITE_STREAM = (1 << 1)
} switch_media_bug_flag_t;
/*!
\enum switch_file_flag_t
\brief File flags
@ -653,6 +691,7 @@ typedef enum {
SWITCH_EVENT_PRESENCE - Presence Info
SWITCH_EVENT_CODEC - Codec Change
SWITCH_EVENT_BACKGROUND_JOB - Background Job
SWITCH_EVENT_DETECTED_SPEECH - Detected Speech
SWITCH_EVENT_ALL - All events at once
</pre>
@ -690,6 +729,7 @@ typedef enum {
SWITCH_EVENT_ROSTER,
SWITCH_EVENT_CODEC,
SWITCH_EVENT_BACKGROUND_JOB,
SWITCH_EVENT_DETECTED_SPEECH,
SWITCH_EVENT_ALL
} switch_event_types_t;
@ -800,10 +840,9 @@ typedef struct switch_io_event_hook_waitfor_write switch_io_event_hook_waitfor_w
typedef struct switch_io_event_hook_send_dtmf switch_io_event_hook_send_dtmf_t;
typedef struct switch_io_routines switch_io_routines_t;
typedef struct switch_io_event_hooks switch_io_event_hooks_t;
typedef struct switch_speech_handle switch_speech_handle_t;
typedef struct switch_asr_handle switch_asr_handle_t;
typedef struct switch_directory_handle switch_directory_handle_t;
typedef struct switch_loadable_module_interface switch_loadable_module_interface_t;
typedef struct switch_endpoint_interface switch_endpoint_interface_t;
typedef struct switch_timer_interface switch_timer_interface_t;
@ -813,6 +852,7 @@ typedef struct switch_application_interface switch_application_interface_t;
typedef struct switch_api_interface switch_api_interface_t;
typedef struct switch_file_interface switch_file_interface_t;
typedef struct switch_speech_interface switch_speech_interface_t;
typedef struct switch_asr_interface switch_asr_interface_t;
typedef struct switch_directory_interface switch_directory_interface_t;
typedef struct switch_chat_interface switch_chat_interface_t;
typedef struct switch_core_port_allocator switch_core_port_allocator_t;

View File

@ -393,10 +393,12 @@ static switch_status_t originate_function(char *cmd, switch_core_session_t *ises
switch_channel_t *caller_channel;
switch_core_session_t *caller_session;
char *argv[7] = {0};
int x, argc = 0;
int i = 0, x, argc = 0;
char *aleg, *exten, *dp, *context, *cid_name, *cid_num;
uint32_t timeout = 60;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
uint8_t machine = 1;
if (isession) {
stream->write_function(stream, "Illegal Usage\n");
return SWITCH_STATUS_SUCCESS;
@ -414,13 +416,18 @@ static switch_status_t originate_function(char *cmd, switch_core_session_t *ises
argv[x] = NULL;
}
}
if (!strcasecmp(argv[0], "machine")) {
machine = 1;
i++;
}
aleg = argv[0];
exten = argv[1];
dp = argv[2];
context = argv[3];
cid_name = argv[4];
cid_num = argv[5];
aleg = argv[i++];
exten = argv[i++];
dp = argv[i++];
context = argv[i++];
cid_name = argv[i++];
cid_num = argv[i++];
if (!dp) {
dp = "XML";
@ -435,7 +442,11 @@ static switch_status_t originate_function(char *cmd, switch_core_session_t *ises
}
if (switch_ivr_originate(NULL, &caller_session, &cause, aleg, timeout, &noop_state_handler, cid_name, cid_num, NULL) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "Cannot Create Outgoing Channel! [%s]\n", aleg);
if (machine) {
stream->write_function(stream, "fail: %s", switch_channel_cause2str(cause));
} else {
stream->write_function(stream, "Cannot Create Outgoing Channel! [%s] cause: %s\n", aleg, switch_channel_cause2str(cause));
}
return SWITCH_STATUS_SUCCESS;
}
@ -467,7 +478,13 @@ static switch_status_t originate_function(char *cmd, switch_core_session_t *ises
} else {
switch_ivr_session_transfer(caller_session, exten, dp, context);
}
stream->write_function(stream, "Created Session: %s\n", switch_core_session_get_uuid(caller_session));
if (machine) {
stream->write_function(stream, "success: %s\n", switch_core_session_get_uuid(caller_session));
} else {
stream->write_function(stream, "Created Session: %s\n", switch_core_session_get_uuid(caller_session));
}
return SWITCH_STATUS_SUCCESS;;
}

View File

@ -666,7 +666,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
switch_memory_pool_t *pool;
if (conference->fnode->type == NODE_TYPE_SPEECH) {
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
switch_core_speech_close(&conference->fnode->sh, &flags);
} else {
switch_core_file_close(&conference->fnode->fh);
@ -957,7 +957,7 @@ static void conference_loop(conference_member_t *member)
switch_memory_pool_t *pool;
if (member->fnode->type == NODE_TYPE_SPEECH) {
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
switch_core_speech_close(&member->fnode->sh, &flags);
} else {
switch_core_file_close(&member->fnode->fh);
@ -1340,7 +1340,7 @@ static switch_status_t conference_member_say(conference_obj_t *conference, confe
{
confernce_file_node_t *fnode, *nptr;
switch_memory_pool_t *pool;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
if (!(conference->tts_engine && conference->tts_voice)) {
return SWITCH_STATUS_SUCCESS;
@ -1399,7 +1399,7 @@ static switch_status_t conference_say(conference_obj_t *conference, char *text,
{
confernce_file_node_t *fnode, *nptr;
switch_memory_pool_t *pool;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
uint32_t count;
switch_mutex_lock(conference->mutex);

View File

@ -34,6 +34,33 @@
static const char modname[] = "mod_dptools";
static const switch_application_interface_t detect_speech_application_interface;
static void detect_speech_function(switch_core_session_t *session, char *data)
{
char *argv[4];
int argc;
char *lbuf = NULL;
if ((lbuf = switch_core_session_strdup(session, data)) && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
if (!strcasecmp(argv[0], "grammar") && argc >= 1) {
switch_ivr_detect_speech_load_grammar(session, argv[1], argv[2]);
} else if (!strcasecmp(argv[0], "nogrammar")) {
switch_ivr_detect_speech_unload_grammar(session, argv[1]);
} else if (!strcasecmp(argv[0], "pause")) {
switch_ivr_pause_detect_speech(session);
} else if (!strcasecmp(argv[0], "resume")) {
switch_ivr_resume_detect_speech(session);
} else if (!strcasecmp(argv[0], "stop")) {
switch_ivr_stop_detect_speech(session);
} else if (argc >= 3) {
switch_ivr_detect_speech(session, argv[0], argv[1], argv[2], argv[3], NULL);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", detect_speech_application_interface.syntax);
}
}
static void ringback_function(switch_core_session_t *session, char *data)
{
@ -253,7 +280,6 @@ static switch_api_interface_t dptools_api_interface = {
/*.next */ &chat_api_interface
};
static switch_api_interface_t presence_api_interface = {
/*.interface_name */ "presence",
/*.desc */ "presence",
@ -262,6 +288,14 @@ static switch_api_interface_t presence_api_interface = {
/*.next */ &dptools_api_interface
};
static const switch_application_interface_t detect_speech_application_interface = {
/*.interface_name */ "detect_speech",
/*.application_function */ detect_speech_function,
/* long_desc */ "Detect speech on a channel.",
/* short_desc */ "Detect speech",
/* syntax */ "<mod_name> <gram_name> <gram_path> [<addr>] OR grammar <gram_name> [<path>] OR pause OR resume",
/*.next */ NULL
};
static const switch_application_interface_t ringback_application_interface = {
/*.interface_name */ "ringback",
@ -269,8 +303,7 @@ static const switch_application_interface_t ringback_application_interface = {
/* long_desc */ "Indicate Ringback on a channel.",
/* short_desc */ "Indicate Ringback",
/* syntax */ "",
/*.next */ NULL
/*.next */ &detect_speech_application_interface
};
static const switch_application_interface_t set_application_interface = {

View File

@ -167,6 +167,123 @@ static void tts_function(switch_core_session_t *session, char *data)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Done\n");
}
#if 1
static void asrtest_function(switch_core_session_t *session, char *data)
{
switch_ivr_detect_speech(session,
"lumenvox",
"demo",
data,
"127.0.0.1",
NULL);
}
#else
static void asrtest_function(switch_core_session_t *session, char *data)
{
switch_asr_handle_t ah = {0};
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
switch_channel_t *channel = switch_core_session_get_channel(session);
char *codec_name = "L16";
switch_codec_t codec = {0}, *read_codec;
switch_frame_t write_frame = {0}, *write_frame_p = NULL;
char xdata[1024] = "";
read_codec = switch_core_session_get_read_codec(session);
assert(read_codec != NULL);
if (switch_core_asr_open(&ah, "lumenvox",
read_codec->implementation->iananame,
8000,
"127.0.0.1",
&flags,
switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
if (strcmp(ah.codec, read_codec->implementation->iananame)) {
if (switch_core_codec_init(&codec,
ah.codec,
NULL,
ah.rate,
read_codec->implementation->microseconds_per_frame / 1000,
read_codec->implementation->number_of_channels,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activated\n");
switch_core_session_set_read_codec(session, &codec);
write_frame.data = xdata;
write_frame.buflen = sizeof(xdata);
write_frame.codec = &codec;
write_frame_p = &write_frame;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec Activation Failed %s@%uhz %u channels %dms\n",
codec_name, read_codec->implementation->samples_per_second, read_codec->implementation->number_of_channels,
read_codec->implementation->microseconds_per_frame / 1000);
switch_core_session_reset(session);
return;
}
}
if (switch_core_asr_load_grammar(&ah, "demo", "/opt/lumenvox/engine_7.0/Lang/BuiltinGrammars/ABNFPhone.gram") != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n");
goto end;
}
while(switch_channel_ready(channel)) {
switch_frame_t *read_frame;
switch_status_t status = switch_core_session_read_frame(session, &read_frame, -1, 0);
char *xmlstr = NULL;
switch_xml_t xml = NULL, result;
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
if (switch_test_flag(read_frame, SFF_CNG)) {
continue;
}
if (switch_core_asr_feed(&ah, read_frame->data, read_frame->datalen, &flags) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error Feeding Data\n");
break;
}
if (switch_core_asr_check_results(&ah, &flags) == SWITCH_STATUS_SUCCESS) {
if (switch_core_asr_get_results(&ah, &xmlstr, &flags) != SWITCH_STATUS_SUCCESS) {
break;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RAW XML\n========\n%s\n", xmlstr);
if ((xml = switch_xml_parse_str(xmlstr, strlen(xmlstr))) && (result = switch_xml_child(xml, "result"))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Results [%s]\n", result->txt);
switch_xml_free(xml);
}
switch_safe_free(xmlstr);
}
if (write_frame_p) {
write_frame.datalen = read_frame->datalen;
switch_core_session_write_frame(session, write_frame_p, -1, 0);
} else {
memset(read_frame->data, 0, read_frame->datalen);
switch_core_session_write_frame(session, read_frame, -1, 0);
}
}
end:
if (write_frame_p) {
switch_core_session_set_read_codec(session, read_codec);
switch_core_codec_destroy(&codec);
}
switch_core_asr_close(&ah, &flags);
switch_core_session_reset(session);
}
}
#endif
static void ivrtest_function(switch_core_session_t *session, char *data)
{
switch_channel_t *channel;
@ -272,13 +389,20 @@ static const switch_application_interface_t ivrtest_application_interface = {
/*.next*/ &dirtest_application_interface
};
static const switch_application_interface_t asrtest_application_interface = {
/*.interface_name */ "asrtest",
/*.application_function */ asrtest_function,
NULL, NULL, NULL,
/*.next*/ &ivrtest_application_interface
};
static const switch_loadable_module_interface_t mod_ivrtest_module_interface = {
/*.module_name = */ modname,
/*.endpoint_interface = */ NULL,
/*.timer_interface = */ NULL,
/*.dialplan_interface = */ NULL,
/*.codec_interface = */ NULL,
/*.application_interface */ &ivrtest_application_interface
/*.application_interface */ &asrtest_application_interface
};
SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)

View File

@ -169,7 +169,7 @@ static void rss_function(switch_core_session_t *session, char *data)
char *voice = TTS_DEFAULT_VOICE;
char *timer_name = NULL;
switch_speech_handle_t sh;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
switch_core_thread_session_t thread_session;
uint32_t rate, interval = 20;
int stream_id = 0;

View File

@ -109,70 +109,65 @@ static swift_result_t write_audio(swift_event *event, swift_event_t type, void *
static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, char *voice_name, int rate, switch_speech_flag_t *flags)
{
if (*flags & SWITCH_SPEECH_FLAG_ASR) {
return SWITCH_STATUS_FALSE;
cepstral_t *cepstral = switch_core_alloc(sh->memory_pool, sizeof(*cepstral));
char srate[25];
if (!cepstral) {
return SWITCH_STATUS_MEMERR;
}
if (*flags & SWITCH_SPEECH_FLAG_TTS) {
cepstral_t *cepstral = switch_core_alloc(sh->memory_pool, sizeof(*cepstral));
char srate[25];
if (!cepstral) {
return SWITCH_STATUS_MEMERR;
}
if (switch_buffer_create_dynamic(&cepstral->audio_buffer, MY_BLOCK_SIZE, MY_BUF_LEN, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Write Buffer Failed!\n");
return SWITCH_STATUS_MEMERR;
}
if (switch_buffer_create_dynamic(&cepstral->audio_buffer, MY_BLOCK_SIZE, MY_BUF_LEN, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Write Buffer Failed!\n");
return SWITCH_STATUS_MEMERR;
}
switch_mutex_init(&cepstral->audio_lock, SWITCH_MUTEX_NESTED, sh->memory_pool);
switch_mutex_init(&cepstral->audio_lock, SWITCH_MUTEX_NESTED, sh->memory_pool);
cepstral->params = swift_params_new(NULL);
swift_params_set_string(cepstral->params, "audio/encoding", "pcm16");
snprintf(srate, sizeof(srate), "%d", rate);
swift_params_set_string(cepstral->params, "audio/sampling-rate", srate);
cepstral->params = swift_params_new(NULL);
swift_params_set_string(cepstral->params, "audio/encoding", "pcm16");
snprintf(srate, sizeof(srate), "%d", rate);
swift_params_set_string(cepstral->params, "audio/sampling-rate", srate);
/* Open a Swift Port through which to make TTS calls */
if (SWIFT_FAILED(cepstral->port = swift_port_open(engine, cepstral->params))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open Swift Port.");
/* Open a Swift Port through which to make TTS calls */
if (SWIFT_FAILED(cepstral->port = swift_port_open(engine, cepstral->params))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open Swift Port.");
goto all_done;
}
if (voice_name && SWIFT_FAILED(swift_port_set_voice_by_name(cepstral->port, voice_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid voice %s!\n", voice_name);
voice_name = NULL;
}
if (!voice_name) {
/* Find the first voice on the system */
if ((cepstral->voice = swift_port_find_first_voice(cepstral->port, NULL, NULL)) == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find any voices!\n");
goto all_done;
}
if (voice_name && SWIFT_FAILED(swift_port_set_voice_by_name(cepstral->port, voice_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid voice %s!\n", voice_name);
voice_name = NULL;
/* Set the voice found by find_first_voice() as the port's current voice */
if ( SWIFT_FAILED(swift_port_set_voice(cepstral->port, cepstral->voice)) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set voice.\n");
goto all_done;
}
if (!voice_name) {
/* Find the first voice on the system */
if ((cepstral->voice = swift_port_find_first_voice(cepstral->port, NULL, NULL)) == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find any voices!\n");
goto all_done;
}
/* Set the voice found by find_first_voice() as the port's current voice */
if ( SWIFT_FAILED(swift_port_set_voice(cepstral->port, cepstral->voice)) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set voice.\n");
goto all_done;
}
voice_name = (char *) swift_voice_get_attribute(cepstral->voice, "name");
}
if (voice_name) {
switch_copy_string(sh->voice, voice_name, sizeof(sh->voice));
}
swift_port_set_callback(cepstral->port, &write_audio, SWIFT_EVENT_AUDIO, cepstral);
sh->private_info = cepstral;
return SWITCH_STATUS_SUCCESS;
voice_name = (char *) swift_voice_get_attribute(cepstral->voice, "name");
}
if (voice_name) {
switch_copy_string(sh->voice, voice_name, sizeof(sh->voice));
}
swift_port_set_callback(cepstral->port, &write_audio, SWIFT_EVENT_AUDIO, cepstral);
sh->private_info = cepstral;
return SWITCH_STATUS_SUCCESS;
all_done:
return SWITCH_STATUS_FALSE;
}
@ -227,7 +222,7 @@ static switch_status_t cepstral_speech_feed_tts(switch_speech_handle_t *sh, char
return SWITCH_STATUS_FALSE;
}
swift_port_speak_text(cepstral->port, "<break time=\"400ms\"/>", 0, NULL, &cepstral->tts_stream, NULL);
swift_port_speak_text(cepstral->port, "<break time=\"500ms\"/>", 0, NULL, &cepstral->tts_stream, NULL);
swift_port_speak_text(cepstral->port, text, 0, NULL, &cepstral->tts_stream, NULL);
}
@ -252,10 +247,10 @@ static void cepstral_speech_flush_tts(switch_speech_handle_t *sh)
}
static switch_status_t cepstral_speech_read_tts(switch_speech_handle_t *sh,
void *data,
size_t *datalen,
uint32_t *rate,
switch_speech_flag_t *flags)
void *data,
size_t *datalen,
uint32_t *rate,
switch_speech_flag_t *flags)
{
cepstral_t *cepstral;
size_t desired = *datalen;
@ -404,8 +399,6 @@ static const switch_speech_interface_t cepstral_speech_interface = {
/*.interface_name*/ "cepstral",
/*.speech_open*/ cepstral_speech_open,
/*.speech_close*/ cepstral_speech_close,
/*.speech_feed_asr*/ NULL,
/*.speech_interpret_asr*/ NULL,
/*.speech_feed_tts*/ cepstral_speech_feed_tts,
/*.speech_read_tts*/ cepstral_speech_read_tts,
/*.speech_flush_tts*/ cepstral_speech_flush_tts,

View File

@ -77,6 +77,7 @@ static struct {
char *ip;
uint16_t port;
char *password;
int done;
} prefs;
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, prefs.ip)
@ -166,6 +167,8 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void)
{
listener_t *l;
prefs.done = 1;
close_socket(&listen_list.sock);
switch_mutex_lock(listen_list.mutex);
@ -1003,7 +1006,11 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
}
if ((rv = switch_socket_accept(&inbound_socket, listen_list.sock, listener_pool))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error\n");
if (prefs.done) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error\n");
}
break;
}

File diff suppressed because it is too large Load Diff

View File

@ -348,7 +348,11 @@ SWITCH_DECLARE(char *) switch_channel_get_variable(switch_channel_t *channel, ch
assert(channel != NULL);
if (!(v=switch_core_hash_find(channel->variables, varname))) {
v = switch_caller_get_field_by_name(channel->caller_profile, varname);
if (!(v = switch_caller_get_field_by_name(channel->caller_profile, varname))) {
if (!strcmp(varname, "base_dir")) {
return SWITCH_GLOBAL_dirs.base_dir;
}
}
}
return v;
@ -986,7 +990,8 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
switch_channel_set_variable(channel, "hangup_cause", switch_channel_cause2str(channel->hangup_cause));
switch_channel_presence(channel, "unavailable", switch_channel_cause2str(channel->hangup_cause));
switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL);
@ -1190,7 +1195,7 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
return in;
}
}
nlen = sub_val ? strlen(sub_val) : 0;
nlen = strlen(sub_val);
if (len + nlen >= olen) {
olen += block;
cpos = c - data;
@ -1205,11 +1210,10 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
vname = data + vvalpos;
}
if (nlen) {
len += nlen;
strcat(c, sub_val);
c += nlen;
}
len += nlen;
strcat(c, sub_val);
c += nlen;
if (func_val) {
free(func_val);
func_val = NULL;

View File

@ -64,6 +64,7 @@ struct switch_media_bug {
switch_mutex_t *write_mutex;
switch_core_session_t *session;
void *user_data;
uint32_t flags;
struct switch_media_bug *next;
};
@ -168,6 +169,11 @@ static void switch_core_media_bug_destroy(switch_media_bug_t *bug)
switch_buffer_destroy(&bug->raw_write_buffer);
}
SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *bug)
{
return bug->user_data;
}
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *bug, switch_frame_t *frame)
{
uint32_t bytes = 0;
@ -175,21 +181,35 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b
uint32_t datalen = 0;
int16_t *dp, *fp;
uint32_t x;
size_t rlen = switch_buffer_inuse(bug->raw_read_buffer);
size_t wlen = switch_buffer_inuse(bug->raw_write_buffer);
size_t rlen = 0;
size_t wlen = 0;
uint32_t blen;
size_t rdlen = 0;
uint32_t maxlen;
if (!rlen && !wlen) {
if (bug->raw_read_buffer) {
rlen = switch_buffer_inuse(bug->raw_read_buffer);
}
if (bug->raw_write_buffer) {
wlen = switch_buffer_inuse(bug->raw_write_buffer);
}
if ((bug->raw_read_buffer && bug->raw_write_buffer) && (!rlen && !wlen)) {
return SWITCH_STATUS_FALSE;
}
maxlen = sizeof(data) > frame->buflen ? frame->buflen : sizeof(data);
if ((rdlen = rlen > wlen ? wlen : rlen) > maxlen) {
rdlen = maxlen;
}
if (!rdlen) {
rdlen = maxlen;
}
frame->datalen = 0;
if (rlen) {
@ -209,6 +229,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b
switch_mutex_unlock(bug->write_mutex);
}
bytes = (datalen > frame->datalen) ? datalen : frame->datalen;
if (bytes) {
@ -233,6 +254,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b
}
frame->datalen = bytes;
return SWITCH_STATUS_SUCCESS;
}
@ -243,6 +266,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session,
switch_media_bug_callback_t callback,
void *user_data,
switch_media_bug_flag_t flags,
switch_media_bug_t **new_bug)
{
@ -256,13 +280,25 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t
bug->callback = callback;
bug->user_data = user_data;
bug->session = session;
bug->flags = flags;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel));
bytes = session->read_codec->implementation->bytes_per_frame;
switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
if (!bug->flags) {
bug->flags = (SMBF_READ_STREAM | SMBF_WRITE_STREAM);
}
if (switch_test_flag(bug, SMBF_READ_STREAM)) {
switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool);
}
bytes = session->write_codec->implementation->bytes_per_frame;
switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool);
switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool);
if (switch_test_flag(bug, SMBF_WRITE_STREAM)) {
switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool);
}
switch_thread_rwlock_wrlock(session->bug_rwlock);
bug->next = session->bugs;
@ -292,6 +328,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all(switch_core_ses
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing BUG from %s\n", switch_channel_get_name(session->channel));
}
switch_thread_rwlock_unlock(session->bug_rwlock);
session->bugs = NULL;
return SWITCH_STATUS_SUCCESS;
}
@ -946,18 +983,108 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t *
return sh->speech_interface->speech_open(sh, voice_name, rate, flags);
}
SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_asr(switch_speech_handle_t *sh, void *data, unsigned int *len, int rate, switch_speech_flag_t *flags)
SWITCH_DECLARE(switch_status_t) switch_core_asr_open(switch_asr_handle_t *ah,
char *module_name,
char *codec,
int rate,
char *dest,
switch_asr_flag_t *flags,
switch_memory_pool_t *pool)
{
assert(sh != NULL);
switch_status_t status;
assert(ah != NULL);
if ((ah->asr_interface = switch_loadable_module_get_asr_interface(module_name)) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid asr module [%s]!\n", module_name);
return SWITCH_STATUS_GENERR;
}
return sh->speech_interface->speech_feed_asr(sh, data, len, rate, flags);
ah->flags = *flags;
if (pool) {
ah->memory_pool = pool;
} else {
if ((status = switch_core_new_memory_pool(&ah->memory_pool)) != SWITCH_STATUS_SUCCESS) {
return status;
}
switch_set_flag(ah, SWITCH_ASR_FLAG_FREE_POOL);
}
ah->rate = rate;
ah->name = switch_core_strdup(ah->memory_pool, module_name);
return ah->asr_interface->asr_open(ah, codec, rate, dest, flags);
}
SWITCH_DECLARE(switch_status_t) switch_core_speech_interpret_asr(switch_speech_handle_t *sh, char *buf, unsigned int buflen, switch_speech_flag_t *flags)
SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, char *grammar, char *path)
{
assert(sh != NULL);
char *epath = NULL;
switch_status_t status;
assert(ah != NULL);
if (*path != '/') {
epath = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, path);
path = epath;
}
status = ah->asr_interface->asr_load_grammar(ah, grammar, path);
switch_safe_free(epath);
return status;
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, char *grammar)
{
switch_status_t status;
assert(ah != NULL);
status = ah->asr_interface->asr_unload_grammar(ah, grammar);
return status;
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_pause(switch_asr_handle_t *ah)
{
assert(ah != NULL);
return ah->asr_interface->asr_pause(ah);
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_resume(switch_asr_handle_t *ah)
{
assert(ah != NULL);
return ah->asr_interface->asr_resume(ah);
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
{
assert(ah != NULL);
return ah->asr_interface->asr_close(ah, flags);
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags)
{
assert(ah != NULL);
return sh->speech_interface->speech_interpret_asr(sh, buf, buflen, flags);
return ah->asr_interface->asr_feed(ah, data, len, flags);
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
{
assert(ah != NULL);
return ah->asr_interface->asr_check_results(ah, flags);
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags)
{
assert(ah != NULL);
return ah->asr_interface->asr_get_results(ah, xmlstr, flags);
}
SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags)
@ -1765,12 +1892,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
switch_media_bug_t *bp;
switch_thread_rwlock_rdlock(session->bug_rwlock);
for (bp = session->bugs; bp; bp = bp->next) {
switch_mutex_lock(bp->read_mutex);
switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
if (bp->callback) {
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ);
if (switch_test_flag(bp, SMBF_READ_STREAM)) {
switch_mutex_lock(bp->read_mutex);
switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
if (bp->callback) {
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ);
}
switch_mutex_unlock(bp->read_mutex);
}
switch_mutex_unlock(bp->read_mutex);
}
switch_thread_rwlock_unlock(session->bug_rwlock);
}
@ -1999,11 +2128,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
switch_media_bug_t *bp;
switch_thread_rwlock_rdlock(session->bug_rwlock);
for (bp = session->bugs; bp; bp = bp->next) {
switch_mutex_lock(bp->write_mutex);
switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen);
switch_mutex_unlock(bp->write_mutex);
if (bp->callback) {
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE);
if (switch_test_flag(bp, SMBF_WRITE_STREAM)) {
switch_mutex_lock(bp->write_mutex);
switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen);
switch_mutex_unlock(bp->write_mutex);
if (bp->callback) {
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE);
}
}
}
switch_thread_rwlock_unlock(session->bug_rwlock);
@ -3193,7 +3324,7 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thre
switch_mutex_unlock(runtime.session_table_mutex);
switch_core_session_run(session);
switch_core_media_bug_remove_all(session);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session %u (%s) Locked, Waiting on external entities\n", session->id, switch_channel_get_name(session->channel));
switch_core_session_write_lock(session);
switch_core_session_rwunlock(session);
@ -3609,6 +3740,9 @@ SWITCH_DECLARE(void) switch_core_set_globals(void)
if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) {
snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%shtdocs", exePath);
}
if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) {
snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%sgrammar", exePath);
}
#else
SWITCH_GLOBAL_dirs.base_dir = SWITCH_PREFIX_DIR;
SWITCH_GLOBAL_dirs.mod_dir = SWITCH_MOD_DIR;
@ -3617,6 +3751,7 @@ SWITCH_DECLARE(void) switch_core_set_globals(void)
SWITCH_GLOBAL_dirs.db_dir = SWITCH_DB_DIR;
SWITCH_GLOBAL_dirs.script_dir = SWITCH_SCRIPT_DIR;
SWITCH_GLOBAL_dirs.htdocs_dir = SWITCH_HTDOCS_DIR;
SWITCH_GLOBAL_dirs.grammar_dir = SWITCH_GRAMMAR_DIR;
#endif
#ifdef SWITCH_TEMP_DIR
SWITCH_GLOBAL_dirs.temp_dir = SWITCH_TEMP_DIR;
@ -3987,6 +4122,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
free(SWITCH_GLOBAL_dirs.db_dir);
free(SWITCH_GLOBAL_dirs.script_dir);
free(SWITCH_GLOBAL_dirs.htdocs_dir);
free(SWITCH_GLOBAL_dirs.grammar_dir);
free(SWITCH_GLOBAL_dirs.temp_dir);
#endif

View File

@ -128,6 +128,7 @@ static char *EVENT_NAMES[] = {
"ROSTER",
"CODEC",
"BACKGROUND_JOB",
"DETECTED_SPEECH",
"ALL"
};
@ -539,15 +540,17 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event)
switch_event_t *ep = *event;
switch_event_header_t *hp, *this;
for (hp = ep->headers; hp;) {
this = hp;
hp = hp->next;
FREE(this->name);
FREE(this->value);
FREE(this);
if (ep) {
for (hp = ep->headers; hp;) {
this = hp;
hp = hp->next;
FREE(this->name);
FREE(this->value);
FREE(this);
}
FREE(ep->body);
FREE(ep);
}
FREE(ep->body);
FREE(ep);
*event = NULL;
}

View File

@ -46,7 +46,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
switch_time_t start, now, done = switch_time_now() + (ms * 1000);
switch_frame_t *read_frame;
int32_t left, elapsed;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
@ -174,13 +174,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session)
}
SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session,
switch_input_callback_function_t input_callback,
void *buf,
unsigned int buflen)
switch_input_callback_function_t input_callback,
void *buf,
unsigned int buflen,
unsigned int timeout)
{
switch_channel_t *channel;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_time_t started = 0;
unsigned int elapsed;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
@ -188,12 +191,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s
return SWITCH_STATUS_GENERR;
}
if (timeout) {
started = switch_time_now();
}
while(switch_channel_ready(channel)) {
switch_frame_t *read_frame;
switch_event_t *event;
char dtmf[128];
if (timeout) {
elapsed = (unsigned int)((switch_time_now() - started) / 1000);
if (elapsed >= timeout) {
break;
}
}
if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) {
switch_ivr_parse_event(session, event);
@ -585,6 +597,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
if ((status = switch_core_media_bug_add(session,
record_callback,
fh,
SMBF_BOTH,
&bug)) != SWITCH_STATUS_SUCCESS) {
switch_core_file_close(fh);
return status;
@ -595,6 +608,299 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
return SWITCH_STATUS_SUCCESS;
}
struct speech_thread_handle {
switch_core_session_t *session;
switch_asr_handle_t *ah;
switch_media_bug_t *bug;
switch_mutex_t *mutex;
switch_thread_cond_t *cond;
switch_memory_pool_t *pool;
};
static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj)
{
struct speech_thread_handle *sth = (struct speech_thread_handle *) obj;
switch_channel_t *channel = switch_core_session_get_channel(sth->session);
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
switch_status_t status;
switch_thread_cond_create(&sth->cond, sth->pool);
switch_mutex_init(&sth->mutex, SWITCH_MUTEX_NESTED, sth->pool);
switch_core_session_read_lock(sth->session);
switch_mutex_lock(sth->mutex);
while (switch_channel_ready(channel) && !switch_test_flag(sth->ah, SWITCH_ASR_FLAG_CLOSED)) {
char *xmlstr = NULL;
switch_thread_cond_wait(sth->cond, sth->mutex);
if (switch_core_asr_check_results(sth->ah, &flags) == SWITCH_STATUS_SUCCESS) {
switch_event_t *event;
status = switch_core_asr_get_results(sth->ah, &xmlstr, &flags);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
goto done;
}
if (switch_event_create(&event, SWITCH_EVENT_DETECTED_SPEECH) == SWITCH_STATUS_SUCCESS) {
if (status == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speech-Type", "detected-speech");
switch_event_add_body(event, xmlstr);
} else {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speech-Type", "begin-speaking");
}
if (switch_test_flag(sth->ah, SWITCH_ASR_FLAG_FIRE_EVENTS)) {
switch_event_t *dup;
if (switch_event_dup(&dup, event) == SWITCH_STATUS_SUCCESS) {
switch_event_fire(&dup);
}
}
if (switch_core_session_queue_event(sth->session, &event) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event queue failed!\n");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
switch_event_fire(&event);
}
}
switch_safe_free(xmlstr);
}
}
done:
switch_mutex_unlock(sth->mutex);
switch_core_session_rwunlock(sth->session);
return NULL;
}
static void speech_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
struct speech_thread_handle *sth = (struct speech_thread_handle *) user_data;
uint8_t data[SWITCH_RECCOMMENDED_BUFFER_SIZE];
switch_frame_t frame = {0};
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
frame.data = data;
frame.buflen = SWITCH_RECCOMMENDED_BUFFER_SIZE;
switch(type) {
case SWITCH_ABC_TYPE_INIT: {
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
switch_threadattr_create(&thd_attr, sth->pool);
switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&thread, thd_attr, speech_thread, sth, sth->pool);
}
break;
case SWITCH_ABC_TYPE_CLOSE:
switch_core_asr_close(sth->ah, &flags);
switch_mutex_lock(sth->mutex);
switch_thread_cond_signal(sth->cond);
switch_mutex_unlock(sth->mutex);
case SWITCH_ABC_TYPE_READ:
if (sth->ah) {
if (switch_core_media_bug_read(bug, &frame) == SWITCH_STATUS_SUCCESS) {
if (switch_core_asr_feed(sth->ah, frame.data, frame.datalen, &flags) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error Feeding Data\n");
return;
}
if (switch_core_asr_check_results(sth->ah, &flags) == SWITCH_STATUS_SUCCESS) {
switch_mutex_lock(sth->mutex);
switch_thread_cond_signal(sth->cond);
switch_mutex_unlock(sth->mutex);
}
}
}
break;
case SWITCH_ABC_TYPE_WRITE:
break;
}
}
SWITCH_DECLARE(switch_status_t) switch_ivr_stop_detect_speech(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
struct speech_thread_handle *sth;
assert(channel != NULL);
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
switch_channel_set_private(channel, SWITCH_SPEECH_KEY, NULL);
switch_core_media_bug_remove(session, &sth->bug);
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_pause_detect_speech(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
struct speech_thread_handle *sth;
assert(channel != NULL);
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
switch_core_asr_pause(sth->ah);
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_resume_detect_speech(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
struct speech_thread_handle *sth;
assert(channel != NULL);
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
switch_core_asr_resume(sth->ah);
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *path)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
struct speech_thread_handle *sth;
assert(channel != NULL);
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
if (switch_core_asr_load_grammar(sth->ah, grammar, path) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n");
switch_core_asr_close(sth->ah, &flags);
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, char *grammar)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
struct speech_thread_handle *sth;
assert(channel != NULL);
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
if (switch_core_asr_unload_grammar(sth->ah, grammar) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error unloading Grammar\n");
switch_core_asr_close(sth->ah, &flags);
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session,
char *mod_name,
char *grammar,
char *path,
char *dest,
switch_asr_handle_t *ah)
{
switch_channel_t *channel;
switch_codec_t *read_codec;
switch_status_t status;
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
struct speech_thread_handle *sth;
char *val;
if (!ah) {
if (!(ah = switch_core_session_alloc(session, sizeof(*ah)))) {
return SWITCH_STATUS_MEMERR;
}
}
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
read_codec = switch_core_session_get_read_codec(session);
assert(read_codec != NULL);
if ((val = switch_channel_get_variable(channel, "fire_asr_events"))) {
switch_set_flag(ah, SWITCH_ASR_FLAG_FIRE_EVENTS);
}
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
if (switch_core_asr_load_grammar(sth->ah, grammar, path) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n");
switch_core_asr_close(sth->ah, &flags);
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_SUCCESS;
}
if (switch_core_asr_open(ah,
mod_name,
"L16",
read_codec->implementation->samples_per_second,
dest,
&flags,
switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
if (switch_core_asr_load_grammar(ah, grammar, path) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n");
switch_core_asr_close(ah, &flags);
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_STATUS_FALSE;
}
} else {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_STATUS_FALSE;
}
sth = switch_core_session_alloc(session, sizeof(*sth));
sth->pool = switch_core_session_get_pool(session);
sth->session = session;
sth->ah = ah;
if ((status = switch_core_media_bug_add(session,
speech_callback,
sth,
SMBF_READ_STREAM,
&sth->bug)) != SWITCH_STATUS_SUCCESS) {
switch_core_asr_close(ah, &flags);
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return status;
}
switch_channel_set_private(channel, SWITCH_SPEECH_KEY, sth);
return SWITCH_STATUS_SUCCESS;
}
#define FILE_STARTSAMPLES 1024 * 32
#define FILE_BLOCKSIZE 1024 * 8
#define FILE_BUFSIZE 1024 * 64
@ -1130,7 +1436,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
int done = 0;
int lead_in_out = 10;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
uint32_t rate = 0, samples = 0;
channel = switch_core_session_get_channel(session);
@ -1323,7 +1629,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
int stream_id;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_speech_handle_t sh;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
channel = switch_core_session_get_channel(session);
@ -1502,7 +1808,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
status = input_callback(session_a, event, SWITCH_INPUT_TYPE_EVENT, user_data, 0);
}
if (switch_core_session_receive_event(session_b, &event) != SWITCH_STATUS_SUCCESS) {
if (event->event_id != SWITCH_EVENT_MESSAGE || switch_core_session_receive_event(session_b, &event) != SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&event);
}

View File

@ -51,6 +51,7 @@ struct switch_loadable_module_container {
switch_hash_t *api_hash;
switch_hash_t *file_hash;
switch_hash_t *speech_hash;
switch_hash_t *asr_hash;
switch_hash_t *directory_hash;
switch_hash_t *chat_hash;
switch_memory_pool_t *pool;
@ -218,6 +219,20 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable
}
}
if (new_module->module_interface->asr_interface) {
const switch_asr_interface_t *ptr;
for (ptr = new_module->module_interface->asr_interface; ptr; ptr = ptr->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Asr interface '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "asr");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
switch_event_fire(&event);
}
switch_core_hash_insert(loadable_modules.asr_hash, (char *) ptr->interface_name, (void *) ptr);
}
}
if (new_module->module_interface->directory_interface) {
const switch_directory_interface_t *ptr;
@ -490,6 +505,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
switch_core_hash_init(&loadable_modules.api_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.file_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.speech_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.asr_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.directory_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.chat_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.dialplan_hash, loadable_modules.pool);
@ -582,12 +598,18 @@ SWITCH_DECLARE(void) switch_loadable_module_shutdown(void)
for (hi = switch_hash_first(loadable_modules.pool, loadable_modules.module_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
module = (switch_loadable_module_t *) val;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Checking %s\t", module->module_interface->module_name);
if (module->switch_module_shutdown) {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "(yes)\n");
module->switch_module_shutdown();
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping: %s\n", module->module_interface->module_name);
if (module->switch_module_shutdown() == SWITCH_STATUS_UNLOAD) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s unloaded.\n", module->module_interface->module_name);
apr_dso_unload(module->lib);
module->lib = NULL;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s shutdown.\n", module->module_interface->module_name);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "(no)\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s has no shutdown routine\n", module->module_interface->module_name);
}
}
@ -648,6 +670,11 @@ SWITCH_DECLARE(switch_speech_interface_t *) switch_loadable_module_get_speech_in
return switch_core_hash_find(loadable_modules.speech_hash, name);
}
SWITCH_DECLARE(switch_asr_interface_t *) switch_loadable_module_get_asr_interface(char *name)
{
return switch_core_hash_find(loadable_modules.asr_hash, name);
}
SWITCH_DECLARE(switch_directory_interface_t *) switch_loadable_module_get_directory_interface(char *name)
{
return switch_core_hash_find(loadable_modules.directory_hash, name);