forked from LeenkxTeam/LNXSDK
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() {
|
|
}
|
|
}
|