]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8961 Increase robustness of estimation
authorPiotr Gregor <piotrek.gregor@gmail.com>
Sun, 20 Mar 2016 23:58:45 +0000 (23:58 +0000)
committerPiotr Gregor <piotrek.gregor@gmail.com>
Mon, 21 Mar 2016 00:10:36 +0000 (00:10 +0000)
Add optional requirement of consecutive streak
of estimations in SMA buffer. Fix definitions.
Add options to control debugging/printing.

src/mod/applications/mod_avmd/desa2.c
src/mod/applications/mod_avmd/fast_acosf.c
src/mod/applications/mod_avmd/fast_acosf.h
src/mod/applications/mod_avmd/mod_avmd.c
src/mod/applications/mod_avmd/options.h

index 9550a211ce2c832913331067cd767a7c974d0c75..bb19ad1f449b1a9b83a0b891d8fe1aa9f68127cc 100644 (file)
@@ -10,7 +10,7 @@
 #include "desa2.h"
 #include "options.h"
 
-#ifdef FASTMATH
+#ifdef AVMD_FAST_MATH
 #include "fast_acosf.h"
 #endif
 
@@ -40,7 +40,7 @@ extern double desa2(circ_buffer_t *b, size_t i)
     n = ((x2sq) - (x0 * x4)) - ((x1 * x1) - (x0 * x2)) - ((x3 * x3) - (x2 * x4));
 
 
-#ifdef FASTMATH
+#ifdef AVMD_FAST_MATH
     result = 0.5 * (double)fast_acosf((float)n/d);
 #else
     result = 0.5 * acos(n/d);
index 48e2baf58058e0756b4c32de94c71bf70082e668..b959d0b64001737d5353fb253e3d0b784dd035a9 100644 (file)
@@ -20,7 +20,7 @@
 #include "fast_acosf.h"
 #include "options.h"
 
