예제 #1
0
        public unsafe FlacMetadataStreamInfo(Stream stream, Int32 length, bool lastBlock)
            : base(FlacMetaDataType.StreamInfo, lastBlock, length)
        {
            //http://flac.sourceforge.net/format.html#metadata_block_streaminfo
            BinaryReader reader = new BinaryReader(stream, Encoding.ASCII);

            try
            {
                MinBlockSize = reader.ReadInt16();
                MaxBlockSize = reader.ReadInt16();
            }
            catch (IOException e)
            {
                throw new FlacException(e, FlacLayer.Metadata);
            }
            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)
            {
                FlacBitReader bitreader = new FlacBitReader(b, 0);

                MinFrameSize  = bitreader.ReadBits(24);
                MaxFrameSize  = 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));
            }
        }
예제 #2
0
        public unsafe FlacMetadataStreamInfo(Stream stream, Int32 length, bool lastBlock)
            : base(FlacMetaDataType.StreamInfo, lastBlock, length)
        {
            //http://flac.sourceforge.net/format.html#metadata_block_streaminfo
            BinaryReader reader = new BinaryReader(stream, Encoding.ASCII);
            try
            {
                MinBlockSize = reader.ReadInt16();
                MaxBlockSize = reader.ReadInt16();
            }
            catch (IOException e)
            {
                throw new FlacException(e, FlacLayer.Metadata);
            }
            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)
            {
                FlacBitReader bitreader = new FlacBitReader(b, 0);
                MinFrameSize = bitreader.ReadBits(24);
                MaxFrameSize = 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));
            }
        }
예제 #3
0
        public unsafe FlacSubFrameLPC(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps, int order)
            : base(header)
        {

            //warmup
            _warmup = new int[FlacConstant.MaxLpcOrder];
            for (int i = 0; i < order; i++)
            {
                _warmup[i] = data.ResidualBuffer[i] = reader.ReadBitsSigned(bps);
            }

            //header
            int u32 = (int)reader.ReadBits(FlacConstant.SubframeLpcQlpCoeffPrecisionLen);
            if (u32 == (1 << FlacConstant.SubframeLpcQlpCoeffPrecisionLen) - 1)
            {
                Debug.WriteLine("Invalid FlacLPC qlp coeff precision.");
                return; //return false;
            }
            _qlpCoeffPrecision = u32 + 1;

            int level = reader.ReadBitsSigned(FlacConstant.SubframeLpcQlpShiftLen);
            if (level < 0)
                throw new Exception("negative shift");
            _lpcShiftNeeded = level;

            _qlpCoeffs = new int[FlacConstant.MaxLpcOrder];

            //qlp coeffs
            for (int i = 0; i < order; i++)
            {
                _qlpCoeffs[i] = reader.ReadBitsSigned(_qlpCoeffPrecision);
            }

            Residual = new FlacResidual(reader, header, data, order);

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

            int i1 = order;
            int result = 0;
            while ((i1 >>= 1) != 0)
            {
                result++;
            }
            if (bps + _qlpCoeffPrecision + result <= 32)
            {
                if (bps <= 16 && _qlpCoeffPrecision <= 16)
                    RestoreLPCSignal(data.ResidualBuffer + order, data.DestBuffer + order, header.BlockSize - order, order); //Restore(data.residualBuffer + order, data.destBuffer, Header.BlockSize - order, order, order);
                else
                    RestoreLPCSignal(data.ResidualBuffer + order, data.DestBuffer + order, header.BlockSize - order, order);
            }
            else
            {
                RestoreLPCSignalWide(data.ResidualBuffer + order, data.DestBuffer + order, header.BlockSize - order, order);//RestoreWide(data.residualBuffer + order, data.destBuffer, Header.BlockSize - order, order, order);
            }
        }
예제 #4
0
        public unsafe FlacSubFrameFixed(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps, int order)
            : base(header)
        {
            for (int i = 0; i < order; i++)
            {
                data.ResidualBuffer[i] = data.DestBuffer[i] = reader.ReadBitsSigned(bps);
            }

            Residual = new FlacResidual(reader, header, data, order); //necessary for decoding
            RestoreSignal(data, header.BlockSize - order, order);
        }
