Audio Processing Components & Modules API#

In Sound Open Firmware (SOF), all audio processing components—including volume controllers, mixers, equalizers (EQ FIR/IIR), dynamic range compressors (DRC), sample rate converters (SRC/ASRC), crossover filters, and smart amplifiers—are architected as processing modules.

Modules can be built statically into the base firmware binary or compiled and loaded dynamically at runtime as relocatable ELF extensions using the Zephyr Loadable Extension (LLEXT) framework.

Architecture & Module Adapter Layer#

The pipeline execution graph decouples pipeline orchestration from signal processing algorithms through the Module Adapter layer:

+-------------------------------------------------------------------------+
|                             Pipeline Graph                              |
|              pipeline_create() / pipeline_connect() / walk_op           |
+------------------------------------+------------------------------------+
                                     | comp_ops (params, prepare, copy)
                                     v
+-------------------------------------------------------------------------+
|                        Module Adapter Component                         |
|                      DECLARE_MODULE_ADAPTER(name)                       |
|  - Adapts comp_ops into struct module_interface calls                   |
|  - Binds comp_buffer streaming queues to sof_source and sof_sink APIs   |
|  - Handles parameter fragmentation (large configuration blobs)          |
+------------------------------------+------------------------------------+
                                     | module_interface
                                     v
+-------------------------------------------------------------------------+
|                    Audio Processing Algorithm Module                    |
|     (Volume, Mixer, EQ FIR/IIR, DRC, SRC, ASRC, Smart Amp, etc.)       |
|  - init() / prepare() / process() / apply_config() / free()            |
|  - Pulls audio from struct sof_source                                   |
|  - Pushes audio to struct sof_sink                                      |
+------------------------------------+------------------------------------+
                                     | System Services
                                     v
+-------------------------------------------------------------------------+
|                      Host & RTOS System Services                        |
|          (Dynamic Heap Memory, Timers, Tracing, UUID, Math)             |
+-------------------------------------------------------------------------+

Processing Component Catalog#

SOF provides an extensive suite of built-in processing modules optimized for low-latency DSP execution:

Component

Processing Mode

Hardware Acceleration

Primary Function

Volume

Source/Sink (LL / DP)

SIMD HiFi3 / HiFi4 / HiFi5

Smooth logarithmic/linear volume ramp, mute, gain attenuation, zero-crossing detection.

Mixer / Mixout

Source/Sink (LL)

Vectorized summation

Multi-channel audio stream summation, channel splitting, and matrix routing.

EQ (FIR & IIR)

Source/Sink (LL / DP)

DF2T biquad SIMD

Parametric equalization, shelving filters, high/low-pass filters, and speaker tuning.

DRC & Multiband

Source/Sink (LL / DP)

Vectorized RMS detector

Dynamic range compression, peak limiting, soft/hard knee thresholds, and multiband crossover.

SRC & ASRC

Source/Sink (LL / DP)

Polyphase FIR filterbank

Synchronous and asynchronous sample rate conversion with fractional drift compensation.

Crossover

Source/Sink (LL / DP)

4th-order Linkwitz-Riley (LR4)

Multi-way acoustic frequency splitting (woofer, midrange, tweeter).

Smart Amp

Source/Sink (LL / DP)

Thermal/Excursion observer

Speaker transducer protection, coil temperature estimation, and IV-sense feedback.

Sound Dose

Source/Sink (LL / DP)

A-weighted filterbank

Real-time acoustic energy integration complying with IEC 62368-1 and EN 50332 standards.

KPB / MFCC

Source/Sink (LL / DP)

FFT & Mel filterbank

Keyword pre-roll circular buffering and Mel-frequency cepstral coefficient feature extraction.

Module Lifecycle & Interface Contracts#

All audio modules implement struct module_interface:

  1. Initialization (`init`): Invoked when the module adapter component is instantiated (.new()). Allocates private algorithm state memory and registers default parameters. Typically marked __cold.

  2. Stream Preparation (`prepare`): Called when stream parameters are configured (.prepare()). Validates sample rates, channel counts, and buffer formats across all attached sources and sinks.

  3. Audio Block Processing (`process`): The primary execution callback running in the real-time processing loop. Consumes audio samples from source endpoint buffers and emits processed audio samples into sink endpoint buffers.

  4. Dynamic Configuration (`set_configuration` / `get_configuration`): Transfers runtime parameter blobs (filter coefficients, DRC curves, tuning parameters) from the host via IPC. Supports multi-fragment chunking for large configuration structures.

  5. Reset & Teardown (`reset`, `free`): Restores algorithm states to initial default settings and frees runtime buffers.

Streaming Endpoints: Source & Sink APIs#

Modules consume audio data exclusively via struct sof_source and produce audio data via struct sof_sink:

  • Source API (`source_get_data()`, `source_release_data()`): Allows the module to request a contiguous block of audio samples from the input stream. The underlying source handles circular buffer rollover, cache invalidation, and pointer advance.

  • Sink API (`sink_get_buffer()`, `sink_commit_buffer()`): Provides a destination memory region for the module to store processed samples. The sink commits the written bytes, flushes cache lines, and advances write pointers.

Dynamic LLEXT Loading & Identification#

Dynamic processing modules declare their ABI version, format compatibility tag, and unique UUID using standard SOF registration macros:

  • SOF_DEFINE_UUID(): Associates a 128-bit RFC 4122 UUID with the module driver.

  • struct sof_module_api_build_info: Encodes module build timestamp, git hash, and API version.

  • SOF_LLEXT_EXPORT_SYMBOL(): Exposes module entry points for dynamic symbol resolution.

C API Reference#

group Audio Processing Components & Module Interface

Unified interface contracts, lifecycle callbacks, and streaming endpoints for built-in audio components and dynamic LLEXT processing modules (Volume, Mixer, EQ, DRC, SRC, etc.).

UUID API specification.

Defines

UUID_SIZE#

UUID is 16 bytes long.

UUID_NAME_MAX_LEN#

UUID name string max length in bytes, including null termination.

_UUID_INIT(va, vb, vc, d0, d1, d2, d3, d4, d5, d6, d7)#
_UUID(uuid_name)#
_RT_UUID(uuid_name)#
_DEF_UUID(entity_name, uuid_name, initializer)#
SOF_DEFINE_UUID(entity_name, uuid_name, va, vb, vc, vd0, vd1, vd2, vd3, vd4, vd5, vd6, vd7)#

Declares runtime UUID (aaaaaaaa-bbbb-cccc-d0d1-d2d3d4d5d6d7) and name.

UUID value from variables declared with this macro are accessible in runtime code - to dereference use SOF_RT_UUID()

Parameters:
  • entity_name – Name of the object pinted by the software tools.

  • uuid_name – Uuid symbol name used with SOF_UUID() and SOF_RT_UUID().

  • va – aaaaaaaa value.

  • vb – bbbb value.

  • vc – cccc value.

  • vd0 – d0 value (note how d0 and d1 are grouped in formatted uuid)

  • vd1 – d1 value.

  • vd2 – d2 value.

  • vd3 – d3 value.

  • vd4 – d4 value.

  • vd5 – d5 value.

  • vd6 – d6 value.

  • vd7 – d7 value.

SOF_REG_UUID(name)#

Get UUID value sourced from the fixed SOF registry.

The ID value is sourced by name from the uuid-registry.txt file distributed with the source tree.

Parameters:
  • name – Name of the UUID, must match an entry in uuid-registry.txt

SOF_DEFINE_REG_UUID(name)#

Defines UUID sourced from the fixed SOF registry.

