[asterisk-dev] main/indications.c: Possibility to specify tone levels

Pavel Troller patrol at sinus.cz
Thu May 7 00:58:23 CDT 2009


Hi!
  Current implementation of tones in Asterisk lacks the posssibility to
specify tone levels. Even cheap VoIP gateways (Linksys/SPAxxxx) and VoIP
phones are able to set individual tone levels, but we currently are not.
  To fix this, I've prepared a patch. Because I'm not currently running
SVN trunk at any place, the patch is for 1.6.1.0 branch. However, if it
will be found as useful, I'm willing to make a new patch for the SVN
trunk.
  The patch adds a new, optional syntax element "@level" to all of the
possible tone formats. The level is entered in dB, so negative numbers
have to be used for most cases. However, the level can be set up to +3 dB,
which still generates an undistorted tone. This is similar to Linksys/Sipura
syntax.
  For example, a new definition of SIT with levels of -16 dB is as follows:
info = 950 at -16/330,0/30,1400 at -16/330,0/30,1800 at -16/330,0/1000
  You are even able to specify a different levels for individual tone
fragments, so you can easily create a famous "hobbling" British congestion
tone:
congestion = 400 at -10/400,0/350,400 at -5/225,0/525
  Of course the patch doesn't change the current behaviour: If a volume
is specified (non-zero) for ast_playtones_start(), it overrides the
levels in the tone spec and all the tone frags are played with the requested
level. It also accepts the original indications.conf file without any changes,
so if the user doesn't want to use this new feature, he doesn't notify any
change.
  Please let me know, whether you are willing to accept the patch and whether
I should prepare a version for SVN trunk.
  With regards, Pavel Troller

-------------- next part --------------
--- indications.c.orig	2009-05-07 07:27:48.000000000 +0200
+++ indications.c	2009-05-07 07:21:20.000000000 +0200
@@ -219,9 +219,6 @@
 	char *stringp;
 	char *separator;
 	
-	if (vol < 1)
-		d.vol = 7219; /* Default to -8db */
-
 	d.interruptible = interruptible;
 	
 	stringp=data;
@@ -233,56 +230,112 @@
 		separator = ",";
 	s = strsep(&stringp,separator);
 	while (s && *s) {
-		int freq1, freq2, duration, modulate = 0, midinote = 0;
+		int freq1, freq2, level, duration, modulate = 0, midinote = 0;
 
 		if (s[0]=='!')
 			s++;
 		else if (d.reppos == -1)
 			d.reppos = d.nitems;
-		if (sscanf(s, "%d+%d/%d", &freq1, &freq2, &duration) == 3) {
+		if (sscanf(s, "%d+%d@%d/%d", &freq1, &freq2, &level, &duration) == 4) {
+			/* f1+f2 at level/time format */
+		} else if (sscanf(s, "%d+%d/%d", &freq1, &freq2, &duration) == 3) {
+			level = -8;
 			/* f1+f2/time format */
+		} else if (sscanf(s, "%d+%d@%d", &freq1, &freq2, &level) == 3) {
+			/* f1+f2 at level format */
+			duration = 0;
 		} else if (sscanf(s, "%d+%d", &freq1, &freq2) == 2) {
 			/* f1+f2 format */
 			duration = 0;
+			level = -8;
+		} else if (sscanf(s, "%d*%d@%d/%d", &freq1, &freq2, &level, &duration) == 4) {
+			/* f1*f2 at level/time format */
+			modulate = 1;
 		} else if (sscanf(s, "%d*%d/%d", &freq1, &freq2, &duration) == 3) {
 			/* f1*f2/time format */
 			modulate = 1;
+			level = -8;
+		} else if (sscanf(s, "%d*%d@%d", &freq1, &freq2, &level) == 3) {
+			/* f1*f2 at level format */
+			duration = 0;
+			modulate = 1;
 		} else if (sscanf(s, "%d*%d", &freq1, &freq2) == 2) {
 			/* f1*f2 format */
 			duration = 0;
 			modulate = 1;
+			level = -8;
+		} else if (sscanf(s, "%d@%d/%d", &freq1, &level, &duration) == 3) {
+			/* f1 at level/time format */
+			freq2 = 0;
 		} else if (sscanf(s, "%d/%d", &freq1, &duration) == 2) {
 			/* f1/time format */
 			freq2 = 0;
+			level = -8;
+		} else if (sscanf(s, "%d@%d", &freq1, &level) == 2) {
+			/* f1 at level format */
+			freq2 = 0;
+			duration = 0;
 		} else if (sscanf(s, "%d", &freq1) == 1) {
 			/* f1 format */
 			freq2 = 0;
 			duration = 0;
+			level = -8;
+		} else if (sscanf(s, "M%d+M%d@%d/%d", &freq1, &freq2, &level, &duration) == 4) {
+			/* Mf1+Mf2 at level/time format */
+			midinote = 1;
 		} else if (sscanf(s, "M%d+M%d/%d", &freq1, &freq2, &duration) == 3) {
 			/* Mf1+Mf2/time format */
 			midinote = 1;
+			level = -8;
+		} else if (sscanf(s, "M%d+M%d@%d", &freq1, &freq2, &level) == 3) {
+			/* Mf1+Mf2 at level format */
+			duration = 0;
+			midinote = 1;
 		} else if (sscanf(s, "M%d+M%d", &freq1, &freq2) == 2) {
 			/* Mf1+Mf2 format */
 			duration = 0;
 			midinote = 1;
+			level = -8;
+		} else if (sscanf(s, "M%d*M%d@%d/%d", &freq1, &freq2, &level, &duration) == 4) {
+			/* Mf1*Mf2 at level/time format */
+			modulate = 1;
+			midinote = 1;
 		} else if (sscanf(s, "M%d*M%d/%d", &freq1, &freq2, &duration) == 3) {
 			/* Mf1*Mf2/time format */
 			modulate = 1;
 			midinote = 1;
+			level = -8;
+		} else if (sscanf(s, "M%d*M%d@%d", &freq1, &freq2, &level) == 3) {
+			/* Mf1*Mf2 at level format */
+			duration = 0;
+			modulate = 1;
+			midinote = 1;
 		} else if (sscanf(s, "M%d*M%d", &freq1, &freq2) == 2) {
 			/* Mf1*Mf2 format */
 			duration = 0;
 			modulate = 1;
 			midinote = 1;
+			level = -8;
+		} else if (sscanf(s, "M%d@%d/%d", &freq1, &level, &duration) == 3) {
+			/* Mf1 at level/time format */
+			freq2 = -1;
+			midinote = 1;
 		} else if (sscanf(s, "M%d/%d", &freq1, &duration) == 2) {
 			/* Mf1/time format */
 			freq2 = -1;
 			midinote = 1;
+			level = -8;
+		} else if (sscanf(s, "M%d@%d", &freq1, &level) == 2) {
+			/* Mf1 at level format */
+			freq2 = -1;
+			duration = 0;
+			midinote = 1;
 		} else if (sscanf(s, "M%d", &freq1) == 1) {
 			/* Mf1 format */
 			freq2 = -1;
 			duration = 0;
 			midinote = 1;
+			level = -8;
 		} else {
 			ast_log(LOG_WARNING,"%s: tone component '%s' of '%s' is no good\n",chan->name,s,playlst);
 			return -1;
@@ -301,6 +354,12 @@
 				freq2 = 0;
 		}
 
+		/* Sanitize tone level */
+		level = (level > 3) ? 3 : level;
+
+		/* Calculate the volume */
+		d.vol = (vol < 1) ? floor(pow(10.0, (level - 3.14) / 20.0) * 65536.0 / 2.0) : vol;
+
 		if (!(d.items = ast_realloc(d.items, (d.nitems + 1) * sizeof(*d.items)))) {
 			return -1;
 		}


More information about the asterisk-dev mailing list