[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