MP3FileReference TEST

by tepe
♥0 | Line 385 | Modified 2011-02-18 10:20:43 | MIT License
play

ActionScript3 source code

/**
 * Copyright tepe ( http://wonderfl.net/user/tepe )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/fycS
 */

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.net.FileFilter;
    import flash.net.FileReference;

    public class MP3FileReferenceTest extends Sprite {
        private var loader:MP3FileReferenceLoader;
        private var fileReference:FileReference;
        public function MP3FileReferenceTest() {
            loader=new MP3FileReferenceLoader();
            loader.addEventListener(MP3SoundEvent.COMPLETE,mp3LoaderCompleteHandler);
            fileReference=new FileReference();
            fileReference.addEventListener(Event.SELECT,fileReferenceSelectHandler);//ファイル選択
            stage.addEventListener(MouseEvent.CLICK,clickHandler);//画面クリック
        }
        private function clickHandler(ev:MouseEvent):void {
            fileReference.browse([new FileFilter("mp3 files","*.mp3")]);//ダイアログを開く
        }
        private function fileReferenceSelectHandler(ev:Event):void {
            loader.getSound(fileReference);//ロード開始
            
        }
        private function mp3LoaderCompleteHandler(ev:MP3SoundEvent):void {
            ev.sound.play();//再生
            
        }
    }
}


import flash.display.*;
import flash.events.*;
import flash.media.Sound;
import flash.net.FileReference;
import flash.utils.ByteArray;
import flash.utils.Endian;
    
[Event(name="complete", type="MP3SoundEvent")]
class MP3FileReferenceLoader extends EventDispatcher{
        private var mp3Parser:MP3Parser;
        
        public function MP3FileReferenceLoader(){
            mp3Parser=new MP3Parser();
            mp3Parser.addEventListener(Event.COMPLETE,parserCompleteHandler);
            
        }

        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.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;
        }
        
}


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;
    
[Event(name="complete", type="flash.events.Event")]
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"){
                    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.utils.ByteArray;
    
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;
        }
}


    
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 
        ];

}