Asterisk - The Open Source Telephony Project  GIT-master-9ed6387
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"

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

Referenced by mf_detect().

◆ BELL_MF_THRESHOLD

#define BELL_MF_THRESHOLD   1.6e9

Definition at line 198 of file dsp.c.

Referenced by mf_detect().

◆ BELL_MF_TWIST

#define BELL_MF_TWIST   4.0 /* 6dB */

Definition at line 199 of file dsp.c.

Referenced by mf_detect().

◆ CONFIG_FILE_NAME

#define CONFIG_FILE_NAME   "dsp.conf"

Definition at line 245 of file dsp.c.

Referenced by _dsp_init().

◆ DEF_DTMF_HITS_TO_BEGIN

#define DEF_DTMF_HITS_TO_BEGIN   2

Definition at line 232 of file dsp.c.

Referenced by _dsp_init().

◆ DEF_DTMF_MISSES_TO_END

#define DEF_DTMF_MISSES_TO_END   3

Definition at line 237 of file dsp.c.

Referenced by _dsp_init().

◆ DEF_DTMF_NORMAL_TWIST

#define DEF_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */

Definition at line 183 of file dsp.c.

Referenced by _dsp_init(), and ast_dsp_get_threshold_from_settings().

◆ DEF_DTMF_REVERSE_TWIST

#define DEF_DTMF_REVERSE_TWIST   2.51 /* 4.01dB */

Definition at line 190 of file dsp.c.

Referenced by _dsp_init(), and ast_dsp_get_threshold_from_settings().

◆ DEF_RELAX_DTMF_NORMAL_TWIST

#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */

Definition at line 184 of file dsp.c.

Referenced by _dsp_init().

◆ DEF_RELAX_DTMF_REVERSE_TWIST

#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98 /* 6.0dB */

Definition at line 191 of file dsp.c.

Referenced by _dsp_init().

◆ DEFAULT_SAMPLE_RATE

#define DEFAULT_SAMPLE_RATE   8000

Definition at line 221 of file dsp.c.

Referenced by ast_dsp_get_threshold_from_settings(), and ast_dsp_new().

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

Referenced by __ast_dsp_new().

◆ DSP_HISTORY

#define DSP_HISTORY   15

Remember last 15 units

Definition at line 151 of file dsp.c.

Referenced by __ast_dsp_new(), __ast_dsp_silence_noise(), ast_dsp_busydetect(), and ast_dsp_set_busy_count().

◆ DTMF_GSIZE

#define DTMF_GSIZE   102

Definition at line 227 of file dsp.c.

Referenced by ast_dsp_get_threshold_from_settings(), and dtmf_detect().

◆ DTMF_RELATIVE_PEAK_COL

#define DTMF_RELATIVE_PEAK_COL   6.3 /* 8dB */

Definition at line 195 of file dsp.c.

Referenced by dtmf_detect().

◆ DTMF_RELATIVE_PEAK_ROW

#define DTMF_RELATIVE_PEAK_ROW   6.3 /* 8dB */

Definition at line 194 of file dsp.c.

Referenced by dtmf_detect().

◆ DTMF_THRESHOLD

#define DTMF_THRESHOLD   8.0e7

Definition at line 180 of file dsp.c.

Referenced by dtmf_detect().

◆ DTMF_TO_TOTAL_ENERGY

#define DTMF_TO_TOTAL_ENERGY   42.0

Definition at line 196 of file dsp.c.

Referenced by dtmf_detect().

◆ FAX_TONE_CED_DB

#define FAX_TONE_CED_DB   16

Definition at line 219 of file dsp.c.

Referenced by ast_fax_detect_init().

◆ FAX_TONE_CED_DURATION

#define FAX_TONE_CED_DURATION   2600 /* ms */

Definition at line 218 of file dsp.c.

Referenced by ast_fax_detect_init().

◆ FAX_TONE_CED_FREQ

#define FAX_TONE_CED_FREQ   2100

Definition at line 217 of file dsp.c.

Referenced by ast_fax_detect_init().

◆ FAX_TONE_CNG_DB

#define FAX_TONE_CNG_DB   16

Definition at line 211 of file dsp.c.

Referenced by ast_fax_detect_init().

◆ FAX_TONE_CNG_DURATION

#define FAX_TONE_CNG_DURATION   500 /* ms */

Definition at line 210 of file dsp.c.

Referenced by ast_fax_detect_init().

◆ FAX_TONE_CNG_FREQ

#define FAX_TONE_CNG_FREQ   1100

Definition at line 209 of file dsp.c.

Referenced by ast_fax_detect_init().

◆ FREQ_ARRAY_SIZE

#define FREQ_ARRAY_SIZE   7

Definition at line 115 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and ast_dsp_prog_reset().

◆ MAX_DTMF_DIGITS

#define MAX_DTMF_DIGITS   128

Definition at line 166 of file dsp.c.

Referenced by store_digit().

◆ MF_GSIZE

#define MF_GSIZE   120

Definition at line 224 of file dsp.c.

Referenced by mf_detect().

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

Referenced by __ast_dsp_call_progress(), and pair_there().

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

Referenced by __ast_dsp_call_progress(), and pair_there().

◆ TONE_THRESHOLD

#define TONE_THRESHOLD   7.8e7

Definition at line 181 of file dsp.c.

Referenced by tone_detect().

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 };
Definition: dsp.c:147
Definition: dsp.c:146

◆ 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 };
Definition: dsp.c:96
Definition: dsp.c:101
Definition: dsp.c:88
Definition: dsp.c:90
Definition: dsp.c:99
Definition: dsp.c:92
Definition: dsp.c:87
Definition: dsp.c:91
Definition: dsp.c:93
Definition: dsp.c:89
Definition: dsp.c:100

◆ 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_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 };

◆ 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 };

Function Documentation

◆ __ast_dsp_call_progress()

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

Definition at line 1064 of file dsp.c.

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

