Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
dsp.c File Reference

Convenience Signal Processing routines. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/format_cache.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/test.h"
Include dependency graph for dsp.c:

Go to the source code of this file.

Data Structures

struct  ast_dsp
 
struct  digit_detect_state_t
 
struct  dtmf_detect_state_t
 
struct  fragment_t
 
struct  goertzel_result_t
 
struct  goertzel_state_t
 
struct  mf_detect_state_t
 
struct  progalias
 
struct  progress
 
struct  tone_detect_state_t
 

Macros

#define BELL_MF_RELATIVE_PEAK   12.6 /* 11dB */
 
#define BELL_MF_THRESHOLD   1.6e9
 
#define BELL_MF_TWIST   4.0 /* 6dB */
 
#define CONFIG_FILE_NAME   "dsp.conf"
 
#define DEF_DTMF_HITS_TO_BEGIN   2
 
#define DEF_DTMF_MISSES_TO_END   3
 
#define DEF_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */
 
#define DEF_DTMF_REVERSE_TWIST   2.51 /* 4.01dB */
 
#define DEF_RELAX_DTMF_NORMAL_TWIST   6.31 /* 8.0dB */
 
#define DEF_RELAX_DTMF_REVERSE_TWIST   3.98 /* 6.0dB */
 
#define DEFAULT_SAMPLE_RATE   8000
 
#define DEFAULT_THRESHOLD   512
 Default minimum average magnitude threshold to determine talking/noise by the DSP. More...
 
#define DSP_HISTORY   15
 
#define DTMF_GSIZE   102
 
#define DTMF_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_AMPLITUDE_MAX   0x7fff /* Max signed linear amplitude */
 
#define TONE_AMPLITUDE_MIN   80 /* Min signed linear amplitude detectable */
 
#define TONE_MIN_THRESH   1e8
 
#define TONE_THRESH   10.0
 
#define TONE_THRESHOLD   7.8e7
 

Enumerations

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

Functions

static int __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len)
 
static struct ast_dsp__ast_dsp_new (unsigned int sample_rate)
 
static int __ast_dsp_silence_noise (struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static int _dsp_init (int reload)
 
static void ast_digit_detect_init (digit_detect_state_t *s, int mf, unsigned int sample_rate)
 
int ast_dsp_busydetect (struct ast_dsp *dsp)
 Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called. More...
 
int ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf)
 Scans for progress indication in audio. More...
 
void ast_dsp_digitreset (struct ast_dsp *dsp)
 Reset DTMF detector. More...
 
void ast_dsp_free (struct ast_dsp *dsp)
 
int ast_dsp_get_features (struct ast_dsp *dsp)
 Get features. More...
 
unsigned int ast_dsp_get_sample_rate (const struct ast_dsp *dsp)
 Retrieve the sample rate this DSP structure was created with. More...
 
int ast_dsp_get_tcount (struct ast_dsp *dsp)
 Get tcount (Threshold counter) More...
 
int ast_dsp_get_threshold_from_settings (enum threshold which)
 Get silence threshold from dsp.conf. More...
 
int ast_dsp_get_tstate (struct ast_dsp *dsp)
 Get tstate (Tone State) More...
 
struct ast_dspast_dsp_new (void)
 Allocates a new dsp, assumes 8khz for internal sample rate. More...
 
struct ast_dspast_dsp_new_with_rate (unsigned int sample_rate)
 Allocates a new dsp with a specific internal sample rate used during processing. More...
 
int ast_dsp_noise (struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
 Process the audio frame for noise. More...
 
struct ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
 Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled. More...
 
static void ast_dsp_prog_reset (struct ast_dsp *dsp)
 
void ast_dsp_reset (struct ast_dsp *dsp)
 Reset total silence count. More...
 
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
 Set number of required cadences for busy. More...
 
void ast_dsp_set_busy_pattern (struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
 Set expected lengths of the busy tone. More...
 
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
 Set zone for doing progress detection. More...
 
int ast_dsp_set_digitmode (struct ast_dsp *dsp, int digitmode)
 Set digit mode. More...
 
int ast_dsp_set_faxmode (struct ast_dsp *dsp, int faxmode)
 Set fax mode. More...
 
void ast_dsp_set_features (struct ast_dsp *dsp, int features)
 Select feature set. More...
 
int ast_dsp_set_freqmode (struct ast_dsp *dsp, int freq, int dur, int db, int squelch)
 Set arbitrary frequency detection mode. More...
 
void ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold)
 Set the minimum average magnitude threshold to determine talking by the DSP. More...
 
int ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
 Process the audio frame for silence. More...
 
static int ast_dsp_silence_noise_with_energy (struct ast_dsp *dsp, struct ast_frame *f, int *total, int *frames_energy, int noise)
 
int ast_dsp_silence_with_energy (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence, int *frames_energy)
 Process the audio frame for silence. More...
 
int ast_dsp_was_muted (struct ast_dsp *dsp)
 Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio. More...
 
static void ast_dtmf_detect_init (dtmf_detect_state_t *s, unsigned int sample_rate)
 
static void ast_fax_detect_init (struct ast_dsp *s)
 
static void ast_freq_detect_init (struct ast_dsp *s, int freq, int dur, int db, int squelch)
 
static void ast_mf_detect_init (mf_detect_state_t *s, unsigned int sample_rate)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (test_dsp_fax_detect)
 
 AST_TEST_DEFINE (test_dsp_dtmf_detect)
 
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 test_dtmf_amplitude_sweep (struct ast_test *test, struct ast_dsp *dsp, int digit_index)
 
static int test_dtmf_twist_sweep (struct ast_test *test, struct ast_dsp *dsp, int digit_index)
 
static void test_dual_sample_gen (short *slin_buf, int samples, int rate, int f1, short a1, int f2, short a2)
 
static int test_tone_amplitude_sweep (struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state)
 
static int test_tone_freq_sweep (struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state, short amplitude)
 
static void test_tone_sample_gen (short *slin_buf, int samples, int rate, int freq, short amplitude)
 
static void test_tone_sample_gen_add (short *slin_buf, int samples, int rate, int freq, short amplitude)
 
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 test_dtmf_twist_sweep().

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

◆ 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

◆ 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 dtmf_detect(), test_dtmf_amplitude_sweep(), and test_dtmf_twist_sweep().

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

#define TONE_AMPLITUDE_MAX   0x7fff /* Max signed linear amplitude */

Definition at line 2034 of file dsp.c.

Referenced by AST_TEST_DEFINE(), test_dtmf_amplitude_sweep(), and test_tone_amplitude_sweep().

◆ TONE_AMPLITUDE_MIN

#define TONE_AMPLITUDE_MIN   80 /* Min signed linear amplitude detectable */

Definition at line 2035 of file dsp.c.

Referenced by AST_TEST_DEFINE(), test_dtmf_amplitude_sweep(), and test_tone_amplitude_sweep().

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

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

1723 {
1724  struct ast_dsp *dsp;
1725 
1726  if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
1729  dsp->busycount = DSP_HISTORY;
1732  dsp->sample_rate = sample_rate;
1733  dsp->freqcount = 0;
1734  /* Initialize digit detector */
1736  dsp->display_inband_dtmf_warning = 1;
1737  /* Initialize initial DSP progress detect parameters */
1738  ast_dsp_prog_reset(dsp);
1739  /* Initialize fax detector */
1740  ast_fax_detect_init(dsp);
1741  }
1742  return dsp;
1743 }
static void ast_digit_detect_init(digit_detect_state_t *s, int mf, unsigned int sample_rate)
Definition: dsp.c:559
#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:1700
digit_detect_state_t digit_state
Definition: dsp.c:435
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:433
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:511
#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:430
#define DSP_FAXMODE_DETECT_CNG
Definition: dsp.h:47
#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 1229 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().

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

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2466 of file dsp.c.

