use midly::num::u14;
use midly::num::u7;
pub(crate) struct FactoredState {
pub(crate) fnum_msb: [u8; 0x10],
pub(crate) fnum_lsb: [u8; 0x10],
pub(crate) fnum_1: [u32; 0x10],
pub(crate) fnum_2: [u32; 0x10],
pub(crate) hz_1: [f64; 0x10],
pub(crate) hz_2: [f64; 0x10],
pub(crate) note_1: [f64; 0x10],
pub(crate) note_2: [f64; 0x10],
pub(crate) midi_instrument: [u7; 0x10],
pub(crate) midi_note: [u7; 0x10],
pub(crate) midi_wheel: [u14; 0x10],
pub(crate) midi_volume: [u7; 0x10],
pub(crate) midi_pan: [u7; 0x10],
pub(crate) midi_mod: [u7; 0x10],
pub(crate) note_on_1: [bool; 0x10],
pub(crate) note_on_2: [bool; 0x10],
}
impl Default for FactoredState {
fn default() -> Self {
FactoredState {
fnum_msb: [0; 0x10],
fnum_lsb: [0; 0x10],
fnum_1: [0; 0x10],
fnum_2: [0; 0x10],
hz_1: [0.0; 0x10],
hz_2: [0.0; 0x10],
note_1: [0xFF.into(); 0x10],
note_2: [0xFF.into(); 0x10],
midi_instrument: [0xFF.into(); 0x10],
midi_note: [0xFF.into(); 0x10],
midi_wheel: [0x8000.into(); 0x10],
midi_volume: [0xFF.into(); 0x10],
midi_pan: [0.into(); 0x10],
midi_mod: [0xFF.into(); 0x10],
note_on_1: [false; 0x10],
note_on_2: [false; 0x10],
}
}
}
pub(crate) fn shift<T: Copy>(buf: &mut T, new: T) -> T {
let old = *buf;
*buf = new;
old
}
pub(crate) fn midi_from_note(note: f64) -> u7 {
(note.round() as u8).into()
}
#[test]
fn test_hz_to_note() {
assert!((hz_to_note(110.0) - 45.0).abs() < 0.01);
assert!((hz_to_note(220.0) - 57.0).abs() < 0.01);
assert!((hz_to_note(261.63) - 60.0).abs() < 0.01);
assert!((hz_to_note(440.0) - 69.0).abs() < 0.01);
assert!((hz_to_note(523.25) - 72.0).abs() < 0.01);
assert!((hz_to_note(880.0) - 81.0).abs() < 0.01);
assert!((hz_to_note(1760.0) - 93.0).abs() < 0.01);
}
pub(crate) fn hz_to_note(freq: f64) -> f64 {
if freq == 0.into() {
0xFF.into()
} else {
f64::log(freq / 440.0, f64::powf(2.0, 1.0 / 12.0)) + 69.0
}
}