1065 {
1066  short samp;
1067  int x;
1068  int y;
1069  int pass;
1070  int newstate = DSP_TONE_STATE_SILENCE;
1071  int res = 0;
1072  int freqcount = dsp->freqcount > FREQ_ARRAY_SIZE ? FREQ_ARRAY_SIZE : dsp->freqcount;
1073 
1074  while (len) {
1075  /* Take the lesser of the number of samples we need and what we have */
1076  pass = len;
1077  if (pass > dsp->gsamp_size - dsp->gsamps) {
1078  pass = dsp->gsamp_size - dsp->gsamps;
1079  }
1080  for (x = 0; x < pass; x++) {
1081  samp = s[x];
1082  dsp->genergy += (int32_t) samp * (int32_t) samp;
1083  for (y = 0; y < freqcount; y++) {
1084  goertzel_sample(&dsp->freqs[y], samp);
1085  }
1086  }
1087  s += pass;
1088  dsp->gsamps += pass;
1089  len -= pass;
1090  if (dsp->gsamps == dsp->gsamp_size) {
1091  float hz[FREQ_ARRAY_SIZE];
1092  for (y = 0; y < FREQ_ARRAY_SIZE; y++) {
1093  hz[y] = goertzel_result(&dsp->freqs[y]);
1094  }
1095  switch (dsp->progmode) {
1096  case PROG_MODE_NA:
1097  if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
1098  newstate = DSP_TONE_STATE_BUSY;
1099  } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
1100  newstate = DSP_TONE_STATE_RINGING;
1101  } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
1102  newstate = DSP_TONE_STATE_DIALTONE;
1103  } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
1104  newstate = DSP_TONE_STATE_SPECIAL1;
1105  } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
1106  /* End of SPECIAL1 or middle of SPECIAL2 */
1108  newstate = DSP_TONE_STATE_SPECIAL2;
1109  }
1110  } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
1111  /* End of SPECIAL2 or middle of SPECIAL3 */
1113  newstate = DSP_TONE_STATE_SPECIAL3;
1114  }
1115  } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1116  newstate = DSP_TONE_STATE_TALKING;
1117  } else {
1118  newstate = DSP_TONE_STATE_SILENCE;
1119  }
1120  break;
1121  case PROG_MODE_CR:
1122  if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
1123  newstate = DSP_TONE_STATE_RINGING;
1124  } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1125  newstate = DSP_TONE_STATE_TALKING;
1126  } else {
1127  newstate = DSP_TONE_STATE_SILENCE;
1128  }
1129  break;
1130  case PROG_MODE_UK:
1131  if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
1132  newstate = DSP_TONE_STATE_HUNGUP;
1133  } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
1134  newstate = DSP_TONE_STATE_DIALTONE;
1135  }
1136  break;
1137  default:
1138  ast_log(LOG_WARNING, "Can't process in unknown prog mode '%u'\n", dsp->progmode);
1139  }
1140  if (newstate == dsp->tstate) {
1141  dsp->tcount++;
1142  if (dsp->ringtimeout) {
1143  dsp->ringtimeout++;
1144  }
1145  switch (dsp->tstate) {
1147  if ((dsp->features & DSP_PROGRESS_RINGING) &&
1148  (dsp->tcount == THRESH_RING)) {
1149  res = AST_CONTROL_RINGING;
1150  dsp->ringtimeout = 1;
1151  }
1152  break;
1153  case DSP_TONE_STATE_BUSY:
1154  if ((dsp->features & DSP_PROGRESS_BUSY) &&
1155  (dsp->tcount == THRESH_BUSY)) {
1156  res = AST_CONTROL_BUSY;
1158  }
1159  break;
1161  if ((dsp->features & DSP_PROGRESS_TALK) &&
1162  (dsp->tcount == THRESH_TALK)) {
1163  res = AST_CONTROL_ANSWER;
1165  }
1166  break;
1168  if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
1169  (dsp->tcount == THRESH_CONGESTION)) {
1170  res = AST_CONTROL_CONGESTION;
1172  }
1173  break;
1174  case DSP_TONE_STATE_HUNGUP:
1175  if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
1176  (dsp->tcount == THRESH_HANGUP)) {
1177  res = AST_CONTROL_HANGUP;
1179  }
1180  break;
1181  }
1182  if (dsp->ringtimeout == THRESH_RING2ANSWER) {
1183  ast_debug(1, "Consider call as answered because of timeout after last ring\n");
1184  res = AST_CONTROL_ANSWER;
1186  }
1187  } else {
1188  ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
1189  ast_debug(5, "Start state %d\n", newstate);
1190  dsp->tstate = newstate;
1191  dsp->tcount = 1;
1192  }
1193 
1194  /* Reset goertzel */
1195  for (x = 0; x < 7; x++) {
1196  dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1197  }
1198  dsp->gsamps = 0;
1199  dsp->genergy = 0.0;
1200  }
1201  }
1202 
1203  return res;
1204 }
static char pass[512]
#define DSP_PROGRESS_RINGING
Definition: dsp.h:40
float genergy
Definition: dsp.c:430
#define DSP_TONE_STATE_HUNGUP
Definition: dsp.h:59
goertzel_state_t freqs[FREQ_ARRAY_SIZE]
Definition: dsp.c:419
#define DSP_PROGRESS_BUSY
Definition: dsp.h:41
#define LOG_WARNING
Definition: logger.h:274
Definition: dsp.c:96
Definition: dsp.c:101
#define DSP_PROGRESS_TALK
Definition: dsp.h:39
#define DSP_FEATURE_CALL_PROGRESS
Definition: dsp.h:43
Definition: dsp.c:88
#define DSP_TONE_STATE_DIALTONE
Definition: dsp.h:53
Definition: dsp.c:90
#define DSP_PROGRESS_CONGESTION
Definition: dsp.h:42
#define DSP_TONE_STATE_TALKING
Definition: dsp.h:54
#define TONE_THRESH
Definition: dsp.c:153
Definition: dsp.c:99
Definition: dsp.c:92
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define DSP_TONE_STATE_SPECIAL2
Definition: dsp.h:57
enum gsamp_size gsamp_size
Definition: dsp.c:422
#define DSP_TONE_STATE_RINGING
Definition: dsp.h:52
#define DSP_TONE_STATE_BUSY
Definition: dsp.h:55
int freqcount
Definition: dsp.c:420
#define DSP_TONE_STATE_SPECIAL3
Definition: dsp.h:58
Definition: dsp.c:87
#define DSP_TONE_STATE_SPECIAL1
Definition: dsp.h:56
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Definition: dsp.c:91
Definition: dsp.c:93
int tcount
Definition: dsp.c:425
#define TONE_MIN_THRESH
Definition: dsp.c:154
int gsamps
Definition: dsp.c:421
int features
Definition: dsp.c:412
static void goertzel_sample(goertzel_state_t *s, short sample)
Definition: dsp.c:336
Definition: dsp.c:89
#define FREQ_ARRAY_SIZE
Definition: dsp.c:115
static float goertzel_result(goertzel_state_t *s)
Definition: dsp.c:362
int tstate
Definition: dsp.c:424
#define DSP_TONE_STATE_SILENCE
Definition: dsp.h:51
int int32_t
Definition: db.h:60
Definition: dsp.c:100
int ringtimeout
Definition: dsp.c:413
static int pair_there(float p1, float p2, float i1, float i2, float e)
Definition: dsp.c:1041
enum prog_mode progmode
Definition: dsp.c:423

◆ __ast_dsp_new()

static struct ast_dsp* __ast_dsp_new ( unsigned int  sample_rate)
static

Definition at line 1696 of file dsp.c.

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

