Skip to content
Snippets Groups Projects
dsp.c 49.6 KiB
Newer Older
Mark Spencer's avatar
Mark Spencer committed
/*
 * Asterisk -- A telephony toolkit for Linux.
 *
 * Convenience Signal Processing routines
 * 
 * Copyright (C) 2002, Digium
 *
 * Mark Spencer <markster@linux-support.net>
 *
 * This program is free software, distributed under the terms of
 * the GNU General Public License.
 *
 * Goertzel routines are borrowed from Steve Underwood's tremendous work on the
 * DTMF detector.
 *
 */

/* Some routines from tone_detect.c by Steven Underwood as published under the zapata library */
/*
	tone_detect.c - General telephony tone detection, and specific
                        detection of DTMF.

        Copyright (C) 2001  Steve Underwood <steveu@coppice.org>

        Despite my general liking of the GPL, I place this code in the
        public domain for the benefit of all mankind - even the slimy
        ones who might try to proprietize my work and use it to my
        detriment.
*/

#include <sys/types.h>
Mark Spencer's avatar
Mark Spencer committed
#include <asterisk/frame.h>
#include <asterisk/channel.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/logger.h>
#include <asterisk/dsp.h>
#include <asterisk/ulaw.h>
#include <asterisk/alaw.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <stdio.h>

/* Number of goertzels for progress detect */
#define GSAMP_SIZE_NA 183			/* North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */
#define GSAMP_SIZE_CR 188			/* Costa Rica - Only care about 425 Hz */

#define PROG_MODE_NA		0
#define PROG_MODE_CR		1	

/* For US modes */
#define HZ_350  0
#define HZ_440  1
#define HZ_480  2
#define HZ_620  3
#define HZ_950  4
#define HZ_1400 5
#define HZ_1800 6

/* For CR modes */
#define HZ_425	0

static struct progalias {
	char *name;
	int mode;
} aliases[] = {
	{ "us", PROG_MODE_NA },
	{ "ca", PROG_MODE_NA },
	{ "cr", PROG_MODE_CR },
};

static struct progress {
	int size;
	int freqs[7];
} modes[] = {
	{ GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } },	/* North America */
	{ GSAMP_SIZE_CR, { 425 } },
};

Mark Spencer's avatar
Mark Spencer committed
#define DEFAULT_THRESHOLD 1024

#define BUSY_PERCENT		10	/* The percentage diffrence between the two last silence periods */
#define BUSY_THRESHOLD		100	/* Max number of ms difference between max and min times in busy */
#define BUSY_MIN		75	/* Busy must be at least 80 ms in half-cadence */
Mark Spencer's avatar
Mark Spencer committed
#define BUSY_MAX		1100	/* Busy can't be longer than 1100 ms in half-cadence */

/* Remember last 15 units */
#define DSP_HISTORY 15
/* Define if you want the fax detector -- NOT RECOMMENDED IN -STABLE */
#define FAX_DETECT

Mark Spencer's avatar
Mark Spencer committed
#define TONE_THRESH 10.0	/* How much louder the tone should be than channel energy */
#define TONE_MIN_THRESH 1e8	/* How much tone there should be at least to attempt */
#define COUNT_THRESH  3		/* Need at least 50ms of stuff to count it */

#define TONE_STATE_SILENCE  0
#define TONE_STATE_RINGING  1 
#define TONE_STATE_DIALTONE 2
#define TONE_STATE_TALKING  3
#define TONE_STATE_BUSY     4
#define TONE_STATE_SPECIAL1	5
#define TONE_STATE_SPECIAL2 6
#define TONE_STATE_SPECIAL3 7

#define	MAX_DTMF_DIGITS 128

/* Basic DTMF specs:
 *
 * Minimum tone on = 40ms
 * Minimum tone off = 50ms
 * Maximum digit rate = 10 per second
 * Normal twist <= 8dB accepted
 * Reverse twist <= 4dB accepted
 * S/N >= 15dB will detect OK
 * Attenuation <= 26dB will detect OK
 * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
 */

#define DTMF_THRESHOLD              8.0e7
#define FAX_THRESHOLD              8.0e7
#define FAX_2ND_HARMONIC       		2.0     /* 4dB */
#define DTMF_NORMAL_TWIST           6.3     /* 8dB */
#ifdef	RADIO_RELAX
#define DTMF_REVERSE_TWIST          ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 6.5 : 2.5)     /* 4dB normal */
#else
Mark Spencer's avatar
Mark Spencer committed
#define DTMF_REVERSE_TWIST          ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5)     /* 4dB normal */
Mark Spencer's avatar
Mark Spencer committed
#define DTMF_RELATIVE_PEAK_ROW      6.3     /* 8dB */
#define DTMF_RELATIVE_PEAK_COL      6.3     /* 8dB */
#define DTMF_2ND_HARMONIC_ROW       ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5)     /* 4dB normal */
#define DTMF_2ND_HARMONIC_COL       63.1    /* 18dB */
#ifndef OLD_DSP_ROUTINES
#define DTMF_TO_TOTAL_ENERGY	    42.0
#endif
Mark Spencer's avatar
Mark Spencer committed
#define MF_THRESHOLD              8.0e7
#define MF_NORMAL_TWIST           5.3     /* 8dB */
#define MF_REVERSE_TWIST          4.0     /* was 2.5 */
#define MF_RELATIVE_PEAK      5.3     /* 8dB */
#define MF_2ND_HARMONIC       1.7 /* was 2.5  */
#else
#define BELL_MF_THRESHOLD           1.6e9
#define BELL_MF_TWIST               4.0     /* 6dB */
#define BELL_MF_RELATIVE_PEAK       12.6    /* 11dB */
#endif
Mark Spencer's avatar
Mark Spencer committed

typedef struct {
	float v2;
	float v3;
	float fac;
Mark Spencer's avatar
Mark Spencer committed
} goertzel_state_t;

typedef struct
{

    goertzel_state_t row_out[4];
    goertzel_state_t col_out[4];
Mark Spencer's avatar
Mark Spencer committed
    goertzel_state_t row_out2nd[4];
    goertzel_state_t col_out2nd[4];
    int hit1;
    int hit2;
    int hit3;
    int hit4;
#else
    int hits[3];
#endif	
    int mhit;
Mark Spencer's avatar
Mark Spencer committed
    float energy;
    int current_sample;
Mark Spencer's avatar
Mark Spencer committed
    char digits[MAX_DTMF_DIGITS + 1];
    int current_digits;
    int detected_digits;
    int lost_digits;
    int digit_hits[16];
Mark Spencer's avatar
Mark Spencer committed
	int fax_hits;
Mark Spencer's avatar
Mark Spencer committed
} dtmf_detect_state_t;

typedef struct
{
Loading
Loading full blame...