Thu Jul 9 13:41:16 2009

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_FAXMODE_DETECT_ALL   (DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED)
#define DSP_FAXMODE_DETECT_CED   (1 << 1)
#define DSP_FAXMODE_DETECT_CNG   (1 << 0)
#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_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.
int ast_dsp_set_faxmode (struct ast_dsp *dsp, int faxmode)
 Set fax mode.
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

Detect DTMF digits

Definition at line 31 of file dsp.h.

Referenced by ast_dsp_digitmode(), ast_dsp_new(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), sip_new(), ss_thread(), and store_config().

#define DSP_DIGITMODE_MF   1

Detect MF digits

Definition at line 32 of file dsp.h.

Referenced by __ast_dsp_digitdetect(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_new(), and ss_thread().

#define DSP_DIGITMODE_MUTECONF   (1 << 9)

Mute conference

Definition at line 35 of file dsp.h.

Referenced by ast_dsp_digitmode(), ast_dsp_process(), dahdi_setoption(), and store_config().

#define DSP_DIGITMODE_MUTEMAX   (1 << 10)

Delay audio by a frame to try to extra quelch

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)

Do not quelch DTMF from in-band

Definition at line 34 of file dsp.h.

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

#define DSP_DIGITMODE_RELAXDTMF   (1 << 11)

"Radio" mode (relaxed DTMF)

Definition at line 37 of file dsp.h.

Referenced by __ast_dsp_digitdetect(), dahdi_setoption(), process_dahdi(), sip_new(), and store_config().

#define DSP_FAXMODE_DETECT_ALL   (DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED)

Definition at line 47 of file dsp.h.

#define DSP_FAXMODE_DETECT_CED   (1 << 1)

Definition at line 46 of file dsp.h.

Referenced by __ast_dsp_digitdetect().

#define DSP_FAXMODE_DETECT_CNG   (1 << 0)

Definition at line 45 of file dsp.h.

Referenced by __ast_dsp_digitdetect(), ast_dsp_new(), and transmit_audio().

#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_process(), and dahdi_new().

#define DSP_FEATURE_DTMF_DETECT   (1 << 3)

Definition at line 28 of file dsp.h.

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

#define DSP_FEATURE_FAX_DETECT   (1 << 4)

Definition at line 29 of file dsp.h.

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

#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)

Enable busy tone detection

Definition at line 41 of file dsp.h.

#define DSP_PROGRESS_CONGESTION   (1 << 19)

Enable congestion tone detection

Definition at line 42 of file dsp.h.

#define DSP_PROGRESS_RINGING   (1 << 17)

Enable calling tone detection

Definition at line 40 of file dsp.h.

#define DSP_PROGRESS_TALK   (1 << 16)

Enable talk detection

Definition at line 39 of file dsp.h.

Referenced by dahdi_new().

#define DSP_TONE_STATE_BUSY   4

Definition at line 53 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_DIALTONE   2

Definition at line 51 of file dsp.h.

#define DSP_TONE_STATE_HUNGUP   8

Definition at line 57 of file dsp.h.

#define DSP_TONE_STATE_RINGING   1

Definition at line 50 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_SILENCE   0

Definition at line 49 of file dsp.h.

Referenced by __ast_dsp_call_progress().

#define DSP_TONE_STATE_SPECIAL1   5

Definition at line 54 of file dsp.h.

#define DSP_TONE_STATE_SPECIAL2   6

Definition at line 55 of file dsp.h.

#define DSP_TONE_STATE_SPECIAL3   7

Definition at line 56 of file dsp.h.

#define DSP_TONE_STATE_TALKING   3

Definition at line 52 of file dsp.h.


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

References ast_log(), buf, 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().