◆ _dsp_init()

static int _dsp_init ( int  reload)
static

Definition at line 1908 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().

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

560 {
561  s->current_digits = 0;
562  s->detected_digits = 0;
563  s->lost_digits = 0;
564  s->digits[0] = '\0';
565 
566  if (mf) {
567  ast_mf_detect_init(&s->td.mf, sample_rate);
568  } else {
569  ast_dtmf_detect_init(&s->td.dtmf, sample_rate);
570  }
571 }
union digit_detect_state_t::@383 td
int current_digits
Definition: dsp.c:307
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:531
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:547
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 1295 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().

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

1217 {
1218  if (inf->frametype != AST_FRAME_VOICE) {
1219  ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1220  return 0;
1221  }
1223  ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
1224  return 0;
1225  }
1226  return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
1227 }
#define LOG_WARNING
Definition: logger.h:274
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
Definition: dsp.c:1074
struct ast_frame_subclass subclass
#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
union ast_frame::@263 data
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 1797 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(), mbl_new(), my_dsp_reset_and_flush_digits(), test_dtmf_amplitude_sweep(), and test_dtmf_twist_sweep().

1798 {
1799  int i;
1800 
1801  dsp->dtmf_began = 0;
1802  if (dsp->digitmode & DSP_DIGITMODE_MF) {
1803  mf_detect_state_t *s = &dsp->digit_state.td.mf;
1804  /* Reinitialise the detector for the next block */
1805  for (i = 0; i < 6; i++) {
1806  goertzel_reset(&s->tone_out[i]);
1807  }
1808  s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = 0;
1809  s->current_hit = 0;
1810  s->current_sample = 0;
1811  } else {
1813  /* Reinitialise the detector for the next block */
1814  for (i = 0; i < 4; i++) {
1815  goertzel_reset(&s->row_out[i]);
1816  goertzel_reset(&s->col_out[i]);
1817  }
1818  s->lasthit = 0;
1819  s->current_hit = 0;
1820  s->energy = 0.0;
1821  s->current_sample = 0;
1822  s->hits = 0;
1823  s->misses = 0;
1824  }
1825 
1826  dsp->digit_state.digits[0] = '\0';
1827  dsp->digit_state.current_digits = 0;
1828 }
union digit_detect_state_t::@383 td
#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
static void goertzel_reset(goertzel_state_t *s)
Definition: dsp.c:382
digit_detect_state_t digit_state
Definition: dsp.c:435
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:429
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 1764 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().

1765 {
1766  return (dsp->features);
1767 }
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 1717 of file dsp.c.

References ast_dsp::sample_rate.

1718 {
1719  return dsp->sample_rate;
1720 }
unsigned int sample_rate
Definition: dsp.c:433

◆ ast_dsp_get_tcount()

int ast_dsp_get_tcount ( struct ast_dsp dsp)

Get tcount (Threshold counter)

Definition at line 1903 of file dsp.c.

References ast_dsp::tcount.

Referenced by dahdi_read().

1904 {
1905  return dsp->tcount;
1906 }
int tcount
Definition: dsp.c:425

◆ ast_dsp_get_threshold_from_settings()

int ast_dsp_get_threshold_from_settings ( enum threshold  which)

Get silence threshold from dsp.conf.

Since
1.6.1

Definition at line 1996 of file dsp.c.

References thresholds.

Referenced by actual_load_config(), app_exec(), ast_record_review(), conf_rec_name(), conf_run(), do_waiting(), handle_recordfile(), load_config(), record_exec(), setup_privacy_args(), and talk_detect_fn_write().

1997 {
1998  return thresholds[which];
1999 }
static int thresholds[THRESHOLD_MAX]
Definition: dsp.c:328

◆ ast_dsp_get_tstate()

int ast_dsp_get_tstate ( struct ast_dsp dsp)

Get tstate (Tone State)

Definition at line 1898 of file dsp.c.

References ast_dsp::tstate.

Referenced by dahdi_read().

1899 {
1900  return dsp->tstate;
1901 }
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 1750 of file dsp.c.

References __ast_dsp_new().

Referenced by set_softmix_bridge_data(), and set_talk_detect().

1751 {
1752  return __ast_dsp_new(sample_rate);
1753 }
static struct ast_dsp * __ast_dsp_new(unsigned int sample_rate)
Definition: dsp.c:1722

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

