ポケミクの内蔵エフェクトの威力を自作ソフトでテスト

ポケミクさんの内蔵エフェクト

 大人の科学 ポケット・ミクにはGM音源に加えて様々なエフェクトがかけられます。説明書によるとリバーブ(29種類)、コーラス(24種類)、インサーション(181種類)と234種類もあるみたいです。
 これらの効果はGM音源部だけでなく、もちろんポケットミクさんにもかけることができます。ということで早速テストしてみました。

エフェクトかけるためにMIDIのお勉強

 といっても大人の科学のマニュアルには全然詳しいことが書いていないので、ポケミクで使われている音源チップNSX-1のデータシートをみることにします。
 ただ、この仕様書結構難しいというか、MIDIの知識があることを前提に書かれているので結構初心者には分かりにくかったりします。エフェクトに関して参考にしたのは以下のサイトとかです。

XGデータ制作講座

 なんというか結構MIDI関連の情報は見た感じから年季の入ったサイトが多いですね(10年くらい前の感じ)、そして結構そのまま知識が使えるからいかにMIDIがレガシーな規格かがわかります。未だにこれが生き残ってWeb MIDIとして不思議進化しようとしているんだからビックリですね。
 そして、エフェクトには通常システムエフェクトとインサーションエフェクトの2種類あり、リバーブ、コーラスは通常システムエフェクトですが、バリエーションエフェクト(VARIATION EFFECT)と呼ばれるものはシステムエフェクト(SYSTEM EFFECT)、インサーションエフェクト(INSERTION EFFECT)と切り替えられるらしいのですが、私はここで盛大にはまりました。実はポケット・ミクのバリエーションエフェクトはインサーションエフェクトとしては使えず、システムエフェクトとしてしか使えないようなのです。仕様書の11pにも確かにそうとれるような表現があるのですが非常に分かりにくい。大人の科学のマニュアルにもインサーションって表現使っているからより分かりにくいです。一言書いてくれればよいのに。
 ネットだとあんまりここらへんの情報を詳しく書いてあるところもなかったので、ここの情報で同じ被害者が一人でも救われることを祈ります。結構あきらめたり、ミクさんの声にはエフェクトかけられないと思っている人も多そう。

エフェクト使うためのMIDIコマンド具体例

 例えばディレイをかけたいときは、具体的なMIDIコマンドは以下になります。仕様書と以下のコマンドを見比べれば分かる人には分かるし分からない人には分からないです(当たり前)。適当なMIDIシーケンサからコマンド送ってやって下さい。私はよいソフトをもっていないので仕方なく自作しました。

0xF0, 0x43, 0x10, 0x4C, 0x02, 0x01, 0x5A, 0x01, 0xF7
まずはこのコマンドでバリエーションエフェクトをシステムエフェクトに設定します。これ重要。
まあ良くわからない人はおまじないと思って下さい。

0xB0, 0x5E, 0x7F
1ch(ポケット・ミクさんのパート)からのセンドパラメータを設定します。大きいほど効果が大きくなります。
0xB0で1chを指定して、0x5Eがセンドパラメータの指定、0x7Fがパラメータの値を示しています。

0xF0, 0x43, 0x10, 0x4C, 0x02, 0x01, 0x56, 0x7F, 0xF7
センドでおくられたものをリターンしてやりましょう。

0xF0, 0x43, 0x10, 0x4C, 0x02, 0x01, 0x40, 0x05, 0x00, 0xF7
エフェクトの種類を指定しています。最後の 0x05, 0x00でDELAYを指定しています。

 バリエーションエフェクトの181種類のナンバは仕様書を見ればわかります。さらにエフェクトの細かい設定も仕様書を見ればわかります。うんざりするほど沢山パラメータあります。

動画


ポケミク職人の朝は早い 朝からポケミクのエフェクトをテストするのである

 とりあえずテストしてみた動画です。ディレイとピッチシフトをかけています。

今後

 とりあえずパラメータ設定とかしやすいポケミクエフェクタ的なものを作ってみようかなと思います。あとはちゃんと演奏動画も作ってみたいですね。

関連記事

ポケット・ミク関連情報まとめ - karaage. [からあげ]
Processingでポケット・ミクの簡易シーケンサを自作してみました - karaage. [からあげ]

 自作ソフトのソースコードとか欲しい奇特な人は続きを読んでみて下さい。
Processing2とMac(Mac book pro Retina), OS X 10.9.2で動作確認しています。Windowsでは動かないかも。

使い方

hで「変デジ研究所」としゃべります。dでdelay ON, pでPitch Shift ON。OFFはできないクソ仕様です。

ソースコード

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


byte[] data0= {(byte)0xF0, (byte)0x43, (byte)0x10, (byte)0x4C, // header(SysEx)
               (byte)0x02, (byte)0x01, (byte)0x5A, (byte)0x01, // set System Effect
               (byte)0xF7  // footer(SysEx)
             };


byte[] data1= {(byte)0xB0, (byte)0x5E, (byte)0x7F};  // set Send parameter 

byte[] data2= {(byte)0xF0, (byte)0x43, (byte)0x10, (byte)0x4C, // header(SysEx)
               (byte)0x02, (byte)0x01, (byte)0x56, (byte)0x7F, // set Return parameter
               (byte)0xF7  // footer(SysEx)
              };

byte[] data3= {(byte)0xF0, (byte)0x43, (byte)0x10, (byte)0x4C, // header(SysEx)
               (byte)0x02, (byte)0x01, (byte)0x40, (byte)0x05, (byte)0x00, // set Delay effect
               (byte)0xF7  // footer(SysEx)
             };

byte[] data4= {(byte)0xF0, (byte)0x43, (byte)0x10, (byte)0x4C, // header(SysEx)
               (byte)0x02, (byte)0x01, (byte)0x40, (byte)0x50, (byte)0x00, // set Pitch Shift effect
               (byte)0xF7  // footer(SysEx)
             };


void setup() {
  size(400, 300);
  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);
  text("Press d -> Delay Effect", 15, 150);
  text("Press p -> Pitch shift effect", 15, 200);
}

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 == 'd'){
    mo_vocaloid = ms.openMidiOutput(2);     // OSX specific
    mo_vocaloid.sendMidi(data0);             // OSX specific
    mo_vocaloid.sendMidi(data1);             // OSX specific
    mo_vocaloid.sendMidi(data2);             // OSX specific
    mo_vocaloid.sendMidi(data3);             // OSX specific
  }

  if(key == 'p'){
    mo_vocaloid = ms.openMidiOutput(2);     // OSX specific
    mo_vocaloid.sendMidi(data0);             // OSX specific
    mo_vocaloid.sendMidi(data1);             // OSX specific
    mo_vocaloid.sendMidi(data2);             // OSX specific
    mo_vocaloid.sendMidi(data4);             // OSX specific
  }

  if(key == 'h'){
    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();
}