Sat Jul 26 06:14:07 2008

Asterisk developer's documentation


dsp.h File Reference

Convenient Signal Processing routines. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define DSP_DIGITMODE_DTMF   0
#define DSP_DIGITMODE_MF   1
#define DSP_DIGITMODE_MUTECONF   (1 << 9)
#define DSP_DIGITMODE_MUTEMAX   (1 << 10)
#define DSP_DIGITMODE_NOQUELCH   (1 << 8)
#define DSP_DIGITMODE_RELAXDTMF   (1 << 11)
#define DSP_FEATURE_BUSY_DETECT   (1 << 1)
#define DSP_FEATURE_CALL_PROGRESS   (DSP_PROGRESS_TALK | DSP_PROGRESS_RINGING | DSP_PROGRESS_BUSY | DSP_PROGRESS_CONGESTION)
#define DSP_FEATURE_DTMF_DETECT   (1 << 3)
#define DSP_FEATURE_FAX_DETECT   (1 << 4)
#define DSP_FEATURE_SILENCE_SUPPRESS   (1 << 0)
#define DSP_PROGRESS_BUSY   (1 << 18)
#define DSP_PROGRESS_CONGESTION   (1 << 19)
#define DSP_PROGRESS_RINGING   (1 << 17)
#define DSP_PROGRESS_TALK   (1 << 16)
#define DSP_TONE_STATE_BUSY   4
#define DSP_TONE_STATE_DIALTONE   2
#define DSP_TONE_STATE_HUNGUP   8
#define DSP_TONE_STATE_RINGING   1
#define DSP_TONE_STATE_SILENCE   0
#define DSP_TONE_STATE_SPECIAL1   5
#define DSP_TONE_STATE_SPECIAL2   6
#define DSP_TONE_STATE_SPECIAL3   7
#define DSP_TONE_STATE_TALKING   3

Functions

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 *f)
 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_frame_freed (struct ast_frame *fr)
 Hint that a frame from a dsp was freed.
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.
ast_dspast_dsp_new (void)
ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
 Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
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.


Detailed Description

Convenient Signal Processing routines.

Definition in file dsp.h.


Define Documentation

#define DSP_DIGITMODE_DTMF   0

Definition at line 31 of file dsp.h.

Referenced by ast_dsp_digitmode(), sip_new(), ss_thread(), zt_hangup(), zt_new(), and zt_setoption().

#define DSP_DIGITMODE_MF   1

Definition at line 32 of file dsp.h.

