Ejemplo n.º 1
0
        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;
        }
Ejemplo n.º 2
0
        private void ReadSetupHeader(BitReader r)
        {
            uint numCodebooks = r.ReadUnsigned(8) + 1;
            WriteLine("  Codebooks: {0}", numCodebooks);

            for (int i = 0; i < numCodebooks; ++i)
            {
                WriteLine("  Codebook[{0}]", i);

                if (r.ReadUnsigned(24) != 0x564342)
                {
                    throw new VorbisReadException("Lost codebook sync");
                }

                Codebook cb = ReadCodebook(r);

                cb.BuildLookup();
                //cb.Dump();
                codebooks.Add(cb);
            }

            // just ignore some shit
            int timeCount = (int)r.ReadUnsigned(6) + 1;
            for (int i = 0; i < timeCount; ++i)
            {
                uint val = r.ReadUnsigned(16);
                if (val != 0)
                {
                    throw new VorbisReadException("Bad timecount value. Ought to be zero.");
                }
            }

            int floorCount = (int)r.ReadUnsigned(6) + 1;
            WriteLine("  Floors: {0}", floorCount);
            for (int i = 0; i < floorCount; ++i)
            {
                WriteLine("  Floor[{0}]", i);
                Floor floor = ReadFloor(r);
                floors.Add(floor);
            }

            int residueCount = (int)r.ReadUnsigned(6) + 1;
            WriteLine("  Residues: {0}", residueCount);

            for (int i = 0; i < residueCount; ++i)
            {
                WriteLine("  Residue[{0}]", i);
                Residue res = ReadResidue(r);
                residues.Add(res);
            }

            int mappingCount = (int)r.ReadUnsigned(6) + 1;
            WriteLine("  Mappings: {0}", mappingCount);

            for (int i = 0; i < mappingCount; ++i)
            {
                WriteLine("  Mapping[{0}]", i);
                mappings.Add(ReadMapping(r));
            }

            int modeCount = (int)r.ReadUnsigned(6) + 1;
            WriteLine("  Modes: {0}", modeCount);

            for (int i = 0; i < modeCount; ++i)
            {
                WriteLine("  Mode[{0}]", i);
                modes.Add(ReadMode(r));
            }

            bool framingFlag = r.ReadBit();
            if (!framingFlag)
            {
                throw new VorbisReadException("Framing flag was 0; should be 1.");
            }

            //WriteLine("  Remaining bits in packet: {0}", r.BitsLeft);
            //Console.WriteLine("Framing flag OK. Completed setup read.");
        }
