Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:48 2009

## Asterisk developer's documentation

# dsp.c File Reference

Convenience Signal Processing routines. More...

`#include <sys/types.h>`
`#include <stdlib.h>`
`#include <unistd.h>`
`#include <string.h>`
`#include <math.h>`
`#include <errno.h>`
`#include <stdio.h>`
`#include "asterisk.h"`
`#include "asterisk/frame.h"`
`#include "asterisk/channel.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/dsp.h"`
`#include "asterisk/ulaw.h"`
`#include "asterisk/alaw.h"`

Include dependency graph for dsp.c:

Go to the source code of this file.

## Data Structures

struct | ast_dsp
struct | dtmf_detect_state_t
struct | goertzel_state_t
struct | mf_detect_state_t
struct | progalias
struct | progress

## Defines

#define | BELL_MF_RELATIVE_PEAK 12.6
#define | BELL_MF_THRESHOLD 1.6e9
#define | BELL_MF_TWIST 4.0
#define | BUSY_MAX 3100
#define | BUSY_MIN 75
#define | BUSY_PAT_PERCENT 7
#define | BUSY_PERCENT 10
#define | BUSY_THRESHOLD 100
#define | BUSYDETECT_MARTIN
#define | COUNT_THRESH 3
#define | DEFAULT_THRESHOLD 512
#define | DSP_HISTORY 15
#define | DTMF_2ND_HARMONIC_COL 63.1
#define | DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5)
#define | DTMF_NORMAL_TWIST 6.3
#define | DTMF_RELATIVE_PEAK_COL 6.3
#define | DTMF_RELATIVE_PEAK_ROW 6.3
#define | DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5)
#define | DTMF_THRESHOLD 8.0e7
#define | DTMF_TO_TOTAL_ENERGY 42.0
#define | FAX_2ND_HARMONIC 2.0
#define | FAX_DETECT
#define | FAX_THRESHOLD 8.0e7
#define | FIX_INF(inf)
#define | GSAMP_SIZE_CR 188
#define | GSAMP_SIZE_NA 183
#define | GSAMP_SIZE_UK 160
#define | HZ_1400 5
#define | HZ_1800 6
#define | HZ_350 0
#define | HZ_400 0
#define | HZ_425 0
#define | HZ_440 1
#define | HZ_480 2
#define | HZ_620 3
#define | HZ_950 4
#define | MAX_DTMF_DIGITS 128
#define | MF_GSIZE 120
#define | PROG_MODE_CR 1
#define | PROG_MODE_NA 0
#define | PROG_MODE_UK 2
#define | TONE_MIN_THRESH 1e8
#define | TONE_THRESH 10.0
#define | UK_HANGUP_THRESH 60

## Functions

static int | __ast_dsp_call_progress (struct ast_dsp *dsp, short *s, int len)
static int | __ast_dsp_digitdetect (struct ast_dsp *dsp, short *s, int len, int *writeback)
static int | __ast_dsp_silence (struct ast_dsp *dsp, short *s, int len, int *totalsilence)
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.
int | ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf)
| Scans for progress indication in audio.
int | ast_dsp_digitdetect (struct ast_dsp *dsp, struct ast_frame *inf)
| Return non-zero if DTMF hit was found.
int | ast_dsp_digitmode (struct ast_dsp *dsp, int digitmode)
| Set digit mode.
void | ast_dsp_digitreset (struct ast_dsp *dsp)
| Reset DTMF detector.
void | ast_dsp_free (struct ast_dsp *dsp)
int | ast_dsp_get_tcount (struct ast_dsp *dsp)
| Get tcount (Threshold counter).
int | ast_dsp_get_tstate (struct ast_dsp *dsp)
| Get tstate (Tone State).
int | ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
| Get pending DTMF/MF digits.
struct ast_dsp * | ast_dsp_new (void)
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.
static void | ast_dsp_prog_reset (struct ast_dsp *dsp)
void | ast_dsp_reset (struct ast_dsp *dsp)
| Reset total silence count.
void | ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
| Set number of required cadences for busy.
void | ast_dsp_set_busy_pattern (struct ast_dsp *dsp, int tonelength, int quietlength)
| Set expected lengths of the busy tone.
int | ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
| Set zone for doing progress detection.
void | ast_dsp_set_features (struct ast_dsp *dsp, int features)
| Select feature set.
void | ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold)
| Set threshold value for silence.
int | ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
| Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
static void | ast_dtmf_detect_init (dtmf_detect_state_t *s)
static void | ast_mf_detect_init (mf_detect_state_t *s)
static int | dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback, int faxdetect)
static void | goertzel_init (goertzel_state_t *s, float freq, int samples)
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 void | goertzel_update (goertzel_state_t *s, short *samps, int count)
static int | mf_detect (mf_detect_state_t *s, int16_t amp[], int samples, int digitmode, int *writeback)
static int | pair_there (float p1, float p2, float i1, float i2, float e)

## Variables

static struct progalias | aliases []
static char | bell_mf_positions [] = "1247C-358A--69*---0B----#"
static float | dtmf_col []
static char | dtmf_positions [] = "123A" "456B" "789C" "*0#D"
static float | dtmf_row []
static float | fax_freq = 1100.0
static float | mf_tones []
static struct progress | modes []

## Detailed Description

Convenience Signal Processing routines.

Definition in file dsp.c.

## Define Documentation

#define BELL_MF_RELATIVE_PEAK 12.6

Definition at line 162 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_THRESHOLD 1.6e9

Definition at line 160 of file dsp.c.

Referenced by mf_detect().

#define BELL_MF_TWIST 4.0

Definition at line 161 of file dsp.c.

Referenced by mf_detect().

#define BUSY_MAX 3100

Definition at line 110 of file dsp.c.

Referenced by ast_dsp_busydetect().

#define BUSY_MIN 75

Definition at line 109 of file dsp.c.

Referenced by ast_dsp_busydetect().

#define BUSY_PAT_PERCENT 7

Definition at line 107 of file dsp.c.

Referenced by ast_dsp_busydetect().

#define BUSY_PERCENT 10

Definition at line 106 of file dsp.c.

Referenced by __ast_dsp_silence(), and ast_dsp_busydetect().

#define BUSY_THRESHOLD 100

Definition at line 108 of file dsp.c.

Referenced by ast_dsp_busydetect().

#define BUSYDETECT_MARTIN

Definition at line 166 of file dsp.c.

#define COUNT_THRESH 3

Definition at line 120 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define DEFAULT_THRESHOLD 512

Definition at line 104 of file dsp.c.

Referenced by ast_dsp_new().

#define DSP_HISTORY 15

Definition at line 113 of file dsp.c.

Referenced by __ast_dsp_silence(), ast_dsp_busydetect(), ast_dsp_new(), and ast_dsp_set_busy_count().

#define DTMF_2ND_HARMONIC_COL 63.1

Definition at line 150 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5)

Definition at line 149 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_NORMAL_TWIST 6.3

Definition at line 141 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_COL 6.3

Definition at line 148 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_RELATIVE_PEAK_ROW 6.3

Definition at line 147 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5)

Definition at line 145 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_THRESHOLD 8.0e7

Definition at line 138 of file dsp.c.

Referenced by dtmf_detect().

#define DTMF_TO_TOTAL_ENERGY 42.0

Definition at line 151 of file dsp.c.

Referenced by dtmf_detect().

#define FAX_2ND_HARMONIC 2.0

Definition at line 140 of file dsp.c.

#define FAX_DETECT

Definition at line 116 of file dsp.c.

#define FAX_THRESHOLD 8.0e7

Definition at line 139 of file dsp.c.

Referenced by dtmf_detect().

#define FIX_INF | ( | inf |  | ) |

Referenced by ast_dsp_process().

#define GSAMP_SIZE_CR 188

Definition at line 62 of file dsp.c.

#define GSAMP_SIZE_NA 183

Definition at line 61 of file dsp.c.

#define GSAMP_SIZE_UK 160

Definition at line 63 of file dsp.c.

#define HZ_1400 5

Definition at line 75 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_1800 6

Definition at line 76 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_350 0

Definition at line 70 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_400 0

Definition at line 82 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_425 0

Definition at line 79 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_440 1

Definition at line 71 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_480 2

Definition at line 72 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_620 3

Definition at line 73 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define HZ_950 4

Definition at line 74 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define MAX_DTMF_DIGITS 128

Definition at line 124 of file dsp.c.

Referenced by dtmf_detect(), and mf_detect().

#define MF_GSIZE 120

Definition at line 670 of file dsp.c.

Referenced by mf_detect().

#define PROG_MODE_CR 1

Definition at line 66 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define PROG_MODE_NA 0

Definition at line 65 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define PROG_MODE_UK 2

Definition at line 67 of file dsp.c.

Referenced by __ast_dsp_call_progress().

#define TONE_MIN_THRESH 1e8

Definition at line 119 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().

#define TONE_THRESH 10.0

Definition at line 118 of file dsp.c.

Referenced by __ast_dsp_call_progress(), and pair_there().

#define UK_HANGUP_THRESH 60

Definition at line 121 of file dsp.c.

Referenced by __ast_dsp_call_progress().

## Function Documentation

static int __ast_dsp_call_progress | ( | struct ast_dsp * | dsp,
|  | short * | s,
|  | int | len |
| ) |  |  | `[static]`

Definition at line 1031 of file dsp.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_log(), COUNT_THRESH, 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, 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_400, HZ_425, HZ_440, HZ_480, HZ_620, HZ_950, LOG_WARNING, pair_there(), pass, PROG_MODE_CR, PROG_MODE_NA, PROG_MODE_UK, ast_dsp::progmode, ast_dsp::tcount, TONE_MIN_THRESH, TONE_THRESH, ast_dsp::tstate, UK_HANGUP_THRESH, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by ast_dsp_call_progress(), and ast_dsp_process().

    01032 {
    01033    int x;
    01034    int y;
    01035    int pass;
    01036    int newstate = DSP_TONE_STATE_SILENCE;
    01037    int res = 0;
    01038    int thresh = (dsp->progmode == PROG_MODE_UK) ? UK_HANGUP_THRESH : COUNT_THRESH;
    01039    while(len) {
    01040       /* Take the lesser of the number of samples we need and what we have */
    01041       pass = len;
    01042       if (pass > dsp->gsamp_size - dsp->gsamps)
    01043          pass = dsp->gsamp_size - dsp->gsamps;
    01044       for (x=0;x<pass;x++) {
    01045          for (y=0;y<dsp->freqcount;y++)
    01046             goertzel_sample(&dsp->freqs[y], s[x]);
    01047          dsp->genergy += s[x] * s[x];
    01048       }
    01049       s += pass;
    01050       dsp->gsamps += pass;
    01051       len -= pass;
    01052       if (dsp->gsamps == dsp->gsamp_size) {
    01053          float hz[7];
    01054          for (y=0;y<7;y++)
    01055             hz[y] = goertzel_result(&dsp->freqs[y]);
    01056 #if 0
    01057          printf("\n350:     425:     440:     480:     620:     950:     1400:    1800:    Energy:   \n");
    01058          printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n",
    01059             hz[HZ_350], hz[HZ_425], hz[HZ_440], hz[HZ_480], hz[HZ_620], hz[HZ_950], hz[HZ_1400], hz[HZ_1800], dsp->genergy);
    01060 #endif
    01061          switch(dsp->progmode) {
    01062          case PROG_MODE_NA:
    01063             if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
    01064                newstate = DSP_TONE_STATE_BUSY;
    01065             } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
    01066                newstate = DSP_TONE_STATE_RINGING;
    01067             } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
    01068                newstate = DSP_TONE_STATE_DIALTONE;
    01069             } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
    01070                newstate = DSP_TONE_STATE_SPECIAL1;
    01071             } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
    01072                if (dsp->tstate == DSP_TONE_STATE_SPECIAL1)
    01073                   newstate = DSP_TONE_STATE_SPECIAL2;
    01074             } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
    01075                if (dsp->tstate == DSP_TONE_STATE_SPECIAL2)
    01076                   newstate = DSP_TONE_STATE_SPECIAL3;
    01077             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
    01078                newstate = DSP_TONE_STATE_TALKING;
    01079             } else
    01080                newstate = DSP_TONE_STATE_SILENCE;
    01081             break;
    01082          case PROG_MODE_CR:
    01083             if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
    01084                newstate = DSP_TONE_STATE_RINGING;
    01085             } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
    01086                newstate = DSP_TONE_STATE_TALKING;
    01087             } else
    01088                newstate = DSP_TONE_STATE_SILENCE;
    01089             break;
    01090          case PROG_MODE_UK:
    01091             if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) {
    01092                newstate = DSP_TONE_STATE_HUNGUP;
    01093             }
    01094             break;
    01095          default:
    01096             ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
    01097          }
    01098          if (newstate == dsp->tstate) {
    01099             dsp->tcount++;
    01100             if (dsp->tcount == thresh) {
    01101                if ((dsp->features & DSP_PROGRESS_BUSY) &&
    01102                    dsp->tstate == DSP_TONE_STATE_BUSY) {
    01103                   res = AST_CONTROL_BUSY;
    01104                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
    01105                } else if ((dsp->features & DSP_PROGRESS_TALK) &&
    01106                      dsp->tstate == DSP_TONE_STATE_TALKING) {
    01107                   res = AST_CONTROL_ANSWER;
    01108                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
    01109                } else if ((dsp->features & DSP_PROGRESS_RINGING) &&
    01110                      dsp->tstate == DSP_TONE_STATE_RINGING)
    01111                   res = AST_CONTROL_RINGING;
    01112                else if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
    01113                    dsp->tstate == DSP_TONE_STATE_SPECIAL3) {
    01114                   res = AST_CONTROL_CONGESTION;
    01115                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
    01116                } else if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
    01117                   dsp->tstate == DSP_TONE_STATE_HUNGUP) {
    01118                   res = AST_CONTROL_HANGUP;
    01119                   dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
    01120                }
    01121             }
    01122          } else {
    01123 #if 0
    01124             printf("Newstate: %d\n", newstate);
    01125 #endif
    01126             dsp->tstate = newstate;
    01127             dsp->tcount = 1;
    01128          }
    01129
    01130          /* Reset goertzel */
    01131          for (x=0;x<7;x++)
    01132             dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
    01133          dsp->gsamps = 0;
    01134          dsp->genergy = 0.0;
    01135       }
    01136    }
    01137 #if 0
    01138    if (res)
    01139       printf("Returning %d\n", res);
    01140 #endif
    01141    return res;
    01142 }

static int __ast_dsp_digitdetect | ( | struct ast_dsp * | dsp,
|  | short * | s,
|  | int | len,
|  | int * | writeback |
| ) |  |  | `[static]`

Definition at line 956 of file dsp.c.

References ast_dsp::digitmode, DSP_DIGITMODE_MF, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_FAX_DETECT, ast_dsp::dtmf, dtmf_detect(), ast_dsp::features, ast_dsp::mf, mf_detect(), and ast_dsp::td.

Referenced by ast_dsp_digitdetect(), and ast_dsp_process().

    00957 {
    00958    int res;
    00959
    00960    if (dsp->digitmode & DSP_DIGITMODE_MF)
    00961       res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
    00962    else
    00963       res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT);
    00964    return res;
    00965 }

static int __ast_dsp_silence | ( | struct ast_dsp * | dsp,
|  | short * | s,
|  | int | len,
|  | int * | totalsilence |
| ) |  |  | `[static]`

Definition at line 1157 of file dsp.c.

References BUSY_PERCENT, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalnoise, and ast_dsp::totalsilence.

Referenced by ast_dsp_process(), and ast_dsp_silence().

    01158 {
    01159    int accum;
    01160    int x;
    01161    int res = 0;
    01162
    01163    if (!len)
    01164       return 0;
    01165    accum = 0;
    01166    for (x=0;x<len; x++)
    01167       accum += abs(s[x]);
    01168    accum /= len;
    01169    if (accum < dsp->threshold) {
    01170       /* Silent */
    01171       dsp->totalsilence += len/8;
    01172       if (dsp->totalnoise) {
    01173          /* Move and save history */
    01174          memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
    01175          dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
    01176 /* we don't want to check for busydetect that frequently */
    01177 #if 0
    01178          dsp->busymaybe = 1;
    01179 #endif
    01180       }
    01181       dsp->totalnoise = 0;
    01182       res = 1;
    01183    } else {
    01184       /* Not silent */
    01185       dsp->totalnoise += len/8;
    01186       if (dsp->totalsilence) {
    01187          int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
    01188          int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
    01189          /* Move and save history */
    01190          memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
    01191          dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
    01192          /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
    01193          if (silence1 < silence2) {
    01194             if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
    01195                dsp->busymaybe = 1;
    01196             else
    01197                dsp->busymaybe = 0;
    01198          } else {
    01199             if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
    01200                dsp->busymaybe = 1;
    01201             else
    01202                dsp->busymaybe = 0;
    01203          }
    01204       }
    01205       dsp->totalsilence = 0;
    01206    }
    01207    if (totalsilence)
    01208       *totalsilence = dsp->totalsilence;
    01209    return res;
    01210 }

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

References ast_dsp_busydetect(), ast_log(), BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busy_quietlength, BUSY_THRESHOLD, ast_dsp::busy_tonelength, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_DEBUG, and LOG_NOTICE.