1697 {
1698  struct ast_dsp *dsp;
1699 
1700  if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
1703  dsp->busycount = DSP_HISTORY;
1706  dsp->sample_rate = sample_rate;
1707  dsp->freqcount = 0;
1708  /* Initialize digit detector */
1710  dsp->display_inband_dtmf_warning = 1;
1711  /* Initialize initial DSP progress detect parameters */
1712  ast_dsp_prog_reset(dsp);
1713  /* Initialize fax detector */
1714  ast_fax_detect_init(dsp);
1715  }
1716  return dsp;
1717 }
static void ast_digit_detect_init(digit_detect_state_t *s, int mf, unsigned int sample_rate)
Definition: dsp.c:549
#define DSP_DIGITMODE_DTMF
Definition: dsp.h:31
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
static void ast_dsp_prog_reset(struct ast_dsp *dsp)
Definition: dsp.c:1674
digit_detect_state_t digit_state
Definition: dsp.c:434
int faxmode
Definition: dsp.c:427
int busycount
Definition: dsp.c:415
Definition: dsp.c:405
#define DSP_FEATURE_SILENCE_SUPPRESS
Definition: dsp.h:26
int freqcount
Definition: dsp.c:420
#define DEFAULT_THRESHOLD
Default minimum average magnitude threshold to determine talking/noise by the DSP.
Definition: dsp.c:140
unsigned int sample_rate
Definition: dsp.c:432
int threshold
Definition: dsp.c:407
int digitmode
Definition: dsp.c:426
static void ast_fax_detect_init(struct ast_dsp *s)
Definition: dsp.c:510
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int features
Definition: dsp.c:412
int display_inband_dtmf_warning
Definition: dsp.c:429
#define DSP_FAXMODE_DETECT_CNG
Definition: dsp.h:46
#define DSP_HISTORY
Definition: dsp.c:151

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

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

1220 {
1221  int accum;
1222  int x;
1223  int res = 0;
1224 
1225  if (!len) {
1226  return 0;
1227  }
1228  accum = 0;
1229  for (x = 0; x < len; x++) {
1230  accum += abs(s[x]);
1231  }
1232  accum /= len;
1233  if (accum < dsp->threshold) {
1234  /* Silent */
1235  dsp->totalsilence += len / (dsp->sample_rate / 1000);
1236  if (dsp->totalnoise) {
1237  /* Move and save history */
1238  memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0]));
1239  dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
1240 /* we don't want to check for busydetect that frequently */
1241 #if 0
1242  dsp->busymaybe = 1;
1243 #endif
1244  }
1245  dsp->totalnoise = 0;
1246  res = 1;
1247  } else {
1248  /* Not silent */
1249  dsp->totalnoise += len / (dsp->sample_rate / 1000);
1250  if (dsp->totalsilence) {
1251  int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
1252  int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
1253  /* Move and save history */
1254  memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0]));
1255  dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
1256  /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
1257  if (silence1 < silence2) {
1258  if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) {
1259  dsp->busymaybe = 1;
1260  } else {
1261  dsp->busymaybe = 0;
1262  }
1263  } else {
1264  if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) {
1265  dsp->busymaybe = 1;
1266  } else {
1267  dsp->busymaybe = 0;
1268  }
1269  }
1270  }
1271  dsp->totalsilence = 0;
1272  }
1273  if (totalsilence) {
1274  *totalsilence = dsp->totalsilence;
1275  }
1276  if (totalnoise) {
1277  *totalnoise = dsp->totalnoise;
1278  }
1279  if (frames_energy) {
1280  *frames_energy = accum;
1281  }
1282  return res;
1283 }
int busymaybe
Definition: dsp.c:414
int historicsilence[DSP_HISTORY]
Definition: dsp.c:418
int historicnoise[DSP_HISTORY]
Definition: dsp.c:417
int totalsilence
Definition: dsp.c:409
threshold
Definition: dsp.h:70
int busycount
Definition: dsp.c:415
unsigned int sample_rate
Definition: dsp.c:432
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define abs(x)
Definition: f2c.h:195
int totalnoise
Definition: dsp.c:411
#define DSP_HISTORY
Definition: dsp.c:151

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2429 of file dsp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2429 of file dsp.c.

◆ _dsp_init()

static int _dsp_init ( int  reload)
static

Definition at line 1871 of file dsp.c.

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, THRESHOLD_SILENCE, thresholds, and ast_variable::value.

Referenced by load_module(), and reload_module().

1872 {
1873  struct ast_config *cfg;
1874  struct ast_variable *v;
1875  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1876  int cfg_threshold;
1877  float cfg_twist;
1878 
1879  if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
1880  return 0;
1881  }
1882 
1890 
1892  return 0;
1893  }
1894 
1895  for (v = ast_variable_browse(cfg, "default"); v; v = v->next) {
1896  if (!strcasecmp(v->name, "silencethreshold")) {
1897  if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1898  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1899  } else if (cfg_threshold < 0) {
1900  ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
1901  } else {
1902  thresholds[THRESHOLD_SILENCE] = cfg_threshold;
1903  }
1904  } else if (!strcasecmp(v->name, "dtmf_normal_twist")) {
1905  if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1906  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1907  } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1908  ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
1909  } else {
1910  dtmf_normal_twist = cfg_twist;
1911  }
1912  } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) {
1913  if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1914  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1915  } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1916  ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
1917  } else {
1918  dtmf_reverse_twist = cfg_twist;
1919  }
1920  } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) {
1921  if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1922  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1923  } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1924  ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
1925  } else {
1926  relax_dtmf_normal_twist = cfg_twist;
1927  }
1928  } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) {
1929  if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
1930  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1931  } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
1932  ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
1933  } else {
1934  relax_dtmf_reverse_twist = cfg_twist;
1935  }
1936  } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) {
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 < 1) { /* must be 1 or greater */
1940  ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
1941  } else {
1942  dtmf_hits_to_begin = cfg_threshold;
1943  }
1944  } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) {
1945  if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
1946  ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
1947  } else if (cfg_threshold < 1) { /* must be 1 or greater */
1948  ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
1949  } else {
1950  dtmf_misses_to_end = cfg_threshold;
1951  }
1952  }
1953  }
1954  ast_config_destroy(cfg);
1955 
1956  return 0;
1957 }
struct ast_variable * next
static float relax_dtmf_reverse_twist
Definition: dsp.c:332
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define LOG_WARNING
Definition: logger.h:274
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:243
#define CONFIG_STATUS_FILEINVALID
#define DEF_DTMF_NORMAL_TWIST
Definition: dsp.c:183
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:3154
Structure for variables, used for configurations and for channel variables.
#define DEF_DTMF_HITS_TO_BEGIN
Definition: dsp.c:232
#define CONFIG_FILE_NAME
Definition: dsp.c:245
static int dtmf_hits_to_begin
Definition: dsp.c:333
#define ast_log
Definition: astobj2.c:42
#define DEF_DTMF_REVERSE_TWIST
Definition: dsp.c:190
static int dtmf_misses_to_end
Definition: dsp.c:334
#define DEF_DTMF_MISSES_TO_END
Definition: dsp.c:237
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define DEF_RELAX_DTMF_NORMAL_TWIST
Definition: dsp.c:184
#define CONFIG_STATUS_FILEUNCHANGED
static float dtmf_normal_twist
Definition: dsp.c:329
static float relax_dtmf_normal_twist
Definition: dsp.c:331
static int reload(void)
Definition: cdr_mysql.c:741
Structure used to handle boolean flags.
Definition: utils.h:199
#define CONFIG_STATUS_FILEMISSING
static float dtmf_reverse_twist
Definition: dsp.c:330
#define DEF_RELAX_DTMF_REVERSE_TWIST
Definition: dsp.c:191
static int thresholds[THRESHOLD_MAX]
Definition: dsp.c:328

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

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

