topical media & game development

talk show tell print

student-musicpad-MatrixPad.ax

student-musicpad-MatrixPad.ax [swf] [flash] flex


  /*
   * Copyright suweller
   * based on Tenorion by keim_at_Si ( http://wonderfl.net/user/keim_at_Si )
   */
  package {
          import flash.display.*;
          import flash.events.*;
          import flash.geom.*;
  
      import org.si.sion.SiONDriver;
      import org.si.sion.events.*;
      import org.si.sion.utils.SiONPresetVoice;
  
          public class @ax-student-musicpad-MatrixPad extends Bitmap {
          public var driver:SiONDriver;
          public var presetVoice:SiONPresetVoice = new SiONPresetVoice();
  
                  private const NOTE_LENGTH:Number =  0.01;
                  private const LOWEST_NOTE:int    = 36;
  
                  // music variables
                  public var sequences:Vector.<int>;
                  public var lowest_note:int = LOWEST_NOTE;
                  private var _notes:int;
                  private var _steps:int;
  
                  // graphic dimensions
                  private var _note_body:int    = 7;
                  private var _note_border:int  = 1;
                  private var _note_spacing:int = 1;
                  private var _total_height:int;
                  private var _total_width:int;
  
                  // graphic variables
                  private var canvas:Shape = new Shape();
                  private var buffer:BitmapData;
                  private var pad_on:BitmapData;
                  private var pad_off:BitmapData;
                  private var pt:Point = new Point();
  
                  // color transform settings highlighting the current step
                  private var colt:ColorTransform = new ColorTransform(1,1,1,0.2);
  
          // beat counter
          public var beatCounter:int;
  
                  function @ax-student-musicpad-MatrixPad(stage:Stage, d:SiONDriver, notes:int, steps:int) {
                          // set global variables
                          _notes        = notes;
                          _steps        = steps;
                          beatCounter   = 0;
                          driver        = d;
  
                          // calculate global variables
                          _total_height = _notes * note_side();
                          _total_width  = _steps * note_side();
                          sequences     = new Vector.<int>(_steps);
                          for (var i:int = 0; i < _notes; i++) sequences[i] = 0;
  
                          // setup the drawing areas
                          super(new BitmapData(_total_width, _total_height, false, 0));
                          buffer = new BitmapData(_total_width, _total_height, true, 0);
  
                          initialize@ax-student-musicpad-MatrixPad();
  
                          addEventListener("enterFrame", _onEnterFrame);
                          stage.addEventListener("click",  _onClick);
  
              with(driver) {
                      setBeatCallbackInterval(1);
                                  addEventListener(SiONTrackEvent.BEAT, _onBeat);
                      setTimerInterruption(1, _onTimerInterruption);
                          }
                  }
  
                  private function initialize@ax-student-musicpad-MatrixPad() : void {
                          pad_on  = _pad(0x336600, 0x669933);
                          pad_off = _pad(0x666600, 0x333300);
                          for (var __x:int = 0; __x < _steps; __x++) {
                                  for (var __y:int = 0; __y < _notes; __y++) {
                                          pt.x = __x * note_side();
                                          pt.y = __y * note_side();
                                          buffer.copyPixels(pad_off, pad_off.rect, pt);
                                          bitmapData.copyPixels(pad_off, pad_off.rect, pt);
                                  }
                          }
                  }
  
                  private function note_side() : int {
                          return _note_body + (_note_border * 2) + _note_spacing;
                  }
  
                  private function _pad(border:int, face:int) : BitmapData {
                          var pix:BitmapData = new BitmapData(note_side(), note_side(), false, 0);
                          with(canvas.graphics) {
                                  clear();
                                  lineStyle(_note_border, border);
                                  beginFill(face);
                                  drawRect(1, 1, note_side(), note_side());
                                  endFill();
                          }
                          pix.draw(canvas);
                          return pix;
                  }
  
                  private function _onClick(e:Event) : void {
                          if (mouseX >= 0 && mouseX < _total_width && mouseY >= 0 && mouseY < _total_height ) {
                                  var clicked_note:int = (_notes - 1) - int(_notes * mouseY / _total_height);
                                  var clicked_step:int = int(_steps * mouseX / _total_width);
  
                                  sequences[clicked_note] ^= 1 << clicked_step;
                                  pt.x = clicked_step * note_side();
                                  pt.y = ( (_notes - 1) - clicked_note) * note_side();
  
                                  if (sequences[clicked_note] & (1 << clicked_step)) {
                                          buffer.copyPixels(pad_on, pad_on.rect, pt);
                                  } else {
                                          buffer.copyPixels(pad_off, pad_off.rect, pt);
                                  }
                          }
                  }
  
                  private function _onEnterFrame(e:Event) : void {
                          bitmapData.draw(buffer, null, colt);
                  }
  
          // _onBeat (SiONTrackEvent.BEAT) is called back in each beat at the sound timing.
          private function _onBeat(e:SiONTrackEvent) : void {
              var beat16th:int = e.eventTriggerID & (_steps - 1);
  
                          for (pt.x = beat16th * note_side(), pt.y = 0; pt.y < _total_height; pt.y += note_side()) {
                                  bitmapData.copyPixels(pad_on, pad_on.rect, pt);
                          }
                  }
  
          // _onTimerInterruption (SiONDriver.setTimerInterruption) is called back in each beat at the buffering timing.
          public function _onTimerInterruption() : void {
              var beatIndex:int = beatCounter & (_steps - 1);
  
              for (var i:int = 0; i < _notes; i++) {
                  if (sequences[i] & (1 << beatIndex)) {
                                          driver.noteOn(lowest_note + i, presetVoice["default.saw"], NOTE_LENGTH);
                                  }
              }
              beatCounter++;
          }
  
          }
  
  }
  


(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.