As for SOF_DEFINE_UUID(), but the ID value is sourced by name from the uuid-registry.txt file distributed with the source tree. The string name field will be identical with the name passed (which is passed as a symbol!), runtime symbol (e.g. the “uuid_name” argument to SOF_DEFINE_UUID()) will be the same, postfixed with a “_uuid”.

Parameters:
  • name – Name of the UUID, must match an entry in uuid-registry.txt

SOF_UUID(uuid_name)#

Creates local unique 32-bit representation of UUID structure.

In Zephyr builds, this has the same address as the result of SOF_RT_UUID, but has type of “struct sof_uuid *” and not “struct

sof_uid_record *”

Parameters:
  • uuid_name – UUID symbol name declared with DECLARE_SOF_UUID() or DECLARE_SOF_RT_UUID().

SOF_RT_UUID(uuid_name)#

Dereference unique 32-bit representation of UUID structure in runtime.

Parameters:
  • uuid_name – UUID symbol name declared with DECLARE_SOF_RT_UUID().

Enums

enum sof_audio_buffer_state#

Define states of an audio stream buffer connecting two components.

This enum represents the lifecycle of an audio stream, including its initialization, readiness, and end-of-stream handling. It is used to track and manage the state transitions of the stream during audio processing.

Values:

enumerator AUDIOBUF_STATE_INITIAL#
enumerator AUDIOBUF_STATE_READY#
enumerator AUDIOBUF_STATE_END_OF_STREAM#
enumerator AUDIOBUF_STATE_END_OF_STREAM_FLUSH#

Functions

static inline size_t circ_buf_frames_without_wrap(const void *began, const void *end, size_t sample_bytes, size_t channels)#

Number of whole frames available before a circular buffer wraps.

Computes (end - began) / channels expressed in frames. The pointer distance is evaluated in bytes so the helper works for any sample width.

Parameters:
  • began – current position in the circular buffer

  • end – one past the last sample of the circular buffer

  • sample_bytes – size of a single sample in bytes (2 for s16, 4 for s32)

  • channels – number of channels, i.e. samples per frame

Returns:

number of frames that can be processed without wrapping

static inline size_t cir_buf_samples_to_wrap_s16(const int16_t *ptr, const int16_t *buf_start, size_t buf_samples)#

Calculates numbers of s16 samples to buffer wrap.

Parameters:
  • ptr – Read or write pointer of circular buffer.

  • buf_start – Start address of circular buffer.

  • buf_samples – Total size of circular buffer in samples.

Returns:

Number of samples to buffer wrap.

static inline size_t cir_buf_samples_to_wrap_s32(const int32_t *ptr, const int32_t *buf_start, size_t buf_samples)#

Calculates numbers of s32 samples to buffer wrap.

Parameters:
  • ptr – Read or write pointer of circular buffer.

  • buf_start – Start address of circular buffer.

  • buf_samples – Total size of circular buffer in samples.

Returns:

Number of samples to buffer wrap.

static inline size_t cir_buf_samples_without_wrap_s16(const void *ptr, const void *buf_end)#

Calculates numbers of s16 samples to buffer wrap when reading a circular buffer forward from current pointer towards the buffer end.

Parameters:
  • ptr – Read or write pointer of circular buffer.

  • buf_end – End address of circular buffer.

Returns:

Number of s16 samples between the pointer and the buffer end.

static inline size_t cir_buf_samples_without_wrap_s32(const void *ptr, const void *buf_end)#

Calculates numbers of s32 samples to buffer wrap when reading a circular buffer forward from current pointer towards the buffer end.

Parameters:
  • ptr – Read or write pointer of circular buffer.

  • buf_end – End address of circular buffer.

Returns:

Number of s32 samples between the pointer and the buffer end.

static inline size_t cir_buf_bytes_without_wrap(const void *ptr, const void *buf_end)#

Calculates number of bytes to buffer wrap when reading a circular buffer forward from current pointer towards the buffer end.

