Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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 1077 of file dsp.c.

1078{
1079 short samp;
1080 int x;
1081 int y;
1082 int pass;
1083 int newstate = DSP_TONE_STATE_SILENCE;
1084 int res = 0;
1085 int freqcount = dsp->freqcount > FREQ_ARRAY_SIZE ? FREQ_ARRAY_SIZE : dsp->freqcount;
1086
1087 while (len) {
1088 /* Take the lesser of the number of samples we need and what we have */
1089 pass = len;
1090 if (pass > dsp->gsamp_size - dsp->gsamps) {
1091 pass = dsp->gsamp_size - dsp->gsamps;
1092 }
1093 for (x = 0; x < pass; x++) {
1094 samp = s[x];
1095 dsp->genergy += (int32_t) samp * (int32_t) samp;
1096 for (y = 0; y < freqcount; y++) {
1097 goertzel_sample(&dsp->freqs[y], samp);
1098 }
1099 }
1100 s += pass;
1101 dsp->gsamps += pass;
1102 len -= pass;
1103 if (dsp->gsamps == dsp->gsamp_size) {
1104 float hz[FREQ_ARRAY_SIZE];
1105 for (y = 0; y < FREQ_ARRAY_SIZE; y++) {
1106 hz[y] = goertzel_result(&dsp->freqs[y]);
1107 }
1108 switch (dsp->progmode) {
1109 case PROG_MODE_NA:
1110 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
1111 newstate = DSP_TONE_STATE_BUSY;
1112 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
1113 newstate = DSP_TONE_STATE_RINGING;
1114 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
1115 newstate = DSP_TONE_STATE_DIALTONE;
1116 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
1117 newstate = DSP_TONE_STATE_SPECIAL1;
1118 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
1119 /* End of SPECIAL1 or middle of SPECIAL2 */
1121 newstate = DSP_TONE_STATE_SPECIAL2;
1122 }
1123 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
1124 /* End of SPECIAL2 or middle of SPECIAL3 */
1126 newstate = DSP_TONE_STATE_SPECIAL3;
1127 }
1128 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1129 newstate = DSP_TONE_STATE_TALKING;
1130 } else {
1131 newstate = DSP_TONE_STATE_SILENCE;
1132 }
1133 break;
1134 case PROG_MODE_CR:
1135 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
1136 newstate = DSP_TONE_STATE_RINGING;
1137 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1138 newstate = DSP_TONE_STATE_TALKING;
1139 } else {
1140 newstate = DSP_TONE_STATE_SILENCE;
1141 }
1142 break;
1143 case PROG_MODE_UK:
1144 if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
1145 newstate = DSP_TONE_STATE_HUNGUP;
1146 } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
1147 newstate = DSP_TONE_STATE_DIALTONE;
1148 }
1149 break;
1150 default:
1151 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%u'\n", dsp->progmode);
1152 }
1153 if (newstate == dsp->tstate) {
1154 dsp->tcount++;
1155 if (dsp->ringtimeout) {
1156 dsp->ringtimeout++;
1157 }
1158 switch (dsp->tstate) {
1160 if ((dsp->features & DSP_PROGRESS_RINGING) &&
1161 (dsp->tcount == THRESH_RING)) {
1162 res = AST_CONTROL_RINGING;
1163 dsp->ringtimeout = 1;
1164 }
1165 break;
1167 if ((dsp->features & DSP_PROGRESS_BUSY) &&
1168 (dsp->tcount == THRESH_BUSY)) {
1169 res = AST_CONTROL_BUSY;
1170 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1171 }
1172 break;
1174 if ((dsp->features & DSP_PROGRESS_TALK) &&
1175 (dsp->tcount == THRESH_TALK)) {
1176 res = AST_CONTROL_ANSWER;
1177 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1178 }
1179 break;
1181 if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
1182 (dsp->tcount == THRESH_CONGESTION)) {
1184 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1185 }
1186 break;
1188 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
1189 (dsp->tcount == THRESH_HANGUP)) {
1190 res = AST_CONTROL_HANGUP;
1191 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1192 }
1193 break;
1194 }
1195 if (dsp->ringtimeout == THRESH_RING2ANSWER) {
1196 ast_debug(1, "Consider call as answered because of timeout after last ring\n");
1197 res = AST_CONTROL_ANSWER;
1198 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1199 }
1200 } else {
1201 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
1202 ast_debug(5, "Start state %d\n", newstate);
1203 dsp->tstate = newstate;
1204 dsp->tcount = 1;
1205 }
1206
1207 /* Reset goertzel */
1208 for (x = 0; x < 7; x++) {
1209 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1210 }
1211 dsp->gsamps = 0;
1212 dsp->genergy = 0.0;
1213 }
1214 }
1215
1216 return res;
1217}
#define ast_log
Definition: astobj2.c:42
int int32_t
Definition: db.h:60
#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:1054
#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 1735 of file dsp.c.

