Asterisk - The Open Source Telephony Project GIT-master-80b953f
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_DIGITMODES   (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_R2_FORWARD | DSP_DIGITMODE_R2_BACKWARD)
 
#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 R2_GSIZE   133
 
#define R2_MF_RELATIVE_PEAK   12.6f /* 11dB */
 
#define R2_MF_THRESHOLD   5.0e8f
 
#define R2_MF_TWIST   5.0f /* 7dB */
 
#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 digitmode, 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_r2_detect_init (mf_detect_state_t *s, unsigned int sample_rate, int backward)
 
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 r2_detect (struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax, const char *r2_positions)
 
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 const float r2_backward_tones []
 
static const float r2_forward_tones []
 
static const char r2_mf_positions [] = "1247B-358C--69D---0E----F"
 
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 254 of file dsp.c.

◆ DEF_DTMF_HITS_TO_BEGIN

#define DEF_DTMF_HITS_TO_BEGIN   2

Definition at line 241 of file dsp.c.

◆ DEF_DTMF_MISSES_TO_END

#define DEF_DTMF_MISSES_TO_END   3

Definition at line 246 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 227 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_DIGITMODES

Definition at line 2042 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 233 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 225 of file dsp.c.

◆ FAX_TONE_CED_DURATION

#define FAX_TONE_CED_DURATION   2600 /* ms */

Definition at line 224 of file dsp.c.

◆ FAX_TONE_CED_FREQ

#define FAX_TONE_CED_FREQ   2100

Definition at line 223 of file dsp.c.

◆ FAX_TONE_CNG_DB

#define FAX_TONE_CNG_DB   16

Definition at line 217 of file dsp.c.

◆ FAX_TONE_CNG_DURATION

#define FAX_TONE_CNG_DURATION   500 /* ms */

Definition at line 216 of file dsp.c.

◆ FAX_TONE_CNG_FREQ

#define FAX_TONE_CNG_FREQ   1100

Definition at line 215 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 230 of file dsp.c.

◆ R2_GSIZE

#define R2_GSIZE   133

Definition at line 236 of file dsp.c.

◆ R2_MF_RELATIVE_PEAK

#define R2_MF_RELATIVE_PEAK   12.6f /* 11dB */

Definition at line 206 of file dsp.c.

◆ R2_MF_THRESHOLD

#define R2_MF_THRESHOLD   5.0e8f

Definition at line 204 of file dsp.c.

◆ R2_MF_TWIST

#define R2_MF_TWIST   5.0f /* 7dB */

Definition at line 205 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 1261 of file dsp.c.

1262{
1263 short samp;
1264 int x;
1265 int y;
1266 int pass;
1267 int newstate = DSP_TONE_STATE_SILENCE;
1268 int res = 0;
1269 int freqcount = dsp->freqcount > FREQ_ARRAY_SIZE ? FREQ_ARRAY_SIZE : dsp->freqcount;
1270
1271 while (len) {
1272 /* Take the lesser of the number of samples we need and what we have */
1273 pass = len;
1274 if (pass > dsp->gsamp_size - dsp->gsamps) {
1275 pass = dsp->gsamp_size - dsp->gsamps;
1276 }
1277 for (x = 0; x < pass; x++) {
1278 samp = s[x];
1279 dsp->genergy += (int32_t) samp * (int32_t) samp;
1280 for (y = 0; y < freqcount; y++) {
1281 goertzel_sample(&dsp->freqs[y], samp);
1282 }
1283 }
1284 s += pass;
1285 dsp->gsamps += pass;
1286 len -= pass;
1287 if (dsp->gsamps == dsp->gsamp_size) {
1288 float hz[FREQ_ARRAY_SIZE];
1289 for (y = 0; y < FREQ_ARRAY_SIZE; y++) {
1290 hz[y] = goertzel_result(&dsp->freqs[y]);
1291 }
1292 switch (dsp->progmode) {
1293 case PROG_MODE_NA:
1294 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
1295 newstate = DSP_TONE_STATE_BUSY;
1296 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
1297 newstate = DSP_TONE_STATE_RINGING;
1298 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
1299 newstate = DSP_TONE_STATE_DIALTONE;
1300 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
1301 newstate = DSP_TONE_STATE_SPECIAL1;
1302 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
1303 /* End of SPECIAL1 or middle of SPECIAL2 */
1305 newstate = DSP_TONE_STATE_SPECIAL2;
1306 }
1307 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
1308 /* End of SPECIAL2 or middle of SPECIAL3 */
1310 newstate = DSP_TONE_STATE_SPECIAL3;
1311 }
1312 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1313 newstate = DSP_TONE_STATE_TALKING;
1314 } else {
1315 newstate = DSP_TONE_STATE_SILENCE;
1316 }
1317 break;
1318 case PROG_MODE_CR:
1319 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
1320 newstate = DSP_TONE_STATE_RINGING;
1321 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1322 newstate = DSP_TONE_STATE_TALKING;
1323 } else {
1324 newstate = DSP_TONE_STATE_SILENCE;
1325 }
1326 break;
1327 case PROG_MODE_UK:
1328 if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
1329 newstate = DSP_TONE_STATE_HUNGUP;
1330 } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
1331 newstate = DSP_TONE_STATE_DIALTONE;
1332 }
1333 break;
1334 default:
1335 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%u'\n", dsp->progmode);
1336 }
1337 if (newstate == dsp->tstate) {
1338 dsp->tcount++;
1339 if (dsp->ringtimeout) {
1340 dsp->ringtimeout++;
1341 }
1342 switch (dsp->tstate) {
1344 if ((dsp->features & DSP_PROGRESS_RINGING) &&
1345 (dsp->tcount == THRESH_RING)) {
1346 res = AST_CONTROL_RINGING;
1347 dsp->ringtimeout = 1;
1348 }
1349 break;
1351 if ((dsp->features & DSP_PROGRESS_BUSY) &&
1352 (dsp->tcount == THRESH_BUSY)) {
1353 res = AST_CONTROL_BUSY;
1354 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1355 }
1356 break;
1358 if ((dsp->features & DSP_PROGRESS_TALK) &&
1359 (dsp->tcount == THRESH_TALK)) {
1360 res = AST_CONTROL_ANSWER;
1361 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1362 }
1363 break;
1365 if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
1366 (dsp->tcount == THRESH_CONGESTION)) {
1368 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1369 }
1370 break;
1372 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
1373 (dsp->tcount == THRESH_HANGUP)) {
1374 res = AST_CONTROL_HANGUP;
1375 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1376 }
1377 break;
1378 }
1379 if (dsp->ringtimeout == THRESH_RING2ANSWER) {
1380 ast_debug(1, "Consider call as answered because of timeout after last ring\n");
1381 res = AST_CONTROL_ANSWER;
1382 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1383 }
1384 } else {
1385 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
1386 ast_debug(5, "Start state %d\n", newstate);
1387 dsp->tstate = newstate;
1388 dsp->tcount = 1;
1389 }
1390
1391 /* Reset goertzel */
1392 for (x = 0; x < 7; x++) {
1393 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1394 }
1395 dsp->gsamps = 0;
1396 dsp->genergy = 0.0;
1397 }
1398 }
1399
1400 return res;
1401}
#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:378
static void goertzel_sample(goertzel_state_t *s, short sample)
Definition dsp.c:352
static int pair_there(float p1, float p2, float i1, float i2, float e)
Definition dsp.c:1238
#define FREQ_ARRAY_SIZE
Definition dsp.c:115
#define TONE_THRESH
Definition dsp.c:153
#define DSP_PROGRESS_RINGING
Definition dsp.h:42
#define DSP_TONE_STATE_SPECIAL3
Definition dsp.h:61
#define DSP_TONE_STATE_SPECIAL2
Definition dsp.h:60
#define DSP_TONE_STATE_DIALTONE
Definition dsp.h:56
#define DSP_PROGRESS_TALK
Definition dsp.h:41
#define DSP_TONE_STATE_SILENCE
Definition dsp.h:54
#define DSP_TONE_STATE_BUSY
Definition dsp.h:58
#define DSP_PROGRESS_BUSY
Definition dsp.h:43
#define DSP_TONE_STATE_SPECIAL1
Definition dsp.h:59
#define DSP_PROGRESS_CONGESTION
Definition dsp.h:44
#define DSP_FEATURE_CALL_PROGRESS
Definition dsp.h:45
#define DSP_TONE_STATE_HUNGUP
Definition dsp.h:62
#define DSP_TONE_STATE_TALKING
Definition dsp.h:57
#define DSP_TONE_STATE_RINGING
Definition dsp.h:55
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:441
goertzel_state_t freqs[FREQ_ARRAY_SIZE]
Definition dsp.c:435
int tstate
Definition dsp.c:440
enum prog_mode progmode
Definition dsp.c:439
int freqcount
Definition dsp.c:436
int features
Definition dsp.c:428
enum gsamp_size gsamp_size
Definition dsp.c:438
float genergy
Definition dsp.c:447
int gsamps
Definition dsp.c:437
int ringtimeout
Definition dsp.c:429

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 1920 of file dsp.c.

