From b1c66224a0fab355eefa3bcbc9e791c13a31ce0f Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 16 Sep 2008 14:33:16 +0000 Subject: Ticket #619: added configuration to force floating point algorithm to be used in the tone generator, and added fade-in and fade out options git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2281 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/include/pjmedia/config.h | 59 ++++++++++++++++++++++++++++++++++++++-- pjmedia/src/pjmedia/tonegen.c | 42 +++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 3 deletions(-) (limited to 'pjmedia') diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h index 46bf18b9..e592fcfb 100644 --- a/pjmedia/include/pjmedia/config.h +++ b/pjmedia/include/pjmedia/config.h @@ -541,10 +541,65 @@ * Enable high quality of tone generation, the better quality will cost * more CPU load. This is only applied to floating point enabled machines. * - * By default it is enabled. + * By default it is enabled when PJ_HAS_FLOATING_POINT is set. + * + * @see PJMEDIA_TONEGEN_FORCE_FLOAT */ #ifndef PJMEDIA_USE_HIGH_QUALITY_TONEGEN -# define PJMEDIA_USE_HIGH_QUALITY_TONEGEN 1 +# define PJMEDIA_USE_HIGH_QUALITY_TONEGEN PJ_HAS_FLOATING_POINT +#endif + + +/** + * Force the tone generation to use floating point computation, even when + * PJ_HAS_FLOATING_POINT is disabled. This may be necessary if the tone + * generator is used to produce DTMF to be sent inband, since the fixed + * point algorithm may not have the correct frequency accuracy. + * + * This option, combined with PJ_HAS_FLOATING_POINT will produce the + * following selection of tone generator algorithm: + * - if both PJ_HAS_FLOATING_POINT and PJMEDIA_USE_HIGH_QUALITY_TONEGEN + * are set, the standard sin() function will be used. This will produce + * the highest quality tones, at the expense of more processing power. + * - if PJ_HAS_FLOATING_POINT is not set: + * - if both PJMEDIA_USE_HIGH_QUALITY_TONEGEN and + * PJMEDIA_TONEGEN_FORCE_FLOAT are set, sin() based algorithm will + * be used (similar as above). + * - if PJMEDIA_USE_HIGH_QUALITY_TONEGEN is not set but the + * PJMEDIA_TONEGEN_FORCE_FLOAT is set, a floating point approximation + * algorithm will be used. This should produce good enough tone + * for most uses, and the performance is faster than using pure + * sin() based algorithm. Note that linking to math library may + * still be needed. + * - if both are not set, the fixed point approximation algorithm + * will be used. + * + * Default: 1 + */ +#ifndef PJMEDIA_TONEGEN_FORCE_FLOAT +# define PJMEDIA_TONEGEN_FORCE_FLOAT 1 +#endif + + +/** + * Fade-in duration for the tone, in milliseconds. Set to zero to disable + * this feature. + * + * Default: 1 (msec) + */ +#ifndef PJMEDIA_TONEGEN_FADE_IN_TIME +# define PJMEDIA_TONEGEN_FADE_IN_TIME 1 +#endif + + +/** + * Fade-out duration for the tone, in milliseconds. Set to zero to disable + * this feature. + * + * Default: 2 (msec) + */ +#ifndef PJMEDIA_TONEGEN_FADE_OUT_TIME +# define PJMEDIA_TONEGEN_FADE_OUT_TIME 2 #endif diff --git a/pjmedia/src/pjmedia/tonegen.c b/pjmedia/src/pjmedia/tonegen.c index c217894e..562195d5 100644 --- a/pjmedia/src/pjmedia/tonegen.c +++ b/pjmedia/src/pjmedia/tonegen.c @@ -38,7 +38,8 @@ #endif -#if defined(PJ_HAS_FLOATING_POINT) && PJ_HAS_FLOATING_POINT!=0 +#if (defined(PJ_HAS_FLOATING_POINT) && PJ_HAS_FLOATING_POINT!=0) || \ + (defined(PJMEDIA_TONEGEN_FORCE_FLOAT) && PJMEDIA_TONEGEN_FORCE_FLOAT != 0) # include # if defined(PJMEDIA_USE_HIGH_QUALITY_TONEGEN) && \ @@ -249,6 +250,8 @@ struct tonegen /* options */ unsigned options; unsigned playback_options; + unsigned fade_in_len; /* fade in for this # of samples */ + unsigned fade_out_len; /* fade out for this # of samples*/ /* lock */ pj_lock_t *lock; @@ -335,6 +338,9 @@ PJ_DEF(pj_status_t) pjmedia_tonegen_create2(pj_pool_t *pool, tonegen->base.on_destroy = &tonegen_destroy; tonegen->digit_map = &digit_map; + tonegen->fade_in_len = PJMEDIA_TONEGEN_FADE_IN_TIME * clock_rate / 1000; + tonegen->fade_out_len = PJMEDIA_TONEGEN_FADE_OUT_TIME * clock_rate / 1000; + /* Lock */ if (options & PJMEDIA_TONEGEN_NO_LOCK) { status = pj_lock_create_null_mutex(pool, "tonegen", &tonegen->lock); @@ -533,10 +539,44 @@ static pj_status_t tonegen_get_frame(pjmedia_port *port, cnt = required; generate_tone(&tonegen->state, port->info.channel_count, cnt, dst); + dst += cnt; tonegen->dig_samples += cnt; required -= cnt; + if (tonegen->dig_samples == cnt) { + /* Fade in */ + short *samp = (dst - cnt); + short *end; + + if (cnt > tonegen->fade_in_len) + cnt = tonegen->fade_in_len; + end = samp + cnt; + if (cnt) { + const unsigned step = 0xFFFF / cnt; + unsigned scale = 0; + + for (; samp < end; ++samp) { + (*samp) = (short)(((*samp) * scale) >> 16); + scale += step; + } + } + } else if (tonegen->dig_samples == on_samp) { + /* Fade out */ + if (cnt > tonegen->fade_out_len) + cnt = tonegen->fade_out_len; + if (cnt) { + short *samp = (dst - cnt); + const unsigned step = 0xFFFF / cnt; + unsigned scale = 0xFFFF - step; + + for (; samp < dst; ++samp) { + (*samp) = (short)(((*samp) * scale) >> 16); + scale -= step; + } + } + } + if (dst == end) break; } -- cgit v1.2.3