Fri Aug 24 02:25:40 2007

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_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(), nv_background_detect_exec(), nv_detectfax_exec(), 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(), nv_background_detect_exec(), nv_detectfax_exec(), 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(), nv_background_detect_exec(), nv_detectfax_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(), nv_background_detect_exec(), nv_detectfax_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 1262 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().

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

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

01194 {
01195    if (inf->frametype != AST_FRAME_VOICE) {
01196       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01197       return 0;
01198    }
01199    if (inf->subclass != AST_FORMAT_SLINEAR) {
01200       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01201       return 0;
01202    }
01203    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01204 }

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame f 
)

Return non-zero if DTMF hit was found.

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

00993 {
00994    short *s;
00995    int len;
00996    int ign=0;
00997 
00998    if (inf->frametype != AST_FRAME_VOICE) {
00999       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01000       return 0;
01001    }
01002    if (inf->subclass != AST_FORMAT_SLINEAR) {
01003       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01004       return 0;
01005    }
01006    s = inf->data;
01007    len = inf->datalen / 2;
01008    return __ast_dsp_digitdetect(dsp, s, len, &ign);
01009 }

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

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

01733 {
01734    int new;
01735    int old;
01736    
01737    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01738    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01739    if (old != new) {
01740       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01741       if (new & DSP_DIGITMODE_MF)
01742          ast_mf_detect_init(&dsp->td.mf);
01743       else
01744          ast_dtmf_detect_init(&dsp->td.dtmf);
01745    }
01746    dsp->digitmode = digitmode;
01747    return 0;
01748 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

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

01670 {
01671    int i;
01672    
01673    dsp->thinkdigit = 0;
01674    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01675       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01676       dsp->td.mf.current_digits = 0;
01677       /* Reinitialise the detector for the next block */
01678       for (i = 0;  i < 6;  i++) {
01679          goertzel_reset(&dsp->td.mf.tone_out[i]);
01680 #ifdef OLD_DSP_ROUTINES
01681          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01682 #endif         
01683       }
01684 #ifdef OLD_DSP_ROUTINES
01685       dsp->td.mf.energy = 0.0;
01686       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01687 #else
01688       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;
01689 #endif      
01690       dsp->td.mf.current_sample = 0;
01691    } else {
01692       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01693       dsp->td.dtmf.current_digits = 0;
01694       /* Reinitialise the detector for the next block */
01695       for (i = 0;  i < 4;  i++) {
01696          goertzel_reset(&dsp->td.dtmf.row_out[i]);
01697          goertzel_reset(&dsp->td.dtmf.col_out[i]);
01698 #ifdef OLD_DSP_ROUTINES
01699          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01700          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01701 #endif         
01702       }
01703 #ifdef FAX_DETECT
01704       goertzel_reset (&dsp->td.dtmf.fax_tone);
01705 #endif
01706 #ifdef OLD_DSP_ROUTINES
01707 #ifdef FAX_DETECT
01708       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01709 #endif
01710       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01711 #else
01712       dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] =  dsp->td.dtmf.mhit = 0;
01713 #endif      
01714       dsp->td.dtmf.energy = 0.0;
01715       dsp->td.dtmf.current_sample = 0;
01716    }
01717 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1643 of file dsp.c.

References free.

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

01644 {
01645    free(dsp);
01646 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1769 of file dsp.c.

References ast_dsp::tcount.

01770 {
01771    return dsp->tcount;
01772 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1764 of file dsp.c.

References ast_dsp::tstate.

01765 {
01766    return dsp->tstate;
01767 }

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

Get pending DTMF/MF digits.

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

01032 {
01033    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01034       if (max > dsp->td.mf.current_digits)
01035          max = dsp->td.mf.current_digits;
01036       if (max > 0) {
01037          memcpy(buf, dsp->td.mf.digits, max);
01038          memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
01039          dsp->td.mf.current_digits -= max;
01040       }
01041       buf[max] = '\0';
01042       return  max;
01043    } else {
01044       if (max > dsp->td.dtmf.current_digits)
01045          max = dsp->td.dtmf.current_digits;
01046       if (max > 0) {
01047          memcpy (buf, dsp->td.dtmf.digits, max);
01048          memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
01049          dsp->td.dtmf.current_digits -= max;
01050       }
01051       buf[max] = '\0';
01052       return  max;
01053    }
01054 }

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1622 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(), nv_background_detect_exec(), nv_detectfax_exec(), read_config(), sip_dtmfmode(), sip_new(), and zt_new().

01623 {
01624    struct ast_dsp *dsp;
01625    
01626    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01627       dsp->threshold = DEFAULT_THRESHOLD;
01628       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01629       dsp->busycount = DSP_HISTORY;
01630       /* Initialize DTMF detector */
01631       ast_dtmf_detect_init(&dsp->td.dtmf);
01632       /* Initialize initial DSP progress detect parameters */
01633       ast_dsp_prog_reset(dsp);
01634    }
01635    return dsp;
01636 }

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 1416 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_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, len, LOG_DEBUG, LOG_WARNING, ast_dsp::mf, silence, ast_frame::src, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.

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

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

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01720 {
01721    int x;
01722    
01723    dsp->totalsilence = 0;
01724    dsp->gsamps = 0;
01725    for (x=0;x<4;x++)
01726       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01727    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01728    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01729    dsp->ringtimeout= 0;
01730 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1653 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by zt_new().

01654 {
01655    if (cadences < 4)
01656       cadences = 4;
01657    if (cadences > DSP_HISTORY)
01658       cadences = DSP_HISTORY;
01659    dsp->busycount = cadences;
01660 }

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

Set expected lengths of the busy tone.

Definition at line 1662 of file dsp.c.

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

Referenced by zt_new().

01663 {
01664    dsp->busy_tonelength = tonelength;
01665    dsp->busy_quietlength = quietlength;
01666    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01667 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1750 of file dsp.c.

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

Referenced by zt_new().

01751 {
01752    int x;
01753    
01754    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01755       if (!strcasecmp(aliases[x].name, zone)) {
01756          dsp->progmode = aliases[x].mode;
01757          ast_dsp_prog_reset(dsp);
01758          return 0;
01759       }
01760    }
01761    return -1;
01762 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1638 of file dsp.c.

References ast_dsp::features.

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

01639 {
01640    dsp->features = features;
01641 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1648 of file dsp.c.

References ast_dsp::threshold.

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

01649 {
01650    dsp->threshold = threshold;
01651 }

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 1398 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(), isAnsweringMachine(), nv_background_detect_exec(), and nv_detectfax_exec().

01399 {
01400    short *s;
01401    int len;
01402    
01403    if (f->frametype != AST_FRAME_VOICE) {
01404       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01405       return 0;
01406    }
01407    if (f->subclass != AST_FORMAT_SLINEAR) {
01408       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01409       return 0;
01410    }
01411    s = f->data;
01412    len = f->datalen/2;
01413    return __ast_dsp_silence(dsp, s, len, totalsilence);
01414 }


Generated on Fri Aug 24 02:25:40 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1