1921{
1922 struct ast_dsp *dsp;
1923
1924 if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
1927 dsp->busycount = DSP_HISTORY;
1930 dsp->sample_rate = sample_rate;
1931 dsp->freqcount = 0;
1932 /* Initialize digit detector */
1935 /* Initialize initial DSP progress detect parameters */
1936 ast_dsp_prog_reset(dsp);
1937 /* Initialize fax detector */
1939 }
1940 return dsp;
1941}
#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:527
static void ast_digit_detect_init(digit_detect_state_t *s, int digitmode, unsigned int sample_rate)
Definition dsp.c:587
#define DSP_HISTORY
Definition dsp.c:151
static void ast_dsp_prog_reset(struct ast_dsp *dsp)
Definition dsp.c:1898
#define DSP_FAXMODE_DETECT_CNG
Definition dsp.h:49
#define DSP_FEATURE_SILENCE_SUPPRESS
Definition dsp.h:26
#define DSP_DIGITMODE_DTMF
Definition dsp.h:31
Definition dsp.c:421
int faxmode
Definition dsp.c:443
unsigned int sample_rate
Definition dsp.c:449
int busycount
Definition dsp.c:431
int threshold
Definition dsp.c:423
digit_detect_state_t digit_state
Definition dsp.c:451
int digitmode
Definition dsp.c:442
int display_inband_dtmf_warning
Definition dsp.c:446

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_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 1417 of file dsp.c.

1418{
1419 int accum;
1420 int x;
1421 int res = 0;
1422
1423 if (!len) {
1424 return 0;
1425 }
1426 accum = 0;
1427 for (x = 0; x < len; x++) {
1428 accum += abs(s[x]);
1429 }
1430 accum /= len;
1431 if (accum < dsp->threshold) {
1432 /* Silent */
1433 dsp->totalsilence += len / (dsp->sample_rate / 1000);
1434 if (dsp->totalnoise) {
1435 /* Move and save history */
1436 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0]));
1437 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
1438/* we don't want to check for busydetect that frequently */
1439#if 0
1440 dsp->busymaybe = 1;
1441#endif
1442 }
1443 dsp->totalnoise = 0;
1444 res = 1;
1445 } else {
1446 /* Not silent */
1447 dsp->totalnoise += len / (dsp->sample_rate / 1000);
1448 if (dsp->totalsilence) {
1449 int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
1450 int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
1451 /* Move and save history */
1452 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0]));
1453 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
1454 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
1455 if (silence1 < silence2) {
1456 if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) {
1457 dsp->busymaybe = 1;
1458 } else {
1459 dsp->busymaybe = 0;
1460 }
1461 } else {
1462 if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) {
1463 dsp->busymaybe = 1;
1464 } else {
1465 dsp->busymaybe = 0;
1466 }
1467 }
1468 }
1469 dsp->totalsilence = 0;
1470 }
1471 if (totalsilence) {
1472 *totalsilence = dsp->totalsilence;
1473 }
1474 if (totalnoise) {
1475 *totalnoise = dsp->totalnoise;
1476 }
1477 if (frames_energy) {
1478 *frames_energy = accum;
1479 }
1480 return res;
1481}
threshold
Definition dsp.h:73
#define abs(x)
Definition f2c.h:195
int historicnoise[DSP_HISTORY]
Definition dsp.c:433
int busymaybe
Definition dsp.c:430
int totalsilence
Definition dsp.c:425
int totalnoise
Definition dsp.c:427
int historicsilence[DSP_HISTORY]
Definition dsp.c:434

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 2666 of file dsp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2666 of file dsp.c.

◆ _dsp_init()

static int _dsp_init ( int  reload)
static

Definition at line 2108 of file dsp.c.