Referenced by ast_dsp_busydetect(), and ast_dsp_process().

    01214 {
    01215    int res = 0, x;
    01216 #ifndef BUSYDETECT_TONEONLY
    01217    int avgsilence = 0, hitsilence = 0;
    01218 #endif
    01219    int avgtone = 0, hittone = 0;
    01220    if (!dsp->busymaybe)
    01221       return res;
    01222    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
    01223 #ifndef BUSYDETECT_TONEONLY
    01224       avgsilence += dsp->historicsilence[x];
    01225 #endif
    01226       avgtone += dsp->historicnoise[x];
    01227    }
    01228 #ifndef BUSYDETECT_TONEONLY
    01229    avgsilence /= dsp->busycount;
    01230 #endif
    01231    avgtone /= dsp->busycount;
    01232    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
    01233 #ifndef BUSYDETECT_TONEONLY
    01234       if (avgsilence > dsp->historicsilence[x]) {
    01235          if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
    01236             hitsilence++;
    01237       } else {
    01238          if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
    01239             hitsilence++;
    01240       }
    01241 #endif
    01242       if (avgtone > dsp->historicnoise[x]) {
    01243          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
    01244             hittone++;
    01245       } else {
    01246          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
    01247             hittone++;
    01248       }
    01249    }
    01250 #ifndef BUSYDETECT_TONEONLY
    01251    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) &&
    01252        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) &&
    01253        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
    01254 #else
    01255    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
    01256 #endif
    01257 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
    01258 #ifdef BUSYDETECT_TONEONLY
    01259 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
    01260 #endif
    01261       if (avgtone > avgsilence) {
    01262          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
    01263             res = 1;
    01264       } else {
    01265          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
    01266             res = 1;
    01267       }
    01268 #else
    01269       res = 1;
    01270 #endif
    01271    }
    01272    /* If we know the expected busy tone length, check we are in the range */
    01273    if (res && (dsp->busy_tonelength > 0)) {
    01274       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
    01275 #if 0
    01276          ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n",
    01277                   avgtone, dsp->busy_tonelength);
    01278 #endif
    01279          res = 0;
    01280       }
    01281    }
    01282 #ifndef BUSYDETECT_TONEONLY
    01283    /* If we know the expected busy tone silent-period length, check we are in the range */
    01284    if (res && (dsp->busy_quietlength > 0)) {
    01285       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
    01286 #if 0
    01287          ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
    01288                   avgsilence, dsp->busy_quietlength);
    01289 #endif
    01290          res = 0;
    01291       }
    01292    }
    01293 #endif
    01294 #if 1
    01295 #ifndef BUSYDETECT_TONEONLY
    01296    if (res)
    01297       ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
    01298 #endif
    01299 #endif
    01300    return res;
    01301 }

int ast_dsp_call_progress | ( | struct ast_dsp * | dsp,
|  | struct ast_frame * | inf |
| ) |  |  |

Scans for progress indication in audio.

Definition at line 1144 of file dsp.c.

