From 0cec73a6fb845e94e41d4df21d80be98d42933b1 Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Wed, 4 May 2022 16:03:54 +0200 Subject: [PATCH] attdet: Move to fixed point --- include/lc3_private.h | 2 +- src/attdet.c | 34 +++++++++++++++++----------------- src/attdet.h | 2 +- src/lc3.c | 2 +- test/attdet.py | 8 ++++---- test/attdet_py.c | 4 ++-- test/ctypes.h | 8 ++++---- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/lc3_private.h b/include/lc3_private.h index 970ef8e..3d9ec0f 100644 --- a/include/lc3_private.h +++ b/include/lc3_private.h @@ -75,7 +75,7 @@ enum lc3_srate { */ typedef struct lc3_attdet_analysis { - float en1, an1; + int32_t en1, an1; int p_att; } lc3_attdet_analysis_t; diff --git a/src/attdet.c b/src/attdet.c index 3f146f1..3d1528d 100644 --- a/src/attdet.c +++ b/src/attdet.c @@ -23,7 +23,7 @@ * Time domain attack detector */ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, - int nbytes, struct lc3_attdet_analysis *attdet, const float *x) + int nbytes, struct lc3_attdet_analysis *attdet, const int16_t *x) { /* --- Check enabling --- */ @@ -40,32 +40,32 @@ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, /* --- Filtering & Energy calculation --- */ int nblk = 4 - (dt == LC3_DT_7M5); - float e[4]; + int32_t e[4]; for (int i = 0; i < nblk; i++) { e[i] = 0; if (sr == LC3_SRATE_32K) { - float xn2 = x[-4] + x[-3]; - float xn1 = x[-2] + x[-1]; - float xn, xf; + int16_t xn2 = (x[-4] + x[-3]) >> 1; + int16_t xn1 = (x[-2] + x[-1]) >> 1; + int16_t xn, xf; for (int j = 0; j < 40; j++, x += 2, xn2 = xn1, xn1 = xn) { - xn = x[0] + x[1]; - xf = 0.375f * xn - 0.5f * xn1 + 0.125f * xn2; - e[i] += xf * xf; + xn = (x[0] + x[1]) >> 1; + xf = (3 * xn - 4 * xn1 + 1 * xn2) >> 3; + e[i] += (xf * xf) >> 5; } } else { - float xn2 = x[-6] + x[-5] + x[-4]; - float xn1 = x[-3] + x[-2] + x[-1]; - float xn, xf; + int16_t xn2 = (x[-6] + x[-5] + x[-4]) >> 2; + int16_t xn1 = (x[-3] + x[-2] + x[-1]) >> 2; + int16_t xn, xf; for (int j = 0; j < 40; j++, x += 3, xn2 = xn1, xn1 = xn) { - xn = x[0] + x[1] + x[2]; - xf = 0.375f * xn - 0.5f * xn1 + 0.125f * xn2; - e[i] += xf * xf; + xn = (x[0] + x[1] + x[2]) >> 2; + xf = (3 * xn - 4 * xn1 + 1 * xn2) >> 3; + e[i] += (xf * xf) >> 5; } } } @@ -75,13 +75,13 @@ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, * in such way, it will be initialized to 0 */ int p_att = 0; - float a[4]; + int32_t a[4]; for (int i = 0; i < nblk; i++) { - a[i] = fmaxf(0.25f * attdet->an1, attdet->en1); + a[i] = LC3_MAX(attdet->an1 >> 2, attdet->en1); attdet->en1 = e[i], attdet->an1 = a[i]; - if (e[i] > 8.5f * a[i]) + if ((e[i] >> 3) > a[i] + (a[i] >> 4)) p_att = i + 1; } diff --git a/src/attdet.h b/src/attdet.h index 8428376..14073bd 100644 --- a/src/attdet.h +++ b/src/attdet.h @@ -38,7 +38,7 @@ * return 1: Attack detected 0: Otherwise */ bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr, - int nbytes, lc3_attdet_analysis_t *attdet, const float *x); + int nbytes, lc3_attdet_analysis_t *attdet, const int16_t *x); #endif /* __LC3_ATTDET_H */ diff --git a/src/lc3.c b/src/lc3.c index 6560b6e..ba45b96 100644 --- a/src/lc3.c +++ b/src/lc3.c @@ -214,7 +214,7 @@ static void analyze(struct lc3_encoder *encoder, /* --- Temporal --- */ - bool att = lc3_attdet_run(dt, sr_pcm, nbytes, &encoder->attdet, xs); + bool att = lc3_attdet_run(dt, sr_pcm, nbytes, &encoder->attdet, xt); side->pitch_present = lc3_ltpf_analyse(dt, sr_pcm, &encoder->ltpf, xt, &side->ltpf); diff --git a/test/attdet.py b/test/attdet.py index 0bb6f90..c318e32 100644 --- a/test/attdet.py +++ b/test/attdet.py @@ -132,8 +132,8 @@ def check_unit(rng, dt, sr): ### Generate noise, and an attack at random point - x = (2 * rng.random(ns)) - 1 - x[(ns * rng.random()).astype(int)] *= 100 + x = ((2 * rng.random(ns)) - 1) * (2 ** 8 - 1) + x[(ns * rng.random()).astype(int)] *= 2 ** 7 ### Check Implementation @@ -143,8 +143,8 @@ def check_unit(rng, dt, sr): f_att_c = lc3.attdet_run(dt, sr, 100, state_c, x_c) ok = ok and f_att_c == f_att - ok = ok and np.amax(np.abs(1 - state_c['en1']/attdet.en1)) < 1e-6 - ok = ok and np.amax(np.abs(1 - state_c['an1']/attdet.an1)) < 1e-6 + ok = ok and np.amax(np.abs(1 - state_c['en1']/attdet.en1)) < 2 + ok = ok and np.amax(np.abs(1 - state_c['an1']/attdet.an1)) < 2 ok = ok and state_c['p_att'] == attdet.p_att return ok diff --git a/test/attdet_py.c b/test/attdet_py.c index 08c51fb..d85a8a5 100644 --- a/test/attdet_py.c +++ b/test/attdet_py.c @@ -27,7 +27,7 @@ static PyObject *attdet_run_py(PyObject *m, PyObject *args) unsigned dt, sr, nbytes; PyObject *attdet_obj, *x_obj; struct lc3_attdet_analysis attdet = { 0 }; - float *x; + int16_t *x; if (!PyArg_ParseTuple(args, "IIIOO", &dt, &sr, &nbytes, &attdet_obj, &x_obj)) @@ -39,7 +39,7 @@ static PyObject *attdet_run_py(PyObject *m, PyObject *args) int ns = LC3_NS(dt, sr); - CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ns+6, &x)); + CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_INT16, ns+6, &x)); int att = lc3_attdet_run(dt, sr, nbytes, &attdet, x+6); diff --git a/test/ctypes.h b/test/ctypes.h index 5627494..1c1e56a 100644 --- a/test/ctypes.h +++ b/test/ctypes.h @@ -201,10 +201,10 @@ static PyObject *to_attdet_analysis( CTYPES_CHECK("attdet", obj && PyDict_Check(obj)); CTYPES_CHECK("attdet.en1", to_scalar( - PyDict_GetItemString(obj, "en1"), NPY_FLOAT, &attdet->en1)); + PyDict_GetItemString(obj, "en1"), NPY_INT32, &attdet->en1)); CTYPES_CHECK("attdet.an1", to_scalar( - PyDict_GetItemString(obj, "an1"), NPY_FLOAT, &attdet->an1)); + PyDict_GetItemString(obj, "an1"), NPY_INT32, &attdet->an1)); CTYPES_CHECK("attdet.p_att", to_scalar( PyDict_GetItemString(obj, "p_att"), NPY_INT, &attdet->p_att)); @@ -219,10 +219,10 @@ static PyObject *from_attdet_analysis( if (!obj) obj = PyDict_New(); PyDict_SetItemString(obj, "en1", - new_scalar(NPY_FLOAT, &attdet->en1)); + new_scalar(NPY_INT32, &attdet->en1)); PyDict_SetItemString(obj, "an1", - new_scalar(NPY_FLOAT, &attdet->an1)); + new_scalar(NPY_INT32, &attdet->an1)); PyDict_SetItemString(obj, "p_att", new_scalar(NPY_INT, &attdet->p_att));