Asterisk - The Open Source Telephony Project GIT-master-a63eec2
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions | Variables
dsp.c File Reference

Convenience Signal Processing routines. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/test.h"
Include dependency graph for dsp.c:

Go to the source code of this file.

Data Structures

struct  ast_dsp
 
struct  digit_detect_state_t
 
struct  dtmf_detect_state_t
 
struct  fragment_t
 
struct  goertzel_result_t
 
struct  goertzel_state_t
 
struct  mf_detect_state_t
 
struct  progalias
 
struct  progress
 
struct  tone_detect_state_t
 

Macros

#define BELL_MF_RELATIVE_PEAK   12.6 /* 11dB */
 
#define BELL_MF_THRESHOLD   1.6e9
 
#define BELL_MF_TWIST   4.0 /* 6dB */
 
#define CONFIG_FILE_NAME   "dsp.conf"
 
#define DEF_DTMF_HITS_TO_BEGIN   2
 
#define DEF_DTMF_MISSES_TO_END   3
 
#define DEF_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */
 
#define DEF_DTMF_REVERSE_TWIST   2.51 /* 4.01dB */
 
#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */
 
#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98 /* 6.0dB */
 
#define DEFAULT_SAMPLE_RATE   8000
 
#define DEFAULT_THRESHOLD   512
 Default minimum average magnitude threshold to determine talking/noise by the DSP.
 
#define DSP_HISTORY   15
 
#define DTMF_GSIZE   102
 
#define DTMF_MATRIX_SIZE   4
 
#define DTMF_RELATIVE_PEAK_COL   6.3 /* 8dB */
 
#define DTMF_RELATIVE_PEAK_ROW   6.3 /* 8dB */
 
#define DTMF_THRESHOLD   8.0e7
 
#define DTMF_TO_TOTAL_ENERGY   42.0
 
#define FAX_TONE_CED_DB   16
 
#define FAX_TONE_CED_DURATION   2600 /* ms */
 
#define FAX_TONE_CED_FREQ   2100
 
#define FAX_TONE_CNG_DB   16
 
#define FAX_TONE_CNG_DURATION   500 /* ms */
 
#define FAX_TONE_CNG_FREQ   1100
 
#define FREQ_ARRAY_SIZE   7
 
#define MAX_DTMF_DIGITS   128
 
#define MF_GSIZE   120
 
#define TONE_MIN_THRESH   1e8
 
#define TONE_THRESH   10.0
 
#define TONE_THRESHOLD   7.8e7
 

Enumerations

enum  busy_detect {
  BUSY_PERCENT = 10 , BUSY_PAT_PERCENT = 7 , BUSY_THRESHOLD = 100 , BUSY_MIN = 75 ,
  BUSY_MAX = 3100
}
 
enum  freq_index {
  HZ_350 = 0 , HZ_440 , HZ_480 , HZ_620 ,
  HZ_950 , HZ_1400 , HZ_1800 , HZ_425 = 0 ,
  HZ_350UK = 0 , HZ_400UK , HZ_440UK
}
 
enum  gsamp_size { GSAMP_SIZE_NA = 183 , GSAMP_SIZE_CR = 188 , GSAMP_SIZE_UK = 160 }
 
enum  gsamp_thresh {
  THRESH_RING = 8 , THRESH_TALK = 2 , THRESH_BUSY = 4 , THRESH_CONGESTION = 4 ,
  THRESH_HANGUP = 60 , THRESH_RING2ANSWER = 300
}
 
enum  prog_mode { PROG_MODE_NA = 0 , PROG_MODE_CR , PROG_MODE_UK }
 

Functions

static int __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len)
 
static struct ast_dsp__ast_dsp_new (unsigned int sample_rate)
 
static int __ast_dsp_silence_noise (struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static int _dsp_init (int reload)
 
static void ast_digit_detect_init (digit_detect_state_t *s, int mf, unsigned int sample_rate)
 
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 called.
 
int ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf)
 Scans for progress indication in audio.
 
void ast_dsp_digitreset (struct ast_dsp *dsp)
 Reset DTMF detector.
 
void ast_dsp_free (struct ast_dsp *dsp)
 
int ast_dsp_get_features (struct ast_dsp *dsp)
 Get features.
 
unsigned int ast_dsp_get_sample_rate (const struct ast_dsp *dsp)
 Retrieve the sample rate this DSP structure was created with.
 
int ast_dsp_get_tcount (struct ast_dsp *dsp)
 Get tcount (Threshold counter)
 
int ast_dsp_get_threshold_from_settings (enum threshold which)
 Get silence threshold from dsp.conf.
 
int ast_dsp_get_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State)
 
struct ast_dspast_dsp_new (void)
 Allocates a new dsp, assumes 8khz for internal sample rate.
 
struct ast_dspast_dsp_new_with_rate (unsigned int sample_rate)
 Allocates a new dsp with a specific internal sample rate used during processing.
 
int ast_dsp_noise (struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
 Process the audio frame for noise.
 
struct ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
 Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
 
static void ast_dsp_prog_reset (struct ast_dsp *dsp)
 
void ast_dsp_reset (struct ast_dsp *dsp)
 Reset total silence count.
 
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
 Set number of required cadences for busy.
 
void ast_dsp_set_busy_pattern (struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
 Set expected lengths of the busy tone.
 
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
 Set zone for doing progress detection.
 
int ast_dsp_set_digitmode (struct ast_dsp *dsp, int digitmode)
 Set digit mode.
 
int ast_dsp_set_faxmode (struct ast_dsp *dsp, int faxmode)
 Set fax mode.
 
void ast_dsp_set_features (struct ast_dsp *dsp, int features)
 Select feature set.
 
int ast_dsp_set_freqmode (struct ast_dsp *dsp, int freq, int dur, int db, int squelch)
 Set arbitrary frequency detection mode.
 
void ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold)
 Set the minimum average magnitude threshold to determine talking by the DSP.
 
int ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
 Process the audio frame for silence.
 
static int ast_dsp_silence_noise_with_energy (struct ast_dsp *dsp, struct ast_frame *f, int *total, int *frames_energy, int noise)
 
int ast_dsp_silence_with_energy (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence, int *frames_energy)
 Process the audio frame for silence.
 
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) happens when DSP code removes DTMF/MF/generic tones from the audio.
 
static void ast_dtmf_detect_init (dtmf_detect_state_t *s, unsigned int sample_rate)
 
static void ast_fax_detect_init (struct ast_dsp *s)
 
static void ast_freq_detect_init (struct ast_dsp *s, int freq, int dur, int db, int squelch)
 
static void ast_mf_detect_init (mf_detect_state_t *s, unsigned int sample_rate)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void ast_tone_detect_init (tone_detect_state_t *s, int freq, int duration, int amp, unsigned int sample_rate)
 
static int dtmf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
 
static void goertzel_init (goertzel_state_t *s, float freq, unsigned int sample_rate)
 
static void goertzel_reset (goertzel_state_t *s)
 
static float goertzel_result (goertzel_state_t *s)
 
static void goertzel_sample (goertzel_state_t *s, short sample)
 
static int load_module (void)
 
static int mf_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
 
static void mute_fragment (struct ast_dsp *dsp, fragment_t *fragment)
 
static int pair_there (float p1, float p2, float i1, float i2, float e)
 
static int reload_module (void)
 
static void store_digit (digit_detect_state_t *s, char digit)
 
static int tone_detect (struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "DSP" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
 
static struct progalias aliases []
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const char bell_mf_positions [] = "1247C-358A--69*---0B----#"
 
static const int DEFAULT_SILENCE_THRESHOLD = 256
 The default silence threshold we will use if an alternate configured value is not present or is invalid.
 
static const float dtmf_col []
 
static int dtmf_hits_to_begin
 
static int dtmf_misses_to_end
 
static float dtmf_normal_twist
 
static const char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
 
static float dtmf_reverse_twist
 
static const float dtmf_row []
 
static const float mf_tones []
 
static struct progress modes []
 
static float relax_dtmf_normal_twist
 
static float relax_dtmf_reverse_twist
 
static int thresholds [THRESHOLD_MAX]
 

Detailed Description

Convenience Signal Processing routines.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Steve Underwood steve.nosp@m.u@co.nosp@m.ppice.nosp@m..org

Definition in file dsp.c.

Macro Definition Documentation

◆ BELL_MF_RELATIVE_PEAK

#define BELL_MF_RELATIVE_PEAK   12.6 /* 11dB */

Definition at line 202 of file dsp.c.

◆ BELL_MF_THRESHOLD

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 200 of file dsp.c.

◆ BELL_MF_TWIST

#define BELL_MF_TWIST   4.0 /* 6dB */

Definition at line 201 of file dsp.c.

◆ CONFIG_FILE_NAME

#define CONFIG_FILE_NAME   "dsp.conf"

Definition at line 247 of file dsp.c.

◆ DEF_DTMF_HITS_TO_BEGIN

#define DEF_DTMF_HITS_TO_BEGIN   2

Definition at line 234 of file dsp.c.

◆ DEF_DTMF_MISSES_TO_END

#define DEF_DTMF_MISSES_TO_END   3

Definition at line 239 of file dsp.c.

◆ DEF_DTMF_NORMAL_TWIST

#define DEF_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */

Definition at line 185 of file dsp.c.

◆ DEF_DTMF_REVERSE_TWIST

#define DEF_DTMF_REVERSE_TWIST   2.51 /* 4.01dB */

Definition at line 192 of file dsp.c.

◆ DEF_RELAX_DTMF_NORMAL_TWIST

#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */

Definition at line 186 of file dsp.c.

◆ DEF_RELAX_DTMF_REVERSE_TWIST

#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98 /* 6.0dB */

Definition at line 193 of file dsp.c.

◆ DEFAULT_SAMPLE_RATE

#define DEFAULT_SAMPLE_RATE   8000

Definition at line 223 of file dsp.c.

◆ DEFAULT_THRESHOLD

#define DEFAULT_THRESHOLD   512

Default minimum average magnitude threshold to determine talking/noise by the DSP.

The magnitude calculated for this threshold is determined by averaging the absolute value of all samples within a frame.

This value is the threshold for which a frame's average magnitude is determined to either be silence (below the threshold) or noise/talking (at or above the threshold). Please note that while the default threshold is an even exponent of 2, there is no requirement that it be so. The threshold will work for any value between 1 and 2^15.

Definition at line 140 of file dsp.c.

◆ DSP_HISTORY

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 151 of file dsp.c.

◆ DTMF_GSIZE

#define DTMF_GSIZE   102

Definition at line 229 of file dsp.c.

◆ DTMF_MATRIX_SIZE

#define DTMF_MATRIX_SIZE   4

Definition at line 168 of file dsp.c.

◆ DTMF_RELATIVE_PEAK_COL

#define DTMF_RELATIVE_PEAK_COL   6.3 /* 8dB */

Definition at line 197 of file dsp.c.

◆ DTMF_RELATIVE_PEAK_ROW

#define DTMF_RELATIVE_PEAK_ROW   6.3 /* 8dB */

Definition at line 196 of file dsp.c.

◆ DTMF_THRESHOLD

#define DTMF_THRESHOLD   8.0e7

Definition at line 182 of file dsp.c.

◆ DTMF_TO_TOTAL_ENERGY

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 198 of file dsp.c.

◆ FAX_TONE_CED_DB

#define FAX_TONE_CED_DB   16

Definition at line 221 of file dsp.c.

◆ FAX_TONE_CED_DURATION

#define FAX_TONE_CED_DURATION   2600 /* ms */

Definition at line 220 of file dsp.c.

◆ FAX_TONE_CED_FREQ

#define FAX_TONE_CED_FREQ   2100

Definition at line 219 of file dsp.c.

◆ FAX_TONE_CNG_DB

#define FAX_TONE_CNG_DB   16

Definition at line 213 of file dsp.c.

◆ FAX_TONE_CNG_DURATION

#define FAX_TONE_CNG_DURATION   500 /* ms */

Definition at line 212 of file dsp.c.

◆ FAX_TONE_CNG_FREQ

#define FAX_TONE_CNG_FREQ   1100

Definition at line 211 of file dsp.c.

◆ FREQ_ARRAY_SIZE

#define FREQ_ARRAY_SIZE   7

Definition at line 115 of file dsp.c.

◆ MAX_DTMF_DIGITS

#define MAX_DTMF_DIGITS   128

Definition at line 166 of file dsp.c.

◆ MF_GSIZE

#define MF_GSIZE   120

Definition at line 226 of file dsp.c.

◆ TONE_MIN_THRESH

#define TONE_MIN_THRESH   1e8

How much tone there should be at least to attempt

Definition at line 154 of file dsp.c.

◆ TONE_THRESH

#define TONE_THRESH   10.0

How much louder the tone should be than channel energy

Definition at line 153 of file dsp.c.

◆ TONE_THRESHOLD

#define TONE_THRESHOLD   7.8e7

Definition at line 183 of file dsp.c.

Enumeration Type Documentation

◆ busy_detect

Enumerator
BUSY_PERCENT 

The percentage difference between the two last silence periods

BUSY_PAT_PERCENT 

The percentage difference between measured and actual pattern

BUSY_THRESHOLD 

Max number of ms difference between max and min times in busy

BUSY_MIN 

Busy must be at least 80 ms in half-cadence

BUSY_MAX 

Busy can't be longer than 3100 ms in half-cadence

Definition at line 142 of file dsp.c.

142 {
143 BUSY_PERCENT = 10, /*!< The percentage difference between the two last silence periods */
144 BUSY_PAT_PERCENT = 7, /*!< The percentage difference between measured and actual pattern */
145 BUSY_THRESHOLD = 100, /*!< Max number of ms difference between max and min times in busy */
146 BUSY_MIN = 75, /*!< Busy must be at least 80 ms in half-cadence */
147 BUSY_MAX = 3100 /*!< Busy can't be longer than 3100 ms in half-cadence */
148};
@ BUSY_MAX
Definition dsp.c:147
@ BUSY_PAT_PERCENT
Definition dsp.c:144
@ BUSY_MIN
Definition dsp.c:146
@ BUSY_PERCENT
Definition dsp.c:143
@ BUSY_THRESHOLD
Definition dsp.c:145

◆ freq_index

enum freq_index
Enumerator
HZ_350 

For US modes {

HZ_440 
HZ_480 
HZ_620 
HZ_950 
HZ_1400 
HZ_1800 

}

HZ_425 

For CR/BR modes

HZ_350UK 

For UK mode

HZ_400UK 
HZ_440UK 

Definition at line 85 of file dsp.c.

85 {
86 /*! For US modes { */
87 HZ_350 = 0,
88 HZ_440,
89 HZ_480,
90 HZ_620,
91 HZ_950,
92 HZ_1400,
93 HZ_1800, /*!< } */
94
95 /*! For CR/BR modes */
96 HZ_425 = 0,
97
98 /*! For UK mode */
99 HZ_350UK = 0,
100 HZ_400UK,
102};
@ HZ_425
Definition dsp.c:96
@ HZ_950
Definition dsp.c:91
@ HZ_350UK
Definition dsp.c:99
@ HZ_620
Definition dsp.c:90
@ HZ_440
Definition dsp.c:88
@ HZ_440UK
Definition dsp.c:101
@ HZ_480
Definition dsp.c:89
@ HZ_350
Definition dsp.c:87
@ HZ_1400
Definition dsp.c:92
@ HZ_400UK
Definition dsp.c:100
@ HZ_1800
Definition dsp.c:93

◆ gsamp_size

enum gsamp_size

Number of goertzels for progress detect

Enumerator
GSAMP_SIZE_NA 

North America - 350, 440, 480, 620, 950, 1400, 1800 Hz

GSAMP_SIZE_CR 

Costa Rica, Brazil - Only care about 425 Hz

GSAMP_SIZE_UK 

UK disconnect goertzel feed - should trigger 400hz

Definition at line 73 of file dsp.c.

73 {
74 GSAMP_SIZE_NA = 183, /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */
75 GSAMP_SIZE_CR = 188, /*!< Costa Rica, Brazil - Only care about 425 Hz */
76 GSAMP_SIZE_UK = 160 /*!< UK disconnect goertzel feed - should trigger 400hz */
77};
@ GSAMP_SIZE_NA
Definition dsp.c:74
@ GSAMP_SIZE_CR
Definition dsp.c:75
@ GSAMP_SIZE_UK
Definition dsp.c:76

◆ gsamp_thresh

All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms)

