mlua-pulse 0.1.0

Lua-friendly music composition and audio export bindings built on tunes and mlua
Documentation
use crate::error::{PulseError, PulseResult};

/// Converts a frequency in Hz to a MIDI note number.
pub fn frequency_to_midi_note(frequency: f32) -> PulseResult<u8> {
    if !frequency.is_finite() || frequency <= 0.0 {
        return Err(PulseError::InvalidFrequency { frequency });
    }

    Ok(tunes::midi::frequency_to_midi_note(frequency))
}

/// Converts a MIDI note number to a frequency in Hz.
pub fn midi_note_to_frequency(note: i64) -> PulseResult<f32> {
    if !(0..=127).contains(&note) {
        return Err(PulseError::InvalidMidiNote { note });
    }

    let note = u8::try_from(note).map_err(|_| PulseError::InvalidMidiNote { note })?;
    Ok(tunes::midi::midi_note_to_frequency(note))
}

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

    #[test]
    fn converts_between_frequency_and_midi_notes() {
        assert_eq!(frequency_to_midi_note(440.0).unwrap(), 69);
        assert!((midi_note_to_frequency(69).unwrap() - 440.0).abs() < 0.01);
    }

    #[test]
    fn rejects_invalid_midi_inputs() {
        assert_eq!(
            midi_note_to_frequency(200).unwrap_err().to_string(),
            "invalid midi note: 200"
        );
        assert_eq!(
            frequency_to_midi_note(f32::NAN).unwrap_err().to_string(),
            "invalid frequency: NaN"
        );
        assert_eq!(
            frequency_to_midi_note(0.0).unwrap_err().to_string(),
            "invalid frequency: 0"
        );
        assert_eq!(
            frequency_to_midi_note(-440.0).unwrap_err().to_string(),
            "invalid frequency: -440"
        );
    }
}