Skip to main content
Every SDK object that takes audio is stateful over time. A processor’s enhancement, a VAD’s speech history, and an analyzer’s rolling window all depend on the blocks you passed before. This page covers how that state is scoped, how to clear it, and which calls are safe on an audio thread.

One object per stream

State belongs to the object, not to the model. Create one processor, VAD, or collector and analyzer pair per stream, pass that stream’s blocks to it in order, and reuse the same model handle across all of them. Interleaving two streams through one object mixes their history and produces unstable output. This is also why the two sides of a call, or the channels of a multi-channel input that represent independent streams, each need their own object. See Audio Format.

Resetting state

Reset clears the internal buffers and history of one object while keeping its audio configuration. The object stays initialized, so you can continue processing immediately afterwards without reinitializing. Call reset when the audio you are about to pass is not a continuation of the audio you passed before:
  • The stream was interrupted, or a caller reconnected
  • You are seeking in a file or a recording
  • You are reusing the object for a new call or a new stream
  • A long gap in the audio makes the previous content irrelevant
Skipping the reset leaves the object convolving new audio with unrelated history, which causes artifacts in enhanced output and mispredictions in the VAD and the analyzer.
Resetting is per object. If you run enhancement, VAD, and analysis side by side on one stream, reset all of them when that stream is interrupted.
Reset is not a replacement for reinitialization. Changing the sample rate or the maximum block size requires initializing the object again, which allocates memory and must not happen on a real-time audio thread. See Block size.

Real-time safety

The audio path is designed to run inside a real-time callback. Setup, analysis, and anything that talks to our backend is not.
The analyzer is the one that catches people out. Analysis models cost far more than a real-time audio block, which is exactly why the collector and the analyzer are separate objects. See Real-Time Analysis.
Each object is also single-threaded with respect to itself: do not call process on one processor from two threads at once. Parallelize across streams with one object per stream instead. See Performance.

Contexts

Control and query APIs live on a separate context handle rather than on the audio object itself, so they can be used from a different thread than the one running audio:
Create a context once during setup and keep it for as long as you need it. In C, contexts are independent handles: aic_processor_context_destroy does not destroy the processor, and a context may be destroyed before or after the object it controls, in any order.