References __ast_dsp_call_progress(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass.

    01145 {
    01146    if (inf->frametype != AST_FRAME_VOICE) {
    01147       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
    01148       return 0;
    01149    }
    01150    if (inf->subclass != AST_FORMAT_SLINEAR) {
    01151       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
    01152       return 0;
    01153    }
    01154    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
    01155 }

int ast_dsp_digitdetect | ( | struct ast_dsp * | dsp,
|  | struct ast_frame * | inf |
| ) |  |  |

Return non-zero if DTMF hit was found.

Definition at line 967 of file dsp.c.

References __ast_dsp_digitdetect(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass.

    00968 {
    00969    short *s;
    00970    int len;
    00971    int ign=0;
    00972
    00973    if (inf->frametype != AST_FRAME_VOICE) {
    00974       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
    00975       return 0;
    00976    }
    00977    if (inf->subclass != AST_FORMAT_SLINEAR) {
    00978       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
    00979       return 0;
    00980    }
    00981    s = inf->data;
    00982    len = inf->datalen / 2;
    00983    return __ast_dsp_digitdetect(dsp, s, len, &ign);
    00984 }

int ast_dsp_digitmode | ( | struct ast_dsp * | dsp,
|  | int | digitmode |
| ) |  |  |

Set digit mode.

Definition at line 1688 of file dsp.c.

References ast_dtmf_detect_init(), ast_mf_detect_init(), ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.

Referenced by i4l_answer(), i4l_startrec(), mgcp_new(), mkif(), mkintf(), sip_new(), ss_thread(), zt_hangup(), zt_new(), and zt_setoption().

    01689 {
    01690    int new;
    01691    int old;
    01692
    01693    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
    01694    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
    01695    if (old != new) {
    01696       /* Must initialize structures if switching from MF to DTMF or vice-versa */
    01697       if (new & DSP_DIGITMODE_MF)
    01698          ast_mf_detect_init(&dsp->td.mf);
    01699       else
    01700          ast_dtmf_detect_init(&dsp->td.dtmf);
    01701    }
    01702    dsp->digitmode = digitmode;
    01703    return 0;
    01704 }

void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |

Reset DTMF detector.

Definition at line 1626 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_digits, mf_detect_state_t::current_digits, dtmf_detect_state_t::current_sample, mf_detect_state_t::current_sample, ast_dsp::digitmode, dtmf_detect_state_t::digits, mf_detect_state_t::digits, DSP_DIGITMODE_MF, ast_dsp::dtmf, dtmf_detect_state_t::energy, dtmf_detect_state_t::fax_tone, goertzel_reset(), dtmf_detect_state_t::hits, mf_detect_state_t::hits, ast_dsp::mf, dtmf_detect_state_t::mhit, mf_detect_state_t::mhit, dtmf_detect_state_t::row_out, ast_dsp::td, ast_dsp::thinkdigit, and mf_detect_state_t::tone_out.

Referenced by ss_thread().

    01627 {
    01628    int i;
    01629
    01630    dsp->thinkdigit = 0;
    01631    if (dsp->digitmode & DSP_DIGITMODE_MF) {
    01632       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
    01633       dsp->td.mf.current_digits = 0;
    01634       /* Reinitialise the detector for the next block */
    01635       for (i = 0;  i < 6;  i++) {
    01636          goertzel_reset(&dsp->td.mf.tone_out[i]);
    01637 #ifdef OLD_DSP_ROUTINES
    01638          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
    01639 #endif
    01640       }
    01641 #ifdef OLD_DSP_ROUTINES
    01642       dsp->td.mf.energy = 0.0;
    01643       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
    01644 #else
    01645       dsp->td.mf.hits[4] = dsp->td.mf.hits[3] = dsp->td.mf.hits[2] = dsp->td.mf.hits[1] = dsp->td.mf.hits[0] = dsp->td.mf.mhit = 0;
    01646 #endif
    01647       dsp->td.mf.current_sample = 0;
    01648    } else {
    01649       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
    01650       dsp->td.dtmf.current_digits = 0;
    01651       /* Reinitialise the detector for the next block */
    01652       for (i = 0;  i < 4;  i++) {
    01653          goertzel_reset(&dsp->td.dtmf.row_out[i]);
    01654          goertzel_reset(&dsp->td.dtmf.col_out[i]);
    01655 #ifdef OLD_DSP_ROUTINES
    01656          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
    01657          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
    01658 #endif
    01659       }
    01660 #ifdef FAX_DETECT
    01661       goertzel_reset (&dsp->td.dtmf.fax_tone);
    01662 #endif
    01663 #ifdef OLD_DSP_ROUTINES
    01664 #ifdef FAX_DETECT
    01665       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
    01666 #endif
    01667       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
    01668 #else
    01669       dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] =  dsp->td.dtmf.mhit = 0;
    01670 #endif
    01671       dsp->td.dtmf.energy = 0.0;
    01672       dsp->td.dtmf.current_sample = 0;
    01673    }
    01674 }

void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |

Definition at line 1600 of file dsp.c.

References free.

Referenced by __oh323_destroy(), ast_app_getvoice(), ast_play_and_prepend(), ast_play_and_record_full(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), conf_run(), destroy_endpoint(), do_waiting(), handle_recordfile(), i4l_hangup(), mgcp_hangup(), record_exec(), sip_dtmfmode(), sip_hangup(), ss_thread(), vpb_hangup(), and zt_hangup().

    01601 {
    01602    free(dsp);
    01603 }

int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |

Get tcount (Threshold counter).

Definition at line 1725 of file dsp.c.

References ast_dsp::tcount.

    01726 {
    01727    return dsp->tcount;
    01728 }

int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |

Get tstate (Tone State).

Definition at line 1720 of file dsp.c.

References ast_dsp::tstate.

    01721 {
    01722    return dsp->tstate;
    01723 }

int ast_dsp_getdigits | ( | struct ast_dsp * | dsp,
|  | char * | buf,
|  | int | max |
| ) |  |  |

Get pending DTMF/MF digits.

Definition at line 1006 of file dsp.c.

References dtmf_detect_state_t::current_digits, mf_detect_state_t::current_digits, ast_dsp::digitmode, dtmf_detect_state_t::digits, mf_detect_state_t::digits, DSP_DIGITMODE_MF, ast_dsp::dtmf, ast_dsp::mf, and ast_dsp::td.

    01007 {
    01008    if (dsp->digitmode & DSP_DIGITMODE_MF) {
    01009       if (max > dsp->td.mf.current_digits)
    01010          max = dsp->td.mf.current_digits;
    01011       if (max > 0) {
    01012          memcpy(buf, dsp->td.mf.digits, max);
    01013          memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
    01014          dsp->td.mf.current_digits -= max;
    01015       }
    01016       buf[max] = '\0';
    01017       return  max;
    01018    } else {
    01019       if (max > dsp->td.dtmf.current_digits)
    01020          max = dsp->td.dtmf.current_digits;
    01021       if (max > 0) {
    01022          memcpy (buf, dsp->td.dtmf.digits, max);
    01023          memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
    01024          dsp->td.dtmf.current_digits -= max;
    01025       }
    01026       buf[max] = '\0';
    01027       return  max;
    01028    }
    01029 }

struct ast_dsp* ast_dsp_new | ( | void |  | ) | `[read]`

Definition at line 1577 of file dsp.c.

References ast_dsp_prog_reset(), ast_dtmf_detect_init(), ast_dsp::busycount, DEFAULT_THRESHOLD, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::dtmf, ast_dsp::features, malloc, ast_dsp::td, and ast_dsp::threshold.

Referenced by __oh323_new(), ast_app_getvoice(), ast_play_and_prepend(), ast_play_and_record_full(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), i4l_answer(), i4l_startrec(), mgcp_new(), misdn_set_opt_exec(), mkif(), record_exec(), sip_dtmfmode(), sip_new(), and zt_new().

    01578 {
    01579    struct ast_dsp *dsp;
    01580
    01581    dsp = malloc(sizeof(struct ast_dsp));
    01582    if (dsp) {
    01583       memset(dsp, 0, sizeof(struct ast_dsp));
    01584       dsp->threshold = DEFAULT_THRESHOLD;
    01585       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
    01586       dsp->busycount = DSP_HISTORY;
    01587       /* Initialize DTMF detector */
    01588       ast_dtmf_detect_init(&dsp->td.dtmf);
    01589       /* Initialize initial DSP progress detect parameters */
    01590       ast_dsp_prog_reset(dsp);
    01591    }
    01592    return dsp;
    01593 }

struct ast_frame* ast_dsp_process | ( | struct ast_channel * | chan,
|  | struct ast_dsp * | dsp,
|  | struct ast_frame * | af |
| ) |  |  | `[read]`

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

References __ast_dsp_call_progress(), __ast_dsp_digitdetect(), __ast_dsp_silence(), ast_channel::_softhangup, AST_ALAW, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_dsp_busydetect(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, dtmf_detect_state_t::current_digits, mf_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digitmode, dtmf_detect_state_t::digits, mf_detect_state_t::digits, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::dtmf, ast_dsp::f, ast_dsp::features, FIX_INF, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_dsp::mf, ast_channel::name, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.

Referenced by do_chanreads(), i4l_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), sip_rtp_read(), and zt_read().

    01368 {
    01369    int silence;
    01370    int res;
    01371    int digit;
    01372    int x;
    01373    short *shortdata;
    01374    unsigned char *odata;
    01375    int len;
    01376    int writeback = 0;
    01377
    01378 #define FIX_INF(inf) do { \
    01379       if (writeback) { \
    01380          switch(inf->subclass) { \
    01381          case AST_FORMAT_SLINEAR: \
    01382             break; \
    01383          case AST_FORMAT_ULAW: \
    01384             for (x=0;x<len;x++) \
    01385                odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
    01386             break; \
    01387          case AST_FORMAT_ALAW: \
    01388             for (x=0;x<len;x++) \
    01389                odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
    01390             break; \
    01391          } \
    01392       } \
    01393    } while(0)
    01394
    01395    if (!af)
    01396       return NULL;
    01397    if (af->frametype != AST_FRAME_VOICE)
    01398       return af;
    01399    odata = af->data;
    01400    len = af->datalen;
    01401    /* Make sure we have short data */
    01402    switch(af->subclass) {
    01403    case AST_FORMAT_SLINEAR:
    01404       shortdata = af->data;
    01405       len = af->datalen / 2;
    01406       break;
    01407    case AST_FORMAT_ULAW:
    01408       shortdata = alloca(af->datalen * 2);
    01409       if (!shortdata) {
    01410          ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
    01411          return af;
    01412       }
    01413       for (x=0;x<len;x++)
    01414          shortdata[x] = AST_MULAW(odata[x]);
    01415       break;
    01416    case AST_FORMAT_ALAW:
    01417       shortdata = alloca(af->datalen * 2);
    01418       if (!shortdata) {
    01419          ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
    01420          return af;
    01421       }
    01422       for (x=0;x<len;x++)
    01423          shortdata[x] = AST_ALAW(odata[x]);
    01424       break;
    01425    default:
    01426       ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
    01427       return af;
    01428    }
    01429    silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
    01430    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
    01431       memset(&dsp->f, 0, sizeof(dsp->f));
    01432       dsp->f.frametype = AST_FRAME_NULL;
    01433       return &dsp->f;
    01434    }
    01435    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
    01436       chan->_softhangup |= AST_SOFTHANGUP_DEV;
    01437       memset(&dsp->f, 0, sizeof(dsp->f));
    01438       dsp->f.frametype = AST_FRAME_CONTROL;
    01439       dsp->f.subclass = AST_CONTROL_BUSY;
    01440       ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
    01441       return &dsp->f;
    01442    }
    01443    if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
    01444       digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
    01445 #if 0
    01446       if (digit)
    01447          printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
    01448 #endif
    01449       if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
    01450          if (!dsp->thinkdigit) {
    01451             if (digit) {
    01452                /* Looks like we might have something.
    01453                 * Request a conference mute for the moment */
    01454                memset(&dsp->f, 0, sizeof(dsp->f));
    01455                dsp->f.frametype = AST_FRAME_DTMF;
    01456                dsp->f.subclass = 'm';
    01457                dsp->thinkdigit = 'x';
    01458                FIX_INF(af);
    01459                if (chan)
    01460                   ast_queue_frame(chan, af);
    01461                ast_frfree(af);
    01462                return &dsp->f;
    01463             }
    01464          } else {
    01465             if (digit) {
    01466                /* Thought we saw one last time.  Pretty sure we really have now */
    01467                if (dsp->thinkdigit) {
    01468                   if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
    01469                      /* If we found a digit, and we're changing digits, go
    01470                         ahead and send this one, but DON'T stop confmute because
    01471                         we're detecting something else, too... */
    01472                      memset(&dsp->f, 0, sizeof(dsp->f));
    01473                      dsp->f.frametype = AST_FRAME_DTMF;
    01474                      dsp->f.subclass = dsp->thinkdigit;
    01475                      FIX_INF(af);
    01476                      if (chan)
    01477                         ast_queue_frame(chan, af);
    01478                      ast_frfree(af);
    01479                   }
    01480                   dsp->thinkdigit = digit;
    01481                   return &dsp->f;
    01482                }
    01483                dsp->thinkdigit = digit;
    01484             } else {
    01485                if (dsp->thinkdigit) {
    01486                   memset(&dsp->f, 0, sizeof(dsp->f));
    01487                   if (dsp->thinkdigit != 'x') {
    01488                      /* If we found a digit, send it now */
    01489                      dsp->f.frametype = AST_FRAME_DTMF;
    01490                      dsp->f.subclass = dsp->thinkdigit;
    01491                      dsp->thinkdigit = 0;
    01492                   } else {
    01493                      dsp->f.frametype = AST_FRAME_DTMF;
    01494                      dsp->f.subclass = 'u';
    01495                      dsp->thinkdigit = 0;
    01496                   }
    01497                   FIX_INF(af);
    01498                   if (chan)
    01499                      ast_queue_frame(chan, af);
    01500                   ast_frfree(af);
    01501                   return &dsp->f;
    01502                }
    01503             }
    01504          }
    01505       } else if (!digit) {
    01506          /* Only check when there is *not* a hit... */
    01507          if (dsp->digitmode & DSP_DIGITMODE_MF) {
    01508             if (dsp->td.mf.current_digits) {
    01509                memset(&dsp->f, 0, sizeof(dsp->f));
    01510                dsp->f.frametype = AST_FRAME_DTMF;
    01511                dsp->f.subclass = dsp->td.mf.digits[0];
    01512                memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
    01513                dsp->td.mf.current_digits--;
    01514                FIX_INF(af);
    01515                if (chan)
    01516                   ast_queue_frame(chan, af);
    01517                ast_frfree(af);
    01518                return &dsp->f;
    01519             }
    01520          } else {
    01521             if (dsp->td.dtmf.current_digits) {
    01522                memset(&dsp->f, 0, sizeof(dsp->f));
    01523                dsp->f.frametype = AST_FRAME_DTMF;
    01524                dsp->f.subclass = dsp->td.dtmf.digits[0];
    01525                memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
    01526                dsp->td.dtmf.current_digits--;
    01527                FIX_INF(af);
    01528                if (chan)
    01529                   ast_queue_frame(chan, af);
    01530                ast_frfree(af);
    01531                return &dsp->f;
    01532             }
    01533          }
    01534       }
    01535    }
    01536    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
    01537       res = __ast_dsp_call_progress(dsp, shortdata, len);
    01538       if (res) {
    01539          switch(res) {
    01540          case AST_CONTROL_ANSWER:
    01541          case AST_CONTROL_BUSY:
    01542          case AST_CONTROL_RINGING:
    01543          case AST_CONTROL_CONGESTION:
    01544          case AST_CONTROL_HANGUP:
    01545             memset(&dsp->f, 0, sizeof(dsp->f));
    01546             dsp->f.frametype = AST_FRAME_CONTROL;
    01547             dsp->f.subclass = res;
    01548             dsp->f.src = "dsp_progress";
    01549             if (chan)
    01550                ast_queue_frame(chan, &dsp->f);
    01551             break;
    01552          default:
    01553             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
    01554          }
    01555       }
    01556    }
    01557    FIX_INF(af);
    01558    return af;
    01559 }