-#ifdef FASTMATH
+#ifdef AVMD_FAST_MATH
 
 
 typedef union {
index a5f2f0649e5fa529d9cbf88e328fb202297c901b..e70c8f936b179748fc5e1a0febd3ec13fbf10793 100644 (file)
@@ -7,7 +7,7 @@
 /*! \brief Arc cosine table initialization.
  *
  * @author Eric des Courtis
- * @par    Changes: Piotr Gregor, 07 Feb 2016 (FS-8809, FS-8810)
+ * @par    Modifications: Piotr Gregor < piotrek.gregor gmail.com >
  * @return 0 on success, negative value otherwise:
  *          -1 can't access arc cos table with error != NOENT,
  *          -2 table creation failed (compute_table)
@@ -19,7 +19,7 @@ extern int init_fast_acosf(void);
 /*! \brief Arc cosine table deinitialization.
  *
  * @author Eric des Courtis
- * @par    Changes: Piotr Gregor, 09 Feb 2016 (FS-8809, FS-8810)
+ * @par    Modifications: Piotr Gregor < piotrek.gregor gmail.com >
  * @return 0 on success, negative value otherwise:
  *          -1 munmap failed,
  *          -2 close failed
@@ -35,7 +35,7 @@ extern float fast_acosf(float x);
 /*! \brief Arc cosine table creation.
  *
  * @author Eric des Courtis
- * @par    Changes: Piotr Gregor, 07 Feb 2016 (FS-8809, FS-8810)
+ * @par    Modifications: Piotr Gregor < piotrek.gregor gmail.com >
  * @return 0 on success, negative value otherwise:
  *          -1 fwrite failed,
  *          -2 fclose failed
index ed1b676756785f18839d798b624a9bf65289b8c7..4acba1ca6d9445acf4583812e080b67773f698a0 100644 (file)
 #define ISNAN(x) (isnan(x))
 #endif
 
+
+#include "amplitude.h"
+#include "buffer.h"
+#include "desa2.h"
+//#include "goertzel.h"
+#include "psi.h"
+#include "sma_buf.h"
+#include "options.h"
+
+#ifdef AVMD_FAST_MATH
+#include "fast_acosf.h"
+#endif
+
+
 /*! Calculate how many audio samples per ms based on the rate */
 #define SAMPLES_PER_MS(r, m) ((r) / (1000/(m)))
 /*! Minimum beep length */
 /* decrease this value to eliminate false positives */
 #define VARIANCE_THRESHOLD (0.001)
 
-#include "amplitude.h"
-#include "buffer.h"
-#include "desa2.h"
-//#include "goertzel.h"
-#include "psi.h"
-#include "sma_buf.h"
-#include "options.h"
-
-#ifdef FASTMATH
-#include "fast_acosf.h"
+#ifdef AVMD_REQUIRE_CONTINUOUS_STREAK
+    /* increase this value to eliminate false positives */
+    #define SAMPLES_CONSECUTIVE_STREAK 3
 #endif
 
 /*! Syntax of the API call. */
@@ -148,6 +155,10 @@ typedef struct {
        /* freq_table_t ft; */
        avmd_state_t state;
        switch_time_t start_time;
+#ifdef AVMD_REQUIRE_CONTINUOUS_STREAK
+    size_t samples_streak; /* number of DESA samples in single streak without reset
+                              needed to validate SMA estimator, half the size of SMA buffer */
+#endif
 } avmd_session_t;
 
 static void avmd_process(avmd_session_t *session, switch_frame_t *frame);
@@ -164,13 +175,19 @@ static void init_avmd_session_data(avmd_session_t *avmd_session,  switch_core_se
 {
        /*! This is a worst case sample rate estimate */
        avmd_session->rate = 48000;
-       INIT_CIRC_BUFFER(&avmd_session->b, (size_t)BEEP_LEN(avmd_session->rate), (size_t)FRAME_LEN(avmd_session->rate), fs_session);
+       INIT_CIRC_BUFFER(&avmd_session->b,
+            (size_t)BEEP_LEN(avmd_session->rate),
+            (size_t)FRAME_LEN(avmd_session->rate),
+            fs_session);
 
        avmd_session->session = fs_session;
        avmd_session->pos = 0;
        avmd_session->f = 0.0;
        avmd_session->state.last_beep = 0;
        avmd_session->state.beep_state = BEEP_NOTDETECTED;
+#ifdef AVMD_REQUIRE_CONTINUOUS_STREAK
+    avmd_session->samples_streak = SAMPLES_CONSECUTIVE_STREAK;
+#endif
 
        INIT_SMA_BUFFER(
                &avmd_session->sma_b,
@@ -239,7 +256,7 @@ static switch_bool_t avmd_callback(switch_media_bug_t * bug, void *user_data, sw
  */
 SWITCH_MODULE_LOAD_FUNCTION(mod_avmd_load)
 {
-#ifdef FASTMATH
+#ifdef AVMD_FAST_MATH
     char    err[150];
     int     ret;
 #endif
@@ -263,7 +280,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_avmd_load)
                "Advanced Voicemail detection enabled\n"
        );
 
-#ifdef FASTMATH
+#ifdef AVMD_FAST_MATH
     ret = init_fast_acosf();
     if (ret != 0) {
         strerror_r(errno, err, 150);
@@ -414,13 +431,13 @@ SWITCH_STANDARD_APP(avmd_start_function)
  */
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_avmd_shutdown)
 {
-#ifdef FASTMATH
+#ifdef AVMD_FAST_MATH
        int res;
 #endif
 
        switch_event_free_subclass(AVMD_EVENT_BEEP);
        
-#ifdef FASTMATH
+#ifdef AVMD_FAST_MATH
        res = destroy_fast_acosf();
     if (res != 0) {
         switch (res) {
@@ -639,22 +656,39 @@ static void avmd_process(avmd_session_t *session, switch_frame_t *frame)
 
                        if (f < MIN_FREQUENCY_R(session->rate) || f > MAX_FREQUENCY_R(session->rate)) {
                                v = 99999.0;
+#ifdef AVMD_REQUIRE_CONTINUOUS_STREAK
                                RESET_SMA_BUFFER(&session->sma_b);
                                RESET_SMA_BUFFER(&session->sqa_b);
+                session->samples_streak = SAMPLES_CONSECUTIVE_STREAK;
+#endif
                        } else {
                                APPEND_SMA_VAL(&session->sma_b, f);
                                APPEND_SMA_VAL(&session->sqa_b, f * f);
-
+#ifdef AVMD_REQUIRE_CONTINUOUS_STREAK
+                if (session->samples_streak > 0)
+                    --session->samples_streak;
+#endif
                                /* calculate variance */
                                v = session->sqa_b.sma - (session->sma_b.sma * session->sma_b.sma);
-
+#ifdef AVMD_DEBUG
+#ifdef AVMD_REQUIRE_CONTINUOUS_STREAK
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session->session), SWITCH_LOG_DEBUG,
+                    "<<< AVMD v[%f] f[%f] [%f]Hz\tsma[%f][%f]Hz\tsqa[%f]\tstreak[%zu] pos[%zu] >>>\n", v, f, TO_HZ(session->rate, f),
+                    session->sma_b.sma, TO_HZ(session->rate, session->sma_b.sma), session->sqa_b.sma, session->samples_streak, session->sma_b.pos);
+#else
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session->session), SWITCH_LOG_DEBUG,
-                    "<<< AVMD v=[%f] f=[%f] [%f]Hz sma=[%f] sqa=[%f] >>>\n", v, f, TO_HZ(session->rate, f),
-                    session->sma_b.sma, session->sqa_b.sma);
+                    "<<< AVMD v[%f] f[%f] [%f]Hz\tsma[%f][%f]Hz\tsqa[%f]\tpos[%zu] >>>\n", v, f, TO_HZ(session->rate, f),
+                    session->sma_b.sma, TO_HZ(session->rate, session->sma_b.sma), session->sqa_b.sma, session->sma_b.pos);
+#endif
+#endif
                        }
 
                        /* If variance is less than threshold then we have detection */
+#ifdef AVMD_REQUIRE_CONTINUOUS_STREAK
+                       if (v < VARIANCE_THRESHOLD && (session->sma_b.pos > 1) && (session->samples_streak == 0)) {
+#else
                        if (v < VARIANCE_THRESHOLD && (session->sma_b.pos > 1)) {
+#endif
                                switch_channel_set_variable_printf(channel, "avmd_total_time",
                         "[%d]", (int)(switch_micro_time_now() - session->start_time) / 1000);
                                switch_channel_execute_on(channel, "execute_on_avmd_beep");
@@ -673,8 +707,10 @@ static void avmd_process(avmd_session_t *session, switch_frame_t *frame)
                                switch_core_session_queue_event(session->session, &event);
                                switch_event_fire(&event_copy);
 
+#ifdef AVMD_REPORT_STATUS
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session->session), SWITCH_LOG_DEBUG,
                         "<<< AVMD - Beep Detected f = [%f] >>>\n", TO_HZ(session->rate, session->sma_b.sma));
+#endif
                                switch_channel_set_variable(channel, "avmd_detect", "TRUE");
                                RESET_SMA_BUFFER(&session->sma_b);
                                RESET_SMA_BUFFER(&session->sqa_b);
@@ -689,6 +725,8 @@ static void avmd_process(avmd_session_t *session, switch_frame_t *frame)
                }
        }
        session->pos = pos;
+
+    return;
 }
 
 /* For Emacs:
index 9be3263938675c35eec0bb5234228a14f059ff9f..39274a52c9e53a46d4791eee470a0771e5250a5e 100644 (file)
@@ -1,7 +1,32 @@
+/*
+ * @brief   Options controlling avmd module.
+ *
+ * @author Eric des Courtis
+ * @par    Modifications: Piotr Gregor < piotrek.gregor gmail.com >
+ */
+
+
 #ifndef __OPTIONS_H__
 #define __OPTIONS_H__
 
-/* #define FASTMATH */
+
+/* #define AVMD_DEBUG 1 */
+
+/* define/undef this to enable/disable reporting of beep
+ * detection status after session ended */
+#define AVMD_REPORT_STATUS 1
+
+/* define/undefine this to enable/disable faster computation
+ * of arcus cosine - table will be created mapping floats
+ * to integers and returning arc cos values given these integer
+ * indexes into table */
+/* #define AVMD_FAST_MATH */
+
+/* define/undefine this to classify avmd beep detection as valid
+ * only when there is required number of consecutive elements
+ * in the SMA buffer without reset */
+#define AVMD_REQUIRE_CONTINUOUS_STREAK 1
+
 
 #endif