Пример #1
0
        private IEnumerator <int> ReadResidualData(FlacBitStreamReader bitReader, int blockSize, int predictorOrder)
        {
            const byte RiceCodingWith4BitParameter = 0;
            const byte RiceCodingWith5BitParameter = 1;

            uint residualRiceParamSizeType = bitReader.ReadBits(2);

            int residualRiceParamSize;

            if (residualRiceParamSizeType == RiceCodingWith4BitParameter)
            {
                residualRiceParamSize = 4;
            }
            else if (residualRiceParamSizeType == RiceCodingWith5BitParameter)
            {
                residualRiceParamSize = 5;
            }
            else
            {
                throw new FlacException("Reserved residual coding method");
            }

            // rice and rice2 almost the same
            // read rice partitined method
            int partitionOrder = (int)bitReader.ReadBits(4);
            int partitionCount = 1 << partitionOrder;
            int sampleCount    = blockSize >> partitionOrder;

            if (sampleCount < predictorOrder || sampleCount < 1 ||
                (sampleCount << partitionOrder) != blockSize)
            {
                throw new FlacException("Invalid partition order");
            }

            for (int i = 0; i < partitionCount; i++)
            {
                int skipSamples = i == 0 ? predictorOrder : 0;

                int riceParameter = (int)bitReader.ReadBits(residualRiceParamSize);
                if (riceParameter + 1 == 1 << residualRiceParamSize)
                {
                    // escape mode
                    int bitsPerSample = (int)bitReader.ReadBits(5);

                    for (int j = skipSamples; j < sampleCount; j++)
                    {
                        yield return(bitReader.ReadSignedBits(bitsPerSample));
                    }
                }
                else
                {
                    int maxRiceK = int.MaxValue >> riceParameter;
                    for (int j = skipSamples; j < sampleCount; j++)
                    {
                        yield return(bitReader.ReadRice(riceParameter));
                    }
                }
            }
        }
Пример #2
0
 private IEnumerable <int> ReadValuesVerbatim(FlacBitStreamReader bitReader, int blockSize, int bitsPerSample)
 {
     for (int i = 0; i < blockSize; i++)
     {
         int value = bitReader.ReadSignedBits(bitsPerSample);
         yield return(value);
     }
 }
Пример #3
0
        public byte[] ReadFrameRawData()
        {
            if (recordType != FlacRecordType.Frame)
            {
                throw new FlacException("Cannot read non-frame data");
            }

            MemoryStream ms = new MemoryStream();

            ms.Write(lastFrameHeaderData, 0, lastFrameHeaderData.Length);

            // replace bitReader
            ushort currentCrc16 = bitReader.Complete();

            bitReader = new FlacBitStreamReader(
                new SinkedStream(BaseStream, ms), currentCrc16);

            // read subframes
            for (int i = 0; i < FrameChannelCount; i++)
            {
                ReadSubframe();
                SkipSampleValues();
            }
            bitReader.Complete();
            bitReader = null;

            // read footer
            byte[] crc16 = ReadExactly(2);
            recordType = FlacRecordType.FrameFooter;

            int frameDataLength = checked ((int)ms.Length);

            ms.Write(crc16, 0, crc16.Length);

            byte[] frameData = ms.ToArray();

            // check CRC16
            ushort dataCrc16 = CrcUtils.Crc16(0, frameData, 0, frameDataLength);
            int    footerCrc = (crc16[0] << 8) | crc16[1];

            if (dataCrc16 != footerCrc)
            {
                throw new FlacException("Invalid frame footer CRC16");
            }

            return(frameData);
        }
Пример #4
0
        private void ReadFrameFooter()
        {
            ushort crc16 = bitReader.Complete();

            bitReader = null;

            byte[] data        = ReadExactly(2);
            int    footerCrc16 = data[0] << 8 | data[1];

            if (crc16 != footerCrc16)
            {
                throw new FlacException("Invalid frame footer CRC16");
            }

            subframeIndex = 0;

            this.recordType = FlacRecordType.FrameFooter;
        }
