Asterisk - The Open Source Telephony Project GIT-master-77d630f
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. More...
 
#define DSP_HISTORY   15
 
#define DTMF_GSIZE   102
 
#define DTMF_MATRIX_SIZE   4
 
#define DTMF_RELATIVE_PEAK_COL   6.3 /* 8dB */
 
#define DTMF_RELATIVE_PEAK_ROW   6.3 /* 8dB */
 
#define DTMF_THRESHOLD   8.0e7
 
#define DTMF_TO_TOTAL_ENERGY   42.0
 
#define FAX_TONE_CED_DB   16
 
#define FAX_TONE_CED_DURATION   2600 /* ms */
 
#define FAX_TONE_CED_FREQ   2100
 
#define FAX_TONE_CNG_DB   16
 
#define FAX_TONE_CNG_DURATION   500 /* ms */
 
#define FAX_TONE_CNG_FREQ   1100
 
#define FREQ_ARRAY_SIZE   7
 
#define MAX_DTMF_DIGITS   128
 
#define MF_GSIZE   120
 
#define TONE_MIN_THRESH   1e8
 
#define TONE_THRESH   10.0
 
#define TONE_THRESHOLD   7.8e7
 

Enumerations

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

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "DSP" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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. More...
 
static const float dtmf_col []
 
static int dtmf_hits_to_begin
 
static int dtmf_misses_to_end
 
static float dtmf_normal_twist
 
static const char dtmf_positions [] = "123A" "456B" "789C" "*0#D"
 
static float dtmf_reverse_twist
 
static const float dtmf_row []
 
static const float mf_tones []
 
static struct progress modes []
 
static float relax_dtmf_normal_twist
 
static float relax_dtmf_reverse_twist
 
static int thresholds [THRESHOLD_MAX]
 

Detailed Description

Convenience Signal Processing routines.

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

Definition in file dsp.c.

Macro Definition Documentation

◆ BELL_MF_RELATIVE_PEAK

#define BELL_MF_RELATIVE_PEAK   12.6 /* 11dB */

Definition at line 202 of file dsp.c.

◆ BELL_MF_THRESHOLD

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 200 of file dsp.c.

◆ BELL_MF_TWIST

#define BELL_MF_TWIST   4.0 /* 6dB */

Definition at line 201 of file dsp.c.

◆ CONFIG_FILE_NAME

#define CONFIG_FILE_NAME   "dsp.conf"

Definition at line 247 of file dsp.c.

◆ DEF_DTMF_HITS_TO_BEGIN

#define DEF_DTMF_HITS_TO_BEGIN   2

Definition at line 234 of file dsp.c.

◆ DEF_DTMF_MISSES_TO_END

#define DEF_DTMF_MISSES_TO_END   3

Definition at line 239 of file dsp.c.

◆ DEF_DTMF_NORMAL_TWIST

#define DEF_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */

Definition at line 185 of file dsp.c.

◆ DEF_DTMF_REVERSE_TWIST

#define DEF_DTMF_REVERSE_TWIST   2.51 /* 4.01dB */

Definition at line 192 of file dsp.c.

◆ DEF_RELAX_DTMF_NORMAL_TWIST

#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */

Definition at line 186 of file dsp.c.

◆ DEF_RELAX_DTMF_REVERSE_TWIST

#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98 /* 6.0dB */

Definition at line 193 of file dsp.c.

◆ DEFAULT_SAMPLE_RATE

#define DEFAULT_SAMPLE_RATE   8000

Definition at line 223 of file dsp.c.

◆ DEFAULT_THRESHOLD

#define DEFAULT_THRESHOLD   512

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

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

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

Definition at line 140 of file dsp.c.

◆ DSP_HISTORY

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 151 of file dsp.c.

◆ DTMF_GSIZE

#define DTMF_GSIZE   102

Definition at line 229 of file dsp.c.

◆ DTMF_MATRIX_SIZE

#define DTMF_MATRIX_SIZE   4

Definition at line 168 of file dsp.c.

◆ DTMF_RELATIVE_PEAK_COL

#define DTMF_RELATIVE_PEAK_COL   6.3 /* 8dB */

Definition at line 197 of file dsp.c.

