summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/baresip.h12
-rw-r--r--src/aulevel.c85
-rw-r--r--src/srcs.mk1
-rw-r--r--test/aulevel.c61
-rw-r--r--test/main.c1
-rw-r--r--test/srcs.mk1
-rw-r--r--test/test.h1
7 files changed, 162 insertions, 0 deletions
diff --git a/include/baresip.h b/include/baresip.h
index f00b5c9..5087296 100644
--- a/include/baresip.h
+++ b/include/baresip.h
@@ -65,6 +65,18 @@ const char *account_stun_host(const struct account *acc);
/*
+ * Audio-level
+ */
+
+
+#define AULEVEL_MIN (-96.0)
+#define AULEVEL_MAX (0.0)
+
+
+double aulevel_calc_dbov(const int16_t *sampv, size_t sampc);
+
+
+/*
* Call
*/
diff --git a/src/aulevel.c b/src/aulevel.c
new file mode 100644
index 0000000..bc9a27a
--- /dev/null
+++ b/src/aulevel.c
@@ -0,0 +1,85 @@
+/**
+ * @file src/aulevel.c Audio level
+ *
+ * Copyright (C) 2017 Creytiv.com
+ */
+
+#include <math.h>
+#include <re.h>
+#include <baresip.h>
+#include "core.h"
+
+
+/**
+ * Generic routine to calculate RMS (Root-Mean-Square) from
+ * a set of signed 16-bit values
+ *
+ * \verbatim
+
+ .---------------
+ | N-1
+ | ----.
+ | \
+ | \ 2
+ | | s[n]
+ | /
+ | /
+ _ | ----'
+ \ | n=0
+ \ | ------------
+ \| N
+
+ \endverbatim
+ *
+ * @param data Array of signed 16-bit values
+ * @param len Number of values
+ *
+ * @return RMS value from 0 to 32768
+ */
+static double calc_rms(const int16_t *data, size_t len)
+{
+ double sum = 0;
+ size_t i;
+
+ if (!data || !len)
+ return .0;
+
+ for (i = 0; i < len; i++) {
+ const double sample = data[i];
+
+ sum += sample * sample;
+ }
+
+ return sqrt(sum / (double)len);
+}
+
+
+/**
+ * Calculate the audio level in dBov from a set of audio samples.
+ * dBov is the level, in decibels, relative to the overload point
+ * of the system
+ *
+ * @param sampv Audio samples
+ * @param sampc Number of audio samples
+ *
+ * @return Audio level expressed in dBov
+ */
+double aulevel_calc_dbov(const int16_t *sampv, size_t sampc)
+{
+ static const double peak = 32767.0;
+ double rms, dbov;
+
+ if (!sampv || !sampc)
+ return AULEVEL_MIN;
+
+ rms = calc_rms(sampv, sampc) / peak;
+
+ dbov = 20 * log10(rms);
+
+ if (dbov < AULEVEL_MIN)
+ dbov = AULEVEL_MIN;
+ else if (dbov > AULEVEL_MAX)
+ dbov = AULEVEL_MAX;
+
+ return dbov;
+}
diff --git a/src/srcs.mk b/src/srcs.mk
index c538600..cdb2a26 100644
--- a/src/srcs.mk
+++ b/src/srcs.mk
@@ -8,6 +8,7 @@ SRCS += account.c
SRCS += aucodec.c
SRCS += audio.c
SRCS += aufilt.c
+SRCS += aulevel.c
SRCS += auplay.c
SRCS += ausrc.c
SRCS += baresip.c
diff --git a/test/aulevel.c b/test/aulevel.c
new file mode 100644
index 0000000..6d083f6
--- /dev/null
+++ b/test/aulevel.c
@@ -0,0 +1,61 @@
+/**
+ * @file test/aulevel.c Baresip selftest -- audio levels
+ *
+ * Copyright (C) 2010 - 2017 Creytiv.com
+ */
+
+#include <re.h>
+#include <baresip.h>
+#include "test.h"
+
+
+#define DEBUG_MODULE "aulevel"
+#define DEBUG_LEVEL 5
+#include <re_dbg.h>
+
+
+#define PREC .6
+
+
+int test_aulevel(void)
+{
+ static const struct {
+ int16_t sampv[2];
+ double level;
+ } testv[] = {
+
+ { { 0, -0}, -96.0 },
+ { { 0, 1}, -93.0 },
+ { { 1, -1}, -90.0 },
+ { { 2, -2}, -84.0 },
+ { { 4, -4}, -78.0 },
+ { { 8, -8}, -72.0 },
+ { { 16, -16}, -66.0 },
+ { { 32, -32}, -60.0 },
+ { { 64, -64}, -54.0 },
+ { { 128, -128}, -48.0 },
+ { { 256, -256}, -42.0 },
+ { { 512, -512}, -36.0 },
+ { { 1024, -1024}, -30.0 },
+ { { 2048, -2048}, -24.0 },
+ { { 4096, -4096}, -18.0 },
+ { { 8192, -8192}, -12.0 },
+ { {16384, -16384}, -6.0 },
+ { {32767, -32768}, 0.0 },
+ };
+ size_t i;
+ int err = 0;
+
+ for (i=0; i<ARRAY_SIZE(testv); i++) {
+
+ double level;
+
+ level = aulevel_calc_dbov(testv[i].sampv,
+ ARRAY_SIZE(testv[i].sampv));
+
+ ASSERT_DOUBLE_EQ(testv[i].level, level, PREC);
+ }
+
+ out:
+ return err;
+}
diff --git a/test/main.c b/test/main.c
index 125f1ec..f443dcb 100644
--- a/test/main.c
+++ b/test/main.c
@@ -23,6 +23,7 @@ struct test {
static const struct test tests[] = {
TEST(test_account),
+ TEST(test_aulevel),
TEST(test_call_af_mismatch),
TEST(test_call_answer),
TEST(test_call_answer_hangup_a),
diff --git a/test/srcs.mk b/test/srcs.mk
index 3c481ac..b3a2637 100644
--- a/test/srcs.mk
+++ b/test/srcs.mk
@@ -9,6 +9,7 @@
# Test-cases:
#
TEST_SRCS += account.c
+TEST_SRCS += aulevel.c
TEST_SRCS += call.c
TEST_SRCS += cmd.c
TEST_SRCS += contact.c
diff --git a/test/test.h b/test/test.h
index 3a19ec1..a68d61d 100644
--- a/test/test.h
+++ b/test/test.h
@@ -178,6 +178,7 @@ int mock_vidisp_register(struct vidisp **vidispp);
/* test cases */
int test_account(void);
+int test_aulevel(void);
int test_cmd(void);
int test_cmd_long(void);
int test_contact(void);