[Sound-open-firmware] [PATCH] EQ IIR: Get filter config and response switch via ABI

Seppo Ingalsuo seppo.ingalsuo at linux.intel.com
Mon Sep 25 15:13:59 CEST 2017


The IIR equalizer configure and control is updated to use the new
component ABI. In addition there are checks added to protect IIR
equalizer from invalid setup.

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
---
 src/audio/eq_iir.c    |  76 +++++++++++++++++---------------
 src/audio/eq_iir.h    |  47 --------------------
 src/include/uapi/eq.h | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 159 insertions(+), 83 deletions(-)
 create mode 100644 src/include/uapi/eq.h

diff --git a/src/audio/eq_iir.c b/src/audio/eq_iir.c
index 58a06a3..86f879a 100644
--- a/src/audio/eq_iir.c
+++ b/src/audio/eq_iir.c
@@ -44,6 +44,7 @@
 #include <reef/audio/pipeline.h>
 #include <reef/audio/format.h>
 #include <uapi/ipc.h>
+#include <uapi/eq.h>
 #include "eq_iir.h"
 #include "iir.h"
 
@@ -57,7 +58,7 @@
 
 /* src component private data */
 struct comp_data {
-	struct eq_iir_configuration *config;
+	struct sof_eq_iir_config *config;
 	uint32_t period_bytes;
 	struct iir_state_df2t iir[PLATFORM_MAX_CHANNELS];
 	void (*eq_iir_func)(struct comp_dev *dev,
@@ -120,7 +121,7 @@ static void eq_iir_s32_default(struct comp_dev *dev,
 	}
 }
 
-static void eq_iir_free_parameters(struct eq_iir_configuration **config)
+static void eq_iir_free_parameters(struct sof_eq_iir_config **config)
 {
 	if (*config != NULL)
 		rfree(*config);
@@ -150,27 +151,31 @@ static void eq_iir_free_delaylines(struct iir_state_df2t *iir)
 }
 
 static int eq_iir_setup(struct iir_state_df2t iir[],
-	struct eq_iir_configuration *config, int nch)
+	struct sof_eq_iir_config *config, int nch)
 {
 	int i, j, idx, resp;
 	size_t s;
 	size_t size_sum = 0;
 	int64_t *iir_delay; /* TODO should not need to know the type */
+	int32_t *coef_data, *assign_response;
 	int response_index[PLATFORM_MAX_CHANNELS];
 
-	if (nch > PLATFORM_MAX_CHANNELS)
-		return -EINVAL;
-
 	/* Free existing IIR channels data if it was allocated */
 	eq_iir_free_delaylines(iir);
 
+	if ((nch > PLATFORM_MAX_CHANNELS)
+		|| (config->channels_in_config > PLATFORM_MAX_CHANNELS))
+		return -EINVAL;
+
 	/* Collect index of respose start positions in all_coefficients[]  */
 	j = 0;
+	assign_response = &config->data[0];
+	coef_data = &config->data[config->channels_in_config];
 	for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) {
-		if (i < config->number_of_responses_defined) {
+		if (i < config->number_of_responses) {
 			response_index[i] = j;
 			j += NHEADER_DF2T
-				+ NBIQUAD_DF2T * config->all_coefficients[j];
+				+ NBIQUAD_DF2T * coef_data[j];
 		} else {
 			response_index[i] = 0;
 		}
@@ -178,15 +183,17 @@ static int eq_iir_setup(struct iir_state_df2t iir[],
 
 	/* Initialize 1st phase */
 	for (i = 0; i < nch; i++) {
-		resp = config->assign_response[i];
+		resp = assign_response[i];
+		if (resp > config->number_of_responses - 1)
+			return -EINVAL;
+
 		if (resp < 0) {
 			/* Initialize EQ channel to bypass */
 			iir_reset_df2t(&iir[i]);
 		} else {
 			/* Initialize EQ coefficients */
 			idx = response_index[resp];
-			s = iir_init_coef_df2t(&iir[i],
-				&config->all_coefficients[idx]);
+			s = iir_init_coef_df2t(&iir[i], &coef_data[idx]);
 			if (s > 0)
 				size_sum += s;
 			else
@@ -204,9 +211,8 @@ static int eq_iir_setup(struct iir_state_df2t iir[],
 
 	/* Initialize 2nd phase to set EQ delay lines pointers */
 	for (i = 0; i < nch; i++) {
-		resp = config->assign_response[i];
+		resp = assign_response[i];
 		if (resp >= 0) {
-			idx = response_index[resp];
 			iir_init_delay_df2t(&iir[i], &iir_delay);
 		}
 
@@ -216,18 +222,19 @@ static int eq_iir_setup(struct iir_state_df2t iir[],
 }
 
 static int eq_iir_switch_response(struct iir_state_df2t iir[],
-	struct eq_iir_configuration *config, struct eq_iir_update *update,
-	int nch)
+	struct sof_eq_iir_config *config,
+	struct sof_ipc_ctrl_value_comp compv[], uint32_t num_elemens, int nch)
 {
-	int i, ret;
+	int i, j, ret;
 
 	/* Copy assign response from update and re-initilize EQ */
 	if (config == NULL)
 		return -EINVAL;
 
-	for (i = 0; i < config->stream_max_channels; i++) {
-		if (i < update->stream_max_channels)
-			config->assign_response[i] = update->assign_response[i];
+	for (i = 0; i < num_elemens; i++) {
+		j = compv[i].index;
+		if (j < config->channels_in_config)
+			config->data[i] = compv[i].svalue;
 	}
 
 	ret = eq_iir_setup(iir, config, nch);
@@ -293,7 +300,11 @@ static int eq_iir_params(struct comp_dev *dev)
 
 	trace_eq_iir("par");
 
-	/* calculate period size based on config */
+	/* Calculate period size based on config. First make sure that
+	 * frame_bytes is set.
+	 */
+	dev->frame_bytes =
+		dev->params.sample_container_bytes * dev->params.channels;
 	cd->period_bytes = dev->frames * dev->frame_bytes;
 
 	/* configure downstream buffer */
@@ -316,21 +327,21 @@ static int eq_iir_params(struct comp_dev *dev)
 static int iir_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
 {
 	struct comp_data *cd = comp_get_drvdata(dev);
-	struct eq_iir_update *iir_update; /* TODO: move to IPC header as part of ABI */
+	struct sof_ipc_ctrl_value_comp *compv;
 	int i, ret = 0;
 	size_t bs;
 
 	switch (cdata->cmd) {
 	case SOF_CTRL_CMD_EQ_SWITCH:
 		trace_eq_iir("EFx");
-		iir_update = (struct eq_iir_update *) cdata->data;
+		compv = (struct sof_ipc_ctrl_value_comp *) cdata->data->data;
 		ret = eq_iir_switch_response(cd->iir, cd->config,
-			iir_update, PLATFORM_MAX_CHANNELS);
+			compv, cdata->num_elems, PLATFORM_MAX_CHANNELS);
 
 		/* Print trace information */
-		tracev_value(iir_update->stream_max_channels);
-		for (i = 0; i < iir_update->stream_max_channels; i++)
-			tracev_value(iir_update->assign_response[i]);
+		tracev_value(cd->config->channels_in_config);
+		for (i = 0; i < cd->config->channels_in_config; i++)
+			tracev_value(cd->config->data[i]);
 
 		break;
 	case SOF_CTRL_CMD_EQ_CONFIG:
@@ -339,8 +350,8 @@ static int iir_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
 		eq_iir_free_parameters(&cd->config);
 
 		/* Copy new config, need to decode data to know the size */
-		bs = cdata->num_elems;
-		if (bs > EQ_IIR_MAX_BLOB_SIZE)
+		bs = cdata->data->size;
+		if ((bs > SOF_EQ_IIR_MAX_SIZE) || (bs < 1))
 			return -EINVAL;
 
 		/* Allocate and make a copy of the blob and setup IIR */
@@ -348,18 +359,11 @@ static int iir_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
 		if (cd->config == NULL)
 			return -EINVAL;
 
-		memcpy(cd->config, cdata->data, bs);
+		memcpy(cd->config, cdata->data->data, bs);
 		/* Initialize all channels, the actual number of channels may
 		 * not be set yet.
 		 */
 		ret = eq_iir_setup(cd->iir, cd->config, PLATFORM_MAX_CHANNELS);
-
-		/* Print trace information */
-		tracev_value(cd->config->stream_max_channels);
-		tracev_value(cd->config->number_of_responses_defined);
-		for (i = 0; i < cd->config->stream_max_channels; i++)
-			tracev_value(cd->config->assign_response[i]);
-
 		break;
 	case SOF_CTRL_CMD_MUTE:
 		trace_eq_iir("EFm");
diff --git a/src/audio/eq_iir.h b/src/audio/eq_iir.h
index 42d95c1..e28a1a3 100644
--- a/src/audio/eq_iir.h
+++ b/src/audio/eq_iir.h
@@ -33,51 +33,4 @@
 #ifndef EQ_IIR_H
 #define EQ_IIR_H
 
-
-
-/* eq_iir_configuration
- *     uint32_t platform max channels
- *     uint32_t number_of_responses_defined
- *         0=no responses, 1=one response defined, 2=two responses defined, etc.
- *     uint32_t assign_response[PLATFORM_MAX_CHANNELS]
- *         -1 = not defined, 0 = use first response, 1 = use 2nd response, etc.
- *         E.g. {0, 0, 0, 0, -1, -1, -1, -1} would apply to channels 0-3 the
- *         same first defined response and leave channels 4-7 unequalized.
- *     all_coefficients[]
- *         <1st EQ>
- *         uint32_t num_biquads
- *         uint32_t num_biquads_in_series
- *         <1st biquad>
- *         int32_t coef_a2       Q2.30 format
- *         int32_t coef_a1       Q2.30 format
- *         int32_t coef_b2       Q2.30 format
- *         int32_t coef_b1       Q2.30 format
- *         int32_t coef_b0       Q2.30 format
- *         int32_t output_shift  number of shifts right, shift left is negative
- *         int32_t output_gain   Q2.14 format
- *         <2nd biquad>
- *         ...
- *         <2nd EQ>
- *
- *         Note: A flat response biquad can be made with a section set to
- *         b0 = 1.0, gain = 1.0, and other parameters set to 0
- *         {0, 0, 0, 0, 1073741824, 0, 16484}
- */
-
-#define EQ_IIR_MAX_BLOB_SIZE 1024 /* In bytes or size_t */
-
-#define NHEADER_EQ_IIR_BLOB 2 /* Blob is two words plus asssigns plus coef */
-
-struct eq_iir_configuration {
-	int32_t stream_max_channels;
-	int32_t number_of_responses_defined;
-	int32_t assign_response[PLATFORM_MAX_CHANNELS];
-	int32_t all_coefficients[];
-};
-
-struct eq_iir_update {
-	int32_t stream_max_channels;
-	int32_t assign_response[PLATFORM_MAX_CHANNELS];
-};
-
 #endif
diff --git a/src/include/uapi/eq.h b/src/include/uapi/eq.h
new file mode 100644
index 0000000..9c42a51
--- /dev/null
+++ b/src/include/uapi/eq.h
@@ -0,0 +1,119 @@
+/*
+ * 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 EQ_H
+#define EQ_H
+
+/* FIR EQ type */
+
+/* Component will reject non-matching configuration. The version number need
+ * to be incremented with any ABI changes in function fir_cmd().
+ */
+#define SOF_EQ_FIR_ABI_VERSION 1
+
+#define SOF_EQ_FIR_MAX_SIZE 4096 /* Max size allowed for coef data in bytes */
+
+/*
+ * eq_fir_configuration data structure contains this information
+ *     uint16_t channels_in_config
+ *         This describes the number of channels in this EQ config data. It
+ *         can be different from PLATFORM_MAX_CHANNELS.
+ *     uint16_t number_of_responses
+ *         0=no responses, 1=one response defined, 2=two responses defined, etc.
+ *     int16_t data[]
+ *         assign_response[STREAM_MAX_CHANNELS]
+ *             -1 = not defined, 0 = use first response, 1 = use 2nd response, etc.
+ *             E.g. {0, 0, 0, 0, -1, -1, -1, -1} would apply to channels 0-3 the
+ *	       same first defined response and leave channels 4-7 unequalized.
+ *         coef_data[]
+ *             Repeated data { filter_length, input_shift, output_shift, h[] }
+ *	       for every EQ response defined where vector h has filter_length 
+ *             number of coefficients. Coefficients in h[] are in Q1.15 format.
+ *             E.g. 16384 (Q1.15) = 0.5. The shifts are number of right shifts.
+ */
+
+struct sof_eq_fir_config {
+	uint16_t channels_in_config;
+	uint16_t number_of_responses;
+	int16_t data[];
+};
+
+/* IIR EQ type */
+
+/* Component will reject non-matching configuration. The version number need
+ * to be incremented with any ABI changes in function fir_cmd().
+ */
+#define SOF_EQ_FIR_ABI_VERSION 1
+
+#define SOF_EQ_IIR_MAX_SIZE 1024 /* Max size allowed for coef data in bytes */
+
+/* eq_iir_configuration
+ *     uint32_t channels_in_config
+ *         This describes the number of channels in this EQ config data. It
+ *         can be different from PLATFORM_MAX_CHANNELS.
+ *     uint32_t number_of_responses_defined
+ *         0=no responses, 1=one response defined, 2=two responses defined, etc.
+ *     int32_t data[]
+ *         Data consist of two parts. First is the response assign vector that
+ *	   has length of channels_in_config. The latter part is coefficient
+ *         data.
+ *         uint32_t assign_response[channels_in_config]
+ *             -1 = not defined, 0 = use first response, 1 = use 2nd, etc.
+ *             E.g. {0, 0, 0, 0, -1, -1, -1, -1} would apply to channels 0-3 the
+ *             same first defined response and leave channels 4-7 unequalized.
+ *         coefficient_data[]
+ *             <1st EQ>
+ *             uint32_t num_biquads
+ *             uint32_t num_biquads_in_series
+ *             <1st biquad>
+ *             int32_t coef_a2       Q2.30 format
+ *             int32_t coef_a1       Q2.30 format
+ *             int32_t coef_b2       Q2.30 format
+ *             int32_t coef_b1       Q2.30 format
+ *             int32_t coef_b0       Q2.30 format
+ *             int32_t output_shift  number of shifts right, shift left is negative
+ *             int32_t output_gain   Q2.14 format
+ *             <2nd biquad>
+ *             ...
+ *             <2nd EQ>
+ *
+ *         Note: A flat response biquad can be made with a section set to
+ *         b0 = 1.0, gain = 1.0, and other parameters set to 0
+ *         {0, 0, 0, 0, 1073741824, 0, 16484}
+ */
+
+struct sof_eq_iir_config {
+	uint32_t channels_in_config;
+	uint32_t number_of_responses;
+	int32_t data[];
+};
+
+#endif /* EQ_H */
+
-- 
2.11.0



More information about the Sound-open-firmware mailing list