rosa 0.1.0

Audio feature extraction library matching librosa output
Documentation
mod common;

use rosa::matrix::Matrix;
use rosa::segment::{DistanceMetric, RecurrenceMode, RecurrenceParams, recurrence_matrix};

#[test]
fn test_recurrence_connectivity_matches_librosa() {
    let ref_data = common::load_audio_reference("recurrence_matrix.json");

    let rows = ref_data["input_rows"].as_u64().unwrap() as usize;
    let cols = ref_data["input_cols"].as_u64().unwrap() as usize;
    let input_flat: Vec<f64> = serde_json::from_value(ref_data["input"].clone()).unwrap();
    let input = Matrix::from_vec(input_flat, rows, cols);

    let expected_rows = ref_data["connectivity_rows"].as_u64().unwrap() as usize;
    let expected_cols = ref_data["connectivity_cols"].as_u64().unwrap() as usize;
    let expected: Vec<f64> = serde_json::from_value(ref_data["connectivity"].clone()).unwrap();

    let params = RecurrenceParams {
        metric: DistanceMetric::Euclidean,
        mode: RecurrenceMode::Connectivity,
        sym: true,
        ..Default::default()
    };
    let result = recurrence_matrix(&input, &params);
    assert_eq!(
        result.shape(),
        (expected_rows, expected_cols),
        "recurrence connectivity shape mismatch"
    );
    // Binary matrix — should be exact
    common::assert_approx_eq(
        result.as_slice(),
        &expected,
        1e-10,
        "recurrence_connectivity",
    );
}

#[test]
fn test_recurrence_affinity_matches_librosa() {
    let ref_data = common::load_audio_reference("recurrence_matrix.json");

    let rows = ref_data["input_rows"].as_u64().unwrap() as usize;
    let cols = ref_data["input_cols"].as_u64().unwrap() as usize;
    let input_flat: Vec<f64> = serde_json::from_value(ref_data["input"].clone()).unwrap();
    let input = Matrix::from_vec(input_flat, rows, cols);

    let expected_rows = ref_data["affinity_rows"].as_u64().unwrap() as usize;
    let expected_cols = ref_data["affinity_cols"].as_u64().unwrap() as usize;
    let expected: Vec<f64> = serde_json::from_value(ref_data["affinity"].clone()).unwrap();

    let params = RecurrenceParams {
        metric: DistanceMetric::Euclidean,
        mode: RecurrenceMode::Affinity,
        ..Default::default()
    };
    let result = recurrence_matrix(&input, &params);
    assert_eq!(
        result.shape(),
        (expected_rows, expected_cols),
        "recurrence affinity shape mismatch"
    );
    common::assert_approx_eq(result.as_slice(), &expected, 1e-6, "recurrence_affinity");
}