Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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,
101  HZ_440UK
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;
1166  case DSP_TONE_STATE_BUSY:
1167  if ((dsp->features & DSP_PROGRESS_BUSY) &&
1168  (dsp->tcount == THRESH_BUSY)) {
1169  res = AST_CONTROL_BUSY;
1171  }
1172  break;
1174  if ((dsp->features & DSP_PROGRESS_TALK) &&
1175  (dsp->tcount == THRESH_TALK)) {
1176  res = AST_CONTROL_ANSWER;
1178  }
1179  break;
1181  if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
1182  (dsp->tcount == THRESH_CONGESTION)) {
1183  res = AST_CONTROL_CONGESTION;
1185  }
1186  break;
1187  case DSP_TONE_STATE_HUNGUP:
1188  if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
1189  (dsp->tcount == THRESH_HANGUP)) {
1190  res = AST_CONTROL_HANGUP;
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;
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 1725 of file dsp.c.

1726 {
1727  struct ast_dsp *dsp;
1728 
1729  if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
1732  dsp->busycount = DSP_HISTORY;
1735  dsp->sample_rate = sample_rate;
1736  dsp->freqcount = 0;
1737  /* Initialize digit detector */
1739  dsp->display_inband_dtmf_warning = 1;
1740  /* Initialize initial DSP progress detect parameters */
1741  ast_dsp_prog_reset(dsp);
1742  /* Initialize fax detector */
1743  ast_fax_detect_init(dsp);
1744  }
1745  return dsp;
1746 }
#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:1703
#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 1232 of file dsp.c.

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

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2469 of file dsp.c.

◆ _dsp_init()

static int _dsp_init ( int  reload)
static

Definition at line 1911 of file dsp.c.

1912 {
1913  struct ast_config *cfg;
1914  struct ast_variable *v;
1915  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1916  int cfg_threshold;
1917  float cfg_twist;
1918 
1919  if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
1920  return 0;
1921  }
1922 
1930 
1932  return 0;
1933  }
1934 
1935  for (v = ast_variable_browse(cfg, "default"); v; v = v->next) {
1936  if (!strcasecmp(v->name, "silencethreshold")) {
1937  if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1938  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1939  } else if (cfg_threshold < 0) {
1940  ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
1941  } else {
1942  thresholds[THRESHOLD_SILENCE] = cfg_threshold;
1943  }
1944  } else if (!strcasecmp(v->name, "dtmf_normal_twist")) {
1945  if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1946  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1947  } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1948  ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
1949  } else {
1950  dtmf_normal_twist = cfg_twist;
1951  }
1952  } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) {
1953  if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1954  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1955  } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1956  ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
1957  } else {
1958  dtmf_reverse_twist = cfg_twist;
1959  }
1960  } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) {
1961  if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1962  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1963  } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1964  ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
1965  } else {
1966  relax_dtmf_normal_twist = cfg_twist;
1967  }
1968  } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) {
1969  if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1970  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1971  } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1972  ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
1973  } else {
1974  relax_dtmf_reverse_twist = cfg_twist;
1975  }
1976  } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) {
1977  if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1978  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1979  } else if (cfg_threshold < 1) { /* must be 1 or greater */
1980  ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
1981  } else {
1982  dtmf_hits_to_begin = cfg_threshold;
1983  }
1984  } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) {
1985  if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1986  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1987  } else if (cfg_threshold < 1) { /* must be 1 or greater */
1988  ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
1989  } else {
1990  dtmf_misses_to_end = cfg_threshold;
1991  }
1992  }
1993  }
1994  ast_config_destroy(cfg);
1995 
1996  return 0;
1997 }
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
#define CONFIG_STATUS_FILEMISSING
@ CONFIG_FLAG_FILEUNCHANGED
#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_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3220
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
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().

◆ 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
union digit_detect_state_t::@375 td
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

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

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

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\n");
1227  return 0;
1228  }
1229  return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
1230 }
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
Definition: dsp.c:1077
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::@254 data
enum ast_frame_type frametype