Enumerator
THRESH_RING 

Need at least 150ms ring to accept

THRESH_TALK 

Talk detection does not work continuously

THRESH_BUSY 

Need at least 80ms to accept

THRESH_CONGESTION 

Need at least 80ms to accept

THRESH_HANGUP 

Need at least 1300ms to accept hangup

THRESH_RING2ANSWER 

Timeout from start of ring to answer (about 6600 ms)

Definition at line 157 of file dsp.c.

157 {
158 THRESH_RING = 8, /*!< Need at least 150ms ring to accept */
159 THRESH_TALK = 2, /*!< Talk detection does not work continuously */
160 THRESH_BUSY = 4, /*!< Need at least 80ms to accept */
161 THRESH_CONGESTION = 4, /*!< Need at least 80ms to accept */
162 THRESH_HANGUP = 60, /*!< Need at least 1300ms to accept hangup */
163 THRESH_RING2ANSWER = 300 /*!< Timeout from start of ring to answer (about 6600 ms) */
164};
@ THRESH_RING
Definition dsp.c:158
@ THRESH_CONGESTION
Definition dsp.c:161
@ THRESH_RING2ANSWER
Definition dsp.c:163
@ THRESH_TALK
Definition dsp.c:159
@ THRESH_HANGUP
Definition dsp.c:162
@ THRESH_BUSY
Definition dsp.c:160

◆ prog_mode

enum prog_mode
Enumerator
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 79 of file dsp.c.

79 {
80 PROG_MODE_NA = 0,
83};
@ PROG_MODE_CR
Definition dsp.c:81
@ PROG_MODE_UK
Definition dsp.c:82
@ PROG_MODE_NA
Definition dsp.c:80

Function Documentation

◆ __ast_dsp_call_progress()

static int __ast_dsp_call_progress ( struct ast_dsp dsp,
short *  s,
int  len 
)
static

Definition at line 1081 of file dsp.c.

1082{
1083 short samp;
1084 int x;
1085 int y;
1086 int pass;
1087 int newstate = DSP_TONE_STATE_SILENCE;
1088 int res = 0;
1089 int freqcount = dsp->freqcount > FREQ_ARRAY_SIZE ? FREQ_ARRAY_SIZE : dsp->freqcount;
1090
1091 while (len) {
1092 /* Take the lesser of the number of samples we need and what we have */
1093 pass = len;
1094 if (pass > dsp->gsamp_size - dsp->gsamps) {
1095 pass = dsp->gsamp_size - dsp->gsamps;
1096 }
1097 for (x = 0; x < pass; x++) {
1098 samp = s[x];
1099 dsp->genergy += (int32_t) samp * (int32_t) samp;
1100 for (y = 0; y < freqcount; y++) {
1101 goertzel_sample(&dsp->freqs[y], samp);
1102 }
1103 }
1104 s += pass;
1105 dsp->gsamps += pass;
1106 len -= pass;
1107 if (dsp->gsamps == dsp->gsamp_size) {
1108 float hz[FREQ_ARRAY_SIZE];
1109 for (y = 0; y < FREQ_ARRAY_SIZE; y++) {
1110 hz[y] = goertzel_result(&dsp->freqs[y]);
1111 }
1112 switch (dsp->progmode) {
1113 case PROG_MODE_NA:
1114 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
1115 newstate = DSP_TONE_STATE_BUSY;
1116 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
1117 newstate = DSP_TONE_STATE_RINGING;
1118 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
1119 newstate = DSP_TONE_STATE_DIALTONE;
1120 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
1121 newstate = DSP_TONE_STATE_SPECIAL1;
1122 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
1123 /* End of SPECIAL1 or middle of SPECIAL2 */
1125 newstate = DSP_TONE_STATE_SPECIAL2;
1126 }
1127 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
1128 /* End of SPECIAL2 or middle of SPECIAL3 */
1130 newstate = DSP_TONE_STATE_SPECIAL3;
1131 }
1132 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1133 newstate = DSP_TONE_STATE_TALKING;
1134 } else {
1135 newstate = DSP_TONE_STATE_SILENCE;
1136 }
1137 break;
1138 case PROG_MODE_CR:
1139 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
1140 newstate = DSP_TONE_STATE_RINGING;
1141 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1142 newstate = DSP_TONE_STATE_TALKING;
1143 } else {
1144 newstate = DSP_TONE_STATE_SILENCE;
1145 }
1146 break;
1147 case PROG_MODE_UK:
1148 if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
1149 newstate = DSP_TONE_STATE_HUNGUP;
1150 } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
1151 newstate = DSP_TONE_STATE_DIALTONE;
1152 }
1153 break;
1154 default:
1155 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%u'\n", dsp->progmode);
1156 }
1157 if (newstate == dsp->tstate) {
1158 dsp->tcount++;
1159 if (dsp->ringtimeout) {
1160 dsp->ringtimeout++;
1161 }
1162 switch (dsp->tstate) {
1164 if ((dsp->features & DSP_PROGRESS_RINGING) &&
1165 (dsp->tcount == THRESH_RING)) {
1166 res = AST_CONTROL_RINGING;
1167 dsp->ringtimeout = 1;
1168 }
1169 break;
1171 if ((dsp->features & DSP_PROGRESS_BUSY) &&
1172 (dsp->tcount == THRESH_BUSY)) {
1173 res = AST_CONTROL_BUSY;
1174 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1175 }
1176 break;
1178 if ((dsp->features & DSP_PROGRESS_TALK) &&
1179 (dsp->tcount == THRESH_TALK)) {
1180 res = AST_CONTROL_ANSWER;
1181 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1182 }
1183 break;
1185 if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
1186 (dsp->tcount == THRESH_CONGESTION)) {
1188 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1189 }
1190 break;
1192 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
1193 (dsp->tcount == THRESH_HANGUP)) {
1194 res = AST_CONTROL_HANGUP;
1195 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1196 }
1197 break;
1198 }
1199 if (dsp->ringtimeout == THRESH_RING2ANSWER) {
1200 ast_debug(1, "Consider call as answered because of timeout after last ring\n");
1201 res = AST_CONTROL_ANSWER;
1202 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1203 }
1204 } else {
1205 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
1206 ast_debug(5, "Start state %d\n", newstate);
1207 dsp->tstate = newstate;
1208 dsp->tcount = 1;
1209 }
1210
1211 /* Reset goertzel */
1212 for (x = 0; x < 7; x++) {
1213 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1214 }
1215 dsp->gsamps = 0;
1216 dsp->genergy = 0.0;
1217 }
1218 }
1219
1220 return res;
1221}
#define ast_log
Definition astobj2.c:42
#define TONE_MIN_THRESH
Definition dsp.c:154
static float goertzel_result(goertzel_state_t *s)
Definition dsp.c:364
static void goertzel_sample(goertzel_state_t *s, short sample)
Definition dsp.c:338
static int pair_there(float p1, float p2, float i1, float i2, float e)
Definition dsp.c:1058
#define FREQ_ARRAY_SIZE
Definition dsp.c:115
#define TONE_THRESH
Definition dsp.c:153
#define DSP_PROGRESS_RINGING
Definition dsp.h:40
#define DSP_TONE_STATE_SPECIAL3
Definition dsp.h:59
#define DSP_TONE_STATE_SPECIAL2
Definition dsp.h:58
#define DSP_TONE_STATE_DIALTONE
Definition dsp.h:54
#define DSP_PROGRESS_TALK
Definition dsp.h:39
#define DSP_TONE_STATE_SILENCE
Definition dsp.h:52
#define DSP_TONE_STATE_BUSY
Definition dsp.h:56
#define DSP_PROGRESS_BUSY
Definition dsp.h:41
#define DSP_TONE_STATE_SPECIAL1
Definition dsp.h:57
#define DSP_PROGRESS_CONGESTION
Definition dsp.h:42
#define DSP_FEATURE_CALL_PROGRESS
Definition dsp.h:43
#define DSP_TONE_STATE_HUNGUP
Definition dsp.h:60
#define DSP_TONE_STATE_TALKING
Definition dsp.h:55
#define DSP_TONE_STATE_RINGING
Definition dsp.h:53
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HANGUP
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
static char pass[512]
int tcount
Definition dsp.c:427
goertzel_state_t freqs[FREQ_ARRAY_SIZE]
Definition dsp.c:421
int tstate
Definition dsp.c:426
enum prog_mode progmode
Definition dsp.c:425
int freqcount
Definition dsp.c:422
int features
Definition dsp.c:414
enum gsamp_size gsamp_size
Definition dsp.c:424
float genergy
Definition dsp.c:433
int gsamps
Definition dsp.c:423
int ringtimeout
Definition dsp.c:415

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_log, DSP_FEATURE_CALL_PROGRESS, DSP_PROGRESS_BUSY, DSP_PROGRESS_CONGESTION, DSP_PROGRESS_RINGING, DSP_PROGRESS_TALK, DSP_TONE_STATE_BUSY, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_HUNGUP, DSP_TONE_STATE_RINGING, DSP_TONE_STATE_SILENCE, DSP_TONE_STATE_SPECIAL1, DSP_TONE_STATE_SPECIAL2, DSP_TONE_STATE_SPECIAL3, DSP_TONE_STATE_TALKING, ast_dsp::features, FREQ_ARRAY_SIZE, ast_dsp::freqcount, ast_dsp::freqs, ast_dsp::genergy, goertzel_result(), goertzel_sample(), ast_dsp::gsamp_size, ast_dsp::gsamps, HZ_1400, HZ_1800, HZ_350, HZ_350UK, HZ_400UK, HZ_425, HZ_440, HZ_440UK, HZ_480, HZ_620, HZ_950, len(), LOG_WARNING, pair_there(), pass, PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::ringtimeout, ast_dsp::tcount, THRESH_BUSY, THRESH_CONGESTION, THRESH_HANGUP, THRESH_RING, THRESH_RING2ANSWER, THRESH_TALK, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