Пример #5
0
        private void ReadFrame()
        {
            const int FrameHeaderLength            = 2 + 1 + 1;
            const int FrameSync                    = 0xFFF8;
            const int FrameSyncMask                = 0xFFFC;
            const int ReservedBlockSizeSamplesType = 0;
            const int InvalidSampleRateType        = 15;

            int read;

            byte[] data = new byte[FrameHeaderLength];
            if (recordType != FlacRecordType.Sync)
            {
                read = BaseStream.Read(data, 0, FrameHeaderLength);
                if (read < FrameHeaderLength)
                {
                    if (read <= 0)
                    {
                        recordType = FlacRecordType.Eof;
                        return;
                    }
                    throw new FlacException("Unexpected eof of stream: invalid frame header length");
                }

                if (((data[0] << 8 | data[1]) & FrameSyncMask) != FrameSync)
                {
                    throw new FlacException("Frame sync is expected");
                }
            }
            else
            {
                const int SyncReadLength = 2;
                read = BaseStream.Read(data, SyncReadLength, FrameHeaderLength - SyncReadLength);
                if (read + SyncReadLength < FrameHeaderLength)
                {
                    throw new FlacException("Unexpected eof of stream: invalid frame header length");
                }

                data[0] = (byte)(FrameSync >> 8); data[1] = secondSyncByte;
            }

            if ((data[1] & 0x02) != 0)
            {
                throw new FlacException("Frame header reserved bit (15) shall not be 1");
            }

            this.variableBlockSize = (data[1] & 0x01) != 0;

            int blockSizeSamplesType = data[2] >> 4;

            if (blockSizeSamplesType == ReservedBlockSizeSamplesType)
            {
                throw new FlacException("Frame header block size samples shall not be set to reserved");
            }

            int previousBlockSize = this.blockSize;

            this.blockSize = FlacCommons.StaticBlockSizeSamples[blockSizeSamplesType];

            int sampleRateType = data[2] & 0x0F;

            if (sampleRateType == InvalidSampleRateType)
            {
                throw new FlacException("Frame header sample rate type is invalid");
            }

            this.sampleRate = FlacCommons.StaticSampleRates[sampleRateType];

            int channelAssignmentType = data[3] >> 4;

            if (channelAssignmentType >= FlacCommons.StaticChannelAssignments.Length)
            {
                throw new FlacException("Frame header channel assignments are defined as reserved");
            }

            this.channelAssignmentType = (SoundChannelAssignmentType)channelAssignmentType;
            this.channelAssignment     = FlacCommons.StaticChannelAssignments[channelAssignmentType];
            if (channelAssignment == null)
            {
                throw new FlacException("Frame header channel assignment are not defined");
            }

            this.channelCount = channelAssignment.Length;

            int sampleSizeInBitsType = (data[3] >> 1) & 0x07;

            if (sampleSizeInBitsType == FlacCommons.StreaminfoSizeInBitsType)
            {
                this.sampleSizeInBits = Streaminfo.BitsPerSample;
            }
            else if (FlacCommons.StaticSampleSizeInBits[sampleSizeInBitsType] > 0)
            {
                this.sampleSizeInBits = FlacCommons.StaticSampleSizeInBits[sampleSizeInBitsType];
            }
            else
            {
                throw new FlacException("Frame header sample size is defined as reserved");
            }

            if ((data[3] & 1) != 0)
            {
                throw new FlacException("Frame header reserved bit (31) shall not be 1");
            }

            MemoryStream ms = new MemoryStream(20);

            ms.Write(data, 0, FrameHeaderLength);

            byte[] numberData;
            if (variableBlockSize)
            {
                ReadUtf8Number(out this.sampleNumber, out numberData);
                if (numberData.Length > 7)
                {
                    throw new FlacException("Invalid variable block size");
                }
            }
            else
            {
                ReadUtf8Number(out this.frameNumber, out numberData);
                if (numberData.Length > 6)
                {
                    throw new FlacException("Invalid frame number");
                }
                this.sampleNumber = this.frameNumber == 0 ? 0 :
                                    previousBlockSize *this.frameNumber;
            }
            ms.Write(numberData, 0, numberData.Length);

            byte[] blockSizeData = null;
            switch (blockSizeSamplesType)
            {
            case FlacCommons.Bit8BlockSizeSamplesType:
                blockSizeData  = ReadExactly(1);
                this.blockSize = (int)blockSizeData[0] + 1;
                break;

            case FlacCommons.Bit16BlockSizeSamplesType:
                blockSizeData  = ReadExactly(2);
                this.blockSize = (blockSizeData[0] << 8 | blockSizeData[1]) + 1;
                break;
            }
            if (blockSizeData != null)
            {
                ms.Write(blockSizeData, 0, blockSizeData.Length);
            }

            byte[] sampleRateData = null;
            switch (sampleRateType)
            {
            case FlacCommons.StreaminfoSampleRateType:
                this.sampleRate = Streaminfo.SampleRate;
                break;

            case FlacCommons.Bit8SampleRateType:
                sampleRateData  = ReadExactly(1);
                this.sampleRate = sampleRateData[0];
                break;

            case FlacCommons.Bit16SampleRateType:
                sampleRateData  = ReadExactly(2);
                this.sampleRate = sampleRateData[0] << 8 | sampleRateData[1];
                break;

            case FlacCommons.Bit16Mult10SampleRateType:
                sampleRateData  = ReadExactly(2);
                this.sampleRate = (sampleRateData[0] << 8 | sampleRateData[1]) * 10;
                break;
            }
            if (sampleRateData != null)
            {
                ms.Write(sampleRateData, 0, sampleRateData.Length);
            }

            byte[] readData   = ms.ToArray();
            byte   crc8       = CrcUtils.Crc8(0, readData);
            int    headerCrc8 = BaseStream.ReadByte();

            if (headerCrc8 < 0)
            {
                throw new FlacException("Unexpected end of stream: frame CRC8 expected");
            }
            else if (crc8 != headerCrc8)
            {
                throw new FlacException("Invalid frame CRC");
            }

            ushort currentCrc16 = CrcUtils.Crc16(
                CrcUtils.Crc16(0, readData), (byte)headerCrc8);

            bitReader = new FlacBitStreamReader(BaseStream, currentCrc16);

            lastFrameHeaderData = new byte[readData.Length + 1];
            Array.Copy(readData, lastFrameHeaderData, readData.Length);
            lastFrameHeaderData[readData.Length] = crc8;

            recordType = FlacRecordType.Frame;
        }