1736{
1737 struct ast_dsp *dsp;
1738
1739 if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
1742 dsp->busycount = DSP_HISTORY;
1745 dsp->sample_rate = sample_rate;
1746 dsp->freqcount = 0;
1747 /* Initialize digit detector */
1750 /* Initialize initial DSP progress detect parameters */
1751 ast_dsp_prog_reset(dsp);
1752 /* Initialize fax detector */
1754 }
1755 return dsp;
1756}
#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:1713
#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 1233 of file dsp.c.

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

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2479 of file dsp.c.

◆ _dsp_init()

static int _dsp_init ( int  reload)
static

Definition at line 1921 of file dsp.c.

1922{
1923 struct ast_config *cfg;
1924 struct ast_variable *v;
1925 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1926 int cfg_threshold;
1927 float cfg_twist;
1928
1929 if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
1930 return 0;
1931 }
1932
1940
1942 return 0;
1943 }
1944
1945 for (v = ast_variable_browse(cfg, "default"); v; v = v->next) {
1946 if (!strcasecmp(v->name, "silencethreshold")) {
1947 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1948 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1949 } else if (cfg_threshold < 0) {
1950 ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
1951 } else {
1952 thresholds[THRESHOLD_SILENCE] = cfg_threshold;
1953 }
1954 } else if (!strcasecmp(v->name, "dtmf_normal_twist")) {
1955 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1956 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1957 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1958 ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
1959 } else {
1960 dtmf_normal_twist = cfg_twist;
1961 }
1962 } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) {
1963 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1964 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1965 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1966 ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
1967 } else {
1968 dtmf_reverse_twist = cfg_twist;
1969 }
1970 } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) {
1971 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1972 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1973 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1974 ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
1975 } else {
1976 relax_dtmf_normal_twist = cfg_twist;
1977 }
1978 } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) {
1979 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1980 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1981 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1982 ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
1983 } else {
1984 relax_dtmf_reverse_twist = cfg_twist;
1985 }
1986 } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) {
1987 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1988 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1989 } else if (cfg_threshold < 1) { /* must be 1 or greater */
1990 ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
1991 } else {
1992 dtmf_hits_to_begin = cfg_threshold;
1993 }
1994 } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) {
1995 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1996 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1997 } else if (cfg_threshold < 1) { /* must be 1 or greater */
1998 ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
1999 } else {
2000 dtmf_misses_to_end = cfg_threshold;
2001 }
2002 }
2003 }
2004 ast_config_destroy(cfg);
2005
2006 return 0;
2007}
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:3321
#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:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
static int reload(void)
Structure used to handle boolean flags.
Definition: utils.h:199
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
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
union digit_detect_state_t::@345 td

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

Referenced by __ast_dsp_new(), and ast_dsp_set_digitmode().

◆ ast_dsp_busydetect()

int ast_dsp_busydetect ( struct ast_dsp dsp)

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

Definition at line 1299 of file dsp.c.

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

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

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

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

