Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

dsp.h File Reference

Go to the source code of this file.

Defines

#define DSP_FEATURE_SILENCE_SUPPRESS   (1 << 0)
#define DSP_FEATURE_BUSY_DETECT   (1 << 1)
#define DSP_FEATURE_CALL_PROGRESS   (1 << 2)
#define DSP_FEATURE_DTMF_DETECT   (1 << 3)
#define DSP_FEATURE_FAX_DETECT   (1 << 4)
#define DSP_DIGITMODE_DTMF   0
#define DSP_DIGITMODE_MF   1
#define DSP_DIGITMODE_NOQUELCH   (1 << 8)
#define DSP_DIGITMODE_MUTECONF   (1 << 9)
#define DSP_DIGITMODE_MUTEMAX   (1 << 10)
#define DSP_DIGITMODE_RELAXDTMF   (1 << 11)

Functions

ast_dspast_dsp_new (void)
void ast_dsp_free (struct ast_dsp *dsp)
void ast_dsp_set_threshold (struct ast_dsp *dsp, int threshold)
void ast_dsp_set_busy_count (struct ast_dsp *dsp, int cadences)
int ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf)
int ast_dsp_set_call_progress_zone (struct ast_dsp *dsp, char *zone)
ast_frameast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
int ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
int ast_dsp_busydetect (struct ast_dsp *dsp)
int ast_dsp_digitdetect (struct ast_dsp *dsp, struct ast_frame *f)
void ast_dsp_reset (struct ast_dsp *dsp)
void ast_dsp_digitreset (struct ast_dsp *dsp)
void ast_dsp_set_features (struct ast_dsp *dsp, int features)
int ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
int ast_dsp_digitmode (struct ast_dsp *dsp, int digitmode)


Define Documentation

#define DSP_DIGITMODE_DTMF   0
 

Definition at line 23 of file dsp.h.

Referenced by ast_dsp_digitmode().

#define DSP_DIGITMODE_MF   1
 

Definition at line 24 of file dsp.h.

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

#define DSP_DIGITMODE_MUTECONF   (1 << 9)
 

Definition at line 27 of file dsp.h.

Referenced by ast_dsp_digitmode(), and ast_dsp_process().

#define DSP_DIGITMODE_MUTEMAX   (1 << 10)
 

Definition at line 28 of file dsp.h.

Referenced by ast_dsp_digitmode(), and ast_dsp_process().

#define DSP_DIGITMODE_NOQUELCH   (1 << 8)
 

Definition at line 26 of file dsp.h.

#define DSP_DIGITMODE_RELAXDTMF   (1 << 11)
 

Definition at line 29 of file dsp.h.

#define DSP_FEATURE_BUSY_DETECT   (1 << 1)
 

Definition at line 18 of file dsp.h.

Referenced by ast_dsp_process().

#define DSP_FEATURE_CALL_PROGRESS   (1 << 2)
 

Definition at line 19 of file dsp.h.

Referenced by ast_dsp_process().

#define DSP_FEATURE_DTMF_DETECT   (1 << 3)
 

Definition at line 20 of file dsp.h.

Referenced by ast_dsp_process().

#define DSP_FEATURE_FAX_DETECT   (1 << 4)
 

Definition at line 21 of file dsp.h.

#define DSP_FEATURE_SILENCE_SUPPRESS   (1 << 0)
 

Definition at line 17 of file dsp.h.

Referenced by ast_dsp_new(), and ast_dsp_process().


Function Documentation

int ast_dsp_busydetect struct ast_dsp   dsp
 

Referenced by ast_dsp_process().

int ast_dsp_call_progress struct ast_dsp   dsp,
struct ast_frame   inf
 

Definition at line 1213 of file dsp.c.

References ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass.

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

int ast_dsp_digitdetect struct ast_dsp   dsp,
struct ast_frame   f
 

Definition at line 1047 of file dsp.c.

References ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass.

