diff --git a/src/audio/aria/aria.c b/src/audio/aria/aria.c index 0c9ffee5dd39..dc265cfac240 100644 --- a/src/audio/aria/aria.c +++ b/src/audio/aria/aria.c @@ -168,11 +168,6 @@ static void aria_set_stream_params(struct comp_buffer *buffer, const struct ipc4_audio_format *audio_fmt = &mod->priv.cfg.base_cfg.audio_fmt; ipc4_update_buffer_format(buffer, audio_fmt); -#if SOF_USE_HIFI(3, ARIA) || SOF_USE_HIFI(4, ARIA) - audio_stream_set_align(8, 1, &buffer->stream); -#elif SOF_USE_HIFI(5, ARIA) - audio_stream_set_align(16, 1, &buffer->stream); -#endif } static int aria_prepare(struct processing_module *mod, @@ -195,6 +190,7 @@ static int aria_prepare(struct processing_module *mod, aria_set_stream_params(source, mod); aria_set_stream_params(sink, mod); + audio_stream_set_align(SOF_FRAME_BYTE_ALIGN, SOF_FRAME_COUNT_ALIGN, &source->stream); if (audio_stream_get_valid_fmt(&source->stream) != SOF_IPC_FRAME_S24_4LE || audio_stream_get_valid_fmt(&sink->stream) != SOF_IPC_FRAME_S24_4LE) { diff --git a/src/audio/audio_stream.c b/src/audio/audio_stream.c index c4c5f7b04acb..aa16617f066c 100644 --- a/src/audio/audio_stream.c +++ b/src/audio/audio_stream.c @@ -51,6 +51,6 @@ void audio_stream_init(struct audio_stream *audio_stream, void *buff_addr, uint3 audio_stream->addr = buff_addr; audio_stream->end_addr = (char *)audio_stream->addr + size; - audio_stream_set_align(1, 1, audio_stream); + audio_stream_set_align(SOF_FRAME_BYTE_ALIGN, SOF_FRAME_COUNT_ALIGN, audio_stream); audio_stream_reset(audio_stream); } diff --git a/src/audio/eq_fir/eq_fir.c b/src/audio/eq_fir/eq_fir.c index 39cce7fd7974..5427e99ff1ac 100644 --- a/src/audio/eq_fir/eq_fir.c +++ b/src/audio/eq_fir/eq_fir.c @@ -369,11 +369,10 @@ static int eq_fir_process(struct processing_module *mod, static void eq_fir_set_alignment(struct audio_stream *source, struct audio_stream *sink) { - const uint32_t byte_align = 1; + const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN; const uint32_t frame_align_req = 2; /* Process multiples of 2 frames */ audio_stream_set_align(byte_align, frame_align_req, source); - audio_stream_set_align(byte_align, frame_align_req, sink); } static int eq_fir_prepare(struct processing_module *mod, diff --git a/src/audio/eq_iir/eq_iir.c b/src/audio/eq_iir/eq_iir.c index 0f07fbeda03c..016c2c8caf82 100644 --- a/src/audio/eq_iir/eq_iir.c +++ b/src/audio/eq_iir/eq_iir.c @@ -142,7 +142,7 @@ static int eq_iir_process(struct processing_module *mod, static void eq_iir_set_alignment(struct audio_stream *source, struct audio_stream *sink) { - const uint32_t byte_align = 8; + const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN; const uint32_t frame_align_req = 2; audio_stream_set_align(byte_align, frame_align_req, source); diff --git a/src/audio/igo_nr/igo_nr.c b/src/audio/igo_nr/igo_nr.c index bde7d2b8fe32..e398af7d964b 100644 --- a/src/audio/igo_nr/igo_nr.c +++ b/src/audio/igo_nr/igo_nr.c @@ -832,8 +832,7 @@ static int32_t igo_nr_prepare(struct processing_module *mod, if (ret) return ret; - source_set_alignment_constants(source, 1, IGO_FRAME_SIZE); - sink_set_alignment_constants(sink, 1, IGO_FRAME_SIZE); + source_set_alignment_constants(source, SOF_FRAME_BYTE_ALIGN, IGO_FRAME_SIZE); igo_nr_set_igo_params(mod); diff --git a/src/audio/mixer/mixer.c b/src/audio/mixer/mixer.c index 6300d5b86bc5..cdc74fd2f1e7 100644 --- a/src/audio/mixer/mixer.c +++ b/src/audio/mixer/mixer.c @@ -187,18 +187,18 @@ static int mixer_reset(struct processing_module *mod) /* init and calculate the aligned setting for available frames and free frames retrieve*/ static inline void mixer_set_frame_alignment(struct audio_stream *source) { -#if XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4 /* Xtensa intrinsics ask for 8-byte aligned. 5.1 format SSE audio - * requires 16-byte aligned. + * requires 16-byte aligned. Note: The SOF_FRAME_BYTE_ALIGN is the + * same value 16 with HiFi5. */ - const uint32_t byte_align = audio_stream_get_channels(source) == 6 ? 16 : 8; + const uint32_t byte_align = audio_stream_get_channels(source) == 6 ? + MIXER_HIFI_FRAME_BYTE_ALIGN_6CH : SOF_FRAME_BYTE_ALIGN; /*There is no limit for frame number, so set it as 1*/ - const uint32_t frame_align_req = 1; + const uint32_t frame_align_req = SOF_FRAME_COUNT_ALIGN; audio_stream_set_align(byte_align, frame_align_req, source); -#endif } static int mixer_prepare(struct processing_module *mod, @@ -216,7 +216,6 @@ static int mixer_prepare(struct processing_module *mod, } md->mix_func = mixer_get_processing_function(dev, sink); - mixer_set_frame_alignment(&sink->stream); /* check each mixer source state */ struct comp_buffer *source; diff --git a/src/audio/mixer/mixer.h b/src/audio/mixer/mixer.h index 118aaf1c914f..875ddcbb26fe 100644 --- a/src/audio/mixer/mixer.h +++ b/src/audio/mixer/mixer.h @@ -32,6 +32,9 @@ void sys_comp_module_mixer_interface_init(void); #define MIXER_MAX_SOURCES 2 +/* Xtensa HiFi optimized version needs this for 5.1ch */ +#define MIXER_HIFI_FRAME_BYTE_ALIGN_6CH 16 + /* mixer component private data */ struct mixer_data { void (*mix_func)(struct comp_dev *dev, struct audio_stream *sink, diff --git a/src/audio/selector/selector.c b/src/audio/selector/selector.c index 8d99d785a899..6afc92d8bdfc 100644 --- a/src/audio/selector/selector.c +++ b/src/audio/selector/selector.c @@ -1007,8 +1007,7 @@ static int selector_prepare(struct processing_module *mod, sourceb = comp_dev_get_first_data_producer(dev); sinkb = comp_dev_get_first_data_consumer(dev); - audio_stream_set_align(4, 1, &sourceb->stream); - audio_stream_set_align(4, 1, &sinkb->stream); + audio_stream_set_align(SOF_FRAME_BYTE_ALIGN, SOF_FRAME_COUNT_ALIGN, &sourceb->stream); /* get source data format and period bytes */ cd->source_format = audio_stream_get_frm_fmt(&sourceb->stream); diff --git a/src/audio/src/src_common.c b/src/audio/src/src_common.c index cb595f3e8877..3a9c7dac280f 100644 --- a/src/audio/src/src_common.c +++ b/src/audio/src/src_common.c @@ -384,13 +384,12 @@ int src_copy_sxx(struct comp_data *cd, struct sof_source *source, return -ENOTSUP; } -void src_set_alignment(struct sof_source *source, struct sof_sink *sink) +void src_set_alignment(struct sof_source *source) { - const uint32_t byte_align = 1; - const uint32_t frame_align_req = 1; + const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN; + const uint32_t frame_align_req = SOF_FRAME_COUNT_ALIGN; source_set_alignment_constants(source, byte_align, frame_align_req); - sink_set_alignment_constants(sink, byte_align, frame_align_req); } static int src_verify_params(struct processing_module *mod) diff --git a/src/audio/src/src_common.h b/src/audio/src/src_common.h index ae3c60574eec..98f29a263131 100644 --- a/src/audio/src/src_common.h +++ b/src/audio/src/src_common.h @@ -143,7 +143,7 @@ int32_t src_input_rates(void); int32_t src_output_rates(void); -void src_set_alignment(struct sof_source *source, struct sof_sink *sink); +void src_set_alignment(struct sof_source *source); struct comp_data { #if CONFIG_IPC_MAJOR_4 diff --git a/src/audio/src/src_ipc3.c b/src/audio/src/src_ipc3.c index b161155193fc..541efcdb24be 100644 --- a/src/audio/src/src_ipc3.c +++ b/src/audio/src/src_ipc3.c @@ -105,7 +105,7 @@ int src_prepare_general(struct processing_module *mod, enum sof_ipc_frame sink_format; /* set align requirements */ - src_set_alignment(source, sink); + src_set_alignment(source); /* get source/sink data format */ source_format = source_get_frm_fmt(source); diff --git a/src/audio/src/src_ipc4.c b/src/audio/src/src_ipc4.c index 1240a86bd48e..91f286347a5f 100644 --- a/src/audio/src/src_ipc4.c +++ b/src/audio/src/src_ipc4.c @@ -151,7 +151,7 @@ int src_prepare_general(struct processing_module *mod, int ret = 0; /* set align requirements */ - src_set_alignment(source, sink); + src_set_alignment(source); switch (cd->ipc_config.base.audio_fmt.valid_bit_depth) { #if CONFIG_FORMAT_S16LE diff --git a/src/audio/tdfb/tdfb.c b/src/audio/tdfb/tdfb.c index fa6a207d49e6..69998c390ed2 100644 --- a/src/audio/tdfb/tdfb.c +++ b/src/audio/tdfb/tdfb.c @@ -692,11 +692,10 @@ static int tdfb_process(struct processing_module *mod, static void tdfb_set_alignment(struct audio_stream *source, struct audio_stream *sink) { - const uint32_t byte_align = 1; + const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN; const uint32_t frame_align_req = 2; /* Process multiples of 2 frames */ audio_stream_set_align(byte_align, frame_align_req, source); - audio_stream_set_align(byte_align, frame_align_req, sink); } static int tdfb_prepare(struct processing_module *mod, diff --git a/src/audio/volume/volume.c b/src/audio/volume/volume.c index aed356a3ec83..d44dbde6752f 100644 --- a/src/audio/volume/volume.c +++ b/src/audio/volume/volume.c @@ -556,6 +556,7 @@ static int volume_process(struct processing_module *mod, struct output_stream_buffer *output_buffers, int num_output_buffers) { struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = input_buffers[0].data; uint32_t avail_frames = input_buffers[0].size; uint32_t frames; int64_t prev_sum = 0; @@ -571,12 +572,23 @@ static int volume_process(struct processing_module *mod, frames = avail_frames; } else if (cd->ramp_type == SOF_VOLUME_LINEAR_ZC) { /* with ZC ramping look for next ZC offset */ - frames = cd->zc_get(input_buffers[0].data, cd->vol_ramp_frames, &prev_sum); + frames = cd->zc_get(source, cd->vol_ramp_frames, &prev_sum); + /* Align frames count to audio stream constraints */ + frames = audio_stream_align_frames_round_up(source, frames); } else { - /* without ZC process max ramp chunk */ - frames = cd->vol_ramp_frames; + /* During volume ramp align the number of frames used in this + * gain step. Align up since with low rates this would typically + * become zero. + */ + frames = audio_stream_align_frames_round_up(source, cd->vol_ramp_frames); } + /* Cancel the gain step for ZC or smaller ramp step if it exceeds + * the available frames. + */ + if (frames > avail_frames) + frames = avail_frames; + if (!cd->ramp_finished) { volume_ramp(mod); cd->vol_ramp_elapsed_frames += frames; @@ -625,28 +637,34 @@ static vol_zc_func vol_get_zc_function(struct comp_dev *dev, * \param[in,out] source Structure pointer of source. * \param[in,out] sink Structure pointer of sink. */ -static void volume_set_alignment(struct audio_stream *source, - struct audio_stream *sink) +static void volume_set_alignment(struct audio_stream *source) { + const int channels = audio_stream_get_channels(source); + /* Both source and sink buffer in HiFi5 processing version, * xtensa intrinsics ask for 16-byte aligned. + * Note: The SOF_FRAME_BYTE_ALIGN is the same value 16 with HiFi5 * * Both source and sink buffer in HiFi3 or HiFi4 processing version, * xtensa intrinsics ask for 8-byte aligned. 5.1 format SSE audio * requires 16-byte aligned. */ -#if SOF_USE_HIFI(3, VOLUME) || SOF_USE_HIFI(4, VOLUME) - const uint32_t byte_align = audio_stream_get_channels(source) == 6 ? - VOLUME_HIFI3_HIFI4_FRAME_BYTE_ALIGN_6CH : SOF_FRAME_BYTE_ALIGN; + const uint32_t byte_align = + (channels == 6) ? VOLUME_HIFI3_HIFI4_FRAME_BYTE_ALIGN_6CH : SOF_FRAME_BYTE_ALIGN; + + /* On HiFi5 the number of samples to process must be multiple of four for s32 + * and multiple of eight for s16. For HiFi4 and HiFi3 the number of samples + * need to be multiple of two for s32 and multiple of four for s16. + */ +#if SOF_USE_HIFI(5, VOLUME) + const int n = (audio_stream_get_valid_fmt(source) == SOF_IPC_FRAME_S16_LE) ? 8 : 4; #else - const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN; + const int n = (audio_stream_get_valid_fmt(source) == SOF_IPC_FRAME_S16_LE) ? 4 : 2; #endif - /*There is no limit for frame number, so both source and sink set it to be 1*/ - const uint32_t frame_align_req = 1; + const uint32_t frame_align_req = (uint32_t)(n / gcd(n, channels)); audio_stream_set_align(byte_align, frame_align_req, source); - audio_stream_set_align(byte_align, frame_align_req, sink); } /** @@ -682,7 +700,7 @@ static int volume_prepare(struct processing_module *mod, ret = volume_peak_prepare(cd, mod); - volume_set_alignment(&sourceb->stream, &sinkb->stream); + volume_set_alignment(&sourceb->stream); /* get sink period bytes */ sink_period_bytes = audio_stream_period_bytes(&sinkb->stream, diff --git a/src/include/sof/audio/audio_stream.h b/src/include/sof/audio/audio_stream.h index 9703ec9cadea..4fe97cda55a9 100644 --- a/src/include/sof/audio/audio_stream.h +++ b/src/include/sof/audio/audio_stream.h @@ -591,9 +591,9 @@ audio_stream_avail_frames(const struct audio_stream *source, } /** - * Computes maximum number of frames aligned that can be copied from - * source buffer to sink buffer, verifying number of available source - * frames vs. free space available in sink. + * Computes maximum number of frames aligned with source align criteria + * that can be copied from source buffer to sink buffer, verifying number + * of available source frames vs. free space available in sink. * @param source Buffer of source. * @param sink Buffer of sink. * @return Number of frames. @@ -602,14 +602,45 @@ static inline uint32_t audio_stream_avail_frames_aligned(const struct audio_stream *source, const struct audio_stream *sink) { - uint32_t src_frames = (audio_stream_get_avail_bytes(source) >> - source->runtime_stream_params.align_shift_idx) * - source->runtime_stream_params.align_frame_cnt; - uint32_t sink_frames = (audio_stream_get_free_bytes(sink) >> - sink->runtime_stream_params.align_shift_idx) * - sink->runtime_stream_params.align_frame_cnt; + int src_frames = audio_stream_get_avail_frames(source); + int sink_frames = audio_stream_get_free_frames(sink); + int n = MIN(src_frames, sink_frames); - return MIN(src_frames, sink_frames); + return (uint32_t)((n * audio_stream_frame_bytes(source) >> + source->runtime_stream_params.align_shift_idx) * + source->runtime_stream_params.align_frame_cnt); +} + +/** + * Rounds down a frame count to meet the alignment constraint of the stream. + * @param stream Audio stream with alignment requirements set. + * @param frames Frame count to round down. + * @return Largest aligned frame count less than or equal to frames. + */ +static inline uint32_t audio_stream_align_frames_round_down(const struct audio_stream *stream, + uint32_t frames) +{ + uint16_t align = stream->runtime_stream_params.align_frame_cnt; + + return (frames / align) * align; +} + +/** + * Rounds up a frame count to meet the alignment constraint of the stream. + * @param stream Audio stream with alignment requirements set. + * @param frames Frame count to round up. + * @return Smallest aligned frame count greater than or equal to frames. + */ +static inline uint32_t audio_stream_align_frames_round_up(const struct audio_stream *stream, + uint32_t frames) +{ + uint16_t align = stream->runtime_stream_params.align_frame_cnt; + uint32_t aligned_frames = (frames / align) * align; + + if (aligned_frames < frames) + aligned_frames += align; + + return aligned_frames; } /** diff --git a/src/include/sof/common.h b/src/include/sof/common.h index 4bb279b039aa..28c49644fd62 100644 --- a/src/include/sof/common.h +++ b/src/include/sof/common.h @@ -223,6 +223,9 @@ # define SOF_FRAME_BYTE_ALIGN 4 #endif +/* Default frames count align is one */ +#define SOF_FRAME_COUNT_ALIGN 1 + #ifndef __GLIBC_USE #define __GLIBC_USE(x) 0 #endif