better quality midi

This commit is contained in:
2026-01-31 23:23:36 +01:00
parent fed39c01e8
commit 15a4300db5
4 changed files with 78 additions and 46 deletions

View File

@@ -1,10 +1,12 @@
use midir::{MidiInput, MidiOutput};
use std::sync::{Arc, Mutex};
use midir::{MidiInput, MidiOutput};
use crate::model::CcMemory;
#[derive(Clone, Debug)]
pub struct MidiDeviceInfo {
pub name: String,
pub port_index: usize,
}
pub fn list_midi_outputs() -> Vec<MidiDeviceInfo> {
@@ -14,12 +16,11 @@ pub fn list_midi_outputs() -> Vec<MidiDeviceInfo> {
midi_out
.ports()
.iter()
.enumerate()
.filter_map(|(idx, port)| {
midi_out.port_name(port).ok().map(|name| MidiDeviceInfo {
name,
port_index: idx,
})
.filter_map(|port| {
midi_out
.port_name(port)
.ok()
.map(|name| MidiDeviceInfo { name })
})
.collect()
}
@@ -31,18 +32,15 @@ pub fn list_midi_inputs() -> Vec<MidiDeviceInfo> {
midi_in
.ports()
.iter()
.enumerate()
.filter_map(|(idx, port)| {
midi_in.port_name(port).ok().map(|name| MidiDeviceInfo {
name,
port_index: idx,
})
.filter_map(|port| {
midi_in
.port_name(port)
.ok()
.map(|name| MidiDeviceInfo { name })
})
.collect()
}
pub type CcMemory = Arc<Mutex<[[u8; 128]; 16]>>;
pub struct MidiState {
output_conn: Option<midir::MidiOutputConnection>,
input_conn: Option<midir::MidiInputConnection<CcMemory>>,
@@ -80,13 +78,6 @@ impl MidiState {
Ok(())
}
pub fn disconnect_output(&mut self) {
if let Some(conn) = self.output_conn.take() {
conn.close();
}
self.selected_output = None;
}
pub fn connect_input(&mut self, index: usize) -> Result<(), String> {
let midi_in = MidiInput::new("cagire-in").map_err(|e| e.to_string())?;
let ports = midi_in.ports();
@@ -120,13 +111,6 @@ impl MidiState {
Ok(())
}
pub fn disconnect_input(&mut self) {
if let Some(conn) = self.input_conn.take() {
conn.close();
}
self.selected_input = None;
}
pub fn send_note_on(&mut self, channel: u8, note: u8, velocity: u8) {
if let Some(conn) = &mut self.output_conn {
let status = 0x90 | (channel & 0x0F);
@@ -148,29 +132,32 @@ impl MidiState {
}
}
pub fn send_all_notes_off(&mut self) {
pub fn send_pitch_bend(&mut self, channel: u8, value: u16) {
if let Some(conn) = &mut self.output_conn {
for channel in 0..16u8 {
let status = 0xB0 | channel;
let _ = conn.send(&[status, 123, 0]); // CC 123 = All Notes Off
}
let status = 0xE0 | (channel & 0x0F);
let lsb = (value & 0x7F) as u8;
let msb = ((value >> 7) & 0x7F) as u8;
let _ = conn.send(&[status, lsb, msb]);
}
}
pub fn get_cc(&self, channel: u8, cc: u8) -> u8 {
let channel = (channel as usize).min(15);
let cc = (cc as usize).min(127);
self.cc_memory
.lock()
.map(|mem| mem[channel][cc])
.unwrap_or(0)
pub fn send_pressure(&mut self, channel: u8, value: u8) {
if let Some(conn) = &mut self.output_conn {
let status = 0xD0 | (channel & 0x0F);
let _ = conn.send(&[status, value & 0x7F]);
}
}
pub fn is_output_connected(&self) -> bool {
self.output_conn.is_some()
pub fn send_program_change(&mut self, channel: u8, program: u8) {
if let Some(conn) = &mut self.output_conn {
let status = 0xC0 | (channel & 0x0F);
let _ = conn.send(&[status, program & 0x7F]);
}
}
pub fn is_input_connected(&self) -> bool {
self.input_conn.is_some()
pub fn send_realtime(&mut self, msg: u8) {
if let Some(conn) = &mut self.output_conn {
let _ = conn.send(&[msg]);
}
}
}