Referenced by __ast_dsp_digitdetect(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_getdigits(), ast_dsp_process(), and ss_thread().

#define DSP_DIGITMODE_MUTECONF   (1 << 9)

Definition at line 35 of file dsp.h.

Referenced by ast_dsp_digitmode(), ast_dsp_process(), and zt_setoption().

#define DSP_DIGITMODE_MUTEMAX   (1 << 10)

Definition at line 36 of file dsp.h.

Referenced by ast_dsp_digitmode(), ast_dsp_process(), and zt_setoption().

#define DSP_DIGITMODE_NOQUELCH   (1 << 8)

Definition at line 34 of file dsp.h.

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

#define DSP_DIGITMODE_RELAXDTMF   (1 << 11)

Definition at line 37 of file dsp.h.

Referenced by __ast_dsp_digitdetect(), process_zap(), sip_new(), and zt_setoption().

#define DSP_FEATURE_BUSY_DETECT   (1 << 1)

Definition at line 27 of file dsp.h.

Referenced by ast_dsp_process(), and zt_new().

#define DSP_FEATURE_CALL_PROGRESS   (DSP_PROGRESS_TALK | DSP_PROGRESS_RINGING | DSP_PROGRESS_BUSY | DSP_PROGRESS_CONGESTION)

Definition at line 43 of file dsp.h.

Referenced by __ast_dsp_call_progress(), ast_dsp_process(), and zt_new().

#define DSP_FEATURE_DTMF_DETECT   (1 << 3)

Definition at line 28 of file dsp.h.

Referenced by __oh323_new(), ast_dsp_process(), disable_dtmf_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_dtmfmode(), sip_new(), and zt_new().

#define DSP_FEATURE_FAX_DETECT   (1 << 4)

Definition at line 29 of file dsp.h.

Referenced by __ast_dsp_digitdetect(), misdn_set_opt_exec(), read_config(), and zt_new().

#define DSP_FEATURE_SILENCE_SUPPRESS   (1 << 0)

Definition at line 26 of file dsp.h.

Referenced by ast_dsp_new(), and ast_dsp_process().

#define DSP_PROGRESS_BUSY   (1 << 18)

Definition at line 41 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_PROGRESS_CONGESTION   (1 << 19)

Definition at line 42 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_PROGRESS_RINGING   (1 << 17)

Definition at line 40 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_PROGRESS_TALK   (1 << 16)

Definition at line 39 of file dsp.h.

Referenced by __ast_dsp_call_progress(), and zt_new().

#define DSP_TONE_STATE_BUSY   4

Definition at line 49 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_DIALTONE   2

Definition at line 47 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_HUNGUP   8

Definition at line 53 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_RINGING   1

Definition at line 46 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_SILENCE   0

Definition at line 45 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_SPECIAL1   5

Definition at line 50 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_SPECIAL2   6

Definition at line 51 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_SPECIAL3   7

Definition at line 52 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_TALKING   3

Definition at line 48 of file dsp.h.

Referenced by __ast_dsp_call_progress().


Function Documentation

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

01277 {
01278    int res = 0, x;
01279 #ifndef BUSYDETECT_TONEONLY
01280    int avgsilence = 0, hitsilence = 0;
01281 #endif
01282    int avgtone = 0, hittone = 0;
01283    if (!dsp->busymaybe)
01284       return res;
01285    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01286 #ifndef BUSYDETECT_TONEONLY
01287       avgsilence += dsp->historicsilence[x];
01288 #endif
01289       avgtone += dsp->historicnoise[x];
01290    }
01291 #ifndef BUSYDETECT_TONEONLY
01292    avgsilence /= dsp->busycount;
01293 #endif
01294    avgtone /= dsp->busycount;
01295    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01296 #ifndef BUSYDETECT_TONEONLY
01297       if (avgsilence > dsp->historicsilence[x]) {
01298          if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01299             hitsilence++;
01300       } else {
01301          if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01302             hitsilence++;
01303       }
01304 #endif
01305       if (avgtone > dsp->historicnoise[x]) {
01306          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01307             hittone++;
01308       } else {
01309          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01310             hittone++;
01311       }
01312    }
01313 #ifndef BUSYDETECT_TONEONLY
01314    if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && 
01315        (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && 
01316        (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
01317 #else
01318    if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01319 #endif
01320 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01321 #ifdef BUSYDETECT_TONEONLY
01322 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
01323 #endif
01324       if (avgtone > avgsilence) {
01325          if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01326             res = 1;
01327       } else {
01328          if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01329             res = 1;
01330       }
01331 #else
01332       res = 1;
01333 #endif
01334    }
01335    /* If we know the expected busy tone length, check we are in the range */
01336    if (res && (dsp->busy_tonelength > 0)) {
01337       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
01338 #if 0
01339          ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n",
01340                   avgtone, dsp->busy_tonelength);
01341 #endif
01342          res = 0;
01343       }
01344    }
01345 #ifndef BUSYDETECT_TONEONLY
01346    /* If we know the expected busy tone silent-period length, check we are in the range */
01347    if (res && (dsp->busy_quietlength > 0)) {
01348       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
01349 #if 0
01350          ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
01351                   avgsilence, dsp->busy_quietlength);
01352 #endif
01353          res = 0;
01354       }
01355    }
01356 #endif
01357 #ifndef BUSYDETECT_TONEONLY
01358 #if 1
01359    if (res)
01360       ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01361 #endif
01362 #endif
01363    return res;
01364 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