01085 {
01086    int res = 0, x;
01087    int avgsilence = 0, hitsilence = 0;
01088    int avgtone = 0, hittone = 0;
01089 #ifdef DEBUG_DSP_BUSYDETECT
01090    char buf[16];
01091    char silence_list[64]="", tone_list[64]="";
01092 #endif
01093    
01094    if (!dsp->busymaybe)
01095       return res;
01096    dsp->busymaybe = 0;
01097 
01098    for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
01099       avgsilence += dsp->historicsilence[x];
01100       avgtone += dsp->historicnoise[x];
01101    }
01102    avgsilence /= dsp->busycount;
01103    avgtone /= dsp->busycount;
01104 #ifdef DEBUG_DSP_BUSYDETECT
01105    sprintf(silence_list,"Silences: ");
01106    sprintf(tone_list,"Tones:    ");
01107 #endif
01108    for (x=DSP_HISTORY - dsp->busycount; x<DSP_HISTORY; x++) {
01109 #ifdef DEBUG_DSP_BUSYDETECT
01110       snprintf(buf, sizeof(buf), "%5d ", dsp->historicsilence[x]);
01111       strcat(silence_list, buf);
01112       snprintf(buf, sizeof(buf), "%5d ", dsp->historicnoise[x]);
01113       strcat(tone_list, buf); 
01114 #endif
01115       if (!dsp->busytoneonly) {
01116          if (avgsilence > dsp->historicsilence[x]) {
01117             if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
01118                hitsilence++;
01119          } else {
01120             if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
01121                hitsilence++;
01122          }
01123       }
01124       if (avgtone > dsp->historicnoise[x]) {
01125          if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
01126             hittone++;
01127       } else {
01128          if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
01129             hittone++;
01130       }
01131    }
01132 #ifdef DEBUG_DSP_BUSYDETECT
01133    fprintf(stderr, "BUSY DETECTOR\n");   
01134    fprintf(stderr, "%s\n", tone_list);
01135    fprintf(stderr, "%s\n", silence_list)
01136 #endif
01137    if ((dsp->busytoneonly || 
01138        (hitsilence >= dsp->busycount - 1 && avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) &&
01139       (hittone >= dsp->busycount - 1 && avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
01140       if (dsp->busycompare) {
01141            if (dsp->busytoneonly) {
01142              res = 1;
01143             ast_log(LOG_ERROR, "You can't use busytoneonly together with busycompare");
01144          } else {
01145               if (avgtone > avgsilence) {
01146                  if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
01147                     res = 1;
01148             } else {
01149                  if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
01150                    res = 1;
01151             }
01152          }
01153       } else {
01154          res = 1;
01155       }
01156    }
01157    /* If we know the expected busy tone length, check we are in the range */
01158    if (res && (dsp->busy_tonelength > 0)) {
01159       if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*dsp->busy_pattern_fuzzy/100)) {
01160 #ifdef BUSYDETECT_DEBUG
01161          if(option_debug) {
01162             ast_log(LOG_DEBUG, "busy detector: avgtone of %d not close enough to desired %d\n", avgtone, dsp->busy_tonelength);
01163          }
01164 #endif
01165          res = 0;
01166       }
01167    }
01168    /* If we know the expected busy tone silent-period length, check we are in the range */
01169    if (res && (!dsp->busytoneonly) && (dsp->busy_quietlength > 0)) {
01170       if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*dsp->busy_pattern_fuzzy/100)) {
01171 #ifdef BUSYDETECT_DEBUG
01172          if(option_debug) {
01173             ast_log(LOG_DEBUG, "busy detector: avgsilence of %d not close enough to desired %d\n", avgsilence, dsp->busy_quietlength);
01174          }
01175 #endif
01176          res = 0;
01177       }
01178    }
01179    if (res) {
01180       if (option_debug)
01181          ast_log(LOG_NOTICE, "ast_dsp_busydetect detected busy sequence, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01182    } else {
01183       if (option_debug)
01184          ast_log(LOG_NOTICE, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
01185    }
01186    return res;
01187 }

int ast_dsp_call_progress ( struct ast_dsp dsp,
struct ast_frame inf 
)

Scans for progress indication in audio.

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

01015 {
01016    if (inf->frametype != AST_FRAME_VOICE) {
01017       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01018       return 0;
01019    }
01020    if (inf->subclass != AST_FORMAT_SLINEAR) {
01021       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01022       return 0;
01023    }
01024    return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
01025 }

int ast_dsp_digitdetect ( struct ast_dsp dsp,
struct ast_frame f 
)

Return non-zero if DTMF hit was found.

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

00838 {
00839    short *s;
00840    int len;
00841    int ign=0;
00842 
00843    if (inf->frametype != AST_FRAME_VOICE) {
00844       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
00845       return 0;
00846    }
00847    if (inf->subclass != AST_FORMAT_SLINEAR) {
00848       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
00849       return 0;
00850    }
00851    s = inf->data;
00852    len = inf->datalen / 2;
00853    return __ast_dsp_digitdetect(dsp, s, len, &ign);
00854 }

int ast_dsp_digitmode ( struct ast_dsp dsp,
int  digitmode 
)

Set digit mode.

Definition at line 1541 of file dsp.c.

References ast_digit_detect_init(), ast_dsp::digit_state, ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, and DSP_DIGITMODE_MUTEMAX.

Referenced by dahdi_hangup(), dahdi_new(), dahdi_setoption(), mgcp_new(), sip_new(), ss_thread(), and store_config().

01542 {
01543    int new;
01544    int old;
01545    
01546    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01547    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01548    if (old != new) {
01549       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01550       ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF);
01551    }
01552    dsp->digitmode = digitmode;
01553    return 0;
01554 }

void ast_dsp_digitreset ( struct ast_dsp dsp  ) 

Reset DTMF detector.

Definition at line 1499 of file dsp.c.

References digit_detect_state_t::current_digits, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MF, digit_detect_state_t::dtmf, goertzel_reset(), digit_detect_state_t::mf, s, digit_detect_state_t::td, and ast_dsp::thinkdigit.

Referenced by ss_thread().

01500 {
01501    int i;
01502    
01503    dsp->thinkdigit = 0;
01504    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01505       mf_detect_state_t *s = &dsp->digit_state.td.mf;
01506       /* Reinitialise the detector for the next block */
01507       for (i = 0;  i < 6;  i++) {
01508          goertzel_reset(&s->tone_out[i]);
01509       }
01510       s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0;
01511       s->current_sample = 0;
01512    } else {
01513       dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf;
01514       /* Reinitialise the detector for the next block */
01515       for (i = 0;  i < 4;  i++) {
01516          goertzel_reset(&s->row_out[i]);
01517          goertzel_reset(&s->col_out[i]);
01518       }
01519       s->lasthit = s->current_hit = 0;
01520       s->energy = 0.0;
01521       s->current_sample = 0;
01522    }
01523 
01524    dsp->digit_state.digits[0] = '\0';
01525    dsp->digit_state.current_digits = 0;
01526 }

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

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

Referenced by __frame_free().

01590 {
01591    struct ast_dsp *dsp;
01592 
01593    ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
01594 
01595    dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
01596 
01597    if (dsp->freqcount != -1)
01598       return;
01599    
01600    ast_dsp_free(dsp);
01601 }

void ast_dsp_free ( struct ast_dsp dsp  ) 

Definition at line 1446 of file dsp.c.

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

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

01447 {
01448    if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
01449       /* If this flag is still set, that means that the dsp's destruction 
01450        * been torn down, while we still have a frame out there being used.
01451        * When ast_frfree() gets called on that frame, this ast_trans_pvt
01452        * will get destroyed, too. */
01453 
01454       /* Set the magic flag to destroy the dsp when the frame is freed */
01455       dsp->freqcount = -1;
01456 
01457       return;
01458    }
01459    ast_free(dsp);
01460 }

int ast_dsp_get_tcount ( struct ast_dsp dsp  ) 

Get tcount (Threshold counter).

Definition at line 1584 of file dsp.c.

References ast_dsp::tcount.

01585 {
01586    return dsp->tcount;
01587 }

int ast_dsp_get_tstate ( struct ast_dsp dsp  ) 

Get tstate (Tone State).

Definition at line 1579 of file dsp.c.

References ast_dsp::tstate.

01580 {
01581    return dsp->tstate;
01582 }

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

Get pending DTMF/MF digits.

Definition at line 876 of file dsp.c.

References digit_detect_state_t::current_digits, ast_dsp::digit_state, and digit_detect_state_t::digits.

