Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause

if(CONFIG_IPC_MAJOR_3)
set(mixer_src mixer.c)
set(mixer_src mixer/mixer.c mixer/mixer_generic.c mixer/mixer_hifi3.c)
elseif(CONFIG_IPC_MAJOR_4)
set(mixer_src mixin_mixout.c)
endif()
Expand Down
2 changes: 2 additions & 0 deletions src/audio/mixer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_local_sources(sof mixer.c mixer_generic.c mixer_hifi3.c)

165 changes: 1 addition & 164 deletions src/audio/mixer.c → src/audio/mixer/mixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,146 +49,6 @@ struct mixer_data {
uint32_t frames);
};

#if CONFIG_FORMAT_S16LE
/* Mix n 16 bit PCM source streams to one sink stream */
static void mix_n_s16(struct comp_dev *dev, struct audio_stream __sparse_cache *sink,
const struct audio_stream __sparse_cache **sources, uint32_t num_sources,
uint32_t frames)
{
int16_t *src[PLATFORM_MAX_CHANNELS];
int16_t *dest;
int32_t val;
int nmax;
int i, j, n, ns;
int processed = 0;
int nch = sink->channels;
int samples = frames * nch;

dest = sink->w_ptr;
for (j = 0; j < num_sources; j++)
src[j] = sources[j]->r_ptr;

while (processed < samples) {
nmax = samples - processed;
n = audio_stream_bytes_without_wrap(sink, dest) >> 1; /* divide 2 */
n = MIN(n, nmax);
for (i = 0; i < num_sources; i++) {
ns = audio_stream_bytes_without_wrap(sources[i], src[i]) >> 1;
n = MIN(n, ns);
}
for (i = 0; i < n; i++) {
val = 0;
for (j = 0; j < num_sources; j++) {
val += *src[j];
src[j]++;
}

/* Saturate to 16 bits */
*dest = sat_int16(val);
dest++;
}
processed += n;
dest = audio_stream_wrap(sink, dest);
for (i = 0; i < num_sources; i++)
src[i] = audio_stream_wrap(sources[i], src[i]);
}
}
#endif /* CONFIG_FORMAT_S16LE */

#if CONFIG_FORMAT_S24LE
/* Mix n 24 bit PCM source streams to one sink stream */
static void mix_n_s24(struct comp_dev *dev, struct audio_stream __sparse_cache *sink,
const struct audio_stream __sparse_cache **sources, uint32_t num_sources,
uint32_t frames)
{
int32_t *src[PLATFORM_MAX_CHANNELS];
int32_t *dest;
int32_t val;
int32_t x;
int nmax;
int i, j, n, ns;
int processed = 0;
int nch = sink->channels;
int samples = frames * nch;

dest = sink->w_ptr;
for (j = 0; j < num_sources; j++)
src[j] = sources[j]->r_ptr;

while (processed < samples) {
nmax = samples - processed;
n = audio_stream_bytes_without_wrap(sink, dest) >> 2; /* divide 4 */
n = MIN(n, nmax);
for (i = 0; i < num_sources; i++) {
ns = audio_stream_bytes_without_wrap(sources[i], src[i]) >> 2;
n = MIN(n, ns);
}
for (i = 0; i < n; i++) {
val = 0;
for (j = 0; j < num_sources; j++) {
x = *src[j] << 8;
val += x >> 8; /* Sign extend */
src[j]++;
}

/* Saturate to 24 bits */
*dest = sat_int24(val);
dest++;
}
processed += n;
dest = audio_stream_wrap(sink, dest);
for (i = 0; i < num_sources; i++)
src[i] = audio_stream_wrap(sources[i], src[i]);
}
}
#endif /* CONFIG_FORMAT_S24LE */