static void ast_dsp_prog_reset | ( | struct ast_dsp * | dsp | ) | `[static]`

Definition at line 1561 of file dsp.c.

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

Referenced by ast_dsp_new(), and ast_dsp_set_call_progress_zone().

    01562 {
    01563    int max = 0;
    01564    int x;
    01565
    01566    dsp->gsamp_size = modes[dsp->progmode].size;
    01567    dsp->gsamps = 0;
    01568    for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
    01569       if (modes[dsp->progmode].freqs[x]) {
    01570          goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
    01571          max = x + 1;
    01572       }
    01573    }
    01574    dsp->freqcount = max;
    01575 }

void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |

Reset total silence count.

Definition at line 1676 of file dsp.c.

References ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3.

    01677 {
    01678    int x;
    01679
    01680    dsp->totalsilence = 0;
    01681    dsp->gsamps = 0;
    01682    for (x=0;x<4;x++)
    01683       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
    01684    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
    01685    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
    01686 }

void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp,
|  | int | cadences |
| ) |  |  |

Set number of required cadences for busy.

Definition at line 1610 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by zt_new().

    01611 {
    01612    if (cadences < 4)
    01613       cadences = 4;
    01614    if (cadences > DSP_HISTORY)
    01615       cadences = DSP_HISTORY;
    01616    dsp->busycount = cadences;
    01617 }

void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp,
|  | int | tonelength,
|  | int | quietlength |
| ) |  |  |

Set expected lengths of the busy tone.

Definition at line 1619 of file dsp.c.

References ast_log(), ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, and LOG_DEBUG.

Referenced by zt_new().

    01620 {
    01621    dsp->busy_tonelength = tonelength;
    01622    dsp->busy_quietlength = quietlength;
    01623    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
    01624 }

int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp,
|  | char * | zone |
| ) |  |  |

Set zone for doing progress detection.

Definition at line 1706 of file dsp.c.

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

Referenced by zt_new().

    01707 {
    01708    int x;
    01709
    01710    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
    01711       if (!strcasecmp(aliases[x].name, zone)) {
    01712          dsp->progmode = aliases[x].mode;
    01713          ast_dsp_prog_reset(dsp);
    01714          return 0;
    01715       }
    01716    }
    01717    return -1;
    01718 }

void ast_dsp_set_features | ( | struct ast_dsp * | dsp,
|  | int | features |
| ) |  |  |

Select feature set.

Definition at line 1595 of file dsp.c.

References ast_dsp::features.

Referenced by __oh323_new(), disable_dtmf_detect(), enable_dtmf_detect(), i4l_answer(), i4l_startrec(), mgcp_new(), misdn_set_opt_exec(), mkif(), sip_dtmfmode(), sip_new(), and zt_new().

    01596 {
    01597    dsp->features = features;
    01598 }

void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp,
|  | int | threshold |
| ) |  |  |

Set threshold value for silence.

Definition at line 1605 of file dsp.c.

References ast_dsp::threshold.

Referenced by ast_play_and_prepend(), ast_play_and_record_full(), do_waiting(), handle_recordfile(), and record_exec().

    01606 {
    01607    dsp->threshold = threshold;
    01608 }

int ast_dsp_silence | ( | struct ast_dsp * | dsp,
|  | struct ast_frame * | f,
|  | int * | totalsilence |
| ) |  |  |

Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.

Definition at line 1349 of file dsp.c.

References __ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass.

Referenced by ast_app_getvoice(), ast_play_and_prepend(), ast_play_and_record_full(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), and record_exec().

    01350 {
    01351    short *s;
    01352    int len;
    01353
    01354    if (f->frametype != AST_FRAME_VOICE) {
    01355       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
    01356       return 0;
    01357    }
    01358    if (f->subclass != AST_FORMAT_SLINEAR) {
    01359       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
    01360       return 0;
    01361    }
    01362    s = f->data;
    01363    len = f->datalen/2;
    01364    return __ast_dsp_silence(dsp, s, len, totalsilence);
    01365 }

static void ast_dtmf_detect_init | ( | dtmf_detect_state_t * | s | ) | `[static]`

Definition at line 338 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_digits, dtmf_detect_state_t::current_sample, dtmf_detect_state_t::detected_digits, dtmf_detect_state_t::digits, dtmf_detect_state_t::energy, dtmf_detect_state_t::fax_tone, goertzel_init(), dtmf_detect_state_t::hits, dtmf_detect_state_t::lost_digits, dtmf_detect_state_t::mhit, and dtmf_detect_state_t::row_out.

Referenced by ast_dsp_digitmode(), and ast_dsp_new().

    00339 {
    00340    int i;
    00341
    00342 #ifdef OLD_DSP_ROUTINES
    00343    s->hit1 =
    00344    s->mhit =
    00345    s->hit3 =
    00346    s->hit4 =
    00347    s->hit2 = 0;
    00348 #else
    00349    s->hits[0] = s->hits[1] = s->hits[2] = 0;
    00350 #endif
    00351    for (i = 0;  i < 4;  i++) {
    00352       goertzel_init (&s->row_out[i], dtmf_row[i], 102);
    00353       goertzel_init (&s->col_out[i], dtmf_col[i], 102);
    00354 #ifdef OLD_DSP_ROUTINES
    00355       goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102);
    00356       goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102);
    00357 #endif
    00358       s->energy = 0.0;
    00359    }
    00360 #ifdef FAX_DETECT
    00361    /* Same for the fax dector */
    00362    goertzel_init (&s->fax_tone, fax_freq, 102);
    00363
    00364 #ifdef OLD_DSP_ROUTINES
    00365    /* Same for the fax dector 2nd harmonic */
    00366    goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102);
    00367 #endif
    00368 #endif /* FAX_DETECT */
    00369    s->current_sample = 0;
    00370    s->detected_digits = 0;
    00371    s->current_digits = 0;
    00372    memset(&s->digits, 0, sizeof(s->digits));
    00373    s->lost_digits = 0;
    00374    s->digits[0] = '\0';
    00375 }

static void ast_mf_detect_init | ( | mf_detect_state_t * | s | ) | `[static]`

Definition at line 377 of file dsp.c.

References mf_detect_state_t::current_digits, mf_detect_state_t::current_sample, mf_detect_state_t::detected_digits, mf_detect_state_t::digits, goertzel_init(), mf_detect_state_t::hits, mf_detect_state_t::lost_digits, mf_detect_state_t::mhit, and mf_detect_state_t::tone_out.

Referenced by ast_dsp_digitmode().

    00378 {
    00379    int i;
    00380 #ifdef OLD_DSP_ROUTINES
    00381    s->hit1 =
    00382    s->hit2 = 0;
    00383 #else
    00384    s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
    00385 #endif
    00386    for (i = 0;  i < 6;  i++) {
    00387       goertzel_init (&s->tone_out[i], mf_tones[i], 160);
    00388 #ifdef OLD_DSP_ROUTINES
    00389       goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160);
    00390       s->energy = 0.0;
    00391 #endif
    00392    }
    00393    s->current_digits = 0;
    00394    memset(&s->digits, 0, sizeof(s->digits));
    00395    s->current_sample = 0;
    00396    s->detected_digits = 0;
    00397    s->lost_digits = 0;
    00398    s->digits[0] = '\0';
    00399    s->mhit = 0;
    00400 }

static int dtmf_detect | ( | dtmf_detect_state_t * | s,
|  | int16_t | amp[],
|  | int | samples,
|  | int | digitmode,
|  | int * | writeback,
|  | int | faxdetect |
| ) |  |  | `[static]`

Definition at line 402 of file dsp.c.