◆ DTMF_RELATIVE_PEAK_ROW

#define DTMF_RELATIVE_PEAK_ROW   6.3 /* 8dB */

Definition at line 196 of file dsp.c.

◆ DTMF_THRESHOLD

#define DTMF_THRESHOLD   8.0e7

Definition at line 182 of file dsp.c.

◆ DTMF_TO_TOTAL_ENERGY

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 198 of file dsp.c.

◆ FAX_TONE_CED_DB

#define FAX_TONE_CED_DB   16

Definition at line 221 of file dsp.c.

◆ FAX_TONE_CED_DURATION

#define FAX_TONE_CED_DURATION   2600 /* ms */

Definition at line 220 of file dsp.c.

◆ FAX_TONE_CED_FREQ

#define FAX_TONE_CED_FREQ   2100

Definition at line 219 of file dsp.c.

◆ FAX_TONE_CNG_DB

#define FAX_TONE_CNG_DB   16

Definition at line 213 of file dsp.c.

◆ FAX_TONE_CNG_DURATION

#define FAX_TONE_CNG_DURATION   500 /* ms */

Definition at line 212 of file dsp.c.

◆ FAX_TONE_CNG_FREQ

#define FAX_TONE_CNG_FREQ   1100

Definition at line 211 of file dsp.c.

◆ FREQ_ARRAY_SIZE

#define FREQ_ARRAY_SIZE   7

Definition at line 115 of file dsp.c.

◆ MAX_DTMF_DIGITS

#define MAX_DTMF_DIGITS   128

Definition at line 166 of file dsp.c.

◆ MF_GSIZE

#define MF_GSIZE   120

Definition at line 226 of file dsp.c.

◆ TONE_MIN_THRESH

#define TONE_MIN_THRESH   1e8

How much tone there should be at least to attempt

Definition at line 154 of file dsp.c.

◆ TONE_THRESH

#define TONE_THRESH   10.0

How much louder the tone should be than channel energy

Definition at line 153 of file dsp.c.

◆ TONE_THRESHOLD

#define TONE_THRESHOLD   7.8e7

Definition at line 183 of file dsp.c.

Enumeration Type Documentation

◆ busy_detect

Enumerator
BUSY_PERCENT 

The percentage difference between the two last silence periods

BUSY_PAT_PERCENT 

The percentage difference between measured and actual pattern

BUSY_THRESHOLD 

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

BUSY_MIN 

Busy must be at least 80 ms in half-cadence

BUSY_MAX 

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

Definition at line 142 of file dsp.c.

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

◆ freq_index

enum freq_index
Enumerator
HZ_350 

For US modes {

HZ_440 
HZ_480 
HZ_620 
HZ_950 
HZ_1400 
HZ_1800 

}

HZ_425 

For CR/BR modes

HZ_350UK 

For UK mode

HZ_400UK 
HZ_440UK 

Definition at line 85 of file dsp.c.

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

◆ gsamp_size

enum gsamp_size

Number of goertzels for progress detect

Enumerator
GSAMP_SIZE_NA 

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

GSAMP_SIZE_CR 

Costa Rica, Brazil - Only care about 425 Hz

GSAMP_SIZE_UK 

UK disconnect goertzel feed - should trigger 400hz

Definition at line 73 of file dsp.c.

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

◆ gsamp_thresh

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

Enumerator
THRESH_RING 

Need at least 150ms ring to accept

THRESH_TALK 

Talk detection does not work continuously

THRESH_BUSY 

Need at least 80ms to accept

THRESH_CONGESTION 

Need at least 80ms to accept

THRESH_HANGUP 

Need at least 1300ms to accept hangup

THRESH_RING2ANSWER 

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

Definition at line 157 of file dsp.c.

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

◆ prog_mode

enum prog_mode
Enumerator
PROG_MODE_NA 
PROG_MODE_CR 
PROG_MODE_UK 

Definition at line 79 of file dsp.c.

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

Function Documentation

◆ __ast_dsp_call_progress()

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

Definition at line 1079 of file dsp.c.

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

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

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

◆ __ast_dsp_new()

static struct ast_dsp * __ast_dsp_new ( unsigned int  sample_rate)
static