References ast_dsp_silence_noise_with_energy(), and NULL.

1489 {
1490  return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
1491 }
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:1433
#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 1494 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_FREQ_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, DSP_FEATURE_WAITDIALTONE, ast_dsp::dtmf_began, dtmf_detect(), fragment_t::end, ast_dsp::f, ast_dsp::faxmode, ast_dsp::features, ast_frame_subclass::format, ast_frame::frametype, ast_dsp::freqmode, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_frame_subclass::integer, 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(), detect_callback(), fax_detect_framehook(), mbl_read(), mgcp_rtp_read(), ooh323_rtp_read(), process_ast_dsp(), read_mf_digits(), read_sf_digits(), sip_rtp_read(), and wait_exec().

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

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

1831 {
1832  int x;
1833 
1834  dsp->totalsilence = 0;
1835  dsp->gsamps = 0;
1836  for (x = 0; x < 4; x++) {
1837  dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1838  }
1839  memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1840  memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1841  dsp->ringtimeout = 0;
1842 }
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 1780 of file dsp.c.

References ast_dsp::busycount, cadences, and DSP_HISTORY.

Referenced by dahdi_new().

1781 {
1782  if (cadences < 4) {
1783  cadences = 4;
1784  }
1785  if (cadences > DSP_HISTORY) {
1787  }
1788  dsp->busycount = cadences;
1789 }
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 1791 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().

1792 {
1793  dsp->busy_cadence = *cadence;
1794  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);
1795 }
int pattern[4]
Definition: dsp.h:68
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
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 1879 of file dsp.c.

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

Referenced by dahdi_new().

1880 {
1881  int x;
1882 
1883  for (x = 0; x < ARRAY_LEN(aliases); x++) {
1884  if (!strcasecmp(aliases[x].name, zone)) {
1885  dsp->progmode = aliases[x].mode;
1886  ast_dsp_prog_reset(dsp);
1887  return 0;
1888  }
1889  }
1890  return -1;
1891 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void ast_dsp_prog_reset(struct ast_dsp *dsp)
Definition: dsp.c:1700
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 1844 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(), ooh323_new(), and read_mf_digits().

1845 {
1846  int new;
1847  int old;
1848 
1851  if (old != new) {
1852  /* Must initialize structures if switching from MF to DTMF or vice-versa */
1854  }
1855  dsp->digitmode = digitmode;
1856  return 0;
1857 }
static void ast_digit_detect_init(digit_detect_state_t *s, int mf, unsigned int sample_rate)
Definition: dsp.c:559
#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:435
unsigned int sample_rate
Definition: dsp.c:433
#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 1870 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

Referenced by fax_detect_new(), and ooh323_new().

1871 {
1872  if (dsp->faxmode != faxmode) {
1873  dsp->faxmode = faxmode;
1874  ast_fax_detect_init(dsp);
1875  }
1876  return 0;
1877 }
int faxmode
Definition: dsp.c:427
static void ast_fax_detect_init(struct ast_dsp *s)
Definition: dsp.c:511

◆ ast_dsp_set_features()

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

◆ ast_dsp_set_freqmode()

int ast_dsp_set_freqmode ( struct ast_dsp dsp,
int  freq,
int  dur,
int  db,
int  squelch 
)

Set arbitrary frequency detection mode.

Definition at line 1859 of file dsp.c.

References ast_freq_detect_init(), and ast_dsp::freqmode.

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

1860 {
1861  if (freq > 0) {
1862  dsp->freqmode = 1;
1863  ast_freq_detect_init(dsp, freq, dur, db, squelch);
1864  } else {
1865  dsp->freqmode = 0;
1866  }
1867  return 0;
1868 }
int freqmode
Definition: dsp.c:428
static sqlite3 * db
static void ast_freq_detect_init(struct ast_dsp *s, int freq, int dur, int db, int squelch)
Definition: dsp.c:522

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

1776 {
1777  dsp->threshold = threshold;
1778 }
threshold
Definition: dsp.h:71
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 1483 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().

1484 {
1485  return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
1486 }
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:1433
#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 1433 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_CMP_EQUAL, ast_format_ulaw, AST_FRAME_VOICE, ast_log, AST_MULAW, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, len(), LOG_WARNING, NULL, ast_frame::ptr, and ast_frame::subclass.

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

1434 {
1435  short *s;
1436  int len;
1437  int x;
1438  unsigned char *odata;
1439 
1440  if (!f) {
1441  return 0;
1442  }
1443 
1444  if (f->frametype != AST_FRAME_VOICE) {
1445  ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
1446  return 0;
1447  }
1448 
1450  s = f->data.ptr;
1451  len = f->datalen/2;
1452  } else {
1453  odata = f->data.ptr;
1454  len = f->datalen;
1456  s = ast_alloca(len * 2);
1457  for (x = 0; x < len; x++) {
1458  s[x] = AST_MULAW(odata[x]);
1459  }
1461  s = ast_alloca(len * 2);
1462  for (x = 0; x < len; x++) {
1463  s[x] = AST_ALAW(odata[x]);
1464  }
1465  } else {
1466  ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames :(\n");
1467  return 0;
1468  }
1469  }
1470 
1471  if (noise) {
1472  return __ast_dsp_silence_noise(dsp, s, len, NULL, total, frames_energy);
1473  } else {
1474  return __ast_dsp_silence_noise(dsp, s, len, total, NULL, frames_energy);
1475  }
1476 }
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
#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:1229
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
static int total
Definition: res_adsi.c:968
union ast_frame::@263 data
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 1478 of file dsp.c.

References ast_dsp_silence_noise_with_energy().

Referenced by softmix_bridge_write_voice().