Parameters:
  • ptr – Read or write pointer of circular buffer.

  • buf_end – End address of circular buffer.

Returns:

Number of bytes between the pointer and the buffer end.

static inline void *cir_buf_wrap(const void *ptr, const void *buf_addr, const void *buf_end)#

Verifies the pointer and performs rollover when reaching the end of the circular buffer.

Parameters:
  • ptr – Read pointer that may have moved past the buffer end.

  • buf_addr – Start address of the circular buffer.

  • buf_end – End address of the circular buffer.

Returns:

Pointer, adjusted if necessary.

static inline const void *source_cir_buf_wrap(const void *ptr, const void *buf_addr, const void *buf_end)#

Verifies a read pointer and performs rollover when reaching the end of the circular buffer.

Parameters:
  • ptr – Read pointer that may have moved past the buffer end.

  • buf_addr – Start address of the circular buffer.

  • buf_end – End address of the circular buffer.

Returns:

Pointer, adjusted if necessary.

static inline size_t cir_buf_bytes_without_wrap_rewind(const void *ptr, const void *buf_start)#

Calculates number of bytes to buffer wrap when reading a circular buffer backwards from current pointer towards the buffer start.

Parameters:
  • ptr – Read or write pointer of circular buffer.

  • buf_start – Start address of circular buffer.

Returns:

Number of bytes between the buffer start and the pointer.

static inline const void *source_cir_buf_rewind_wrap(const void *ptr, const void *buf_start, const void *buf_end)#

Verifies the pointer and performs rollover when reading a read-only circular buffer backwards past its start address.

Parameters:
  • ptr – Pointer that may have moved below the buffer start.

  • buf_start – Start address of the circular buffer.

  • buf_end – End address of the circular buffer.

Returns:

Pointer, wrapped to the end of the buffer if necessary.

void sink_init(struct sof_sink *sink, const struct sink_ops *ops, struct sof_audio_stream_params *audio_stream_params)#

Initialize sink API structure before any operation.

NOTE: audio_stream_params must be accessible by the caller core, and the implementation must ensure coherent access to the parameters (e.g. for a cross-core shared queue, it must be located in non-cached memory).

Parameters:
  • sink – [inout] Pointer to sink structure.

  • ops – [in] Pointer to API operations vtable.

  • audio_stream_params – [in] Pointer to structure with audio parameters.

size_t sink_get_num_of_processed_bytes(struct sof_sink *sink)#

Get total number of bytes processed by the sink (committed by sink_commit_buffer()).

Parameters:
  • sink – [in] Pointer to sink structure.

Returns:

Total number of processed bytes.

void sink_reset_num_of_processed_bytes(struct sof_sink *sink)#

Reset counter of total processed bytes to zero.

Parameters:
  • sink – [inout] Pointer to sink structure.

bool sink_get_overrun(struct sof_sink *sink)#

Check if buffer overrun is permitted on sink stream.

Parameters:
  • sink – [in] Pointer to sink structure.

Returns:

True if overrun is permitted by audio stream params, false otherwise.

void sink_set_min_free_space(struct sof_sink *sink, size_t min_free_space)#

Set minimum free space required in sink buffer.

Parameters:
  • sink – [inout] Pointer to sink structure.

  • min_free_space – [in] Minimum free space in bytes.

void source_init(struct sof_source *source, const struct source_ops *ops, struct sof_audio_stream_params *audio_stream_params)#

Initialize source API structure before any operation.

NOTE: audio_stream_params must be accessible by the caller core, and the implementation must ensure coherent access to the parameters (e.g. for a cross-core shared queue, it must be located in non-cached memory).

Parameters:
  • source – [inout] Pointer to source structure.

  • ops – [in] Pointer to API operations vtable.

  • audio_stream_params – [in] Pointer to structure with audio parameters.

size_t source_get_num_of_processed_bytes(struct sof_source *source)#

Get total number of bytes processed by the source (freed by source_release_data()).

