Пример #1
0
static void put_text_msg(void *user_data, const uint8_t *msg, int len)
{
	switch_tdd_t *pvt = (switch_tdd_t *) user_data;
	switch_event_t *event, *clone;
	switch_channel_t *channel = switch_core_session_get_channel(pvt->session);
	switch_core_session_t *other_session;


	switch_channel_add_variable_var_check(channel, "tdd_messages", (char *)msg, SWITCH_FALSE, SWITCH_STACK_PUSH);


	if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TDD_RECV_MESSAGE) == SWITCH_STATUS_SUCCESS) {

		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", "mod_spandsp");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "tdd");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "TDD MESSAGE");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "TDD-Data", (char *)msg);
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(pvt->session));
		switch_event_add_body(event, "%s\n\n", (char *)msg);

		if (switch_core_session_get_partner(pvt->session, &other_session) == SWITCH_STATUS_SUCCESS) {

			if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
				switch_core_session_receive_event(other_session, &clone);
			}

			if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
				switch_core_session_queue_event(other_session, &clone);
			}

			switch_core_session_rwunlock(other_session);
		}

		switch_event_fire(&event);


	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s got TDD Message [%s]\n", switch_channel_get_name(channel), (char *)msg);

}
Пример #2
0
static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
	switch_fsk_detect_t *pvt = (switch_fsk_detect_t *) user_data;
	//switch_frame_t *frame = NULL;
	switch_channel_t *channel = switch_core_session_get_channel(pvt->session);

	switch (type) {
	case SWITCH_ABC_TYPE_INIT: {
		switch_codec_implementation_t read_impl = { 0 };
		switch_core_session_get_read_impl(pvt->session, &read_impl);
		
		if (fsk_demod_init(&pvt->fsk_data, read_impl.actual_samples_per_second, pvt->fbuf, sizeof(pvt->fbuf))) {
			return SWITCH_FALSE;
		}
		
		break;
	}
	case SWITCH_ABC_TYPE_CLOSE:
		{
			fsk_demod_destroy(&pvt->fsk_data);
		}
		break;

	case SWITCH_ABC_TYPE_WRITE_REPLACE:
	case SWITCH_ABC_TYPE_READ_REPLACE:
		{
			switch_frame_t *rframe;

			if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
				rframe = switch_core_media_bug_get_read_replace_frame(bug);
			} else {
				rframe = switch_core_media_bug_get_write_replace_frame(bug);
			}

			if (!pvt->skip && fsk_demod_feed(&pvt->fsk_data, rframe->data, rframe->datalen / 2) != SWITCH_STATUS_SUCCESS) {
				char str[1024] = "";
				size_t type, mlen;
				char *sp;
				switch_event_t *event;
				const char *app_var;
				int total = 0;

				switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA);
				
				while(fsk_data_parse(&pvt->fsk_data, &type, &sp, &mlen) == SWITCH_STATUS_SUCCESS) {
					char *varname = NULL, *val, *p;
					
					switch_copy_string(str, sp, mlen+1);
					*(str+mlen) = '\0';
					switch_clean_string(str);
					//printf("TYPE %u LEN %u VAL [%s]\n", (unsigned)type, (unsigned)mlen, str);

					val = str;

					switch(type) {
					case MDMF_DATETIME:
						varname = "fsk_datetime";
						break;
					case MDMF_PHONE_NAME:
						varname = "fsk_phone_name";
						break;
					case MDMF_PHONE_NUM:
						varname = "fsk_phone_num";
						break;
					case MDMF_NAME_VALUE:
						varname = switch_core_session_sprintf(pvt->session, "fsk_%s", val);
						if ((p = strchr(varname, ':'))) {
							*p++ = '\0';
							val = p;
						}
						break;
					default:
						break;
					}

					if (varname && val) {
						total++;
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s setting FSK var [%s][%s]\n", 
										  switch_channel_get_name(channel), varname, val);
						switch_channel_set_variable(channel, varname, val);
						if (event) {
							switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, varname, val);
						}
					}
				}

				if (event) {
					if (switch_core_session_queue_event(pvt->session, &event) != SWITCH_STATUS_SUCCESS) {
						switch_event_destroy(&event);
					}
				}
				
				if (total && (app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) {
					char *app_arg;

					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s processing execute_on_fsk [%s]\n", 
									  switch_channel_get_name(channel), app_var);
					if ((app_arg = strchr(app_var, ' '))) {
						*app_arg++ = '\0';
					}
					switch_core_session_execute_application(pvt->session, app_var, app_arg);
				}
				
				pvt->skip = 10;
			}
			
			memset(rframe->data, 255, rframe->datalen);

			if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
				switch_core_media_bug_set_read_replace_frame(bug, rframe);
			} else {
				switch_core_media_bug_set_write_replace_frame(bug, rframe);
			}

			if (pvt->skip && !--pvt->skip) {
				return SWITCH_FALSE;
			}

		}
		break;
	case SWITCH_ABC_TYPE_WRITE:
	default:
		break;
	}

	return SWITCH_TRUE;
}
Пример #3
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;
        }
    }
}
Пример #4
0
/*! \brief Find voicemail beep in the audio stream 
 *
 * @author Eric des Courtis
 * @param vmd_info The session information associated with the call.
 * @param frame The audio data.
 * @return The success or failure of the function.
 */