1479 {
1480  return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
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:1433

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

References ast_dsp::mute_fragments.

Referenced by dahdi_read().

1894 {
1895  return (dsp->mute_fragments > 0);
1896 }
int mute_fragments
Definition: dsp.c:432

◆ ast_dtmf_detect_init()

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

Definition at line 531 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().

532 {
533  int i;
534 
535  for (i = 0; i < 4; i++) {
536  goertzel_init(&s->row_out[i], dtmf_row[i], sample_rate);
537  goertzel_init(&s->col_out[i], dtmf_col[i], sample_rate);
538  }
539  s->lasthit = 0;
540  s->current_hit = 0;
541  s->energy = 0.0;
542  s->current_sample = 0;
543  s->hits = 0;
544  s->misses = 0;
545 }
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 511 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().

512 {
516  s->cng_tone_state.squelch = 1;
517  s->ced_tone_state.squelch = 1;
518  }
519 
520 }
#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:49
#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:433
static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, int amp, unsigned int sample_rate)
Definition: dsp.c:450
tone_detect_state_t ced_tone_state
Definition: dsp.c:437
tone_detect_state_t cng_tone_state
Definition: dsp.c:436

◆ ast_freq_detect_init()

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

Definition at line 522 of file dsp.c.

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

Referenced by ast_dsp_set_freqmode().

523 {
524  /* we can conveniently just use one of the two fax tone states */
525  ast_tone_detect_init(&s->cng_tone_state, freq, dur, db, s->sample_rate);
526  if (s->freqmode & squelch) {
527  s->cng_tone_state.squelch = 1;
528  }
529 }
int freqmode
Definition: dsp.c:428
static sqlite3 * db
unsigned int sample_rate
Definition: dsp.c:433
static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, int amp, unsigned int sample_rate)
Definition: dsp.c:450
tone_detect_state_t cng_tone_state
Definition: dsp.c:436

◆ ast_mf_detect_init()

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

Definition at line 547 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().

548 {
549  int i;
550 
551  for (i = 0; i < 6; i++) {
552  goertzel_init(&s->tone_out[i], mf_tones[i], sample_rate);
553  }
554  s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
555  s->current_sample = 0;
556  s->current_hit = 0;
557 }
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 2466 of file dsp.c.

◆ AST_TEST_DEFINE() [1/2]

AST_TEST_DEFINE ( test_dsp_fax_detect  )

Definition at line 2336 of file dsp.c.

References ast_dsp_free(), ast_dsp_new(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, sip_to_pjsip::info(), result, TEST_EXECUTE, TEST_INIT, test_tone_amplitude_sweep(), test_tone_freq_sweep(), TONE_AMPLITUDE_MAX, and TONE_AMPLITUDE_MIN.

2337 {
2338  struct ast_dsp *dsp;
2340 
2341  switch (cmd) {
2342  case TEST_INIT:
2343  info->name = "fax";
2344  info->category = "/main/dsp/";
2345  info->summary = "DSP fax tone detect unit test";
2346  info->description =
2347  "Tests fax tone detection code.";
2348  return AST_TEST_NOT_RUN;
2349  case TEST_EXECUTE:
2350  break;
2351  }
2352 
2353  dsp = ast_dsp_new();
2354  if (!dsp) {
2355  return AST_TEST_FAIL;
2356  }
2357 
2358  result = AST_TEST_PASS;
2359 
2360  /* Test CNG tone amplitude detection */
2361  if (test_tone_amplitude_sweep(test, dsp, &dsp->cng_tone_state)) {
2362  result = AST_TEST_FAIL;
2363  }
2364 
2365  /* Test CED tone amplitude detection */
2366  if (test_tone_amplitude_sweep(test, dsp, &dsp->ced_tone_state)) {
2367  result = AST_TEST_FAIL;
2368  }
2369 
2370  /* Test CNG tone frequency detection */
2372  result = AST_TEST_FAIL;
2373  }
2375  result = AST_TEST_FAIL;
2376  }
2377 
2378  /* Test CED tone frequency detection */
2380  result = AST_TEST_FAIL;
2381  }
2383  result = AST_TEST_FAIL;
2384  }
2385 
2386  ast_dsp_free(dsp);
2387  return result;
2388 }
static int test_tone_freq_sweep(struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state, short amplitude)
Definition: dsp.c:2274
Definition: dsp.c:405
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
static int test_tone_amplitude_sweep(struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state)
Definition: dsp.c:2037
#define TONE_AMPLITUDE_MIN
Definition: dsp.c:2035
def info(msg)
#define TONE_AMPLITUDE_MAX
Definition: dsp.c:2034
tone_detect_state_t ced_tone_state
Definition: dsp.c:437
static PGresult * result
Definition: cel_pgsql.c:88
tone_detect_state_t cng_tone_state
Definition: dsp.c:436
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
ast_test_result_state
Definition: test.h:200

◆ AST_TEST_DEFINE() [2/2]

AST_TEST_DEFINE ( test_dsp_dtmf_detect  )

Definition at line 2392 of file dsp.c.

References ast_dsp_free(), ast_dsp_new(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, dtmf_positions, sip_to_pjsip::info(), result, test_dtmf_amplitude_sweep(), test_dtmf_twist_sweep(), TEST_EXECUTE, and TEST_INIT.

2393 {
2394  int idx;
2395  struct ast_dsp *dsp;
2397 
2398  switch (cmd) {
2399  case TEST_INIT:
2400  info->name = "dtmf";
2401  info->category = "/main/dsp/";
2402  info->summary = "DSP DTMF detect unit test";
2403  info->description =
2404  "Tests DTMF detection code.";
2405  return AST_TEST_NOT_RUN;
2406  case TEST_EXECUTE:
2407  break;
2408  }
2409 
2410  dsp = ast_dsp_new();
2411  if (!dsp) {
2412  return AST_TEST_FAIL;
2413  }
2414 
2415  result = AST_TEST_PASS;
2416 
2417  for (idx = 0; dtmf_positions[idx]; ++idx) {
2418  if (test_dtmf_amplitude_sweep(test, dsp, idx)) {
2419  result = AST_TEST_FAIL;
2420  }
2421  }
2422 
2423  for (idx = 0; dtmf_positions[idx]; ++idx) {
2424  if (test_dtmf_twist_sweep(test, dsp, idx)) {
2425  result = AST_TEST_FAIL;
2426  }
2427  }
2428 
2429  ast_dsp_free(dsp);
2430  return result;
2431 }
static int test_dtmf_twist_sweep(struct ast_test *test, struct ast_dsp *dsp, int digit_index)
Definition: dsp.c:2176
static const char dtmf_positions[]
Definition: dsp.c:326
static int test_dtmf_amplitude_sweep(struct ast_test *test, struct ast_dsp *dsp, int digit_index)
Definition: dsp.c:2096
Definition: dsp.c:405
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
def info(msg)
static PGresult * result
Definition: cel_pgsql.c:88
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
ast_test_result_state
Definition: test.h:200

◆ 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 450 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(), and ast_freq_detect_init().

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

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

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

Referenced by reload_module().

2443 {
2444  if (_dsp_init(0)) {
2445  return AST_MODULE_LOAD_FAILURE;
2446  }
2447 
2448  AST_TEST_REGISTER(test_dsp_fax_detect);
2449  AST_TEST_REGISTER(test_dsp_dtmf_detect);
2450 
2451  return AST_MODULE_LOAD_SUCCESS;
2452 }
#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:1908

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

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

441 {
442  if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
443  ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
444  return;
445  }
446 
447  dsp->mute_data[dsp->mute_fragments++] = *fragment;
448 }
#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:432
fragment_t mute_data[5]
Definition: dsp.c:434

◆ pair_there()

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

Definition at line 1051 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

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

2455 {
2456  return _dsp_init(1);
2457 }
static int _dsp_init(int reload)
Definition: dsp.c:1908

◆ store_digit()

static void store_digit ( digit_detect_state_t s,
char  digit 
)
static

Definition at line 680 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().

681 {
682  s->detected_digits++;
683  if (s->current_digits < MAX_DTMF_DIGITS) {
684  s->digitlen[s->current_digits] = 0;
685  s->digits[s->current_digits++] = digit;
686  s->digits[s->current_digits] = '\0';
687  } else {
688  ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
689  s->lost_digits++;
690  }
691 }
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

◆ test_dtmf_amplitude_sweep()

static int test_dtmf_amplitude_sweep ( struct ast_test test,
struct ast_dsp dsp,
int  digit_index 
)
static

Definition at line 2096 of file dsp.c.

References ARRAY_LEN, ast_debug, ast_dsp_digitreset(), ast_test_status_update, DEFAULT_SAMPLE_RATE, digit, ast_dsp::digit_state, dtmf_col, dtmf_detect(), DTMF_GSIZE, dtmf_positions, dtmf_row, result, test_dual_sample_gen(), TONE_AMPLITUDE_MAX, and TONE_AMPLITUDE_MIN.

Referenced by AST_TEST_DEFINE().

2097 {
2098  short slin_buf[DTMF_GSIZE];
2099  int result;
2100  int row;
2101  int column;
2102  int idx;
2103  struct {
2104  short amp_val;
2105  int digit;
2106  } amp_tests[] = {
2107  /*
2108  * XXX Since there is no current DTMF level detection issue. This test
2109  * just checks the current detection levels.
2110  */
2111  { .amp_val = TONE_AMPLITUDE_MAX/2, .digit = dtmf_positions[digit_index], },
2112  { .amp_val = 10000, .digit = dtmf_positions[digit_index], },
2113  { .amp_val = 1000, .digit = dtmf_positions[digit_index], },
2114  { .amp_val = 500, .digit = dtmf_positions[digit_index], },
2115  { .amp_val = 250, .digit = dtmf_positions[digit_index], },
2116  { .amp_val = 200, .digit = dtmf_positions[digit_index], },
2117  { .amp_val = 180, .digit = dtmf_positions[digit_index], },
2118  /* Various digits detect and not detect in this range */
2119  { .amp_val = 170, .digit = 0, },
2120  { .amp_val = 100, .digit = 0, },
2121  /*
2122  * Amplitudes below TONE_AMPLITUDE_MIN start having questionable detection
2123  * over quantization and background noise.
2124  */
2125  { .amp_val = TONE_AMPLITUDE_MIN, .digit = 0, },
2126  { .amp_val = 75, .digit = 0, },
2127  { .amp_val = 10, .digit = 0, },
2128  { .amp_val = 1, .digit = 0, },
2129  };
2130 
2131  row = (digit_index >> 2) & 0x03;
2132  column = digit_index & 0x03;
2133 
2134  result = 0;
2135 
2136  for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
2137  int digit;
2138  int duration;
2139 
2140  ast_debug(1, "Test '%c' at amplitude %d\n",
2141  dtmf_positions[digit_index], amp_tests[idx].amp_val);
2142  test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
2143  (int) dtmf_row[row], amp_tests[idx].amp_val,
2144  (int) dtmf_col[column], amp_tests[idx].amp_val);
2145 
2146  digit = 0;
2147  for (duration = 0; !digit && duration < 3; ++duration) {
2148  digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
2149  0, 0);
2150  }
2151  if (amp_tests[idx].digit != digit) {
2152  /*
2153  * Both messages are needed. ast_debug for when figuring out
2154  * what went wrong and the test update for normal output before
2155  * you start debugging. The different logging methods are not
2156  * synchronized.
2157  */
2158  ast_debug(1,
2159  "Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
2160  dtmf_positions[digit_index], amp_tests[idx].amp_val,
2161  digit ?: ' ');
2163  "Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
2164  dtmf_positions[digit_index], amp_tests[idx].amp_val,
2165  digit ?: ' ');
2166  result = -1;
2167  }
2168  ast_dsp_digitreset(dsp);
2169  }
2170 
2171  return result;
2172 }
char digit
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
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:693
static const char dtmf_positions[]
Definition: dsp.c:326
#define DTMF_GSIZE
Definition: dsp.c:227
digit_detect_state_t digit_state
Definition: dsp.c:435
static const float dtmf_col[]
Definition: dsp.c:320
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static const float dtmf_row[]
Definition: dsp.c:317
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition: dsp.c:1797
#define TONE_AMPLITUDE_MIN
Definition: dsp.c:2035
#define TONE_AMPLITUDE_MAX
Definition: dsp.c:2034
#define DEFAULT_SAMPLE_RATE
Definition: dsp.c:221
static void test_dual_sample_gen(short *slin_buf, int samples, int rate, int f1, short a1, int f2, short a2)
Definition: dsp.c:2026
static PGresult * result
Definition: cel_pgsql.c:88

