Skip to main content
Skip table of contents

Pipeline - Android

The pipeline manages a data flow from a single producer through a series of modifiers to one or more consumers. It consists of:

  • One Producer: Responsible for generating data buffers and driving the pipeline execution. The producer thread is where dispatchBuffer() is called, initiating the processing chain.

  • Multiple Modifiers: Applied sequentially in the order they were added to the pipeline. Each modifier processes data in synchronous mode, executing in the same thread as the producer.

  • Multiple Consumers: Executed in the order they were added. Consumers can run either in synchronous mode, in the producer’s thread, or in asynchronous mode, in which case they must make a copy of the buffer to prevent concurrency issues. Consumers only start processing when the first buffer is received. If the pipeline is started but no audio is ever dispatched, consumers remain inactive, and no buffer—empty or otherwise—needs to be sent.

The pipeline has direct control only over the producer. For modifiers and consumers, it simply invokes their processing callbacks in the proper order and execution mode, without managing their internal state or execution details.

Asynchronous Mode

In asynchronous mode, the pipeline operates as a non-blocking state machine, allowing other tasks to run concurrently while audio processing continues in the background.

image-20250813-105622.png

Starting the pipeline

When pipeline.start() is called, the system first invokes the producer’s open() (if not already open), which in turn calls the specific implementation openImpl() to transition from Closed to Opened. Next, it calls start(), which triggers startImpl() to move the pipeline to the Started state. startImpl() is responsible for updating the state, either synchronously or asynchronously.

Pausing and resuming

From the Started state, calling pipeline.pause() triggers the producer’s pause(), which calls pauseImpl(), transitioning the pipeline to the Paused state. To resume processing, pipeline.resume() calls resume(), which triggers resumeImpl() and returns the pipeline to the Started state. Both pauseImpl() and resumeImpl() are responsible for updating the state, either synchronously or asynchronously.

Stopping and closing

Calling pipeline.stop() from Started or Paused invokes the producer’s stop(), which calls stopImpl() to update the state back to Opened. From there, pipeline.close() triggers the producer’s close(), which calls closeImpl() to move the pipeline to the Closed state and release all resources.

Idle state

The producer may remain in the Starting state until stop() is called. If the producer finishes its task beforehand, it can enter the Idle state. In this state, calls to pipeline.stop() or pipeline.start() will typically not invoke stopImpl() or startImpl(). The producer can decide to return to the Started state if an event occurs that requires it to resume processing.

This mode enables fine-grained control over processing without blocking the calling thread, while strictly enforcing the defined state transitions.

Synchronous mode:

In synchronous mode, the audio processing pipeline executes in a blocking manner, meaning the calling thread is held until the entire process has completed. This ensures that processing tasks run in a predictable, step-by-step sequence without overlapping execution. When pipeline.run() is called, the system automatically manages the producer’s lifecycle by invoking the producer’s open(), run(), and close() methods in that exact order. If an error occurs at any stage, the operation is immediately halted and an exception is thrown, allowing for direct error handling by the caller.

image-20250813-152826.png
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.