2109{
2110 struct ast_config *cfg;
2111 struct ast_variable *v;
2112 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2113 int cfg_threshold;
2114 float cfg_twist;
2115
2116 if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
2117 return 0;
2118 }
2119
2127
2129 return 0;
2130 }
2131
2132 for (v = ast_variable_browse(cfg, "default"); v; v = v->next) {
2133 if (!strcasecmp(v->name, "silencethreshold")) {
2134 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
2135 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2136 } else if (cfg_threshold < 0) {
2137 ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
2138 } else {
2139 thresholds[THRESHOLD_SILENCE] = cfg_threshold;
2140 }
2141 } else if (!strcasecmp(v->name, "dtmf_normal_twist")) {
2142 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
2143 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2144 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
2145 ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
2146 } else {
2147 dtmf_normal_twist = cfg_twist;
2148 }
2149 } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) {
2150 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
2151 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2152 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
2153 ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
2154 } else {
2155 dtmf_reverse_twist = cfg_twist;
2156 }
2157 } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) {
2158 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
2159 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2160 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
2161 ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
2162 } else {
2163 relax_dtmf_normal_twist = cfg_twist;
2164 }
2165 } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) {
2166 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
2167 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2168 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
2169 ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
2170 } else {
2171 relax_dtmf_reverse_twist = cfg_twist;
2172 }
2173 } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) {
2174 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
2175 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2176 } else if (cfg_threshold < 1) { /* must be 1 or greater */
2177 ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
2178 } else {
2179 dtmf_hits_to_begin = cfg_threshold;
2180 }
2181 } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) {
2182 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
2183 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2184 } else if (cfg_threshold < 1) { /* must be 1 or greater */
2185 ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
2186 } else {
2187 dtmf_misses_to_end = cfg_threshold;
2188 }
2189 }
2190 }
2191 ast_config_destroy(cfg);
2192
2193 return 0;
2194}
static int thresholds[THRESHOLD_MAX]
Definition dsp.c:344
#define DEF_DTMF_HITS_TO_BEGIN
Definition dsp.c:241
#define DEF_DTMF_REVERSE_TWIST
Definition dsp.c:192
#define DEF_DTMF_MISSES_TO_END
Definition dsp.c:246
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:252
#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:254
#define DEF_RELAX_DTMF_REVERSE_TWIST
Definition dsp.c:193
static float dtmf_reverse_twist
Definition dsp.c:346
static int dtmf_misses_to_end
Definition dsp.c:350
static int dtmf_hits_to_begin
Definition dsp.c:349
static float relax_dtmf_normal_twist
Definition dsp.c:347
static float dtmf_normal_twist
Definition dsp.c:345
static float relax_dtmf_reverse_twist
Definition dsp.c:348
@ THRESHOLD_SILENCE
Definition dsp.h:75
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
@ CONFIG_FLAG_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
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:220
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  digitmode,
unsigned int  sample_rate 
)
static

Definition at line 587 of file dsp.c.

588{
589 s->current_digits = 0;
590 s->detected_digits = 0;
591 s->lost_digits = 0;
592 s->digits[0] = '\0';
593
594 if (digitmode & DSP_DIGITMODE_R2_FORWARD) {
595 ast_r2_detect_init(&s->td.mf, sample_rate, 0);
596 } else if (digitmode & DSP_DIGITMODE_R2_BACKWARD) {
597 ast_r2_detect_init(&s->td.mf, sample_rate, 1);
598 } else if (digitmode & DSP_DIGITMODE_MF) {
599 ast_mf_detect_init(&s->td.mf, sample_rate);
600 } else {
601 ast_dtmf_detect_init(&s->td.dtmf, sample_rate);
602 }
603}
static void ast_mf_detect_init(mf_detect_state_t *s, unsigned int sample_rate)
Definition dsp.c:563
static void ast_dtmf_detect_init(dtmf_detect_state_t *s, unsigned int sample_rate)
Definition dsp.c:547
static void ast_r2_detect_init(mf_detect_state_t *s, unsigned int sample_rate, int backward)
Definition dsp.c:575
#define DSP_DIGITMODE_MF
Definition dsp.h:32
#define DSP_DIGITMODE_R2_BACKWARD
Definition dsp.h:34
#define DSP_DIGITMODE_R2_FORWARD
Definition dsp.h:33
mf_detect_state_t mf
Definition dsp.c:322
dtmf_detect_state_t dtmf
Definition dsp.c:321
char digits[MAX_DTMF_DIGITS+1]
Definition dsp.c:314
union digit_detect_state_t::@368 td

References ast_dtmf_detect_init(), ast_mf_detect_init(), ast_r2_detect_init(), digit_detect_state_t::current_digits, digit_detect_state_t::detected_digits, digit_detect_state_t::digits, DSP_DIGITMODE_MF, DSP_DIGITMODE_R2_BACKWARD, DSP_DIGITMODE_R2_FORWARD, 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 1483 of file dsp.c.

1484{
1485 int res = 0, x;
1486#ifndef BUSYDETECT_TONEONLY
1487 int avgsilence = 0, hitsilence = 0;
1488#endif
1489 int avgtone = 0, hittone = 0;
1490
1491 /* if we have a 4 length pattern, the way busymaybe is set doesn't help us. */
1492 if (dsp->busy_cadence.length != 4) {
1493 if (!dsp->busymaybe) {
1494 return res;
1495 }
1496 }
1497
1498 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
1499#ifndef BUSYDETECT_TONEONLY
1500 avgsilence += dsp->historicsilence[x];
1501#endif
1502 avgtone += dsp->historicnoise[x];
1503 }
1504#ifndef BUSYDETECT_TONEONLY
1505 avgsilence /= dsp->busycount;
1506#endif
1507 avgtone /= dsp->busycount;
1508 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
1509#ifndef BUSYDETECT_TONEONLY
1510 if (avgsilence > dsp->historicsilence[x]) {
1511 if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) {
1512 hitsilence++;
1513 }
1514 } else {
1515 if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) {
1516 hitsilence++;
1517 }
1518 }
1519#endif
1520 if (avgtone > dsp->historicnoise[x]) {
1521 if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
1522 hittone++;
1523 }
1524 } else {
1525 if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
1526 hittone++;
1527 }
1528 }
1529 }
1530#ifndef BUSYDETECT_TONEONLY
1531 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) &&
1532 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) &&
1533 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX))
1534#else
1535 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX))
1536#endif
1537 {
1538#ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
1539 if (avgtone > avgsilence) {
1540 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) {
1541 res = 1;
1542 }
1543 } else {
1544 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) {
1545 res = 1;
1546 }
1547 }
1548#else
1549 res = 1;
1550#endif
1551 }
1552
1553 /* If we have a 4-length pattern, we can go ahead and just check it in a different way. */
1554 if (dsp->busy_cadence.length == 4) {
1555 int x;
1556 int errors = 0;
1557 int errors_max = ((4 * dsp->busycount) / 100.0) * BUSY_PAT_PERCENT;
1558
1559 for (x = DSP_HISTORY - (dsp->busycount); x < DSP_HISTORY; x += 2) {
1560 int temp_error;
1561 temp_error = abs(dsp->historicnoise[x] - dsp->busy_cadence.pattern[0]);
1562 if ((temp_error * 100) / dsp->busy_cadence.pattern[0] > BUSY_PERCENT) {
1563 errors++;
1564 }
1565
1566 temp_error = abs(dsp->historicnoise[x + 1] - dsp->busy_cadence.pattern[2]);
1567 if ((temp_error * 100) / dsp->busy_cadence.pattern[2] > BUSY_PERCENT) {
1568 errors++;
1569 }
1570
1571 temp_error = abs(dsp->historicsilence[x] - dsp->busy_cadence.pattern[1]);
1572 if ((temp_error * 100) / dsp->busy_cadence.pattern[1] > BUSY_PERCENT) {
1573 errors++;
1574 }
1575
1576 temp_error = abs(dsp->historicsilence[x + 1] - dsp->busy_cadence.pattern[3]);
1577 if ((temp_error * 100) / dsp->busy_cadence.pattern[3] > BUSY_PERCENT) {
1578 errors++;
1579 }
1580 }
1581
1582 ast_debug(5, "errors = %d max = %d\n", errors, errors_max);
1583
1584 if (errors <= errors_max) {
1585 return 1;
1586 }
1587 }
1588
1589 /* If we know the expected busy tone length, check we are in the range */
1590 if (res && (dsp->busy_cadence.pattern[0] > 0)) {
1591 if (abs(avgtone - dsp->busy_cadence.pattern[0]) > MAX(dsp->busy_cadence.pattern[0]*BUSY_PAT_PERCENT/100, 20)) {
1592#ifdef BUSYDETECT_DEBUG
1593 ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
1594 avgtone, dsp->busy_cadence.pattern[0]);
1595#endif
1596 res = 0;
1597 }
1598 }
1599#ifndef BUSYDETECT_TONEONLY
1600 /* If we know the expected busy tone silent-period length, check we are in the range */
1601 if (res && (dsp->busy_cadence.pattern[1] > 0)) {
1602 if (abs(avgsilence - dsp->busy_cadence.pattern[1]) > MAX(dsp->busy_cadence.pattern[1]*BUSY_PAT_PERCENT/100, 20)) {
1603#ifdef BUSYDETECT_DEBUG
1604 ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
1605 avgsilence, dsp->busy_cadence.pattern[1]);
1606#endif
1607 res = 0;
1608 }
1609 }
1610#endif
1611#if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
1612 if (res) {
1613 ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1614 } else {
1615 ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1616 }
1617#endif
1618 return res;
1619}
int pattern[4]
Definition dsp.h:70
struct ast_dsp_busy_pattern busy_cadence
Definition dsp.c:432
#define MAX(a, b)
Definition utils.h:254

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 1403 of file dsp.c.

