Home - Flash - Flash : MIDI機器とFlashを連携(その2) - キーボードも使ってみる

Flash : MIDI機器とFlashを連携(その2) - キーボードも使ってみる

  • posted on 2009年2月 5日 15:28 / update 2011年8月26日 19:13 / by hoehoe3

090201_midi2as1.gif

MIDIらしくMIDIキーボードとFlashの連携も実装してみたよ。入力にはnanoKEY(そろった。。)を、音源にはzk33さんのFlashで音生成などオーディオ操作ができるライブラリsazamekiを使ってみました。

早速実装するよ。

sazamekiがよくできてるんでサンプルを数行いじるだけでできました。わーい。
sazamekiはSparkProjectの方で配布されてるんでダウンロードしてきます。ソースはFlashPlayer10用のソース(branchese/fp10/)の方を使います。fp10向けにコンパイルできるように設定は忘れずにね。んで構成はこんな感じ。

090201_midi2as2

いじるサンプルはPCのキーボードを鍵盤の入力に使うやつ(branchese/fp10/sample/SamplerSample.as)を使います。元々入力に使うNoteOn/NoteOffとかイベントまわりはしっかり実装されていてる様子なんで。サンプルからPCキーボード入力の部分を省いていって、入力周りだけを変更していきます。MIDIキーボードの入力→VispでBNAGまで処理(NoteEventクラスがかぶってるので注意)→BangEvent.BANG_ON/BangEvent.BANG_OFFを拾う→sazameki側でNoteOnイベントを投げる、pitchとvelocityも放り込む→音がなる。てな感じ。