static void find_beep(vmd_session_info_t *vmd_info, switch_frame_t *frame)
{
	int i;
	int c;
	double m[POINTS];
	double med;
	unsigned int j = (vmd_info->pos + 1) % POINTS;
	unsigned int k = j;
	switch_event_t *event;
	switch_status_t status;
	switch_event_t *event_copy;
	switch_channel_t *channel = switch_core_session_get_channel(vmd_info->session);

	switch (vmd_info->state) {
	case BEEP_DETECTED:
		for (c = 0, i = 0; i < POINTS; j++, j %= POINTS, i++) {
			vmd_info->timestamp++;
			if (vmd_info->points[j].freq < TOLERANCE_T(vmd_info->beep_freq) && vmd_info->points[j].freq > TOLERANCE_B(vmd_info->beep_freq)) {
				c++;
				vmd_info->beep_freq = (vmd_info->beep_freq * 0.95) + (vmd_info->points[j].freq * 0.05);
			}
		}

		if (c < (POINTS - MAX_CHIRP)) {
			vmd_info->state = BEEP_NOT_DETECTED;
			if (vmd_info->timestamp < (switch_size_t) vmd_info->minTime) {
				break;
			}

			status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VMD_EVENT_BEEP);
			if (status != SWITCH_STATUS_SUCCESS) {
				return;
			}

			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Beep-Status", "stop");
			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Beep-Time", "%d", (int) vmd_info->timestamp / POINTS);
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(vmd_info->session));
			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Frequency", "%6.4lf", vmd_info->beep_freq);
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "vmd");

			if ((switch_event_dup(&event_copy, event)) != SWITCH_STATUS_SUCCESS) {
				return;
			}

			switch_core_session_queue_event(vmd_info->session, &event);
			switch_event_fire(&event_copy);

			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(vmd_info->session), SWITCH_LOG_INFO, "<<< VMD - Beep Detected >>>\n");
			switch_channel_set_variable(channel, "vmd_detect", "TRUE");

			vmd_info->timestamp = 0;
		}

		break;

	case BEEP_NOT_DETECTED:

		for (i = 0; i < POINTS; k++, k %= POINTS, i++) {
			m[i] = vmd_info->points[k].freq;
			if (ISNAN(m[i])) {
				m[i] = 0.0;
			}
		}

		med = median(m, POINTS);
		if (ISNAN(med)) {
			for (i = 0; i < POINTS; i++) {
				if (!ISNAN(m[i])) {
					med = m[i];
					break;
				}
			}
		}

		for (c = 0, i = 0; i < POINTS; j++, j %= POINTS, i++) {
			if (vmd_info->points[j].freq < TOLERANCE_T(med) && vmd_info->points[j].freq > TOLERANCE_B(med)) {
				if (vmd_info->points[j].ampl > MIN_AMPL && vmd_info->points[j].freq > MIN_FREQ && vmd_info->points[j].freq < MAX_FREQ) {
					c++;
				}
			}
		}

		if (c >= VALID) {
			vmd_info->state = BEEP_DETECTED;
			vmd_info->beep_freq = med;
			vmd_info->timestamp = 0;
		}

		break;
	}
}