Asterisk - The Open Source Telephony Project  GIT-master-0190e70
codec_speex.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19 
20 /*! \file
21  *
22  * \brief Translate between signed linear and Speex (Open Codec)
23  *
24  * \note This work was motivated by Jeremy McNamara
25  * hacked to be configurable by anthm and bkw 9/28/2004
26  *
27  * \ingroup codecs
28  *
29  * The Speex library - http://www.speex.org
30  *
31  */
32 
33 /*** MODULEINFO
34  <depend>speex</depend>
35  <depend>speex_preprocess</depend>
36  <use type="external">speexdsp</use>
37  <support_level>core</support_level>
38  ***/
39 
40 #include "asterisk.h"
41 
42 #include <speex/speex.h>
43 
44 /* We require a post 1.1.8 version of Speex to enable preprocessing
45  * and better type handling
46  */
47 #ifdef _SPEEX_TYPES_H
48 #include <speex/speex_preprocess.h>
49 #endif
50 
51 #include "asterisk/translate.h"
52 #include "asterisk/module.h"
53 #include "asterisk/config.h"
54 #include "asterisk/utils.h"
55 #include "asterisk/frame.h"
56 #include "asterisk/linkedlists.h"
57 
58 /* For struct ast_rtp_rtcp_report and struct ast_rtp_rtcp_report_block */
59 #include "asterisk/rtp_engine.h"
60 
61 /* codec variables */
62 static int quality = 3;
63 static int complexity = 2;
64 static int enhancement = 0;
65 static int vad = 0;
66 static int vbr = 0;
67 static float vbr_quality = 4;
68 static int abr = 0;
69 static int dtx = 0; /* set to 1 to enable silence detection */
70 static int exp_rtcp_fb = 0; /* set to 1 to use experimental RTCP feedback for changing bitrate */
71 
72 static int preproc = 0;
73 static int pp_vad = 0;
74 static int pp_agc = 0;
75 static float pp_agc_level = 8000; /* XXX what is this 8000 ? */
76 static int pp_denoise = 0;
77 static int pp_dereverb = 0;
78 static float pp_dereverb_decay = 0.4;
79 static float pp_dereverb_level = 0.3;
80 
81 #define TYPE_SILENCE 0x2
82 #define TYPE_HIGH 0x0
83 #define TYPE_LOW 0x1
84 #define TYPE_MASK 0x3
85 
86 #define BUFFER_SAMPLES 8000
87 #define SPEEX_SAMPLES 160
88 
89 /* Sample frame data */
90 #include "asterisk/slin.h"
91 #include "ex_speex.h"
92 
94  void *speex;
95  SpeexBits bits;
96  int framesize;
98 
100  int quality;
102 
103 #ifdef _SPEEX_TYPES_H
104  SpeexPreprocessState *pp;
105  spx_int16_t buf[BUFFER_SAMPLES];
106 #else
107  int16_t buf[BUFFER_SAMPLES]; /* input, waiting to be compressed */
108 #endif
109 };
110 
111 static int speex_encoder_construct(struct ast_trans_pvt *pvt, const SpeexMode *profile, int sampling_rate)
112 {
113  struct speex_coder_pvt *tmp = pvt->pvt;
114 
115  if (!(tmp->speex = speex_encoder_init(profile)))
116  return -1;
117 
118  speex_bits_init(&tmp->bits);
119  speex_bits_reset(&tmp->bits);
120  speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
121  speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity);
122 #ifdef _SPEEX_TYPES_H
123  if (preproc) {
124  tmp->pp = speex_preprocess_state_init(tmp->framesize, sampling_rate);
125  speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_VAD, &pp_vad);
126  speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC, &pp_agc);
127  speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &pp_agc_level);
128  speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DENOISE, &pp_denoise);
129  speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB, &pp_dereverb);
130  speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &pp_dereverb_decay);
131  speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &pp_dereverb_level);
132  }
133 #endif
134  if (!abr && !vbr) {
135  speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality);
136  if (vad)
137  speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad);
138  }
139  if (vbr) {
140  speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr);
141  speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality);
142  }
143  if (abr)
144  speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr);
145  if (dtx)
146  speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &dtx);
147  tmp->silent_state = 0;
148 
149  tmp->fraction_lost = 0;
151  tmp->quality = tmp->default_quality;
152  ast_debug(3, "Default quality (%s): %d\n", vbr ? "vbr" : "cbr", tmp->default_quality);
153 
154  return 0;
155 }
156 
157 static int lintospeex_new(struct ast_trans_pvt *pvt)
158 {
159  return speex_encoder_construct(pvt, &speex_nb_mode, 8000);
160 }
161 
162 static int lin16tospeexwb_new(struct ast_trans_pvt *pvt)
163 {
164  return speex_encoder_construct(pvt, &speex_wb_mode, 16000);
165 }
166 
167 static int lin32tospeexuwb_new(struct ast_trans_pvt *pvt)
168 {
169  return speex_encoder_construct(pvt, &speex_uwb_mode, 32000);
170 }
171 
172 static int speex_decoder_construct(struct ast_trans_pvt *pvt, const SpeexMode *profile)
173 {
174  struct speex_coder_pvt *tmp = pvt->pvt;
175 
176  if (!(tmp->speex = speex_decoder_init(profile)))
177  return -1;
178 
179  speex_bits_init(&tmp->bits);
180  speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
181  if (enhancement)
182  speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement);
183 
184  return 0;
185 }
186 
187 static int speextolin_new(struct ast_trans_pvt *pvt)
188 {
189  return speex_decoder_construct(pvt, &speex_nb_mode);
190 }
191 
192 static int speexwbtolin16_new(struct ast_trans_pvt *pvt)
193 {
194  return speex_decoder_construct(pvt, &speex_wb_mode);
195 }
196 
197 static int speexuwbtolin32_new(struct ast_trans_pvt *pvt)
198 {
199  return speex_decoder_construct(pvt, &speex_uwb_mode);
200 }
201 
202 /*! \brief convert and store into outbuf */
203 static int speextolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
204 {
205  struct speex_coder_pvt *tmp = pvt->pvt;
206 
207  /* Assuming there's space left, decode into the current buffer at
208  the tail location. Read in as many frames as there are */
209  int x;
210  int res;
211  int16_t *dst = pvt->outbuf.i16;
212  /* XXX fout is a temporary buffer, may have different types */
213 #ifdef _SPEEX_TYPES_H
214  spx_int16_t fout[1024];
215 #else
216  float fout[1024];
217 #endif
218 
219  if (f->datalen == 0) { /* Native PLC interpolation */
220  if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
221  ast_log(LOG_WARNING, "Out of buffer space\n");
222  return -1;
223  }
224 #ifdef _SPEEX_TYPES_H
225  speex_decode_int(tmp->speex, NULL, dst + pvt->samples);
226 #else
227  speex_decode(tmp->speex, NULL, fout);
228  for (x=0;x<tmp->framesize;x++) {
229  dst[pvt->samples + x] = (int16_t)fout[x];
230  }
231 #endif
232  pvt->samples += tmp->framesize;
233  pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
234  return 0;
235  }
236 
237  /* Read in bits */
238  speex_bits_read_from(&tmp->bits, f->data.ptr, f->datalen);
239  for (;;) {
240 #ifdef _SPEEX_TYPES_H
241  res = speex_decode_int(tmp->speex, &tmp->bits, fout);
242 #else
243  res = speex_decode(tmp->speex, &tmp->bits, fout);
244 #endif
245  if (res < 0)
246  break;
247  if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
248  ast_log(LOG_WARNING, "Out of buffer space\n");
249  return -1;
250  }
251  for (x = 0 ; x < tmp->framesize; x++)
252  dst[pvt->samples + x] = (int16_t)fout[x];
253  pvt->samples += tmp->framesize;
254  pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
255  }
256  return 0;
257 }
258 
259 /*! \brief store input frame in work buffer */
260 static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
261 {
262  struct speex_coder_pvt *tmp = pvt->pvt;
263 
264  /* XXX We should look at how old the rest of our stream is, and if it
265  is too old, then we should overwrite it entirely, otherwise we can
266  get artifacts of earlier talk that do not belong */
267  memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
268  pvt->samples += f->samples;
269  return 0;
270 }
271 
272 /*! \brief convert work buffer and produce output frame */
273 static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt)
274 {
275  struct speex_coder_pvt *tmp = pvt->pvt;
276  struct ast_frame *result = NULL;
277  struct ast_frame *last = NULL;
278  int samples = 0; /* output samples */
279 
280  while (pvt->samples >= tmp->framesize) {
281  struct ast_frame *current;
282  int is_speech = 1;
283 
284  speex_bits_reset(&tmp->bits);
285 
286 #ifdef _SPEEX_TYPES_H
287  /* Preprocess audio */
288  if (preproc)
289  is_speech = speex_preprocess(tmp->pp, tmp->buf + samples, NULL);
290  /* Encode a frame of data */
291  if (is_speech) {
292  /* If DTX enabled speex_encode returns 0 during silence */
293  is_speech = speex_encode_int(tmp->speex, tmp->buf + samples, &tmp->bits) || !dtx;
294  } else {
295  /* 5 zeros interpreted by Speex as silence (submode 0) */
296  speex_bits_pack(&tmp->bits, 0, 5);
297  }
298 #else
299  {
300  float fbuf[1024];
301  int x;
302  /* Convert to floating point */
303  for (x = 0; x < tmp->framesize; x++)
304  fbuf[x] = tmp->buf[samples + x];
305  /* Encode a frame of data */
306  is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx;
307  }
308 #endif
309  samples += tmp->framesize;
310  pvt->samples -= tmp->framesize;
311 
312  /* Use AST_FRAME_CNG to signify the start of any silence period */
313  if (is_speech) {
314  int datalen = 0; /* output bytes */
315 
316  tmp->silent_state = 0;
317  /* Terminate bit stream */
318  speex_bits_pack(&tmp->bits, 15, 5);
319  datalen = speex_bits_write(&tmp->bits, pvt->outbuf.c, pvt->t->buf_size);
320  current = ast_trans_frameout(pvt, datalen, tmp->framesize);
321  } else if (tmp->silent_state) {
322  current = NULL;
323  } else {
324  struct ast_frame frm = {
326  .src = pvt->t->name,
327  };
328 
329  /*
330  * XXX I don't think the AST_FRAME_CNG code has ever
331  * really worked for speex. There doesn't seem to be
332  * any consumers of the frame type. Everyone that
333  * references the type seems to pass the frame on.
334  */
335  tmp->silent_state = 1;
336 
337  /* XXX what now ? format etc... */
338  current = ast_frisolate(&frm);
339  }
340 
341  if (!current) {
342  continue;
343  } else if (last) {
344  AST_LIST_NEXT(last, frame_list) = current;
345  } else {
346  result = current;
347  }
348  last = current;
349  }
350 
351  /* Move the data at the end of the buffer to the front */
352  if (samples) {
353  memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
354  }
355 
356  return result;
357 }
358 
359 /*! \brief handle incoming RTCP feedback and possibly edit encoder settings */
360 static void lintospeex_feedback(struct ast_trans_pvt *pvt, struct ast_frame *feedback)
361 {
362  struct speex_coder_pvt *tmp = pvt->pvt;
363 
364  struct ast_rtp_rtcp_report *rtcp_report;
365  struct ast_rtp_rtcp_report_block *report_block;
366 
367  int fraction_lost;
368  int percent;
369  int bitrate;
370  int q;
371 
372  if(!exp_rtcp_fb)
373  return;
374 
375  /* We only accept feedback information in the form of SR and RR reports */
376  if (feedback->subclass.integer != AST_RTP_RTCP_SR && feedback->subclass.integer != AST_RTP_RTCP_RR) {
377  return;
378  }
379 
380  rtcp_report = (struct ast_rtp_rtcp_report *)feedback->data.ptr;
381  if (rtcp_report->reception_report_count == 0)
382  return;
383  report_block = rtcp_report->report_block[0];
384  fraction_lost = report_block->lost_count.fraction;
385  if (fraction_lost == tmp->fraction_lost)
386  return;
387  /* Per RFC3550, fraction lost is defined to be the number of packets lost
388  * divided by the number of packets expected. Since it's a 8-bit value,
389  * and we want a percentage value, we multiply by 100 and divide by 256. */
390  percent = (fraction_lost*100)/256;
391  bitrate = 0;
392  q = -1;
393  ast_debug(3, "Fraction lost changed: %d --> %d percent loss\n", fraction_lost, percent);
394  /* Handle change */
395  speex_encoder_ctl(tmp->speex, SPEEX_GET_BITRATE, &bitrate);
396  ast_debug(3, "Current bitrate: %d\n", bitrate);
397  ast_debug(3, "Current quality: %d/%d\n", tmp->quality, tmp->default_quality);
398  /* FIXME BADLY Very ugly example of how this could be handled: probably sucks */
399  if (percent < 10) {
400  /* Not that bad, default quality is fine */
401  q = tmp->default_quality;
402  } else if (percent < 20) {
403  /* Quite bad, let's go down a bit */
404  q = tmp->default_quality-1;
405  } else if (percent < 30) {
406  /* Very bad, let's go down even more */
407  q = tmp->default_quality-2;
408  } else {
409  /* Really bad, use the lowest quality possible */
410  q = 0;
411  }
412  if (q < 0)
413  q = 0;
414  if (q != tmp->quality) {
415  ast_debug(3, " -- Setting to %d\n", q);
416  if (vbr) {
417  float vbr_q = q;
418  speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_q);
419  } else {
420  speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &q);
421  }
422  tmp->quality = q;
423  }
425 }
426 
427 static void speextolin_destroy(struct ast_trans_pvt *arg)
428 {
429  struct speex_coder_pvt *pvt = arg->pvt;
430 
431  speex_decoder_destroy(pvt->speex);
432  speex_bits_destroy(&pvt->bits);
433 }
434 
435 static void lintospeex_destroy(struct ast_trans_pvt *arg)
436 {
437  struct speex_coder_pvt *pvt = arg->pvt;
438 #ifdef _SPEEX_TYPES_H
439  if (preproc)
440  speex_preprocess_state_destroy(pvt->pp);
441 #endif
442  speex_encoder_destroy(pvt->speex);
443  speex_bits_destroy(&pvt->bits);
444 }
445 
446 static struct ast_translator speextolin = {
447  .name = "speextolin",
448  .src_codec = {
449  .name = "speex",
450  .type = AST_MEDIA_TYPE_AUDIO,
451  .sample_rate = 8000,
452  },
453  .dst_codec = {
454  .name = "slin",
455  .type = AST_MEDIA_TYPE_AUDIO,
456  .sample_rate = 8000,
457  },
458  .format = "slin",
459  .newpvt = speextolin_new,
460  .framein = speextolin_framein,
461  .destroy = speextolin_destroy,
462  .sample = speex_sample,
463  .desc_size = sizeof(struct speex_coder_pvt),
464  .buffer_samples = BUFFER_SAMPLES,
465  .buf_size = BUFFER_SAMPLES * 2,
466  .native_plc = 1,
467 };
468 
469 static struct ast_translator lintospeex = {
470  .name = "lintospeex",
471  .src_codec = {
472  .name = "slin",
473  .type = AST_MEDIA_TYPE_AUDIO,
474  .sample_rate = 8000,
475  },
476  .dst_codec = {
477  .name = "speex",
478  .type = AST_MEDIA_TYPE_AUDIO,
479  .sample_rate = 8000,
480  },
481  .format = "speex",
482  .newpvt = lintospeex_new,
483  .framein = lintospeex_framein,
484  .frameout = lintospeex_frameout,
485  .feedback = lintospeex_feedback,
486  .destroy = lintospeex_destroy,
487  .sample = slin8_sample,
488  .desc_size = sizeof(struct speex_coder_pvt),
489  .buffer_samples = BUFFER_SAMPLES,
490  .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
491 };
492 
494  .name = "speexwbtolin16",
495  .src_codec = {
496  .name = "speex",
497  .type = AST_MEDIA_TYPE_AUDIO,
498  .sample_rate = 16000,
499  },
500  .dst_codec = {
501  .name = "slin",
502  .type = AST_MEDIA_TYPE_AUDIO,
503  .sample_rate = 16000,
504  },
505  .format = "slin16",
506  .newpvt = speexwbtolin16_new,
507  .framein = speextolin_framein,
508  .destroy = speextolin_destroy,
509  .sample = speex16_sample,
510  .desc_size = sizeof(struct speex_coder_pvt),
511  .buffer_samples = BUFFER_SAMPLES,
512  .buf_size = BUFFER_SAMPLES * 2,
513  .native_plc = 1,
514 };
515 
517  .name = "lin16tospeexwb",
518  .src_codec = {
519  .name = "slin",
520  .type = AST_MEDIA_TYPE_AUDIO,
521  .sample_rate = 16000,
522  },
523  .dst_codec = {
524  .name = "speex",
525  .type = AST_MEDIA_TYPE_AUDIO,
526  .sample_rate = 16000,
527  },
528  .format = "speex16",
529  .newpvt = lin16tospeexwb_new,
530  .framein = lintospeex_framein,
531  .frameout = lintospeex_frameout,
532  .feedback = lintospeex_feedback,
533  .destroy = lintospeex_destroy,
534  .sample = slin16_sample,
535  .desc_size = sizeof(struct speex_coder_pvt),
536  .buffer_samples = BUFFER_SAMPLES,
537  .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
538 };
539 
541  .name = "speexuwbtolin32",
542  .src_codec = {
543  .name = "speex",
544  .type = AST_MEDIA_TYPE_AUDIO,
545  .sample_rate = 32000,
546  },
547  .dst_codec = {
548  .name = "slin",
549  .type = AST_MEDIA_TYPE_AUDIO,
550  .sample_rate = 32000,
551  },
552  .format = "slin32",
553  .newpvt = speexuwbtolin32_new,
554  .framein = speextolin_framein,
555  .destroy = speextolin_destroy,
556  .desc_size = sizeof(struct speex_coder_pvt),
557  .buffer_samples = BUFFER_SAMPLES,
558  .buf_size = BUFFER_SAMPLES * 2,
559  .native_plc = 1,
560 };
561 
563  .name = "lin32tospeexuwb",
564  .src_codec = {
565  .name = "slin",
566  .type = AST_MEDIA_TYPE_AUDIO,
567  .sample_rate = 32000,
568  },
569  .dst_codec = {
570  .name = "speex",
571  .type = AST_MEDIA_TYPE_AUDIO,
572  .sample_rate = 32000,
573  },
574  .format = "speex32",
575  .newpvt = lin32tospeexuwb_new,
576  .framein = lintospeex_framein,
577  .frameout = lintospeex_frameout,
578  .feedback = lintospeex_feedback,
579  .destroy = lintospeex_destroy,
580  .desc_size = sizeof(struct speex_coder_pvt),
581  .buffer_samples = BUFFER_SAMPLES,
582  .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
583 };
584 
585 static int parse_config(int reload)
586 {
587  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
588  struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
589  struct ast_variable *var;
590  int res;
591  float res_f;
592 
594  return 0;
595 
596  for (var = ast_variable_browse(cfg, "speex"); var; var = var->next) {
597  if (!strcasecmp(var->name, "quality")) {
598  res = abs(atoi(var->value));
599  if (res > -1 && res < 11) {
600  ast_verb(3, "CODEC SPEEX: Setting Quality to %d\n",res);
601  quality = res;
602  } else
603  ast_log(LOG_ERROR,"Error Quality must be 0-10\n");
604  } else if (!strcasecmp(var->name, "complexity")) {
605  res = abs(atoi(var->value));
606  if (res > -1 && res < 11) {
607  ast_verb(3, "CODEC SPEEX: Setting Complexity to %d\n",res);
608  complexity = res;
609  } else
610  ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n");
611  } else if (!strcasecmp(var->name, "vbr_quality")) {
612  if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0 && res_f <= 10) {
613  ast_verb(3, "CODEC SPEEX: Setting VBR Quality to %f\n",res_f);
614  vbr_quality = res_f;
615  } else
616  ast_log(LOG_ERROR,"Error! VBR Quality must be 0-10\n");
617  } else if (!strcasecmp(var->name, "abr_quality")) {
618  ast_log(LOG_ERROR,"Error! ABR Quality setting obsolete, set ABR to desired bitrate\n");
619  } else if (!strcasecmp(var->name, "enhancement")) {
620  enhancement = ast_true(var->value) ? 1 : 0;
621  ast_verb(3, "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off");
622  } else if (!strcasecmp(var->name, "vbr")) {
623  vbr = ast_true(var->value) ? 1 : 0;
624  ast_verb(3, "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off");
625  } else if (!strcasecmp(var->name, "abr")) {
626  res = abs(atoi(var->value));
627  if (res >= 0) {
628  if (res > 0)
629  ast_verb(3, "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
630  else
631  ast_verb(3, "CODEC SPEEX: Disabling ABR\n");
632  abr = res;
633  } else
634  ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n");
635  } else if (!strcasecmp(var->name, "vad")) {
636  vad = ast_true(var->value) ? 1 : 0;
637  ast_verb(3, "CODEC SPEEX: VAD Mode. [%s]\n",vad ? "on" : "off");
638  } else if (!strcasecmp(var->name, "dtx")) {
639  dtx = ast_true(var->value) ? 1 : 0;
640  ast_verb(3, "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off");
641  } else if (!strcasecmp(var->name, "preprocess")) {
642  preproc = ast_true(var->value) ? 1 : 0;
643  ast_verb(3, "CODEC SPEEX: Preprocessing. [%s]\n",preproc ? "on" : "off");
644  } else if (!strcasecmp(var->name, "pp_vad")) {
645  pp_vad = ast_true(var->value) ? 1 : 0;
646  ast_verb(3, "CODEC SPEEX: Preprocessor VAD. [%s]\n",pp_vad ? "on" : "off");
647  } else if (!strcasecmp(var->name, "pp_agc")) {
648  pp_agc = ast_true(var->value) ? 1 : 0;
649  ast_verb(3, "CODEC SPEEX: Preprocessor AGC. [%s]\n",pp_agc ? "on" : "off");
650  } else if (!strcasecmp(var->name, "pp_agc_level")) {
651  if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0) {
652  ast_verb(3, "CODEC SPEEX: Setting preprocessor AGC Level to %f\n",res_f);
653  pp_agc_level = res_f;
654  } else
655  ast_log(LOG_ERROR,"Error! Preprocessor AGC Level must be >= 0\n");
656  } else if (!strcasecmp(var->name, "pp_denoise")) {
657  pp_denoise = ast_true(var->value) ? 1 : 0;
658  ast_verb(3, "CODEC SPEEX: Preprocessor Denoise. [%s]\n",pp_denoise ? "on" : "off");
659  } else if (!strcasecmp(var->name, "pp_dereverb")) {
660  pp_dereverb = ast_true(var->value) ? 1 : 0;
661  ast_verb(3, "CODEC SPEEX: Preprocessor Dereverb. [%s]\n",pp_dereverb ? "on" : "off");
662  } else if (!strcasecmp(var->name, "pp_dereverb_decay")) {
663  if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0) {
664  ast_verb(3, "CODEC SPEEX: Setting preprocessor Dereverb Decay to %f\n",res_f);
665  pp_dereverb_decay = res_f;
666  } else
667  ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Decay must be >= 0\n");
668  } else if (!strcasecmp(var->name, "pp_dereverb_level")) {
669  if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0) {
670  ast_verb(3, "CODEC SPEEX: Setting preprocessor Dereverb Level to %f\n",res_f);
671  pp_dereverb_level = res_f;
672  } else
673  ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Level must be >= 0\n");
674  } else if (!strcasecmp(var->name, "experimental_rtcp_feedback")) {
675  exp_rtcp_fb = ast_true(var->value) ? 1 : 0;
676  ast_verb(3, "CODEC SPEEX: Experimental RTCP Feedback. [%s]\n",exp_rtcp_fb ? "on" : "off");
677  }
678  }
679  ast_config_destroy(cfg);
680  return 0;
681 }
682 
683 static int reload(void)
684 {
685  if (parse_config(1))
688 }
689 
690 static int unload_module(void)
691 {
692  ast_unregister_translator(&speextolin);
693  ast_unregister_translator(&lintospeex);
694  ast_unregister_translator(&speexwbtolin16);
695  ast_unregister_translator(&lin16tospeexwb);
696  ast_unregister_translator(&speexuwbtolin32);
697  ast_unregister_translator(&lin32tospeexuwb);
698 
699  return 0;
700 }
701 
702 static int load_module(void)
703 {
704  int res = 0;
705 
706  if (parse_config(0)) {
708  }
709 
710  /* XXX It is most likely a bug in this module if we fail to register a translator */
711  res |= ast_register_translator(&speextolin);
712  res |= ast_register_translator(&lintospeex);
713  res |= ast_register_translator(&speexwbtolin16);
714  res |= ast_register_translator(&lin16tospeexwb);
715  res |= ast_register_translator(&speexuwbtolin32);
716  res |= ast_register_translator(&lin32tospeexuwb);
717  if (res) {
718  unload_module();
720  }
721 
723 }
724 
726  .support_level = AST_MODULE_SUPPORT_CORE,
727  .load = load_module,
728  .unload = unload_module,
729  .reload = reload,
730 );
struct ast_variable * next
static int speexwbtolin16_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:192
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:432
int datalen
actual space used in outbuf
Definition: translate.h:218
static float pp_dereverb_decay
Definition: codec_speex.c:78
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:331
static void lintospeex_destroy(struct ast_trans_pvt *arg)
Definition: codec_speex.c:435
static int exp_rtcp_fb
Definition: codec_speex.c:70
Asterisk main include file. File version handling, generic pbx functions.
static int quality
Definition: codec_speex.c:62
Descriptor of a translator.
Definition: translate.h:137
short int16_t
Definition: db.h:59
union ast_trans_pvt::@321 outbuf
static int preproc
Definition: codec_speex.c:72
SpeexBits bits
Definition: codec_speex.c:95
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
static struct ast_translator lin16tospeexwb
Definition: codec_speex.c:516
Support for translation of data formats. translate.c.
#define LOG_WARNING
Definition: logger.h:274
static int speex_decoder_construct(struct ast_trans_pvt *pvt, const SpeexMode *profile)
Definition: codec_speex.c:172
union ast_frame::@257 data
#define CONFIG_STATUS_FILEINVALID
static int tmp()
Definition: bt_open.c:389
static int lin16tospeexwb_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:162
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
unsigned short reception_report_count
Definition: rtp_engine.h:332
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
static struct ast_frame * lintospeex_frameout(struct ast_trans_pvt *pvt)
convert work buffer and produce output frame
Definition: codec_speex.c:273
struct ast_rtp_rtcp_report_block * report_block[0]
Definition: rtp_engine.h:344
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
struct ast_rtp_rtcp_report_block::@308 lost_count
static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
store input frame in work buffer
Definition: codec_speex.c:260
A report block within a SR/RR report.
Definition: rtp_engine.h:316
static struct ast_translator lin32tospeexuwb
Definition: codec_speex.c:562
int16_t buf[BUFFER_SAMPLES]
Definition: codec_speex.c:107
static int load_module(void)
Definition: codec_speex.c:702
static void speextolin_destroy(struct ast_trans_pvt *arg)
Definition: codec_speex.c:427
static struct ast_frame * slin8_sample(void)
Definition: slin.h:64
static int speexuwbtolin32_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:197
#define NULL
Definition: resample.c:96
void * pvt
Definition: translate.h:219
static int parse_config(int reload)
Definition: codec_speex.c:585
static int lin32tospeexuwb_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:167
#define ast_verb(level,...)
Definition: logger.h:455
static int reload(void)
Definition: codec_speex.c:683
static void lintospeex_feedback(struct ast_trans_pvt *pvt, struct ast_frame *feedback)
handle incoming RTCP feedback and possibly edit encoder settings
Definition: codec_speex.c:360
struct ast_frame_subclass subclass
static int complexity
Definition: codec_speex.c:63
int16_t * i16
Definition: translate.h:223
static struct ast_frame * slin16_sample(void)
Definition: slin.h:81
Utility functions.
Configuration File Parser.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
unsigned short fraction
Definition: rtp_engine.h:319
static float pp_dereverb_level
Definition: codec_speex.c:79
static int speextolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
convert and store into outbuf
Definition: codec_speex.c:203
struct sla_ringing_trunk * last
Definition: app_meetme.c:1092
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:257
Asterisk internal frame definitions.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given tranlator.
Definition: translate.c:1327
A set of macros to manage forward-linked lists.
static int vbr
Definition: codec_speex.c:66
static int pp_vad
Definition: codec_speex.c:73
static int speextolin_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:187
int buf_size
size of outbuf, in bytes. Mandatory. The wrapper code will also allocate an AST_FRIENDLY_OFFSET space...
Definition: translate.h:182
static struct ast_frame * speex_sample(void)
Definition: ex_speex.h:17
#define CONFIG_STATUS_FILEUNCHANGED
static int pp_dereverb
Definition: codec_speex.c:77
static struct ast_translator speexuwbtolin32
Definition: codec_speex.c:540
static int unload_module(void)
Definition: codec_speex.c:690
static struct ast_translator lintospeex
Definition: codec_speex.c:469
#define LOG_ERROR
Definition: logger.h:285
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1822
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
static struct ast_translator speexwbtolin16
Definition: codec_speex.c:493
static int speex_encoder_construct(struct ast_trans_pvt *pvt, const SpeexMode *profile, int sampling_rate)
Definition: codec_speex.c:111
Random Data.
static int vad
Definition: codec_speex.c:65
static struct ast_frame * speex16_sample(void)
Definition: ex_speex.h:49
static int dtx
Definition: codec_speex.c:69
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int pp_denoise
Definition: codec_speex.c:76
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
static int lintospeex_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:157
Structure used to handle boolean flags.
Definition: utils.h:199
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
#define CONFIG_STATUS_FILEMISSING
#define AST_RTP_RTCP_RR
Definition: rtp_engine.h:295
#define abs(x)
Definition: f2c.h:195
#define BUFFER_SAMPLES
Definition: codec_speex.c:86
static int enhancement
Definition: codec_speex.c:64
#define AST_RTP_RTCP_SR
Definition: rtp_engine.h:293
static PGresult * result
Definition: cel_pgsql.c:88
Data structure associated with a single frame of data.
static float vbr_quality
Definition: codec_speex.c:67
struct ast_translator * t
Definition: translate.h:214
enum ast_frame_type frametype
static float pp_agc_level
Definition: codec_speex.c:75
static struct ast_translator speextolin
Definition: codec_speex.c:446
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Pluggable RTP Architecture.
Asterisk module definitions.
static int abr
Definition: codec_speex.c:68
char name[80]
Definition: translate.h:138
static int pp_agc
Definition: codec_speex.c:74