#if CONFIG_FORMAT_S32LE
/* Mix n 32 bit PCM source streams to one sink stream */
static void mix_n_s32(struct comp_dev *dev, struct audio_stream __sparse_cache *sink,
const struct audio_stream __sparse_cache **sources, uint32_t num_sources,
uint32_t frames)
{
int32_t *src[PLATFORM_MAX_CHANNELS];
int32_t *dest;
int64_t val;
int nmax;
int i, j, n, ns;
int processed = 0;
int nch = sink->channels;
int samples = frames * nch;

dest = sink->w_ptr;
for (j = 0; j < num_sources; j++)
src[j] = sources[j]->r_ptr;

while (processed < samples) {
nmax = samples - processed;
n = audio_stream_bytes_without_wrap(sink, dest) >> 2; /* divide 4 */
n = MIN(n, nmax);
for (i = 0; i < num_sources; i++) {
ns = audio_stream_bytes_without_wrap(sources[i], src[i]) >> 2;
n = MIN(n, ns);
}
for (i = 0; i < n; i++) {
val = 0;
for (j = 0; j < num_sources; j++) {
val += *src[j];
src[j]++;
}

/* Saturate to 32 bits */
*dest = sat_int32(val);
dest++;
}
processed += n;
dest = audio_stream_wrap(sink, dest);
for (i = 0; i < num_sources; i++)
src[i] = audio_stream_wrap(sources[i], src[i]);
}
}
#endif /* CONFIG_FORMAT_S32LE */

static struct comp_dev *mixer_new(const struct comp_driver *drv,
struct comp_ipc_config *config,
void *spec)
Expand Down Expand Up @@ -455,7 +315,6 @@ static int mixer_prepare_common(struct comp_dev *dev)
struct mixer_data *md = comp_get_drvdata(dev);
struct comp_buffer *sink;
struct comp_buffer __sparse_cache *sink_c;
enum sof_ipc_frame fmt;
int ret;

comp_dbg(dev, "mixer_prepare()");
Expand All @@ -467,31 +326,9 @@ static int mixer_prepare_common(struct comp_dev *dev)
sink = list_first_item(&dev->bsink_list, struct comp_buffer,
source_list);
sink_c = buffer_acquire(sink);
fmt = sink_c->stream.frame_fmt;
md->mix_func = mixer_get_processing_function(dev, sink_c);
buffer_release(sink_c);

/* currently inactive so setup mixer */
switch (fmt) {
#if CONFIG_FORMAT_S16LE
case SOF_IPC_FRAME_S16_LE:
md->mix_func = mix_n_s16;
break;
#endif /* CONFIG_FORMAT_S16LE */
#if CONFIG_FORMAT_S24LE
case SOF_IPC_FRAME_S24_4LE:
md->mix_func = mix_n_s24;
break;
#endif /* CONFIG_FORMAT_S24LE */
#if CONFIG_FORMAT_S32LE
case SOF_IPC_FRAME_S32_LE:
md->mix_func = mix_n_s32;
break;
#endif /* CONFIG_FORMAT_S32LE */
default:
comp_err(dev, "unsupported data format");
return -EINVAL;
}

ret = comp_set_state(dev, COMP_TRIGGER_PREPARE);
if (ret < 0)
return ret;
Expand Down
166 changes: 166 additions & 0 deletions src/audio/mixer/mixer_generic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2022 Intel Corporation. All rights reserved.
//
// Author: Andrula Song <xiaoyuan.song@intel.com>

#include <sof/audio/mixer.h>
#include <sof/common.h>

#ifdef MIXER_GENERIC

#if CONFIG_FORMAT_S16LE
/* Mix n 16 bit PCM source streams to one sink stream */
static void mix_n_s16(struct comp_dev *dev, struct audio_stream __sparse_cache *sink,
const struct audio_stream __sparse_cache **sources, uint32_t num_sources,
uint32_t frames)
{
int16_t *src[PLATFORM_MAX_CHANNELS];
int16_t *dest;
int32_t val;
int nmax;
int i, j, n, ns;
int processed = 0;
int nch = sink->channels;
int samples = frames * nch;

dest = sink->w_ptr;
for (j = 0; j < num_sources; j++)
src[j] = sources[j]->r_ptr;

while (processed < samples) {
nmax = samples - processed;
n = audio_stream_samples_without_wrap_s16(sink, dest);
n = MIN(n, nmax);
for (i = 0; i < num_sources; i++) {
ns = audio_stream_samples_without_wrap_s16(sources[i], src[i]);
n = MIN(n, ns);
}
for (i = 0; i < n; i++) {
val = 0;
for (j = 0; j < num_sources; j++) {
val += *src[j];
src[j]++;
}

/* Saturate to 16 bits */
*dest = sat_int16(val);
dest++;
}
processed += n;
dest = audio_stream_wrap(sink, dest);
for (i = 0; i < num_sources; i++)
src[i] = audio_stream_wrap(sources[i], src[i]);
}
}
#endif /* CONFIG_FORMAT_S16LE */

