Merge pull request #762 in FS/freeswitch from ~PIOTRGREGOR/freeswitch:bugfix/FS-8961-avmd-increase-robustness-of-variance to master
* commit '63a30499dbb8d280dbf4d18b393aa68ac3ce8c15': FS-8961 Increase robustness of estimation
This commit is contained in:
commit
9e6593aa73
|
@ -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);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "fast_acosf.h"
|
||||
#include "options.h"
|
||||
|
||||
#ifdef FASTMATH
|
||||
#ifdef AVMD_FAST_MATH
|
||||
|
||||
|
||||
typedef union {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,6 +42,20 @@
|
|||
#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 */
|
||||
|
@ -80,16 +94,9 @@
|
|||
/* decrease this value to eliminate false positives */
|
||||
#define VARIANCE_THRESHOLD (0.0001)
|
||||
|
||||
#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. */
|
||||
|
@ -135,6 +142,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);
|
||||
|
@ -151,13 +162,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,
|
||||
|
@ -226,7 +243,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
|
||||
|
@ -250,7 +267,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);
|
||||
|
@ -401,13 +418,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) {
|
||||
|
@ -625,22 +642,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 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]\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\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");
|
||||
|
@ -659,8 +693,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);
|
||||
|
@ -675,6 +711,8 @@ static void avmd_process(avmd_session_t *session, switch_frame_t *frame)
|
|||
}
|
||||
}
|
||||
session->pos = pos;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue