Sat Aug 6 00:39:55 2011

Asterisk developer's documentation


dsp.h File Reference

Convenient Signal Processing routines. More...

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_compare (struct ast_dsp *dsp, int compare)
 Set if silence and noice lengths must be compared for busy.
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, int fuzzy)
 Set expected lengths of the busy tones.
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(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), sip_new(), and ss_thread().

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

#define DSP_DIGITMODE_MUTEMAX   (1 << 10)

Definition at line 36 of file dsp.h.

Referenced by ast_dsp_digitmode(), ast_dsp_process(), and dahdi_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(), dahdi_setoption(), process_dahdi(), and sip_new().

#define DSP_FEATURE_BUSY_DETECT   (1 << 1)

Definition at line 27 of file dsp.h.

Referenced by ast_dsp_process(), and dahdi_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 dahdi_new().

#define DSP_FEATURE_DTMF_DETECT   (1 << 3)

Definition at line 28 of file dsp.h.

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

#define DSP_FEATURE_FAX_DETECT   (1 << 4)

Definition at line 29 of file dsp.h.

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

#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 dahdi_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 1294 of file dsp.c.

References ast_log(), BUSY_MAX, BUSY_MIN, ast_dsp::busy_pattern_fuzzy, BUSY_PERCENT, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busycompare, ast_dsp::busycount, ast_dsp::busymaybe, ast_dsp::busytoneonly, DSP_HISTORY, ast_dsp::historicnoise, ast_dsp::historicsilence, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, and option_debug.

Referenced by ast_dsp_process().

01295 {
01296    int res = 0, x;
01297    int avgsilence = 0, hitsilence = 0;
01298    int avgtone = 0, hittone = 0;
01299 #ifdef DEBUG_DSP_BUSYDETECT
01300    char buf[16];
01301    char silence_list[64]="", tone_list[64]="";
01302 #endif
01303    
01304    if (!dsp->busymaybe)
01305       return res;
01306    dsp->busymaybe = 0;
01307 
01308    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01309       avgsilence += dsp->historicsilence[x];
01310       avgtone += dsp->historicnoise[x];
01311    }
01312    avgsilence /= dsp->busycount;
01313    avgtone /= dsp->busycount;
01314 #ifdef DEBUG_DSP_BUSYDETECT
01315    sprintf(silence_list,"Silences: ");
01316    sprintf(tone_list,"Tones:    ");
01317 #endif
01318    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01319 #ifdef DEBUG_DSP_BUSYDETECT
01320       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01321       strcat(silence_list, buf);
01322       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01323       strcat(tone_list, buf); 
01324 #endif
01325       if (!dsp->busytoneonly) {
01326          if (avgsilence > dsp->historicsilence[x]) {
01327             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01328                hitsilence++;
01329          } else {
01330             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01331                hitsilence++;
01332          }
01333       }
01334       if (avgtone > dsp->historicnoise[x]) {
01335          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01336             hittone++;
01337       } else {
01338          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01339             hittone++;
01340       }
01341    }
01342 #ifdef DEBUG_DSP_BUSYDETECT
01343    fprintf(stderr, "BUSY DETECTOR\n");   
01344    fprintf(stderr, "%s\n", tone_list);
01345    fprintf(stderr, "%s\n", silence_list)
01346 #endif
01347    if ((dsp->busytoneonly || 
01348        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01349       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01350       if (dsp->busycompare) {
01351            if (dsp->busytoneonly) {
01352              res = 1;
01353             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01354          } else {
01355               if (avgtone > avgsilence) {
01356                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01357                     res = 1;
01358             } else {
01359                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01360                    res = 1;
01361             }
01362          }
01363       } else {
01364          res = 1;
01365       }
01366    }
01367    /* If we know the expected busy tone length, check we are in the range */
01368    if (res && (dsp->busy_tonelength > 0)) {
01369       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100)) {
01370          if(option_debug) {
01371             ast_log(LOG_DEBUG, "busy detector: avgtone of %d not close enough to desired %d\n", avgtone, dsp->busy_tonelength);
01372          }
01373          res = 0;
01374       }
01375    }
01376    /* If we know the expected busy tone silent-period length, check we are in the range */
01377    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01378       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100)) {
01379          if(option_debug) {
01380             ast_log(LOG_DEBUG, "busy detector: avgsilence of %d not close enough to desired %d\n", avgsilence, dsp->busy_quietlength);
01381          }
01382          res = 0;
01383       }
01384    }
01385    if (res && option_debug)
01386       ast_log(LOG_NOTICE, "Detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01387    return res;
01388 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

01224 {
01225    if (inf->frametype != AST_FRAME_VOICE) {
01226       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01227       return 0;
01228    }
01229    if (inf->subclass != AST_FORMAT_SLINEAR) {
01230       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01231       return 0;
01232    }
01233    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01234 }

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame f 
)

Return non-zero if DTMF hit was found.

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

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

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Definition at line 1805 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 dahdi_hangup(), dahdi_new(), dahdi_setoption(), mgcp_new(), sip_new(), and ss_thread().