00877 {
00878    if (max > dsp->digit_state.current_digits)
00879       max = dsp->digit_state.current_digits;
00880    if (max > 0) {
00881       memcpy(buf, dsp->digit_state.digits, max);
00882       memmove(dsp->digit_state.digits, dsp->digit_state.digits + max, dsp->digit_state.current_digits - max);
00883       dsp->digit_state.current_digits -= max;
00884    }
00885    buf[max] = '\0';
00886    return  max;
00887 }

struct ast_dsp* ast_dsp_new ( void   ) 

Definition at line 1407 of file dsp.c.

References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), BUSY_PAT_PERCENT, DEFAULT_THRESHOLD, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_FAXMODE_DETECT_CNG, 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(), sip_new(), store_config(), and transmit_audio().

01408 {
01409    struct ast_dsp *dsp;
01410    
01411    if ((dsp = ast_calloc(1, sizeof(*dsp)))) {      
01412       dsp->threshold = DEFAULT_THRESHOLD;
01413       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01414       dsp->busycount = DSP_HISTORY;
01415       dsp->digitmode = DSP_DIGITMODE_DTMF;
01416       dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
01417       dsp->busy_pattern_fuzzy = BUSY_PAT_PERCENT;
01418 #ifdef BUSYDETECT_TONEONLY
01419       dsp->busytoneonly = 1;
01420 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01421 #error "You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE");
01422 #endif
01423 #else
01424    dsp->busytoneonly = 0;
01425 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
01426    dsp->busycompare = 1;
01427 #else
01428    dsp->busycompare = 0;
01429 #endif
01430 #endif
01431       /* Initialize digit detector */
01432       ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF);
01433       /* Initialize initial DSP progress detect parameters */
01434       ast_dsp_prog_reset(dsp);
01435       /* Initialize fax detector */
01436       ast_fax_detect_init(dsp);
01437    }
01438    return dsp;
01439 }

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 1207 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_debug, 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, chan, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, ast_dsp::f, ast_dsp::features, FIX_INF, ast_frame::frametype, len(), LOG_WARNING, ast_channel::name, ast_frame::src, ast_frame::subclass, and ast_dsp::thinkdigit.

Referenced by dahdi_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), sip_rtp_read(), transmit_audio(), and usbradio_read().