◆ test_dtmf_twist_sweep()

static int test_dtmf_twist_sweep ( struct ast_test test,
struct ast_dsp dsp,
int  digit_index 
)
static

Definition at line 2176 of file dsp.c.

References ARRAY_LEN, ast_debug, ast_dsp_digitreset(), ast_test_status_update, DEF_DTMF_NORMAL_TWIST, DEF_DTMF_REVERSE_TWIST, DEFAULT_SAMPLE_RATE, digit, ast_dsp::digit_state, dtmf_col, dtmf_detect(), DTMF_GSIZE, dtmf_normal_twist, dtmf_positions, dtmf_reverse_twist, dtmf_row, result, and test_dual_sample_gen().

Referenced by AST_TEST_DEFINE().

2177 {
2178  short slin_buf[DTMF_GSIZE];
2179  int result;
2180  int row;
2181  int column;
2182  int idx;
2183  struct {
2184  short amp_row;
2185  short amp_col;
2186  int digit;
2187  } twist_tests[] = {
2188  /*
2189  * XXX Since there is no current DTMF twist detection issue. This test
2190  * just checks the current detection levels.
2191  *
2192  * Normal twist has the column higher than the row amplitude.
2193  * Reverse twist is the other way.
2194  */
2195  { .amp_row = 1000 + 1800, .amp_col = 1000 + 0, .digit = 0, },
2196  { .amp_row = 1000 + 1700, .amp_col = 1000 + 0, .digit = 0, },
2197  /* Various digits detect and not detect in this range */
2198  { .amp_row = 1000 + 1400, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2199  { .amp_row = 1000 + 1300, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2200  { .amp_row = 1000 + 1200, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2201  { .amp_row = 1000 + 1100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2202  { .amp_row = 1000 + 1000, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2203  { .amp_row = 1000 + 100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2204  { .amp_row = 1000 + 0, .amp_col = 1000 + 100, .digit = dtmf_positions[digit_index], },
2205  { .amp_row = 1000 + 0, .amp_col = 1000 + 200, .digit = dtmf_positions[digit_index], },
2206  { .amp_row = 1000 + 0, .amp_col = 1000 + 300, .digit = dtmf_positions[digit_index], },
2207  { .amp_row = 1000 + 0, .amp_col = 1000 + 400, .digit = dtmf_positions[digit_index], },
2208  { .amp_row = 1000 + 0, .amp_col = 1000 + 500, .digit = dtmf_positions[digit_index], },
2209  { .amp_row = 1000 + 0, .amp_col = 1000 + 550, .digit = dtmf_positions[digit_index], },
2210  /* Various digits detect and not detect in this range */
2211  { .amp_row = 1000 + 0, .amp_col = 1000 + 650, .digit = 0, },
2212  { .amp_row = 1000 + 0, .amp_col = 1000 + 700, .digit = 0, },
2213  { .amp_row = 1000 + 0, .amp_col = 1000 + 800, .digit = 0, },
2214  };
2215  float save_normal_twist;
2216  float save_reverse_twist;
2217 
2218  save_normal_twist = dtmf_normal_twist;
2219  save_reverse_twist = dtmf_reverse_twist;
2222 
2223  row = (digit_index >> 2) & 0x03;
2224  column = digit_index & 0x03;
2225 
2226  result = 0;
2227 
2228  for (idx = 0; idx < ARRAY_LEN(twist_tests); ++idx) {
2229  int digit;
2230  int duration;
2231 
2232  ast_debug(1, "Test '%c' twist row %d col %d amplitudes\n",
2233  dtmf_positions[digit_index],
2234  twist_tests[idx].amp_row, twist_tests[idx].amp_col);
2235  test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
2236  (int) dtmf_row[row], twist_tests[idx].amp_row,
2237  (int) dtmf_col[column], twist_tests[idx].amp_col);
2238 
2239  digit = 0;
2240  for (duration = 0; !digit && duration < 3; ++duration) {
2241  digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
2242  0, 0);
2243  }
2244  if (twist_tests[idx].digit != digit) {
2245  /*
2246  * Both messages are needed. ast_debug for when figuring out
2247  * what went wrong and the test update for normal output before
2248  * you start debugging. The different logging methods are not
2249  * synchronized.
2250  */
2251  ast_debug(1,
2252  "Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
2253  dtmf_positions[digit_index],
2254  twist_tests[idx].amp_row, twist_tests[idx].amp_col,
2255  digit ?: ' ');
2257  "Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
2258  dtmf_positions[digit_index],
2259  twist_tests[idx].amp_row, twist_tests[idx].amp_col,
2260  digit ?: ' ');
2261  result = -1;
2262  }
2263  ast_dsp_digitreset(dsp);
2264  }
2265 
2266  dtmf_normal_twist = save_normal_twist;
2267  dtmf_reverse_twist = save_reverse_twist;
2268 
2269  return result;
2270 }
char digit
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define DEF_DTMF_NORMAL_TWIST
Definition: dsp.c:183
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:693
static const char dtmf_positions[]
Definition: dsp.c:326
#define DTMF_GSIZE
Definition: dsp.c:227
digit_detect_state_t digit_state
Definition: dsp.c:435
static const float dtmf_col[]
Definition: dsp.c:320
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define DEF_DTMF_REVERSE_TWIST
Definition: dsp.c:190
static const float dtmf_row[]
Definition: dsp.c:317
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition: dsp.c:1797
static float dtmf_normal_twist
Definition: dsp.c:329
#define DEFAULT_SAMPLE_RATE
Definition: dsp.c:221
static void test_dual_sample_gen(short *slin_buf, int samples, int rate, int f1, short a1, int f2, short a2)
Definition: dsp.c:2026
static PGresult * result
Definition: cel_pgsql.c:88
static float dtmf_reverse_twist
Definition: dsp.c:330

◆ test_dual_sample_gen()

static void test_dual_sample_gen ( short *  slin_buf,
int  samples,
int  rate,
int  f1,
short  a1,
int  f2,
short  a2 
)
static

Definition at line 2026 of file dsp.c.

References test_tone_sample_gen(), and test_tone_sample_gen_add().

Referenced by test_dtmf_amplitude_sweep(), and test_dtmf_twist_sweep().

2027 {
2028  test_tone_sample_gen(slin_buf, samples, rate, f1, a1);
2029  test_tone_sample_gen_add(slin_buf, samples, rate, f2, a2);
2030 }
static void test_tone_sample_gen(short *slin_buf, int samples, int rate, int freq, short amplitude)
Definition: dsp.c:2002
static void test_tone_sample_gen_add(short *slin_buf, int samples, int rate, int freq, short amplitude)
Definition: dsp.c:2014

◆ test_tone_amplitude_sweep()

static int test_tone_amplitude_sweep ( struct ast_test test,
struct ast_dsp dsp,
tone_detect_state_t tone_state 
)
static

Definition at line 2037 of file dsp.c.

References ARRAY_LEN, ast_debug, ast_test_status_update, tone_detect_state_t::block_size, DEFAULT_SAMPLE_RATE, tone_detect_state_t::freq, tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, result, test_tone_sample_gen(), TONE_AMPLITUDE_MAX, TONE_AMPLITUDE_MIN, and tone_detect().

Referenced by AST_TEST_DEFINE().

2038 {
2039  short slin_buf[tone_state->block_size];
2040  int result;
2041  int idx;
2042  struct {
2043  short amp_val;
2044  int detect;
2045  } amp_tests[] = {
2046  { .amp_val = TONE_AMPLITUDE_MAX, .detect = 1, },
2047  { .amp_val = 10000, .detect = 1, },
2048  { .amp_val = 1000, .detect = 1, },
2049  { .amp_val = 100, .detect = 1, },
2050  { .amp_val = TONE_AMPLITUDE_MIN, .detect = 1, },
2051  { .amp_val = 75, .detect = 0, },
2052  { .amp_val = 10, .detect = 0, },
2053  { .amp_val = 1, .detect = 0, },
2054  };
2055 
2056  result = 0;
2057 
2058  for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
2059  int detected;
2060  int duration;
2061 
2062  ast_debug(1, "Test %d Hz at amplitude %d\n",
2063  tone_state->freq, amp_tests[idx].amp_val);
2064  test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE,
2065  tone_state->freq, amp_tests[idx].amp_val);
2066 
2067  detected = 0;
2068  for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
2069  detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
2070  }
2071  if (amp_tests[idx].detect != detected) {
2072  /*
2073  * Both messages are needed. ast_debug for when figuring out
2074  * what went wrong and the test update for normal output before
2075  * you start debugging. The different logging methods are not
2076  * synchronized.
2077  */
2078  ast_debug(1,
2079  "Test %d Hz at amplitude %d failed. Detected: %s\n",
2080  tone_state->freq, amp_tests[idx].amp_val,
2081  detected ? "yes" : "no");
2083  "Test %d Hz at amplitude %d failed. Detected: %s\n",
2084  tone_state->freq, amp_tests[idx].amp_val,
2085  detected ? "yes" : "no");
2086  result = -1;
2087  }
2088  tone_state->hit_count = 0;
2089  }
2090 
2091  return result;
2092 }
int hits_required
Definition: dsp.c:273
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void test_tone_sample_gen(short *slin_buf, int samples, int rate, int freq, short amplitude)
Definition: dsp.c:2002
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define TONE_AMPLITUDE_MIN
Definition: dsp.c:2035
#define TONE_AMPLITUDE_MAX
Definition: dsp.c:2034
#define DEFAULT_SAMPLE_RATE
Definition: dsp.c:221
static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
Definition: dsp.c:573
static PGresult * result
Definition: cel_pgsql.c:88

