Exemplo n.º 1
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;
        }
Exemplo n.º 2
0
        public void WriteFrame(FlacMethodAndDataPair[] methods, SoundChannelAssignmentType channelAssignment)
        {
            EnsureFramesMode();

            sink.StartFrame(streamPosition, currentSample);

            if (methods == null)
            {
                throw new ArgumentNullException("methods");
            }
            if (methods.Length != Streaminfo.ChannelsCount)
            {
                throw new ArgumentNullException("Methods items does not correspond to amount of channels");
            }

            int samplesCount = methods[0].Data.Length;

            const byte Blocking = 0x00; // fixed

            MemoryStream frameHeader = new MemoryStream();

            // sync code + reserved = 0 + blocking
            frameHeader.WriteByte(0xFF); frameHeader.WriteByte(0xF8 | Blocking);

            int interChannelSamplesTypeIndex = Array.IndexOf(FlacCommons.StaticBlockSizeSamples, samplesCount);
            int interChannelSamplesType;

            if (interChannelSamplesTypeIndex > 0)
            {
                interChannelSamplesType = interChannelSamplesTypeIndex;
            }
            else if (samplesCount > 256)
            {
                interChannelSamplesType = FlacCommons.Bit16BlockSizeSamplesType;
            }
            else
            {
                interChannelSamplesType = FlacCommons.Bit8BlockSizeSamplesType;
            }

            int sampleRateTypeIndex = Array.IndexOf(FlacCommons.StaticSampleRates, Streaminfo.SampleRate);
            int sampleRateType      = sampleRateTypeIndex > 0
                ? sampleRateTypeIndex : FlacCommons.StreaminfoSampleRateType;

            frameHeader.WriteByte((byte)(interChannelSamplesType << 4 | sampleRateType));

            int channelAssignmetType = (int)channelAssignment;

            int sampleSizeInBitsTypeIndex = Array.IndexOf(FlacCommons.StaticSampleSizeInBits, Streaminfo.BitsPerSample);
            int sampleSizeInBitsType      = sampleSizeInBitsTypeIndex > 0
                ? sampleSizeInBitsTypeIndex : FlacCommons.StreaminfoSizeInBitsType;

            frameHeader.WriteByte((byte)(channelAssignmetType << 4 | sampleSizeInBitsType << 1));

            WriteUtf8Number(frameHeader, frameNumber);
            switch (interChannelSamplesType)
            {
            case FlacCommons.Bit8BlockSizeSamplesType:
                frameHeader.WriteByte((byte)(samplesCount - 1)); break;

            case FlacCommons.Bit16BlockSizeSamplesType:
                frameHeader.WriteByte((byte)((samplesCount - 1) >> 8));
                frameHeader.WriteByte((byte)(samplesCount - 1));
                break;
            }
            frameHeader.Dispose();

            byte[] frameHeaderData = frameHeader.ToArray();

            byte crc8 = CrcUtils.Crc8(0, frameHeaderData);

            BaseStream.Write(frameHeaderData, 0, frameHeaderData.Length);
            BaseStream.WriteByte(crc8);

            ++frameNumber;

            ushort crc16Seed = CrcUtils.Crc16(CrcUtils.Crc16(0, frameHeaderData), crc8);

            // write channels
            FlacBitStreamWriter bitWriter = new FlacBitStreamWriter(BaseStream, crc16Seed);

            for (int i = 0; i < methods.Length; i++)
            {
                WriteSubframe(bitWriter, methods[i]);
            }

            int    subframesLength;
            ushort crc16;

            bitWriter.Complete(out crc16, out subframesLength);

            // write footer
            BaseStream.WriteByte((byte)(crc16 >> 8)); BaseStream.WriteByte((byte)crc16);


            int frameSize = frameHeaderData.Length + 1 + subframesLength + 2;

            streamPosition += frameSize;
            currentSample  += samplesCount;

            sink.EndFrame(streamPosition, currentSample);
        }
