#はじめに
ふと、Node.jsからMIDIを簡単そうに操作してるデモ(これ)をみてRubyでも出来ないかと検索したところ、UniMIDIというライブラリが有ることを知る。
ところが先のNodeの奴はGarageBand立ち上げるだけで鳴ってたのにUniMIDIでは鳴らないから、まずMIDI環境のセットアップをすることから始める。
#MIDIスタジオの設定
ユーティリティの中のAudio MIDI 設定.appを開く。これだけじゃMIDIスタジオが出ない場合は、ウインドウ > MIDI スタジオを表示を選択。
この中のIAC ドライバのプロパティでポートの+を押して追加。右上の装置はオンラインをチェック。
#GarageBandを立ち上げる
Steinway Grand Pianoが選ばれてる状態だと思うのでそのまま待機。のちにこれを鳴らすんだけど結構いい音がする。
#UniMIDIを入れる
実際のところの主役UniMIDIを入れる。これのお陰で簡単にRubyからMIDI信号を操れる。
gem install unimidi
以下のサンプルを実行してみる。内容は0x90鍵盤押下、48が音程(ド。C3)、強さ100、っていうMIDI信号を出して、1秒後に0x80で鍵盤を離す、っていう簡単なサンプル。ポーンって鳴ったら成功。
require 'unimidi'
output = UniMIDI::Output.use(:first)
output.puts(0x90, 48, 100) # note on
sleep 1 # wait
output.puts(0x80, 48, 100) # note off
何かMIDIのデバイスつないでる人は:firstのあたり修正しないとダメかも。
#本題
というのが経緯でこれからが主題。
RubyでMIDIが操れて面白いなあ、ポーンじゃなくてもう少し何か鳴らしたいなあ、じゃあルビーの指環かなあ、だけど48のドを何秒、50のレを何秒って手で書くのは馬鹿らしすぎるなあ、となって、
じゃあ(PCの)キーボードでリアルタイムに入力してその48を何秒のデータ生成すればいいじゃない、って思った。
ruby hoge.rb
ってやってPCのキーボードをかちゃかちゃやるとそのまま、音がなるアプリ。
もちろんその手の、PCのキーボードを楽器に見立てるソフトはすでにあるのも知ってる(GarageBandにもある)けど、せっかくMIDIの出力が容易になったので入力部分も作れば、立派に楽器になるという点が興味を引いた。
#stdinからキャラクターを取り出す
さてRubyでキーの入力を取り出すにはどうしたもんかなあ、と考えて、ノンブロックなgetcならcursesで出来たような気がすることを思い出す。
いつの間にか、cursesはRuby標準じゃなくなってたのでGemで入れる。
gem install curses
Curses.getch
で入力したキーが取り出せる。
#対応した音を鳴らす
次は入力に応じて、適当にマッピングした音程のMIDI信号を送ってあげればいい。
ここでは取り敢えず、PCキーボードのaをド、sをレ、dをミをする。
require 'unimidi'
require 'curses'
output = UniMIDI::Output.use(:first)
Curses.timeout = 10
loop do
char = Curses.getch
notes = {'a'=>48, 's'=>50, 'd'=>52}
if notes[char]
output.puts(0x90, notes[char], 100)
end
end
実行してかちゃかちゃasdを叩けば音がなる。これだけでも楽器になってて感動する。
#機能追加
ここまでできればあとは作りこみ次第。
aから]までマッピングを増やしてqの列を黒鍵盤に当てたりする。
入力した時間とキーを覚えておくモードをつければ録音機能になって、演奏の再現ができるようになる。
Cメジャー以外も簡単に弾けるようにトランスポーズをつける。
あと表示もちょっと整えて、わかりやすくする。
そうして出来たもの:https://github.com/ymmtmdk/keyboard_keyboard
#演奏してみた
準備が整ったので心のおもむくままルビーの指環を弾いて完成。