tek/src/core/midi.rs

92 lines
2.1 KiB
Rust

use crate::core::*;
pub type MIDIMessage =
Vec<u8>;
pub type MIDIChunk =
[Vec<MIDIMessage>];
/// Add "all notes off" to the start of a buffer.
pub fn all_notes_off (output: &mut MIDIChunk) {
let mut buf = vec![];
let msg = MidiMessage::Controller { controller: 123.into(), value: 0.into() };
let evt = LiveEvent::Midi { channel: 0.into(), message: msg };
evt.write(&mut buf).unwrap();
output[0].push(buf);
}
pub fn parse_midi_input (input: MidiIter) -> Box<dyn Iterator<Item=(usize, LiveEvent, &[u8])> + '_> {
Box::new(input.map(|RawMidi { time, bytes }|(
time as usize,
LiveEvent::parse(bytes).unwrap(),
bytes
)))
}
/// Write to JACK port from output buffer (containing notes from sequence and/or monitor)
pub fn write_midi_output (writer: &mut ::jack::MidiWriter, output: &MIDIChunk, frames: usize) {
for time in 0..frames {
for event in output[time].iter() {
writer.write(&::jack::RawMidi { time: time as u32, bytes: &event })
.expect(&format!("{event:?}"));
}
}
}
/// (pulses, name)
pub const NOTE_DURATIONS: [(u16, &str);26] = [
(1, "1/384"),
(2, "1/192"),
(3, "1/128"),
(4, "1/96"),
(6, "1/64"),
(8, "1/48"),
(12, "1/32"),
(16, "1/24"),
(24, "1/16"),
(32, "1/12"),
(48, "1/8"),
(64, "1/6"),
(96, "1/4"),
(128, "1/3"),
(192, "1/2"),
(256, "2/3"),
(384, "1/1"),
(512, "4/3"),
(576, "3/2"),
(768, "2/1"),
(1152, "3/1"),
(1536, "4/1"),
(2304, "6/1"),
(3072, "8/1"),
(3456, "9/1"),
(6144, "16/1"),
];
pub fn prev_note_length (ppq: u16) -> u16 {
for i in 1..=16 {
let length = NOTE_DURATIONS[16-i].0;
if length < ppq {
return length
}
}
ppq
}
pub fn next_note_length (ppq: u16) -> u16 {
for (length, _) in &NOTE_DURATIONS {
if *length > ppq {
return *length
}
}
ppq
}
pub fn ppq_to_name (ppq: u16) -> &'static str {
for (length, name) in &NOTE_DURATIONS {
if *length == ppq {
return name
}
}
""
}