Sound-open-firmware
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
October 2017
- 7 participants
- 26 discussions
Hi Sven,
Btw, best to subscribe as non member posts are blocked and delayed.
On Tue, 2017-10-17 at 20:49 +0200, Sven Schwermer wrote:
> Hi guys,
>
> Thanks for your replies. I had tried a running a vanilla kernel on the
> Edison. There, the sst_pci driver is probed, but the platform data is
> not set and that’s basically where I got stuck because I couldn’t
> figure out where that’s supposed to be set. Is that usually ACPI’s
> job?
>
I dont think ACPI is used by the ADSP on Edison, I think it's purely a
PCI device. Vanilla kernel wont work either atm, you will need my
topic/sof-v4.13 branch from here :-
git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc.git
Note that this branch only works on the SOF 1.0-dev branches (that are
not stable) and not the stable master branch.
The stable SOF master firmware branch has a different IPC ABI and only
works with the topic/reef kernels (that unfortunately dont support PCI
mode on Edison) :(
> What exactly should happen once the mrfld_sst SFI IPC is enumerated? I
> am lacking the big picture and the order of events here. Is there an
> overview document somewhere available online?
>
There is also more than one driver upstream. The sst driver is for
Intel's closed source FW. The open source FW uses different ABIs and
APIs to the closed source version, currently you need to blacklist the
old SST modules in order to load the SOF FW and driver (this is being
fixed in upstream atm)
> I guess, the nocodec mode would be fine as a start.
>
Yes.
Liam
> Thanks, Sven
>
> > On 16 Oct 2017, at 17:59, Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com> wrote:
> >
> > On 10/16/17 10:19 AM, Liam Girdwood wrote:
> >> On Sun, 2017-10-15 at 19:51 +0200, Sven Schwermer wrote:
> >>> Hi.
> >>>
> >>> I was wondering if the Tangier SoC (Merrifield platform) is or will be
> >>> supported by SOF? I have the Intel Edison compute module in mind.
> >>>
> >> Yes, it _should_ work on Merrifield, but I don't have Edison HW so some
> >> things on the driver side might need some work.
> >> The 1.0-dev branch and sof-v4.13 kernel will probably be better for
> >> Edison than the stable 0.95 branch atm (mainly due to driver updates),
> >> but 1.0-dev is still has a few issues prior to doing an rc1 tag.
> >
> > The main difference with Baytrail is pci/acpi enumeration, and sfi/acpi for the firmware. I've been wanting to enable Tangier for some time but could never figure out how to add a reference to an audio codec, so it'd likely work in 'nocodec' mode, with just the I2S signals on the connector.
>
4
10
[Sound-open-firmware] [PATCH] Volume, FIR EQ, IIR EQ, tone: Fix SOF_CTRL_CMD_SWITCH polarity
by Seppo Ingalsuo 30 Oct '17
by Seppo Ingalsuo 30 Oct '17
30 Oct '17
This patch inverts the use of switch value. A non-zero value
unmutes the audio path.
Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo(a)linux.intel.com>
---
src/audio/eq_fir.c | 11 +++++++----
src/audio/eq_iir.c | 9 +++++----
src/audio/tone.c | 9 +++++----
src/audio/volume.c | 6 +++---
4 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/src/audio/eq_fir.c b/src/audio/eq_fir.c
index 9056808..8babed3 100644
--- a/src/audio/eq_fir.c
+++ b/src/audio/eq_fir.c
@@ -33,6 +33,7 @@
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
+#include <stdbool.h>
#include <reef/reef.h>
#include <reef/lock.h>
#include <reef/list.h>
@@ -330,21 +331,23 @@ static int fir_cmd_set_value(struct comp_dev *dev, struct sof_ipc_ctrl_data *cda
struct comp_data *cd = comp_get_drvdata(dev);
int j;
uint32_t ch;
+ bool val;
if (cdata->cmd == SOF_CTRL_CMD_SWITCH) {
trace_eq("mst");
for (j = 0; j < cdata->num_elems; j++) {
ch = cdata->chanv[j].channel;
+ val = cdata->chanv[j].value;
tracev_value(ch);
- tracev_value(cdata->chanv[j].value);
+ tracev_value(val);
if (ch >= PLATFORM_MAX_CHANNELS) {
trace_eq_error("che");
return -EINVAL;
}
- if (cdata->chanv[j].value > 0)
- fir_mute(&cd->fir[ch]);
- else
+ if (val)
fir_unmute(&cd->fir[ch]);
+ else
+ fir_mute(&cd->fir[ch]);
}
} else {
trace_eq_error("ste");
diff --git a/src/audio/eq_iir.c b/src/audio/eq_iir.c
index d3a8fa3..88382fe 100644
--- a/src/audio/eq_iir.c
+++ b/src/audio/eq_iir.c
@@ -33,6 +33,7 @@
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
+#include <stdbool.h>
#include <reef/reef.h>
#include <reef/lock.h>
#include <reef/list.h>
@@ -331,7 +332,7 @@ static int iir_cmd_set_value(struct comp_dev *dev, struct sof_ipc_ctrl_data *cda
struct comp_data *cd = comp_get_drvdata(dev);
int j;
uint32_t ch;
- uint32_t val;
+ bool val;
if (cdata->cmd == SOF_CTRL_CMD_SWITCH) {
trace_eq_iir("mst");
@@ -344,10 +345,10 @@ static int iir_cmd_set_value(struct comp_dev *dev, struct sof_ipc_ctrl_data *cda
trace_eq_iir_error("che");
return -EINVAL;
}
- if (val > 0)
- iir_mute_df2t(&cd->iir[ch]);
- else
+ if (val)
iir_unmute_df2t(&cd->iir[ch]);
+ else
+ iir_mute_df2t(&cd->iir[ch]);
}
} else {
trace_eq_iir_error("ste");
diff --git a/src/audio/tone.c b/src/audio/tone.c
index d565c17..3eb08e9 100644
--- a/src/audio/tone.c
+++ b/src/audio/tone.c
@@ -33,6 +33,7 @@
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
+#include <stdbool.h>
#include <reef/reef.h>
#include <reef/lock.h>
#include <reef/list.h>
@@ -466,7 +467,7 @@ static int tone_cmd_set_value(struct comp_dev *dev, struct sof_ipc_ctrl_data *cd
struct comp_data *cd = comp_get_drvdata(dev);
int j;
uint32_t ch;
- uint32_t val;
+ bool val;
if (cdata->cmd == SOF_CTRL_CMD_SWITCH) {
trace_tone("mst");
@@ -479,10 +480,10 @@ static int tone_cmd_set_value(struct comp_dev *dev, struct sof_ipc_ctrl_data *cd
trace_tone_error("che");
return -EINVAL;
}
- if (val > 0)
- tonegen_mute(&cd->sg[ch]);
- else
+ if (val)
tonegen_unmute(&cd->sg[ch]);
+ else
+ tonegen_mute(&cd->sg[ch]);
}
} else {
diff --git a/src/audio/volume.c b/src/audio/volume.c
index 28d3225..f52ab46 100644
--- a/src/audio/volume.c
+++ b/src/audio/volume.c
@@ -468,10 +468,10 @@ static int volume_ctrl_set_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *c
tracev_value(cdata->chanv[j].channel);
tracev_value(cdata->chanv[j].value);
if (cdata->chanv[j].channel == cd->chan[i]) {
- if (cdata->chanv[j].value > 0)
- volume_set_chan_mute(dev, i);
- else
+ if (cdata->chanv[j].value)
volume_set_chan_unmute(dev, i);
+ else
+ volume_set_chan_mute(dev, i);
}
}
}
--
2.11.0
2
1
[Sound-open-firmware] [PATCH 1/5] IPC: Add new enum commands and an index into control data struct
by Seppo Ingalsuo 24 Oct '17
by Seppo Ingalsuo 24 Oct '17
24 Oct '17
This patch adds to struct sof_ipc_ctrl_data three new commands
SOF_CTRL_CMD_ENUM, SOF_CTRL_CMD_SWITCH, and SOF_CTRL_CMD_BINARY. In
addition an index parameter is added to address various features or
registers.
Commands SOF_CTRL_CMD_ROUTE, SOF_CTRL_CMD_SRC, SOF_CTRL_CMD_LOOPBACK,
SOF_CTRL_CMD_EQ_SWITCH, SOF_CTRL_CMD_EQ_CONFIG, SOF_CTRL_CMD_MUTE, and
SOF_CTRL_CMD_UNMUTE are removed.
Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo(a)linux.intel.com>
---
src/include/uapi/ipc.h | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h
index 281e77a..5658b9a 100644
--- a/src/include/uapi/ipc.h
+++ b/src/include/uapi/ipc.h
@@ -437,25 +437,23 @@ struct sof_ipc_stream_posn {
/* control data type and direction */
enum sof_ipc_ctrl_type {
+ /* per channel data - uses struct sof_ipc_ctrl_value_chan */
SOF_CTRL_TYPE_VALUE_CHAN_GET = 0,
SOF_CTRL_TYPE_VALUE_CHAN_SET,
+ /* per component data - uses struct sof_ipc_ctrl_value_comp */
SOF_CTRL_TYPE_VALUE_COMP_GET,
SOF_CTRL_TYPE_VALUE_COMP_SET,
+ /* bespoke data - struct struct sof_abi_hdr */
SOF_CTRL_TYPE_DATA_GET,
SOF_CTRL_TYPE_DATA_SET,
};
/* control command type */
enum sof_ipc_ctrl_cmd {
- SOF_CTRL_CMD_VOLUME = 0,
- SOF_CTRL_CMD_ROUTE,
- SOF_CTRL_CMD_SRC,
- SOF_CTRL_CMD_LOOPBACK,
- SOF_CTRL_CMD_EQ_SWITCH,
- SOF_CTRL_CMD_EQ_CONFIG,
- /* Mute is similar to volume, but maps better onto ALSA switch controls */
- SOF_CTRL_CMD_MUTE,
- SOF_CTRL_CMD_UNMUTE,
+ SOF_CTRL_CMD_VOLUME = 0, /* maps to ALSA volume style controls */
+ SOF_CTRL_CMD_ENUM, /* maps to ALSA enum style controls */
+ SOF_CTRL_CMD_SWITCH, /* maps to ALSA switch style controls */
+ SOF_CTRL_CMD_BINARY, /* maps to ALSA binary style controls */
};
/* generic channel mapped value data */
@@ -481,6 +479,7 @@ struct sof_ipc_ctrl_data {
/* control access and data type */
enum sof_ipc_ctrl_type type;
enum sof_ipc_ctrl_cmd cmd;
+ uint32_t index; /* control index for comps > 1 control */
/* control data - can either be appended or DMAed from host */
struct sof_ipc_host_buffer buffer;
@@ -497,7 +496,6 @@ struct sof_ipc_ctrl_data {
};
} __attribute__((packed));
-
/*
* Component
*/
--
2.11.0
2
10
[Sound-open-firmware] [PATCH V2] SRC: Use a multi-channel FIR core to optimize speed plus other cleanup
by Seppo Ingalsuo 20 Oct '17
by Seppo Ingalsuo 20 Oct '17
20 Oct '17
This patch changes the sample rate conversion processing to use a single
multi-channel filter instead of per channel called mono filter instances.
The filter output is now rounded with 1/2 LSB add. The polyphase filter
input input block sizes are multiplied in SRC initialization to reach
near to or exacly the period length to reduce polyphase filter call
overhead.
The polyphase filter is now called via function pointer for more
flexibility with audio data formats. Currently S32_LE and S24_4LE are
supported.
Code cleanup includes removal of redundant variables and some debug
print code.
Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo(a)linux.intel.com>
---
src/audio/src.c | 200 +++++++++++------------
src/audio/src_core.c | 448 +++++++++++++++++++++++++++------------------------
src/audio/src_core.h | 42 +----
3 files changed, 329 insertions(+), 361 deletions(-)
diff --git a/src/audio/src.c b/src/audio/src.c
index 4c4bc6e..9fe81d3 100644
--- a/src/audio/src.c
+++ b/src/audio/src.c
@@ -55,7 +55,7 @@
/* src component private data */
struct comp_data {
- struct polyphase_src src[PLATFORM_MAX_CHANNELS];
+ struct polyphase_src src;
struct src_param param;
int32_t *delay_lines;
uint32_t sink_rate;
@@ -63,16 +63,16 @@ struct comp_data {
int32_t *sbuf_w_ptr;
int32_t *sbuf_r_ptr;
int sbuf_avail;
- 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,
size_t *consumed,
size_t *produced);
+ void (* polyphase_func)(struct src_stage_prm *s);
};
/* Fallback function */
-static void fallback_s32(struct comp_dev *dev, struct comp_buffer *source,
+static void src_fallback(struct comp_dev *dev, struct comp_buffer *source,
struct comp_buffer *sink, size_t *bytes_read, size_t *bytes_written)
{
*bytes_read = 0;
@@ -84,101 +84,110 @@ static void src_2s_s32_default(struct comp_dev *dev,
struct comp_buffer *source, struct comp_buffer *sink,
size_t *bytes_read, size_t *bytes_written)
{
- struct polyphase_src *s;
struct src_stage_prm s1;
struct src_stage_prm s2;
- int j;
+ int s1_blk_in;
+ int s1_blk_out;
+ int s2_blk_in;
+ int s2_blk_out;
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *dest = (int32_t *) sink->w_ptr;
int32_t *src = (int32_t *) source->r_ptr;
- int32_t *sbuf_addr = cd->delay_lines;
int32_t *sbuf_end_addr = &cd->delay_lines[cd->param.sbuf_length];
int32_t sbuf_size = cd->param.sbuf_length * sizeof(int32_t);
- const int nch = dev->params.channels;
- const int s1_blk_in = cd->src[0].stage1->blk_in * nch;
- const int s1_blk_out = cd->src[0].stage1->blk_out * nch;
- const int s2_blk_in = cd->src[0].stage2->blk_in * nch;
- const int s2_blk_out = cd->src[0].stage2->blk_out * nch;
+ int nch = dev->params.channels;
int sbuf_free = cd->param.sbuf_length - cd->sbuf_avail;
- int source_check = (source->avail >> 2) - s1_blk_in; /* for int32_t */
- int sink_check = (sink->free >> 2) - s2_blk_out; /* For int32_t */
int n_read = 0;
int n_written = 0;
int n1 = 0;
int n2 = 0;
+ int avail_b = source->avail;
+ int free_b = sink->free;
+ int sz = sizeof(int32_t);
- s1.times = 1;
s1.x_end_addr = source->end_addr;
s1.x_size = source->size;
- s1.x_inc = nch;
s1.y_end_addr = sbuf_end_addr;
s1.y_size = sbuf_size;
- s1.y_inc = nch;
+ s1.state = &cd->src.state1;
+ s1.stage = cd->src.stage1;
+ s1.x_rptr = src;
+ s1.y_wptr = cd->sbuf_w_ptr;
+ s1.nch = nch;
- s2.times = 1;
s2.x_end_addr = sbuf_end_addr;
s2.x_size = sbuf_size;
- s2.x_inc = nch;
s2.y_end_addr = sink->end_addr;
s2.y_size = sink->size;
- s2.y_inc = nch;
+ s2.state = &cd->src.state2;
+ s2.stage = cd->src.stage2;
+ s2.x_rptr = cd->sbuf_r_ptr;
+ s2.y_wptr = dest;
+ s2.nch = nch;
+
- /* 1st stage runs once a long multiplied length block.
- * The stage buffer much be large enough to fit one s1 output block
- * plus one s2 input block plus jitter in s2 consumption.
+ /* Test if 1st stage can be run with default block length to reach
+ * the period length or just under it.
*/
- while ((n1 < cd->param.stage1_times_max)
- && (n_read <= source_check)
- && (sbuf_free >= s1_blk_out)) {
- for (j = 0; j < nch; j++) {
- s = &cd->src[j]; /* Point to src[] for this channel */
- s1.x_rptr = src++;
- s1.y_wptr = cd->sbuf_w_ptr++;
- src_circ_inc_wrap(&src, source->end_addr, source->size);
- src_circ_inc_wrap(&cd->sbuf_w_ptr, sbuf_end_addr, sbuf_size);
- s1.state = &s->state1;
- s1.stage = s->stage1;
- if (cd->sign_extend_s24)
- src_polyphase_stage_cir_s24(&s1);
- else
- src_polyphase_stage_cir(&s1);
-
- }
+ s1.times = cd->param.stage1_times;
+ s1_blk_in = s1.times * cd->src.stage1->blk_in * nch;
+ s1_blk_out = s1.times * cd->src.stage1->blk_out * nch;
+ if ((avail_b >= s1_blk_in * sz) && (sbuf_free >= s1_blk_out)) {
+ cd->polyphase_func(&s1);
+
+ cd->sbuf_w_ptr = s1.y_wptr;
+ cd->sbuf_avail += s1_blk_out;
n_read += s1_blk_in;
+ avail_b -= s1_blk_in * sz;
+ sbuf_free -= s1_blk_out;
+ n1 = s1.times;
+ }
+
+ /* Run one block at time the remaining data for 1st stage. */
+ s1.times = 1;
+ s1_blk_in = cd->src.stage1->blk_in * nch;
+ s1_blk_out = cd->src.stage1->blk_out * nch;
+ while ((n1 < cd->param.stage1_times_max) && (avail_b >= s1_blk_in * sz)
+ && (sbuf_free >= s1_blk_out)) {
+ cd->polyphase_func(&s1);
+
+ cd->sbuf_w_ptr = s1.y_wptr;
cd->sbuf_avail += s1_blk_out;
+ n_read += s1_blk_in;
+ avail_b -= s1_blk_in * sz;
sbuf_free -= s1_blk_out;
- src = s1.x_rptr - nch + 1;
- cd->sbuf_w_ptr = s1.y_wptr - nch + 1;
- src_circ_dec_wrap(&src, source->addr, source->size);
- src_circ_dec_wrap(&cd->sbuf_w_ptr, sbuf_addr, sbuf_size);
- n1++;
+ n1 += s1.times;
+ }
+
+ /* Test if 2nd stage can be run with default block length. */
+ s2.times = cd->param.stage2_times;
+ s2_blk_in = s2.times * cd->src.stage2->blk_in * nch;
+ s2_blk_out = s2.times * cd->src.stage2->blk_out * nch;
+ if ((cd->sbuf_avail >= s2_blk_in) && (free_b >= s2_blk_out * sz)) {
+ cd->polyphase_func(&s2);
+
+ cd->sbuf_r_ptr = s2.x_rptr;
+ cd->sbuf_avail -= s2_blk_in;
+ free_b -= s2_blk_out * sz;
+ n_written += s2_blk_out;
+ n2 = s2.times;
}
- /* 2nd stage runs as many min size blocks as buffers allow */
+
+ /* Run one block at time the remaining 2nd stage output */
+ s2.times = 1;
+ s2_blk_in = cd->src.stage2->blk_in * nch;
+ s2_blk_out = cd->src.stage2->blk_out * nch;
while ((n2 < cd->param.stage2_times_max)
&& (cd->sbuf_avail >= s2_blk_in)
- && (n_written <= sink_check)) {
- for (j = 0; j < nch; j++) {
- s2.x_rptr = cd->sbuf_r_ptr++;
- s2.y_wptr = dest++;
- src_circ_inc_wrap(&cd->sbuf_r_ptr, sbuf_end_addr, sbuf_size);
- src_circ_inc_wrap(&dest, sink->end_addr, sink->size);
- s = &cd->src[j]; /* Point to src[] for this channel */
- s2.state = &s->state2;
- s2.stage = s->stage2;
- if (cd->sign_extend_s24)
- src_polyphase_stage_cir_s24(&s2);
- else
- src_polyphase_stage_cir(&s2);
-
- }
- cd->sbuf_r_ptr = s2.x_rptr - nch + 1;
- dest = s2.y_wptr - nch + 1;
- src_circ_dec_wrap(&cd->sbuf_r_ptr, sbuf_addr, sbuf_size);
- src_circ_dec_wrap(&dest, sink->addr, sink->size);
- n_written += s2_blk_out;
+ && (free_b >= s2_blk_out * sz)) {
+ cd->polyphase_func(&s2);
+
+ cd->sbuf_r_ptr = s2.x_rptr;
cd->sbuf_avail -= s2_blk_in;
- n2++;
+ free_b -= s2_blk_out * sz;
+ n_written += s2_blk_out;
+ n2 += s2.times;
}
*bytes_read = sizeof(int32_t) * n_read;
*bytes_written = sizeof(int32_t) * n_written;
@@ -189,42 +198,27 @@ static void src_1s_s32_default(struct comp_dev *dev,
struct comp_buffer *source, struct comp_buffer *sink,
size_t *bytes_read, size_t *bytes_written)
{
- struct polyphase_src *s;
struct src_stage_prm s1;
- int j;
struct comp_data *cd = comp_get_drvdata(dev);
- int32_t *dest = (int32_t *) sink->w_ptr;
- int32_t *src = (int32_t *) source->r_ptr;
int nch = dev->params.channels;
int n_read = 0;
int n_written = 0;
s1.times = cd->param.stage1_times;
+ s1.x_rptr = (int32_t *) source->r_ptr;
s1.x_end_addr = source->end_addr;
s1.x_size = source->size;
- s1.x_inc = nch;
+ s1.y_wptr = (int32_t *) sink->w_ptr;
s1.y_end_addr = sink->end_addr;
s1.y_size = sink->size;
- s1.y_inc = nch;
- s1.x_rptr = src + nch - 1;
- s1.y_wptr = dest + nch - 1;
-
- for (j = 0; j < nch; j++) {
- s = &cd->src[j]; /* Point to src for this channel */
- s1.x_rptr = src++;
- s1.y_wptr = dest++;
- src_circ_inc_wrap(&src, source->end_addr, source->size);
- src_circ_inc_wrap(&dest, sink->end_addr, sink->size);
- s1.state = &s->state1;
- s1.stage = s->stage1;
- if (cd->sign_extend_s24)
- src_polyphase_stage_cir_s24(&s1);
- else
- src_polyphase_stage_cir(&s1);
-
- n_read += cd->param.blk_in;
- n_written += cd->param.blk_out;
- }
+ s1.state = &cd->src.state1;
+ s1.stage = cd->src.stage1;
+ s1.nch = dev->params.channels;
+
+ cd->polyphase_func(&s1);
+
+ n_read += nch * cd->param.blk_in;
+ n_written += nch * cd->param.blk_out;
*bytes_read = n_read * sizeof(int32_t);
*bytes_written = n_written * sizeof(int32_t);
}
@@ -271,7 +265,6 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp)
struct sof_ipc_comp_src *src;
struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *) comp;
struct comp_data *cd;
- int i;
trace_src("new");
@@ -299,8 +292,8 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp)
cd->delay_lines = NULL;
cd->src_func = src_2s_s32_default;
- for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
- src_polyphase_reset(&cd->src[i]);
+ cd->polyphase_func = src_polyphase_stage_cir;
+ src_polyphase_reset(&cd->src);
dev->state = COMP_STATE_READY;
return dev;
@@ -334,10 +327,8 @@ static int src_params(struct comp_dev *dev)
uint32_t sink_rate;
int32_t *buffer_start;
int n = 0;
- int i;
int err;
int frames_is_for_source;
- int nch;
int q;
trace_src("par");
@@ -345,10 +336,10 @@ static int src_params(struct comp_dev *dev)
/* SRC supports S24_4LE and S32_LE formats */
switch (config->frame_fmt) {
case SOF_IPC_FRAME_S24_4LE:
- cd->sign_extend_s24 = 1;
+ cd->polyphase_func = src_polyphase_stage_cir_s24;
break;
case SOF_IPC_FRAME_S32_LE:
- cd->sign_extend_s24 = 0;
+ cd->polyphase_func = src_polyphase_stage_cir;
break;
default:
trace_src_error("sr0");
@@ -407,11 +398,7 @@ static int src_params(struct comp_dev *dev)
buffer_start = cd->delay_lines + cd->param.sbuf_length;
/* Initize SRC for actual sample rate */
- nch = MIN(params->channels, PLATFORM_MAX_CHANNELS);
- for (i = 0; i < nch; i++) {
- n = src_polyphase_init(&cd->src[i], &cd->param, buffer_start);
- buffer_start += cd->param.single_src;
- }
+ n = src_polyphase_init(&cd->src, &cd->param, buffer_start);
/* Reset stage buffer */
cd->sbuf_r_ptr = cd->delay_lines;
@@ -434,7 +421,7 @@ static int src_params(struct comp_dev *dev)
* muted if copy() is run.
*/
trace_src("SFa");
- cd->src_func = fallback_s32;
+ cd->src_func = src_fallback;
return -EINVAL;
break;
}
@@ -532,7 +519,6 @@ static int src_copy(struct comp_dev *dev)
/* Run SRC function if buffers avail and free allow */
if (((int) source->avail >= need_source) && ((int) sink->free >= need_sink)) {
- /* Run src */
cd->src_func(dev, source, sink, &consumed, &produced);
/* Calc new free and available if data was processed. These
@@ -561,14 +547,12 @@ static int src_preload(struct comp_dev *dev)
static int src_reset(struct comp_dev *dev)
{
- int i;
struct comp_data *cd = comp_get_drvdata(dev);
trace_src("SRe");
cd->src_func = src_2s_s32_default;
- for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
- src_polyphase_reset(&cd->src[i]);
+ src_polyphase_reset(&cd->src);
comp_set_state(dev, COMP_CMD_RESET);
return 0;
diff --git a/src/audio/src_core.c b/src/audio/src_core.c
index 4ee2efd..080256c 100644
--- a/src/audio/src_core.c
+++ b/src/audio/src_core.c
@@ -45,12 +45,20 @@
#include "src_core.h"
#include "src_config.h"
+#define trace_src(__e) trace_event(TRACE_CLASS_SRC, __e)
+#define tracev_src(__e) tracev_event(TRACE_CLASS_SRC, __e)
+#define trace_src_error(__e) trace_error(TRACE_CLASS_SRC, __e)
+
/* TODO: These should be defined somewhere else. */
#define SOF_RATES_LENGTH 15
int sof_rates[SOF_RATES_LENGTH] = {8000, 11025, 12000, 16000, 18900,
22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400,
192000};
+/* The FIR maximum lenghts are per channel so need to multiply them */
+#define MAX_FIR_DELAY_SIZE_XNCH (PLATFORM_MAX_CHANNELS * MAX_FIR_DELAY_SIZE)
+#define MAX_OUT_DELAY_SIZE_XNCH (PLATFORM_MAX_CHANNELS * MAX_OUT_DELAY_SIZE)
+
/* Calculate ceil() for integer division */
int src_ceil_divide(int a, int b)
{
@@ -131,6 +139,13 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch,
int num;
int frames2;
+ if (nch > PLATFORM_MAX_CHANNELS) {
+ trace_src_error("che");
+ tracev_value(nch);
+ return -EINVAL;
+ }
+
+ a->nch = nch;
a->idx_in = src_find_fs(src_in_fs, NUM_IN_FS, fs_in);
a->idx_out = src_find_fs(src_out_fs, NUM_OUT_FS, fs_out);
@@ -146,8 +161,8 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch,
stage1 = src_table1[a->idx_out][a->idx_in];
stage2 = src_table2[a->idx_out][a->idx_in];
- a->fir_s1 = src_fir_delay_length(stage1);
- a->out_s1 = src_out_delay_length(stage1);
+ a->fir_s1 = nch * src_fir_delay_length(stage1);
+ a->out_s1 = nch * src_out_delay_length(stage1);
/* Find out how many additional times the SRC can be executed
while having block size less or equal to max_frames.
@@ -191,8 +206,8 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch,
a->stage2_times_max = 0;
a->sbuf_length = 0;
} else {
- a->fir_s2 = src_fir_delay_length(stage2);
- a->out_s2 = src_out_delay_length(stage2);
+ a->fir_s2 = nch * src_fir_delay_length(stage2);
+ a->out_s2 = nch * src_out_delay_length(stage2);
/* 2x is an empirically tested length. Since the sink buffer
* capability to receive samples varies a shorter stage 2 output
* block will create a peak in internal buffer usage.
@@ -200,8 +215,8 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch,
a->sbuf_length = 2 * nch * stage1->blk_out * a->stage1_times_max;
}
- a->single_src = a->fir_s1 + a->fir_s2 + a->out_s1 + a->out_s2;
- a->total = a->sbuf_length + nch * a->single_src;
+ a->src_multich = a->fir_s1 + a->fir_s2 + a->out_s1 + a->out_s2;
+ a->total = a->sbuf_length + a->src_multich;
return 0;
}
@@ -212,8 +227,6 @@ static void src_state_reset(struct src_state *state)
state->fir_delay_size = 0;
state->out_delay_size = 0;
state->fir_wi = 0;
- state->fir_ri = 0;
- state->out_wi = 0;
state->out_ri = 0;
}
@@ -229,17 +242,8 @@ static int init_stages(
src->number_of_stages = n;
src->stage1 = stage1;
src->stage2 = stage2;
- src->blk_in = p->blk_in;
- src->blk_out = p->blk_out;
- if (n == 1) {
- src->stage1_times = p->stage1_times;
- src->stage2_times = 0;
- if (stage1->blk_out == 0)
- return -EINVAL;
- } else {
- src->stage1_times = p->stage1_times;
- src->stage2_times = p->stage2_times;
- }
+ if ((n == 1) && (stage1->blk_out == 0))
+ return -EINVAL;
/* Delay line sizes */
src->state1.fir_delay_size = p->fir_s1;
@@ -262,10 +266,10 @@ static int init_stages(
}
/* Check the sizes are less than MAX */
- if ((src->state1.fir_delay_size > MAX_FIR_DELAY_SIZE)
- || (src->state1.out_delay_size > MAX_OUT_DELAY_SIZE)
- || (src->state2.fir_delay_size > MAX_FIR_DELAY_SIZE)
- || (src->state2.out_delay_size > MAX_OUT_DELAY_SIZE)) {
+ if ((src->state1.fir_delay_size > MAX_FIR_DELAY_SIZE_XNCH)
+ || (src->state1.out_delay_size > MAX_OUT_DELAY_SIZE_XNCH)
+ || (src->state2.fir_delay_size > MAX_FIR_DELAY_SIZE_XNCH)
+ || (src->state2.out_delay_size > MAX_OUT_DELAY_SIZE_XNCH)) {
src->state1.fir_delay = NULL;
src->state1.out_delay = NULL;
src->state2.fir_delay = NULL;
@@ -279,12 +283,7 @@ static int init_stages(
void src_polyphase_reset(struct polyphase_src *src)
{
- src->mute = 0;
src->number_of_stages = 0;
- src->blk_in = 0;
- src->blk_out = 0;
- src->stage1_times = 0;
- src->stage2_times = 0;
src->stage1 = NULL;
src->stage2 = NULL;
src_state_reset(&src->state1);
@@ -294,14 +293,12 @@ void src_polyphase_reset(struct polyphase_src *src)
int src_polyphase_init(struct polyphase_src *src, struct src_param *p,
int32_t *delay_lines_start)
{
- int n_stages;
- int ret;
struct src_stage *stage1;
struct src_stage *stage2;
+ int n_stages;
+ int ret;
if ((p->idx_in < 0) || (p->idx_out < 0)) {
- src->blk_in = p->blk_in;
- src->blk_out = p->blk_out;
return -EINVAL;
}
@@ -335,109 +332,157 @@ int src_polyphase_init(struct polyphase_src *src, struct src_param *p,
#if SRC_SHORT == 1
/* Calculate a FIR filter part that does not need circular modification */
-static inline void fir_part(int64_t *y, int ntaps, const int16_t c[], int *ic,
- int32_t d[], int *id)
+
+static inline void fir_part(int64_t y[], int *id, int *ic,
+ const int32_t data[], const int16_t coef[], int nch_x_taps, int nch)
{
+ int64_t tap0;
+ int64_t tap1;
int n;
int64_t a = 0;
+ int64_t b = 0;
+ int c = *ic;
+ int d = *id;
+ int d_end = d - nch_x_taps;
/* Data is Q1.31, coef is Q1.15, product is Q2.46 */
- for (n = 0; n < (ntaps >> 1); n++) {
- a += (int64_t) c[*ic] * d[*id]
- + (int64_t) c[*ic + 1] * d[*id - 1];
- *ic += 2;
- *id -= 2;
+ if (nch == 2) {
+ for (n = 0; n < (nch_x_taps >> 2); n++) {
+ tap0 = coef[c++];
+ tap1 = coef[c++];
+ b += data[d--] * tap0;
+ a += data[d--] * tap0;
+ b += data[d--] * tap1;
+ a += data[d--] * tap1;
+ }
+ if (d > d_end) {
+ tap0 = coef[c++];
+ b += data[d--] * tap0;
+ a += data[d--] * tap0;
+ }
+ y[1] += b;
+ y[0] += a;
+ } else {
+ while (d > d_end) {
+ tap0 = coef[c++];
+ for (n = nch - 1; n >= 0; n--)
+ y[n] += data[d--] * tap0;
+ }
}
- if (ntaps & 1)
- a += (int64_t) c[(*ic)++] * d[(*id)--];
-
- *y += a;
+ *ic = c;
+ *id = d;
}
+
#else
-/* Calculate a FIR filter part that does not need circular modification */
-static inline void fir_part(int64_t *y, int ntaps, const int32_t c[], int *ic,
- int32_t d[], int *id)
+static inline void fir_part(int64_t y[], int *id, int *ic,
+ const int32_t data[], const int32_t coef[], int nch_x_taps, int nch)
{
+ int64_t tap0;
+ int64_t tap1;
int n;
int64_t a = 0;
-
- /* Data is Q8.24, coef is Q1.23, product is Q9.47 */
- for (n = 0; n < (ntaps >> 1); n++) {
- a += (int64_t) c[*ic] * d[*id]
- + (int64_t) c[*ic + 1] * d[*id - 1];
- *ic += 2;
- *id -= 2;
+ int64_t b = 0;
+ int c = *ic;
+ int d = *id;
+ int d_end = d - nch_x_taps;
+
+ /* Data is Q1.31, coef is Q1.23, product is Q2.54 */
+ if (nch == 2) {
+ for (n = 0; n < (nch_x_taps >> 2); n++) {
+ tap0 = coef[c++];
+ tap1 = coef[c++];
+ b += data[d--] * tap0;
+ a += data[d--] * tap0;
+ b += data[d--] * tap1;
+ a += data[d--] * tap1;
+ }
+ if (d > d_end) {
+ tap0 = coef[c++];
+ b += data[d--] * tap0;
+ a += data[d--] * tap0;
+ }
+ y[1] += b;
+ y[0] += a;
+ } else {
+ while (d > d_end) {
+ tap0 = coef[c++];
+ for (n = nch - 1; n >= 0; n--)
+ y[n] += data[d--] * tap0;
+ }
}
- if (ntaps & 1)
- a += (int64_t) c[(*ic)++] * d[(*id)--];
-
- *y += a;
+ *ic = c;
+ *id = d;
}
+
#endif
#if SRC_SHORT == 1
-static inline int32_t fir_filter(
- struct src_state *fir, const int16_t coefs[],
- int *coefi, int filter_length, int shift)
+static void fir_filter(int ri0, int *ci, int wi0, int32_t in_delay[],
+ int32_t out_delay[], const int16_t coefs[], int dsm1, int taps,
+ int shift, int nch)
{
- int64_t y = 0;
- int n1;
int n2;
-
- n1 = fir->fir_ri + 1;
- if (n1 > filter_length) {
- /* No need to un-wrap fir read index, make sure fir_fi
- * is ge 0 after FIR computation.
- */
- fir_part(&y, filter_length, coefs, coefi, fir->fir_delay,
- &fir->fir_ri);
+ int i;
+ int64_t y[PLATFORM_MAX_CHANNELS];
+ int ri = ri0;
+ int wi = wi0;
+ int n1 = ri0 + 1; /* Convert to number of sequential frames */
+ int qshift = 15 + shift; /* Q2.46 -> Q2.31 */
+ int32_t rnd = 1 << (qshift - 1); /* Half LSB */
+ int nch_x_taps = nch * taps;
+
+ /* Initialize to half LSB for rounding */
+ for (i = 0; i < nch; i++)
+ y[i] = rnd;
+
+ if (n1 >= nch_x_taps) {
+ fir_part(y, &ri, ci, in_delay, coefs, nch_x_taps, nch);
} else {
- n2 = filter_length - n1;
- /* Part 1, loop n1 times, fir_ri becomes -1 */
- fir_part(&y, n1, coefs, coefi, fir->fir_delay, &fir->fir_ri);
-
- /* Part 2, unwrap fir_ri, continue rest of filter */
- fir->fir_ri = fir->fir_delay_size - 1;
- fir_part(&y, n2, coefs, coefi, fir->fir_delay, &fir->fir_ri);
+ n2 = nch_x_taps - n1;
+ fir_part(y, &ri, ci, in_delay, coefs, n1, nch);
+ ri = dsm1;
+ fir_part(y, &ri, ci, in_delay, coefs, n2, nch);
}
- /* Q2.46 -> Q2.31, saturate to Q1.31 */
- y = y >> (15 + shift);
- return(int32_t) sat_int32(y);
+ for (i = 0; i < nch; i++)
+ out_delay[wi++] = sat_int32(y[i] >> qshift);
}
#else
-static inline int32_t fir_filter(
- struct src_state *fir, const int32_t coefs[],
- int *coefi, int filter_length, int shift)
+static void fir_filter(int ri0, int *ci, int wi0, int32_t in_delay[],
+ int32_t out_delay[], const int32_t coefs[], int dsm1, int taps,
+ int shift, int nch)
{
- int64_t y = 0;
- int n1;
int n2;
-
- n1 = fir->fir_ri + 1;
- if (n1 > filter_length) {
- /* No need to un-wrap fir read index, make sure fir_fi
- * is ge 0 after FIR computation.
- */
- fir_part(&y, filter_length, coefs, coefi, fir->fir_delay,
- &fir->fir_ri);
+ int i;
+ int64_t y[PLATFORM_MAX_CHANNELS];
+ int ri = ri0;
+ int wi = wi0;
+ int n1 = ri0 + 1; /* Convert to number of sequential frames */
+ int qshift = 23 + shift; /* Q2.54 -> Q2.31 */
+ int32_t rnd = 1 << (qshift - 1); /* Half LSB */
+ int nch_x_taps = nch * taps;
+
+ /* Initialize to half LSB for rounding */
+ for (i = 0; i < nch; i++)
+ y[i] = rnd;
+
+ if (n1 >= nch_x_taps) {
+ fir_part(y, &ri, ci, in_delay, coefs, nch_x_taps, nch);
} else {
- n2 = filter_length - n1;
- /* Part 1, loop n1 times, fir_ri becomes -1 */
- fir_part(&y, n1, coefs, coefi, fir->fir_delay, &fir->fir_ri);
-
- /* Part 2, unwrap fir_ri, continue rest of filter */
- fir->fir_ri = fir->fir_delay_size - 1;
- fir_part(&y, n2, coefs, coefi, fir->fir_delay, &fir->fir_ri);
+ n2 = nch_x_taps - n1;
+ fir_part(y, &ri, ci, in_delay, coefs, n1, nch);
+ ri = dsm1;
+ fir_part(y, &ri, ci, in_delay, coefs, n2, nch);
}
- /* Q9.47 -> Q9.24, saturate to Q8.24 */
- y = y >> (23 + shift);
- return(int32_t) sat_int32(y);
+ for (i = 0; i < nch; i++)
+ out_delay[wi++] = sat_int32(y[i] >> qshift);
+
}
+
#endif
void src_polyphase_stage_cir(struct src_stage_prm * s)
@@ -447,29 +492,42 @@ void src_polyphase_stage_cir(struct src_stage_prm * s)
int n;
int m;
int f;
- int c;
- int r;
+ int ci;
+ int ri;
int n_wrap_fir;
int n_wrap_buf;
int n_wrap_min;
int n_min;
- int32_t z;
+ int wi;
+ const void *coef = cfg->coefs;
+ int32_t *in_delay = fir->fir_delay;
+ int32_t *out_delay = fir->out_delay;
+ int dsm1 = fir->fir_delay_size - 1;
+ int shift = cfg->shift;
+ int nch = s->nch;
+ int rewind = -nch * (cfg->blk_in
+ + (cfg->num_of_subfilters - 1) * cfg->idm) + nch - 1;
+ int nch_x_idm = cfg->idm * nch;
+ int nch_x_odm = cfg->odm * nch;
+ size_t sz = sizeof(int32_t);
+ int blk_in_bytes = nch * cfg->blk_in * sz;
+ int blk_out_bytes = nch * cfg->num_of_subfilters * sz;
+
for (n = 0; n < s->times; n++) {
/* Input data */
- m = s->x_inc * cfg->blk_in;
+ m = blk_in_bytes;
while (m > 0) {
- n_wrap_fir = (fir->fir_delay_size - fir->fir_wi)
- * s->x_inc;
+ n_wrap_fir = (fir->fir_delay_size - fir->fir_wi) * sz;
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;
n_min = (m < n_wrap_min) ? m : n_wrap_min;
while (n_min > 0) {
fir->fir_delay[fir->fir_wi++] = *s->x_rptr;
- s->x_rptr += s->x_inc;
- n_min -= s->x_inc;
- m -= s->x_inc;
+ s->x_rptr++;
+ n_min -= sz;
+ m -= sz;
}
/* Check for wrap */
src_circ_inc_wrap(&s->x_rptr, s->x_end_addr, s->x_size);
@@ -478,41 +536,38 @@ void src_polyphase_stage_cir(struct src_stage_prm * s)
}
/* Filter */
- c = 0;
- r = fir->fir_wi - cfg->blk_in
- - (cfg->num_of_subfilters - 1) * cfg->idm;
- if (r < 0)
- r += fir->fir_delay_size;
+ ci = 0; /* Reset to 1st coefficient */
+ ri = fir->fir_wi + rewind; /* Newest data for last subfilter */
+ if (ri < 0)
+ ri += fir->fir_delay_size;
- fir->out_wi = fir->out_ri;
+ wi = fir->out_ri;
for (f = 0; f < cfg->num_of_subfilters; f++) {
- fir->fir_ri = r;
- z = fir_filter(fir, cfg->coefs, &c,
- cfg->subfilter_length, cfg->shift);
- r += cfg->idm;
- if (r >= fir->fir_delay_size)
- r -= fir->fir_delay_size;
-
- fir->out_delay[fir->out_wi] = z;
- fir->out_wi += cfg->odm;
- if (fir->out_wi >= fir->out_delay_size)
- fir->out_wi -= fir->out_delay_size;
+ fir_filter(ri, &ci, wi, in_delay, out_delay, coef,
+ dsm1, cfg->subfilter_length, shift, nch);
+
+ wi += nch_x_odm;
+ if (wi >= fir->out_delay_size)
+ wi -= fir->out_delay_size;
+
+ ri += nch_x_idm; /* Next sub-filter start */
+ if (ri >= fir->fir_delay_size)
+ ri -= fir->fir_delay_size;
}
/* Output */
- m = s->y_inc * cfg->num_of_subfilters;
+ m = blk_out_bytes;
while (m > 0) {
- n_wrap_fir = (fir->out_delay_size - fir->out_ri)
- * s->y_inc;
+ n_wrap_fir = (fir->out_delay_size - fir->out_ri) * sz;
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;
n_min = (m < n_wrap_min) ? m : n_wrap_min;
while (n_min > 0) {
*s->y_wptr = fir->out_delay[fir->out_ri++];
- s->y_wptr += s->y_inc;
- n_min -= s->y_inc;
- m -= s->y_inc;
+ s->y_wptr++;
+ n_min -= sz;
+ m -= sz;
}
/* Check wrap */
src_circ_inc_wrap(&s->y_wptr, s->y_end_addr, s->y_size);
@@ -522,38 +577,48 @@ void src_polyphase_stage_cir(struct src_stage_prm * s)
}
}
-void src_polyphase_stage_cir_s24(struct src_stage_prm * s)
+void src_polyphase_stage_cir_s24(struct src_stage_prm *s)
{
struct src_state *fir = s->state;
struct src_stage *cfg = s->stage;
int n;
int m;
int f;
- int c;
- int r;
+ int ci;
+ int ri;
int n_wrap_fir;
int n_wrap_buf;
int n_wrap_min;
int n_min;
- int32_t z;
- int32_t se;
+ int wi;
+ const void *coef = cfg->coefs;
+ int32_t *in_delay = fir->fir_delay;
+ int32_t *out_delay = fir->out_delay;
+ int dsm1 = fir->fir_delay_size - 1;
+ int shift = cfg->shift;
+ int nch = s->nch;
+ int rewind = -nch * (cfg->blk_in
+ + (cfg->num_of_subfilters - 1) * cfg->idm) + nch - 1;
+ int nch_x_idm = cfg->idm * nch;
+ int nch_x_odm = cfg->odm * nch;
+ size_t sz = sizeof(int32_t);
+ int blk_in_bytes = nch * cfg->blk_in * sz;
+ int blk_out_bytes = nch * cfg->num_of_subfilters * sz;
for (n = 0; n < s->times; n++) {
/* Input data */
- m = s->x_inc * cfg->blk_in;
+ m = blk_in_bytes;
while (m > 0) {
- n_wrap_fir = (fir->fir_delay_size - fir->fir_wi)
- * s->x_inc;
+ n_wrap_fir = (fir->fir_delay_size - fir->fir_wi) * sz;
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;
n_min = (m < n_wrap_min) ? m : n_wrap_min;
while (n_min > 0) {
- se = *s->x_rptr << 8;
- fir->fir_delay[fir->fir_wi++] = se >> 8;
- s->x_rptr += s->x_inc;
- n_min -= s->x_inc;
- m -= s->x_inc;
+ fir->fir_delay[fir->fir_wi++] = *s->x_rptr << 8;
+ s->x_rptr++;
+ n_min -= sz;
+ m -= sz;
}
/* Check for wrap */
src_circ_inc_wrap(&s->x_rptr, s->x_end_addr, s->x_size);
@@ -562,41 +627,38 @@ void src_polyphase_stage_cir_s24(struct src_stage_prm * s)
}
/* Filter */
- c = 0;
- r = fir->fir_wi - cfg->blk_in
- - (cfg->num_of_subfilters - 1) * cfg->idm;
- if (r < 0)
- r += fir->fir_delay_size;
+ ci = 0; /* Reset to 1st coefficient */
+ ri = fir->fir_wi + rewind; /* Newest data for last subfilter */
+ if (ri < 0)
+ ri += fir->fir_delay_size;
- fir->out_wi = fir->out_ri;
+ wi = fir->out_ri;
for (f = 0; f < cfg->num_of_subfilters; f++) {
- fir->fir_ri = r;
- z = fir_filter(fir, cfg->coefs, &c,
- cfg->subfilter_length, cfg->shift);
- r += cfg->idm;
- if (r >= fir->fir_delay_size)
- r -= fir->fir_delay_size;
-
- fir->out_delay[fir->out_wi] = z;
- fir->out_wi += cfg->odm;
- if (fir->out_wi >= fir->out_delay_size)
- fir->out_wi -= fir->out_delay_size;
+ fir_filter(ri, &ci, wi, in_delay, out_delay, coef,
+ dsm1, cfg->subfilter_length, shift, nch);
+
+ wi += nch_x_odm;
+ if (wi >= fir->out_delay_size)
+ wi -= fir->out_delay_size;
+
+ ri += nch_x_idm; /* Next sub-filter start */
+ if (ri >= fir->fir_delay_size)
+ ri -= fir->fir_delay_size;
}
/* Output */
- m = s->y_inc * cfg->num_of_subfilters;
+ m = blk_out_bytes;
while (m > 0) {
- n_wrap_fir = (fir->out_delay_size - fir->out_ri)
- * s->y_inc;
+ n_wrap_fir = (fir->out_delay_size - fir->out_ri) * sz;
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;
n_min = (m < n_wrap_min) ? m : n_wrap_min;
while (n_min > 0) {
- *s->y_wptr = fir->out_delay[fir->out_ri++];
- s->y_wptr += s->y_inc;
- n_min -= s->y_inc;
- m -= s->y_inc;
+ *s->y_wptr = fir->out_delay[fir->out_ri++] >> 8;
+ s->y_wptr++;
+ n_min -= sz;
+ m -= sz;
}
/* Check wrap */
src_circ_inc_wrap(&s->y_wptr, s->y_end_addr, s->y_size);
@@ -604,47 +666,5 @@ void src_polyphase_stage_cir_s24(struct src_stage_prm * s)
fir->out_ri = 0;
}
}
-}
-
-#ifdef MODULE_TEST
-
-void src_print_info(struct polyphase_src * src)
-{
-
- int n1;
- int n2;
-
- n1 = src->stage1->filter_length;
- n2 = src->stage2->filter_length;
- printf("SRC stages %d\n", src->number_of_stages);
- printf("SRC input blk %d\n", src->blk_in);
- printf("SRC output blk %d\n", src->blk_out);
- printf("SRC stage1 %d times\n", src->stage1_times);
- printf("SRC stage2 %d times\n", src->stage2_times);
-
- printf("SRC1 filter length %d\n", n1);
- printf("SRC1 subfilter length %d\n", src->stage1->subfilter_length);
- printf("SRC1 number of subfilters %d\n",
- src->stage1->num_of_subfilters);
- printf("SRC1 idm %d\n", src->stage1->idm);
- printf("SRC1 odm %d\n", src->stage1->odm);
- printf("SRC1 input blk %d\n", src->stage1->blk_in);
- printf("SRC1 output blk %d\n", src->stage1->blk_out);
- printf("SRC1 halfband %d\n", src->stage1->halfband);
- printf("SRC1 FIR delay %d\n", src->state1.fir_delay_size);
- printf("SRC1 out delay %d\n", src->state1.out_delay_size);
-
- printf("SRC2 filter length %d\n", n2);
- printf("SRC2 subfilter length %d\n", src->stage2->subfilter_length);
- printf("SRC2 number of subfilters %d\n",
- src->stage2->num_of_subfilters);
- printf("SRC2 idm %d\n", src->stage2->idm);
- printf("SRC2 odm %d\n", src->stage2->odm);
- printf("SRC2 input blk %d\n", src->stage2->blk_in);
- printf("SRC2 output blk %d\n", src->stage2->blk_out);
- printf("SRC2 halfband %d\n", src->stage2->halfband);
- printf("SRC2 FIR delay %d\n", src->state2.fir_delay_size);
- printf("SRC2 out delay %d\n", src->state2.out_delay_size);
}
-#endif
diff --git a/src/audio/src_core.h b/src/audio/src_core.h
index 3859e6f..3ea6028 100644
--- a/src/audio/src_core.h
+++ b/src/audio/src_core.h
@@ -41,7 +41,7 @@ struct src_param {
int out_s1;
int out_s2;
int sbuf_length;
- int single_src;
+ int src_multich;
int total;
int blk_in;
int blk_out;
@@ -51,6 +51,7 @@ struct src_param {
int stage2_times_max;
int idx_in;
int idx_out;
+ int nch;
};
struct src_stage {
@@ -70,20 +71,13 @@ struct src_state {
int fir_delay_size;
int out_delay_size;
int fir_wi;
- int fir_ri;
- int out_wi;
int out_ri;
int32_t *fir_delay;
int32_t *out_delay;
};
struct polyphase_src {
- int mute;
int number_of_stages;
- int blk_in;
- int blk_out;
- int stage1_times;
- int stage2_times;
struct src_stage *stage1;
struct src_stage *stage2;
struct src_state state1;
@@ -91,15 +85,14 @@ struct polyphase_src {
};
struct src_stage_prm {
+ int nch;
int times;
int32_t *x_rptr;
int32_t *x_end_addr;
size_t x_size;
- int x_inc;
int32_t *y_wptr;
int32_t *y_end_addr;
size_t y_size;
- int y_inc;
struct src_state *state;
struct src_stage *stage;
};
@@ -116,31 +109,6 @@ static inline void src_circ_dec_wrap(int32_t **ptr, int32_t *addr, size_t size)
*ptr = (int32_t *) ((size_t) * ptr + size);
}
-static inline void src_polyphase_mute(struct polyphase_src *src)
-{
- src->mute = 1;
-}
-
-static inline void src_polyphase_unmute(struct polyphase_src *src)
-{
- src->mute = 0;
-}
-
-static inline int src_polyphase_getmute(struct polyphase_src *src)
-{
- return src->mute;
-}
-
-static inline int src_polyphase_get_blk_in(struct polyphase_src *src)
-{
- return src->blk_in;
-}
-
-static inline int src_polyphase_get_blk_out(struct polyphase_src *src)
-{
- return src->blk_out;
-}
-
void src_polyphase_reset(struct polyphase_src *src);
int src_polyphase_init(struct polyphase_src *src, struct src_param *p,
@@ -162,8 +130,4 @@ int32_t src_output_rates(void);
int src_ceil_divide(int a, int b);
-#ifdef MODULE_TEST
-void src_print_info(struct polyphase_src *src);
-#endif
-
#endif
--
2.11.0
1
0
[Sound-open-firmware] [PATCH 2/2] Move DMA tracing intialization calling.
by yan.wang@linux.intel.com 20 Oct '17
by yan.wang@linux.intel.com 20 Oct '17
20 Oct '17
From: Yan Wang <yan.wang(a)linux.intel.com>
Move it from ipc handler into platform_init().
Signed-off-by: Yan Wang <yan.wang(a)linux.intel.com>
---
src/ipc/intel-ipc.c | 7 -------
src/platform/baytrail/platform.c | 4 ++++
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/src/ipc/intel-ipc.c b/src/ipc/intel-ipc.c
index f6d88ef..902e5a6 100644
--- a/src/ipc/intel-ipc.c
+++ b/src/ipc/intel-ipc.c
@@ -583,13 +583,6 @@ static int ipc_dma_trace_config(uint32_t header)
trace_ipc_error("DA1");
- /* Initialize DMA for Trace*/
- err = dma_trace_init(&_ipc->dmat);
- if (err < 0) {
- trace_ipc_error("eIP");
- goto error;
- }
-
/* use DMA to read in compressed page table ringbuffer from host */
err = get_page_descriptors(iipc, ¶ms->buffer);
if (err < 0) {
diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c
index b701196..61596bb 100644
--- a/src/platform/baytrail/platform.c
+++ b/src/platform/baytrail/platform.c
@@ -46,6 +46,7 @@
#include <reef/clock.h>
#include <reef/ipc.h>
#include <reef/trace.h>
+#include <reef/dma-trace.h>
#include <reef/audio/component.h>
#include <config.h>
#include <string.h>
@@ -296,6 +297,9 @@ int platform_init(struct reef *reef)
trace_point(TRACE_BOOT_PLATFORM_IPC);
ipc_init(reef);
+ /* Initialize DMA for Trace*/
+ dma_trace_init(&reef->ipc->dmat);
+
/* init DMACs */
trace_point(TRACE_BOOT_PLATFORM_DMA);
dmac0 = dma_get(DMA_ID_DMAC0);
--
2.7.4
1
0
[Sound-open-firmware] [PATCH 1/2] Move DMA tracing implementaion from src/audio to src/lib.
by yan.wang@linux.intel.com 20 Oct '17
by yan.wang@linux.intel.com 20 Oct '17
20 Oct '17
From: Yan Wang <yan.wang(a)linux.intel.com>
1. Move source and header file.
2. Change src/lib/Makefile.am and src/audio/Makefile.am.
3. Chnage header file path.
Signed-off-by: Yan Wang <yan.wang(a)linux.intel.com>
---
src/audio/Makefile.am | 1 -
src/include/reef/{audio => }/dma-trace.h | 0
src/include/reef/ipc.h | 2 +-
src/lib/Makefile.am | 1 +
src/{audio => lib}/dma-trace.c | 3 +--
src/lib/trace.c | 2 +-
6 files changed, 4 insertions(+), 5 deletions(-)
rename src/include/reef/{audio => }/dma-trace.h (100%)
rename src/{audio => lib}/dma-trace.c (98%)
diff --git a/src/audio/Makefile.am b/src/audio/Makefile.am
index 7ffe01f..285422e 100644
--- a/src/audio/Makefile.am
+++ b/src/audio/Makefile.am
@@ -17,7 +17,6 @@ libaudio_a_SOURCES = \
pipeline.c \
pipeline_static.c \
component.c \
- dma-trace.c \
buffer.c
libaudio_a_CFLAGS = \
diff --git a/src/include/reef/audio/dma-trace.h b/src/include/reef/dma-trace.h
similarity index 100%
rename from src/include/reef/audio/dma-trace.h
rename to src/include/reef/dma-trace.h
diff --git a/src/include/reef/ipc.h b/src/include/reef/ipc.h
index a552626..472aca8 100644
--- a/src/include/reef/ipc.h
+++ b/src/include/reef/ipc.h
@@ -40,7 +40,7 @@
#include <uapi/ipc.h>
#include <reef/audio/pipeline.h>
#include <reef/audio/component.h>
-#include <reef/audio/dma-trace.h>
+#include <reef/dma-trace.h>
struct reef;
struct dai_config;
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index acdbd85..b4521df 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -6,6 +6,7 @@ libcore_a_SOURCES = \
work.c \
notifier.c \
trace.c \
+ dma-trace.c \
schedule.c
libcore_a_CFLAGS = \
diff --git a/src/audio/dma-trace.c b/src/lib/dma-trace.c
similarity index 98%
rename from src/audio/dma-trace.c
rename to src/lib/dma-trace.c
index b0267fa..5885037 100644
--- a/src/audio/dma-trace.c
+++ b/src/lib/dma-trace.c
@@ -29,7 +29,7 @@
*/
#include <reef/trace.h>
-#include <reef/audio/dma-trace.h>
+#include <reef/dma-trace.h>
#include <reef/ipc.h>
#include <reef/reef.h>
#include <reef/alloc.h>
@@ -172,7 +172,6 @@ int dma_trace_enable(struct dma_trace_data *d)
return -ENODEV;
}
- /* TODO: fix crash when enabled */
d->enabled = 1;
work_schedule_default(&d->dmat_work, DMA_TRACE_US);
return 0;
diff --git a/src/lib/trace.c b/src/lib/trace.c
index c0abf7c..eec93b5 100644
--- a/src/lib/trace.c
+++ b/src/lib/trace.c
@@ -34,7 +34,7 @@
#include <arch/cache.h>
#include <platform/timer.h>
#include <reef/lock.h>
-#include <reef/audio/dma-trace.h>
+#include <reef/dma-trace.h>
#include <stdint.h>
struct trace {
--
2.7.4
1
0
[Sound-open-firmware] [PATCH v5] volume: fix for DC offset and handling of sign extension for 24-bit samples
by Ranjani Sridharan 20 Oct '17
by Ranjani Sridharan 20 Oct '17
20 Oct '17
This patch fixes the DC offsets introduced in the volume component
due to shifts and handles sign extension for 24-bit input samples
Signed-off-by: Ranjani Sridharan <ranjani.sridharan(a)linux.intel.com>
---
src/audio/tone.c | 19 +++++++----
src/audio/volume.c | 71 +++++++++++++++++++++++++++--------------
src/include/reef/audio/format.h | 50 ++++++++++++++++++++++-------
src/math/trig.c | 3 +-
4 files changed, 99 insertions(+), 44 deletions(-)
diff --git a/src/audio/tone.c b/src/audio/tone.c
index 0baf247..1fde455 100644
--- a/src/audio/tone.c
+++ b/src/audio/tone.c
@@ -149,7 +149,9 @@ static int32_t tonegen(struct tone_state *sg)
/* sg->w is angle in Q4.28 radians format, sin() returns Q1.31 */
/* sg->a is amplitude as Q1.31 */
- sine = q_mults_32x32(sin_fixed(sg->w), sg->a, 31, 31, 31);
+ sine =
+ q_mults_32x32(sin_fixed(sg->w), sg->a,
+ Q_SHIFT_BITS_64(31, 31, 31));
/* Next point */
w = (int64_t) sg->w + sg->w_step;
@@ -208,15 +210,16 @@ static void tonegen_control(struct tone_state *sg)
&& (sg->repeat_count + 1 < sg->repeats)) {
sg->block_count = 0;
if (sg->ampl_coef > 0) {
- sg->a_target = sat_int32(q_multsr_32x32(
- sg->a_target,
- sg->ampl_coef, 31, 30, 31));
+ sg->a_target =
+ sat_int32(q_multsr_32x32(sg->a_target,
+ sg->ampl_coef, Q_SHIFT_BITS_64(31, 30, 31)));
sg->a = (sg->ramp_step > sg->a_target)
? sg->a_target : sg->ramp_step;
}
if (sg->freq_coef > 0) {
/* f is Q16.16, freq_coef is Q2.30 */
- p = q_multsr_32x32(sg->f, sg->freq_coef, 16, 30, 16);
+ p = q_multsr_32x32(sg->f, sg->freq_coef,
+ Q_SHIFT_BITS_64(16, 30, 16));
tonegen_update_f(sg, (int32_t) p); /* No saturation */
}
sg->repeat_count++;
@@ -297,7 +300,8 @@ static void tonegen_update_f(struct tone_state *sg, int32_t f)
f_max = Q_SHIFT_LEFT((int64_t) sg->fs, 0, 16 - 1);
f_max = (f_max > INT32_MAXVALUE) ? INT32_MAXVALUE : f_max;
sg->f = (f > f_max) ? f_max : f;
- w_tmp = q_multsr_32x32(sg->f, sg->c, 16, 31, 28); /* Q16 x Q31 -> Q28 */
+ /* Q16 x Q31 -> Q28 */
+ w_tmp = q_multsr_32x32(sg->f, sg->c, Q_SHIFT_BITS_64(16, 31, 28));
w_tmp = (w_tmp > PI_Q4_28) ? PI_Q4_28 : w_tmp; /* Limit to pi Q4.28 */
sg->w_step = (int32_t) w_tmp;
@@ -362,7 +366,8 @@ static int tonegen_init(struct tone_state *sg, int32_t fs, int32_t f, int32_t a)
tonegen_update_f(sg, f);
/* 125us as Q1.31 is 268435, calculate fs * 125e-6 in Q31.0 */
- sg->samples_in_block = (int32_t) q_multsr_32x32(fs, 268435, 0, 31, 0);
+ sg->samples_in_block =
+ (int32_t) q_multsr_32x32(fs, 268435, Q_SHIFT_BITS_64(0, 31, 0));
return 0;
}
diff --git a/src/audio/volume.c b/src/audio/volume.c
index 472aab9..137be3c 100644
--- a/src/audio/volume.c
+++ b/src/audio/volume.c
@@ -99,8 +99,8 @@ static void vol_s16_to_s32(struct comp_dev *dev, struct comp_buffer *sink,
int32_t *dest = (int32_t *) sink->w_ptr;
int32_t i;
-
/* buffer sizes are always divisible by period frames */
+ /* Samples are Q1.15 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < frames * 2; i += 2) {
dest[i] = (int32_t)src[i] * cd->volume[0];
dest[i + 1] = (int32_t)src[i + 1] * cd->volume[1];
@@ -117,9 +117,12 @@ static void vol_s32_to_s16(struct comp_dev *dev, struct comp_buffer *sink,
int32_t i;
/* buffer sizes are always divisible by period frames */
+ /* Samples are Q1.31 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < frames * 2; i += 2) {
- dest[i] = (((int32_t)src[i] >> 16) * cd->volume[0]) >> 16;
- dest[i + 1] = (((int32_t)src[i + 1] >> 16) * cd->volume[1]) >> 16;
+ dest[i] = (int16_t)q_multsr_sat_32x32(
+ src[i], cd->volume[0], Q_SHIFT_BITS_64(31, 16, 15));
+ dest[i + 1] = (int16_t)q_multsr_sat_32x32(
+ src[i + 1], cd->volume[1], Q_SHIFT_BITS_64(31, 16, 15));
}
}
@@ -133,9 +136,12 @@ static void vol_s32_to_s32(struct comp_dev *dev, struct comp_buffer *sink,
int32_t i;
/* buffer sizes are always divisible by period frames */
+ /* Samples are Q1.31 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < frames * 2; i += 2) {
- dest[i] = ((int64_t)src[i] * cd->volume[0]) >> 16;
- dest[i + 1] = ((int64_t)src[i + 1] * cd->volume[1]) >> 16;
+ dest[i] = q_multsr_sat_32x32(
+ src[i], cd->volume[0], Q_SHIFT_BITS_64(31, 16, 31));
+ dest[i + 1] = q_multsr_sat_32x32(
+ src[i + 1], cd->volume[1], Q_SHIFT_BITS_64(31, 16, 31));
}
}
@@ -149,9 +155,12 @@ static void vol_s16_to_s16(struct comp_dev *dev, struct comp_buffer *sink,
int32_t i;
/* buffer sizes are always divisible by period frames */
+ /* Samples are Q1.15 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < frames * 2; i += 2) {
- dest[i] = ((int32_t)src[i] * cd->volume[0]) >> 16;
- dest[i + 1] = ((int32_t)src[i + 1] * cd->volume[1]) >> 16;
+ dest[i] = q_multsr_sat_16x16(
+ src[i], cd->volume[0], Q_SHIFT_BITS_32(15, 16, 15));
+ dest[i + 1] = q_multsr_sat_16x16(
+ src[i + 1], cd->volume[1], Q_SHIFT_BITS_32(15, 16, 15));
}
}
@@ -165,9 +174,12 @@ static void vol_s16_to_s24(struct comp_dev *dev, struct comp_buffer *sink,
int32_t i;
/* buffer sizes are always divisible by period frames */
+ /* Samples are Q1.15 and volume is Q1.16 */
for (i = 0; i < frames * 2; i += 2) {
- dest[i] = ((int32_t)src[i] * cd->volume[0]) >> 8;
- dest[i + 1] = ((int32_t)src[i + 1] * cd->volume[1]) >> 8;
+ dest[i] = q_multsr_sat_32x32(
+ src[i], cd->volume[0], Q_SHIFT_BITS_64(15, 16, 23));
+ dest[i + 1] = q_multsr_sat_32x32(
+ src[i], cd->volume[0], Q_SHIFT_BITS_64(15, 16, 23));
}
}
@@ -181,11 +193,14 @@ static void vol_s24_to_s16(struct comp_dev *dev, struct comp_buffer *sink,
int32_t i;
/* buffer sizes are always divisible by period frames */
+ /* Samples are Q1.23 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < frames * 2; i += 2) {
- dest[i] = (int16_t)((((int32_t)src[i] >> 8) *
- cd->volume[0]) >> 16);
- dest[i + 1] = (int16_t)((((int32_t)src[i + 1] >> 8) *
- cd->volume[1]) >> 16);
+ dest[i] = (int16_t)q_multsr_sat_32x32(
+ sign_extend_s24(src[i]), cd->volume[0],
+ Q_SHIFT_BITS_64(23, 16, 15));
+ dest[i + 1] = (int16_t)q_multsr_sat_32x32(
+ sign_extend_s24(src[i + 1]), cd->volume[1],
+ Q_SHIFT_BITS_64(23, 16, 15));
}
}
@@ -199,9 +214,12 @@ static void vol_s32_to_s24(struct comp_dev *dev, struct comp_buffer *sink,
int32_t i;
/* buffer sizes are always divisible by period frames */
+ /* Samples are Q1.31 --> Q1.23 and volume is Q1.16 */
for (i = 0; i < frames * 2; i += 2) {
- dest[i] = ((int64_t)src[i] * cd->volume[0]) >> 24;
- dest[i + 1] = ((int64_t)src[i + 1] * cd->volume[1]) >> 24;
+ dest[i] = q_multsr_sat_32x32(
+ src[i], cd->volume[0], Q_SHIFT_BITS_64(31, 16, 23));
+ dest[i + 1] = q_multsr_sat_32x32(
+ src[i + 1], cd->volume[1], Q_SHIFT_BITS_64(31, 16, 23));
}
}
@@ -215,11 +233,14 @@ static void vol_s24_to_s32(struct comp_dev *dev, struct comp_buffer *sink,
int32_t i;
/* buffer sizes are always divisible by period frames */
+ /* Samples are Q1.23 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < frames * 2; i += 2) {
- dest[i] = (int32_t)(((int64_t)src[i] *
- cd->volume[0]) >> 8);
- dest[i + 1] = (int32_t)(((int64_t)src[i + 1] *
- cd->volume[1]) >> 8);
+ dest[i] = q_multsr_sat_32x32(
+ sign_extend_s24(src[i]), cd->volume[0],
+ Q_SHIFT_BITS_64(23, 16, 31));
+ dest[i + 1] = q_multsr_sat_32x32(
+ sign_extend_s24(src[i + 1]), cd->volume[1],
+ Q_SHIFT_BITS_64(23, 16, 31));
}
}
@@ -234,12 +255,14 @@ static void vol_s24_to_s24(struct comp_dev *dev, struct comp_buffer *sink,
int32_t *dest = (int32_t*) sink->w_ptr;
/* buffer sizes are always divisible by period frames */
- /* Samples are Q1.23 and volume is Q1.16 */
+ /* Samples are Q1.23 --> Q1.23 and volume is Q1.16 */
for (i = 0; i < frames * 2; i += 2) {
- dest[i] = (int32_t)(Q_MULTS_32X32(
- (int64_t)src[i], cd->volume[0], 23, 16, 23));
- dest[i + 1] = (int32_t)(Q_MULTS_32X32(
- (int64_t)src[i+1], cd->volume[1], 23, 16, 23));
+ dest[i] = q_multsr_sat_32x32(
+ sign_extend_s24(src[i]), cd->volume[0],
+ Q_SHIFT_BITS_64(23, 16, 23));
+ dest[i + 1] = q_multsr_sat_32x32(
+ sign_extend_s24(src[i + 1]), cd->volume[1],
+ Q_SHIFT_BITS_64(23, 16, 23));
}
}
diff --git a/src/include/reef/audio/format.h b/src/include/reef/audio/format.h
index 945a968..b9263f1 100644
--- a/src/include/reef/audio/format.h
+++ b/src/include/reef/audio/format.h
@@ -56,6 +56,18 @@
#define MINUS_80DB_Q1_31 214748 /* 10^(-80/20) */
#define MINUS_90DB_Q1_31 67909 /* 10^(-90/20) */
+/* Compute the number of shifts
+ * This will result in a compiler overflow error if shift bits are out of
+ * range as INT64_MAX/MIN is greater than 32 bit Q shift parameter
+ */
+#define Q_SHIFT_BITS_64(qx, qy, qz) \
+ ((qx + qy - qz) <= 63 ? (((qx + qy - qz) >= 0) ? \
+ (qx + qy - qz) : INT64_MIN) : INT64_MAX)
+
+#define Q_SHIFT_BITS_32(qx, qy, qz) \
+ ((qx + qy - qz) <= 31 ? (((qx + qy - qz) >= 0) ? \
+ (qx + qy - qz) : INT32_MIN) : INT32_MAX)
+
/* Convert a float number to fractional Qnx.ny format. Note that there is no
* check for nx+ny number of bits to fit the word length of int.
*/
@@ -82,28 +94,24 @@
#define SATP_INT32(x) (((x) > INT32_MAXVALUE) ? INT32_MAXVALUE : (x))
#define SATM_INT32(x) (((x) < INT32_MINVALUE) ? INT32_MINVALUE : (x))
-static inline int64_t q_mults_32x32(int32_t x, int32_t y,
- const int qx, const int qy, const int qp)
+static inline int64_t q_mults_32x32(int32_t x, int32_t y, const int shift_bits)
{
- return ((int64_t)x * y) >> (qx+qy-qp);
+ return ((int64_t)x * y) >> shift_bits;
}
-static inline int64_t q_multsr_32x32(int32_t x, int32_t y,
- const int qx, const int qy, const int qp)
+static inline int64_t q_multsr_32x32(int32_t x, int32_t y, const int shift_bits)
{
- return ((((int64_t)x * y) >> (qx+qy-qp-1)) + 1) >> 1;
+ return ((((int64_t)x * y) >> (shift_bits - 1)) + 1) >> 1;
}
-static inline int32_t q_mults_16x16(int16_t x, int16_t y,
- const int qx, const int qy, const int qp)
+static inline int32_t q_mults_16x16(int16_t x, int32_t y, const int shift_bits)
{
- return ((int32_t)x * y) >> (qx+qy-qp);
+ return ((int32_t)x * y) >> shift_bits;
}
-static inline int16_t q_multsr_16x16(int16_t x, int16_t y,
- const int qx, const int qy, const int qp)
+static inline int16_t q_multsr_16x16(int16_t x, int32_t y, const int shift_bits)
{
- return ((((int32_t)x * y) >> (qx+qy-qp-1)) + 1) >> 1;
+ return ((((int32_t)x * y) >> (shift_bits - 1)) + 1) >> 1;
}
/* Saturation inline functions */
@@ -147,4 +155,22 @@ static inline int16_t sat_int16(int32_t x)
return (int16_t)x;
}
+/* Fractional multiplication with shift and saturation */
+static inline int32_t q_multsr_sat_32x32(int32_t x, int32_t y,
+ const int shift_bits)
+{
+ return sat_int32(((((int64_t)x * y) >> (shift_bits - 1)) + 1) >> 1);
+}
+
+static inline int16_t q_multsr_sat_16x16(int16_t x, int32_t y,
+ const int shift_bits)
+{
+ return sat_int16(((((int32_t)x * y) >> (shift_bits - 1)) + 1) >> 1);
+}
+
+static inline int32_t sign_extend_s24(int32_t x)
+{
+ return (x << 8) >> 8;
+}
+
#endif
diff --git a/src/math/trig.c b/src/math/trig.c
index 79eb480..70593e4 100644
--- a/src/math/trig.c
+++ b/src/math/trig.c
@@ -594,6 +594,7 @@ int32_t sin_fixed(int32_t w) {
delta = s1 - s0; /* Q1.31 */
//sine = (int64_t) frac*delta; /* Q1.31 x Q1.31 -> Q2.62 */
//sine = (sine >> 31) + s0; /* Q2.31 */
- sine = s0 + q_mults_32x32(frac, delta, 31, 31, 31); /* All Q1.31 */
+ /* All Q1.31 */
+ sine = s0 + q_mults_32x32(frac, delta, Q_SHIFT_BITS_64(31, 31, 31));
return (int32_t) sine;
}
--
2.11.0
2
1
[Sound-open-firmware] [PATCH 1/2] comp: remove unused list in struct component.
by Liam Girdwood 20 Oct '17
by Liam Girdwood 20 Oct '17
20 Oct '17
Not used so remove.
Signed-off-by: Liam Girdwood <liam.r.girdwood(a)linux.intel.com>
---
src/include/reef/audio/component.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h
index db5f35b..8f5a508 100644
--- a/src/include/reef/audio/component.h
+++ b/src/include/reef/audio/component.h
@@ -186,7 +186,6 @@ struct comp_dev {
struct comp_driver *drv;
/* lists */
- struct list_item list; /* list in components */
struct list_item bsource_list; /* list of source buffers */
struct list_item bsink_list; /* list of sink buffers */
--
2.11.0
1
0
Update trace to align with FW and use 64bit data size.
Signed-off-by: Liam Girdwood <liam.r.girdwood(a)linux.intel.com>
---
rmbox/rmbox.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/rmbox/rmbox.c b/rmbox/rmbox.c
index 9313f4b..b872694 100644
--- a/rmbox/rmbox.c
+++ b/rmbox/rmbox.c
@@ -129,16 +129,28 @@ static void show_trace(uint64_t val, uint64_t addr, uint64_t *timestamp, double
/* 64-bit timestamp */
us = to_usecs(val, clk);
- printf("[%6.6f]\tdelta [%6.6f]\t",
+ /* empty data ? */
+ if (val == 0) {
+ *timestamp = 0;
+ return;
+ }
+
+ /* detect wrap around */
+ if (fdelta < 1000.0 * 1000.0 * 1000.0)
+ printf("0x%lx [%6.6f]\tdelta [%6.6f]\t", addr,
us / 1000000.0 , fdelta / 1000000.0);
+ else
+ printf("0x%lx [%6.6f]\tdelta [********]\t", addr,
+ us / 1000000.0);
*timestamp = val;
return;
- }
+ } else if (*timestamp == 0)
+ return;
/* check for printable values - otherwise it's a value */
if (!isprint((char)(val >> 16)) || !isprint((char)(val >> 8)) || !isprint((char)val)) {
- printf("value 0x%8.8x\n", (uint32_t)val);
+ printf("value 0x%16.16lx\n", val);
return;
}
@@ -237,9 +249,6 @@ trace:
tmp[TRACE_BLOCK_SIZE - i - 1] = c;
}
- if (val == 0)
- break;
-
show_trace(val, addr, ×tamp, clk);
if (out_fd) {
--
1.9.1
1
0
[Sound-open-firmware] [PATCH] SRC: Use a multi-channel FIR core to optimize speed plus other cleanup
by Seppo Ingalsuo 19 Oct '17
by Seppo Ingalsuo 19 Oct '17
19 Oct '17
This patch changes the sample rate conversion processing to use a single
multi-channel filter instead of per channel called mono filter instances.
The filter output is now rounded with 1/2 LSB add. The polyphase filter
input input block sizes are multiplied in SRC initialization to reach
near to or exacly the period length to reduce polyphase filter call
overhead.
The polyphase filter is now called via function pointer for more
flexibility with audio data formats. Currently S32_LE and S24_4LE are
supported.
Code cleanup includes removal of redundant variables and some debug
print code.
Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo(a)linux.intel.com>
---
src/audio/src.c | 198 ++++++++++-------------
src/audio/src_core.c | 447 ++++++++++++++++++++++++++-------------------------
src/audio/src_core.h | 42 +----
3 files changed, 323 insertions(+), 364 deletions(-)
diff --git a/src/audio/src.c b/src/audio/src.c
index 4c4bc6e..854cb82 100644
--- a/src/audio/src.c
+++ b/src/audio/src.c
@@ -55,7 +55,7 @@
/* src component private data */
struct comp_data {
- struct polyphase_src src[PLATFORM_MAX_CHANNELS];
+ struct polyphase_src src;
struct src_param param;
int32_t *delay_lines;
uint32_t sink_rate;
@@ -63,16 +63,16 @@ struct comp_data {
int32_t *sbuf_w_ptr;
int32_t *sbuf_r_ptr;
int sbuf_avail;
- 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,
size_t *consumed,
size_t *produced);
+ void (* polyphase_func)(struct src_stage_prm *s);
};
/* Fallback function */
-static void fallback_s32(struct comp_dev *dev, struct comp_buffer *source,
+static void src_fallback(struct comp_dev *dev, struct comp_buffer *source,
struct comp_buffer *sink, size_t *bytes_read, size_t *bytes_written)
{
*bytes_read = 0;
@@ -84,101 +84,105 @@ static void src_2s_s32_default(struct comp_dev *dev,
struct comp_buffer *source, struct comp_buffer *sink,
size_t *bytes_read, size_t *bytes_written)
{
- struct polyphase_src *s;
struct src_stage_prm s1;
struct src_stage_prm s2;
- int j;
+ int s1_blk_in;
+ int s1_blk_out;
+ int s2_blk_in;
+ int s2_blk_out;
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *dest = (int32_t *) sink->w_ptr;
int32_t *src = (int32_t *) source->r_ptr;
- int32_t *sbuf_addr = cd->delay_lines;
int32_t *sbuf_end_addr = &cd->delay_lines[cd->param.sbuf_length];
int32_t sbuf_size = cd->param.sbuf_length * sizeof(int32_t);
- const int nch = dev->params.channels;
- const int s1_blk_in = cd->src[0].stage1->blk_in * nch;
- const int s1_blk_out = cd->src[0].stage1->blk_out * nch;
- const int s2_blk_in = cd->src[0].stage2->blk_in * nch;
- const int s2_blk_out = cd->src[0].stage2->blk_out * nch;
+ int nch = dev->params.channels;
int sbuf_free = cd->param.sbuf_length - cd->sbuf_avail;
- int source_check = (source->avail >> 2) - s1_blk_in; /* for int32_t */
- int sink_check = (sink->free >> 2) - s2_blk_out; /* For int32_t */
int n_read = 0;
int n_written = 0;
int n1 = 0;
int n2 = 0;
+ int avail = source->avail >> 2; /* For int32_t */
+ int free = sink->free >> 2; /* For int32_t */
- s1.times = 1;
s1.x_end_addr = source->end_addr;
s1.x_size = source->size;
- s1.x_inc = nch;
s1.y_end_addr = sbuf_end_addr;
s1.y_size = sbuf_size;
- s1.y_inc = nch;
+ s1.state = &cd->src.state1;
+ s1.stage = cd->src.stage1;
+ s1.x_rptr = src;
+ s1.y_wptr = cd->sbuf_w_ptr;
+ s1.nch = nch;
- s2.times = 1;
s2.x_end_addr = sbuf_end_addr;
s2.x_size = sbuf_size;
- s2.x_inc = nch;
s2.y_end_addr = sink->end_addr;
s2.y_size = sink->size;
- s2.y_inc = nch;
+ s2.state = &cd->src.state2;
+ s2.stage = cd->src.stage2;
+ s2.x_rptr = cd->sbuf_r_ptr;
+ s2.y_wptr = dest;
+ s2.nch = nch;
+
- /* 1st stage runs once a long multiplied length block.
- * The stage buffer much be large enough to fit one s1 output block
- * plus one s2 input block plus jitter in s2 consumption.
+ /* Test if 1st stage can be run with default block length to reach
+ * the period length or just under it.
*/
- while ((n1 < cd->param.stage1_times_max)
- && (n_read <= source_check)
- && (sbuf_free >= s1_blk_out)) {
- for (j = 0; j < nch; j++) {
- s = &cd->src[j]; /* Point to src[] for this channel */
- s1.x_rptr = src++;
- s1.y_wptr = cd->sbuf_w_ptr++;
- src_circ_inc_wrap(&src, source->end_addr, source->size);
- src_circ_inc_wrap(&cd->sbuf_w_ptr, sbuf_end_addr, sbuf_size);
- s1.state = &s->state1;
- s1.stage = s->stage1;
- if (cd->sign_extend_s24)
- src_polyphase_stage_cir_s24(&s1);
- else
- src_polyphase_stage_cir(&s1);
-
- }
+ s1.times = cd->param.stage1_times;
+ s1_blk_in = s1.times * cd->src.stage1->blk_in * nch;
+ s1_blk_out = s1.times * cd->src.stage1->blk_out * nch;
+ if ((avail >= s1_blk_in) && (sbuf_free >= s1_blk_out)) {
+ cd->polyphase_func(&s1);
+ cd->sbuf_w_ptr = s1.y_wptr;
+ cd->sbuf_avail += s1_blk_out;
n_read += s1_blk_in;
+ avail -= s1_blk_in;
+ sbuf_free -= s1_blk_out;
+ n1 = s1.times;
+ }
+
+ /* Run one block at time the remaining data for 1st stage. */
+ s1.times = 1;
+ s1_blk_in = cd->src.stage1->blk_in * nch;
+ s1_blk_out = cd->src.stage1->blk_out * nch;
+ while ((n1 < cd->param.stage1_times_max) && (avail >= s1_blk_in)
+ && (sbuf_free >= s1_blk_out)) {
+ cd->polyphase_func(&s1);
+ cd->sbuf_w_ptr = s1.y_wptr;
cd->sbuf_avail += s1_blk_out;
+ n_read += s1_blk_in;
+ avail -= s1_blk_in;
sbuf_free -= s1_blk_out;
- src = s1.x_rptr - nch + 1;
- cd->sbuf_w_ptr = s1.y_wptr - nch + 1;
- src_circ_dec_wrap(&src, source->addr, source->size);
- src_circ_dec_wrap(&cd->sbuf_w_ptr, sbuf_addr, sbuf_size);
- n1++;
+ n1 += s1.times;
+ }
+
+ /* Test if 2nd stage can be run with default block length. */
+ s2.times = cd->param.stage2_times;
+ s2_blk_in = s2.times * cd->src.stage2->blk_in * nch;
+ s2_blk_out = s2.times * cd->src.stage2->blk_out * nch;
+ if ((cd->sbuf_avail >= s2_blk_in) && (free >= s2_blk_out)) {
+ cd->polyphase_func(&s2);
+ cd->sbuf_r_ptr = s2.x_rptr;
+ cd->sbuf_avail -= s2_blk_in;
+ free -= s2_blk_out;
+ n_written += s2_blk_out;
+ n2 = s2.times;
}
- /* 2nd stage runs as many min size blocks as buffers allow */
+
+ /* Run one block at time the remaining 2nd stage output */
+ s2.times = 1;
+ s2_blk_in = cd->src.stage2->blk_in * nch;
+ s2_blk_out = cd->src.stage2->blk_out * nch;
while ((n2 < cd->param.stage2_times_max)
&& (cd->sbuf_avail >= s2_blk_in)
- && (n_written <= sink_check)) {
- for (j = 0; j < nch; j++) {
- s2.x_rptr = cd->sbuf_r_ptr++;
- s2.y_wptr = dest++;
- src_circ_inc_wrap(&cd->sbuf_r_ptr, sbuf_end_addr, sbuf_size);
- src_circ_inc_wrap(&dest, sink->end_addr, sink->size);
- s = &cd->src[j]; /* Point to src[] for this channel */
- s2.state = &s->state2;
- s2.stage = s->stage2;
- if (cd->sign_extend_s24)
- src_polyphase_stage_cir_s24(&s2);
- else
- src_polyphase_stage_cir(&s2);
-
- }
- cd->sbuf_r_ptr = s2.x_rptr - nch + 1;
- dest = s2.y_wptr - nch + 1;
- src_circ_dec_wrap(&cd->sbuf_r_ptr, sbuf_addr, sbuf_size);
- src_circ_dec_wrap(&dest, sink->addr, sink->size);
- n_written += s2_blk_out;
+ && (free >= s2_blk_out)) {
+ cd->polyphase_func(&s2);
+ cd->sbuf_r_ptr = s2.x_rptr;
cd->sbuf_avail -= s2_blk_in;
- n2++;
+ free -= s2_blk_out;
+ n_written += s2_blk_out;
+ n2 += s2.times;
}
*bytes_read = sizeof(int32_t) * n_read;
*bytes_written = sizeof(int32_t) * n_written;
@@ -189,42 +193,27 @@ static void src_1s_s32_default(struct comp_dev *dev,
struct comp_buffer *source, struct comp_buffer *sink,
size_t *bytes_read, size_t *bytes_written)
{
- struct polyphase_src *s;
struct src_stage_prm s1;
- int j;
struct comp_data *cd = comp_get_drvdata(dev);
- int32_t *dest = (int32_t *) sink->w_ptr;
- int32_t *src = (int32_t *) source->r_ptr;
int nch = dev->params.channels;
int n_read = 0;
int n_written = 0;
s1.times = cd->param.stage1_times;
+ s1.x_rptr = (int32_t *) source->r_ptr;
s1.x_end_addr = source->end_addr;
s1.x_size = source->size;
- s1.x_inc = nch;
+ s1.y_wptr = (int32_t *) sink->w_ptr;
s1.y_end_addr = sink->end_addr;
s1.y_size = sink->size;
- s1.y_inc = nch;
- s1.x_rptr = src + nch - 1;
- s1.y_wptr = dest + nch - 1;
-
- for (j = 0; j < nch; j++) {
- s = &cd->src[j]; /* Point to src for this channel */
- s1.x_rptr = src++;
- s1.y_wptr = dest++;
- src_circ_inc_wrap(&src, source->end_addr, source->size);
- src_circ_inc_wrap(&dest, sink->end_addr, sink->size);
- s1.state = &s->state1;
- s1.stage = s->stage1;
- if (cd->sign_extend_s24)
- src_polyphase_stage_cir_s24(&s1);
- else
- src_polyphase_stage_cir(&s1);
-
- n_read += cd->param.blk_in;
- n_written += cd->param.blk_out;
- }
+ s1.state = &cd->src.state1;
+ s1.stage = cd->src.stage1;
+ s1.nch = dev->params.channels;
+
+ cd->polyphase_func(&s1);
+
+ n_read += nch * cd->param.blk_in;
+ n_written += nch * cd->param.blk_out;
*bytes_read = n_read * sizeof(int32_t);
*bytes_written = n_written * sizeof(int32_t);
}
@@ -271,7 +260,6 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp)
struct sof_ipc_comp_src *src;
struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *) comp;
struct comp_data *cd;
- int i;
trace_src("new");
@@ -299,8 +287,8 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp)
cd->delay_lines = NULL;
cd->src_func = src_2s_s32_default;
- for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
- src_polyphase_reset(&cd->src[i]);
+ cd->polyphase_func = src_polyphase_stage_cir;
+ src_polyphase_reset(&cd->src);
dev->state = COMP_STATE_READY;
return dev;
@@ -334,10 +322,8 @@ static int src_params(struct comp_dev *dev)
uint32_t sink_rate;
int32_t *buffer_start;
int n = 0;
- int i;
int err;
int frames_is_for_source;
- int nch;
int q;
trace_src("par");
@@ -345,10 +331,10 @@ static int src_params(struct comp_dev *dev)
/* SRC supports S24_4LE and S32_LE formats */
switch (config->frame_fmt) {
case SOF_IPC_FRAME_S24_4LE:
- cd->sign_extend_s24 = 1;
+ cd->polyphase_func = src_polyphase_stage_cir_s24;
break;
case SOF_IPC_FRAME_S32_LE:
- cd->sign_extend_s24 = 0;
+ cd->polyphase_func = src_polyphase_stage_cir;
break;
default:
trace_src_error("sr0");
@@ -407,11 +393,7 @@ static int src_params(struct comp_dev *dev)
buffer_start = cd->delay_lines + cd->param.sbuf_length;
/* Initize SRC for actual sample rate */
- nch = MIN(params->channels, PLATFORM_MAX_CHANNELS);
- for (i = 0; i < nch; i++) {
- n = src_polyphase_init(&cd->src[i], &cd->param, buffer_start);
- buffer_start += cd->param.single_src;
- }
+ n = src_polyphase_init(&cd->src, &cd->param, buffer_start);
/* Reset stage buffer */
cd->sbuf_r_ptr = cd->delay_lines;
@@ -434,7 +416,7 @@ static int src_params(struct comp_dev *dev)
* muted if copy() is run.
*/
trace_src("SFa");
- cd->src_func = fallback_s32;
+ cd->src_func = src_fallback;
return -EINVAL;
break;
}
@@ -532,7 +514,6 @@ static int src_copy(struct comp_dev *dev)
/* Run SRC function if buffers avail and free allow */
if (((int) source->avail >= need_source) && ((int) sink->free >= need_sink)) {
- /* Run src */
cd->src_func(dev, source, sink, &consumed, &produced);
/* Calc new free and available if data was processed. These
@@ -561,14 +542,12 @@ static int src_preload(struct comp_dev *dev)
static int src_reset(struct comp_dev *dev)
{
- int i;
struct comp_data *cd = comp_get_drvdata(dev);
trace_src("SRe");
cd->src_func = src_2s_s32_default;
- for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
- src_polyphase_reset(&cd->src[i]);
+ src_polyphase_reset(&cd->src);
comp_set_state(dev, COMP_CMD_RESET);
return 0;
@@ -576,7 +555,8 @@ static int src_reset(struct comp_dev *dev)
struct comp_driver comp_src = {
.type = SOF_COMP_SRC,
- .ops = {
+ .ops =
+ {
.new = src_new,
.free = src_free,
.params = src_params,
diff --git a/src/audio/src_core.c b/src/audio/src_core.c
index 4ee2efd..0d8cc17 100644
--- a/src/audio/src_core.c
+++ b/src/audio/src_core.c
@@ -51,6 +51,10 @@ int sof_rates[SOF_RATES_LENGTH] = {8000, 11025, 12000, 16000, 18900,
22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400,
192000};
+/* The FIR maximum lenghts are per channel so need to multiply them */
+#define MAX_FIR_DELAY_SIZE_XNCH (PLATFORM_MAX_CHANNELS * MAX_FIR_DELAY_SIZE)
+#define MAX_OUT_DELAY_SIZE_XNCH (PLATFORM_MAX_CHANNELS * MAX_OUT_DELAY_SIZE)
+
/* Calculate ceil() for integer division */
int src_ceil_divide(int a, int b)
{
@@ -131,6 +135,10 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch,
int num;
int frames2;
+ if (nch > PLATFORM_MAX_CHANNELS)
+ return -EINVAL;
+
+ a->nch = nch;
a->idx_in = src_find_fs(src_in_fs, NUM_IN_FS, fs_in);
a->idx_out = src_find_fs(src_out_fs, NUM_OUT_FS, fs_out);
@@ -146,8 +154,8 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch,
stage1 = src_table1[a->idx_out][a->idx_in];
stage2 = src_table2[a->idx_out][a->idx_in];
- a->fir_s1 = src_fir_delay_length(stage1);
- a->out_s1 = src_out_delay_length(stage1);
+ a->fir_s1 = nch * src_fir_delay_length(stage1);
+ a->out_s1 = nch * src_out_delay_length(stage1);
/* Find out how many additional times the SRC can be executed
while having block size less or equal to max_frames.
@@ -191,8 +199,8 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch,
a->stage2_times_max = 0;
a->sbuf_length = 0;
} else {
- a->fir_s2 = src_fir_delay_length(stage2);
- a->out_s2 = src_out_delay_length(stage2);
+ a->fir_s2 = nch * src_fir_delay_length(stage2);
+ a->out_s2 = nch * src_out_delay_length(stage2);
/* 2x is an empirically tested length. Since the sink buffer
* capability to receive samples varies a shorter stage 2 output
* block will create a peak in internal buffer usage.
@@ -200,8 +208,8 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch,
a->sbuf_length = 2 * nch * stage1->blk_out * a->stage1_times_max;
}
- a->single_src = a->fir_s1 + a->fir_s2 + a->out_s1 + a->out_s2;
- a->total = a->sbuf_length + nch * a->single_src;
+ a->src_multich = a->fir_s1 + a->fir_s2 + a->out_s1 + a->out_s2;
+ a->total = a->sbuf_length + a->src_multich;
return 0;
}
@@ -212,8 +220,6 @@ static void src_state_reset(struct src_state *state)
state->fir_delay_size = 0;
state->out_delay_size = 0;
state->fir_wi = 0;
- state->fir_ri = 0;
- state->out_wi = 0;
state->out_ri = 0;
}
@@ -229,17 +235,8 @@ static int init_stages(
src->number_of_stages = n;
src->stage1 = stage1;
src->stage2 = stage2;
- src->blk_in = p->blk_in;
- src->blk_out = p->blk_out;
- if (n == 1) {
- src->stage1_times = p->stage1_times;
- src->stage2_times = 0;
- if (stage1->blk_out == 0)
- return -EINVAL;
- } else {
- src->stage1_times = p->stage1_times;
- src->stage2_times = p->stage2_times;
- }
+ if ((n == 1) && (stage1->blk_out == 0))
+ return -EINVAL;
/* Delay line sizes */
src->state1.fir_delay_size = p->fir_s1;
@@ -262,10 +259,10 @@ static int init_stages(
}
/* Check the sizes are less than MAX */
- if ((src->state1.fir_delay_size > MAX_FIR_DELAY_SIZE)
- || (src->state1.out_delay_size > MAX_OUT_DELAY_SIZE)
- || (src->state2.fir_delay_size > MAX_FIR_DELAY_SIZE)
- || (src->state2.out_delay_size > MAX_OUT_DELAY_SIZE)) {
+ if ((src->state1.fir_delay_size > MAX_FIR_DELAY_SIZE_XNCH)
+ || (src->state1.out_delay_size > MAX_OUT_DELAY_SIZE_XNCH)
+ || (src->state2.fir_delay_size > MAX_FIR_DELAY_SIZE_XNCH)
+ || (src->state2.out_delay_size > MAX_OUT_DELAY_SIZE_XNCH)) {
src->state1.fir_delay = NULL;
src->state1.out_delay = NULL;
src->state2.fir_delay = NULL;
@@ -279,12 +276,7 @@ static int init_stages(
void src_polyphase_reset(struct polyphase_src *src)
{
- src->mute = 0;
src->number_of_stages = 0;
- src->blk_in = 0;
- src->blk_out = 0;
- src->stage1_times = 0;
- src->stage2_times = 0;
src->stage1 = NULL;
src->stage2 = NULL;
src_state_reset(&src->state1);
@@ -300,8 +292,6 @@ int src_polyphase_init(struct polyphase_src *src, struct src_param *p,
struct src_stage *stage2;
if ((p->idx_in < 0) || (p->idx_out < 0)) {
- src->blk_in = p->blk_in;
- src->blk_out = p->blk_out;
return -EINVAL;
}
@@ -335,141 +325,203 @@ int src_polyphase_init(struct polyphase_src *src, struct src_param *p,
#if SRC_SHORT == 1
/* Calculate a FIR filter part that does not need circular modification */
-static inline void fir_part(int64_t *y, int ntaps, const int16_t c[], int *ic,
- int32_t d[], int *id)
+
+static inline void fir_part(int64_t y[], int *id, int *ic,
+ const int32_t data[], const int16_t coef[], int nch_x_taps, int nch)
{
+ int64_t tap0;
+ int64_t tap1;
int n;
int64_t a = 0;
+ int64_t b = 0;
+ int c = *ic;
+ int d = *id;
+ int d_end = d - nch_x_taps;
/* Data is Q1.31, coef is Q1.15, product is Q2.46 */
- for (n = 0; n < (ntaps >> 1); n++) {
- a += (int64_t) c[*ic] * d[*id]
- + (int64_t) c[*ic + 1] * d[*id - 1];
- *ic += 2;
- *id -= 2;
+ if (nch == 2) {
+ for (n = 0; n < (nch_x_taps >> 2); n++) {
+ tap0 = coef[c++];
+ tap1 = coef[c++];
+ b += data[d--] * tap0;
+ a += data[d--] * tap0;
+ b += data[d--] * tap1;
+ a += data[d--] * tap1;
+ }
+ if (d > d_end) {
+ tap0 = coef[c++];
+ b += data[d--] * tap0;
+ a += data[d--] * tap0;
+ }
+ y[1] += b;
+ y[0] += a;
+ } else {
+ while (d > d_end) {
+ tap0 = coef[c++];
+ for (n = nch - 1; n >= 0; n--)
+ y[n] += data[d--] * tap0;
+ }
}
- if (ntaps & 1)
- a += (int64_t) c[(*ic)++] * d[(*id)--];
-
- *y += a;
+ *ic = c;
+ *id = d;
}
+
#else
-/* Calculate a FIR filter part that does not need circular modification */
-static inline void fir_part(int64_t *y, int ntaps, const int32_t c[], int *ic,
- int32_t d[], int *id)
+static inline void fir_part(int64_t y[], int *id, int *ic,
+ const int32_t data[], const int32_t coef[], int nch_x_taps, int nch)
{
+ int64_t tap0;
+ int64_t tap1;
int n;
int64_t a = 0;
-
- /* Data is Q8.24, coef is Q1.23, product is Q9.47 */
- for (n = 0; n < (ntaps >> 1); n++) {
- a += (int64_t) c[*ic] * d[*id]
- + (int64_t) c[*ic + 1] * d[*id - 1];
- *ic += 2;
- *id -= 2;
+ int64_t b = 0;
+ int c = *ic;
+ int d = *id;
+ int d_end = d - nch_x_taps;
+
+ /* Data is Q1.31, coef is Q1.23, product is Q2.54 */
+ if (nch == 2) {
+ for (n = 0; n < (nch_x_taps >> 2); n++) {
+ tap0 = coef[c++];
+ tap1 = coef[c++];
+ b += data[d--] * tap0;
+ a += data[d--] * tap0;
+ b += data[d--] * tap1;
+ a += data[d--] * tap1;
+ }
+ if (d > d_end) {
+ tap0 = coef[c++];
+ b += data[d--] * tap0;
+ a += data[d--] * tap0;
+ }
+ y[1] += b;
+ y[0] += a;
+ } else {
+ while (d > d_end) {
+ tap0 = coef[c++];
+ for (n = nch - 1; n >= 0; n--)
+ y[n] += data[d--] * tap0;
+ }
}
- if (ntaps & 1)
- a += (int64_t) c[(*ic)++] * d[(*id)--];
-
- *y += a;
+ *ic = c;
+ *id = d;
}
+
#endif
#if SRC_SHORT == 1
-static inline int32_t fir_filter(
- struct src_state *fir, const int16_t coefs[],
- int *coefi, int filter_length, int shift)
+static void fir_filter(int ri0, int *ci, int wi0, int32_t in_delay[],
+ int32_t out_delay[], const int16_t coefs[], int dsm1, int taps,
+ int shift, int nch)
{
- int64_t y = 0;
- int n1;
int n2;
-
- n1 = fir->fir_ri + 1;
- if (n1 > filter_length) {
- /* No need to un-wrap fir read index, make sure fir_fi
- * is ge 0 after FIR computation.
- */
- fir_part(&y, filter_length, coefs, coefi, fir->fir_delay,
- &fir->fir_ri);
+ int i;
+ int64_t y[PLATFORM_MAX_CHANNELS];
+ int ri = ri0;
+ int wi = wi0;
+ int n1 = ri0 + 1; /* Convert to number of sequential frames */
+ int qshift = 15 + shift; /* Q2.46 -> Q2.31 */
+ int32_t rnd = 1 << (qshift - 1); /* Half LSB */
+ int nch_x_taps = nch * taps;
+
+ /* Initialize to half LSB for rounding */
+ for (i = 0; i < nch; i++)
+ y[i] = rnd;
+
+ if (n1 >= nch_x_taps) {
+ fir_part(y, &ri, ci, in_delay, coefs, nch_x_taps, nch);
} else {
- n2 = filter_length - n1;
- /* Part 1, loop n1 times, fir_ri becomes -1 */
- fir_part(&y, n1, coefs, coefi, fir->fir_delay, &fir->fir_ri);
-
- /* Part 2, unwrap fir_ri, continue rest of filter */
- fir->fir_ri = fir->fir_delay_size - 1;
- fir_part(&y, n2, coefs, coefi, fir->fir_delay, &fir->fir_ri);
+ n2 = nch_x_taps - n1;
+ fir_part(y, &ri, ci, in_delay, coefs, n1, nch);
+ ri = dsm1;
+ fir_part(y, &ri, ci, in_delay, coefs, n2, nch);
}
- /* Q2.46 -> Q2.31, saturate to Q1.31 */
- y = y >> (15 + shift);
- return(int32_t) sat_int32(y);
+ for (i = 0; i < nch; i++)
+ out_delay[wi++] = sat_int32(y[i] >> qshift);
}
#else
-static inline int32_t fir_filter(
- struct src_state *fir, const int32_t coefs[],
- int *coefi, int filter_length, int shift)
+static void fir_filter(int ri0, int *ci, int wi0, int32_t in_delay[],
+ int32_t out_delay[], const int32_t coefs[], int dsm1, int taps,
+ int shift, int nch)
{
- int64_t y = 0;
- int n1;
int n2;
-
- n1 = fir->fir_ri + 1;
- if (n1 > filter_length) {
- /* No need to un-wrap fir read index, make sure fir_fi
- * is ge 0 after FIR computation.
- */
- fir_part(&y, filter_length, coefs, coefi, fir->fir_delay,
- &fir->fir_ri);
+ int i;
+ int64_t y[PLATFORM_MAX_CHANNELS];
+ int ri = ri0;
+ int wi = wi0;
+ int n1 = ri0 + 1; /* Convert to number of sequential frames */
+ int qshift = 23 + shift; /* Q2.54 -> Q2.31 */
+ int32_t rnd = 1 << (qshift - 1); /* Half LSB */
+ int nch_x_taps = nch * taps;
+
+ /* Initialize to half LSB for rounding */
+ for (i = 0; i < nch; i++)
+ y[i] = rnd;
+
+ if (n1 >= nch_x_taps) {
+ fir_part(y, &ri, ci, in_delay, coefs, nch_x_taps, nch);
} else {
- n2 = filter_length - n1;
- /* Part 1, loop n1 times, fir_ri becomes -1 */
- fir_part(&y, n1, coefs, coefi, fir->fir_delay, &fir->fir_ri);
-
- /* Part 2, unwrap fir_ri, continue rest of filter */
- fir->fir_ri = fir->fir_delay_size - 1;
- fir_part(&y, n2, coefs, coefi, fir->fir_delay, &fir->fir_ri);
+ n2 = nch_x_taps - n1;
+ fir_part(y, &ri, ci, in_delay, coefs, n1, nch);
+ ri = dsm1;
+ fir_part(y, &ri, ci, in_delay, coefs, n2, nch);
}
- /* Q9.47 -> Q9.24, saturate to Q8.24 */
- y = y >> (23 + shift);
- return(int32_t) sat_int32(y);
+ for (i = 0; i < nch; i++)
+ out_delay[wi++] = sat_int32(y[i] >> qshift);
+
}
+
#endif
void src_polyphase_stage_cir(struct src_stage_prm * s)
{
- struct src_state *fir = s->state;
- struct src_stage *cfg = s->stage;
int n;
int m;
int f;
- int c;
- int r;
+ int ci;
+ int ri;
int n_wrap_fir;
int n_wrap_buf;
int n_wrap_min;
int n_min;
- int32_t z;
+ int wi;
+
+ struct src_state *fir = s->state;
+ struct src_stage *cfg = s->stage;
+ const void *coef = cfg->coefs;
+ int32_t *in_delay = fir->fir_delay;
+ int32_t *out_delay = fir->out_delay;
+ int dsm1 = fir->fir_delay_size - 1;
+ int shift = cfg->shift;
+ int nch = s->nch;
+ int rewind = -nch * (cfg->blk_in
+ + (cfg->num_of_subfilters - 1) * cfg->idm) + nch - 1;
+ int nch_x_idm = cfg->idm * nch;
+ int nch_x_odm = cfg->odm * nch;
+ size_t sz = sizeof(int32_t);
+ int blk_in_bytes = nch * cfg->blk_in * sz;
+ int blk_out_bytes = nch * cfg->num_of_subfilters * sz;
+
for (n = 0; n < s->times; n++) {
/* Input data */
- m = s->x_inc * cfg->blk_in;
+ m = blk_in_bytes;
while (m > 0) {
- n_wrap_fir = (fir->fir_delay_size - fir->fir_wi)
- * s->x_inc;
+ n_wrap_fir = (fir->fir_delay_size - fir->fir_wi) * sz;
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;
n_min = (m < n_wrap_min) ? m : n_wrap_min;
while (n_min > 0) {
fir->fir_delay[fir->fir_wi++] = *s->x_rptr;
- s->x_rptr += s->x_inc;
- n_min -= s->x_inc;
- m -= s->x_inc;
+ s->x_rptr++;
+ n_min -= sz;
+ m -= sz;
}
/* Check for wrap */
src_circ_inc_wrap(&s->x_rptr, s->x_end_addr, s->x_size);
@@ -478,41 +530,38 @@ void src_polyphase_stage_cir(struct src_stage_prm * s)
}
/* Filter */
- c = 0;
- r = fir->fir_wi - cfg->blk_in
- - (cfg->num_of_subfilters - 1) * cfg->idm;
- if (r < 0)
- r += fir->fir_delay_size;
+ ci = 0; /* Reset to 1st coefficient */
+ ri = fir->fir_wi + rewind; /* Newest data for last subfilter */
+ if (ri < 0)
+ ri += fir->fir_delay_size;
- fir->out_wi = fir->out_ri;
+ wi = fir->out_ri;
for (f = 0; f < cfg->num_of_subfilters; f++) {
- fir->fir_ri = r;
- z = fir_filter(fir, cfg->coefs, &c,
- cfg->subfilter_length, cfg->shift);
- r += cfg->idm;
- if (r >= fir->fir_delay_size)
- r -= fir->fir_delay_size;
-
- fir->out_delay[fir->out_wi] = z;
- fir->out_wi += cfg->odm;
- if (fir->out_wi >= fir->out_delay_size)
- fir->out_wi -= fir->out_delay_size;
+ fir_filter(ri, &ci, wi, in_delay, out_delay, coef,
+ dsm1, cfg->subfilter_length, shift, nch);
+
+ wi += nch_x_odm;
+ if (wi >= fir->out_delay_size)
+ wi -= fir->out_delay_size;
+
+ ri += nch_x_idm; /* Next sub-filter start */
+ if (ri >= fir->fir_delay_size)
+ ri -= fir->fir_delay_size;
}
/* Output */
- m = s->y_inc * cfg->num_of_subfilters;
+ m = blk_out_bytes;
while (m > 0) {
- n_wrap_fir = (fir->out_delay_size - fir->out_ri)
- * s->y_inc;
+ n_wrap_fir = (fir->out_delay_size - fir->out_ri) * sz;
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;
n_min = (m < n_wrap_min) ? m : n_wrap_min;
while (n_min > 0) {
*s->y_wptr = fir->out_delay[fir->out_ri++];
- s->y_wptr += s->y_inc;
- n_min -= s->y_inc;
- m -= s->y_inc;
+ s->y_wptr++;
+ n_min -= sz;
+ m -= sz;
}
/* Check wrap */
src_circ_inc_wrap(&s->y_wptr, s->y_end_addr, s->y_size);
@@ -522,38 +571,49 @@ void src_polyphase_stage_cir(struct src_stage_prm * s)
}
}
-void src_polyphase_stage_cir_s24(struct src_stage_prm * s)
+void src_polyphase_stage_cir_s24(struct src_stage_prm *s)
{
- struct src_state *fir = s->state;
- struct src_stage *cfg = s->stage;
int n;
int m;
int f;
- int c;
- int r;
+ int ci;
+ int ri;
int n_wrap_fir;
int n_wrap_buf;
int n_wrap_min;
int n_min;
- int32_t z;
- int32_t se;
+ int wi;
+
+ struct src_state *fir = s->state;
+ struct src_stage *cfg = s->stage;
+ const void *coef = cfg->coefs;
+ int32_t *in_delay = fir->fir_delay;
+ int32_t *out_delay = fir->out_delay;
+ int dsm1 = fir->fir_delay_size - 1;
+ int shift = cfg->shift;
+ int nch = s->nch;
+ int rewind = -nch * (cfg->blk_in
+ + (cfg->num_of_subfilters - 1) * cfg->idm) + nch - 1;
+ int nch_x_idm = cfg->idm * nch;
+ int nch_x_odm = cfg->odm * nch;
+ size_t sz = sizeof(int32_t);
+ int blk_in_bytes = nch * cfg->blk_in * sz;
+ int blk_out_bytes = nch * cfg->num_of_subfilters * sz;
for (n = 0; n < s->times; n++) {
/* Input data */
- m = s->x_inc * cfg->blk_in;
+ m = blk_in_bytes;
while (m > 0) {
- n_wrap_fir = (fir->fir_delay_size - fir->fir_wi)
- * s->x_inc;
+ n_wrap_fir = (fir->fir_delay_size - fir->fir_wi) * sz;
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;
n_min = (m < n_wrap_min) ? m : n_wrap_min;
while (n_min > 0) {
- se = *s->x_rptr << 8;
- fir->fir_delay[fir->fir_wi++] = se >> 8;
- s->x_rptr += s->x_inc;
- n_min -= s->x_inc;
- m -= s->x_inc;
+ fir->fir_delay[fir->fir_wi++] = *s->x_rptr << 8;
+ s->x_rptr++;
+ n_min -= sz;
+ m -= sz;
}
/* Check for wrap */
src_circ_inc_wrap(&s->x_rptr, s->x_end_addr, s->x_size);
@@ -562,41 +622,38 @@ void src_polyphase_stage_cir_s24(struct src_stage_prm * s)
}
/* Filter */
- c = 0;
- r = fir->fir_wi - cfg->blk_in
- - (cfg->num_of_subfilters - 1) * cfg->idm;
- if (r < 0)
- r += fir->fir_delay_size;
+ ci = 0; /* Reset to 1st coefficient */
+ ri = fir->fir_wi + rewind; /* Newest data for last subfilter */
+ if (ri < 0)
+ ri += fir->fir_delay_size;
- fir->out_wi = fir->out_ri;
+ wi = fir->out_ri;
for (f = 0; f < cfg->num_of_subfilters; f++) {
- fir->fir_ri = r;
- z = fir_filter(fir, cfg->coefs, &c,
- cfg->subfilter_length, cfg->shift);
- r += cfg->idm;
- if (r >= fir->fir_delay_size)
- r -= fir->fir_delay_size;
-
- fir->out_delay[fir->out_wi] = z;
- fir->out_wi += cfg->odm;
- if (fir->out_wi >= fir->out_delay_size)
- fir->out_wi -= fir->out_delay_size;
+ fir_filter(ri, &ci, wi, in_delay, out_delay, coef,
+ dsm1, cfg->subfilter_length, shift, nch);
+
+ wi += nch_x_odm;
+ if (wi >= fir->out_delay_size)
+ wi -= fir->out_delay_size;
+
+ ri += nch_x_idm; /* Next sub-filter start */
+ if (ri >= fir->fir_delay_size)
+ ri -= fir->fir_delay_size;
}
/* Output */
- m = s->y_inc * cfg->num_of_subfilters;
+ m = blk_out_bytes;
while (m > 0) {
- n_wrap_fir = (fir->out_delay_size - fir->out_ri)
- * s->y_inc;
+ n_wrap_fir = (fir->out_delay_size - fir->out_ri) * sz;
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;
n_min = (m < n_wrap_min) ? m : n_wrap_min;
while (n_min > 0) {
- *s->y_wptr = fir->out_delay[fir->out_ri++];
- s->y_wptr += s->y_inc;
- n_min -= s->y_inc;
- m -= s->y_inc;
+ *s->y_wptr = fir->out_delay[fir->out_ri++] >> 8;
+ s->y_wptr++;
+ n_min -= sz;
+ m -= sz;
}
/* Check wrap */
src_circ_inc_wrap(&s->y_wptr, s->y_end_addr, s->y_size);
@@ -604,47 +661,5 @@ void src_polyphase_stage_cir_s24(struct src_stage_prm * s)
fir->out_ri = 0;
}
}
-}
-
-#ifdef MODULE_TEST
-
-void src_print_info(struct polyphase_src * src)
-{
-
- int n1;
- int n2;
-
- n1 = src->stage1->filter_length;
- n2 = src->stage2->filter_length;
- printf("SRC stages %d\n", src->number_of_stages);
- printf("SRC input blk %d\n", src->blk_in);
- printf("SRC output blk %d\n", src->blk_out);
- printf("SRC stage1 %d times\n", src->stage1_times);
- printf("SRC stage2 %d times\n", src->stage2_times);
-
- printf("SRC1 filter length %d\n", n1);
- printf("SRC1 subfilter length %d\n", src->stage1->subfilter_length);
- printf("SRC1 number of subfilters %d\n",
- src->stage1->num_of_subfilters);
- printf("SRC1 idm %d\n", src->stage1->idm);
- printf("SRC1 odm %d\n", src->stage1->odm);
- printf("SRC1 input blk %d\n", src->stage1->blk_in);
- printf("SRC1 output blk %d\n", src->stage1->blk_out);
- printf("SRC1 halfband %d\n", src->stage1->halfband);
- printf("SRC1 FIR delay %d\n", src->state1.fir_delay_size);
- printf("SRC1 out delay %d\n", src->state1.out_delay_size);
-
- printf("SRC2 filter length %d\n", n2);
- printf("SRC2 subfilter length %d\n", src->stage2->subfilter_length);
- printf("SRC2 number of subfilters %d\n",
- src->stage2->num_of_subfilters);
- printf("SRC2 idm %d\n", src->stage2->idm);
- printf("SRC2 odm %d\n", src->stage2->odm);
- printf("SRC2 input blk %d\n", src->stage2->blk_in);
- printf("SRC2 output blk %d\n", src->stage2->blk_out);
- printf("SRC2 halfband %d\n", src->stage2->halfband);
- printf("SRC2 FIR delay %d\n", src->state2.fir_delay_size);
- printf("SRC2 out delay %d\n", src->state2.out_delay_size);
}
-#endif
diff --git a/src/audio/src_core.h b/src/audio/src_core.h
index 3859e6f..3ea6028 100644
--- a/src/audio/src_core.h
+++ b/src/audio/src_core.h
@@ -41,7 +41,7 @@ struct src_param {
int out_s1;
int out_s2;
int sbuf_length;
- int single_src;
+ int src_multich;
int total;
int blk_in;
int blk_out;
@@ -51,6 +51,7 @@ struct src_param {
int stage2_times_max;
int idx_in;
int idx_out;
+ int nch;
};
struct src_stage {
@@ -70,20 +71,13 @@ struct src_state {
int fir_delay_size;
int out_delay_size;
int fir_wi;
- int fir_ri;
- int out_wi;
int out_ri;
int32_t *fir_delay;
int32_t *out_delay;
};
struct polyphase_src {
- int mute;
int number_of_stages;
- int blk_in;
- int blk_out;
- int stage1_times;
- int stage2_times;
struct src_stage *stage1;
struct src_stage *stage2;
struct src_state state1;
@@ -91,15 +85,14 @@ struct polyphase_src {
};
struct src_stage_prm {
+ int nch;
int times;
int32_t *x_rptr;
int32_t *x_end_addr;
size_t x_size;
- int x_inc;
int32_t *y_wptr;
int32_t *y_end_addr;
size_t y_size;
- int y_inc;
struct src_state *state;
struct src_stage *stage;
};
@@ -116,31 +109,6 @@ static inline void src_circ_dec_wrap(int32_t **ptr, int32_t *addr, size_t size)
*ptr = (int32_t *) ((size_t) * ptr + size);
}
-static inline void src_polyphase_mute(struct polyphase_src *src)
-{
- src->mute = 1;
-}
-
-static inline void src_polyphase_unmute(struct polyphase_src *src)
-{
- src->mute = 0;
-}
-
-static inline int src_polyphase_getmute(struct polyphase_src *src)
-{
- return src->mute;
-}
-
-static inline int src_polyphase_get_blk_in(struct polyphase_src *src)
-{
- return src->blk_in;
-}
-
-static inline int src_polyphase_get_blk_out(struct polyphase_src *src)
-{
- return src->blk_out;
-}
-
void src_polyphase_reset(struct polyphase_src *src);
int src_polyphase_init(struct polyphase_src *src, struct src_param *p,
@@ -162,8 +130,4 @@ int32_t src_output_rates(void);
int src_ceil_divide(int a, int b);
-#ifdef MODULE_TEST
-void src_print_info(struct polyphase_src *src);
-#endif
-
#endif
--
2.11.0
2
1