01208 {
01209    int silence;
01210    int res;
01211    int digit;
01212    int x;
01213    short *shortdata;
01214    unsigned char *odata;
01215    int len;
01216    int writeback = 0;
01217 
01218 #define FIX_INF(inf) do { \
01219       if (writeback) { \
01220          switch (inf->subclass) { \
01221          case AST_FORMAT_SLINEAR: \
01222             break; \
01223          case AST_FORMAT_ULAW: \
01224             for (x=0;x<len;x++) \
01225                odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
01226             break; \
01227          case AST_FORMAT_ALAW: \
01228             for (x=0;x<len;x++) \
01229                odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
01230             break; \
01231          } \
01232       } \
01233    } while(0) 
01234 
01235    if (!af)
01236       return NULL;
01237    if (af->frametype != AST_FRAME_VOICE)
01238       return af;
01239    odata = af->data;
01240    len = af->datalen;
01241    /* Make sure we have short data */
01242    switch (af->subclass) {
01243    case AST_FORMAT_SLINEAR:
01244       shortdata = af->data;
01245       len = af->datalen / 2;
01246       break;
01247    case AST_FORMAT_ULAW:
01248       shortdata = alloca(af->datalen * 2);
01249       for (x = 0;x < len; x++) 
01250          shortdata[x] = AST_MULAW(odata[x]);
01251       break;
01252    case AST_FORMAT_ALAW:
01253       shortdata = alloca(af->datalen * 2);
01254       for (x = 0; x < len; x++) 
01255          shortdata[x] = AST_ALAW(odata[x]);
01256       break;
01257    default:
01258       ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
01259       return af;
01260    }
01261    silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
01262    if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
01263       memset(&dsp->f, 0, sizeof(dsp->f));
01264       dsp->f.frametype = AST_FRAME_NULL;
01265       ast_frfree(af);
01266       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01267       return &dsp->f;
01268    }
01269    if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
01270       chan->_softhangup |= AST_SOFTHANGUP_DEV;
01271       memset(&dsp->f, 0, sizeof(dsp->f));
01272       dsp->f.frametype = AST_FRAME_CONTROL;
01273       dsp->f.subclass = AST_CONTROL_BUSY;
01274       ast_frfree(af);
01275       ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
01276       ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01277       return &dsp->f;
01278    }
01279    if (((dsp->features & DSP_FEATURE_DTMF_DETECT) || (dsp->features & DSP_FEATURE_FAX_DETECT))) {
01280       digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
01281 #if 0
01282       if (digit)
01283          printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
01284 #endif
01285       if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
01286          if (!dsp->thinkdigit) {
01287             if (digit) {
01288                /* Looks like we might have something.  
01289                 * Request a conference mute for the moment */
01290                memset(&dsp->f, 0, sizeof(dsp->f));
01291                dsp->f.frametype = AST_FRAME_DTMF;
01292                dsp->f.subclass = 'm';
01293                dsp->thinkdigit = 'x';
01294                FIX_INF(af);
01295                if (chan)
01296                   ast_queue_frame(chan, af);
01297                ast_frfree(af);
01298                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01299                return &dsp->f;
01300             }
01301          } else {
01302             if (digit) {
01303                /* Thought we saw one last time.  Pretty sure we really have now */
01304                if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
01305                   /* If we found a digit, and we're changing digits, go
01306                      ahead and send this one, but DON'T stop confmute because
01307                      we're detecting something else, too... */
01308                   memset(&dsp->f, 0, sizeof(dsp->f));
01309                   dsp->f.frametype = AST_FRAME_DTMF_END;
01310                   dsp->f.subclass = dsp->thinkdigit;
01311                   FIX_INF(af);
01312                   if (chan)
01313                      ast_queue_frame(chan, af);
01314                   ast_frfree(af);
01315                } else {
01316                   dsp->thinkdigit = digit;
01317                   memset(&dsp->f, 0, sizeof(dsp->f));
01318                   dsp->f.frametype = AST_FRAME_DTMF_BEGIN;
01319                   dsp->f.subclass = dsp->thinkdigit;
01320                   FIX_INF(af);
01321                   if (chan)
01322                      ast_queue_frame(chan, af);
01323                   ast_frfree(af);
01324                }
01325                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01326                return &dsp->f;
01327             } else {
01328                memset(&dsp->f, 0, sizeof(dsp->f));
01329                if (dsp->thinkdigit != 'x') {
01330                   /* If we found a digit, send it now */
01331                   dsp->f.frametype = AST_FRAME_DTMF_END;
01332                   dsp->f.subclass = dsp->thinkdigit;
01333                   dsp->thinkdigit = 0;
01334                } else {
01335                   dsp->f.frametype = AST_FRAME_DTMF;
01336                   dsp->f.subclass = 'u';
01337                   dsp->thinkdigit = 0;
01338                }
01339                FIX_INF(af);
01340                if (chan)
01341                   ast_queue_frame(chan, af);
01342                ast_frfree(af);
01343                ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01344                return &dsp->f;
01345             }
01346          }
01347       } else if (dsp->digit_state.current_digits > 1 ||
01348          (dsp->digit_state.current_digits == 1 && digit != dsp->digit_state.digits[0])) {
01349          /* Since we basically generate DTMF_END frames we do it only when a digit
01350             has finished. */
01351 
01352          memset(&dsp->f, 0, sizeof(dsp->f));
01353          dsp->f.frametype = AST_FRAME_DTMF;
01354          dsp->f.subclass = dsp->digit_state.digits[0];
01355          memmove(dsp->digit_state.digits, dsp->digit_state.digits + 1, dsp->digit_state.current_digits);
01356          dsp->digit_state.current_digits--;
01357          FIX_INF(af);
01358          if (chan)
01359             ast_queue_frame(chan, af);
01360          ast_frfree(af);
01361          ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
01362          return &dsp->f;
01363       }
01364    }
01365    if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
01366       res = __ast_dsp_call_progress(dsp, shortdata, len);
01367       if (res) {
01368          switch (res) {
01369          case AST_CONTROL_ANSWER:
01370          case AST_CONTROL_BUSY:
01371          case AST_CONTROL_RINGING:
01372          case AST_CONTROL_CONGESTION:
01373          case AST_CONTROL_HANGUP:
01374             memset(&dsp->f, 0, sizeof(dsp->f));
01375             dsp->f.frametype = AST_FRAME_CONTROL;
01376             dsp->f.subclass = res;
01377             dsp->f.src = "dsp_progress";
01378             if (chan) 
01379                ast_queue_frame(chan, &dsp->f);
01380             break;
01381          default:
01382             ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
01383          }
01384       }
01385    }
01386    FIX_INF(af);
01387    return af;
01388 }

