forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			214 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			214 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								package kha.audio2.ogg.vorbis.data;
							 | 
						||
| 
								 | 
							
								import haxe.ds.Vector;
							 | 
						||
| 
								 | 
							
								import haxe.io.BytesInput;
							 | 
						||
| 
								 | 
							
								import haxe.io.BytesOutput;
							 | 
						||
| 
								 | 
							
								import haxe.io.Input;
							 | 
						||
| 
								 | 
							
								import haxe.io.Output;
							 | 
						||
| 
								 | 
							
								import kha.audio2.ogg.vorbis.data.Comment;
							 | 
						||
| 
								 | 
							
								import kha.audio2.ogg.vorbis.data.Page.PageFlag;
							 | 
						||
| 
								 | 
							
								import kha.audio2.ogg.vorbis.data.ReaderError.ReaderErrorType;
							 | 
						||
| 
								 | 
							
								import kha.audio2.ogg.vorbis.VorbisDecodeState;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * ...
							 | 
						||
| 
								 | 
							
								 * @author shohei909
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								class Header {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    static public inline var PACKET_ID = 1;
							 | 
						||
| 
								 | 
							
								    static public inline var PACKET_COMMENT = 3;
							 | 
						||
| 
								 | 
							
								    static public inline var PACKET_SETUP = 5;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public var maximumBitRate(default, null):UInt;
							 | 
						||
| 
								 | 
							
								    public var nominalBitRate(default, null):UInt;
							 | 
						||
| 
								 | 
							
								    public var minimumBitRate(default, null):UInt;
							 | 
						||
| 
								 | 
							
								    public var sampleRate(default, null):UInt;
							 | 
						||
| 
								 | 
							
								    public var channel(default, null):Int;
							 | 
						||
| 
								 | 
							
								    public var blocksize0(default, null):Int;
							 | 
						||
| 
								 | 
							
								    public var blocksize1(default, null):Int;
							 | 
						||
| 
								 | 
							
								    public var codebooks(default, null):Vector<Codebook>;
							 | 
						||
| 
								 | 
							
								    public var floorConfig(default, null):Vector<Floor>;
							 | 
						||
| 
								 | 
							
								    public var residueConfig(default, null):Vector<Residue>;
							 | 
						||
| 
								 | 
							
								    public var mapping(default, null):Vector<Mapping>;
							 | 
						||
| 
								 | 
							
								    public var modes(default, null):Vector<Mode>; // [64] varies
							 | 
						||
| 
								 | 
							
								    public var comment(default, null):Comment;
							 | 
						||
| 
								 | 
							
								    public var vendor(default, null):String;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function new() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    static public function read(decodeState:VorbisDecodeState):Header {
							 | 
						||
| 
								 | 
							
								        var page = decodeState.page;
							 | 
						||
| 
								 | 
							
								        page.start(decodeState);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if ((page.flag & PageFlag.FIRST_PAGE) == 0) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_FIRST_PAGE, "not firstPage");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if ((page.flag & PageFlag.LAST_PAGE) != 0) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_FIRST_PAGE, "lastPage");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if ((page.flag & PageFlag.CONTINUED_PACKET) != 0) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_FIRST_PAGE, "continuedPacket");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        decodeState.firstPageValidate();
							 | 
						||
| 
								 | 
							
								        if (decodeState.readByte() != PACKET_ID) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_FIRST_PAGE, "decodeState head");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // vorbis header
							 | 
						||
| 
								 | 
							
								        decodeState.vorbisValidate();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // vorbisVersion
							 | 
						||
| 
								 | 
							
								        var version = decodeState.readInt32();
							 | 
						||
| 
								 | 
							
								        if (version != 0) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_FIRST_PAGE, "vorbis version : " + version);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        var header = new Header();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        header.channel = decodeState.readByte();
							 | 
						||
| 
								 | 
							
								        if (header.channel == 0) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_FIRST_PAGE, "no channel");
							 | 
						||
| 
								 | 
							
								        } else if (header.channel > Setting.MAX_CHANNELS) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(TOO_MANY_CHANNELS, "too many channels");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        header.sampleRate = decodeState.readInt32();
							 | 
						||
| 
								 | 
							
								        if (header.sampleRate == 0) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_FIRST_PAGE, "no sampling rate");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        header.maximumBitRate = decodeState.readInt32();
							 | 
						||
| 
								 | 
							
								        header.nominalBitRate = decodeState.readInt32();
							 | 
						||
| 
								 | 
							
								        header.minimumBitRate = decodeState.readInt32();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        var x = decodeState.readByte();
							 | 
						||
| 
								 | 
							
								        var log0 = x & 15;
							 | 
						||
| 
								 | 
							
								        var log1 = x >> 4;
							 | 
						||
| 
								 | 
							
								        header.blocksize0 = 1 << log0;
							 | 
						||
| 
								 | 
							
								        header.blocksize1 = 1 << log1;
							 | 
						||
| 
								 | 
							
								        if (log0 < 6 || log0 > 13) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_SETUP);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (log1 < 6 || log1 > 13) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_SETUP);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (log0 > log1) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_SETUP);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // framingFlag
							 | 
						||
| 
								 | 
							
								        var x = decodeState.readByte();
							 | 
						||
| 
								 | 
							
								        if (x & 1 == 0) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(INVALID_FIRST_PAGE);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // comment fields
							 | 
						||
