121 #define DEFAULT_THRESHOLD 512
132 #define DSP_HISTORY 15
134 #define TONE_THRESH 10.0
135 #define TONE_MIN_THRESH 1e8
147 #define MAX_DTMF_DIGITS 128
161 #define DTMF_THRESHOLD 8.0e7
162 #define FAX_THRESHOLD 8.0e7
163 #define FAX_2ND_HARMONIC 2.0
165 #define DEF_DTMF_NORMAL_TWIST 6.31
166 #define DEF_RELAX_DTMF_NORMAL_TWIST 6.31
169 #define DEF_DTMF_REVERSE_TWIST 2.51
170 #define DEF_RELAX_DTMF_REVERSE_TWIST 6.61
172 #define DEF_DTMF_REVERSE_TWIST 2.51
173 #define DEF_RELAX_DTMF_REVERSE_TWIST 3.98
176 #define DTMF_RELATIVE_PEAK_ROW 6.3
177 #define DTMF_RELATIVE_PEAK_COL 6.3
178 #define DTMF_2ND_HARMONIC_ROW (relax ? 1.7 : 2.5)
179 #define DTMF_2ND_HARMONIC_COL 63.1
180 #define DTMF_TO_TOTAL_ENERGY 42.0
182 #define BELL_MF_THRESHOLD 1.6e9
183 #define BELL_MF_TWIST 4.0
184 #define BELL_MF_RELATIVE_PEAK 12.6
186 #if defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
187 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
193 #define FAX_TONE_CNG_FREQ 1100
194 #define FAX_TONE_CNG_DURATION 500
195 #define FAX_TONE_CNG_DB 16
201 #define FAX_TONE_CED_FREQ 2100
202 #define FAX_TONE_CED_DURATION 2600
203 #define FAX_TONE_CED_DB 16
205 #define SAMPLE_RATE 8000
213 #define SAMPLES_IN_FRAME 160
219 #define DTMF_GSIZE 102
224 #define DEF_DTMF_HITS_TO_BEGIN 2
229 #define DEF_DTMF_MISSES_TO_END 3
237 #define CONFIG_FILE_NAME "dsp.conf"
307 697.0, 770.0, 852.0, 941.0
310 1209.0, 1336.0, 1477.0, 1633.0
313 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
332 s->
v3 = (s->
fac * s->
v2) >> 15;
334 if (abs(s->
v3) > 32768) {
345 for (i = 0; i < count; i++) {
357 return (
float)r.
value * (float)(1 << r.
power);
437 int duration_samples;
439 int periods_in_block;
446 duration_samples = duration_samples * 9 / 10;
458 if (periods_in_block < 5)
459 periods_in_block = 5;
489 x = pow(10.0, amp / 10.0);
507 for (i = 0; i < 4; i++) {
521 for (i = 0; i < 6; i++) {
559 for (start = 0; start <
samples; start = end) {
561 limit = samples - start;
567 for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
570 s->
energy += (int32_t) samp * (int32_t) samp;
588 ast_debug(10,
"tone %d, Ew=%.2E, Et=%.2E, s/n=%10.2f\n", s->
freq, tone_energy, s->
energy, tone_energy / (s->
energy - tone_energy));
638 if (mute.
end > samples) {
681 for (sample = 0; sample <
samples; sample = limit) {
690 for (j = sample; j < limit; j++) {
713 for (best_row = best_col = 0, i = 1; i < 4; i++) {
715 if (row_energy[i] > row_energy[best_row]) {
719 if (col_energy[i] > col_energy[best_col]) {
727 col_energy[best_col] < row_energy[best_row] * (relax ? relax_dtmf_reverse_twist : dtmf_reverse_twist) &&
728 row_energy[best_row] < col_energy[best_col] * (relax ? relax_dtmf_normal_twist : dtmf_normal_twist)) {
730 for (i = 0; i < 4; i++) {
731 if ((i != best_col &&
742 hit = dtmf_positions[(best_row << 2) + best_col];
834 if (squelch && hit) {
844 for (i = 0; i < 4; i++) {
852 if (squelch && mute.
end) {
853 if (mute.
end > samples) {
864 int samples,
int squelch,
int relax)
883 for (sample = 0; sample <
samples; sample = limit) {
893 for (j = sample; j < limit; j++) {
917 if (energy[0] > energy[1]) {
925 for (i = 2; i < 6; i++) {
927 if (energy[i] >= energy[best]) {
930 }
else if (energy[i] >= energy[second_best]) {
941 for (i = 0; i < 6; i++) {
942 if (i != best && i != second_best) {
953 if (second_best < best) {
958 best = best * 5 + second_best - 1;
959 hit = bell_mf_positions[best];
987 if (squelch && hit) {
997 for (i = 0; i < 6; i++)
1002 if (squelch && mute.
end) {
1003 if (mute.
end > samples) {
1013 static inline int pair_there(
float p1,
float p2,
float i1,
float i2,
float e)
1025 if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
1029 if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
1049 for (x = 0; x <
pass; x++) {
1060 for (y = 0; y < 7; y++) {
1067 }
else if (
pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->
genergy)) {
1069 }
else if (
pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->
genergy)) {
1108 if (newstate == dsp->
tstate) {
1151 ast_debug(1,
"Consider call as answered because of timeout after last ring\n");
1157 ast_debug(5,
"Start state %d\n", newstate);
1163 for (x = 0; x < 7; x++) {
1197 for (x = 0; x <
len; x++) {
1204 #ifdef DEBUG_DSP_BUSYDETECT
1205 fprintf(stderr,
"SILENCE: len = %d, level = %d\n", dsp->
totalsilence, accum);
1214 if (tone1 < tone2) {
1231 #ifdef DEBUG_DSP_BUSYDETECT
1232 fprintf(stderr,
"NOISE: len = %d, level = %d\n", dsp->
totalnoise, accum);
1253 int avgsilence = 0, hitsilence = 0;
1254 int avgtone = 0, hittone = 0;
1255 #ifdef DEBUG_DSP_BUSYDETECT
1257 char silence_list[64]=
"", tone_list[64]=
"";
1271 #ifdef DEBUG_DSP_BUSYDETECT
1272 sprintf(silence_list,
"Silences: ");
1273 sprintf(tone_list,
"Tones: ");
1276 #ifdef DEBUG_DSP_BUSYDETECT
1278 strcat(silence_list, buf);
1280 strcat(tone_list, buf);
1301 #ifdef DEBUG_DSP_BUSYDETECT
1302 fprintf(stderr,
"BUSY DETECTOR\n");
1303 fprintf(stderr,
"%s\n", tone_list);
1304 fprintf(stderr,
"%s\n", silence_list)
1312 ast_log(
LOG_ERROR,
"You can't use busytoneonly together with busycompare");
1314 if (avgtone > avgsilence) {
1329 #ifdef BUSYDETECT_DEBUG
1330 ast_debug(5,
"busy detector: avgtone of %d not close enough to desired %d\n",
1339 #ifdef BUSYDETECT_DEBUG
1340 ast_debug(5,
"busy detector: avgsilence of %d not close enough to desired %d\n",
1348 ast_log(
LOG_NOTICE,
"ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1350 ast_debug(5,
"busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1396 int digit = 0, fax_digit = 0;
1399 unsigned char *odata;
1421 for (x = 0;x <
len; x++) {
1427 for (x = 0; x <
len; x++) {
1448 memset(&dsp->
f, 0,
sizeof(dsp->
f));
1455 memset(&dsp->
f, 0,
sizeof(dsp->
f));
1460 ast_debug(1,
"Requesting Hangup because the busy tone was detected on channel %s\n", chan->
name);
1481 int event = 0, event_len = 0;
1482 char event_digit = 0;
1509 ast_debug(1,
"DTMF Detected - Reset busydetector\n");
1514 memset(&dsp->
f, 0,
sizeof(dsp->
f));
1517 dsp->
f.
len = event_len;
1527 memset(&dsp->
f, 0,
sizeof(dsp->
f));
1543 memset(&dsp->
f, 0,
sizeof(dsp->
f));
1546 dsp->
f.
src =
"dsp_progress";
1568 for (x = 0; x <
len; x++) {
1569 odata[x] =
AST_LIN2MU((
unsigned short) shortdata[x]);
1573 for (x = 0; x <
len; x++) {
1574 odata[x] =
AST_LIN2A((
unsigned short) shortdata[x]);
1618 #ifdef BUSYDETECT_TONEONLY
1620 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
1621 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
1625 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
1657 if (threshold < 256)
1685 if (quietlength > 0)
1689 ast_debug(1,
"dsp busy pattern set to %d,%d\n", tonelength, quietlength);
1690 if( fuzzy > 0 && fuzzy < 50 )
1702 for (i = 0; i < 6; i++) {
1710 for (i = 0; i < 4; i++) {
1731 for (x = 0; x < 4; x++) {
1756 if (dsp->
faxmode != faxmode) {
1817 if (!strcasecmp(v->
name,
"silencethreshold")) {
1818 if (sscanf(v->
value,
"%30d", &cfg_threshold) < 1) {
1820 }
else if (cfg_threshold < 0) {
1821 ast_log(
LOG_WARNING,
"Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
1825 }
else if (!strcasecmp(v->
name,
"dtmf_normal_twist")) {
1826 if (sscanf(v->
value,
"%30f", &cfg_twist) < 1) {
1828 }
else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {
1829 ast_log(
LOG_WARNING,
"Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
1831 dtmf_normal_twist = cfg_twist;
1833 }
else if (!strcasecmp(v->
name,
"dtmf_reverse_twist")) {
1834 if (sscanf(v->
value,
"%30f", &cfg_twist) < 1) {
1836 }
else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {
1837 ast_log(
LOG_WARNING,
"Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
1839 dtmf_reverse_twist = cfg_twist;
1841 }
else if (!strcasecmp(v->
name,
"relax_dtmf_normal_twist")) {
1842 if (sscanf(v->
value,
"%30f", &cfg_twist) < 1) {
1844 }
else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {
1845 ast_log(
LOG_WARNING,
"Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
1847 relax_dtmf_normal_twist = cfg_twist;
1849 }
else if (!strcasecmp(v->
name,
"relax_dtmf_reverse_twist")) {
1850 if (sscanf(v->
value,
"%30f", &cfg_twist) < 1) {
1852 }
else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {
1853 ast_log(
LOG_WARNING,
"Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
1855 relax_dtmf_reverse_twist = cfg_twist;
1857 }
else if (!strcasecmp(v->
name,
"dtmf_hits_to_begin")) {
1858 if (sscanf(v->
value,
"%30d", &cfg_threshold) < 1) {
1860 }
else if (cfg_threshold < 1) {
1861 ast_log(
LOG_WARNING,
"Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
1863 dtmf_hits_to_begin = cfg_threshold;
1865 }
else if (!strcasecmp(v->
name,
"dtmf_misses_to_end")) {
1866 if (sscanf(v->
value,
"%30d", &cfg_threshold) < 1) {
1868 }
else if (cfg_threshold < 1) {
1869 ast_log(
LOG_WARNING,
"Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
1871 dtmf_misses_to_end = cfg_threshold;
1882 return thresholds[which];
static void mute_fragment(struct ast_dsp *dsp, fragment_t *fragment)
A-Law to Signed linear conversion.
union ast_frame_subclass subclass
#define DSP_PROGRESS_RINGING
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Main Channel structure associated with a channel.
static float relax_dtmf_reverse_twist
Asterisk main include file. File version handling, generic pbx functions.
#define DTMF_RELATIVE_PEAK_COL
#define FAX_TONE_CNG_FREQ
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define DSP_TONE_STATE_HUNGUP
#define DSP_DIGITMODE_DTMF
void ast_dsp_free(struct ast_dsp *dsp)
int ast_dsp_get_tcount(struct ast_dsp *dsp)
Get tcount (Threshold counter)
#define DSP_FEATURE_DIGIT_DETECT
#define DTMF_RELATIVE_PEAK_ROW
Convenient Signal Processing routines.
#define DSP_DIGITMODE_MUTECONF
static const char bell_mf_positions[]
#define DSP_PROGRESS_BUSY
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
static const int DEFAULT_SILENCE_THRESHOLD
The default silence threshold we will use if an alternate configured value is not present or is inval...
#define DSP_PROGRESS_TALK
#define DSP_FEATURE_CALL_PROGRESS
#define DEF_DTMF_NORMAL_TWIST
struct ast_dsp * ast_dsp_new(void)
#define DSP_TONE_STATE_DIALTONE
#define DTMF_TO_TOTAL_ENERGY
Structure for variables, used for configurations and for channel variables.
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
int historicsilence[DSP_HISTORY]
#define DSP_PROGRESS_CONGESTION
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
int ast_dsp_was_muted(struct ast_dsp *dsp)
Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) hap...
static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise)
Configuration File Parser.
#define DEF_DTMF_HITS_TO_BEGIN
static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
static const char dtmf_positions[]
static void ast_mf_detect_init(mf_detect_state_t *s)
goertzel_state_t tone_out[6]
struct ast_frame * ast_frisolate(struct ast_frame *fr)
Makes a frame independent of any static storage.
#define FAX_TONE_CNG_DURATION
#define DSP_TONE_STATE_TALKING
int ast_dsp_init(void)
Load dsp settings from dsp.conf.
#define FAX_TONE_CED_FREQ
static void ast_dsp_prog_reset(struct ast_dsp *dsp)
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
static void goertzel_reset(goertzel_state_t *s)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
digit_detect_state_t digit_state
int historicnoise[DSP_HISTORY]
char digits[MAX_DTMF_DIGITS+1]
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
#define CONFIG_STATUS_FILEMISSING
static const float dtmf_col[]
static void ast_digit_detect_init(digit_detect_state_t *s, int mf)
static int dtmf_hits_to_begin
#define FAX_TONE_CED_DURATION
#define DSP_DIGITMODE_RELAXDTMF
#define ast_debug(level,...)
Log a DEBUG message.
#define DEF_DTMF_REVERSE_TWIST
#define DSP_TONE_STATE_SPECIAL2
static struct progress modes[]
u-Law to Signed linear conversion
static const float dtmf_row[]
enum gsamp_size gsamp_size
General Asterisk PBX channel definitions.
#define DSP_TONE_STATE_RINGING
static int dtmf_misses_to_end
#define DSP_TONE_STATE_BUSY
Asterisk internal frame definitions.
#define DEF_DTMF_MISSES_TO_END
#define DSP_FEATURE_SILENCE_SUPPRESS
#define DSP_FEATURE_FAX_DETECT
int ast_dsp_set_faxmode(struct ast_dsp *dsp, int faxmode)
Set fax mode.
#define DSP_TONE_STATE_SPECIAL3
static struct progalias aliases[]
goertzel_state_t col_out[4]
#define DEFAULT_THRESHOLD
This value is the minimum threshold, calculated by averaging all of the samples within a frame...
int ast_dsp_get_tstate(struct ast_dsp *dsp)
Get tstate (Tone State)
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength, int fuzzy)
Set expected lengths of the busy tones.
#define DEF_RELAX_DTMF_NORMAL_TWIST
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
static void store_digit(digit_detect_state_t *s, char digit)
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set threshold value for silence.
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
static const float mf_tones[]
static float dtmf_normal_twist
#define DSP_DIGITMODE_MUTEMAX
static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
char * ast_getformatname(format_t format)
Get the name of a format.
static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, int amp)
static float relax_dtmf_normal_twist
void ast_dsp_set_busy_compare(struct ast_dsp *dsp, int compare)
Set if silence and noice lengths must be compared for busy.
#define DSP_TONE_STATE_SPECIAL1
#define DSP_FAXMODE_DETECT_CED
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_FORMAT_TESTLAW
const ast_string_field name
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
static void ast_fax_detect_init(struct ast_dsp *s)
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
goertzel_state_t freqs[7]
#define DSP_FEATURE_BUSY_DETECT
tone_detect_state_t ced_tone_state
Structure used to handle boolean flags.
static int _dsp_init(int reload)
static void goertzel_update(goertzel_state_t *s, short *samps, int count)
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silenc...
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
#define AST_FORMAT_SLINEAR
static void goertzel_sample(goertzel_state_t *s, short sample)
#define BELL_MF_RELATIVE_PEAK
#define BELL_MF_THRESHOLD
int ast_dsp_reload(void)
Reloads dsp settings from dsp.conf.
static int compare(const char *text, const char *template)
int display_inband_dtmf_warning
tone_detect_state_t cng_tone_state
Data structure associated with a single frame of data.
int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
Scans for progress indication in audio.
int digitlen[MAX_DTMF_DIGITS+1]
static float goertzel_result(goertzel_state_t *s)
Options provided by main asterisk program.
#define DSP_FAXMODE_DETECT_CNG
enum ast_frame_type frametype
#define DSP_TONE_STATE_SILENCE
struct ast_variable * next
#define DSP_DIGITMODE_NOQUELCH
#define CONFIG_STATUS_FILEINVALID
#define DSP_FEATURE_WAITDIALTONE
int ast_dsp_busydetect(struct ast_dsp *dsp)
Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been ...
static float dtmf_reverse_twist
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
union ast_frame::@172 data
#define DEF_RELAX_DTMF_REVERSE_TWIST
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
static void goertzel_init(goertzel_state_t *s, float freq, int samples)
static int pair_there(float p1, float p2, float i1, float i2, float e)
union digit_detect_state_t::@254 td
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
goertzel_state_t row_out[4]
#define CONFIG_STATUS_FILEUNCHANGED
static int thresholds[THRESHOLD_MAX]
int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise...
static void ast_dtmf_detect_init(dtmf_detect_state_t *s)