1404{
1405 if (inf->frametype != AST_FRAME_VOICE) {
1406 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1407 return 0;
1408 }
1410 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames, %s not supported\n",
1412 return 0;
1413 }
1414 return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
1415}
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
Definition dsp.c:1261
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::@235 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 1995 of file dsp.c.

1996{
1997 int i;
1998
1999 dsp->dtmf_began = 0;
2002 /* Reinitialise the detector for the next block */
2003 for (i = 0; i < 6; i++) {
2004 goertzel_reset(&s->tone_out[i]);
2005 }
2006 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = 0;
2007 s->current_hit = 0;
2008 s->current_sample = 0;
2009 } else {
2011 /* Reinitialise the detector for the next block */
2012 for (i = 0; i < 4; i++) {
2013 goertzel_reset(&s->row_out[i]);
2014 goertzel_reset(&s->col_out[i]);
2015 }
2016 s->lasthit = 0;
2017 s->current_hit = 0;
2018 s->energy = 0.0;
2019 s->current_sample = 0;
2020 s->hits = 0;
2021 s->misses = 0;
2022 }
2023
2024 dsp->digit_state.digits[0] = '\0';
2025 dsp->digit_state.current_digits = 0;
2026}
static void goertzel_reset(goertzel_state_t *s)
Definition dsp.c:398
int dtmf_began
Definition dsp.c:445
goertzel_state_t row_out[DTMF_MATRIX_SIZE]
Definition dsp.c:292
goertzel_state_t col_out[DTMF_MATRIX_SIZE]
Definition dsp.c:293
int hits[5]
Definition dsp.c:307
goertzel_state_t tone_out[6]
Definition dsp.c:305
int current_hit
Definition dsp.c:306
int current_sample
Definition dsp.c:308

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, DSP_DIGITMODE_R2_BACKWARD, DSP_DIGITMODE_R2_FORWARD, 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 1962 of file dsp.c.

1963{
1964 return (dsp->features);
1965}

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 1915 of file dsp.c.

1916{
1917 return dsp->sample_rate;
1918}

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 2103 of file dsp.c.

2104{
2105 return dsp->tcount;
2106}

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 2196 of file dsp.c.

2197{
2198 return thresholds[which];
2199}

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 2098 of file dsp.c.

2099{
2100 return dsp->tstate;
2101}

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 1948 of file dsp.c.

1949{
1950 return __ast_dsp_new(sample_rate);
1951}

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 1677 of file dsp.c.

1678{
1679 return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
1680}
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:1621
#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 1683 of file dsp.c.