Definition at line 1737 of file dsp.c.

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

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

Referenced by ast_dsp_new(), and ast_dsp_new_with_rate().

◆ __ast_dsp_silence_noise()

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

Definition at line 1235 of file dsp.c.

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

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

Referenced by ast_dsp_process(), and ast_dsp_silence_noise_with_energy().

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2481 of file dsp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2481 of file dsp.c.

◆ _dsp_init()

static int _dsp_init ( int  reload)
static

Definition at line 1923 of file dsp.c.

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

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

Referenced by load_module(), and reload_module().

◆ ast_digit_detect_init()

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

Definition at line 561 of file dsp.c.

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

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

Referenced by __ast_dsp_new(), and ast_dsp_set_digitmode().

◆ ast_dsp_busydetect()

int ast_dsp_busydetect ( struct ast_dsp dsp)

Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called.

Definition at line 1301 of file dsp.c.

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

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

Referenced by ast_dsp_process().

◆ ast_dsp_call_progress()

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

Definition at line 1221 of file dsp.c.

1222{
1223 if (inf->frametype != AST_FRAME_VOICE) {
1224 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1225 return 0;
1226 }
1228 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames, %s not supported\n",
1230 return 0;
1231 }
1232 return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
1233}
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
Definition: dsp.c:1079
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.
Definition: format_cache.c:534
@ AST_FRAME_VOICE
struct ast_format * format
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@231 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 1812 of file dsp.c.

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

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

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

◆ ast_dsp_free()

void ast_dsp_free ( struct ast_dsp dsp)

◆ ast_dsp_get_features()

int ast_dsp_get_features ( struct ast_dsp dsp)

Get features.

Definition at line 1779 of file dsp.c.

1780{
1781 return (dsp->features);
1782}

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

1733{
1734 return dsp->sample_rate;
1735}

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

1919{
1920 return dsp->tcount;
1921}

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

2012{
2013 return thresholds[which];
2014}

References thresholds.

Referenced by actual_load_config(), app_exec(), ast_record_review(), conf_rec_name(), conf_run(), do_waiting(), handle_recordfile(), 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 1913 of file dsp.c.

1914{
1915 return dsp->tstate;
1916}

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

1766{
1767 return __ast_dsp_new(sample_rate);
1768}

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

1496{
1497 return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
1498}
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:1439
#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 1501 of file dsp.c.

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

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

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

◆ ast_dsp_prog_reset()

static void ast_dsp_prog_reset ( struct ast_dsp dsp)
static

Definition at line 1715 of file dsp.c.

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

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

Referenced by __ast_dsp_new(), and ast_dsp_set_call_progress_zone().

◆ ast_dsp_reset()

void ast_dsp_reset ( struct ast_dsp dsp)

Reset total silence count.

Definition at line 1845 of file dsp.c.

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

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

1796{
1797 if (cadences < 4) {
1798 cadences = 4;
1799 }
1800 if (cadences > DSP_HISTORY) {
1802 }
1803 dsp->busycount = cadences;
1804}
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:765

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

1807{
1808 dsp->busy_cadence = *cadence;
1809 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);
1810}

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

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

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

Referenced by dahdi_new(), and scan_exec().

◆ ast_dsp_set_digitmode()

int ast_dsp_set_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Version
1.6.1 renamed from ast_dsp_digitmode to ast_dsp_set_digitmode

Definition at line 1859 of file dsp.c.

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

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

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

◆ ast_dsp_set_faxmode()

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1885 of file dsp.c.

1886{
1887 if (dsp->faxmode != faxmode) {
1888 dsp->faxmode = faxmode;
1890 }
1891 return 0;
1892}

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

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

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

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

◆ ast_dsp_set_threshold()

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

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

Definition at line 1790 of file dsp.c.

1791{
1792 dsp->threshold = threshold;
1793}

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

1491{
1492 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
1493}

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

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

1486{
1487 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
1488}

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

1909{
1910 return (dsp->mute_fragments > 0);
1911}

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

◆ ast_dtmf_detect_init()

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

Definition at line 533 of file dsp.c.

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

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

Referenced by ast_digit_detect_init().