01208 {
01209    if (inf->frametype != AST_FRAME_VOICE) {
01210       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01211       return 0;
01212    }
01213    if (inf->subclass != AST_FORMAT_SLINEAR) {
01214       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01215       return 0;
01216    }
01217    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01218 }

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame f 
)

Return non-zero if DTMF hit was found.

Definition at line 1006 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, len, LOG_WARNING, s, and ast_frame::subclass.

01007 {
01008    short *s;
01009    int len;
01010    int ign=0;
01011 
01012    if (inf->frametype != AST_FRAME_VOICE) {
01013       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01014       return 0;
01015    }
01016    if (inf->subclass != AST_FORMAT_SLINEAR) {
01017       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01018       return 0;
01019    }
01020    s = inf->data;
01021    len = inf->datalen / 2;
01022    return __ast_dsp_digitdetect(dsp, s, len, &ign);
01023 }

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Definition at line 1765 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 mgcp_new(), sip_new(), ss_thread(), zt_hangup(), zt_new(), and zt_setoption().

01766 {
01767    int new;
01768    int old;
01769    
01770    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01771    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01772    if (old != new) {
01773       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01774       if (new & DSP_DIGITMODE_MF)
01775          ast_mf_detect_init(&dsp->td.mf);
01776       else
01777          ast_dtmf_detect_init(&dsp->td.dtmf);
01778    }
01779    dsp->digitmode = digitmode;
01780    return 0;
01781 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1702 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(), mf_detect_state_t::hits, dtmf_detect_state_t::lasthit, 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().

01703 {
01704    int i;
01705    
01706    dsp->thinkdigit = 0;
01707    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01708       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01709       dsp->td.mf.current_digits = 0;
01710       /* Reinitialise the detector for the next block */
01711       for (i = 0;  i < 6;  i++) {
01712          goertzel_reset(&dsp->td.mf.tone_out[i]);
01713 #ifdef OLD_DSP_ROUTINES
01714          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01715 #endif         
01716       }
01717 #ifdef OLD_DSP_ROUTINES
01718       dsp->td.mf.energy = 0.0;
01719       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01720 #else
01721       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;
01722 #endif      
01723       dsp->td.mf.current_sample = 0;
01724    } else {
01725       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01726       dsp->td.dtmf.current_digits = 0;
01727       /* Reinitialise the detector for the next block */
01728       for (i = 0;  i < 4;  i++) {
01729          goertzel_reset(&dsp->td.dtmf.row_out[i]);
01730          goertzel_reset(&dsp->td.dtmf.col_out[i]);
01731 #ifdef OLD_DSP_ROUTINES
01732          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01733          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01734 #endif         
01735       }
01736 #ifdef FAX_DETECT
01737       goertzel_reset (&dsp->td.dtmf.fax_tone);
01738 #endif
01739 #ifdef OLD_DSP_ROUTINES
01740 #ifdef FAX_DETECT
01741       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01742 #endif
01743       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01744 #else
01745       dsp->td.dtmf.lasthit = dsp->td.dtmf.mhit = 0;
01746 #endif      
01747       dsp->td.dtmf.energy = 0.0;
01748       dsp->td.dtmf.current_sample = 0;
01749    }
01750 }

void ast_dsp_frame_freed ( struct ast_frame fr  ) 

Hint that a frame from a dsp was freed.

This is called from ast_frame_free if AST_FRFLAG_FROM_DSP is set. This occurs because it is possible for the dsp to be freed while someone still holds a reference to the frame that is in that dsp. This has been known to happen when the dsp on a Zap channel detects a busy signal. The channel is hung up, and the application that read the frame to begin with still has a reference to the frame.

Returns:
nothing

Definition at line 1807 of file dsp.c.

References ast_clear_flag, ast_dsp_free(), AST_FRFLAG_FROM_DSP, f, and ast_dsp::freqcount.

Referenced by ast_frame_free().

