Expand description
§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.
§Installation
Add to your project:
cargo add aic-sdk --features download-lib§Quick Start
use aic_sdk::{include_model, ProcessorConfig, Model, Processor};
// Embed model at compile time (or use Model::from_file to load at runtime)
static MODEL: &'static [u8] = include_model!("/path/to/model.aicmodel");
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Get your license key from the environment variable
let license_key = std::env::var("AIC_SDK_LICENSE")?;
// Load the embedded model (or download manually at https://artifacts.ai-coustics.io/)
let model = Model::from_buffer(MODEL)?;
// Get optimal configuration based on the selected model
let config = ProcessorConfig::optimal(&model).with_num_channels(2);
// Create a processor and initialize it
let mut processor = Processor::new(&model, &license_key)?.with_config(&config)?;
// Process audio (interleaved: channels × frames)
let mut audio_buffer = vec![0.0f32; config.num_channels as usize * config.num_frames];
processor.process_interleaved(&mut audio_buffer)?;
Ok(())
}§Usage
§SDK Information
use aic_sdk;
// Get SDK version
println!("SDK version: {}", aic_sdk::get_sdk_version());
// Get compatible model version
println!("Compatible model version: {}", aic_sdk::get_compatible_model_version());§Loading Models
Download models and find available IDs at artifacts.ai-coustics.io.
§Load from File
use aic_sdk::Model;
let model = Model::from_file("path/to/model.aicmodel")?;§Embed at Compile Time
use aic_sdk::{Model, include_model};
static MODEL: &'static [u8] = include_model!("/path/to/model.aicmodel");
let model = Model::from_buffer(MODEL)?;§Download from CDN
Enable the download-model feature:
cargo add aic-sdk --features download-lib,download-modeluse aic_sdk::Model;
let model_path = Model::download("quail-vf-2.1-s-16khz", "./models")?;
let model = Model::from_file(&model_path)?;§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(48000);§Configuring the Processor
use aic_sdk::{Processor, ProcessorConfig};
// Get optimal configuration for the model
let config = ProcessorConfig::optimal(&model)
.with_num_channels(1)
.with_allow_variable_frames(false);
println!("{:?}", config); // ProcessorConfig { sample_rate: 48000, num_channels: 1, num_frames: 480, allow_variable_frames: false }
// Or create from scratch
let config = ProcessorConfig {
sample_rate: 48000,
num_channels: 2,
num_frames: 480,
allow_variable_frames: false,
};
// Processor needs to be initialized before processing
// Option 1: Create and initialize in one step
let processor = Processor::new(&model, &license_key)?.with_config(&config)?;
// Option 2: Create first, then initialize separately
let mut processor = Processor::new(&model, &license_key)?;
processor.initialize(&config)?;§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 aic_sdk::{OtelConfig, Processor};
let otel = OtelConfig::with_session_id("session-1");
let processor = Processor::with_otel_config(&model, &license_key, &otel)?
.with_config(&config)?;§Processing Audio
// Interleaved processing (channels interleaved in single buffer)
// Format: [l, r, l, r, ...]
let mut audio_buffer = vec![0.0f32; config.num_channels as usize * config.num_frames];
processor.process_interleaved(&mut audio_buffer)?;
// Sequential processing (channels in sequence)
// Format: [l, l, ..., r, r, ...]
let mut audio_sequential = vec![0.0f32; config.num_channels as usize * config.num_frames];
processor.process_sequential(&mut audio_sequential)?;
// Planar processing (separate buffer per channel)
// Format: [[l, l, ...], [r, r, ...]]
let mut audio = vec![vec![0.0f32; config.num_frames]; config.num_channels as usize];
processor.process_planar(&mut audio)?;§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 aic_sdk::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(ProcessorParameter::EnhancementLevel, 0.8)?;
proc_ctx.set_parameter(ProcessorParameter::Bypass, 0.0)?;
// Get parameter values
let level = proc_ctx.parameter(ProcessorParameter::EnhancementLevel)?;
println!("Enhancement level: {}", level);§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 aic_sdk::VadParameter;
// Get VAD context from processor
let vad_ctx = processor.vad_context();
// Configure VAD parameters
vad_ctx.set_parameter(VadParameter::Sensitivity, 6.0)?;
vad_ctx.set_parameter(VadParameter::SpeechHoldDuration, 0.05)?;
vad_ctx.set_parameter(VadParameter::MinimumSpeechDuration, 0.0)?;
// Get parameter values
let sensitivity = vad_ctx.parameter(VadParameter::Sensitivity)?;
println!("VAD sensitivity: {}", sensitivity);
// Check for speech (after processing audio through the processor)
if vad_ctx.is_speech_detected() {
println!("Speech detected!");
}§Working with the Analyzer
Instantiate an analyzer pair:
let (mut collector, mut analyzer) = aic_sdk::analyzer_pair(&model, &license_key)?;Initialize the collector, similar to the processor initialization
let config = ProcessorConfig::optimal(&model);
collector.initialize(&config)?;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!("Risk score: {}", result.risk_score);§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.
cargo add aic-sdk --features asyncuse aic_sdk::{Model, ProcessorAsync, ProcessorConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let license_key = std::env::var("AIC_SDK_LICENSE")?;
let model = Model::from_file("path/to/model.aicmodel")?;
let config = ProcessorConfig::optimal(&model).with_num_channels(2);
let processor = ProcessorAsync::new(&model, &license_key)?
.with_config(&config)
.await?;
// The async API takes ownership of the buffer and returns it back.
let audio = vec![0.0f32; config.num_channels as usize * config.num_frames];
let audio = processor.process_interleaved(audio).await?;
Ok(())
}§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:
export AIC_SDK_LICENSE="your_license_key_here"
cargo run --example basic_usage --features download-lib,download-model§Documentation
- Full Documentation: docs.ai-coustics.com
- Rust API Reference: docs.rs/aic-sdk
- Available Models: artifacts.ai-coustics.io
§Linking the native SDK
By default, aic-sdk-sys links the native AIC SDK statically. Static linking is the preferred way to use this library because it produces a self-contained binary and avoids runtime library discovery. Two opt-in features link a shared libaic instead when you need dynamic loading. 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. Prefer the default static link unless you specifically need to ship and load a shared library:
AIC_SDK_LICENSE="…" cargo run --example basic_usage \
--features "download-lib download-model"§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: prefer the default static link. If you opt into dynamic/runtime linking, package
libaic.sointo the APK under the matching ABI directory, such aslib/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 { aic_sdk::load_library("/path/to/libaic.so")?; } // optional override§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:
./scripts/generate-notice.sh # requires: cargo install cargo-aboutThe 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.
Macros§
- include_
model - Embeds the bytes of model file, ensuring proper alignment.
Structs§
- Analysis
Result - The result of analyzing an audio signal with an
Analyzer. - Analyzer
- Runs an analysis model over the audio buffered by a
Collector. - Collector
- Buffers audio for later analysis.
- File
Analyzer - Analyzes complete mono audio buffers.
- Model
- High-level wrapper for the ai-coustics audio enhancement model.
- Otel
Config - OpenTelemetry configuration for a
Processor. - Processor
- High-level wrapper for the ai-coustics audio enhancement processor.
- Processor
Async async - A wrapper around
Processorfor use in async contexts. - Processor
Config - Audio processing configuration passed to
Processor::initialize. - Processor
Context - VadContext
- Voice Activity Detector backed by an ai-coustics speech enhancement model.
Enums§
- AicError
- Error type for AIC SDK operations.
- Dynamic
Loading Error runtime-linking - Error returned when loading the AIC dynamic library at runtime fails.
- Processor
Parameter - Configurable parameters for audio enhancement
- VadParameter
- Configurable parameters for Voice Activity Detection.
Functions§
- analyzer_
pair - Creates a collector/analyzer pair for non-real-time analysis.
- get_
compatible_ model_ version - Returns the model version number compatible with this SDK build.
- get_
sdk_ version - Returns the version of the ai-coustics SDK library.
- is_
library_ loaded runtime-linking - Returns whether an AIC dynamic library has already been loaded.
- load_
library ⚠runtime-linking - Loads the AIC dynamic library from
pathwhen theruntime-linkingfeature is enabled. - set_
sdk_ ⚠id - This function is only used to identify SDKs by ai-coustics and should not be called by users of this crate.