音出し

あの楽器の画面エフェクトが とりあえず終わった(?)ので次は音出しの実装。

とりあえず試したいひとは こちら

  • 縦にドラッグすると音量が変化します。Windowsの方は、ボリュームの画面で SWシンセサイザのボリュームを最大にしておいてください。
  • 左上のメッセージは、上の段が、MIDIOUTのデバイス名、下の段がプログラム番号(音色)です。それぞれの文字の 左端をクリックすると デバイス名、プログラム番号が変化します。

音出しはMidiOutに依存する。さっそく processing用のMIDIライブラリをグーグル様に問い合わせると、ありました proMIDI。sampleがついてたので色々ためす。おお音が出る。いいぞいいぞ。。。。

あれ sendNote はあるけど、NoteOn NoteOff が 送信できないじゃないですか。これはいけません。ピアノみたいに 音が減衰するやつはいいけど、オルガンみたいな鳴りっぱなしの音を人の操作で止める方法がない。それに和音の実装ができないですなこれじゃ。和音はNoteOnをまとめて送って、NoteOff するって実装になるはず。ありゃ、これは使えないです。

どうやら、これはMIDI Inでイベントを取るのを主目的にしたライブラリの模様。このライブラリの利用は断念。

では 次はと、グーグル様に問い合わせると、RWMidiいいよ とのこと、ダウンロードはこちら。これには NoteOn NoteOff があるのを確認。でも sample、ドキュメントがいまいち不親切と感じた。

ともあれ 実装開始。

import rwmidi.*;
MidiOutput output;
int ch_s = 0;
int pit_s = 60;
int vel_s = 100;

int program_s;
int device_s;