550 {
551  s->current_digits = 0;
552  s->detected_digits = 0;
553  s->lost_digits = 0;
554  s->digits[0] = '\0';
555 
556  if (mf) {
557  ast_mf_detect_init(&s->td.mf, sample_rate);
558  } else {
559  ast_dtmf_detect_init(&s->td.dtmf, sample_rate);
560  }
561 }
int current_digits
Definition: dsp.c:307
union digit_detect_state_t::@375 td
char digits[MAX_DTMF_DIGITS+1]
Definition: dsp.c:305
dtmf_detect_state_t dtmf
Definition: dsp.c:312
static void ast_dtmf_detect_init(dtmf_detect_state_t *s, unsigned int sample_rate)
Definition: dsp.c:521
int detected_digits
Definition: dsp.c:308
static void ast_mf_detect_init(mf_detect_state_t *s, unsigned int sample_rate)
Definition: dsp.c:537
mf_detect_state_t mf
Definition: dsp.c:313

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

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

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

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

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.

1207 {
1208  if (inf->frametype != AST_FRAME_VOICE) {
1209  ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1210  return 0;
1211  }
1213  ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
1214  return 0;
1215  }
1216  return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
1217 }
#define LOG_WARNING
Definition: logger.h:274
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
Definition: dsp.c:1064
struct ast_frame_subclass subclass
union ast_frame::@255 data
#define ast_log
Definition: astobj2.c:42
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:542
enum ast_frame_type frametype
struct ast_format * format

◆ ast_dsp_digitreset()

void ast_dsp_digitreset ( struct ast_dsp dsp)

Reset DTMF detector.

Definition at line 1771 of file dsp.c.

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(), ast_dsp_get_threshold_from_settings(), mbl_new(), and my_dsp_reset_and_flush_digits().

1772 {
1773  int i;
1774 
1775  dsp->dtmf_began = 0;
1776  if (dsp->digitmode & DSP_DIGITMODE_MF) {
1777  mf_detect_state_t *s = &dsp->digit_state.td.mf;
1778  /* Reinitialise the detector for the next block */
1779  for (i = 0; i < 6; i++) {
1780  goertzel_reset(&s->tone_out[i]);
1781  }
1782  s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = 0;
1783  s->current_hit = 0;
1784  s->current_sample = 0;
1785  } else {
1787  /* Reinitialise the detector for the next block */
1788  for (i = 0; i < 4; i++) {
1789  goertzel_reset(&s->row_out[i]);
1790  goertzel_reset(&s->col_out[i]);
1791  }
1792  s->lasthit = 0;
1793  s->current_hit = 0;
1794  s->energy = 0.0;
1795  s->current_sample = 0;
1796  s->hits = 0;
1797  s->misses = 0;
1798  }
1799 
1800  dsp->digit_state.digits[0] = '\0';
1801  dsp->digit_state.current_digits = 0;
1802 }
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
int current_digits
Definition: dsp.c:307
goertzel_state_t tone_out[6]
Definition: dsp.c:296
union digit_detect_state_t::@375 td
static void goertzel_reset(goertzel_state_t *s)
Definition: dsp.c:382
digit_detect_state_t digit_state
Definition: dsp.c:434
char digits[MAX_DTMF_DIGITS+1]
Definition: dsp.c:305
dtmf_detect_state_t dtmf
Definition: dsp.c:312
int current_sample
Definition: dsp.c:290
goertzel_state_t col_out[4]
Definition: dsp.c:284
int hits[5]
Definition: dsp.c:298
int dtmf_began
Definition: dsp.c:428
int digitmode
Definition: dsp.c:426
int current_sample
Definition: dsp.c:299
float energy
Definition: dsp.c:289
int current_hit
Definition: dsp.c:297
mf_detect_state_t mf
Definition: dsp.c:313
goertzel_state_t row_out[4]
Definition: dsp.c:283

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

References ast_dsp::features.

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

1739 {
1740  return (dsp->features);
1741 }
int features
Definition: dsp.c:412

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

References ast_dsp::sample_rate.

1692 {
1693  return dsp->sample_rate;
1694 }
unsigned int sample_rate
Definition: dsp.c:432

◆ ast_dsp_get_tcount()

int ast_dsp_get_tcount ( struct ast_dsp dsp)

Get tcount (Threshold counter)

Definition at line 1866 of file dsp.c.

References ast_dsp::tcount.

Referenced by dahdi_read().

1867 {
1868  return dsp->tcount;
1869 }
int tcount
Definition: dsp.c:425

◆ ast_dsp_get_threshold_from_settings()

int ast_dsp_get_threshold_from_settings ( enum threshold  which)

◆ ast_dsp_get_tstate()

int ast_dsp_get_tstate ( struct ast_dsp dsp)

Get tstate (Tone State)

Definition at line 1861 of file dsp.c.

References ast_dsp::tstate.

Referenced by dahdi_read().

1862 {
1863  return dsp->tstate;
1864 }
int tstate
Definition: dsp.c:424

◆ ast_dsp_new()

struct ast_dsp* ast_dsp_new ( void  )

◆ ast_dsp_new_with_rate()

struct ast_dsp* ast_dsp_new_with_rate ( unsigned int  sample_rate)

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

Definition at line 1724 of file dsp.c.

References __ast_dsp_new().

Referenced by set_softmix_bridge_data(), and set_talk_detect().

1725 {
1726  return __ast_dsp_new(sample_rate);
1727 }
static struct ast_dsp * __ast_dsp_new(unsigned int sample_rate)
Definition: dsp.c:1696

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

References ast_dsp_silence_noise_with_energy(), and NULL.

1479 {
1480  return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
1481 }
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:1423
#define NULL
Definition: resample.c:96

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

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_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::historicnoise, ast_dsp::historicsilence, ast_frame_subclass::integer, ast_frame::len, 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(), fax_detect_framehook(), mbl_read(), mgcp_rtp_read(), ooh323_rtp_read(), process_ast_dsp(), and sip_rtp_read().

