2009年7月4日土曜日

モーツァルトを弾いてみた。

Flex Builder 3で、Flash Player 10の新機能ダイナミックサウンドを利用してみた。Flex Builder 3で、Flash Player 10の機能を利用する方法は、前回の投稿を参考にしてもらいたい。

20年以上前のパソコンについていた、演奏機能のようなものが出来上がった。コードは、次のとおり。

package {
   import flash.events.Event;
   import flash.events.EventDispatcher;
   import flash.events.SampleDataEvent;
   import flash.events.TimerEvent;
   import flash.media.Sound;
   import flash.media.SoundChannel;
   import flash.utils.Timer;

   public class Sampling extends EventDispatcher {
     private const FREQ:Number = 261.63;
     private const BASE_RATE:Number = 44100;
     private var _rate:Number = 44100;
     private var _noise:Number = 0;

     private var _tones:Object = new Object();
     private var _timer:Timer;

     private var _rateArray:Array = new Array ();

     private var _sound:Sound = new Sound();
     private var _soundChannelObject:SoundChannel = new SoundChannel ();

     public function Sampling() {
      _tones["R"] = 0;
      _tones["C"] = 261.63/220/2;
      _tones["D"] = 293.67/220/2;
      _tones["E"] = 329.63/220/2;
      _tones["F"] = 349.23/220/2;
      _tones["G"] = 392.00/220/2;
      _tones["A"] = 1;
      _tones["B"] = 233.08/220;
      _tones["H"] = 246.94/220;
      _timer = new Timer (80,0)
      _sound.addEventListener (SampleDataEvent.SAMPLE_DATA, samplingHandler);
    }

     private function parse(notes:String):void {
       var note:String;
       var l:int;
       var i:int;
       var arr:Array = notes.split(/(\d+)/);
       while(arr.length > 0) {
         note = arr.shift();
         l = 32/parseInt(arr.shift())-1;

         for(i=0;i < l;i++) {
           _rateArray.push(_tones[note]/BASE_RATE);
        }
        _rateArray.push(0);
      }
    }

     public function play(score:String):void {
      parse(score);
      _timer.addEventListener (TimerEvent.TIMER, timerHandler);
    _timer.start ();
    _soundChannelObject = _sound.play();
    }

     private function timerHandler(e:TimerEvent):void {
       if (!_rateArray.length) {
        _timer.stop ();
        _timer.removeEventListener(TimerEvent.TIMER, timerHandler);
        _soundChannelObject.stop ();
        dispatchEvent (new Event(Event.COMPLETE));
      }
      _rate = _rateArray.shift();
    }

     private function samplingHandler(e:SampleDataEvent):void {
       var samples:Number;
       var s:Number;
       for(var i:int=0; i<2048; i++){
        _noise += (FREQ) * _rate;
        samples = _noise * Math.PI * 2;
        s = (Math.cos(samples) + Math.cos(samples*2) + Math.cos(samples*4))/3;
        e.data.writeFloat(s);
        e.data.writeFloat(s);
      }
    }
  }
}


このクラスの使い方は、こんな感じになる。

var sampling:Sampling = new Sampling();
sampling.play("C4C4G4G4A4A4G2F4F4E4E4D4D4C2G4G4F4F4E4E4D2G4G4F4F4E4E4D2C4C4G4G4A4A4G2F4F4E4E4D4D4C2");



以上は、このページを参考にさせてもらった。