1684{
1685 int silence;
1686 int res;
1687 int digit = 0, fax_digit = 0, custom_freq_digit = 0;
1688 int x;
1689 short *shortdata;
1690 unsigned char *odata;
1691 int len;
1692 struct ast_frame *outf = NULL;
1693
1694 if (!af) {
1695 return NULL;
1696 }
1697 if (af->frametype != AST_FRAME_VOICE) {
1698 return af;
1699 }
1700
1701 odata = af->data.ptr;
1702 len = af->datalen;
1703 /* Make sure we have short data */
1705 shortdata = af->data.ptr;
1706 len = af->datalen / 2;
1708 shortdata = ast_alloca(af->datalen * 2);
1709 for (x = 0; x < len; x++) {
1710 shortdata[x] = AST_MULAW(odata[x]);
1711 }
1713 shortdata = ast_alloca(af->datalen * 2);
1714 for (x = 0; x < len; x++) {
1715 shortdata[x] = AST_ALAW(odata[x]);
1716 }
1717 } else {
1718 /* Display warning only once. Otherwise you would get hundreds of warnings every second */
1719 if (dsp->display_inband_dtmf_warning) {
1720 /* If DTMF is enabled for the DSP, try to be helpful and warn about that specifically,
1721 * otherwise emit a more generic message that covers all other cases. */
1723 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n",
1725 } else {
1726 ast_log(LOG_WARNING, "Can only do DSP on signed-linear, alaw or ulaw frames (%s not supported)\n",
1728 }
1729 }
1731 return af;
1732 }
1733
1734 /* Initially we do not want to mute anything */
1735 dsp->mute_fragments = 0;
1736
1737 /* Need to run the silence detection stuff for silence suppression and busy detection */
1739 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL, NULL);
1740 }
1741
1742 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
1743 memset(&dsp->f, 0, sizeof(dsp->f));
1744 dsp->f.frametype = AST_FRAME_NULL;
1745 ast_frfree(af);
1746 return ast_frisolate(&dsp->f);
1747 }
1750 memset(&dsp->f, 0, sizeof(dsp->f));
1753 ast_frfree(af);
1754 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", ast_channel_name(chan));
1755 return ast_frisolate(&dsp->f);
1756 }
1757
1758 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
1759 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1760 fax_digit = 'f';
1761 }
1762
1763 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
1764 fax_digit = 'e';
1765 }
1766 }
1767
1768 if ((dsp->features & DSP_FEATURE_FREQ_DETECT)) {
1769 if ((dsp->freqmode) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1770 custom_freq_digit = 'q';
1771 }
1772 }
1773
1777 } else if (dsp->digitmode & DSP_DIGITMODE_MF) {
1778 digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1779 } else {
1780 digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1781 }
1782
1783 if (dsp->digit_state.current_digits) {
1784 int event = 0, event_len = 0;
1785 char event_digit = 0;
1786
1787 if (!dsp->dtmf_began) {
1788 /* We have not reported DTMF_BEGIN for anything yet */
1789
1791 event = AST_FRAME_DTMF_BEGIN;
1792 event_digit = dsp->digit_state.digits[0];
1793 }
1794 dsp->dtmf_began = 1;
1795 } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
1796 /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
1798 event = AST_FRAME_DTMF_END;
1799 event_digit = dsp->digit_state.digits[0];
1800 event_len = dsp->digit_state.digitlen[0] * 1000 / dsp->sample_rate;
1801 }
1802 memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
1803 memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
1805 dsp->dtmf_began = 0;
1806
1807 if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
1808 /* Reset Busy Detector as we have some confirmed activity */
1809 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1810 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1811 ast_debug(1, "DTMF Detected - Reset busydetector\n");
1812 }
1813 }
1814
1815 if (event) {
1816 memset(&dsp->f, 0, sizeof(dsp->f));
1817 dsp->f.frametype = event;
1818 dsp->f.subclass.integer = event_digit;
1819 dsp->f.len = event_len;
1820 outf = &dsp->f;
1821 goto done;
1822 }
1823 }
1824 }
1825
1826 if (fax_digit) {
1827 /* Fax was detected - digit is either 'f' or 'e' */
1828
1829 memset(&dsp->f, 0, sizeof(dsp->f));
1830 dsp->f.frametype = AST_FRAME_DTMF;
1831 dsp->f.subclass.integer = fax_digit;
1832 outf = &dsp->f;
1833 goto done;
1834 }
1835
1836 if (custom_freq_digit) {
1837 /* Custom frequency was detected - digit is 'q' */
1838
1839 memset(&dsp->f, 0, sizeof(dsp->f));
1840 dsp->f.frametype = AST_FRAME_DTMF;
1841 dsp->f.subclass.integer = custom_freq_digit;
1842 outf = &dsp->f;
1843 goto done;
1844 }
1845
1846 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
1847 res = __ast_dsp_call_progress(dsp, shortdata, len);
1848 if (res) {
1849 switch (res) {
1850 case AST_CONTROL_ANSWER:
1851 case AST_CONTROL_BUSY:
1854 case AST_CONTROL_HANGUP:
1855 memset(&dsp->f, 0, sizeof(dsp->f));
1857 dsp->f.subclass.integer = res;
1858 dsp->f.src = "dsp_progress";
1859 if (chan) {
1860 ast_queue_frame(chan, &dsp->f);
1861 }
1862 break;
1863 default:
1864 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
1865 }
1866 }
1867 } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
1868 res = __ast_dsp_call_progress(dsp, shortdata, len);
1869 }
1870
1871done:
1872 /* Mute fragment of the frame */
1873 for (x = 0; x < dsp->mute_fragments; x++) {
1874 memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
1875 }
1876
1878 for (x = 0; x < len; x++) {
1879 odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
1880 }
1882 for (x = 0; x < len; x++) {
1883 odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
1884 }
1885 }
1886
1887 if (outf) {
1888 if (chan) {
1889 ast_queue_frame(chan, af);
1890 }
1891 ast_frfree(af);
1892 return ast_frisolate(outf);
1893 } else {
1894 return af;
1895 }
1896}
#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:1171
@ AST_SOFTHANGUP_DEV
Definition channel.h:1141
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
Definition dsp.c:605
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:937
static int r2_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax, const char *r2_positions)
Definition dsp.c:1088
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:729
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:1483
static const char r2_mf_positions[]
Definition dsp.c:343
static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
Definition dsp.c:1417
#define DSP_FEATURE_WAITDIALTONE
Definition dsp.h:46
#define DSP_FEATURE_BUSY_DETECT
Definition dsp.h:27
#define DSP_DIGITMODE_NOQUELCH
Definition dsp.h:36
#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:50
#define DSP_FEATURE_FREQ_DETECT
Definition dsp.h:47
#define DSP_DIGITMODE_RELAXDTMF
Definition dsp.h:39
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:450
int mute_fragments
Definition dsp.c:448
struct ast_frame f
Definition dsp.c:422
tone_detect_state_t ced_tone_state
Definition dsp.c:453
int freqmode
Definition dsp.c:444
tone_detect_state_t cng_tone_state
Definition dsp.c:452
Data structure associated with a single frame of data.
int digitlen[MAX_DTMF_DIGITS+1]
Definition dsp.c:315
int start
Definition dsp.c:404
int end
Definition dsp.c:405
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_R2_BACKWARD, DSP_DIGITMODE_R2_FORWARD, 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, r2_detect(), r2_mf_positions, 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 1898 of file dsp.c.

1899{
1900 int max = 0;
1901 int x;
1902
1903 dsp->gsamp_size = modes[dsp->progmode].size;
1904 dsp->gsamps = 0;
1905 for (x = 0; x < FREQ_ARRAY_SIZE; x++) {
1906 if (modes[dsp->progmode].freqs[x]) {
1907 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->sample_rate);
1908 max = x + 1;
1909 }
1910 }
1911 dsp->freqcount = max;
1912 dsp->ringtimeout = 0;
1913}
static void goertzel_init(goertzel_state_t *s, float freq, unsigned int sample_rate)
Definition dsp.c:392
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 2028 of file dsp.c.

2029{
2030 int x;
2031
2032 dsp->totalsilence = 0;
2033 dsp->gsamps = 0;
2034 for (x = 0; x < 4; x++) {
2035 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
2036 }
2037 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
2038 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
2039 dsp->ringtimeout = 0;
2040}

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 1978 of file dsp.c.

1979{
1980 if (cadences < 4) {
1981 cadences = 4;
1982 }
1983 if (cadences > DSP_HISTORY) {
1985 }
1986 dsp->busycount = cadences;
1987}
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 1989 of file dsp.c.

1990{
1991 dsp->busy_cadence = *cadence;
1992 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);
1993}

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 2079 of file dsp.c.

2080{
2081 int x;
2082
2083 for (x = 0; x < ARRAY_LEN(aliases); x++) {
2084 if (!strcasecmp(aliases[x].name, zone)) {
2085 dsp->progmode = aliases[x].mode;
2086 ast_dsp_prog_reset(dsp);
2087 return 0;
2088 }
2089 }
2090 return -1;
2091}
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:706

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 2044 of file dsp.c.

