void ObjectElement(BitExtractor extractor, int objectCount, int bedOrISFObjects)
        {
            MDUpdateInfo(extractor);
            if (!extractor.ReadBit())   // Reserved
            {
                extractor.Skip(5);
            }

            if (blockUsed.Length != rampDuration.Length || infoBlocks.Length != objectCount)
            {
                blockUsed  = new bool[rampDuration.Length];
                infoBlocks = new ObjectInfoBlock[objectCount][];
                for (int obj = 0; obj < objectCount; ++obj)
                {
                    infoBlocks[obj] = new ObjectInfoBlock[rampDuration.Length];
                    for (int blk = 0; blk < infoBlocks[obj].Length; ++blk)
                    {
                        infoBlocks[obj][blk] = new ObjectInfoBlock();
                    }
                }
                future = new Vector3[objectCount];
            }

            Array.Clear(blockUsed, 0, blockUsed.Length);
            for (int obj = 0; obj < objectCount; ++obj)
            {
                for (int blk = 0; blk < infoBlocks[obj].Length; ++blk)
                {
                    infoBlocks[obj][blk].Update(extractor, blk, obj < bedOrISFObjects);
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Read new information for this block.
        /// </summary>
        public void Update(BitExtractor extractor, int blk, bool bedOrISFObject)
        {
            bool inactive        = extractor.ReadBit();
            int  basicInfoStatus = inactive ? 0 : (blk == 0 ? 1 : extractor.Read(2));

            if ((basicInfoStatus & 1) == 1)
            {
                ObjectBasicInfo(extractor, basicInfoStatus == 1);
            }

            int renderInfoStatus = 0;

            if (!inactive && !bedOrISFObject)
            {
                renderInfoStatus = blk == 0 ? 1 : extractor.Read(2);
            }
            if ((renderInfoStatus & 1) == 1)
            {
                ObjectRenderInfo(extractor, blk, renderInfoStatus == 1);
            }

            if (extractor.ReadBit())   // Additional table data
            {
                extractor.Skip((extractor.Read(4) + 1) * 8);
            }

            if (bedOrISFObject)
            {
                anchor = ObjectAnchor.Speaker;
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Decodes the E-AC-3 header after the ID of the decoder.
        /// </summary>
        void BitStreamInformationEAC3(BitExtractor extractor)
        {
            dialnorm = extractor.Read(5);
            compr    = extractor.ReadConditional(8);

            if (ChannelMode == 0)
            {
                dialnorm2 = extractor.Read(5);
                compr2    = extractor.ReadConditional(8);
            }

            if (StreamType == StreamTypes.Dependent)
            {
                channelMapping = extractor.ReadConditional(channelMappingBits);
            }
            ReadMixingMetadata(extractor);
            ReadInfoMetadata(extractor);
            if (StreamType == StreamTypes.Independent && Blocks != 6)
            {
                convsync = extractor.ReadBit();
            }
            if (StreamType == StreamTypes.Repackaged && (blkid = Blocks == 6 || extractor.ReadBit()))
            {
                frmsizecod = extractor.Read(6);
            }

            if (addbsie = extractor.ReadBit())
            {
                addbsi = extractor.ReadBytes(extractor.Read(6) + 1);
            }
        }
Esempio n. 4
0
        void DecodeInfo(BitExtractor extractor)
        {
            int gainPower = extractor.Read(3);

            Gain = 1 + (extractor.Read(5) / 32f) * MathF.Pow(2, gainPower - 4);
            extractor.Skip(10); // Sequence counter
            for (int obj = 0; obj < ObjectCount; ++obj)
            {
                if (ObjectActive[obj] = extractor.ReadBit())
                {
                    bandsIndex[obj]        = (byte)extractor.Read(3);
                    bands[obj]             = JointObjectCodingTables.joc_num_bands[bandsIndex[obj]];
                    sparseCoded[obj]       = extractor.ReadBit();
                    quantizationTable[obj] = (byte)extractor.ReadBitInt();

                    // joc_data_point_info
                    steepSlope[obj] = extractor.ReadBit();
                    dataPoints[obj] = extractor.Read(1) + 1;
                    if (steepSlope[obj])
                    {
                        for (int dp = 0; dp < dataPoints[obj]; ++dp)
                        {
                            timeslotOffsets[obj][dp] = extractor.Read(5) + 1;
                        }
                    }
                }
            }
        }
Esempio n. 5
0
        public void BitExtractor_GetBits_FourBit_Success()
        {
            byte[]       data    = new byte[] { 0x48, 0x45, 0x4C, 0x4C, 0x4F };
            BitExtractor fourBit = new BitExtractor(data, BitsToEncode.Four);

            Assert.AreEqual(0xF4, fourBit.GetBits(0));
            Assert.AreEqual(0xF8, fourBit.GetBits(1));
        }
Esempio n. 6
0
        public void BitExtractor_GetBits_EightBit_Success()
        {
            byte[]       data     = new byte[] { 0x48, 0x45, 0x4C, 0x4C, 0x4F };
            BitExtractor eightBit = new BitExtractor(data, BitsToEncode.Eight);

            Assert.AreEqual(0x48, eightBit.GetBits(0));
            Assert.AreEqual(0x45, eightBit.GetBits(1));
        }
Esempio n. 7
0
        public void BitExtractor_GetBits_NegativeIndex_Throws()
        {
            byte[] data = new byte[] { 0x48, 0x45, 0x4C, 0x4C, 0x4F };

            BitExtractor oneBit = new BitExtractor(data, BitsToEncode.One);

            oneBit.GetBits(-1);
        }
Esempio n. 8
0
        public void BitExtractor_GetBits_IndexTooLarge_Throws()
        {
            byte[] data = new byte[] { 0x48, 0x45, 0x4C, 0x4C, 0x4F };

            BitExtractor oneBit = new BitExtractor(data, BitsToEncode.One);

            oneBit.GetBits(40);
        }
Esempio n. 9
0
        public void BitExtractor_GetBits_InvalidBitsEnum_Throws()
        {
            byte[] data = new byte[] { 0x48, 0x45, 0x4C, 0x4C, 0x4F };

            BitExtractor oneBit = new BitExtractor(data, (BitsToEncode)3);

            oneBit.GetBits(5);
        }
Esempio n. 10
0
        int HuffmanDecode(int[][] joc_huff_code, BitExtractor extractor)
        {
            int node = 0;

            do
            {
                node = joc_huff_code[node][extractor.ReadBit() ? 1 : 0];
            } while (node > 0);
            return(-1 - node);
        }
Esempio n. 11
0
        public void BitExtractor_GetBits_TwoBit_Success()
        {
            byte[] data = new byte[] { 0x48, 0x45, 0x4C, 0x4C, 0x4F };

            BitExtractor twoBit = new BitExtractor(data, BitsToEncode.Two);

            Assert.AreEqual(0xFD, twoBit.GetBits(0));
            Assert.AreEqual(0xFC, twoBit.GetBits(1));
            Assert.AreEqual(0xFE, twoBit.GetBits(2));
            Assert.AreEqual(0xFC, twoBit.GetBits(3));
        }
Esempio n. 12
0
 void DecodeHeader(BitExtractor extractor)
 {
     joc_dmx_config_idx = extractor.Read(3);
     if (joc_dmx_config_idx > 2)
     {
         throw new UnsupportedFeatureException("DMXconfig");
     }
     ChannelCount = (joc_dmx_config_idx == 0 || joc_dmx_config_idx == 3) ? 5 : 7;
     ObjectCount  = extractor.Read(6) + 1;
     UpdateCache();
     joc_ext_config_idx = extractor.Read(3);
 }
Esempio n. 13
0
        /// <summary>
        /// Decode the next EMDF frame from a bitstream.
        /// </summary>
        public void Decode(BitExtractor extractor)
        {
            HasObjects = false;
            int syncword = 0;

            while (extractor.Position < extractor.BackPosition - 32)
            {
                syncword = ((syncword << 8) & 0xFFFF) + extractor.Read(8); // Syncwords are byte-padded
                if (syncword == syncWord && DecodeBlock(extractor))
                {
                    break;
                }
            }
        }
Esempio n. 14
0
        public void BitExtractor_Constructor_EmptyData_Success()
        {
            byte[] data = new byte[0];

            BitExtractor oneBit   = new BitExtractor(data, BitsToEncode.One);
            BitExtractor twoBit   = new BitExtractor(data, BitsToEncode.Two);
            BitExtractor fourBit  = new BitExtractor(data, BitsToEncode.Four);
            BitExtractor eightBit = new BitExtractor(data, BitsToEncode.Eight);

            Assert.AreEqual(0, oneBit.EncodedByteLength);
            Assert.AreEqual(0, twoBit.EncodedByteLength);
            Assert.AreEqual(0, fourBit.EncodedByteLength);
            Assert.AreEqual(0, eightBit.EncodedByteLength);
        }
Esempio n. 15
0
        public void BitExtractor_Constructor_Data_Success()
        {
            byte[] data = new byte[] { 0x48, 0x45, 0x4C, 0x4C, 0x4F };

            BitExtractor oneBit   = new BitExtractor(data, BitsToEncode.One);
            BitExtractor twoBit   = new BitExtractor(data, BitsToEncode.Two);
            BitExtractor fourBit  = new BitExtractor(data, BitsToEncode.Four);
            BitExtractor eightBit = new BitExtractor(data, BitsToEncode.Eight);

            Assert.AreEqual(40, oneBit.EncodedByteLength);
            Assert.AreEqual(20, twoBit.EncodedByteLength);
            Assert.AreEqual(10, fourBit.EncodedByteLength);
            Assert.AreEqual(5, eightBit.EncodedByteLength);
        }
Esempio n. 16
0
 void MDUpdateInfo(BitExtractor extractor)
 {
     sampleOffset = extractor.Read(2) switch {
         0 => 0,
         1 => sampleOffsetIndex[extractor.Read(2)],
         2 => (byte)extractor.Read(5),
         _ => throw new UnsupportedFeatureException("mdOffset"),
     };
     blockOffsetFactor = new short[extractor.Read(3) + 1];
     rampDuration      = new short[blockOffsetFactor.Length];
     for (int blk = 0; blk < rampDuration.Length; ++blk)
     {
         BlockUpdateInfo(extractor, blk);
     }
 }
Esempio n. 17
0
        /// <summary>
        /// Read variable-length values from an EMDF stream with a limit on length.
        /// The <paramref name="limit"/> parameter takes 1 less than the actual length because reasons.
        /// </summary>
        public static int VariableBits(this BitExtractor extractor, byte bits, int limit)
        {
            int  value = 0;
            bool readMore;

            do
            {
                value += extractor.Read(bits);
                if (readMore = extractor.ReadBit())
                {
                    value = (value + 1) << bits;
                }
            } while (readMore && limit-- != 0);
            return(value);
        }
Esempio n. 18
0
        public void BitExtractor_GetBits_OneBit_Success()
        {
            byte[] data = new byte[] { 0x48, 0x45, 0x4C, 0x4C, 0x4F };

            BitExtractor oneBit = new BitExtractor(data, BitsToEncode.One);

            Assert.AreEqual(0xFE, oneBit.GetBits(0));
            Assert.AreEqual(0xFF, oneBit.GetBits(1));
            Assert.AreEqual(0xFE, oneBit.GetBits(2));
            Assert.AreEqual(0xFE, oneBit.GetBits(3));
            Assert.AreEqual(0xFF, oneBit.GetBits(4));
            Assert.AreEqual(0xFE, oneBit.GetBits(5));
            Assert.AreEqual(0xFE, oneBit.GetBits(6));
            Assert.AreEqual(0xFE, oneBit.GetBits(7));
        }
Esempio n. 19
0
            public void ReadMantissa(BitExtractor extractor, int[] target, int start, int end)
            {
                for (int bin = start; bin < end; ++bin)
                {
                    switch (bap[bin])
                    {
                    case 1:
                        if (bap1Bits == 0)
                        {
                            bap1Bits = 2;
                            extractor.Skip(bitsToRead[1]);     // TODO: temp
                        }
                        else
                        {
                            --bap1Bits;
                        }
                        break;

                    case 2:
                        if (bap2Bits == 0)
                        {
                            bap2Bits = 2;
                            extractor.Skip(bitsToRead[2]);     // TODO: temp
                        }
                        else
                        {
                            --bap2Bits;
                        }
                        break;

                    case 4:
                        if (bap4Bits == 0)
                        {
                            bap4Bits = 1;
                            extractor.Skip(bitsToRead[4]);     // TODO: temp
                        }
                        else
                        {
                            --bap4Bits;
                        }
                        break;

                    default:
                        target[bin] = extractor.Read(bitsToRead[bap[bin]]);
                        break;
                    }
                }
            }
Esempio n. 20
0
        /// <summary>
        /// Decodes a OAMD frame from an EMDF payload.
        /// </summary>
        public void Decode(BitExtractor extractor, int offset)
        {
            this.offset = offset;
            int versionNumber = extractor.Read(2);

            if (versionNumber == 3)
            {
                versionNumber += extractor.Read(3);
            }
            if (versionNumber != 0)
            {
                throw new UnsupportedFeatureException("OAver");
            }
            ObjectCount = extractor.Read(5) + 1;
            if (ObjectCount == 32)
            {
                ObjectCount += extractor.Read(7);
            }
            ProgramAssignment(extractor);
            bool alternateObjectPresent = extractor.ReadBit();
            int  elementCount           = extractor.Read(4);

            if (elementCount == 15)
            {
                elementCount += extractor.Read(5);
            }

            int bedOrISFObjects = beds;

            if (isfInUse)
            {
                bedOrISFObjects += isfObjectCount[isfIndex];
            }

            if (elements.Length != elementCount)
            {
                elements = new OAElementMD[elementCount];
                for (int i = 0; i < elementCount; ++i)
                {
                    elements[i] = new OAElementMD();
                }
            }
            for (int i = 0; i < elementCount; ++i)
            {
                elements[i].Read(extractor, alternateObjectPresent, ObjectCount, bedOrISFObjects);
            }
        }
Esempio n. 21
0
        /// <summary>
        /// Decodes the legacy or alternative AC-3 header after the ID of the decoder.
        /// </summary>
        void BitStreamInformation(BitExtractor extractor)
        {
            if ((ChannelMode & 0x1) != 0 && (ChannelMode != 0x1)) // 3 fronts exist
            {
                centerDownmix = extractor.Read(2);
            }
            if ((ChannelMode & 0x4) != 0) // Surrounds exist
            {
                surroundDownmix = extractor.Read(2);
            }
            if (ChannelMode == 0x2) // Stereo
            {
                dsurmod = extractor.Read(2);
            }

            LFE      = extractor.ReadBit();
            dialnorm = extractor.Read(5);
            compr    = extractor.ReadConditional(8);
            langcod  = extractor.ReadConditional(8);
            if (audprodie = extractor.ReadBit())
            {
                mixlevel = extractor.Read(5);
                roomtyp  = extractor.Read(2);
            }

            if (ChannelMode == 0)
            {
                dialnorm2 = extractor.Read(5);
                compr2    = extractor.ReadConditional(8);
                langcod2  = extractor.ReadConditional(8);
                if (audprodi2e = extractor.ReadBit())
                {
                    mixlevel2 = extractor.Read(5);
                    roomtyp2  = extractor.Read(2);
                }
            }

            copyrightb            = extractor.ReadBit();
            origbs                = extractor.ReadBit();
            additionalDownmixInfo = extractor.ReadConditional(14);
            additionalMixInfo     = extractor.ReadConditional(14);
            if (addbsie = extractor.ReadBit())
            {
                addbsi = extractor.ReadBytes(extractor.Read(6) + 1);
            }
        }
Esempio n. 22
0
            /// <summary>
            /// Read the delta bit allocation from the bitstream.
            /// </summary>
            public void Read(BitExtractor extractor)
            {
                int segments = extractor.Read(3) + 1;

                if (Offset.Length != segments)
                {
                    Offset        = new int[segments];
                    Length        = new int[segments];
                    BitAllocation = new int[segments];
                }
                for (int segment = 0; segment < segments; ++segment)
                {
                    Offset[segment]        = extractor.Read(5);
                    Length[segment]        = extractor.Read(4);
                    BitAllocation[segment] = extractor.Read(3);
                }
            }
Esempio n. 23
0
        /// <summary>
        /// Decodes an object audio element metadata block.
        /// </summary>
        public void Read(BitExtractor extractor, bool alternateObjectPresent, int objectCount, int bedOrISFObjects)
        {
            int elementIndex = extractor.Read(4);
            int endPos       = extractor.Position + ExtensibleMetadataExtensions.VariableBits(extractor, 4, 4) + 1;

            extractor.Skip(alternateObjectPresent ? 5 : 1);
            switch (elementIndex)
            {
            case objectElementIndex:
                ObjectElement(extractor, objectCount, bedOrISFObjects);
                break;

            case extendedObjectElementIndex:
            // TODO: support other element types
            default:
                blockOffsetFactor = new short[] { -1 };
                break;
            }
            extractor.Position = endPos; // Padding
        }
Esempio n. 24
0
        void BlockUpdateInfo(BitExtractor extractor, int blk)
        {
            blockOffsetFactor[blk] = (short)(extractor.Read(6) + sampleOffset);
            int rampDurationCode = extractor.Read(2);

            if (rampDurationCode == 3)
            {
                if (extractor.ReadBit())
                {
                    rampDuration[blk] = rampDurationIndex[extractor.Read(4)];
                }
                else
                {
                    rampDuration[blk] = (short)extractor.Read(11);
                }
            }
            else
            {
                rampDuration[blk] = rampDurations[rampDurationCode];
            }
        }
Esempio n. 25
0
 void DecodeData(BitExtractor extractor)
 {
     for (int obj = 0; obj < ObjectCount; ++obj)
     {
         if (ObjectActive[obj])
         {
             for (int dp = 0; dp < dataPoints[obj]; ++dp)
             {
                 int[][] codeTable;
                 if (sparseCoded[obj])
                 {
                     jocChannel[obj][dp][0] = extractor.Read(3);
                     codeTable = JointObjectCodingTables.GetHuffCodeTable(ChannelCount, HuffmanType.IDX);
                     for (int pb = 1; pb < bands[obj]; ++pb)
                     {
                         jocChannel[obj][dp][pb] = HuffmanDecode(codeTable, extractor);
                     }
                     codeTable =
                         JointObjectCodingTables.GetHuffCodeTable(quantizationTable[obj], HuffmanType.VEC);
                     for (int pb = 0; pb < bands[obj]; ++pb)
                     {
                         jocVector[obj][dp][pb] = HuffmanDecode(codeTable, extractor);
                     }
                 }
                 else
                 {
                     codeTable = JointObjectCodingTables.GetHuffCodeTable(quantizationTable[obj],
                                                                          HuffmanType.MTX);
                     for (int ch = 0; ch < ChannelCount; ++ch)
                     {
                         for (int pb = 0; pb < bands[obj]; ++pb)
                         {
                             jocMatrix[obj][dp][ch][pb] = HuffmanDecode(codeTable, extractor);
                         }
                     }
                 }
             }
         }
     }
 }
Esempio n. 26
0
        /// <summary>
        /// Parse informational metadata.
        /// </summary>
        void ReadInfoMetadata(BitExtractor extractor)
        {
            if (!(infomdate = extractor.ReadBit()))
            {
                return;
            }

            bsmod      = extractor.Read(3);
            copyrightb = extractor.ReadBit();
            origbs     = extractor.ReadBit();
            if (ChannelMode == 2)
            {
                dsurmod      = extractor.Read(2);
                dheadphonmod = extractor.Read(2);
            }
            if (ChannelMode >= 6)
            {
                dsurexmod = extractor.Read(2);
            }
            if (audprodie = extractor.ReadBit())
            {
                mixlevel  = extractor.Read(5);
                roomtyp   = extractor.Read(2);
                adconvtyp = extractor.ReadBit();
            }
            if (ChannelMode == 0)
            {
                if (audprodi2e = extractor.ReadBit())
                {
                    mixlevel2  = extractor.Read(5);
                    roomtyp2   = extractor.Read(2);
                    adconvtyp2 = extractor.ReadBit();
                }
            }
            if (SampleRateCode < 3)
            {
                sourcefscod = extractor.ReadBit();
            }
        }
Esempio n. 27
0
        void ObjectBasicInfo(BitExtractor extractor, bool readAllBlocks)
        {
            int blocks = readAllBlocks ? 3 : extractor.Read(2);

            // Gain
            if ((blocks & 2) != 0)
            {
                int gainHelper = extractor.Read(2);
                gain = gainHelper switch {
                    0 => 1,
                    1 => 0,
                    2 => (gainHelper = extractor.Read(6)) < 15 ?
                    QMath.DbToGain(15 - gainHelper) : QMath.DbToGain(14 - gainHelper),
                    _ => - 1,
                };
            }

            // Priority - unneccessary, everything's rendered
            if ((blocks & 1) != 0 && !extractor.ReadBit())
            {
                extractor.Skip(5);
            }
        }
Esempio n. 28
0
 /// <summary>
 /// Decodes a JOC frame from an EMDF payload.
 /// </summary>
 public void Decode(BitExtractor extractor)
 {
     DecodeHeader(extractor);
     DecodeInfo(extractor);
     DecodeData(extractor);
 }
Esempio n. 29
0
        void ProgramAssignment(BitExtractor extractor)
        {
            if (extractor.ReadBit())     // Dynamic object-only program
            {
                if (extractor.ReadBit()) // LFE present
                {
                    bedAssignment    = new bool[1][];
                    bedAssignment[0] = new bool[(int)NonStandardBedChannel.Max];
                    bedAssignment[0][(int)NonStandardBedChannel.LowFrequencyEffects] = true;
                }
            }
            else
            {
                int contentDescription = extractor.Read(4);

                // Object(s) with speaker-anchored coordinate(s) (bed objects)
                if ((contentDescription & 8) != 0)
                {
                    extractor.Skip(1); // The object is distributable - Cavern will do it anyway
                    bedAssignment = new bool[extractor.ReadBit() ? extractor.Read(3) + 2 : 1][];
                    for (int bed = 0; bed < bedAssignment.Length; ++bed)
                    {
                        if (extractor.ReadBit())   // LFE only
                        {
                            bedAssignment[bed] = new bool[(int)NonStandardBedChannel.Max];
                            bedAssignment[bed][(int)NonStandardBedChannel.LowFrequencyEffects] = true;
                        }
                        else
                        {
                            if (extractor.ReadBit())   // Standard bed assignment
                            {
                                bool[] standardAssignment = extractor.ReadBits(10);
                                for (int i = 0; i < standardAssignment.Length; ++i)
                                {
                                    for (int j = 0; j < standardBedChannels[i].Length; ++j)
                                    {
                                        bedAssignment[bed][standardBedChannels[i][j]] = standardAssignment[i];
                                    }
                                }
                            }
                            else
                            {
                                bedAssignment[bed] = extractor.ReadBits((int)NonStandardBedChannel.Max);
                            }
                        }
                    }
                }

                // Intermediate spatial format (ISF)
                if (isfInUse = (contentDescription & 4) != 0)
                {
                    isfIndex = (byte)extractor.Read(3);
                    if (isfIndex >= isfObjectCount.Length)
                    {
                        throw new UnsupportedFeatureException("ISF");
                    }
                }

                // Object(s) with room-anchored or screen-anchored coordinates
                if ((contentDescription & 2) != 0)   // This is useless, same as ObjectCount - bedOrISFObjects, also found in JOC
                {
                    if (extractor.Read(5) == 31)
                    {
                        extractor.Skip(7);
                    }
                }

                // Reserved
                if ((contentDescription & 1) != 0)
                {
                    extractor.Skip((extractor.Read(4) + 1) * 8);
                }
            }

            beds = 0;
            for (int bed = 0; bed < bedAssignment.Length; ++bed)
            {
                for (int i = 0; i < (int)NonStandardBedChannel.Max; ++i)
                {
                    if (bedAssignment[bed][i])
                    {
                        ++beds;
                    }
                }
            }
        }
Esempio n. 30
0
 public void BitExtractor_Constructor_NullData_Throws()
 {
     BitExtractor extractor = new BitExtractor(null, BitsToEncode.One);
 }