bonar note

京都のエンジニア bonar の技術的なことや技術的でない日常のブログです。

KORG nanoKEY and CoreMIDI

KORG の小型MIDIキーボード nanoKEY を購入しました。

f:id:bonar:20090311175220j:image

打鍵感はやっぱりへにゃへにゃで安っぽいですが、この小ささと見た目のよさ、そして5000円という価格は魅力ですね。なによりmacbookと横幅がぴったり合ってるのが素敵。

f:id:bonar:20090315224235j:image

KORG nanoKEY
http://www.korg.co.jp/Product/Synthesizer/nano/nanoKEY.html

これを使って色々面白いことが出来たらいいなと思うのですが、MIDIキーボードの入力を取るっていうのが初めての経験で色々調べた割にまだ何も出来ておらず。。

とりあえず Java Sound API 経由だと、接続されてるはずのデバイスが見えてない感じになってました。これは僕のコードが悪いのかな。。ちょっと根本的に何か勘違いしてる可能性があるかもです。

import java.io.*;
import javax.sound.midi.*;

public class MidiKeyboardTrace {
    public static void main(String[] args) throws Exception {
        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
        for (int i = 0; i < infos.length; i++) {
            MidiDevice.Info info = infos[i];
            System.out.println(info.toString() + "/" + info.getDescription());
        }
    }
}
bash-3.2$ java MidiKeyboardTrace
Real Time Sequencer/Software sequencer
Java Sound Synthesizer/Software wavetable synthesizer and receiver

CoreMIDI

あきらめて、Mac限定ですが、CoreMIDI 経由で取得できそうなのですが、こちらも初めてで(且つドキュメントもあまり見つからずで)難航中です。とりあえず実践的になものに関してはCoreAudio SDK に含まれるヘッダファイル、サンプルコードを見るのが良さそうです。

MIDIキーボードからの入力をそのまま返すエコーサーバ的なコードが以下のパスにあります。

/Developer/Examples/CoreAudio/MIDI/SampleTools/Echo.cpp

ただどういうわけか、stdoutに出す部分がコメントアウトされているので、以下の2行のコメントを外して

static void MyReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)                                                                                                                                                 
{
    if (gOutPort != NULL && gDest != NULL) {
        MIDIPacket *packet = (MIDIPacket *)pktlist->packet; // remove const (!)
        for (unsigned int j = 0; j < pktlist->numPackets; ++j) {
            for (int i = 0; i < packet->length; ++i) {
//              printf("%02X ", packet->data[i]);

                // rechannelize status bytes
                if (packet->data[i] >= 0x80 && packet->data[i] < 0xF0)
                    packet->data[i] = (packet->data[i] & 0xF0) | gChannel;
            }

//          printf("\n");
            packet = MIDIPacketNext(packet);
        }

        MIDISend(gOutPort, gDest, pktlist);
    }
}

コンパイルします

gcc -lstdc++ -framework CoreFoundation -framework CoreMIDI Echo.cpp

ちゃんと KORG nanoKEY が認識されてるっぽいので、こいつの番号(デバイス配列の添字)を指定してやると、打鍵に反応して3バイト1セットのMIDIメッセージが表示されるようになりました(以下コメントはあとがき)。

bash-3.2$ ./a.out 2
name=, manuf=Apple Computer, Inc., model=
name=, manuf=, model=
name=nanoKEY, manuf=KORG INC., model=nanoKEY
1 sources
Echoing to channel 2 of CTRL
90 30 12 # 左端の「ド」を押す
80 30 40 # 離す
90 32 3B # ひとつ右の「レ」を押す
80 32 40 # 離す
B0 01 7F # MOD 押す
B0 01 00 # MOD 押す

サンプルコードをコンパイルしただけですが、なんか「おお」って感じですね。リアルデバイスはなぜかときめきますね。あとはサンプルコードをちゃんと理解すれば、このイベントに望みの処理を入れ放題と。

CoreMIDI に関しては Mac::CoreMIDI っていうライブラリがあるのですが、2005年から更新が止まってるのと、色々と足りてないものがあるので、使うにしてもちょっと追加修正が必要かもですね。
http://search.cpan.org/~crenz/Mac-CoreMIDI-0.04/lib/Mac/CoreMIDI.pm

半日ずっと調べていたのにここまでしか進まないという、、でもMIDI周りの実装方法に関して調べるいい機会になりました。nanoKEYは気軽に買えるおもちゃだと思えば非常に良く出来ていると思います。