Exemplo n.º 3
0
        public void WriteFrame(int[][] samples, SoundChannelAssignmentType channelAssigment)
        {
            if (samples == null)
            {
                throw new ArgumentNullException("samples");
            }
            int channelsCount = Streaminfo.ChannelsCount;

            if (samples.Length != channelsCount)
            {
                throw new ArgumentException("Expected same amount of channels as in Streaminfo");
            }
            int samplesPerChannel = samples[0].Length;

            if ( // samplesPerChannel < Streaminfo.MinBlockSize ||
                Streaminfo.MaxBlockSize < samplesPerChannel)
            {
                throw new ArgumentException("Amount of samples more or less than specified in Streaminfo");
            }

            for (int i = 1; i < channelsCount; i++)
            {
                if (samplesPerChannel != samples[i].Length)
                {
                    throw new ArgumentException("Expected same amount of samples on all the channels");
                }
            }

            FlacMethod[] methods;

            if (channelsCount == 2 && channelAssigment == SoundChannelAssignmentType.Auto)
            {
                FlacMethodAndDataPair[] methodsForLeftAndRight;

                SoundChannelAssignmentType assigmentType =
                    FindBestMethod(samples[0], samples[1], out methodsForLeftAndRight);

                WriteFrame(methodsForLeftAndRight, assigmentType);
            }
            else
            {
                methods = new FlacMethod[channelsCount];

                SoundChannelAssignment[]   assignments;
                SoundChannelAssignmentType definedChannelAssigmentType;
                if (channelAssigment == SoundChannelAssignmentType.Auto)
                {
                    assignments = FlacCommons.StaticChannelAssignments[channelsCount - 1];
                    definedChannelAssigmentType = (SoundChannelAssignmentType)(channelsCount - 1);
                }
                else
                {
                    assignments = FlacCommons.StaticChannelAssignments[(int)channelAssigment];
                    definedChannelAssigmentType = channelAssigment;
                }

                FlacMethodAndDataPair[] samplesAndMethods = estimator.FindBestMethods(
                    samples, Streaminfo.BitsPerSample);

                WriteFrame(samplesAndMethods, definedChannelAssigmentType);
            }
        }
Exemplo n.º 4
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;
        }
