Ah, I'm tired of reading the Linux Kernel documentation, so toys came out and I played.
――It's good that things move. --low level / raw level Important for debugging.
We examined based on the contents of the following site. However, I haven't changed my voice yet, so I'd like to consider it a little more ...
-Linux Bimbo Road-Tomorrow is ALSA Program -[Pocket Miku (NSX-39) SysEx Memo](http://mergecells.hatenablog.com/entry/2016/10/04/231818#%E3%81%AA%E3%81%9C%E3% 83% 9D% E3% 82% B1% E3% 83% 9F% E3% 82% AF% E3% 81% A7SysEx% E3% 81% 8C% E5% BF% 85% E8% A6% 81% E3% 81% AA% E3% 81% AE% E3% 81% 8B)
I wondered if I could use RUST to move the "Pocket Miku" that came out after cleaning up.
When I checked using the account command, it looks like "20: 0" because it is NSX-39.
[kmtr@localhost rust-alsa]$ sudo LANG=C aconnect -l
client 0: 'System' [type=kernel]
0 'Timer '
1 'Announce '
client 14: 'Midi Through' [type=kernel]
0 'Midi Through Port-0'
client 16: 'Ensoniq AudioPCI' [type=kernel,card=0]
0 'ES1371 '
client 20: 'NSX-39' [type=kernel,card=1]
0 'NSX-39 MIDI 1 '
[kmtr@localhost rust-alsa]$
Added alsa and clap to Cargo.toml.
Cargo.toml
[package]
name = "rust-alsa"
version = "0.1.0"
authors = ["kmtr"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
alsa = "0.4.2"
clap = "2.20"
rust's alsa wrapper This is neither in one hand nor in this one. For the time being, I confirmed that there was a sound.
src/main.rs
extern crate alsa;
use std::error;
use alsa::seq;
use std::ffi::CString;
use std::thread::sleep;
use std::time::Duration;
const DEFAULT_NAME: &str = "RUSTMIKU";
const MIKU_ID: i32 = 20;
const MIKU_PORT: i32 = 0;
fn note( s: &alsa::Seq, evt : alsa::seq::EventType, channel : u8, note: u8, velocity : u8, s_port:i32)
{
let o_note = alsa::seq::EvNote {
channel,
note,
velocity,
off_velocity: 0,
duration: 0
};
let mut o_event = alsa::seq::Event::new( evt , &o_note );
o_event.set_direct();
o_event.set_source( s_port );
o_event.set_dest( alsa::seq::Addr { client: MIKU_ID, port: MIKU_PORT } );
s.event_output( &mut o_event ) ;
s.drain_output();
}
fn sing() -> Result<alsa::Seq, Box<dyn error::Error> > {
// snd_seq_open()
let miku = alsa::Seq::open( None, Some(alsa::Direction::Playback), false ) ?;
// snd_seq_create_simple_port()
let cstr = CString::new(DEFAULT_NAME)?;
let client_port = miku.create_simple_port(&cstr,
alsa::seq::PortCap::READ,
alsa::seq::PortType::MIDI_GENERIC | alsa::seq::PortType::APPLICATION )?;
// subscribe_port()
let client_id = miku.client_id()?;
let subs = seq::PortSubscribe::empty()?;
subs.set_dest (seq::Addr { client: MIKU_ID, port: MIKU_PORT } );
subs.set_sender(seq::Addr { client: client_id, port: client_port });
miku.subscribe_port(&subs)?;
// Note on
note ( &miku, alsa::seq::EventType::Noteon, 0, 60, 64, client_port );
// Wait
sleep ( Duration::from_millis(1000) );
// Note off
note ( &miku, alsa::seq::EventType::Noteoff, 0, 60, 64, client_port );
Ok(miku)
}
fn main() {
sing();
}
At first, I was wondering why there was no sound. At this time, it was strace that was useful for debugging.
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
ioctl(3, SNDRV_SEQ_IOCTL_PVERSION, 0x7ffe4a9ffeb8) = 0
ioctl(3, SNDRV_SEQ_IOCTL_CLIENT_ID, 0x7ffe4a9ffebc) = 0
ioctl(3, SNDRV_SEQ_IOCTL_RUNNING_MODE, 0x7ffe4a9ffec0) = 0
ioctl(3, SNDRV_SEQ_IOCTL_CREATE_PORT, 0x7ffe4aa00260) = 0
ioctl(3, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, 0x560006f2b5b0) = 0
write(3, "\5\0\0\375\0\0\0\0\0\0\0\0\0\0\24\0\0<@\0\0\0\0\0\0\0\0\0", 28) = -1 EINVAL (Invalid argument)
nanosleep({tv_sec=1, tv_nsec=0}, 0x7ffe4aa00340) = 0
write(3, "\5\0\0\375\0\0\0\0\0\0\0\0\0\0\24\0\0<@\0\0\0\0\0\0\0\0\0\7\0\0\375"..., 56) = -1 EINVAL (Invalid argument)
close(3) = 0
sigaltstack({ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=8192}, NULL) = 0
munmap(0x7f57fe537000, 8192) = 0
exit_group(0) = ?
+++ exited with 0 +++
Hmm? I can't handle anything. so,
note (& miku, alsa :: seq :: EventType :: Note, 0, 60, 64, client_port); You noticed that
note (& miku, alsa :: seq :: EventType :: Noteon, 0, 60, 64, client_port);`.
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
ioctl(3, SNDRV_SEQ_IOCTL_PVERSION, 0x7ffc72b00148) = 0
ioctl(3, SNDRV_SEQ_IOCTL_CLIENT_ID, 0x7ffc72b0014c) = 0
ioctl(3, SNDRV_SEQ_IOCTL_RUNNING_MODE, 0x7ffc72b00150) = 0
ioctl(3, SNDRV_SEQ_IOCTL_CREATE_PORT, 0x7ffc72b004f0) = 0
ioctl(3, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, 0x556f313ee5b0) = 0
write(3, "\6\0\0\375\0\0\0\0\0\0\0\0\0\0\24\0\0<@\0\0\0\0\0\0\0\0\0", 28) = 28
nanosleep({tv_sec=1, tv_nsec=0}, 0x7ffc72b005d0) = 0
write(3, "\7\0\0\375\0\0\0\0\0\0\0\0\0\0\24\0\0<@\0\0\0\0\0\0\0\0\0", 28) = 28
close(3) = 0
sigaltstack({ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=8192}, NULL) = 0
munmap(0x7f59d2ff5000, 8192) = 0
exit_group(0)
After all, debugging at raw level / low level is important! !!
TODO
I want to use sysex to change what I say ...
That's it.
Recommended Posts