Ejemplo n.º 3
0
        private void ReadWavePacket(byte[] packet)
        {
            if (wr == null)
                wr = new BinaryWriter(File.Create("out.pcm"));

            BitReader r = new BitReader(packet, packet.Length);

            if (r.ReadBit())
                throw new VorbisReadException("First bit of packet should be zero (audio)");

            //Console.WriteLine("Audio Packet");

            int modeNumber = (int)r.ReadUnsigned(VorbisUtil.InverseLog(modes.Count - 1));
            if(modeNumber >= modes.Count)
                throw new VorbisReadException("Bad mode count");
            Mode mode = modes[modeNumber];

            //Console.WriteLine("  Mode: {0}", modeNumber);

            int blocksize = mode.BlockFlag ? blocksize1 : blocksize0;

            bool previousWindowFlag = false;
            bool nextWindowFlag = false;

            if (mode.BlockFlag)
            {
                previousWindowFlag = r.ReadBit();
                nextWindowFlag = r.ReadBit();
            }

            List<float[]> floors = new List<float[]>();
            bool[] noResidue = new bool[channels];
            bool[] doNotDecodeFlags = new bool[channels];

            Mapping map = mode.Mapping;

            for (int i = 0; i < channels; ++i)
            {
                //Console.WriteLine("  Channel[{0}]", i);
                Floor floor = map.SubMapsByChannel[i].Floor;

                float[] data = new float[blocksize / 2];
                if (!floor.Decode(r, blocksize / 2, data))
                {
                    noResidue[i] = true;
                }

                floors.Add(data);
            }

            // verify some stuff
            foreach (CouplingStep step in map.CouplingSteps)
            {
                if(noResidue[step.MagnitudeChannel] != noResidue[step.AngleChannel])
                    throw new VorbisReadException("Magnitude and angle channel must both have no_residue[i] set to true or both set to false");
            }

            float[][] channelResidues = new float[channels][];

            // TODO: Necessary?
            for (int i = 0; i < channels; ++i)
                channelResidues[i] = new float[blocksize / 2];

            for (int i = 0; i < map.SubMaps.Length; ++i)
            {
                int ch = 0;

                for (int j = 0; j < channels; ++j)
                {
                    if (map.SubMapsByChannel[j] == map.SubMaps[i])
                    {
                        doNotDecodeFlags[ch] = noResidue[j];
                        ++ch;
                    }
                }

                Residue residue = map.SubMaps[i].Residue;

                // TODO:
                // "decode [ch] vectors using residue [residue_number], according to type [residue_type],
                // also passing vector [do_not_decode_flag] to indicate which vectors in the bundle should not be decoded.
                // Correct per-vector decode length is [n]/2."
                float[][] residueResult = residue.Decode(r, ch,  blocksize/2, doNotDecodeFlags);

                ch = 0;
                for (int j = 0; j < channels; ++j)
                {
                    if (map.SubMapsByChannel[j] == map.SubMaps[i])
                    {
                        // TODO: "residue vector for channel [j] is set to decoded residue vector [ch]"
                        channelResidues[j] = residueResult[ch];
                        ++ch;
                    }
                }
            }

            // Inverse channel coupling
            for (int i = map.CouplingSteps.Length - 1; i >= 0; --i)
            {
                float[] magnitude = channelResidues[map.CouplingSteps[i].MagnitudeChannel];
                float[] angle = channelResidues[map.CouplingSteps[i].AngleChannel];

                for (int j = 0; j < magnitude.Length; ++j)
                {
                    float M = magnitude[j];
                    float A = angle[j];

                    float new_M;
                    float new_A;

                    if (M > 0)
                    {
                        if (A > 0)
                        {
                            new_M = M;
                            new_A = M - A;
                        }
                        else
                        {
                            new_A = M;
                            new_M = M + A;
                        }
                    }
                    else
                    {
                        if (A > 0)
                        {
                            new_M = M;
                            new_A = M+A;
                        }
                        else
                        {
                            new_A = M;
                            new_M = M - A;
                        }
                    }

                    magnitude[j] = new_M;
                    angle[j] = new_A;
                }
            }

            /*for (int i = 0; i < channels; ++i)
            {
                Console.Write("RESIDUE INVERSE: ");
                for (int k = 0; k < blocksize / 2; ++k)
                    Console.Write("{0}{1}", (k != 0) ? "," : "", floors[i][k] * channelResidues[i][k]);
                Console.WriteLine();
            }*/

            for (int i = 0; i < 1 /*channels*/; ++i)
            {
                float[] floor = floors[i];
                float[] residue = channelResidues[i];
                float[] mdctInput = new float[blocksize / 2];
                for (int j = 0; j < floor.Length; ++j)
                    mdctInput[j] = floor[j] * residue[j];

                float[] mdctOutput = new float[blocksize];

                MDCT(mdctInput, mdctOutput, blocksize / 2);

                int n = blocksize;
                int windowCenter = n / 2;

                int leftStart, leftEnd, leftN;
                int rightStart, rightEnd, rightN;

                if (mode.BlockFlag && !previousWindowFlag)
                {
                    leftStart = n / 4 - blocksize0 / 4;
                    leftEnd = n / 4 + blocksize0 / 4;
                    leftN = blocksize0 / 2;
                }
                else
                {
                    leftStart = 0;
                    leftEnd = windowCenter;
                    leftN = n / 2;
                }

                if (mode.BlockFlag && !nextWindowFlag)
                {
                    rightStart = n * 3/ 4 - blocksize0 / 4;
                    rightEnd = n * 3 / 4 + blocksize0 / 4;
                    rightN = blocksize0 / 2;
                }
                else
                {
                    rightStart = windowCenter;
                    rightEnd = n;
                    rightN = n / 2;
                }

                for (int j = 0; j < leftStart; ++j)
                    mdctOutput[j] = 0;

                for (int j = leftStart; j < leftEnd; ++j)
                    mdctOutput[j] *= VorbisWindow(j - leftStart, leftN*2);

                for (int j = rightStart; j < rightEnd; ++j)
                    mdctOutput[j] *= VorbisWindow(rightN + (j - rightStart), rightN*2);

                for (int j = rightEnd; j < n; ++j)
                    mdctOutput[j] = 0;

                if (i == 0)
                {
                    if (lastLap.Count > 0)
                    {
                        for (int j = leftStart; j < leftEnd; ++j)
                            mdctOutput[j] += lastLap[j - leftStart];
                    }

                    lastLap.Clear();

                    for (int j = leftStart; j < rightStart; ++j)
                    {
                        wr.Write(mdctOutput[j]);
                        ++samples;
                        if (samples % 4410 == 0)
                        {
                            Console.WriteLine("{0:0.0} seconds", samples / 44100.0);
                        }
                    }

                    for (int j = rightStart; j < rightEnd;  ++j)
                    {
                        lastLap.Add(mdctOutput[j]);
                    }
                }
            }
        }
