mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-29 05:30:14 +00:00
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:
commit
ba403891ac
@ -25,6 +25,22 @@
|
|||||||
*
|
*
|
||||||
* This module detects voicemail beeps using a generalized approach.
|
* 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>
|
#include <switch.h>
|
||||||
@ -59,9 +75,20 @@
|
|||||||
#define TO_HZ(r, f) (((r) * (f)) / (2.0 * M_PI))
|
#define TO_HZ(r, f) (((r) * (f)) / (2.0 * M_PI))
|
||||||
/*! Minimum beep frequency in Hertz */
|
/*! Minimum beep frequency in Hertz */
|
||||||
#define MIN_FREQUENCY (300.0)
|
#define MIN_FREQUENCY (300.0)
|
||||||
|
/*! Minimum frequency as digital normalized frequency */
|
||||||
#define MIN_FREQUENCY_R(r) ((2.0 * M_PI * MIN_FREQUENCY) / (r))
|
#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)
|
#define MAX_FREQUENCY (2500.0)
|
||||||
|
/*! Maximum frequency as digital normalized frequency */
|
||||||
#define MAX_FREQUENCY_R(r) ((2.0 * M_PI * MAX_FREQUENCY) / (r))
|
#define MAX_FREQUENCY_R(r) ((2.0 * M_PI * MAX_FREQUENCY) / (r))
|
||||||
/* decrease this value to eliminate false positives */
|
/* decrease this value to eliminate false positives */
|
||||||
#define VARIANCE_THRESHOLD (0.001)
|
#define VARIANCE_THRESHOLD (0.001)
|
||||||
@ -560,6 +587,8 @@ end:
|
|||||||
|
|
||||||
/*! \brief Process one frame of data with avmd algorithm.
|
/*! \brief Process one frame of data with avmd algorithm.
|
||||||
* @author Eric des Courtis
|
* @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 session An avmd session.
|
||||||
* @param frame An audio frame.
|
* @param frame An audio frame.
|
||||||
*/
|
*/
|
||||||
@ -587,25 +616,25 @@ static void avmd_process(avmd_session_t *session, switch_frame_t *frame)
|
|||||||
|
|
||||||
b = &session->b;
|
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;
|
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_i = SINE_LEN(session->rate);
|
||||||
//sine_len = (double)sine_len_i;
|
//sine_len = (double)sine_len_i;
|
||||||
//beep_len_i = BEEP_LEN(session->rate);
|
//beep_len_i = BEEP_LEN(session->rate);
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(session->session);
|
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);
|
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);
|
//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++) {
|
for (pos = session->pos; pos < (GET_CURRENT_POS(b) - P); pos++) {
|
||||||
if ((pos % sine_len_i) == 0) {
|
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);
|
f = desa2(b, pos);
|
||||||
|
|
||||||
if (f < MIN_FREQUENCY_R(session->rate) || f > MAX_FREQUENCY_R(session->rate)) {
|
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);
|
session->sma_b.sma, session->sqa_b.sma);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! If variance is less than threshold then we have detection */
|
/* If variance is less than threshold then we have detection */
|
||||||
if (v < VARIANCE_THRESHOLD) {
|
if (v < VARIANCE_THRESHOLD && (session->sma_b.pos > 1)) {
|
||||||
|
|
||||||
switch_channel_set_variable_printf(channel, "avmd_total_time",
|
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");
|
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);
|
status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, AVMD_EVENT_BEEP);
|
||||||
if (status != SWITCH_STATUS_SUCCESS) return;
|
if (status != SWITCH_STATUS_SUCCESS) return;
|
||||||
|
|
||||||
@ -646,7 +674,7 @@ static void avmd_process(avmd_session_t *session, switch_frame_t *frame)
|
|||||||
switch_event_fire(&event_copy);
|
switch_event_fire(&event_copy);
|
||||||
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session->session), SWITCH_LOG_DEBUG,
|
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");
|
switch_channel_set_variable(channel, "avmd_detect", "TRUE");
|
||||||
RESET_SMA_BUFFER(&session->sma_b);
|
RESET_SMA_BUFFER(&session->sma_b);
|
||||||
RESET_SMA_BUFFER(&session->sqa_b);
|
RESET_SMA_BUFFER(&session->sqa_b);
|
||||||
|
@ -41,10 +41,11 @@ typedef struct {
|
|||||||
|
|
||||||
#define APPEND_SMA_VAL(b, v) \
|
#define APPEND_SMA_VAL(b, v) \
|
||||||
{ \
|
{ \
|
||||||
INC_SMA_POS(b); \
|
|
||||||
(b)->sma -= ((b)->data[(b)->pos] / (BUFF_TYPE)(b)->len); \
|
(b)->sma -= ((b)->data[(b)->pos] / (BUFF_TYPE)(b)->len); \
|
||||||
(b)->data[(b)->pos] = (v); \
|
(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) \
|
#define RESET_SMA_BUFFER(b) \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user