Tesla coil
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.SampleDataEvent;
import flash.filters.GlowFilter;
import flash.geom.Point;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
import flash.utils.ByteArray;
/**
* Click to load your mp3.
* Obligatory: imperial march :)
* Doesn't sound quite right, but whatever... here it goes to wonderfl.
* @author makc
*/
[SWF(width=465,height=465,backgroundColor=0)]
public class TeslaCoil extends Sprite {
public var mp3:ClientMP3Loader;
public var sound:Sound;
public var samples:int = 4096;
public var frequency:Number = 50;
public var avgEnergy:Number = 0;
public var curEnergy:Number = 0;
public var particles:Vector.<Point> = new Vector.<Point> (50, true);
public function TeslaCoil () {
mp3 = new ClientMP3Loader;
stage.addEventListener (MouseEvent.CLICK, mp3.load);
from = new Point (
0.5 * stage.stageWidth,
1.0 * stage.stageHeight
);
stage.addEventListener (Event.ENTER_FRAME, draw);
sound = new Sound;
sound.addEventListener (SampleDataEvent.SAMPLE_DATA, modulate);
sound.play ();
filters = [
new GlowFilter (0x5F3FFF, 1, 64, 64, 8, 2)
];
}
public function modulate (ev:SampleDataEvent):void {
var actually:int = mp3.sound.extract (ev.data, samples);
for (var i:int = 0; i < samples - actually; i++) {
ev.data.writeFloat (0);
ev.data.writeFloat (0);
}
var p:int;
var noise:Number = 0.5;
var w:Number = 2 * Math.PI * frequency / 44100;
var a:Number = 0, b:Number = 0, c:Number, d:Number, e:Number = 0;
// lame high pass filter
c = 0;
d = 0;
ev.data.position = 0;
for (i = 0; i < samples; i++) {
p = ev.data.position;
a = ev.data.readFloat (); c = 0.01 * c + 0.99 * a;
b = ev.data.readFloat (); d = 0.01 * d + 0.99 * b;
ev.data.position = p;
ev.data.writeFloat (200 * (a - c));
ev.data.writeFloat (200 * (b - d));
}
ev.data.position = 0;
for (i = 0; i < samples; i++) {
p = ev.data.position;
// read samples in a, b while calculating squared wave energy in c, d
c = a; a = ev.data.readFloat (); c -= a; c *= c; c += a * a; e += Math.sqrt (c);
d = b; b = ev.data.readFloat (); d -= b; d *= d; d += b * b; e += Math.sqrt (d);
// modulation + noise
ev.data.position = p;
var sine:Number = Math.sin (w * (i + ev.position));
ev.data.writeFloat (a * sine * (1 - noise + noise * (Math.random () - Math.random ())));
ev.data.writeFloat (b * sine * (1 - noise + noise * (Math.random () - Math.random ())));
}
// running average of e
avgEnergy *= 0.95;
avgEnergy += 0.05 * e;
// if combined wave energy is below some threshold, mute
if (e <= 0.3 * avgEnergy) {
curEnergy = 0;
ev.data.position = 0;
for (i = 0; i < samples; i++) {
ev.data.writeFloat (0);
ev.data.writeFloat (0);
}
} else {
curEnergy = Math.min (3, e / (avgEnergy + 1e-6));
}
}
public var count:int = 10;
public var from:Point, to:Point = new Point;
public function draw (e:Event):void {
to.x = mouseX;
to.y = mouseY;
if (particles [0] == null) resetParticles ();
var i:int, k:Number, m:Number;
// move particles upwards from the line connecting endpoints
var d0:Point = to.subtract (from);
d0.normalize (30);
var up:Point = new Point (d0.y, -d0.x);
if (up.y > 0) {
up.x *= -1;
up.y *= -1;
}
for (i = 0; i < particles.length; i++) {
k = i / (particles.length - 1);
m = (1 - k);
k = Math.sqrt (k);
m = Math.sqrt (m);
particles [i].x += up.x + (m - k) * d0.x + 500 * (Math.random () - Math.random ()) / particles.length;
particles [i].y += up.y + (m - k) * d0.y + 500 * (Math.random () - Math.random ()) / particles.length;
}
// tighten the chain
for (i = 0; i < particles.length -1; i++) {
particles [i].x = particles [i].x * 0.8 + particles [i + 1].x * 0.2;
particles [i].y = particles [i].y * 0.8 + particles [i + 1].y * 0.2;
}
// reconnect to endpoints
var d1:Point = from.subtract (particles [0]);
var d2:Point = to.subtract (particles [particles.length -1]);
for (i = 0; i < particles.length; i++) {
k = i / (particles.length - 1);
m = (1 - k);
k *= k;
m *= m;
particles [i].x += d1.x * m;
particles [i].y += d1.y * m;
particles [i].x += d2.x * k;
particles [i].y += d2.y * k;
}
graphics.clear ();
if (curEnergy > 0) {
graphics.lineStyle (3 * curEnergy, 0xFFFFFF);
graphics.moveTo (particles [0].x, particles [0].y);
for (i = 1; i < particles.length; i++) {
graphics.lineTo (particles [i].x, particles [i].y);
}
} else {
resetParticles ();
}
if (count-- < 0) {
resetParticles ();
count = 5 + 20 * Math.random ();
}
}
public function resetParticles ():void {
for (var i:int = 0; i < particles.length; i++) {
particles [i] = Point.interpolate (from, to, i / (particles.length - 1));
particles [i].x += 3 * (from.x - to.x) * (Math.random () - Math.random ()) / particles.length;
particles [i].y += 3 * (from.y - to.y) * (Math.random () - Math.random ()) / particles.length;
}
}
}
}
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.events.Event;
import flash.events.EventDispatcher;
import flash.media.Sound;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.utils.ByteArray;
/**
* This loads MP3 from HDD.
*
* @see http://wiki.github.com/claus/as3swf/play-mp3-directly-from-bytearray
* @see http://github.com/claus/as3swf/raw/master/bin/as3swf.swc
*/
class ClientMP3Loader extends EventDispatcher {
/**
* Use this object after Event.COMPLETE.
*/
public var sound:Sound = new Sound;
/**
* Call this to load MP3 from HDD.
*/
public function load (ignore:* = null):void {
file = new FileReference;
file.addEventListener (Event.CANCEL, onUserCancelled);
file.addEventListener (Event.SELECT, onFileSelected);
file.addEventListener (Event.COMPLETE, onFileLoaded);
file.browse ([ new FileFilter ("MP3 files", "*.mp3") ]);
}
private var file:FileReference;
private function onUserCancelled (e:Event):void { dispatchEvent (new Event (Event.CANCEL)); }
private function onFileSelected (e:Event):void { file.load (); }
private function onFileLoaded (e:Event):void {
// Wrap the MP3 with a SWF
var swf:ByteArray = createSWFFromMP3 (file.data);
// Load the SWF with Loader::loadBytes()
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, initHandler);
loader.loadBytes(swf);
}
private function initHandler(e:Event):void {
// Get the sound class definition
var SoundClass:Class = LoaderInfo(e.currentTarget).applicationDomain.getDefinition("MP3Wrapper_soundClass") as Class;
// Instantiate the sound class
sound = new SoundClass() as Sound;
// Report Event.COMPLETE
dispatchEvent (new Event (Event.COMPLETE));
}
private 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();
}