References dtmf_detect_state_t::col_out, dtmf_detect_state_t::current_digits, dtmf_detect_state_t::current_sample, dtmf_detect_state_t::detected_digits, dtmf_detect_state_t::digit_hits, dtmf_detect_state_t::digits, DSP_DIGITMODE_NOQUELCH, DTMF_2ND_HARMONIC_COL, DTMF_2ND_HARMONIC_ROW, DTMF_NORMAL_TWIST, DTMF_RELATIVE_PEAK_COL, DTMF_RELATIVE_PEAK_ROW, DTMF_REVERSE_TWIST, DTMF_THRESHOLD, DTMF_TO_TOTAL_ENERGY, dtmf_detect_state_t::energy, goertzel_state_t::fac, dtmf_detect_state_t::fax_hits, FAX_THRESHOLD, dtmf_detect_state_t::fax_tone, goertzel_reset(), goertzel_result(), dtmf_detect_state_t::hits, dtmf_detect_state_t::lost_digits, MAX_DTMF_DIGITS, dtmf_detect_state_t::mhit, dtmf_detect_state_t::row_out, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by __ast_dsp_digitdetect().

    00404 {
    00405    float row_energy[4];
    00406    float col_energy[4];
    00407 #ifdef FAX_DETECT
    00408    float fax_energy;
    00409 #ifdef OLD_DSP_ROUTINES
    00410    float fax_energy_2nd;
    00411 #endif
    00412 #endif /* FAX_DETECT */
    00413    float famp;
    00414    float v1;
    00415    int i;
    00416    int j;
    00417    int sample;
    00418    int best_row;
    00419    int best_col;
    00420    int hit;
    00421    int limit;
    00422
    00423    hit = 0;
    00424    for (sample = 0;  sample < samples;  sample = limit) {
    00425       /* 102 is optimised to meet the DTMF specs. */
    00426       if ((samples - sample) >= (102 - s->current_sample))
    00427          limit = sample + (102 - s->current_sample);
    00428       else
    00429          limit = samples;
    00430 #if defined(USE_3DNOW)
    00431       _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
    00432       _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
    00433 #ifdef OLD_DSP_ROUTINES
    00434       _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
    00435       _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
    00436 #endif
    00437       /* XXX Need to fax detect for 3dnow too XXX */
    00438       #warning "Fax Support Broken"
    00439 #else
    00440       /* The following unrolled loop takes only 35% (rough estimate) of the
    00441          time of a rolled loop on the machine on which it was developed */
    00442       for (j=sample;j<limit;j++) {
    00443          famp = amp[j];
    00444          s->energy += famp*famp;
    00445          /* With GCC 2.95, the following unrolled code seems to take about 35%
    00446             (rough estimate) as long as a neat little 0-3 loop */
    00447          v1 = s->row_out[0].v2;
    00448          s->row_out[0].v2 = s->row_out[0].v3;
    00449          s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp;
    00450          v1 = s->col_out[0].v2;
    00451          s->col_out[0].v2 = s->col_out[0].v3;
    00452          s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp;
    00453          v1 = s->row_out[1].v2;
    00454          s->row_out[1].v2 = s->row_out[1].v3;
    00455          s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp;
    00456          v1 = s->col_out[1].v2;
    00457          s->col_out[1].v2 = s->col_out[1].v3;
    00458          s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp;
    00459          v1 = s->row_out[2].v2;
    00460          s->row_out[2].v2 = s->row_out[2].v3;
    00461          s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp;
    00462          v1 = s->col_out[2].v2;
    00463          s->col_out[2].v2 = s->col_out[2].v3;
    00464          s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp;
    00465          v1 = s->row_out[3].v2;
    00466          s->row_out[3].v2 = s->row_out[3].v3;
    00467          s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp;
    00468          v1 = s->col_out[3].v2;
    00469          s->col_out[3].v2 = s->col_out[3].v3;
    00470          s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp;
    00471 #ifdef FAX_DETECT
    00472          /* Update fax tone */
    00473          v1 = s->fax_tone.v2;
    00474          s->fax_tone.v2 = s->fax_tone.v3;
    00475          s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp;
    00476 #endif /* FAX_DETECT */
    00477 #ifdef OLD_DSP_ROUTINES
    00478          v1 = s->col_out2nd[0].v2;
    00479          s->col_out2nd[0].v2 = s->col_out2nd[0].v3;
    00480          s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp;
    00481          v1 = s->row_out2nd[0].v2;
    00482          s->row_out2nd[0].v2 = s->row_out2nd[0].v3;
    00483          s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp;
    00484          v1 = s->col_out2nd[1].v2;
    00485          s->col_out2nd[1].v2 = s->col_out2nd[1].v3;
    00486          s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp;
    00487          v1 = s->row_out2nd[1].v2;
    00488          s->row_out2nd[1].v2 = s->row_out2nd[1].v3;
    00489          s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp;
    00490          v1 = s->col_out2nd[2].v2;
    00491          s->col_out2nd[2].v2 = s->col_out2nd[2].v3;
    00492          s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp;
    00493          v1 = s->row_out2nd[2].v2;
    00494          s->row_out2nd[2].v2 = s->row_out2nd[2].v3;
    00495          s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp;
    00496          v1 = s->col_out2nd[3].v2;
    00497          s->col_out2nd[3].v2 = s->col_out2nd[3].v3;
    00498          s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp;
    00499          v1 = s->row_out2nd[3].v2;
    00500          s->row_out2nd[3].v2 = s->row_out2nd[3].v3;
    00501          s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp;
    00502 #ifdef FAX_DETECT
    00503          /* Update fax tone */
    00504          v1 = s->fax_tone.v2;
    00505          s->fax_tone2nd.v2 = s->fax_tone2nd.v3;
    00506          s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp;
    00507 #endif /* FAX_DETECT */
    00508 #endif
    00509       }
    00510 #endif
    00511       s->current_sample += (limit - sample);
    00512       if (s->current_sample < 102) {
    00513          if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
    00514             /* If we had a hit last time, go ahead and clear this out since likely it
    00515                will be another hit */
    00516             for (i=sample;i<limit;i++)
    00517                amp[i] = 0;
    00518             *writeback = 1;
    00519          }
    00520          continue;
    00521       }
    00522 #ifdef FAX_DETECT
    00523       /* Detect the fax energy, too */
    00524       fax_energy = goertzel_result(&s->fax_tone);
    00525 #endif
    00526       /* We are at the end of a DTMF detection block */
    00527       /* Find the peak row and the peak column */
    00528       row_energy[0] = goertzel_result (&s->row_out[0]);
    00529       col_energy[0] = goertzel_result (&s->col_out[0]);
    00530
    00531       for (best_row = best_col = 0, i = 1;  i < 4;  i++) {
    00532          row_energy[i] = goertzel_result (&s->row_out[i]);
    00533          if (row_energy[i] > row_energy[best_row])
    00534             best_row = i;
    00535          col_energy[i] = goertzel_result (&s->col_out[i]);
    00536          if (col_energy[i] > col_energy[best_col])
    00537             best_col = i;
    00538       }
    00539       hit = 0;
    00540       /* Basic signal level test and the twist test */
    00541       if (row_energy[best_row] >= DTMF_THRESHOLD &&
    00542           col_energy[best_col] >= DTMF_THRESHOLD &&
    00543           col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
    00544           col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
    00545          /* Relative peak test */
    00546          for (i = 0;  i < 4;  i++) {
    00547             if ((i != best_col &&
    00548                 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
    00549                 (i != best_row
    00550                  && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
    00551                break;
    00552             }
    00553          }
    00554 #ifdef OLD_DSP_ROUTINES
    00555          /* ... and second harmonic test */
    00556          if (i >= 4 &&
    00557              (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy &&
    00558                       goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col]
    00559              && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
    00560 #else
    00561          /* ... and fraction of total energy test */
    00562          if (i >= 4 &&
    00563              (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) {
    00564 #endif
    00565             /* Got a hit */
    00566             hit = dtmf_positions[(best_row << 2) + best_col];
    00567             if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
    00568                /* Zero out frame data if this is part DTMF */
    00569                for (i=sample;i<limit;i++)
    00570                   amp[i] = 0;
    00571                *writeback = 1;
    00572             }
    00573             /* Look for two successive similar results */
    00574             /* The logic in the next test is:
    00575                We need two successive identical clean detects, with
    00576                something different preceeding it. This can work with
    00577                back to back differing digits. More importantly, it
    00578                can work with nasty phones that give a very wobbly start
    00579                to a digit */
    00580 #ifdef OLD_DSP_ROUTINES
    00581             if (hit == s->hit3  &&  s->hit3 != s->hit2) {
    00582                s->mhit = hit;
    00583                s->digit_hits[(best_row << 2) + best_col]++;
    00584                s->detected_digits++;
    00585                if (s->current_digits < MAX_DTMF_DIGITS) {
    00586                   s->digits[s->current_digits++] = hit;
    00587                   s->digits[s->current_digits] = '\0';
    00588                } else {
    00589                   s->lost_digits++;
    00590                }
    00591             }
    00592 #else
    00593             if (hit == s->hits[2]  &&  hit != s->hits[1]  &&  hit != s->hits[0]) {
    00594                s->mhit = hit;
    00595                s->digit_hits[(best_row << 2) + best_col]++;
    00596                s->detected_digits++;
    00597                if (s->current_digits < MAX_DTMF_DIGITS) {
    00598                   s->digits[s->current_digits++] = hit;
    00599                   s->digits[s->current_digits] = '\0';
    00600                } else {
    00601                   s->lost_digits++;
    00602                }
    00603             }
    00604 #endif
    00605          }
    00606       }
    00607 #ifdef FAX_DETECT
    00608       if (!hit && (fax_energy >= FAX_THRESHOLD) &&
    00609          (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) &&
    00610          (faxdetect)) {
    00611 #if 0
    00612          printf("Fax energy/Second Harmonic: %f\n", fax_energy);
    00613 #endif
    00614          /* XXX Probably need better checking than just this the energy XXX */
    00615          hit = 'f';
    00616          s->fax_hits++;
    00617       } else {
    00618          if (s->fax_hits > 5) {
    00619             hit = 'f';
    00620             s->mhit = 'f';
    00621             s->detected_digits++;
    00622             if (s->current_digits < MAX_DTMF_DIGITS) {
    00623                s->digits[s->current_digits++] = hit;
    00624                s->digits[s->current_digits] = '\0';
    00625             } else {
    00626                s->lost_digits++;
    00627             }
    00628          }
    00629          s->fax_hits = 0;
    00630       }
    00631 #endif /* FAX_DETECT */
    00632 #ifdef OLD_DSP_ROUTINES
    00633       s->hit1 = s->hit2;
    00634       s->hit2 = s->hit3;
    00635       s->hit3 = hit;
    00636 #else
    00637       s->hits[0] = s->hits[1];
    00638       s->hits[1] = s->hits[2];
    00639       s->hits[2] = hit;
    00640 #endif
    00641       /* Reinitialise the detector for the next block */
    00642       for (i = 0;  i < 4;  i++) {
    00643          goertzel_reset(&s->row_out[i]);
    00644          goertzel_reset(&s->col_out[i]);
    00645 #ifdef OLD_DSP_ROUTINES
    00646          goertzel_reset(&s->row_out2nd[i]);
    00647          goertzel_reset(&s->col_out2nd[i]);
    00648 #endif
    00649       }
    00650 #ifdef FAX_DETECT
    00651       goertzel_reset (&s->fax_tone);
    00652 #ifdef OLD_DSP_ROUTINES
    00653       goertzel_reset (&s->fax_tone2nd);
    00654 #endif
    00655 #endif
    00656       s->energy = 0.0;
    00657       s->current_sample = 0;
    00658    }
    00659    if ((!s->mhit) || (s->mhit != hit)) {
    00660       s->mhit = 0;
    00661       return(0);
    00662    }
    00663    return (hit);
    00664 }

static void goertzel_init | ( | goertzel_state_t * | s,
|  | float | freq,
|  | int | samples |
| ) |  |  | `[inline, static]`

Definition at line 296 of file dsp.c.

References goertzel_state_t::fac, goertzel_state_t::samples, goertzel_state_t::v2, and goertzel_state_t::v3.

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

    00297 {
    00298    s->v2 = s->v3 = 0.0;
    00299    s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0));
    00300 #ifndef OLD_DSP_ROUTINES
    00301    s->samples = samples;
    00302 #endif
    00303 }

