Beispiel #1
0
        public FlacResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order)
        {
            FlacEntropyCoding codingMethod = (FlacEntropyCoding)reader.ReadBits(FlacConstant.EntropyCodingMethodTypeLen); // 2 Bit

            if (codingMethod == FlacEntropyCoding.PartitionedRice || codingMethod == FlacEntropyCoding.PartitionedRice2)
            {
                int riceOrder = (int)reader.ReadBits(FlacConstant.EntropyCodingMethodPartitionedRiceOrderLen);

                FlacPartitionedRice rice = new FlacPartitionedRice(riceOrder, codingMethod, data.Content);

                if (rice.ProcessResidual(reader, header, data, order) == false)
                {
                    throw new FlacException("Decoding Flac Residual failed.", FlacLayer.SubFrame);
                }

#if DEBUG
                CodingMethod = codingMethod;
                RiceOrder    = riceOrder;
                Rice         = rice;
#endif
            }
            else
            {
                throw new FlacException("Not supported RICE-Coding-Method. Stream unparseable!", FlacLayer.SubFrame);
            }
        }
Beispiel #2
0
        public FlacResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order)
        {
            FlacEntropyCoding codingMethod = (FlacEntropyCoding)reader.ReadBits(FlacConstant.ENTROPY_CODING_METHOD_TYPE_LEN); // 2 Bit
            int riceOrder = -1;

            if (codingMethod == FlacEntropyCoding.PartitionedRice || codingMethod == FlacEntropyCoding.PartitionedRice2)
            {
                riceOrder = (int)reader.ReadBits(FlacConstant.ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN); // 4 Bit

                FlacPartitionedRice rice = new FlacPartitionedRice(riceOrder, codingMethod, data.Content);

                if (rice.ProcessResidual(reader, header, data, order) == false)
                {
                    throw new FlacException("Decoding Flac Residual failed.", FlacLayer.SubFrame);
                }

                CodingMethod = codingMethod;
                RiceOrder = riceOrder;
                Rice = rice;
            }
            else
            {
                throw new FlacException("Not supported RICE-Coding-Method. Stream unparseable!", FlacLayer.SubFrame);
            }
        }
Beispiel #3
0
        public FlacResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order)
        {
            FlacEntropyCoding codingMethod = (FlacEntropyCoding)reader.ReadBits(FlacConstant.EntropyCodingMethodTypeLen); // 2 Bit

            if (codingMethod == FlacEntropyCoding.PartitionedRice || codingMethod == FlacEntropyCoding.PartitionedRice2)
            {
                int riceOrder = (int)reader.ReadBits(FlacConstant.EntropyCodingMethodPartitionedRiceOrderLen);

                FlacPartitionedRice rice = new FlacPartitionedRice(riceOrder, codingMethod, data.Content);

                if (rice.ProcessResidual(reader, header, data, order) == false)
                {
                    throw new FlacException("Decoding Flac Residual failed.", FlacLayer.SubFrame);
                }

#if DEBUG
                CodingMethod = codingMethod;
                RiceOrder = riceOrder;
                Rice = rice;
#endif

            }
            else
            {
                throw new FlacException("Not supported RICE-Coding-Method. Stream unparseable!", FlacLayer.SubFrame);
            }
        }