1485 {
1486  int silence;
1487  int res;
1488  int digit = 0, fax_digit = 0;
1489  int x;
1490  short *shortdata;
1491  unsigned char *odata;
1492  int len;
1493  struct ast_frame *outf = NULL;
1494 
1495  if (!af) {
1496  return NULL;
1497  }
1498  if (af->frametype != AST_FRAME_VOICE) {
1499  return af;
1500  }
1501 
1502  odata = af->data.ptr;
1503  len = af->datalen;
1504  /* Make sure we have short data */
1506  shortdata = af->data.ptr;
1507  len = af->datalen / 2;
1509  shortdata = ast_alloca(af->datalen * 2);
1510  for (x = 0; x < len; x++) {
1511  shortdata[x] = AST_MULAW(odata[x]);
1512  }
1514  shortdata = ast_alloca(af->datalen * 2);
1515  for (x = 0; x < len; x++) {
1516  shortdata[x] = AST_ALAW(odata[x]);
1517  }
1518  } else {
1519  /*Display warning only once. Otherwise you would get hundreds of warnings every second */
1520  if (dsp->display_inband_dtmf_warning) {
1521  ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_format_get_name(af->subclass.format));
1522  }
1523  dsp->display_inband_dtmf_warning = 0;
1524  return af;
1525  }
1526 
1527  /* Initially we do not want to mute anything */
1528  dsp->mute_fragments = 0;
1529 
1530  /* Need to run the silence detection stuff for silence suppression and busy detection */
1532  res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL, NULL);
1533  }
1534 
1535  if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
1536  memset(&dsp->f, 0, sizeof(dsp->f));
1537  dsp->f.frametype = AST_FRAME_NULL;
1538  ast_frfree(af);
1539  return ast_frisolate(&dsp->f);
1540  }
1541  if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
1543  memset(&dsp->f, 0, sizeof(dsp->f));
1544  dsp->f.frametype = AST_FRAME_CONTROL;
1546  ast_frfree(af);
1547  ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", ast_channel_name(chan));
1548  return ast_frisolate(&dsp->f);
1549  }
1550 
1551  if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
1552  if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1553  fax_digit = 'f';
1554  }
1555 
1556  if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
1557  fax_digit = 'e';
1558  }
1559  }
1560 
1562  if (dsp->digitmode & DSP_DIGITMODE_MF) {
1563  digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1564  } else {
1565  digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1566  }
1567 
1568  if (dsp->digit_state.current_digits) {
1569  int event = 0, event_len = 0;
1570  char event_digit = 0;
1571 
1572  if (!dsp->dtmf_began) {
1573  /* We have not reported DTMF_BEGIN for anything yet */
1574 
1575  if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
1576  event = AST_FRAME_DTMF_BEGIN;
1577  event_digit = dsp->digit_state.digits[0];
1578  }
1579  dsp->dtmf_began = 1;
1580 
1581  } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
1582  /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
1583  if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
1584  event = AST_FRAME_DTMF_END;
1585  event_digit = dsp->digit_state.digits[0];
1586  event_len = dsp->digit_state.digitlen[0] * 1000 / dsp->sample_rate;
1587  }
1588  memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
1589  memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
1590  dsp->digit_state.current_digits--;
1591  dsp->dtmf_began = 0;
1592 
1593  if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
1594  /* Reset Busy Detector as we have some confirmed activity */
1595  memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1596  memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1597  ast_debug(1, "DTMF Detected - Reset busydetector\n");
1598  }
1599  }
1600 
1601  if (event) {
1602  memset(&dsp->f, 0, sizeof(dsp->f));
1603  dsp->f.frametype = event;
1604  dsp->f.subclass.integer = event_digit;
1605  dsp->f.len = event_len;
1606  outf = &dsp->f;
1607  goto done;
1608  }
1609  }
1610  }
1611 
1612  if (fax_digit) {
1613  /* Fax was detected - digit is either 'f' or 'e' */
1614 
1615  memset(&dsp->f, 0, sizeof(dsp->f));
1616  dsp->f.frametype = AST_FRAME_DTMF;
1617  dsp->f.subclass.integer = fax_digit;
1618  outf = &dsp->f;
1619  goto done;
1620  }
1621 
1622  if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
1623  res = __ast_dsp_call_progress(dsp, shortdata, len);
1624  if (res) {
1625  switch (res) {
1626  case AST_CONTROL_ANSWER:
1627  case AST_CONTROL_BUSY:
1628  case AST_CONTROL_RINGING:
1630  case AST_CONTROL_HANGUP:
1631  memset(&dsp->f, 0, sizeof(dsp->f));
1632  dsp->f.frametype = AST_FRAME_CONTROL;
1633  dsp->f.subclass.integer = res;
1634  dsp->f.src = "dsp_progress";
1635  if (chan) {
1636  ast_queue_frame(chan, &dsp->f);
1637  }
1638  break;
1639  default:
1640  ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
1641  }
1642  }
1643  } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
1644  res = __ast_dsp_call_progress(dsp, shortdata, len);
1645  }
1646 
1647 done:
1648  /* Mute fragment of the frame */
1649  for (x = 0; x < dsp->mute_fragments; x++) {
1650  memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
1651  }
1652 
1654  for (x = 0; x < len; x++) {
1655  odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
1656  }
1658  for (x = 0; x < len; x++) {
1659  odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
1660  }
1661  }
1662 
1663  if (outf) {
1664  if (chan) {
1665  ast_queue_frame(chan, af);
1666  }
1667  ast_frfree(af);
1668  return ast_frisolate(outf);
1669  } else {
1670  return af;
1671  }
1672 }
char digit
int start
Definition: dsp.c:388
short int16_t
Definition: db.h:59
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
struct ast_frame f
Definition: dsp.c:406
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
#define LOG_WARNING
Definition: logger.h:274
#define AST_ALAW(a)
Definition: alaw.h:84
#define DSP_FEATURE_CALL_PROGRESS
Definition: dsp.h:43
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
Definition: dsp.c:1064
int historicsilence[DSP_HISTORY]
Definition: dsp.c:418
Definition: astman.c:222
int current_digits
Definition: dsp.c:307
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:683
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
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:1285
digit_detect_state_t digit_state
Definition: dsp.c:434
int historicnoise[DSP_HISTORY]
Definition: dsp.c:417
struct ast_frame_subclass subclass
char digits[MAX_DTMF_DIGITS+1]
Definition: dsp.c:305
int done
Definition: test_amihooks.c:48
union ast_frame::@255 data
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
int faxmode
Definition: dsp.c:427
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
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
const char * src
#define AST_MULAW(a)
Definition: ulaw.h:85
#define DSP_FEATURE_SILENCE_SUPPRESS
Definition: dsp.h:26
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
unsigned int sample_rate
Definition: dsp.c:432
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:542
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1135
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
int end
Definition: dsp.c:389
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:890
int dtmf_began
Definition: dsp.c:428
#define DSP_FAXMODE_DETECT_CED
Definition: dsp.h:47
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int digitmode
Definition: dsp.c:426
#define DSP_FEATURE_BUSY_DETECT
Definition: dsp.h:27
static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
Definition: dsp.c:1219
int mute_fragments
Definition: dsp.c:431
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
int features
Definition: dsp.c:412
tone_detect_state_t ced_tone_state
Definition: dsp.c:436
static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
Definition: dsp.c:563
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
const char * ast_channel_name(const struct ast_channel *chan)
int display_inband_dtmf_warning
Definition: dsp.c:429
#define ast_frfree(fr)
tone_detect_state_t cng_tone_state
Definition: dsp.c:435
Data structure associated with a single frame of data.
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
int digitlen[MAX_DTMF_DIGITS+1]
Definition: dsp.c:306
#define DSP_FAXMODE_DETECT_CNG
Definition: dsp.h:46
fragment_t mute_data[5]
Definition: dsp.c:433
enum ast_frame_type frametype
#define DSP_DIGITMODE_NOQUELCH
Definition: dsp.h:34
struct ast_format * format
#define DSP_FEATURE_WAITDIALTONE
Definition: dsp.h:44
#define AST_LIN2MU(a)
Definition: ulaw.h:49
#define AST_LIN2A(a)
Definition: alaw.h:50