01808 {
01809    struct ast_dsp *dsp;
01810 
01811    ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
01812 
01813    dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
01814 
01815    if (dsp->freqcount != -1)
01816       return;
01817    
01818    ast_dsp_free(dsp);
01819 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1665 of file dsp.c.

References AST_FRFLAG_FROM_DSP, ast_test_flag, ast_dsp::f, free, and ast_dsp::freqcount.

Referenced by __ast_play_and_record(), __oh323_destroy(), ast_dsp_frame_freed(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), sip_dtmfmode(), sip_hangup(), ss_thread(), and zt_hangup().

01666 {
01667    if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
01668       /* If this flag is still set, that means that the dsp's destruction 
01669        * been torn down, while we still have a frame out there being used.
01670        * When ast_frfree() gets called on that frame, this ast_trans_pvt
01671        * will get destroyed, too. */
01672 
01673       /* Set the magic hint that this has been requested to be destroyed. */
01674       dsp->freqcount = -1;
01675 
01676       return;
01677    }
01678    free(dsp);
01679 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1802 of file dsp.c.

References ast_dsp::tcount.

01803 {
01804    return dsp->tcount;
01805 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1797 of file dsp.c.

References ast_dsp::tstate.

01798 {
01799    return dsp->tstate;
01800 }

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

Get pending DTMF/MF digits.

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

01046 {
01047    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01048       if (max > dsp->td.mf.current_digits)
01049          max = dsp->td.mf.current_digits;
01050       if (max > 0) {
01051          memcpy(buf, dsp->td.mf.digits, max);
01052          memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
01053          dsp->td.mf.current_digits -= max;
01054       }
01055       buf[max] = '\0';
01056       return  max;
01057    } else {
01058       if (max > dsp->td.dtmf.current_digits)
01059          max = dsp->td.dtmf.current_digits;
01060       if (max > 0) {
01061          memcpy (buf, dsp->td.dtmf.digits, max);
01062          memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
01063          dsp->td.dtmf.current_digits -= max;
01064       }
01065       buf[max] = '\0';
01066       return  max;
01067    }
01068 }

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1644 of file dsp.c.

References ast_calloc, ast_dsp_prog_reset(), ast_dtmf_detect_init(), DEFAULT_THRESHOLD, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, and ast_dsp::threshold.

Referenced by __ast_play_and_record(), __oh323_new(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_dtmfmode(), sip_new(), and zt_new().

01645 {
01646    struct ast_dsp *dsp;
01647    
01648    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01649       dsp->threshold = DEFAULT_THRESHOLD;
01650       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01651       dsp->busycount = DSP_HISTORY;
01652       /* Initialize DTMF detector */
01653       ast_dtmf_detect_init(&dsp->td.dtmf);
01654       /* Initialize initial DSP progress detect parameters */
01655       ast_dsp_prog_reset(dsp);
01656    }
01657    return dsp;
01658 }

struct ast_frame* ast_dsp_process ( struct ast_channel chan,
struct ast_dsp dsp,
struct ast_frame inf 
)

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 1430 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_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRFLAG_FROM_DSP, ast_frfree, ast_getformatname(), ast_log(), AST_MULAW, ast_queue_frame(), ast_set_flag, 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, len, LOG_WARNING, ast_dsp::mf, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.

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

01431 {
01432    int silence;
01433    int res;
01434    int digit;
01435    int x;
01436    short *shortdata;
01437    unsigned char *odata;
01438    int len;
01439    int writeback = 0;
01440 
01441 #define FIX_INF(inf) do { \
01442       if (writeback) { \
01443          switch(inf->subclass) { \
01444          case AST_FORMAT_SLINEAR: \
01445             break; \
01446          case AST_FORMAT_ULAW: \
01447             for (x=0;x<len;x++) \
01448                odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
01449             break; \
01450          case AST_FORMAT_ALAW: \
01451             for (x=0;x<len;x++) \
01452                odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
01453             break; \
01454          } \
01455       } \
01456    } while(0) 
01457 
01458    if (!af)
01459       return NULL;
01460    if (af->frametype != AST_FRAME_VOICE)
01461       return af;
01462    odata = af->data;
01463    len = af->datalen;
01464    /* Make sure we have short data */
01465    switch(af->subclass) {
01466    case AST_FORMAT_SLINEAR:
01467       shortdata = af->data;
01468       len = af->datalen / 2;
01469       break;
01470    case AST_FORMAT_ULAW:
01471       shortdata = alloca(af->datalen * 2);
01472       for (x = 0;x < len; x++) 
01473          shortdata[x] = AST_MULAW(odata[x]);
01474       break;
01475    case AST_FORMAT_ALAW:
01476       shortdata = alloca(af->datalen * 2);
01477       for (x = 0; x < len; x++) 
01478          shortdata[x] = AST_ALAW(odata[x]);
01479       break;
01480    default:
01481       ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
01482       return af;
01483    }
01484    silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
01485    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01486       memset(&dsp->f, 0, sizeof(dsp->f));
01487       dsp->f.frametype = AST_FRAME_NULL;
01488       ast_frfree(af);
01489       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01490       return &dsp->f;
01491    }
01492    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01493       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01494       memset(&dsp->f, 0, sizeof(dsp->f));
01495       dsp->f.frametype = AST_FRAME_CONTROL;
01496       dsp->f.subclass = AST_CONTROL_BUSY;
01497       ast_frfree(af);
01498       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01499       return &dsp->f;
01500    }
01501    if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
01502       digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
01503 #if 0
01504       if (digit)
01505          printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
01506 #endif         
01507       if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
01508          if (!dsp->thinkdigit) {
01509             if (digit) {
01510                /* Looks like we might have something.  
01511                 * Request a conference mute for the moment */
01512                memset(&dsp->f, 0, sizeof(dsp->f));
01513                dsp->f.frametype = AST_FRAME_DTMF;
01514                dsp->f.subclass = 'm';
01515                dsp->thinkdigit = 'x';
01516                FIX_INF(af);
01517                if (chan)
01518                   ast_queue_frame(chan, af);
01519                ast_frfree(af);
01520                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01521                return &dsp->f;
01522             }
01523          } else {
01524             if (digit) {
01525                /* Thought we saw one last time.  Pretty sure we really have now */
01526                if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
01527                   /* If we found a digit, and we're changing digits, go
01528                      ahead and send this one, but DON'T stop confmute because
01529                      we're detecting something else, too... */
01530                   memset(&dsp->f, 0, sizeof(dsp->f));
01531                   dsp->f.frametype = AST_FRAME_DTMF_END;
01532                   dsp->f.subclass = dsp->thinkdigit;
01533                   FIX_INF(af);
01534                   if (chan)
01535                      ast_queue_frame(chan, af);
01536                   ast_frfree(af);
01537                } else {
01538                   dsp->thinkdigit = digit;
01539                   memset(&dsp->f, 0, sizeof(dsp->f));
01540                   dsp->f.frametype = AST_FRAME_DTMF_BEGIN;
01541                   dsp->f.subclass = dsp->thinkdigit;
01542                   FIX_INF(af);
01543                   if (chan)
01544                      ast_queue_frame(chan, af);
01545                   ast_frfree(af);
01546                }
01547                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01548                return &dsp->f;
01549             } else {
01550                memset(&dsp->f, 0, sizeof(dsp->f));
01551                if (dsp->thinkdigit != 'x') {
01552                   /* If we found a digit, send it now */
01553                   dsp->f.frametype = AST_FRAME_DTMF_END;
01554                   dsp->f.subclass = dsp->thinkdigit;
01555                   dsp->thinkdigit = 0;
01556                } else {
01557                   dsp->f.frametype = AST_FRAME_DTMF;
01558                   dsp->f.subclass = 'u';
01559                   dsp->thinkdigit = 0;
01560                }
01561                FIX_INF(af);
01562                if (chan)
01563                   ast_queue_frame(chan, af);
01564                ast_frfree(af);
01565                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01566                return &dsp->f;
01567             }
01568          }
01569       } else if (!digit) {
01570          /* Only check when there is *not* a hit... */
01571          if (dsp->digitmode & DSP_DIGITMODE_MF) {
01572             if (dsp->td.mf.current_digits) {
01573                memset(&dsp->f, 0, sizeof(dsp->f));
01574                dsp->f.frametype = AST_FRAME_DTMF;
01575                dsp->f.subclass = dsp->td.mf.digits[0];
01576                memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
01577                dsp->td.mf.current_digits--;
01578                FIX_INF(af);
01579                if (chan)
01580                   ast_queue_frame(chan, af);
01581                ast_frfree(af);
01582                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01583                return &dsp->f;
01584             }
01585          } else {
01586             if (dsp->td.dtmf.current_digits) {
01587                memset(&dsp->f, 0, sizeof(dsp->f));
01588                dsp->f.frametype = AST_FRAME_DTMF_END;
01589                dsp->f.subclass = dsp->td.dtmf.digits[0];
01590                memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
01591                dsp->td.dtmf.current_digits--;
01592                FIX_INF(af);
01593                if (chan)
01594                   ast_queue_frame(chan, af);
01595                ast_frfree(af);
01596                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01597                return &dsp->f;
01598             }
01599          }
01600       }
01601    }
01602    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01603       res = __ast_dsp_call_progress(dsp, shortdata, len);
01604       if (res) {
01605          switch(res) {
01606          case AST_CONTROL_ANSWER:
01607          case AST_CONTROL_BUSY:
01608          case AST_CONTROL_RINGING:
01609          case AST_CONTROL_CONGESTION:
01610          case AST_CONTROL_HANGUP:
01611             memset(&dsp->f, 0, sizeof(dsp->f));
01612             dsp->f.frametype = AST_FRAME_CONTROL;
01613             dsp->f.subclass = res;
01614             dsp->f.src = "dsp_progress";
01615             if (chan) 
01616                ast_queue_frame(chan, &dsp->f);
01617             break;
01618          default:
01619             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01620          }
01621       }
01622    }
01623    FIX_INF(af);
01624    return af;
01625 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01753 {
01754    int x;
01755    
01756    dsp->totalsilence = 0;
01757    dsp->gsamps = 0;
01758    for (x=0;x<4;x++)
01759       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01760    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01761    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01762    dsp->ringtimeout= 0;
01763 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1686 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by zt_new().

01687 {
01688    if (cadences < 4)
01689       cadences = 4;
01690    if (cadences > DSP_HISTORY)
01691       cadences = DSP_HISTORY;
01692    dsp->busycount = cadences;
01693 }

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

Set expected lengths of the busy tone.

Definition at line 1695 of file dsp.c.

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

Referenced by zt_new().

01696 {
01697    dsp->busy_tonelength = tonelength;
01698    dsp->busy_quietlength = quietlength;
01699    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01700 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1783 of file dsp.c.

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

Referenced by zt_new().

01784 {
01785    int x;
01786    
01787    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01788       if (!strcasecmp(aliases[x].name, zone)) {
01789          dsp->progmode = aliases[x].mode;
01790          ast_dsp_prog_reset(dsp);
01791          return 0;
01792       }
01793    }
01794    return -1;
01795 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1660 of file dsp.c.

References ast_dsp::features.

Referenced by __oh323_new(), disable_dtmf_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_dtmfmode(), sip_new(), and zt_new().

01661 {
01662    dsp->features = features;
01663 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1681 of file dsp.c.

References ast_dsp::threshold.

Referenced by __ast_play_and_record(), do_waiting(), handle_recordfile(), and isAnsweringMachine().

01682 {
01683    dsp->threshold = threshold;
01684 }

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

References __ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), f, len, LOG_WARNING, and s.

Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), and isAnsweringMachine().

01413 {
01414    short *s;
01415    int len;
01416    
01417    if (f->frametype != AST_FRAME_VOICE) {
01418       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01419       return 0;
01420    }
01421    if (f->subclass != AST_FORMAT_SLINEAR) {
01422       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01423       return 0;
01424    }
01425    s = f->data;
01426    len = f->datalen/2;
01427    return __ast_dsp_silence(dsp, s, len, totalsilence);
01428 }


Generated on Sat Jul 26 06:14:07 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1