Use Rust to move Pocket Miku.

Ah, I'm tired of reading the Linux Kernel documentation, so toys came out and I played.

Finally: I tried moving Pocket Miku with Rust

――It's good that things move. --low level / raw level Important for debugging.

Reference material

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)

What did you want to do

I wondered if I could use RUST to move the "Pocket Miku" that came out after cleaning up.

Check the ID etc. recognized by alsa.

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]$

Incorporate a library for manipulating midi with 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"

Make a sound from Pocket Miku via alsa

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();
}

It was strace that helped debug

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

Use Rust to move Pocket Miku.
How to use Python-shell
How to use tf.data
How to use virtualenv
How to use Seaboan
How to use image-match
How to use shogun
How to use Pandas 2
How to use Virtualenv
How to use numpy.vectorize
How to use pytest_report_header
Easy to use Flask
How to use partial
How to use Bio.Phylo
How to use SymPy
How to use x-means
How to use WikiExtractor.py
How to use IPython
How to use virtualenv
How to use Matplotlib
How to use iptables
How to use numpy
Reasons to use logarithm
How to use TokyoTechFes2015
How to use venv
How to use dictionary {}
How to use Pyenv
Easy to use SQLite3
How to use list []
How to use python-kabusapi
Python-How to use pyinstaller
How to use OptParse
How to use return
How to use dotenv
How to use pyenv-virtualenv
How to use Go.mod
How to use imutils
How to use import
How to use Qt Designer
How to use search sorted
[gensim] How to use Doc2Vec
python3: How to use bottle (2)
Understand how to use django-filter
Use MeCab to fetch readings
How to use the generator
[Python] How to use list 1
QSM analysis-How to use MEDI-
How to use FastAPI ③ OpenAPI
How to use Python argparse
How to use IPython Notebook
How to use Pandas Rolling
[Note] How to use virtualenv
How to use redis-py Dictionaries
Python: How to use pydub
[Python] How to use checkio
[Go] How to use "... (3 periods)"
How to use Django's GeoIp2
Easy to use E-Cell 4 Intermediate
[Python] How to use input ()
How to use the decorator
[Introduction] How to use open3d