FreeSWITCH API Documentation  1.7.0
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 buf[256] = "";
46  char *param = NULL;
47 
48  if (strchr(module_name, ':')) {
49  switch_set_string(buf, module_name);
50  if ((param = strchr(buf, ':'))) {
51  *param++ = '\0';
52  module_name = buf;
53  }
54  }
55 
56  switch_assert(ah != NULL);
57 
58  if ((ah->asr_interface = switch_loadable_module_get_asr_interface(module_name)) == 0) {
59  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid ASR module [%s]!\n", module_name);
60  return SWITCH_STATUS_GENERR;
61  }
62 
63  ah->flags = *flags;
64 
65  if (pool) {
66  ah->memory_pool = pool;
67  } else {
68  if ((status = switch_core_new_memory_pool(&ah->memory_pool)) != SWITCH_STATUS_SUCCESS) {
69  UNPROTECT_INTERFACE(ah->asr_interface);
70  return status;
71  }
73  }
74 
75  if (param) {
76  ah->param = switch_core_strdup(ah->memory_pool, param);
77  }
78  ah->rate = rate;
79  ah->name = switch_core_strdup(ah->memory_pool, module_name);
80  ah->samplerate = rate;
81  ah->native_rate = rate;
82 
83  status = ah->asr_interface->asr_open(ah, codec, rate, dest, flags);
84 
85  if (status != SWITCH_STATUS_SUCCESS) {
86  UNPROTECT_INTERFACE(ah->asr_interface);
87  }
88 
89  return status;
90 
91 }
92 
94 {
96  char *param_string = NULL;
97  char *data = NULL;
98  char *lgrammar = NULL;
99 
100  switch_assert(ah != NULL);
101 
102  if (zstr(grammar)) {
103  status = SWITCH_STATUS_FALSE;
104  goto done;
105  }
106 
107  /* Set ASR parameters from params in the grammar string
108  * Params are defined as follows {name1=val1,name2=val2,name3=val3}grammar text
109  */
110  lgrammar = strdup(grammar);
111  data = lgrammar;
112 
113  /* strip leading spaces */
114  while (data && *data == ' ') {
115  data++;
116  }
117  if (zstr(data)) {
118  status = SWITCH_STATUS_FALSE;
119  goto done;
120  }
121 
122  /* extract params */
123  if (*data == '{') {
124  param_string = data + 1;
125  data = switch_find_end_paren(data, '{', '}');
126  if (zstr(data)) {
127  status = SWITCH_STATUS_FALSE;
128  goto done;
129  } else {
130  *data = '\0';
131  data++;
132  }
133  }
134 
135  /* set ASR params */
136  if (!zstr(param_string)) {
137  char *param[256] = { 0 };
138  int i;
139  int argc = switch_separate_string(param_string, ',', param, (sizeof(param) / sizeof(param[0])));
140  for (i = 0; i < argc && param[i]; ++i) {
141  char *param_pair[2] = { 0 };
142  if (switch_separate_string(param[i], '=', param_pair, (sizeof(param_pair) / sizeof(param_pair[0]))) == 2) {
143  switch_core_asr_text_param(ah, param_pair[0], param_pair[1]);
144  }
145  }
146  }
147 
148  status = ah->asr_interface->asr_load_grammar(ah, data, name);
149 
150  done:
151 
152  switch_safe_free(lgrammar);
153  return status;
154 }
155 
157 {
158  switch_status_t status;
159 
160  switch_assert(ah != NULL);
161  status = ah->asr_interface->asr_unload_grammar(ah, name);
162 
163  return status;
164 }
165 
167 {
169 
170  switch_assert(ah != NULL);
171 
172  if (ah->asr_interface->asr_enable_grammar) {
173  status = ah->asr_interface->asr_enable_grammar(ah, name);
174  }
175 
176  return status;
177 }
178 
180 {
182 
183  switch_assert(ah != NULL);
184 
185  if (ah->asr_interface->asr_disable_grammar) {
186  status = ah->asr_interface->asr_disable_grammar(ah, name);
187  }
188 
189  return status;
190 }
191 
193 {
195 
196  switch_assert(ah != NULL);
197 
198  if (ah->asr_interface->asr_disable_all_grammars) {
199  status = ah->asr_interface->asr_disable_all_grammars(ah);
200  }
201 
202  return status;
203 }
204 
206 {
207  switch_assert(ah != NULL);
208 
209  return ah->asr_interface->asr_pause(ah);
210 }
211 
213 {
214  switch_assert(ah != NULL);
215 
216  return ah->asr_interface->asr_resume(ah);
217 }
218 
220 {
221  switch_status_t status;
222 
223  switch_assert(ah != NULL);
224 
225  status = ah->asr_interface->asr_close(ah, flags);
227 
228  switch_resample_destroy(&ah->resampler);
229 
230  UNPROTECT_INTERFACE(ah->asr_interface);
231 
233  switch_core_destroy_memory_pool(&ah->memory_pool);
234  }
235 
236  return status;
237 }
238 
240 {
241  switch_size_t orig_len = len;
242  switch_assert(ah != NULL);
243 
244  if (ah->native_rate && ah->samplerate && ah->native_rate != ah->samplerate) {
245  if (!ah->resampler) {
246  if (switch_resample_create(&ah->resampler,
247  ah->samplerate, ah->native_rate, (uint32_t) orig_len, SWITCH_RESAMPLE_QUALITY, 1) != SWITCH_STATUS_SUCCESS) {
248  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
249  return SWITCH_STATUS_GENERR;
250  }
251  }
252 
253  switch_resample_process(ah->resampler, data, len / 2);
254  if (ah->resampler->to_len > orig_len) {
255  if (!ah->dbuf) {
256  void *mem;
257  ah->dbuflen = ah->resampler->to_len * 2;
258  mem = realloc(ah->dbuf, ah->dbuflen);
259  switch_assert(mem);
260  ah->dbuf = mem;
261  }
262  switch_assert(ah->resampler->to_len * 2 <= ah->dbuflen);
263  memcpy(ah->dbuf, ah->resampler->to, ah->resampler->to_len * 2);
264  data = ah->dbuf;
265  } else {
266  memcpy(data, ah->resampler->to, ah->resampler->to_len * 2);
267  }
268 
269  len = ah->resampler->to_len;
270  }
271 
272  return ah->asr_interface->asr_feed(ah, data, len, flags);
273 }
274 
276 {
278 
279  switch_assert(ah != NULL);
280 
281  if (ah->asr_interface->asr_feed_dtmf) {
282  status = ah->asr_interface->asr_feed_dtmf(ah, dtmf, flags);
283  }
284 
285  return status;
286 }
287 
289 {
290  switch_assert(ah != NULL);
291 
292  return ah->asr_interface->asr_check_results(ah, flags);
293 }
294 
296 {
297  switch_assert(ah != NULL);
298 
299  return ah->asr_interface->asr_get_results(ah, xmlstr, flags);
300 }
301 
303 {
304  switch_assert(ah != NULL);
305 
306  if (ah->asr_interface->asr_get_result_headers) {
307  return ah->asr_interface->asr_get_result_headers(ah, headers, flags);
308  } else {
309  /* Since this is not always implemented, return success if the function can't be called */
310  return SWITCH_STATUS_SUCCESS;
311  }
312 }
313 
315 {
317 
318  switch_assert(ah != NULL);
319 
320  if (ah->asr_interface->asr_start_input_timers) {
321  status = ah->asr_interface->asr_start_input_timers(ah);
322  }
323 
324  return status;
325 }
326 
327 SWITCH_DECLARE(void) switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val)
328 {
329  switch_assert(ah != NULL);
330 
331  if (ah->asr_interface->asr_text_param) {
332  ah->asr_interface->asr_text_param(ah, param, val);
333  }
334 }
335 
337 {
338  switch_assert(ah != NULL);
339 
340  if (ah->asr_interface->asr_numeric_param) {
341  ah->asr_interface->asr_numeric_param(ah, param, val);
342  }
343 }
344 
346 {
347  switch_assert(ah != NULL);
348 
349  if (ah->asr_interface->asr_float_param) {
350  ah->asr_interface->asr_float_param(ah, param, val);
351  }
352 }
353 
354 /* For Emacs:
355  * Local Variables:
356  * mode:c
357  * indent-tabs-mode:t
358  * tab-width:4
359  * c-basic-offset:4
360  * End:
361  * For VIM:
362  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
363  */
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:631
switch_status_t switch_core_asr_start_input_timers(switch_asr_handle_t *ah)
Start input timers on an asr handle.
char name[CACHE_DB_LEN]
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
#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:661
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 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:729
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 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:640
switch_memory_pool_t * pool
Representation of an event.
Definition: switch_event.h:80
#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.
void switch_resample_destroy(switch_audio_resampler_t **resampler)
Destroy an existing resampler handle.
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:281
#define UNPROTECT_INTERFACE(_it)
switch_byte_t switch_byte_t * buf
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.
void switch_core_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val)
Set a numeric parameter on an asr handle.
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
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_asr_interface_t * switch_loadable_module_get_asr_interface(const char *name)
Retrieve the asr interface by it's registered name.
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)
#define switch_set_string(_dst, _src)
Definition: switch_utils.h:665
struct apr_pool_t switch_memory_pool_t
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:624
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.
#define switch_assert(expr)
switch_status_t switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name)
Unload a grammar from an asr handle.
void switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val)
Set a text parameter on an asr handle.
#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.