diff -ur apps/app_milliwatt.c asterisk/apps/app_milliwatt.c --- apps/app_milliwatt.c 2005-12-29 10:25:26.000000000 -0800 +++ apps/app_milliwatt.c 2005-12-29 10:55:00.000000000 -0800 @@ -75,13 +75,22 @@ struct ast_frame wf; unsigned char waste[AST_FRIENDLY_OFFSET]; unsigned char buf[640]; - int i,*indexp = (int *) data; + const int maxsamples = sizeof (buf) / sizeof (buf[0]); + int i, *indexp = (int *) data; - if (len > sizeof(buf)) + /* Instead of len, use samples, because channel.c generator_force + * generate(chan, tmp, 0, 160) ignores len. In any case, len is + * a multiple of samples, given by number of samples times bytes per + * sample. In the case of ulaw, len = samples. for signed linear + * len = 2 * samples */ + + if (samples > maxsamples) { - ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)sizeof(buf),len); - len = sizeof(buf); + ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples); + samples = maxsamples; } + len = samples * sizeof (buf[0]); + waste[0] = 0; /* make compiler happy */ wf.frametype = AST_FRAME_VOICE; wf.subclass = AST_FORMAT_ULAW; @@ -89,7 +98,7 @@ wf.mallocd = 0; wf.data = buf; wf.datalen = len; - wf.samples = wf.datalen; + wf.samples = samples; wf.src = "app_milliwatt"; wf.delivery.tv_sec = 0; wf.delivery.tv_usec = 0; diff -ur apps/app_sms.c asterisk/apps/app_sms.c --- apps/app_sms.c 2005-12-29 10:25:26.000000000 -0800 +++ apps/app_sms.c 2005-12-29 10:26:01.000000000 -0800 @@ -1179,32 +1179,31 @@ { struct ast_frame f = { 0 }; unsigned char waste[AST_FRIENDLY_OFFSET]; +#define MAXSAMPLES (800) #ifdef OUTALAW - unsigned char buf[800]; + unsigned char buf[MAXSAMPLES]; #else - signed short buf[800]; + signed short buf[MAXSAMPLES]; #endif +#define SAMPLE2LEN (sizeof (buf[0])) sms_t *h = data; int i; - if (len > sizeof (buf)) { - ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len); - len = sizeof (buf); -#ifdef OUTALAW - samples = len; -#else - samples = len / 2; -#endif + if (samples > MAXSAMPLES) { + ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n", + MAXSAMPLES, samples); + samples = MAXSAMPLES; } - waste[0] = 0; /* make compiler happy */ + len = samples * SAMPLE2LEN; + + waste[0] = 0; /* make compiler happy */ f.frametype = AST_FRAME_VOICE; #ifdef OUTALAW f.subclass = AST_FORMAT_ALAW; - f.datalen = samples; #else f.subclass = AST_FORMAT_SLINEAR; - f.datalen = samples * 2; #endif + f.datalen = len; f.offset = AST_FRIENDLY_OFFSET; f.mallocd = 0; f.data = buf; @@ -1256,6 +1255,8 @@ return -1; } return 0; +#undef SAMPLE2LEN +#undef MAXSAMPLES } static void sms_process (sms_t * h, int samples, signed short *data) diff -ur asterisk.8 asterisk/asterisk.8 --- asterisk.8 2005-12-29 10:25:42.000000000 -0800 +++ asterisk.8 2005-12-29 10:26:01.000000000 -0800 @@ -114,6 +114,9 @@ for controlling it. Additionally, if connection to the Asterisk process is lost, attempt to reconnect for as long as 30 seconds. .TP +\fB-s\fR +Enable silence suppression if timing device is available. +.TP \fB-t\fR When recording files, write them first into a temporary holding directory, then move them into the final location when done. diff -ur asterisk.c asterisk/asterisk.c --- asterisk.c 2005-12-29 10:25:42.000000000 -0800 +++ asterisk.c 2005-12-29 10:27:46.000000000 -0800 @@ -150,6 +150,9 @@ double option_maxload = 0.0; /*!< Max load avg on system */ int option_maxcalls = 0; /*!< Max number of active calls */ +int option_silence_suppression = 0; + + /*! @} */ char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR; @@ -1958,7 +1961,10 @@ /* Transmit SLINEAR silence while a channel is being recorded */ } else if (!strcasecmp(v->name, "transmit_silence_during_record")) { option_transmit_silence_during_record = ast_true(v->value); - } else if (!strcasecmp(v->name, "maxcalls")) { + /* Enable silence suppression */ + } else if (!strcasecmp(v->name, "silence_suppression")) { + option_silence_suppression = ast_true(v->value); +} else if (!strcasecmp(v->name, "maxcalls")) { if ((sscanf(v->value, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0)) { option_maxcalls = 0; } @@ -2034,7 +2040,7 @@ } */ /* Check for options */ - while((c=getopt(argc, argv, "tThfdvVqprRgcinx:U:G:C:L:M:")) != -1) { + while((c=getopt(argc, argv, "tThfdvVqprRgcinsx:U:G:C:L:M:")) != -1) { switch(c) { case 'd': option_debug++; @@ -2073,6 +2079,9 @@ case 'q': ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET); break; + case 's': + option_silence_suppression++; + break; case 't': ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES); break; diff -ur channel.c asterisk/channel.c --- channel.c 2005-12-29 10:25:42.000000000 -0800 +++ channel.c 2005-12-29 10:30:47.000000000 -0800 @@ -1763,6 +1763,14 @@ return 0; /* Time is up */ } +int ast_silence_suppression_enabled(struct ast_channel *chan) +{ + int ret = option_silence_suppression && chan->timingfd > -1; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Silence suppression is %s (option_silence_suppression=%d chan->timingfd=%d)\n", ret? "enabled": "disabled", option_silence_suppression, chan->timingfd); + return ret; +} + struct ast_frame *ast_read(struct ast_channel *chan) { struct ast_frame *f = NULL; @@ -1948,18 +1948,13 @@ ast_cdr_answer(chan->cdr); } - /* Run any generator sitting on the line */ - if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) { - /* Mask generator data temporarily and apply. If there is a timing function, it - will be calling the generator instead */ + /* Run generator sitting on the line if timing device not available + * and synchronous generation of outgoing frames is necessary */ + if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata && !ast_silence_suppression_enabled(chan)) { void *tmp; int res; int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples); - if (chan->timingfunc) { - ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n"); - ast_settimeout(chan, 0, NULL, NULL); - } tmp = chan->generatordata; chan->generatordata = NULL; generate = chan->generator->generate; @@ -1969,11 +1964,6 @@ ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); ast_deactivate_generator(chan); } - } else if (f && (f->frametype == AST_FRAME_CNG)) { - if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) { - ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n"); - ast_settimeout(chan, 160, generator_force, chan); - } } /* High bit prints debugging */ if (chan->fin & 0x80000000) diff -ur channels/chan_sip.c asterisk/channels/chan_sip.c --- channels/chan_sip.c 2005-12-29 10:25:25.000000000 -0800 +++ channels/chan_sip.c 2005-12-29 10:26:01.000000000 -0800 @@ -4444,7 +4444,8 @@ debug); } - ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n"); + if(!ast_silence_suppression_enabled(p->owner)) + ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n"); if ((m_audio_left < 2) || (m_video_left < 2) || (a_audio_left == 0) || (a_video_left == 0)) ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n"); diff -ur doc/README.asterisk.conf asterisk/doc/README.asterisk.conf --- doc/README.asterisk.conf 2005-12-29 10:25:26.000000000 -0800 +++ doc/README.asterisk.conf 2005-12-29 10:26:01.000000000 -0800 @@ -52,6 +52,7 @@ runuser = asterisk ; User to run asterisk as (-U) NOTE: will require changes to ; directory and device permisions rungroup = asterisk ; Group to run asterisk as (-G) +silence_suppression = yes | no ; Enable silence suppression support (-s) ;These options have no command line equivalent cache_record_files = yes | no ; Cache record() files in another directory until completion diff -ur include/asterisk/channel.h asterisk/include/asterisk/channel.h --- include/asterisk/channel.h 2005-12-29 10:25:26.000000000 -0800 +++ include/asterisk/channel.h 2005-12-29 10:26:01.000000000 -0800 @@ -1109,6 +1109,16 @@ */ void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state); +/*! + \brief Check if the channel can run in silence suppression mode. + \param chan The channel to check + \return boolean + + This function will return 1 if silence suppression is enabled and the timing + device is available. + */ +int ast_silence_suppression_enabled(struct ast_channel *chan); + /* Misc. functions below */ /* Helper function for migrating select to poll */ diff -ur include/asterisk/options.h asterisk/include/asterisk/options.h --- include/asterisk/options.h 2005-12-29 10:25:26.000000000 -0800 +++ include/asterisk/options.h 2005-12-29 10:32:04.000000000 -0800 @@ -97,6 +97,7 @@ extern int option_verbose; extern int option_debug; extern int option_nofork; +extern int option_silence_suppression; extern int option_quiet; extern int option_console; extern int option_initcrypto; diff -ur Makefile asterisk/Makefile --- Makefile 2005-12-29 10:25:42.000000000 -0800 +++ Makefile 2005-12-29 10:36:52.000000000 -0800 @@ -767,6 +767,8 @@ echo ";astctlowner = root" ; \ echo ";astctlgroup = apache" ; \ echo ";astctl = asterisk.ctl" ; \ + echo ";[options]" ; \ + echo ";silence_suppression = yes" ; \ ) > $(DESTDIR)$(ASTCONFPATH) ; \ else \ echo "Skipping asterisk.conf creation"; \