References __ast_dsp_call_progress(), ast_format_cache_is_slinear(), 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 1800 of file dsp.c.

1801 {
1802  int i;
1803 
1804  dsp->dtmf_began = 0;
1805  if (dsp->digitmode & DSP_DIGITMODE_MF) {
1806  mf_detect_state_t *s = &dsp->digit_state.td.mf;
1807  /* Reinitialise the detector for the next block */
1808  for (i = 0; i < 6; i++) {
1809  goertzel_reset(&s->tone_out[i]);
1810  }
1811  s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = 0;
1812  s->current_hit = 0;
1813  s->current_sample = 0;
1814  } else {
1816  /* Reinitialise the detector for the next block */
1817  for (i = 0; i < 4; i++) {
1818  goertzel_reset(&s->row_out[i]);
1819  goertzel_reset(&s->col_out[i]);
1820  }
1821  s->lasthit = 0;
1822  s->current_hit = 0;
1823  s->energy = 0.0;
1824  s->current_sample = 0;
1825  s->hits = 0;
1826  s->misses = 0;
1827  }
1828 
1829  dsp->digit_state.digits[0] = '\0';
1830  dsp->digit_state.current_digits = 0;
1831 }
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 1767 of file dsp.c.

1768 {
1769  return (dsp->features);
1770 }

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

1721 {
1722  return dsp->sample_rate;
1723 }

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

1907 {
1908  return dsp->tcount;
1909 }

References ast_dsp::tcount.

Referenced by dahdi_read(), and detect_callback().

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

2000 {
2001  return thresholds[which];
2002 }

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

1902 {
1903  return dsp->tstate;
1904 }

References ast_dsp::tstate.

Referenced by dahdi_read(), and detect_callback().

◆ ast_dsp_new()

struct ast_dsp* ast_dsp_new ( void  )

Allocates a new dsp, assumes 8khz for internal sample rate.

Definition at line 1748 of file dsp.c.

1749 {
1751 }
static struct ast_dsp * __ast_dsp_new(unsigned int sample_rate)
Definition: dsp.c:1725
#define DEFAULT_SAMPLE_RATE
Definition: dsp.c:223

References __ast_dsp_new(), and DEFAULT_SAMPLE_RATE.

Referenced by __ast_play_and_record(), ast_sip_session_alloc(), background_detect_exec(), conf_run(), dahdi_new(), detect_write(), do_waiting(), enable_dsp_detect(), fax_detect_new(), fax_session_new(), handle_recordfile(), isAnsweringMachine(), mbl_load_device(), mgcp_new(), my_dsp_set_digitmode(), ooh323_new(), pjsip_acf_dtmf_mode_write(), read_mf_digits(), read_sf_digits(), record_exec(), and wait_exec().

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

1754 {
1755  return __ast_dsp_new(sample_rate);
1756 }

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

1492 {
1493  return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
1494 }
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:1436
#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 1497 of file dsp.c.

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

◆ ast_dsp_prog_reset()

static void ast_dsp_prog_reset ( struct ast_dsp dsp)
static

Definition at line 1703 of file dsp.c.

1704 {
1705  int max = 0;
1706  int x;
1707 
1708  dsp->gsamp_size = modes[dsp->progmode].size;
1709  dsp->gsamps = 0;
1710  for (x = 0; x < FREQ_ARRAY_SIZE; x++) {
1711  if (modes[dsp->progmode].freqs[x]) {
1712  goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->sample_rate);
1713  max = x + 1;
1714  }
1715  }
1716  dsp->freqcount = max;
1717  dsp->ringtimeout = 0;
1718 }
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 1833 of file dsp.c.

1834 {
1835  int x;
1836 
1837  dsp->totalsilence = 0;
1838  dsp->gsamps = 0;
1839  for (x = 0; x < 4; x++) {
1840  dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1841  }
1842  memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1843  memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1844  dsp->ringtimeout = 0;
1845 }

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

