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 */
7374static 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+
204216static 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,
251261static 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};
0 commit comments