Пример #6
0
 private IEnumerable<int> ReadValuesVerbatim(FlacBitStreamReader bitReader, int blockSize, int bitsPerSample)
 {
     for (int i = 0; i < blockSize; i++)
     {
         int value = bitReader.ReadSignedBits(bitsPerSample);
         yield return value;
     }
 }
Пример #7
0
        private IEnumerator<int> ReadResidualData(FlacBitStreamReader bitReader, int blockSize, int predictorOrder)
        {
            const byte RiceCodingWith4BitParameter = 0;
            const byte RiceCodingWith5BitParameter = 1;

            uint residualRiceParamSizeType = bitReader.ReadBits(2);

            int residualRiceParamSize;
            if (residualRiceParamSizeType == RiceCodingWith4BitParameter)
                residualRiceParamSize = 4;
            else if (residualRiceParamSizeType == RiceCodingWith5BitParameter)
                residualRiceParamSize = 5;
            else
                throw new FlacException("Reserved residual coding method");

            // rice and rice2 almost the same
            // read rice partitined method
            int partitionOrder = (int)bitReader.ReadBits(4);
            int partitionCount = 1 << partitionOrder;
            int sampleCount = blockSize >> partitionOrder;

            if (sampleCount < predictorOrder || sampleCount < 1 ||
                (sampleCount << partitionOrder) != blockSize )
                throw new FlacException("Invalid partition order");

            for (int i = 0; i < partitionCount; i++)
            {
                int skipSamples = i == 0 ? predictorOrder : 0;

                int riceParameter = (int)bitReader.ReadBits(residualRiceParamSize);
                if (riceParameter + 1 == 1 << residualRiceParamSize)
                {
                    // escape mode
                    int bitsPerSample = (int)bitReader.ReadBits(5);

                    for (int j = skipSamples; j < sampleCount; j++)
                    {
                        yield return bitReader.ReadSignedBits(bitsPerSample);
                    }
                }
                else
                {
                    int maxRiceK = int.MaxValue >> riceParameter;
                    for (int j = skipSamples; j < sampleCount; j++)
                    {
                        yield return bitReader.ReadRice(riceParameter);
                    }
                }
            }
        }