1811{
1812 int i;
1813
1814 dsp->dtmf_began = 0;
1815 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1817 /* Reinitialise the detector for the next block */
1818 for (i = 0; i < 6; i++) {
1819 goertzel_reset(&s->tone_out[i]);
1820 }
1821 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = 0;
1822 s->current_hit = 0;
1823 s->current_sample = 0;
1824 } else {
1826 /* Reinitialise the detector for the next block */
1827 for (i = 0; i < 4; i++) {
1828 goertzel_reset(&s->row_out[i]);
1829 goertzel_reset(&s->col_out[i]);
1830 }
1831 s->lasthit = 0;
1832 s->current_hit = 0;
1833 s->energy = 0.0;
1834 s->current_sample = 0;
1835 s->hits = 0;
1836 s->misses = 0;
1837 }
1838
1839 dsp->digit_state.digits[0] = '\0';
1840 dsp->digit_state.current_digits = 0;
1841}
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 1777 of file dsp.c.

1778{
1779 return (dsp->features);
1780}

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

1731{
1732 return dsp->sample_rate;
1733}

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

1917{
1918 return dsp->tcount;
1919}

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

2010{
2011 return thresholds[which];
2012}

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

1912{
1913 return dsp->tstate;
1914}

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

1764{
1765 return __ast_dsp_new(sample_rate);
1766}

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

1494{
1495 return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
1496}
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:1437
#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 1499 of file dsp.c.

