Add support for Costa Rica to DSP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2576 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
4b234476bb
commit
1ccab64d86
|
@ -28,7 +28,7 @@ eagi-sphinx-test: eagi-sphinx-test.o
|
|||
$(CC) -o eagi-sphinx-test eagi-sphinx-test.o
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o look .depend
|
||||
rm -f *.so *.o look .depend eagi-test
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
|
|
|
@ -137,6 +137,7 @@ static char callerid[256] = "";
|
|||
|
||||
static char language[MAX_LANGUAGE] = "";
|
||||
static char musicclass[MAX_LANGUAGE] = "";
|
||||
static char progzone[10]= "";
|
||||
|
||||
static int usedistinctiveringdetection = 0;
|
||||
|
||||
|
@ -3998,6 +3999,8 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
|
|||
if (i->dsp) {
|
||||
ast_dsp_set_features(i->dsp, features);
|
||||
ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
|
||||
if (strlen(progzone))
|
||||
ast_dsp_set_call_progress_zone(i->dsp, progzone);
|
||||
if (i->busydetect && CANBUSYDETECT(i)) {
|
||||
ast_dsp_set_busy_count(i->dsp, i->busycount);
|
||||
}
|
||||
|
@ -8092,6 +8095,8 @@ static int reload_zt(void)
|
|||
strncpy(context, v->value, sizeof(context)-1);
|
||||
} else if (!strcasecmp(v->name, "language")) {
|
||||
strncpy(language, v->value, sizeof(language)-1);
|
||||
} else if (!strcasecmp(v->name, "progzone")) {
|
||||
strncpy(progzone, v->value, sizeov(progzone) - 1);
|
||||
} else if (!strcasecmp(v->name, "musiconhold")) {
|
||||
strncpy(musicclass, v->value, sizeof(musicclass)-1);
|
||||
} else if (!strcasecmp(v->name, "stripmsd")) {
|
||||
|
|
|
@ -240,12 +240,16 @@ immediate=no
|
|||
; of a call through RINGING, BUSY, and ANSWERING. If turned on, call
|
||||
; progress attempts to determine answer, busy, and ringing on phone lines.
|
||||
; This feature is HIGHLY EXPERIMENTAL and can easily detect false answers,
|
||||
; so don't count on it being very accurate. Also, it is ONLY configured for
|
||||
; standard U.S. tones. This feature can also easily detect false hangups.
|
||||
; The symptoms of this is being disconnected in the middle of a call for no
|
||||
; reason.
|
||||
; so don't count on it being very accurate.
|
||||
;
|
||||
; Few zones are supported at the time of this writing, but may
|
||||
; be selected with "progzone"
|
||||
;
|
||||
; This feature can also easily detect false hangups. The symptoms of this
|
||||
; is being disconnected in the middle of a call for no reason.
|
||||
;
|
||||
;callprogress=yes
|
||||
;progzone=us
|
||||
;
|
||||
; Select which class of music to use for music on hold. If not specified
|
||||
; then the default will be used.
|
||||
|
|
169
dsp.c
169
dsp.c
|
@ -43,6 +43,42 @@
|
|||
#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 } },
|
||||
};
|
||||
|
||||
#define DEFAULT_THRESHOLD 1024
|
||||
|
||||
#define BUSY_PERCENT 10 /* The percentage diffrence between the two last silence periods */
|
||||
|
@ -53,20 +89,9 @@
|
|||
/* Remember last 15 units */
|
||||
#define DSP_HISTORY 15
|
||||
|
||||
/* Number of goertzels for progress detect */
|
||||
#define GSAMP_SIZE 183
|
||||
|
||||
/* Define if you want the fax detector -- NOT RECOMMENDED IN -STABLE */
|
||||
#define FAX_DETECT
|
||||
|
||||
#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
|
||||
|
||||
#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 */
|
||||
|
@ -270,7 +295,10 @@ struct ast_dsp {
|
|||
int historicnoise[DSP_HISTORY];
|
||||
int historicsilence[DSP_HISTORY];
|
||||
goertzel_state_t freqs[7];
|
||||
int freqcount;
|
||||
int gsamps;
|
||||
int gsamp_size;
|
||||
int progmode;
|
||||
int tstate;
|
||||
int tcount;
|
||||
int digitmode;
|
||||
|
@ -1099,65 +1127,63 @@ int ast_dsp_getdigits (struct ast_dsp *dsp,
|
|||
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int pass;
|
||||
int newstate = TONE_STATE_SILENCE;
|
||||
int res = 0;
|
||||
while(len) {
|
||||
/* Take the lesser of the number of samples we need and what we have */
|
||||
pass = len;
|
||||
if (pass > GSAMP_SIZE - dsp->gsamps)
|
||||
pass = GSAMP_SIZE - dsp->gsamps;
|
||||
if (pass > dsp->gsamp_size - dsp->gsamps)
|
||||
pass = dsp->gsamp_size - dsp->gsamps;
|
||||
for (x=0;x<pass;x++) {
|
||||
goertzel_sample(&dsp->freqs[HZ_350], s[x]);
|
||||
goertzel_sample(&dsp->freqs[HZ_440], s[x]);
|
||||
goertzel_sample(&dsp->freqs[HZ_480], s[x]);
|
||||
goertzel_sample(&dsp->freqs[HZ_620], s[x]);
|
||||
goertzel_sample(&dsp->freqs[HZ_950], s[x]);
|
||||
goertzel_sample(&dsp->freqs[HZ_1400], s[x]);
|
||||
goertzel_sample(&dsp->freqs[HZ_1800], s[x]);
|
||||
for (y=0;y<dsp->freqcount;y++)
|
||||
goertzel_sample(&dsp->freqs[y], s[x]);
|
||||
dsp->genergy += s[x] * s[x];
|
||||
}
|
||||
s += pass;
|
||||
dsp->gsamps += pass;
|
||||
len -= pass;
|
||||
if (dsp->gsamps == GSAMP_SIZE) {
|
||||
float hz_350;
|
||||
float hz_440;
|
||||
float hz_480;
|
||||
float hz_620;
|
||||
float hz_950;
|
||||
float hz_1400;
|
||||
float hz_1800;
|
||||
hz_350 = goertzel_result(&dsp->freqs[HZ_350]);
|
||||
hz_440 = goertzel_result(&dsp->freqs[HZ_440]);
|
||||
hz_480 = goertzel_result(&dsp->freqs[HZ_480]);
|
||||
hz_620 = goertzel_result(&dsp->freqs[HZ_620]);
|
||||
hz_950 = goertzel_result(&dsp->freqs[HZ_950]);
|
||||
hz_1400 = goertzel_result(&dsp->freqs[HZ_1400]);
|
||||
hz_1800 = goertzel_result(&dsp->freqs[HZ_1800]);
|
||||
if (dsp->gsamps == dsp->gsamp_size) {
|
||||
float hz[7];
|
||||
for (y=0;y<7;y++)
|
||||
hz[y] = goertzel_result(&dsp->freqs[y]);
|
||||
#if 0
|
||||
printf("Got whole dsp state: 350: %e, 440: %e, 480: %e, 620: %e, 950: %e, 1400: %e, 1800: %e, Energy: %e\n",
|
||||
hz_350, hz_440, hz_480, hz_620, hz_950, hz_1400, hz_1800, dsp->genergy);
|
||||
#endif
|
||||
if (pair_there(hz_480, hz_620, hz_350, hz_440, dsp->genergy)) {
|
||||
newstate = TONE_STATE_BUSY;
|
||||
} else if (pair_there(hz_440, hz_480, hz_350, hz_620, dsp->genergy)) {
|
||||
newstate = TONE_STATE_RINGING;
|
||||
} else if (pair_there(hz_350, hz_440, hz_480, hz_620, dsp->genergy)) {
|
||||
newstate = TONE_STATE_DIALTONE;
|
||||
} else if (hz_950 > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
newstate = TONE_STATE_SPECIAL1;
|
||||
} else if (hz_1400 > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
if (dsp->tstate == TONE_STATE_SPECIAL1)
|
||||
newstate = TONE_STATE_SPECIAL2;
|
||||
} else if (hz_1800 > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
if (dsp->tstate == TONE_STATE_SPECIAL2)
|
||||
newstate = TONE_STATE_SPECIAL3;
|
||||
} else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
newstate = TONE_STATE_TALKING;
|
||||
} else
|
||||
newstate = TONE_STATE_SILENCE;
|
||||
|
||||
switch(dsp->progmode) {
|
||||
case PROG_MODE_NA:
|
||||
if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
|
||||
newstate = TONE_STATE_BUSY;
|
||||
} else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
|
||||
newstate = TONE_STATE_RINGING;
|
||||
} else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
|
||||
newstate = TONE_STATE_DIALTONE;
|
||||
} else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
newstate = TONE_STATE_SPECIAL1;
|
||||
} else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
if (dsp->tstate == TONE_STATE_SPECIAL1)
|
||||
newstate = TONE_STATE_SPECIAL2;
|
||||
} else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
if (dsp->tstate == TONE_STATE_SPECIAL2)
|
||||
newstate = TONE_STATE_SPECIAL3;
|
||||
} else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
newstate = TONE_STATE_TALKING;
|
||||
} else
|
||||
newstate = TONE_STATE_SILENCE;
|
||||
break;
|
||||
case PROG_MODE_CR:
|
||||
if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
newstate = TONE_STATE_RINGING;
|
||||
} else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
|
||||
newstate = TONE_STATE_TALKING;
|
||||
} else
|
||||
newstate = TONE_STATE_SILENCE;
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
|
||||
}
|
||||
if (newstate == dsp->tstate) {
|
||||
dsp->tcount++;
|
||||
if (dsp->tcount == COUNT_THRESH) {
|
||||
|
@ -1581,6 +1607,21 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
|
|||
return af;
|
||||
}
|
||||
|
||||
static void ast_dsp_prog_reset(struct ast_dsp *dsp)
|
||||
{
|
||||
int max = 0;
|
||||
int x;
|
||||
dsp->gsamp_size = modes[dsp->progmode].size;
|
||||
dsp->gsamps = 0;
|
||||
for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
|
||||
if (modes[dsp->progmode].freqs[x]) {
|
||||
goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
|
||||
max = x;
|
||||
}
|
||||
}
|
||||
dsp->freqcount = max;
|
||||
}
|
||||
|
||||
struct ast_dsp *ast_dsp_new(void)
|
||||
{
|
||||
struct ast_dsp *dsp;
|
||||
|
@ -1590,14 +1631,6 @@ struct ast_dsp *ast_dsp_new(void)
|
|||
dsp->threshold = DEFAULT_THRESHOLD;
|
||||
dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
|
||||
dsp->busycount = DSP_HISTORY;
|
||||
/* Initialize goertzels */
|
||||
goertzel_init(&dsp->freqs[HZ_350], 350.0, GSAMP_SIZE);
|
||||
goertzel_init(&dsp->freqs[HZ_440], 440.0, GSAMP_SIZE);
|
||||
goertzel_init(&dsp->freqs[HZ_480], 480.0, GSAMP_SIZE);
|
||||
goertzel_init(&dsp->freqs[HZ_620], 620.0, GSAMP_SIZE);
|
||||
goertzel_init(&dsp->freqs[HZ_950], 950.0, GSAMP_SIZE);
|
||||
goertzel_init(&dsp->freqs[HZ_1400], 1400.0, GSAMP_SIZE);
|
||||
goertzel_init(&dsp->freqs[HZ_1800], 1800.0, GSAMP_SIZE);
|
||||
/* Initialize DTMF detector */
|
||||
ast_dtmf_detect_init(&dsp->td.dtmf);
|
||||
}
|
||||
|
@ -1705,3 +1738,15 @@ int ast_dsp_digitmode(struct ast_dsp *dsp, int digitmode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
|
||||
{
|
||||
int x;
|
||||
for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
|
||||
if (!strcasecmp(aliases[x].name, zone)) {
|
||||
dsp->progmode = aliases[x].mode;
|
||||
ast_dsp_prog_reset(dsp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@ void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences);
|
|||
/* Scans for progress indication in audio */
|
||||
int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf);
|
||||
|
||||
/* Set zone for doing progress detection */
|
||||
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone);
|
||||
|
||||
/* Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on
|
||||
busies, and call progress, all dependent upon which features are enabled */
|
||||
struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf, int needlock);
|
||||
|
|
Loading…
Reference in New Issue