1784 {
1785  if (cadences < 4) {
1786  cadences = 4;
1787  }
1788  if (cadences > DSP_HISTORY) {
1790  }
1791  dsp->busycount = cadences;
1792 }
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:622

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

1795 {
1796  dsp->busy_cadence = *cadence;
1797  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);
1798 }

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

1883 {
1884  int x;
1885 
1886  for (x = 0; x < ARRAY_LEN(aliases); x++) {
1887  if (!strcasecmp(aliases[x].name, zone)) {
1888  dsp->progmode = aliases[x].mode;
1889  ast_dsp_prog_reset(dsp);
1890  return 0;
1891  }
1892  }
1893  return -1;
1894 }
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:661

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

Referenced by dahdi_new().

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

1848 {
1849  int new;
1850  int old;
1851 
1854  if (old != new) {
1855  /* Must initialize structures if switching from MF to DTMF or vice-versa */
1857  }
1858  dsp->digitmode = digitmode;
1859  return 0;
1860 }
#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(), enable_dsp_detect(), mbl_load_device(), mgcp_new(), 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 1873 of file dsp.c.

1874 {
1875  if (dsp->faxmode != faxmode) {
1876  dsp->faxmode = faxmode;
1877  ast_fax_detect_init(dsp);
1878  }
1879  return 0;
1880 }

References ast_fax_detect_init(), and ast_dsp::faxmode.

Referenced by fax_detect_new(), and ooh323_new().

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

1863 {
1864  if (freq > 0) {
1865  dsp->freqmode = 1;
1866  ast_freq_detect_init(dsp, freq, dur, db, squelch);
1867  } else {
1868  dsp->freqmode = 0;
1869  }
1870  return 0;
1871 }
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(), 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 1778 of file dsp.c.

1779 {
1780  dsp->threshold = threshold;
1781 }

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

1487 {
1488  return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
1489 }

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

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

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

1482 {
1483  return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
1484 }

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

1897 {
1898  return (dsp->mute_fragments > 0);
1899 }

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 */
527  ast_tone_detect_init(&s->cng_tone_state, freq, dur, db, s->sample_rate);
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 2469 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 
492  s->samples_pending = s->block_size;
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++) {
885  goertzel_reset(&s->td.dtmf.row_out[i]);
886  goertzel_reset(&s->td.dtmf.col_out[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 }
static int mute
Definition: chan_alsa.c:148
#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, 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, mute_fragment(), dtmf_detect_state_t::mute_samples, relax_dtmf_normal_twist, relax_dtmf_reverse_twist, dtmf_detect_state_t::row_out, 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:349
#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 2445 of file dsp.c.

2446 {
2447  if (_dsp_init(0)) {
2448  return AST_MODULE_LOAD_FAILURE;
2449  }
2450 
2451  AST_TEST_REGISTER(test_dsp_fax_detect);
2452  AST_TEST_REGISTER(test_dsp_dtmf_detect);
2453 
2454  return AST_MODULE_LOAD_SUCCESS;
2455 }
static int _dsp_init(int reload)
Definition: dsp.c:1911
@ 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, goertzel_reset(), goertzel_result(), goertzel_sample(), mf_detect_state_t::hits, digit_detect_state_t::mf, MF_GSIZE, mute, mute_fragment(), mf_detect_state_t::mute_samples, 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 2457 of file dsp.c.

2458 {
2459  return _dsp_init(1);
2460 }

◆ 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++;
685  if (s->current_digits < MAX_DTMF_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;
666  s->samples_pending = s->block_size;
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, 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, mute_fragment(), tone_detect_state_t::mute_samples, tone_detect_state_t::samples_pending, tone_detect_state_t::squelch, 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 2437 of file dsp.c.

2438 {
2439  AST_TEST_UNREGISTER(test_dsp_fax_detect);
2440  AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
2441 
2442  return 0;
2443 }
#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 2457 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 2469 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().