예제 #5
0
        public unsafe FlacSubFrameFixed(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps, int order)
            : base(header)
        {
            for (int i = 0; i < order; i++)
            {
                data.ResidualBuffer[i] = data.DestBuffer[i] = reader.ReadBitsSigned(bps);
            }

            Residual = new FlacResidual(reader, header, data, order); //necessary for decoding
            RestoreSignal(data, header.BlockSize - order, order);
        }
예제 #6
0
        private unsafe void ReadSubFrames()
        {
            List <FlacSubFrameBase> subFrames = new List <FlacSubFrameBase>();

            //alocateOutput
            var data = AllocOuputMemory();

            _data = 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 bps = Header.BitsPerSample;
                    if (Header.ChannelAssignment == ChannelAssignment.MidSide || Header.ChannelAssignment == ChannelAssignment.LeftSide)
                    {
                        bps += c;
                    }
                    else if (Header.ChannelAssignment == ChannelAssignment.RightSide)
                    {
                        bps += 1 - c;
                    }

                    var subframe = FlacSubFrameBase.GetSubFrame(reader, data[c], Header, bps);

                    subFrames.Add(subframe);
                }

                reader.Flush();
                Crc16 = (ushort)reader.ReadBits(16);

                _stream.Position -= read - reader.Position;

                SamplesToBytes(_data);

                //return reader.Position;
            }
        }
예제 #7
0
        public unsafe static FlacMetadata FromStream(Stream stream)
        {
            bool             lastBlock = false;
            FlacMetaDataType type      = FlacMetaDataType.Undef;
            int length = 0;

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

                    lastBlock = bitReader.ReadBits(1) == 1;
                    type      = (FlacMetaDataType)bitReader.ReadBits(7);
                    length    = (int)bitReader.ReadBits(24);
                    ////1000 0000
                    //if (((b[0] & 0x80) >> 7) == 1)
                    //    lastBlock = true;
                    //type = (FlacMetaDataType)(b[0] & 0x7F);
                    //int length = (b[1] + (b[2] << 8) + (b[3] << 16));
                }

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

                switch (type)
                {
                case FlacMetaDataType.StreamInfo:
                    data = new FlacMetadataStreamInfo(stream, length, lastBlock);
                    break;

                case FlacMetaDataType.Seektable:
                    data = new FlacMetadataSeekTable(stream, length, lastBlock);
                    break;

                default:
                    data = new FlacMetadata(type, lastBlock, length);
                    break;
                }

                stream.Seek(length - (stream.Position - streamStartPosition), SeekOrigin.Current);
                return(data);
        }
예제 #8
0
        public unsafe static FlacMetadata FromStream(Stream stream)
        {
            bool lastBlock = false;
            FlacMetaDataType type = FlacMetaDataType.Undef;
            int length = 0;

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

                lastBlock = bitReader.ReadBits(1) == 1;
                type = (FlacMetaDataType)bitReader.ReadBits(7);
                length = (int)bitReader.ReadBits(24);
                ////1000 0000
                //if (((b[0] & 0x80) >> 7) == 1)
                //    lastBlock = true;
                //type = (FlacMetaDataType)(b[0] & 0x7F);
                //int length = (b[1] + (b[2] << 8) + (b[3] << 16));
            }

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

            switch (type)
            {
                case FlacMetaDataType.StreamInfo:
                    data = new FlacMetadataStreamInfo(stream, length, lastBlock);
                    break;

                case FlacMetaDataType.Seektable:
                    data = new FlacMetadataSeekTable(stream, length, lastBlock);
                    break;

                default:
                    data = new FlacMetadata(type, lastBlock, length);
                    break;
            }

            stream.Seek(length - (stream.Position - streamStartPosition), SeekOrigin.Current);
            return data;
        }