◆ ast_dsp_prog_reset()

static void ast_dsp_prog_reset ( struct ast_dsp dsp)
static

Definition at line 1674 of file dsp.c.

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

1675 {
1676  int max = 0;
1677  int x;
1678 
1679  dsp->gsamp_size = modes[dsp->progmode].size;
1680  dsp->gsamps = 0;
1681  for (x = 0; x < FREQ_ARRAY_SIZE; x++) {
1682  if (modes[dsp->progmode].freqs[x]) {
1683  goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->sample_rate);
1684  max = x + 1;
1685  }
1686  }
1687  dsp->freqcount = max;
1688  dsp->ringtimeout = 0;
1689 }
goertzel_state_t freqs[FREQ_ARRAY_SIZE]
Definition: dsp.c:419
enum gsamp_size size
Definition: dsp.c:118
int freqs[FREQ_ARRAY_SIZE]
Definition: dsp.c:119
static struct progress modes[]
enum gsamp_size gsamp_size
Definition: dsp.c:422
int freqcount
Definition: dsp.c:420
unsigned int sample_rate
Definition: dsp.c:432
static void goertzel_init(goertzel_state_t *s, float freq, unsigned int sample_rate)
Definition: dsp.c:376
int gsamps
Definition: dsp.c:421
#define FREQ_ARRAY_SIZE
Definition: dsp.c:115
int ringtimeout
Definition: dsp.c:413
enum prog_mode progmode
Definition: dsp.c:423
#define max(a, b)
Definition: f2c.h:198

◆ ast_dsp_reset()

void ast_dsp_reset ( struct ast_dsp dsp)

Reset total silence count.

Definition at line 1804 of file dsp.c.

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

1805 {
1806  int x;
1807 
1808  dsp->totalsilence = 0;
1809  dsp->gsamps = 0;
1810  for (x = 0; x < 4; x++) {
1811  dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1812  }
1813  memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1814  memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1815  dsp->ringtimeout = 0;
1816 }
goertzel_state_t freqs[FREQ_ARRAY_SIZE]
Definition: dsp.c:419
int historicsilence[DSP_HISTORY]
Definition: dsp.c:418
int historicnoise[DSP_HISTORY]
Definition: dsp.c:417
int totalsilence
Definition: dsp.c:409
int gsamps
Definition: dsp.c:421
int ringtimeout
Definition: dsp.c:413

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

References ast_dsp::busycount, cadences, and DSP_HISTORY.

Referenced by dahdi_new().

1755 {
1756  if (cadences < 4) {
1757  cadences = 4;
1758  }
1759  if (cadences > DSP_HISTORY) {
1761  }
1762  dsp->busycount = cadences;
1763 }
int busycount
Definition: dsp.c:415
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition: chan_dahdi.c:569
#define DSP_HISTORY
Definition: dsp.c:151

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

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

Referenced by dahdi_new().

1766 {
1767  dsp->busy_cadence = *cadence;
1768  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);
1769 }
int pattern[4]
Definition: dsp.h:67
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
struct ast_dsp_busy_pattern busy_cadence
Definition: dsp.c:416

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

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

Referenced by dahdi_new().

1843 {
1844  int x;
1845 
1846  for (x = 0; x < ARRAY_LEN(aliases); x++) {
1847  if (!strcasecmp(aliases[x].name, zone)) {
1848  dsp->progmode = aliases[x].mode;
1849  ast_dsp_prog_reset(dsp);
1850  return 0;
1851  }
1852  }
1853  return -1;
1854 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void ast_dsp_prog_reset(struct ast_dsp *dsp)
Definition: dsp.c:1674
static struct progalias aliases[]
static const char name[]
Definition: cdr_mysql.c:74
enum prog_mode mode
Definition: dsp.c:106
enum prog_mode progmode
Definition: dsp.c:423

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

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

1819 {
1820  int new;
1821  int old;
1822 
1825  if (old != new) {
1826  /* Must initialize structures if switching from MF to DTMF or vice-versa */
1828  }
1829  dsp->digitmode = digitmode;
1830  return 0;
1831 }
static void ast_digit_detect_init(digit_detect_state_t *s, int mf, unsigned int sample_rate)
Definition: dsp.c:549
#define DSP_DIGITMODE_DTMF
Definition: dsp.h:31
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
#define DSP_DIGITMODE_MUTECONF
Definition: dsp.h:35
digit_detect_state_t digit_state
Definition: dsp.c:434
unsigned int sample_rate
Definition: dsp.c:432
#define DSP_DIGITMODE_MUTEMAX
Definition: dsp.h:36
int digitmode
Definition: dsp.c:426

◆ ast_dsp_set_faxmode()

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1833 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

Referenced by fax_detect_new(), and ooh323_new().

1834 {
1835  if (dsp->faxmode != faxmode) {
1836  dsp->faxmode = faxmode;
1837  ast_fax_detect_init(dsp);
1838  }
1839  return 0;
1840 }
int faxmode
Definition: dsp.c:427
static void ast_fax_detect_init(struct ast_dsp *s)
Definition: dsp.c:510

◆ ast_dsp_set_features()

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

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

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

1750 {
1751  dsp->threshold = threshold;
1752 }
threshold
Definition: dsp.h:70
int threshold
Definition: dsp.c:407

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

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

1474 {
1475  return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
1476 }
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:1423
#define NULL
Definition: resample.c:96

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

References __ast_dsp_silence_noise(), AST_ALAW, ast_alloca, ast_format_alaw, ast_format_cache_is_slinear(), ast_format_cmp(), 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, and ast_frame::subclass.

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

1424 {
1425  short *s;
1426  int len;
1427  int x;
1428  unsigned char *odata;
1429 
1430  if (!f) {
1431  return 0;
1432  }
1433 
1434  if (f->frametype != AST_FRAME_VOICE) {
1435  ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
1436  return 0;
1437  }
1438 
1440  s = f->data.ptr;
1441  len = f->datalen/2;
1442  } else {
1443  odata = f->data.ptr;
1444  len = f->datalen;
1446  s = ast_alloca(len * 2);
1447  for (x = 0; x < len; x++) {
1448  s[x] = AST_MULAW(odata[x]);
1449  }
1450  } else if (ast_format_cmp(f->subclass.format, ast_format_alaw)) {
1451  s = ast_alloca(len * 2);
1452  for (x = 0; x < len; x++) {
1453  s[x] = AST_ALAW(odata[x]);
1454  }
1455  } else {
1456  ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames :(\n");
1457  return 0;
1458  }
1459  }
1460 
1461  if (noise) {
1462  return __ast_dsp_silence_noise(dsp, s, len, NULL, total, frames_energy);
1463  } else {
1464  return __ast_dsp_silence_noise(dsp, s, len, total, NULL, frames_energy);
1465  }
1466 }
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
#define LOG_WARNING
Definition: logger.h:274
#define AST_ALAW(a)
Definition: alaw.h:84
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
union ast_frame::@255 data
#define ast_log
Definition: astobj2.c:42
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
#define AST_MULAW(a)
Definition: ulaw.h:85
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:542
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
Definition: dsp.c:1219
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
static int total
Definition: res_adsi.c:968
enum ast_frame_type frametype
struct ast_format * format

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

