/**
* Copyright Nos_lkSsvOhB ( http://wonderfl.net/user/Nos_lkSsvOhB )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/obsL
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.text.TextField;
import flash.text.TextFormat;
[SWF(width=465,height=465,backgroundColor=0xFFFFFF,frameRate=60)]
public class Main extends Sprite
{
private var _sound:Sound = new Sound();
private var _channel:SoundChannel;
private var _loader:MP3FileReferenceLoader = new MP3FileReferenceLoader();
private var _fr:FileReference = new FileReference();
private var sp:Sprite = new Sprite();
private var spBlur:BlurFilter = new BlurFilter(8, 4);
private var _tx:TextField;
public function Main()
{
// 音楽ファイルの選択
_fr = new FileReference();
_fr.addEventListener(Event.SELECT, fileSelectedHandler);
_tx = new TextField();
_tx.defaultTextFormat = new TextFormat(null, 32, 0x000000);
_tx.text = "Click to load MP3 file";
_tx.width = 400;
_tx.x = 80;
_tx.y = 200;
_tx.selectable = false;
this.addChild(_tx);
// 描画用
addChild(sp);
stage.addEventListener(MouseEvent.MOUSE_DOWN, browse);
}
private function browse(e:Event):void
{
// ファイルの選択
_fr.browse([new FileFilter("mp3 files", "*.mp3")]);
}
private function fileSelectedHandler(e:Event):void
{
_loader.getSound(_fr);
_loader.addEventListener(MP3SoundEvent.COMPLETE, onComplete);
}
private function onComplete(e:MP3SoundEvent):void
{
trace("complete");
//e.sound.play();
this.removeChild(_tx);
stage.removeEventListener(MouseEvent.MOUSE_DOWN, browse);
// サウンドのロード
_sound = e.sound;
//_sound.addEventListener(Event.COMPLETE, onLoadComplete);
onLoadComplete(null);
}
private function onLoadComplete(evt:Event):void
{
trace("mp3 loaded");
this.addEventListener(Event.ENTER_FRAME, loop);
_channel = _sound.play(0, int.MAX_VALUE);
}
/**
* メインループ
*
* @private
*/
private function loop(evt:Event):void
{
var dd:Number = Math.max(_channel.rightPeak, _channel.leftPeak) * 100;
sp.graphics.clear();
sp.graphics.lineStyle(8, 0xFF7F00, 1);
sp.graphics.moveTo(230 + (.5 - Math.random()) * dd, 65 + (.5 - Math.random()) * dd);
sp.graphics.lineTo(230 + (.5 - Math.random()) * dd, 400 + (.5 - Math.random()) * dd);
sp.filters = [spBlur]; // ブラー
}
}
}
import flash.utils.ByteArray;
internal class ByteArraySegment
{
public var start:uint;
public var length:uint;
public var byteArray:ByteArray;
public function ByteArraySegment(ba:ByteArray, start:uint, length:uint)
{
byteArray = ba;
this.start = start;
this.length = length;
}
}
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.media.Sound;
import flash.net.FileReference;
import flash.utils.ByteArray;
import flash.utils.Endian;
class MP3FileReferenceLoader extends EventDispatcher
{
private var mp3Parser:MP3Parser;
/**
* Constructs an new MP3FileReferenceLoader instance
*
*/
public function MP3FileReferenceLoader()
{
mp3Parser = new MP3Parser();
mp3Parser.addEventListener(Event.COMPLETE, parserCompleteHandler);
}
/**
* Once a FileReference instance has been obtained, and the user has browsed to a file, call getSound to start loading the MP3 data.
* When the data is ready, an <code>MP3SoundEvent.COMPLETE</code> event is emitted.
* @param fr A reference to a local file.
* @see MP3SoundEvent
*/
public function getSound(fr:FileReference):void
{
mp3Parser.loadFileRef(fr);
}
private function parserCompleteHandler(ev:Event):void
{
var parser:MP3Parser = ev.currentTarget as MP3Parser;
generateSound(parser);
}
private function generateSound(mp3Source:MP3Parser):Boolean
{
var swfBytes:ByteArray = new ByteArray();
swfBytes.endian = Endian.LITTLE_ENDIAN;
for (var i:uint = 0; i < SoundClassSwfByteCode.soundClassSwfBytes1.length; ++i)
{
swfBytes.writeByte(SoundClassSwfByteCode.soundClassSwfBytes1[i]);
}
var swfSizePosition:uint = swfBytes.position;
swfBytes.writeInt(0); //swf size will go here
for (i = 0; i < SoundClassSwfByteCode.soundClassSwfBytes2.length; ++i)
{
swfBytes.writeByte(SoundClassSwfByteCode.soundClassSwfBytes2[i]);
}
var audioSizePosition:uint = swfBytes.position;
swfBytes.writeInt(0); //audiodatasize+7 to go here
swfBytes.writeByte(1);
swfBytes.writeByte(0);
mp3Source.writeSwfFormatByte(swfBytes);
var sampleSizePosition:uint = swfBytes.position;
swfBytes.writeInt(0); //number of samples goes here
swfBytes.writeByte(0); //seeksamples
swfBytes.writeByte(0);
var frameCount:uint = 0;
var byteCount:uint = 0; //this includes the seeksamples written earlier
for (; ; )
{
var seg:ByteArraySegment = mp3Source.getNextFrame();
if (seg == null)
break;
swfBytes.writeBytes(seg.byteArray, seg.start, seg.length);
byteCount += seg.length;
frameCount++;
}
if (byteCount == 0)
{
return false;
}
byteCount += 2;
var currentPos:uint = swfBytes.position;
swfBytes.position = audioSizePosition;
swfBytes.writeInt(byteCount + 7);
swfBytes.position = sampleSizePosition;
swfBytes.writeInt(frameCount * 1152);
swfBytes.position = currentPos;
for (i = 0; i < SoundClassSwfByteCode.soundClassSwfBytes3.length; ++i)
{
swfBytes.writeByte(SoundClassSwfByteCode.soundClassSwfBytes3[i]);
}
swfBytes.position = swfSizePosition;
swfBytes.writeInt(swfBytes.length);
swfBytes.position = 0;
var swfBytesLoader:Loader = new Loader();
swfBytesLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfCreated);
swfBytesLoader.loadBytes(swfBytes);
return true;
}
private function swfCreated(ev:Event):void
{
var loaderInfo:LoaderInfo = ev.currentTarget as LoaderInfo;
var soundClass:Class = loaderInfo.applicationDomain.getDefinition("SoundClass") as Class;
var sound:Sound = new soundClass();
dispatchEvent(new MP3SoundEvent(MP3SoundEvent.COMPLETE, sound));
}
}
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.net.FileReference;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.ByteArray;
internal class MP3Parser extends EventDispatcher
{
private var mp3Data:ByteArray;
private var loader:URLLoader;
private var currentPosition:uint;
private var sampleRate:uint;
private var channels:uint;
private var version:uint;
private static var bitRates:Array = [-1, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1, -1, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1];
private static var versions:Array = [2.5, -1, 2, 1];
private static var samplingRates:Array = [44100, 48000, 32000];
public function MP3Parser()
{
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, loaderCompleteHandler);
}
internal function load(url:String):void
{
var req:URLRequest = new URLRequest(url);
loader.load(req);
}
internal function loadFileRef(fileRef:FileReference):void
{
fileRef.addEventListener(Event.COMPLETE, loaderCompleteHandler);
fileRef.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
//fileRef.addEventListener(Event.COMPLETE,loaderCompleteHandler);
fileRef.load();
}
private function errorHandler(ev:IOErrorEvent):void
{
trace("error\n" + ev.text);
}
private function loaderCompleteHandler(ev:Event):void
{
mp3Data = ev.currentTarget.data as ByteArray;
currentPosition = getFirstHeaderPosition();
dispatchEvent(ev);
}
private function getFirstHeaderPosition():uint
{
mp3Data.position = 0;
while (mp3Data.position < mp3Data.length)
{
var readPosition:uint = mp3Data.position;
var str:String = mp3Data.readMultiByte(3, "us-ascii");
if (str == "ID3") //here's an id3v2 header. fuck that for a laugh. skipping
{
mp3Data.position += 3;
var b3:int = (mp3Data.readByte() & 0x7F) << 21;
var b2:int = (mp3Data.readByte() & 0x7F) << 14;
var b1:int = (mp3Data.readByte() & 0x7F) << 7;
var b0:int = mp3Data.readByte() & 0x7F;
var headerLength:int = b0 + b1 + b2 + b3;
var newPosition:int = mp3Data.position + headerLength;
trace("Found id3v2 header, length " + headerLength.toString(16) + " bytes. Moving to " + newPosition.toString(16));
mp3Data.position = newPosition;
readPosition = newPosition;
}
else
{
mp3Data.position = readPosition;
}
var val:uint = mp3Data.readInt();
if (isValidHeader(val))
{
parseHeader(val);
mp3Data.position = readPosition + getFrameSize(val);
if (isValidHeader(mp3Data.readInt()))
{
return readPosition;
}
}
}
throw(new Error("Could not locate first header. This isn't an MP3 file"));
}
internal function getNextFrame():ByteArraySegment
{
mp3Data.position = currentPosition;
var headerByte:uint;
var frameSize:uint;
while (true)
{
if (currentPosition > (mp3Data.length - 4))
{
trace("passed eof");
return null;
}
headerByte = mp3Data.readInt();
if (isValidHeader(headerByte))
{
frameSize = getFrameSize(headerByte);
if (frameSize != 0xffffffff)
{
break;
}
}
currentPosition = mp3Data.position;
}
mp3Data.position = currentPosition;
if ((currentPosition + frameSize) > mp3Data.length)
{
return null;
}
currentPosition += frameSize;
return new ByteArraySegment(mp3Data, mp3Data.position, frameSize);
}
internal function writeSwfFormatByte(byteArray:ByteArray):void
{
var sampleRateIndex:uint = 4 - (44100 / sampleRate);
byteArray.writeByte((2 << 4) + (sampleRateIndex << 2) + (1 << 1) + (channels - 1));
}
private function parseHeader(headerBytes:uint):void
{
var channelMode:uint = getModeIndex(headerBytes);
version = getVersionIndex(headerBytes);
var samplingRate:uint = getFrequencyIndex(headerBytes);
channels = (channelMode > 2) ? 1 : 2;
var actualVersion:Number = versions[version];
var samplingRates:Array = [44100, 48000, 32000];
sampleRate = samplingRates[samplingRate];
switch (actualVersion)
{
case 2:
sampleRate /= 2;
break;
case 2.5:
sampleRate /= 4;
}
}
private function getFrameSize(headerBytes:uint):uint
{
var version:uint = getVersionIndex(headerBytes);
var bitRate:uint = getBitrateIndex(headerBytes);
var samplingRate:uint = getFrequencyIndex(headerBytes);
var padding:uint = getPaddingBit(headerBytes);
//var channelMode:uint=getModeIndex(headerBytes);
var actualVersion:Number = versions[version];
var sampleRate:uint = samplingRates[samplingRate];
if (sampleRate != this.sampleRate || this.version != version)
{
return 0xffffffff;
}
switch (actualVersion)
{
case 2:
sampleRate /= 2;
break;
case 2.5:
sampleRate /= 4;
}
var bitRatesYIndex:uint = ((actualVersion == 1) ? 0 : 1) * bitRates.length / 2;
var actualBitRate:uint = bitRates[bitRatesYIndex + bitRate] * 1000;
var frameLength:uint = (((actualVersion == 1 ? 144 : 72) * actualBitRate) / sampleRate) + padding;
return frameLength;
}
private function isValidHeader(headerBits:uint):Boolean
{
return (((getFrameSync(headerBits) & 2047) == 2047) && ((getVersionIndex(headerBits) & 3) != 1) && ((getLayerIndex(headerBits) & 3) != 0) && ((getBitrateIndex(headerBits) & 15) != 0) && ((getBitrateIndex(headerBits) & 15) != 15) && ((getFrequencyIndex(headerBits) & 3) != 3) && ((getEmphasisIndex(headerBits) & 3) != 2));
}
private function getFrameSync(headerBits:uint):uint
{
return uint((headerBits >> 21) & 2047);
}
private function getVersionIndex(headerBits:uint):uint
{
return uint((headerBits >> 19) & 3);
}
private function getLayerIndex(headerBits:uint):uint
{
return uint((headerBits >> 17) & 3);
}
private function getBitrateIndex(headerBits:uint):uint
{
return uint((headerBits >> 12) & 15);
}
private function getFrequencyIndex(headerBits:uint):uint
{
return uint((headerBits >> 10) & 3);
}
private function getPaddingBit(headerBits:uint):uint
{
return uint((headerBits >> 9) & 1);
}
private function getModeIndex(headerBits:uint):uint
{
return uint((headerBits >> 6) & 3);
}
private function getEmphasisIndex(headerBits:uint):uint
{
return uint(headerBits & 3);
}
}
import flash.events.Event;
import flash.media.Sound;
class MP3SoundEvent extends Event
{
public var sound:Sound;
public static const COMPLETE:String = "complete";
public function MP3SoundEvent(type:String, sound:Sound, bubbles:Boolean = false, cancelable:Boolean = false)
{
super(type, bubbles, cancelable);
this.sound = sound;
}
}
internal final class SoundClassSwfByteCode
{
internal static const silentMp3Frame:Array = [0xFF, 0xFA, 0x92, 0x40, 0x78, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x70, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x2E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x25, 0xC0, 0x00, 0x00, 0x04, 0xB0, 0x04, 0xB1, 0x00, 0x06, 0xBA, 0xA8, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
internal static const soundClassSwfBytes1:Array = [0x46, 0x57, 0x53, 0x09];
internal static const soundClassSwfBytes2:Array = [0x78, 0x00, 0x05, 0x5F, 0x00, 0x00, 0x0F, 0xA0, 0x00, 0x00, 0x0C, 0x01, 0x00, 0x44, 0x11, 0x08, 0x00, 0x00, 0x00, 0x43, 0x02, 0xFF, 0xFF, 0xFF, 0xBF, 0x15, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x20, 0x31, 0x00, 0x00, 0xBF, 0x14, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0A, 0x53, 0x6F, 0x75, 0x6E, 0x64, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x00, 0x0B, 0x66, 0x6C, 0x61, 0x73, 0x68, 0x2E, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x05, 0x53, 0x6F, 0x75, 0x6E, 0x64, 0x06, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x0F, 0x45, 0x76, 0x65, 0x6E, 0x74, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x0C, 0x66, 0x6C, 0x61, 0x73, 0x68, 0x2E, 0x65, 0x76, 0x65, 0x6E, 0x74, 0x73, 0x06, 0x05, 0x01, 0x16, 0x02, 0x16, 0x03, 0x18, 0x01, 0x16, 0x07, 0x00, 0x05, 0x07, 0x02, 0x01, 0x07, 0x03, 0x04, 0x07, 0x02, 0x05, 0x07, 0x05, 0x06, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x08, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x01, 0x04, 0x01, 0x00, 0x03, 0x00, 0x01, 0x01, 0x05, 0x06, 0x03, 0xD0, 0x30, 0x47, 0x00, 0x00, 0x01, 0x01, 0x01, 0x06, 0x07, 0x06, 0xD0, 0x30, 0xD0, 0x49, 0x00, 0x47, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x05, 0x1F, 0xD0, 0x30, 0x65, 0x00, 0x5D, 0x03, 0x66, 0x03, 0x30, 0x5D, 0x04, 0x66, 0x04, 0x30, 0x5D, 0x02, 0x66, 0x02, 0x30, 0x5D, 0x02, 0x66, 0x02, 0x58, 0x00, 0x1D, 0x1D, 0x1D, 0x68, 0x01, 0x47, 0x00, 0x00, 0xBF, 0x03];
internal static const soundClassSwfBytes3:Array = [0x3F, 0x13, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x53, 0x6F, 0x75, 0x6E, 0x64, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x00, 0x44, 0x0B, 0x0F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00];
}