One object per stream
Create one processor, VAD or collector/analyzer pair per stream and pass its blocks in order. Objects can share a model handle, but each owns its processing state. Interleaving streams mixes their history and produces unstable output. Give each side of a call or other independent channel its own object. See audio format.Resetting state
Reset clears history and internal buffers while preserving audio configuration. The object stays initialized.
Reset at a discontinuity:
- 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
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.
Real-time safety
The native core audio path is designed for a real-time callback. The table describes core operations; language bindings and application code add their own allocation, locking and scheduling behavior. PythonProcessor.process() copies its input and creates an output array, so the native guarantee does not make the Python call allocation-free. Keep setup, analysis and network operations off a real-time callback.
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
Use a context handle to control and query an object from a different thread than the audio thread: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.
Ordering, cancellation and teardown
For asynchronous bindings, await each stream’s processing call before submitting its next frame. A per-instance lock prevents concurrent mutation; it does not promise that concurrently submitted frames execute in audio order. Use separate instances to parallelize independent streams. Keep queues bounded. Cancelling a Python await does not establish that already-running native work has stopped or that its state changes were rolled back. Stop admitting frames, resolve in-flight work and then reset, reinitialize or dispose of the stream. Prefer a new instance when the processing boundary is uncertain. Reset clears audio history; it does not create a new authorization session or reverseterminate_session(). Stop submitting audio before requesting termination. Processing may be disabled after the termination call returns, so its return is not permission to submit another frame. Termination and object destruction may block while session work drains, so perform them on a control thread. Stop refresh and analysis tasks during shutdown and release contexts according to your binding’s ownership rules.
For reconnects, choose one owner to coordinate stopping input, settling work, clearing each object’s state and restarting the warmup/sample counters. Avoid resetting while another application task is still submitting frames from the previous call.