Processingでポケット・ミクの簡易シーケンサを自作してみました

Processingでポケット・ミクソフト自作

 早速大人の科学のポケット・ミク(以下ポケミク)のソフトを作ろうと思いました(既に過去形)。
ヤマハさんが公開しているオープンソースのWebアプリとかをベースに自作するのが王道なのでしょうが、自分はProcessingというプログラミング言語使って作ってみることにしました。理由は以下3つです。

  • 簡単(Webアプリはちょっと難しそうですし、公開が面倒くさそう)
  • 慣れている(自分がですけど)
  • eVY1シールド用にProcessingのサンプルコードがいくつか公開されている

 まあようは自分が慣れててすぐできそうだったからです。

完成したソフトの動画

ポケットミクの簡易シーケンサを自作したのでテスト

karaageさん(@karaage)がシェアした投稿 -

 こんな感じです。PCのボタン一つで「変デジ研究所♩」ってポケミクが歌ってくれます。詳しい説明とかソースコードはそのうち公開する予定です。多分。気が向いたら。詳しく書いてみます。読みたい方は続きを読むをクリック下さい(2014/04/07追記)。

準備するもの

Win/MAC共通

  • ポケミク

アマゾンさんで買いましょう。

  • USBケーブル

アマゾンさんで買いましょう。

  • パソコン

WindowsでもMacでもよいのですが、Windowsの方が手間が少ないかもです(私は未検証ですが)

  • Processing2

Processing.orgからダウンロード。最新の2.1.1をダウンロードしましょう。

以下MAC限定

  • mmj

mmj - Midi for java on Mac OS Xからダウンロード。Mac OSの人限定です。

手順

Win/MAC共通

  • Processingを起動
  • メニュの Sketch -> Import Library -> Add Library で「midibus」を検索。「The MidiBus」が出てくるはずなのでInstallボタンをクリック
  • この記事の下の方にあるソースコードをコピペ
  • スケッチ(ソースコードファイル)を適当なフォルダに保存

以下MAC限定

  • スケッチを保存したフォルダに「code」というフォルダを作成
  • ダウンロードしたmmjのフォルダの中の「mmj.jar」と「libmmj.jnilib」を「code」フォルダ以下にコピー

使い方

  • ポケミクをPCとUSB接続して電源ON
  • Processingのプログラムを実行
  • ウィンドウが表示されたらキーボードの「h」を押して下さい
  • 「変デジ研究所」とミクちゃんがしゃべってくれます

Win限定

 ソースコードの //OSX specificと書かれている行は消してやって下さい。そうすれば多分動きます。

MAC限定

 動かなかったら、ウィンドウが出て来たら「a」を押して下さい。
ずらずらと数字と謎のアルファベットの羅列が出て来ると思います。その中で「NSX-39 」という文字列を探して下さい。そしたら、「NSX-39 」の前にある数字を確認して下さい。その数字が例えば「3」だったら。以下のソースコードの部分の数字を「3」に置き換えて下さい。

mo_vocaloid = ms.openMidiOutput(2);     // OSX specific

ソースコード

 ソースコードは以下です。

//////////////////////////////////////////////////////////////////
// This sketch is based on the sketch: eVY1_example.pde and ariakekousen.pde
//      at https://github.com/SWITCHSCIENCE/eVY1_Shield .
//      at http://www.ie.ariake-nct.ac.jp/~tetsuya/?p=1128 .
// Thanks to SWITCHSCIENCE ! AND MATSUNOTE Lab
//////////////////////////////////////////////////////////////////
import themidibus.*;
import de.humatic.mmj.*; // OSX specific
 
//// Please refer http://www.humatic.de/htools/mmj/doc/
//CoreMidiDevice[] cmd;    // OSX specific
MidiOutput mo_vocaloid;  // OSX specific
MidiSystem ms;           // OSX specific
 
MidiBus vocaloid;
//int channel = 0; //0:eVocaloid
//int pitch = 0;
//int velocity = 0;
 
byte[] data = {(byte)0xF0, (byte)0x43, (byte)0x79, (byte)0x09, // header(SysEx)
               (byte)0x11, (byte)0x0A, (byte)0x00,             // header(SysEx)
               (byte)0x4A,                                     // HE
               (byte)0x7B,                                     // N
               (byte)0x31,                                     // DE
               (byte)0x25,                                     // JI
               (byte)0x08,                                     // KE
               (byte)0x7B,                                     // N
               (byte)0x10,                                     // KYU
               (byte)0x02,                                     // U
               (byte)0x28,                                     // JYO
               (byte)0xF7  // footer(SysEx)
             };

