topical media & game development
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.