diff --git a/src/audio/mux/mux.c b/src/audio/mux/mux.c index b6d34120a260..0faa0e371c2b 100644 --- a/src/audio/mux/mux.c +++ b/src/audio/mux/mux.c @@ -49,6 +49,9 @@ static int mux_set_values(struct comp_dev *dev, struct comp_data *cd, { uint8_t i; uint8_t j; + bool channel_set; + + comp_info(dev, "mux_set_values()"); /* check if number of streams configured doesn't exceed maximum */ if (cfg->num_streams > MUX_MAX_STREAMS) { @@ -69,12 +72,44 @@ static int mux_set_values(struct comp_dev *dev, struct comp_data *cd, } } + for (i = 0; i < cfg->num_streams; i++) { + for (j = 0 ; j < PLATFORM_MAX_CHANNELS; j++) { + if (popcount(cfg->streams[i].mask[j]) > 1) { + comp_cl_err(&comp_mux, "mux_set_values(): mux component is not able to mix channels"); + return -EINVAL; + } + } + } + + if (dev->comp.type == SOF_COMP_MUX) { + for (j = 0 ; j < PLATFORM_MAX_CHANNELS; j++) { + channel_set = false; + for (i = 0 ; i < cfg->num_streams; i++) { + if (popcount(cfg->streams[i].mask[j])) { + if (!channel_set) { + channel_set = true; + } else { + comp_cl_err(&comp_mux, "mux_set_values(): mux component is not able to mix channels"); + return -EINVAL; + } + } + } + } + } + for (i = 0; i < cfg->num_streams; i++) { cd->config.streams[i].pipeline_id = cfg->streams[i].pipeline_id; for (j = 0; j < PLATFORM_MAX_CHANNELS; j++) cd->config.streams[i].mask[j] = cfg->streams[i].mask[j]; } + cd->config.num_streams = cfg->num_streams; + + if (dev->comp.type == SOF_COMP_MUX) + mux_prepare_look_up_table(dev); + else + demux_prepare_look_up_table(dev); + if (dev->state > COMP_STATE_INIT) { if (dev->comp.type == SOF_COMP_MUX) cd->mux = mux_get_processing_function(dev); @@ -157,6 +192,21 @@ static uint8_t get_stream_index(struct comp_data *cd, uint32_t pipe_id) return 0; } +static struct mux_look_up *get_lookup_table(struct comp_data *cd, + uint32_t pipe_id) +{ + int i; + + for (i = 0; i < MUX_MAX_STREAMS; i++) + if (cd->config.streams[i].pipeline_id == pipe_id) + return &cd->lookup[i]; + + comp_cl_err(&comp_mux, "get_lookup_table(): couldn't find configuration for connected pipeline %u", + pipe_id); + + return 0; +} + static int mux_verify_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { @@ -269,6 +319,32 @@ static int mux_cmd(struct comp_dev *dev, int cmd, void *data, } } +static void prepare_active_look_up(struct comp_dev *dev, + struct audio_stream *sink, + const struct audio_stream **sources) +{ + struct comp_data *cd = comp_get_drvdata(dev); + const struct audio_stream *source; + uint8_t active_elem; + uint8_t elem; + + cd->active_lookup.num_elems = 0; + + active_elem = 0; + + /* init pointers */ + for (elem = 0; elem < cd->lookup[0].num_elems; elem++) { + source = sources[cd->lookup[0].copy_elem[elem].stream_id]; + if (!source) + continue; + + cd->active_lookup.copy_elem[active_elem] = + cd->lookup[0].copy_elem[elem]; + active_elem++; + cd->active_lookup.num_elems = active_elem; + } +} + /* process and copy stream data from source to sink buffers */ static int demux_copy(struct comp_dev *dev) { @@ -276,6 +352,8 @@ static int demux_copy(struct comp_dev *dev) struct comp_buffer *source; struct comp_buffer *sink; struct comp_buffer *sinks[MUX_MAX_STREAMS] = { NULL }; + struct mux_look_up *look_ups[MUX_MAX_STREAMS] = { NULL }; + struct mux_look_up *look_up; struct list_item *clist; uint32_t num_sinks = 0; uint32_t i = 0; @@ -300,7 +378,9 @@ static int demux_copy(struct comp_dev *dev) if (sink->sink->state == dev->state) { num_sinks++; i = get_stream_index(cd, sink->pipeline_id); + look_up = get_lookup_table(cd, sink->pipeline_id); sinks[i] = sink; + look_ups[i] = look_up; } buffer_unlock(sink, flags); } @@ -346,8 +426,8 @@ static int demux_copy(struct comp_dev *dev) continue; buffer_invalidate(source, source_bytes); - cd->demux(&sinks[i]->stream, &source->stream, frames, - &cd->config.streams[i]); + cd->demux(dev, &sinks[i]->stream, &source->stream, frames, + look_ups[i]); buffer_writeback(sinks[i], sinks_bytes[i]); } @@ -441,9 +521,11 @@ static int mux_copy(struct comp_dev *dev) } sink_bytes = frames * audio_stream_frame_bytes(&sink->stream); + prepare_active_look_up(dev, &sink->stream, &sources_stream[0]); + /* produce output */ - cd->mux(&sink->stream, &sources_stream[0], frames, - &cd->config.streams[0]); + cd->mux(dev, &sink->stream, &sources_stream[0], frames, + &cd->active_lookup); buffer_writeback(sink, sink_bytes); /* update components */ diff --git a/src/audio/mux/mux_generic.c b/src/audio/mux/mux_generic.c index 3941a04bd35b..e9c0c92651f6 100644 --- a/src/audio/mux/mux_generic.c +++ b/src/audio/mux/mux_generic.c @@ -18,347 +18,524 @@ #include #include -#if CONFIG_FORMAT_S16LE -/* - * \brief Fetch 16b samples from source buffer and perform routing operations - * based on mask provided. - * \param[in,out] source Source buffer. - * \param[in] offset Offset in source buffer. - * \param[in] mask Routing bitmask for calculating output sample. - */ -UT_STATIC inline int32_t calc_sample_s16le(const struct audio_stream *source, - uint32_t offset, uint8_t mask) +static void mux_check_for_wrap(struct audio_stream *sink, + const struct audio_stream **sources, + struct mux_look_up *lookup) { - int32_t sample = 0; - int16_t *src; - int8_t in_ch; + const struct audio_stream *source; + uint32_t elem; + + /* check sources and destinations for wrap */ + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; + lookup->copy_elem[elem].dest = + audio_stream_wrap(sink, lookup->copy_elem[elem].dest); + lookup->copy_elem[elem].src = + audio_stream_wrap(source, lookup->copy_elem[elem].src); + } +} - if (mask == 0) - return 0; +static void demux_check_for_wrap(struct audio_stream *sink, + const struct audio_stream *source, + struct mux_look_up *lookup) +{ + uint32_t elem; + + /* check sources and destinations for wrap */ + for (elem = 0; elem < lookup->num_elems; elem++) { + lookup->copy_elem[elem].dest = + audio_stream_wrap(sink, lookup->copy_elem[elem].dest); + lookup->copy_elem[elem].src = + audio_stream_wrap(source, lookup->copy_elem[elem].src); + } +} - for (in_ch = 0; in_ch < source->channels; in_ch++) { - if (mask & BIT(in_ch)) { - src = audio_stream_read_frag_s16(source, - offset + in_ch); - sample += *src; - } +static uint32_t mux_calc_frames_without_wrap_s32(struct comp_dev *dev, + struct audio_stream *sink, + const struct audio_stream + **sources, + struct mux_look_up *lookup) +{ + const struct audio_stream *source; + uint32_t frames; + uint32_t min_frames; + uint32_t elem; + void *ptr; + + /* dest pointer for all copy_elems in lookup refers to the same + * sink buffer (mux has one sink buffer), so dest min_frames + * calculation based only on lookup table first element is sufficient. + */ + ptr = (int32_t *)lookup->copy_elem[0].dest - + lookup->copy_elem[0].out_ch; + min_frames = audio_stream_frames_without_wrap(sink, ptr); + + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; + + ptr = (int32_t *)lookup->copy_elem[elem].src - + lookup->copy_elem[elem].in_ch; + frames = audio_stream_frames_without_wrap(source, ptr); + + min_frames = (frames < min_frames) ? frames : min_frames; } - return sample; + return min_frames; } -/* \brief Demuxing 16 bit streams. - * - * Source stream is routed to sink with regard to routing bitmasks from - * mux_stream_data structure. Each bitmask describes composition of single - * output channel. - * - * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. - * \param[in] frames Number of frames to process. - * \param[in] data Parameters describing channel count and routing. - */ -static void demux_s16le(struct audio_stream *sink, - const struct audio_stream *source, uint32_t frames, - struct mux_stream_data *data) +static uint32_t mux_calc_frames_without_wrap_s16(struct comp_dev *dev, + struct audio_stream *sink, + const struct audio_stream + **sources, + struct mux_look_up *lookup) { - int32_t sample; - int16_t *dst; - uint32_t dst_idx; - uint8_t i; - uint8_t out_ch; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < sink->channels; out_ch++) { - sample = calc_sample_s16le(source, - i * source->channels, - data->mask[out_ch]); - - /* saturate to 16 bits */ - dst_idx = i * sink->channels + out_ch; - dst = audio_stream_write_frag_s16(sink, dst_idx); - *dst = sat_int16(sample); - } + const struct audio_stream *source; + uint32_t frames; + uint32_t min_frames; + uint32_t elem; + void *ptr; + + /* dest pointer for all copy_elems in lookup refers to the same + * sink buffer (mux has one sink buffer), so dest min_frames + * calculation based only on lookup table first element is sufficient. + */ + ptr = (int16_t *)lookup->copy_elem[0].dest - + lookup->copy_elem[0].out_ch; + min_frames = audio_stream_frames_without_wrap(sink, ptr); + + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; + + ptr = (int16_t *)lookup->copy_elem[elem].src - + lookup->copy_elem[elem].in_ch; + frames = audio_stream_frames_without_wrap(source, ptr); + + min_frames = (frames < min_frames) ? frames : min_frames; } + + return min_frames; } -/* \brief Muxing 16 bit streams. - * - * Source streams are routed to sink with regard to routing bitmasks from - * mux_stream_data structures array. Each source stream has bitmask for each - * of it's channels describing to which channels of output stream it - * contributes. - * - * \param[in,out] sink Destination buffer. - * \param[in,out] sources Array of source buffers. - * \param[in] frames Number of frames to process. - * \param[in] data Array of parameters describing channel count and routing for - * each stream. - */ -static void mux_s16le(struct audio_stream *sink, - const struct audio_stream **sources, uint32_t frames, - struct mux_stream_data *data) +static uint32_t demux_calc_frames_without_wrap_s32(struct comp_dev *dev, + struct audio_stream *sink, + const struct audio_stream + *source, + struct mux_look_up *lookup) +{ + uint32_t frames; + uint32_t min_frames; + void *ptr; + + /* for demux we process each source buffer separately - dest/src for + * each copy_elem refers to the same sink/source buffer, so min_frames + * calculation based only on lookup table first element is sufficient. + */ + ptr = (int32_t *)lookup->copy_elem[0].dest - + lookup->copy_elem[0].out_ch; + min_frames = audio_stream_frames_without_wrap(sink, ptr); + + ptr = (int32_t *)lookup->copy_elem[0].src - + lookup->copy_elem[0].in_ch; + frames = audio_stream_frames_without_wrap(source, ptr); + + min_frames = (frames < min_frames) ? frames : min_frames; + + return min_frames; +} + +static uint32_t demux_calc_frames_without_wrap_s16(struct comp_dev *dev, + struct audio_stream *sink, + const struct audio_stream + *source, + struct mux_look_up *lookup) +{ + uint32_t frames; + uint32_t min_frames; + void *ptr; + + /* for demux we process each source buffer separately - dest/src for + * each copy_elem refers to the same sink/source buffer, so min_frames + * calculation based only on lookup table first element is sufficient. + */ + ptr = (int16_t *)lookup->copy_elem[0].dest - + lookup->copy_elem[0].out_ch; + min_frames = audio_stream_frames_without_wrap(sink, ptr); + + ptr = (int16_t *)lookup->copy_elem[0].src - + lookup->copy_elem[0].in_ch; + frames = audio_stream_frames_without_wrap(source, ptr); + + min_frames = (frames < min_frames) ? frames : min_frames; + + return min_frames; +} + +static void mux_init_look_up_pointers_s32(struct comp_dev *dev, + struct audio_stream *sink, + const struct audio_stream **sources, + struct mux_look_up *lookup) { const struct audio_stream *source; - uint8_t i; - uint8_t j; - uint8_t out_ch; - int16_t *dst; - uint32_t dst_idx; - int32_t sample; + uint32_t elem; - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < sink->channels; out_ch++) { - sample = 0; + /* init pointers */ + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; - for (j = 0; j < MUX_MAX_STREAMS; j++) { - source = sources[j]; - if (!source) - continue; + lookup->copy_elem[elem].src = (int32_t *)source->r_ptr + + lookup->copy_elem[elem].in_ch; + lookup->copy_elem[elem].src_inc = source->channels; - sample += calc_sample_s16le(source, - i * source->channels, - data[j].mask[out_ch]); - } - dst_idx = i * sink->channels + out_ch; - dst = audio_stream_write_frag_s16(sink, dst_idx); - *dst = sat_int16(sample); - } + lookup->copy_elem[elem].dest = (int32_t *)sink->w_ptr + + lookup->copy_elem[elem].out_ch; + lookup->copy_elem[elem].dest_inc = sink->channels; } } -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE -/* - * \brief Fetch 24b samples from source buffer and perform routing operations - * based on mask provided. - * \param[in,out] source Source buffer. - * \param[in] offset Offset in source buffer. - * \param[in] mask Routing bitmask for calculating output sample. - */ -UT_STATIC inline int32_t calc_sample_s24le(const struct audio_stream *source, - uint32_t offset, uint8_t mask) +static void mux_init_look_up_pointers_s16(struct comp_dev *dev, + struct audio_stream *sink, + const struct audio_stream **sources, + struct mux_look_up *lookup) { - int32_t sample = 0; - int32_t *src; - int8_t in_ch; + const struct audio_stream *source; + uint32_t elem; - if (mask == 0) - return 0; + /* init pointers */ + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; - for (in_ch = 0; in_ch < source->channels; in_ch++) { - if (mask & BIT(in_ch)) { - src = audio_stream_read_frag_s32(source, - offset + in_ch); - sample += sign_extend_s24(*src); - } + lookup->copy_elem[elem].src = (int16_t *)source->r_ptr + + lookup->copy_elem[elem].in_ch; + lookup->copy_elem[elem].src_inc = source->channels; + + lookup->copy_elem[elem].dest = (int16_t *)sink->w_ptr + + lookup->copy_elem[elem].out_ch; + lookup->copy_elem[elem].dest_inc = sink->channels; } +} - return sample; +static void demux_init_look_up_pointers_s16(struct comp_dev *dev, + struct audio_stream *sink, + const struct audio_stream *source, + struct mux_look_up *lookup) +{ + uint32_t elem; + + /* init pointers */ + for (elem = 0; elem < lookup->num_elems; elem++) { + lookup->copy_elem[elem].src = (int16_t *)source->r_ptr + + lookup->copy_elem[elem].in_ch; + lookup->copy_elem[elem].src_inc = source->channels; + + lookup->copy_elem[elem].dest = (int16_t *)sink->w_ptr + + lookup->copy_elem[elem].out_ch; + lookup->copy_elem[elem].dest_inc = sink->channels; + } } -/* \brief Demuxing 24 bit streams. - * - * Source stream is routed to sink with regard to routing bitmasks from - * mux_stream_data structure. Each bitmask describes composition of single - * output channel. - * - * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. - * \param[in] frames Number of frames to process. - * \param[in] data Parameters describing channel count and routing. - */ -static void demux_s24le(struct audio_stream *sink, - const struct audio_stream *source, uint32_t frames, - struct mux_stream_data *data) +static void demux_init_look_up_pointers_s32(struct comp_dev *dev, + struct audio_stream *sink, + const struct audio_stream *source, + struct mux_look_up *lookup) { - int32_t sample; - int32_t *dst; - uint32_t dst_idx; - uint8_t i; - uint8_t out_ch; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < sink->channels; out_ch++) { - sample = calc_sample_s24le(source, - i * source->channels, - data->mask[out_ch]); - - /* saturate to 24 bits */ - dst_idx = i * sink->channels + out_ch; - dst = audio_stream_write_frag_s32(sink, dst_idx); - *dst = sat_int24(sample); - } + uint32_t elem; + + /* init pointers */ + for (elem = 0; elem < lookup->num_elems; elem++) { + lookup->copy_elem[elem].src = (int32_t *)source->r_ptr + + lookup->copy_elem[elem].in_ch; + lookup->copy_elem[elem].src_inc = source->channels; + + lookup->copy_elem[elem].dest = (int32_t *)sink->w_ptr + + lookup->copy_elem[elem].out_ch; + lookup->copy_elem[elem].dest_inc = sink->channels; } } -/* \brief Muxing 24 bit streams. - * - * Source streams are routed to sink with regard to routing bitmasks from - * mux_stream_data structures array. Each source stream has bitmask for each - * of it's channels describing to which channels of output stream it - * contributes. +#if CONFIG_FORMAT_S16LE +/** + * Source stream are routed to sinks with regard to look up table based on + * routing bitmasks from mux_stream_data structures array. Each sink channel + * has it's own lookup[].copy_elem describing source and sink fragment of + * memory featured in copying. * - * \param[in,out] sink Destination buffer. - * \param[in,out] sources Array of source buffers. - * \param[in] frames Number of frames to process. - * \param[in] data Array of parameters describing channel count and routing for - * each stream. + * @param[in] dev Component device + * @param[in,out] sink Destination buffer. + * @param[in,out] sources Array of source buffers. + * @param[in] frames Number of frames to process. + * @param[in] lookup mux look up table. */ -static void mux_s24le(struct audio_stream *sink, - const struct audio_stream **sources, uint32_t frames, - struct mux_stream_data *data) +static void demux_s16le(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream *source, uint32_t frames, + struct mux_look_up *lookup) { - const struct audio_stream *source; uint8_t i; - uint8_t j; - uint8_t out_ch; - int32_t *dst; - uint32_t dst_idx; - int32_t sample; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < sink->channels; out_ch++) { - sample = 0; - for (j = 0; j < MUX_MAX_STREAMS; j++) { - source = sources[j]; - if (!source) - continue; - - sample += calc_sample_s24le(source, - i * source->channels, - data[j].mask[out_ch]); + int16_t *src; + int16_t *dst; + uint32_t elem; + uint32_t frames_without_wrap; + + comp_dbg(dev, "demux_s16le()"); + + if (!lookup || !lookup->num_elems) + return; + + demux_init_look_up_pointers_s16(dev, sink, source, lookup); + + while (frames) { + frames_without_wrap = + demux_calc_frames_without_wrap_s16(dev, sink, source, + lookup); + + frames_without_wrap = MIN(frames, frames_without_wrap); + + for (i = 0; i < frames_without_wrap; i++) { + for (elem = 0; elem < lookup->num_elems; elem++) { + src = (int16_t *)lookup->copy_elem[elem].src; + dst = (int16_t *)lookup->copy_elem[elem].dest; + *dst = *src; + lookup->copy_elem[elem].src = src + + lookup->copy_elem[elem].src_inc; + lookup->copy_elem[elem].dest = dst + + lookup->copy_elem[elem].dest_inc; } - dst_idx = i * sink->channels + out_ch; - dst = audio_stream_write_frag_s32(sink, dst_idx); - *dst = sat_int24(sample); } + + demux_check_for_wrap(sink, source, lookup); + + frames -= frames_without_wrap; } } -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE -/* - * \brief Fetch 32b samples from source buffer and perform routing operations - * based on mask provided. - * \param[in,out] source Source buffer. - * \param[in] offset Offset in source buffer. - * \param[in] mask Routing bitmask for calculating output sample. +/** + * Source streams are routed to sink with regard to look up table based on + * routing bitmasks from mux_stream_data structures array. Each sink channel + * has it's own lookup[].copy_elem describing source and sink fragment of + * memory featured in copying. + * + * @param[in] dev Component device + * @param[in,out] sink Destination buffer. + * @param[in,out] sources Array of source buffers. + * @param[in] frames Number of frames to process. + * @param[in] lookup mux look up table. */ -UT_STATIC inline int64_t calc_sample_s32le(const struct audio_stream *source, - uint32_t offset, uint8_t mask) +static void mux_s16le(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t frames, + struct mux_look_up *lookup) { - int64_t sample = 0; - int32_t *src; - int8_t in_ch; + uint8_t i; + int16_t *src; + int16_t *dst; + uint32_t elem; + uint32_t frames_without_wrap; + + comp_dbg(dev, "mux_s16le()"); + + if (!lookup || !lookup->num_elems) + return; + + mux_init_look_up_pointers_s16(dev, sink, sources, lookup); + + while (frames) { + frames_without_wrap = + mux_calc_frames_without_wrap_s16(dev, sink, sources, + lookup); - if (mask == 0) - return 0; + frames_without_wrap = MIN(frames, frames_without_wrap); - for (in_ch = 0; in_ch < source->channels; in_ch++) { - if (mask & BIT(in_ch)) { - src = audio_stream_read_frag_s32(source, - offset + in_ch); - sample += *src; + for (i = 0; i < frames_without_wrap; i++) { + for (elem = 0; elem < lookup->num_elems; elem++) { + src = (int16_t *)lookup->copy_elem[elem].src; + dst = (int16_t *)lookup->copy_elem[elem].dest; + *dst = *src; + lookup->copy_elem[elem].src = src + + lookup->copy_elem[elem].src_inc; + lookup->copy_elem[elem].dest = dst + + lookup->copy_elem[elem].dest_inc; + } } - } - return sample; + mux_check_for_wrap(sink, sources, lookup); + + frames -= frames_without_wrap; + } } +#endif /* CONFIG_FORMAT_S16LE */ -/* \brief Demuxing 32 bit streams. - * - * Source stream is routed to sink with regard to routing bitmasks from - * mux_stream_data structure. Each bitmask describes composition of single - * output channel. +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +/** + * Source stream are routed to sinks with regard to look up table based on + * routing bitmasks from mux_stream_data structures array. Each sink channel + * has it's own lookup[].copy_elem describing source and sink fragment of + * memory featured in copying. * - * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. - * \param[in] frames Number of frames to process. - * \param[in] data Parameters describing channel count and routing. + * @param[in] dev Component device + * @param[in,out] sink Destination buffer. + * @param[in,out] sources Array of source buffers. + * @param[in] frames Number of frames to process. + * @param[in] lookup mux look up table. */ -static void demux_s32le(struct audio_stream *sink, +static void demux_s32le(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream *source, uint32_t frames, - struct mux_stream_data *data) + struct mux_look_up *lookup) { - int64_t sample; - int32_t *dst; - uint32_t dst_idx; uint8_t i; - uint8_t out_ch; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < sink->channels; out_ch++) { - sample = calc_sample_s32le(source, - i * source->channels, - data->mask[out_ch]); - - /* saturate to 32 bits */ - dst_idx = i * sink->channels + out_ch; - dst = audio_stream_write_frag_s32(sink, dst_idx); - *dst = sat_int32(sample); + int32_t *src; + int32_t *dst; + uint32_t elem; + uint32_t frames_without_wrap; + + comp_dbg(dev, "demux_s32le"); + + if (!lookup || !lookup->num_elems) + return; + + demux_init_look_up_pointers_s32(dev, sink, source, lookup); + + while (frames) { + frames_without_wrap = + demux_calc_frames_without_wrap_s32(dev, sink, source, + lookup); + + frames_without_wrap = MIN(frames, frames_without_wrap); + + for (i = 0; i < frames_without_wrap; i++) { + for (elem = 0; elem < lookup->num_elems; elem++) { + src = (int32_t *)lookup->copy_elem[elem].src; + dst = (int32_t *)lookup->copy_elem[elem].dest; + *dst = *src; + lookup->copy_elem[elem].src = src + + lookup->copy_elem[elem].src_inc; + lookup->copy_elem[elem].dest = dst + + lookup->copy_elem[elem].dest_inc; + } } + + demux_check_for_wrap(sink, source, lookup); + + frames -= frames_without_wrap; } } -/* \brief Muxing 32 bit streams. - * - * Source streams are routed to sink with regard to routing bitmasks from - * mux_stream_data structures array. Each source stream has bitmask for each - * of it's channels describing to which channels of output stream it - * contributes. +/** + * Source streams are routed to sink with regard to look up table based on + * routing bitmasks from mux_stream_data structures array. Each sink channel + * has it's own lookup[].copy_elem describing source and sink fragment of + * memory featured in copying. * - * \param[in,out] sink Destination buffer. - * \param[in,out] sources Array of source buffers. - * \param[in] frames Number of frames to process. - * \param[in] data Array of parameters describing channel count and routing for - * each stream. + * @param[in] dev Component device + * @param[in,out] sink Destination buffer. + * @param[in,out] sources Array of source buffers. + * @param[in] frames Number of frames to process. + * @param[in] lookup mux look up table. */ -static void mux_s32le(struct audio_stream *sink, +static void mux_s32le(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream **sources, uint32_t frames, - struct mux_stream_data *data) + struct mux_look_up *lookup) { - const struct audio_stream *source; uint8_t i; - uint8_t j; - uint8_t out_ch; + int32_t *src; int32_t *dst; - uint32_t dst_idx; - int64_t sample; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < sink->channels; out_ch++) { - sample = 0; - for (j = 0; j < MUX_MAX_STREAMS; j++) { - source = sources[j]; - if (!source) - continue; - - sample += calc_sample_s32le(source, - i * source->channels, - data[j].mask[out_ch]); + uint32_t elem; + uint32_t frames_without_wrap; + + comp_dbg(dev, "mux_s32le()"); + + if (!lookup || !lookup->num_elems) + return; + + mux_init_look_up_pointers_s32(dev, sink, sources, lookup); + + while (frames) { + frames_without_wrap = + mux_calc_frames_without_wrap_s32(dev, sink, sources, + lookup); + + frames_without_wrap = MIN(frames, frames_without_wrap); + + for (i = 0; i < frames_without_wrap; i++) { + for (elem = 0; elem < lookup->num_elems; elem++) { + src = (int32_t *)lookup->copy_elem[elem].src; + dst = (int32_t *)lookup->copy_elem[elem].dest; + *dst = *src; + lookup->copy_elem[elem].src = src + + lookup->copy_elem[elem].src_inc; + lookup->copy_elem[elem].dest = dst + + lookup->copy_elem[elem].dest_inc; } - dst_idx = i * sink->channels + out_ch; - dst = audio_stream_write_frag_s32(sink, dst_idx); - *dst = sat_int32(sample); } + + mux_check_for_wrap(sink, sources, lookup); + + frames -= frames_without_wrap; } } -#endif /* CONFIG_FORMAT_S32LE */ +#endif /* CONFIG_FORMAT_S24LE CONFIG_FORMAT_S32LE */ const struct comp_func_map mux_func_map[] = { #if CONFIG_FORMAT_S16LE { SOF_IPC_FRAME_S16_LE, &mux_s16le, &demux_s16le }, #endif #if CONFIG_FORMAT_S24LE - { SOF_IPC_FRAME_S24_4LE, &mux_s24le, &demux_s24le }, + { SOF_IPC_FRAME_S24_4LE, &mux_s32le, &demux_s32le }, #endif #if CONFIG_FORMAT_S32LE { SOF_IPC_FRAME_S32_LE, &mux_s32le, &demux_s32le }, #endif }; +void mux_prepare_look_up_table(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + uint8_t i; + uint8_t j; + uint8_t k; + uint8_t idx = 0; + + /* Prepare look up table */ + for (i = 0; i < cd->config.num_streams; i++) { + for (j = 0; j < PLATFORM_MAX_CHANNELS; j++) { + for (k = 0; k < PLATFORM_MAX_CHANNELS; k++) { + if (cd->config.streams[i].mask[j] & BIT(k)) { + /* MUX component has only one sink */ + cd->lookup[0].copy_elem[idx].in_ch = k; + cd->lookup[0].copy_elem[idx].out_ch = j; + cd->lookup[0].copy_elem[idx].stream_id = + i; + cd->lookup[0].num_elems = ++idx; + } + } + } + } +} + +void demux_prepare_look_up_table(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + uint8_t i; + uint8_t j; + uint8_t k; + uint8_t idx; + + /* Prepare look up table */ + for (i = 0; i < cd->config.num_streams; i++) { + idx = 0; + for (j = 0; j < PLATFORM_MAX_CHANNELS; j++) { + for (k = 0; k < PLATFORM_MAX_CHANNELS; k++) { + if (cd->config.streams[i].mask[j] & BIT(k)) { + /* MUX component has only one sink */ + cd->lookup[i].copy_elem[idx].in_ch = k; + cd->lookup[i].copy_elem[idx].out_ch = j; + cd->lookup[i].copy_elem[idx].stream_id = + i; + cd->lookup[i].num_elems = ++idx; + } + } + } + } +} + mux_func mux_get_processing_function(struct comp_dev *dev) { struct comp_buffer *sinkb; diff --git a/src/include/sof/audio/audio_stream.h b/src/include/sof/audio/audio_stream.h index cb109b029fb9..68c09e9a80dd 100644 --- a/src/include/sof/audio/audio_stream.h +++ b/src/include/sof/audio/audio_stream.h @@ -526,6 +526,23 @@ audio_stream_bytes_without_wrap(const struct audio_stream *source, return to_end; } +/** + * @brief Calculates numbers of frames to buffer wrap and return + * minimum of calculated value. + * @param source Stream to get information from. + * @param ptr Read or write pointer from source + * @return Number of data frames to buffer wrap. + */ +static inline uint32_t +audio_stream_frames_without_wrap(const struct audio_stream *source, + const void *ptr) +{ + uint32_t bytes = audio_stream_bytes_without_wrap(source, ptr); + uint32_t frame_bytes = audio_stream_frame_bytes(source); + + return bytes / frame_bytes; +} + /** * Copies data from source buffer to sink buffer. * @param source Source buffer. diff --git a/src/include/sof/audio/mux.h b/src/include/sof/audio/mux.h index 8f6d7ff84838..7afb83127b4f 100644 --- a/src/include/sof/audio/mux.h +++ b/src/include/sof/audio/mux.h @@ -35,6 +35,23 @@ struct comp_dev; STATIC_ASSERT(MUX_MAX_STREAMS < PLATFORM_MAX_STREAMS, unsupported_amount_of_streams_for_mux); +struct mux_copy_elem { + uint32_t stream_id; + uint32_t in_ch; + uint32_t out_ch; + + void *dest; + void *src; + + uint32_t dest_inc; + uint32_t src_inc; +}; + +struct mux_look_up { + uint32_t num_elems; + struct mux_copy_elem copy_elem[PLATFORM_MAX_CHANNELS]; +}; + struct mux_stream_data { uint32_t pipeline_id; uint8_t num_channels_deprecated; /* deprecated in ABI 3.15 */ @@ -43,12 +60,12 @@ struct mux_stream_data { uint8_t reserved[(20 - PLATFORM_MAX_CHANNELS - 1) % 4]; // padding to ensure proper alignment of following instances }; -typedef void(*demux_func)(struct audio_stream *sink, +typedef void(*demux_func)(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream *source, uint32_t frames, - struct mux_stream_data *data); -typedef void(*mux_func)(struct audio_stream *sink, + struct mux_look_up *look_up); +typedef void(*mux_func)(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream **sources, uint32_t frames, - struct mux_stream_data *data); + struct mux_look_up *look_up); struct sof_mux_config { uint16_t frame_format_deprecated; /* deprecated in ABI 3.15 */ @@ -66,6 +83,8 @@ struct comp_data { demux_func demux; }; + struct mux_look_up lookup[MUX_MAX_STREAMS]; + struct mux_look_up active_lookup; struct sof_mux_config config; }; @@ -77,6 +96,9 @@ struct comp_func_map { extern const struct comp_func_map mux_func_map[]; +void mux_prepare_look_up_table(struct comp_dev *dev); +void demux_prepare_look_up_table(struct comp_dev *dev); + mux_func mux_get_processing_function(struct comp_dev *dev); demux_func demux_get_processing_function(struct comp_dev *dev); diff --git a/test/cmocka/src/audio/mux/CMakeLists.txt b/test/cmocka/src/audio/mux/CMakeLists.txt index da4ad31605fa..9d7e8c1f7614 100644 --- a/test/cmocka/src/audio/mux/CMakeLists.txt +++ b/test/cmocka/src/audio/mux/CMakeLists.txt @@ -36,28 +36,3 @@ cmocka_test( demux_copy.c mock.c ) - -if(CONFIG_FORMAT_S16LE) -cmocka_test( - mux_generic_calc_sample_s16le - mux_generic_calc_sample_s16le.c - mock.c -) -endif() - -if(CONFIG_FORMAT_S24LE) -cmocka_test( - mux_generic_calc_sample_s24le - mux_generic_calc_sample_s24le.c - mock.c -) -endif() - - -if(CONFIG_FORMAT_S32LE) -cmocka_test( - mux_generic_calc_sample_s32le - mux_generic_calc_sample_s32le.c - mock.c -) -endif() diff --git a/test/cmocka/src/audio/mux/demux_copy.c b/test/cmocka/src/audio/mux/demux_copy.c index 5b8d7661a3fe..4dee86b19e14 100644 --- a/test/cmocka/src/audio/mux/demux_copy.c +++ b/test/cmocka/src/audio/mux/demux_copy.c @@ -33,6 +33,11 @@ static int16_t input_16b[PLATFORM_MAX_CHANNELS] = { 0x111, 0x112, 0x114, 0x118, }; +static int32_t input_24b[PLATFORM_MAX_CHANNELS] = { + 0x1a1001, 0x2a2002, 0x4a4004, 0x8a8008, + 0x1b1011, 0x2b2012, 0x4b4014, 0x8b8018, +}; + static int32_t input_32b[PLATFORM_MAX_CHANNELS] = { 0xd1a1001, 0xd2a2002, 0xd4a4004, 0xd8a8008, 0xe1b1011, 0xe2b2012, 0xe4b4014, 0xe8b8018, @@ -46,38 +51,32 @@ static uint16_t valid_formats[] = { static uint8_t masks[][MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { { { 0x01, }, }, + { { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, + { { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, + { { }, + { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, + { { }, + { }, + { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, { { 0x01, }, - { 0x01, }, - { 0x01, }, - { 0x01, }, }, - { { 0x00, 0x00, 0x00, 0x01, }, + { 0x00, 0x01, }, + { 0x00, 0x00, 0x01, }, + { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10}, }, + { { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10}, { 0x00, 0x00, 0x01, }, { 0x00, 0x01, }, { 0x01, }, }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, - { 0x00, 0x00, 0x00, 0x00, 0x01, }, }, - { { 0x02, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, }, - { 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, }, - { 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x3f, }, - { 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0xff, }, }, - { { 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, }, - { 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, }, - { 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, }, - { 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, }, }, - { { 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, }, - { 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, }, - { 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, }, - { 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, }, }, - { { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, - { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, - { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, - { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, }, - { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, }, + { 0x10, 0x08, 0x04, 0x02, 0x01, },}, + { { 0x01, }, + { 0x00, 0x01, }, + { 0x00, 0x00, 0x01, }, + { 0x00, 0x00, 0x00, 0x01, },}, }; static int setup_group(void **state) @@ -125,6 +124,8 @@ static void prepare_sinks(struct test_data *td, size_t sample_size) td->sinks[i]->stream.free = sample_size * PLATFORM_MAX_CHANNELS; td->outputs[i] = malloc(sample_size * PLATFORM_MAX_CHANNELS); td->sinks[i]->stream.w_ptr = td->outputs[i]; + + memset(td->outputs[i], 0, td->sinks[i]->stream.free); } } @@ -138,6 +139,8 @@ static void prepare_source(struct test_data *td, size_t sample_size) if (td->format == SOF_IPC_FRAME_S16_LE) td->source->stream.r_ptr = input_16b; + else if (td->format == SOF_IPC_FRAME_S24_4LE) + td->source->stream.r_ptr = input_24b; else td->source->stream.r_ptr = input_32b; } @@ -198,9 +201,9 @@ static void test_demux_copy_proc_16(void **state) for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) if (td->mask[i][j] & BIT(k)) - sample += input_16b[k]; + sample = input_16b[k]; - expected_results[i][j] = sat_int16(sample); + expected_results[i][j] = sample; } } @@ -219,13 +222,13 @@ static void test_demux_copy_proc_24(void **state) for (i = 0; i < MUX_MAX_STREAMS; ++i) { for (j = 0; j < PLATFORM_MAX_CHANNELS; ++j) { - int64_t sample = 0; + int32_t sample = 0; for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) if (td->mask[i][j] & BIT(k)) - sample += sign_extend_s24(input_32b[k]); + sample = input_24b[k]; - expected_results[i][j] = sat_int24(sample); + expected_results[i][j] = sample; } } @@ -244,13 +247,13 @@ static void test_demux_copy_proc_32(void **state) for (i = 0; i < MUX_MAX_STREAMS; ++i) { for (j = 0; j < PLATFORM_MAX_CHANNELS; ++j) { - int64_t sample = 0; + int32_t sample = 0; for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) if (td->mask[i][j] & BIT(k)) - sample += input_32b[k]; + sample = input_32b[k]; - expected_results[i][j] = sat_int32(sample); + expected_results[i][j] = sample; } } diff --git a/test/cmocka/src/audio/mux/mux_copy.c b/test/cmocka/src/audio/mux/mux_copy.c index 4fafb5ea75ad..dbdfb2be95f9 100644 --- a/test/cmocka/src/audio/mux/mux_copy.c +++ b/test/cmocka/src/audio/mux/mux_copy.c @@ -39,6 +39,17 @@ static int16_t input_16b[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { 0x411, 0x412, 0x414, 0x418, }, }; +static int32_t input_24b[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { + { 0x1a1001, 0x2a2002, 0x4a4004, 0x8a8008, + 0x1b1011, 0x2b2012, 0x4b4014, 0x8b8018, }, + { 0x1a1101, 0x2a2102, 0x4a4104, 0x8a8108, + 0x1b1111, 0x2b2112, 0x4b4114, 0x8b8118, }, + { 0x1a1201, 0x2a2202, 0x4a4204, 0x8a8208, + 0x1b1211, 0x2b2212, 0x4b4214, 0x8b8218, }, + { 0x1a1401, 0x2a2402, 0x4a4404, 0x8a8408, + 0x1b1411, 0x2b2412, 0x4b4414, 0x8b8418, }, +}; + static int32_t input_32b[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { { 0xd1a1001, 0xd2a2002, 0xd4a4004, 0xd8a8008, 0xe1b1011, 0xe2b2012, 0xe4b4014, 0xe8b8018, }, @@ -58,38 +69,32 @@ static uint16_t valid_formats[] = { static uint8_t masks[][MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { { { 0x01, }, }, + { { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, + { { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, + { { }, + { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, + { { }, + { }, + { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, { { 0x01, }, - { 0x01, }, - { 0x01, }, - { 0x01, }, }, - { { 0x00, 0x00, 0x00, 0x01, }, + { 0x00, 0x01, }, + { 0x00, 0x00, 0x01, }, + { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10}, }, + { { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10}, { 0x00, 0x00, 0x01, }, { 0x00, 0x01, }, { 0x01, }, }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, - { 0x00, 0x00, 0x00, 0x00, 0x01, }, }, - { { 0x02, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, }, - { 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, }, - { 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x3f, }, - { 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0xff, }, }, - { { 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, }, - { 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, }, - { 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, }, - { 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, }, }, - { { 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, }, - { 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, }, - { 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, }, - { 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, }, }, - { { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, - { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, - { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, - { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, }, - { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, }, + { 0x10, 0x08, 0x04, 0x02, 0x01, },}, + { { 0x01, }, + { 0x00, 0x01, }, + { 0x00, 0x00, 0x01, }, + { 0x00, 0x00, 0x00, 0x01, },}, }; static int setup_group(void **state) @@ -134,6 +139,8 @@ static void prepare_sink(struct test_data *td, size_t sample_size) td->sink->stream.free = sample_size * PLATFORM_MAX_CHANNELS; td->output = malloc(sample_size * PLATFORM_MAX_CHANNELS); td->sink->stream.w_ptr = td->output; + + memset(td->output, 0, td->sink->stream.free); } static void prepare_sources(struct test_data *td, size_t sample_size) @@ -150,6 +157,8 @@ static void prepare_sources(struct test_data *td, size_t sample_size) if (td->format == SOF_IPC_FRAME_S16_LE) td->sources[i]->stream.r_ptr = input_16b[i]; + else if (td->format == SOF_IPC_FRAME_S24_4LE) + td->sources[i]->stream.r_ptr = input_24b[i]; else td->sources[i]->stream.r_ptr = input_32b[i]; } @@ -210,10 +219,10 @@ static void test_mux_copy_proc_16(void **state) for (j = 0; j < MUX_MAX_STREAMS; ++j) { for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) { if (td->mask[j][i] & BIT(k)) - sample += input_16b[j][k]; + sample = input_16b[j][k]; } } - expected_result[i] = sat_int16(sample); + expected_result[i] = sample; } assert_memory_equal(td->output, expected_result, @@ -225,22 +234,19 @@ static void test_mux_copy_proc_24(void **state) struct test_data *td = *((struct test_data **)state); int32_t expected_result[PLATFORM_MAX_CHANNELS]; int i, j, k; - int32_t val; assert_int_equal(comp_copy(td->dev), 0); for (i = 0; i < PLATFORM_MAX_CHANNELS; ++i) { - int64_t sample = 0; + int32_t sample = 0; for (j = 0; j < MUX_MAX_STREAMS; ++j) { for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) { - if (td->mask[j][i] & BIT(k)) { - val = input_32b[j][k]; - sample += sign_extend_s24(val); - } + if (td->mask[j][i] & BIT(k)) + sample = input_24b[j][k]; } } - expected_result[i] = sat_int24(sample); + expected_result[i] = sample; } assert_memory_equal(td->output, expected_result, @@ -256,15 +262,15 @@ static void test_mux_copy_proc_32(void **state) assert_int_equal(comp_copy(td->dev), 0); for (i = 0; i < PLATFORM_MAX_CHANNELS; ++i) { - int64_t sample = 0; + int32_t sample = 0; for (j = 0; j < MUX_MAX_STREAMS; ++j) { for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) { if (td->mask[j][i] & BIT(k)) - sample += input_32b[j][k]; + sample = input_32b[j][k]; } } - expected_result[i] = sat_int32(sample); + expected_result[i] = sample; } assert_memory_equal(td->output, expected_result, diff --git a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s16le.c b/test/cmocka/src/audio/mux/mux_generic_calc_sample_s16le.c deleted file mode 100644 index b0f769378169..000000000000 --- a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s16le.c +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Daniel Bogdzia -// Janusz Jankowski - -#include -#include - -#include -#include -#include -#include -#include -#include - -struct test_data { - const char *name; - uint32_t channels; - uint8_t mask; - int16_t *input; - struct comp_buffer *buffer; - int32_t expected_result; -}; - -static int16_t input_samples[][PLATFORM_MAX_CHANNELS] = { - { 0x1, 0x2, 0x4, 0x8, - 0x10, 0x20, 0x40, 0x80, }, - { 0x100, 0x200, 0x400, 0x800, - 0x1000, 0x2000, 0x4000, 0x8000, }, - { 0x8000, 0xf000, 0x8000, 0xf000, - 0xf000, 0x8000, 0xf000, 0x8000, }, -}; - -#define TEST_CASE(channels, mask, input_index) \ - { ("test_calc_sample_s16le_ch_" #channels "_mask_" #mask \ - "_input_" #input_index), channels, mask, \ - input_samples[input_index], NULL, 0 } - -static struct test_data test_cases[] = { - TEST_CASE(1, 0x0, 0), - TEST_CASE(1, 0x0, 1), - TEST_CASE(1, 0x0, 2), - TEST_CASE(1, 0x1, 0), - TEST_CASE(1, 0x1, 1), - TEST_CASE(1, 0x1, 2), - TEST_CASE(2, 0x0, 0), - TEST_CASE(2, 0x0, 1), - TEST_CASE(2, 0x0, 2), - TEST_CASE(2, 0x1, 0), - TEST_CASE(2, 0x1, 2), - TEST_CASE(2, 0x2, 0), - TEST_CASE(2, 0x2, 2), - TEST_CASE(2, 0x3, 0), - TEST_CASE(2, 0x3, 2), - TEST_CASE(3, 0x1, 1), - TEST_CASE(3, 0x7, 1), - TEST_CASE(5, 0x4, 1), - TEST_CASE(5, 0x12, 1), - TEST_CASE(7, 0x10, 1), - TEST_CASE(7, 0x11, 1), - TEST_CASE(8, 0x0f, 1), - TEST_CASE(8, 0x0f, 2), - TEST_CASE(8, 0x10, 0), - TEST_CASE(8, 0x11, 0), - TEST_CASE(8, 0xf0, 1), - TEST_CASE(8, 0xf0, 2), - TEST_CASE(8, 0xff, 1), - TEST_CASE(8, 0xff, 2), -}; - -static void test_calc_sample(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - int32_t ret = calc_sample_s16le(&td->buffer->stream, - 0, - td->mask); - - assert_int_equal(ret, td->expected_result); -} - -static int setup(void **state) -{ - struct test_data *td = *((struct test_data **)state); - int ch; - - td->buffer = calloc(1, sizeof(struct comp_buffer)); - td->buffer->stream.r_ptr = td->input; - td->buffer->stream.channels = td->channels; - - td->expected_result = 0; - - for (ch = 0; ch < td->channels; ++ch) { - if (td->mask & BIT(ch)) - td->expected_result += td->input[ch]; - } - - return 0; -} - -static int teardown(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - free(td->buffer); - - return 0; -} - -int main(void) -{ - int i; - struct CMUnitTest tests[ARRAY_SIZE(test_cases)]; - - for (i = 0; i < ARRAY_SIZE(test_cases); ++i) { - tests[i].name = test_cases[i].name; - tests[i].test_func = test_calc_sample; - tests[i].initial_state = &test_cases[i]; - tests[i].setup_func = setup; - tests[i].teardown_func = teardown; - } - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s24le.c b/test/cmocka/src/audio/mux/mux_generic_calc_sample_s24le.c deleted file mode 100644 index 83fd03fa4bdb..000000000000 --- a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s24le.c +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Daniel Bogdzia -// Janusz Jankowski - -#include -#include - -#include -#include -#include -#include -#include -#include - -struct test_data { - const char *name; - uint32_t channels; - uint8_t mask; - int32_t *input; - struct comp_buffer *buffer; - int32_t expected_result; -}; - -static int32_t input_samples[][PLATFORM_MAX_CHANNELS] = { - { 0x1, 0x2, 0x4, 0x8, - 0x10, 0x20, 0x40, 0x80, }, - { 0x10000, 0x20000, 0x40000, 0x80000, - 0x100000, 0x200000, 0x400000, 0x800000, }, - { 0x1000000, 0x2000000, 0x4000000, 0x8000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, }, - { 0x80000000, 0xf0000000, 0x80000000, 0xf0000000, - 0xf0000000, 0x80000000, 0xf0000000, 0x80000000, }, -}; - -#define TEST_CASE(channels, mask, input_index) \ - { ("test_calc_sample_s24le_ch_" #channels "_mask_" #mask \ - "_input_" #input_index), channels, mask, \ - input_samples[input_index], NULL, 0 } - -static struct test_data test_cases[] = { - TEST_CASE(1, 0x0, 0), - TEST_CASE(1, 0x0, 1), - TEST_CASE(1, 0x0, 2), - TEST_CASE(1, 0x1, 0), - TEST_CASE(1, 0x1, 1), - TEST_CASE(1, 0x1, 2), - TEST_CASE(2, 0x0, 0), - TEST_CASE(2, 0x0, 1), - TEST_CASE(2, 0x0, 2), - TEST_CASE(2, 0x1, 0), - TEST_CASE(2, 0x1, 2), - TEST_CASE(2, 0x2, 0), - TEST_CASE(2, 0x2, 2), - TEST_CASE(2, 0x3, 0), - TEST_CASE(2, 0x3, 2), - TEST_CASE(3, 0x1, 1), - TEST_CASE(3, 0x7, 1), - TEST_CASE(5, 0x4, 1), - TEST_CASE(5, 0x12, 1), - TEST_CASE(7, 0x10, 2), - TEST_CASE(7, 0x11, 2), - TEST_CASE(8, 0x0f, 1), - TEST_CASE(8, 0x0f, 3), - TEST_CASE(8, 0x10, 0), - TEST_CASE(8, 0x11, 0), - TEST_CASE(8, 0xf0, 2), - TEST_CASE(8, 0xf0, 3), - TEST_CASE(8, 0xff, 2), - TEST_CASE(8, 0xff, 3), -}; - -static void test_calc_sample(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - int32_t ret = calc_sample_s24le(&td->buffer->stream, - 0, - td->mask); - - assert_int_equal(ret, td->expected_result); -} - -static int setup(void **state) -{ - struct test_data *td = *((struct test_data **)state); - int ch; - - td->buffer = calloc(1, sizeof(struct comp_buffer)); - td->buffer->stream.r_ptr = td->input; - td->buffer->stream.channels = td->channels; - - td->expected_result = 0; - - for (ch = 0; ch < td->channels; ++ch) { - /* 8 MSB should be ignored */ - if (td->mask & BIT(ch)) - td->expected_result += (td->input[ch] & 0x00ffffff); - } - - return 0; -} - -static int teardown(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - free(td->buffer); - - return 0; -} - -int main(void) -{ - int i; - struct CMUnitTest tests[ARRAY_SIZE(test_cases)]; - - for (i = 0; i < ARRAY_SIZE(test_cases); ++i) { - tests[i].name = test_cases[i].name; - tests[i].test_func = test_calc_sample; - tests[i].initial_state = &test_cases[i]; - tests[i].setup_func = setup; - tests[i].teardown_func = teardown; - } - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s32le.c b/test/cmocka/src/audio/mux/mux_generic_calc_sample_s32le.c deleted file mode 100644 index 33061abe1ee9..000000000000 --- a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s32le.c +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Daniel Bogdzia -// Janusz Jankowski - -#include -#include - -#include -#include -#include -#include -#include -#include - -struct test_data { - const char *name; - uint32_t channels; - uint8_t mask; - int32_t *input; - struct comp_buffer *buffer; - int64_t expected_result; -}; - -static int32_t input_samples[][PLATFORM_MAX_CHANNELS] = { - { 0x1, 0x2, 0x4, 0x8, - 0x10, 0x20, 0x40, 0x80, }, - { 0x10000, 0x20000, 0x40000, 0x80000, - 0x100000, 0x200000, 0x400000, 0x800000, }, - { 0x1000000, 0x2000000, 0x4000000, 0x8000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, }, - { 0x80000000, 0xf0000000, 0x80000000, 0xf0000000, - 0xf0000000, 0x80000000, 0xf0000000, 0x80000000, }, -}; - -#define TEST_CASE(channels, mask, input_index) \ - { ("test_calc_sample_s32le_ch_" #channels "_mask_" #mask \ - "_input_" #input_index), channels, mask, \ - input_samples[input_index], NULL, 0 } - -static struct test_data test_cases[] = { - TEST_CASE(1, 0x0, 0), - TEST_CASE(1, 0x0, 1), - TEST_CASE(1, 0x0, 2), - TEST_CASE(1, 0x1, 0), - TEST_CASE(1, 0x1, 1), - TEST_CASE(1, 0x1, 2), - TEST_CASE(2, 0x0, 0), - TEST_CASE(2, 0x0, 1), - TEST_CASE(2, 0x0, 2), - TEST_CASE(2, 0x1, 0), - TEST_CASE(2, 0x1, 2), - TEST_CASE(2, 0x2, 0), - TEST_CASE(2, 0x2, 2), - TEST_CASE(2, 0x3, 0), - TEST_CASE(2, 0x3, 2), - TEST_CASE(3, 0x1, 1), - TEST_CASE(3, 0x7, 1), - TEST_CASE(5, 0x4, 1), - TEST_CASE(5, 0x12, 1), - TEST_CASE(7, 0x10, 2), - TEST_CASE(7, 0x11, 2), - TEST_CASE(8, 0x0f, 1), - TEST_CASE(8, 0x0f, 3), - TEST_CASE(8, 0x10, 0), - TEST_CASE(8, 0x11, 0), - TEST_CASE(8, 0xf0, 2), - TEST_CASE(8, 0xf0, 3), - TEST_CASE(8, 0xff, 2), - TEST_CASE(8, 0xff, 3), -}; - -static void test_calc_sample(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - int64_t ret = calc_sample_s32le(&td->buffer->stream, - 0, - td->mask); - - assert_int_equal(ret, td->expected_result); -} - -static int setup(void **state) -{ - struct test_data *td = *((struct test_data **)state); - int ch; - - td->buffer = calloc(1, sizeof(struct comp_buffer)); - td->buffer->stream.r_ptr = td->input; - td->buffer->stream.channels = td->channels; - - td->expected_result = 0; - - for (ch = 0; ch < td->channels; ++ch) { - if (td->mask & BIT(ch)) - td->expected_result += td->input[ch]; - } - - return 0; -} - -static int teardown(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - free(td->buffer); - - return 0; -} - -int main(void) -{ - int i; - struct CMUnitTest tests[ARRAY_SIZE(test_cases)]; - - for (i = 0; i < ARRAY_SIZE(test_cases); ++i) { - tests[i].name = test_cases[i].name; - tests[i].test_func = test_calc_sample; - tests[i].initial_state = &test_cases[i]; - tests[i].setup_func = setup; - tests[i].teardown_func = teardown; - } - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -}