From 90cfc9e3bc780d9b1dcce497a1b4cb504e15e62f Mon Sep 17 00:00:00 2001
From: Mark Spencer <markster@digium.com>
Date: Sun, 16 Oct 2005 03:07:15 +0000
Subject: [PATCH] Make indications work more efficiently and without heavy
 floating point (bug #5360)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6796 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 indications.c | 67 +++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 49 insertions(+), 18 deletions(-)

diff --git a/indications.c b/indications.c
index 5f00a31798..6b2095216f 100755
--- a/indications.c
+++ b/indications.c
@@ -61,10 +61,14 @@ static int midi_tohz[128] = {
 			};
 
 struct playtones_item {
-	int freq1;
-	int freq2;
-	int duration;
+	int fac1;
+	int init_v2_1;
+	int init_v3_1;
+	int fac2;
+	int init_v2_2;
+	int init_v3_2;
 	int modulate;
+	int duration;
 };
 
 struct playtones_def {
@@ -77,10 +81,17 @@ struct playtones_def {
 
 struct playtones_state {
 	int vol;
+	int v1_1;
+	int v2_1;
+	int v3_1;
+	int v1_2;
+	int v2_2;
+	int v3_2;
 	int reppos;
 	int nitems;
 	struct playtones_item *items;
 	int npos;
+	int oldnpos;
 	int pos;
 	int origwfmt;
 	struct ast_frame f;
@@ -115,6 +126,7 @@ static void * playtones_alloc(struct ast_channel *chan, void *params)
 		ps->reppos = pd->reppos;
 		ps->nitems = pd->nitems;
 		ps->items = pd->items;
+		ps->oldnpos = -1;
 	}
 	/* Let interrupts interrupt :) */
 	if (pd->interruptible)
@@ -140,20 +152,34 @@ static int playtones_generator(struct ast_channel *chan, void *data, int len, in
 	memset(&ps->f, 0, sizeof(ps->f));
 
 	pi = &ps->items[ps->npos];
+	if (ps->oldnpos != ps->npos) {
+		/* Load new parameters */
+		ps->v1_1 = 0;
+		ps->v2_1 = pi->init_v2_1;
+		ps->v3_1 = pi->init_v3_1;
+		ps->v1_2 = 0;
+		ps->v2_2 = pi->init_v2_2;
+		ps->v3_2 = pi->init_v3_2;
+		ps->oldnpos = ps->npos;
+	}
 	for (x=0;x<len/2;x++) {
-		if (pi->modulate)
-		/* Modulate 1st tone with 2nd, to 90% modulation depth */
-		ps->data[x] = ps->vol * 2 * (
-			sin((pi->freq1 * 2.0 * M_PI / 8000.0) * (ps->pos + x)) *
-			(0.9 * fabs(sin((pi->freq2 * 2.0 * M_PI / 8000.0) * (ps->pos + x))) + 0.1)
-			);
-		else
-			/* Add 2 tones together */
-			ps->data[x] = ps->vol * (
-				sin((pi->freq1 * 2.0 * M_PI / 8000.0) * (ps->pos + x)) +
-				sin((pi->freq2 * 2.0 * M_PI / 8000.0) * (ps->pos + x))
-			);
+		ps->v1_1 = ps->v2_1;
+		ps->v2_1 = ps->v3_1;
+		ps->v3_1 = (pi->fac1 * ps->v2_1 >> 15) - ps->v1_1;
+		
+		ps->v1_2 = ps->v2_2;
+		ps->v2_2 = ps->v3_2;
+		ps->v3_2 = (pi->fac2 * ps->v2_2 >> 15) - ps->v1_2;
+		if (pi->modulate) {
+			int p;
+			p = ps->v3_2 - 32768;
+			if (p < 0) p = -p;
+			p = ((p * 9) / 10) + 1;
+			ps->data[x] = (ps->v3_1 * p) >> 15;
+		} else
+			ps->data[x] = ps->v3_1 + ps->v3_2; 
 	}
+	
 	ps->f.frametype = AST_FRAME_VOICE;
 	ps->f.subclass = AST_FORMAT_SLINEAR;
 	ps->f.datalen = len;
@@ -192,7 +218,7 @@ int ast_playtones_start(struct ast_channel *chan, int vol, const char *playlst,
 	if (!data)
 		return -1;
 	if (vol < 1)
-		d.vol = 8192;
+		d.vol = 7219; /* Default to -8db */
 
 	d.interruptible = interruptible;
 	
@@ -278,8 +304,13 @@ int ast_playtones_start(struct ast_channel *chan, int vol, const char *playlst,
 			ast_log(LOG_WARNING, "Realloc failed!\n");
 			return -1;
 		}
-		d.items[d.nitems].freq1    = freq1;
-		d.items[d.nitems].freq2    = freq2;
+		d.items[d.nitems].fac1 = 2.0 * cos(2.0 * M_PI * (freq1 / 8000.0)) * 32768.0;
+		d.items[d.nitems].init_v2_1 = sin(-4.0 * M_PI * (freq1 / 8000.0)) * d.vol;
+		d.items[d.nitems].init_v3_1 = sin(-2.0 * M_PI * (freq1 / 8000.0)) * d.vol;
+
+		d.items[d.nitems].fac2 = 2.0 * cos(2.0 * M_PI * (freq2 / 8000.0)) * 32768.0;
+		d.items[d.nitems].init_v2_2 = sin(-4.0 * M_PI * (freq2 / 8000.0)) * d.vol;
+		d.items[d.nitems].init_v3_2 = sin(-2.0 * M_PI * (freq2 / 8000.0)) * d.vol;
 		d.items[d.nitems].duration = time;
 		d.items[d.nitems].modulate = modulate;
 		d.nitems++;
-- 
GitLab