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