◆ test_tone_freq_sweep()

static int test_tone_freq_sweep ( struct ast_test test,
struct ast_dsp dsp,
tone_detect_state_t tone_state,
short  amplitude 
)
static

Definition at line 2274 of file dsp.c.

References ast_debug, ast_test_status_update, tone_detect_state_t::block_size, DEFAULT_SAMPLE_RATE, tone_detect_state_t::freq, tone_detect_state_t::hit_count, tone_detect_state_t::hits_required, result, test_tone_sample_gen(), and tone_detect().

Referenced by AST_TEST_DEFINE().

2275 {
2276  short slin_buf[tone_state->block_size];
2277  int result;
2278  int freq;
2279  int lower_freq;
2280  int upper_freq;
2281 
2282  /* Calculate detection frequency range */
2283  lower_freq = tone_state->freq - 4;
2284  upper_freq = tone_state->freq + 4;
2285 
2286  result = 0;
2287 
2288  /* Sweep frequencies loop. */
2289  for (freq = 100; freq <= 3500; freq += 1) {
2290  int detected;
2291  int duration;
2292  int expect_detection;
2293 
2294  if (freq == tone_state->freq) {
2295  /* This case is done by the amplitude sweep. */
2296  continue;
2297  }
2298 
2299  expect_detection = (lower_freq <= freq && freq <= upper_freq) ? 1 : 0;
2300 
2301  ast_debug(1, "Test %d Hz detection given %d Hz tone at amplitude %d. Range:%d-%d Expect detect: %s\n",
2302  tone_state->freq, freq, amplitude, lower_freq, upper_freq,
2303  expect_detection ? "yes" : "no");
2304  test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE, freq,
2305  amplitude);
2306 
2307  detected = 0;
2308  for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
2309  detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
2310  }
2311  if (expect_detection != detected) {
2312  /*
2313  * Both messages are needed. ast_debug for when figuring out
2314  * what went wrong and the test update for normal output before
2315  * you start debugging. The different logging methods are not
2316  * synchronized.
2317  */
2318  ast_debug(1,
2319  "Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
2320  tone_state->freq, freq, amplitude, lower_freq, upper_freq,
2321  detected ? "yes" : "no");
2323  "Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
2324  tone_state->freq, freq, amplitude, lower_freq, upper_freq,
2325  detected ? "yes" : "no");
2326  result = -1;
2327  }
2328  tone_state->hit_count = 0;
2329  }
2330 
2331  return result;
2332 }
int hits_required
Definition: dsp.c:273
static void test_tone_sample_gen(short *slin_buf, int samples, int rate, int freq, short amplitude)
Definition: dsp.c:2002
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define DEFAULT_SAMPLE_RATE
Definition: dsp.c:221
static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
Definition: dsp.c:573
static PGresult * result
Definition: cel_pgsql.c:88