예제 #9
0
        public unsafe bool ProcessResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order)
        {
            data.Content.UpdateSize(PartitionOrder);

            int porder = PartitionOrder;
            FlacEntropyCoding codingMethod = CodingMethod;

            int psize  = header.BlockSize >> porder;
            int resCnt = psize - order;

            int ricelength = 4 + (int)codingMethod; //4bit = RICE I | 5bit = RICE II

            //residual
            int  j = order;
            int *r = data.ResidualBuffer + j;

            int partitioncount = 1 << porder;

            for (int p = 0; p < partitioncount; p++)
            {
                if (p == 1)
                {
                    resCnt = psize;
                }
                int n = Math.Min(resCnt, header.BlockSize - j);

                int k = Content.Parameters[p] = (int)reader.ReadBits(ricelength);
                if (k == (1 << ricelength) - 1)
                {
                    k = (int)reader.ReadBits(5);
                    for (int i = n; i > 0; i--)
                    {
                        *(r) = reader.ReadBitsSigned((int)k);
                    }
                }
                else
                {
                    ReadFlacRiceBlock(reader, n, (int)k, r);
                    r += n;
                }
                j += n;
            }

            return(true);
        }
예제 #10
0
        private 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 = 0;
                        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));
                    }
                }
            }
        }
예제 #11
0
        private 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 = 0;
                        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));
                    }
                }
            }
        }
예제 #12
0
        public unsafe bool ProcessResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order)
        {
            data.Content.UpdateSize(PartitionOrder);

            int porder = PartitionOrder;
            FlacEntropyCoding codingMethod = CodingMethod;

            int psize = header.BlockSize >> porder;
            int resCnt = psize - order;

            int ricelength = 4 + (int)codingMethod; //4bit = RICE I | 5bit = RICE II

            //residual
            int j = order;
            int* r = data.ResidualBuffer + j;

            int partitioncount = 1 << porder;

            for (int p = 0; p < partitioncount; p++)
            {
                if (p == 1) resCnt = psize;
                int n = Math.Min(resCnt, header.BlockSize - j);

                int k = Content.Parameters[p] = (int)reader.ReadBits(ricelength);
                if (k == (1 << ricelength) - 1)
                {
                    k = (int)reader.ReadBits(5);
                    for (int i = n; i > 0; i--)
                    {
                        *(r) = reader.ReadBitsSigned((int)k);
                    }
                }
                else
                {
                    ReadFlacRiceBlock(reader, n, (int)k, r);
                    r += n;
                }
                j += n;
            }

            return true;
        }
예제 #13
0
        private unsafe bool ParseHeader(ref byte *headerBuffer, FlacMetadataStreamInfo streamInfo)
        {
            const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)";
            int          x = -1;                                         //tmp value to store in

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

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

                #region blocksize

                //blocksize
                x = headerBuffer[2] >> 4;
                int blocksize = -1;

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

                #endregion blocksize

                #region samplerate

                //samplerate
                x = headerBuffer[2] & 0x0F;
                int sampleRate = -1;

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

                #endregion samplerate

                #region channels

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

                #endregion channels

                #region bitspersample

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

                BitsPerSample = bitsPerSample;

                #endregion bitspersample

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

                //reader.SkipBits(4 * 8); //erste 3 bytes headerbytes überspringen, da diese schon ohne reader verarbeitet
                reader.ReadBits(32);

                //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)
                    {
                        NumberType   = FlacNumberType.SampleNumber;
                        SampleNumber = samplenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Samplenumber coding.", loggerLocation);
                        return(false);
                    }
                }
                else //fixed blocksize
                {
                    uint framenumber;// = reader.ReadUTF8();

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

                #endregion utf8

                #region read hints

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

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

                #endregion read hints

                //if (Channels == 1 && BitsPerSample == 24 && SampleRate == 44100)
                //    System.Diagnostics.Debugger.Break();

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

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

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

            uint x             = reader.ReadBits(8);
            bool hasWastedBits = (x & 1) != 0;

            x &= 0xFE; //1111 1110

            if (hasWastedBits)
            {
                int u = (int)reader.ReadUnary();
                wastedBits = u + 1;
                bps       -= wastedBits;
            }

            if ((x & 0x80) != 0)
            {
                Debug.WriteLine("Flacdecoder lost sync while reading FlacSubFrameHeader. [x & 0x80].");
                return(null);
            }

            FlacSubFrameBase subFrame;

            if ((x > 2 && x < 16) ||
                (x > 24 && x < 64))
            {
                Debug.WriteLine("Invalid FlacSubFrameHeader. [" + x.ToString("x") + "]");
                return(null);
            }

            if (x == 0)
            {
                subFrame = new FlacSubFrameConstant(reader, header, data, bps);
            }
            else if (x == 2)
            {
                //verbatim
                subFrame = new FlacSubFrameVerbatim(reader, header, data, bps);
            }
            else if (x >= 16 && x <= 24)
            {
                //fixed
                order    = (int)((x >> 1) & 7);
                subFrame = new FlacSubFrameFixed(reader, header, data, bps, order);
            }
            else if (x >= 64)
            {
                //lpc
                order    = (int)(((x >> 1) & 31) + 1);
                subFrame = new FlacSubFrameLPC(reader, header, data, bps, order);
            }
            else
            {
                Debug.WriteLine("Invalid Flac-SubframeType: x = " + x + ".");
                return(null);
            }

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

            //System.Diagnostics.Debug.WriteLine(subFrame.GetType().Name);

            //check null removed
            subFrame.WastedBits = wastedBits;

            return(subFrame);
        }