Beispiel #4
0
        public FlacResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order)
        {
            FlacEntropyCoding codingMethod = (FlacEntropyCoding)reader.ReadBits(FlacConstant.ENTROPY_CODING_METHOD_TYPE_LEN); // 2 Bit
            int riceOrder = -1;

            if (codingMethod == FlacEntropyCoding.PartitionedRice || codingMethod == FlacEntropyCoding.PartitionedRice2)
            {
                riceOrder = (int)reader.ReadBits(FlacConstant.ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN); // 4 Bit

                FlacPartitionedRice rice = new FlacPartitionedRice(riceOrder, codingMethod, data.Content);

                if (rice.ProcessResidual(reader, header, data, order) == false)
                {
                    throw new FlacException("Decoding Flac Residual failed.", FlacLayer.SubFrame);
                }

                CodingMethod = codingMethod;
                RiceOrder    = riceOrder;
                Rice         = rice;
            }
            else
            {
                throw new FlacException("Not supported RICE-Coding-Method. Stream unparseable!", FlacLayer.SubFrame);
            }
        }
        /// <summary>
        /// Reads and returns a single <see cref="FlacMetadata"/> from the specified <paramref name="stream"/>.
        /// </summary>
        /// <param name="stream">The stream which contains the <see cref="FlacMetadata"/>.</param>
        /// <returns>Returns the read <see cref="FlacMetadata"/>.</returns>
        /// <exception cref="FlacException">Could not read metadata.</exception>
        public unsafe FlacMetadata ParseMetadata(Stream stream)
        {
            bool             isLastBlock;
            FlacMetaDataType type;
            int length;

            byte[] b = new byte[4];
            if (stream.Read(b, 0, 4) <= 0)
            {
                throw new FlacException(new EndOfStreamException("Could not read metadata."), FlacLayer.Metadata);

                fixed(byte *headerBytes = b)
                {
                    FlacBitReader bitReader = new FlacBitReader(headerBytes, 0);

                    isLastBlock = bitReader.ReadBits(1) == 1;
                    type        = (FlacMetaDataType)bitReader.ReadBits(7);
                    length      = (int)bitReader.ReadBits(24);
                }

                long streamStartPosition = stream.Position;
                if (type < 0 || (int)type > 6)
                    return(null); }

                var data = CreateFlacMetadataInstance(type);
                data.Initialize(stream, length, isLastBlock);

                stream.Seek(length - (stream.Position - streamStartPosition), SeekOrigin.Current);
                return(data);
        }
        public FlacSubFrameConstant(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps)
            : base(header)
        {
            Value = (int)reader.ReadBits(bps);

            unsafe
            {
                for (int i = 0; i < header.BlockSize; i++)
                {
                    int* ptr = data.destBuffer;
                    *ptr++ = Value;
                }
            }
        }
        public static unsafe void ProcessResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data,
                                                  int order, int partitionOrder, FlacResidualCodingMethod codingMethod)
        {
            data.Content.UpdateSize(partitionOrder);
            bool isRice2             = codingMethod == FlacResidualCodingMethod.PartitionedRice2;
            int  riceParameterLength = isRice2 ? 5 : 4;
            int  escapeCode          = isRice2 ? 31 : 15; //11111 : 1111

            int samplesPerPartition;

            int partitionCount = 1 << partitionOrder;  //2^partitionOrder -> There will be 2^order partitions. -> "order" = partitionOrder in this case

            int *residualBuffer = data.ResidualBuffer + order;

            for (int p = 0; p < partitionCount; p++)
            {
                if (partitionOrder == 0)
                {
                    samplesPerPartition = header.BlockSize - order;
                }
                else if (p > 0)
                {
                    samplesPerPartition = header.BlockSize >> partitionOrder;
                }
                else
                {
                    samplesPerPartition = (header.BlockSize >> partitionOrder) - order;
                }

                var riceParameter = reader.ReadBits(riceParameterLength);
                data.Content.Parameters[p] = (int)riceParameter;

                if (riceParameter >= escapeCode)
                {
                    var raw = reader.ReadBits(5); //raw is always 5 bits (see ...(+5))
                    data.Content.RawBits[p] = (int)raw;
                    for (int i = 0; i < samplesPerPartition; i++)
                    {
                        int sample = reader.ReadBitsSigned((int)raw);
                        *(residualBuffer) = sample;
                        residualBuffer++;
                    }
                }
                else
                {
                    ReadFlacRiceBlock(reader, samplesPerPartition, (int)riceParameter, residualBuffer);
                    residualBuffer += samplesPerPartition;
                }
            }
        }
