module: volume: Rework module to use sink/source api#10959
Conversation
Add a new header file panic.h that defines an assert() macro for runtime assertions. This macro is used by inline static functions in module api header files. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Add two inline utility functions for calculating the number of samples to the end of a circular buffer: cir_buf_samples_to_wrap_s16() for 16-bit samples and cir_buf_samples_to_wrap_s32() for 32-bit samples. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Introduce two new structures cir_buf_source and cir_buf_sink. The cir_buf_source structure provides a read-only view of source data in a circular buffer, with const pointers. The cir_buf_sink structure provides a writable view of sink data in a circular buffer. Both structures include pointers for buffer start, end, and current position. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Introduce functions to calculate aligned frames for sink and source api. Add sink_get_free_frames_aligned() to compute free aligned frames in a sink. Add source_get_aligned_frames_available() to compute aligned available frames in a source. Add source_sink_avail_frames_aligned to determine the maximum number of aligned frames that can be processed between a source and a sink. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Move circular buffer helper functions cir_buf_samples_without_wrap_s32() and cir_buf_wrap() to a public module api header. Introduce a new cir_buf_samples_without_wrap_s16() variant that returns the number of samples without buffer wrap for s16 data. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
…dling Introduce cir_buf_bytes_without_wrap_rewind() to calculate the number of bytes to rewind in a circular buffer from the current pointer to the buffer start. This function ensures proper handling of backward reads. Add cir_buf_rewind_wrap() to verify and adjust pointers when rewinding past the start of a circular buffer. This function wraps the pointer to the buffer's end if necessary, ensuring correct behavior. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Add source_align_frames_round_up() and source_align_frames_round_nearest() helpers based on existing audio_stream_* alignment utilities, adapting them to operate on source api. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Rework the volume 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>
There was a problem hiding this comment.
Pull request overview
This PR refactors the volume processing module to use the sink/source API (buffer acquire/commit via sof_source / sof_sink) rather than the legacy input/output stream buffer API, as a step toward the pipeline 2.0 transition.
Changes:
- Update volume processing entrypoints to acquire source/sink buffers once per period and commit via sink/source APIs.
- Rework volume DSP backends (generic + HiFi3/4/5, with and without peakvol) to operate on circular-buffer “views” instead of stream buffer structs.
- Add/adjust sink/source alignment helpers and circular buffer utilities to support the new processing flow.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| test/cmocka/src/audio/volume/volume_process.c | Adjust unit test harness to call volume processing via circular-buffer views and initialize channel count. |
| src/include/sof/audio/sink_source_utils.h | Add helper to compute aligned available frames across source+sink. |
| src/include/sof/audio/audio_stream.h | Remove some circular-buffer helper inlines from SOF audio_stream header. |
| src/include/module/audio/source_api.h | Add aligned-frames helpers and frame-rounding helpers for sources. |
| src/include/module/audio/sink_api.h | Add aligned free-frames helper for sinks. |
| src/include/module/audio/audio_stream.h | Add circular buffer view structs and wrap/rewind/sample helper inlines for module-facing code. |
| src/audio/volume/volume.h | Change processing function typedefs to accept circular-buffer views and pass channel count explicitly for ZC. |
| src/audio/volume/volume.c | Rework prepare/process to use sink/source APIs and new alignment helpers; update ZC logic to use views. |
| src/audio/volume/volume_hifi5.c | Update HiFi5 backend to process via circular-buffer views. |
| src/audio/volume/volume_hifi5_with_peakvol.c | Update HiFi5+peakvol backend to process via circular-buffer views. |
| src/audio/volume/volume_hifi4.c | Update HiFi4 backend to process via circular-buffer views. |
| src/audio/volume/volume_hifi4_with_peakvol.c | Update HiFi4+peakvol backend to process via circular-buffer views. |
| src/audio/volume/volume_hifi3.c | Update HiFi3 backend to process via circular-buffer views. |
| src/audio/volume/volume_hifi3_with_peakvol.c | Update HiFi3+peakvol backend to process via circular-buffer views. |
| src/audio/volume/volume_generic.c | Update generic backend to process via circular-buffer views. |
| src/audio/volume/volume_generic_with_peakvol.c | Update generic+peakvol backend to process via circular-buffer views. |
| lmdk/include/rtos/panic.h | Add LMKD-specific panic/assert header to satisfy new module-header dependency on <rtos/panic.h>. |
| static inline size_t source_sink_avail_frames_aligned(struct sof_source *source, | ||
| struct sof_sink *sink) | ||
| { | ||
| return MIN(source_get_aligned_frames_available(source), sink_get_free_frames_aligned(sink)); | ||
| } |
| return frames; | ||
|
|
||
| aligned_frames = ROUND_DOWN(frames, align); | ||
| if (aligned_frames < frames) | ||
| aligned_frames += align; |
|
|
||
| if (!align) | ||
| return frames; | ||
|
|
||
| return ROUND_DOWN(frames + (align >> 1), align); | ||
| } |
| if (sink_get_free_size(sinks[0]) < sink_period_bytes) { | ||
| comp_err(dev, "sink buffer size %d is insufficient < %d", | ||
| audio_stream_get_size(&sinkb->stream), sink_period_bytes); | ||
| sink_get_free_size(sinks[0]), sink_period_bytes); | ||
| ret = -ENOMEM; |
| /* runtime assertion */ | ||
| #define assert(x) do {if (!(x)) while (1);} while (0) | ||
|
|
| */ | ||
| struct cir_buf_sink { | ||
| void *buf_start; /**< Start address of the circular buffer. */ | ||
| void *buf_end; /**< End address of the circular buffer. */ |
There was a problem hiding this comment.
can the above two be const too? They shouldn't be used for writing, only the ptr below?
| /** | ||
| * @brief Calculates numbers of s16 samples to buffer wrap when reading stream | ||
| * backwards from current sample pointed by ptr towards begin. | ||
| * @param ptr Read or write pointer og circular buffer. |
| { | ||
| int to_end = (const int16_t *)buf_end - (const int16_t *)ptr; | ||
|
|
||
| assert((intptr_t)buf_end >= (intptr_t)ptr); |
There was a problem hiding this comment.
assert() only works in debug builds, is that enough or should this be checked always?
| */ | ||
| static inline int cir_buf_bytes_without_wrap_rewind(const void *ptr, const void *buf_start) | ||
| { | ||
| assert((intptr_t)ptr >= (intptr_t)buf_start); |
There was a problem hiding this comment.
void * cannot be compared directly?
|
|
||
| assert((intptr_t)ptr >= (intptr_t)buf_start); | ||
|
|
||
| return (void *)ptr; |
There was a problem hiding this comment.
ouch. no. we should never ("almost never") drop const
| uint16_t align = source->audio_stream_params->align_frame_cnt; | ||
| uint32_t aligned_frames; | ||
|
|
||
| if (!align) |
|
|
||
| aligned_frames = ROUND_DOWN(frames, align); | ||
| if (aligned_frames < frames) | ||
| aligned_frames += align; |
| ae_f16x4 *out = (ae_f16x4 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) | ||
| + bsink->size); | ||
| const int channels_count = audio_stream_get_channels(sink); | ||
| ae_f16x4 *in = (void *)source->ptr; |
There was a problem hiding this comment.
const? maybe also check the rest of in pointers - this one just occurred to me
Rework the volume to only use the sink/source api to prepare sof for the full transition to pipeline 2.0.