static void goertzel_reset | ( | goertzel_state_t * | s | ) | `[inline, static]`

Definition at line 305 of file dsp.c.

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

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

    00306 {
    00307    s->v2 = s->v3 = 0.0;
    00308 }

static float goertzel_result | ( | goertzel_state_t * | s | ) | `[inline, static]`

Definition at line 291 of file dsp.c.

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

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

    00292 {
    00293    return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac;
    00294 }

static void goertzel_sample | ( | goertzel_state_t * | s,
|  | short | sample |
| ) |  |  | `[inline, static]`

Definition at line 272 of file dsp.c.

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

Referenced by __ast_dsp_call_progress(), and goertzel_update().

    00273 {
    00274    float v1;
    00275    float fsamp  = sample;
    00276
    00277    v1 = s->v2;
    00278    s->v2 = s->v3;
    00279    s->v3 = s->fac * s->v2 - v1 + fsamp;
    00280 }

static void goertzel_update | ( | goertzel_state_t * | s,
|  | short * | samps,
|  | int | count |
| ) |  |  | `[inline, static]`

Definition at line 282 of file dsp.c.

References goertzel_sample().

    00283 {
    00284    int i;
    00285
    00286    for (i=0;i<count;i++)
    00287       goertzel_sample(s, samps[i]);
    00288 }

static int mf_detect | ( | mf_detect_state_t * | s,
|  | int16_t | amp[],
|  | int | samples,
|  | int | digitmode,
|  | int * | writeback |
| ) |  |  | `[static]`

Definition at line 673 of file dsp.c.

References BELL_MF_RELATIVE_PEAK, BELL_MF_THRESHOLD, BELL_MF_TWIST, mf_detect_state_t::current_digits, mf_detect_state_t::current_sample, mf_detect_state_t::detected_digits, mf_detect_state_t::digits, DSP_DIGITMODE_NOQUELCH, goertzel_state_t::fac, goertzel_reset(), goertzel_result(), mf_detect_state_t::hits, mf_detect_state_t::lost_digits, MAX_DTMF_DIGITS, MF_GSIZE, mf_detect_state_t::mhit, mf_detect_state_t::tone_out, goertzel_state_t::v2, and goertzel_state_t::v3.

