Example #1
0
        private unsafe void ReadSubFrames()
        {
            List <FlacSubFrameBase> subFrames = new List <FlacSubFrameBase>();

            //alocateOutput
            var data = AllocOuputMemory();

            _subFrameData = data;

            byte[] 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];
            }

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

            fixed(byte *ptrBuffer = buffer)
            {
                FlacBitReader reader = new FlacBitReader(ptrBuffer, 0);

                for (int c = 0; c < Header.Channels; c++)
                {
                    int 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);
            }

#if FLAC_DEBUG
            _subFrames = subFrames.AsReadOnly();
#endif
        }
        public unsafe FlacSubFrameFixed(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bitsPerSample, int order)
            : base(header)
        {
            for (int i = 0; i < order; i++) //order = predictor order
            {
                data.ResidualBuffer[i] = data.DestinationBuffer[i] = reader.ReadBitsSigned(bitsPerSample);
            }

            var residual = new FlacResidual(reader, header, data, order); //necessary for decoding

            RestoreSignal(data, header.BlockSize - order, order);

#if FLAC_DEBUG
            Residual = residual;
#endif
        }
Example #3
0
        /// <summary>
        /// Initializes the properties of the <see cref="FlacMetadata"/> by reading them from the <paramref name="stream"/>.
        /// </summary>
        /// <param name="stream">The stream which contains the metadata.</param>
        protected override unsafe void InitializeByStream(Stream stream)
        {
            //http://flac.sourceforge.net/format.html#metadata_block_streaminfo
            var reader = new BinaryReader(stream, Encoding.ASCII);

            try
            {
                MinBlockSize = reader.ReadInt16();
                MaxBlockSize = reader.ReadInt16();
            }
            catch (IOException e)
            {
                throw new FlacException(e, FlacLayer.Metadata);
            }
            const int bytesToRead = (240 / 8) - 16;

            byte[] buffer = reader.ReadBytes(bytesToRead);
            if (buffer.Length != bytesToRead)
            {
                throw new FlacException(new EndOfStreamException("Could not read StreamInfo-content"),
                                        FlacLayer.Metadata);
            }

            fixed(byte *b = buffer)
            {
                var bitreader = new FlacBitReader(b, 0);

                MinFrameSize  = (int)bitreader.ReadBits(24);
                MaxFrameSize  = (int)bitreader.ReadBits(24);
                SampleRate    = (int)bitreader.ReadBits(20);
                Channels      = 1 + (int)bitreader.ReadBits(3);
                BitsPerSample = 1 + (int)bitreader.ReadBits(5);
                TotalSamples  = (long)bitreader.ReadBits64(36);
                Md5           = new String(reader.ReadChars(16));
            }
        }
