Merge pull request #973 in FS/freeswitch from ~PIOTRGREGOR/freeswitch:feature/FS-9564-add-lagged-detectors to master

* commit 'b44b6e5b20d93e1fdc7330385c56fa5c37c3eaec':
  FS-9564 [avmd]: add lagged detectors
This commit is contained in:
Mike Jerris 2016-09-29 11:06:29 -05:00
commit a15dcbe351
7 changed files with 328 additions and 72 deletions

View File

@ -37,7 +37,7 @@
<!-- required number of consecutive elements in the SMA buffer <!-- required number of consecutive elements in the SMA buffer
without reset. This parameter helps to avoid false beeps, bigger this value is without reset. This parameter helps to avoid false beeps, bigger this value is
smaller the probability of getting false detection --> smaller the probability of getting false detection -->
<param name="sample_n_continuous_streak" value="5"/> <param name="sample_n_continuous_streak" value="3"/>
<!-- define number of samples to skip starting from the beginning <!-- define number of samples to skip starting from the beginning
of the frame and/or after reset has happened. This serves the purpose of skipping first few of the frame and/or after reset has happened. This serves the purpose of skipping first few
@ -46,7 +46,7 @@
<param name="sample_n_to_skip" value="0"/> <param name="sample_n_to_skip" value="0"/>
<param name="require_continuous_streak_amp" value="1"/> <param name="require_continuous_streak_amp" value="1"/>
<param name="sample_n_continuous_streak_amp" value="5"/> <param name="sample_n_continuous_streak_amp" value="3"/>
<!-- define/undefine this to enable/disable simplified estimation <!-- define/undefine this to enable/disable simplified estimation
of frequency based on approximation of sin(x) with (x) of frequency based on approximation of sin(x) with (x)

View File

@ -37,7 +37,7 @@
<!-- required number of consecutive elements in the SMA buffer <!-- required number of consecutive elements in the SMA buffer
without reset. This parameter helps to avoid false beeps, bigger this value is without reset. This parameter helps to avoid false beeps, bigger this value is
smaller the probability of getting false detection --> smaller the probability of getting false detection -->
<param name="sample_n_continuous_streak" value="5"/> <param name="sample_n_continuous_streak" value="3"/>
<!-- define number of samples to skip starting from the beginning <!-- define number of samples to skip starting from the beginning
of the frame and/or after reset has happened. This serves the purpose of skipping first few of the frame and/or after reset has happened. This serves the purpose of skipping first few
@ -46,7 +46,7 @@
<param name="sample_n_to_skip" value="0"/> <param name="sample_n_to_skip" value="0"/>
<param name="require_continuous_streak_amp" value="1"/> <param name="require_continuous_streak_amp" value="1"/>
<param name="sample_n_continuous_streak_amp" value="5"/> <param name="sample_n_continuous_streak_amp" value="3"/>
<!-- define/undefine this to enable/disable simplified estimation <!-- define/undefine this to enable/disable simplified estimation
of frequency based on approximation of sin(x) with (x) of frequency based on approximation of sin(x) with (x)

View File

@ -324,7 +324,7 @@
<extension name="618"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) --> <extension name="618"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) -->
<condition field="destination_number" expression="^(618)$"> <condition field="destination_number" expression="^(618)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=1"/> <action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=1"/>
<action application="playback" data="tone_stream://L=1;%(1850,1000,1900,2000)" /> <action application="playback" data="tone_stream://L=1;%(1850,1000,1900,1950)" />
<action application="avmd_stop"/> <action application="avmd_stop"/>
<action application="hangup"/> <action application="hangup"/>
</condition> </condition>
@ -332,7 +332,7 @@
<extension name="619"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) --> <extension name="619"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) -->
<condition field="destination_number" expression="^(619)$"> <condition field="destination_number" expression="^(619)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=1"/> <action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=1"/>
<action application="playback" data="tone_stream://L=1;%(1850,1000,100,1000)" /> <action application="playback" data="tone_stream://L=1;%(1850,1000,200,500)" />
<action application="avmd_stop"/> <action application="avmd_stop"/>
<action application="hangup"/> <action application="hangup"/>
</condition> </condition>
@ -340,7 +340,7 @@
<extension name="620"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) --> <extension name="620"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) -->
<condition field="destination_number" expression="^(620)$"> <condition field="destination_number" expression="^(620)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=1"/> <action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=1"/>
<action application="playback" data="tone_stream://L=1;%(1850,1000,1000,2000)" /> <action application="playback" data="tone_stream://L=1;%(1850,1000,500,700)" />
<action application="avmd_stop"/> <action application="avmd_stop"/>
<action application="hangup"/> <action application="hangup"/>
</condition> </condition>
@ -493,7 +493,7 @@
<extension name="718"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) --> <extension name="718"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) -->
<condition field="destination_number" expression="^(718)$"> <condition field="destination_number" expression="^(718)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=2"/> <action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=2"/>
<action application="playback" data="tone_stream://L=1;%(1850,1000,1900,2000)" /> <action application="playback" data="tone_stream://L=1;%(1850,1000,1900,1950)" />
<action application="avmd_stop"/> <action application="avmd_stop"/>
<action application="hangup"/> <action application="hangup"/>
</condition> </condition>
@ -501,7 +501,7 @@
<extension name="719"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) --> <extension name="719"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) -->
<condition field="destination_number" expression="^(719)$"> <condition field="destination_number" expression="^(719)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=2"/> <action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=2"/>
<action application="playback" data="tone_stream://L=1;%(1850,1000,100,1000)" /> <action application="playback" data="tone_stream://L=1;%(1850,1000,200,500)" />
<action application="avmd_stop"/> <action application="avmd_stop"/>
<action application="hangup"/> <action application="hangup"/>
</condition> </condition>
@ -509,7 +509,7 @@
<extension name="720"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) --> <extension name="720"><!-- this BEEP must be DETECETD in detection_mode 1 (FREQ), NOTDETECTED in detection_mode 0 (AMP) and 2 (BOTH) -->
<condition field="destination_number" expression="^(720)$"> <condition field="destination_number" expression="^(720)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=2"/> <action application="avmd_start" data="inbound_channel=1,outbound_channel=0,debug=0,detection_mode=2"/>
<action application="playback" data="tone_stream://L=1;%(1850,1000,1000,2000)" /> <action application="playback" data="tone_stream://L=1;%(1850,1000,500,700)" />
<action application="avmd_stop"/> <action application="avmd_stop"/>
<action application="hangup"/> <action application="hangup"/>
</condition> </condition>
@ -780,3 +780,61 @@
<action application="hangup"/> <action application="hangup"/>
</condition> </condition>
</extension> </extension>
<extension name="840531400"><!-- obscure voicemail pack 2 -->
<condition field="destination_number" expression="^(840531400)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,detection_mode=2,debug=0"/>
<action application="playback" data="voicemail/8000/2764944714-18-15-bad.wav"/>
<action application="avmd_stop"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="840531401"><!-- obscure voicemail pack 2 -->
<condition field="destination_number" expression="^(840531401)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,detection_mode=2,debug=0"/>
<action application="playback" data="voicemail/8000/3054957758-18-15-bad.wav"/>
<action application="avmd_stop"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="840531402"><!-- obscure voicemail pack 2 -->
<condition field="destination_number" expression="^(840531402)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,detection_mode=2,debug=0"/>
<action application="playback" data="voicemail/8000/5044810548-18-15-bad.wav"/>
<action application="avmd_stop"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="840531403"><!-- obscure voicemail pack 2 -->
<condition field="destination_number" expression="^(840531403)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,detection_mode=2,debug=0"/>
<action application="playback" data="voicemail/8000/5852842171-18-15-bad.wav"/>
<action application="avmd_stop"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="840531404"><!-- obscure voicemail pack 2 -->
<condition field="destination_number" expression="^(840531404)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,detection_mode=2,debug=0"/>
<action application="playback" data="voicemail/8000/5857330628-18-15-bad.wav"/>
<action application="avmd_stop"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="840531405"><!-- obscure voicemail pack 2 -->
<condition field="destination_number" expression="^(840531405)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,detection_mode=2,debug=0"/>
<action application="playback" data="voicemail/8000/8702463704-18-15-bad.wav"/>
<action application="avmd_stop"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="840531051"><!-- fragment of "Save tonight" by Eagle-Eye Cherry covered by D-Lete-Funk-K -->
<condition field="destination_number" expression="^(840531051)$">
<action application="avmd_start" data="inbound_channel=1,outbound_channel=0,detection_mode=2,debug=0"/>
<action application="playback" data="voicemail/8000/save_tonight_8000.wav"/>
<action application="avmd_stop"/>
<action application="hangup"/>
</condition>
</extension>