예제 #15
0
        public unsafe static FlacSubFrameBase GetSubFrame(FlacBitReader reader, FlacSubFrameData data, FlacFrameHeader header, int bps)
        {
            int wastedBits = 0, order = 0;

            uint x = reader.ReadBits(8);
            bool hasWastedBits = (x & 1) != 0;
            x &= 0xFE; //1111 1110

            if (hasWastedBits)
            {
                int u = (int)reader.ReadUnary();
                wastedBits = u + 1;
                bps -= wastedBits;
            }

            if ((x & 0x80) != 0)
            {
                Debug.WriteLine("Flacdecoder lost sync while reading FlacSubFrameHeader. [x & 0x80].");
                return null;
            }

            FlacSubFrameBase subFrame;

            if ((x > 2 && x < 16) ||
                 (x > 24 && x < 64))
            {
                Debug.WriteLine("Invalid FlacSubFrameHeader. [" + x.ToString("x") + "]");
                return null;
            }

            if (x == 0)
            {
                subFrame = new FlacSubFrameConstant(reader, header, data, bps);
            }
            else if (x == 2)
            {
                //verbatim
                subFrame = new FlacSubFrameVerbatim(reader, header, data, bps);
            }
            else if (x >= 16 && x <= 24)
            {
                //fixed
                order = (int)((x >> 1) & 7);
                subFrame = new FlacSubFrameFixed(reader, header, data, bps, order);
            }
            else if (x >= 64)
            {
                //lpc
                order = (int)(((x >> 1) & 31) + 1);
                subFrame = new FlacSubFrameLPC(reader, header, data, bps, order);
            }
            else
            {
                Debug.WriteLine("Invalid Flac-SubframeType: x = " + x + ".");
                return null;
            }

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

            //System.Diagnostics.Debug.WriteLine(subFrame.GetType().Name);

            //check null removed
            subFrame.WastedBits = wastedBits;

            return subFrame;
        }
