Asterisk - The Open Source Telephony Project GIT-master-2de1a68
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"
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 */
62static int quality = 3;
63static int complexity = 2;
64static int enhancement = 0;
65static int vad = 0;
66static int vbr = 0;
67static float vbr_quality = 4;
68static int abr = 0;
69static int dtx = 0; /* set to 1 to enable silence detection */
70static int exp_rtcp_fb = 0; /* set to 1 to use experimental RTCP feedback for changing bitrate */
71
72static int preproc = 0;
73static int pp_vad = 0;
74static int pp_agc = 0;
75static float pp_agc_level = 8000; /* XXX what is this 8000 ? */
76static int pp_denoise = 0;
77static int pp_dereverb = 0;
78static float pp_dereverb_decay = 0.4;
79static 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;
98
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
111static 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;
150 tmp->default_quality = vbr ? vbr_quality : quality;
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
157static int lintospeex_new(struct ast_trans_pvt *pvt)
158{
159 return speex_encoder_construct(pvt, &speex_nb_mode, 8000);
160}
161
162static int lin16tospeexwb_new(struct ast_trans_pvt *pvt)
163{
164 return speex_encoder_construct(pvt, &speex_wb_mode, 16000);
165}
166
167static int lin32tospeexuwb_new(struct ast_trans_pvt *pvt)
168{
169 return speex_encoder_construct(pvt, &speex_uwb_mode, 32000);
170}
171
172static 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
187static int speextolin_new(struct ast_trans_pvt *pvt)
188{
189 return speex_decoder_construct(pvt, &speex_nb_mode);
190}
191
192static int speexwbtolin16_new(struct ast_trans_pvt *pvt)
193{
194 return speex_decoder_construct(pvt, &speex_wb_mode);
195}
196
197static 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 */
203static 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 */
260static 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 */
273static 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) {
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 */
360static 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 }
424 tmp->fraction_lost = fraction_lost;
425}
426
427static 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
435static 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
446static 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
469static 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
585static 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(5, "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(5, "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(5, "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(5, "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(5, "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(5, "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
630 else
631 ast_verb(5, "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(5, "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(5, "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(5, "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(5, "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(5, "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(5, "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(5, "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(5, "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(5, "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(5, "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(5, "CODEC SPEEX: Experimental RTCP Feedback. [%s]\n",exp_rtcp_fb ? "on" : "off");
677 }
678 }
680 return 0;
681}
682
683static int reload(void)
684{
685 if (parse_config(1))
688}
689
690static int unload_module(void)
691{
698
699 return 0;
700}
701
702static 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 */
717 if (res) {
720 }
721
723}
724
726 .support_level = AST_MODULE_SUPPORT_CORE,
727 .load = load_module,
728 .unload = unload_module,
729 .reload = reload,
struct sla_ringing_trunk * last
Definition: app_sla.c:332
#define var
Definition: ast_expr2f.c:605
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
Asterisk main include file. File version handling, generic pbx functions.
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
static PGresult * result
Definition: cel_pgsql.c:84
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
static int vbr
Definition: codec_speex.c:66
static struct ast_translator speextolin
Definition: codec_speex.c:446
static int parse_config(int reload)
Definition: codec_speex.c:585
#define BUFFER_SAMPLES
Definition: codec_speex.c:86
static struct ast_translator speexuwbtolin32
Definition: codec_speex.c:540
static int enhancement
Definition: codec_speex.c:64
static int speexuwbtolin32_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:197
static struct ast_translator speexwbtolin16
Definition: codec_speex.c:493
static struct ast_translator lintospeex
Definition: codec_speex.c:469
static float pp_agc_level
Definition: codec_speex.c:75
static int speextolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
convert and store into outbuf
Definition: codec_speex.c:203
static int pp_dereverb
Definition: codec_speex.c:77
static int speex_encoder_construct(struct ast_trans_pvt *pvt, const SpeexMode *profile, int sampling_rate)
Definition: codec_speex.c:111
static int complexity
Definition: codec_speex.c:63
static int pp_agc
Definition: codec_speex.c:74
static int speextolin_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:187
static int lintospeex_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:157
static int lin32tospeexuwb_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:167
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
static int speexwbtolin16_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:192
static int exp_rtcp_fb
Definition: codec_speex.c:70
static int dtx
Definition: codec_speex.c:69
static int pp_denoise
Definition: codec_speex.c:76
static struct ast_frame * lintospeex_frameout(struct ast_trans_pvt *pvt)
convert work buffer and produce output frame
Definition: codec_speex.c:273
static int pp_vad
Definition: codec_speex.c:73
static int abr
Definition: codec_speex.c:68
static void lintospeex_destroy(struct ast_trans_pvt *arg)
Definition: codec_speex.c:435
static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
store input frame in work buffer
Definition: codec_speex.c:260
static void speextolin_destroy(struct ast_trans_pvt *arg)
Definition: codec_speex.c:427
static int load_module(void)
Definition: codec_speex.c:702
static struct ast_translator lin32tospeexuwb
Definition: codec_speex.c:562
static int quality
Definition: codec_speex.c:62
static float pp_dereverb_level
Definition: codec_speex.c:79
static float vbr_quality
Definition: codec_speex.c:67
static int lin16tospeexwb_new(struct ast_trans_pvt *pvt)
Definition: codec_speex.c:162
static int unload_module(void)
Definition: codec_speex.c:690
static int reload(void)
Definition: codec_speex.c:683
static int preproc
Definition: codec_speex.c:72
static int speex_decoder_construct(struct ast_trans_pvt *pvt, const SpeexMode *profile)
Definition: codec_speex.c:172
static struct ast_translator lin16tospeexwb
Definition: codec_speex.c:516
static float pp_dereverb_decay
Definition: codec_speex.c:78
static int vad
Definition: codec_speex.c:65
short int16_t
Definition: db.h:59
Random Data.
static struct ast_frame * speex16_sample(void)
Definition: ex_speex.h:49
static struct ast_frame * speex_sample(void)
Definition: ex_speex.h:17
#define abs(x)
Definition: f2c.h:195
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
Asterisk internal frame definitions.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
A set of macros to manage forward-linked lists.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
size_t current
Definition: main/cli.c:113
Asterisk module definitions.
@ AST_MODFLAG_DEFAULT
Definition: module.h:315
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define NULL
Definition: resample.c:96
Pluggable RTP Architecture.
#define AST_RTP_RTCP_SR
Definition: rtp_engine.h:318
#define AST_RTP_RTCP_RR
Definition: rtp_engine.h:320
static struct ast_frame * slin8_sample(void)
Definition: slin.h:64
static struct ast_frame * slin16_sample(void)
Definition: slin.h:81
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
Structure used to handle boolean flags.
Definition: utils.h:199
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
A report block within a SR/RR report.
Definition: rtp_engine.h:341
struct ast_rtp_rtcp_report_block::@272 lost_count
unsigned short fraction
Definition: rtp_engine.h:344
An object that represents data sent during a SR/RR RTCP report.
Definition: rtp_engine.h:356
unsigned short reception_report_count
Definition: rtp_engine.h:357
struct ast_rtp_rtcp_report_block * report_block[0]
Definition: rtp_engine.h:369
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
void * pvt
Definition: translate.h:219
struct ast_translator * t
Definition: translate.h:214
int datalen
actual space used in outbuf
Definition: translate.h:218
union ast_trans_pvt::@287 outbuf
int16_t * i16
Definition: translate.h:223
Descriptor of a translator.
Definition: translate.h:137
char name[80]
Definition: translate.h:138
int buf_size
size of outbuf, in bytes. Mandatory. The wrapper code will also allocate an AST_FRIENDLY_OFFSET space...
Definition: translate.h:182
Structure for variables, used for configurations and for channel variables.
int16_t buf[BUFFER_SAMPLES]
Definition: codec_speex.c:107
SpeexBits bits
Definition: codec_speex.c:95
Support for translation of data formats. translate.c.
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:258
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given translator.
Definition: translate.c:1350
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:439
Utility functions.