◆ __ast_dsp_new()

static struct ast_dsp * __ast_dsp_new ( unsigned int  sample_rate)
static

Definition at line 1739 of file dsp.c.

1740{
1741 struct ast_dsp *dsp;
1742
1743 if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
1746 dsp->busycount = DSP_HISTORY;
1749 dsp->sample_rate = sample_rate;
1750 dsp->freqcount = 0;
1751 /* Initialize digit detector */
1754 /* Initialize initial DSP progress detect parameters */
1755 ast_dsp_prog_reset(dsp);
1756 /* Initialize fax detector */
1758 }
1759 return dsp;
1760}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define DEFAULT_THRESHOLD
Default minimum average magnitude threshold to determine talking/noise by the DSP.
Definition dsp.c:140
static void ast_fax_detect_init(struct ast_dsp *s)
Definition dsp.c:513
#define DSP_HISTORY
Definition dsp.c:151
static void ast_digit_detect_init(digit_detect_state_t *s, int mf, unsigned int sample_rate)
Definition dsp.c:561
static void ast_dsp_prog_reset(struct ast_dsp *dsp)
Definition dsp.c:1717
#define DSP_DIGITMODE_MF
Definition dsp.h:32
#define DSP_FAXMODE_DETECT_CNG
Definition dsp.h:47
#define DSP_FEATURE_SILENCE_SUPPRESS
Definition dsp.h:26
#define DSP_DIGITMODE_DTMF
Definition dsp.h:31
Definition dsp.c:407
int faxmode
Definition dsp.c:429
unsigned int sample_rate
Definition dsp.c:435
int busycount
Definition dsp.c:417
int threshold
Definition dsp.c:409
digit_detect_state_t digit_state
Definition dsp.c:437
int digitmode
Definition dsp.c:428
int display_inband_dtmf_warning
Definition dsp.c:432

References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), ast_dsp::busycount, DEFAULT_THRESHOLD, ast_dsp::digit_state, ast_dsp::digitmode, ast_dsp::display_inband_dtmf_warning, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::faxmode, ast_dsp::features, ast_dsp::freqcount, ast_dsp::sample_rate, and ast_dsp::threshold.

Referenced by ast_dsp_new(), and ast_dsp_new_with_rate().

◆ __ast_dsp_silence_noise()

static int __ast_dsp_silence_noise ( struct ast_dsp dsp,
short *  s,
int  len,
int *  totalsilence,
int *  totalnoise,
int *  frames_energy 
)
static

Definition at line 1237 of file dsp.c.

1238{
1239 int accum;
1240 int x;
1241 int res = 0;
1242
1243 if (!len) {
1244 return 0;
1245 }
1246 accum = 0;
1247 for (x = 0; x < len; x++) {
1248 accum += abs(s[x]);
1249 }
1250 accum /= len;
1251 if (accum < dsp->threshold) {
1252 /* Silent */
1253 dsp->totalsilence += len / (dsp->sample_rate / 1000);
1254 if (dsp->totalnoise) {
1255 /* Move and save history */
1256 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0]));
1257 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
1258/* we don't want to check for busydetect that frequently */
1259#if 0
1260 dsp->busymaybe = 1;
1261#endif
1262 }
1263 dsp->totalnoise = 0;
1264 res = 1;
1265 } else {
1266 /* Not silent */
1267 dsp->totalnoise += len / (dsp->sample_rate / 1000);
1268 if (dsp->totalsilence) {
1269 int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
1270 int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
1271 /* Move and save history */
1272 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0]));
1273 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
1274 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
1275 if (silence1 < silence2) {
1276 if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) {
1277 dsp->busymaybe = 1;
1278 } else {
1279 dsp->busymaybe = 0;
1280 }
1281 } else {
1282 if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) {
1283 dsp->busymaybe = 1;
1284 } else {
1285 dsp->busymaybe = 0;
1286 }
1287 }
1288 }
1289 dsp->totalsilence = 0;
1290 }
1291 if (totalsilence) {
1292 *totalsilence = dsp->totalsilence;
1293 }
1294 if (totalnoise) {
1295 *totalnoise = dsp->totalnoise;
1296 }
1297 if (frames_energy) {
1298 *frames_energy = accum;
1299 }
1300 return res;
1301}
threshold
Definition dsp.h:71
#define abs(x)
Definition f2c.h:195
int historicnoise[DSP_HISTORY]
Definition dsp.c:419
int busymaybe
Definition dsp.c:416
int totalsilence
Definition dsp.c:411
int totalnoise
Definition dsp.c:413
int historicsilence[DSP_HISTORY]
Definition dsp.c:420

References abs, BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, len(), ast_dsp::sample_rate, ast_dsp::totalnoise, and ast_dsp::totalsilence.

Referenced by ast_dsp_process(), and ast_dsp_silence_noise_with_energy().

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2483 of file dsp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2483 of file dsp.c.

◆ _dsp_init()

static int _dsp_init ( int  reload)
static

Definition at line 1925 of file dsp.c.

1926{
1927 struct ast_config *cfg;
1928 struct ast_variable *v;
1929 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1930 int cfg_threshold;
1931 float cfg_twist;
1932
1933 if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
1934 return 0;
1935 }
1936
1944
1946 return 0;
1947 }
1948
1949 for (v = ast_variable_browse(cfg, "default"); v; v = v->next) {
1950 if (!strcasecmp(v->name, "silencethreshold")) {
1951 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1952 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1953 } else if (cfg_threshold < 0) {
1954 ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
1955 } else {
1956 thresholds[THRESHOLD_SILENCE] = cfg_threshold;
1957 }
1958 } else if (!strcasecmp(v->name, "dtmf_normal_twist")) {
1959 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1960 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1961 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1962 ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
1963 } else {
1964 dtmf_normal_twist = cfg_twist;
1965 }
1966 } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) {
1967 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1968 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1969 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1970 ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
1971 } else {
1972 dtmf_reverse_twist = cfg_twist;
1973 }
1974 } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) {
1975 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1976 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1977 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1978 ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
1979 } else {
1980 relax_dtmf_normal_twist = cfg_twist;
1981 }
1982 } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) {
1983 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1984 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1985 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1986 ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
1987 } else {
1988 relax_dtmf_reverse_twist = cfg_twist;
1989 }
1990 } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) {
1991 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1992 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1993 } else if (cfg_threshold < 1) { /* must be 1 or greater */
1994 ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
1995 } else {
1996 dtmf_hits_to_begin = cfg_threshold;
1997 }
1998 } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) {
1999 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
2000 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2001 } else if (cfg_threshold < 1) { /* must be 1 or greater */
2002 ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
2003 } else {
2004 dtmf_misses_to_end = cfg_threshold;
2005 }
2006 }
2007 }
2008 ast_config_destroy(cfg);
2009
2010 return 0;
2011}
static int thresholds[THRESHOLD_MAX]
Definition dsp.c:330
#define DEF_DTMF_HITS_TO_BEGIN
Definition dsp.c:234
#define DEF_DTMF_REVERSE_TWIST
Definition dsp.c:192
#define DEF_DTMF_MISSES_TO_END
Definition dsp.c:239
static const int DEFAULT_SILENCE_THRESHOLD
The default silence threshold we will use if an alternate configured value is not present or is inval...
Definition dsp.c:245
#define DEF_RELAX_DTMF_NORMAL_TWIST
Definition dsp.c:186
#define DEF_DTMF_NORMAL_TWIST
Definition dsp.c:185
#define CONFIG_FILE_NAME
Definition dsp.c:247
#define DEF_RELAX_DTMF_REVERSE_TWIST
Definition dsp.c:193
static float dtmf_reverse_twist
Definition dsp.c:332
static int dtmf_misses_to_end
Definition dsp.c:336
static int dtmf_hits_to_begin
Definition dsp.c:335
static float relax_dtmf_normal_twist
Definition dsp.c:333
static float dtmf_normal_twist
Definition dsp.c:331
static float relax_dtmf_reverse_twist
Definition dsp.c:334
@ THRESHOLD_SILENCE
Definition dsp.h:73
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
static int reload(void)
Structure used to handle boolean flags.
Definition utils.h:217
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next

References ast_config_destroy(), ast_config_load2(), ast_log, ast_variable_browse(), CONFIG_FILE_NAME, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, DEF_DTMF_HITS_TO_BEGIN, DEF_DTMF_MISSES_TO_END, DEF_DTMF_NORMAL_TWIST, DEF_DTMF_REVERSE_TWIST, DEF_RELAX_DTMF_NORMAL_TWIST, DEF_RELAX_DTMF_REVERSE_TWIST, DEFAULT_SILENCE_THRESHOLD, dtmf_hits_to_begin, dtmf_misses_to_end, dtmf_normal_twist, dtmf_reverse_twist, LOG_WARNING, ast_variable::name, ast_variable::next, relax_dtmf_normal_twist, relax_dtmf_reverse_twist, reload(), THRESHOLD_SILENCE, thresholds, and ast_variable::value.

Referenced by load_module(), and reload_module().

◆ ast_digit_detect_init()

static void ast_digit_detect_init ( digit_detect_state_t s,
int  mf,
unsigned int  sample_rate 
)
static

Definition at line 561 of file dsp.c.

562{
563 s->current_digits = 0;
564 s->detected_digits = 0;
565 s->lost_digits = 0;
566 s->digits[0] = '\0';
567
568 if (mf) {
569 ast_mf_detect_init(&s->td.mf, sample_rate);
570 } else {
571 ast_dtmf_detect_init(&s->td.dtmf, sample_rate);
572 }
573}
static void ast_mf_detect_init(mf_detect_state_t *s, unsigned int sample_rate)
Definition dsp.c:549
static void ast_dtmf_detect_init(dtmf_detect_state_t *s, unsigned int sample_rate)
Definition dsp.c:533
mf_detect_state_t mf
Definition dsp.c:315
dtmf_detect_state_t dtmf
Definition dsp.c:314
char digits[MAX_DTMF_DIGITS+1]
Definition dsp.c:307
union digit_detect_state_t::@372 td

References ast_dtmf_detect_init(), ast_mf_detect_init(), digit_detect_state_t::current_digits, digit_detect_state_t::detected_digits, digit_detect_state_t::digits, digit_detect_state_t::dtmf, digit_detect_state_t::lost_digits, digit_detect_state_t::mf, and digit_detect_state_t::td.

Referenced by __ast_dsp_new(), and ast_dsp_set_digitmode().

◆ ast_dsp_busydetect()

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 called.

Definition at line 1303 of file dsp.c.

