Music Atom
Just click to pick and mp3 file from your hard drive.
It is final entry for Music Visualization contest at DeviantArt, you can read more in my final blog post about it here
http://blog.wonderwhy-er.com/audio-visualization-contest-results-and-code-on-wonderfl/
+ links to other posts.
/**
* Copyright wonderwhyer ( http://wonderfl.net/user/wonderwhyer )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zBu2
*/
package {
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextField;
import com.codeazur.as3swf.SWF;
import com.codeazur.as3swf.SWFData;
import com.codeazur.as3swf.data.SWFScene;
import com.codeazur.as3swf.data.SWFSymbol;
import com.codeazur.as3swf.data.consts.SoundCompression;
import com.codeazur.as3swf.data.consts.SoundRate;
import com.codeazur.as3swf.data.consts.SoundSize;
import com.codeazur.as3swf.data.consts.SoundType;
import com.codeazur.as3swf.tags.TagDefineSceneAndFrameLabelData;
import com.codeazur.as3swf.tags.TagDefineSound;
import com.codeazur.as3swf.tags.TagDoABC;
import com.codeazur.as3swf.tags.TagEnd;
import com.codeazur.as3swf.tags.TagFileAttributes;
import com.codeazur.as3swf.tags.TagSetBackgroundColor;
import com.codeazur.as3swf.tags.TagShowFrame;
import com.codeazur.as3swf.tags.TagSymbolClass;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.utils.ByteArray;
import flash.events.MouseEvent;
import net.hires.debug.Stats;
/**
* MP3 Loading based on this code:
* http://code.google.com/p/makc/source/browse/trunk/flash/fp10_fft/ClientMP3Loader.as
*/
[SWF(width=465,height=465,backgroundColor=0x000000, frameRate = 30)]
public class MusicalCircles extends Sprite {
public var fr:FileReference;
public var soundSource:Sound;
public var currentSong:SoundChannel;
public var visualizer:Visualizer;
public function MusicalCircles() {
stage.addEventListener(MouseEvent.MOUSE_UP,up);
addEventListener(Event.ENTER_FRAME,update);
var txt:TextField = new TextField();
txt.defaultTextFormat = new TextFormat(null,12,0xffffff);
txt.autoSize = TextFieldAutoSize.LEFT;
txt.selectable=false;
txt.text = "Click anywhere to select an mp3 file";
txt.x = 120;
visualizer = new Visualizer();
addChild(visualizer);
//addChild(new Stats());
addChild(txt);
}
public function update(e:Event):void {
if(currentSong)
visualizer.update();
}
public function up(e:Event):void {
fr = new FileReference();
fr.addEventListener(Event.SELECT, onFileSelected);
fr.addEventListener(Event.COMPLETE, parse);
var mp3Filter:FileFilter = new FileFilter("mp3","*.mp3");
fr.browse([mp3Filter]);
if (currentSong)
{
currentSong.stop();
currentSong = null;
visualizer.clean();
}
}
public function onFileSelected(e:Event):void
{
fr.load();
}
public function parse(e:Event):void
{
var swf:ByteArray = createSWFFromMP3(fr.data);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, SoundLoaded);
loader.loadBytes(swf);
}
public function SoundLoaded(e:Event):void
{
var SoundClass:Class = LoaderInfo(e.currentTarget).applicationDomain.getDefinition("MP3Wrapper_soundClass") as Class;
soundSource = new SoundClass() as Sound;
currentSong = soundSource.play();
currentSong.addEventListener(Event.COMPLETE,songEnded);
}
public function songEnded(e:Event):void
{
currentSong = null;
}
public function createSWFFromMP3(mp3:ByteArray):ByteArray
{
// Create an empty SWF
// Defaults to v10, 550x400px, 50fps, one frame (works fine for us)
var swf:SWF = new SWF();
// Add FileAttributes tag
// Defaults: as3 true, all other flags false (works fine for us)
swf.tags.push(new TagFileAttributes());
// Add SetBackgroundColor tag
// Default: white background (works fine for us)
swf.tags.push(new TagSetBackgroundColor());
// Add DefineSceneAndFrameLabelData tag
// (with the only entry being "Scene 1" at offset 0)
var defineSceneAndFrameLabelData:TagDefineSceneAndFrameLabelData = new TagDefineSceneAndFrameLabelData();
defineSceneAndFrameLabelData.scenes.push(new SWFScene(0, "Scene 1"));
swf.tags.push(defineSceneAndFrameLabelData);
// Add DefineSound tag
// The ID is 1, all other parameters are automatically
// determined from the mp3 itself.
swf.tags.push(TagDefineSound.createWithMP3(1, mp3));
// Add DoABC tag
// Contains the AS3 byte code for the document class and the
// class definition for the embedded sound
swf.tags.push(TagDoABC.create(abc));
// Add SymbolClass tag
// Specifies the document class and binds the sound class
// definition to the embedded sound
var symbolClass:TagSymbolClass = new TagSymbolClass();
symbolClass.symbols.push(SWFSymbol.create(1, "MP3Wrapper_soundClass"));
symbolClass.symbols.push(SWFSymbol.create(0, "MP3Wrapper"));
swf.tags.push(symbolClass);
// Add ShowFrame tag
swf.tags.push(new TagShowFrame());
// Add End tag
swf.tags.push(new TagEnd());
// Publish the SWF
var swfData:SWFData = new SWFData();
swf.publish(swfData);
return swfData;
}
private static var abcData:Array = [
0x10, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x07, 0x6d, 0x78, 0x2e, 0x63, 0x6f, 0x72, 0x65,
0x0a, 0x49, 0x46, 0x6c, 0x65, 0x78, 0x41, 0x73, 0x73, 0x65, 0x74, 0x0a, 0x53, 0x6f, 0x75, 0x6e,
0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x0b, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x6d, 0x65, 0x64,
0x69, 0x61, 0x05, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x6d, 0x78, 0x2e, 0x63, 0x6f, 0x72, 0x65,
0x3a, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x00, 0x15, 0x4d, 0x50, 0x33,
0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6c, 0x61,
0x73, 0x73, 0x0a, 0x4d, 0x50, 0x33, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x0d, 0x66, 0x6c,
0x61, 0x73, 0x68, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x06, 0x53, 0x70, 0x72, 0x69,
0x74, 0x65, 0x0a, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x05, 0x43, 0x6c,
0x61, 0x73, 0x73, 0x2a, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61,
0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x32, 0x30, 0x30, 0x36, 0x2f, 0x66, 0x6c,
0x65, 0x78, 0x2f, 0x6d, 0x78, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x07, 0x56,
0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x06, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x07, 0x33, 0x2e,
0x30, 0x2e, 0x30, 0x2e, 0x30, 0x0b, 0x6d, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x0c, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x65,
0x76, 0x65, 0x6e, 0x74, 0x73, 0x0f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x73, 0x70, 0x61,
0x74, 0x63, 0x68, 0x65, 0x72, 0x0d, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x16, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x0a, 0x16, 0x01, 0x16,
0x04, 0x18, 0x06, 0x16, 0x07, 0x18, 0x08, 0x16, 0x0a, 0x18, 0x09, 0x08, 0x0e, 0x16, 0x14, 0x03,
0x01, 0x01, 0x01, 0x04, 0x14, 0x07, 0x01, 0x02, 0x07, 0x01, 0x03, 0x07, 0x02, 0x05, 0x09, 0x02,
0x01, 0x07, 0x04, 0x08, 0x07, 0x04, 0x09, 0x07, 0x06, 0x0b, 0x07, 0x04, 0x0c, 0x07, 0x04, 0x0d,
0x07, 0x08, 0x0f, 0x07, 0x04, 0x10, 0x07, 0x01, 0x12, 0x09, 0x03, 0x01, 0x07, 0x04, 0x13, 0x07,
0x09, 0x15, 0x09, 0x08, 0x02, 0x07, 0x06, 0x16, 0x07, 0x06, 0x17, 0x07, 0x06, 0x18, 0x0d, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x05, 0x00, 0x02, 0x00, 0x02, 0x03, 0x09, 0x03, 0x01,
0x04, 0x05, 0x00, 0x05, 0x02, 0x09, 0x05, 0x00, 0x08, 0x00, 0x06, 0x07, 0x09, 0x07, 0x00, 0x0b,
0x01, 0x08, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x04, 0x01, 0x0a, 0x06, 0x01, 0x0b, 0x11, 0x01,
0x07, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x01, 0x0c, 0x06, 0x00, 0x00, 0x08, 0x08, 0x03, 0x01, 0x01,
0x04, 0x00, 0x00, 0x06, 0x01, 0x02, 0x04, 0x00, 0x01, 0x09, 0x01, 0x05, 0x04, 0x00, 0x02, 0x0c,
0x01, 0x06, 0x04, 0x01, 0x03, 0x0c, 0x00, 0x01, 0x01, 0x01, 0x02, 0x03, 0xd0, 0x30, 0x47, 0x00,
0x00, 0x01, 0x00, 0x01, 0x03, 0x03, 0x01, 0x47, 0x00, 0x00, 0x03, 0x02, 0x01, 0x01, 0x02, 0x0a,
0xd0, 0x30, 0x5d, 0x04, 0x20, 0x58, 0x00, 0x68, 0x01, 0x47, 0x00, 0x00, 0x04, 0x02, 0x01, 0x05,
0x06, 0x09, 0xd0, 0x30, 0x5e, 0x0a, 0x2c, 0x11, 0x68, 0x0a, 0x47, 0x00, 0x00, 0x05, 0x01, 0x01,
0x06, 0x07, 0x06, 0xd0, 0x30, 0xd0, 0x49, 0x00, 0x47, 0x00, 0x00, 0x06, 0x02, 0x01, 0x01, 0x05,
0x17, 0xd0, 0x30, 0x5d, 0x0d, 0x60, 0x0e, 0x30, 0x60, 0x0f, 0x30, 0x60, 0x03, 0x30, 0x60, 0x03,
0x58, 0x01, 0x1d, 0x1d, 0x1d, 0x68, 0x02, 0x47, 0x00, 0x00, 0x07, 0x01, 0x01, 0x06, 0x07, 0x03,
0xd0, 0x30, 0x47, 0x00, 0x00, 0x08, 0x01, 0x01, 0x07, 0x08, 0x06, 0xd0, 0x30, 0xd0, 0x49, 0x00,
0x47, 0x00, 0x00, 0x09, 0x02, 0x01, 0x01, 0x06, 0x1b, 0xd0, 0x30, 0x5d, 0x10, 0x60, 0x0e, 0x30,
0x60, 0x0f, 0x30, 0x60, 0x03, 0x30, 0x60, 0x02, 0x30, 0x60, 0x02, 0x58, 0x02, 0x1d, 0x1d, 0x1d,
0x1d, 0x68, 0x05, 0x47, 0x00, 0x00, 0x0a, 0x01, 0x01, 0x08, 0x09, 0x03, 0xd0, 0x30, 0x47, 0x00,
0x00, 0x0b, 0x02, 0x01, 0x09, 0x0a, 0x0b, 0xd0, 0x30, 0xd0, 0x60, 0x05, 0x68, 0x08, 0xd0, 0x49,
0x00, 0x47, 0x00, 0x00, 0x0c, 0x02, 0x01, 0x01, 0x08, 0x23, 0xd0, 0x30, 0x65, 0x00, 0x60, 0x0e,
0x30, 0x60, 0x0f, 0x30, 0x60, 0x11, 0x30, 0x60, 0x12, 0x30, 0x60, 0x13, 0x30, 0x60, 0x07, 0x30,
0x60, 0x07, 0x58, 0x03, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x68, 0x06, 0x47, 0x00, 0x00
];
private static function abcDataToByteArray():ByteArray {
var ba:ByteArray = new ByteArray();
for (var i:uint = 0; i < abcData.length; i++) {
ba.writeByte(abcData[i]);
}
return ba;
}
private static var abc:ByteArray = abcDataToByteArray();
}
}
import flash.display.BlendMode;
import flash.display.Graphics;
import flash.geom.Rectangle;
import flash.filters.BlurFilter;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.ColorTransform;
import flash.utils.ByteArray;
import flash.display.Sprite;
import flash.media.SoundMixer;
import org.si.utils.FFT;
class Dot {
public var x:Number;
public var y:Number;
public var dx:Number = 0;
public var dy:Number = 0;
public var direction:Number;
public var color:uint = 0;
public var alpha:Number = 0;
public function Dot(x:Number,y:Number,direction:Number) {
this.x = x;
this.y = y;
this.direction = direction;
}
}
class Visualizer extends Sprite{
private var wave:ByteArray;
private var xx:Number;
private var yy:Number;
private var direction:Number = 0;
private var color:Number = 0;
private var view:BitmapData;
private var bmp:Bitmap;
public var c:uint=0;
public var steps:uint = 8;
public var sp:Sprite;
public var dots:Vector.<Dot>;
public var bf:BlurFilter = new BlurFilter(1.5,1.5,1);
public function Visualizer()
{
wave = new ByteArray();
view = new BitmapData(450,450,false,0);
bmp = new Bitmap(view);
addChild(bmp);
bmp.x=0;
bmp.y=0;
xx = view.width/2;
yy = view.height/2;
dots = new Vector.<Dot>();
for(var i:uint=0;i<steps;i++)
{
dots.push(new Dot(0,0,Math.random()*Math.PI*2));
}
sp = new Sprite();
}
public function update():void {
SoundMixer.computeSpectrum(wave,false);
var spVal:Number;
var i:uint;
var inRe:Vector.<Number> = new Vector.<Number>();
var g:Graphics = sp.graphics;
c++;
if(c%20==0){
var ct:ColorTransform = new ColorTransform(1,1,1,0.999);
view.colorTransform(view.rect,ct);
}
var halfPos:uint = wave.length/2;
for(i=0;i<256;i++)
{
wave.position = i*4;
var sp1:Number = wave.readFloat();
wave.position = i*4+halfPos;
var sp2:Number=wave.readFloat();
inRe.push((sp1+sp2)/2);
}
var fft:FFT = new FFT(256);
fft.setData(inRe);
var spec:FFT = fft.calcRealFFT();
var res:Vector.<Number> = spec.getData();
var part:uint = 256/steps;
var shift:uint = 600/(steps+1);
var pow:Number = -1.8;
for(var j:uint=0;j<steps;j++){
var sec1:Vector.<Number> = res.splice(0,part);
var fft2:FFT = new FFT(part);
fft2.setData(sec1);
fft2.calcRealIFFT();
var wave1:Vector.<Number> = fft2.getData();
var m:Number = (Math.pow(j+1,pow)+0.004)*10;
var dot:Dot = dots[j];
dot.alpha*=0.5;
var d:Number = Math.sin(dot.y*0.05);
var xx:Number = view.width/2+Math.sin(dot.x*0.05)*200*d;
var yy:Number = view.height/2+Math.cos(dot.x*0.05)*200*d;
g.clear();
g.moveTo(xx,yy);
for(i=1;i<part;i++)
{
spVal = wave1[i]/m;
dot.alpha = dot.alpha*0.9 + Math.min(1,Math.abs(spVal*0.5))*0.1;
dot.direction+=spVal*0.1;
dot.x+=Math.sin(dot.direction);//*0.5;
dot.y+=Math.cos(dot.direction);//*0.5;
g.lineStyle(dot.alpha*0.5,HSLtoRGB(1,dot.direction*4,1,0.0001+dot.alpha*0.5));
d = Math.sin(dot.y*0.05);
xx = view.width/2+Math.sin(dot.x*0.05)*200*d;
yy = view.height/2+Math.cos(dot.x*0.05)*200*d;
g.lineTo(xx,yy);
}
view.draw(sp,null,null,BlendMode.ADD);
}
view.applyFilter(view,view.rect,view.rect.topLeft,bf);
}
public function clean():void
{
view.fillRect(view.rect,0);
dots = new Vector.<Dot>();
for(var i:uint=0;i<steps;i++)
{
dots.push(new Dot(0,0,Math.random()*Math.PI*2));
}
}
private function HSLtoRGB(a:Number=1,hue:Number=0,saturation:Number=1,lightness:Number=0.5):uint
{
a = Math.max(0,Math.min(1,a));
saturation = Math.max(0,Math.min(1,saturation));
lightness = Math.max(0,Math.min(1,lightness));
hue = hue%360;
if(hue<0)hue+=360;
hue/=60;
var C:Number = (1-Math.abs(2*lightness-1))*saturation;
var X:Number = C*(1-Math.abs((hue%2)-1));
var m:Number = lightness-0.5*C;
C=(C+m)*255;
X=(X+m)*255;
m*=255;
if(hue<1) return (C<<16) + (X<<8) + m;
if(hue<2) return (X<<16) + (C<<8) + m;
if(hue<3) return (m<<16) + (C<<8) + X;
if(hue<4) return (m<<16) + (X<<8) + C;
if(hue<5) return (X<<16) + (m<<8) + C;
return (C<<16) + (m<<8) + X;
}
}