aic-sdk - Rust Bindings for ai-coustics SDK
Rust wrapper for the ai-coustics Speech Enhancement SDK.
For comprehensive documentation, visit docs.ai-coustics.com.
[!NOTE] This SDK requires a license key. Generate your key at developers.ai-coustics.com.
[!WARNING] The bundled libraries were built with Rust
1.97.0-beta.6. Building your crate with that exact toolchain version fails to link, so use any other Rust version. This affects the default static linking only — thedynamic-linkingandruntime-linkingmodes are unaffected (see Linking the native SDK).
Installation
Add to your project:
Quick Start
use ;
// Embed model at compile time (or use Model::from_file to load at runtime)
static MODEL: &'static = include_model!;
Linking the native SDK
By default, aic-sdk-sys links the native AIC SDK statically. Two opt-in features link a shared libaic instead. They are mutually exclusive; enabling both (e.g. via --all-features) selects runtime-linking.
| Feature | Linking | How libaic is located |
|---|---|---|
| (default) | static, at build time | AIC_LIB_PATH directory, or downloaded with download-lib |
dynamic-linking |
dynamic, at build time | same to link; then OS loader search at run time |
runtime-linking |
dynamic, lazy on first use | OS loader search by name, or aic_sdk::load_library(path) |
In every mode, point the build at the SDK with AIC_LIB_PATH=/path/to/aic-sdk/lib, or enable download-lib to fetch it automatically:
AIC_SDK_LICENSE="…"
[!NOTE] The
dynamic-linkingandruntime-linkingmodes are not affected by the toolchain link issue in the warning above; it applies to default static linking only.
Finding the library at run time
With dynamic-linking and runtime-linking, the OS dynamic loader must locate libaic when the program runs — download-lib only covers build time. Point the loader at the SDK lib directory, ship the library next to the binary, or install it system-wide:
- Linux:
LD_LIBRARY_PATH=/path/to/aic-sdk/lib, or an rpath (RUSTFLAGS="-C link-arg=-Wl,-rpath,\$ORIGIN"+ shiplibaic.sobeside the binary). - macOS:
DYLD_LIBRARY_PATH,@rpath/@loader_path, or a bundle layout. - Windows: put
aic.dllnext to the.exeor onPATH(the build-time import libaic.liband the runtimeaic.dllmay be in different directories). - Android: package
libaic.so(arm64 only) into the APK underlib/arm64-v8a/.
runtime-linking loads libaic automatically on the first SDK call, by platform default name (libaic.so / libaic.dylib / aic.dll). To choose an exact file, call load_library first; if the library can't be found, that first call panics with a descriptive message:
unsafe // optional override
Usage
SDK Information
use aic_sdk;
// Get SDK version
println!;
// Get compatible model version
println!;
Loading Models
Download models and find available IDs at artifacts.ai-coustics.io.
Load from File
use Model;
let model = from_file?;
Embed at Compile Time
use ;
static MODEL: &'static = include_model!;
let model = from_buffer?;
Download from CDN
Enable the download-model feature:
use Model;
let model_path = download?;
let model = from_file?;
Model Information
// Get model ID
let model_id = model.id;
// Get optimal sample rate for the model
let optimal_rate = model.optimal_sample_rate;
// Get optimal frame count for a specific sample rate
let optimal_frames = model.optimal_num_frames;
Configuring the Processor
use ;
// Get optimal configuration for the model
let config = optimal
.with_num_channels
.with_allow_variable_frames;
println!; // ProcessorConfig { sample_rate: 48000, num_channels: 1, num_frames: 480, allow_variable_frames: false }
// Or create from scratch
let config = ProcessorConfig ;
// Processor needs to be initialized before processing
// Option 1: Create and initialize in one step
let processor = new?.with_config?;
// Option 2: Create first, then initialize separately
let mut processor = new?;
processor.initialize?;
OpenTelemetry
By default, processor telemetry follows the SDK environment configuration, such as
AIC_SDK_OTEL_ENABLE. Use OtelConfig when a single processor needs an explicit
telemetry setting or session ID.
use ;
let otel = with_session_id;
let processor = with_otel_config?
.with_config?;
Processing Audio
// Interleaved processing (channels interleaved in single buffer)
// Format: [l, r, l, r, ...]
let mut audio_buffer = vec!;
processor.process_interleaved?;
// Sequential processing (channels in sequence)
// Format: [l, l, ..., r, r, ...]
let mut audio_sequential = vec!;
processor.process_sequential?;
// Planar processing (separate buffer per channel)
// Format: [[l, l, ...], [r, r, ...]]
let mut audio = vec!;
processor.process_planar?;
Processor Context
The processor context provides thread-safe access to processor parameters and state. You can create multiple contexts and move them to any thread for concurrent parameter updates.
use ProcessorParameter;
// Get processor context
let proc_ctx = processor.processor_context;
// Get output delay in samples
let delay = proc_ctx.output_delay;
// Reset processor state (clears internal buffers)
proc_ctx.reset?;
// Set enhancement parameters
proc_ctx.set_parameter?;
proc_ctx.set_parameter?;
// Get parameter values
let level = proc_ctx.parameter?;
println!;
Voice Activity Detection (VAD)
The VAD context provides thread-safe access to VAD parameters and state. You can create multiple contexts and move them to any thread for concurrent parameter updates.
use VadParameter;
// Get VAD context from processor
let vad_ctx = processor.vad_context;
// Configure VAD parameters
vad_ctx.set_parameter?;
vad_ctx.set_parameter?;
vad_ctx.set_parameter?;
// Get parameter values
let sensitivity = vad_ctx.parameter?;
println!;
// Check for speech (after processing audio through the processor)
if vad_ctx.is_speech_detected
Working with the Analyzer
Instantiate an analyzer pair:
let = analyzer_pair?;
Initialize the collector, similar to the processor initialization
let config = optimal;
collector.initialize?;
Buffer the audio using the Collector::buffer_* APIs. They mirror the Processor::process_* APIs.
See the Processing Audio section for more details.
Analyze the buffered audio in a separate thread:
let result = analyzer.analyze_buffered?;
println!;
Async Processing
Enable the async feature to use [ProcessorAsync], which offloads
processing to a background thread pool and returns a future. The implementation
is runtime-agnostic and works on any executor (tokio, smol, async-std, ...).
The pool defaults to one thread per logical CPU; override with the
AIC_NUM_THREADS environment variable.
use ;
async
Examples
See the example files for complete working examples:
examples/basic_usage.rs- Basic usage exampleexamples/build-time-download- Download and embed models at compile-timeexamples/benchmark.rs- Run multiple processor instances concurrently until the real-time requirements are not metexamples/parallel_async.rs- Async processing withProcessorAsyncacross multiple instances (requiresasync)
Run examples with:
Documentation
- Full Documentation: docs.ai-coustics.com
- Rust API Reference: docs.rs/aic-sdk
- Available Models: artifacts.ai-coustics.io
License
This Rust wrapper is distributed under the Apache 2.0 license. The core C SDK is distributed under the proprietary AIC-SDK license.
Third-party notices
NOTICE.txt lists the third-party software distributed with the SDK, in two parts: the open-source code statically linked into the native libaic library, and the third-party Rust crates the bindings depend on. It is generated, not edited by hand. Regenerate with:
The libaic part is mirrored from the SDK release into aic-sdk-sys/NOTICE.libaic.txt and kept in sync by CI; update it from a release's NOTICE.txt whenever you bump aic-sdk-sys/checksum.txt.