Skip to main content

Model

Struct Model 

Source
pub struct Model<'a> { /* private fields */ }
Expand description

High-level wrapper for an ai-coustics model.

A single model instance can be used to create multiple processors, VADs or analyzers, according to the model type.

Each processor, VAD or analyzer created with a given model keeps the underlying model alive through internal reference counting. When the reference count reaches zero the model is destroyed. You may therefore drop the model before those objects, in any order.

§Sharing and Multi-threading

Model is Send and Sync, so you can share it across threads. It does not implement Clone, so wrap it in an Arc if you need shared ownership.

§Example

let model = Model::from_file("/path/to/model.aicmodel")?;
let config = ProcessorConfig::optimal(&model);
let mut processor = Processor::new(&model, &license_key)?;
processor.initialize(&config)?;
let mut audio_block = vec![0.0f32; config.block_size];
processor.process(&mut audio_block)?;

§Multi-threaded Example

let model = Arc::new(Model::from_file("/path/to/model.aicmodel")?);

// Spawn multiple threads, each with its own processor but sharing the same model
let handles: Vec<_> = (0..4)
    .map(|i| {
        let model_clone = Arc::clone(&model);
        thread::spawn(move || {
            let license_key = std::env::var("AIC_SDK_LICENSE").unwrap();
            let mut processor = Processor::new(&model_clone, &license_key).unwrap();
            // Process audio in this thread...
        })
    })
    .collect();

for handle in handles {
    handle.join().unwrap();
}

Implementations§

Source§

impl<'a> Model<'a>

Source

pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Model<'static>, AicError>

Creates a new model instance from a model file.

A single model instance can be used to create multiple processors, VADs or analyzers, according to the model type.

§Lifetime and ownership

Each processor, VAD or analyzer created with a given model keeps the underlying model alive through internal reference counting. When the reference count reaches zero the model is destroyed. You may therefore drop the model before those objects, in any order.

The model data is memory-mapped from the file, not copied into the process. Make sure the file is not modified or deleted while the model, or any object created from it, is alive.

§Arguments
  • path - Filesystem path to a model file.
§Returns

Returns a Result containing the new Model instance or an AicError if creation fails.

§Example
let model = Model::from_file("/path/to/model.aicmodel")?;
Source

pub fn from_buffer(buffer: &'a [u8]) -> Result<Self, AicError>

Creates a new model instance from a memory buffer.

A single model instance can be used to create multiple processors, VADs or analyzers, according to the model type.

§Lifetime and ownership

Each processor, VAD or analyzer created with a given model keeps the underlying model alive through internal reference counting. When the reference count reaches zero the model is destroyed. You may therefore drop the model before those objects, in any order.

The buffer must be 64-byte aligned.

Consider using include_model! to embed a model file at compile time with the correct alignment.

§Arguments
  • buffer - Raw bytes of the model file.
§Returns

Returns a Result containing the new Model instance or an AicError if creation fails.

§Example
static MODEL: &[u8] = include_model!("path/to/model.aicmodel");
let model = Model::from_buffer(MODEL)?;
Source

pub fn id(&self) -> &str

Returns the model identifier.

The returned string is UTF-8 encoded.

Source

pub fn optimal_sample_rate(&self) -> u32

Retrieves the optimal sample rate of the model.

Each model is optimized for a specific sample rate, which determines the frequency range of the enhanced audio output. While you can process audio at any sample rate, understanding the model’s native rate helps predict the enhancement quality.

How sample rate affects enhancement:

  • Models trained at lower sample rates (e.g., 8 kHz) can only enhance frequencies up to their Nyquist limit (4 kHz for 8 kHz models)
  • When processing higher sample rate input (e.g., 48 kHz) with a lower-rate model, only the lower frequency components will be enhanced

Enhancement blending: When enhancement strength is set below 1.0, the enhanced signal is blended with the original, maintaining the full frequency spectrum of your input while adding the model’s noise reduction capabilities to the lower frequencies.

Sample rate and optimal block size relationship: When using different sample rates than the model’s native rate, the optimal samples per block (returned by Model::optimal_block_size) will change. The processor’s output delay remains constant regardless of sample rate as long as you use the optimal block size for that rate.

Recommendation: For maximum enhancement quality across the full frequency spectrum, match your input sample rate to the model’s native rate when possible.

§Returns

Returns the model’s native sample rate.

§Example
let optimal_sample_rate = model.optimal_sample_rate();
println!("Optimal sample rate: {optimal_sample_rate} Hz");
Source

pub fn optimal_block_size(&self, sample_rate: u32) -> usize

Retrieves the optimal block size for the model at a given sample rate.

Using the optimal block size minimizes latency by avoiding internal buffering.

When you use a different block size than the optimal value, the processor will introduce additional buffering latency on top of its base processing delay.

The optimal block size varies based on the sample rate. Each model operates on a fixed time window length, so the required number of samples changes with sample rate. For example, a model designed for 10 ms processing windows requires 480 samples at 48 kHz, but only 160 samples at 16 kHz to capture the same duration of audio.

Call this function with your intended sample rate before calling Processor::initialize to determine the best block size for minimal latency.

§Arguments
  • sample_rate - The sample rate in Hz for which to calculate the optimal block size.
§Returns

Returns the optimal block size.

§Example
let optimal_block_size = model.optimal_block_size(sample_rate);
println!("Optimal block size: {optimal_block_size}");
Source

pub fn download<P: AsRef<Path>>( model_id: &str, download_dir: P, ) -> Result<PathBuf, AicError>

Available on crate feature download-model only.

Downloads a model file from the ai-coustics artifact CDN.

This method verifies that the requested model exists in a version compatible with this library, and downloads the model file to the specified directory. If the model file already exists, it will not be re-downloaded. If the existing file’s checksum does not match, the model will be downloaded and the existing file will be replaced.

The artifact manifest is cached in download_dir and shared by all models. It is refetched when it expires, or when a cached entry turns out to be stale.

Available models can be browsed at artifacts.ai-coustics.io.

§Arguments
  • model_id - The model identifier (e.g., "quail-l-16khz").
  • download_dir - Directory where the model file will be stored.
§Returns

Returns the full path to the model file on success, or an AicError if the operation fails.

§Note

This is a blocking operation that performs network I/O.

Trait Implementations§

Source§

impl<'a> Drop for Model<'a>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl<'a> Send for Model<'a>

Source§

impl<'a> Sync for Model<'a>

Auto Trait Implementations§

§

impl<'a> Freeze for Model<'a>

§

impl<'a> RefUnwindSafe for Model<'a>

§

impl<'a> Unpin for Model<'a>

§

impl<'a> UnsafeUnpin for Model<'a>

§

impl<'a> UnwindSafe for Model<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more