Ejemplo n.º 4
0
        public void ReadHeader(byte[] data)
        {
            BitReader r = new BitReader(data, data.Length);

            byte firstByte = data[0];

            // skip 1st byte
            r.ReadUnsigned(8);

            string sig = "vorbis";
            for (int i = 0; i < 6; ++i)
            {
                if (r.ReadUnsigned(8) != (uint)sig[i])
                {
                    throw new VorbisReadException("Bad header signature, should be 'vorbis'");
                }
            }

            if (firstByte == 0x01)
            {
                WriteLine("Identification header");

                uint vorbisVersion = r.ReadUnsigned(32);

                if (vorbisVersion != 0)
                {
                    throw new VorbisReadException("Bad vorbis version: {0}", vorbisVersion);
                }

                channels = (int)r.ReadUnsigned(8);
                sampleRate = (uint)r.ReadUnsigned(32);
                bitrateMax = r.ReadSigned(32);
                bitrateNominal = r.ReadSigned(32);
                bitrateMin = r.ReadSigned(32);
                uint blocksize0exp = r.ReadUnsigned(4);
                uint blocksize1exp = r.ReadUnsigned(4);
                //framingFlag = r.ReadBit();
                if (channels == 0)
                    throw new VorbisReadException("Zero channels");
                if (sampleRate == 0)
                    throw new VorbisReadException("Zero sample rate");
                if (!r.ReadBit())
                    throw new VorbisReadException("Framing error on identification header");

                if (blocksize0exp < 6 || blocksize0exp > 13)
                {
                    throw new VorbisReadException("Bad blocksize0: 2^{0}", blocksize0exp);
                }

                if (blocksize1exp < 6 || blocksize1exp > 13)
                {
                    throw new VorbisReadException("Bad blocksize1: 2^{0}", blocksize1exp);
                }

                blocksize0 = 1 << (int)blocksize0exp;
                blocksize1 = 1 << (int)blocksize1exp;

                WriteLine("  Version: {0}", vorbisVersion);
                WriteLine("  Channels: {0}", channels);
                WriteLine("  Sample rate: {0} Hz", sampleRate);
                WriteLine("  Bitrate (maximum): {0:0.0} kbps", bitrateMax / 1000.0);
                WriteLine("  Bitrate (nominal): {0:0.0} kbps", bitrateNominal / 1000.0);
                WriteLine("  Bitrate (minimum): {0:0.0} kbps", bitrateMin / 1000.0);
                WriteLine("  Block size 0: {0} (2^{1})", blocksize0, blocksize0exp);
                WriteLine("  Block size 1: {0} (2^{1})", blocksize1, blocksize1exp);
                //Console.WriteLine("  Framing flag: {0}", framingFlag ? 1 : 0);
            }
            else if (firstByte == 0x03)
            {
                WriteLine("Comment header");

                vendor = r.ReadString();
                WriteLine("  Vendor: \"{0}\"", vendor);
                uint comments = r.ReadUnsigned(32);
                for (int i = 0; i < comments; ++i)
                {
                    string comment = r.ReadString();
                    userComments.Add(comment);
                    WriteLine("  Comment[{0}]: \"{1}\"", i, comment);
                }
                if (!r.ReadBit())
                    throw new VorbisReadException("Framing error on comment header");
            }
            else if (firstByte == 0x05)
            {
                WriteLine("Setup header");
                ReadSetupHeader(r);
            }
            else
            {
                throw new VorbisReadException("Invalid header type: 0x{0:2X}", firstByte);
            }
        }