References ast_dsp_silence_noise_with_energy().

Referenced by softmix_bridge_write_voice().

1469 {
1470  return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
1471 }
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:1423

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

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

1857 {
1858  return (dsp->mute_fragments > 0);
1859 }
int mute_fragments
Definition: dsp.c:431

◆ ast_dtmf_detect_init()

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

Definition at line 521 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, dtmf_col, 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().

522 {
523  int i;
524 
525  for (i = 0; i < 4; i++) {
526  goertzel_init(&s->row_out[i], dtmf_row[i], sample_rate);
527  goertzel_init(&s->col_out[i], dtmf_col[i], sample_rate);
528  }
529  s->lasthit = 0;
530  s->current_hit = 0;
531  s->energy = 0.0;
532  s->current_sample = 0;
533  s->hits = 0;
534  s->misses = 0;
535 }
static const float dtmf_col[]
Definition: dsp.c:320
static const float dtmf_row[]
Definition: dsp.c:317
int current_sample
Definition: dsp.c:290
goertzel_state_t col_out[4]
Definition: dsp.c:284
static void goertzel_init(goertzel_state_t *s, float freq, unsigned int sample_rate)
Definition: dsp.c:376
float energy
Definition: dsp.c:289
goertzel_state_t row_out[4]
Definition: dsp.c:283

◆ ast_fax_detect_init()

static void ast_fax_detect_init ( struct ast_dsp s)
static

Definition at line 510 of file dsp.c.

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

511 {
515  s->cng_tone_state.squelch = 1;
516  s->ced_tone_state.squelch = 1;
517  }
518 
519 }
#define FAX_TONE_CNG_FREQ
Definition: dsp.c:209
#define FAX_TONE_CED_DB
Definition: dsp.c:219
#define DSP_FAXMODE_DETECT_SQUELCH
Definition: dsp.h:48
#define FAX_TONE_CNG_DURATION
Definition: dsp.c:210
#define FAX_TONE_CED_FREQ
Definition: dsp.c:217
#define FAX_TONE_CNG_DB
Definition: dsp.c:211
#define FAX_TONE_CED_DURATION
Definition: dsp.c:218
int faxmode
Definition: dsp.c:427
unsigned int sample_rate
Definition: dsp.c:432
static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, int amp, unsigned int sample_rate)
Definition: dsp.c:449
tone_detect_state_t ced_tone_state
Definition: dsp.c:436
tone_detect_state_t cng_tone_state
Definition: dsp.c:435

◆ ast_mf_detect_init()

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

Definition at line 537 of file dsp.c.

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

538 {
539  int i;
540 
541  for (i = 0; i < 6; i++) {
542  goertzel_init(&s->tone_out[i], mf_tones[i], sample_rate);
543  }
544  s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
545  s->current_sample = 0;
546  s->current_hit = 0;
547 }
goertzel_state_t tone_out[6]
Definition: dsp.c:296
static void goertzel_init(goertzel_state_t *s, float freq, unsigned int sample_rate)
Definition: dsp.c:376
static const float mf_tones[]
Definition: dsp.c:323
int hits[5]
Definition: dsp.c:298
int current_sample
Definition: dsp.c:299
int current_hit
Definition: dsp.c:297

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

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

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

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

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

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_misses_to_end, dtmf_normal_twist, dtmf_positions, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, dtmf_reverse_twist, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, fragment_t::end, dtmf_detect_state_t::energy, goertzel_reset(), goertzel_result(), goertzel_sample(), dtmf_detect_state_t::hits, dtmf_detect_state_t::lasthit, dtmf_detect_state_t::misses, mute, mute_fragment(), dtmf_detect_state_t::mute_samples, relax_dtmf_normal_twist, relax_dtmf_reverse_twist, dtmf_detect_state_t::row_out, fragment_t::start, store_digit(), and digit_detect_state_t::td.

Referenced by ast_dsp_get_threshold_from_settings(), and ast_dsp_process().

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

◆ goertzel_init()

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

Definition at line 376 of file dsp.c.

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

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

◆ goertzel_reset()

static void goertzel_reset ( goertzel_state_t s)
inlinestatic

Definition at line 382 of file dsp.c.

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

383 {
384  s->v2 = s->v3 = s->chunky = 0;
385 }
int chunky
Definition: dsp.c:253

◆ goertzel_result()

static float goertzel_result ( goertzel_state_t s)
inlinestatic

Definition at line 362 of file dsp.c.

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

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

◆ goertzel_sample()

static void goertzel_sample ( goertzel_state_t s,
short  sample 
)
inlinestatic

Definition at line 336 of file dsp.c.

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

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

◆ load_module()

static int load_module ( void  )
static

Definition at line 2405 of file dsp.c.

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

Referenced by reload_module().

2406 {
2407  if (_dsp_init(0)) {
2408  return AST_MODULE_LOAD_FAILURE;
2409  }
2410 
2411  AST_TEST_REGISTER(test_dsp_fax_detect);
2412  AST_TEST_REGISTER(test_dsp_dtmf_detect);
2413 
2414  return AST_MODULE_LOAD_SUCCESS;
2415 }
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
Module could not be loaded properly.
Definition: module.h:102
static int _dsp_init(int reload)
Definition: dsp.c:1871

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

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

Referenced by ast_dsp_process().

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

◆ mute_fragment()

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

Definition at line 439 of file dsp.c.

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

440 {
441  if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
442  ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
443  return;
444  }
445 
446  dsp->mute_data[dsp->mute_fragments++] = *fragment;
447 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
int mute_fragments
Definition: dsp.c:431
fragment_t mute_data[5]
Definition: dsp.c:433

◆ pair_there()

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

Definition at line 1041 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

1042 {
1043  /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
1044  /* Make sure absolute levels are high enough */
1045  if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
1046  return 0;
1047  }
1048  /* Amplify ignored stuff */
1049  i2 *= TONE_THRESH;
1050  i1 *= TONE_THRESH;
1051  e *= TONE_THRESH;
1052  /* Check first tone */
1053  if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
1054  return 0;
1055  }
1056  /* And second */
1057  if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
1058  return 0;
1059  }
1060  /* Guess it's there... */
1061  return 1;
1062 }
#define TONE_THRESH
Definition: dsp.c:153
#define TONE_MIN_THRESH
Definition: dsp.c:154

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2417 of file dsp.c.

