public int ScalarLookup(BitReader r) { HuffNode cur = RootNode; while (cur.Internal) { if (r.ReadBit()) cur = cur.One; else cur = cur.Zero; if (cur == null) throw new VorbisReadException("Bad huffman code encountered"); } return cur.Code; }
public float[][] Decode(BitReader r, int numVectors, int vectorLength, bool[] doNotDecodeFlags) { if (Type == 0 || Type == 1) { return Decode01(Type, r, numVectors, vectorLength, doNotDecodeFlags); } else if (Type == 2) { float[][] result = new float[numVectors][]; for (int i = 0; i < numVectors; ++i) result[i] = new float[vectorLength]; if (doNotDecodeFlags.All((x) => (x == true))) { // done early return result; } else { float[][] tmp = Decode01(1, r, 1, vectorLength*numVectors, doNotDecodeFlags); //float[] tmp0 = tmp[0]; //int m = 0; for (int i = 0; i < vectorLength; ++i) { for (int j = 0; j < numVectors; ++j) { result[j][i] = tmp[0][i * numVectors + j]; } } return result; } } else throw new VorbisReadException("bad residue type from setup"); }
private float[][] Decode01(int type, BitReader r, int numVectors, int vectorLength, bool[] doNotDecodeFlags) { int limitResidueBegin = Math.Min(Begin, vectorLength); int limitResidueEnd = Math.Min(End, vectorLength); int classWordsPerCodeWord = ClassBook.Dimensions; int nToRead = limitResidueEnd - limitResidueBegin; int partitionsToRead = nToRead / PartitionSize; float[][] result = new float[numVectors][]; for (int i = 0; i < numVectors; ++i) result[i] = new float[vectorLength]; if (nToRead == 0) return result; int[,] classifications = new int[numVectors, classWordsPerCodeWord + partitionsToRead]; for (int pass = 0; pass < 8; ++pass) { int partitionCount = 0; while (partitionCount < partitionsToRead) { if (pass == 0) { for (int j = 0; j < numVectors; ++j) { if (!doNotDecodeFlags[j]) { int temp = ClassBook.ScalarLookup(r); for (int i = classWordsPerCodeWord - 1; i >= 0; --i) { // TODO: Isn't this indexing f*****g weird? classifications[j,i+partitionCount] = temp % ClassificationCount; temp = temp / ClassificationCount; } } } } for (int i = 0; i < classWordsPerCodeWord && partitionCount < partitionsToRead; ++i ) { for (int j = 0; j < numVectors; ++j) { int vqclass = classifications[j, partitionCount]; Codebook vqbook = Books[vqclass, pass]; if (vqbook != null) { int offset = limitResidueBegin + partitionCount * PartitionSize; if (type == 0) { //DecodeFormat0(r, vqbook, offset, result[j]); throw new NotImplementedException(); } else if (type == 1) { DecodeFormat1(r, vqbook, offset, result[j]); } } } ++partitionCount; } } } return result; }
private void DecodeFormat1(BitReader r, Codebook vqbook, int offset, float[] v) { int n = PartitionSize; int i=0; do { float[] entryTemp = vqbook.VectorLookup(r); for (int j = 0; j < vqbook.Dimensions; ++j) { v[offset + i] += entryTemp[j]; ++i; } } while(i <n); }
public override bool Decode(BitReader r, int samples, float[] data) { throw new NotImplementedException(); }
public abstract bool Decode(BitReader r, int samples, float[] data);
public override bool Decode(BitReader r, int samples, float[] data) { if (!r.ReadBit()) { //Console.WriteLine(" (zero)"); //data = null; return false; } int[] ylist = ylistStorage; int range; if (Multiplier == 1) range = 256; else if (Multiplier == 2) range = 128; else if (Multiplier == 3) range = 84; else if (Multiplier == 4) range = 64; else // this is really a consistency check throw new VorbisReadException("Bad multiplier"); ylist[0] = (int)r.ReadUnsigned(VorbisUtil.InverseLog(range - 1)); ylist[1] = (int)r.ReadUnsigned(VorbisUtil.InverseLog(range - 1)); int offset = 2; foreach (Floor1Class cls in ClassesByPartition) { int cdim = cls.Dimensions; int cbits = cls.SubclassBits; int csub = (1 << cbits) - 1; int cval = 0; if (cbits > 0) { cval = cls.MasterCodebook.ScalarLookup(r); } for (int j = 0; j < cdim; ++j) { Codebook book = cls.SubclassBooks[cval & csub]; cval = cval >> cbits; if (book != null) { ylist[offset + j] = book.ScalarLookup(r); } else { ylist[offset + j] = 0; } } offset += cdim; } /*Console.Write(" X vals: "); for (int i = 0; i < XList.Length; ++i) Console.Write("{0},", XList[i]); Console.WriteLine(); Console.Write(" Y vals: "); for (int i = 0; i < XList.Length; ++i) Console.Write("{0},", ylist[i]); Console.WriteLine();*/ /*Console.Write(" >>> "); for(int i=0; i<XList.Length; ++i) Console.Write("{0},{1},", XList[i], ylist[i]); Console.WriteLine();*/ // "amplitude value synthesis" -- // "Unwrap the always-positive-or-zero values read from the packet into +/- difference values, then apply to line prediction." bool[] step2Flag = step2FlagStorage;// new bool[XList.Length]; int[] finalY = ylist;//new int[XList.Length]; step2Flag[0] = true; step2Flag[1] = true; //finalY[0] = ylist[0]; //finalY[1] = ylist[1]; for (int i = 2; i<ylist.Length; ++i) { int lowNeighborOffset = LowNeighborLookup[i];// lowNeighbor(XList, i); int highNeighborOffset = HighNeighborLookup[i];// highNeighbor(XList, i); //Console.WriteLine("lo={0},hi={1}", lowNeighborOffset, highNeighborOffset); int predicted = renderPoint(XList[lowNeighborOffset], finalY[lowNeighborOffset], XList[highNeighborOffset], finalY[highNeighborOffset], XList[i]); int val = ylist[i]; int highroom = range - predicted; int lowroom = predicted; int room = (highroom < lowroom) ? (highroom * 2) : (lowroom * 2); /*Console.WriteLine("lo={0}, hi={1}, loroom={2}, hiroom={3}, room={4}, val={5}, predicted={6}", lowNeighborOffset, highNeighborOffset, lowroom, highroom, room, val, predicted); Console.WriteLine("finalY[{0}]={1}, finalY[{2}]={3}", lowNeighborOffset, finalY[lowNeighborOffset], highNeighborOffset, finalY[highNeighborOffset]); */ if (val != 0) { step2Flag[lowNeighborOffset] = true; step2Flag[highNeighborOffset] = true; step2Flag[i] = true; if (val >= room) { if (highroom > lowroom) { finalY[i] = val - lowroom + predicted; } else // highroom <= lowroom { finalY[i] = predicted - val + highroom - 1; } } else // val < room { // val is odd if ((val % 2) != 0) { finalY[i] = predicted - ((val + 1) / 2); } // val is even else { finalY[i] = predicted + (val / 2); } } } else { step2Flag[i] = false; finalY[i] = predicted; } //Console.WriteLine("Wrote finalY[{0}] = {1}", i, finalY[i]); } /* Console.Write(" reconstituted y vals: "); for (int i = 0; i < XList.Length; ++i) Console.Write("{0},", finalY[i]); Console.WriteLine(); Console.Write(" Flags: "); for (int i = 0; i < XList.Length; ++i) Console.Write("{0},", step2Flag[i]?1:0); Console.WriteLine(); */ /*Console.Write(" >>> "); for(int i=0; i<XList.Length; ++i) if(step2Flag[i]) Console.Write("{0},{1},", XList[i], finalY[i]); Console.WriteLine();*/ /*int[] indices = new int[XList.Length]; for (int i = 0; i < indices.Length; ++i) indices[i] = i;*/ /*int[] xlistSorted = new int[XList.Length]; int[] finalYSorted = new int[XList.Length]; bool[] step2FlagSorted = new bool[XList.Length]; int n = 0; foreach(int i in SortTable)//indices.OrderBy((i) => XList[i])) { xlistSorted[n] = XList[i]; finalYSorted[n] = finalY[i]; step2FlagSorted[n] = step2Flag[i]; ++n; }*/ /* Console.Write(" $$$ "); for(int i=0; i<XList.Length; ++i) if(step2FlagSorted[i]) Console.Write("{0},{1},", xlistSorted[i], finalYSorted[i]); Console.WriteLine();*/ //int maxX = XList.Max(); int hx = 0; int hy = 0; int lx = 0; int ly = finalY[SortTable[0]] * Multiplier; for (int i = 1; i < XList.Length; ++i) { int j = SortTable[i]; if (step2Flag[j]) { hy = finalY[j] * Multiplier; hx = XList[j]; renderLine(samples, lx, ly, hx, hy, data); lx = hx; ly = hy; } } // TODO: Not 100% certain what we ought to do here. // Check spec/libvorbis. if (hx < samples) { renderLine(samples, hx, hy, samples, hy, data); } /*Console.Write(" ### "); for (int i = 0; i < floor.Length; ++i) Console.Write("{0},", floor[i]); Console.WriteLine();*/ /*float[] clippedFloor = new float[samples]; for (int i = 0; i <= maxX && i < samples; ++i) clippedFloor[i] = inverseDecibelTable[floor[i]];*/ /*Console.Write("FLOOR INVERSE: "); for (int i = 0; i < samples; ++i) Console.Write("{0}{1}", (i != 0) ? "," : "", data[i]); Console.WriteLine();*/ return true; }
public float[] VectorLookup(BitReader r) { return Lookup[ScalarLookup(r)]; }