Пример #8
0
        private void ReadFrameFooter()
        {
            ushort crc16 = bitReader.Complete();
            bitReader = null;

            byte[] data = ReadExactly(2);
            int footerCrc16 = data[0] << 8 | data[1];

            if (crc16 != footerCrc16)
                throw new FlacException("Invalid frame footer CRC16");

            subframeIndex = 0;

            this.recordType = FlacRecordType.FrameFooter;
        }
Пример #9
0
        private void ReadFrame()
        {
            const int FrameHeaderLength = 2 + 1 + 1;
            const int FrameSync = 0xFFF8;
            const int FrameSyncMask = 0xFFFC;
            const int ReservedBlockSizeSamplesType = 0;
            const int InvalidSampleRateType = 15;

            int read;
            byte[] data = new byte[FrameHeaderLength];
            if (recordType != FlacRecordType.Sync)
            {
                read = BaseStream.Read(data, 0, FrameHeaderLength);
                if (read < FrameHeaderLength)
                {
                    if (read <= 0)
                    {
                        recordType = FlacRecordType.Eof;
                        return;
                    }
                    throw new FlacException("Unexpected eof of stream: invalid frame header length");
                }

                if (((data[0] << 8 | data[1]) & FrameSyncMask) != FrameSync)
                    throw new FlacException("Frame sync is expected");
            }
            else
            {
                const int SyncReadLength = 2;
                read = BaseStream.Read(data, SyncReadLength, FrameHeaderLength - SyncReadLength);
                if(read + SyncReadLength < FrameHeaderLength)
                    throw new FlacException("Unexpected eof of stream: invalid frame header length");

                data[0] = (byte)(FrameSync >> 8); data[1] = secondSyncByte;
            }

            if((data[1] & 0x02) != 0)
                throw new FlacException("Frame header reserved bit (15) shall not be 1");

            this.variableBlockSize = (data[1] & 0x01) != 0;

            int blockSizeSamplesType = data[2] >> 4;
            if(blockSizeSamplesType == ReservedBlockSizeSamplesType)
                throw new FlacException("Frame header block size samples shall not be set to reserved");

            int previousBlockSize = this.blockSize;

            this.blockSize = FlacCommons.StaticBlockSizeSamples[blockSizeSamplesType];

            int sampleRateType = data[2] & 0x0F;
            if(sampleRateType == InvalidSampleRateType)
                throw new FlacException("Frame header sample rate type is invalid");

            this.sampleRate = FlacCommons.StaticSampleRates[sampleRateType];

            int channelAssignmentType = data[3] >> 4;

            if (channelAssignmentType >= FlacCommons.StaticChannelAssignments.Length)
                throw new FlacException("Frame header channel assignments are defined as reserved");

            this.channelAssignmentType = (SoundChannelAssignmentType)channelAssignmentType;
            this.channelAssignment = FlacCommons.StaticChannelAssignments[channelAssignmentType];
            if (channelAssignment == null)
                throw new FlacException("Frame header channel assignment are not defined");

            this.channelCount = channelAssignment.Length;

            int sampleSizeInBitsType = (data[3] >> 1) & 0x07;
            if (sampleSizeInBitsType == FlacCommons.StreaminfoSizeInBitsType)
                this.sampleSizeInBits = Streaminfo.BitsPerSample;
            else if (FlacCommons.StaticSampleSizeInBits[sampleSizeInBitsType] > 0)
                this.sampleSizeInBits = FlacCommons.StaticSampleSizeInBits[sampleSizeInBitsType];
            else
                throw new FlacException("Frame header sample size is defined as reserved");

            if((data[3] & 1) != 0)
                throw new FlacException("Frame header reserved bit (31) shall not be 1");

            MemoryStream ms = new MemoryStream(20);
            ms.Write(data, 0, FrameHeaderLength);

            byte[] numberData;
            if (variableBlockSize)
            {
                ReadUtf8Number(out this.sampleNumber, out numberData);
                if (numberData.Length > 7)
                    throw new FlacException("Invalid variable block size");
            }
            else
            {
                ReadUtf8Number(out this.frameNumber, out numberData);
                if (numberData.Length > 6)
                    throw new FlacException("Invalid frame number");
                this.sampleNumber = this.frameNumber == 0 ? 0 :
                    previousBlockSize * this.frameNumber;
            }
            ms.Write(numberData, 0, numberData.Length);

            byte[] blockSizeData = null;
            switch (blockSizeSamplesType)
            {
                case FlacCommons.Bit8BlockSizeSamplesType:
                    blockSizeData = ReadExactly(1);
                    this.blockSize = (int)blockSizeData[0] + 1;
                    break;
                case FlacCommons.Bit16BlockSizeSamplesType:
                    blockSizeData = ReadExactly(2);
                    this.blockSize = (blockSizeData[0] << 8 | blockSizeData[1]) + 1;
                    break;
            }
            if(blockSizeData != null)
                ms.Write(blockSizeData, 0, blockSizeData.Length);

            byte[] sampleRateData = null;
            switch (sampleRateType)
            {
                case FlacCommons.StreaminfoSampleRateType:
                    this.sampleRate = Streaminfo.SampleRate;
                    break;
                case FlacCommons.Bit8SampleRateType:
                    sampleRateData = ReadExactly(1);
                    this.sampleRate = sampleRateData[0];
                    break;
                case FlacCommons.Bit16SampleRateType:
                    sampleRateData = ReadExactly(2);
                    this.sampleRate = sampleRateData[0] << 8 | sampleRateData[1];
                    break;
                case FlacCommons.Bit16Mult10SampleRateType:
                    sampleRateData = ReadExactly(2);
                    this.sampleRate = (sampleRateData[0] << 8 | sampleRateData[1]) * 10;
                    break;
            }
            if (sampleRateData != null)
                ms.Write(sampleRateData, 0, sampleRateData.Length);

            byte[] readData = ms.ToArray();
            byte crc8 = CrcUtils.Crc8(0, readData);
            int headerCrc8 = BaseStream.ReadByte();
            if (headerCrc8 < 0)
                throw new FlacException("Unexpected end of stream: frame CRC8 expected");
            else if(crc8 != headerCrc8)
                throw new FlacException("Invalid frame CRC");

            ushort currentCrc16 = CrcUtils.Crc16(
                CrcUtils.Crc16(0, readData), (byte)headerCrc8);

            bitReader = new FlacBitStreamReader(BaseStream, currentCrc16);

            lastFrameHeaderData = new byte[readData.Length + 1];
            Array.Copy(readData, lastFrameHeaderData, readData.Length);
            lastFrameHeaderData[readData.Length] = crc8;

            recordType = FlacRecordType.Frame;
        }
