SoundSpectrum 2012-7-17 02
/**
* Copyright bongiovi015 ( http://wonderfl.net/user/bongiovi015 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/h2bn
*/
package {
import com.adobe.utils.AGALMiniAssembler;
import com.adobe.utils.PerspectiveMatrix3D;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.Shape;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DTextureFormat;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.display3D.textures.Texture;
import flash.events.Event;
import flash.geom.Matrix;
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 flash.display.Sprite;
import flash.display3D.Context3D;
import flash.events.Event;
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/2;
public const NUM_LINES : int = 120/2;
public const SPAN : Number = 20;
public const PARTICLE_SIZE : int = 7;
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();
_initTexture();
_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 _initTexture() : void {
var textureSize:Number = 256;
var strokeWeight:Number = 5;
var s:Shape = new Shape();
s.graphics.beginFill(0x000000, 1);
s.graphics.drawRect(0, 0, textureSize, textureSize);
s.graphics.endFill();
s.graphics.beginFill(0xFFFFFF, 1);
s.graphics.drawRect(strokeWeight, strokeWeight, textureSize-strokeWeight*2, textureSize-strokeWeight*2);
s.graphics.endFill();
var texture:Texture = context.createTexture(textureSize, textureSize, Context3DTextureFormat.BGRA, false);
var ws:int = textureSize;
var hs:int = textureSize;
var tmp:BitmapData;
var level:int=0;
var transform:Matrix = new Matrix();
tmp = new BitmapData(s.width, s.height, true, 0x00000000);
while ( ws >= 1 && hs >= 1 ) {
tmp.draw(s, transform, null, null, null, true);
texture.uploadFromBitmapData(tmp, level);
transform.scale(0.5, 0.5);
level++;
ws >>= 1;
hs >>= 1;
if (hs && ws) {
tmp.dispose();
tmp = new BitmapData(ws, hs, true, 0x00000000);
}
}
tmp.dispose();
context.setTextureAt(0, texture);
}
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) * 180, new Vector3D(0, 0, 1), center);
viewMatrix.appendRotation( -(stage.mouseY / stage.stageHeight-.5) * 180, 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_2);
context.setVertexBufferAt(2, _vbuffer, 5, 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;
}
}
_getVertexBufferFromParticles();
}
private function _getVertexBufferFromParticles() : void {
var numVertices:int = _particles.length * 4;
_vbuffer = context.createVertexBuffer(numVertices, 8);
var vbuf:Vector.<Number> = new Vector.<Number>(numVertices * 8);
var index:int = 0, i:int, j:int, tempIndex:int, ti:int, tj:int;
var r:Number, g:Number, b:Number;
for (j=0; j<NUM_SAMPLE; j++) {
for (i=0; i<NUM_LINES; i++) {
tempIndex = j*NUM_LINES + i;
vbuf[index++] = _particles[tempIndex].x;
vbuf[index++] = _particles[tempIndex].y;
vbuf[index++] = _particles[tempIndex].z;
vbuf[index++] = 0;
vbuf[index++] = 0;
vbuf[index++] = _particles[tempIndex].r;
vbuf[index++] = _particles[tempIndex].g;
vbuf[index++] = _particles[tempIndex].b;
r = _particles[tempIndex].r;
g = _particles[tempIndex].g;
b = _particles[tempIndex].b;
ti = i == NUM_LINES-1 ? i : i+1;
tj = j;
tempIndex = tj*NUM_LINES + ti;
vbuf[index++] = _particles[tempIndex].x;
vbuf[index++] = _particles[tempIndex].y;
vbuf[index++] = _particles[tempIndex].z;
vbuf[index++] = 1;
vbuf[index++] = 0;
vbuf[index++] = r;
vbuf[index++] = g;
vbuf[index++] = b;
ti = i == NUM_LINES-1 ? i : i+1;
tj = j == NUM_SAMPLE-1 ? j : j+1;
tempIndex = tj*NUM_LINES + ti;
vbuf[index++] = _particles[tempIndex].x;
vbuf[index++] = _particles[tempIndex].y;
vbuf[index++] = _particles[tempIndex].z;
vbuf[index++] = 1;
vbuf[index++] = 1;
vbuf[index++] = r;
vbuf[index++] = g;
vbuf[index++] = b;
ti = i;
tj = j == NUM_SAMPLE-1 ? j : j+1;
tempIndex = tj*NUM_LINES + ti;
vbuf[index++] = _particles[tempIndex].x;
vbuf[index++] = _particles[tempIndex].y;
vbuf[index++] = _particles[tempIndex].z;
vbuf[index++] = 0;
vbuf[index++] = 1;
vbuf[index++] = r;
vbuf[index++] = g;
vbuf[index++] = b;
}
}
_vbuffer.uploadFromVector(vbuf, 0, numVertices);
}
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";
code += "mov v1, va2\n";
var vertexShader:ByteArray = agal.assemble(Context3DProgramType.VERTEX, code);
code = "mov oc, v0\n";
code = "tex ft1, v0, fs0 <2d,clamp,linear,mipnearest>\n";
code += "mul oc ft1, v1\n";
var fragmentShader:ByteArray = agal.assemble(Context3DProgramType.FRAGMENT, code);
var program:Program3D = context.createProgram();
program.upload(vertexShader, fragmentShader);
context.setProgram(program);
}
}
}
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;
}
}