NoteOff へ NoteOn時の情報を渡すための変数を 設定。なんか初期化してあるけど、気にしない(笑) プログラムナンバー、デバイスナンバーもとりあえず保存する。将来、切り替えられるようにね(^^

void setup() {
size( 800,380 );
device_s = 0;
program_s = 0;
output = RWMidi.getOutputDevices()[device_s].createOutput();
output.sendProgramChange(program_s);
println( output.getName() );
}

画面、デバイスNo,プログラムNo とか初期値設定して MidiOutputを作成して、プログラムNoを送っておく。

音出しするだけなら、draw は 何もかかなくて OK。実際は、前回のEffectテストに追加して書いてます。

Mouseのクリックで 音出し開始。とりあえず Volmeの変化はなしの方向で。

void mousePressed() {
// mouseX, mouseY
println( “mouse pressed” );

org_mouseX = mouseX;
org_mouseY = mouseY;
// Midi Out
int iw;
iw = int( width / 24 );
pit_s = 60 + int( mouseX/iw );
//
output.sendNoteOn( ch_s, pit_s, vel_s);
}

mousePressed イベントに記述。org_mouseX,org_mouseY は将来ドラッグして ベロシティの変化とか、ピッチベントに使うので、保存しておく。

まずは、画面の幅を24(2オクターブ幅)で割って、mouseXの位置からPitch(音階)を生成。チャンネル、ベロシティはデフォ値そのまま。で NoteOn!

次はNoteOffを送信。

void mouseReleased() {
println( “mouse released” );
output.sendNoteOff( ch_s, pit_s, vel_s);
}

mouseRelase イベントで NoteOffを送信。 それだけ。

これで 音出しテスト。おお 結構いけてるよこれ。ソース上で プログラムNoを書き換えて音を変更してみる。 OkOk いい感じ。和音もいけるかテスト、3つのNoteOnを書いて、NoteOffを送信。いけてるーー。和音はひとまず外してっと。

こうなると、音量、ピッチベンド つけたくなるよねえ。

※以下のPitchBendの項目勘違いしてます。次の記事参照。

マウスドラッグのイベントで 変更するメッセージ流せばいいんじゃね?

Midiシーケンサ(Cherry)立ち上げて、PitchBendの番号を調べる。153 ね。データの範囲は-8192 ~ +8191 ねぇ。なんか 広いなぁ。

で、とりあえず。Mouseドラッグに 適当に実装。

void mouseDragged() {
// Xdrag で Bent
print( “mouse dragged ” );
println( (mouseX - org_mouseX)*8 );
output.sendController( ch_s, 153, (mouseX - org_mouseX)*8 );
}

まだ、テスト段階だから、適当にマジックナンバー割り当てと。ほい実行。わっ思いっきりエラーだ。なになに、153 が値を超えてる?なんじゃこりゃ と思って調べてみると、

  1. sendoControllerメソッドで扱えるのは 127 までの#CC(コントロールコードの略らしい)
  2. それを越えると、sendSysExメソッドで エクスクルーシブメッセージを自分で作らないといけないらしい。
  3. MIDIのサイトをいくつかめぐってみたが、メッセージの作り方がよくわからん。0xF0で始まって0xF7 で終わるメッセージらしいんだけど、間にメーカーコードとか 入れないといけないようだ。わからんorz。
  4. よさげなサンプルがないかと さぐってみたけどまだ見つけられない。
  5. JavaMIDIのサンプルをさぐってみたほうがいいかもしれない。

ピッチベンドは後回し決定。

※このPitchBendの項目勘違いしてます。次の記事参照。

じゃあ 縦ドラッグで、Volume変更だ。というわけで イベント書いてみた。

void mouseDragged() {

// Ydrag で Volume…
int v = vel_s - ( org_mouseY-mouseY );
if( 0 <= v && v<128 ){
output.sendController( ch_s, 7, v );
}
}

あれ だめじゃん。次のNoteOnのVolumeまで影響してるよ。

調べてみると、ふつう、NoteOn中の音量調整は、11.Expressionでやるらしい。なるほど。で sendController の 7を11 にして 実行。 あれ やっぱりVolume変更の情報残ってるよ(´・ω・`)

じゃ NoteOnの直前に 11.Expression 戻してみるか。

というわけで、実際の実装

mousePressed

output.sendController( ch_s, 11, vel_s );
output.sendNoteOn( ch_s, pit_s, vel_s);

sendNoteOn の前に Expression を リセット

mouseDragged

// Ydrag で Volume…
v = vel_s - int(( org_mouseY-mouseY )/4);
if( v < 0 ){ v=0; }
if( v > 127 ){ v=127; }
output.sendController( ch_s, 11, v );

}

変化の範囲を 1/4 にして、ドラッグの範囲を広げた、値が Expressionの範囲を越えたら 最大値、最小値にする。(ドラッグ処理落ちの対応)

なんとなく いい感じじゃない? これは採用。

で、デバイスの変更と、プログラム(音色)の変更を実装。

mousePressed

if( mouseX<100 && mouseY<40 ){
if( mouseY<20 ){
output.closeMidi();
device_s = device_s+1;
if( device_s >= RWMidi.getOutputDevices().length ){
device_s=0;
}
output = RWMidi.getOutputDevices()[device_s].createOutput();
println( output.getName() );
int retx = output.sendProgramChange(program_s);
} else {
program_s = program_s+1;
int retx = output.sendProgramChange(program_s);
}
} else {

左上 100*40 の範囲は コントロール用。上のクリックで デバイスを変更。注意点は、変更する場合は、一旦閉じないといけないということ。 output.closeMidi()を忘れないでね。getOutPutDevices で デバイスの配列がとれます。クリックが配列数をオーバーしないように処理しています。プログラムNoは、チェックしてないです。127 越えたら 0 にするような処理が必要ですね。Applet には 実装。

あとは、演奏中のデバイス名と、プログラムNoを表示するようにして完成。

※このへんは ソース見てください。Applet画面に ソースへのリンクがあります。

単音 音出し、完了。試してみたい方はここ

  1. エフェクト作成。
  2. (今ここ→)音出し作成。(単音、和音)
  3. 音階ボタン作成。
  4. 音階ボタンから音生成。
  5. 筐体作成。
  6. 完成。

コメントをどうぞ