Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 91 additions & 40 deletions src/audio/eq_fir/eq_fir.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <sof/audio/data_blob.h>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new FIR worked in my device tests, but I could not run tests with xtensa build of sof-testbench4. There is a build fail. It also appears as a warning in normal FW build. Please fix it to preserve test-ability.

#include <sof/audio/pipeline.h>
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/audio/sink_source_utils.h>
#include <sof/audio/ipc-config.h>
#include <sof/common.h>
#include <rtos/panic.h>
Expand Down Expand Up @@ -40,21 +41,6 @@ LOG_MODULE_REGISTER(eq_fir, CONFIG_SOF_LOG_LEVEL);

SOF_DEFINE_REG_UUID(eq_fir);

/* Pass-through functions to replace FIR core while not configured for
* response.
*/

static void eq_fir_passthrough(struct fir_state_32x16 fir[],
struct input_stream_buffer *bsource,
struct output_stream_buffer *bsink,
int frames)
{
struct audio_stream *source = bsource->data;
struct audio_stream *sink = bsink->data;

audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source));
}

static void eq_fir_free_delaylines(struct processing_module *mod)
{
struct comp_data *cd = module_get_private_data(mod);
Expand Down Expand Up @@ -378,14 +364,20 @@ static int eq_fir_set_config(struct processing_module *mod, uint32_t config_id,

/* copy and process stream data from source to sink buffers */
static int eq_fir_process(struct processing_module *mod,
struct input_stream_buffer *input_buffers,
int num_input_buffers,
struct output_stream_buffer *output_buffers,
int num_output_buffers)
struct sof_source **sources, int num_of_sources,
struct sof_sink **sinks, int num_of_sinks)
Comment thread
piotrhoppeintel marked this conversation as resolved.
{
struct comp_data *cd = module_get_private_data(mod);
struct audio_stream *source = input_buffers[0].data;
uint32_t frame_count = input_buffers[0].size;
struct sof_source *source = sources[0];
struct sof_sink *sink = sinks[0];
struct cir_buf_source source_buf;
struct cir_buf_sink sink_buf;
size_t source_frame_bytes;
size_t sink_frame_bytes;
size_t source_bytes;
size_t sink_bytes;
size_t buffer_size;
size_t frame_count;
int ret;

comp_dbg(mod->dev, "entry");
Expand All @@ -395,17 +387,17 @@ static int eq_fir_process(struct processing_module *mod,
cd->config = comp_get_data_blob(cd->model_handler, &cd->config_size, NULL);
if (!cd->config || eq_fir_check_blob_size(mod->dev, cd->config_size) < 0)
return -EINVAL;
ret = eq_fir_setup(mod, audio_stream_get_channels(source));
ret = eq_fir_setup(mod, source_get_channels(source));
if (ret < 0) {
comp_err(mod->dev, "failed FIR setup");
return ret;
} else if (cd->fir_delay_size) {
comp_dbg(mod->dev, "active");
ret = set_fir_func(mod, audio_stream_get_frm_fmt(source));
ret = set_fir_func(mod, source_get_frm_fmt(source));
if (ret < 0)
return ret;
} else {
cd->eq_fir_func = eq_fir_passthrough;
cd->eq_fir_func = NULL;
comp_dbg(mod->dev, "pass-through");
}
}
Expand All @@ -418,56 +410,115 @@ static int eq_fir_process(struct processing_module *mod,
* break the delay line alignment if called with odd number of frames
* so it can't be used here.
*/

frame_count = source_sink_avail_frames_aligned(source, sink);
frame_count &= ~0x1;
if (frame_count) {
cd->eq_fir_func(cd->fir, &input_buffers[0], &output_buffers[0], frame_count);
module_update_buffer_position(&input_buffers[0], &output_buffers[0], frame_count);
if (!frame_count)
return 0;

source_frame_bytes = source_get_frame_bytes(source);
sink_frame_bytes = sink_get_frame_bytes(sink);
source_bytes = frame_count * source_frame_bytes;
sink_bytes = frame_count * sink_frame_bytes;

if (!cd->fir_delay_size) {
if (source_frame_bytes != sink_frame_bytes)
return -EINVAL;

return source_to_sink_copy(source, sink, true, source_bytes);
}

return 0;
if (!cd->eq_fir_func)
return -EINVAL;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is actually impossible, right? cd->eq_fir_func == NULL is only possible if cd->fir_delay_size == 0 and then you'd take one of returns in lines 425 or 427. If you really want you could just use an assertion here.


ret = source_get_data(source, source_bytes, &source_buf.ptr,
&source_buf.buf_start, &buffer_size);
if (ret < 0)
return ret;
if (buffer_size < source_bytes) {
comp_err(mod->dev, "source buffer size %zu is insufficient for %zu bytes",
buffer_size, source_bytes);
source_release_data(source, 0);
return -EINVAL;
}
source_buf.buf_end = (const char *)source_buf.buf_start + buffer_size;

ret = sink_get_buffer(sink, sink_bytes, &sink_buf.ptr, &sink_buf.buf_start,
&buffer_size);
if (ret < 0) {
source_release_data(source, 0);
return ret;
}
if (buffer_size < sink_bytes) {
comp_err(mod->dev, "sink buffer size %zu is insufficient for %zu bytes",
buffer_size, sink_bytes);
source_release_data(source, 0);
sink_commit_buffer(sink, 0);
return -EINVAL;
}
sink_buf.buf_end = (char *)sink_buf.buf_start + buffer_size;

cd->eq_fir_func(cd->fir, &source_buf, &sink_buf, frame_count, cd->nch);

ret = source_release_data(source, source_bytes);
if (ret < 0) {
sink_commit_buffer(sink, 0);
return ret;
}

return sink_commit_buffer(sink, sink_bytes);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you be converting them all to use your new release_source_and_commit_sink()?

}

static void eq_fir_set_alignment(struct audio_stream *source)
static int eq_fir_set_alignment(struct sof_source *source)
{
const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN;
const uint32_t frame_align_req = 2; /* Process multiples of 2 frames */

audio_stream_set_align(byte_align, frame_align_req, source);
return source_set_alignment_constants(source, byte_align, frame_align_req);
}

static int eq_fir_prepare(struct processing_module *mod,
struct sof_source **sources, int num_of_sources,
struct sof_sink **sinks, int num_of_sinks)
{
struct comp_data *cd = module_get_private_data(mod);
struct comp_buffer *sourceb, *sinkb;
struct comp_dev *dev = mod->dev;
struct sof_source *source;
struct sof_sink *sink;
int channels;
enum sof_ipc_frame frame_fmt;
int ret = 0;

comp_dbg(dev, "entry");

/* EQ component will only ever have 1 source and 1 sink buffer. */
sourceb = comp_dev_get_first_data_producer(dev);
sinkb = comp_dev_get_first_data_consumer(dev);
if (!sourceb || !sinkb) {
if (num_of_sources != 1 || num_of_sinks != 1) {
comp_err(dev, "no source or sink buffer");
return -ENOTCONN;
}

source = sources[0];
sink = sinks[0];

ret = eq_fir_params(mod);
if (ret < 0) {
comp_set_state(dev, COMP_TRIGGER_RESET);
return ret;
}

eq_fir_set_alignment(&sourceb->stream);
channels = audio_stream_get_channels(&sinkb->stream);
frame_fmt = audio_stream_get_frm_fmt(&sourceb->stream);
ret = eq_fir_set_alignment(source);
if (ret < 0)
return ret;

if (source_get_channels(source) != sink_get_channels(sink) ||
source_get_frm_fmt(source) != sink_get_frm_fmt(sink)) {
comp_err(dev, "source and sink audio formats do not match");
return -EINVAL;
}

channels = sink_get_channels(sink);
frame_fmt = source_get_frm_fmt(source);

cd->eq_fir_func = eq_fir_passthrough;
cd->eq_fir_func = NULL;
cd->config = comp_get_data_blob(cd->model_handler, &cd->config_size, NULL);
if (cd->config) {
if (eq_fir_check_blob_size(dev, cd->config_size) < 0)
Expand Down Expand Up @@ -514,7 +565,7 @@ static const struct module_interface eq_fir_interface = {
.free = eq_fir_free,
.set_configuration = eq_fir_set_config,
.get_configuration = eq_fir_get_config,
.process_audio_stream = eq_fir_process,
.process = eq_fir_process,
.prepare = eq_fir_prepare,
.reset = eq_fir_reset,
};
Expand Down
40 changes: 20 additions & 20 deletions src/audio/eq_fir/eq_fir.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
#include <user/fir.h>
#include <stdint.h>

/** \brief Macros to convert without division bytes count to samples count */
#define EQ_FIR_BYTES_TO_S16_SAMPLES(b) ((b) >> 1)
#define EQ_FIR_BYTES_TO_S32_SAMPLES(b) ((b) >> 2)

/* fir component private data */
/**
* \brief FIR component private data.
*
* FIR implementations receive already acquired circular source and sink views.
*/
struct comp_data {
struct fir_state_32x16 fir[PLATFORM_MAX_CHANNELS]; /**< filters state */
struct comp_data_blob_handler *model_handler;
Expand All @@ -39,34 +39,34 @@ struct comp_data {
size_t config_size; /**< configuration size */
size_t fir_delay_size; /**< allocated size */
void (*eq_fir_func)(struct fir_state_32x16 fir[],
struct input_stream_buffer *bsource,
struct output_stream_buffer *bsink,
int frames);
struct cir_buf_source *source,
struct cir_buf_sink *sink,
int frames, int channels);
int nch;
};

#if CONFIG_FORMAT_S16LE
void eq_fir_s16(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource,
struct output_stream_buffer *bsink, int frames);
void eq_fir_s16(struct fir_state_32x16 *fir, struct cir_buf_source *source,
struct cir_buf_sink *sink, int frames, int channels);

void eq_fir_2x_s16(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource,
struct output_stream_buffer *bsink, int frames);
void eq_fir_2x_s16(struct fir_state_32x16 *fir, struct cir_buf_source *source,
struct cir_buf_sink *sink, int frames, int channels);
#endif /* CONFIG_FORMAT_S16LE */

#if CONFIG_FORMAT_S24LE
void eq_fir_s24(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource,
struct output_stream_buffer *bsink, int frames);
void eq_fir_s24(struct fir_state_32x16 *fir, struct cir_buf_source *source,
struct cir_buf_sink *sink, int frames, int channels);

void eq_fir_2x_s24(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource,
struct output_stream_buffer *bsink, int frames);
void eq_fir_2x_s24(struct fir_state_32x16 *fir, struct cir_buf_source *source,
struct cir_buf_sink *sink, int frames, int channels);
#endif /* CONFIG_FORMAT_S24LE */

#if CONFIG_FORMAT_S32LE
void eq_fir_s32(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource,
struct output_stream_buffer *bsink, int frames);
void eq_fir_s32(struct fir_state_32x16 *fir, struct cir_buf_source *source,
struct cir_buf_sink *sink, int frames, int channels);

void eq_fir_2x_s32(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource,
struct output_stream_buffer *bsink, int frames);
void eq_fir_2x_s32(struct fir_state_32x16 *fir, struct cir_buf_source *source,
struct cir_buf_sink *sink, int frames, int channels);
#endif /* CONFIG_FORMAT_S32LE */

int set_fir_func(struct processing_module *mod, enum sof_ipc_frame fmt);
Expand Down
Loading
Loading