1304{
1305 int res = 0, x;
1306#ifndef BUSYDETECT_TONEONLY
1307 int avgsilence = 0, hitsilence = 0;
1308#endif
1309 int avgtone = 0, hittone = 0;
1310
1311 /* if we have a 4 length pattern, the way busymaybe is set doesn't help us. */
1312 if (dsp->busy_cadence.length != 4) {
1313 if (!dsp->busymaybe) {
1314 return res;
1315 }
1316 }
1317
1318 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
1319#ifndef BUSYDETECT_TONEONLY
1320 avgsilence += dsp->historicsilence[x];
1321#endif
1322 avgtone += dsp->historicnoise[x];
1323 }
1324#ifndef BUSYDETECT_TONEONLY
1325 avgsilence /= dsp->busycount;
1326#endif
1327 avgtone /= dsp->busycount;
1328 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
1329#ifndef BUSYDETECT_TONEONLY
1330 if (avgsilence > dsp->historicsilence[x]) {
1331 if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) {
1332 hitsilence++;
1333 }
1334 } else {
1335 if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) {
1336 hitsilence++;
1337 }
1338 }
1339#endif
1340 if (avgtone > dsp->historicnoise[x]) {
1341 if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
1342 hittone++;
1343 }
1344 } else {
1345 if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
1346 hittone++;
1347 }
1348 }
1349 }
1350#ifndef BUSYDETECT_TONEONLY
1351 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) &&
1352 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) &&
1353 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX))
1354#else
1355 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX))
1356#endif
1357 {
1358#ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
1359 if (avgtone > avgsilence) {
1360 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) {
1361 res = 1;
1362 }
1363 } else {
1364 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) {
1365 res = 1;
1366 }
1367 }
1368#else
1369 res = 1;
1370#endif
1371 }
1372
1373 /* If we have a 4-length pattern, we can go ahead and just check it in a different way. */
1374 if (dsp->busy_cadence.length == 4) {
1375 int x;
1376 int errors = 0;
1377 int errors_max = ((4 * dsp->busycount) / 100.0) * BUSY_PAT_PERCENT;
1378
1379 for (x = DSP_HISTORY - (dsp->busycount); x < DSP_HISTORY; x += 2) {
1380 int temp_error;
1381 temp_error = abs(dsp->historicnoise[x] - dsp->busy_cadence.pattern[0]);
1382 if ((temp_error * 100) / dsp->busy_cadence.pattern[0] > BUSY_PERCENT) {
1383 errors++;
1384 }
1385
1386 temp_error = abs(dsp->historicnoise[x + 1] - dsp->busy_cadence.pattern[2]);
1387 if ((temp_error * 100) / dsp->busy_cadence.pattern[2] > BUSY_PERCENT) {
1388 errors++;
1389 }
1390
1391 temp_error = abs(dsp->historicsilence[x] - dsp->busy_cadence.pattern[1]);
1392 if ((temp_error * 100) / dsp->busy_cadence.pattern[1] > BUSY_PERCENT) {
1393 errors++;
1394 }
1395
1396 temp_error = abs(dsp->historicsilence[x + 1] - dsp->busy_cadence.pattern[3]);
1397 if ((temp_error * 100) / dsp->busy_cadence.pattern[3] > BUSY_PERCENT) {
1398 errors++;
1399 }
1400 }
1401
1402 ast_debug(5, "errors = %d max = %d\n", errors, errors_max);
1403
1404 if (errors <= errors_max) {
1405 return 1;
1406 }
1407 }
1408
1409 /* If we know the expected busy tone length, check we are in the range */
1410 if (res && (dsp->busy_cadence.pattern[0] > 0)) {
1411 if (abs(avgtone - dsp->busy_cadence.pattern[0]) > MAX(dsp->busy_cadence.pattern[0]*BUSY_PAT_PERCENT/100, 20)) {
1412#ifdef BUSYDETECT_DEBUG
1413 ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
1414 avgtone, dsp->busy_cadence.pattern[0]);
1415#endif
1416 res = 0;
1417 }
1418 }
1419#ifndef BUSYDETECT_TONEONLY
1420 /* If we know the expected busy tone silent-period length, check we are in the range */
1421 if (res && (dsp->busy_cadence.pattern[1] > 0)) {
1422 if (abs(avgsilence - dsp->busy_cadence.pattern[1]) > MAX(dsp->busy_cadence.pattern[1]*BUSY_PAT_PERCENT/100, 20)) {
1423#ifdef BUSYDETECT_DEBUG
1424 ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
1425 avgsilence, dsp->busy_cadence.pattern[1]);
1426#endif
1427 res = 0;
1428 }
1429 }
1430#endif
1431#if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
1432 if (res) {
1433 ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1434 } else {
1435 ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1436 }
1437#endif
1438 return res;
1439}
int pattern[4]
Definition dsp.h:68
struct ast_dsp_busy_pattern busy_cadence
Definition dsp.c:418
#define MAX(a, b)
Definition utils.h:251

References abs, ast_debug, ast_dsp::busy_cadence, BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp_busy_pattern::length, MAX, and ast_dsp_busy_pattern::pattern.

Referenced by ast_dsp_process().

◆ ast_dsp_call_progress()

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

Definition at line 1223 of file dsp.c.

1224{
1225 if (inf->frametype != AST_FRAME_VOICE) {
1226 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1227 return 0;
1228 }
1230 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames, %s not supported\n",
1232 return 0;
1233 }
1234 return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
1235}
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
Definition dsp.c:1081
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition format.c:334
int ast_format_cache_is_slinear(struct ast_format *format)
Determines if a format is one of the cached slin formats.
struct ast_format * format
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@239 data

References __ast_dsp_call_progress(), ast_format_cache_is_slinear(), ast_format_get_name(), AST_FRAME_VOICE, ast_log, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.

◆ ast_dsp_digitreset()

void ast_dsp_digitreset ( struct ast_dsp dsp)

Reset DTMF detector.

Definition at line 1814 of file dsp.c.

1815{
1816 int i;
1817
1818 dsp->dtmf_began = 0;
1819 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1821 /* Reinitialise the detector for the next block */
1822 for (i = 0; i < 6; i++) {
1823 goertzel_reset(&s->tone_out[i]);
1824 }
1825 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = 0;
1826 s->current_hit = 0;
1827 s->current_sample = 0;
1828 } else {
1830 /* Reinitialise the detector for the next block */
1831 for (i = 0; i < 4; i++) {
1832 goertzel_reset(&s->row_out[i]);
1833 goertzel_reset(&s->col_out[i]);
1834 }
1835 s->lasthit = 0;
1836 s->current_hit = 0;
1837 s->energy = 0.0;
1838 s->current_sample = 0;
1839 s->hits = 0;
1840 s->misses = 0;
1841 }
1842
1843 dsp->digit_state.digits[0] = '\0';
1844 dsp->digit_state.current_digits = 0;
1845}
static void goertzel_reset(goertzel_state_t *s)
Definition dsp.c:384
int dtmf_began
Definition dsp.c:431
goertzel_state_t row_out[DTMF_MATRIX_SIZE]
Definition dsp.c:285
goertzel_state_t col_out[DTMF_MATRIX_SIZE]
Definition dsp.c:286
int hits[5]
Definition dsp.c:300
goertzel_state_t tone_out[6]
Definition dsp.c:298
int current_hit
Definition dsp.c:299
int current_sample
Definition dsp.c:301

References dtmf_detect_state_t::col_out, digit_detect_state_t::current_digits, dtmf_detect_state_t::current_hit, mf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, mf_detect_state_t::current_sample, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MF, digit_detect_state_t::dtmf, ast_dsp::dtmf_began, dtmf_detect_state_t::energy, goertzel_reset(), dtmf_detect_state_t::hits, mf_detect_state_t::hits, dtmf_detect_state_t::lasthit, digit_detect_state_t::mf, dtmf_detect_state_t::misses, dtmf_detect_state_t::row_out, digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by analog_ss_thread(), mbl_new(), and my_dsp_reset_and_flush_digits().

◆ ast_dsp_free()

void ast_dsp_free ( struct ast_dsp dsp)

◆ ast_dsp_get_features()

int ast_dsp_get_features ( struct ast_dsp dsp)

Get features.

Definition at line 1781 of file dsp.c.

1782{
1783 return (dsp->features);
1784}

References ast_dsp::features.

Referenced by chan_pjsip_cng_tone_detected(), chan_pjsip_read_stream(), pjsip_acf_dtmf_mode_write(), and set_caps().

◆ ast_dsp_get_sample_rate()

unsigned int ast_dsp_get_sample_rate ( const struct ast_dsp dsp)

Retrieve the sample rate this DSP structure was created with.

Definition at line 1734 of file dsp.c.

1735{
1736 return dsp->sample_rate;
1737}

References ast_dsp::sample_rate.

◆ ast_dsp_get_tcount()

int ast_dsp_get_tcount ( struct ast_dsp dsp)

Get tcount (Threshold counter)

Definition at line 1920 of file dsp.c.

1921{
1922 return dsp->tcount;
1923}

References ast_dsp::tcount.

Referenced by dahdi_read(), detect_callback(), and scan_exec().

◆ ast_dsp_get_threshold_from_settings()

int ast_dsp_get_threshold_from_settings ( enum threshold  which)

Get silence threshold from dsp.conf.

Since
1.6.1

Definition at line 2013 of file dsp.c.

2014{
2015 return thresholds[which];
2016}

References thresholds.

Referenced by actual_load_config(), app_exec(), ast_record_review(), conf_rec_name(), conf_run(), do_waiting(), handle_recordfile(), load_config(), load_config(), record_exec(), setup_privacy_args(), and talk_detect_fn_write().

◆ ast_dsp_get_tstate()

int ast_dsp_get_tstate ( struct ast_dsp dsp)

Get tstate (Tone State)

Definition at line 1915 of file dsp.c.

1916{
1917 return dsp->tstate;
1918}

References ast_dsp::tstate.

Referenced by dahdi_read(), detect_callback(), and scan_exec().

◆ ast_dsp_new()

struct ast_dsp * ast_dsp_new ( void  )

◆ ast_dsp_new_with_rate()

struct ast_dsp * ast_dsp_new_with_rate ( unsigned int  sample_rate)

Allocates a new dsp with a specific internal sample rate used during processing.

Definition at line 1767 of file dsp.c.

1768{
1769 return __ast_dsp_new(sample_rate);
1770}

References __ast_dsp_new(), and ast_dsp::sample_rate.

Referenced by set_softmix_bridge_data(), and set_talk_detect().

◆ ast_dsp_noise()

int ast_dsp_noise ( struct ast_dsp dsp,
struct ast_frame f,
int *  totalnoise 
)

Process the audio frame for noise.

Since
1.6.1
Parameters
dspDSP processing audio media.
fAudio frame to process.
totalnoiseVariable to set to the total accumulated noise in ms seen by the DSP since the last silence.
Returns
Non-zero if the frame is silence.

Definition at line 1497 of file dsp.c.

1498{
1499 return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
1500}
static int ast_dsp_silence_noise_with_energy(struct ast_dsp *dsp, struct ast_frame *f, int *total, int *frames_energy, int noise)
Definition dsp.c:1441
#define NULL
Definition resample.c:96

References ast_dsp_silence_noise_with_energy(), and NULL.

◆ ast_dsp_process()

struct ast_frame * ast_dsp_process ( struct ast_channel chan,
struct ast_dsp dsp,
struct ast_frame af 
)

Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.

Definition at line 1503 of file dsp.c.