Ejemplo n.º 5
0
        private Residue ReadResidue(BitReader r)
        {
            int residueType = (int)r.ReadUnsigned(16);

            int begin = (int)r.ReadUnsigned(24);
            int end = (int)r.ReadUnsigned(24);
            int partitionSize = (int)r.ReadUnsigned(24) + 1;
            int classifications = (int)r.ReadUnsigned(6) + 1;
            int classBook = (int)r.ReadUnsigned(8);

            if (begin > end)
                throw new VorbisReadException("Residue begin should not be greater than end");

            if (classBook >= codebooks.Count)
                throw new VorbisReadException("Bad codebook index for residue's classBook: {0}", classBook);

            WriteLine("    Residue type: {0}", residueType);
            WriteLine("    Begin: {0}", begin);
            WriteLine("    End: {0}", end);
            WriteLine("    Partition size: {0}", partitionSize);
            WriteLine("    Classifications: {0}", classifications);
            WriteLine("    Class book: {0}", classBook);

            int[] residueCascade = new int[classifications];
            //int[,] residueBooks = new int[classifications, 8];
            //bool[,] residueBooksUsed = new bool[classifications, 8];
            Codebook[,] residueBooks = new Codebook[classifications, 8];

            for (int i = 0; i < classifications; ++i)
            {
                int highBits = 0;
                int lowBits = (int)r.ReadUnsigned(3);
                bool bitFlag = r.ReadBit();
                if (bitFlag)
                    highBits = (int)r.ReadUnsigned(5);
                residueCascade[i] = highBits * 8 + lowBits;

                WriteLine("    Residue cascade[{0}] = {1}", i, residueCascade[i]);
            }

            for (int i = 0; i < classifications; ++i)
            {
                for (int j = 0; j < 8; ++j)
                {
                    if ((residueCascade[i] & (1 << j)) != 0)
                    {
                        int booknum = (int)r.ReadUnsigned(8);
                        if (booknum >= codebooks.Count)
                            throw new VorbisReadException("Bad codebook index when reading residueBooks[{0}][{1}]: {2}", i, j, booknum);

                        WriteLine("    Residue books[{0},{1}] = {2}", i, j, booknum);
                        residueBooks[i, j] = codebooks[booknum];
                    }
                    else
                    {
                        WriteLine("    Residue books[{0},{1}] = unused", i, j);
                    }
                }
            }

            Residue residue = new Residue();
            residue.Type = residueType;
            residue.Begin = begin;
            residue.End = end;
            residue.PartitionSize = partitionSize;
            residue.ClassificationCount = classifications;
            residue.ClassBook = codebooks[classBook];
            residue.Cascade = residueCascade;
            residue.Books = residueBooks;
            return residue;
        }
Ejemplo n.º 6
0
        private Mode ReadMode(BitReader r)
        {
            Mode mode = new Mode();

            mode.BlockFlag = r.ReadBit();
            int windowType = (int)r.ReadUnsigned(16);

            if (windowType != 0)
                throw new VorbisReadException("Bad window type in mode: {0}", windowType);

            int transformType = (int)r.ReadUnsigned(16);

            if (transformType != 0)
                throw new VorbisReadException("Bad transform type in mode: {0}", transformType);

            int mapping = (int)r.ReadUnsigned(8);

            if (mapping >= mappings.Count)
                throw new VorbisReadException("Bad mapping index in mode: {0}", mapping);

            mode.Mapping = mappings[mapping];

            WriteLine("    Block flag: {0}", mode.BlockFlag ? 1 : 0);
            WriteLine("    Window type: {0}", windowType);
            WriteLine("    Transform type: {0}", transformType);
            WriteLine("    Mapping: {0}", mapping);

            return mode;
        }