Пример #10
0
        public byte[] ReadFrameRawData()
        {
            if(recordType != FlacRecordType.Frame)
                throw new FlacException("Cannot read non-frame data");

            MemoryStream ms = new MemoryStream();
            ms.Write(lastFrameHeaderData, 0, lastFrameHeaderData.Length);

            // replace bitReader
            ushort currentCrc16 = bitReader.Complete();
            bitReader = new FlacBitStreamReader(
                new SinkedStream(BaseStream, ms), currentCrc16);

            // read subframes
            for (int i = 0; i < FrameChannelCount; i++)
            {
                ReadSubframe();
                SkipSampleValues();
            }
            bitReader.Complete();
            bitReader = null;

            // read footer
            byte[] crc16 = ReadExactly(2);
            recordType = FlacRecordType.FrameFooter;

            int frameDataLength = checked((int)ms.Length);
            ms.Write(crc16, 0, crc16.Length);

            byte[] frameData = ms.ToArray();

            // check CRC16
            ushort dataCrc16 = CrcUtils.Crc16(0, frameData, 0, frameDataLength);
            int footerCrc = (crc16[0] << 8) | crc16[1];
            if(dataCrc16 != footerCrc)
                throw new FlacException("Invalid frame footer CRC16");

            return frameData;
        }