1504{
1505 int silence;
1506 int res;
1507 int digit = 0, fax_digit = 0, custom_freq_digit = 0;
1508 int x;
1509 short *shortdata;
1510 unsigned char *odata;
1511 int len;
1512 struct ast_frame *outf = NULL;
1513
1514 if (!af) {
1515 return NULL;
1516 }
1517 if (af->frametype != AST_FRAME_VOICE) {
1518 return af;
1519 }
1520
1521 odata = af->data.ptr;
1522 len = af->datalen;
1523 /* Make sure we have short data */
1525 shortdata = af->data.ptr;
1526 len = af->datalen / 2;
1528 shortdata = ast_alloca(af->datalen * 2);
1529 for (x = 0; x < len; x++) {
1530 shortdata[x] = AST_MULAW(odata[x]);
1531 }
1533 shortdata = ast_alloca(af->datalen * 2);
1534 for (x = 0; x < len; x++) {
1535 shortdata[x] = AST_ALAW(odata[x]);
1536 }
1537 } else {
1538 /* Display warning only once. Otherwise you would get hundreds of warnings every second */
1539 if (dsp->display_inband_dtmf_warning) {
1540 /* If DTMF is enabled for the DSP, try to be helpful and warn about that specifically,
1541 * otherwise emit a more generic message that covers all other cases. */
1543 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n",
1545 } else {
1546 ast_log(LOG_WARNING, "Can only do DSP on signed-linear, alaw or ulaw frames (%s not supported)\n",
1548 }
1549 }
1551 return af;
1552 }
1553
1554 /* Initially we do not want to mute anything */
1555 dsp->mute_fragments = 0;
1556
1557 /* Need to run the silence detection stuff for silence suppression and busy detection */
1559 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL, NULL);
1560 }
1561
1562 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
1563 memset(&dsp->f, 0, sizeof(dsp->f));
1564 dsp->f.frametype = AST_FRAME_NULL;
1565 ast_frfree(af);
1566 return ast_frisolate(&dsp->f);
1567 }
1570 memset(&dsp->f, 0, sizeof(dsp->f));
1573 ast_frfree(af);
1574 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", ast_channel_name(chan));
1575 return ast_frisolate(&dsp->f);
1576 }
1577
1578 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
1579 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1580 fax_digit = 'f';
1581 }
1582
1583 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
1584 fax_digit = 'e';
1585 }
1586 }
1587
1588 if ((dsp->features & DSP_FEATURE_FREQ_DETECT)) {
1589 if ((dsp->freqmode) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1590 custom_freq_digit = 'q';
1591 }
1592 }
1593
1595 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1596 digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1597 } else {
1598 digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1599 }
1600
1601 if (dsp->digit_state.current_digits) {
1602 int event = 0, event_len = 0;
1603 char event_digit = 0;
1604
1605 if (!dsp->dtmf_began) {
1606 /* We have not reported DTMF_BEGIN for anything yet */
1607
1609 event = AST_FRAME_DTMF_BEGIN;
1610 event_digit = dsp->digit_state.digits[0];
1611 }
1612 dsp->dtmf_began = 1;
1613
1614 } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
1615 /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
1617 event = AST_FRAME_DTMF_END;
1618 event_digit = dsp->digit_state.digits[0];
1619 event_len = dsp->digit_state.digitlen[0] * 1000 / dsp->sample_rate;
1620 }
1621 memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
1622 memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
1624 dsp->dtmf_began = 0;
1625
1626 if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
1627 /* Reset Busy Detector as we have some confirmed activity */
1628 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1629 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1630 ast_debug(1, "DTMF Detected - Reset busydetector\n");
1631 }
1632 }
1633
1634 if (event) {
1635 memset(&dsp->f, 0, sizeof(dsp->f));
1636 dsp->f.frametype = event;
1637 dsp->f.subclass.integer = event_digit;
1638 dsp->f.len = event_len;
1639 outf = &dsp->f;
1640 goto done;
1641 }
1642 }
1643 }
1644
1645 if (fax_digit) {
1646 /* Fax was detected - digit is either 'f' or 'e' */
1647
1648 memset(&dsp->f, 0, sizeof(dsp->f));
1649 dsp->f.frametype = AST_FRAME_DTMF;
1650 dsp->f.subclass.integer = fax_digit;
1651 outf = &dsp->f;
1652 goto done;
1653 }
1654
1655 if (custom_freq_digit) {
1656 /* Custom frequency was detected - digit is 'q' */
1657
1658 memset(&dsp->f, 0, sizeof(dsp->f));
1659 dsp->f.frametype = AST_FRAME_DTMF;
1660 dsp->f.subclass.integer = custom_freq_digit;
1661 outf = &dsp->f;
1662 goto done;
1663 }
1664
1665 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
1666 res = __ast_dsp_call_progress(dsp, shortdata, len);
1667 if (res) {
1668 switch (res) {
1669 case AST_CONTROL_ANSWER:
1670 case AST_CONTROL_BUSY:
1673 case AST_CONTROL_HANGUP:
1674 memset(&dsp->f, 0, sizeof(dsp->f));
1676 dsp->f.subclass.integer = res;
1677 dsp->f.src = "dsp_progress";
1678 if (chan) {
1679 ast_queue_frame(chan, &dsp->f);
1680 }
1681 break;
1682 default:
1683 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
1684 }
1685 }
1686 } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
1687 res = __ast_dsp_call_progress(dsp, shortdata, len);
1688 }
1689
1690done:
1691 /* Mute fragment of the frame */
1692 for (x = 0; x < dsp->mute_fragments; x++) {
1693 memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
1694 }
1695
1697 for (x = 0; x < len; x++) {
1698 odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
1699 }
1701 for (x = 0; x < len; x++) {
1702 odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
1703 }
1704 }
1705
1706 if (outf) {
1707 if (chan) {
1708 ast_queue_frame(chan, af);
1709 }
1710 ast_frfree(af);
1711 return ast_frisolate(outf);
1712 } else {
1713 return af;
1714 }
1715}
#define AST_LIN2A(a)
Definition alaw.h:50
#define AST_ALAW(a)
Definition alaw.h:84
char digit
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
const char * ast_channel_name(const struct ast_channel *chan)
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition channel.c:1170
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
@ AST_SOFTHANGUP_DEV
Definition channel.h:1141
static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
Definition dsp.c:575
static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
Definition dsp.c:907
static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
Definition dsp.c:699
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 ...
Definition dsp.c:1303
static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
Definition dsp.c:1237
#define DSP_FEATURE_WAITDIALTONE
Definition dsp.h:44
#define DSP_FEATURE_BUSY_DETECT
Definition dsp.h:27
#define DSP_DIGITMODE_NOQUELCH
Definition dsp.h:34
#define DSP_FEATURE_DIGIT_DETECT
Definition dsp.h:28
#define DSP_FEATURE_FAX_DETECT
Definition dsp.h:29
#define DSP_FAXMODE_DETECT_CED
Definition dsp.h:48
#define DSP_FEATURE_FREQ_DETECT
Definition dsp.h:45
#define DSP_DIGITMODE_RELAXDTMF
Definition dsp.h:37
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition format.h:36
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
struct ast_format * ast_format_alaw
Built-in cached alaw format.
#define AST_FRAME_DTMF
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frfree(fr)
@ AST_FRAME_DTMF_END
@ AST_FRAME_DTMF_BEGIN
@ AST_FRAME_CONTROL
fragment_t mute_data[5]
Definition dsp.c:436
int mute_fragments
Definition dsp.c:434
struct ast_frame f
Definition dsp.c:408
tone_detect_state_t ced_tone_state
Definition dsp.c:439
int freqmode
Definition dsp.c:430
tone_detect_state_t cng_tone_state
Definition dsp.c:438
Data structure associated with a single frame of data.
int digitlen[MAX_DTMF_DIGITS+1]
Definition dsp.c:308
int start
Definition dsp.c:390
int end
Definition dsp.c:391
int done
#define AST_MULAW(a)
Definition ulaw.h:85
#define AST_LIN2MU(a)
Definition ulaw.h:49

References __ast_dsp_call_progress(), __ast_dsp_silence_noise(), AST_ALAW, ast_alloca, ast_channel_name(), ast_channel_softhangup_internal_flag_add(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_debug, ast_dsp_busydetect(), ast_format_alaw, ast_format_cache_is_slinear(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_name(), ast_format_ulaw, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree, ast_frisolate, AST_LIN2A, AST_LIN2MU, ast_log, AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, digit, ast_dsp::digit_state, digit_detect_state_t::digitlen, ast_dsp::digitmode, digit_detect_state_t::digits, ast_dsp::display_inband_dtmf_warning, done, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_NOQUELCH, DSP_DIGITMODE_RELAXDTMF, DSP_FAXMODE_DETECT_CED, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_FREQ_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, DSP_FEATURE_WAITDIALTONE, ast_dsp::dtmf_began, dtmf_detect(), fragment_t::end, ast_dsp::f, ast_dsp::faxmode, ast_dsp::features, ast_frame_subclass::format, ast_frame::frametype, ast_dsp::freqmode, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_frame_subclass::integer, len(), ast_frame::len, LOG_WARNING, mf_detect(), ast_dsp::mute_data, ast_dsp::mute_fragments, NULL, ast_frame::ptr, ast_dsp::sample_rate, ast_frame::src, fragment_t::start, ast_frame::subclass, and tone_detect().

Referenced by chan_pjsip_read_stream(), dahdi_read(), detect_callback(), fax_detect_framehook(), mbl_read(), ooh323_rtp_read(), read_mf_digits(), read_sf_digits(), scan_exec(), and wait_exec().

◆ ast_dsp_prog_reset()

static void ast_dsp_prog_reset ( struct ast_dsp dsp)
static

Definition at line 1717 of file dsp.c.

1718{
1719 int max = 0;
1720 int x;
1721
1722 dsp->gsamp_size = modes[dsp->progmode].size;
1723 dsp->gsamps = 0;
1724 for (x = 0; x < FREQ_ARRAY_SIZE; x++) {
1725 if (modes[dsp->progmode].freqs[x]) {
1726 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->sample_rate);
1727 max = x + 1;
1728 }
1729 }
1730 dsp->freqcount = max;
1731 dsp->ringtimeout = 0;
1732}
static void goertzel_init(goertzel_state_t *s, float freq, unsigned int sample_rate)
Definition dsp.c:378
static struct progress modes[]
#define max(a, b)
Definition f2c.h:198
enum gsamp_size size
Definition dsp.c:118
int freqs[FREQ_ARRAY_SIZE]
Definition dsp.c:119

References FREQ_ARRAY_SIZE, ast_dsp::freqcount, progress::freqs, ast_dsp::freqs, goertzel_init(), ast_dsp::gsamp_size, ast_dsp::gsamps, max, modes, ast_dsp::progmode, ast_dsp::ringtimeout, ast_dsp::sample_rate, and progress::size.

Referenced by __ast_dsp_new(), and ast_dsp_set_call_progress_zone().

◆ ast_dsp_reset()

void ast_dsp_reset ( struct ast_dsp dsp)

Reset total silence count.

Definition at line 1847 of file dsp.c.

1848{
1849 int x;
1850
1851 dsp->totalsilence = 0;
1852 dsp->gsamps = 0;
1853 for (x = 0; x < 4; x++) {
1854 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1855 }
1856 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1857 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1858 dsp->ringtimeout = 0;
1859}

References ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::ringtimeout, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by debug_check_frame_for_silence().

◆ ast_dsp_set_busy_count()

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1797 of file dsp.c.

1798{
1799 if (cadences < 4) {
1800 cadences = 4;
1801 }
1802 if (cadences > DSP_HISTORY) {
1804 }
1805 dsp->busycount = cadences;
1806}
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition chan_dahdi.c:820

References ast_dsp::busycount, cadences, and DSP_HISTORY.

Referenced by dahdi_new().

◆ ast_dsp_set_busy_pattern()

void ast_dsp_set_busy_pattern ( struct ast_dsp dsp,
const struct ast_dsp_busy_pattern cadence 
)

Set expected lengths of the busy tone.

Definition at line 1808 of file dsp.c.

1809{
1810 dsp->busy_cadence = *cadence;
1811 ast_debug(1, "dsp busy pattern set to %d,%d,%d,%d\n", cadence->pattern[0], cadence->pattern[1], (cadence->length == 4) ? cadence->pattern[2] : 0, (cadence->length == 4) ? cadence->pattern[3] : 0);
1812}

References ast_debug, ast_dsp::busy_cadence, ast_dsp_busy_pattern::length, and ast_dsp_busy_pattern::pattern.

Referenced by dahdi_new().

◆ ast_dsp_set_call_progress_zone()

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1896 of file dsp.c.

1897{
1898 int x;
1899
1900 for (x = 0; x < ARRAY_LEN(aliases); x++) {
1901 if (!strcasecmp(aliases[x].name, zone)) {
1902 dsp->progmode = aliases[x].mode;
1903 ast_dsp_prog_reset(dsp);
1904 return 0;
1905 }
1906 }
1907 return -1;
1908}
static struct progalias aliases[]
static const char name[]
Definition format_mp3.c:68
enum prog_mode mode
Definition dsp.c:106
#define ARRAY_LEN(a)
Definition utils.h:703

References aliases, ARRAY_LEN, ast_dsp_prog_reset(), progalias::mode, name, and ast_dsp::progmode.

Referenced by dahdi_new(), and scan_exec().

◆ ast_dsp_set_digitmode()

int ast_dsp_set_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Version
1.6.1 renamed from ast_dsp_digitmode to ast_dsp_set_digitmode

Definition at line 1861 of file dsp.c.

1862{
1863 int new;
1864 int old;
1865
1868 if (old != new) {
1869 /* Must initialize structures if switching from MF to DTMF or vice-versa */
1871 }
1872 dsp->digitmode = digitmode;
1873 return 0;
1874}
#define DSP_DIGITMODE_MUTEMAX
Definition dsp.h:36
#define DSP_DIGITMODE_MUTECONF
Definition dsp.h:35

References ast_digit_detect_init(), ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, and ast_dsp::sample_rate.

Referenced by analog_ss_thread(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), mbl_load_device(), mkintf(), my_dsp_set_digitmode(), ooh323_new(), and read_mf_digits().

◆ ast_dsp_set_faxmode()

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1887 of file dsp.c.

1888{
1889 if (dsp->faxmode != faxmode) {
1890 dsp->faxmode = faxmode;
1892 }
1893 return 0;
1894}

References ast_fax_detect_init(), and ast_dsp::faxmode.

Referenced by fax_detect_new(), ooh323_new(), and scan_exec().

◆ ast_dsp_set_features()

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

◆ ast_dsp_set_freqmode()

int ast_dsp_set_freqmode ( struct ast_dsp dsp,
int  freq,
int  dur,
int  db,
int  squelch 
)

Set arbitrary frequency detection mode.

Definition at line 1876 of file dsp.c.

1877{
1878 if (freq > 0) {
1879 dsp->freqmode = 1;
1880 ast_freq_detect_init(dsp, freq, dur, db, squelch);
1881 } else {
1882 dsp->freqmode = 0;
1883 }
1884 return 0;
1885}
static sqlite3 * db
static void ast_freq_detect_init(struct ast_dsp *s, int freq, int dur, int db, int squelch)
Definition dsp.c:524

References ast_freq_detect_init(), db, and ast_dsp::freqmode.

Referenced by detect_write(), read_sf_digits(), scan_exec(), and wait_exec().

◆ ast_dsp_set_threshold()

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set the minimum average magnitude threshold to determine talking by the DSP.

Definition at line 1792 of file dsp.c.

1793{
1794 dsp->threshold = threshold;
1795}

References ast_dsp::threshold.

Referenced by __ast_play_and_record(), do_waiting(), fax_session_new(), handle_recordfile(), isAnsweringMachine(), record_exec(), set_softmix_bridge_data(), and set_talk_detect().

◆ ast_dsp_silence()

int ast_dsp_silence ( struct ast_dsp dsp,
struct ast_frame f,
int *  totalsilence 
)

Process the audio frame for silence.

Parameters
dspDSP processing audio media.
fAudio frame to process.
totalsilenceVariable to set to the total accumulated silence in ms seen by the DSP since the last noise.
Returns
Non-zero if the frame is silence.

Definition at line 1492 of file dsp.c.

1493{
1494 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
1495}

References ast_dsp_silence_noise_with_energy(), and NULL.

Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), debug_check_frame_for_silence(), handle_recordfile(), isAnsweringMachine(), record_exec(), and talk_detect_audiohook_cb().