01806 {
01807    int new;
01808    int old;
01809    
01810    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01811    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01812    if (old != new) {
01813       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01814       if (new & DSP_DIGITMODE_MF)
01815          ast_mf_detect_init(&dsp->td.mf);
01816       else
01817          ast_dtmf_detect_init(&dsp->td.dtmf);
01818    }
01819    dsp->digitmode = digitmode;
01820    return 0;
01821 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

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

01743 {
01744    int i;
01745    
01746    dsp->thinkdigit = 0;
01747    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01748       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01749       dsp->td.mf.current_digits = 0;
01750       /* Reinitialise the detector for the next block */
01751       for (i = 0;  i < 6;  i++) {
01752          goertzel_reset(&dsp->td.mf.tone_out[i]);
01753 #ifdef OLD_DSP_ROUTINES
01754          goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01755 #endif         
01756       }
01757 #ifdef OLD_DSP_ROUTINES
01758       dsp->td.mf.energy = 0.0;
01759       dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01760 #else
01761       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;
01762 #endif      
01763       dsp->td.mf.current_sample = 0;
01764    } else {
01765       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01766       dsp->td.dtmf.current_digits = 0;
01767       /* Reinitialise the detector for the next block */
01768       for (i = 0;  i < 4;  i++) {
01769          goertzel_reset(&dsp->td.dtmf.row_out[i]);
01770          goertzel_reset(&dsp->td.dtmf.col_out[i]);
01771 #ifdef OLD_DSP_ROUTINES
01772          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01773          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01774 #endif         
01775       }
01776 #ifdef FAX_DETECT
01777       goertzel_reset (&dsp->td.dtmf.fax_tone);
01778 #endif
01779 #ifdef OLD_DSP_ROUTINES
01780 #ifdef FAX_DETECT
01781       goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01782 #endif
01783       dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01784 #else
01785       dsp->td.dtmf.lasthit = dsp->td.dtmf.mhit = 0;
01786 #endif      
01787       dsp->td.dtmf.energy = 0.0;
01788       dsp->td.dtmf.current_sample = 0;
01789    }
01790 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1700 of file dsp.c.

References free.

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

01701 {
01702    free(dsp);
01703 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1842 of file dsp.c.

References ast_dsp::tcount.

01843 {
01844    return dsp->tcount;
01845 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1837 of file dsp.c.

References ast_dsp::tstate.

01838 {
01839    return dsp->tstate;
01840 }

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

Get pending DTMF/MF digits.

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

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

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1664 of file dsp.c.

References ast_calloc, ast_dsp_prog_reset(), ast_dtmf_detect_init(), BUSY_PAT_PERCENT, 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(), dahdi_new(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_dtmfmode(), and sip_new().

01665 {
01666    struct ast_dsp *dsp;
01667    
01668    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01669       dsp->threshold = DEFAULT_THRESHOLD;
01670       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01671       dsp->busycount = DSP_HISTORY;
01672       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01673 #ifdef BUSYDETECT_TONEONLY
01674       dsp->busytoneonly = 1;
01675 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01676 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01677 #endif
01678 #else
01679       dsp->busytoneonly = 0;
01680 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01681       dsp->busycompare = 1;
01682 #else
01683       dsp->busycompare = 0;
01684 #endif
01685 #endif
01686       dsp->display_inband_dtmf_warning = 1;
01687       /* Initialize DTMF detector */
01688       ast_dtmf_detect_init(&dsp->td.dtmf);
01689       /* Initialize initial DSP progress detect parameters */
01690       ast_dsp_prog_reset(dsp);
01691    }
01692    return dsp;
01693 }

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 1454 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_frisolate(), 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, ast_dsp::display_inband_dtmf_warning, 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(), and sip_rtp_read().

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

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01793 {
01794    int x;
01795    
01796    dsp->totalsilence = 0;
01797    dsp->gsamps = 0;
01798    for (x=0;x<4;x++)
01799       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01800    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01801    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01802    dsp->ringtimeout= 0;
01803 }

void ast_dsp_set_busy_compare ( struct ast_dsp dsp,
int  compare 
)

Set if silence and noice lengths must be compared for busy.

Definition at line 1722 of file dsp.c.

References ast_dsp::busycompare.

Referenced by dahdi_new().

01723 {
01724   if (compare > 0)
01725       dsp->busycompare = 1;
01726   else
01727       dsp->busycompare = 0;
01728 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1713 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01714 {
01715    if (cadences < 4)
01716       cadences = 4;
01717    if (cadences > DSP_HISTORY)
01718       cadences = DSP_HISTORY;
01719    dsp->busycount = cadences;
01720 }

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

Set expected lengths of the busy tones.

Definition at line 1730 of file dsp.c.

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

Referenced by dahdi_new().

01731 {
01732    dsp->busy_tonelength = tonelength;
01733    if (quietlength > 0)
01734       dsp->busy_quietlength = quietlength;
01735    else 
01736      dsp->busytoneonly = 1;
01737    ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01738    if( fuzzy > 0 && fuzzy < 50 ) 
01739       dsp->busy_pattern_fuzzy = fuzzy;
01740 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1823 of file dsp.c.

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

Referenced by dahdi_new().

01824 {
01825    int x;
01826    
01827    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01828       if (!strcasecmp(aliases[x].name, zone)) {
01829          dsp->progmode = aliases[x].mode;
01830          ast_dsp_prog_reset(dsp);
01831          return 0;
01832       }
01833    }
01834    return -1;
01835 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1695 of file dsp.c.

References ast_dsp::features.

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

01696 {
01697    dsp->features = features;
01698 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1705 of file dsp.c.

References ast_dsp::threshold.

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

01706 {
01707    if (threshold < 256)
01708      dsp->threshold = 256;
01709    else
01710      dsp->threshold = threshold;
01711 }

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

01437 {
01438    short *s;
01439    int len;
01440    
01441    if (f->frametype != AST_FRAME_VOICE) {
01442       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01443       return 0;
01444    }
01445    if (f->subclass != AST_FORMAT_SLINEAR) {
01446       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01447       return 0;
01448    }
01449    s = f->data;
01450    len = f->datalen/2;
01451    return __ast_dsp_silence(dsp, s, len, totalsilence);
01452 }


Generated on Sat Aug 6 00:39:55 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7