Example #4
0
        private unsafe bool ParseHeader(ref byte *headerBuffer, FlacMetadataStreamInfo streamInfo)
        {
            const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)";
            int          val;

            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);
                }

                byte *        __headerbufferPtr = headerBuffer;
                FlacBitReader reader            = new FlacBitReader(__headerbufferPtr, 0);

                #region blocksize

                //blocksize
                val = headerBuffer[2] >> 4;
                int 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;
                int 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))
                {
                    ulong samplenumber;
                    if (reader.ReadUTF8_64(out samplenumber) && samplenumber != ulong.MaxValue)
                    {
                        BlockingStrategy = BlockingStrategy.VariableBlockSize;
                        SampleNumber     = (long)samplenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Samplenumber coding.", loggerLocation);
                        return(false);
                    }
                }
                else //fixed blocksize
                {
                    uint framenumber;

                    if (reader.ReadUTF8_32(out framenumber) && framenumber != uint.MaxValue)
                    {
                        BlockingStrategy = BlockingStrategy.FixedBlockSize;
                        FrameNumber      = (int)framenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Framenumber coding.", loggerLocation);
                        return(false);
                    }
                }

                #endregion utf8

                #region read hints

                //blocksize am ende des frameheaders
                if (_blocksizeHint != 0)
                {
                    val = (int)reader.ReadBits(8);
                    if (_blocksizeHint == 7)
                    {
                        val = (val << 8) | (int)reader.ReadBits(8);
                    }
                    BlockSize = val + 1;
                }

                //samplerate
                if (_sampleRateHint != 0)
                {
                    val = (int)reader.ReadBits(8);
                    if (_sampleRateHint != 12)
                    {
                        val = (val << 8) | (int)reader.ReadBits(8);
                    }
                    if (_sampleRateHint == 12)
                    {
                        SampleRate = val * 1000;
                    }
                    else if (_sampleRateHint == 13)
                    {
                        SampleRate = val;
                    }
                    else
                    {
                        SampleRate = val * 10;
                    }
                }

                #endregion read hints

                if (DoCrc)
                {
                    var crc8 = Utils.CRC8.Instance.CalcCheckSum(reader.Buffer, 0, reader.Position);
                    Crc8 = (byte)reader.ReadBits(8);
                    if (Crc8 != crc8)
                    {
                        Error("CRC8 missmatch", loggerLocation);
                        return(false);
                    }
                }
                else
                {
                    Crc8 = (byte)reader.ReadBits(8);
                }

                headerBuffer += reader.Position;
                return(true);
            }

            Error("Invalid Syncbits", loggerLocation);
            return(false);
        }
        public unsafe static FlacSubFrameBase GetSubFrame(FlacBitReader reader, FlacSubFrameData data, FlacFrameHeader header, int bitsPerSample)
        {
            int wastedBits = 0, order;

            uint firstByte = reader.ReadBits(8);

            if ((firstByte & 0x80) != 0) //Zero bit padding, to prevent sync-fooling string of 1s
            {
                Debug.WriteLine("Flacdecoder subframe-header got no zero-bit padding.");
                return(null);
            }

            bool hasWastedBits = (firstByte & 1) != 0; //Wasted bits-per-sample' flag

            if (hasWastedBits)
            {
                int k = (int)reader.ReadUnary();
                wastedBits     = k + 1; //"k-1" follows -> add 1
                bitsPerSample -= wastedBits;
            }

            FlacSubFrameBase subFrame;
            var subframeType = (firstByte & 0x7E) >> 1; //0111 1110

            if (subframeType == 0)                      //000000
            {
                subFrame = new FlacSubFrameConstant(reader, header, data, bitsPerSample);
            }
            else if (subframeType == 1) //000001
            {
                subFrame = new FlacSubFrameVerbatim(reader, header, data, bitsPerSample);
            }
            else if ((subframeType & 0x20) != 0) //100000 = 0x20
            {
                order    = (int)(subframeType & 0x1F) + 1;
                subFrame = new FlacSubFrameLPC(reader, header, data, bitsPerSample, order);
            }
            else if ((subframeType & 0x08) != 0) //001000 = 0x08
            {
                order = (int)(subframeType & 0x07);
                if (order > 4)
                {
                    return(null);
                }
                subFrame = new FlacSubFrameFixed(reader, header, data, bitsPerSample, order);
            }
            else
            {
                Debug.WriteLine(String.Format("Invalid Flac-SubframeType. SubframeType: 0x{0:x}.", subframeType));
                return(null);
            }

            if (hasWastedBits)
            {
                int *destination = data.DestinationBuffer;
                for (int i = 0; i < header.BlockSize; i++)
                {
                    *(destination++) <<= wastedBits;
                }
            }

#if FLAC_DEBUG
            subFrame.WastedBits = wastedBits;
#endif
            return(subFrame);
        }
Example #6
0
        public unsafe FlacSubFrameLPC(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bitsPerSample, int order)
            : base(header)
        {
            var warmup = new int[order];

            for (int i = 0; i < order; i++)
            {
                warmup[i] = data.ResidualBuffer[i] = reader.ReadBitsSigned(bitsPerSample);
            }

            int coefPrecision = (int)reader.ReadBits(4);

            if (coefPrecision == 0x0F)
            {
                throw new FlacException("Invalid \"quantized linear predictor coefficients' precision in bits\" was invalid. Must not be 0x0F.",
                                        FlacLayer.SubFrame);
            }
            coefPrecision += 1;

            int shiftNeeded = reader.ReadBitsSigned(5);

            if (shiftNeeded < 0)
            {
                throw new FlacException("'\"Quantized linear predictor coefficient shift needed in bits\" was negative.", FlacLayer.SubFrame);
            }

            var q = new int[order];

            for (int i = 0; i < order; i++)
            {
                q[i] = reader.ReadBitsSigned(coefPrecision);
            }

            //decode the residual
            var residual = new FlacResidual(reader, header, data, order);

            for (int i = 0; i < order; i++)
            {
                data.DestinationBuffer[i] = data.ResidualBuffer[i];
            }

            int *residualBuffer0    = data.ResidualBuffer + order;
            int *destinationBuffer0 = data.DestinationBuffer + order;
            int  blockSizeToProcess = header.BlockSize - order;

            if (bitsPerSample + coefPrecision + Log2(order) <= 32)
            {
                RestoreLPCSignal32(residualBuffer0, destinationBuffer0, blockSizeToProcess, order, q, shiftNeeded);
            }
            else
            {
                RestoreLPCSignal64(residualBuffer0, destinationBuffer0, blockSizeToProcess, order, q, shiftNeeded);
            }

#if FLAC_DEBUG
            QLPCoeffPrecision = coefPrecision;
            LPCShiftNeeded    = shiftNeeded;
            Warmup            = warmup;
            Residual          = residual;
            QLPCoeffs         = q;
#endif
        }