knf_rs/
lib.rs

1use eyre::{bail, Context, ContextCompat, Result};
2use ndarray::Array2;
3
4pub fn compute_fbank(samples: &[f32]) -> Result<Array2<f32>> {
5    if samples.is_empty() {
6        bail!("The samples array is empty. No features to compute.")
7    }
8
9    let mut result = unsafe {
10        knf_rs_sys::ComputeFbank(
11            samples.as_ptr(),
12            samples.len().try_into().context("samples len")?,
13        )
14    };
15
16    // Extract frames
17    let frames = unsafe {
18        std::slice::from_raw_parts(
19            result.frames,
20            (result.num_frames * result.num_bins) as usize,
21        )
22        .to_vec()
23    };
24
25    let frames_array = Array2::from_shape_vec(
26        (
27            result.num_frames.try_into().context("num_frames")?,
28            result.num_bins.try_into().context("num_bins")?,
29        ),
30        frames,
31    )?;
32
33    unsafe {
34        knf_rs_sys::DestroyFbankResult(&mut result as *mut _);
35    }
36
37    if frames_array.is_empty() {
38        bail!("The frames array is empty. No features to compute.")
39    }
40
41    let mean = frames_array.mean_axis(ndarray::Axis(0)).context("mean")?;
42    let features = frames_array - mean;
43
44    Ok(features)
45}
46
47pub fn convert_integer_to_float_audio(samples: &[i16], output: &mut [f32]) {
48    for (input, output) in samples.iter().zip(output.iter_mut()) {
49        *output = *input as f32 / 32768.0;
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use crate::compute_fbank;
56    use std::f32::consts::PI;
57
58    fn generate_sine_wave(sample_rate: usize, duration: usize, frequency: f32) -> Vec<f32> {
59        let waveform_size = sample_rate * duration;
60        let mut waveform = Vec::with_capacity(waveform_size);
61
62        for i in 0..waveform_size {
63            let sample = 0.5 * (2.0 * PI * frequency * i as f32 / sample_rate as f32).sin();
64            waveform.push(sample);
65        }
66        waveform
67    }
68
69    #[test]
70    fn it_works() {
71        let sample_rate = 16000;
72        let duration = 1; // 1 second
73        let frequency = 440.0; // A4 note
74
75        let waveform = generate_sine_wave(sample_rate, duration, frequency);
76        let features = compute_fbank(&waveform);
77        println!("features: {:?}", features);
78    }
79}