[Sound-open-firmware] [PATCH 4/5] SRC: Add S24_4LE format and platform specific coefficient set

Seppo Ingalsuo seppo.ingalsuo at linux.intel.com
Thu Sep 14 15:00:05 CEST 2017


This patch adds missing S24_4LE format. Input and output format need to
be still the same. The filter coefficient set is configured in
src_config.h per platform. BYT uses a small int24 set, other use
standard int24 set. SRC wasnot unmuted by pipeline so in this version
SRC initialized to unmuted state.

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
---
 src/audio/src.c        |  35 ++++++++++----
 src/audio/src_config.h |  47 +++++++++++++++++++
 src/audio/src_core.c   | 124 ++++++++++++++++++++++++++++++++++++++++++-------
 src/audio/src_core.h   |  12 +----
 4 files changed, 183 insertions(+), 35 deletions(-)
 create mode 100644 src/audio/src_config.h

diff --git a/src/audio/src.c b/src/audio/src.c
index 2ecf025..bc32f95 100644
--- a/src/audio/src.c
+++ b/src/audio/src.c
@@ -57,10 +57,11 @@
 struct comp_data {
 	struct polyphase_src src[PLATFORM_MAX_CHANNELS];
 	int32_t *delay_lines;
-	int scratch_length;
 	uint32_t sink_rate;
 	uint32_t source_rate;
 	uint32_t period_bytes; /* sink period */
+	int scratch_length; /* Buffer for stage1-stage2 */
+	int sign_extend_s24; /* Set if need to copy sign bit to b24..b31 */
 	void (*src_func)(struct comp_dev *dev,
 		struct comp_buffer *source,
 		struct comp_buffer *sink,
@@ -154,12 +155,12 @@ static void src_2s_s32_default(struct comp_dev *dev,
 	s1.x_size = source->size;
 	s1.x_inc = nch;
 	s1.y_end_addr = &cd->delay_lines[cd->scratch_length];
-	s1.y_size = STAGE_BUF_SIZE * sizeof(int32_t);
+	s1.y_size = cd->scratch_length * sizeof(int32_t);
 	s1.y_inc = 1;
 
 	s2.times = n_times2;
 	s2.x_end_addr = &cd->delay_lines[cd->scratch_length];
-	s2.x_size = STAGE_BUF_SIZE * sizeof(int32_t);
+	s2.x_size = cd->scratch_length * sizeof(int32_t);
 	s2.x_inc = 1;
 	s2.y_end_addr = sink->end_addr;
 	s2.y_size = sink->size;
@@ -180,9 +181,14 @@ static void src_2s_s32_default(struct comp_dev *dev,
 		for (i = 0; i < source_frames - blk_in + 1; i += blk_in) {
 			/* Reset output to buffer start, read interleaved */
 			s1.y_wptr = cd->delay_lines;
-			src_polyphase_stage_cir(&s1);
 			s2.x_rptr = cd->delay_lines;
-			src_polyphase_stage_cir(&s2);
+			if (cd->sign_extend_s24) {
+				src_polyphase_stage_cir_s24(&s1);
+				src_polyphase_stage_cir_s24(&s2);
+			} else {
+				src_polyphase_stage_cir(&s1);
+				src_polyphase_stage_cir(&s2);
+			}
 
 			n_read += blk_in;
 			n_written += blk_out;
@@ -198,7 +204,6 @@ static void src_1s_s32_default(struct comp_dev *dev,
 	uint32_t source_frames, uint32_t sink_frames)
 {
 	int i, j;
-	//int32_t *xp, *yp;
 	struct polyphase_src *s;
 
 	struct comp_data *cd = comp_get_drvdata(dev);
@@ -236,7 +241,10 @@ static void src_1s_s32_default(struct comp_dev *dev,
 		s1.stage = s->stage1;
 
 		for (i = 0; i + blk_in - 1 < source_frames; i += blk_in) {
-			src_polyphase_stage_cir(&s1);
+			if (cd->sign_extend_s24)
+				src_polyphase_stage_cir_s24(&s1);
+			else
+				src_polyphase_stage_cir(&s1);
 
 			n_read += blk_in;
 			n_written += blk_out;
@@ -317,8 +325,15 @@ static int src_params(struct comp_dev *dev)
 
 	trace_src("par");
 
-	/* SRC supports only S32_LE PCM format */
-	if (config->frame_fmt != SOF_IPC_FRAME_S32_LE) {
+	/* SRC supports S24_4LE and S32_LE formats */
+	switch (config->frame_fmt) {
+	case SOF_IPC_FRAME_S24_4LE:
+		cd->sign_extend_s24 = 1;
+		break;
+	case SOF_IPC_FRAME_S32_LE:
+		cd->sign_extend_s24 = 0;
+		break;
+	default:
 		trace_src_error("sr0");
 		return -EINVAL;
 	}
@@ -423,6 +438,8 @@ static int src_params(struct comp_dev *dev)
 	err = buffer_set_size(sink, q * dev->frames * dev->frame_bytes);
 	if (err < 0) {
 		trace_src_error("eSz");
+		trace_value(sink->alloc_size);
+		trace_value(q * dev->frames * dev->frame_bytes);
 		return err;
 	}
 
diff --git a/src/audio/src_config.h b/src/audio/src_config.h
new file mode 100644
index 0000000..f983723
--- /dev/null
+++ b/src/audio/src_config.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of the Intel Corporation nor the
+ *     names of its contributors may be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+ *
+ */
+
+#ifndef SRC_CONFIG_H
+#define SRC_CONFIG_H
+
+#include <config.h>
+
+#if CONFIG_BAYTRAIL
+#define SRC_SHORT 0
+#include <reef/audio/coefficients/src/src_small_int24_define.h>
+#include <reef/audio/coefficients/src/src_small_int24_table.h>
+#else
+#define SHORT_SHORT 0
+#include <reef/audio/coefficients/src/src_std_int24_define.h>
+#include <reef/audio/coefficients/src/src_std_int24_table.h>
+#endif
+
+#endif
diff --git a/src/audio/src_core.c b/src/audio/src_core.c
index a9331a0..342e8a7 100644
--- a/src/audio/src_core.c
+++ b/src/audio/src_core.c
@@ -43,13 +43,7 @@
 #include <reef/audio/format.h>
 #include <reef/math/numbers.h>
 #include "src_core.h"
-
-/* Include conversion tables */
-#if SRC_SHORT == 1
-#include <reef/audio/coefficients/src/src_int16_table.h>
-#else
-#include <reef/audio/coefficients/src/src_int24_table.h>
-#endif
+#include "src_config.h"
 
 /* TODO: These should be defined somewhere else. */
 #define SOF_RATES_LENGTH 15
@@ -256,7 +250,7 @@ static int init_stages(
 void src_polyphase_reset(struct polyphase_src *src)
 {
 
-	src->mute = 1;
+	src->mute = 0;
 	src->number_of_stages = 0;
 	src->blk_in = 0;
 	src->blk_out = 0;
@@ -401,15 +395,8 @@ static inline int32_t fir_filter(
 
 void src_polyphase_stage_cir(struct src_stage_prm *s)
 {
-	int n;
-	int m;
-	int f;
-	int c;
-	int r;
+	int n, m, f, c, r, n_wrap_fir, n_wrap_buf, n_wrap_min;
 	int32_t z;
-	int n_wrap_fir;
-	int n_wrap_buf;
-	int n_wrap_min;
 
 	for (n = 0; n < s->times; n++) {
 		/* Input data */
@@ -510,6 +497,111 @@ void src_polyphase_stage_cir(struct src_stage_prm *s)
 	}
 }
 
+void src_polyphase_stage_cir_s24(struct src_stage_prm *s)
+{
+	int n, m, f, c, r, n_wrap_fir, n_wrap_buf, n_wrap_min;
+	int32_t se, z;
+
+	for (n = 0; n < s->times; n++) {
+		/* Input data */
+		m = s->x_inc * s->stage->blk_in;
+		while (m > 0) {
+			n_wrap_fir =
+				(s->state->fir_delay_size - s->state->fir_wi)
+				* s->x_inc;
+			n_wrap_buf = s->x_end_addr - s->x_rptr;
+			n_wrap_min = (n_wrap_fir < n_wrap_buf)
+				? n_wrap_fir : n_wrap_buf;
+			if (m < n_wrap_min) {
+				/* No circular wrap need */
+				while (m > 0) {
+					se = *s->x_rptr << 8;
+					s->state->fir_delay[s->state->fir_wi++]
+						= se >> 8;
+					s->x_rptr += s->x_inc;
+					m -= s->x_inc;
+				}
+			} else {
+				/* Wrap in n_wrap_min/x_inc samples */
+				while (n_wrap_min > 0) {
+					se = *s->x_rptr << 8;
+					s->state->fir_delay[s->state->fir_wi++]
+						= se >> 8;
+					s->x_rptr += s->x_inc;
+					n_wrap_min -= s->x_inc;
+					m -= s->x_inc;
+				}
+				/* Check both */
+				if (s->x_rptr >= s->x_end_addr)
+					s->x_rptr = (int32_t *)
+					((size_t) s->x_rptr - s->x_size);
+				if (s->state->fir_wi
+					== s->state->fir_delay_size)
+					s->state->fir_wi = 0;
+			}
+		}
+
+		/* Filter */
+		c = 0;
+		r = s->state->fir_wi - s->stage->blk_in
+			- (s->stage->num_of_subfilters - 1) * s->stage->idm;
+		if (r < 0)
+			r += s->state->fir_delay_size;
+
+		s->state->out_wi = s->state->out_ri;
+		for (f = 0; f < s->stage->num_of_subfilters; f++) {
+			s->state->fir_ri = r;
+			z = fir_filter(s->state, s->stage->coefs, &c,
+				s->stage->subfilter_length, s->stage->shift);
+			r += s->stage->idm;
+			if (r > s->state->fir_delay_size - 1)
+				r -= s->state->fir_delay_size;
+
+			s->state->out_delay[s->state->out_wi] = z;
+			s->state->out_wi += s->stage->odm;
+			if (s->state->out_wi > s->state->out_delay_size - 1)
+				s->state->out_wi -= s->state->out_delay_size;
+		}
+
+		/* Output */
+		m = s->y_inc * s->stage->num_of_subfilters;
+		while (m > 0) {
+			n_wrap_fir =
+				(s->state->out_delay_size - s->state->out_ri)
+				* s->y_inc;
+			n_wrap_buf = s->y_end_addr - s->y_wptr;
+			n_wrap_min = (n_wrap_fir < n_wrap_buf)
+				? n_wrap_fir : n_wrap_buf;
+			if (m < n_wrap_min) {
+				/* No circular wrap need */
+				while (m > 0) {
+					*s->y_wptr = s->state->out_delay[
+						s->state->out_ri++];
+					s->y_wptr += s->y_inc;
+					m -= s->y_inc;
+				}
+			} else {
+				/* Wrap in n_wrap_min/y_inc samples */
+				while (n_wrap_min > 0) {
+					*s->y_wptr = s->state->out_delay[
+						s->state->out_ri++];
+					s->y_wptr += s->y_inc;
+					n_wrap_min -= s->y_inc;
+					m -= s->y_inc;
+				}
+				/* Check both */
+				if (s->y_wptr >= s->y_end_addr)
+					s->y_wptr =
+					(int32_t *)
+					((size_t) s->y_wptr - s->y_size);
+
+				if (s->state->out_ri
+					== s->state->out_delay_size)
+					s->state->out_ri = 0;
+			}
+		}
+	}
+}
 
 #ifdef MODULE_TEST
 
diff --git a/src/audio/src_core.h b/src/audio/src_core.h
index ae1223a..5977421 100644
--- a/src/audio/src_core.h
+++ b/src/audio/src_core.h
@@ -32,18 +32,8 @@
 #ifndef SRC_CORE_H
 #define SRC_CORE_H
 
-/* TODO: This should be made per platform configurable */
-#define SRC_SHORT 1
-
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 
-/* Include SRC min/max constants etc. */
-#if SRC_SHORT == 1
-#include <reef/audio/coefficients/src/src_int16_define.h>
-#else
-#include <reef/audio/coefficients/src/src_int24_define.h>
-#endif
-
 struct src_alloc {
 	int fir_s1;
 	int fir_s2;
@@ -151,6 +141,8 @@ int src_polyphase(struct polyphase_src *src, int32_t x[], int32_t y[],
 
 void src_polyphase_stage_cir(struct src_stage_prm *s);
 
+void src_polyphase_stage_cir_s24(struct src_stage_prm *s);
+
 int src_buffer_lengths(struct src_alloc *a, int fs_in, int fs_out, int nch,
 	int max_frames, int max_frames_is_for_source);
 
-- 
2.11.0



More information about the Sound-open-firmware mailing list