Skip to main content

Crate aic_sdk

Crate aic_sdk 

Source
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-model
use 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 async
use 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:

Run examples with:

export AIC_SDK_LICENSE="your_license_key_here"
cargo run --example basic_usage --features download-lib,download-model

§Documentation

§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.

FeatureLinkingHow libaic is located
(default)static, at build timeAIC_LIB_PATH directory, or downloaded with download-lib
dynamic-linkingdynamic, at build timesame to link; then OS loader search at run time
runtime-linkingdynamic, lazy on first useOS 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" + ship libaic.so beside the binary).
  • macOS: DYLD_LIBRARY_PATH, @rpath/@loader_path, or a bundle layout.
  • Windows: put aic.dll next to the .exe or on PATH (the build-time import lib aic.lib and the runtime aic.dll may be in different directories).
  • Android: prefer the default static link. If you opt into dynamic/runtime linking, package libaic.so into the APK under the matching ABI directory, such as lib/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-about

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.

Macros§

include_model
Embeds the bytes of model file, ensuring proper alignment.

Structs§

AnalysisResult
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.
FileAnalyzer
Analyzes complete mono audio buffers.
Model
High-level wrapper for the ai-coustics audio enhancement model.
OtelConfig
OpenTelemetry configuration for a Processor.
Processor
High-level wrapper for the ai-coustics audio enhancement processor.
ProcessorAsyncasync
A wrapper around Processor for use in async contexts.
ProcessorConfig
Audio processing configuration passed to Processor::initialize.
ProcessorContext
VadContext
Voice Activity Detector backed by an ai-coustics speech enhancement model.

Enums§

AicError
Error type for AIC SDK operations.
DynamicLoadingErrorruntime-linking
Error returned when loading the AIC dynamic library at runtime fails.
ProcessorParameter
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_loadedruntime-linking
Returns whether an AIC dynamic library has already been loaded.
load_libraryruntime-linking
Loads the AIC dynamic library from path when the runtime-linking feature 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.