Exemplo n.º 5
0
        public void WriteFrame(FlacMethodAndDataPair[] methods, SoundChannelAssignmentType channelAssignment)
        {
            EnsureFramesMode();

            sink.StartFrame(streamPosition, currentSample);

            if (methods == null) throw new ArgumentNullException("methods");
            if(methods.Length != Streaminfo.ChannelsCount)
                throw new ArgumentNullException("Methods items does not correspond to amount of channels");

            int samplesCount = methods[0].Data.Length;

            const byte Blocking = 0x00; // fixed

            MemoryStream frameHeader = new MemoryStream();
            // sync code + reserved = 0 + blocking
            frameHeader.WriteByte(0xFF); frameHeader.WriteByte(0xF8 | Blocking);

            int interChannelSamplesTypeIndex = Array.IndexOf(FlacCommons.StaticBlockSizeSamples, samplesCount);
            int interChannelSamplesType;
            if (interChannelSamplesTypeIndex > 0)
                interChannelSamplesType = interChannelSamplesTypeIndex;
            else if (samplesCount > 256)
                interChannelSamplesType = FlacCommons.Bit16BlockSizeSamplesType;
            else
                interChannelSamplesType = FlacCommons.Bit8BlockSizeSamplesType;

            int sampleRateTypeIndex = Array.IndexOf(FlacCommons.StaticSampleRates, Streaminfo.SampleRate);
            int sampleRateType = sampleRateTypeIndex > 0
                ? sampleRateTypeIndex : FlacCommons.StreaminfoSampleRateType;
            frameHeader.WriteByte((byte)(interChannelSamplesType << 4 | sampleRateType));

            int channelAssignmetType = (int)channelAssignment;

            int sampleSizeInBitsTypeIndex = Array.IndexOf(FlacCommons.StaticSampleSizeInBits, Streaminfo.BitsPerSample);
            int sampleSizeInBitsType = sampleSizeInBitsTypeIndex > 0
                ? sampleSizeInBitsTypeIndex : FlacCommons.StreaminfoSizeInBitsType;
            frameHeader.WriteByte((byte)(channelAssignmetType << 4 | sampleSizeInBitsType << 1));

            WriteUtf8Number(frameHeader, frameNumber);
            switch (interChannelSamplesType)
            {
                case FlacCommons.Bit8BlockSizeSamplesType:
                    frameHeader.WriteByte((byte)(samplesCount - 1)); break;
                case FlacCommons.Bit16BlockSizeSamplesType:
                    frameHeader.WriteByte((byte)((samplesCount - 1) >> 8));
                    frameHeader.WriteByte((byte)(samplesCount - 1));
                    break;
            }
            frameHeader.Close();

            byte[] frameHeaderData = frameHeader.ToArray();

            byte crc8 = CrcUtils.Crc8(0, frameHeaderData);

            BaseStream.Write(frameHeaderData, 0, frameHeaderData.Length);
            BaseStream.WriteByte(crc8);

            ++frameNumber;

            ushort crc16Seed = CrcUtils.Crc16(CrcUtils.Crc16(0, frameHeaderData), crc8);

            // write channels
            FlacBitStreamWriter bitWriter = new FlacBitStreamWriter(BaseStream, crc16Seed);

            for (int i = 0; i < methods.Length; i++)
            {
                WriteSubframe(bitWriter, methods[i]);
            }

            int subframesLength;
            ushort crc16;
            bitWriter.Complete(out crc16, out subframesLength);

            // write footer
            BaseStream.WriteByte((byte)(crc16 >> 8)); BaseStream.WriteByte((byte)crc16);

            int frameSize = frameHeaderData.Length + 1 + subframesLength + 2;
            streamPosition += frameSize;
            currentSample += samplesCount;

            sink.EndFrame(streamPosition, currentSample);
        }
Exemplo n.º 6
0
        public void WriteFrame(int[][] samples, SoundChannelAssignmentType channelAssigment)
        {
            if(samples == null) throw new ArgumentNullException("samples");
            int channelsCount = Streaminfo.ChannelsCount;
            if (samples.Length != channelsCount)
                throw new ArgumentException("Expected same amount of channels as in Streaminfo");
            int samplesPerChannel = samples[0].Length;
            if( // samplesPerChannel < Streaminfo.MinBlockSize ||
                Streaminfo.MaxBlockSize < samplesPerChannel)
                throw new ArgumentException("Amount of samples more or less than specified in Streaminfo");

            for (int i = 1; i < channelsCount; i++)
            {
                if(samplesPerChannel != samples[i].Length)
                throw new ArgumentException("Expected same amount of samples on all the channels");
            }

            FlacMethod[] methods;

            if(channelsCount == 2 && channelAssigment == SoundChannelAssignmentType.Auto)
            {
                FlacMethodAndDataPair[] methodsForLeftAndRight;

                SoundChannelAssignmentType assigmentType =
                    FindBestMethod(samples[0], samples[1], out methodsForLeftAndRight);

                WriteFrame(methodsForLeftAndRight, assigmentType);
            }
            else
            {
                methods = new FlacMethod[channelsCount];

                SoundChannelAssignment[] assignments;
                SoundChannelAssignmentType definedChannelAssigmentType;
                if (channelAssigment == SoundChannelAssignmentType.Auto)
                {
                    assignments = FlacCommons.StaticChannelAssignments[channelsCount - 1];
                    definedChannelAssigmentType = (SoundChannelAssignmentType)(channelsCount - 1);
                }
                else
                {
                    assignments = FlacCommons.StaticChannelAssignments[(int)channelAssigment];
                    definedChannelAssigmentType = channelAssigment;
                }

                FlacMethodAndDataPair[] samplesAndMethods = estimator.FindBestMethods(
                    samples, Streaminfo.BitsPerSample);

                WriteFrame(samplesAndMethods, definedChannelAssigmentType);
            }
        }