예제 #16
0
        private unsafe bool ParseHeader(ref byte* headerBuffer, FlacMetadataStreamInfo streamInfo)
        {
            const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)";
            int x = -1; //tmp value to store in
            if (headerBuffer[0] == 0xFF && headerBuffer[1] >> 1 == 0x7C) //sync bits
            {
                if ((headerBuffer[1] & 0x02) != 0) // ...10 2. letzes bits muss 0 sein
                {
                    Error("Invalid FlacFrame. Reservedbit_0 is 1", loggerLocation);
                    return false;
                }

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

                #region blocksize

                //blocksize
                x = headerBuffer[2] >> 4;
                int blocksize = -1;

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

                #endregion blocksize

                #region samplerate

                //samplerate
                x = headerBuffer[2] & 0x0F;
                int sampleRate = -1;

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

                #endregion samplerate

                #region channels

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

                #endregion channels

                #region bitspersample

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

                BitsPerSample = bitsPerSample;

                #endregion bitspersample

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

                //reader.SkipBits(4 * 8); //erste 3 bytes headerbytes überspringen, da diese schon ohne reader verarbeitet
                reader.ReadBits(32);

                //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)
                    {
                        NumberType = FlacNumberType.SampleNumber;
                        SampleNumber = samplenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Samplenumber coding.", loggerLocation);
                        return false;
                    }
                }
                else //fixed blocksize
                {
                    uint framenumber;// = reader.ReadUTF8();

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

                #endregion utf8

                #region read hints

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

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

                #endregion read hints

                //if (Channels == 1 && BitsPerSample == 24 && SampleRate == 44100)
                //    System.Diagnostics.Debugger.Break();

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

                headerBuffer += reader.Position;
                return true;
            }

            Error("Invalid Syncbits", loggerLocation);
            return false;
        }
예제 #17
0
        private unsafe void ReadSubFrames()
        {
            List<FlacSubFrameBase> subFrames = new List<FlacSubFrameBase>();

            //alocateOutput
            var data = AllocOuputMemory();
            _data = 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 bps = Header.BitsPerSample;
                    if (Header.ChannelAssignment == ChannelAssignment.MidSide || Header.ChannelAssignment == ChannelAssignment.LeftSide)
                        bps += c;
                    else if (Header.ChannelAssignment == ChannelAssignment.RightSide)
                        bps += 1 - c;

                    var subframe = FlacSubFrameBase.GetSubFrame(reader, data[c], Header, bps);

                    subFrames.Add(subframe);
                }

                reader.Flush();
                Crc16 = (ushort)reader.ReadBits(16);

                _stream.Position -= read - reader.Position;

                SamplesToBytes(_data);

                //return reader.Position;
            }
        }
예제 #18
0
        public unsafe FlacSubFrameLPC(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps, int order)
            : base(header)
        {
            //warmup
            _warmup = new int[FlacConstant.MaxLpcOrder];
            for (int i = 0; i < order; i++)
            {
                _warmup[i] = data.ResidualBuffer[i] = reader.ReadBitsSigned(bps);
            }

            //header
            int u32 = (int)reader.ReadBits(FlacConstant.SubframeLpcQlpCoeffPrecisionLen);

            if (u32 == (1 << FlacConstant.SubframeLpcQlpCoeffPrecisionLen) - 1)
            {
                Debug.WriteLine("Invalid FlacLPC qlp coeff precision.");
                return; //return false;
            }
            _qlpCoeffPrecision = u32 + 1;

            int level = reader.ReadBitsSigned(FlacConstant.SubframeLpcQlpShiftLen);

            if (level < 0)
            {
                throw new Exception("negative shift");
            }
            _lpcShiftNeeded = level;

            _qlpCoeffs = new int[FlacConstant.MaxLpcOrder];

            //qlp coeffs
            for (int i = 0; i < order; i++)
            {
                _qlpCoeffs[i] = reader.ReadBitsSigned(_qlpCoeffPrecision);
            }

            Residual = new FlacResidual(reader, header, data, order);

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

            int i1     = order;
            int result = 0;

            while ((i1 >>= 1) != 0)
            {
                result++;
            }
            if (bps + _qlpCoeffPrecision + result <= 32)
            {
                if (bps <= 16 && _qlpCoeffPrecision <= 16)
                {
                    RestoreLPCSignal(data.ResidualBuffer + order, data.DestBuffer + order, header.BlockSize - order, order); //Restore(data.residualBuffer + order, data.destBuffer, Header.BlockSize - order, order, order);
                }
                else
                {
                    RestoreLPCSignal(data.ResidualBuffer + order, data.DestBuffer + order, header.BlockSize - order, order);
                }
            }
            else
            {
                RestoreLPCSignalWide(data.ResidualBuffer + order, data.DestBuffer + order, header.BlockSize - order, order);//RestoreWide(data.residualBuffer + order, data.destBuffer, Header.BlockSize - order, order, order);
            }
        }