| 
								 | 
							
								        decodeState.page.start(decodeState);
							 | 
						||
| 
								 | 
							
								        decodeState.startPacket();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        var len = 0;
							 | 
						||
| 
								 | 
							
								        var output = new BytesOutput();
							 | 
						||
| 
								 | 
							
								        while((len = decodeState.next()) != 0) {
							 | 
						||
| 
								 | 
							
								            output.write(decodeState.readBytes(len));
							 | 
						||
| 
								 | 
							
								            decodeState.bytesInSeg = 0;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            var packetInput = new BytesInput(output.getBytes());
							 | 
						||
| 
								 | 
							
								            packetInput.readByte();
							 | 
						||
| 
								 | 
							
								            packetInput.read(6);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            var vendorLength:UInt = packetInput.readInt32();
							 | 
						||
| 
								 | 
							
								            header.vendor = packetInput.readString(vendorLength);
							 | 
						||
| 
								 | 
							
								            header.comment = new Comment();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            var commentCount = packetInput.readInt32();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            for (i in 0...commentCount) {
							 | 
						||
| 
								 | 
							
								                var n = packetInput.readInt32();
							 | 
						||
| 
								 | 
							
								                var str = packetInput.readString(n);
							 | 
						||
| 
								 | 
							
								                var splitter = str.indexOf("=");
							 | 
						||
| 
								 | 
							
								                if (splitter != -1) {
							 | 
						||
| 
								 | 
							
								                    header.comment.add(str.substring(0, splitter), str.substring(splitter + 1));
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            var x = packetInput.readByte();
							 | 
						||
| 
								 | 
							
								            if (x & 1 == 0) {
							 | 
						||
| 
								 | 
							
								                throw new ReaderError(ReaderErrorType.INVALID_SETUP);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // third packet!
							 | 
						||
| 
								 | 
							
								        decodeState.startPacket();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (decodeState.readPacket() != PACKET_SETUP) {
							 | 
						||
| 
								 | 
							
								            throw new ReaderError(ReaderErrorType.INVALID_SETUP, "setup packet");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        decodeState.vorbisValidate();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // codebooks
							 | 
						||
| 
								 | 
							
								        var codebookCount = decodeState.readBits(8) + 1;
							 | 
						||
| 
								 | 
							
								        header.codebooks = new Vector(codebookCount);
							 | 
						||
| 
								 | 
							
								        for (i in 0...codebookCount) {
							 | 
						||
| 
								 | 
							
								            header.codebooks[i] = Codebook.read(decodeState);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // time domain transfers (notused)
							 | 
						||
| 
								 | 
							
								        x = decodeState.readBits(6) + 1;
							 | 
						||
| 
								 | 
							
								        for (i in 0...x) {
							 | 
						||
| 
								 | 
							
								            if (decodeState.readBits(16) != 0) {
							 | 
						||
| 
								 | 
							
								                throw new ReaderError(INVALID_SETUP);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Floors
							 | 
						||
| 
								 | 
							
								        var floorCount = decodeState.readBits(6) + 1;
							 | 
						||
| 
								 | 
							
								        header.floorConfig = new Vector(floorCount);
							 | 
						||
| 
								 | 
							
								        for (i in 0...floorCount) {
							 | 
						||
| 
								 | 
							
								            header.floorConfig[i] = Floor.read(decodeState, header.codebooks);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Residue
							 | 
						||
| 
								 | 
							
								        var residueCount = decodeState.readBits(6) + 1;
							 | 
						||
| 
								 | 
							
								        header.residueConfig = new Vector(residueCount);
							 | 
						||
| 
								 | 
							
								        for (i in 0...residueCount) {
							 | 
						||
| 
								 | 
							
								            header.residueConfig[i] = Residue.read(decodeState, header.codebooks);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        //Mapping
							 | 
						||
| 
								 | 
							
								        var mappingCount = decodeState.readBits(6) + 1;
							 | 
						||
| 
								 | 
							
								        header.mapping = new Vector(mappingCount);
							 | 
						||
| 
								 | 
							
								        for (i in 0...mappingCount) {
							 | 
						||
| 
								 | 
							
								            var map = Mapping.read(decodeState, header.channel);
							 | 
						||
| 
								 | 
							
								            header.mapping[i] = map;
							 | 
						||
| 
								 | 
							
								            for (j in 0...map.submaps) {
							 | 
						||
| 
								 | 
							
								                if (map.submapFloor[j] >= header.floorConfig.length) {
							 | 
						||
| 
								 | 
							
								                    throw new ReaderError(INVALID_SETUP);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                if (map.submapResidue[j] >= header.residueConfig.length) {
							 | 
						||
| 
								 | 
							
								                    throw new ReaderError(INVALID_SETUP);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        var modeCount = decodeState.readBits(6) + 1;
							 | 
						||
| 
								 | 
							
								        header.modes = new Vector(modeCount);
							 | 
						||
| 
								 | 
							
								        for (i in 0...modeCount) {
							 | 
						||
| 
								 | 
							
								            var mode = Mode.read(decodeState);
							 | 
						||
| 
								 | 
							
								            header.modes[i] = mode;
							 | 
						||
| 
								 | 
							
								            if (mode.mapping >= header.mapping.length) {
							 | 
						||
| 
								 | 
							
								                throw new ReaderError(INVALID_SETUP);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        decodeState.flushPacket();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return header;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |