summaryrefslogtreecommitdiff
path: root/pjmedia
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-09-16 14:33:16 +0000
committerBenny Prijono <bennylp@teluu.com>2008-09-16 14:33:16 +0000
commitb1c66224a0fab355eefa3bcbc9e791c13a31ce0f (patch)
treee30fcb1c7298ea37d7bd364f0dcd2ed6d398f2c3 /pjmedia
parent1a617d04a43d1bb2b32f7eca393f6ac3c65523e4 (diff)
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
Diffstat (limited to 'pjmedia')
-rw-r--r--pjmedia/include/pjmedia/config.h59
-rw-r--r--pjmedia/src/pjmedia/tonegen.c42
2 files changed, 98 insertions, 3 deletions
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 <math.h>
# 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;
}