◆ ast_dsp_silence_noise_with_energy()

static int ast_dsp_silence_noise_with_energy ( struct ast_dsp dsp,
struct ast_frame f,
int *  total,
int *  frames_energy,
int  noise 
)
static

Definition at line 1441 of file dsp.c.

1442{
1443 short *s;
1444 int len;
1445 int x;
1446 unsigned char *odata;
1447
1448 if (!f) {
1449 return 0;
1450 }
1451
1452 if (f->frametype != AST_FRAME_VOICE) {
1453 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
1454 return 0;
1455 }
1456
1458 s = f->data.ptr;
1459 len = f->datalen/2;
1460 } else {
1461 odata = f->data.ptr;
1462 len = f->datalen;
1464 s = ast_alloca(len * 2);
1465 for (x = 0; x < len; x++) {
1466 s[x] = AST_MULAW(odata[x]);
1467 }
1469 s = ast_alloca(len * 2);
1470 for (x = 0; x < len; x++) {
1471 s[x] = AST_ALAW(odata[x]);
1472 }
1473 } else {
1474 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames, %s not supported\n",
1476 return 0;
1477 }
1478 }
1479
1480 if (noise) {
1481 return __ast_dsp_silence_noise(dsp, s, len, NULL, total, frames_energy);
1482 } else {
1483 return __ast_dsp_silence_noise(dsp, s, len, total, NULL, frames_energy);
1484 }
1485}
static int total
Definition res_adsi.c:970

References __ast_dsp_silence_noise(), AST_ALAW, ast_alloca, ast_format_alaw, ast_format_cache_is_slinear(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_name(), ast_format_ulaw, AST_FRAME_VOICE, ast_log, AST_MULAW, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, len(), LOG_WARNING, NULL, ast_frame::ptr, ast_frame::subclass, and total.

Referenced by ast_dsp_noise(), ast_dsp_silence(), and ast_dsp_silence_with_energy().

◆ ast_dsp_silence_with_energy()

int ast_dsp_silence_with_energy ( struct ast_dsp dsp,
struct ast_frame f,
int *  totalsilence,
int *  frames_energy 
)

Process the audio frame for silence.

Parameters
dspDSP processing audio media.
fAudio frame to process.
totalsilenceVariable to set to the total accumulated silence in ms seen by the DSP since the last noise.
frames_energyVariable to set to the average energy of the samples in the frame.
Returns
Non-zero if the frame is silence.

Definition at line 1487 of file dsp.c.

1488{
1489 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
1490}

References ast_dsp_silence_noise_with_energy().

Referenced by softmix_bridge_write_voice().

◆ ast_dsp_was_muted()

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) happens when DSP code removes DTMF/MF/generic tones from the audio.

Since
1.6.1

Definition at line 1910 of file dsp.c.

1911{
1912 return (dsp->mute_fragments > 0);
1913}

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

◆ ast_dtmf_detect_init()

static void ast_dtmf_detect_init ( dtmf_detect_state_t s,
unsigned int  sample_rate 
)
static

Definition at line 533 of file dsp.c.

534{
535 int i;
536
537 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
538 goertzel_init(&s->row_out[i], dtmf_row[i], sample_rate);
539 goertzel_init(&s->col_out[i], dtmf_col[i], sample_rate);
540 }
541 s->lasthit = 0;
542 s->current_hit = 0;
543 s->energy = 0.0;
544 s->current_sample = 0;
545 s->hits = 0;
546 s->misses = 0;
547}
#define DTMF_MATRIX_SIZE
Definition dsp.c:168
static const float dtmf_row[]
Definition dsp.c:319
static const float dtmf_col[]
Definition dsp.c:322

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, dtmf_col, DTMF_MATRIX_SIZE, dtmf_row, dtmf_detect_state_t::energy, goertzel_init(), dtmf_detect_state_t::hits, dtmf_detect_state_t::lasthit, dtmf_detect_state_t::misses, and dtmf_detect_state_t::row_out.

Referenced by ast_digit_detect_init().

◆ ast_fax_detect_init()

static void ast_fax_detect_init ( struct ast_dsp s)
static

Definition at line 513 of file dsp.c.

514{
518 s->cng_tone_state.squelch = 1;
519 s->ced_tone_state.squelch = 1;
520 }
521
522}
static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, int amp, unsigned int sample_rate)
Definition dsp.c:452
#define FAX_TONE_CED_DB
Definition dsp.c:221
#define FAX_TONE_CNG_FREQ
Definition dsp.c:211
#define FAX_TONE_CED_DURATION
Definition dsp.c:220
#define FAX_TONE_CNG_DB
Definition dsp.c:213
#define FAX_TONE_CED_FREQ
Definition dsp.c:219
#define FAX_TONE_CNG_DURATION
Definition dsp.c:212
#define DSP_FAXMODE_DETECT_SQUELCH
Definition dsp.h:49

References ast_tone_detect_init(), ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, DSP_FAXMODE_DETECT_SQUELCH, FAX_TONE_CED_DB, FAX_TONE_CED_DURATION, FAX_TONE_CED_FREQ, FAX_TONE_CNG_DB, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_FREQ, ast_dsp::faxmode, ast_dsp::sample_rate, and tone_detect_state_t::squelch.

Referenced by __ast_dsp_new(), and ast_dsp_set_faxmode().

◆ ast_freq_detect_init()

static void ast_freq_detect_init ( struct ast_dsp s,
int  freq,
int  dur,
int  db,
int  squelch 
)
static

Definition at line 524 of file dsp.c.

525{
526 /* we can conveniently just use one of the two fax tone states */
528 if (s->freqmode & squelch) {
529 s->cng_tone_state.squelch = 1;
530 }
531}

References ast_tone_detect_init(), ast_dsp::cng_tone_state, db, ast_dsp::freqmode, ast_dsp::sample_rate, and tone_detect_state_t::squelch.

Referenced by ast_dsp_set_freqmode().

◆ ast_mf_detect_init()

static void ast_mf_detect_init ( mf_detect_state_t s,
unsigned int  sample_rate 
)
static

Definition at line 549 of file dsp.c.

550{
551 int i;
552
553 for (i = 0; i < 6; i++) {
554 goertzel_init(&s->tone_out[i], mf_tones[i], sample_rate);
555 }
556 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
557 s->current_sample = 0;
558 s->current_hit = 0;
559}
static const float mf_tones[]
Definition dsp.c:325

References mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, goertzel_init(), mf_detect_state_t::hits, mf_tones, and mf_detect_state_t::tone_out.

Referenced by ast_digit_detect_init().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 2483 of file dsp.c.

◆ ast_tone_detect_init()

static void ast_tone_detect_init ( tone_detect_state_t s,
int  freq,
int  duration,
int  amp,
unsigned int  sample_rate 
)
static

Definition at line 452 of file dsp.c.

453{
454 int duration_samples;
455 float x;
456 int periods_in_block;
457
458 s->freq = freq;
459
460 /* Desired tone duration in samples */
461 duration_samples = duration * sample_rate / 1000;
462 /* We want to allow 10% deviation of tone duration */
463 duration_samples = duration_samples * 9 / 10;
464
465 /* If we want to remove tone, it is important to have block size not
466 to exceed frame size. Otherwise by the moment tone is detected it is too late
467 to squelch it from previous frames. Block size is 20ms at the given sample rate.*/
468 s->block_size = (20 * sample_rate) / 1000;
469
470 periods_in_block = s->block_size * freq / sample_rate;
471
472 /* Make sure we will have at least 5 periods at target frequency for analysis.
473 This may make block larger than expected packet and will make squelching impossible
474 but at least we will be detecting the tone */
475 if (periods_in_block < 5) {
476 periods_in_block = 5;
477 }
478
479 /* Now calculate final block size. It will contain integer number of periods */
480 s->block_size = periods_in_block * sample_rate / freq;
481
482 /* tone_detect is generally only used to detect fax tones and we
483 do not need squelching the fax tones */
484 s->squelch = 0;
485
486 /* Account for the first and the last block to be incomplete
487 and thus no tone will be detected in them */
488 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size;
489
490 goertzel_init(&s->tone, freq, sample_rate);
491
493 s->hit_count = 0;
494 s->last_hit = 0;
495 s->energy = 0.0;
496
497 /* We want tone energy to be amp decibels above the rest of the signal (the noise).
498 According to Parseval's theorem the energy computed in time domain equals to energy
499 computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result)
500 from the energy in the time domain we will get energy of the remaining signal (without the tone
501 we are detecting). We will be checking that
502 10*log(Ew / (Et - Ew)) > amp
503 Calculate threshold so that we will be actually checking
504 Ew > Et * threshold
505 */
506
507 x = pow(10.0, amp / 10.0);
508 s->threshold = x / (x + 1);
509
510 ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required);
511}
float threshold
Definition dsp.c:276
goertzel_state_t tone
Definition dsp.c:270
int samples_pending
Definition dsp.c:272