View File

@ -62,7 +62,7 @@ int __isnan(double);
/*! Calculate how many audio samples per ms based on the rate */ /*! Calculate how many audio samples per ms based on the rate */
#define AVMD_SAMPLES_PER_MS(r, m) ((r) / (1000/(m))) #define AVMD_SAMPLES_PER_MS(r, m) ((r) / (1000/(m)))
/*! Minimum beep length */ /*! Minimum beep length */
#define AVMD_BEEP_TIME (4) #define AVMD_BEEP_TIME (2)
/*! How often to evaluate the output of DESA-2 in ms */ /*! How often to evaluate the output of DESA-2 in ms */
#define AVMD_SINE_TIME (1*0.125) #define AVMD_SINE_TIME (1*0.125)
/*! How long in samples does DESA-2 results get evaluated */ /*! How long in samples does DESA-2 results get evaluated */
@ -78,9 +78,9 @@ int __isnan(double);
/*! Conversion to Hertz */ /*! Conversion to Hertz */
#define AVMD_TO_HZ(r, f) (((r) * (f)) / (2.0 * M_PI)) #define AVMD_TO_HZ(r, f) (((r) * (f)) / (2.0 * M_PI))
/*! Minimum absolute pressure/amplitude */ /*! Minimum absolute pressure/amplitude */
#define AVMD_MIN_AMP (5.0) #define AVMD_MIN_AMP (17.0)
/*! Minimum beep frequency in Hertz */ /*! Minimum beep frequency in Hertz */
#define AVMD_MIN_FREQUENCY (400.0) #define AVMD_MIN_FREQUENCY (440.0)
/*! Minimum frequency as digital normalized frequency */ /*! Minimum frequency as digital normalized frequency */
#define AVMD_MIN_FREQUENCY_R(r) ((2.0 * M_PI * AVMD_MIN_FREQUENCY) / (r)) #define AVMD_MIN_FREQUENCY_R(r) ((2.0 * M_PI * AVMD_MIN_FREQUENCY) / (r))
/*! /*!
@ -101,8 +101,9 @@ int __isnan(double);
/*! Maximum frequency as digital normalized frequency */ /*! Maximum frequency as digital normalized frequency */
#define AVMD_MAX_FREQUENCY_R(r) ((2.0 * M_PI * AVMD_MAX_FREQUENCY) / (r)) #define AVMD_MAX_FREQUENCY_R(r) ((2.0 * M_PI * AVMD_MAX_FREQUENCY) / (r))
#define AVMD_VARIANCE_RSD_THRESHOLD (0.000025) #define AVMD_VARIANCE_RSD_THRESHOLD (0.000025)
#define AVMD_AMPLITUDE_RSD_THRESHOLD (0.015) #define AVMD_AMPLITUDE_RSD_THRESHOLD (0.0148)
#define AVMD_DETECTORS_N 45 #define AVMD_DETECTORS_N 45
#define AVMD_DETECTORS_LAGGED_N 3
/*! Syntax of the API call. */ /*! Syntax of the API call. */
@ -115,8 +116,7 @@ int __isnan(double);
#define AVMD_PARAMS_APP_START_MIN 0u #define AVMD_PARAMS_APP_START_MIN 0u
#define AVMD_PARAMS_APP_START_MAX 20u #define AVMD_PARAMS_APP_START_MAX 20u
/* don't forget to update avmd_events_str table /* don't forget to update avmd_events_str table if you modify this */
* if you modify this */
enum avmd_event enum avmd_event
{ {
AVMD_EVENT_BEEP = 0, AVMD_EVENT_BEEP = 0,
@ -215,6 +215,7 @@ struct avmd_detector {
avmd_session_t *s; avmd_session_t *s;
size_t samples; size_t samples;
uint8_t idx; uint8_t idx;
uint8_t lagged, lag;
}; };
/*! Type that holds session information pertinent to the avmd module. */ /*! Type that holds session information pertinent to the avmd module. */
@ -228,12 +229,12 @@ struct avmd_session {
double f; double f;
avmd_state_t state; avmd_state_t state;
switch_time_t start_time, stop_time, detection_start_time, detection_stop_time; switch_time_t start_time, stop_time, detection_start_time, detection_stop_time;
size_t sample_count; size_t frame_n;
uint8_t frame_n_to_skip; uint8_t frame_n_to_skip;
switch_mutex_t *mutex_detectors_done; switch_mutex_t *mutex_detectors_done;
switch_thread_cond_t *cond_detectors_done; switch_thread_cond_t *cond_detectors_done;
struct avmd_detector detectors[AVMD_DETECTORS_N]; struct avmd_detector detectors[AVMD_DETECTORS_N + AVMD_DETECTORS_LAGGED_N];
}; };
struct avmd_globals struct avmd_globals
@ -241,6 +242,7 @@ struct avmd_globals
switch_mutex_t *mutex; switch_mutex_t *mutex;
struct avmd_settings settings; struct avmd_settings settings;
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
size_t session_n;
} avmd_globals; } avmd_globals;
static void avmd_process(avmd_session_t *session, switch_frame_t *frame); static void avmd_process(avmd_session_t *session, switch_frame_t *frame);
@ -251,7 +253,7 @@ static switch_status_t avmd_register_all_events(void);
static void avmd_unregister_all_events(void); static void avmd_unregister_all_events(void);
static void avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq, double v_freq, double amp, double v_amp, avmd_beep_state_t beep_status, uint8_t info, static void avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq, double v_freq, double amp, double v_amp, avmd_beep_state_t beep_status, uint8_t info,
switch_time_t detection_start_time, switch_time_t detection_stop_time, switch_time_t start_time, switch_time_t stop_time); switch_time_t detection_start_time, switch_time_t detection_stop_time, switch_time_t start_time, switch_time_t stop_time, uint8_t resolution, uint8_t offset, uint8_t idx);
static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buffer_t *b, size_t sample_n, size_t pos, struct avmd_detector *d); static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buffer_t *b, size_t sample_n, size_t pos, struct avmd_detector *d);
@ -282,17 +284,36 @@ static uint8_t
avmd_detection_in_progress(avmd_session_t *s); avmd_detection_in_progress(avmd_session_t *s);
static switch_status_t avmd_launch_threads(avmd_session_t *s) { static switch_status_t avmd_launch_threads(avmd_session_t *s) {
uint8_t idx; uint8_t idx;
switch_threadattr_t *thd_attr = NULL; struct avmd_detector *d;
switch_threadattr_t *thd_attr = NULL;
idx = 0; idx = 0;
while (idx < AVMD_DETECTORS_N) { while (idx < AVMD_DETECTORS_N) {
s->detectors[idx].flag_processing_done = 1; d = &s->detectors[idx];
s->detectors[idx].flag_should_exit = 0; d->flag_processing_done = 1;
s->detectors[idx].result = AVMD_DETECT_NONE; d->flag_should_exit = 0;
d->result = AVMD_DETECT_NONE;
d->lagged = 0;
d->lag = 0;
switch_threadattr_create(&thd_attr, avmd_globals.pool); switch_threadattr_create(&thd_attr, avmd_globals.pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
if (switch_thread_create(&s->detectors[idx].thread, thd_attr, avmd_detector_func, (void *)&s->detectors[idx], switch_core_session_get_pool(s->session)) != SWITCH_STATUS_SUCCESS) { if (switch_thread_create(&d->thread, thd_attr, avmd_detector_func, (void *)d, switch_core_session_get_pool(s->session)) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
++idx;
}
idx = 0;
while (idx < AVMD_DETECTORS_LAGGED_N) {
d = &s->detectors[AVMD_DETECTORS_N + idx];
d->flag_processing_done = 1;
d->flag_should_exit = 0;
d->result = AVMD_DETECT_NONE;
d->lagged = 1;
d->lag = idx + 1;
switch_threadattr_create(&thd_attr, avmd_globals.pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
if (switch_thread_create(&d->thread, thd_attr, avmd_detector_func, (void *)d, switch_core_session_get_pool(s->session)) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
} }
++idx; ++idx;
@ -377,7 +398,7 @@ static switch_status_t init_avmd_session_data(avmd_session_t *avmd_session, swit
avmd_session->state.beep_state = BEEP_NOTDETECTED; avmd_session->state.beep_state = BEEP_NOTDETECTED;
memcpy(&avmd_session->settings, &avmd_globals.settings, sizeof(struct avmd_settings)); memcpy(&avmd_session->settings, &avmd_globals.settings, sizeof(struct avmd_settings));
switch_mutex_init(&avmd_session->mutex, SWITCH_MUTEX_DEFAULT, switch_core_session_get_pool(fs_session)); switch_mutex_init(&avmd_session->mutex, SWITCH_MUTEX_DEFAULT, switch_core_session_get_pool(fs_session));
avmd_session->sample_count = 0; avmd_session->frame_n = 0;
avmd_session->detection_start_time = 0; avmd_session->detection_start_time = 0;
avmd_session->detection_stop_time = 0; avmd_session->detection_stop_time = 0;
avmd_session->frame_n_to_skip = 0; avmd_session->frame_n_to_skip = 0;
@ -408,8 +429,26 @@ static switch_status_t init_avmd_session_data(avmd_session_t *avmd_session, swit
++idx; ++idx;
} }
} }
idx = 0;
resolution = 1;
offset = 0;
while (idx < AVMD_DETECTORS_LAGGED_N) {
d = &avmd_session->detectors[AVMD_DETECTORS_N + idx];
if (avmd_init_buffer(&d->buffer, buf_sz, resolution, offset, fs_session) != SWITCH_STATUS_SUCCESS) {
status = SWITCH_STATUS_FALSE;
goto end;
}
d->s = avmd_session;
d->flag_processing_done = 1;
d->flag_should_exit = 1;
d->idx = AVMD_DETECTORS_N + idx;
switch_mutex_init(&d->mutex, SWITCH_MUTEX_DEFAULT, switch_core_session_get_pool(fs_session));
switch_thread_cond_create(&d->cond_start_processing, switch_core_session_get_pool(fs_session));
++idx;
}
switch_mutex_init(&avmd_session->mutex_detectors_done, SWITCH_MUTEX_DEFAULT, switch_core_session_get_pool(fs_session)); switch_mutex_init(&avmd_session->mutex_detectors_done, SWITCH_MUTEX_DEFAULT, switch_core_session_get_pool(fs_session));
switch_thread_cond_create(&avmd_session->cond_detectors_done, switch_core_session_get_pool(fs_session)); switch_thread_cond_create(&avmd_session->cond_detectors_done, switch_core_session_get_pool(fs_session));
end: end:
if (mutex != NULL) if (mutex != NULL)
{ {
@ -431,7 +470,7 @@ static void avmd_session_close(avmd_session_t *s) {
switch_mutex_unlock(s->mutex_detectors_done); switch_mutex_unlock(s->mutex_detectors_done);
idx = 0; idx = 0;
while (idx < AVMD_DETECTORS_N) { while (idx < AVMD_DETECTORS_N + AVMD_DETECTORS_LAGGED_N) {
d = &s->detectors[idx]; d = &s->detectors[idx];
switch_mutex_lock(d->mutex); switch_mutex_lock(d->mutex);
d = &s->detectors[idx]; d = &s->detectors[idx];
@ -529,6 +568,11 @@ static switch_bool_t avmd_callback(switch_media_bug_t * bug, void *user_data, sw
case SWITCH_ABC_TYPE_CLOSE: case SWITCH_ABC_TYPE_CLOSE:
avmd_session_close(avmd_session); avmd_session_close(avmd_session);
switch_mutex_lock(avmd_globals.mutex);
if (avmd_globals.session_n > 0) {
--avmd_globals.session_n;
}
switch_mutex_unlock(avmd_globals.mutex);
break; break;
default: default:
@ -569,7 +613,7 @@ static void avmd_unregister_all_events(void) {
} }
static void avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq, double v_freq, double amp, double v_amp, avmd_beep_state_t beep_status, uint8_t info, static void avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq, double v_freq, double amp, double v_amp, avmd_beep_state_t beep_status, uint8_t info,
switch_time_t detection_start_time, switch_time_t detection_stop_time, switch_time_t start_time, switch_time_t stop_time) { switch_time_t detection_start_time, switch_time_t detection_stop_time, switch_time_t start_time, switch_time_t stop_time, uint8_t resolution, uint8_t offset, uint8_t idx) {
int res; int res;
switch_event_t *event; switch_event_t *event;
switch_time_t detection_time, total_time; switch_time_t detection_time, total_time;
@ -622,6 +666,27 @@ static void avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, d
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detection-time", "ERROR (TRUNCATED)"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detection-time", "ERROR (TRUNCATED)");
} }
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detection-time", buf); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detection-time", buf);
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%u", resolution);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Error, truncated [%s], [%d] attempeted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detector-resolution", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detector-resolution", buf);
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%u", offset);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Error, truncated [%s], [%d] attempeted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detector-offset", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detector-offset", buf);
res = snprintf(buf, AVMD_CHAR_BUF_LEN, "%u", idx);
if (res < 0 || res > AVMD_CHAR_BUF_LEN - 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_s), SWITCH_LOG_ERROR, "Error, truncated [%s], [%d] attempeted!\n", buf, res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detector-index", "ERROR (TRUNCATED)");
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detector-index", buf);
break; break;
case AVMD_EVENT_SESSION_START: case AVMD_EVENT_SESSION_START:
@ -1255,7 +1320,7 @@ SWITCH_STANDARD_APP(avmd_start_app) {
goto end; goto end;
} }
switch_channel_set_private(channel, "_avmd_", bug); /* Set the avmd tag to detect an existing avmd media bug */ switch_channel_set_private(channel, "_avmd_", bug); /* Set the avmd tag to detect an existing avmd media bug */
avmd_fire_event(AVMD_EVENT_SESSION_START, session, 0, 0, 0, 0, 0, 0, 0, 0, avmd_session->start_time, 0); avmd_fire_event(AVMD_EVENT_SESSION_START, session, 0, 0, 0, 0, 0, 0, 0, 0, avmd_session->start_time, 0, 0, 0, 0);
if (avmd_session->settings.report_status == 1) { if (avmd_session->settings.report_status == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Avmd on channel [%s] started!\n", switch_channel_get_name(channel)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Avmd on channel [%s] started!\n", switch_channel_get_name(channel));
} }
@ -1265,6 +1330,10 @@ SWITCH_STANDARD_APP(avmd_start_app) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to start detection threads!\n"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to start detection threads!\n");
goto end; goto end;
} }
switch_mutex_lock(avmd_globals.mutex);
++avmd_globals.session_n;
switch_mutex_unlock(avmd_globals.mutex);
end: end:
switch_mutex_unlock(avmd_session->mutex); switch_mutex_unlock(avmd_session->mutex);
@ -1310,13 +1379,14 @@ SWITCH_STANDARD_APP(avmd_stop_app) {
stop_time = avmd_session->stop_time; stop_time = avmd_session->stop_time;
total_time = stop_time - start_time; total_time = stop_time - start_time;
switch_mutex_unlock(avmd_session->mutex); switch_mutex_unlock(avmd_session->mutex);
avmd_fire_event(AVMD_EVENT_SESSION_STOP, session, 0, 0, 0, 0, beep_status, 1, 0, 0, start_time, stop_time); avmd_fire_event(AVMD_EVENT_SESSION_STOP, session, 0, 0, 0, 0, beep_status, 1, 0, 0, start_time, stop_time, 0, 0, 0);
if (report_status == 1) { if (report_status == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Avmd on channel [%s] stopped, beep status: [%s], total running time [%" PRId64 "] [us]\n", switch_channel_get_name(channel), beep_status == BEEP_DETECTED ? "DETECTED" : "NOTDETECTED", total_time); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Avmd on channel [%s] stopped, beep status: [%s], total running time [%" PRId64 "] [us]\n", switch_channel_get_name(channel), beep_status == BEEP_DETECTED ? "DETECTED" : "NOTDETECTED", total_time);
} }
} }
switch_channel_set_private(channel, "_avmd_", NULL); switch_channel_set_private(channel, "_avmd_", NULL);
switch_core_media_bug_remove(session, &bug); switch_core_media_bug_remove(session, &bug);
return; return;
} }
@ -1349,12 +1419,19 @@ SWITCH_STANDARD_APP(avmd_start_function) {
} }
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_avmd_shutdown) { SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_avmd_shutdown) {
size_t session_n;
#ifndef WIN32 #ifndef WIN32
int res; int res;
#endif #endif
switch_mutex_lock(avmd_globals.mutex); switch_mutex_lock(avmd_globals.mutex);
session_n = avmd_globals.session_n;
if (session_n > 0) {
switch_mutex_unlock(avmd_globals.mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "PLEASE DO NOT RELOAD MODULE WHILE SESSIONS ARE RUNNING\n");
}
avmd_unregister_all_events(); avmd_unregister_all_events();
#ifndef WIN32 #ifndef WIN32
@ -1382,9 +1459,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_avmd_shutdown) {
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
/*! \brief FreeSWITCH API handler function. /*! \brief FreeSWITCH API handler function. */
* This function handles API calls from mod_event_socket and LUA scripts.
*/
SWITCH_STANDARD_API(avmd_api_main) { SWITCH_STANDARD_API(avmd_api_main) {
switch_media_bug_t *bug; switch_media_bug_t *bug;
avmd_session_t *avmd_session; avmd_session_t *avmd_session;
@ -1527,7 +1602,7 @@ SWITCH_STANDARD_API(avmd_api_main) {
uuid_dup = switch_core_strdup(switch_core_session_get_pool(fs_session), uuid); uuid_dup = switch_core_strdup(switch_core_session_get_pool(fs_session), uuid);
switch_channel_set_private(channel, "_avmd_", NULL); switch_channel_set_private(channel, "_avmd_", NULL);
switch_core_media_bug_remove(fs_session, &bug); switch_core_media_bug_remove(fs_session, &bug);
avmd_fire_event(AVMD_EVENT_SESSION_STOP, fs_session, 0, 0, 0, 0, 0, 0, 0, 0, avmd_session->start_time, avmd_session->stop_time); avmd_fire_event(AVMD_EVENT_SESSION_STOP, fs_session, 0, 0, 0, 0, 0, 0, 0, 0, avmd_session->start_time, avmd_session->stop_time, 0, 0, 0);
if (avmd_globals.settings.report_status == 1) { if (avmd_globals.settings.report_status == 1) {
stream->write_function(stream, "+OK\n [%s] [%s] stopped\n\n", uuid_dup, switch_channel_get_name(channel)); stream->write_function(stream, "+OK\n [%s] [%s] stopped\n\n", uuid_dup, switch_channel_get_name(channel));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session), SWITCH_LOG_INFO, "Avmd on channel [%s] stopped!\n", switch_channel_get_name(channel)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session), SWITCH_LOG_INFO, "Avmd on channel [%s] stopped!\n", switch_channel_get_name(channel));
@ -1617,7 +1692,7 @@ SWITCH_STANDARD_API(avmd_api_main) {
switch_channel_set_private(channel, "_avmd_", bug); /* Set the vmd tag to detect an existing vmd media bug */ switch_channel_set_private(channel, "_avmd_", bug); /* Set the vmd tag to detect an existing vmd media bug */
avmd_fire_event(AVMD_EVENT_SESSION_START, fs_session, 0, 0, 0, 0, 0, 0, 0, 0, avmd_session->start_time, 0); avmd_fire_event(AVMD_EVENT_SESSION_START, fs_session, 0, 0, 0, 0, 0, 0, 0, 0, avmd_session->start_time, 0, 0, 0, 0);
if (avmd_globals.settings.report_status == 1) { if (avmd_globals.settings.report_status == 1) {
stream->write_function(stream, "+OK\n [%s] [%s] started!\n\n", uuid, switch_channel_get_name(channel)); stream->write_function(stream, "+OK\n [%s] [%s] started!\n\n", uuid, switch_channel_get_name(channel));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session), SWITCH_LOG_INFO, "Avmd on channel [%s] started!\n", switch_channel_get_name(channel)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session), SWITCH_LOG_INFO, "Avmd on channel [%s] started!\n", switch_channel_get_name(channel));
@ -1638,11 +1713,17 @@ end:
static int static int
avmd_decision_amplitude(const avmd_session_t *s, const struct avmd_buffer *b, double v, double rsd_threshold) { avmd_decision_amplitude(const avmd_session_t *s, const struct avmd_buffer *b, double v, double rsd_threshold) {
double rsd; double a, rsd;
size_t lpos;
if ((s->settings.require_continuous_streak_amp == 1 && (b->sma_amp_b.lpos > s->settings.sample_n_continuous_streak_amp) && (b->samples_streak_amp == 0)) lpos = b->sma_b.lpos;
|| (s->settings.require_continuous_streak_amp == 0 && (b->sma_amp_b.lpos > 1))) { if ((lpos >= AVMD_BEEP_LEN(s->rate) / b->resolution) && ((s->settings.require_continuous_streak_amp == 1 && (b->sma_amp_b.lpos > s->settings.sample_n_continuous_streak_amp) && (b->samples_streak_amp == 0))
rsd = sqrt(v) / fabs(b->sma_amp_b.sma); || (s->settings.require_continuous_streak_amp == 0 && (b->sma_amp_b.lpos > 1)))) {
a = fabs(b->sma_amp_b.sma);
if (a < AVMD_MIN_AMP) {
return 0;
}
rsd = sqrt(v) / a;
if (rsd < rsd_threshold) { if (rsd < rsd_threshold) {
return 1; return 1;
} }
@ -1668,19 +1749,20 @@ avmd_decision_freq(const avmd_session_t *s, const struct avmd_buffer *b, double
if ((rsd < 0.6 * rsd_threshold) && (b->sma_amp_b.sma >= 0.01 * b->amplitude_max)) { if ((rsd < 0.6 * rsd_threshold) && (b->sma_amp_b.sma >= 0.01 * b->amplitude_max)) {
return 1; return 1;
} }
if ((rsd < rsd_threshold) && (b->sma_amp_b.sma >= 0.02 * b->amplitude_max)) { if ((rsd < rsd_threshold) && (b->sma_amp_b.sma >= 0.015 * b->amplitude_max)) {
return 1; return 1;
} }
} }
return 0; return 0;
} }
static void avmd_report_detection(avmd_session_t *s, enum avmd_detection_mode mode, const struct avmd_buffer *b) { static void avmd_report_detection(avmd_session_t *s, enum avmd_detection_mode mode, const struct avmd_detector *d) {
switch_channel_t *channel; switch_channel_t *channel;
switch_time_t detection_time; switch_time_t detection_time;
double f_sma = 0.0; double f_sma = 0.0;
double v_amp = 9999.9, v_fir = 9999.9; double v_amp = 9999.9, v_fir = 9999.9;
const struct avmd_buffer *b = &d->buffer;
const sma_buffer_t *sma_b_fir = &b->sma_b_fir; const sma_buffer_t *sma_b_fir = &b->sma_b_fir;
const sma_buffer_t *sqa_b_fir = &b->sqa_b_fir; const sma_buffer_t *sqa_b_fir = &b->sqa_b_fir;
@ -1698,20 +1780,20 @@ static void avmd_report_detection(avmd_session_t *s, enum avmd_detection_mode mo
case AVMD_DETECT_AMP: case AVMD_DETECT_AMP:
v_amp = sqa_amp_b->sma - (sma_amp_b->sma * sma_amp_b->sma); /* calculate variance of amplitude (biased estimator) */ v_amp = sqa_amp_b->sma - (sma_amp_b->sma * sma_amp_b->sma); /* calculate variance of amplitude (biased estimator) */
avmd_fire_event(AVMD_EVENT_BEEP, s->session, 0, 0, sma_amp_b->sma, v_amp, 0, 0, s->detection_start_time, s->detection_stop_time, 0, 0); avmd_fire_event(AVMD_EVENT_BEEP, s->session, 0, 0, sma_amp_b->sma, v_amp, 0, 0, s->detection_start_time, s->detection_stop_time, 0, 0, b->resolution, b->offset, d->idx);
if (s->settings.report_status == 1) { if (s->settings.report_status == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_INFO, "<<< AVMD - Beep Detected [%u][%u][%u]: amplitude = [%f] variance = [%f], detection time [%" PRId64 "] [us] >>>\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_INFO, "<<< AVMD - Beep Detected [%u][%u][%u][%u]: amplitude = [%f](max [%f]) variance = [%f], detection time [%" PRId64 "] [us] >>>\n",
mode, b->resolution, b->offset, sma_amp_b->sma, v_amp, detection_time); mode, b->resolution, b->offset, d->idx, sma_amp_b->sma, b->amplitude_max, v_amp, detection_time);
} }
break; break;
case AVMD_DETECT_FREQ: case AVMD_DETECT_FREQ:
f_sma = sma_b_fir->sma; f_sma = sma_b_fir->sma;
v_fir = sqa_b_fir->sma - (sma_b_fir->sma * sma_b_fir->sma); /* calculate variance of filtered samples */ v_fir = sqa_b_fir->sma - (sma_b_fir->sma * sma_b_fir->sma); /* calculate variance of filtered samples */
avmd_fire_event(AVMD_EVENT_BEEP, s->session, AVMD_TO_HZ(s->rate, f_sma), v_fir, 0, 0, 0, 0, s->detection_start_time, s->detection_stop_time, 0, 0); avmd_fire_event(AVMD_EVENT_BEEP, s->session, AVMD_TO_HZ(s->rate, f_sma), v_fir, 0, 0, 0, 0, s->detection_start_time, s->detection_stop_time, 0, 0, b->resolution, b->offset, d->idx);
if (s->settings.report_status == 1) { if (s->settings.report_status == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_INFO, "<<< AVMD - Beep Detected [%u][%u][%u]: f = [%f] variance = [%f], detection time [%" PRId64 "] [us] >>>\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_INFO, "<<< AVMD - Beep Detected [%u][%u][%u][%u]: f = [%f] variance = [%f], detection time [%" PRId64 "] [us] >>>\n",
mode, b->resolution, b->offset, AVMD_TO_HZ(s->rate, f_sma), v_fir, detection_time); mode, b->resolution, b->offset, d->idx, AVMD_TO_HZ(s->rate, f_sma), v_fir, detection_time);
} }
break; break;
@ -1719,10 +1801,10 @@ static void avmd_report_detection(avmd_session_t *s, enum avmd_detection_mode mo
v_amp = sqa_amp_b->sma - (sma_amp_b->sma * sma_amp_b->sma); /* calculate variance of amplitude (biased estimator) */ v_amp = sqa_amp_b->sma - (sma_amp_b->sma * sma_amp_b->sma); /* calculate variance of amplitude (biased estimator) */
f_sma = sma_b_fir->sma; f_sma = sma_b_fir->sma;
v_fir = sqa_b_fir->sma - (sma_b_fir->sma * sma_b_fir->sma); /* calculate variance of filtered samples */ v_fir = sqa_b_fir->sma - (sma_b_fir->sma * sma_b_fir->sma); /* calculate variance of filtered samples */
avmd_fire_event(AVMD_EVENT_BEEP, s->session, AVMD_TO_HZ(s->rate, f_sma), v_fir, sma_amp_b->sma, v_amp, 0, 0, s->detection_start_time, s->detection_stop_time, 0, 0); avmd_fire_event(AVMD_EVENT_BEEP, s->session, AVMD_TO_HZ(s->rate, f_sma), v_fir, sma_amp_b->sma, v_amp, 0, 0, s->detection_start_time, s->detection_stop_time, 0, 0, b->resolution, b->offset, d->idx);
if (s->settings.report_status == 1) { if (s->settings.report_status == 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_INFO, "<<< AVMD - Beep Detected [%u][%u][%u]: f = [%f] variance = [%f], amplitude = [%f] variance = [%f], detection time [%" PRId64 "] [us] >>>\n", switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(s->session), SWITCH_LOG_INFO, "<<< AVMD - Beep Detected [%u][%u][%u][%u]: f = [%f] variance = [%f], amplitude = [%f](max [%f]) variance = [%f], detection time [%" PRId64 "] [us] >>>\n",
mode, b->resolution, b->offset, AVMD_TO_HZ(s->rate, f_sma), v_fir, sma_amp_b->sma, v_amp, detection_time); mode, b->resolution, b->offset, d->idx, AVMD_TO_HZ(s->rate, f_sma), v_fir, sma_amp_b->sma, b->amplitude_max, v_amp, detection_time);
} }
break; break;
@ -1735,7 +1817,7 @@ static void avmd_report_detection(avmd_session_t *s, enum avmd_detection_mode mo
static uint8_t static uint8_t
avmd_detection_in_progress(avmd_session_t *s) { avmd_detection_in_progress(avmd_session_t *s) {
uint8_t idx = 0; uint8_t idx = 0;
while (idx < AVMD_DETECTORS_N) { while (idx < AVMD_DETECTORS_N +AVMD_DETECTORS_LAGGED_N) {
switch_mutex_lock(s->detectors[idx].mutex); switch_mutex_lock(s->detectors[idx].mutex);
if (s->detectors[idx].flag_processing_done == 0) { if (s->detectors[idx].flag_processing_done == 0) {
switch_mutex_unlock(s->detectors[idx].mutex); switch_mutex_unlock(s->detectors[idx].mutex);
@ -1751,10 +1833,10 @@ static enum avmd_detection_mode
avmd_detection_result(avmd_session_t *s) { avmd_detection_result(avmd_session_t *s) {
enum avmd_detection_mode res; enum avmd_detection_mode res;
uint8_t idx = 0; uint8_t idx = 0;
while (idx < AVMD_DETECTORS_N) { while (idx < AVMD_DETECTORS_N + AVMD_DETECTORS_LAGGED_N) {
res = s->detectors[idx].result; res = s->detectors[idx].result;
if (res != AVMD_DETECT_NONE) { if (res != AVMD_DETECT_NONE) {
avmd_report_detection(s, res, &s->detectors[idx].buffer); avmd_report_detection(s, res, &s->detectors[idx]);
return res; return res;
} }
++idx; ++idx;
@ -1792,17 +1874,16 @@ static void avmd_process(avmd_session_t *s, switch_frame_t *frame) {
} }
INSERT_INT16_FRAME(b, (int16_t *)(frame->data), frame->samples); /* Insert frame of 16 bit samples into buffer */ INSERT_INT16_FRAME(b, (int16_t *)(frame->data), frame->samples); /* Insert frame of 16 bit samples into buffer */
s->sample_count += frame->samples;
idx = 0; idx = 0;
while (idx < AVMD_DETECTORS_N) { while (idx < AVMD_DETECTORS_N + AVMD_DETECTORS_LAGGED_N) {
d = &s->detectors[idx]; d = &s->detectors[idx];
switch_mutex_lock(d->mutex); switch_mutex_lock(d->mutex);
d = &s->detectors[idx]; d = &s->detectors[idx];
if (d->result == AVMD_DETECT_NONE) { if (d->result == AVMD_DETECT_NONE) {
d->flag_processing_done = 0; d->flag_processing_done = 0;
d->flag_should_exit = 0; d->flag_should_exit = 0;
d->samples = frame->samples; d->samples = (s->frame_n == 0 ? frame->samples - AVMD_P : frame->samples);
switch_thread_cond_signal(d->cond_start_processing); switch_thread_cond_signal(d->cond_start_processing);
} }
switch_mutex_unlock(d->mutex); switch_mutex_unlock(d->mutex);
@ -1816,7 +1897,12 @@ static void avmd_process(avmd_session_t *s, switch_frame_t *frame) {
avmd_detection_result(s); avmd_detection_result(s);
switch_mutex_unlock(s->mutex_detectors_done); switch_mutex_unlock(s->mutex_detectors_done);
s->pos += frame->samples - AVMD_P; ++s->frame_n;
if (s->frame_n == 1) {
s->pos += frame->samples - AVMD_P;
} else {
s->pos += frame->samples;
}
s->pos &= b->mask; s->pos &= b->mask;
return; return;
@ -1854,7 +1940,7 @@ static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buff
omega = avmd_desa2_tweaked(b, pos + sample_n, &amplitude); omega = avmd_desa2_tweaked(b, pos + sample_n, &amplitude);
if (mode == AVMD_DETECT_AMP || mode == AVMD_DETECT_BOTH) { if (mode == AVMD_DETECT_AMP || mode == AVMD_DETECT_BOTH) {
if (ISNAN(amplitude)) { if (ISNAN(amplitude) || ISINF(amplitude)) {
valid_amplitude = 0; valid_amplitude = 0;
if (s->settings.require_continuous_streak_amp == 1) { if (s->settings.require_continuous_streak_amp == 1) {
RESET_SMA_BUFFER(sma_amp_b); RESET_SMA_BUFFER(sma_amp_b);
@ -1940,7 +2026,7 @@ static enum avmd_detection_mode avmd_process_sample(avmd_session_t *s, circ_buff
return AVMD_DETECT_FREQ; return AVMD_DETECT_FREQ;
} }
if (mode == AVMD_DETECT_BOTH) { if (mode == AVMD_DETECT_BOTH) {
if ((sma_amp_b->sma > AVMD_MIN_AMP) && (avmd_decision_amplitude(s, buffer, v_amp, AVMD_AMPLITUDE_RSD_THRESHOLD) == 1) && (avmd_decision_freq(s, buffer, v_fir, AVMD_VARIANCE_RSD_THRESHOLD) == 1) && (valid_omega == 1)) { if ((avmd_decision_amplitude(s, buffer, v_amp, AVMD_AMPLITUDE_RSD_THRESHOLD) == 1) && (avmd_decision_freq(s, buffer, v_fir, AVMD_VARIANCE_RSD_THRESHOLD) == 1) && (valid_omega == 1)) {
return AVMD_DETECT_BOTH; return AVMD_DETECT_BOTH;
} }
} }
@ -1974,10 +2060,18 @@ avmd_detector_func(switch_thread_t *thread, void *arg) {
resolution = d->buffer.resolution; resolution = d->buffer.resolution;
offset = d->buffer.offset; offset = d->buffer.offset;
samples = d->samples; samples = d->samples;
switch_mutex_unlock(d->mutex);
sample_n = 0; if (d->lagged == 1) {
while (sample_n < (samples - AVMD_P)) { if (d->lag > 0) {
--d->lag;
goto done;
}
pos += AVMD_P;
}
switch_mutex_unlock(d->mutex);
sample_n = 1;
while (sample_n <= samples) {
if (((sample_n + offset) % resolution) == 0) { if (((sample_n + offset) % resolution) == 0) {
res = avmd_process_sample(d->s, &s->b, sample_n, pos, d); res = avmd_process_sample(d->s, &s->b, sample_n, pos, d);
if (res != AVMD_DETECT_NONE) { if (res != AVMD_DETECT_NONE) {
@ -1987,6 +2081,7 @@ avmd_detector_func(switch_thread_t *thread, void *arg) {
++sample_n; ++sample_n;
} }
switch_mutex_lock(d->mutex); switch_mutex_lock(d->mutex);
done:
d->flag_processing_done = 1; d->flag_processing_done = 1;
d->result = res; d->result = res;
switch_mutex_unlock(d->mutex); switch_mutex_unlock(d->mutex);

View File

@ -1,8 +1,7 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
#brief Call single voicemail available in default dialplan #brief Call single voicemail and print detection result to the console.
# and print detection result to the console.
#author Piotr Gregor <piotrgregor@rsyncme.org> #author Piotr Gregor <piotrgregor@rsyncme.org>
#date 15 Sept 2016 02:44 PM #date 15 Sept 2016 02:44 PM
@ -74,7 +73,7 @@ sub test_once {
my $uuid = $con->api('create_uuid')->getBody(); my $uuid = $con->api('create_uuid')->getBody();
my ($time_epoch, $time_hires) = Time::HiRes::gettimeofday(); my ($time_epoch, $time_hires) = Time::HiRes::gettimeofday();
printf("Calling with uuid [%s] [%s]...\n", $uuid, POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime($time_epoch)), $time_hires); printf("Calling with uuid [%s] [%s]...\n", $uuid, POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime($time_epoch)));
$con->bgapi(sprintf($originate_string, $uuid)); $con->bgapi(sprintf($originate_string, $uuid));

View File

@ -0,0 +1,87 @@
#!/usr/bin/perl -w
#brief Call (possibly) multiple voicemails
# and print detection result to the console.
#author Piotr Gregor <piotrgregor@rsyncme.org>
#date 15 Sept 2016 02:44 PM
use strict;
use warnings;
require ESL;
use POSIX;
use Time::HiRes;
my $host = "127.0.0.1";
my $port = "8021";
my $pass = "ClueCon";
my $extension_base = "sofia/internal/1000\@192.168.1.60";
my $playback = 'local_stream://moh';
my $context = 'default';
#Example:
#my $endpoint = "originate {originator_codec=PCMA,origination_uuid=%s}sofia/gateway/box_b/840534002 \&park()";
my $endpoint = "originate {originator_codec=PCMA,origination_uuid=%s}sofia/gateway/%s/%s \&park()";
my $gateway;
my $dest;
my $callerid;
my $thread_n;
my $idx = 0;
if ($#ARGV + 1 eq 4) {
$gateway = $ARGV[0];
$dest = $ARGV[1];
$callerid = $ARGV[2];
$thread_n = $ARGV[3];
print "Dialing [" .$thread_n ."] calls simultaneously to [" .$gateway ."][" .$dest ."] as [" .$callerid ."]\n";
} else {
die "Please specify gateway, destination number, caller id and number of calls to make\n";
}
my $con = new ESL::ESLconnection($host, $port, $pass);
if (!$con) {
die "Unable to establish connection to $host:$port\n";
}
if ($con->connected()) {
print "OK, Connected.\n";
} else {
die "Connection failure.\n";
}
while($con->connected() && ($idx < $thread_n)) {
call_once($dest, $callerid, $idx);
$idx++;
Time::HiRes::sleep(0.15); # avoid switch_core_session.c:2265 Throttle Error! 33, switch_time.c:1227 Over Session Rate of 30!
}
print "Disconnected.\n\n";
sub call_once {
my ($dest, $callerid, $idx) = @_;
my $uuid =
my $originate_string =
'originate ' .
'{ignore_early_media=true,' .
'originator_codec=PCMA,' .
'origination_uuid=%s,' .
'originate_timeout=60,' .
'origination_caller_id_number=' . $callerid . ',' .
'origination_caller_id_name=' . $callerid . '}';
if(defined($endpoint)) {
$originate_string = '';
$originate_string .= $endpoint;
} else {
$originate_string .= 'loopback/' . $dest . '/' . $context;
$originate_string .= ' ' . '&playback(' . $playback . ')';
}
my $uuid = $con->api('create_uuid')->getBody();
my ($time_epoch, $time_hires) = Time::HiRes::gettimeofday();
printf("[%s]\tCalling with uuid [%s] [%s]... [%s]\n", $idx + 1, $uuid, POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime($time_epoch)), $originate_string);
$con->bgapi(sprintf($originate_string, $uuid, $gateway, $dest));
$con->api('uuid_setvar ' . $uuid .' execute_on_answer avmd_start');
}

View File

@ -1,13 +1,13 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
#brief Test module avmd by calling all voicemails available #brief Test module avmd by calling voicemails from avmd test suite
# in avmd test suite and print detection results to the console. # and print detection results to the console.
#author Piotr Gregor <piotrgregor@rsyncme.org> #author Piotr Gregor <piotrgregor@rsyncme.org>
#details If you are testing serving voicemails from dialplan then avmd #details If you are testing serving voicemails from dialplan then avmd
# must be set to inbound mode, either globally (by avmd set inbound # must be set to inbound mode, either globally (by avmd set inbound
# in fs_cli) or in dialplan settings (<action application="avmd_start" # in fs_cli) or in dialplan settings (<action application="avmd_start"
# data="inbound_channel=1,outbound_channel=0"). # data="inbound_channel=1,outbound_channel=0") or dynamically per call.
#date 15 Sept 2016 03:00 PM #date 15 Sept 2016 03:00 PM
@ -114,6 +114,13 @@ my %numbers = (
840531212 => "DETECTED", 840531212 => "DETECTED",
840531213 => "DETECTED", 840531213 => "DETECTED",
840531214 => "DETECTED", 840531214 => "DETECTED",
840531400 => "DETECTED", # obscure voicemails ATT pack
840531401 => "DETECTED",
840531402 => "DETECTED",
840531403 => "DETECTED",
840531404 => "DETECTED",
840531405 => "DETECTED",
840531051 => "NOTDETECTED", # fragment of "Save tonight" by Eagle-Eye Cherry covered by D-Lete-Funk-K
); );
my $host = "127.0.0.1"; my $host = "127.0.0.1";
@ -122,7 +129,7 @@ my $pass = "ClueCon";
my $extension_base = "sofia/internal/1000\@192.168.1.60"; my $extension_base = "sofia/internal/1000\@192.168.1.60";
my $playback = 'local_stream://moh'; my $playback = 'local_stream://moh';
my $context = 'default'; my $context = 'default';
my $endpoint; my $endpoint;
my $dest; my $dest;
my $expectation; my $expectation;
@ -162,7 +169,7 @@ $con->events("plain", "CHANNEL_HANGUP");
print "OK.\n\n"; print "OK.\n\n";
printf("\nRunning [" .keys(%numbers) ."] tests.\n\n"); printf("\nRunning [" .keys(%numbers) ."] tests.\n\n");
printf("outbound uuid | destination number | timestamp | expectation | test result\n\n"); printf("outbound uuid | destination number | timestamp | expectation | test result | freq | f-variance | amplitude | a-variance\n\n");
foreach $dest (sort keys %numbers) { foreach $dest (sort keys %numbers) {
if (!$con->connected()) { if (!$con->connected()) {
last; last;
@ -182,7 +189,7 @@ sub test_once {
my $originate_string = my $originate_string =
'originate ' . 'originate ' .
'{ignore_early_media=true,' . '{ignore_early_media=true,' .
'origination_uuid=%s,' . 'origination_uuid=%s,' .
'originate_timeout=60,' . 'originate_timeout=60,' .
'origination_caller_id_number=' . $callerid . ',' . 'origination_caller_id_number=' . $callerid . ',' .
'origination_caller_id_name=' . $callerid . '}'; 'origination_caller_id_name=' . $callerid . '}';
@ -192,6 +199,11 @@ sub test_once {
my $uuid_in = ""; my $uuid_in = "";
my $freq = "N/A"; my $freq = "N/A";
my $freq_var = "N/A"; my $freq_var = "N/A";
my $amp = "N/A";
my $amp_var = "N/A";
my $resolution = "N/A";
my $offset = "N/A";
my $idx = "N/A";
if(defined($endpoint)) { if(defined($endpoint)) {
$originate_string .= $endpoint; $originate_string .= $endpoint;
@ -220,6 +232,11 @@ sub test_once {
if ($avmd_event_type eq 'avmd::beep') { if ($avmd_event_type eq 'avmd::beep') {
$freq = $e->getHeader("Frequency"); $freq = $e->getHeader("Frequency");
$freq_var = $e->getHeader("Frequency-variance"); $freq_var = $e->getHeader("Frequency-variance");
$amp = $e->getHeader("Amplitude");
$amp_var = $e->getHeader("Amplitude-variance");
$resolution = $e->getHeader("Detector-resolution");
$offset = $e->getHeader("Detector-offset");
$idx = $e->getHeader("Detector-index");
} }
$outcome = $e->getHeader("Beep-Status"); $outcome = $e->getHeader("Beep-Status");
if ($outcome eq $expectation) { if ($outcome eq $expectation) {
@ -243,6 +260,6 @@ sub test_once {
} }
} }
} }
printf("\t[%s]\t[%s]\t\t[%s]\t[%s]HZ\t[%s]\n", POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime($time_epoch)), $expectation, $result, $freq, $freq_var); printf("\t[%s]\t[%s]\t\t[%s]\t[%s]HZ\t[%s]\t[%s]\t[%s]\t[%s][%s][%s]\n", POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime($time_epoch)), $expectation, $result, $freq, $freq_var, $amp, $amp_var, $resolution, $offset, $idx);
Time::HiRes::sleep(0.5); # avoid switch_core_session.c:2265 Throttle Error! 33, switch_time.c:1227 Over Session Rate of 30! Time::HiRes::sleep(0.5); # avoid switch_core_session.c:2265 Throttle Error! 33, switch_time.c:1227 Over Session Rate of 30!
} }