1500{
1501 int silence;
1502 int res;
1503 int digit = 0, fax_digit = 0, custom_freq_digit = 0;
1504 int x;
1505 short *shortdata;
1506 unsigned char *odata;
1507 int len;
1508 struct ast_frame *outf = NULL;
1509
1510 if (!af) {
1511 return NULL;
1512 }
1513 if (af->frametype != AST_FRAME_VOICE) {
1514 return af;
1515 }
1516
1517 odata = af->data.ptr;
1518 len = af->datalen;
1519 /* Make sure we have short data */
1521 shortdata = af->data.ptr;
1522 len = af->datalen / 2;
1524 shortdata = ast_alloca(af->datalen * 2);
1525 for (x = 0; x < len; x++) {
1526 shortdata[x] = AST_MULAW(odata[x]);
1527 }
1529 shortdata = ast_alloca(af->datalen * 2);
1530 for (x = 0; x < len; x++) {
1531 shortdata[x] = AST_ALAW(odata[x]);
1532 }
1533 } else {
1534 /* Display warning only once. Otherwise you would get hundreds of warnings every second */
1535 if (dsp->display_inband_dtmf_warning) {
1536 /* If DTMF is enabled for the DSP, try to be helpful and warn about that specifically,
1537 * otherwise emit a more generic message that covers all other cases. */
1539 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n",
1541 } else {
1542 ast_log(LOG_WARNING, "Can only do DSP on signed-linear, alaw or ulaw frames (%s not supported)\n",
1544 }
1545 }
1547 return af;
1548 }
1549
1550 /* Initially we do not want to mute anything */
1551 dsp->mute_fragments = 0;
1552
1553 /* Need to run the silence detection stuff for silence suppression and busy detection */
1555 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL, NULL);
1556 }
1557
1558 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
1559 memset(&dsp->f, 0, sizeof(dsp->f));
1560 dsp->f.frametype = AST_FRAME_NULL;
1561 ast_frfree(af);
1562 return ast_frisolate(&dsp->f);
1563 }
1566 memset(&dsp->f, 0, sizeof(dsp->f));
1569 ast_frfree(af);
1570 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", ast_channel_name(chan));
1571 return ast_frisolate(&dsp->f);
1572 }
1573
1574 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
1575 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1576 fax_digit = 'f';
1577 }
1578
1579 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
1580 fax_digit = 'e';
1581 }
1582 }
1583
1584 if ((dsp->features & DSP_FEATURE_FREQ_DETECT)) {
1585 if ((dsp->freqmode) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1586 custom_freq_digit = 'q';
1587 }
1588 }
1589
1591 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1592 digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1593 } else {
1594 digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1595 }
1596
1597 if (dsp->digit_state.current_digits) {
1598 int event = 0, event_len = 0;
1599 char event_digit = 0;
1600
1601 if (!dsp->dtmf_began) {
1602 /* We have not reported DTMF_BEGIN for anything yet */
1603
1605 event = AST_FRAME_DTMF_BEGIN;
1606 event_digit = dsp->digit_state.digits[0];
1607 }
1608 dsp->dtmf_began = 1;
1609
1610 } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
1611 /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
1613 event = AST_FRAME_DTMF_END;
1614 event_digit = dsp->digit_state.digits[0];
1615 event_len = dsp->digit_state.digitlen[0] * 1000 / dsp->sample_rate;
1616 }
1617 memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
1618 memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
1620 dsp->dtmf_began = 0;
1621
1622 if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
1623 /* Reset Busy Detector as we have some confirmed activity */
1624 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1625 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1626 ast_debug(1, "DTMF Detected - Reset busydetector\n");
1627 }
1628 }
1629
1630 if (event) {
1631 memset(&dsp->f, 0, sizeof(dsp->f));
1632 dsp->f.frametype = event;
1633 dsp->f.subclass.integer = event_digit;
1634 dsp->f.len = event_len;
1635 outf = &dsp->f;
1636 goto done;
1637 }
1638 }
1639 }
1640
1641 if (fax_digit) {
1642 /* Fax was detected - digit is either 'f' or 'e' */
1643
1644 memset(&dsp->f, 0, sizeof(dsp->f));
1645 dsp->f.frametype = AST_FRAME_DTMF;
1646 dsp->f.subclass.integer = fax_digit;
1647 outf = &dsp->f;
1648 goto done;
1649 }
1650
1651 if (custom_freq_digit) {
1652 /* Custom frequency was detected - digit is 'q' */
1653
1654 memset(&dsp->f, 0, sizeof(dsp->f));
1655 dsp->f.frametype = AST_FRAME_DTMF;
1656 dsp->f.subclass.integer = custom_freq_digit;
1657 outf = &dsp->f;
1658 goto done;
1659 }
1660
1661 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
1662 res = __ast_dsp_call_progress(dsp, shortdata, len);
1663 if (res) {
1664 switch (res) {
1665 case AST_CONTROL_ANSWER:
1666 case AST_CONTROL_BUSY:
1669 case AST_CONTROL_HANGUP:
1670 memset(&dsp->f, 0, sizeof(dsp->f));
1672 dsp->f.subclass.integer = res;
1673 dsp->f.src = "dsp_progress";
1674 if (chan) {
1675 ast_queue_frame(chan, &dsp->f);
1676 }
1677 break;
1678 default:
1679 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
1680 }
1681 }
1682 } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
1683 res = __ast_dsp_call_progress(dsp, shortdata, len);
1684 }
1685
1686done:
1687 /* Mute fragment of the frame */
1688 for (x = 0; x < dsp->mute_fragments; x++) {
1689 memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
1690 }
1691
1693 for (x = 0; x < len; x++) {
1694 odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
1695 }
1697 for (x = 0; x < len; x++) {
1698 odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
1699 }
1700 }
1701
1702 if (outf) {
1703 if (chan) {
1704 ast_queue_frame(chan, af);
1705 }
1706 ast_frfree(af);
1707 return ast_frisolate(outf);
1708 } else {
1709 return af;
1710 }
1711}
#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:1139
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121
short int16_t
Definition: db.h:59
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:903
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:695
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:1299
static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
Definition: dsp.c:1233
#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 1713 of file dsp.c.

1714{
1715 int max = 0;
1716 int x;
1717
1718 dsp->gsamp_size = modes[dsp->progmode].size;
1719 dsp->gsamps = 0;
1720 for (x = 0; x < FREQ_ARRAY_SIZE; x++) {
1721 if (modes[dsp->progmode].freqs[x]) {
1722 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->sample_rate);
1723 max = x + 1;
1724 }
1725 }
1726 dsp->freqcount = max;
1727 dsp->ringtimeout = 0;
1728}
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 1843 of file dsp.c.

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

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

1794{
1795 if (cadences < 4) {
1796 cadences = 4;
1797 }
1798 if (cadences > DSP_HISTORY) {
1800 }
1801 dsp->busycount = cadences;
1802}
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:690

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

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

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

