summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2015-06-19 19:20:47 +0200
committerAlfred E. Heggestad <aeh@db.org>2015-06-19 19:20:47 +0200
commitfb624cb2e74ec627c0dd52e0f5eab725d0345601 (patch)
tree8814a50947ea1ec2f370633e830645f71993b836
parentfef6933d984b4a304c2e8f33163e046de54eb2c5 (diff)
added new module CODEC2
-rw-r--r--modules/codec2/codec2.c201
-rw-r--r--modules/codec2/module.mk11
2 files changed, 212 insertions, 0 deletions
diff --git a/modules/codec2/codec2.c b/modules/codec2/codec2.c
new file mode 100644
index 0000000..422adc9
--- /dev/null
+++ b/modules/codec2/codec2.c
@@ -0,0 +1,201 @@
+/**
+ * @file codec2.c CODEC2 audio codec
+ *
+ * Copyright (C) 2015 Creytiv.com
+ */
+#include <re.h>
+#include <rem.h>
+#include <baresip.h>
+#include <codec2/codec2.h>
+
+
+/**
+ * @defgroup codec2 codec2
+ *
+ * The CODEC2 audio codec
+ *
+ * https://en.wikipedia.org/wiki/Codec2
+ */
+
+
+enum {
+ CODEC2_MODE = CODEC2_MODE_2400
+};
+
+
+struct auenc_state {
+ struct CODEC2 *c2;
+};
+
+struct audec_state {
+ struct CODEC2 *c2;
+};
+
+
+static void encode_destructor(void *data)
+{
+ struct auenc_state *st = data;
+
+ if (st->c2)
+ codec2_destroy(st->c2);
+}
+
+
+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->c2 = codec2_create(CODEC2_MODE);
+ if (!st->c2) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ info("codec2: %d samples per frame, %d bits per frame\n",
+ codec2_samples_per_frame(st->c2),
+ codec2_bits_per_frame(st->c2));
+
+ out:
+ if (err)
+ mem_deref(st);
+ else
+ *aesp = st;
+
+ return err;
+}
+
+
+static void decode_destructor(void *data)
+{
+ struct audec_state *st = data;
+
+ if (st->c2)
+ codec2_destroy(st->c2);
+}
+
+
+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->c2 = codec2_create(CODEC2_MODE);
+ if (!st->c2) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ out:
+ if (err)
+ mem_deref(st);
+ else
+ *adsp = st;
+
+ return err;
+}
+
+
+static int encode(struct auenc_state *aes, uint8_t *buf,
+ size_t *len, const int16_t *sampv, size_t sampc)
+{
+ if (!buf || !len || !sampv)
+ return EINVAL;
+
+ if (*len < (size_t)codec2_bits_per_frame(aes->c2)/8)
+ return ENOMEM;
+ if (sampc != (size_t)codec2_samples_per_frame(aes->c2))
+ return EPROTO;
+
+ codec2_encode(aes->c2, buf, (short *)sampv);
+
+ *len = codec2_bits_per_frame(aes->c2)/8;
+
+ return 0;
+}
+
+
+static int decode(struct audec_state *ads, int16_t *sampv,
+ size_t *sampc, const uint8_t *buf, size_t len)
+{
+ if (!sampv || !sampc || !buf)
+ return EINVAL;
+
+ if (*sampc < (size_t)codec2_samples_per_frame(ads->c2))
+ return ENOMEM;
+ if (len < (size_t)codec2_bits_per_frame(ads->c2)/8)
+ return EPROTO;
+
+ codec2_decode(ads->c2, sampv, buf);
+
+ *sampc = codec2_samples_per_frame(ads->c2);
+
+ return 0;
+}
+
+
+static struct aucodec codec2 = {
+ LE_INIT,
+ NULL,
+ "CODEC2",
+ 8000,
+ 1,
+ NULL,
+ encode_update,
+ encode,
+ decode_update,
+ decode,
+ NULL,
+ NULL,
+ NULL
+};
+
+
+static int module_init(void)
+{
+ aucodec_register(&codec2);
+
+ return 0;
+}
+
+
+static int module_close(void)
+{
+ aucodec_unregister(&codec2);
+
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(codec2) = {
+ "codec2",
+ "audio codec",
+ module_init,
+ module_close,
+};
diff --git a/modules/codec2/module.mk b/modules/codec2/module.mk
new file mode 100644
index 0000000..2d4d5d8
--- /dev/null
+++ b/modules/codec2/module.mk
@@ -0,0 +1,11 @@
+#
+# module.mk
+#
+# Copyright (C) 2010 Creytiv.com
+#
+
+MOD := codec2
+$(MOD)_SRCS += codec2.c
+$(MOD)_LFLAGS += -lcodec2
+
+include mk/mod.mk