audionimbus 0.14.0

A safe wrapper around Steam Audio that provides spatial audio capabilities with realistic occlusion, reverb, and HRTF effects, accounting for physical attributes and scene geometry.
Documentation
#[cfg(feature = "bevy")]
use bevy::prelude::{GlobalTransform, Mat4};

/// A `ROWSxCOLS` matrix of type T elements.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Matrix<T, const ROWS: usize, const COLS: usize> {
    /// Matrix elements, in row-major order.
    pub elements: [[T; COLS]; ROWS],
}

impl Matrix<f32, 3, 3> {
    pub const IDENTITY: Self = Self {
        elements: [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
    };
}

impl Default for Matrix<f32, 3, 3> {
    fn default() -> Self {
        Self::IDENTITY
    }
}

impl Matrix<f32, 4, 4> {
    pub const IDENTITY: Self = Self {
        elements: [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [0.0, 0.0, 0.0, 1.0],
        ],
    };
}

impl Default for Matrix<f32, 4, 4> {
    fn default() -> Self {
        Self::IDENTITY
    }
}

impl<T, const ROWS: usize, const COLS: usize> Matrix<T, ROWS, COLS> {
    /// Creates a new matrix.
    pub const fn new(elements: [[T; COLS]; ROWS]) -> Self {
        Self { elements }
    }
}

impl From<Matrix<f32, 4, 4>> for audionimbus_sys::IPLMatrix4x4 {
    fn from(matrix: Matrix<f32, 4, 4>) -> Self {
        Self {
            elements: matrix.elements,
        }
    }
}

impl From<&Matrix<f32, 4, 4>> for audionimbus_sys::IPLMatrix4x4 {
    fn from(matrix: &Matrix<f32, 4, 4>) -> Self {
        Self {
            elements: matrix.elements,
        }
    }
}

pub type Matrix3 = Matrix<f32, 3, 3>;
pub type Matrix4 = Matrix<f32, 4, 4>;

#[cfg(feature = "bevy")]
impl From<GlobalTransform> for Matrix4 {
    fn from(global_transform: GlobalTransform) -> Self {
        Self::from(global_transform.to_matrix())
    }
}

#[cfg(feature = "bevy")]
impl From<Mat4> for Matrix4 {
    fn from(matrix: Mat4) -> Self {
        Self::new(matrix.to_cols_array_2d())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_matrix3x3_identity() {
        let m = Matrix::<f32, 3, 3>::IDENTITY;

        #[rustfmt::skip]
        assert_eq!(
            m,
            Matrix {
                elements: [
                    [1.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0],
                    [0.0, 0.0, 1.0],
                ]
            }
        );
    }

    #[test]
    fn test_matrix4x4_identity() {
        let m = Matrix::<f32, 4, 4>::IDENTITY;

        #[rustfmt::skip]
        assert_eq!(
            m,
            Matrix {
                elements: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ]
            }
        );
    }

    #[test]
    fn test_matrix_new() {
        let elements = [[1.0, 2.0], [3.0, 4.0]];
        let m = Matrix::new(elements);

        #[rustfmt::skip]
        assert_eq!(
            m,
            Matrix {
                elements: [
                    [1.0, 2.0],
                    [3.0, 4.0],
                ]
            }
        );
    }

    #[test]
    fn test_matrix4x4_default() {
        let m = Matrix::<f32, 4, 4>::default();
        assert_eq!(m, Matrix::<f32, 4, 4>::IDENTITY);
    }
}