void desa2_freeswitch_int(int16_t *input, double *mean1, double *mean2, double *var1, double *var2) { int i; circ_buffer_t b; sma_buffer_t sma_b; sma_buffer_t sqa_b; double freq[BLOCK]; // frequency estimates INIT_CIRC_BUFFER(&b, BLOCK); INIT_SMA_BUFFER(&sma_b, 10); INIT_SMA_BUFFER(&sqa_b, 10); INSERT_INT16_FRAME(&b, input, BLOCK); // calculate the frequency estimate for each sample as in FS for (i = 0; i < (BLOCK - P); i++) { freq[i] = desa2_fs(&b, i); APPEND_SMA_VAL(&sma_b, freq[i]); APPEND_SMA_VAL(&sqa_b, freq[i] * freq[i]); *var1 = sqa_b.sma - (sma_b.sma * sma_b.sma); printf("<<< AVMD v[%f] f[%f][%f]Hz sma[%f][%f]Hz sqa[%f]\tsample[%d]\t[%d] >>>\n", *var1, freq[i], TO_HZ(8000, freq[i]), sma_b.sma, TO_HZ(8000, sma_b.sma), sqa_b.sma, i, input[i]); } /* set mean */ *mean1 = sma_b.sma; /* calculate the variance */ *var1 = sqa_b.sma - (sma_b.sma * sma_b.sma); /* for comparison calculate mean2 frequency & var2 */ double mean = 0.0; for (i = 0; i < (BLOCK - P); i++) { mean += freq[i]; } mean /= (double) (BLOCK - P); *mean2 = mean; *var2 = 0.0; for (i = 0; i < (BLOCK - P); i++ ) { *var2 += freq[i] * freq[i]; } *var2 /= (double)(BLOCK - P); *var2 -= (mean * mean); free(b.buf); return; }
/*! \brief Process one frame of data with avmd algorithm * @author Eric des Courtis * @param session An avmd session * @param frame A audio frame */ static void avmd_process(avmd_session_t *session, switch_frame_t *frame) { switch_event_t *event; switch_status_t status; switch_event_t *event_copy; switch_channel_t *channel; circ_buffer_t *b; size_t pos; double f; double a; double error = 0.0; double success = 0.0; double amp = 0.0; double s_rate; double e_rate; double avg_a; double sine_len; uint32_t sine_len_i; int valid; b = &session->b; /*! 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 */ sine_len_i = SINE_LEN(session->rate); sine_len = (double)sine_len_i; channel = switch_core_session_get_channel(session->session); /*! Insert frame of 16 bit samples into buffer */ INSERT_INT16_FRAME(b, (int16_t *)(frame->data), frame->samples); /*! INNER LOOP -- OPTIMIZATION TARGET */ for(pos = GET_BACKLOG_POS(b); pos != (GET_CURRENT_POS(b) - P); pos++){ /*! Get a desa2 frequency estimate in Hertz */ f = TO_HZ(session->rate, desa2(b, pos)); /*! Don't caculate amplitude if frequency is not within range */ if(f < MIN_FREQUENCY || f > MAX_FREQUENCY) { a = 0.0; error += 1.0; } else { a = amplitude(b, pos, f); success += 1.0; if(!ISNAN(a)){ amp += a; } } /*! Every once in a while we evaluate the desa2 and amplitude results */ if(((pos + 1) % sine_len_i) == 0){ s_rate = success / (error + success); e_rate = error / (error + success); avg_a = amp / sine_len; /*! Results out of these ranges are considered invalid */ valid = 0; if( s_rate > 0.60 && avg_a > 0.50) valid = 1; else if(s_rate > 0.65 && avg_a > 0.45) valid = 1; else if(s_rate > 0.70 && avg_a > 0.40) valid = 1; else if(s_rate > 0.80 && avg_a > 0.30) valid = 1; else if(s_rate > 0.95 && avg_a > 0.05) valid = 1; else if(s_rate >= 0.99 && avg_a > 0.04) valid = 1; else if(s_rate == 1.00 && avg_a > 0.02) valid = 1; if(valid) { APPEND_SMA_VAL(&session->sma_b, s_rate * avg_a); } else { APPEND_SMA_VAL(&session->sma_b, 0.0 ); } /*! If sma is higher then 0 we have some kind of detection (increase this value to eliminate false positives ex: 0.01) */ if(session->sma_b.sma > 0.00){ /*! Throw an event to FreeSWITCH */ status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, AVMD_EVENT_BEEP); if(status != SWITCH_STATUS_SUCCESS) { return; } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Beep-Status", "stop"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session->session)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "avmd"); if ((switch_event_dup(&event_copy, event)) != SWITCH_STATUS_SUCCESS) { return; } switch_core_session_queue_event(session->session, &event); switch_event_fire(&event_copy); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session->session), SWITCH_LOG_INFO, "<<< AVMD - Beep Detected >>>\n"); switch_channel_set_variable(channel, "avmd_detect", "TRUE"); RESET_SMA_BUFFER(&session->sma_b); session->state.beep_state = BEEP_DETECTED; return; } amp = 0.0; success = 0.0; error = 0.0; } } }