RTS API Documentation  1.10.11
switch_core_asr.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Michael Jerris <mike@jerris.com>
28  * Paul D. Tinsley <pdt at jackhammer.org>
29  * Christopher M. Rienzo <chris@rienzo.com>
30  * Luke Dashjr <luke@openmethods.com> (OpenMethods, LLC)
31  *
32  *
33  * switch_core_asr.c -- Main Core Library (Speech Detection Interface)
34  *
35  */
36 
37 #include <switch.h>
39 
41  const char *module_name,
42  const char *codec, int rate, const char *dest, switch_asr_flag_t *flags, switch_memory_pool_t *pool)
43 {
44  switch_status_t status;
45  char *module_name_dup = NULL;
46  char *param = NULL;
47  int free_pool = 0;
48 
49  if (!pool) {
50  if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) {
51  return status;
52  }
53  free_pool = 1;
54  }
55 
56  if (strchr(module_name, ':')) {
57  module_name_dup = switch_core_strdup(pool, module_name);
58  if ((param = strchr(module_name_dup, ':'))) {
59  *param++ = '\0';
60  module_name = module_name_dup;
61  }
62  }
63 
64  switch_assert(ah != NULL);
65 
66  if ((ah->asr_interface = switch_loadable_module_get_asr_interface(module_name)) == 0) {
67  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid ASR module [%s]!\n", module_name);
68  if (free_pool) {
70  }
71  return SWITCH_STATUS_GENERR;
72  }
73 
74  ah->flags = *flags;
75 
76  ah->memory_pool = pool;
77  if (free_pool) {
79  }
80  if (param) {
81  ah->param = param;
82  }
83  ah->rate = rate;
84  ah->name = switch_core_strdup(ah->memory_pool, module_name);
85  ah->samplerate = rate;
86  ah->native_rate = rate;
87 
88  status = ah->asr_interface->asr_open(ah, codec, rate, dest, flags);
89 
90  if (status != SWITCH_STATUS_SUCCESS) {
93  }
95  }
96 
97  return status;
98 
99 }
100 
102 {
104  char *param_string = NULL;
105  char *data = NULL;
106  char *lgrammar = NULL;
107 
108  switch_assert(ah != NULL);
109 
110  if (zstr(grammar)) {
111  status = SWITCH_STATUS_FALSE;
112  goto done;
113  }
114 
115  /* Set ASR parameters from params in the grammar string
116  * Params are defined as follows {name1=val1,name2=val2,name3=val3}grammar text
117  */
118  lgrammar = strdup(grammar);
119  data = lgrammar;
120 
121  /* strip leading spaces */
122  while (data && *data == ' ') {
123  data++;
124  }
125  if (zstr(data)) {
126  status = SWITCH_STATUS_FALSE;
127  goto done;
128  }
129 
130  /* extract params */
131  if (*data == '{') {
132  param_string = data + 1;
133  data = switch_find_end_paren(data, '{', '}');
134  if (zstr(data)) {
135  status = SWITCH_STATUS_FALSE;
136  goto done;
137  } else {
138  *data = '\0';
139  data++;
140  }
141  }
142 
143  /* set ASR params */
144  if (!zstr(param_string)) {
145  char *param[256] = { 0 };
146  int i;
147  int argc = switch_separate_string(param_string, ',', param, (sizeof(param) / sizeof(param[0])));
148  for (i = 0; i < argc && param[i]; ++i) {
149  char *param_pair[2] = { 0 };
150  if (switch_separate_string(param[i], '=', param_pair, (sizeof(param_pair) / sizeof(param_pair[0]))) == 2) {
151  switch_core_asr_text_param(ah, param_pair[0], param_pair[1]);
152  }
153  }
154  }
155 
156  status = ah->asr_interface->asr_load_grammar(ah, data, name);
157 
158  done:
159 
160  switch_safe_free(lgrammar);
161  return status;
162 }
163 
165 {
166  switch_status_t status;
167 
168  switch_assert(ah != NULL);
169  status = ah->asr_interface->asr_unload_grammar(ah, name);
170 
171  return status;
172 }
173 
175 {
177 
178  switch_assert(ah != NULL);
179 
181  status = ah->asr_interface->asr_enable_grammar(ah, name);
182  }
183 
184  return status;
185 }
186 
188 {
190 
191  switch_assert(ah != NULL);
192 
194  status = ah->asr_interface->asr_disable_grammar(ah, name);
195  }
196 
197  return status;
198 }
199 
201 {
203 
204  switch_assert(ah != NULL);
205 
207  status = ah->asr_interface->asr_disable_all_grammars(ah);
208  }
209 
210  return status;
211 }
212 
214 {
215  switch_assert(ah != NULL);
216 
217  return ah->asr_interface->asr_pause(ah);
218 }
219 
221 {
222  switch_assert(ah != NULL);
223 
224  return ah->asr_interface->asr_resume(ah);
225 }
226 
228 {
229  switch_status_t status;
230 
231  switch_assert(ah != NULL);
232 
233  status = ah->asr_interface->asr_close(ah, flags);
235 
236  switch_safe_free(ah->dbuf);
238 
240 
243  }
244 
245  return status;
246 }
247 
249 {
250  switch_size_t orig_len = len;
251  switch_assert(ah != NULL);
252 
253  if (ah->native_rate && ah->samplerate && ah->native_rate != ah->samplerate) {
254  if (!ah->resampler) {
256  ah->samplerate, ah->native_rate, (uint32_t) orig_len, SWITCH_RESAMPLE_QUALITY, 1) != SWITCH_STATUS_SUCCESS) {
257  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
258  return SWITCH_STATUS_GENERR;
259  }
260  }
261 
262  switch_resample_process(ah->resampler, data, len / 2);
263  if (ah->resampler->to_len * 2 > orig_len) {
264  if (ah->dbuflen < ah->resampler->to_len * 2) {
265  void *mem;
266  ah->dbuflen = ah->resampler->to_len * 2;
267  mem = realloc(ah->dbuf, ah->dbuflen);
268  switch_assert(mem);
269  ah->dbuf = mem;
270  }
271  switch_assert(ah->resampler->to_len * 2 <= ah->dbuflen);
272  memcpy(ah->dbuf, ah->resampler->to, ah->resampler->to_len * 2);
273  data = ah->dbuf;
274  } else {
275  memcpy(data, ah->resampler->to, ah->resampler->to_len * 2);
276  }
277 
278  len = ah->resampler->to_len * 2;
279  }
280 
281  return ah->asr_interface->asr_feed(ah, data, len, flags);
282 }
283 
285 {
287 
288  switch_assert(ah != NULL);
289 
290  if (ah->asr_interface->asr_feed_dtmf) {
291  status = ah->asr_interface->asr_feed_dtmf(ah, dtmf, flags);
292  }
293 
294  return status;
295 }
296 
298 {
299  switch_assert(ah != NULL);
300 
301  return ah->asr_interface->asr_check_results(ah, flags);
302 }
303 
305 {
306  switch_assert(ah != NULL);
307 
308  return ah->asr_interface->asr_get_results(ah, xmlstr, flags);
309 }
310 
312 {
313  switch_assert(ah != NULL);
314 
316  return ah->asr_interface->asr_get_result_headers(ah, headers, flags);
317  } else {
318  /* Since this is not always implemented, return success if the function can't be called */
319  return SWITCH_STATUS_SUCCESS;
320  }
321 }
322 
324 {
326 
327  switch_assert(ah != NULL);
328 
330  status = ah->asr_interface->asr_start_input_timers(ah);
331  }
332 
333  return status;
334 }
335 
336 SWITCH_DECLARE(void) switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val)
337 {
338  switch_assert(ah != NULL);
339 
340  if (ah->asr_interface->asr_text_param) {
341  ah->asr_interface->asr_text_param(ah, param, val);
342  }
343 }
344 
346 {
347  switch_assert(ah != NULL);
348 
349  if (ah->asr_interface->asr_numeric_param) {
350  ah->asr_interface->asr_numeric_param(ah, param, val);
351  }
352 }
353 
355 {
356  switch_assert(ah != NULL);
357 
358  if (ah->asr_interface->asr_float_param) {
359  ah->asr_interface->asr_float_param(ah, param, val);
360  }
361 }
362 
363 /* For Emacs:
364  * Local Variables:
365  * mode:c
366  * indent-tabs-mode:t
367  * tab-width:4
368  * c-basic-offset:4
369  * End:
370  * For VIM:
371  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
372  */
switch_status_t(* asr_get_result_headers)(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags)
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
switch_status_t switch_core_asr_start_input_timers(switch_asr_handle_t *ah)
Start input timers on an asr handle.
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
#define SWITCH_CHANNEL_LOG
switch_status_t switch_core_asr_disable_all_grammars(switch_asr_handle_t *ah)
Disable all grammars from an asr handle.
void switch_core_asr_float_param(switch_asr_handle_t *ah, char *param, double val)
Set a float parameter on an asr handle.
char * switch_find_end_paren(const char *s, char open, char close)
Definition: switch_utils.c:796
switch_status_t switch_core_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags)
Get result headers from an asr handle.
switch_status_t(* asr_unload_grammar)(switch_asr_handle_t *ah, const char *name)
switch_status_t switch_core_asr_open(switch_asr_handle_t *ah, const char *module_name, const char *codec, int rate, const char *dest, switch_asr_flag_t *flags, switch_memory_pool_t *pool)
Open an asr handle.
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:733
switch_status_t(* asr_get_results)(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags)
switch_status_t(* asr_open)(switch_asr_handle_t *ah, const char *codec, int rate, const char *dest, switch_asr_flag_t *flags)
switch_status_t switch_core_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags)
Get results from an asr handle.
switch_status_t(* asr_disable_grammar)(switch_asr_handle_t *ah, const char *name)
switch_status_t(* asr_load_grammar)(switch_asr_handle_t *ah, const char *grammar, const char *name)
switch_status_t switch_core_asr_feed_dtmf(switch_asr_handle_t *ah, const switch_dtmf_t *dtmf, switch_asr_flag_t *flags)
Feed DTMF to an asr handle.
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
switch_memory_pool_t * pool
Representation of an event.
Definition: switch_event.h:80
switch_status_t(* asr_close)(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
switch_status_t(* asr_enable_grammar)(switch_asr_handle_t *ah, const char *name)
#define SWITCH_RESAMPLE_QUALITY
switch_status_t switch_core_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags)
Feed audio data to an asr handle.
switch_status_t(* asr_start_input_timers)(switch_asr_handle_t *ah)
switch_status_t(* asr_check_results)(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
switch_asr_interface_t * asr_interface
void switch_resample_destroy(switch_audio_resampler_t **resampler)
Destroy an existing resampler handle.
void(* asr_text_param)(switch_asr_handle_t *ah, char *param, const char *val)
switch_status_t switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name)
Load a grammar to an asr handle.
switch_status_t switch_core_asr_pause(switch_asr_handle_t *ah)
Pause detection on an asr handle.
#define zstr(x)
Definition: switch_utils.h:314
#define UNPROTECT_INTERFACE(_it)
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
switch_status_t switch_core_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
Close an asr handle.
switch_status_t(* asr_resume)(switch_asr_handle_t *ah)
void switch_core_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val)
Set a numeric parameter on an asr handle.
switch_status_t(* asr_feed_dtmf)(switch_asr_handle_t *ah, const switch_dtmf_t *dtmf, switch_asr_flag_t *flags)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_status_t switch_core_asr_disable_grammar(switch_asr_handle_t *ah, const char *name)
Disable a grammar from an asr handle.
uintptr_t switch_size_t
uint32_t switch_asr_flag_t
switch_status_t(* asr_disable_all_grammars)(switch_asr_handle_t *ah)
switch_asr_interface_t * switch_loadable_module_get_asr_interface(const char *name)
Retrieve the asr interface by it&#39;s registered name.
switch_status_t(* asr_pause)(switch_asr_handle_t *ah)
switch_status_t switch_core_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
Check an asr handle for results.
switch_status_t
Common return values.
Main Library Header.
switch_status_t switch_core_asr_resume(switch_asr_handle_t *ah)
Resume detection on an asr handle.
#define SWITCH_DECLARE(type)
void(* asr_numeric_param)(switch_asr_handle_t *ah, char *param, int val)
switch_memory_pool_t * memory_pool
switch_status_t switch_core_asr_enable_grammar(switch_asr_handle_t *ah, const char *name)
Enable a grammar from an asr handle.
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
struct fspr_pool_t switch_memory_pool_t
const char *const name
Definition: switch_cJSON.h:250
#define switch_assert(expr)
switch_audio_resampler_t * resampler
switch_status_t switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name)
Unload a grammar from an asr handle.
switch_status_t(* asr_feed)(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags)
void switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val)
Set a text parameter on an asr handle.
void(* asr_float_param)(switch_asr_handle_t *ah, char *param, double val)
#define switch_resample_create(_n, _fr, _tr, _ts, _q, _c)
uint32_t switch_resample_process(switch_audio_resampler_t *resampler, int16_t *src, uint32_t srclen)
Resample one float buffer into another using specifications of a given handle.