Merge pull request #714 in FS/freeswitch from ~PIOTRGREGOR/freeswitch:bugfix/FS-8855-avmd-bug-in-calculation-of-tone-s to master

* commit 'f561f1cdd6e724a092bb47ad0de301ddcf290976':
  FS-8855 fix calc of variance of tone's freq estimator
This commit is contained in:
Mike Jerris 2016-03-17 12:58:15 -05:00
commit ba403891ac
2 changed files with 44 additions and 15 deletions

View File

@ -25,6 +25,22 @@
*
* This module detects voicemail beeps using a generalized approach.
*
* Mofdifications:
*
* Piotr Gregor <piotrek.gregor@gmail.com>
* 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 <switch.h>
@ -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;

View File

@ -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) \