#if CONFIG_FORMAT_S24LE
/* Mix n 24 bit PCM source streams to one sink stream */
static void mix_n_s24(struct comp_dev *dev, struct audio_stream __sparse_cache *sink,
const struct audio_stream __sparse_cache **sources, uint32_t num_sources,
uint32_t frames)
{
int32_t *src[PLATFORM_MAX_CHANNELS];
int32_t *dest;
int32_t val;
int32_t x;
int nmax;
int i, j, n, ns;
int processed = 0;
int nch = sink->channels;
int samples = frames * nch;

dest = sink->w_ptr;
for (j = 0; j < num_sources; j++)
src[j] = sources[j]->r_ptr;

while (processed < samples) {
nmax = samples - processed;
n = audio_stream_samples_without_wrap_s24(sink, dest);
n = MIN(n, nmax);
for (i = 0; i < num_sources; i++) {
ns = audio_stream_samples_without_wrap_s24(sources[i], src[i]);
n = MIN(n, ns);
}
for (i = 0; i < n; i++) {
val = 0;
for (j = 0; j < num_sources; j++) {
x = *src[j] << 8;
val += x >> 8; /* Sign extend */
src[j]++;
}

/* Saturate to 24 bits */
*dest = sat_int24(val);
dest++;
}
processed += n;
dest = audio_stream_wrap(sink, dest);
for (i = 0; i < num_sources; i++)
src[i] = audio_stream_wrap(sources[i], src[i]);
}
}
#endif /* CONFIG_FORMAT_S24LE */

#if CONFIG_FORMAT_S32LE
/* Mix n 32 bit PCM source streams to one sink stream */
static void mix_n_s32(struct comp_dev *dev, struct audio_stream __sparse_cache *sink,
const struct audio_stream __sparse_cache **sources, uint32_t num_sources,
uint32_t frames)
{
int32_t *src[PLATFORM_MAX_CHANNELS];
int32_t *dest;
int64_t val;
int nmax;
int i, j, n, ns;
int processed = 0;
int nch = sink->channels;
int samples = frames * nch;

dest = sink->w_ptr;
for (j = 0; j < num_sources; j++)
src[j] = sources[j]->r_ptr;

while (processed < samples) {
nmax = samples - processed;
n = audio_stream_samples_without_wrap_s32(sink, dest);
n = MIN(n, nmax);
for (i = 0; i < num_sources; i++) {
ns = audio_stream_samples_without_wrap_s32(sources[i], src[i]);
n = MIN(n, ns);
}
for (i = 0; i < n; i++) {
val = 0;
for (j = 0; j < num_sources; j++) {
val += *src[j];
src[j]++;
}

/* Saturate to 32 bits */
*dest = sat_int32(val);
dest++;
}
processed += n;
dest = audio_stream_wrap(sink, dest);
for (i = 0; i < num_sources; i++)
src[i] = audio_stream_wrap(sources[i], src[i]);
}
}
#endif /* CONFIG_FORMAT_S32LE */

const struct mixer_func_map mixer_func_map[] = {
#if CONFIG_FORMAT_S16LE
{ SOF_IPC_FRAME_S16_LE, mix_n_s16 },
#endif
#if CONFIG_FORMAT_S24LE
{ SOF_IPC_FRAME_S24_4LE, mix_n_s24 },
#endif
#if CONFIG_FORMAT_S32LE
{ SOF_IPC_FRAME_S32_LE, mix_n_s32 },
#endif
};

const size_t mixer_func_count = ARRAY_SIZE(mixer_func_map);

#endif
Loading