Music Blocks
A blocky musical experiment.
/**
* Copyright royi ( http://wonderfl.net/user/royi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/6ofs
*/
package {
import flash.events.MouseEvent;
import flash.utils.getTimer;
import flash.events.Event;
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.display.Sprite;
import com.bit101.components.*;
[SWF(width=465, height=465, backgroundColor=0x000000, frameRate=60)]
public class Main extends Sprite {
private static const SAMPLE_RATE:int = 44100;
private static const SAMPLE_TIME:Number = 1 / 44100;
private static const BUFFER:int = 3072;
private var sound:Sound = new Sound();
private var sine:Vector.<Number> = new Vector.<Number>(SAMPLE_RATE);
private var freq:Number = 440;
private var amplitude:Number = 0;
private var soundPos:Number = 0;
private var notes:Array;
private var note:int = 0;
private var attacking:Boolean;
private var attack:Number = .0005;
private var decay:Number = .9997;
private var speed:Number = .3;
private var pool:Array = [];
private var canvas:Sprite = new Sprite();
private var frame:Number, lastFrame:Number, delta:Number;
private var tick:Number = 0;
private var sw:int, sh:int;
private var debug:Label;
public function Main() {
sw = stage.stageWidth;
sh = stage.stageHeight;
canvas.graphics.beginFill(0x261d33);
canvas.graphics.drawRect(0, 0, sw, sh);
canvas.graphics.endFill();
addChild(canvas);
var pos:Number = 0;
for (var i:int = 0; i < SAMPLE_RATE; i++) {
pos = i / SAMPLE_RATE;
sine[i] = Math.sin(Math.PI * 2 * pos);
}
notes = [-2,0,
2,5,3,3,7,5,5,10,9,10,5,2,
-2,0,2,3,5,7,5,3,2,0,2,-2,
-3,-2,0,-7,-3,0,3,2,0,2,-2,0,
2,5,3,3,7,5,5,10,9,10,5,2,
-2,0,2,0,5,3,2,0,-2,-7,-2,-3,
-2,2,5,10,5,2,-2,2,5,10,,-15,
2,,-17,3,,-15,5,,-17,5,,-19,
5,,-17,3,,-15,3,,-14,2,,-12,
0,-7,-5,-3,0,-2,0,3,2,3,0,-3,
-7,-3,0,3,2,0,2,-2,0,2,5,3,
3,7,5,5,10,9,10,5,2,-2,0,2,
-5,5,3,2,0,-2,-7,-2,-3,-2];
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
sound.play();
this.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
lastFrame = getTimer();
addEventListener(Event.ENTER_FRAME, loop);
debug = new Label(this);
}
private function onMouseMove(e:MouseEvent):void {
//debug.text = String(mouseX * .000001);
decay = 1-(mouseY * .000001);
attack = mouseX * .000001;
speed = (mouseX * -.001) + .6;
}
private function loop(e:Event):void {
for (var i:int = 0; i < pool.length; i++) {
pool[i].update();
}
frame = getTimer();
delta = (frame - lastFrame) / 1000;
lastFrame = frame;
tick += delta;
if (tick >= speed) {
tick = tick % speed;
doTick();
}
}
private function doTick():void {
if (notes[note] == null) {
note++;
if (note >= notes.length)
note = 0;
return;
}
for (var i:int = 0; i < pool.length; i++) {
pool[i].gotoX -= pool[i].width;
}
var block:Block = newBlock();
block.gotoX = sw - block.width;
block.y = (sw * .5) - (notes[note] * (block.height * .3))-100;
block.affect(notes[note]);
playNote(notes[note]);
note++;
if (note >= notes.length)
note = 0;
}
private function playNote(noteNumber:int):void {
amplitude = 0;
freq = Math.pow(2, noteNumber / 12) * 440;
attacking = true;
}
private function newBlock():Block {
for (var i:int = 0; i < pool.length; i++) {
if (pool[i].x < -pool[i].width) {
return pool[i];
}
}
var block:Block = new Block();
canvas.addChild(block);
pool.push(block);
return block;
}
private function onSampleData(e:SampleDataEvent):void {
var pos:int;
var sample:Number;
for (var i:int = 0; i < BUFFER; i++) {
pos = (SAMPLE_RATE * freq * soundPos) % SAMPLE_RATE;
sample = sine[pos] * amplitude;
e.data.writeFloat(sample);
e.data.writeFloat(sample);
soundPos += SAMPLE_TIME;
if (attacking) {
amplitude += attack;
if (amplitude >= .5)
attacking = false;
} else {
amplitude *= decay;
}
}
}
}
}
import flash.geom.ColorTransform;
import flash.display.Sprite;
class Block extends Sprite {
public var vr:Number = 0;
public var vx:Number = 0;
public var vy:Number = 0;
public var gravity:Number = .02;
public var gotoX:int = 0;
private var colorTransform:ColorTransform = new ColorTransform();
public function Block() {
graphics.beginFill(0xffffff);
graphics.drawRect(-15, -15, 30, 30);
graphics.endFill();
}
public function affect(noteValue:int = 0):void {
vr = noteValue * .1;
vy = -.2;
scaleX = scaleY = (noteValue * .04)+1;
colorTransform.color = (noteValue * 50) + 44651000;
transform.colorTransform = colorTransform;
}
public function update():void {
rotation += vr;
rotationX += vr;
vy += gravity;
x += vx;
y += vy;
x += (gotoX - x) * .5;
}
}