2045{
2046 int new;
2047 int old;
2048
2051 if (old != new) {
2052 /* Must initialize structures if switching from MF to DTMF or vice-versa */
2054 }
2055 dsp->digitmode = digitmode;
2056 return 0;
2057}
#define DSP_DIGITMODES
Definition dsp.c:2042
#define DSP_DIGITMODE_MUTEMAX
Definition dsp.h:38
#define DSP_DIGITMODE_MUTECONF
Definition dsp.h:37

References ast_digit_detect_init(), ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODES, 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 2070 of file dsp.c.

2071{
2072 if (dsp->faxmode != faxmode) {
2073 dsp->faxmode = faxmode;
2075 }
2076 return 0;
2077}

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 2059 of file dsp.c.

2060{
2061 if (freq > 0) {
2062 dsp->freqmode = 1;
2063 ast_freq_detect_init(dsp, freq, dur, db, squelch);
2064 } else {
2065 dsp->freqmode = 0;
2066 }
2067 return 0;
2068}
static void ast_freq_detect_init(struct ast_dsp *s, int freq, int dur, int db, int squelch)
Definition dsp.c:538

References ast_freq_detect_init(), 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 1973 of file dsp.c.

1974{
1975 dsp->threshold = threshold;
1976}

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 1672 of file dsp.c.

1673{
1674 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
1675}

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 1621 of file dsp.c.

1622{
1623 short *s;
1624 int len;
1625 int x;
1626 unsigned char *odata;
1627
1628 if (!f) {
1629 return 0;
1630 }
1631
1632 if (f->frametype != AST_FRAME_VOICE) {
1633 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
1634 return 0;
1635 }
1636
1638 s = f->data.ptr;
1639 len = f->datalen/2;
1640 } else {
1641 odata = f->data.ptr;
1642 len = f->datalen;
1644 s = ast_alloca(len * 2);
1645 for (x = 0; x < len; x++) {
1646 s[x] = AST_MULAW(odata[x]);
1647 }
1649 s = ast_alloca(len * 2);
1650 for (x = 0; x < len; x++) {
1651 s[x] = AST_ALAW(odata[x]);
1652 }
1653 } else {
1654 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames, %s not supported\n",
1656 return 0;
1657 }
1658 }
1659
1660 if (noise) {
1661 return __ast_dsp_silence_noise(dsp, s, len, NULL, total, frames_energy);
1662 } else {
1663 return __ast_dsp_silence_noise(dsp, s, len, total, NULL, frames_energy);
1664 }
1665}
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 1667 of file dsp.c.

1668{
1669 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
1670}

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 2093 of file dsp.c.

2094{
2095 return (dsp->mute_fragments > 0);
2096}

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 547 of file dsp.c.

548{
549 int i;
550
551 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
552 goertzel_init(&s->row_out[i], dtmf_row[i], sample_rate);
553 goertzel_init(&s->col_out[i], dtmf_col[i], sample_rate);
554 }
555 s->lasthit = 0;
556 s->current_hit = 0;
557 s->energy = 0.0;
558 s->current_sample = 0;
559 s->hits = 0;
560 s->misses = 0;
561}
#define DTMF_MATRIX_SIZE
Definition dsp.c:168
static const float dtmf_row[]
Definition dsp.c:326
static const float dtmf_col[]
Definition dsp.c:329

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 527 of file dsp.c.

528{
532 s->cng_tone_state.squelch = 1;
533 s->ced_tone_state.squelch = 1;
534 }
535
536}
static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, int amp, unsigned int sample_rate)
Definition dsp.c:466
#define FAX_TONE_CED_DB
Definition dsp.c:225
#define FAX_TONE_CNG_FREQ
Definition dsp.c:215
#define FAX_TONE_CED_DURATION
Definition dsp.c:224
#define FAX_TONE_CNG_DB
Definition dsp.c:217
#define FAX_TONE_CED_FREQ
Definition dsp.c:223
#define FAX_TONE_CNG_DURATION
Definition dsp.c:216
#define DSP_FAXMODE_DETECT_SQUELCH
Definition dsp.h:51

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 538 of file dsp.c.

539{
540 /* we can conveniently just use one of the two fax tone states */
541 ast_tone_detect_init(&s->cng_tone_state, freq, dur, db, s->sample_rate);
542 if (s->freqmode & squelch) {
543 s->cng_tone_state.squelch = 1;
544 }
545}

References ast_tone_detect_init(), ast_dsp::cng_tone_state, 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 563 of file dsp.c.

564{
565 int i;
566
567 for (i = 0; i < 6; i++) {
568 goertzel_init(&s->tone_out[i], mf_tones[i], sample_rate);
569 }
570 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
571 s->current_sample = 0;
572 s->current_hit = 0;
573}
static const float mf_tones[]
Definition dsp.c:332

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 2666 of file dsp.c.

◆ ast_r2_detect_init()

static void ast_r2_detect_init ( mf_detect_state_t s,
unsigned int  sample_rate,
int  backward 
)
static

Definition at line 575 of file dsp.c.

576{
577 int i;
578
579 for (i = 0; i < 6; i++) {
580 goertzel_init(&s->tone_out[i], backward ? r2_backward_tones[i] : r2_forward_tones[i], sample_rate);
581 }
582 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
583 s->current_sample = 0;
584 s->current_hit = 0;
585}
static const float r2_forward_tones[]
Definition dsp.c:335
static const float r2_backward_tones[]
Definition dsp.c:338

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

Referenced by ast_digit_detect_init().

◆ 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 466 of file dsp.c.

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

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 729 of file dsp.c.

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

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 392 of file dsp.c.

393{
394 s->v2 = s->v3 = s->chunky = 0;
395 s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / sample_rate));
396}
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(), ast_r2_detect_init(), and ast_tone_detect_init().

◆ goertzel_reset()

static void goertzel_reset ( goertzel_state_t s)
inlinestatic

Definition at line 398 of file dsp.c.

399{
400 s->v2 = s->v3 = s->chunky = 0;
401}

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

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

◆ goertzel_result()

static float goertzel_result ( goertzel_state_t s)
inlinestatic

Definition at line 378 of file dsp.c.

379{
381
382 r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
383 r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
384 /*
385 * We have to double the exponent because we multiplied the
386 * previous sample calculation values together.
387 */
388 r.power = s->chunky * 2;
389 return (float)r.value * (float)(1 << r.power);
390}

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(), r2_detect(), and tone_detect().

◆ goertzel_sample()

static void goertzel_sample ( goertzel_state_t s,
short  sample 
)
inlinestatic

Definition at line 352 of file dsp.c.

353{
354 int v1;
355
356 /*
357 * Shift previous values so
358 * v1 is previous previous value
359 * v2 is previous value
360 * until the new v3 is calculated.
361 */
362 v1 = s->v2;
363 s->v2 = s->v3;
364
365 /* Discard the binary fraction introduced by s->fac */
366 s->v3 = (s->fac * s->v2) >> 15;
367 /* Scale sample to match previous values */
368 s->v3 = s->v3 - v1 + (sample >> s->chunky);
369
370 if (abs(s->v3) > (1 << 15)) {
371 /* The result is now too large so increase the chunky power. */
372 s->chunky++;
373 s->v3 = s->v3 >> 1;
374 s->v2 = s->v2 >> 1;
375 }
376}

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(), r2_detect(), and tone_detect().

◆ load_module()

static int load_module ( void  )
static

Definition at line 2642 of file dsp.c.

2643{
2644 if (_dsp_init(0)) {
2646 }
2647
2648 AST_TEST_REGISTER(test_dsp_fax_detect);
2649 AST_TEST_REGISTER(test_dsp_dtmf_detect);
2650
2652}
static int _dsp_init(int reload)
Definition dsp.c:2108
@ 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 937 of file dsp.c.

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

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 456 of file dsp.c.

457{
458 if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
459 ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
460 return;
461 }
462
463 dsp->mute_data[dsp->mute_fragments++] = *fragment;
464}
#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(), r2_detect(), and tone_detect().

◆ pair_there()

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

Definition at line 1238 of file dsp.c.

1239{
1240 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
1241 /* Make sure absolute levels are high enough */
1242 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
1243 return 0;
1244 }
1245 /* Amplify ignored stuff */
1246 i2 *= TONE_THRESH;
1247 i1 *= TONE_THRESH;
1248 e *= TONE_THRESH;
1249 /* Check first tone */
1250 if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
1251 return 0;
1252 }
1253 /* And second */
1254 if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
1255 return 0;
1256 }
1257 /* Guess it's there... */
1258 return 1;
1259}

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

◆ r2_detect()

static int r2_detect ( struct ast_dsp dsp,
digit_detect_state_t s,
int16_t  amp[],
int  samples,
int  squelch,
int  relax,
const char *  r2_positions 
)
static

Definition at line 1088 of file dsp.c.

1090{
1091 float energy[6];
1092 int best;
1093 int second_best;
1094 int i;
1095 int j;
1096 int sample;
1097 short samp;
1098 int hit;
1099 int limit;
1100 fragment_t mute = {0, 0};
1101
1102 if (squelch && s->td.mf.mute_samples > 0) {
1103 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
1104 s->td.mf.mute_samples -= mute.end;
1105 }
1106
1107 hit = 0;
1108 for (sample = 0; sample < samples; sample = limit) {
1109 if ((samples - sample) >= (R2_GSIZE - s->td.mf.current_sample)) {
1110 limit = sample + (R2_GSIZE - s->td.mf.current_sample);
1111 } else {
1112 limit = samples;
1113 }
1114 /* The following unrolled loop takes only 35% (rough estimate) of the
1115 time of a rolled loop on the machine on which it was developed */
1116 for (j = sample; j < limit; j++) {
1117 /* With GCC 2.95, the following unrolled code seems to take about 35%
1118 (rough estimate) as long as a neat little 0-3 loop */
1119 samp = amp[j];
1120 goertzel_sample(s->td.mf.tone_out, samp);
1121 goertzel_sample(s->td.mf.tone_out + 1, samp);
1122 goertzel_sample(s->td.mf.tone_out + 2, samp);
1123 goertzel_sample(s->td.mf.tone_out + 3, samp);
1124 goertzel_sample(s->td.mf.tone_out + 4, samp);
1125 goertzel_sample(s->td.mf.tone_out + 5, samp);
1126 }
1127 s->td.mf.current_sample += (limit - sample);
1128 if (s->td.mf.current_sample < R2_GSIZE) {
1129 continue;
1130 }
1131 /* We're at the end of an MF detection block. */
1132 /* Find the two highest energies. The spec says to look for
1133 two tones and two tones only. Taking this literally -ie
1134 only two tones pass the minimum threshold - doesn't work
1135 well. The sinc function mess, due to rectangular windowing
1136 ensure that! Find the two highest energies and ensure they
1137 are considerably stronger than any of the others. */
1138 energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
1139 energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
1140 if (energy[0] > energy[1]) {
1141 best = 0;
1142 second_best = 1;
1143 } else {
1144 best = 1;
1145 second_best = 0;
1146 }
1147 /*endif*/
1148 for (i = 2; i < 6; i++) {
1149 energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
1150 if (energy[i] >= energy[best]) {
1151 second_best = best;
1152 best = i;
1153 } else if (energy[i] >= energy[second_best]) {
1154 second_best = i;
1155 }
1156 }
1157 /* Basic signal level and twist tests */
1158 hit = 0;
1159 if (energy[best] >= R2_MF_THRESHOLD && energy[second_best] >= R2_MF_THRESHOLD
1160 && energy[best] < energy[second_best]*R2_MF_TWIST
1161 && energy[best] * R2_MF_TWIST > energy[second_best]) {
1162 /* Relative peak test */
1163 hit = -1;
1164 for (i = 0; i < 6; i++) {
1165 if (i != best && i != second_best) {
1166 if (energy[i]*R2_MF_RELATIVE_PEAK >= energy[second_best]) {
1167 /* The best two are not clearly the best */
1168 hit = 0;
1169 break;
1170 }
1171 }
1172 }
1173 }
1174 if (hit) {
1175 /* Get the values into ascending order */
1176 if (second_best < best) {
1177 i = best;
1178 best = second_best;
1179 second_best = i;
1180 }
1181 best = best * 5 + second_best - 1;
1182 hit = r2_positions[best];
1183
1184 if (relax) {
1185 /* Continuous tone detection.
1186 * The application is responsible for debouncing. */
1187 store_digit(s, hit);
1188 } else {
1189 /* Discrete digit detection.
1190 * Look for two successive similar results, with something different preceding.
1191 * This is a subset of the MF logic and seems to ensure discrete digit detection. */
1192 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] && hit != s->td.mf.hits[2]) {
1193 store_digit(s, hit);
1194 }
1195 }
1196 } else {
1197 hit = 0;
1198 }
1199
1200 s->td.mf.current_hit = hit;
1201
1202 if (!relax) {
1203 s->td.mf.hits[0] = s->td.mf.hits[1];
1204 s->td.mf.hits[1] = s->td.mf.hits[2];
1205 s->td.mf.hits[2] = s->td.mf.hits[3];
1206 s->td.mf.hits[3] = s->td.mf.hits[4];
1207 s->td.mf.hits[4] = hit;
1208 }
1209
1210 /* If we had a hit in this block, include it into mute fragment */
1211 if (squelch && hit) {
1212 if (mute.end < sample - R2_GSIZE) {
1213 /* There is a gap between fragments */
1214 mute_fragment(dsp, &mute);
1215 mute.start = (sample > R2_GSIZE) ? (sample - R2_GSIZE) : 0;
1216 }
1217 mute.end = limit + R2_GSIZE;
1218 }
1219
1220 /* Reinitialise the detector for the next block */
1221 for (i = 0; i < 6; i++) {
1222 goertzel_reset(&s->td.mf.tone_out[i]);
1223 }
1224 s->td.mf.current_sample = 0;
1225 }
1226
1227 if (squelch && mute.end) {
1228 if (mute.end > samples) {
1229 s->td.mf.mute_samples = mute.end - samples;
1230 mute.end = samples;
1231 }
1232 mute_fragment(dsp, &mute);
1233 }
1234
1235 return (s->td.mf.current_hit);
1236}
#define R2_MF_THRESHOLD
Definition dsp.c:204
#define R2_GSIZE
Definition dsp.c:236
#define R2_MF_TWIST
Definition dsp.c:205
#define R2_MF_RELATIVE_PEAK
Definition dsp.c:206

