1use crate::error::{PulseError, PulseResult};
2
3pub fn frequency_to_midi_note(frequency: f32) -> PulseResult<u8> {
5 if !frequency.is_finite() || frequency <= 0.0 {
6 return Err(PulseError::InvalidFrequency { frequency });
7 }
8
9 Ok(tunes::midi::frequency_to_midi_note(frequency))
10}
11
12pub fn midi_note_to_frequency(note: i64) -> PulseResult<f32> {
14 if !(0..=127).contains(¬e) {
15 return Err(PulseError::InvalidMidiNote { note });
16 }
17
18 let note = u8::try_from(note).map_err(|_| PulseError::InvalidMidiNote { note })?;
19 Ok(tunes::midi::midi_note_to_frequency(note))
20}
21
22#[cfg(test)]
23mod tests {
24 use super::*;
25
26 #[test]
27 fn converts_between_frequency_and_midi_notes() {
28 assert_eq!(frequency_to_midi_note(440.0).unwrap(), 69);
29 assert!((midi_note_to_frequency(69).unwrap() - 440.0).abs() < 0.01);
30 }
31
32 #[test]
33 fn rejects_invalid_midi_inputs() {
34 assert_eq!(
35 midi_note_to_frequency(200).unwrap_err().to_string(),
36 "invalid midi note: 200"
37 );
38 assert_eq!(
39 frequency_to_midi_note(f32::NAN).unwrap_err().to_string(),
40 "invalid frequency: NaN"
41 );
42 assert_eq!(
43 frequency_to_midi_note(0.0).unwrap_err().to_string(),
44 "invalid frequency: 0"
45 );
46 assert_eq!(
47 frequency_to_midi_note(-440.0).unwrap_err().to_string(),
48 "invalid frequency: -440"
49 );
50 }
51}