Ejemplo n.º 7
0
        private Mapping ReadMapping(BitReader r)
        {
            Mapping mapping = new Mapping();

            int mappingType = (int)r.ReadUnsigned(16);

            if (mappingType != 0)
            {
                throw new VorbisReadException("Bad mapping type: {0}", mappingType);
            }
            //Console.WriteLine("    Mapping type: {0}", mappingType);

            int submaps = 1;

            if (r.ReadBit())
                submaps = (int)r.ReadUnsigned(4) + 1;

            //Console.WriteLine("    Submaps: {0}", submaps);

            /*
            int[] magnitudes;
            int[] angles;
            */

            int couplingSteps = 0;

            if (r.ReadBit())
            {
                couplingSteps = (int)r.ReadUnsigned(8) + 1;
            }

            mapping.CouplingSteps = new CouplingStep[couplingSteps];

            int channelBits = VorbisUtil.InverseLog(channels-1);

            //Console.WriteLine("    Coupling steps: {0}",couplingSteps);

            for (int j = 0; j < couplingSteps; ++j)
            {
                CouplingStep step = new CouplingStep();

                step.MagnitudeChannel = (int)r.ReadUnsigned(channelBits);
                step.AngleChannel = (int)r.ReadUnsigned(channelBits);

                mapping.CouplingSteps[j] = step;

                WriteLine("    Coupling step {0}: Magnitude from channel {1}, angle from channel {2}", j, step.MagnitudeChannel, step.AngleChannel);
            }

            int reserved = (int)r.ReadUnsigned(2);
            if (reserved != 0)
            {
                throw new VorbisReadException("Bad 2-bit reserved value in mapping: {0}", reserved);
            }

            int[] mux = new int[channels];

            if (submaps > 1)
            {
                for (int j = 0; j < channels; ++j)
                {
                    mux[j] = (int)r.ReadUnsigned(4);
                    if (mux[j] >= submaps)
                    {
                        throw new VorbisReadException("Bad multiplex value in mapping: {0}", mux[j]);
                    }
                }
            }
            else
            {
                // All channels use the single submap
                for (int j = 0; j < channels; ++j)
                    mux[j] = 0;
            }

            for (int j = 0; j < channels; ++j)
            {
                //Console.WriteLine("    Multiplex: Channel {0} uses submap {1}", j, mux[j]);
            }

            //mapping.ChannelToSubmapTable = mux;

            SubMap[] submapTable = new SubMap[submaps];

            for (int j = 0; j < submaps; ++j)
            {
                // discard
                r.ReadUnsigned(8);

                SubMap sm = new SubMap();

                int floorNum = (int)r.ReadUnsigned(8);
                if (floorNum >= floors.Count)
                    throw new VorbisReadException("Invalid floor index in mapping: {0}", floorNum);

                sm.FloorNumber = floorNum;
                sm.Floor = floors[floorNum];

                int residueNum = (int)r.ReadUnsigned(8);
                if (floorNum >= residues.Count)
                    throw new VorbisReadException("Invalid residue index in mapping: {0}", floorNum);

                sm.ResidueNumber = residueNum;
                sm.Residue = residues[residueNum];

                //Console.WriteLine("    Submap[{0}]", j);
                //Console.WriteLine("      Floor: {0}", floorNum);
                //Console.WriteLine("      Residue: {0}", residueNum);

                submapTable[j] = sm;
            }

            mapping.SubMaps = submapTable;
            mapping.SubMapsByChannel = new SubMap[channels];
            for (int j = 0; j < channels; ++j)
            {
                mapping.SubMapsByChannel[j] = submapTable[mux[j]];
                WriteLine("    Channel {0} uses Floor {1}, Residue {2}", j, mapping.SubMapsByChannel[j].FloorNumber, mapping.SubMapsByChannel[j].ResidueNumber);
            }

            return mapping;
        }
