From 98bf08bdcf2edd9d397f32650a8bfe62186fbecf Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Sun, 9 Feb 2014 11:50:07 +0100 Subject: baresip 0.4.10 --- modules/speex_aec/speex_aec.c | 222 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 modules/speex_aec/speex_aec.c (limited to 'modules/speex_aec/speex_aec.c') diff --git a/modules/speex_aec/speex_aec.c b/modules/speex_aec/speex_aec.c new file mode 100644 index 0000000..15ea552 --- /dev/null +++ b/modules/speex_aec/speex_aec.c @@ -0,0 +1,222 @@ +/** + * @file speex_aec.c Speex Acoustic Echo Cancellation + * + * Copyright (C) 2010 Creytiv.com + */ +#include +#include +#include +#include +#include +#include + + +struct speex_st { + int16_t *out; + SpeexEchoState *state; +}; + +struct enc_st { + struct aufilt_enc_st af; /* base class */ + struct speex_st *st; +}; + +struct dec_st { + struct aufilt_dec_st af; /* base class */ + struct speex_st *st; +}; + + +static void enc_destructor(void *arg) +{ + struct enc_st *st = arg; + + list_unlink(&st->af.le); + mem_deref(st->st); +} + + +static void dec_destructor(void *arg) +{ + struct dec_st *st = arg; + + list_unlink(&st->af.le); + mem_deref(st->st); +} + + +#ifdef SPEEX_SET_VBR_MAX_BITRATE +static void speex_aec_destructor(void *arg) +{ + struct speex_st *st = arg; + + if (st->state) + speex_echo_state_destroy(st->state); + + mem_deref(st->out); +} + + +static int aec_alloc(struct speex_st **stp, void **ctx, struct aufilt_prm *prm) +{ + struct speex_st *st; + uint32_t sampc; + int err, tmp, fl; + + if (!stp || !ctx || !prm) + return EINVAL; + + if (*ctx) { + *stp = mem_ref(*ctx); + return 0; + } + + st = mem_zalloc(sizeof(*st), speex_aec_destructor); + if (!st) + return ENOMEM; + + sampc = prm->srate * prm->ch * prm->ptime / 1000; + + st->out = mem_alloc(2 * sampc, NULL); + if (!st->out) { + err = ENOMEM; + goto out; + } + + /* Echo canceller with 200 ms tail length */ + fl = 10 * sampc; + st->state = speex_echo_state_init(sampc, fl); + if (!st->state) { + err = ENOMEM; + goto out; + } + + tmp = prm->srate; + err = speex_echo_ctl(st->state, SPEEX_ECHO_SET_SAMPLING_RATE, &tmp); + if (err < 0) { + warning("speex_aec: speex_echo_ctl: err=%d\n", err); + } + + info("speex_aec: Speex AEC loaded: srate = %uHz\n", prm->srate); + + out: + if (err) + mem_deref(st); + else + *ctx = *stp = st; + + return err; +} + + +static int encode_update(struct aufilt_enc_st **stp, void **ctx, + const struct aufilt *af, struct aufilt_prm *prm) +{ + struct enc_st *st; + int err; + + if (!stp || !ctx || !af || !prm) + return EINVAL; + + if (*stp) + return 0; + + st = mem_zalloc(sizeof(*st), enc_destructor); + if (!st) + return ENOMEM; + + err = aec_alloc(&st->st, ctx, prm); + + if (err) + mem_deref(st); + else + *stp = (struct aufilt_enc_st *)st; + + return err; +} + + +static int decode_update(struct aufilt_dec_st **stp, void **ctx, + const struct aufilt *af, struct aufilt_prm *prm) +{ + struct dec_st *st; + int err; + + if (!stp || !ctx || !af || !prm) + return EINVAL; + + if (*stp) + return 0; + + st = mem_zalloc(sizeof(*st), dec_destructor); + if (!st) + return ENOMEM; + + err = aec_alloc(&st->st, ctx, prm); + + if (err) + mem_deref(st); + else + *stp = (struct aufilt_dec_st *)st; + + return err; +} + + +static int encode(struct aufilt_enc_st *st, int16_t *sampv, size_t *sampc) +{ + struct enc_st *est = (struct enc_st *)st; + struct speex_st *sp = est->st; + + if (*sampc) { + speex_echo_capture(sp->state, sampv, sp->out); + memcpy(sampv, sp->out, *sampc * 2); + } + + return 0; +} + + +static int decode(struct aufilt_dec_st *st, int16_t *sampv, size_t *sampc) +{ + struct dec_st *dst = (struct dec_st *)st; + struct speex_st *sp = dst->st; + + if (*sampc) + speex_echo_playback(sp->state, sampv); + + return 0; +} +#endif + + +static struct aufilt speex_aec = { + LE_INIT, "speex_aec", encode_update, encode, decode_update, decode +}; + + +static int module_init(void) +{ + /* Note: Hack to check libspeex version */ +#ifdef SPEEX_SET_VBR_MAX_BITRATE + aufilt_register(&speex_aec); + return 0; +#else + return ENOSYS; +#endif +} + + +static int module_close(void) +{ + aufilt_unregister(&speex_aec); + return 0; +} + + +EXPORT_SYM const struct mod_export DECL_EXPORTS(speex_aec) = { + "speex_aec", + "filter", + module_init, + module_close +}; -- cgit v1.2.3