Skip to content

Commit e1e5a4b

Browse files
committed
module: mixer: rework module to use sink/source api
Rework the mixer module to only use the sink/source api to prepare sof for the full transition to pipeline 2.0. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
1 parent b6c6a05 commit e1e5a4b

5 files changed

Lines changed: 206 additions & 180 deletions

File tree

‎src/audio/mixer/mixer.c‎

Lines changed: 83 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <sof/audio/component.h>
1010
#include <sof/audio/format.h>
1111
#include <sof/audio/module_adapter/module/generic.h>
12+
#include <sof/audio/sink_source_utils.h>
1213
#include <sof/audio/pipeline.h>
1314
#include <sof/audio/ipc-config.h>
1415
#include <sof/common.h>
@@ -71,39 +72,36 @@ static int mixer_free(struct processing_module *mod)
7172
* Mix N source PCM streams to one sink PCM stream. Frames copied is constant.
7273
*/
7374
static int mixer_process(struct processing_module *mod,
74-
struct input_stream_buffer *input_buffers, int num_input_buffers,
75-
struct output_stream_buffer *output_buffers, int num_output_buffers)
75+
struct sof_source **sources, int num_of_sources,
76+
struct sof_sink **sinks, int num_of_sinks)
7677
{
7778
struct mixer_data *md = module_get_private_data(mod);
7879
struct comp_dev *dev = mod->dev;
79-
const struct audio_stream *sources_stream[PLATFORM_MAX_STREAMS];
80-
int sources_indices[PLATFORM_MAX_STREAMS];
81-
int32_t i = 0, j = 0;
82-
uint32_t frames = INT32_MAX;
83-
/* Redundant, but helps the compiler */
84-
uint32_t source_bytes = 0;
85-
uint32_t sink_bytes;
80+
struct sof_source *active_sources[PLATFORM_MAX_STREAMS];
81+
struct cir_buf_source source_bufs[PLATFORM_MAX_STREAMS];
82+
struct cir_buf_sink sink_buf;
83+
size_t bytes, samples, source_bytes, sink_bytes;
84+
size_t frames = SIZE_MAX;
8685
int active_input_buffers = 0;
86+
int i, j, ret;
8787

88-
comp_dbg(dev, "%d", num_input_buffers);
88+
comp_dbg(dev, "%d", num_of_sources);
8989

9090
/* too many sources ? */
91-
if (num_input_buffers >= PLATFORM_MAX_STREAMS)
91+
if (num_of_sources >= PLATFORM_MAX_STREAMS)
9292
return -EINVAL;
9393

94-
/* check for underruns */
95-
for (i = 0; i < num_input_buffers; i++) {
96-
uint32_t avail_frames;
97-
98-
avail_frames = audio_stream_avail_frames_aligned(mod->input_buffers[i].data,
99-
mod->output_buffers[0].data);
94+
/* find active sources and compute frame count */
95+
for (i = 0; i < num_of_sources; i++) {
96+
size_t avail_frames = source_sink_avail_frames_aligned(sources[i], sinks[0]);
10097

10198
/* if one source is inactive, skip it */
10299
if (avail_frames == 0)
103100
continue;
104101

105-
active_input_buffers++;
106102
frames = MIN(frames, avail_frames);
103+
active_sources[active_input_buffers] = sources[i];
104+
active_input_buffers++;
107105
}
108106

109107
if (!active_input_buffers) {
@@ -113,43 +111,43 @@ static int mixer_process(struct processing_module *mod,
113111
* generating silence until at least one of the
114112
* sources start to have data available (frames!=0).
115113
*/
116-
sink_bytes = dev->frames * audio_stream_frame_bytes(mod->output_buffers[0].data);
117-
if (!audio_stream_set_zero(mod->output_buffers[0].data, sink_bytes))
118-
mod->output_buffers[0].size = sink_bytes;
119-
120-
return 0;
114+
return sink_fill_with_silence(sinks[0],
115+
dev->frames * sink_get_frame_bytes(sinks[0]));
121116
}
122117

123-
/* Every source has the same format, so calculate bytes based on the first one */
124-
source_bytes = frames * audio_stream_frame_bytes(mod->input_buffers[0].data);
118+
comp_dbg(dev, "frames = %zu", frames);
125119

126-
sink_bytes = frames * audio_stream_frame_bytes(mod->output_buffers[0].data);
120+
sink_bytes = frames * sink_get_frame_bytes(sinks[0]);
121+
samples = frames * sink_get_channels(sinks[0]);
127122

128-
comp_dbg(dev, "source_bytes = 0x%x, sink_bytes = 0x%x",
129-
source_bytes, sink_bytes);
130-
131-
/* mix streams */
132-
for (i = 0; i < num_input_buffers; i++) {
133-
uint32_t avail_frames;
134-
135-
avail_frames = audio_stream_avail_frames_aligned(mod->input_buffers[i].data,
136-
mod->output_buffers[0].data);
137-
138-
/* if one source is inactive, skip it */
139-
if (avail_frames == 0)
140-
continue;
123+
/* acquire the sink buffer */
124+
ret = sink_get_buffer(sinks[0], sink_bytes, &sink_buf.ptr, &sink_buf.buf_start, &bytes);
125+
if (ret < 0)
126+
return ret;
127+
sink_buf.buf_end = (char *)sink_buf.buf_start + bytes;
141128

142-
sources_indices[j] = i;
143-
sources_stream[j++] = mod->input_buffers[i].data;
129+
/* Every source has the same format, so calculate bytes based on the first one */
130+
source_bytes = frames * source_get_frame_bytes(active_sources[0]);
131+
132+
/* acquire all active source buffers */
133+
for (i = 0; i < active_input_buffers; i++) {
134+
ret = source_get_data(active_sources[i], source_bytes, &source_bufs[i].ptr,
135+
&source_bufs[i].buf_start, &bytes);
136+
if (ret < 0) {
137+
for (j = 0; j < i; j++)
138+
source_release_data(active_sources[j], 0);
139+
sink_commit_buffer(sinks[0], 0);
140+
return ret;
141+
}
142+
source_bufs[i].buf_end = (const char *)source_bufs[i].buf_start + bytes;
144143
}
145144

146-
if (j)
147-
md->mix_func(dev, mod->output_buffers[0].data, sources_stream, j, frames);
148-
mod->output_buffers[0].size = sink_bytes;
145+
md->mix_func(&sink_buf, source_bufs, active_input_buffers, samples);
149146

150-
/* update source buffer consumed bytes */
151-
for (i = 0; i < j; i++)
152-
mod->input_buffers[sources_indices[i]].consumed = source_bytes;
147+
/* commit the consumed and produced data */
148+
for (i = 0; i < active_input_buffers; i++)
149+
source_release_data(active_sources[i], source_bytes);
150+
sink_commit_buffer(sinks[0], sink_bytes);
153151

154152
return 0;
155153
}
@@ -163,13 +161,13 @@ static int mixer_reset(struct processing_module *mod)
163161
comp_dbg(dev, "entry");
164162

165163
if (dir == SOF_IPC_STREAM_PLAYBACK) {
166-
struct comp_buffer *source;
164+
int i;
167165

168-
comp_dev_for_each_producer(dev, source) {
166+
for (i = 0; i < mod->num_of_sources; i++) {
169167
/* FIXME: this is racy and implicitly protected by serialised IPCs */
170168
bool stop = false;
171169

172-
if (comp_buffer_get_source_state(source) > COMP_STATE_READY)
170+
if (source_get_comp_state(mod->sources[i]) > COMP_STATE_READY)
173171
stop = true;
174172

175173
/* only mix the sources with the same state with mixer */
@@ -185,46 +183,60 @@ static int mixer_reset(struct processing_module *mod)
185183
}
186184

187185
/* init and calculate the aligned setting for available frames and free frames retrieve*/
188-
static inline void mixer_set_frame_alignment(struct audio_stream *source)
186+
#if XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4
187+
static inline uint32_t mixer_get_byte_align(uint32_t channels)
189188
{
190-
191189
/* Xtensa intrinsics ask for 8-byte aligned. 5.1 format SSE audio
192-
* requires 16-byte aligned. Note: The SOF_FRAME_BYTE_ALIGN is the
193-
* same value 16 with HiFi5.
190+
* requires 16-byte aligned.
194191
*/
195-
const uint32_t byte_align = audio_stream_get_channels(source) == 6 ?
196-
MIXER_HIFI_FRAME_BYTE_ALIGN_6CH : SOF_FRAME_BYTE_ALIGN;
192+
return channels == 6 ? 16 : 8;
193+
}
197194

198-
/* There is no limit for frame number, so set it as default (1). */
199-
const uint32_t frame_align_req = SOF_FRAME_COUNT_ALIGN;
195+
static void mixer_set_source_frame_alignment(struct sof_source *src)
196+
{
197+
const uint32_t byte_align = mixer_get_byte_align(source_get_channels(src));
198+
199+
/* There is no limit for frame number, so set it as 1 */
200+
const uint32_t frame_align_req = 1;
200201

201-
audio_stream_set_align(byte_align, frame_align_req, source);
202+
source_set_alignment_constants(src, byte_align, frame_align_req);
202203
}
203204

205+
static void mixer_set_sink_frame_alignment(struct sof_sink *snk)
206+
{
207+
const uint32_t byte_align = mixer_get_byte_align(sink_get_channels(snk));
208+
209+
/* There is no limit for frame number, so set it as 1 */
210+
const uint32_t frame_align_req = 1;
211+
212+
sink_set_alignment_constants(snk, byte_align, frame_align_req);
213+
}
214+
#endif
215+
204216
static int mixer_prepare(struct processing_module *mod,
205217
struct sof_source **sources, int num_of_sources,
206218
struct sof_sink **sinks, int num_of_sinks)
207219
{
208220
struct mixer_data *md = module_get_private_data(mod);
209221
struct comp_dev *dev = mod->dev;
210-
struct comp_buffer *sink;
222+
int i;
211223

212-
sink = comp_dev_get_first_data_consumer(dev);
213-
if (!sink) {
224+
if (!num_of_sinks) {
214225
comp_err(dev, "no sink");
215226
return -ENOTCONN;
216227
}
217228

218-
md->mix_func = mixer_get_processing_function(dev, sink);
229+
#if XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4
230+
mixer_set_sink_frame_alignment(sinks[0]);
231+
for (i = 0; i < num_of_sources; i++)
232+
mixer_set_source_frame_alignment(sources[i]);
233+
#endif
219234

220-
/* No need to set sink align constraints, set constraints for each
221-
* source next. The sink align will follow to common source alignment.
222-
*/
235+
md->mix_func = mixer_get_processing_function(dev, sink_get_frm_fmt(sinks[0]));
223236

224237
/* check each mixer source state */
225-
struct comp_buffer *source;
226-
227-
comp_dev_for_each_producer(dev, source) {
238+
for (i = 0; i < num_of_sources; i++) {
239+
int state = source_get_comp_state(sources[i]);
228240
bool stop;
229241

230242
/*
@@ -235,9 +247,7 @@ static int mixer_prepare(struct processing_module *mod,
235247
* preparing the mixer, so they shouldn't touch it until we're
236248
* done.
237249
*/
238-
mixer_set_frame_alignment(&source->stream);
239-
stop = comp_buffer_get_source_state(source) == COMP_STATE_PAUSED ||
240-
comp_buffer_get_source_state(source) == COMP_STATE_ACTIVE;
250+
stop = state == COMP_STATE_PAUSED || state == COMP_STATE_ACTIVE;
241251

242252
/* only prepare downstream if we have no active sources */
243253
if (stop)
@@ -251,7 +261,7 @@ static int mixer_prepare(struct processing_module *mod,
251261
static const struct module_interface mixer_interface = {
252262
.init = mixer_init,
253263
.prepare = mixer_prepare,
254-
.process_audio_stream = mixer_process,
264+
.process = mixer_process,
255265
.reset = mixer_reset,
256266
.free = mixer_free,
257267
};

‎src/audio/mixer/mixer.h‎

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,26 @@ void sys_comp_module_mixer_interface_init(void);
3232

3333
#define MIXER_MAX_SOURCES 2
3434

35-
/* Xtensa HiFi optimized version needs this for 5.1ch */
36-
#define MIXER_HIFI_FRAME_BYTE_ALIGN_6CH 16
35+
/**
36+
* \brief mixer processing function interface
37+
*
38+
* The buffers are acquired and committed by the module's process callback. Each
39+
* processing function receives ready-to-use circular buffer descriptors and only
40+
* performs the mixing.
41+
*
42+
* \param[in,out] sink Sink circular buffer descriptor to write mixed data to.
43+
* \param[in] sources Array of source circular buffer descriptors to mix.
44+
* \param[in] num_sources Number of valid entries in \p sources.
45+
* \param[in] samples Total number of samples (frames * channels) to mix.
46+
*/
47+
typedef void (*mixer_func)(struct cir_buf_sink *sink, struct cir_buf_source *sources,
48+
int num_sources, size_t samples);
3749

3850
/* mixer component private data */
3951
struct mixer_data {
40-
void (*mix_func)(struct comp_dev *dev, struct audio_stream *sink,
41-
const struct audio_stream **sources, uint32_t count,
42-
uint32_t frames);
52+
mixer_func mix_func;
4353
};
4454

45-
/**
46-
* \brief mixer processing function interface
47-
*/
48-
typedef void (*mixer_func)(struct comp_dev *dev, struct audio_stream *sink,
49-
const struct audio_stream **sources, uint32_t num_sources,
50-
uint32_t frames);
51-
5255
/** \brief Volume processing functions map. */
5356
struct mixer_func_map {
5457
enum sof_ipc_frame frame_fmt; /**< frame format */
@@ -64,16 +67,16 @@ extern const size_t mixer_func_count;
6467
/**
6568
* \brief Retrievies mixer processing function.
6669
* \param[in,out] dev Mixer base component device.
67-
* \param[in] sinkb Sink buffer to match against
70+
* \param[in] fmt Frame format to match against.
6871
*/
6972
static inline mixer_func mixer_get_processing_function(struct comp_dev *dev,
70-
struct comp_buffer *sinkb)
73+
enum sof_ipc_frame fmt)
7174
{
7275
int i;
7376

7477
/* map the volume function for source and sink buffers */
7578
for (i = 0; i < mixer_func_count; i++) {
76-
if (audio_stream_get_frm_fmt(&sinkb->stream) != mixer_func_map[i].frame_fmt)
79+
if (fmt != mixer_func_map[i].frame_fmt)
7780
continue;
7881

7982
return mixer_func_map[i].func;

0 commit comments

Comments
 (0)