summaryrefslogtreecommitdiff
path: root/modules/amr
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
committerAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
commit98bf08bdcf2edd9d397f32650a8bfe62186fbecf (patch)
treeebc6ec71f44bff8c42e4eefced61948623df02fc /modules/amr
parente6ad5cf4401b860ba402d4b7b3c7c254bc87a019 (diff)
baresip 0.4.10
Diffstat (limited to 'modules/amr')
-rw-r--r--modules/amr/amr.c340
-rw-r--r--modules/amr/module.mk64
2 files changed, 404 insertions, 0 deletions
diff --git a/modules/amr/amr.c b/modules/amr/amr.c
new file mode 100644
index 0000000..3b29788
--- /dev/null
+++ b/modules/amr/amr.c
@@ -0,0 +1,340 @@
+/**
+ * @file amr.c Adaptive Multi-Rate (AMR) audio codec
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <stdlib.h>
+#ifdef AMR_NB
+#include <interf_enc.h>
+#include <interf_dec.h>
+#endif
+#ifdef AMR_WB
+#ifdef _TYPEDEF_H
+#define typedef_h
+#endif
+#include <enc_if.h>
+#include <dec_if.h>
+#endif
+#include <re.h>
+#include <baresip.h>
+
+
+#define DEBUG_MODULE "amr"
+#define DEBUG_LEVEL 5
+#include <re_dbg.h>
+
+
+#ifdef VO_AMRWBENC_ENC_IF_H
+#define IF2E_IF_encode E_IF_encode
+#define IF2D_IF_decode D_IF_decode
+#endif
+
+
+/*
+ * This module supports both AMR Narrowband (8000 Hz) and
+ * AMR Wideband (16000 Hz) audio codecs.
+ *
+ * Reference:
+ *
+ * http://tools.ietf.org/html/rfc4867
+ *
+ * http://www.penguin.cz/~utx/amr
+ */
+
+
+#ifndef L_FRAME16k
+#define L_FRAME16k 320
+#endif
+
+#ifndef NB_SERIAL_MAX
+#define NB_SERIAL_MAX 61
+#endif
+
+enum {
+ FRAMESIZE_NB = 160
+};
+
+
+struct auenc_state {
+ const struct aucodec *ac;
+ void *enc; /**< Encoder state */
+};
+
+struct audec_state {
+ const struct aucodec *ac;
+ void *dec; /**< Decoder state */
+};
+
+
+static void encode_destructor(void *arg)
+{
+ struct auenc_state *st = arg;
+
+ switch (st->ac->srate) {
+
+#ifdef AMR_NB
+ case 8000:
+ Encoder_Interface_exit(st->enc);
+ break;
+#endif
+
+#ifdef AMR_WB
+ case 16000:
+ E_IF_exit(st->enc);
+ break;
+#endif
+ }
+}
+
+
+static void decode_destructor(void *arg)
+{
+ struct audec_state *st = arg;
+
+ switch (st->ac->srate) {
+
+#ifdef AMR_NB
+ case 8000:
+ Decoder_Interface_exit(st->dec);
+ break;
+#endif
+
+#ifdef AMR_WB
+ case 16000:
+ D_IF_exit(st->dec);
+ break;
+#endif
+ }
+}
+
+
+static int encode_update(struct auenc_state **aesp,
+ const struct aucodec *ac,
+ struct auenc_param *prm, const char *fmtp)
+{
+ struct auenc_state *st;
+ int err = 0;
+ (void)prm;
+ (void)fmtp;
+
+ if (!aesp || !ac)
+ return EINVAL;
+
+ if (*aesp)
+ return 0;
+
+ st = mem_zalloc(sizeof(*st), encode_destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->ac = ac;
+
+ switch (ac->srate) {
+
+#ifdef AMR_NB
+ case 8000:
+ st->enc = Encoder_Interface_init(0);
+ break;
+#endif
+
+#ifdef AMR_WB
+ case 16000:
+ st->enc = E_IF_init();
+ break;
+#endif
+ }
+
+ if (!st->enc)
+ err = ENOMEM;
+
+ if (err)
+ mem_deref(st);
+ else
+ *aesp = st;
+
+ return err;
+}
+
+
+static int decode_update(struct audec_state **adsp,
+ const struct aucodec *ac, const char *fmtp)
+{
+ struct audec_state *st;
+ int err = 0;
+ (void)fmtp;
+
+ if (!adsp || !ac)
+ return EINVAL;
+
+ if (*adsp)
+ return 0;
+
+ st = mem_zalloc(sizeof(*st), decode_destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->ac = ac;
+
+ switch (ac->srate) {
+
+#ifdef AMR_NB
+ case 8000:
+ st->dec = Decoder_Interface_init();
+ break;
+#endif
+
+#ifdef AMR_WB
+ case 16000:
+ st->dec = D_IF_init();
+ break;
+#endif
+ }
+
+ if (!st->dec)
+ err = ENOMEM;
+
+ if (err)
+ mem_deref(st);
+ else
+ *adsp = st;
+
+ return err;
+}
+
+
+#ifdef AMR_WB
+static int encode_wb(struct auenc_state *st, uint8_t *buf, size_t *len,
+ const int16_t *sampv, size_t sampc)
+{
+ int n;
+
+ if (sampc != L_FRAME16k)
+ return EINVAL;
+
+ if (*len < NB_SERIAL_MAX)
+ return ENOMEM;
+
+ n = IF2E_IF_encode(st->enc, 8, sampv, buf, 0);
+ if (n <= 0) {
+ DEBUG_WARNING("encode error: %d\n", n);
+ return EPROTO;
+ }
+
+ *len = n;
+
+ return 0;
+}
+
+
+static int decode_wb(struct audec_state *st, int16_t *sampv, size_t *sampc,
+ const uint8_t *buf, size_t len)
+{
+ if (*sampc < L_FRAME16k)
+ return ENOMEM;
+ if (len > NB_SERIAL_MAX)
+ return EINVAL;
+
+ IF2D_IF_decode(st->dec, buf, sampv, 0);
+
+ *sampc = L_FRAME16k;
+
+ return 0;
+}
+#endif
+
+
+#ifdef AMR_NB
+static int encode_nb(struct auenc_state *st, uint8_t *buf,
+ size_t *len, const int16_t *sampv, size_t sampc)
+{
+ int r;
+
+ if (!st || !buf || !len || !sampv || sampc != FRAMESIZE_NB)
+ return EINVAL;
+ if (*len < NB_SERIAL_MAX)
+ return ENOMEM;
+
+ r = Encoder_Interface_Encode(st->enc, MR475, sampv, buf, 0);
+ if (r <= 0)
+ return EPROTO;
+
+ *len = r;
+
+ return 0;
+}
+
+
+static int decode_nb(struct audec_state *st, int16_t *sampv,
+ size_t *sampc, const uint8_t *buf, size_t len)
+{
+ if (!st || !sampv || !sampc || !buf)
+ return EINVAL;
+
+ if (len > NB_SERIAL_MAX)
+ return EPROTO;
+
+ if (*sampc < L_FRAME16k)
+ return ENOMEM;
+
+ Decoder_Interface_Decode(st->dec, buf, sampv, 0);
+
+ *sampc = FRAMESIZE_NB;
+
+ return 0;
+}
+#endif
+
+
+#ifdef AMR_WB
+static struct aucodec amr_wb = {
+ LE_INIT, NULL, "AMR-WB", 16000, 1, NULL,
+ encode_update, encode_wb,
+ decode_update, decode_wb,
+ NULL, NULL, NULL
+};
+#endif
+#ifdef AMR_NB
+static struct aucodec amr_nb = {
+ LE_INIT, NULL, "AMR", 8000, 1, NULL,
+ encode_update, encode_nb,
+ decode_update, decode_nb,
+ NULL, NULL, NULL
+};
+#endif
+
+
+static int module_init(void)
+{
+ int err = 0;
+
+#ifdef AMR_WB
+ aucodec_register(&amr_wb);
+#endif
+#ifdef AMR_NB
+ aucodec_register(&amr_nb);
+#endif
+
+ return err;
+}
+
+
+static int module_close(void)
+{
+#ifdef AMR_WB
+ aucodec_unregister(&amr_wb);
+#endif
+#ifdef AMR_NB
+ aucodec_unregister(&amr_nb);
+#endif
+
+ return 0;
+}
+
+
+/** Module exports */
+EXPORT_SYM const struct mod_export DECL_EXPORTS(amr) = {
+ "amr",
+ "codec",
+ module_init,
+ module_close
+};
diff --git a/modules/amr/module.mk b/modules/amr/module.mk
new file mode 100644
index 0000000..cbe1013
--- /dev/null
+++ b/modules/amr/module.mk
@@ -0,0 +1,64 @@
+#
+# module.mk
+#
+# Copyright (C) 2010 Creytiv.com
+#
+
+MOD := amr
+$(MOD)_SRCS += amr.c
+
+
+ifneq ($(shell [ -d $(SYSROOT)/include/opencore-amrnb ] && echo 1 ),)
+CFLAGS += -DAMR_NB=1 -I$(SYSROOT)/include/opencore-amrnb
+$(MOD)_LFLAGS += -lopencore-amrnb
+else
+ifneq ($(shell [ -d $(SYSROOT_ALT)/include/opencore-amrnb ] && echo 1 ),)
+CFLAGS += -DAMR_NB=1 -I$(SYSROOT_ALT)/include/opencore-amrnb
+$(MOD)_LFLAGS += -lopencore-amrnb
+else
+ifneq ($(shell [ -d $(SYSROOT)/local/include/amrnb ] && echo 1),)
+CFLAGS += -DAMR_NB=1 -I$(SYSROOT)/local/include/amrnb
+$(MOD)_LFLAGS += -lamrnb
+else
+ifneq ($(shell [ -d $(SYSROOT)/include/amrnb ] && echo 1),)
+CFLAGS += -DAMR_NB=1 -I$(SYSROOT)/include/amrnb
+$(MOD)_LFLAGS += -lamrnb
+endif
+endif
+endif
+endif
+
+
+ifneq ($(shell [ -f $(SYSROOT_ALT)/include/opencore-amrwb/enc_if.h ] && \
+ echo 1 ),)
+CFLAGS += -DAMR_WB=1 -I$(SYSROOT_ALT)/include/opencore-amrwb
+$(MOD)_LFLAGS += -lopencore-amrwb
+else
+ifneq ($(shell [ -f $(SYSROOT)/local/include/amrwb/enc_if.h ] && echo 1),)
+CFLAGS += -DAMR_WB=1 -I$(SYSROOT)/local/include/amrwb
+$(MOD)_LFLAGS += -lamrwb
+else
+ifneq ($(shell [ -f $(SYSROOT)/include/amrwb/enc_if.h ] && echo 1),)
+CFLAGS += -DAMR_WB=1 -I$(SYSROOT)/include/amrwb
+$(MOD)_LFLAGS += -lamrwb
+else
+ifneq ($(shell [ -f $(SYSROOT)/include/vo-amrwbenc/enc_if.h ] && echo 1),)
+CFLAGS += -DAMR_WB=1 -I$(SYSROOT)/include/vo-amrwbenc
+$(MOD)_LFLAGS += -lvo-amrwbenc
+endif
+endif
+endif
+endif
+
+
+# extra for decoder
+ifneq ($(shell [ -f $(SYSROOT)/include/opencore-amrwb/dec_if.h ] && echo 1 ),)
+CFLAGS += -I$(SYSROOT)/include/opencore-amrwb
+$(MOD)_LFLAGS += -lopencore-amrwb
+endif
+
+
+$(MOD)_LFLAGS += -lm
+
+
+include mk/mod.mk