Index: pjproject/trunk/pjmedia/include/pjmedia/tonegen.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/tonegen.h	(revision 693)
+++ pjproject/trunk/pjmedia/include/pjmedia/tonegen.h	(revision 694)
@@ -63,4 +63,5 @@
     short   on_msec;	    /**< Playback ON duration, in miliseconds.	    */
     short   off_msec;	    /**< Playback OFF duration, ini miliseconds.    */
+    short   volume;	    /**< Volume (1-16383), or 0 for default.	    */
 } pjmedia_tone_desc;
 
@@ -76,4 +77,5 @@
     short   on_msec;	    /**< Playback ON duration, in miliseconds.	    */
     short   off_msec;	    /**< Playback OFF duration, ini miliseconds.    */
+    short   volume;	    /**< Volume (1-16383), or 0 for default.	    */
 } pjmedia_tone_digit;
 
Index: pjproject/trunk/pjmedia/src/pjmedia/tonegen.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/tonegen.c	(revision 693)
+++ pjproject/trunk/pjmedia/src/pjmedia/tonegen.c	(revision 694)
@@ -43,5 +43,5 @@
      * This produces good quality tone in relatively faster time than
      * the normal sin() generator.
-     * Speed = 32,500 cycles (to generate 100 msec single-tone).
+     * Speed = 40.6 cycles per sample.
      */
 #   include <math.h>
@@ -54,10 +54,10 @@
 				 var.s0 = A; \
 				 var.s1 = 0
-#   define GEN_SAMP(val,var,A)	 var.s0 = var.s0 - var.a * var.s1; \
+#   define GEN_SAMP(val,var)	 var.s0 = var.s0 - var.a * var.s1; \
 				 var.s1 = var.s1 + var.a * var.s0; \
 				 val = (short) var.s0
 
 
-#elif defined(PJ_HAS_FLOATING_POINT) && PJ_HAS_FLOATING_POINT!=0
+#elif !defined(PJ_HAS_FLOATING_POINT) || PJ_HAS_FLOATING_POINT==0
     /* 
      * Fallback algorithm when floating point is disabled.
@@ -66,5 +66,7 @@
      *    http://www.audiomulch.com/~rossb/code/sinusoids/ 
      * Quality wise not so good, but it's blazing fast!
-     * Speed = 9,776 cycles (to generate 100 msec single-tone).
+     * Speed: 
+     *	- with volume adjustment: 14 cycles per sample 
+     *  - without volume adjustment: 12.22 cycles per sample
      */
     PJ_INLINE(int) approximate_sin3(unsigned x)
@@ -81,10 +83,16 @@
 	unsigned add;
 	unsigned c;
+	unsigned vol;
     };
 
 #   define MAXI			((unsigned)0xFFFFFFFF)
 #   define SIN			approximate_sin3
-#   define GEN_INIT(var,R,F,A)	var.add = MAXI/R * F, var.c=0
-#   define GEN_SAMP(val,var,A)	val = (short) (SIN(var.c) >> 16); \
+#   if 1    /* set this to 0 to disable volume adjustment */
+#	define VOL(var,v)	(((v) * var.vol) >> 16)
+#   else
+#	define VOL(var,v)	(v)
+#   endif
+#   define GEN_INIT(var,R,F,A)	var.add = MAXI/R * F, var.c=0, var.vol=A
+#   define GEN_SAMP(val,var)	val = (short) VOL(SIN(var.c)>>16));\
 				var.c += var.add
 
@@ -96,5 +104,5 @@
      * Should never really reach here, but anyway it's provided for reference.
      * This is the good old tone generator using sin().
-     * Speed = 178,000 cycles (to generate 100 msec single-tone).
+     * Speed = 222.5 cycles per sample.
      */
     struct gen
@@ -102,8 +110,9 @@
 	DATA add;
 	DATA c;
+	DATA vol;
     };
 
-#   define GEN_INIT(var,R,F,A) var.add = ((DATA)F)/R, var.c=0
-#   define GEN_SAMP(val,var,A) val = (short) (sin(var.c * 2 * M_PI) * A); \
+#   define GEN_INIT(var,R,F,A) var.add = ((DATA)F)/R, var.c=0, var.vol=A
+#   define GEN_SAMP(val,var)   val = (short)(sin(var.c * 2 * M_PI) * var.vol);\
 			       var.c += var.add
 
@@ -120,7 +129,8 @@
 static void init_generate_single_tone(struct gen_state *state,
 				      unsigned clock_rate, 
-				      unsigned freq)
-{
-    GEN_INIT(state->tone1,clock_rate,freq,AMP);
+				      unsigned freq,
+				      unsigned vol)
+{
+    GEN_INIT(state->tone1,clock_rate,freq,vol);
     state->has_tone2 = PJ_FALSE;
 }
@@ -136,5 +146,5 @@
 
 	while (buf < end) {
-	    GEN_SAMP(*buf++, state->tone1, AMP);
+	    GEN_SAMP(*buf++, state->tone1);
 	}
 
@@ -142,5 +152,5 @@
 
 	while (buf < end) {
-	    GEN_SAMP(*buf, state->tone1, AMP);
+	    GEN_SAMP(*buf, state->tone1);
 	    *(buf+1) = *buf;
 	    buf += 2;
@@ -153,8 +163,9 @@
 				    unsigned clock_rate, 
 				    unsigned freq1,
-				    unsigned freq2)
-{
-    GEN_INIT(state->tone1,clock_rate,freq1,AMP);
-    GEN_INIT(state->tone2,clock_rate,freq2,AMP);
+				    unsigned freq2,
+				    unsigned vol)
+{
+    GEN_INIT(state->tone1,clock_rate,freq1,vol);
+    GEN_INIT(state->tone2,clock_rate,freq2,vol);
     state->has_tone2 = PJ_TRUE;
 }
@@ -171,6 +182,6 @@
 	int val, val2;
 	while (buf < end) {
-	    GEN_SAMP(val, state->tone1, AMP);
-	    GEN_SAMP(val2, state->tone2, AMP);
+	    GEN_SAMP(val, state->tone1);
+	    GEN_SAMP(val2, state->tone2);
 	    *buf++ = (short)((val+val2) >> 1);
 	}
@@ -179,6 +190,6 @@
 	while (buf < end) {
 
-	    GEN_SAMP(val, state->tone1, AMP);
-	    GEN_SAMP(val2, state->tone2, AMP);
+	    GEN_SAMP(val, state->tone1);
+	    GEN_SAMP(val2, state->tone2);
 	    val = (val + val2) >> 1;
 
@@ -193,10 +204,11 @@
 			       unsigned clock_rate, 
 			       unsigned freq1,
-			       unsigned freq2)
+			       unsigned freq2,
+			       unsigned vol)
 {
     if (freq2)
-	init_generate_dual_tone(state, clock_rate, freq1, freq2);
+	init_generate_dual_tone(state, clock_rate, freq1, freq2 ,vol);
     else
-	init_generate_single_tone(state, clock_rate, freq1);
+	init_generate_single_tone(state, clock_rate, freq1,vol);
 }
 
@@ -384,5 +396,5 @@
 	if (tonegen->dig_samples == 0) {
 	    init_generate_tone(&tonegen->state, port->info.clock_rate,
-			       dig->freq1, dig->freq2);
+			       dig->freq1, dig->freq2, dig->volume);
 	}
 
@@ -439,4 +451,5 @@
 {
     struct tonegen *tonegen = (struct tonegen*) port;
+    unsigned i;
 
     PJ_ASSERT_RETURN(port && port->info.signature == SIGNATURE &&
@@ -447,6 +460,17 @@
 		     PJ_ETOOMANY);
 
+    /* Copy digits */
     pj_memcpy(tonegen->digits + tonegen->count,
 	      tones, count * sizeof(pjmedia_tone_desc));
+    
+    /* Normalize volume */
+    for (i=0; i<count; ++i) {
+	pjmedia_tone_desc *t = &tonegen->digits[i+tonegen->count];
+	if (t->volume == 0)
+	    t->volume = AMP;
+	else if (t->volume < 0)
+	    t->volume = (short) -t->volume;
+    }
+
     tonegen->count += count;
 
@@ -488,4 +512,5 @@
 	tones[i].on_msec = digits[i].on_msec;
 	tones[i].off_msec = digits[i].off_msec;
+	tones[i].volume = digits[i].volume;
     }
 