Parameters:
  • source – [in] Pointer to source structure.

Returns:

Total number of processed bytes.

void source_reset_num_of_processed_bytes(struct sof_source *source)#

Reset counter of total processed bytes to zero.

Parameters:
  • source – [inout] Pointer to source structure.

bool source_get_underrun(struct sof_source *source)#

Check if buffer underrun is permitted on source stream.

Parameters:
  • source – [in] Pointer to source structure.

Returns:

True if underrun is permitted by audio stream params, false otherwise.

uint32_t source_get_id(struct sof_source *source)#

Get unique stream identifier for source.

Parameters:
  • source – [in] Pointer to source structure.

Returns:

Stream identifier.

int source_set_frm_fmt(struct sof_source *source, enum sof_ipc_frame frm_fmt)#

Set audio frame format for source.

Parameters:
  • source – [inout] Pointer to source structure.

  • frm_fmt – [in] Audio frame format.

Returns:

0 on success, negative error code on failure.

int source_set_valid_fmt(struct sof_source *source, enum sof_ipc_frame valid_sample_fmt)#

Set valid sample format for source.

Parameters:
  • source – [inout] Pointer to source structure.

  • valid_sample_fmt – [in] Valid sample format.

Returns:

0 on success, negative error code on failure.

int source_set_rate(struct sof_source *source, unsigned int rate)#

Set sample rate for source.

Parameters:
  • source – [inout] Pointer to source structure.

  • rate – [in] Sample rate in Hz.

Returns:

0 on success, negative error code on failure.

int source_set_channels(struct sof_source *source, unsigned int channels)#

Set channel count for source.

Parameters:
  • source – [inout] Pointer to source structure.

  • channels – [in] Number of audio channels.

Returns:

0 on success, negative error code on failure.

int source_set_underrun(struct sof_source *source, bool underrun_permitted)#

Configure whether underrun is permitted on source.

Parameters:
  • source – [inout] Pointer to source structure.

  • underrun_permitted – [in] True if underrun is permitted, false otherwise.

Returns:

0 on success, negative error code on failure.

int source_set_buffer_fmt(struct sof_source *source, uint32_t buffer_fmt)#

Set buffer format for source.

Parameters:
  • source – [inout] Pointer to source structure.

  • buffer_fmt – [in] Buffer format identifier.

Returns:

0 on success, negative error code on failure.

void source_set_min_available(struct sof_source *source, size_t min_available)#

Set minimum available data requirement in bytes.

Parameters:
  • source – [inout] Pointer to source structure.

  • min_available – [in] Minimum available bytes.

int source_set_params(struct sof_source *source, struct sof_ipc_stream_params *params, bool force_update)#

Configure initial set of audio parameters.

Parameters:
  • source – [inout] Pointer to source structure.

  • params – [in] Audio stream parameters.

  • force_update – [in] True to force parameters override.

Returns:

0 on success, negative error code on failure.

int source_set_alignment_constants(struct sof_source *source, const uint32_t byte_align, const uint32_t frame_align_req)#

Set byte and frame alignment constants for source stream.

Sets frame_align_shift and frame_align of stream according to byte_align and frame_align_req requirements. Once the channel number and frame size are determined, the frame_align and frame_align_shift are determined too. These features are used by audio_stream_get_avail_frames_aligned() to calculate available frames.

Note

This must be called in component prepare or param functions only once after channel count and frame size are known and before stream copying begins. If omitted or called late, aligned availability can evaluate to zero and no data will be copied.

Parameters:
  • source – [inout] Pointer to source structure.

  • byte_align – [in] Processing byte alignment requirement.

  • frame_align_req – [in] Processing frames alignment requirement.

Returns:

0 on success, negative error code on failure.

struct sof_audio_stream_params#
#include <src/include/module/audio/audio_stream.h>

set of parameters describing audio stream this structure is shared between audio_stream.h and sink/source interface TODO: compressed formats

