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_DIGIT_DETECT (1 << 3) |
#define | DSP_FEATURE_FAX_DETECT (1 << 4) |
#define | DSP_FEATURE_SILENCE_SUPPRESS (1 << 0) |
#define | DSP_FEATURE_WAITDIALTONE (1 << 20) |
#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 |
Enumerations | |
enum | threshold { THRESHOLD_SILENCE = 0, THRESHOLD_MAX = 1 } |
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. | |
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_threshold_from_settings (enum threshold which) |
Get silence threshold from dsp.conf. | |
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. | |
int | ast_dsp_init (void) |
Load dsp settings from dsp.conf. | |
struct ast_dsp * | ast_dsp_new (void) |
int | ast_dsp_noise (struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise) |
Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise. | |
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. | |
int | ast_dsp_reload (void) |
Reloads dsp settings from dsp.conf. | |
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. | |
int | ast_dsp_set_digitmode (struct ast_dsp *dsp, int digitmode) |
Set digit mode. | |
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. | |
int | ast_dsp_was_muted (struct ast_dsp *dsp) |
Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio. |
Convenient Signal Processing routines.
Definition in file dsp.h.
#define DSP_DIGITMODE_DTMF 0 |
Detect DTMF digits
Definition at line 31 of file dsp.h.
Referenced by ast_dsp_new(), ast_dsp_set_digitmode(), dahdi_hangup(), dahdi_new(), dahdi_setoption(), mkintf(), 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_digitreset(), ast_dsp_new(), ast_dsp_process(), ast_dsp_set_digitmode(), and ss_thread().
#define DSP_DIGITMODE_MUTECONF (1 << 9) |
Mute conference
Definition at line 35 of file dsp.h.
Referenced by ast_dsp_set_digitmode(), 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_set_digitmode(), 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 ast_dsp_process(), 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_process(), dahdi_setoption(), process_dahdi(), sip_new(), and store_config().
#define DSP_FAXMODE_DETECT_ALL (DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED) |
#define DSP_FAXMODE_DETECT_CED (1 << 1) |
Definition at line 47 of file dsp.h.
Referenced by ast_dsp_process().
#define DSP_FAXMODE_DETECT_CNG (1 << 0) |
Definition at line 46 of file dsp.h.
Referenced by ast_dsp_new(), and ast_dsp_process().
#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_DIGIT_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(), sip_new(), sip_rtp_read(), and store_config().
#define DSP_FEATURE_FAX_DETECT (1 << 4) |
Definition at line 29 of file dsp.h.
Referenced by ast_dsp_process(), dahdi_new(), misdn_set_opt_exec(), read_config(), and sip_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_FEATURE_WAITDIALTONE (1 << 20) |
Enable dial tone detection
Definition at line 44 of file dsp.h.
Referenced by ast_dsp_process(), dahdi_new(), and dahdi_read().
#define DSP_PROGRESS_BUSY (1 << 18) |
Enable busy tone detection
Definition at line 41 of file dsp.h.
Referenced by __ast_dsp_call_progress().
#define DSP_PROGRESS_CONGESTION (1 << 19) |
Enable congestion tone detection
Definition at line 42 of file dsp.h.
Referenced by __ast_dsp_call_progress().
#define DSP_PROGRESS_RINGING (1 << 17) |
Enable calling tone detection
Definition at line 40 of file dsp.h.
Referenced by __ast_dsp_call_progress().
#define DSP_PROGRESS_TALK (1 << 16) |
Enable talk detection
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 54 of file dsp.h.
Referenced by __ast_dsp_call_progress().
#define DSP_TONE_STATE_DIALTONE 2 |
Definition at line 52 of file dsp.h.
Referenced by __ast_dsp_call_progress(), and dahdi_read().
#define DSP_TONE_STATE_HUNGUP 8 |
Definition at line 58 of file dsp.h.
Referenced by __ast_dsp_call_progress().
#define DSP_TONE_STATE_RINGING 1 |
Definition at line 51 of file dsp.h.
Referenced by __ast_dsp_call_progress(), and dahdi_read().
#define DSP_TONE_STATE_SILENCE 0 |
Definition at line 50 of file dsp.h.
Referenced by __ast_dsp_call_progress().
#define DSP_TONE_STATE_SPECIAL1 5 |
Definition at line 55 of file dsp.h.
Referenced by __ast_dsp_call_progress().
#define DSP_TONE_STATE_SPECIAL2 6 |
Definition at line 56 of file dsp.h.
Referenced by __ast_dsp_call_progress().
#define DSP_TONE_STATE_SPECIAL3 7 |
Definition at line 57 of file dsp.h.
Referenced by __ast_dsp_call_progress().
#define DSP_TONE_STATE_TALKING 3 |
Definition at line 53 of file dsp.h.
Referenced by __ast_dsp_call_progress().
enum threshold |
Definition at line 62 of file dsp.h.
{ /* Array offsets */ THRESHOLD_SILENCE = 0, /* Always the last */ THRESHOLD_MAX = 1, };
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 1187 of file dsp.c.
References ast_debug, BUSY_MAX, BUSY_MIN, BUSY_PAT_PERCENT, BUSY_PERCENT, ast_dsp::busy_quietlength, ast_dsp::busy_tonelength, ast_dsp::busycount, ast_dsp::busymaybe, DSP_HISTORY, ast_dsp::historicnoise, and ast_dsp::historicsilence.
Referenced by ast_dsp_process().
{ int res = 0, x; #ifndef BUSYDETECT_TONEONLY int avgsilence = 0, hitsilence = 0; #endif int avgtone = 0, hittone = 0; if (!dsp->busymaybe) { return res; } for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { #ifndef BUSYDETECT_TONEONLY avgsilence += dsp->historicsilence[x]; #endif avgtone += dsp->historicnoise[x]; } #ifndef BUSYDETECT_TONEONLY avgsilence /= dsp->busycount; #endif avgtone /= dsp->busycount; for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { #ifndef BUSYDETECT_TONEONLY if (avgsilence > dsp->historicsilence[x]) { if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) { hitsilence++; } } else { if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) { hitsilence++; } } #endif if (avgtone > dsp->historicnoise[x]) { if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) { hittone++; } } else { if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) { hittone++; } } } #ifndef BUSYDETECT_TONEONLY if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) { #else if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) { #endif #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE if (avgtone > avgsilence) { if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) { res = 1; } } else { if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) { res = 1; } } #else res = 1; #endif } /* If we know the expected busy tone length, check we are in the range */ if (res && (dsp->busy_tonelength > 0)) { if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) { #ifdef BUSYDETECT_DEBUG ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n", avgtone, dsp->busy_tonelength); #endif res = 0; } } #ifndef BUSYDETECT_TONEONLY /* If we know the expected busy tone silent-period length, check we are in the range */ if (res && (dsp->busy_quietlength > 0)) { if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) { #ifdef BUSYDETECT_DEBUG ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n", avgsilence, dsp->busy_quietlength); #endif res = 0; } } #endif #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG) if (res) { ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence); } else { ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence); } #endif return res; }
Scans for progress indication in audio.
Definition at line 1111 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, ast_frame::ptr, and ast_frame::subclass.
{ if (inf->frametype != AST_FRAME_VOICE) { ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); return 0; } if (inf->subclass != AST_FORMAT_SLINEAR) { ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); return 0; } return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2); }
Return non-zero if DTMF hit was found.
void ast_dsp_digitreset | ( | struct ast_dsp * | dsp | ) |
Reset DTMF detector.
Definition at line 1599 of file dsp.c.
References dtmf_detect_state_t::col_out, digit_detect_state_t::current_digits, dtmf_detect_state_t::current_hit, mf_detect_state_t::current_hit, dtmf_detect_state_t::current_sample, mf_detect_state_t::current_sample, ast_dsp::digit_state, ast_dsp::digitmode, digit_detect_state_t::digits, DSP_DIGITMODE_MF, digit_detect_state_t::dtmf, ast_dsp::dtmf_began, dtmf_detect_state_t::energy, goertzel_reset(), dtmf_detect_state_t::hits, mf_detect_state_t::hits, dtmf_detect_state_t::lasthit, digit_detect_state_t::mf, dtmf_detect_state_t::misses, dtmf_detect_state_t::row_out, s, digit_detect_state_t::td, and mf_detect_state_t::tone_out.
Referenced by ss_thread().
{ int i; dsp->dtmf_began = 0; if (dsp->digitmode & DSP_DIGITMODE_MF) { mf_detect_state_t *s = &dsp->digit_state.td.mf; /* Reinitialise the detector for the next block */ for (i = 0; i < 6; i++) { goertzel_reset(&s->tone_out[i]); } s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = s->current_hit = 0; s->current_sample = 0; } else { dtmf_detect_state_t *s = &dsp->digit_state.td.dtmf; /* Reinitialise the detector for the next block */ for (i = 0; i < 4; i++) { goertzel_reset(&s->row_out[i]); goertzel_reset(&s->col_out[i]); } s->lasthit = s->current_hit = 0; s->energy = 0.0; s->current_sample = 0; s->hits = 0; s->misses = 0; } dsp->digit_state.digits[0] = '\0'; dsp->digit_state.current_digits = 0; }
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.
Definition at line 1744 of file dsp.c.
References ast_clear_flag, ast_dsp_free(), AST_FRFLAG_FROM_DSP, ast_dsp::destroy, and f.
Referenced by __frame_free().
{ struct ast_dsp *dsp; ast_clear_flag(fr, AST_FRFLAG_FROM_DSP); dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f)); if (!dsp->destroy) return; ast_dsp_free(dsp); }
void ast_dsp_free | ( | struct ast_dsp * | dsp | ) |
Definition at line 1561 of file dsp.c.
References ast_free, AST_FRFLAG_FROM_DSP, ast_test_flag, ast_dsp::destroy, and ast_dsp::f.
Referenced by __ast_play_and_record(), __oh323_destroy(), ast_dsp_frame_freed(), background_detect_exec(), cl_dequeue_chan(), cleanup_connection(), conf_run(), dahdi_hangup(), destroy_endpoint(), do_waiting(), handle_recordfile(), isAnsweringMachine(), mgcp_hangup(), record_exec(), sip_dtmfmode(), sip_hangup(), sip_rtp_read(), ss_thread(), and unload_module().
{ if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) { /* If this flag is still set, that means that the dsp's destruction * been torn down, while we still have a frame out there being used. * When ast_frfree() gets called on that frame, this ast_trans_pvt * will get destroyed, too. */ dsp->destroy = 1; return; } ast_free(dsp); }
int ast_dsp_get_tcount | ( | struct ast_dsp * | dsp | ) |
Get tcount (Threshold counter)
Definition at line 1692 of file dsp.c.
References ast_dsp::tcount.
Referenced by dahdi_read().
{ return dsp->tcount; }
int ast_dsp_get_threshold_from_settings | ( | enum threshold | which | ) |
Get silence threshold from dsp.conf.
Definition at line 1729 of file dsp.c.
Referenced by app_exec(), ast_record_review(), conf_run(), do_waiting(), handle_recordfile(), load_config(), record_exec(), and setup_privacy_args().
{ return thresholds[which]; }
int ast_dsp_get_tstate | ( | struct ast_dsp * | dsp | ) |
Get tstate (Tone State)
Definition at line 1687 of file dsp.c.
References ast_dsp::tstate.
Referenced by dahdi_read().
{ return dsp->tstate; }
int ast_dsp_getdigits | ( | struct ast_dsp * | dsp, |
char * | buf, | ||
int | max | ||
) |
Get pending DTMF/MF digits.
int ast_dsp_init | ( | void | ) |
Load dsp settings from dsp.conf.
Definition at line 1734 of file dsp.c.
References _dsp_init().
Referenced by main().
{ return _dsp_init(0); }
struct ast_dsp* ast_dsp_new | ( | void | ) | [read] |
Definition at line 1535 of file dsp.c.
References ast_calloc, ast_digit_detect_init(), ast_dsp_prog_reset(), ast_fax_detect_init(), ast_dsp::busycount, DEFAULT_THRESHOLD, ast_dsp::digit_state, ast_dsp::digitmode, ast_dsp::display_inband_dtmf_warning, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::faxmode, ast_dsp::features, 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(), record_exec(), sip_dtmfmode(), sip_new(), and store_config().
{ struct ast_dsp *dsp; if ((dsp = ast_calloc(1, sizeof(*dsp)))) { dsp->threshold = DEFAULT_THRESHOLD; dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; dsp->busycount = DSP_HISTORY; dsp->digitmode = DSP_DIGITMODE_DTMF; dsp->faxmode = DSP_FAXMODE_DETECT_CNG; /* Initialize digit detector */ ast_digit_detect_init(&dsp->digit_state, dsp->digitmode & DSP_DIGITMODE_MF); dsp->display_inband_dtmf_warning = 1; /* Initialize initial DSP progress detect parameters */ ast_dsp_prog_reset(dsp); /* Initialize fax detector */ ast_fax_detect_init(dsp); } return dsp; }
Return non-zero if this is noise. Updates "totalnoise" with the total number of seconds of noise.
Definition at line 1300 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, s, and ast_frame::subclass.
Referenced by do_waiting().
{ short *s; int len; if (f->frametype != AST_FRAME_VOICE) { ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n"); return 0; } if (f->subclass != AST_FORMAT_SLINEAR) { ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n"); return 0; } s = f->data.ptr; len = f->datalen/2; return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise); }
struct ast_frame* ast_dsp_process | ( | struct ast_channel * | chan, |
struct ast_dsp * | dsp, | ||
struct ast_frame * | inf | ||
) | [read] |
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress, all dependent upon which features are enabled.
Definition at line 1319 of file dsp.c.
References __ast_dsp_call_progress(), __ast_dsp_silence_noise(), 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_LIN2A, AST_LIN2MU, ast_log(), AST_MULAW, ast_queue_frame(), ast_set_flag, AST_SOFTHANGUP_DEV, ast_dsp::ced_tone_state, ast_dsp::cng_tone_state, digit_detect_state_t::current_digits, ast_frame::data, ast_frame::datalen, ast_dsp::digit_state, digit_detect_state_t::digitlen, ast_dsp::digitmode, digit_detect_state_t::digits, ast_dsp::display_inband_dtmf_warning, DSP_DIGITMODE_MF, DSP_DIGITMODE_NOQUELCH, DSP_DIGITMODE_RELAXDTMF, DSP_FAXMODE_DETECT_CED, DSP_FAXMODE_DETECT_CNG, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_SILENCE_SUPPRESS, DSP_FEATURE_WAITDIALTONE, ast_dsp::dtmf_began, dtmf_detect(), fragment_t::end, ast_dsp::f, ast_dsp::faxmode, ast_dsp::features, ast_frame::frametype, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_frame::len, len(), LOG_WARNING, mf_detect(), ast_dsp::mute_data, ast_dsp::mute_fragments, ast_channel::name, ast_frame::ptr, SAMPLE_RATE, ast_frame::src, fragment_t::start, ast_frame::subclass, and tone_detect().
Referenced by dahdi_read(), mgcp_rtp_read(), oh323_rtp_read(), process_ast_dsp(), sip_rtp_read(), and usbradio_read().
{ int silence; int res; int digit = 0, fax_digit = 0; int x; short *shortdata; unsigned char *odata; int len; struct ast_frame *outf = NULL; if (!af) { return NULL; } if (af->frametype != AST_FRAME_VOICE) { return af; } odata = af->data.ptr; len = af->datalen; /* Make sure we have short data */ switch (af->subclass) { case AST_FORMAT_SLINEAR: shortdata = af->data.ptr; len = af->datalen / 2; break; case AST_FORMAT_ULAW: shortdata = alloca(af->datalen * 2); for (x = 0;x < len; x++) { shortdata[x] = AST_MULAW(odata[x]); } break; case AST_FORMAT_ALAW: shortdata = alloca(af->datalen * 2); for (x = 0; x < len; x++) { shortdata[x] = AST_ALAW(odata[x]); } break; default: /*Display warning only once. Otherwise you would get hundreds of warnings every second */ if (dsp->display_inband_dtmf_warning) ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); dsp->display_inband_dtmf_warning = 0; return af; } /* Initially we do not want to mute anything */ dsp->mute_fragments = 0; /* Need to run the silence detection stuff for silence suppression and busy detection */ if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) { res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL); } if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { memset(&dsp->f, 0, sizeof(dsp->f)); dsp->f.frametype = AST_FRAME_NULL; ast_frfree(af); ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); return &dsp->f; } if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { chan->_softhangup |= AST_SOFTHANGUP_DEV; memset(&dsp->f, 0, sizeof(dsp->f)); dsp->f.frametype = AST_FRAME_CONTROL; dsp->f.subclass = AST_CONTROL_BUSY; ast_frfree(af); ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP); return &dsp->f; } if ((dsp->features & DSP_FEATURE_FAX_DETECT)) { if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) { fax_digit = 'f'; } if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) { fax_digit = 'e'; } } if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) { if (dsp->digitmode & DSP_DIGITMODE_MF) digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); else digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); if (dsp->digit_state.current_digits) { int event = 0, event_len = 0; char event_digit = 0; if (!dsp->dtmf_began) { /* We have not reported DTMF_BEGIN for anything yet */ if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { event = AST_FRAME_DTMF_BEGIN; event_digit = dsp->digit_state.digits[0]; } dsp->dtmf_began = 1; } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) { /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */ if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { event = AST_FRAME_DTMF_END; event_digit = dsp->digit_state.digits[0]; event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE; } memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits); memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0])); dsp->digit_state.current_digits--; dsp->dtmf_began = 0; if (dsp->features & DSP_FEATURE_BUSY_DETECT) { /* Reset Busy Detector as we have some confirmed activity */ memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); ast_debug(1, "DTMF Detected - Reset busydetector\n"); } } if (event) { memset(&dsp->f, 0, sizeof(dsp->f)); dsp->f.frametype = event; dsp->f.subclass = event_digit; dsp->f.len = event_len; outf = &dsp->f; goto done; } } } if (fax_digit) { /* Fax was detected - digit is either 'f' or 'e' */ memset(&dsp->f, 0, sizeof(dsp->f)); dsp->f.frametype = AST_FRAME_DTMF; dsp->f.subclass = fax_digit; outf = &dsp->f; goto done; } if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { res = __ast_dsp_call_progress(dsp, shortdata, len); if (res) { switch (res) { case AST_CONTROL_ANSWER: case AST_CONTROL_BUSY: case AST_CONTROL_RINGING: case AST_CONTROL_CONGESTION: case AST_CONTROL_HANGUP: memset(&dsp->f, 0, sizeof(dsp->f)); dsp->f.frametype = AST_FRAME_CONTROL; dsp->f.subclass = res; dsp->f.src = "dsp_progress"; if (chan) ast_queue_frame(chan, &dsp->f); break; default: ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); } } } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) { res = __ast_dsp_call_progress(dsp, shortdata, len); } done: /* Mute fragment of the frame */ for (x = 0; x < dsp->mute_fragments; x++) { memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start)); } switch (af->subclass) { case AST_FORMAT_SLINEAR: break; case AST_FORMAT_ULAW: for (x = 0; x < len; x++) { odata[x] = AST_LIN2MU((unsigned short) shortdata[x]); } break; case AST_FORMAT_ALAW: for (x = 0; x < len; x++) { odata[x] = AST_LIN2A((unsigned short) shortdata[x]); } break; } if (outf) { if (chan) { ast_queue_frame(chan, af); } ast_frfree(af); ast_set_flag(outf, AST_FRFLAG_FROM_DSP); return outf; } else { return af; } }
int ast_dsp_reload | ( | void | ) |
Reloads dsp settings from dsp.conf.
Definition at line 1739 of file dsp.c.
References _dsp_init().
{ return _dsp_init(1); }
void ast_dsp_reset | ( | struct ast_dsp * | dsp | ) |
Reset total silence count.
Definition at line 1630 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.
{ int x; dsp->totalsilence = 0; dsp->gsamps = 0; for (x = 0; x < 4; x++) { dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; } memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); dsp->ringtimeout= 0; }
void ast_dsp_set_busy_count | ( | struct ast_dsp * | dsp, |
int | cadences | ||
) |
Set number of required cadences for busy.
Definition at line 1581 of file dsp.c.
References ast_dsp::busycount, cadences, and DSP_HISTORY.
Referenced by dahdi_new().
{ if (cadences < 4) { cadences = 4; } if (cadences > DSP_HISTORY) { cadences = DSP_HISTORY; } dsp->busycount = cadences; }
void ast_dsp_set_busy_pattern | ( | struct ast_dsp * | dsp, |
int | tonelength, | ||
int | quietlength | ||
) |
Set expected lengths of the busy tone.
Definition at line 1592 of file dsp.c.
References ast_debug, ast_dsp::busy_quietlength, and ast_dsp::busy_tonelength.
Referenced by dahdi_new().
{ dsp->busy_tonelength = tonelength; dsp->busy_quietlength = quietlength; ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); }
int ast_dsp_set_call_progress_zone | ( | struct ast_dsp * | dsp, |
char * | zone | ||
) |
Set zone for doing progress detection.
Definition at line 1668 of file dsp.c.
References aliases, ARRAY_LEN, ast_dsp_prog_reset(), progalias::mode, name, and ast_dsp::progmode.
Referenced by dahdi_new().
int ast_dsp_set_digitmode | ( | struct ast_dsp * | dsp, |
int | digitmode | ||
) |
Set digit mode.
Definition at line 1644 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(), mkintf(), sip_new(), ss_thread(), and store_config().
{ int new; int old; old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); if (old != new) { /* Must initialize structures if switching from MF to DTMF or vice-versa */ ast_digit_detect_init(&dsp->digit_state, new & DSP_DIGITMODE_MF); } dsp->digitmode = digitmode; return 0; }
int ast_dsp_set_faxmode | ( | struct ast_dsp * | dsp, |
int | faxmode | ||
) |
Set fax mode.
Definition at line 1659 of file dsp.c.
References ast_fax_detect_init(), and ast_dsp::faxmode.
{ if (dsp->faxmode != faxmode) { ast_fax_detect_init(dsp); } dsp->faxmode = faxmode; return 0; }
void ast_dsp_set_features | ( | struct ast_dsp * | dsp, |
int | features | ||
) |
Select feature set.
Definition at line 1556 of file dsp.c.
References ast_dsp::features.
Referenced by __oh323_new(), dahdi_new(), dahdi_read(), disable_dtmf_detect(), enable_dtmf_detect(), mgcp_new(), misdn_set_opt_exec(), read_config(), sip_dtmfmode(), sip_new(), sip_rtp_read(), and store_config().
{ dsp->features = features; }
void ast_dsp_set_threshold | ( | struct ast_dsp * | dsp, |
int | threshold | ||
) |
Set threshold value for silence.
Definition at line 1576 of file dsp.c.
References ast_dsp::threshold.
Referenced by __ast_play_and_record(), do_waiting(), handle_recordfile(), isAnsweringMachine(), and record_exec().
Return non-zero if this is silence. Updates "totalsilence" with the total number of seconds of silence.
Definition at line 1282 of file dsp.c.
References __ast_dsp_silence_noise(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, len(), LOG_WARNING, ast_frame::ptr, s, and ast_frame::subclass.
Referenced by __ast_play_and_record(), background_detect_exec(), conf_run(), do_waiting(), handle_recordfile(), isAnsweringMachine(), and record_exec().
{ short *s; int len; if (f->frametype != AST_FRAME_VOICE) { ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); return 0; } if (f->subclass != AST_FORMAT_SLINEAR) { ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); return 0; } s = f->data.ptr; len = f->datalen/2; return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL); }
int ast_dsp_was_muted | ( | struct ast_dsp * | dsp | ) |
Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) happens when DSP code removes DTMF/MF/generic tones from the audio.
Definition at line 1682 of file dsp.c.
References ast_dsp::mute_fragments.
Referenced by dahdi_read().
{ return (dsp->mute_fragments > 0); }