void ast_dsp_reset ( struct ast_dsp dsp  ) 

Reset total silence count.

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

01529 {
01530    int x;
01531    
01532    dsp->totalsilence = 0;
01533    dsp->gsamps = 0;
01534    for (x=0;x<4;x++)
01535       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01536    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01537    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));  
01538    dsp->ringtimeout= 0;
01539 }

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

References ast_dsp::busycompare.

Referenced by dahdi_new().

01480 {
01481   if (compare > 0)
01482       dsp->busycompare = 1;
01483   else
01484       dsp->busycompare = 0;
01485 }

void ast_dsp_set_busy_count ( struct ast_dsp dsp,
int  cadences 
)

Set number of required cadences for busy.

Definition at line 1470 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

Referenced by dahdi_new().

01471 {
01472    if (cadences < 4)
01473       cadences = 4;
01474    if (cadences > DSP_HISTORY)
01475       cadences = DSP_HISTORY;
01476    dsp->busycount = cadences;
01477 }

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

References ast_debug, ast_dsp::busy_pattern_fuzzy, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, and ast_dsp::busytoneonly.

Referenced by dahdi_new().

01488 {
01489    dsp->busy_tonelength = tonelength;
01490    if (quietlength > 0)
01491       dsp->busy_quietlength = quietlength;
01492    else 
01493      dsp->busytoneonly = 1;
01494    ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
01495    if( fuzzy > 0 && fuzzy < 50 ) 
01496       dsp->busy_pattern_fuzzy = fuzzy;
01497 }

int ast_dsp_set_call_progress_zone ( struct ast_dsp dsp,
char *  zone 
)

Set zone for doing progress detection.

Definition at line 1565 of file dsp.c.

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

Referenced by dahdi_new().

01566 {
01567    int x;
01568    
01569    for (x = 0; x < ARRAY_LEN(aliases); x++) {
01570       if (!strcasecmp(aliases[x].name, zone)) {
01571          dsp->progmode = aliases[x].mode;
01572          ast_dsp_prog_reset(dsp);
01573          return 0;
01574       }
01575    }
01576    return -1;
01577 }

int ast_dsp_set_faxmode ( struct ast_dsp dsp,
int  faxmode 
)

Set fax mode.

Definition at line 1556 of file dsp.c.

References ast_fax_detect_init(), and ast_dsp::faxmode.

Referenced by transmit_audio().

01557 {
01558    if (dsp->faxmode != faxmode) {
01559       ast_fax_detect_init(dsp);
01560    }
01561    dsp->faxmode = faxmode;
01562    return 0;
01563 }

void ast_dsp_set_features ( struct ast_dsp dsp,
int  features 
)

Select feature set.

Definition at line 1441 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(), sip_new(), store_config(), and transmit_audio().

01442 {
01443    dsp->features = features;
01444 }

void ast_dsp_set_threshold ( struct ast_dsp dsp,
int  threshold 
)

Set threshold value for silence.

Definition at line 1462 of file dsp.c.

References ast_dsp::threshold.

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

01463 {
01464    if (threshold < 256)
01465      dsp->threshold = 256;
01466    else
01467      dsp->threshold = threshold;
01468 }

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

01190 {
01191    short *s;
01192    int len;
01193    
01194    if (f->frametype != AST_FRAME_VOICE) {
01195       ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
01196       return 0;
01197    }
01198    if (f->subclass != AST_FORMAT_SLINEAR) {
01199       ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
01200       return 0;
01201    }
01202    s = f->data;
01203    len = f->datalen/2;
01204    return __ast_dsp_silence(dsp, s, len, totalsilence);
01205 }


Generated on Thu Jul 9 13:41:17 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7