◆ test_tone_sample_gen()

static void test_tone_sample_gen ( short *  slin_buf,
int  samples,
int  rate,
int  freq,
short  amplitude 
)
static

Definition at line 2002 of file dsp.c.

References M_PI.

Referenced by test_dual_sample_gen(), test_tone_amplitude_sweep(), and test_tone_freq_sweep().

2003 {
2004  int idx;
2005  double sample_step = 2.0 * M_PI * freq / rate;/* radians per step */
2006 
2007  for (idx = 0; idx < samples; ++idx) {
2008  slin_buf[idx] = amplitude * sin(sample_step * idx);
2009  }
2010 }
#define M_PI
Definition: resample.c:83

◆ test_tone_sample_gen_add()

static void test_tone_sample_gen_add ( short *  slin_buf,
int  samples,
int  rate,
int  freq,
short  amplitude 
)
static

Definition at line 2014 of file dsp.c.

References M_PI.

Referenced by test_dual_sample_gen().

2015 {
2016  int idx;
2017  double sample_step = 2.0 * M_PI * freq / rate;/* radians per step */
2018 
2019  for (idx = 0; idx < samples; ++idx) {
2020  slin_buf[idx] += amplitude * sin(sample_step * idx);
2021  }
2022 }
#define M_PI
Definition: resample.c:83

◆ tone_detect()

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

Definition at line 573 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_process(), test_tone_amplitude_sweep(), and test_tone_freq_sweep().

574 {
575  float tone_energy;
576  int i;
577  int hit = 0;
578  int limit;
579  int res = 0;
580  int16_t *ptr;
581  short samp;
582  int start, end;
583  fragment_t mute = {0, 0};
584 
585  if (s->squelch && s->mute_samples > 0) {
586  mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
587  s->mute_samples -= mute.end;
588  }
589 
590  for (start = 0; start < samples; start = end) {
591  /* Process in blocks. */
592  limit = samples - start;
593  if (limit > s->samples_pending) {
594  limit = s->samples_pending;
595  }
596  end = start + limit;
597 
598  for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
599  samp = *ptr;
600  /* signed 32 bit int should be enough to square any possible signed 16 bit value */
601  s->energy += (int32_t) samp * (int32_t) samp;
602 
603  goertzel_sample(&s->tone, samp);
604  }
605 
606  s->samples_pending -= limit;
607 
608  if (s->samples_pending) {
609  /* Finished incomplete (last) block */
610  break;
611  }
612 
613  tone_energy = goertzel_result(&s->tone);
614 
615  /* Scale to make comparable */
616  tone_energy *= 2.0;
617  s->energy *= s->block_size;
618 
619  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));
620  hit = 0;
621  if (TONE_THRESHOLD <= tone_energy
622  && tone_energy > s->energy * s->threshold) {
623  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));
624  hit = 1;
625  }
626 
627  if (s->hit_count) {
628  s->hit_count++;
629  }
630 
631  if (hit == s->last_hit) {
632  if (!hit) {
633  /* Two successive misses. Tone ended */
634  s->hit_count = 0;
635  } else if (!s->hit_count) {
636  s->hit_count++;
637  }
638 
639  }
640 
641  if (s->hit_count == s->hits_required) {
642  ast_debug(1, "%d Hz tone detected\n", s->freq);
643  res = 1;
644  }
645 
646  s->last_hit = hit;
647 
648  /* If we had a hit in this block, include it into mute fragment */
649  if (s->squelch && hit) {
650  if (mute.end < start - s->block_size) {
651  /* There is a gap between fragments */
652  mute_fragment(dsp, &mute);
653  mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
654  }
655  mute.end = end + s->block_size;
656  }
657 
658  /* Reinitialise the detector for the next block */
659  /* Reset for the next block */
660  goertzel_reset(&s->tone);
661 
662  /* Advance to the next block */
663  s->energy = 0.0;
664  s->samples_pending = s->block_size;
665 
666  amp += limit;
667  }
668 
669  if (s->squelch && mute.end) {
670  if (mute.end > samples) {
671  s->mute_samples = mute.end - samples;
672  mute.end = samples;
673  }
674  mute_fragment(dsp, &mute);
675  }
676 
677  return res;
678 }
static void mute_fragment(struct ast_dsp *dsp, fragment_t *fragment)
Definition: dsp.c:440
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:452
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 2434 of file dsp.c.

References AST_TEST_UNREGISTER.

Referenced by reload_module().

2435 {
2436  AST_TEST_UNREGISTER(test_dsp_fax_detect);
2437  AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
2438 
2439  return 0;
2440 }
#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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 2466 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 2466 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_dtmf_detect_init(), test_dtmf_amplitude_sweep(), and test_dtmf_twist_sweep().

◆ 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(), dtmf_detect(), and test_dtmf_twist_sweep().

◆ dtmf_positions

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

◆ dtmf_reverse_twist

float dtmf_reverse_twist
static

Definition at line 330 of file dsp.c.

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

◆ 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_dtmf_detect_init(), test_dtmf_amplitude_sweep(), and test_dtmf_twist_sweep().

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

◆ modes

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

Referenced by ast_dsp_prog_reset().

◆ relax_dtmf_normal_twist

float relax_dtmf_normal_twist
static

Definition at line 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().