References ast_debug, tone_detect_state_t::block_size, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_init(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, tone_detect_state_t::threshold, and tone_detect_state_t::tone.

Referenced by ast_fax_detect_init(), and ast_freq_detect_init().

◆ dtmf_detect()

static int dtmf_detect ( struct ast_dsp dsp,
digit_detect_state_t s,
int16_t  amp[],
int  samples,
int  squelch,
int  relax 
)
static

Definition at line 699 of file dsp.c.

700{
701 float row_energy[DTMF_MATRIX_SIZE];
702 float col_energy[DTMF_MATRIX_SIZE];
703 int i;
704 int j;
705 int sample;
706 short samp;
707 int best_row;
708 int best_col;
709 int hit;
710 int limit;
711 fragment_t mute = {0, 0};
712
713 if (squelch && s->td.dtmf.mute_samples > 0) {
714 mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples;
715 s->td.dtmf.mute_samples -= mute.end;
716 }
717
718 hit = 0;
719 for (sample = 0; sample < samples; sample = limit) {
720 /* DTMF_GSIZE is optimised to meet the DTMF specs. */
721 if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) {
722 limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample);
723 } else {
724 limit = samples;
725 }
726 /* The following unrolled loop takes only 35% (rough estimate) of the
727 time of a rolled loop on the machine on which it was developed */
728 for (j = sample; j < limit; j++) {
729 samp = amp[j];
730 s->td.dtmf.energy += (int32_t) samp * (int32_t) samp;
731 /* With GCC 2.95, the following unrolled code seems to take about 35%
732 (rough estimate) as long as a neat little 0-3 loop */
733 goertzel_sample(s->td.dtmf.row_out, samp);
734 goertzel_sample(s->td.dtmf.col_out, samp);
735 goertzel_sample(s->td.dtmf.row_out + 1, samp);
736 goertzel_sample(s->td.dtmf.col_out + 1, samp);
737 goertzel_sample(s->td.dtmf.row_out + 2, samp);
738 goertzel_sample(s->td.dtmf.col_out + 2, samp);
739 goertzel_sample(s->td.dtmf.row_out + 3, samp);
740 goertzel_sample(s->td.dtmf.col_out + 3, samp);
741 /* go up to DTMF_MATRIX_SIZE - 1 */
742 }
743 s->td.dtmf.current_sample += (limit - sample);
744 if (s->td.dtmf.current_sample < DTMF_GSIZE) {
745 continue;
746 }
747 /* We are at the end of a DTMF detection block */
748 /* Find the peak row and the peak column */
749 row_energy[0] = goertzel_result(&s->td.dtmf.row_out[0]);
750 col_energy[0] = goertzel_result(&s->td.dtmf.col_out[0]);
751
752 for (best_row = best_col = 0, i = 1; i < DTMF_MATRIX_SIZE; i++) {
753 row_energy[i] = goertzel_result(&s->td.dtmf.row_out[i]);
754 if (row_energy[i] > row_energy[best_row]) {
755 best_row = i;
756 }
757 col_energy[i] = goertzel_result(&s->td.dtmf.col_out[i]);
758 if (col_energy[i] > col_energy[best_col]) {
759 best_col = i;
760 }
761 }
762 ast_debug(10, "DTMF best '%c' Erow=%.4E Ecol=%.4E Erc=%.4E Et=%.4E\n",
763 dtmf_positions[(best_row << 2) + best_col],
764 row_energy[best_row], col_energy[best_col],
765 row_energy[best_row] + col_energy[best_col], s->td.dtmf.energy);
766 hit = 0;
767 /* Basic signal level test and the twist test */
768 if (row_energy[best_row] >= DTMF_THRESHOLD &&
769 col_energy[best_col] >= DTMF_THRESHOLD &&
770 col_energy[best_col] < row_energy[best_row] * (relax ? relax_dtmf_reverse_twist : dtmf_reverse_twist) &&
771 row_energy[best_row] < col_energy[best_col] * (relax ? relax_dtmf_normal_twist : dtmf_normal_twist)) {
772 /* Relative peak test */
773 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
774 if ((i != best_col &&
775 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
776 (i != best_row
777 && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
778 break;
779 }
780 }
781 /* ... and fraction of total energy test */
782 if (i >= DTMF_MATRIX_SIZE &&
783 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
784 /* Got a hit */
785 hit = dtmf_positions[(best_row << 2) + best_col];
786 ast_debug(10, "DTMF hit '%c'\n", hit);
787 }
788 }
789
790/*
791 * Adapted from ETSI ES 201 235-3 V1.3.1 (2006-03)
792 * (40ms reference is tunable with hits_to_begin and misses_to_end)
793 * each hit/miss is 12.75ms with DTMF_GSIZE at 102
794 *
795 * Character recognition: When not DRC *(1) and then
796 * Shall exist VSC > 40 ms (hits_to_begin)
797 * May exist 20 ms <= VSC <= 40 ms
798 * Shall not exist VSC < 20 ms
799 *
800 * Character recognition: When DRC and then
801 * Shall cease Not VSC > 40 ms (misses_to_end)
802 * May cease 20 ms >= Not VSC >= 40 ms
803 * Shall not cease Not VSC < 20 ms
804 *
805 * *(1) or optionally a different digit recognition condition
806 *
807 * Legend: VSC The continuous existence of a valid signal condition.
808 * Not VSC The continuous non-existence of valid signal condition.
809 * DRC The existence of digit recognition condition.
810 * Not DRC The non-existence of digit recognition condition.
811 */
812
813/*
814 * Example: hits_to_begin=2 misses_to_end=3
815 * -------A last_hit=A hits=0&1
816 * ------AA hits=2 current_hit=A misses=0 BEGIN A
817 * -----AA- misses=1 last_hit=' ' hits=0
818 * ----AA-- misses=2
819 * ---AA--- misses=3 current_hit=' ' END A
820 * --AA---B last_hit=B hits=0&1
821 * -AA---BC last_hit=C hits=0&1
822 * AA---BCC hits=2 current_hit=C misses=0 BEGIN C
823 * A---BCC- misses=1 last_hit=' ' hits=0
824 * ---BCC-C misses=0 last_hit=C hits=0&1
825 * --BCC-CC misses=0
826 *
827 * Example: hits_to_begin=3 misses_to_end=2
828 * -------A last_hit=A hits=0&1
829 * ------AA hits=2
830 * -----AAA hits=3 current_hit=A misses=0 BEGIN A
831 * ----AAAB misses=1 last_hit=B hits=0&1
832 * ---AAABB misses=2 current_hit=' ' hits=2 END A
833 * --AAABBB hits=3 current_hit=B misses=0 BEGIN B
834 * -AAABBBB misses=0
835 *
836 * Example: hits_to_begin=2 misses_to_end=2
837 * -------A last_hit=A hits=0&1
838 * ------AA hits=2 current_hit=A misses=0 BEGIN A
839 * -----AAB misses=1 hits=0&1
840 * ----AABB misses=2 current_hit=' ' hits=2 current_hit=B misses=0 BEGIN B
841 * ---AABBB misses=0
842 */
843
844 if (s->td.dtmf.current_hit) {
845 /* We are in the middle of a digit already */
846 if (hit != s->td.dtmf.current_hit) {
847 s->td.dtmf.misses++;
848 if (s->td.dtmf.misses == dtmf_misses_to_end) {
849 /* There were enough misses to consider digit ended */
850 s->td.dtmf.current_hit = 0;
851 }
852 } else {
853 s->td.dtmf.misses = 0;
854 /* Current hit was same as last, so increment digit duration (of last digit) */
855 s->digitlen[s->current_digits - 1] += DTMF_GSIZE;
856 }
857 }
858
859 /* Look for a start of a new digit no matter if we are already in the middle of some
860 digit or not. This is because hits_to_begin may be smaller than misses_to_end
861 and we may find begin of new digit before we consider last one ended. */
862
863 if (hit != s->td.dtmf.lasthit) {
864 s->td.dtmf.lasthit = hit;
865 s->td.dtmf.hits = 0;
866 }
867 if (hit && hit != s->td.dtmf.current_hit) {
868 s->td.dtmf.hits++;
869 if (s->td.dtmf.hits == dtmf_hits_to_begin) {
870 store_digit(s, hit);
872 s->td.dtmf.current_hit = hit;
873 s->td.dtmf.misses = 0;
874 }
875 }
876
877 /* If we had a hit in this block, include it into mute fragment */
878 if (squelch && hit) {
879 if (mute.end < sample - DTMF_GSIZE) {
880 /* There is a gap between fragments */
881 mute_fragment(dsp, &mute);
882 mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0;
883 }
884 mute.end = limit + DTMF_GSIZE;
885 }
886
887 /* Reinitialise the detector for the next block */
888 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
891 }
892 s->td.dtmf.energy = 0.0;
893 s->td.dtmf.current_sample = 0;
894 }
895
896 if (squelch && mute.end) {
897 if (mute.end > samples) {
898 s->td.dtmf.mute_samples = mute.end - samples;
899 mute.end = samples;
900 }
901 mute_fragment(dsp, &mute);
902 }
903
904 return (s->td.dtmf.current_hit); /* return the debounced hit */
905}
#define DTMF_TO_TOTAL_ENERGY
Definition dsp.c:198
static const char dtmf_positions[]
Definition dsp.c:328
#define DTMF_THRESHOLD
Definition dsp.c:182
#define DTMF_RELATIVE_PEAK_COL
Definition dsp.c:197
#define DTMF_GSIZE
Definition dsp.c:229
static void mute_fragment(struct ast_dsp *dsp, fragment_t *fragment)
Definition dsp.c:442
#define DTMF_RELATIVE_PEAK_ROW
Definition dsp.c:196
static void store_digit(digit_detect_state_t *s, char digit)
Definition dsp.c:686

References ast_debug, dtmf_detect_state_t::col_out, digit_detect_state_t::current_digits, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, digit_detect_state_t::digitlen, digit_detect_state_t::dtmf, DTMF_GSIZE, dtmf_hits_to_begin, DTMF_MATRIX_SIZE, dtmf_misses_to_end, dtmf_normal_twist, dtmf_positions, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, dtmf_reverse_twist, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, fragment_t::end, dtmf_detect_state_t::energy, goertzel_reset(), goertzel_result(), goertzel_sample(), dtmf_detect_state_t::hits, dtmf_detect_state_t::lasthit, dtmf_detect_state_t::misses, mute_fragment(), dtmf_detect_state_t::mute_samples, relax_dtmf_normal_twist, relax_dtmf_reverse_twist, dtmf_detect_state_t::row_out, fragment_t::start, store_digit(), and digit_detect_state_t::td.

Referenced by ast_dsp_process().

◆ goertzel_init()

static void goertzel_init ( goertzel_state_t s,
float  freq,
unsigned int  sample_rate 
)
inlinestatic

Definition at line 378 of file dsp.c.

379{
380 s->v2 = s->v3 = s->chunky = 0;
381 s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / sample_rate));
382}
unsigned int cos
Definition chan_iax2.c:380
#define M_PI
Definition resample.c:83

References goertzel_state_t::chunky, cos, goertzel_state_t::fac, M_PI, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_prog_reset(), ast_dtmf_detect_init(), ast_mf_detect_init(), and ast_tone_detect_init().

◆ goertzel_reset()

static void goertzel_reset ( goertzel_state_t s)
inlinestatic

Definition at line 384 of file dsp.c.

385{
386 s->v2 = s->v3 = s->chunky = 0;
387}

References goertzel_state_t::chunky, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_digitreset(), dtmf_detect(), mf_detect(), and tone_detect().

◆ goertzel_result()

static float goertzel_result ( goertzel_state_t s)
inlinestatic

Definition at line 364 of file dsp.c.

365{
367
368 r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
369 r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
370 /*
371 * We have to double the exponent because we multiplied the
372 * previous sample calculation values together.
373 */
374 r.power = s->chunky * 2;
375 return (float)r.value * (float)(1 << r.power);
376}

References goertzel_state_t::chunky, goertzel_state_t::fac, goertzel_result_t::power, goertzel_state_t::v2, goertzel_state_t::v3, and goertzel_result_t::value.

Referenced by __ast_dsp_call_progress(), dtmf_detect(), mf_detect(), and tone_detect().

◆ goertzel_sample()

static void goertzel_sample ( goertzel_state_t s,
short  sample 
)
inlinestatic

Definition at line 338 of file dsp.c.

339{
340 int v1;
341
342 /*
343 * Shift previous values so
344 * v1 is previous previous value
345 * v2 is previous value
346 * until the new v3 is calculated.
347 */
348 v1 = s->v2;
349 s->v2 = s->v3;
350
351 /* Discard the binary fraction introduced by s->fac */
352 s->v3 = (s->fac * s->v2) >> 15;
353 /* Scale sample to match previous values */
354 s->v3 = s->v3 - v1 + (sample >> s->chunky);
355
356 if (abs(s->v3) > (1 << 15)) {
357 /* The result is now too large so increase the chunky power. */
358 s->chunky++;
359 s->v3 = s->v3 >> 1;
360 s->v2 = s->v2 >> 1;
361 }
362}

References abs, goertzel_state_t::chunky, goertzel_state_t::fac, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by __ast_dsp_call_progress(), dtmf_detect(), mf_detect(), and tone_detect().

◆ load_module()

static int load_module ( void  )
static

Definition at line 2459 of file dsp.c.

2460{
2461 if (_dsp_init(0)) {
2463 }
2464
2465 AST_TEST_REGISTER(test_dsp_fax_detect);
2466 AST_TEST_REGISTER(test_dsp_dtmf_detect);
2467
2469}
static int _dsp_init(int reload)
Definition dsp.c:1925
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
#define AST_TEST_REGISTER(cb)
Definition test.h:127

References _dsp_init(), AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

◆ mf_detect()

static int mf_detect ( struct ast_dsp dsp,
digit_detect_state_t s,
int16_t  amp[],
int  samples,
int  squelch,
int  relax 
)
static

Definition at line 907 of file dsp.c.

