Sound Visualizer #02
----------------------------------
Music by "SHW"(http://shw.in/)
----------------------------------
/**
* Copyright hycro ( http://wonderfl.net/user/hycro )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/AfJl2
*/
package
{
//----------------------------------
// Music by "SHW"(http://shw.in/)
//----------------------------------
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.filters.BlurFilter;
import flash.geom.ColorTransform;
import flash.geom.Point;
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.display.F5MovieClip2DBmp;
[SWF(width="465", height="465", frameRate="60")]
public class SoundVisualizer2 extends F5MovieClip2DBmp
{
private static const POLICY_FILE:String = "http://hycro.crz.jp/crossdomain.xml";
private static const SOUND_FILE:String = "http://hycro.crz.jp/wonderfl/sound/tsudumi-japan2.mp3";
private const Radius:uint = 100;
private var _sound:Sound;
private var _channel:SoundChannel;
private var _circle:Circle;
private var _count:uint = 0;
/**
* コンストラクタ
*
*/
public function SoundVisualizer2()
{
_circle = new Circle(0, 128);
_sound = new Sound();
_sound.load(new URLRequest(SOUND_FILE), new SoundLoaderContext(5000, true));
_sound.addEventListener(ProgressEvent.PROGRESS, onProgress);
_sound.addEventListener(Event.COMPLETE, onLoadComplete);
}
/**
* 描画関連の初期化
*
*/
public function setup():void {
size(stage.stageWidth, stage.stageHeight);
background(0x0);
stroke(255, .8);
noFill();
}
/**
* 音楽ファイルロード中の処理
*
*/
private function onProgress(evt:ProgressEvent):void {
_circle.radius = Radius * evt.bytesLoaded / evt.bytesTotal;
}
/**
* 音楽ファイルロード完了
*
*/
private function onLoadComplete(evt:Event):void {
_channel = _sound.play(0, int.MAX_VALUE);
_circle.radius = Radius;
}
/**
* 頂点データの更新
*
*/
private function updateCircle():void {
var data:ByteArray = new ByteArray();
SoundMixer.computeSpectrum(data, true);
var volume:Vector.<Number> = new Vector.<Number>(128);
for (var i:uint = 0; i<64; i++) {
volume[i] = 128*Math.sqrt((data.readFloat() + data.readFloat() + data.readFloat() + data.readFloat()) / 4);
}
for (var j:uint = 0; j<64; j++) {
volume[128-j-1] = 128*Math.sqrt((data.readFloat() + data.readFloat() + data.readFloat() + data.readFloat()) / 4);
}
_circle.update(volume);
}
/**
* 描画
*
*/
public function draw():void {
if (_channel) {
updateCircle();
}
translate( stage.stageWidth / 2, stage.stageHeight / 2 );
beginShape();
for each (var v:Vertex in _circle.vertices) {
this.curveVertex(v.x, v.y);
}
this.curveVertex(_circle.vertices[0].x, _circle.vertices[0].y);
this.curveVertex(_circle.vertices[1].x, _circle.vertices[1].y);
this.curveVertex(_circle.vertices[2].x, _circle.vertices[2].y);
endShape();
if (_count++ % 3 == 0) {
bitmapData.colorTransform(bitmapData.rect, new ColorTransform(.965, .945, .945));
}
if (_count % 5 == 0) {
this.bitmapData.applyFilter(bitmapData, bitmapData.rect, new Point(0, 0), new BlurFilter(4, 4));
}
}
}
}
class Circle {
private var _vertices:Vector.<Vertex>;
private var _radius:Number;
private var _slice:uint;
/**
* コンストラクタ
*
* @param radius 半径
* @param slice 円周の分割数
*/
public function Circle(radius:Number=100, slice:uint=512) {
_vertices = new Vector.<Vertex>();
_radius = radius;
_slice = slice;
var degree:Number = 3*Math.PI/2;
for (var i:uint = 0; i<slice; i++) {
_vertices.push(new Vertex(radius, degree));
degree += 2 * Math.PI / slice;
}
}
/**
* 頂点データの取得
*
*/
public function get vertices():Vector.<Vertex> {
return _vertices;
}
/**
* 半径の設定
*
*/
public function set radius(value:Number):void {
_radius = value;
for each (var v:Vertex in _vertices) {
v.radius = value;
}
}
/**
* 頂点データの更新
*
* @param level 各頂点の移動量
*/
public function update(level:Vector.<Number>):void {
for (var i:uint=0; i<level.length; i++) {
if (_vertices[i].radius > _radius + level[i]) {
_vertices[i].radius = Math.max(_radius, _vertices[i].radius - 5);
} else {
_vertices[i].radius = Math.max(_vertices[i].radius, _radius + level[i]);
}
}
}
}
class Vertex {
private var _radius:Number;
private var _degree:Number;
private var _mutable:Boolean;
private var _x:Number;
private var _y:Number;
public function Vertex(radius:Number, degree:Number, mutable:Boolean=true) {
_radius = radius;
_degree = degree;
_mutable = mutable;
if (!_mutable) {
_x = _radius * Math.cos(_degree);
_y = -_radius * Math.sin(_degree);
}
}
public function get x():Number {
if (_mutable) {
return _radius * Math.cos(_degree);
} else {
return _x;
}
}
public function get y():Number {
if (_mutable) {
return -_radius * Math.sin(_degree);
} else {
return _y;
}
}
public function get radius():Number
{
return _radius;
}
public function set radius(value:Number):void
{
if (_mutable) {
_radius = value;
}
}
public function get degree():Number
{
return _degree;
}
public function set degree(value:Number):void
{
if (_mutable) {
_degree = value;
}
}
}