From f561f1cdd6e724a092bb47ad0de301ddcf290976 Mon Sep 17 00:00:00 2001 From: Piotr Gregor Date: Mon, 22 Feb 2016 18:26:57 +0000 Subject: [PATCH] FS-8855 fix calc of variance of tone's freq estimator Change SMA buffer APPEND_SMA_VAL macro so now the variance of tone's frequency estimation is correctly calculated. Change frequency advertised in log on beep detection from most recently computed value to average of all values used in DESA computation. --- src/mod/applications/mod_avmd/mod_avmd.c | 54 ++++++++++++++++++------ src/mod/applications/mod_avmd/sma_buf.h | 5 ++- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/mod/applications/mod_avmd/mod_avmd.c b/src/mod/applications/mod_avmd/mod_avmd.c index 9d6999d236..ed1b676756 100644 --- a/src/mod/applications/mod_avmd/mod_avmd.c +++ b/src/mod/applications/mod_avmd/mod_avmd.c @@ -25,6 +25,22 @@ * * This module detects voicemail beeps using a generalized approach. * + * Mofdifications: + * + * Piotr Gregor + * FS-8808 : code refactor + * FS-8809 : fix MAP_POPULATE undeclared + * FS-8810 : fix float-int-float fast arc cosine + * mapping construction (reuse) + * FS-8852 : use predefined table length instead + * of hardcoded computation + * FS-8853 : enable change of resolution (and size) + * of fast arc cos table + * FS-8854 : initialize circular buffer + * FS-8855 : fix APPEND_SMA_VAL macro and avmd_process + * callback so that the variance of tone's + * frequency estimation is correctly + * calculated */ #include @@ -59,9 +75,20 @@ #define TO_HZ(r, f) (((r) * (f)) / (2.0 * M_PI)) /*! Minimum beep frequency in Hertz */ #define MIN_FREQUENCY (300.0) +/*! Minimum frequency as digital normalized frequency */ #define MIN_FREQUENCY_R(r) ((2.0 * M_PI * MIN_FREQUENCY) / (r)) -/*! Maximum beep frequency in Hertz */ +/*! + * Maximum beep frequency in Hertz + * Note: The maximum frequency the DESA-2 algorithm can uniquely + * identify is 0.25 of the sampling rate. All the frequencies + * below that level are detected unambiguously. This means 2kHz + * for 8kHz audio. All the frequencies above 0.25 sampling rate + * will be aliased to some frequency below that threshold. + * This is not a problem here as we are interested in detection + * of any sine wave instead of detection of particular frequency. + */ #define MAX_FREQUENCY (2500.0) +/*! Maximum frequency as digital normalized frequency */ #define MAX_FREQUENCY_R(r) ((2.0 * M_PI * MAX_FREQUENCY) / (r)) /* decrease this value to eliminate false positives */ #define VARIANCE_THRESHOLD (0.001) @@ -560,6 +587,8 @@ end: /*! \brief Process one frame of data with avmd algorithm. * @author Eric des Courtis + * @par Modifications: Piotr Gregor (FS-8852, FS-8853, FS-8854, FS-8855) + * (improved variance estimation calculation) * @param session An avmd session. * @param frame An audio frame. */ @@ -587,25 +616,25 @@ static void avmd_process(avmd_session_t *session, switch_frame_t *frame) b = &session->b; - /*! If beep has already been detected skip the CPU heavy stuff */ + /* If beep has already been detected skip the CPU heavy stuff */ if (session->state.beep_state == BEEP_DETECTED) return; - /*! Precompute values used heavily in the inner loop */ + /* Precompute values used heavily in the inner loop */ sine_len_i = SINE_LEN(session->rate); //sine_len = (double)sine_len_i; //beep_len_i = BEEP_LEN(session->rate); channel = switch_core_session_get_channel(session->session); - /*! Insert frame of 16 bit samples into buffer */ + /* Insert frame of 16 bit samples into buffer */ INSERT_INT16_FRAME(b, (int16_t *)(frame->data), frame->samples); //switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session->session), SWITCH_LOG_INFO, "<<< AVMD sine_len_i=%d >>>\n", sine_len_i); - /*! INNER LOOP -- OPTIMIZATION TARGET */ + /* INNER LOOP -- OPTIMIZATION TARGET */ for (pos = session->pos; pos < (GET_CURRENT_POS(b) - P); pos++) { if ((pos % sine_len_i) == 0) { - /*! Get a desa2 frequency estimate every sine len */ + /* Get a desa2 frequency estimate every sine len */ f = desa2(b, pos); if (f < MIN_FREQUENCY_R(session->rate) || f > MAX_FREQUENCY_R(session->rate)) { @@ -624,14 +653,13 @@ static void avmd_process(avmd_session_t *session, switch_frame_t *frame) session->sma_b.sma, session->sqa_b.sma); } - /*! If variance is less than threshold then we have detection */ - if (v < VARIANCE_THRESHOLD) { - + /* If variance is less than threshold then we have detection */ + if (v < VARIANCE_THRESHOLD && (session->sma_b.pos > 1)) { switch_channel_set_variable_printf(channel, "avmd_total_time", - "[%d]", (int)(switch_micro_time_now() - session->start_time) / 1000); + "[%d]", (int)(switch_micro_time_now() - session->start_time) / 1000); switch_channel_execute_on(channel, "execute_on_avmd_beep"); - /*! Throw an event to FreeSWITCH */ + /* Throw an event to FreeSWITCH */ status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, AVMD_EVENT_BEEP); if (status != SWITCH_STATUS_SUCCESS) return; @@ -646,14 +674,14 @@ static void avmd_process(avmd_session_t *session, switch_frame_t *frame) switch_event_fire(&event_copy); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session->session), SWITCH_LOG_DEBUG, - "<<< AVMD - Beep Detected >>>\n"); + "<<< AVMD - Beep Detected f = [%f] >>>\n", TO_HZ(session->rate, session->sma_b.sma)); switch_channel_set_variable(channel, "avmd_detect", "TRUE"); RESET_SMA_BUFFER(&session->sma_b); RESET_SMA_BUFFER(&session->sqa_b); session->state.beep_state = BEEP_DETECTED; return; - } + } //amp = 0.0; //success = 0.0; diff --git a/src/mod/applications/mod_avmd/sma_buf.h b/src/mod/applications/mod_avmd/sma_buf.h index 7e404bf26b..0bbdc3e1f4 100644 --- a/src/mod/applications/mod_avmd/sma_buf.h +++ b/src/mod/applications/mod_avmd/sma_buf.h @@ -41,10 +41,11 @@ typedef struct { #define APPEND_SMA_VAL(b, v) \ { \ - INC_SMA_POS(b); \ (b)->sma -= ((b)->data[(b)->pos] / (BUFF_TYPE)(b)->len); \ (b)->data[(b)->pos] = (v); \ - (b)->sma += ((b)->data[(b)->pos] / (BUFF_TYPE)(b)->len); \ + (((b)->lpos) >= ((b)->len)) ? ((b)->sma += ((b)->data[(b)->pos] / (BUFF_TYPE)(b)->len)) : \ + ((b)->sma = ((((b)->sma)*((b)->pos)) + ((b)->data[(b)->pos])) / ((BUFF_TYPE)(((b)->pos) + 1))) ; \ + INC_SMA_POS(b); \ } #define RESET_SMA_BUFFER(b) \