void setup() {
  size(400, 200);
  background(255);
  MidiBus.list();
  vocaloid = new MidiBus(this, "NSX-39 " , "NSX-39 ");
}
 
void draw() {  
  // draw info
  fill(0,0,0);
  text("Press t -> display MIDI device", 15, 50);
  text("Press h -> NSX-39 is speaking", 15, 100);
}

void keyPressed(){
  if(key == 't'){
    println("Max OSX specific: using MMJ"); // OSX specific
    println(MidiSystem.getOutputs());       // OSX specific
    //    cmd = MidiSystem.getDevices();          // OSX specific
  }

  if(key == 'h'){
    vocaloid.sendTimestamps(false);        // for Win OS
    vocaloid.sendMessage(data);            // for Win OS

    mo_vocaloid = ms.openMidiOutput(2);     // OSX specific
    mo_vocaloid.sendMidi(data);             // OSX specific

    vocaloid.sendNoteOn(0, 74, 80);
    delay(400);
    vocaloid.sendNoteOn(0, 74, 80);
    delay(100);
    vocaloid.sendNoteOn(0, 74, 80);
    delay(400);
    vocaloid.sendNoteOn(0, 74, 80);
    delay(100);
    vocaloid.sendNoteOn(0, 74, 80);
    delay(400);
    vocaloid.sendNoteOn(0, 74, 80);
    delay(100);
    vocaloid.sendNoteOn(0, 74, 80);
    delay(400);
    vocaloid.sendNoteOn(0, 74, 80);
    delay(100);
    vocaloid.sendNoteOn(0, 79, 80);
    delay(200);
    vocaloid.sendNoteOff(0, 79, 80);
  }
}

void exit() {
//  vocaloid.sendNoteOff(channel, pitch, velocity);
  vocaloid.close(); // bye bye!
  super.exit();
}

ソースコード解説

 最初にMIDIデバイスにポケミクを指定しています。以下の部分ね。

vocaloid = new MidiBus(this, "NSX-39 " , "NSX-39 ");

dataの部分は歌詞データになります。ポケミクのマニュアルの最後のページに、MIDIシステムエクスクルーシブデータで以下を指定すれば歌詞を埋め込めると記載されているので、その通りにします。

F0 43 79 09 11 0A 00 XX F7
※XX に文字テーブルの文字番号(16進数)を入力し、発音させたいノートデータの直前に挿入する

文字テーブルはマニュアルの最後のページにあります。ネットでも検索すると出てきます。
http://www.enoie.net/blog/?p=9177とか凄い詳しいです。
文字は一文字ずつじゃなくて、まとめて最大64文字までOK。今回は「ヘ・ン・デ・ジ・ケ・ン・キュ・ウ・ジョ」という9文字を送っています。音を鳴らすたびに歌詞が進んでいきます。

 後は、以下の箇所は曲のシーケンスのデータです。MIDIの形式で送ってやります。

vocaloid.sendNoteOn(0, 74, 80);
delay(400);
vocaloid.sendNoteOn(0, 74, 80);
delay(100);
…

 最初の0はミクちゃんに歌ってもらうためのおまじないです(他の数字を入れると楽器とがが鳴ったりします)。次の数字は音の高さです。ドレミとの対応は以下のサイトとか参考にするとわかります。

MIDIノート番号と音名、周波数の対応表

 上記のサイトによると74は高いレ(D)ですね。
 最後の80は音の大きさを表します。Maxは255です。

 まあ大体こんなものですね、後はこれを応用すれば好きなだけポケミクを歌わせることが可能です。誰でもすぐできちゃうね☆

MAC限定対応(mmj)に関して

 これは結構分からずハマりました。ProcessingではMIDI部にJavaのAPIを使っているのですが、どうもMacのJavaのMIDIは腐っているらしく。ポケミクで歌詞データを送るためのシステムエクスクルーシブデータ(SysEx)を扱うことができないみたいなのです。
 そのため、システムエクスクルーシブデータを使うことができるようにしてくれるmmjという素晴らしいライブラリを使うことでポケミクを使うことができるのです。まあおまじないみたいなものと思って下さい。 

参考にしたサイト

GitHub - SWITCHSCIENCE/eVY1_Shield
來未呼ミキ(2) – 松野て研究室

 偉大なる先人に感謝。特に、下のサイトが無ければMacのJava MIDIが腐っているのに気づかずずっとハマっていたと思います。