References _dsp_init(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CORE, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, load_module(), reload(), and unload_module().

2418 {
2419  return _dsp_init(1);
2420 }
static int _dsp_init(int reload)
Definition: dsp.c:1871

◆ store_digit()

static void store_digit ( digit_detect_state_t s,
char  digit 
)
static

Definition at line 670 of file dsp.c.

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

671 {
672  s->detected_digits++;
673  if (s->current_digits < MAX_DTMF_DIGITS) {
674  s->digitlen[s->current_digits] = 0;
675  s->digits[s->current_digits++] = digit;
676  s->digits[s->current_digits] = '\0';
677  } else {
678  ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
679  s->lost_digits++;
680  }
681 }
char digit
#define LOG_WARNING
Definition: logger.h:274
int current_digits
Definition: dsp.c:307
char digits[MAX_DTMF_DIGITS+1]
Definition: dsp.c:305
#define ast_log
Definition: astobj2.c:42
#define MAX_DTMF_DIGITS
Definition: dsp.c:166
int detected_digits
Definition: dsp.c:308
int digitlen[MAX_DTMF_DIGITS+1]
Definition: dsp.c:306

◆ tone_detect()

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

Definition at line 563 of file dsp.c.

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

Referenced by ast_dsp_get_threshold_from_settings(), and ast_dsp_process().

564 {
565  float tone_energy;
566  int i;
567  int hit = 0;
568  int limit;
569  int res = 0;
570  int16_t *ptr;
571  short samp;
572  int start, end;
573  fragment_t mute = {0, 0};
574 
575  if (s->squelch && s->mute_samples > 0) {
576  mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
577  s->mute_samples -= mute.end;
578  }
579 
580  for (start = 0; start < samples; start = end) {
581  /* Process in blocks. */
582  limit = samples - start;
583  if (limit > s->samples_pending) {
584  limit = s->samples_pending;
585  }
586  end = start + limit;
587 
588  for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
589  samp = *ptr;
590  /* signed 32 bit int should be enough to square any possible signed 16 bit value */
591  s->energy += (int32_t) samp * (int32_t) samp;
592 
593  goertzel_sample(&s->tone, samp);
594  }
595 
596  s->samples_pending -= limit;
597 
598  if (s->samples_pending) {
599  /* Finished incomplete (last) block */
600  break;
601  }
602 
603  tone_energy = goertzel_result(&s->tone);
604 
605  /* Scale to make comparable */
606  tone_energy *= 2.0;
607  s->energy *= s->block_size;
608 
609  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));
610  hit = 0;
611  if (TONE_THRESHOLD <= tone_energy
612  && tone_energy > s->energy * s->threshold) {
613  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));
614  hit = 1;
615  }
616 
617  if (s->hit_count) {
618  s->hit_count++;
619  }
620 
621  if (hit == s->last_hit) {
622  if (!hit) {
623  /* Two successive misses. Tone ended */
624  s->hit_count = 0;
625  } else if (!s->hit_count) {
626  s->hit_count++;
627  }
628 
629  }
630 
631  if (s->hit_count == s->hits_required) {
632  ast_debug(1, "%d Hz tone detected\n", s->freq);
633  res = 1;
634  }
635 
636  s->last_hit = hit;
637 
638  /* If we had a hit in this block, include it into mute fragment */
639  if (s->squelch && hit) {
640  if (mute.end < start - s->block_size) {
641  /* There is a gap between fragments */
642  mute_fragment(dsp, &mute);
643  mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
644  }
645  mute.end = end + s->block_size;
646  }
647 
648  /* Reinitialise the detector for the next block */
649  /* Reset for the next block */
650  goertzel_reset(&s->tone);
651 
652  /* Advance to the next block */
653  s->energy = 0.0;
654  s->samples_pending = s->block_size;
655 
656  amp += limit;
657  }
658 
659  if (s->squelch && mute.end) {
660  if (mute.end > samples) {
661  s->mute_samples = mute.end - samples;
662  mute.end = samples;
663  }
664  mute_fragment(dsp, &mute);
665  }
666 
667  return res;
668 }
static void mute_fragment(struct ast_dsp *dsp, fragment_t *fragment)
Definition: dsp.c:439
int hits_required
Definition: dsp.c:273
int start
Definition: dsp.c:388
short int16_t
Definition: db.h:59
int samples_pending
Definition: dsp.c:270
float energy
Definition: dsp.c:269
char * end
Definition: eagi_proxy.c:73
static void goertzel_reset(goertzel_state_t *s)
Definition: dsp.c:382
static int mute
Definition: chan_alsa.c:144
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
float threshold
Definition: dsp.c:274
int end
Definition: dsp.c:389
#define TONE_THRESHOLD
Definition: dsp.c:181
static void goertzel_sample(goertzel_state_t *s, short sample)
Definition: dsp.c:336
static float goertzel_result(goertzel_state_t *s)
Definition: dsp.c:362
goertzel_state_t tone
Definition: dsp.c:268
int int32_t
Definition: db.h:60
int mute_samples
Definition: dsp.c:271

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2397 of file dsp.c.

References AST_TEST_UNREGISTER.

Referenced by reload_module().

2398 {
2399  AST_TEST_UNREGISTER(test_dsp_fax_detect);
2400  AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
2401 
2402  return 0;
2403 }
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

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

◆ bell_mf_positions

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

Definition at line 327 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 243 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 320 of file dsp.c.

Referenced by ast_dsp_get_threshold_from_settings(), and ast_dtmf_detect_init().

◆ dtmf_hits_to_begin

int dtmf_hits_to_begin
static

Definition at line 333 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_misses_to_end

int dtmf_misses_to_end
static

Definition at line 334 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ dtmf_normal_twist

float dtmf_normal_twist
static

Definition at line 329 of file dsp.c.

Referenced by _dsp_init(), ast_dsp_get_threshold_from_settings(), and dtmf_detect().

◆ dtmf_positions

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

Definition at line 326 of file dsp.c.

Referenced by ast_dsp_get_threshold_from_settings(), and dtmf_detect().

◆ dtmf_reverse_twist

float dtmf_reverse_twist
static

Definition at line 330 of file dsp.c.

Referenced by _dsp_init(), ast_dsp_get_threshold_from_settings(), and dtmf_detect().

◆ dtmf_row

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

Definition at line 317 of file dsp.c.

Referenced by ast_dsp_get_threshold_from_settings(), and 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 323 of file dsp.c.

Referenced by ast_mf_detect_init().

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

Referenced by _dsp_init(), and dtmf_detect().

◆ relax_dtmf_reverse_twist

float relax_dtmf_reverse_twist
static

Definition at line 332 of file dsp.c.

Referenced by _dsp_init(), and dtmf_detect().

◆ thresholds

int thresholds[THRESHOLD_MAX]
static

Definition at line 328 of file dsp.c.

Referenced by _dsp_init(), and ast_dsp_get_threshold_from_settings().