01048 {
01049    short *s;
01050    int len;
01051    int ign=0;
01052    if (inf->frametype != AST_FRAME_VOICE) {
01053       ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
01054       return 0;
01055    }
01056    if (inf->subclass != AST_FORMAT_SLINEAR) {
01057       ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
01058       return 0;
01059    }
01060    s = inf->data;
01061    len = inf->datalen / 2;
01062    return __ast_dsp_digitdetect(dsp, s, len, &ign);
01063 }

int ast_dsp_digitmode struct ast_dsp   dsp,
int    digitmode
 

Definition at line 1717 of file dsp.c.

References ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, and ast_dsp::td.

01718 {
01719    int new, old;
01720    old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01721    new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
01722    if (old != new) {
01723       /* Must initialize structures if switching from MF to DTMF or vice-versa */
01724       if (new & DSP_DIGITMODE_MF)
01725          ast_mf_detect_init(&dsp->td.mf);
01726       else
01727          ast_dtmf_detect_init(&dsp->td.dtmf);
01728    }
01729    dsp->digitmode = digitmode;
01730    return 0;
01731 }

void ast_dsp_digitreset struct ast_dsp   dsp
 

Definition at line 1656 of file dsp.c.

References ast_dsp::digitmode, DSP_DIGITMODE_MF, ast_dsp::td, and ast_dsp::thinkdigit.

01657 {
01658    int i;
01659    dsp->thinkdigit = 0;
01660    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01661       memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
01662       dsp->td.mf.current_digits = 0;
01663       /* Reinitialise the detector for the next block */
01664       for (i = 0;  i < 6;  i++) {
01665             goertzel_reset(&dsp->td.mf.tone_out[i]);
01666 #ifdef OLD_DSP_ROUTINES
01667           goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
01668 #endif         
01669       }
01670 #ifdef OLD_DSP_ROUTINES
01671       dsp->td.mf.energy = 0.0;
01672        dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
01673 #else
01674        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;
01675 #endif      
01676       dsp->td.mf.current_sample = 0;
01677    } else {
01678       memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
01679       dsp->td.dtmf.current_digits = 0;
01680       /* Reinitialise the detector for the next block */
01681       for (i = 0;  i < 4;  i++) {
01682             goertzel_reset(&dsp->td.dtmf.row_out[i]);
01683           goertzel_reset(&dsp->td.dtmf.col_out[i]);
01684 #ifdef OLD_DSP_ROUTINES
01685          goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
01686          goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
01687 #endif         
01688       }
01689 #ifdef FAX_DETECT
01690        goertzel_reset (&dsp->td.dtmf.fax_tone);
01691 #endif
01692 #ifdef OLD_DSP_ROUTINES
01693 #ifdef FAX_DETECT
01694        goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
01695 #endif
01696        dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
01697 #else
01698        dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] =  dsp->td.dtmf.mhit = 0;
01699 #endif      
01700       dsp->td.dtmf.energy = 0.0;
01701       dsp->td.dtmf.current_sample = 0;
01702    }
01703 }

void ast_dsp_free struct ast_dsp   dsp
 

Definition at line 1637 of file dsp.c.

References free.

Referenced by ast_app_getvoice().

01638 {
01639    free(dsp);
01640 }

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

Definition at line 1085 of file dsp.c.

References ast_dsp::digitmode, DSP_DIGITMODE_MF, and ast_dsp::td.

