summaryrefslogtreecommitdiff
path: root/modules/speex_pp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/speex_pp')
-rw-r--r--modules/speex_pp/module.mk15
-rw-r--r--modules/speex_pp/speex_pp.c154
2 files changed, 169 insertions, 0 deletions
diff --git a/modules/speex_pp/module.mk b/modules/speex_pp/module.mk
new file mode 100644
index 0000000..fad5f88
--- /dev/null
+++ b/modules/speex_pp/module.mk
@@ -0,0 +1,15 @@
+#
+# module.mk
+#
+# Copyright (C) 2010 Creytiv.com
+#
+
+MOD := speex_pp
+$(MOD)_SRCS += speex_pp.c
+ifneq ($(HAVE_SPEEXDSP),)
+$(MOD)_LFLAGS += "-lspeexdsp"
+else
+$(MOD)_LFLAGS += "-lspeex"
+endif
+
+include mk/mod.mk
diff --git a/modules/speex_pp/speex_pp.c b/modules/speex_pp/speex_pp.c
new file mode 100644
index 0000000..4c14f65
--- /dev/null
+++ b/modules/speex_pp/speex_pp.c
@@ -0,0 +1,154 @@
+/**
+ * @file speex_pp.c Speex Pre-processor
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <speex/speex.h>
+#include <speex/speex_preprocess.h>
+#include <re.h>
+#include <baresip.h>
+
+
+struct preproc {
+ struct aufilt_enc_st af; /* base class */
+ SpeexPreprocessState *state;
+};
+
+
+/** Speex configuration */
+static struct {
+ int denoise_enabled;
+ int agc_enabled;
+ int vad_enabled;
+ int dereverb_enabled;
+ spx_int32_t agc_level;
+} pp_conf = {
+ 1,
+ 1,
+ 1,
+ 1,
+ 8000
+};
+
+
+static void speexpp_destructor(void *arg)
+{
+ struct preproc *st = arg;
+
+ if (st->state)
+ speex_preprocess_state_destroy(st->state);
+
+ list_unlink(&st->af.le);
+}
+
+
+static int encode_update(struct aufilt_enc_st **stp, void **ctx,
+ const struct aufilt *af, struct aufilt_prm *prm)
+{
+ struct preproc *st;
+ unsigned sampc;
+ (void)ctx;
+
+ if (!stp || !af || !prm || prm->ch != 1)
+ return EINVAL;
+
+ st = mem_zalloc(sizeof(*st), speexpp_destructor);
+ if (!st)
+ return ENOMEM;
+
+ sampc = prm->srate * prm->ch * prm->ptime / 1000;
+
+ st->state = speex_preprocess_state_init(sampc, prm->srate);
+ if (!st->state)
+ goto error;
+
+ speex_preprocess_ctl(st->state, SPEEX_PREPROCESS_SET_DENOISE,
+ &pp_conf.denoise_enabled);
+ speex_preprocess_ctl(st->state, SPEEX_PREPROCESS_SET_AGC,
+ &pp_conf.agc_enabled);
+
+#ifdef SPEEX_PREPROCESS_SET_AGC_TARGET
+ if (pp_conf.agc_enabled) {
+ speex_preprocess_ctl(st->state,
+ SPEEX_PREPROCESS_SET_AGC_TARGET,
+ &pp_conf.agc_level);
+ }
+#endif
+
+ speex_preprocess_ctl(st->state, SPEEX_PREPROCESS_SET_VAD,
+ &pp_conf.vad_enabled);
+ speex_preprocess_ctl(st->state, SPEEX_PREPROCESS_SET_DEREVERB,
+ &pp_conf.dereverb_enabled);
+
+ info("speex_pp: Speex preprocessor loaded: srate = %uHz\n",
+ prm->srate);
+
+ *stp = (struct aufilt_enc_st *)st;
+ return 0;
+
+ error:
+ mem_deref(st);
+ return ENOMEM;
+}
+
+
+static int encode(struct aufilt_enc_st *st, int16_t *sampv, size_t *sampc)
+{
+ struct preproc *pp = (struct preproc *)st;
+ int is_speech = 1;
+
+ if (!*sampc)
+ return 0;
+
+ /* NOTE: Using this macro to check libspeex version */
+#ifdef SPEEX_PREPROCESS_SET_NOISE_SUPPRESS
+ /* New API */
+ is_speech = speex_preprocess_run(pp->state, sampv);
+#else
+ /* Old API - not tested! */
+ is_speech = speex_preprocess(pp->state, sampv, NULL);
+#endif
+
+ /* XXX: Handle is_speech and VAD */
+ (void)is_speech;
+
+ return 0;
+}
+
+
+static void config_parse(struct conf *conf)
+{
+ uint32_t v;
+
+ if (0 == conf_get_u32(conf, "speex_agc_level", &v))
+ pp_conf.agc_level = v;
+}
+
+
+static struct aufilt preproc = {
+ LE_INIT, "speex_pp", encode_update, encode, NULL, NULL
+};
+
+static int module_init(void)
+{
+ config_parse(conf_cur());
+ aufilt_register(&preproc);
+ return 0;
+}
+
+
+static int module_close(void)
+{
+ aufilt_unregister(&preproc);
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(speex_pp) = {
+ "speex_pp",
+ "filter",
+ module_init,
+ module_close
+};