128 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| package kha.audio2.ogg.vorbis.data;
 | |
| import haxe.ds.Vector;
 | |
| import haxe.io.Input;
 | |
| import kha.audio2.ogg.tools.MathTools;
 | |
| import kha.audio2.ogg.vorbis.VorbisDecodeState;
 | |
| 
 | |
| class Mapping
 | |
| {
 | |
|     public var couplingSteps:Int; // uint16 
 | |
|     public var chan:Vector<MappingChannel>;
 | |
|     public var submaps:Int;            // uint8 
 | |
|     public var submapFloor:Vector<Int>;   // uint8 varies
 | |
|     public var submapResidue:Vector<Int>; // uint8 varies
 | |
|     public function new() {
 | |
|     }
 | |
|     
 | |
|     public static function read(decodeState:VorbisDecodeState, channels:Int):Mapping
 | |
|     {
 | |
|         var m = new Mapping();
 | |
|         var mappingType = decodeState.readBits(16);
 | |
|         if (mappingType != 0) {
 | |
|             throw new ReaderError(INVALID_SETUP, "mapping type " + mappingType);
 | |
|         }
 | |
|         
 | |
|         m.chan = new Vector(channels);
 | |
|         for (j in 0...channels) {
 | |
|             m.chan[j] = new MappingChannel();
 | |
|         }
 | |
|         
 | |
|         if (decodeState.readBits(1) != 0) {
 | |
|             m.submaps = decodeState.readBits(4)+1;
 | |
|         } else {
 | |
|             m.submaps = 1;
 | |
|         }
 | |
|         
 | |
|         //if (m.submaps > maxSubmaps) {
 | |
|         //    maxSubmaps = m.submaps;
 | |
|         //}
 | |
|         
 | |
|         if (decodeState.readBits(1) != 0) {
 | |
|             m.couplingSteps = decodeState.readBits(8)+1;
 | |
|             for (k in 0...m.couplingSteps) {
 | |
|                 m.chan[k].magnitude = decodeState.readBits(MathTools.ilog(channels-1));
 | |
|                 m.chan[k].angle = decodeState.readBits(MathTools.ilog(channels-1));
 | |
|                 if (m.chan[k].magnitude >= channels) {
 | |
|                     throw new ReaderError(INVALID_SETUP);
 | |
|                 }
 | |
|                 if (m.chan[k].angle >= channels) {
 | |
|                     throw new ReaderError(INVALID_SETUP);
 | |
|                 }
 | |
|                 if (m.chan[k].magnitude == m.chan[k].angle) {
 | |
|                     throw new ReaderError(INVALID_SETUP);
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             m.couplingSteps = 0;
 | |
|         }
 | |
| 
 | |
|         // reserved field
 | |
|         if (decodeState.readBits(2) != 0) {
 | |
|             throw new ReaderError(INVALID_SETUP);
 | |
|         }
 | |
|         if (m.submaps > 1) {
 | |
|             for (j in 0...channels) {
 | |
|                 m.chan[j].mux = decodeState.readBits(4);
 | |
|                 if (m.chan[j].mux >= m.submaps) {
 | |
|                     throw new ReaderError(INVALID_SETUP);
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             for (j in 0...channels) {
 | |
|                 m.chan[j].mux = 0;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         m.submapFloor = new Vector(m.submaps);
 | |
|         m.submapResidue = new Vector(m.submaps);
 | |
|         
 | |
|         for (j in 0...m.submaps) {
 | |
|             decodeState.readBits(8); // discard
 | |
|             m.submapFloor[j] = decodeState.readBits(8);
 | |
|             m.submapResidue[j] = decodeState.readBits(8);
 | |
|         }
 | |
|         
 | |
|         return m;
 | |
|     }
 | |
|     
 | |
|     public function doFloor(floors:Vector<Floor>, i:Int, n:Int, target:Vector<Float>, finalY:Array<Int>, step2Flag:Vector<Bool>) 
 | |
|     {
 | |
|         var n2 = n >> 1;
 | |
|         var s = chan[i].mux, floor;
 | |
|         var floor = floors[submapFloor[s]];
 | |
|         if (floor.type == 0) {
 | |
|             throw new ReaderError(INVALID_STREAM);
 | |
|         } else {
 | |
|             var g = floor.floor1;
 | |
|             var lx = 0, ly = finalY[0] * g.floor1Multiplier;
 | |
|             for (q in 1...g.values) {
 | |
|                 var j = g.sortedOrder[q];
 | |
|                 if (finalY[j] >= 0)
 | |
|                 {
 | |
|                     var hy = finalY[j] * g.floor1Multiplier;
 | |
|                     var hx = g.xlist[j];
 | |
|                     VorbisTools.drawLine(target, lx, ly, hx, hy, n2);
 | |
|                     lx = hx;
 | |
|                     ly = hy;
 | |
|                 }
 | |
|             }
 | |
|             if (lx < n2) {
 | |
|                 // optimization of: drawLine(target, lx,ly, n,ly, n2);
 | |
|                 for (j in lx...n2) {
 | |
|                     target[j] *= VorbisTools.INVERSE_DB_TABLE[ly];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| class MappingChannel
 | |
| {
 | |
|     public var magnitude:Int; // uint8 
 | |
|     public var angle:Int;     // uint8 
 | |
|     public var mux:Int;       // uint8 
 | |
|     
 | |
|     public function new() {
 | |
|     }
 | |
| }
 |