Skip to content

Commit e9ad2b0

Browse files
singalsulgirdwood
authored andcommitted
Audio: Selector: Add S24_LE processing function
This patch separates processing functions sel_s32le() and sel_s24le(). The common S32_LE and S24_LE format processing is wrong because of different saturation need for the samples. The 32-bit saturation would cause samples with overflow in S24_LE format. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent e648b12 commit e9ad2b0

1 file changed

Lines changed: 76 additions & 3 deletions

File tree

src/audio/selector/selector_generic.c

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,80 @@ static void sel_s16le(struct processing_module *mod, struct input_stream_buffer
241241
}
242242
#endif /* CONFIG_FORMAT_S16LE */
243243

244-
#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE
244+
#if CONFIG_FORMAT_S24LE
245+
/**
246+
* \brief Mixing routine for 24-bit, m channel input x n channel output single frame.
247+
* \param[out] dst Sink buffer.
248+
* \param[in] dst_channels Number of sink channels.
249+
* \param[in] src Source data.
250+
* \param[in] src_channels Number of source channels.
251+
* \param[in] coeffs_config IPC4 micsel config with Q10 coefficients.
252+
*/
253+
static void process_frame_s24le(int32_t dst[], int dst_channels,
254+
int32_t src[], int src_channels,
255+
struct ipc4_selector_coeffs_config *coeffs_config)
256+
{
257+
int64_t accum;
258+
int i, j;
259+
260+
for (i = 0; i < dst_channels; i++) {
261+
accum = 0;
262+
for (j = 0; j < src_channels; j++)
263+
accum += (int64_t)src[j] * (int64_t)coeffs_config->coeffs[i][j];
264+
265+
/* accum is Q1.23 * Q6.10 --> Q7.33, shift right by 10 and
266+
* saturate to get Q1.23.
267+
*/
268+
dst[i] = sat_int24((accum + (1 << 9)) >> 10);
269+
}
270+
}
271+
272+
/**
273+
* \brief Channel selection for 24-bit, m channel input x n channel output data format.
274+
* \param[in] mod Selector base module device.
275+
* \param[in,out] bsource Source buffer.
276+
* \param[in,out] bsink Sink buffer.
277+
* \param[in] frames Number of frames to process.
278+
*/
279+
static void sel_s24le(struct processing_module *mod, struct input_stream_buffer *bsource,
280+
struct output_stream_buffer *bsink, uint32_t frames)
281+
{
282+
struct comp_data *cd = module_get_private_data(mod);
283+
struct audio_stream *source = bsource->data;
284+
struct audio_stream *sink = bsink->data;
285+
int32_t *src = audio_stream_get_rptr(source);
286+
int32_t *dest = audio_stream_get_wptr(sink);
287+
int nmax;
288+
int i;
289+
int n;
290+
int processed = 0;
291+
int source_frame_bytes = audio_stream_frame_bytes(source);
292+
int sink_frame_bytes = audio_stream_frame_bytes(sink);
293+
int n_chan_source = MIN(SEL_SOURCE_CHANNELS_MAX, audio_stream_get_channels(source));
294+
int n_chan_sink = MIN(SEL_SINK_CHANNELS_MAX, audio_stream_get_channels(sink));
295+
296+
while (processed < frames) {
297+
n = frames - processed;
298+
nmax = audio_stream_bytes_without_wrap(source, src) / source_frame_bytes;
299+
n = MIN(n, nmax);
300+
nmax = audio_stream_bytes_without_wrap(sink, dest) / sink_frame_bytes;
301+
n = MIN(n, nmax);
302+
for (i = 0; i < n; i++) {
303+
process_frame_s24le(dest, n_chan_sink, src, n_chan_source,
304+
&cd->coeffs_config);
305+
src += audio_stream_get_channels(source);
306+
dest += audio_stream_get_channels(sink);
307+
}
308+
src = audio_stream_wrap(source, src);
309+
dest = audio_stream_wrap(sink, dest);
310+
processed += n;
311+
}
312+
313+
module_update_buffer_position(bsource, bsink, frames);
314+
}
315+
#endif /* CONFIG_FORMAT_S24LE */
316+
317+
#if CONFIG_FORMAT_S32LE
245318
/**
246319
* \brief Mixing routine for 32-bit, m channel input x n channel output single frame.
247320
* \param[out] dst Sink buffer.
@@ -310,7 +383,7 @@ static void sel_s32le(struct processing_module *mod, struct input_stream_buffer
310383

311384
module_update_buffer_position(bsource, bsink, frames);
312385
}
313-
#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */
386+
#endif /* CONFIG_FORMAT_S32LE */
314387
#endif
315388

316389
const struct comp_func_map func_table[] = {
@@ -335,7 +408,7 @@ const struct comp_func_map func_table[] = {
335408
{SOF_IPC_FRAME_S16_LE, 0, sel_s16le},
336409
#endif
337410
#if CONFIG_FORMAT_S24LE
338-
{SOF_IPC_FRAME_S24_4LE, 0, sel_s32le},
411+
{SOF_IPC_FRAME_S24_4LE, 0, sel_s24le},
339412
#endif
340413
#if CONFIG_FORMAT_S32LE
341414
{SOF_IPC_FRAME_S32_LE, 0, sel_s32le},

0 commit comments

Comments
 (0)