Beispiel #8
0
        public FlacSubFrameConstant(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps)
            : base(header)
        {
            Value = (int)reader.ReadBits(bps);

            unsafe
            {
                for (int i = 0; i < header.BlockSize; i++)
                {
                    int *ptr   = data.destBuffer;
                    *    ptr++ = Value;
                }
            }
        }
        public FlacSubFrameVerbatim(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps)
            : base(header)
        {
            unsafe
            {
                int *ptrDest = data.DestBuffer, ptrResidual = data.ResidualBuffer;

                for (int i = 0; i < header.BlockSize; i++)
                {
                    int x             = (int)reader.ReadBits(bps);
                    *   ptrDest++     = x;
                    *   ptrResidual++ = x;
                }
            }
        }
        public FlacSubFrameVerbatim(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps)
            : base(header)
        {
            unsafe
            {
                int* ptrDest = data.DestBuffer, ptrResidual = data.ResidualBuffer;

                for (int i = 0; i < header.BlockSize; i++)
                {
                    int x = (int)reader.ReadBits(bps);
                    *ptrDest++ = x;
                    *ptrResidual++ = x;
                }
            }
        }
        public FlacSubFrameConstant(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bitsPerSample)
            : base(header)
        {
            int value = (int)reader.ReadBits(bitsPerSample);
            #if FLAC_DEBUG
            Value = value;
            #endif

            unsafe
            {
                int* pDestinationBuffer = data.DestinationBuffer;
                for (int i = 0; i < header.BlockSize; i++)
                {
                    *pDestinationBuffer++ = value;
                }
            }
        }
        /// <summary>
        /// This method is based on the CUETools.NET BitReader (see http://sourceforge.net/p/cuetoolsnet/code/ci/default/tree/CUETools.Codecs/BitReader.cs)
        /// The author "Grigory Chudov" explicitly gave the permission to use the source as part of the cscore source code which got licensed under the ms-pl.
        /// </summary>
        private static unsafe void ReadFlacRiceBlock(FlacBitReader reader, int nvals, int riceParameter, int *ptrDest)
        {
            fixed(byte *putable = FlacBitReader.UnaryTable)
            {
                uint mask = (1u << riceParameter) - 1;

                if (riceParameter == 0)
                {
                    for (int i = 0; i < nvals; i++)
                    {
                        *(ptrDest++) = reader.ReadUnarySigned();
                    }
                }
                else
                {
                    for (int i = 0; i < nvals; i++)
                    {
                        uint bits = putable[reader.Cache >> 24];
                        uint msbs = bits;

                        while (bits == 8)
                        {
                            reader.SeekBits(8);
                            bits  = putable[reader.Cache >> 24];
                            msbs += bits;
                        }

                        uint uval;
                        if (riceParameter <= 16)
                        {
                            int btsk = riceParameter + (int)bits + 1;
                            uval = (msbs << riceParameter) | ((reader.Cache >> (32 - btsk)) & mask);
                            reader.SeekBits(btsk);
                        }
                        else
                        {
                            reader.SeekBits((int)(msbs & 7) + 1);
                            uval = (msbs << riceParameter) | ((reader.Cache >> (32 - riceParameter)));
                            reader.SeekBits(riceParameter);
                        }
                        *(ptrDest++) = (int)(uval >> 1 ^ -(int)(uval & 1));
                    }
                }
            }
        }
        public FlacSubFrameConstant(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bitsPerSample)
            : base(header)
        {
            int value = (int)reader.ReadBits(bitsPerSample);

#if FLAC_DEBUG
            Value = value;
#endif

            unsafe
            {
                int *pDestinationBuffer = data.DestinationBuffer;
                for (int i = 0; i < header.BlockSize; i++)
                {
                    *pDestinationBuffer++ = value;
                }
            }
        }
Beispiel #14
0
        /// <summary>
        /// This method is based on the CUETools.NET BitReader (see http://sourceforge.net/p/cuetoolsnet/code/ci/default/tree/CUETools.Codecs/BitReader.cs)
        /// The author "Grigory Chudov" explicitly gave the permission to use the source as part of the cscore source code which got licensed under the ms-pl.
        /// </summary>
        private static void ReadFlacRiceBlock(FlacBitReader reader, int nvals, int riceParameter, Span <int> ptrDest)
        {
            var putable = FlacBitReader.UnaryTable;
            {
                var mask = (1u << riceParameter) - 1;
                if (riceParameter == 0)
                {
                    for (var i = 0; i < nvals; i++)
                    {
                        ptrDest[i] = reader.ReadUnarySigned();
                    }
                }
                else
                {
                    for (var i = 0; i < nvals; i++)
                    {
                        uint bits = putable[reader.Cache >> 24];
                        var  msbs = bits;

                        while (bits == 8)
                        {
                            reader.SeekBits(8);
                            bits  = putable[reader.Cache >> 24];
                            msbs += bits;
                        }

                        uint uval;
                        if (riceParameter <= 16)
                        {
                            var btsk = riceParameter + (int)bits + 1;
                            uval = (msbs << riceParameter) | ((reader.Cache >> (32 - btsk)) & mask);
                            reader.SeekBits(btsk);
                        }
                        else
                        {
                            reader.SeekBits((int)(msbs & 7) + 1);
                            uval = (msbs << riceParameter) | ((reader.Cache >> (32 - riceParameter)));
                            reader.SeekBits(riceParameter);
                        }
                        ptrDest[i] = (int)((uval >> 1) ^ -(int)(uval & 1));
                    }
                }
            }
        }