909{
910 float energy[6];
911 int best;
912 int second_best;
913 int i;
914 int j;
915 int sample;
916 short samp;
917 int hit;
918 int limit;
919 fragment_t mute = {0, 0};
920
921 if (squelch && s->td.mf.mute_samples > 0) {
922 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
923 s->td.mf.mute_samples -= mute.end;
924 }
925
926 hit = 0;
927 for (sample = 0; sample < samples; sample = limit) {
928 /* 80 is optimised to meet the MF specs. */
929 /* XXX So then why is MF_GSIZE defined as 120? */
930 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) {
931 limit = sample + (MF_GSIZE - s->td.mf.current_sample);
932 } else {
933 limit = samples;
934 }
935 /* The following unrolled loop takes only 35% (rough estimate) of the
936 time of a rolled loop on the machine on which it was developed */
937 for (j = sample; j < limit; j++) {
938 /* With GCC 2.95, the following unrolled code seems to take about 35%
939 (rough estimate) as long as a neat little 0-3 loop */
940 samp = amp[j];
941 goertzel_sample(s->td.mf.tone_out, samp);
942 goertzel_sample(s->td.mf.tone_out + 1, samp);
943 goertzel_sample(s->td.mf.tone_out + 2, samp);
944 goertzel_sample(s->td.mf.tone_out + 3, samp);
945 goertzel_sample(s->td.mf.tone_out + 4, samp);
946 goertzel_sample(s->td.mf.tone_out + 5, samp);
947 }
948 s->td.mf.current_sample += (limit - sample);
949 if (s->td.mf.current_sample < MF_GSIZE) {
950 continue;
951 }
952 /* We're at the end of an MF detection block. */
953 /* Find the two highest energies. The spec says to look for
954 two tones and two tones only. Taking this literally -ie
955 only two tones pass the minimum threshold - doesn't work
956 well. The sinc function mess, due to rectangular windowing
957 ensure that! Find the two highest energies and ensure they
958 are considerably stronger than any of the others. */
959 energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
960 energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
961 if (energy[0] > energy[1]) {
962 best = 0;
963 second_best = 1;
964 } else {
965 best = 1;
966 second_best = 0;
967 }
968 /*endif*/
969 for (i = 2; i < 6; i++) {
970 energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
971 if (energy[i] >= energy[best]) {
972 second_best = best;
973 best = i;
974 } else if (energy[i] >= energy[second_best]) {
975 second_best = i;
976 }
977 }
978 /* Basic signal level and twist tests */
979 hit = 0;
980 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
981 && energy[best] < energy[second_best]*BELL_MF_TWIST
982 && energy[best] * BELL_MF_TWIST > energy[second_best]) {
983 /* Relative peak test */
984 hit = -1;
985 for (i = 0; i < 6; i++) {
986 if (i != best && i != second_best) {
987 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
988 /* The best two are not clearly the best */
989 hit = 0;
990 break;
991 }
992 }
993 }
994 }
995 if (hit) {
996 /* Get the values into ascending order */
997 if (second_best < best) {
998 i = best;
999 best = second_best;
1000 second_best = i;
1001 }
1002 best = best * 5 + second_best - 1;
1003 hit = bell_mf_positions[best];
1004 /* Look for two successive similar results */
1005 /* The logic in the next test is:
1006 For KP we need 4 successive identical clean detects, with
1007 two blocks of something different preceeding it. For anything
1008 else we need two successive identical clean detects, with
1009 two blocks of something different preceeding it. */
1010 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
1011 ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
1012 (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] &&
1013 hit != s->td.mf.hits[0]))) {
1014 store_digit(s, hit);
1015 }
1016 }
1017
1018
1019 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
1020 /* Two successive block without a hit terminate current digit */
1021 s->td.mf.current_hit = 0;
1022 }
1023
1024 s->td.mf.hits[0] = s->td.mf.hits[1];
1025 s->td.mf.hits[1] = s->td.mf.hits[2];
1026 s->td.mf.hits[2] = s->td.mf.hits[3];
1027 s->td.mf.hits[3] = s->td.mf.hits[4];
1028 s->td.mf.hits[4] = hit;
1029
1030 /* If we had a hit in this block, include it into mute fragment */
1031 if (squelch && hit) {
1032 if (mute.end < sample - MF_GSIZE) {
1033 /* There is a gap between fragments */
1034 mute_fragment(dsp, &mute);
1035 mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0;
1036 }
1037 mute.end = limit + MF_GSIZE;
1038 }
1039
1040 /* Reinitialise the detector for the next block */
1041 for (i = 0; i < 6; i++) {
1042 goertzel_reset(&s->td.mf.tone_out[i]);
1043 }
1044 s->td.mf.current_sample = 0;
1045 }
1046
1047 if (squelch && mute.end) {
1048 if (mute.end > samples) {
1049 s->td.mf.mute_samples = mute.end - samples;
1050 mute.end = samples;
1051 }
1052 mute_fragment(dsp, &mute);
1053 }
1054
1055 return (s->td.mf.current_hit); /* return the debounced hit */
1056}
#define BELL_MF_THRESHOLD
Definition dsp.c:200
#define BELL_MF_RELATIVE_PEAK
Definition dsp.c:202
static const char bell_mf_positions[]
Definition dsp.c:329
#define BELL_MF_TWIST
Definition dsp.c:201
#define MF_GSIZE
Definition dsp.c:226
int mute_samples
Definition dsp.c:302

References bell_mf_positions, BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, mf_detect_state_t::current_hit, mf_detect_state_t::current_sample, fragment_t::end, goertzel_reset(), goertzel_result(), goertzel_sample(), mf_detect_state_t::hits, digit_detect_state_t::mf, MF_GSIZE, mute_fragment(), mf_detect_state_t::mute_samples, fragment_t::start, store_digit(), digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by ast_dsp_process().

◆ mute_fragment()

static void mute_fragment ( struct ast_dsp dsp,
fragment_t fragment 
)
static

Definition at line 442 of file dsp.c.

443{
444 if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
445 ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
446 return;
447 }
448
449 dsp->mute_data[dsp->mute_fragments++] = *fragment;
450}
#define LOG_ERROR

References ARRAY_LEN, ast_log, LOG_ERROR, ast_dsp::mute_data, and ast_dsp::mute_fragments.

Referenced by dtmf_detect(), mf_detect(), and tone_detect().

◆ pair_there()

static int pair_there ( float  p1,
float  p2,
float  i1,
float  i2,
float  e 
)
inlinestatic

Definition at line 1058 of file dsp.c.

1059{
1060 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
1061 /* Make sure absolute levels are high enough */
1062 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
1063 return 0;
1064 }
1065 /* Amplify ignored stuff */
1066 i2 *= TONE_THRESH;
1067 i1 *= TONE_THRESH;
1068 e *= TONE_THRESH;
1069 /* Check first tone */
1070 if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
1071 return 0;
1072 }
1073 /* And second */
1074 if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
1075 return 0;
1076 }
1077 /* Guess it's there... */
1078 return 1;
1079}

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2471 of file dsp.c.

2472{
2473 return _dsp_init(1);
2474}

References _dsp_init().

◆ store_digit()

static void store_digit ( digit_detect_state_t s,
char  digit 
)
static

Definition at line 686 of file dsp.c.

687{
688 s->detected_digits++;
690 s->digitlen[s->current_digits] = 0;
691 s->digits[s->current_digits++] = digit;
692 s->digits[s->current_digits] = '\0';
693 } else {
694 ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
695 s->lost_digits++;
696 }
697}
#define MAX_DTMF_DIGITS
Definition dsp.c:166

References ast_log, digit_detect_state_t::current_digits, digit_detect_state_t::detected_digits, digit, digit_detect_state_t::digitlen, digit_detect_state_t::digits, LOG_WARNING, digit_detect_state_t::lost_digits, and MAX_DTMF_DIGITS.

Referenced by dtmf_detect(), and mf_detect().

◆ tone_detect()

static int tone_detect ( struct ast_dsp dsp,
tone_detect_state_t s,
int16_t *  amp,
int  samples 
)
static

Definition at line 575 of file dsp.c.

576{
577 float tone_energy;
578 int i;
579 int hit = 0;
580 int limit;
581 int res = 0;
582 int16_t *ptr;
583 short samp;
584 int start, end;
585 fragment_t mute = {0, 0};
586
587 if (s->squelch && s->mute_samples > 0) {
588 mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
589 s->mute_samples -= mute.end;
590 }
591
592 for (start = 0; start < samples; start = end) {
593 /* Process in blocks. */
594 limit = samples - start;
595 if (limit > s->samples_pending) {
596 limit = s->samples_pending;
597 }
598 end = start + limit;
599
600 for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
601 samp = *ptr;
602 /* signed 32 bit int should be enough to square any possible signed 16 bit value */
603 s->energy += (int32_t) samp * (int32_t) samp;
604
605 goertzel_sample(&s->tone, samp);
606 }
607
608 s->samples_pending -= limit;
609
610 if (s->samples_pending) {
611 /* Finished incomplete (last) block */
612 break;
613 }
614
615 tone_energy = goertzel_result(&s->tone);
616
617 /* Scale to make comparable */
618 tone_energy *= 2.0;
619 s->energy *= s->block_size;
620
621 /* Add 1 to hit_count when logging, since it doesn't get incremented until later in the loop. */
622 if (TONE_THRESHOLD <= tone_energy
623 && tone_energy > s->energy * s->threshold) {
624 ast_debug(9, "%d Hz tone Hit! [%d/%d] Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count + 1, s->hits_required, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
625 hit = 1;
626 } else {
627 ast_debug(10, "%d Hz tone [%d/%d] Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, s->hits_required, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
628 hit = 0;
629 }
630
631 if (s->hit_count) {
632 s->hit_count++;
633 }
634
635 if (hit == s->last_hit) {
636 if (!hit) {
637 /* Two successive misses. Tone ended */
638 if (s->hit_count) {
639 ast_debug(9, "Partial detect expired after %d/%d hits\n", s->hit_count, s->hits_required);
640 }
641 s->hit_count = 0;
642 } else if (!s->hit_count) {
643 s->hit_count++;
644 }
645 }
646
647 if (s->hit_count == s->hits_required) {
648 ast_debug(1, "%d Hz tone detected\n", s->freq);
649 res = 1;
650 }
651
652 s->last_hit = hit;
653
654 /* If we had a hit in this block, include it into mute fragment */
655 if (s->squelch && hit) {
656 if (mute.end < start - s->block_size) {
657 /* There is a gap between fragments */
658 mute_fragment(dsp, &mute);
659 mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
660 }
661 mute.end = end + s->block_size;
662 }
663
664 /* Reinitialise the detector for the next block */
665 /* Reset for the next block */
666 goertzel_reset(&s->tone);
667
668 /* Advance to the next block */
669 s->energy = 0.0;
671
672 amp += limit;
673 }
674
675 if (s->squelch && mute.end) {
676 if (mute.end > samples) {
677 s->mute_samples = mute.end - samples;
678 mute.end = samples;
679 }
680 mute_fragment(dsp, &mute);
681 }
682
683 return res;
684}
#define TONE_THRESHOLD
Definition dsp.c:183
char * end
Definition eagi_proxy.c:73

References ast_debug, tone_detect_state_t::block_size, end, fragment_t::end, tone_detect_state_t::energy, tone_detect_state_t::freq, goertzel_reset(), goertzel_result(), goertzel_sample(), tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, tone_detect_state_t::last_hit, mute_fragment(), tone_detect_state_t::mute_samples, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, fragment_t::start, tone_detect_state_t::threshold, tone_detect_state_t::tone, and TONE_THRESHOLD.

Referenced by ast_dsp_process().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2451 of file dsp.c.

2452{
2453 AST_TEST_UNREGISTER(test_dsp_fax_detect);
2454 AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
2455
2456 return 0;
2457}
#define AST_TEST_UNREGISTER(cb)
Definition test.h:128

References AST_TEST_UNREGISTER.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "DSP" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
static

Definition at line 2483 of file dsp.c.

◆ aliases

struct progalias aliases[]
static

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2483 of file dsp.c.

◆ bell_mf_positions

const char bell_mf_positions[] = "1247C-358A--69*---0B----#"
static

Definition at line 329 of file dsp.c.

Referenced by mf_detect().

◆ DEFAULT_SILENCE_THRESHOLD

const int DEFAULT_SILENCE_THRESHOLD = 256
static

The default silence threshold we will use if an alternate configured value is not present or is invalid.

Definition at line 245 of file dsp.c.

Referenced by _dsp_init().

◆ dtmf_col

const float dtmf_col[]
static
Initial value:
= {
1209.0, 1336.0, 1477.0, 1633.0
}

Definition at line 322 of file dsp.c.

322 {
323 1209.0, 1336.0, 1477.0, 1633.0
324};

Referenced by ast_dtmf_detect_init().

◆ dtmf_hits_to_begin

int dtmf_hits_to_begin
static

Definition at line 335 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_misses_to_end

int dtmf_misses_to_end
static

Definition at line 336 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_normal_twist

float dtmf_normal_twist
static

Definition at line 331 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_positions

const char dtmf_positions[] = "123A" "456B" "789C" "*0#D"
static

Definition at line 328 of file dsp.c.

Referenced by dtmf_detect().

◆ dtmf_reverse_twist

float dtmf_reverse_twist
static

Definition at line 332 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_row

const float dtmf_row[]
static
Initial value:
= {
697.0, 770.0, 852.0, 941.0
}

Definition at line 319 of file dsp.c.

319 {
320 697.0, 770.0, 852.0, 941.0
321};

Referenced by ast_dtmf_detect_init().

◆ mf_tones

const float mf_tones[]
static
Initial value:
= {
700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
}

Definition at line 325 of file dsp.c.

325 {
326 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
327};

Referenced by ast_mf_detect_init(), and ast_senddigit_mf_begin().

◆ modes

struct progress modes[]
static
Initial value:
= {
{ GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } },
{ GSAMP_SIZE_CR, { 425 } },
{ GSAMP_SIZE_UK, { 350, 400, 440 } },
}

Referenced by ast_dsp_prog_reset().

◆ relax_dtmf_normal_twist

float relax_dtmf_normal_twist
static

Definition at line 333 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ relax_dtmf_reverse_twist

float relax_dtmf_reverse_twist
static

Definition at line 334 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ thresholds

int thresholds[THRESHOLD_MAX]
static

Definition at line 330 of file dsp.c.

Referenced by _dsp_init(), and ast_dsp_get_threshold_from_settings().