◆ ast_fax_detect_init()

static void ast_fax_detect_init ( struct ast_dsp s)
static

Definition at line 513 of file dsp.c.

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

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

Referenced by __ast_dsp_new(), and ast_dsp_set_faxmode().

◆ ast_freq_detect_init()

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

Definition at line 524 of file dsp.c.

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

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

Referenced by ast_dsp_set_freqmode().

◆ ast_mf_detect_init()

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

Definition at line 549 of file dsp.c.

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

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

Referenced by ast_digit_detect_init().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 2481 of file dsp.c.

◆ ast_tone_detect_init()

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

Definition at line 452 of file dsp.c.

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

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

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

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

Referenced by ast_dsp_process().

◆ goertzel_init()

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

Definition at line 378 of file dsp.c.

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

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

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

◆ goertzel_reset()

static void goertzel_reset ( goertzel_state_t s)
inlinestatic

Definition at line 384 of file dsp.c.

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

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

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

◆ goertzel_result()

static float goertzel_result ( goertzel_state_t s)
inlinestatic

Definition at line 364 of file dsp.c.

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

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

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

◆ goertzel_sample()

static void goertzel_sample ( goertzel_state_t s,
short  sample 
)
inlinestatic

Definition at line 338 of file dsp.c.

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

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

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

◆ load_module()

static int load_module ( void  )
static

Definition at line 2457 of file dsp.c.

2458{
2459 if (_dsp_init(0)) {
2461 }
2462
2463 AST_TEST_REGISTER(test_dsp_fax_detect);
2464 AST_TEST_REGISTER(test_dsp_dtmf_detect);
2465
2467}
static int _dsp_init(int reload)
Definition: dsp.c:1923
@ 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 905 of file dsp.c.

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

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

Referenced by ast_dsp_process().

◆ mute_fragment()

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

Definition at line 442 of file dsp.c.

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

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

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

◆ pair_there()

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

Definition at line 1056 of file dsp.c.

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

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2469 of file dsp.c.

2470{
2471 return _dsp_init(1);
2472}

References _dsp_init().

◆ store_digit()

static void store_digit ( digit_detect_state_t s,
char  digit 
)
static

Definition at line 684 of file dsp.c.

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

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

Referenced by dtmf_detect(), and mf_detect().

◆ tone_detect()

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

Definition at line 575 of file dsp.c.

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

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

2450{
2451 AST_TEST_UNREGISTER(test_dsp_fax_detect);
2452 AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
2453
2454 return 0;
2455}
#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 = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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 2481 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 2481 of file dsp.c.

◆ bell_mf_positions

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

Definition at line 329 of file dsp.c.

Referenced by mf_detect().

◆ DEFAULT_SILENCE_THRESHOLD

const int DEFAULT_SILENCE_THRESHOLD = 256
static

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

Definition at line 245 of file dsp.c.

Referenced by _dsp_init().

◆ dtmf_col

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

Definition at line 322 of file dsp.c.

Referenced by ast_dtmf_detect_init().

◆ dtmf_hits_to_begin

int dtmf_hits_to_begin
static

Definition at line 335 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_misses_to_end

int dtmf_misses_to_end
static

Definition at line 336 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_normal_twist

float dtmf_normal_twist
static

Definition at line 331 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_positions

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

Definition at line 328 of file dsp.c.

Referenced by dtmf_detect().

◆ dtmf_reverse_twist

float dtmf_reverse_twist
static

Definition at line 332 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_row

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

Definition at line 319 of file dsp.c.

Referenced by ast_dtmf_detect_init().

◆ mf_tones

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

Definition at line 325 of file dsp.c.

Referenced by ast_mf_detect_init(), and ast_senddigit_mf_begin().

◆ modes

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

Referenced by ast_dsp_prog_reset().

◆ relax_dtmf_normal_twist

float relax_dtmf_normal_twist
static

Definition at line 333 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ relax_dtmf_reverse_twist

float relax_dtmf_reverse_twist
static

Definition at line 334 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ thresholds

int thresholds[THRESHOLD_MAX]
static

Definition at line 330 of file dsp.c.

Referenced by _dsp_init(), and ast_dsp_get_threshold_from_settings().