Beispiel #1
0
void
desa2_freeswitch_double(double *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_DOUBLE_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[%f][%f]>>>\n",
            *var1, freq[i], TO_HZ(8000, freq[i]), sma_b.sma, TO_HZ(8000, sma_b.sma), sqa_b.sma, i, input[i], GET_SAMPLE((&b), 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);
    free(sma_b.data);
    free(sqa_b.data);
    return;
}
Beispiel #2
0
static void adc_calibration(struct adc* me, struct adc_event* e) {
    if (me == NULL || e == NULL) {
        return;
    }
    switch (e->super_.signal) {
        case ADC_CALIBRATION_SIG:
            PORTD |= (1 << PD0);                                    /* start calibration */
            PORTC = 0x00;
            RESET_SMA_BUF(&me->sma);                                /* reset SMA buffer and append new value */
        case ADC_NEW_SAMPLE_SIG:
            if (TCNT1 >= CLK_TICKS_PER_SMA_SAMPLES(SMA_SAMPLES_PER_SECONDS(0.5))) {     /* 0.5s passed */
                APPEND_SMA_VAL(&me->sma, MIN(255, e->sample / 4));                      /* buffer stores uint8_t */
                PORTD ^= (1 << PD1);                                                    /* flash PD1 */
                TCNT1 = 0;                                                              /* reset timer counter */
                if (me->sma.lpos >= SMA_SAMPLES_PER_SECONDS(10)) {
                    me->sma_prev = me->sma.sma;
                    me->resolution = MIN(me->sma.sma, 255 - me->sma.sma) / 4;   /* classification segment length */
                    PORTD &= ~(1 << PD0);                                       /* turn PD0 off */
                    FSM_TRANSITION_(&me->super_, &adc_default);                 /* stop calibration */
                }
                break;
            }
        default:
            break;
    }
}
Beispiel #3
0
static void adc_default(struct adc* me, struct adc_event* e) {
    uint8_t sma;
    uint8_t resolution;

    if (me == NULL || e == NULL) {
        return;
    }
    switch (e->super_.signal) {
        case ADC_NEW_SAMPLE_SIG:
            if (TCNT1 >= CLK_TICKS_PER_SMA_SAMPLES(SMA_SAMPLES_PER_SECONDS(0.5))) {   /* 0.5s passed */
                APPEND_SMA_VAL(&me->sma, MIN(255, e->sample / 4)); /* buffer stores uint8_t */
                TCNT1 = 0;              /* reset timer counter */
                PORTD ^= (1 << PD3);    /* toggle PD3 */
            }
            adc_flash(me, e);
            sma = me->sma.sma;
            resolution = me->resolution;
            if (me->sma.lpos >= SMA_SAMPLES_PER_SECONDS(10) && ((sma > me->sma_prev + MIN(resolution, 255 - me->sma_prev)) || (sma < me->sma_prev - MIN(resolution, me->sma_prev)))) {
                FSM_TRANSITION_(&me->super_, &adc_calibration);         /* start calibration, do the state transition */
                e->super_.signal = ADC_CALIBRATION_SIG;
                FSM_DISPATCH_(&me->super_, &e->super_);
            }
            break;
        default:
            break;
    }
}
Beispiel #4
0
/*
 * Purpose: detect a tone using DESA-1 algorithm
 *
 * Parameters:
 *      input       pointer to input samples
 *      variance    the variance of the frequency estimates
 *
 * Return value: frequency estimate in Hz
 */
double
desa1(double *input, double *variance)
{
    // detector variables
    static double diff0 = 0.0;  // delayed differences
    static double diff1 = 0.0;
    static double diff2 = 0.0;
    static double diff3 = 0.0;
    static double x1 = 0.0;     // delayed inputs
    static double x2 = 0.0;
    static double x3 = 0.0;
	sma_buffer_t    sma_b;
	sma_buffer_t    sqa_b;
 
    double num; // numerator
    double den; // denominator
    double freq[BLOCK]; // frequency estimates
    int i;
 
	INIT_SMA_BUFFER(&sma_b, 10);
	INIT_SMA_BUFFER(&sqa_b, 10);
    // calculate the frequency estimate for each sample
    for ( i = 0; i < BLOCK; i++ )
    {
        diff0 = input[i] - x1;
        num = diff2 * diff2 - diff1 * diff3
            + diff1 * diff1 - diff0 * diff2;
        den = x2 * x2 - x1 * x3;
        freq[i] = SAMPLE_RATE * asin(sqrt(num/(8.0 * den))) / M_PI;
        APPEND_SMA_VAL(&sma_b, freq[i]);
        APPEND_SMA_VAL(&sqa_b, freq[i] * freq[i]);
        // handle errors - division by zero, square root of
        // negative number or asin of number > 1 or < -1
        if (isnan(freq[i]))
        {
            freq[i] = 0;
        } else  if (isinf(freq[i]))
        {
            freq[i] = 2000.0;
        }
 
        diff3 = diff2;
        diff2 = diff1;
        diff1 = diff0;
        x3 = x2;
        x2 = x1;
        x1 = input[i];
	printf("<<< AVMD f[%f]Hz\tsample[%d]\t[%f] >>>\n", freq[i], i, input[i]);
	printf("<<< AVMD v[%f] f[%f]Hz sma[%f]Hz sqa[%f]\tsample[%d]\t[%d] >>>\n",
            sqa_b.sma - (sma_b.sma * sma_b.sma), freq[i], sma_b.sma, sqa_b.sma, i, input[i]);
    }
 
    // calculate mean frequency
    double mean = 0.0;
    for ( i = 0; i < BLOCK; i++ )
    {
        mean += freq[i];
    }
    mean /= (double)BLOCK;
 
    // calculate the variance in the frequency estimates
    *variance = 0.0;
    for ( i = 0; i < BLOCK; i++ )
    {
        *variance += freq[i] * freq[i];
    }
    *variance /= (double)BLOCK;
    *variance -= (mean * mean);
 
    return mean;
}
Beispiel #5
0
/*! \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;
        }
    }
}