#include <sys/types.h>
#include <asterisk/frame.h>
#include <asterisk/channel.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/logger.h>
#include <asterisk/dsp.h>
#include <asterisk/ulaw.h>
#include <asterisk/alaw.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <stdio.h>
Go to the source code of this file.
Data Structures | |
struct | ast_dsp |
struct | dtmf_detect_state_t |
struct | goertzel_state_t |
struct | mf_detect_state_t |
Defines | |
#define | DEFAULT_THRESHOLD 1024 |
#define | BUSY_PERCENT 10 |
#define | BUSY_THRESHOLD 100 |
#define | BUSY_MIN 75 |
#define | BUSY_MAX 1100 |
#define | DSP_HISTORY 15 |
#define | GSAMP_SIZE 183 |
#define | HZ_350 0 |
#define | HZ_440 1 |
#define | HZ_480 2 |
#define | HZ_620 3 |
#define | HZ_950 4 |
#define | HZ_1400 5 |
#define | HZ_1800 6 |
#define | TONE_THRESH 10.0 |
#define | TONE_MIN_THRESH 1e8 |
#define | COUNT_THRESH 3 |
#define | TONE_STATE_SILENCE 0 |
#define | TONE_STATE_RINGING 1 |
#define | TONE_STATE_DIALTONE 2 |
#define | TONE_STATE_TALKING 3 |
#define | TONE_STATE_BUSY 4 |
#define | TONE_STATE_SPECIAL1 5 |
#define | TONE_STATE_SPECIAL2 6 |
#define | TONE_STATE_SPECIAL3 7 |
#define | MAX_DTMF_DIGITS 128 |
#define | DTMF_THRESHOLD 8.0e7 |
#define | FAX_THRESHOLD 8.0e7 |
#define | FAX_2ND_HARMONIC 2.0 |
#define | DTMF_NORMAL_TWIST 6.3 |
#define | DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5) |
#define | DTMF_RELATIVE_PEAK_ROW 6.3 |
#define | DTMF_RELATIVE_PEAK_COL 6.3 |
#define | DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) |
#define | DTMF_2ND_HARMONIC_COL 63.1 |
#define | DTMF_TO_TOTAL_ENERGY 42.0 |
#define | BELL_MF_THRESHOLD 1.6e9 |
#define | BELL_MF_TWIST 4.0 |
#define | BELL_MF_RELATIVE_PEAK 12.6 |
#define | MF_GSIZE 120 |
#define | FIX_INF(inf) |
Functions | |
int | ast_dsp_digitdetect (struct ast_dsp *dsp, struct ast_frame *inf) |
int | ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max) |
int | ast_dsp_call_progress (struct ast_dsp *dsp, struct ast_frame *inf) |
int | ast_dsp_silence (struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence) |
ast_frame * | ast_dsp_process (struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af, int needlock) |
ast_dsp * | ast_dsp_new (void) |
void | ast_dsp_set_features (struct ast_dsp *dsp, int features) |
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) |
void | ast_dsp_digitreset (struct ast_dsp *dsp) |
void | ast_dsp_reset (struct ast_dsp *dsp) |
int | ast_dsp_digitmode (struct ast_dsp *dsp, int digitmode) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 46 of file dsp.c. Referenced by ast_dsp_new(). |
|
Definition at line 54 of file dsp.c. Referenced by ast_dsp_new(), and ast_dsp_set_busy_count(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Referenced by ast_dsp_process(). |
|
Definition at line 57 of file dsp.c. Referenced by ast_dsp_new(). |
|
Definition at line 64 of file dsp.c. Referenced by ast_dsp_new(). |
|
Definition at line 65 of file dsp.c. Referenced by ast_dsp_new(). |
|
Definition at line 59 of file dsp.c. Referenced by ast_dsp_new(). |
|
Definition at line 60 of file dsp.c. Referenced by ast_dsp_new(). |
|
Definition at line 61 of file dsp.c. Referenced by ast_dsp_new(). |
|
Definition at line 62 of file dsp.c. Referenced by ast_dsp_new(). |
|
Definition at line 63 of file dsp.c. Referenced by ast_dsp_new(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 1172 of file dsp.c. References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, and ast_frame::subclass.
01173 { 01174 if (inf->frametype != AST_FRAME_VOICE) { 01175 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01176 return 0; 01177 } 01178 if (inf->subclass != AST_FORMAT_SLINEAR) { 01179 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01180 return 0; 01181 } 01182 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2); 01183 } |
|
Definition at line 1004 of file dsp.c. References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass.
01005 { 01006 short *s; 01007 int len; 01008 int ign=0; 01009 if (inf->frametype != AST_FRAME_VOICE) { 01010 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n"); 01011 return 0; 01012 } 01013 if (inf->subclass != AST_FORMAT_SLINEAR) { 01014 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n"); 01015 return 0; 01016 } 01017 s = inf->data; 01018 len = inf->datalen / 2; 01019 return __ast_dsp_digitdetect(dsp, s, len, &ign); 01020 } |
|
Definition at line 1660 of file dsp.c. References ast_dsp::digitmode, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, and ast_dsp::td.
01661 { 01662 int new, old; 01663 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01664 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX); 01665 if (old != new) { 01666 /* Must initialize structures if switching from MF to DTMF or vice-versa */ 01667 if (new & DSP_DIGITMODE_MF) 01668 ast_mf_detect_init(&dsp->td.mf); 01669 else 01670 ast_dtmf_detect_init(&dsp->td.dtmf); 01671 } 01672 dsp->digitmode = digitmode; 01673 return 0; 01674 } |
|
Definition at line 1603 of file dsp.c. References ast_dsp::digitmode, DSP_DIGITMODE_MF, ast_dsp::td, and ast_dsp::thinkdigit.
01604 { 01605 int i; 01606 dsp->thinkdigit = 0; 01607 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01608 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits)); 01609 dsp->td.mf.current_digits = 0; 01610 /* Reinitialise the detector for the next block */ 01611 for (i = 0; i < 6; i++) { 01612 goertzel_reset(&dsp->td.mf.tone_out[i]); 01613 #ifdef OLD_DSP_ROUTINES 01614 goertzel_reset(&dsp->td.mf.tone_out2nd[i]); 01615 #endif 01616 } 01617 #ifdef OLD_DSP_ROUTINES 01618 dsp->td.mf.energy = 0.0; 01619 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0; 01620 #else 01621 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; 01622 #endif 01623 dsp->td.mf.current_sample = 0; 01624 } else { 01625 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits)); 01626 dsp->td.dtmf.current_digits = 0; 01627 /* Reinitialise the detector for the next block */ 01628 for (i = 0; i < 4; i++) { 01629 goertzel_reset(&dsp->td.dtmf.row_out[i]); 01630 goertzel_reset(&dsp->td.dtmf.col_out[i]); 01631 #ifdef OLD_DSP_ROUTINES 01632 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]); 01633 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]); 01634 #endif 01635 } 01636 goertzel_reset (&dsp->td.dtmf.fax_tone); 01637 #ifdef OLD_DSP_ROUTINES 01638 goertzel_reset (&dsp->td.dtmf.fax_tone2nd); 01639 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0; 01640 #else 01641 dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] = dsp->td.dtmf.mhit = 0; 01642 #endif 01643 dsp->td.dtmf.energy = 0.0; 01644 dsp->td.dtmf.current_sample = 0; 01645 } 01646 } |
|
Definition at line 1584 of file dsp.c. References free. Referenced by ast_app_getvoice().
01585 { 01586 free(dsp); 01587 } |
|
Definition at line 1042 of file dsp.c. References ast_dsp::digitmode, DSP_DIGITMODE_MF, and ast_dsp::td.
01045 { 01046 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01047 if (max > dsp->td.mf.current_digits) 01048 max = dsp->td.mf.current_digits; 01049 if (max > 0) 01050 { 01051 memcpy (buf, dsp->td.mf.digits, max); 01052 memmove (dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max); 01053 dsp->td.mf.current_digits -= max; 01054 } 01055 buf[max] = '\0'; 01056 return max; 01057 } else { 01058 if (max > dsp->td.dtmf.current_digits) 01059 max = dsp->td.dtmf.current_digits; 01060 if (max > 0) 01061 { 01062 memcpy (buf, dsp->td.dtmf.digits, max); 01063 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max); 01064 dsp->td.dtmf.current_digits -= max; 01065 } 01066 buf[max] = '\0'; 01067 return max; 01068 } 01069 } |
|
Definition at line 1556 of file dsp.c. References ast_dsp::busycount, DEFAULT_THRESHOLD, DSP_FEATURE_SILENCE_SUPPRESS, DSP_HISTORY, ast_dsp::features, ast_dsp::freqs, GSAMP_SIZE, HZ_1400, HZ_1800, HZ_350, HZ_440, HZ_480, HZ_620, HZ_950, malloc, ast_dsp::td, and ast_dsp::threshold. Referenced by ast_app_getvoice().
01557 { 01558 struct ast_dsp *dsp; 01559 dsp = malloc(sizeof(struct ast_dsp)); 01560 if (dsp) { 01561 memset(dsp, 0, sizeof(struct ast_dsp)); 01562 dsp->threshold = DEFAULT_THRESHOLD; 01563 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS; 01564 dsp->busycount = DSP_HISTORY; 01565 /* Initialize goertzels */ 01566 goertzel_init(&dsp->freqs[HZ_350], 350.0, GSAMP_SIZE); 01567 goertzel_init(&dsp->freqs[HZ_440], 440.0, GSAMP_SIZE); 01568 goertzel_init(&dsp->freqs[HZ_480], 480.0, GSAMP_SIZE); 01569 goertzel_init(&dsp->freqs[HZ_620], 620.0, GSAMP_SIZE); 01570 goertzel_init(&dsp->freqs[HZ_950], 950.0, GSAMP_SIZE); 01571 goertzel_init(&dsp->freqs[HZ_1400], 1400.0, GSAMP_SIZE); 01572 goertzel_init(&dsp->freqs[HZ_1800], 1800.0, GSAMP_SIZE); 01573 /* Initialize DTMF detector */ 01574 ast_dtmf_detect_init(&dsp->td.dtmf); 01575 } 01576 return dsp; 01577 } |
|
Definition at line 1365 of file dsp.c. References ast_channel::_softhangup, AST_ALAW, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_RINGING, ast_dsp_busydetect(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), ast_log(), AST_MULAW, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_frame::data, ast_frame::datalen, ast_dsp::digitmode, 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::f, ast_dsp::features, FIX_INF, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_frame::subclass, ast_dsp::td, and ast_dsp::thinkdigit.
01366 { 01367 int silence; 01368 int res; 01369 int digit; 01370 int x; 01371 unsigned short *shortdata; 01372 unsigned char *odata; 01373 int len; 01374 int writeback = 0; 01375 01376 #define FIX_INF(inf) do { \ 01377 if (writeback) { \ 01378 switch(inf->subclass) { \ 01379 case AST_FORMAT_SLINEAR: \ 01380 break; \ 01381 case AST_FORMAT_ULAW: \ 01382 for (x=0;x<len;x++) \ 01383 odata[x] = AST_LIN2MU(shortdata[x]); \ 01384 break; \ 01385 case AST_FORMAT_ALAW: \ 01386 for (x=0;x<len;x++) \ 01387 odata[x] = AST_LIN2A(shortdata[x]); \ 01388 break; \ 01389 } \ 01390 } \ 01391 } while(0) 01392 01393 if (!af) 01394 return NULL; 01395 if (af->frametype != AST_FRAME_VOICE) 01396 return af; 01397 odata = af->data; 01398 len = af->datalen; 01399 /* Make sure we have short data */ 01400 switch(af->subclass) { 01401 case AST_FORMAT_SLINEAR: 01402 shortdata = af->data; 01403 len = af->datalen / 2; 01404 break; 01405 case AST_FORMAT_ULAW: 01406 shortdata = alloca(af->datalen * 2); 01407 if (!shortdata) { 01408 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01409 return af; 01410 } 01411 for (x=0;x<len;x++) 01412 shortdata[x] = AST_MULAW(odata[x]); 01413 break; 01414 case AST_FORMAT_ALAW: 01415 shortdata = alloca(af->datalen * 2); 01416 if (!shortdata) { 01417 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno)); 01418 return af; 01419 } 01420 for (x=0;x<len;x++) 01421 shortdata[x] = AST_ALAW(odata[x]); 01422 break; 01423 default: 01424 ast_log(LOG_WARNING, "Unable to process inband DTMF on %d frames\n", af->subclass); 01425 return af; 01426 } 01427 silence = __ast_dsp_silence(dsp, shortdata, len, NULL); 01428 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { 01429 memset(&dsp->f, 0, sizeof(dsp->f)); 01430 dsp->f.frametype = AST_FRAME_NULL; 01431 return &dsp->f; 01432 } 01433 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { 01434 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01435 memset(&dsp->f, 0, sizeof(dsp->f)); 01436 dsp->f.frametype = AST_FRAME_CONTROL; 01437 dsp->f.subclass = AST_CONTROL_BUSY; 01438 ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name); 01439 return &dsp->f; 01440 } 01441 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) { 01442 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback); 01443 #if 0 01444 if (digit) 01445 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode); 01446 #endif 01447 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) { 01448 if (!dsp->thinkdigit) { 01449 if (digit) { 01450 /* Looks like we might have something. Request a conference mute for the moment */ 01451 memset(&dsp->f, 0, sizeof(dsp->f)); 01452 dsp->f.frametype = AST_FRAME_DTMF; 01453 dsp->f.subclass = 'm'; 01454 dsp->thinkdigit = 'x'; 01455 FIX_INF(af); 01456 if (chan) 01457 ast_queue_frame(chan, af, needlock); 01458 ast_frfree(af); 01459 return &dsp->f; 01460 } 01461 } else { 01462 if (digit) { 01463 /* Thought we saw one last time. Pretty sure we really have now */ 01464 if (dsp->thinkdigit) { 01465 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) { 01466 /* If we found a digit, and we're changing digits, go 01467 ahead and send this one, but DON'T stop confmute because 01468 we're detecting something else, too... */ 01469 memset(&dsp->f, 0, sizeof(dsp->f)); 01470 dsp->f.frametype = AST_FRAME_DTMF; 01471 dsp->f.subclass = dsp->thinkdigit; 01472 FIX_INF(af); 01473 if (chan) 01474 ast_queue_frame(chan, af, needlock); 01475 ast_frfree(af); 01476 } 01477 dsp->thinkdigit = digit; 01478 return &dsp->f; 01479 } 01480 dsp->thinkdigit = digit; 01481 } else { 01482 if (dsp->thinkdigit) { 01483 memset(&dsp->f, 0, sizeof(dsp->f)); 01484 if (dsp->thinkdigit != 'x') { 01485 /* If we found a digit, send it now */ 01486 dsp->f.frametype = AST_FRAME_DTMF; 01487 dsp->f.subclass = dsp->thinkdigit; 01488 dsp->thinkdigit = 0; 01489 } else { 01490 dsp->f.frametype = AST_FRAME_DTMF; 01491 dsp->f.subclass = 'u'; 01492 dsp->thinkdigit = 0; 01493 } 01494 FIX_INF(af); 01495 if (chan) 01496 ast_queue_frame(chan, af, needlock); 01497 ast_frfree(af); 01498 return &dsp->f; 01499 } 01500 } 01501 } 01502 } else if (!digit) { 01503 /* Only check when there is *not* a hit... */ 01504 if (dsp->digitmode & DSP_DIGITMODE_MF) { 01505 if (dsp->td.mf.current_digits) { 01506 memset(&dsp->f, 0, sizeof(dsp->f)); 01507 dsp->f.frametype = AST_FRAME_DTMF; 01508 dsp->f.subclass = dsp->td.mf.digits[0]; 01509 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits); 01510 dsp->td.mf.current_digits--; 01511 FIX_INF(af); 01512 if (chan) 01513 ast_queue_frame(chan, af, needlock); 01514 ast_frfree(af); 01515 return &dsp->f; 01516 } 01517 } else { 01518 if (dsp->td.dtmf.current_digits) { 01519 memset(&dsp->f, 0, sizeof(dsp->f)); 01520 dsp->f.frametype = AST_FRAME_DTMF; 01521 dsp->f.subclass = dsp->td.dtmf.digits[0]; 01522 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits); 01523 dsp->td.dtmf.current_digits--; 01524 FIX_INF(af); 01525 if (chan) 01526 ast_queue_frame(chan, af, needlock); 01527 ast_frfree(af); 01528 return &dsp->f; 01529 } 01530 } 01531 } 01532 } 01533 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) { 01534 res = __ast_dsp_call_progress(dsp, shortdata, len); 01535 memset(&dsp->f, 0, sizeof(dsp->f)); 01536 dsp->f.frametype = AST_FRAME_CONTROL; 01537 if (res) { 01538 switch(res) { 01539 case AST_CONTROL_ANSWER: 01540 case AST_CONTROL_BUSY: 01541 case AST_CONTROL_RINGING: 01542 case AST_CONTROL_CONGESTION: 01543 dsp->f.subclass = res; 01544 if (chan) 01545 ast_queue_frame(chan, &dsp->f, needlock); 01546 break; 01547 default: 01548 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); 01549 } 01550 } 01551 } 01552 FIX_INF(af); 01553 return af; 01554 } |
|
Definition at line 1648 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.
01649 { 01650 int x; 01651 dsp->totalsilence = 0; 01652 dsp->gsamps = 0; 01653 for (x=0;x<4;x++) 01654 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; 01655 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); 01656 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); 01657 01658 } |
|
Definition at line 1594 of file dsp.c. References ast_dsp::busycount, and DSP_HISTORY.
01595 { 01596 if (cadences < 4) 01597 cadences = 4; 01598 if (cadences > DSP_HISTORY) 01599 cadences = DSP_HISTORY; 01600 dsp->busycount = cadences; 01601 } |
|
Definition at line 1579 of file dsp.c. References ast_dsp::features.
01580 { 01581 dsp->features = features; 01582 } |
|
Definition at line 1589 of file dsp.c. References ast_dsp::threshold.
01590 { 01591 dsp->threshold = threshold; 01592 } |
|
Definition at line 1347 of file dsp.c. References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, s, and ast_frame::subclass. Referenced by ast_app_getvoice().
01348 { 01349 short *s; 01350 int len; 01351 01352 if (f->frametype != AST_FRAME_VOICE) { 01353 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n"); 01354 return 0; 01355 } 01356 if (f->subclass != AST_FORMAT_SLINEAR) { 01357 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n"); 01358 return 0; 01359 } 01360 s = f->data; 01361 len = f->datalen/2; 01362 return __ast_dsp_silence(dsp, s, len, totalsilence); 01363 } |