Beispiel #15
0
        public static unsafe void ProcessResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data,
            int order, int partitionOrder, FlacResidualCodingMethod codingMethod)
        {
            data.Content.UpdateSize(partitionOrder);
            bool isRice2 = codingMethod == FlacResidualCodingMethod.PartitionedRice2;
            int riceParameterLength = isRice2 ? 5 : 4;
            int escapeCode = isRice2 ? 31 : 15; //11111 : 1111

            int samplesPerPartition;

            int partitionCount = 1 << partitionOrder;  //2^partitionOrder -> There will be 2^order partitions. -> "order" = partitionOrder in this case

            int* residualBuffer = data.ResidualBuffer + order;

            for (int p = 0; p < partitionCount; p++)
            {
                if (partitionOrder == 0)
                    samplesPerPartition = header.BlockSize - order;
                else if (p > 0)
                    samplesPerPartition = header.BlockSize >> partitionOrder;
                else
                    samplesPerPartition = (header.BlockSize >> partitionOrder) - order;

                var riceParameter = reader.ReadBits(riceParameterLength);
                data.Content.Parameters[p] = (int)riceParameter;

                if (riceParameter >= escapeCode)
                {
                    var raw = reader.ReadBits(5); //raw is always 5 bits (see ...(+5))
                    data.Content.RawBits[p] = (int)raw;
                    for (int i = 0; i < samplesPerPartition; i++)
                    {
                        int sample = reader.ReadBitsSigned((int)raw);
                        *(residualBuffer) = sample;
                        residualBuffer++;
                    }
                }
                else
                {
                    ReadFlacRiceBlock(reader, samplesPerPartition, (int)riceParameter, residualBuffer);
                    residualBuffer += samplesPerPartition;
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// This method is based on the CUETools.NET BitReader (see http://sourceforge.net/p/cuetoolsnet/code/ci/default/tree/CUETools.Codecs/BitReader.cs)
        /// The author "Grigory Chudov" explicitly gave the permission to use the source as part of the cscore source code which got licensed under the ms-pl.
        /// </summary>
        private static unsafe void ReadFlacRiceBlock(FlacBitReader reader, int nvals, int riceParameter, int* ptrDest)
        {
            fixed (byte* putable = FlacBitReader.UnaryTable)
            {
                uint mask = (1u << riceParameter) - 1;
                if (riceParameter == 0)
                {
                    for (int i = 0; i < nvals; i++)
                    {
                        *(ptrDest++) = reader.ReadUnarySigned();
                    }
                }
                else
                {
                    for (int i = 0; i < nvals; i++)
                    {
                        uint bits = putable[reader.Cache >> 24];
                        uint msbs = bits;

                        while (bits == 8)
                        {
                            reader.SeekBits(8);
                            bits = putable[reader.Cache >> 24];
                            msbs += bits;
                        }

                        uint uval;
                        if (riceParameter <= 16)
                        {
                            int btsk = riceParameter + (int)bits + 1;
                            uval = (msbs << riceParameter) | ((reader.Cache >> (32 - btsk)) & mask);
                            reader.SeekBits(btsk);
                        }
                        else
                        {
                            reader.SeekBits((int)(msbs & 7) + 1);
                            uval = (msbs << riceParameter) | ((reader.Cache >> (32 - riceParameter)));
                            reader.SeekBits(riceParameter);
                        }
                        *(ptrDest++) = (int)(uval >> 1 ^ -(int)(uval & 1));
                    }
                }
            }
        }
Beispiel #17
0
        public FlacResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order)
        {
            FlacResidualCodingMethod codingMethod = (FlacResidualCodingMethod)reader.ReadBits(2); // 2 Bit

            if (codingMethod == FlacResidualCodingMethod.PartitionedRice || codingMethod == FlacResidualCodingMethod.PartitionedRice2)
            {
                int partitionOrder = (int)reader.ReadBits(4); //"Partition order." see https://xiph.org/flac/format.html#partitioned_rice and https://xiph.org/flac/format.html#partitioned_rice2

                FlacPartitionedRice.ProcessResidual(reader, header, data, order, partitionOrder, codingMethod);

#if FLAC_DEBUG
                CodingMethodMethod = codingMethod;
                PartitionOrder     = partitionOrder;
#endif
            }
            else
            {
                throw new FlacException("Not supported RICE-Coding-Method. Stream unparseable!", FlacLayer.SubFrame);
            }
        }
Beispiel #18
0
        private unsafe void ReadSubFrames()
        {
            var subFrames = new List<FlacSubFrameBase>();

            //alocateOutput
            var data = AllocOuputMemory();
            _subFrameData = data;

            var buffer = new byte[0x20000];
            if ((_streamInfo.MaxFrameSize * Header.Channels * Header.BitsPerSample * 2 >> 3) > buffer.Length)
            {
                buffer = new byte[(_streamInfo.MaxFrameSize * Header.Channels * Header.BitsPerSample * 2 >> 3) - FlacConstant.FrameHeaderSize];
            }

            var read = _stream.Read(buffer, 0, (int)Math.Min(buffer.Length, _stream.Length - _stream.Position));

            fixed (byte* ptrBuffer = buffer)
            {
                var reader = new FlacBitReader(ptrBuffer, 0);
                for (var c = 0; c < Header.Channels; c++)
                {
                    var bitsPerSample = Header.BitsPerSample;
                    if (Header.ChannelAssignment == ChannelAssignment.MidSide || Header.ChannelAssignment == ChannelAssignment.LeftSide)
                        bitsPerSample += c;
                    else if (Header.ChannelAssignment == ChannelAssignment.RightSide)
                        bitsPerSample += 1 - c;

                    var subframe = FlacSubFrameBase.GetSubFrame(reader, data[c], Header, bitsPerSample);
                    subFrames.Add(subframe);
                }

                reader.Flush(); //Zero-padding to byte alignment.

                //footer
                Crc16 = (short) reader.ReadBits(16);

                _stream.Position -= read - reader.Position;
                MapToChannels(_subFrameData);
            }

        }
Beispiel #19
0
        public FlacResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order)
        {
            FlacResidualCodingMethod codingMethod = (FlacResidualCodingMethod)reader.ReadBits(2); // 2 Bit

            if (codingMethod == FlacResidualCodingMethod.PartitionedRice || codingMethod == FlacResidualCodingMethod.PartitionedRice2)
            {
                int partitionOrder = (int)reader.ReadBits(4); //"Partition order." see https://xiph.org/flac/format.html#partitioned_rice and https://xiph.org/flac/format.html#partitioned_rice2

                FlacPartitionedRice.ProcessResidual(reader, header, data, order, partitionOrder, codingMethod);

            #if FLAC_DEBUG
                CodingMethodMethod = codingMethod;
                PartitionOrder = partitionOrder;
            #endif

            }
            else
            {
                throw new FlacException("Not supported RICE-Coding-Method. Stream unparseable!", FlacLayer.SubFrame);
            }
        }
Beispiel #20
0
        private unsafe bool ParseHeader(ref byte *headerBuffer, FlacMetadataStreamInfo streamInfo)
        {
            const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)";

            if (headerBuffer[0] == 0xFF && headerBuffer[1] >> 1 == 0x7C) //sync bits
            {
                if ((headerBuffer[1] & 0x02) != 0)
                {
                    Error("Invalid FlacFrame. Reservedbit_0 is 1", loggerLocation);
                    return(false);
                }

                var __headerbufferPtr = headerBuffer;
                var reader            = new FlacBitReader(__headerbufferPtr, 0);

                #region blocksize

                //blocksize
                var val       = headerBuffer[2] >> 4;
                var blocksize = -1;

                if (val == 0)
                {
                    Error("Invalid Blocksize value: 0", loggerLocation);
                    return(false);
                }
                if (val == 1)
                {
                    blocksize = 192;
                }
                else if (val >= 2 && val <= 5)
                {
                    blocksize = 576 << (val - 2);
                }
                else if (val == 6 || val == 7)
                {
                    _blocksizeHint = val;
                }
                else if (val >= 8 && val <= 15)
                {
                    blocksize = 256 << (val - 8);
                }
                else
                {
                    Error("Invalid Blocksize value: " + val, loggerLocation);
                    return(false);
                }
                BlockSize = blocksize;

                #endregion blocksize

                #region samplerate

                //samplerate
                val = headerBuffer[2] & 0x0F;
                var sampleRate = -1;

                if (val == 0)
                {
                    if (streamInfo != null)
                    {
                        sampleRate = streamInfo.SampleRate;
                    }
                    else
                    {
                        Error("Missing Samplerate. Samplerate Index = 0 && streamInfoMetaData == null.", loggerLocation);
                        return(false);
                    }
                }
                else if (val >= 1 && val <= 11)
                {
                    sampleRate = FlacConstant.SampleRateTable[val];
                }
                else if (val >= 12 && val <= 14)
                {
                    _sampleRateHint = val;
                }
                else
                {
                    Error("Invalid SampleRate value: " + val, loggerLocation);
                    return(false);
                }
                SampleRate = sampleRate;

                #endregion samplerate

                #region channels

                val = headerBuffer[3] >> 4; //cc: unsigned
                int channels;
                if ((val & 8) != 0)
                {
                    channels = 2;
                    if ((val & 7) > 2 || (val & 7) < 0)
                    {
                        Error("Invalid ChannelAssignment", loggerLocation);
                        return(false);
                    }
                    ChannelAssignment = (ChannelAssignment)((val & 7) + 1);
                }
                else
                {
                    channels          = val + 1;
                    ChannelAssignment = ChannelAssignment.Independent;
                }
                Channels = channels;

                #endregion channels

                #region bitspersample

                val = (headerBuffer[3] & 0x0E) >> 1;
                int bitsPerSample;
                if (val == 0)
                {
                    if (streamInfo != null)
                    {
                        bitsPerSample = streamInfo.BitsPerSample;
                    }
                    else
                    {
                        Error("Missing BitsPerSample. Index = 0 && streamInfoMetaData == null.", loggerLocation);
                        return(false);
                    }
                }
                else if (val == 3 || val >= 7 || val < 0)
                {
                    Error("Invalid BitsPerSampleIndex", loggerLocation);
                    return(false);
                }
                else
                {
                    bitsPerSample = FlacConstant.BitPerSampleTable[val];
                }

                BitsPerSample = bitsPerSample;

                #endregion bitspersample

                if ((headerBuffer[3] & 0x01) != 0) // reserved bit -> 0
                {
                    Error("Invalid FlacFrame. Reservedbit_1 is 1", loggerLocation);
                    return(false);
                }

                reader.ReadBits(32); //skip the first 4 bytes since they got already processed

                //BYTE 4

                #region utf8

                //variable blocksize
                if ((headerBuffer[1] & 0x01) != 0 ||
                    (streamInfo != null && streamInfo.MinBlockSize != streamInfo.MaxBlockSize))
                {
                    if (reader.ReadUTF8_64(out var samplenumber) && samplenumber != ulong.MaxValue)
                    {
                        BlockingStrategy = BlockingStrategy.VariableBlockSize;
                        SampleNumber     = (long)samplenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Samplenumber coding.", loggerLocation);
                        return(false);
                    }
                }
                else //fixed blocksize
                {
                    if (reader.ReadUTF8_32(out var framenumber) && framenumber != uint.MaxValue)
                    {
                        BlockingStrategy = BlockingStrategy.FixedBlockSize;
                        FrameNumber      = (int)framenumber;
                    }