Accessing Ecasound Audio Sample Buffers in C++

Direct access to internal audio sample buffers in Ecasound is achieved by working directly with the core C++ multimedia classes rather than the high-level control interfaces. By extending the CHAIN_OPERATOR or AUDIO_IO base classes, developers can intercept the signal graph and manipulate Ecasound’s internal SAMPLE_BUFFER objects. This architecture grants real-time access to raw audio sample arrays represented as native floating-point pointers, bypassing the IPC overhead of the standard Ecasound Control Interface (ECA-CI).

The SAMPLE_BUFFER Architecture

At the heart of Ecasound’s internal processing is the SAMPLE_BUFFER class. Ecasound processes audio in discrete chunks determined by the engine's buffer size. Within SAMPLE_BUFFER, audio is represented using the internal sample_t type, which is typically a 32-bit single-precision float (float) or 64-bit double depending on compilation flags.

Rather than exposing raw global memory, SAMPLE_BUFFER manages multi-channel audio data either as interleaved or non-interleaved channel vectors. To retrieve the memory location of raw samples:

Implementing Direct Access via CHAIN_OPERATOR

The primary mechanism to inspect or modify buffers directly is to implement a custom plugin by subclassing CHAIN_OPERATOR. Chain operators are execution units inserted into Ecasound signal chains.

  1. Subclassing: A C++ class inherits from CHAIN_OPERATOR (defined in libcasound).
  2. Overriding process(): The engine invokes the operator’s process() method on every iteration of the processing loop.
  3. Retrieving the Buffer: Inside process(), the operator accesses the chain's active buffer via the protected member pointer chain_buffer or by receiving a direct reference to the current SAMPLE_BUFFER.
  4. Pointer Arithmetic: The developer calls chain_buffer->channel_data(ch) to acquire the underlying sample_t* pointer for each active channel. From there, standard pointer operations or SIMD vector instructions can be used directly on the audio frames.

Implementing Custom Audio Sources or Sinks via AUDIO_IO

For stream endpoints that generate or consume audio directly from memory, the AUDIO_IO base class is used. Inheriting from AUDIO_IO allows developers to bypass disk or ALSA/JACK subsystems:

Concurrency and Performance Implications

Ecasound’s direct C++ API executes custom CHAIN_OPERATOR and AUDIO_IO code directly inside the audio engine’s real-time execution thread. Direct pointer access to SAMPLE_BUFFER memory eliminates dynamic allocation and data copying between buffers. However, because operations run synchronously within the real-time loop, any code accessing these raw buffers must remain deterministic, non-blocking, and free of system calls that could trigger buffer underruns or dropouts.