topical media & game development

talk show tell print

student-mma-16-Clip.mx

student-mma-16-Clip.mx [swf] flex


  <?xml version="1.0" encoding="utf-8"?>
  <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="64" height="78">
   <mx:Script>
    <![CDATA[
     import mx.controls.Alert;
     import mx.controls.Image;
     import mx.controls.Label;
     import de.popforge.audio.output.Audio;
     import de.popforge.audio.output.Sample;
     import de.popforge.format.wav.*;
     
     public static var 
      GREEN:int = 0,
      RED:int = 1,
      BLUE:int = 2,
      YELLOW:int = 3,
      
      STATE_ERROR:int = -1,
      STATE_INACTIVE:int = 0,
      STATE_LOADING:int = 1,
      STATE_IDLE:int = 2,
      STATE_PLAYING:int = 3,
      
      TYPE_NOLOOP:int = 0,
      TYPE_LOOP:int = 1;
     
     public var color:int;
     public var url:String = "";
     public var title:String = "";
     public var type:int = TYPE_NOLOOP;
     public var length:int = 1;
     
     public var lastX:Number; //last steady position (before dragging)
     public var lastY:Number;
     public var lastParent:String; //parent of clip in last steady position
     
     public var state:int = STATE_INACTIVE;
     public var sequencer:student_mma_16_Sequencer;
     public var sequencerSlot:int;
     
     private var wav:WavFormat;
     
     private var progressBar:Shape;
     private var img:Image;
     
     private var c:int = 0;     //clip sample iterator
     private var numSamples:int;
     private var startSample:uint = 0;  //the first buffer sample to add sound to, specified by the sequencer
     private var progressTimer:student_mma_16_MyTimer;
     private var clipLength:uint;   //length of clip in ms
     private var progressCount:uint = 0;
     private var firstRun:Boolean = true;
     private var inited:Boolean = false;
     
     internal var onComplete:Function;
     
     public function init():void {
      if(!inited) {
       setImage();
       setLabel();
       createSound(url);
      }
      else
       state = STATE_IDLE;
     }
     
     
prepare the clip to be launched by the sequencer

  
     public function start(sequencer:student_mma_16_Sequencer):void {
      this.sequencer = sequencer;
      sequencerSlot = sequencer.getSlot(this);
      c = 0;
      progressCount = 0;
     }
     
     
starts the clip launch

  
     internal function launch(startSample:uint = 0):void {
      this.startSample = startSample;
      if(state == STATE_IDLE) {
       state = STATE_PLAYING;
       onComplete = onAudioBufferComplete;
       firstRun = true;
      }
     }
     
     private function loadComplete(e:Event):void {
      wav = WavFormat.decode(ByteArray(e.target.data));
      state = STATE_IDLE;
      inited = true;
      progressBar.graphics.clear();
      
      clipLength = (60 / student_mma_16_Sequencer.BPM) * 4 * length * 1000;
      //make sure the length in samples is correct
      if(type == TYPE_NOLOOP) {
       numSamples = wav.samples.length;
      }
      else {
       numSamples = Math.ceil(44.1 * clipLength);
       if(numSamples > wav.samples.length) {
        //add silent samples at the end
        Alert.show("adding samples");
        for(var i:int = 0; i < numSamples - wav.samples.length; i++) {
         wav.samples.push(new Sample());
        }
       }
      }
      
      
     }
     
     internal function onAudioBufferComplete(buffer: student_mma_16_AudioBuffer): void {
      if(state != STATE_PLAYING) return;
      if(firstRun) {
       //start the progress bar when the audio starts
       var timer:Timer = new Timer(Math.floor(startSample / 44.1 + buffer.numSamples / 44.1), 1);
       timer.addEventListener(TimerEvent.TIMER, startPlayProgressTimer);
       timer.start();
       firstRun = false;
      }
      var samples: Array = buffer.getSamples();
      
      for(var i:int = startSample; i < samples.length; i++) {
       samples[i].left = wav.samples[c].left;
       samples[i].right = wav.samples[c].right;
       c++;
       if(c == wav.samples.length) {
        if(type == TYPE_NOLOOP) {
         stop();
         break;
        }
        c = 0;
       }
      }
      buffer.update();
      startSample = 0;
     }
     
     public function stop():void {
      sequencer.freeSlot(sequencerSlot);
      state = STATE_IDLE;
      img.alpha = 0.5;
      progressTimer.stop();
      progressBar.graphics.clear();
     }
     
     
set clip to inactive

  
     public function remove():void {
      if(state == STATE_PLAYING)
       stop();
      state = student_mma_16_Clip.STATE_INACTIVE;
     }
     
     public function setVolume(vol:Number):void {
      sequencer.changeSlotVolume(sequencerSlot, vol);
     }
     
     private function setImage():void {
      var src:String = "student-mma-16-img-final-";
      
      switch(color) {
       case RED: src += "loop-red.png"; break;
       case BLUE: src += "loop-blue.png"; break;
       case YELLOW: src += "loop-yellow.png";break;
       default: src += "loop-green.png";
      }
      
      img = new Image();
      img.source = src;
      img.width = 64;
      img.height = 78;
      img.alpha = 0.5;
      this.addChild(img);
     }
     
     private function setLabel():void {
      var label:Label = new Label();
      label.text = title;
      label.x = 10;
      label.y = 24;
      label.styleName = "loopLabel";
      label.truncateToFit = false;
      label.width = 46;
      label.setStyle("color", getColor(color));
      this.addChild(label);
     }
     
     private function createSound(url:String):void {
      var loader:URLLoader = new URLLoader();  
      loader.dataFormat = URLLoaderDataFormat.BINARY;  
      loader.addEventListener(Event.COMPLETE, loadComplete );
      loader.addEventListener(IOErrorEvent.IO_ERROR, loadError );
      loader.addEventListener(ProgressEvent.PROGRESS, updateProgress);
      createProgressBar();
      loader.load( new URLRequest(url));
     }
     
     public static function getColor(color:int):uint {
      switch(color) {
       case RED: return 0x7d0000;
       case BLUE: return 0x00527d;
       case YELLOW: return 0x7c7d00;
       default: return 0x007d11;
      }
     }
     
     private function createProgressBar():void {
      progressBar = new Shape();
      this.rawChildren.addChild(progressBar);
     }
     
     private function startPlayProgressTimer(e:TimerEvent):void {
      var reps:int = (type == TYPE_LOOP ? 0 : 10);
      progressTimer = new student_mma_16_MyTimer(clipLength / 10, reps, updatePlayProgress);
      progressTimer.start();
      img.alpha = 1;
     }
     
     private function updatePlayProgress():void {
      progressCount++;
      if(progressCount > 10) progressCount = 1;
      
      var width:int = (progressCount / 10) * 62;
      progressBar.graphics.clear();
      progressBar.graphics.beginFill(0xFFFFFF);
      progressBar.graphics.drawRect(1, 65, width, 12);
     }
     
     private function updateProgress(e:ProgressEvent):void {
      var width:int = (e.bytesLoaded / e.bytesTotal) * 62;
      progressBar.graphics.clear();
      progressBar.graphics.beginFill(0xFFFFFF);
      progressBar.graphics.drawRect(1, 65, width, 12);
     }
     
     private function loadError(e:IOErrorEvent):void {
      state = STATE_ERROR;
     }
    ]]>
   </mx:Script>
   
   
  </mx:Canvas>
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.