Referenced by __ast_dsp_digitdetect().

    00675 {
    00676 #ifdef OLD_DSP_ROUTINES
    00677    float tone_energy[6];
    00678    int best1;
    00679    int best2;
    00680    float max;
    00681    int sofarsogood;
    00682 #else
    00683    float energy[6];
    00684    int best;
    00685    int second_best;
    00686 #endif
    00687    float famp;
    00688    float v1;
    00689    int i;
    00690    int j;
    00691    int sample;
    00692    int hit;
    00693    int limit;
    00694
    00695    hit = 0;
    00696    for (sample = 0;  sample < samples;  sample = limit) {
    00697       /* 80 is optimised to meet the MF specs. */
    00698       if ((samples - sample) >= (MF_GSIZE - s->current_sample))
    00699          limit = sample + (MF_GSIZE - s->current_sample);
    00700       else
    00701          limit = samples;
    00702 #if defined(USE_3DNOW)
    00703       _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
    00704       _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
    00705 #ifdef OLD_DSP_ROUTINES
    00706       _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
    00707       _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
    00708 #endif
    00709       /* XXX Need to fax detect for 3dnow too XXX */
    00710       #warning "Fax Support Broken"
    00711 #else
    00712       /* The following unrolled loop takes only 35% (rough estimate) of the
    00713          time of a rolled loop on the machine on which it was developed */
    00714       for (j = sample;  j < limit;  j++) {
    00715          famp = amp[j];
    00716 #ifdef OLD_DSP_ROUTINES
    00717          s->energy += famp*famp;
    00718 #endif
    00719          /* With GCC 2.95, the following unrolled code seems to take about 35%
    00720             (rough estimate) as long as a neat little 0-3 loop */
    00721          v1 = s->tone_out[0].v2;
    00722          s->tone_out[0].v2 = s->tone_out[0].v3;
    00723          s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp;
    00724          v1 = s->tone_out[1].v2;
    00725          s->tone_out[1].v2 = s->tone_out[1].v3;
    00726          s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp;
    00727          v1 = s->tone_out[2].v2;
    00728          s->tone_out[2].v2 = s->tone_out[2].v3;
    00729          s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp;
    00730          v1 = s->tone_out[3].v2;
    00731          s->tone_out[3].v2 = s->tone_out[3].v3;
    00732          s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp;
    00733          v1 = s->tone_out[4].v2;
    00734          s->tone_out[4].v2 = s->tone_out[4].v3;
    00735          s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp;
    00736          v1 = s->tone_out[5].v2;
    00737          s->tone_out[5].v2 = s->tone_out[5].v3;
    00738          s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp;
    00739 #ifdef OLD_DSP_ROUTINES
    00740          v1 = s->tone_out2nd[0].v2;
    00741          s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3;
    00742          s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp;
    00743          v1 = s->tone_out2nd[1].v2;
    00744          s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3;
    00745          s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp;
    00746          v1 = s->tone_out2nd[2].v2;
    00747          s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3;
    00748          s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp;
    00749          v1 = s->tone_out2nd[3].v2;
    00750          s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3;
    00751          s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp;
    00752          v1 = s->tone_out2nd[4].v2;
    00753          s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3;
    00754          s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp;
    00755          v1 = s->tone_out2nd[3].v2;
    00756          s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3;
    00757          s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp;
    00758 #endif
    00759       }
    00760 #endif
    00761       s->current_sample += (limit - sample);
    00762       if (s->current_sample < MF_GSIZE) {
    00763          if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
    00764             /* If we had a hit last time, go ahead and clear this out since likely it
    00765                will be another hit */
    00766             for (i=sample;i<limit;i++)
    00767                amp[i] = 0;
    00768             *writeback = 1;
    00769          }
    00770          continue;
    00771       }
    00772 #ifdef OLD_DSP_ROUTINES
    00773       /* We're at the end of an MF detection block.  Go ahead and calculate
    00774          all the energies. */
    00775       for (i=0;i<6;i++) {
    00776          tone_energy[i] = goertzel_result(&s->tone_out[i]);
    00777       }
    00778       /* Find highest */
    00779       best1 = 0;
    00780       max = tone_energy[0];
    00781       for (i=1;i<6;i++) {
    00782          if (tone_energy[i] > max) {
    00783             max = tone_energy[i];
    00784             best1 = i;
    00785          }
    00786       }
    00787
    00788       /* Find 2nd highest */
    00789       if (best1) {
    00790          max = tone_energy[0];
    00791          best2 = 0;
    00792       } else {
    00793          max = tone_energy[1];
    00794          best2 = 1;
    00795       }
    00796
    00797       for (i=0;i<6;i++) {
    00798          if (i == best1) continue;
    00799          if (tone_energy[i] > max) {
    00800             max = tone_energy[i];
    00801             best2 = i;
    00802          }
    00803       }
    00804       hit = 0;
    00805       if (best1 != best2)
    00806          sofarsogood=1;
    00807       else
    00808          sofarsogood=0;
    00809       /* Check for relative energies */
    00810       for (i=0;i<6;i++) {
    00811          if (i == best1)
    00812             continue;
    00813          if (i == best2)
    00814             continue;
    00815          if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) {
    00816             sofarsogood = 0;
    00817             break;
    00818          }
    00819          if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) {
    00820             sofarsogood = 0;
    00821             break;
    00822          }
    00823       }
    00824
    00825       if (sofarsogood) {
    00826          /* Check for 2nd harmonic */
    00827          if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1])
    00828             sofarsogood = 0;
    00829          else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2])
    00830             sofarsogood = 0;
    00831       }
    00832       if (sofarsogood) {
    00833          hit = mf_hit[best1][best2];
    00834          if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
    00835             /* Zero out frame data if this is part DTMF */
    00836             for (i=sample;i<limit;i++)
    00837                amp[i] = 0;
    00838             *writeback = 1;
    00839          }
    00840          /* Look for two consecutive clean hits */
    00841          if ((hit == s->hit3) && (s->hit3 != s->hit2)) {
    00842             s->mhit = hit;
    00843             s->detected_digits++;
    00844             if (s->current_digits < MAX_DTMF_DIGITS - 2) {
    00845                s->digits[s->current_digits++] = hit;
    00846                s->digits[s->current_digits] = '\0';
    00847             } else {
    00848                s->lost_digits++;
    00849             }
    00850          }
    00851       }
    00852
    00853       s->hit1 = s->hit2;
    00854       s->hit2 = s->hit3;
    00855       s->hit3 = hit;
    00856       /* Reinitialise the detector for the next block */
    00857       for (i = 0;  i < 6;  i++) {
    00858          goertzel_reset(&s->tone_out[i]);
    00859          goertzel_reset(&s->tone_out2nd[i]);
    00860       }
    00861       s->energy = 0.0;
    00862       s->current_sample = 0;
    00863    }
    00864 #else
    00865       /* We're at the end of an MF detection block.  */
    00866       /* Find the two highest energies. The spec says to look for
    00867          two tones and two tones only. Taking this literally -ie
    00868          only two tones pass the minimum threshold - doesn't work
    00869          well. The sinc function mess, due to rectangular windowing
    00870          ensure that! Find the two highest energies and ensure they
    00871          are considerably stronger than any of the others. */
    00872       energy[0] = goertzel_result(&s->tone_out[0]);
    00873       energy[1] = goertzel_result(&s->tone_out[1]);
    00874       if (energy[0] > energy[1]) {
    00875          best = 0;
    00876          second_best = 1;
    00877       } else {
    00878          best = 1;
    00879          second_best = 0;
    00880       }
    00881       /*endif*/
    00882       for (i=2;i<6;i++) {
    00883          energy[i] = goertzel_result(&s->tone_out[i]);
    00884          if (energy[i] >= energy[best]) {
    00885             second_best = best;
    00886             best = i;
    00887          } else if (energy[i] >= energy[second_best]) {
    00888             second_best = i;
    00889          }
    00890       }
    00891       /* Basic signal level and twist tests */
    00892       hit = 0;
    00893       if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
    00894                && energy[best] < energy[second_best]*BELL_MF_TWIST
    00895                && energy[best]*BELL_MF_TWIST > energy[second_best]) {
    00896          /* Relative peak test */
    00897          hit = -1;
    00898          for (i=0;i<6;i++) {
    00899             if (i != best && i != second_best) {
    00900                if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
    00901                   /* The best two are not clearly the best */
    00902                   hit = 0;
    00903                   break;
    00904                }
    00905             }
    00906          }
    00907       }
    00908       if (hit) {
    00909          /* Get the values into ascending order */
    00910          if (second_best < best) {
    00911             i = best;
    00912             best = second_best;
    00913             second_best = i;
    00914          }
    00915          best = best*5 + second_best - 1;
    00916          hit = bell_mf_positions[best];
    00917          /* Look for two successive similar results */
    00918          /* The logic in the next test is:
    00919             For KP we need 4 successive identical clean detects, with
    00920             two blocks of something different preceeding it. For anything
    00921             else we need two successive identical clean detects, with
    00922             two blocks of something different preceeding it. */
    00923          if (hit == s->hits[4] && hit == s->hits[3] &&
    00924             ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])||
    00925              (hit == '*' && hit == s->hits[2] && hit != s->hits[1] &&
    00926              hit != s->hits[0]))) {
    00927             s->detected_digits++;
    00928             if (s->current_digits < MAX_DTMF_DIGITS) {
    00929                s->digits[s->current_digits++] = hit;
    00930                s->digits[s->current_digits] = '\0';
    00931             } else {
    00932                s->lost_digits++;
    00933             }
    00934          }
    00935       } else {
    00936          hit = 0;
    00937       }
    00938       s->hits[0] = s->hits[1];
    00939       s->hits[1] = s->hits[2];
    00940       s->hits[2] = s->hits[3];
    00941       s->hits[3] = s->hits[4];
    00942       s->hits[4] = hit;
    00943       /* Reinitialise the detector for the next block */
    00944       for (i = 0;  i < 6;  i++)
    00945          goertzel_reset(&s->tone_out[i]);
    00946       s->current_sample = 0;
    00947    }
    00948 #endif
    00949    if ((!s->mhit) || (s->mhit != hit)) {
    00950       s->mhit = 0;
    00951       return(0);
    00952    }
    00953    return (hit);
    00954 }

static int pair_there | ( | float | p1,
|  | float | p2,
|  | float | i1,
|  | float | i2,
|  | float | e |
| ) |  |  | `[inline, static]`

Definition at line 986 of file dsp.c.

References TONE_MIN_THRESH, and TONE_THRESH.

Referenced by __ast_dsp_call_progress().

    00987 {
    00988    /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
    00989    /* Make sure absolute levels are high enough */
    00990    if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
    00991       return 0;
    00992    /* Amplify ignored stuff */
    00993    i2 *= TONE_THRESH;
    00994    i1 *= TONE_THRESH;
    00995    e *= TONE_THRESH;
    00996    /* Check first tone */
    00997    if ((p1 < i1) || (p1 < i2) || (p1 < e))
    00998       return 0;
    00999    /* And second */
    01000    if ((p2 < i1) || (p2 < i2) || (p2 < e))
    01001       return 0;
    01002    /* Guess it's there... */
    01003    return 1;
    01004 }

## Variable Documentation

struct progalias aliases[]`[static]`

Referenced by add_header(), ast_dsp_set_call_progress_zone(), and find_alias().

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

Definition at line 269 of file dsp.c.

float dtmf_col[]`[static]`

Initial value:

    {
       1209.0, 1336.0, 1477.0, 1633.0
    }

Definition at line 243 of file dsp.c.

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

Definition at line 257 of file dsp.c.

float dtmf_row[]`[static]`

Initial value:

    {
       697.0,  770.0,  852.0,  941.0
    }

Definition at line 239 of file dsp.c.

float fax_freq = 1100.0`[static]`

Definition at line 254 of file dsp.c.

float mf_tones[]`[static]`

Initial value:

    {
       700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
    }

Definition at line 248 of file dsp.c.

struct progress modes[]`[static]`

Referenced by ast_dsp_prog_reset().