Public Members

uint32_t id#
uint32_t pipeline_id#
enum sof_ipc_frame frame_fmt#

Sample data format.

enum sof_ipc_frame valid_sample_fmt#
uint32_t rate#

Number of data frames per second [Hz].

uint16_t channels#

Number of samples in each frame.

uint16_t align_frame_cnt#

align_frame_cnt indicates minimum number of frames that satisfies both byte align and frame align requirements.

E.g: Consider an algorithm that processes in blocks of 3 frames configured to process 16-bit stereo using xtensa HiFi3 SIMD. Therefore with 16-bit stereo we have a frame size of 4 bytes, and SIMD intrinsic requirement of 8 bytes(2 frames) for HiFi3 and an algorithim requirement of 3 frames. Hence the common processing block size has to align with frame(1), intrinsic(2) and algorithm (3) giving us an optimum processing block size of 6 frames.

uint16_t align_shift_idx#

the free/available bytes of sink/source right shift align_shift_idx, the result multiplied by align_frame_cnt is the frame count free/available that can meet the align requirement.

bool overrun_permitted#

indicates whether overrun is permitted

bool underrun_permitted#

indicates whether underrun is permitted

uint32_t buffer_fmt#

enum sof_ipc_buffer_format

uint16_t chmap[SOF_IPC_MAX_CHANNELS]#

channel map - SOF_CHMAP_

enum sof_audio_buffer_state state#

audio stream state

struct cir_buf_source#
#include <src/include/module/audio/audio_stream.h>

Read-only view of source data in a circular buffer.

Describes a contiguous fragment of a circular buffer obtained from the source API together with the buffer boundaries needed for wrap handling. All pointers are const because the source data must not be modified.

Public Members

const void *buf_start#

Start address of the circular buffer.

const void *buf_end#

End address of the circular buffer.

const void *ptr#

Current read pointer within the buffer.

struct cir_buf_sink#
#include <src/include/module/audio/audio_stream.h>

Writable view of sink data in a circular buffer.

Describes a contiguous fragment of a circular buffer obtained from the sink API together with the buffer boundaries needed for wrap handling.

Public Members

void *buf_start#

Start address of the circular buffer.

void *buf_end#

End address of the circular buffer.

void *ptr#

Current write pointer within the buffer.

struct sof_uuid#
#include <src/include/sof/lib/uuid.h>

UUID (Universally Unique IDentifier) structure.

Use DECLARE_SOF_UUID() to assigned UUID to the fw part (component implementation, dai implementation, …).

Use SOF_UUID() to store an address of declared UUID.

See existing implementation of components and dais for examples how to UUIDs are declared and assigned to the drivers to provide identification of the source for their log entries.

UUID for a new component may be generated with uuidgen Linux tool, part of the util-linux package.

FIXME: this struct scheme has an endianness bug. On BE systems, the same initialier for the a/b/c fields will produce different memory layout than on LE systems. Within C code, that’s fine, but when compared with external representations (c.f. topology) that pass UUIDs as a linear array of bytes, only one endianness will work. If SOF ever ships on a BE system all use of sof_uuid will need to be modified to byte swap the a/b/c values.

Some identifiers are taken from the module manifest. Since the module manifest structure (sof_man_module) is marked as packed, the pointer to the sof_uuid structure may not be properly aligned. To avoid possible problems with accessing fields of this structure from unaligned addresses, it has been marked as packed.

Public Members

uint32_t a#
uint16_t b#
uint16_t c#
uint8_t d[8]#
struct sof_uuid_entry#
#include <src/include/sof/lib/uuid.h>

Connects UUID with component description.

Declaration of this structure should be done by DECLARE_SOF_UUID(), then declaration will be part of .static_uuids section and SMEX tool use it during ldc file creation.

Public Members

struct sof_uuid id#
const char name[UUID_NAME_MAX_LEN]#