[Sound-open-firmware] [PATCH 3/4] mixer: make mixer more optimal and easier to vectorise

Liam Girdwood liam.r.girdwood at linux.intel.com
Wed Dec 28 17:29:13 CET 2016


Make the mixer compute two channels per loop iteration. This allows for
easier vectorisation. The loop is also more efficient if we update or
source/sink pointers after mixing has completed.

Signed-off-by: Liam Girdwood <liam.r.girdwood at linux.intel.com>
---
 src/audio/mixer.c | 50 +++++++++++++++++++++++++++-----------------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/src/audio/mixer.c b/src/audio/mixer.c
index b244f50..d08bc30 100644
--- a/src/audio/mixer.c
+++ b/src/audio/mixer.c
@@ -49,31 +49,35 @@ struct mixer_data {
 
 /* mix n stream datas to 1 sink buffer */
 static void mix_n(struct comp_dev *dev, struct comp_buffer *sink,
-	struct comp_buffer **sources, uint32_t count, uint32_t frames)
+	struct comp_buffer **sources, uint32_t num_sources, uint32_t frames)
 {
-	int16_t *src;
-	int16_t *dest = (int16_t*) sink->w_ptr;
-	int i, j, k;
-	int32_t val = 0;
-
-	/* buffer sizes are always divisible by period frames */
-	/* TODO: unroll this loop for further optimisation */
-	for (i = 0; i < frames; i++) {
-		for (j = 0; j < sink->params.channels; j++) {
-			val = 0;
-			for (k = 0; k < count; k++) {
-				src = (int16_t*)sources[k]->r_ptr;
-				val += *src;
-				/* TODO: clamp when converting to int16_t */
-				src++;
-				sources[k]->r_ptr = src;
-			}
-			*dest = (int16_t)(val >> (count >> 1)); /* average level */
-			dest++;
+	int32_t *src, *dest = sink->w_ptr, val[2], count;
+	int i, j;
+
+	count = frames * sink->params.channels;
+
+	for (i = 0; i < count; i += 2) {
+		val[0] = 0;
+		val[1] = 0;
+		for (j = 0; j < num_sources; j++) {
+			src = sources[j]->r_ptr;
+
+			/* TODO: clamp */
+			val[0] += src[i];
+			val[1] += src[i + 1];
 		}
+
+		/* TODO: best place for attenuation ? */
+		dest[i] = (val[0] >> (num_sources >> 1));
+		dest[i + 1] = (val[1] >> (num_sources >> 1));
 	}
 
-	sink->w_ptr = dest;
+	/* update R/W pointers */
+	sink->w_ptr = dest + count;
+	for (j = 0; j < num_sources; j++) {
+		src = sources[j]->r_ptr;
+		sources[j]->r_ptr = src + count;
+	}
 }
 
 static struct comp_dev *mixer_new(uint32_t type, uint32_t index,
@@ -203,7 +207,7 @@ static int mixer_copy(struct comp_dev *dev)
 {
 	struct mixer_data *md = comp_get_drvdata(dev);
 	struct comp_buffer *sink, *sources[5], *source;
-	uint32_t i = 0, cframes = PIPELINE_LL_FRAMES;
+	uint32_t i = 0, cframes = PLAT_INT_PERIOD_FRAMES;
 	struct list_item * blist;
 
 	trace_mixer("Mix");
@@ -222,7 +226,7 @@ static int mixer_copy(struct comp_dev *dev)
 	md->mix_func(dev, sink, sources, i, cframes);
 
 	/* update buffer pointers for overflow */
-	for(; i>0; i--) {
+	for(; i > 0; i--) {
 		if (sources[i-1]->r_ptr >= sources[i-1]->end_addr)
 			sources[i-1]->r_ptr = sources[i-1]->addr;
 		comp_update_buffer(sources[i-1]);
-- 
2.9.3



More information about the Sound-open-firmware mailing list