2个不稳定版本
0.2.0 | 2021年4月18日 |
---|---|
0.1.0 | 2021年3月2日 |
#743 in 音频
32KB
563 行
RtMidi
一个围绕RtMidi的封装库,为Linux(ALSA & JACK)、macOS(CoreMIDI & JACK)和Windows(多媒体库)操作系统提供通用的API(应用程序编程接口)用于实时MIDI输入/输出。
lib.rs
:
RtMidi
一个围绕RtMidi的封装库,为Linux(ALSA & JACK)、macOS(CoreMIDI & JACK)和Windows(多媒体库)操作系统提供通用的API(应用程序编程接口)用于实时MIDI输入/输出。
在适用的情况下,可以编译多个API支持,并在创建RtMidi实例时指定特定的API。
MIDI输入和输出功能分别包含在两个结构体中,RtMidiIn
和RtMidiOut
。每个实例仅支持一个MIDI连接。RtMidi不提供定时功能(即,输出消息立即发送)。输入消息使用秒(通过f64
类型)的增量时间戳。MIDI数据通过使用&[u8]
将原始字节传递给用户。
探测端口/设备
客户端通常必须在决定使用哪个端口之前查询可用的MIDI端口。以下示例说明了如何进行此操作。
use rtmidi::{RtMidiIn, RtMidiOut, RtMidiError};
fn main() -> Result<(), RtMidiError> {
// Initialise MIDI input
let input = RtMidiIn::new(Default::default())?;
// Get number of input ports
let input_ports = input.port_count()?;
println!("There are {} MIDI input sources available.", input_ports);
// List input ports
for port in 0..input_ports {
println!("\tInput Port #{}: {}", port+1, input.port_name(port)?);
}
// Initialise MIDI output
let output = RtMidiOut::new(Default::default())?;
// Get number of output ports
let output_ports = output.port_count()?;
println!("There are {} MIDI output ports available.", output_ports);
// List output ports
for port in 0..output_ports {
println!("\tOutput Port #{}: {}", port+1, output.port_name(port)?);
}
Ok(())
}
请注意,端口枚举是系统特定的,如果用户拔除或连接(或打开或关闭新虚拟端口)任何设备,它将发生变化。因此,应在打开端口之前立即验证端口编号。此外,如果用户在端口连接到该设备/端口时拔除设备(或关闭虚拟端口),将生成MIDI系统错误。
MIDI输出
RtMidiOut提供立即通过MIDI连接发送消息的简单功能。不提供定时功能。
use std::thread::sleep;
use std::time::Duration;
use rtmidi::{RtMidiOut, RtMidiError};
fn main() -> Result<(), RtMidiError> {
// Initialise MIDI output
let output = RtMidiOut::new(Default::default())?;
// Check available ports
let ports = output.port_count()?;
if ports < 1 {
eprintln!("No ports available!");
return Ok(());
}
// Open first available port
output.open_port(0, "RtMidi Output")?;
// Program change: 192, 5
output.message(&[192, 5])?;
// Control Change: 176, 7, 100 (volume)
output.message(&[176, 7, 100])?;
// Note On: 144, 64, 90
output.message(&[144, 64, 90])?;
sleep(Duration::from_millis(500));
// Note Off: 128, 64, 40
output.message(&[128, 64, 40])?;
Ok(())
}
MIDI输入
RtMidiIn
使用内部回调函数或线程从端口或设备接收传入的 MIDI 消息。然后,这些消息要么通过调用 RtMidiIn::message
由用户排队并读取,要么立即传递给用户指定的回调函数(必须使用 RtMidiIn::set_callback
进行“注册”)。请注意,如果您有多个 RtMidiIn
实例,每个实例可能都有自己的线程。
RtMidiIn
提供了 RtMidiIn::ignore_types
以指定某些 MIDI 消息类型被忽略。默认情况下,系统专用、定时和活动感知消息被忽略。
在打开端口后立即设置回调是必要的,以避免传入的消息写入队列(当设置回调函数时,队列不会被清空)。如果您担心这种情况发生,可以使用 RtMidiIn::message
检查队列是否为空(在设置回调后)。
use std::io::{stdin, Read};
use rtmidi::{RtMidiIn, RtMidiError};
fn main() -> Result<(), RtMidiError> {
// Initialise MIDI input
let input = RtMidiIn::new(Default::default())?;
// Check available ports
let ports = input.port_count()?;
if ports < 1 {
eprintln!("No ports available!");
return Ok(());
}
// Open first available port
input.open_port(0, "RtMidi Input")?;
// Set our callback function. This should be done immediately after
// opening the port to avoid having incoming messages written to the
// queue.
input.set_callback(|timestamp, message| {
for (index, byte) in message.iter().enumerate() {
println!("Byte {} = 0x{:02x}, ", index, byte);
}
})?;
// Don't ignore sysex, timing, or active sensing messages.
input.ignore_types(false, false, false)?;
println!("Reading MIDI input ...");
stdin().read(&mut [0]).unwrap();
Ok(())
}
无运行时依赖
~0–1.8MB
~34K SLoC