References 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, mute_fragment(), mf_detect_state_t::mute_samples, R2_GSIZE, R2_MF_RELATIVE_PEAK, R2_MF_THRESHOLD, R2_MF_TWIST, fragment_t::start, store_digit(), digit_detect_state_t::td, and mf_detect_state_t::tone_out.

Referenced by ast_dsp_process().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2654 of file dsp.c.

2655{
2656 return _dsp_init(1);
2657}

References _dsp_init().

◆ store_digit()

static void store_digit ( digit_detect_state_t s,
char  digit 
)
static

Definition at line 716 of file dsp.c.

717{
718 s->detected_digits++;
720 s->digitlen[s->current_digits] = 0;
721 s->digits[s->current_digits++] = digit;
722 s->digits[s->current_digits] = '\0';
723 } else {
724 ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
725 s->lost_digits++;
726 }
727}
#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(), mf_detect(), and r2_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 605 of file dsp.c.

606{
607 float tone_energy;
608 int i;
609 int hit = 0;
610 int limit;
611 int res = 0;
612 int16_t *ptr;
613 short samp;
614 int start, end;
615 fragment_t mute = {0, 0};
616
617 if (s->squelch && s->mute_samples > 0) {
618 mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
619 s->mute_samples -= mute.end;
620 }
621
622 for (start = 0; start < samples; start = end) {
623 /* Process in blocks. */
624 limit = samples - start;
625 if (limit > s->samples_pending) {
626 limit = s->samples_pending;
627 }
628 end = start + limit;
629
630 for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
631 samp = *ptr;
632 /* signed 32 bit int should be enough to square any possible signed 16 bit value */
633 s->energy += (int32_t) samp * (int32_t) samp;
634
635 goertzel_sample(&s->tone, samp);
636 }
637
638 s->samples_pending -= limit;
639
640 if (s->samples_pending) {
641 /* Finished incomplete (last) block */
642 break;
643 }
644
645 tone_energy = goertzel_result(&s->tone);
646
647 /* Scale to make comparable */
648 tone_energy *= 2.0;
649 s->energy *= s->block_size;
650
651 /* Add 1 to hit_count when logging, since it doesn't get incremented until later in the loop. */
652 if (TONE_THRESHOLD <= tone_energy
653 && tone_energy > s->energy * s->threshold) {
654 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));
655 hit = 1;
656 } else {
657 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));
658 hit = 0;
659 }
660
661 if (s->hit_count) {
662 s->hit_count++;
663 }
664
665 if (hit == s->last_hit) {
666 if (!hit) {
667 /* Two successive misses. Tone ended */
668 if (s->hit_count) {
669 ast_debug(9, "Partial detect expired after %d/%d hits\n", s->hit_count, s->hits_required);
670 }
671 s->hit_count = 0;
672 } else if (!s->hit_count) {
673 s->hit_count++;
674 }
675 }
676
677 if (s->hit_count == s->hits_required) {
678 ast_debug(1, "%d Hz tone detected\n", s->freq);
679 res = 1;
680 }
681
682 s->last_hit = hit;
683
684 /* If we had a hit in this block, include it into mute fragment */
685 if (s->squelch && hit) {
686 if (mute.end < start - s->block_size) {
687 /* There is a gap between fragments */
688 mute_fragment(dsp, &mute);
689 mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
690 }
691 mute.end = end + s->block_size;
692 }
693
694 /* Reinitialise the detector for the next block */
695 /* Reset for the next block */
696 goertzel_reset(&s->tone);
697
698 /* Advance to the next block */
699 s->energy = 0.0;
701
702 amp += limit;
703 }
704
705 if (s->squelch && mute.end) {
706 if (mute.end > samples) {
707 s->mute_samples = mute.end - samples;
708 mute.end = samples;
709 }
710 mute_fragment(dsp, &mute);
711 }
712
713 return res;
714}
#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 2634 of file dsp.c.

2635{
2636 AST_TEST_UNREGISTER(test_dsp_fax_detect);
2637 AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
2638
2639 return 0;
2640}
#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 2666 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 2666 of file dsp.c.

◆ bell_mf_positions

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

Definition at line 342 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 252 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 329 of file dsp.c.

329 {
330 1209.0, 1336.0, 1477.0, 1633.0
331};

Referenced by ast_dtmf_detect_init().

◆ dtmf_hits_to_begin

int dtmf_hits_to_begin
static

Definition at line 349 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_misses_to_end

int dtmf_misses_to_end
static

Definition at line 350 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_normal_twist

float dtmf_normal_twist
static

Definition at line 345 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 341 of file dsp.c.

Referenced by dtmf_detect().

◆ dtmf_reverse_twist

float dtmf_reverse_twist
static

Definition at line 346 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 326 of file dsp.c.

326 {
327 697.0, 770.0, 852.0, 941.0
328};

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 332 of file dsp.c.

332 {
333 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
334};

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().

◆ r2_backward_tones

const float r2_backward_tones[]
static
Initial value:
= {
1140.0, 1020.0, 900.0, 780.0, 660.0, 540.0
}

Definition at line 338 of file dsp.c.

338 {
339 1140.0, 1020.0, 900.0, 780.0, 660.0, 540.0
340};

Referenced by ast_r2_detect_init().

◆ r2_forward_tones

const float r2_forward_tones[]
static
Initial value:
= {
1380.0, 1500.0, 1620.0, 1740.0, 1860.0, 1980.0
}

Definition at line 335 of file dsp.c.

335 {
336 1380.0, 1500.0, 1620.0, 1740.0, 1860.0, 1980.0
337};

Referenced by ast_r2_detect_init().

◆ r2_mf_positions

const char r2_mf_positions[] = "1247B-358C--69D---0E----F"
static

Definition at line 343 of file dsp.c.

Referenced by ast_dsp_process().

◆ relax_dtmf_normal_twist

float relax_dtmf_normal_twist
static

Definition at line 347 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ relax_dtmf_reverse_twist

float relax_dtmf_reverse_twist
static

Definition at line 348 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ thresholds

int thresholds[THRESHOLD_MAX]
static

Definition at line 344 of file dsp.c.

Referenced by _dsp_init(), and ast_dsp_get_threshold_from_settings().