299 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			299 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| package kha.audio2.ogg.vorbis.data;
 | |
| import haxe.ds.Vector;
 | |
| import haxe.io.Input;
 | |
| import kha.audio2.ogg.vorbis.VorbisDecodeState;
 | |
| 
 | |
| /**
 | |
|  * ...
 | |
|  * @author shohei909
 | |
|  */
 | |
| class Residue
 | |
| {
 | |
|     public var begin(default, null):UInt; // uint32
 | |
|     public var end(default, null):UInt; // uint32
 | |
|     public var partSize(default, null):UInt; // uint32
 | |
|     public var classifications(default, null):Int; // uint8
 | |
|     public var classbook(default, null):Int; // uint8
 | |
|     public var classdata(default, null):Vector<Vector<Int>>; //uint8 **
 | |
|     public var residueBooks(default, null):Vector<Vector<Int>>; //int16 (*)[8]
 | |
|     public var type(default, null):Int;
 | |
| 
 | |
|     public function new() {
 | |
|     }
 | |
| 
 | |
|     public static function read(decodeState:VorbisDecodeState, codebooks:Vector<Codebook>):Residue
 | |
|     {
 | |
|         var r = new Residue();
 | |
|         r.type = decodeState.readBits(16);
 | |
|         if (r.type > 2) {
 | |
|             throw new ReaderError(INVALID_SETUP);
 | |
|         }
 | |
| 
 | |
|         var residueCascade = new Vector<Int>(64);
 | |
|         r.begin = decodeState.readBits(24);
 | |
|         r.end = decodeState.readBits(24);
 | |
|         r.partSize = decodeState.readBits(24)+1;
 | |
|         var classifications = r.classifications = decodeState.readBits(6)+1;
 | |
|         r.classbook = decodeState.readBits(8);
 | |
| 
 | |
|         for (j in 0...r.classifications) {
 | |
|             var highBits = 0;
 | |
|             var lowBits = decodeState.readBits(3);
 | |
|             if (decodeState.readBits(1) != 0){
 | |
|                 highBits = decodeState.readBits(5);
 | |
|             }
 | |
|             residueCascade[j] = highBits * 8 + lowBits;
 | |
|         }
 | |
| 
 | |
|         r.residueBooks = new Vector(r.classifications);
 | |
|         for (j in 0...r.classifications) {
 | |
|             r.residueBooks[j] = new Vector(8);
 | |
|             for (k in 0...8) {
 | |
|                 if (residueCascade[j] & (1 << k) != 0) {
 | |
|                     r.residueBooks[j][k] = decodeState.readBits(8);
 | |
|                     if (r.residueBooks[j][k] >= codebooks.length) {
 | |
|                         throw new ReaderError(INVALID_SETUP);
 | |
|                     }
 | |
|                 } else {
 | |
|                     r.residueBooks[j][k] = -1;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // precompute the classifications[] array to avoid inner-loop mod/divide
 | |
|         // call it 'classdata' since we already have classifications
 | |
|         var el = codebooks[r.classbook].entries;
 | |
|         var classwords = codebooks[r.classbook].dimensions;
 | |
|         r.classdata = new Vector(el);
 | |
| 
 | |
|         for (j in 0...el) {
 | |
|             var temp = j;
 | |
|             var k = classwords;
 | |
|             var cd = r.classdata[j] = new Vector(classwords);
 | |
|             while (--k >= 0) {
 | |
|                 cd[k] = temp % classifications;
 | |
|                 temp = Std.int(temp / classifications);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return r;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public function decode(decodeState:VorbisDecodeState, header:Header, residueBuffers:Vector<Vector<Float>>, ch:Int, n:Int,  doNotDecode:Vector<Bool>, channelBuffers:Vector<Vector<Float>>)
 | |
|     {
 | |
|         // STB_VORBIS_DIVIDES_IN_RESIDUE = true
 | |
|         var codebooks = header.codebooks;
 | |
|         var classwords = codebooks[classbook].dimensions;
 | |
|         var nRead = end - begin;
 | |
|         var partSize = this.partSize;
 | |
|         var partRead = Std.int(nRead / partSize);
 | |
|         var classifications = new Vector<Int>(header.channel * partRead + 1); // + 1 is a hack for a possible crash in line 268 with some ogg files
 | |
| 
 | |
|         VorbisTools.stbProf(2);
 | |
|         for (i in 0...ch) {
 | |
|             if (!doNotDecode[i]) {
 | |
|                 var buffer = residueBuffers[i];
 | |
|                 for (j in 0...buffer.length) {
 | |
|                     buffer[j] = 0;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (type == 2 && ch != 1) {
 | |
|             for (j in 0...ch) {
 | |
|                 if (!doNotDecode[j]) {
 | |
|                     break;
 | |
|                 } else if (j == ch - 1) {
 | |
|                     return;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             VorbisTools.stbProf(3);
 | |
|             for (pass in 0...8) {
 | |
|                 var pcount = 0, classSet = 0;
 | |
|                 if (ch == 2) {
 | |
|                     VorbisTools.stbProf(13);
 | |
|                     while (pcount < partRead) {
 | |
|                         var z = begin + pcount * partSize;
 | |
|                         var cInter = (z & 1);
 | |
|                         var pInter = z >> 1;
 | |
|                         if (pass == 0) {
 | |
|                             var c:Codebook = codebooks[classbook];
 | |
|                             var q = decodeState.decode(c);
 | |
|                             if (q == VorbisTools.EOP) {
 | |
|                                 return;
 | |
|                             }
 | |
|                             var i = classwords;
 | |
|                             while (--i >= 0) {
 | |
|                                 classifications[i + pcount] = q % this.classifications;
 | |
|                                 q = Std.int(q / this.classifications);
 | |
|                             }
 | |
|                         }
 | |
|                         VorbisTools.stbProf(5);
 | |
|                         for (i in 0...classwords) {
 | |
|                             if (pcount >= partRead) {
 | |
|                                 break;
 | |
|                             }
 | |
|                             var z = begin + pcount*partSize;
 | |
|                             var c = classifications[pcount];
 | |
|                             var b = residueBooks[c][pass];
 | |
|                             if (b >= 0) {
 | |
|                                 var book = codebooks[b];
 | |
|                                 VorbisTools.stbProf(20);  // accounts for X time
 | |
|                                 var result = book.decodeDeinterleaveRepeat(decodeState, residueBuffers, ch, cInter, pInter, n, partSize);
 | |
|                                 if (result == null) {
 | |
|                                     return;
 | |
|                                 } else {
 | |
|                                     cInter = result.cInter;
 | |
|                                     pInter = result.pInter;
 | |
|                                 }
 | |
|                                 VorbisTools.stbProf(7);
 | |
|                             } else {
 | |
|                                 z += partSize;
 | |
|                                 cInter = z & 1;
 | |
|                                 pInter = z >> 1;
 | |
|                             }
 | |
|                             ++pcount;
 | |
|                         }
 | |
|                         VorbisTools.stbProf(8);
 | |
|                     }
 | |
|                 } else if (ch == 1) {
 | |
|                     while (pcount < partRead) {
 | |
|                         var z = begin + pcount*partSize;
 | |
|                         var cInter = 0;
 | |
|                         var pInter = z;
 | |
|                         if (pass == 0) {
 | |
|                             var c:Codebook = codebooks[classbook];
 | |
|                             var q = decodeState.decode(c);
 | |
|                             if (q == VorbisTools.EOP) return;
 | |
| 
 | |
|                             var i = classwords;
 | |
|                             while (--i >= 0) {
 | |
|                                 classifications[i + pcount] = q % this.classifications;
 | |
|                                 q = Std.int(q / this.classifications);
 | |
|                             }
 | |
|                         }
 | |
| 
 | |
|                         for (i in 0...classwords) {
 | |
|                             if (pcount >= partRead) {
 | |
|                                 break;
 | |
|                             }
 | |
|                             var z = begin + pcount * partSize;
 | |
|                             var b = residueBooks[classifications[pcount]][pass];
 | |
|                             if (b >= 0) {
 | |
|                                 var book:Codebook = codebooks[b];
 | |
|                                 VorbisTools.stbProf(22);
 | |
|                                 var result = book.decodeDeinterleaveRepeat(decodeState, residueBuffers, ch, cInter, pInter, n, partSize);
 | |
|                                 if (result == null) {
 | |
|                                     return;
 | |
|                                 } else {
 | |
|                                     cInter = result.cInter;
 | |
|                                     pInter = result.pInter;
 | |
|                                 }
 | |
|                                 VorbisTools.stbProf(3);
 | |
|                             } else {
 | |
|                                 z += partSize;
 | |
|                                 cInter = 0;
 | |
|                                 pInter = z;
 | |
|                             }
 | |
|                             ++pcount;
 | |
|                         }
 | |
|                     }
 | |
|                 } else {
 | |
|                     while (pcount < partRead) {
 | |
|                         var z = begin + pcount * partSize;
 | |
|                         var cInter = z % ch;
 | |
|                         var pInter = Std.int(z / ch);
 | |
| 
 | |
|                         if (pass == 0) {
 | |
|                             var c:Codebook = codebooks[classbook];
 | |
|                             var q = decodeState.decode(c);
 | |
|                             if (q == VorbisTools.EOP) {
 | |
|                                 return;
 | |
|                             }
 | |
| 
 | |
|                             var i = classwords;
 | |
|                             while (--i >= 0) {
 | |
|                                 classifications[i+pcount] = q % this.classifications;
 | |
|                                 q = Std.int(q / this.classifications);
 | |
|                             }
 | |
|                         }
 | |
| 
 | |
|                         for (i in 0...classwords) {
 | |
|                             if (pcount >= partRead) {
 | |
|                                 break;
 | |
|                             }
 | |
|                             var z = begin + pcount * partSize;
 | |
|                             var b = residueBooks[classifications[pcount]][pass];
 | |
|                             if (b >= 0) {
 | |
|                                 var book = codebooks[b];
 | |
|                                 VorbisTools.stbProf(22);
 | |
|                                 var result = book.decodeDeinterleaveRepeat(decodeState, residueBuffers, ch, cInter, pInter, n, partSize);
 | |
|                                 if (result == null) {
 | |
|                                     return;
 | |
|                                 } else {
 | |
|                                     cInter = result.cInter;
 | |
|                                     pInter = result.pInter;
 | |
|                                 }
 | |
|                                 VorbisTools.stbProf(3);
 | |
|                             } else {
 | |
|                                 z += partSize;
 | |
|                                 cInter = z % ch;
 | |
|                                 pInter = Std.int(z / ch);
 | |
|                             }
 | |
|                             ++pcount;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             return;
 | |
|         }
 | |
|         VorbisTools.stbProf(9);
 | |
| 
 | |
|         for (pass in 0...8) {
 | |
|             var pcount = 0;
 | |
|             var classSet = 0;
 | |
|             while (pcount < partRead) {
 | |
|                 if (pass == 0) {
 | |
|                     for (j in 0...ch) {
 | |
|                         if (!doNotDecode[j]) {
 | |
|                             var c:Codebook = codebooks[classbook];
 | |
|                             var temp = decodeState.decode(c);
 | |
|                             if (temp == VorbisTools.EOP) {
 | |
|                                 return;
 | |
|                             }
 | |
|                             var i = classwords;
 | |
|                             while (--i >= 0) {
 | |
|                                 classifications[j * partRead + i + pcount] = temp % this.classifications;
 | |
|                                 temp = Std.int(temp / this.classifications);
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 for (i in 0...classwords) {
 | |
|                     if (pcount >= partRead) {
 | |
|                         break;
 | |
|                     }
 | |
|                     for (j in 0...ch) {
 | |
|                         if (!doNotDecode[j]) {
 | |
|                             var c = classifications[j  * partRead + pcount];
 | |
|                             var b = residueBooks[c][pass];
 | |
|                             if (b >= 0) {
 | |
|                                 var target = residueBuffers[j];
 | |
|                                 var offset = begin + pcount * partSize;
 | |
|                                 var n = partSize;
 | |
|                                 var book = codebooks[b];
 | |
|                                 if (!book.residueDecode(decodeState, target, offset, n, type)) {
 | |
|                                     return;
 | |
|                                 }
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     ++pcount;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |