Sound Spectrum 2012-7-16
/**
* Copyright bongiovi015 ( http://wonderfl.net/user/bongiovi015 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/queY
*/
package {
import com.adobe.utils.AGALMiniAssembler;
import com.adobe.utils.PerspectiveMatrix3D;
import flash.display.Sprite;
import flash.display3D.Context3D;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.events.Event;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundLoaderContext;
import flash.media.SoundMixer;
import flash.net.URLRequest;
import flash.utils.ByteArray;
import frocessing.color.ColorHSL;
import net.hires.debug.Stats;
[SWF(width=465, height=465, frameRate=30, backgroundColor=0)]
public class SoundSpectrum0715 extends Sprite {
public const INDEX : Vector.<uint> = Vector.<uint>([0, 1, 2, 0, 2, 3]);
public const MAX_DEPTH : int = 4;
public const NUM_SAMPLE : int = 32;
public const NUM_LINES : int = 60;
public const SPAN : Number = 8;
public const PARTICLE_SIZE : Number = 4;
public var context:Context3D;
public var W:int;
public var H:int;
private var _modelMatrix:Matrix3D;
private var _projectionMatrix:PerspectiveMatrix3D;
private var _particles:Vector.<Particle>;
private var _vbuffer:VertexBuffer3D;
private var _ibuffer:IndexBuffer3D;
private var _sound:Sound;
private var _channel:SoundChannel;
private var _bytes:ByteArray = new ByteArray;
private var soundData:Array;
public function SoundSpectrum0715() {
W = stage.stageWidth;
H = stage.stageHeight;
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, _onContext);
stage.stage3Ds[0].requestContext3D();
addChild(new Stats).y = H-100;
}
protected function _onContext(e:Event) : void {
context = stage.stage3Ds[0].context3D;
context.configureBackBuffer(W, H, 1, true);
_init();
}
protected function _init() : void {
var scale:Number = 2/W;
_modelMatrix = new Matrix3D();
_modelMatrix.appendScale(scale, -scale, 1);
_projectionMatrix = new PerspectiveMatrix3D();
_projectionMatrix.perspectiveFieldOfViewLH(45*Math.PI/180, W/H, 0.1, 1000);
_initParticles();
_initBuffer();
_initShader();
_sound = new Sound;
var soundContext:SoundLoaderContext = new SoundLoaderContext(10, true);
var s:String = "http://www.bongiovi.tw/wonderfl/wumm.mp3";
_sound.load(new URLRequest(s), soundContext);
_channel = _sound.play(0, 5);
addEventListener(Event.ENTER_FRAME, _loop);
}
private function _loop(e:Event) : void {
context.clear(0, 0, 0, 0);
_updateParticlesData();
var viewMatrix:Matrix3D = new Matrix3D();
var center:Vector3D = new Vector3D(0, 0, MAX_DEPTH/2);
viewMatrix.appendRotation( -(stage.mouseX / stage.stageWidth-.5) * 60, new Vector3D(0, 1, 0), center);
viewMatrix.appendRotation( -(stage.mouseY / stage.stageHeight-.5) * 60, new Vector3D(1, 0, 0), center );
var mtx:Matrix3D = _modelMatrix.clone();
mtx.append(viewMatrix);
mtx.append(_projectionMatrix);
context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mtx, true);
context.setVertexBufferAt(0, _vbuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
context.setVertexBufferAt(1, _vbuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
context.drawTriangles(_ibuffer);
context.present();
}
private function _updateParticlesData() : void {
var i:int, j:int, index:int;
SoundMixer.computeSpectrum(_bytes, true);
var datas:Array = [];
for ( i=0; i<NUM_SAMPLE; i++) datas.push(_bytes.readFloat());
soundData.shift();
soundData.push(datas);
var color:ColorHSL = new ColorHSL();
color.h = 0;
color.s = .25;
color.l = .75;
for ( j=0; j<NUM_SAMPLE; j++) {
for(i=0; i<NUM_LINES; i++) {
index = j*NUM_LINES + i;
var p:Particle = _particles[index];
var offset:Number = Math.sin(i/NUM_LINES * Math.PI);
offset = Math.pow(offset, 3);
color.h = soundData[i][j] * 120;
color.l = offset * .8 - (.6-soundData[i][j] * .6);
p.r = color.r/255;
p.g = color.g/255;
p.b = color.b/255;
p.z = 2 - soundData[i][j] * .4 * offset;
}
}
_vbuffer = getVertexBufferFromParticles(context, _particles, PARTICLE_SIZE);
}
private function _initParticles() : void {
_particles = new Vector.<Particle>();
var i:int, j:int;
var totalWidth:Number = SPAN * NUM_LINES;
var totalHeight:Number = SPAN * NUM_SAMPLE;
var sx:Number = -totalWidth/2;
var sy:Number = -totalHeight/2;
soundData = [];
for (i=0; i<NUM_LINES; i++) {
soundData[i] = [];
}
for ( j=0; j<NUM_SAMPLE; j++) {
for(i=0; i<NUM_LINES; i++) {
var p:Particle = new Particle(i*SPAN+sx, j*SPAN+sy, 1.5, 1, 1, 1, 1);
_particles.push(p);
soundData[i][j] = 0;
}
}
}
private function _initBuffer() : void {
var index:int = 0, i:int;
var iBuf:Vector.<uint> = new Vector.<uint>(_particles.length*6);
for ( i=0; i<_particles.length; i++) {
for (var j:int=0; j<INDEX.length; j++) {
iBuf[index++] = INDEX[j] + i*4;
}
}
_ibuffer = context.createIndexBuffer(iBuf.length);
_ibuffer.uploadFromVector(iBuf, 0, iBuf.length);
}
private function _initShader() : void {
var agal:AGALMiniAssembler = new AGALMiniAssembler;
var code:String = "";
code += "m44 op, va0, vc0\n";
code += "mov v0, va1\n";
var vertexShader:ByteArray = agal.assemble(Context3DProgramType.VERTEX, code);
code = "mov oc, v0\n";
var fragmentShader:ByteArray = agal.assemble(Context3DProgramType.FRAGMENT, code);
var program:Program3D = context.createProgram();
program.upload(vertexShader, fragmentShader);
context.setProgram(program);
}
public static function getVertexBufferFromParticles(context:Context3D, ps:Vector.<Particle>, size:Number=10) : VertexBuffer3D {
var numVertices:int = ps.length * 4;
var vbuffer:VertexBuffer3D = context.createVertexBuffer(numVertices, 6);
var vbuf:Vector.<Number> = new Vector.<Number>(numVertices * 6);
var index:int = 0, i:int=0;
for (i=0; i < ps.length; i++) {
vbuf[index++] = ps[i].x-size;
vbuf[index++] = ps[i].y-size;
vbuf[index++] = ps[i].z;
vbuf[index++] = ps[i].r;
vbuf[index++] = ps[i].g;
vbuf[index++] = ps[i].b;
vbuf[index++] = ps[i].x+size;
vbuf[index++] = ps[i].y-size;
vbuf[index++] = ps[i].z;
vbuf[index++] = ps[i].r;
vbuf[index++] = ps[i].g;
vbuf[index++] = ps[i].b;
vbuf[index++] = ps[i].x+size;
vbuf[index++] = ps[i].y+size;
vbuf[index++] = ps[i].z;
vbuf[index++] = ps[i].r;
vbuf[index++] = ps[i].g;
vbuf[index++] = ps[i].b;
vbuf[index++] = ps[i].x-size;
vbuf[index++] = ps[i].y+size;
vbuf[index++] = ps[i].z;
vbuf[index++] = ps[i].r;
vbuf[index++] = ps[i].g;
vbuf[index++] = ps[i].b;
}
vbuffer.uploadFromVector(vbuf, 0, numVertices);
return vbuffer;
}
}
}
class Particle {
public var x:Number;
public var y:Number;
public var z:Number;
public var r:Number;
public var g:Number;
public var b:Number;
public var a:Number;
public function Particle(_x:Number, _y:Number, _z:Number, _r:Number, _g:Number, _b:Number, _a:Number) {
x = _x;
y = _y;
z = _z;
r = _r;
g = _g;
b = _b;
a = _a;
}
}