01088 {
01089    if (dsp->digitmode & DSP_DIGITMODE_MF) {
01090        if (max > dsp->td.mf.current_digits)
01091            max = dsp->td.mf.current_digits;
01092        if (max > 0)
01093        {
01094            memcpy (buf, dsp->td.mf.digits, max);
01095            memmove (dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
01096            dsp->td.mf.current_digits -= max;
01097        }
01098        buf[max] = '\0';
01099        return  max;
01100    } else {
01101        if (max > dsp->td.dtmf.current_digits)
01102            max = dsp->td.dtmf.current_digits;
01103        if (max > 0)
01104        {
01105            memcpy (buf, dsp->td.dtmf.digits, max);
01106            memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
01107            dsp->td.dtmf.current_digits -= max;
01108        }
01109        buf[max] = '\0';
01110        return  max;
01111    }
01112 }

struct ast_dsp* ast_dsp_new void   
 

Definition at line 1615 of file dsp.c.

References ast_dsp::busycount, DEFAULT_THRESHOLD, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::features, malloc, ast_dsp::td, and ast_dsp::threshold.

Referenced by ast_app_getvoice(), ast_play_and_prepend(), and ast_play_and_record().

01616 {
01617    struct ast_dsp *dsp;
01618    dsp = malloc(sizeof(struct ast_dsp));
01619    if (dsp) {
01620       memset(dsp, 0, sizeof(struct ast_dsp));
01621       dsp->threshold = DEFAULT_THRESHOLD;
01622       dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
01623       dsp->busycount = DSP_HISTORY;
01624       /* Initialize DTMF detector */
01625       ast_dtmf_detect_init(&dsp->td.dtmf);
01626       /* Initialize initial DSP progress detect parameters */
01627       ast_dsp_prog_reset(dsp);
01628    }
01629    return dsp;
01630 }

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

Definition at line 1409 of file dsp.c.

References AST_ALAW, ast_codec2str(), ast_dsp_busydetect(), ast_frfree(), ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_frame::data, ast_frame::datalen, 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_frame::frametype, LOG_DEBUG, LOG_WARNING, and ast_frame::subclass.

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

void ast_dsp_reset struct ast_dsp   dsp
 

Definition at line 1705 of file dsp.c.

References ast_dsp::freqs, ast_dsp::gsamps, ast_dsp::historicnoise, ast_dsp::historicsilence, ast_dsp::totalsilence, goertzel_state_t::v2, and goertzel_state_t::v3.

01706 {
01707    int x;
01708    dsp->totalsilence = 0;
01709    dsp->gsamps = 0;
01710    for (x=0;x<4;x++)
01711       dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
01712    memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
01713    memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
01714    
01715 }

void ast_dsp_set_busy_count struct ast_dsp   dsp,
int    cadences
 

Definition at line 1647 of file dsp.c.

References ast_dsp::busycount, and DSP_HISTORY.

01648 {
01649    if (cadences < 4)
01650       cadences = 4;
01651    if (cadences > DSP_HISTORY)
01652       cadences = DSP_HISTORY;
01653    dsp->busycount = cadences;
01654 }

int ast_dsp_set_call_progress_zone struct ast_dsp   dsp,
char *    zone
 

Definition at line 1733 of file dsp.c.

References ast_dsp::progmode.

01734 {
01735    int x;
01736    for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
01737       if (!strcasecmp(aliases[x].name, zone)) {
01738          dsp->progmode = aliases[x].mode;
01739          ast_dsp_prog_reset(dsp);
01740          return 0;
01741       }
01742    }
01743    return -1;
01744 }

void ast_dsp_set_features struct ast_dsp   dsp,
int    features
 

Definition at line 1632 of file dsp.c.

References ast_dsp::features.

01633 {
01634    dsp->features = features;
01635 }

void ast_dsp_set_threshold struct ast_dsp   dsp,
int    threshold
 

Definition at line 1642 of file dsp.c.

References ast_dsp::threshold.

Referenced by ast_play_and_prepend(), and ast_play_and_record().

01643 {
01644    dsp->threshold = threshold;
01645 }

int ast_dsp_silence struct ast_dsp   dsp,
struct ast_frame   f,
int *    totalsilence
 

Definition at line 1391 of file dsp.c.

References ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass.

Referenced by ast_app_getvoice(), ast_play_and_prepend(), and ast_play_and_record().

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


Generated on Thu Oct 28 11:33:02 2004 for Asterisk by doxygen1.2.15