summaryrefslogtreecommitdiff
path: root/modules/sndfile/sndfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/sndfile/sndfile.c')
-rw-r--r--modules/sndfile/sndfile.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/modules/sndfile/sndfile.c b/modules/sndfile/sndfile.c
new file mode 100644
index 0000000..e8fe9c9
--- /dev/null
+++ b/modules/sndfile/sndfile.c
@@ -0,0 +1,180 @@
+/**
+ * @file sndfile.c Audio dumper using libsndfile
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <sndfile.h>
+#include <time.h>
+#include <re.h>
+#include <baresip.h>
+
+
+struct sndfile_enc {
+ struct aufilt_enc_st af; /* base class */
+ SNDFILE *enc;
+};
+
+struct sndfile_dec {
+ struct aufilt_dec_st af; /* base class */
+ SNDFILE *dec;
+};
+
+
+static int timestamp_print(struct re_printf *pf, const struct tm *tm)
+{
+ if (!tm)
+ return 0;
+
+ return re_hprintf(pf, "%d-%02d-%02d-%02d-%02d-%02d",
+ 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+
+static void enc_destructor(void *arg)
+{
+ struct sndfile_enc *st = arg;
+
+ if (st->enc)
+ sf_close(st->enc);
+
+ list_unlink(&st->af.le);
+}
+
+
+static void dec_destructor(void *arg)
+{
+ struct sndfile_dec *st = arg;
+
+ if (st->dec)
+ sf_close(st->dec);
+
+ list_unlink(&st->af.le);
+}
+
+
+static SNDFILE *openfile(const struct aufilt_prm *prm, bool enc)
+{
+ char filename[128];
+ SF_INFO sfinfo;
+ time_t tnow = time(0);
+ struct tm *tm = localtime(&tnow);
+ SNDFILE *sf;
+
+ (void)re_snprintf(filename, sizeof(filename),
+ "dump-%H-%s.wav",
+ timestamp_print, tm, enc ? "enc" : "dec");
+
+ sfinfo.samplerate = prm->srate;
+ sfinfo.channels = prm->ch;
+ sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+
+ sf = sf_open(filename, SFM_WRITE, &sfinfo);
+ if (!sf) {
+ warning("sndfile: could not open: %s\n", filename);
+ puts(sf_strerror(NULL));
+ return NULL;
+ }
+
+ info("sndfile: dumping %s audio to %s\n",
+ enc ? "encode" : "decode", filename);
+
+ return sf;
+}
+
+
+static int encode_update(struct aufilt_enc_st **stp, void **ctx,
+ const struct aufilt *af, struct aufilt_prm *prm)
+{
+ struct sndfile_enc *st;
+ int err = 0;
+ (void)ctx;
+ (void)af;
+
+ st = mem_zalloc(sizeof(*st), enc_destructor);
+ if (!st)
+ return EINVAL;
+
+ st->enc = openfile(prm, true);
+ if (!st->enc)
+ err = ENOMEM;
+
+ 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 sndfile_dec *st;
+ int err = 0;
+ (void)ctx;
+ (void)af;
+
+ st = mem_zalloc(sizeof(*st), dec_destructor);
+ if (!st)
+ return EINVAL;
+
+ st->dec = openfile(prm, false);
+ if (!st->dec)
+ err = ENOMEM;
+
+ 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 sndfile_enc *sf = (struct sndfile_enc *)st;
+
+ sf_write_short(sf->enc, sampv, *sampc);
+
+ return 0;
+}
+
+
+static int decode(struct aufilt_dec_st *st, int16_t *sampv, size_t *sampc)
+{
+ struct sndfile_dec *sf = (struct sndfile_dec *)st;
+
+ sf_write_short(sf->dec, sampv, *sampc);
+
+ return 0;
+}
+
+
+static struct aufilt sndfile = {
+ LE_INIT, "sndfile", encode_update, encode, decode_update, decode
+};
+
+
+static int module_init(void)
+{
+ aufilt_register(&sndfile);
+ return 0;
+}
+
+
+static int module_close(void)
+{
+ aufilt_unregister(&sndfile);
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(sndfile) = {
+ "sndfile",
+ "filter",
+ module_init,
+ module_close
+};