1893{
1894 int x;
1895
1896 for (x = 0; x < ARRAY_LEN(aliases); x++) {
1897 if (!strcasecmp(aliases[x].name, zone)) {
1898 dsp->progmode = aliases[x].mode;
1899 ast_dsp_prog_reset(dsp);
1900 return 0;
1901 }
1902 }
1903 return -1;
1904}
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:666

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

1858{
1859 int new;
1860 int old;
1861
1864 if (old != new) {
1865 /* Must initialize structures if switching from MF to DTMF or vice-versa */
1867 }
1868 dsp->digitmode = digitmode;
1869 return 0;
1870}
#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 1883 of file dsp.c.

1884{
1885 if (dsp->faxmode != faxmode) {
1886 dsp->faxmode = faxmode;
1888 }
1889 return 0;
1890}

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

1873{
1874 if (freq > 0) {
1875 dsp->freqmode = 1;
1876 ast_freq_detect_init(dsp, freq, dur, db, squelch);
1877 } else {
1878 dsp->freqmode = 0;
1879 }
1880 return 0;
1881}
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 1788 of file dsp.c.

1789{
1790 dsp->threshold = threshold;
1791}

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

1489{
1490 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
1491}

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

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

1484{
1485 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
1486}

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

1907{
1908 return (dsp->mute_fragments > 0);
1909}

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

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

2456{
2457 if (_dsp_init(0)) {
2459 }
2460
2461 AST_TEST_REGISTER(test_dsp_fax_detect);
2462 AST_TEST_REGISTER(test_dsp_dtmf_detect);
2463
2465}
static int _dsp_init(int reload)
Definition: dsp.c:1921
@ 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 903 of file dsp.c.

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

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

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2467 of file dsp.c.

2468{
2469 return _dsp_init(1);
2470}

References _dsp_init().

◆ store_digit()

static void store_digit ( digit_detect_state_t s,
char  digit 
)
static

Definition at line 682 of file dsp.c.

683{
684 s->detected_digits++;
686 s->digitlen[s->current_digits] = 0;
687 s->digits[s->current_digits++] = digit;
688 s->digits[s->current_digits] = '\0';
689 } else {
690 ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
691 s->lost_digits++;
692 }
693}
#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 ast_debug(10, "%d Hz tone %2d Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
622 hit = 0;
623 if (TONE_THRESHOLD <= tone_energy
624 && tone_energy > s->energy * s->threshold) {
625 ast_debug(10, "%d Hz tone Hit! %2d Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
626 hit = 1;
627 }
628
629 if (s->hit_count) {
630 s->hit_count++;
631 }
632
633 if (hit == s->last_hit) {
634 if (!hit) {
635 /* Two successive misses. Tone ended */
636 s->hit_count = 0;
637 } else if (!s->hit_count) {
638 s->hit_count++;
639 }
640
641 }
642
643 if (s->hit_count == s->hits_required) {
644 ast_debug(1, "%d Hz tone detected\n", s->freq);
645 res = 1;
646 }
647
648 s->last_hit = hit;
649
650 /* If we had a hit in this block, include it into mute fragment */
651 if (s->squelch && hit) {
652 if (mute.end < start - s->block_size) {
653 /* There is a gap between fragments */
654 mute_fragment(dsp, &mute);
655 mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
656 }
657 mute.end = end + s->block_size;
658 }
659
660 /* Reinitialise the detector for the next block */
661 /* Reset for the next block */
662 goertzel_reset(&s->tone);
663
664 /* Advance to the next block */
665 s->energy = 0.0;
667
668 amp += limit;
669 }
670
671 if (s->squelch && mute.end) {
672 if (mute.end > samples) {
673 s->mute_samples = mute.end - samples;
674 mute.end = samples;
675 }
676 mute_fragment(dsp, &mute);
677 }
678
679 return res;
680}
#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 2447 of file dsp.c.

2448{
2449 AST_TEST_UNREGISTER(test_dsp_fax_detect);
2450 AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
2451
2452 return 0;
2453}
#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 2479 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 2479 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().