Ejemplo n.º 8
0
        private HuffInternalNode ReadHuffman(int entries, BitReader r)
        {
            bool ordered = r.ReadBit();
            //Console.WriteLine("    Ordered: {0}", ordered ? 1 : 0);
            int[] codewordLengths = new int[entries];
            bool[] codewordUsed = new bool[entries];

            if (!ordered)
            {
                bool sparse = r.ReadBit();
                //Console.WriteLine("    Sparse: {0}", sparse ? 1 : 0);

                for (int i = 0; i < entries; ++i)
                {
                    if (sparse)
                    {
                        if (r.ReadBit())
                        {
                            codewordLengths[i] = (int)r.ReadUnsigned(5) + 1;
                            codewordUsed[i] = true;
                        }
                    }
                    else
                    {
                        codewordLengths[i] = (int)r.ReadUnsigned(5) + 1;
                        codewordUsed[i] = true;
                    }
                }
            }
            else
            {
                int currentEntry = 0;
                int currentLength = (int)r.ReadUnsigned(5) + 1;
                while (currentEntry < entries)
                {
                    uint number = r.ReadUnsigned(VorbisUtil.InverseLog(entries - currentEntry));
                    for (int i = 0; i < number; ++i)
                    {
                        codewordUsed[currentEntry] = true;
                        codewordLengths[currentEntry++] = currentLength;
                    }
                    ++currentLength;
                }
            }

            HuffInternalNode root = new HuffInternalNode();

            for (int i = 0; i < entries; ++i)
            {
                if (codewordUsed[i])
                {
                    HuffLeafNode leaf = root.Insert(i, (int)codewordLengths[i]);

                    if (leaf == null)
                    {
                        throw new VorbisReadException("Failed to reserve codeword of length {0} for entry #{1}. Possibly malformed codebook.", codewordLengths[i], i);
                    }

                    //Console.WriteLine("    Entry[{0}]: {1}", i, leaf.Codeword());
                }
            }

            return root;
        }
Ejemplo n.º 9
0
        private Codebook ReadCodebook(BitReader r)
        {
            Codebook cb = new Codebook();

            cb.Dimensions = (int)r.ReadUnsigned(16);
            cb.Entries = (int)r.ReadUnsigned(24);
            int dimensions = cb.Dimensions;
            int entries = cb.Entries;

            //Console.WriteLine("    Dimensions: {0}", cb.Dimensions);
            //Console.WriteLine("    Entries: {0}", cb.Entries);

            cb.RootNode = ReadHuffman(cb.Entries, r);
            //root.Dump();

            int lookupType = (int)r.ReadUnsigned(4);
            cb.LookupType = lookupType;

            //Console.WriteLine("    Lookup type: {0}", lookupType);

            if (lookupType == 0)
            {
                // nothing to do
            }
            else if (lookupType == 1 || lookupType == 2)
            {
                float minimumValue = r.ReadVorbisFloat();
                float deltaValue = r.ReadVorbisFloat();
                uint valueBits = r.ReadUnsigned(4) + 1;
                bool sequenceP = r.ReadBit();
                int lookupValues;
                //Console.WriteLine("      Minimum value: {0}", minimumValue);
                //Console.WriteLine("      Delta value: {0}", deltaValue);
                //Console.WriteLine("      Value bits: {0}", valueBits);
                //Console.WriteLine("      Sequence P: {0}", sequenceP ? 1 : 0);

                cb.MinimumValue = minimumValue;
                cb.DeltaValue = deltaValue;
                cb.SequenceP = sequenceP;

                if (lookupType == 1)
                {
                    lookupValues = lookup1_values(entries, dimensions);

                    if (Math.Pow(lookupValues, dimensions) > entries)
                    {
                        // this is actually not a problem w/ the file, it's a problem w/ the decoder if this happens
                        throw new VorbisReadException("lookup1 is busted");
                    }
                }
                else
                {
                    lookupValues = (int)entries * (int)dimensions;
                }

                //Console.WriteLine("      Lookup values: {0}", lookupValues);

                uint[] multiplicands = new uint[lookupValues];

                for (int i = 0; i < lookupValues; ++i)
                {
                    multiplicands[i] = r.ReadUnsigned((int)valueBits);

                    //Console.WriteLine("      Multiplicands[{0}] = {1}", i, multiplicands[i]);
                }

                cb.Multiplicands = multiplicands;
            }
            else if (lookupType > 2)
            {
                throw new VorbisReadException("Invalid lookup type. Only types 0, 1 and 2 are supported");
            }

            return cb;
        }
Ejemplo n.º 10
0
        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;
        }