package {
 /** 
  * MIDI2AS03.as
  *
  * nanoKEY から入力して音を鳴らすよ。
  *
  **/
  
 import com.visp.events.BangEvent;
 import com.visp.midi.MidiManager;
 import com.visp.midi.NoteEvent;
 
 import flash.display.DisplayObject;
 import flash.display.Sprite;
 import flash.display.StageScaleMode;
 import flash.events.SampleDataEvent;
 import flash.media.Sound;
 import flash.utils.ByteArray;
 
 import org.sazameki.audio.core.AudioSamples;
 import org.sazameki.audio.ctrlEvent.events.NoteOff;
 import org.sazameki.audio.ctrlEvent.events.NoteOn;
 import org.sazameki.audio.engine.MultiSamplePlayer.Instrument;
 import org.sazameki.audio.engine.MultiSamplePlayer.MultiSamplePlayer;
 import org.sazameki.audio.engine.MultiSamplePlayer.NoteRange;
 import org.sazameki.audio.engine.MultiSamplePlayer.ProcessData;
 import org.sazameki.audio.format.wav.Wav;


 public class MIDI2AS03 extends Sprite
 {
  [Embed(source = "asset/bass_c2_9836_10510.wav", mimeType = "application/octet-stream")]
  public const Bass:Class;

  [Embed(source = "asset/Clap.wav", mimeType = "application/octet-stream")]
  public const Clap:Class;
  [Embed(source = "asset/Hat.wav", mimeType = "application/octet-stream")]
  public const Hat:Class;
  [Embed(source = "asset/Kick.wav", mimeType = "application/octet-stream")]
  public const Kick:Class;
  [Embed(source = "asset/Snare.wav", mimeType = "application/octet-stream")]
  public const Snare:Class;
  
  private var sampler:MultiSamplePlayer;
  private var sound:Sound;
  private var procData:ProcessData;
  
  private var _midiMgr:MidiManager;

  public function MIDI2AS03()
  {
   // MIDIマネージャーを作成
   this._midiMgr = MidiManager.getInstance();
   this._midiMgr.initialize();
   // イベントを登録
   this._midiMgr.addEventListener(NoteEvent.NOTE_ON, _handleNoteOn);
   this._midiMgr.addEventListener(NoteEvent.NOTE_OFF, _handleNoteOff);
   this.addEventListener(BangEvent.BANG_ON, _handleBangOn);
   this.addEventListener(BangEvent.BANG_OFF, _handleBangOff);
   
   
   stage.scaleMode = StageScaleMode.NO_SCALE;
   
   var decoder:Wav = new Wav();

   var bassSamples:AudioSamples = decoder.decode(new Bass() as ByteArray);
   var bassInst:Instrument = new Instrument(bassSamples, 9836, 10509, 24);
   
   var clapSamples:AudioSamples = decoder.decode(new Clap() as ByteArray);
   var clapInst:Instrument = new Instrument(clapSamples);
   
   var hatSamples:AudioSamples = decoder.decode(new Hat() as ByteArray);
   var hatInst:Instrument = new Instrument(hatSamples);
   
   var kickSamples:AudioSamples = decoder.decode(new Kick() as ByteArray);
   var kickInst:Instrument = new Instrument(kickSamples);
   
   var snareSamples:AudioSamples = decoder.decode(new Snare() as ByteArray);
   var snareInst:Instrument = new Instrument(snareSamples);
   
   sampler = new MultiSamplePlayer();
   sampler.addInstrument(bassInst, new NoteRange(24));
   sampler.addInstrument(kickInst, new NoteRange(0, 13));
   sampler.addInstrument(hatInst, new NoteRange(18, 23));
   sampler.addInstrument(clapInst, new NoteRange(14, 15));
   sampler.addInstrument(snareInst, new NoteRange(16, 17));
   //prepare processData(sample buffer & event list)
   procData = new ProcessData(2048);
   
   //prepare sound
   sound = new Sound();
   sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSamplesCallback);
   sound.play();

  }
  
  // ノートオンが発生したらBNAG_ONを通知
  private function _handleNoteOn(e:NoteEvent) : void
  {
   if(e.pitch) {
    var bangOn : BangEvent = new BangEvent(BangEvent.BANG_ON, e.pitch, true);
    bangOn.velocity = e.velocity;
    dispatchEvent(bangOn);
   }
  }
  
  // ノートオフが発生したらBANG_OFFを通知
  private function _handleNoteOff(e:NoteEvent) : void
  {
   if(e.pitch){
    var bangOff : BangEvent = new BangEvent(BangEvent.BANG_OFF, e.pitch, true);
    dispatchEvent(bangOff);
   }
  }
  
  // BANG_ONが発生したらsazameki側にイベントを通知
  private function _handleBangOn(e:BangEvent):void
  {
   procData.events.addEvent(new NoteOn(e.id, e.velocity), 0);
  }
  // BANG_OFFが発生したらsazameki側にイベントを通知
  private function _handleBangOff(e:BangEvent):void
  {
   procData.events.addEvent(new NoteOff(e.id), 0);
  }


  private function onSamplesCallback(e:SampleDataEvent):void 
  {

   var left:Vector.<Number>;
   var right:Vector.<Number>;
   
   var audios:AudioSamples = procData.samples;
   
   var len:int = procData.length;
  
   var i:int = 0;
   var sig:Number;
   
   sampler.process(procData);
   
   if (audios.setting.channels == 2)
   {
    left = audios.left;
    right = audios.right;
    for (; i < len; ++i)
    {
     e.data.writeFloat(left[i]);
     e.data.writeFloat(right[i]);
    
    }
   }else
   {
    left = audios.left;
    for (; i < len; ++i)
    {
     sig = left[i];
     e.data.writeFloat(sig);
     e.data.writeFloat(sig);
    }
    
   }
  }
  
 }
}

動かしてみる。

ノートのVelocityにも対応してるんで若干強弱も付けれる。わかんないけど。最後の音が鳴りっぱなしなのはノートオフが取れてない感じ。これでも20回取り直したw

sazamekiおもしれー!。

先の問題は特に解決させずに繋いでみただけ。あんまり速く叩くとMIDI proxyからイベントが送れなくて音が鳴り続けたりするw。sazamekiてば外部からの入力にも便利。よくできてる。あとはユーティリティでソケット通信実装してくたらVispはいらない子。でもMIDI Proxyは手をいれた方がいいなぁ。nanoKONTROLと2つ繋いでで音色変えながらとか楽しそう。

関連エントリ:

参考資料:

COMMENT

Auther
hoehoe: おおさか方面でWebとかやってますよ。
Search
Feeds