FreeSWITCH API Documentation  1.7.0
switch_speex.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  * Christopher M. Rienzo <chris@rienzo.com>
28  *
29  *
30  * core_speex.c -- Speex Codec Module
31  *
32  */
33 
34 #include <switch.h>
35 #include <speex/speex.h>
36 #include <speex/speex_preprocess.h>
37 
38 #ifdef WIN32
39 #undef SWITCH_MOD_DECLARE_DATA
40 #define SWITCH_MOD_DECLARE_DATA __declspec(dllexport)
41 #endif
42 SWITCH_MODULE_LOAD_FUNCTION(core_speex_load);
43 SWITCH_MODULE_DEFINITION(CORE_SPEEX_MODULE, core_speex_load, NULL, NULL);
44 
45 /* nobody has more setting than speex so we will let them set the standard */
46 /*! \brief Various codec settings (currently only relevant to speex) */
48  /*! desired quality */
49  int quality;
50  /*! desired complexity */
52  /*! desired enhancement */
54  /*! desired vad level */
55  int vad;
56  /*! desired vbr level */
57  int vbr;
58  /*! desired vbr quality */
59  float vbr_quality;
60  /*! desired abr level */
61  int abr;
62  /*! desired dtx setting */
63  int dtx;
64  /*! desired preprocessor settings */
65  int preproc;
66  /*! preprocessor vad settings */
67  int pp_vad;
68  /*! preprocessor gain control settings */
69  int pp_agc;
70  /*! preprocessor gain level */
71  float pp_agc_level;
72  /*! preprocessor denoise level */
74  /*! preprocessor dereverb settings */
76  /*! preprocessor dereverb decay level */
78  /*! preprocessor dereverb level */
80 };
81 
83 
85  /*.quality */ 5,
86  /*.complexity */ 5,
87  /*.enhancement */ 1,
88  /*.vad */ 0,
89  /*.vbr */ 0,
90  /*.vbr_quality */ 4,
91  /*.abr */ 0,
92  /*.dtx */ 0,
93  /*.preproc */ 0,
94  /*.pp_vad */ 0,
95  /*.pp_agc */ 0,
96  /*.pp_agc_level */ 8000,
97  /*.pp_denoise */ 0,
98  /*.pp_dereverb */ 0,
99  /*.pp_dereverb_decay */ 0.4f,
100  /*.pp_dereverb_level */ 0.3f,
101 };
102 
106  unsigned int flags;
107 
108  /* Encoder */
110  struct SpeexBits encoder_bits;
111  unsigned int encoder_frame_size;
113  SpeexPreprocessState *pp;
114 
115  /* Decoder */
117  struct SpeexBits decoder_bits;
118  unsigned int decoder_frame_size;
120 };
121 
122 static switch_status_t switch_speex_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
123 {
124  speex_codec_settings_t *codec_settings = NULL;
125  int x, argc;
126  char *argv[10];
127  char *fmtp_dup = NULL;
128 
129  if (!codec_fmtp) {
130  return SWITCH_STATUS_FALSE;
131  }
132 
133  /* load default settings */
134  if (codec_fmtp->private_info) {
135  codec_settings = codec_fmtp->private_info;
136  memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
137  } else {
138  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "codec_fmtp->private_info is NULL\n");
139  return SWITCH_STATUS_SUCCESS;
140  }
141 
142  if (!fmtp) {
143  return SWITCH_STATUS_SUCCESS;
144  }
145 
146  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "got fmtp: %s\n", fmtp);
147 
148  fmtp_dup = strdup(fmtp);
149  switch_assert(fmtp_dup);
150 
151  /* parse ; separated fmtp args */
152  argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
153  for (x = 0; x < argc; x++) {
154  char *data = argv[x];
155  char *arg;
156  switch_assert(data);
157  while (*data == ' ') {
158  data++;
159  }
160  if (!(arg = strchr(data, '='))) {
161  continue;
162  }
163  *arg++ = '\0';
164  if (zstr(arg)) {
165  continue;
166  }
167 
168  if (!strcasecmp("vbr", data)) {
169  /* vbr can be on/off/vad */
170  if (!strcasecmp("vad", arg)) {
171  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "enabling speex vbr=vad\n");
172  codec_settings->vbr = 0;
173  codec_settings->vad = 1;
174  codec_settings->pp_vad = 1;
175  } else {
176  if (switch_true(arg)) {
177  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "enabling speex vbr\n");
178  codec_settings->vbr = 1;
179  codec_settings->vad = 0;
180  codec_settings->pp_vad = 1;
181  } else {
182  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "disabling speex vbr\n");
183  codec_settings->vbr = 0;
184  codec_settings->vad = 0;
185  codec_settings->pp_vad = 0;
186  }
187  }
188  } else if (!strcasecmp("cng", data)) {
189  /* TODO don't know how to turn on CNG */
190  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "speex cng is unsupported\n");
191  } else if (!strcasecmp("mode", data)) {
192  /* mode is a comma-separate list of preferred modes. Use the first mode in the list */
193  char *arg_dup;
194  char *mode[2];
195  if (!strncasecmp("any", arg, 3)) {
196  /* "any", keep the default setting */
197  continue;
198  }
199  arg_dup = strdup(arg);
200  if (switch_separate_string(arg_dup, ',', mode, (sizeof(mode) / sizeof(mode[0])))) {
201  int mode_num = -1;
202  char *mode_str = mode[0];
203  if (mode_str[0] == '"') {
204  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "mode starts with \"\n");
205  mode_str++;
206  }
207  if (switch_is_number(mode_str)) {
208  mode_num = atoi(mode_str);
209  }
210  /* TODO there might be a way to set the mode directly instead of changing the quality */
211  if (codec_fmtp->actual_samples_per_second == 8000) {
212  switch (mode_num) {
213  case 1:
214  codec_settings->quality = 0;
215  break;
216  case 2:
217  codec_settings->quality = 2;
218  break;
219  case 3:
220  codec_settings->quality = 4;
221  break;
222  case 4:
223  codec_settings->quality = 6;
224  break;
225  case 5:
226  codec_settings->quality = 8;
227  break;
228  case 6:
229  codec_settings->quality = 9;
230  break;
231  case 7:
232  codec_settings->quality = 10;
233  break;
234  case 8:
235  codec_settings->quality = 1;
236  break;
237  default:
238  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "ignoring invalid speex/8000 mode %s\n", mode_str);
239  continue;
240  }
241  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "choosing speex/8000 mode %s\n", mode_str);
242  codec_settings->vbr_quality = (float)codec_settings->quality;
243  } else {
244  if (mode_num >= 0 && mode_num <= 10) {
245  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "choosing speex/%d mode %s\n", codec_fmtp->actual_samples_per_second, mode_str);
246  codec_settings->quality = mode_num;
247  codec_settings->vbr_quality = (float)mode_num;
248  } else {
249  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "ignoring invalid speex/%d mode %s\n", codec_fmtp->actual_samples_per_second, mode_str);
250  continue;
251  }
252  }
253  }
254  free(arg_dup);
255  }
256  }
257  free(fmtp_dup);
258  /*codec_fmtp->bits_per_second = bit_rate;*/
259  return SWITCH_STATUS_SUCCESS;
260 }
261 
262 
264 {
265  struct speex_context *context = NULL;
266  int encoding, decoding;
267 
268  encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
269  decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
270 
271  if (!(encoding || decoding) || ((context = switch_core_alloc(codec->memory_pool, sizeof(*context))) == 0)) {
272  return SWITCH_STATUS_FALSE;
273  } else {
274  const SpeexMode *mode = NULL;
275  switch_codec_fmtp_t codec_fmtp;
277 
278  memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
279  codec_fmtp.private_info = &codec_settings;
281  switch_speex_fmtp_parse(codec->fmtp_in, &codec_fmtp);
282 
283  memcpy(&context->codec_settings, &codec_settings, sizeof(context->codec_settings));
284 
285  context->codec = codec;
286  if (codec->implementation->actual_samples_per_second == 8000) {
287  mode = &speex_nb_mode;
288  } else if (codec->implementation->actual_samples_per_second == 16000) {
289  mode = &speex_wb_mode;
290  } else if (codec->implementation->actual_samples_per_second == 32000) {
291  mode = &speex_uwb_mode;
292  }
293 
294  if (!mode) {
295  return SWITCH_STATUS_FALSE;
296  }
297 
298  if (encoding) {
299  speex_bits_init(&context->encoder_bits);
300  context->encoder_state = speex_encoder_init(mode);
301  speex_encoder_ctl(context->encoder_state, SPEEX_GET_FRAME_SIZE, &context->encoder_frame_size);
302  speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &context->codec_settings.complexity);
303  if (context->codec_settings.preproc) {
305  context->pp = speex_preprocess_state_init(context->encoder_frame_size, codec->implementation->actual_samples_per_second);
306  if (context->codec_settings.pp_vad) {
307  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "preprocessor vad on\n");
308  }
309  speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &context->codec_settings.pp_vad);
310  if (context->codec_settings.pp_agc) {
311  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "preprocessor agc on\n");
312  }
313  speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC, &context->codec_settings.pp_agc);
314  speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &context->codec_settings.pp_agc_level);
315  if (context->codec_settings.pp_denoise) {
316  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "preprocessor denoise on\n");
317  }
318  speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &context->codec_settings.pp_denoise);
319  if (context->codec_settings.pp_dereverb) {
320  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "preprocessor dereverb on\n");
321  }
322  speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB, &context->codec_settings.pp_dereverb);
323  speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &context->codec_settings.pp_dereverb_decay);
324  speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &context->codec_settings.pp_dereverb_level);
325  }
326 
327  if (!context->codec_settings.abr && !context->codec_settings.vbr) {
328  speex_encoder_ctl(context->encoder_state, SPEEX_SET_QUALITY, &context->codec_settings.quality);
329  if (context->codec_settings.vad) {
331  speex_encoder_ctl(context->encoder_state, SPEEX_SET_VAD, &context->codec_settings.vad);
332  }
333  }
334  if (context->codec_settings.vbr) {
336  speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR, &context->codec_settings.vbr);
337  speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR_QUALITY, &context->codec_settings.vbr_quality);
338  }
339  if (context->codec_settings.abr) {
341  speex_encoder_ctl(context->encoder_state, SPEEX_SET_ABR, &context->codec_settings.abr);
342  }
343  if (context->codec_settings.dtx) {
345  speex_encoder_ctl(context->encoder_state, SPEEX_SET_DTX, &context->codec_settings.dtx);
346  }
347  }
348 
349  if (decoding) {
350  speex_bits_init(&context->decoder_bits);
351  context->decoder_state = speex_decoder_init(mode);
352  if (context->codec_settings.enhancement) {
353  speex_decoder_ctl(context->decoder_state, SPEEX_SET_ENH, &context->codec_settings.enhancement);
354  }
355  }
356 
357 
358 
359  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "initialized Speex codec \n");
360  codec->private_info = context;
361  return SWITCH_STATUS_SUCCESS;
362  }
363 }
364 
366  switch_codec_t *other_codec,
367  void *decoded_data,
368  uint32_t decoded_data_len,
369  uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate,
370  unsigned int *flag)
371 {
372  struct speex_context *context = codec->private_info;
373  short *buf;
374  int is_speech = 1;
375 
376  if (!context) {
377  return SWITCH_STATUS_FALSE;
378  }
379 
380  buf = decoded_data;
381 
382  if (context->pp) {
383  is_speech = speex_preprocess(context->pp, buf, NULL);
384  }
385 
386  if (is_speech) {
387  is_speech = speex_encode_int(context->encoder_state, buf, &context->encoder_bits)
388  || !context->codec_settings.dtx;
389  } else {
390  speex_bits_pack(&context->encoder_bits, 0, 5);
391  }
392 
393 
394  if (is_speech) {
396  *flag &= ~SFF_CNG;
397  } else {
399  *encoded_data_len = 0;
400  *flag |= SFF_CNG;
401  return SWITCH_STATUS_SUCCESS;
402  }
403 
405  }
406 
407 
408  speex_bits_pack(&context->encoder_bits, 15, 5);
409  *encoded_data_len = speex_bits_write(&context->encoder_bits, (char *) encoded_data, context->encoder_frame_size);
410  speex_bits_reset(&context->encoder_bits);
411  (*encoded_data_len)--;
412 
413  return SWITCH_STATUS_SUCCESS;
414 }
415 
417  switch_codec_t *other_codec,
418  void *encoded_data,
419  uint32_t encoded_data_len,
420  uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate,
421  unsigned int *flag)
422 {
423  struct speex_context *context = codec->private_info;
424  short *buf;
425 
426  if (!context) {
427  return SWITCH_STATUS_FALSE;
428  }
429 
430 
431  buf = decoded_data;
432  if (*flag & SWITCH_CODEC_FLAG_SILENCE) {
433  speex_decode_int(context->decoder_state, NULL, buf);
434  } else {
435  speex_bits_read_from(&context->decoder_bits, (char *) encoded_data, (int) encoded_data_len);
436  speex_decode_int(context->decoder_state, &context->decoder_bits, buf);
437  }
438  *decoded_data_len = codec->implementation->decoded_bytes_per_packet;
439 
440  return SWITCH_STATUS_SUCCESS;
441 }
442 
444 {
445  int encoding, decoding;
446  struct speex_context *context = codec->private_info;
447 
448  if (!context) {
449  return SWITCH_STATUS_FALSE;
450  }
451 
452  encoding = (codec->flags & SWITCH_CODEC_FLAG_ENCODE);
453  decoding = (codec->flags & SWITCH_CODEC_FLAG_DECODE);
454 
455  if (encoding) {
456  speex_bits_destroy(&context->encoder_bits);
457  speex_encoder_destroy(context->encoder_state);
458  }
459 
460  if (decoding) {
461  speex_bits_destroy(&context->decoder_bits);
462  speex_decoder_destroy(context->decoder_state);
463  }
464 
465  codec->private_info = NULL;
466 
467  return SWITCH_STATUS_SUCCESS;
468 }
469 
470 /**
471  * read default settings from speex.conf
472  */
473 static void load_configuration()
474 {
475  switch_xml_t xml = NULL, cfg = NULL;
476 
477  if ((xml = switch_xml_open_cfg("speex.conf", &cfg, NULL))) {
478  switch_xml_t x_lists;
479  if ((x_lists = switch_xml_child(cfg, "settings"))) {
480  const char *settings_name = switch_xml_attr(x_lists, "name");
481  switch_xml_t x_list;
482  if (zstr(settings_name)) {
483  settings_name = "";
484  }
485  for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
486  const char *name = switch_xml_attr(x_list, "name");
487  const char *value = switch_xml_attr(x_list, "value");
488  if (zstr(name)) {
489  continue;
490  }
491 
492  if (zstr(value)) {
493  continue;
494  }
495 
496  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s %s = %s\n", settings_name, name, value);
497 
498  if (!strcasecmp("quality", name)) {
499  /* compression quality, integer 0-10 */
500  int tmp = atoi(value);
501  if (switch_is_number(value) && tmp >= 0 && tmp <= 10) {
502  default_codec_settings.quality = tmp;
503  } else {
504  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid quality value: %s\n", value);
505  }
506  } else if (!strcasecmp("complexity", name)) {
507  /* compression complexity, integer 1-10 */
508  int tmp = atoi(value);
509  if (switch_is_number(value) && tmp >= 1 && tmp <= 10) {
510  default_codec_settings.complexity = tmp;
511  } else {
512  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid complexity value: %s\n", value);
513  }
514  } else if (!strcasecmp("enhancement", name)) {
515  /* enable perceptual enhancement, boolean */
516  default_codec_settings.enhancement = switch_true(value);
517  } else if (!strcasecmp("vad", name)) {
518  /* enable voice activity detection, boolean */
519  default_codec_settings.vad = switch_true(value);
520  } else if (!strcasecmp("vbr", name)) {
521  /* enable variable bit rate, boolean */
522  default_codec_settings.vbr = switch_true(value);
523  } else if (!strcasecmp("vbr-quality", name)) {
524  /* variable bit rate quality, float 0-10 */
525  float tmp = (float)atof(value);
526  if (switch_is_number(value) && tmp >= 0 && tmp <= 10) {
527  default_codec_settings.vbr_quality = tmp;
528  } else {
529  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid vbr-quality value: %s\n", value);
530  }
531  } else if (!strcasecmp("abr", name)) {
532  /* average bit rate, integer bits per sec */
533  int tmp = atoi(value);
534  if (switch_is_number(value) && tmp >= 0) {
535  default_codec_settings.abr = tmp;
536  } else {
537  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid abr value: %s\n", value);
538  }
539  } else if (!strcasecmp("dtx", name)) {
540  /* discontinuous transmit, boolean */
541  default_codec_settings.dtx = switch_true(value);
542  } else if (!strcasecmp("preproc", name)) {
543  /* enable preprocessor, boolean */
544  default_codec_settings.preproc = switch_true(value);
545  } else if (!strcasecmp("pp-vad", name)) {
546  /* enable preprocessor VAD, boolean */
547  default_codec_settings.pp_vad = switch_true(value);
548  } else if (!strcasecmp("pp-agc", name)) {
549  /* enable preprocessor automatic gain control, boolean */
550  default_codec_settings.pp_agc = switch_true(value);
551  } else if (!strcasecmp("pp-agc-level", name)) {
552  /* agc level, float */
553  float tmp = (float)atof(value);
554  if (switch_is_number(value) && tmp >= 0.0f) {
555  default_codec_settings.pp_agc_level = tmp;
556  } else {
557  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid pp-agc-level value: %s\n", value);
558  }
559  } else if (!strcasecmp("pp-denoise", name)) {
560  /* enable preprocessor denoiser, boolean */
561  default_codec_settings.pp_denoise = switch_true(value);
562  } else if (!strcasecmp("pp-dereverb", name)) {
563  /* enable preprocessor reverberation removal, boolean */
564  default_codec_settings.pp_dereverb = switch_true(value);
565  } else if (!strcasecmp("pp-dereverb-decay", name)) {
566  /* reverberation removal decay, float */
567  float tmp = (float)atof(value);
568  if (switch_is_number(value) && tmp >= 0.0f) {
569  default_codec_settings.pp_dereverb_decay = tmp;
570  } else {
571  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid pp-dereverb-decay value: %s\n", value);
572  }
573  } else if (!strcasecmp("pp-dereverb-level", name)) {
574  /* reverberation removal level, float */
575  float tmp = (float)atof(value);
576  if (switch_is_number(value) && tmp >= 0.0f) {
577  default_codec_settings.pp_dereverb_level = tmp;
578  } else {
579  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid pp-dereverb-level value: %s\n", value);
580  }
581  } else {
582  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid unknown param: %s = %s\n", name, value);
583  }
584  }
585  }
586  switch_xml_free(xml);
587  }
588 }
589 
591 {
592  switch_codec_interface_t *codec_interface;
593  int mpf = 20000, spf = 160, bpf = 320, rate = 8000, counta, countb;
594  switch_payload_t ianacode[4] = { 0, 99, 99, 99 };
595  int bps[4] = { 0, 24600, 42200, 44000 };
596  /* connect my internal structure to the blank pointer passed to me */
597  *module_interface = switch_loadable_module_create_module_interface(pool, modname);
598 
600 
601  SWITCH_ADD_CODEC(codec_interface, "Speex");
602  codec_interface->parse_fmtp = switch_speex_fmtp_parse;
603  for (counta = 1; counta <= 3; counta++) {
604  for (countb = 1; countb > 0; countb--) {
605  switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
606  ianacode[counta], /* the IANA code number */
607  "SPEEX", /* the IANA code name */
608  NULL, /* default fmtp to send (can be overridden by the init function) */
609  rate, /* samples transferred per second */
610  rate, /* actual samples transferred per second */
611  bps[counta], /* bits transferred per second */
612  mpf * countb, /* number of microseconds per frame */
613  spf * countb, /* number of samples per frame */
614  bpf * countb, /* number of bytes per frame decompressed */
615  0, /* number of bytes per frame compressed */
616  1, /* number of channels represented */
617  1, /* number of frames per network packet */
618  switch_speex_init, /* function to initialize a codec handle using this implementation */
619  switch_speex_encode, /* function to encode raw data into encoded data */
620  switch_speex_decode, /* function to decode encoded data into raw data */
621  switch_speex_destroy); /* deinitalize a codec handle using this implementation */
622  }
623  rate = rate * 2;
624  spf = spf * 2;
625  bpf = bpf * 2;
626  }
627 
628 
629 
630 
631  /* indicate that the module should continue to be loaded */
632  return SWITCH_STATUS_SUCCESS;
633 }
634 
635 /* For Emacs:
636  * Local Variables:
637  * mode:c
638  * indent-tabs-mode:t
639  * tab-width:4
640  * c-basic-offset:4
641  * End:
642  * For VIM:
643  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
644  */
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
SpeexPreprocessState * pp
Definition: switch_speex.c:113
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
#define SWITCH_CHANNEL_LOG
const char * switch_xml_attr(_In_opt_ switch_xml_t xml, _In_opt_z_ const char *attr)
returns the value of the requested tag attribute, or NULL if not found
SWITCH_MODULE_LOAD_FUNCTION(core_speex_load)
Definition: switch_speex.c:590
void * decoder_state
Definition: switch_speex.c:116
switch_memory_pool_t * pool
speex_codec_settings_t codec_settings
Definition: switch_speex.c:105
static void switch_core_codec_add_implementation(switch_memory_pool_t *pool, switch_codec_interface_t *codec_interface, const switch_codec_type_t codec_type, switch_payload_t ianacode, const char *iananame, char *fmtp, uint32_t samples_per_second, uint32_t actual_samples_per_second, int bits_per_second, int microseconds_per_packet, uint32_t samples_per_packet, uint32_t decoded_bytes_per_packet, uint32_t encoded_bytes_per_packet, uint8_t number_of_channels, int codec_frames_per_packet, switch_core_codec_init_func_t init, switch_core_codec_encode_func_t encode, switch_core_codec_decode_func_t decode, switch_core_codec_destroy_func_t destroy)
switch_bool_t switch_is_number(const char *str)
struct SpeexBits decoder_bits
Definition: switch_speex.c:117
A representation of an XML tree.
Definition: switch_xml.h:76
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
Definition: switch_speex.c:263
#define zstr(x)
Definition: switch_utils.h:281
uint32_t switch_codec_flag_t
static switch_status_t switch_speex_encode(switch_codec_t *codec, switch_codec_t *other_codec, void *decoded_data, uint32_t decoded_data_len, uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag)
Definition: switch_speex.c:365
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:655
static switch_status_t switch_speex_decode(switch_codec_t *codec, switch_codec_t *other_codec, void *encoded_data, uint32_t encoded_data_len, uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
Definition: switch_speex.c:416
const switch_codec_implementation_t * implementation
switch_xml_t next
Definition: switch_xml.h:88
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.
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:682
switch_memory_pool_t * memory_pool
void * encoder_state
Definition: switch_speex.c:109
unsigned int flags
Definition: switch_speex.c:106
Top level module interface to implement a series of codec implementations.
switch_byte_t switch_byte_t uint32_t switch_bitpack_mode_t mode
unsigned int encoder_frame_size
Definition: switch_speex.c:111
#define SWITCH_ADD_CODEC(codec_int, int_name)
switch_status_t
Common return values.
switch_core_codec_fmtp_parse_func_t parse_fmtp
switch_xml_t switch_xml_open_cfg(_In_z_ const char *file_path, _Out_ switch_xml_t *node, _In_opt_ switch_event_t *params)
open a config in the core registry
static void load_configuration()
Definition: switch_speex.c:473
switch_loadable_module_interface_t * switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name)
Main Library Header.
switch_codec_t * codec
Definition: switch_speex.c:104
unsigned int decoder_frame_size
Definition: switch_speex.c:118
SWITCH_MODULE_DEFINITION(CORE_SPEEX_MODULE, core_speex_load, NULL, NULL)
switch_xml_t switch_xml_child(_In_ switch_xml_t xml, _In_z_ const char *name)
returns the first child tag (one level deeper) with the given name or NULL \ if not found ...
#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.
static switch_status_t switch_speex_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
Definition: switch_speex.c:122
#define switch_assert(expr)
memset(buf, 0, buflen)
static switch_status_t switch_speex_destroy(switch_codec_t *codec)
Definition: switch_speex.c:443
uint8_t switch_payload_t
Various codec settings (currently only relevant to speex)
Definition: switch_speex.c:47
static speex_codec_settings_t default_codec_settings
Definition: switch_speex.c:84
struct SpeexBits encoder_bits
Definition: switch_speex.c:110