예제 #1
0
        ////------------------------------------------------------------------------------------------------------------------------------
        public static FlacRicePartition Read(StreamBuffer sb, int partitionNumber, int partitionOrder, int predictOrder, int blockSize, FlacResidualCodingMethod codingMethod)
        {
            FlacRicePartition ricePartition = new FlacRicePartition { _riceParameter = sb.ReadBigEndianInt32(), _codingMethod = codingMethod };
            int riceParameter = ricePartition._riceParameter & ((codingMethod == FlacResidualCodingMethod.PartitionedRice) ? 0x1F : 0xF);
            if (partitionOrder == 0)
                ricePartition.Samples = blockSize - predictOrder;
            else if (partitionNumber == 0)
                ricePartition.Samples = (blockSize >> partitionOrder) - predictOrder;
            else
                ricePartition.Samples = blockSize >> partitionOrder;

            ricePartition.Residuals = new int[ricePartition.Samples];
            if ((riceParameter < 0xF) || ((codingMethod == FlacResidualCodingMethod.PartitionedRice2) && (riceParameter < 0x1F)))
            {
                for (int i = 0; i < ricePartition.Samples; i++)
                {
                    long msbs = sb.ReadUnaryInt();
                    long lsbs = sb.ReadBigEndianInt32() & (0xFFFFFFFF >> (32 - riceParameter));
                    long value = (msbs << riceParameter) | lsbs;
                    ricePartition.Residuals[i] = ((value & 0x01) == 0x01) ? -((int)(value >> 1)) - 1 : (int)(value >> 1);
                }
            }
            else
            {
                // residuals in unencoded form, sample size read from the next 5
                // bits in the stream.
                int size = sb.ReadBigEndianInt32();
                for (int i = 0; i < ricePartition.Samples; i++)
                    ricePartition.Residuals[i] = sb.ReadBigEndianInt32();
            }
            return ricePartition;
        }
        private bool ReadFieldInstance(StreamBuffer sb, long maximumFieldSize)
        {
            if (sb == null)
                throw new ArgumentNullException("sb");

            string identifier = sb.ReadString(FieldIdentifierLength);
            string strFieldSize = sb.ReadString(FieldSizeLength);

            int fieldSize;
            if (!Int32.TryParse(strFieldSize, out fieldSize))
            {
            #if DEBUG
                return false;//throw new InvalidDataException(String.Format("Size value for field {0} is not an int: {1}", identifier, strFieldSize));
            #else
                return false;
            #endif
            }
            Identifier = identifier;
            _data = new byte[fieldSize];
            sb.Read(_data, fieldSize);

            if (!IsValidData(_data))
                return false;

            Data = _data;
            return true;
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BitStream"/> class and sets the specified stream to use as backing data.
        /// </summary>
        /// <param name="stream">The stream to use as backing data.</param>
        public BitStream(Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            _sb = new StreamBuffer(stream);
        }
예제 #4
0
 public void LengthTest()
 {
     byte[] value = new byte[] { 0x01, 0x02, 0x10 };
     StreamBuffer target = new StreamBuffer(value);
     long actual= target.Length;
     Assert.AreEqual(actual, value.Length);
 }
예제 #5
0
 public void CanWriteTest()
 {
     StreamBuffer target = new StreamBuffer(); // TODO: Initialize to an appropriate value
     bool actual;
     actual = target.CanWrite;
     Assert.Inconclusive("Verify the correctness of this test method.");
 }
예제 #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="VbriHeader"/> class.
        /// </summary>
        /// <param name="firstFrame">The first frame.</param>
        /// <param name="firstFrameBuffer">The first frame buffer.</param>
        /// <param name="offset">The offset.</param>
        public VbriHeader(MpaFrame firstFrame, StreamBuffer firstFrameBuffer, long offset)
            : base(firstFrame, firstFrameBuffer, offset, VbrHeaderType.Vbri)
        {
            /*
            FhG VBRI Header
            size    description
            4       'VBRI' (ID)
            2       version
            2       delay
            2       quality
            4       # bytes
            4       # frames
            2       table size (for TOC)
            2       table scale (for TOC)
            2       size of a table entry (max. size = 4 byte (must be stored in an integer))
            2       frames per table entry
            ??      dynamic table consisting out of frames with size 1-4 whole length in table size! (for TOC)
            */

            // name
            Name = firstFrameBuffer.ReadString(4);

            // version
            Version = (short)firstFrameBuffer.ReadBigEndianInt16();

            // delay
            _delay = firstFrameBuffer.ReadBigEndianInt16();

            // quality
            Quality = firstFrameBuffer.ReadBigEndianInt16();

            // size of the file, in bytes, of all the data
            FileSize = firstFrameBuffer.ReadBigEndianInt32();

            // amount of frames
            FrameCount = firstFrameBuffer.ReadBigEndianInt32();

            // number of entries in the table (for TOC)
            TableEntries = (short)firstFrameBuffer.ReadBigEndianInt16();

            // table scale (for TOC)
            TableScale = (short)firstFrameBuffer.ReadBigEndianInt16();

            // size of a table entry (in bytes)
            TableEntrySize = (short)firstFrameBuffer.ReadBigEndianInt16();

            // frames per table entry
            FramesPerTableEntry = (short)firstFrameBuffer.ReadBigEndianInt16();

            // dynamic table consisting out of frames
            TableLength = TableEntries * TableEntrySize;
            Toc = new int[TableEntries + 1];
            for (int i = 0; i <= TableEntries; i++)
            {
                int value = firstFrameBuffer.ReadBigEndianInt(TableEntrySize);
                Toc[i] = value * TableScale;
            }
            _totalLengthMilliseconds = firstFrame.AudioLength * FrameCount;
        }
        ////------------------------------------------------------------------------------------------------------------------------------
        private static Lyrics3v2Field ReadField(StreamBuffer sb, long maximumFieldSize)
        {
            if (sb == null)
                throw new ArgumentNullException("sb");

            string identifier = sb.ReadString(FieldIdentifierLength, false, false);
            Lyrics3v2Field field = GetField(identifier);
            return field.ReadFieldInstance(sb, maximumFieldSize) ? field : null;
        }
예제 #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BitStream"/> class 
        /// based on the specified byte array with an expandable capacity, using <see cref="System.IO.MemoryStream"/> as backing data.
        /// </summary>
        /// <param name="buffer">The array of unsigned bytes from which to create the current stream.</param>
        public BitStream(byte[] buffer)
        {
            if (buffer == null)
                throw new ArgumentNullException("buffer");

            _sb = new StreamBuffer(buffer.Length);
            _sb.Write(buffer, 0, buffer.Length);
            _sb.Position -= buffer.Length;
        }
 ////------------------------------------------------------------------------------------------------------------------------------
 /// <inheritdoc />
 public override byte[] ToByteArray()
 {
     using (StreamBuffer sb = new StreamBuffer())
     {
         sb.Write(base.ToByteArray());
         sb.WriteBigEndianBytes(UnencodedConstantValue, SampleSize / 8);
         return sb.ToByteArray();
     }
 }
예제 #10
0
        ////------------------------------------------------------------------------------------------------------------------------------
        public static FlacResidual Read(StreamBuffer sb, int blockSize, int order)
        {
            FlacResidual residual = new FlacResidual { _values = sb.ReadByte() };
            int partitions = 1 << residual.PartitionOrder;
            residual.RicePartitions = new FlacRicePartition[partitions];
            for (int i = 0; i < partitions; i++)
                residual.RicePartitions[i] = FlacRicePartition.Read(sb, i, residual.PartitionOrder, order, blockSize, residual.CodingMethod);

            return residual;
        }
예제 #11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="XingHeader"/> class.
        /// </summary>
        /// <param name="firstFrame">The first frame.</param>
        /// <param name="firstFrameBuffer">The first frame buffer.</param>
        /// <param name="offset">The offset.</param>
        public XingHeader(MpaFrame firstFrame, StreamBuffer firstFrameBuffer, long offset)
            : base(firstFrame, firstFrameBuffer, offset, VbrHeaderType.Xing)
        {
            /*
            XING VBR-Header
            size    description
            4       'Xing' or 'Info'
            4       flags (indicates which fields are used)
            4       frames (optional)
            4       bytes (optional)
            100     toc (optional)
            4       a VBR quality indicator: 0=best 100=worst (optional)
            --------- +
            120 bytes
            *
            * NOTE: the frames (frameCount) in the XING header does not include its own frame.
            * So the total frames is actually XING framecount + 1
            */

            // name of the tag as found in the file
            Name = firstFrameBuffer.ReadString(4);

            // The flags indicate which fields are used in the XING header
            Flags = firstFrameBuffer.ReadBigEndianInt32();

            // Extract total frames in the file (XING header excludes it's own frame)
            if ((Flags & XingHeaderFlags.FrameCountFlag) != 0)
                FrameCount = firstFrameBuffer.ReadBigEndianInt32();

            // Extract size of the file, in bytes
            if ((Flags & XingHeaderFlags.FileSizeFlag) != 0)
                FileSize = firstFrameBuffer.ReadBigEndianInt32();

            // Extract TOC (Table of Contents) for more accurate seeking
            if ((Flags & XingHeaderFlags.TocFlag) != 0)
            {
                Toc = new int[100];
                for (int i = 0; i < 100; i++)
                    Toc[i] = firstFrameBuffer.ReadByte();
            }

            if ((Flags & XingHeaderFlags.VbrScaleFlag) != 0)
                Quality = firstFrameBuffer.ReadBigEndianInt32();

            // The LAME tag is always 120 bytes after the XING header - regardless of which fields are used
            LameTag = LameTag.FindTag(firstFrameBuffer, offset + 120);
        }
예제 #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="VbrHeader"/> class.
        /// </summary>
        /// <param name="firstFrame">The first frame.</param>
        /// <param name="firstFrameBuffer">The first frame buffer.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="headerType">Type of the header.</param>
        protected VbrHeader(MpaFrame firstFrame, StreamBuffer firstFrameBuffer, long offset, VbrHeaderType headerType)
        {
            if (firstFrame == null)
                throw new ArgumentNullException("firstFrame");

            if (firstFrameBuffer == null)
                throw new ArgumentNullException("firstFrameBuffer");

            ////if (headerType == null)
            ////throw new ArgumentNullException("headerType");

            // first frame contains the vbr header
            FirstFrame = firstFrame;

            // Offset of this header in the first frame.
            Offset = offset;

            // VBR Header type, currently only XING and VBRI
            HeaderType = headerType;
        }
예제 #13
0
        /// <summary>
        /// Finds the <see cref="VbriHeader"/> header within the <paramref name="firstFrame"/>.
        /// </summary>
        /// <param name="firstFrame">The first frame.</param>
        /// <returns>The VBRI header if found; otherwise, null.</returns>
        /// <remarks>
        /// The VBRI header is located exactly 32 bytes after the end of the first MPEG audio header in the file.
        /// It will compare the first 4 bytes against the <see cref="HeaderIndicator"/> 
        /// to see if the header contains a <see cref="VbriHeader"/> or not.
        /// </remarks>
        public static new VbriHeader FindHeader(MpaFrame firstFrame)
        {
            if (firstFrame == null)
                throw new ArgumentNullException("firstFrame");

            using (StreamBuffer buffer = new StreamBuffer())
            {
                byte[] data = firstFrame.ToByteArray();
                buffer.Write(data);

                // 32 bytes = data indicating silence
                const long Offset = MpaFrame.FrameHeaderSize + SilenceDataSize;
                buffer.Seek(Offset, SeekOrigin.Begin);
                string tagName = buffer.ReadString(4, false, false);
                return String.Compare(tagName, HeaderIndicator, StringComparison.OrdinalIgnoreCase) == 0
                           ? new VbriHeader(firstFrame, buffer, Offset)
                           : null;
            }
        }
예제 #14
0
        /// <inheritdoc/>
        public override byte[] ToByteArray()
        {
            using (StreamBuffer buf = new StreamBuffer())
            {
                buf.WriteString(Name);
                buf.WriteBigEndianInt32(Flags);

                if ((Flags & XingHeaderFlags.FrameCountFlag) != 0)
                    buf.WriteBigEndianInt32(FrameCount);

                if ((Flags & XingHeaderFlags.FileSizeFlag) != 0)
                    buf.WriteBigEndianInt32(FileSize);

                // Extract TOC (Table of Contents) for more accurate seeking
                if ((Flags & XingHeaderFlags.TocFlag) != 0)
                {
                    for (int i = 0; i < 100; i++)
                        buf.WriteByte((byte)Toc[i]);
                }

                if ((Flags & XingHeaderFlags.VbrScaleFlag) != 0)
                    buf.WriteBigEndianInt32(Quality);

                return buf.ToByteArray();
            }
        }
예제 #15
0
        /// <summary>
        /// Finds the <see cref="VbriHeader"/> header within the <paramref name="firstFrame"/>.
        /// </summary>
        /// <param name="firstFrame">The first frame.</param>
        /// <returns>The VBRI header if found; otherwise, null.</returns>
        /// <remarks>
        /// The XING header is located after the side information in Layer III in the first MPEG audio header in the file.
        /// It will compare the first 4 bytes against the <see cref="VbrHeaderIndicator"/> 
        /// to see if the header contains a <see cref="XingHeader"/> or not.
        /// </remarks>
        public static new XingHeader FindHeader(MpaFrame firstFrame)
        {
            if (firstFrame == null)
                throw new ArgumentNullException("firstFrame");

            long offset = MpaFrame.FrameHeaderSize + firstFrame.SideInfoSize;
            using (StreamBuffer buffer = new StreamBuffer())
            {
                byte[] data = firstFrame.ToByteArray();
                buffer.Write(data);

                buffer.Seek(offset, SeekOrigin.Begin);
                string tagName = buffer.ReadString(4, false, false);
                if ((String.Compare(tagName, VbrHeaderIndicator, StringComparison.OrdinalIgnoreCase) == 0)
                    || (String.Compare(tagName, CbrHeaderIndicator, StringComparison.OrdinalIgnoreCase) == 0))
                    return new XingHeader(firstFrame, buffer, offset);
            }
            return null;
        }
예제 #16
0
        /// <summary>
        /// Reads a <see cref="MpaFrame"/> from a <see cref="Stream"/>.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <returns>
        /// true if found; otherwise, null.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">Thrown if stream is null.</exception>
        private bool ReadFrame(StreamBuffer stream)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            StartOffset = stream.Position;

            if (!ParseHeader(stream))
                return false;

            int frameLength = FrameLength, audioDataLength = 0;
            if (frameLength > FrameHeaderSize)
                audioDataLength = frameLength - FrameHeaderSize;

            if (audioDataLength == 0)
                return true;

            if ((stream.Length - stream.Position) < audioDataLength)
            {
                // Truncated audio data.
                audioDataLength = (int)(stream.Length - stream.Position);
            }
            AudioData = new byte[audioDataLength];
            int bytesDataRead = stream.Read(AudioData, 0, audioDataLength);

            // Read the CRC
            // Create a buffer to read the CRC stored after the frame (2 bytes)
            if (bytesDataRead >= 2)
            {
                byte[] crc = new byte[2];
                Buffer.BlockCopy(AudioData, 0, crc, 0, 2);
                Crc = StreamBuffer.SwitchEndianness(BitConverter.ToInt16(crc, 0));
            }
            EndOffset = stream.Position;
            return true;
        }
예제 #17
0
        private static string ReadTextField(StreamBuffer sb)
        {
            if (sb == null)
                throw new ArgumentNullException("sb");

            int size = sb.ReadInt16();
            return sb.ReadString(size);
        }
예제 #18
0
        /// <inheritdoc />
        public byte[] ToByteArray()
        {
            using (StreamBuffer sb = new StreamBuffer())
            {
                sb.WriteString(Identifier);
                FlacStreamInfoMetadataBlock streamInfoMetadataBlock = StreamInfoMetadataBlocks.FirstOrDefault();
                if (streamInfoMetadataBlock != null)
                    sb.Write(streamInfoMetadataBlock.ToByteArray());

                foreach (FlacMetadataBlock metadataBlock in MetadataBlocks.Where(m => !ReferenceEquals(m, streamInfoMetadataBlock)))
                    sb.Write(metadataBlock.ToByteArray());

                foreach (FlacFrame frame in Frames)
                    sb.Write(frame.ToByteArray());

                return sb.ToByteArray();
            }
        }
예제 #19
0
        private static ApeHeader ReadHeader(StreamBuffer stream, long startHeaderPosition, long endHeaderPosition)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            stream.Position = startHeaderPosition;
            while (startHeaderPosition < endHeaderPosition)
            {
                int y = 0;
                while (stream.ReadByte() == TagIdentifierBytes[y++])
                {
                    startHeaderPosition++;
                    if (y != TagIdentifierBytes.Length)
                        continue;

                    ApeHeader hdr = new ApeHeader
                    {
                        Position = stream.Position - TagIdentifierBytes.Length,
                        Version = (ApeVersion)(stream.ReadLittleEndianInt32() / 1000),
                        Size = stream.ReadLittleEndianInt32(),
                        FrameCount = stream.ReadLittleEndianInt32(),
                        Flags = stream.ReadLittleEndianInt32(),
                        ReservedBytes = new byte[8]
                    };

                    stream.Read(hdr.ReservedBytes, 8);
                    if (IsValidTag(hdr))
                        return hdr;

                    startHeaderPosition -= ApeTag.HeaderSize;
                    stream.Position = startHeaderPosition + 1;
                    break;
                }
                startHeaderPosition++;
            }
            return null;
        }
예제 #20
0
        private static MusicMatchHeader ReadHeader(StreamBuffer stream, TagOrigin tagOrigin)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            long startPosition = stream.Position;
            long streamLength = stream.Length;
            if (streamLength < MusicMatchTag.HeaderSize)
                return null;

            if (tagOrigin == TagOrigin.Start)
            {
                // Look for a header at the current position
                long startPositionHeader = startPosition;
                long endPositionHeader = Math.Min(startPositionHeader + HeaderIdentifierBytes.Length, streamLength);
                MusicMatchHeader header = ReadHeaderFooter(stream, startPositionHeader, endPositionHeader, HeaderIdentifierBytes, TagOrigin.Start);
                if (header != null)
                    return header;

                // Look for a header past the current position
                startPositionHeader = endPositionHeader;
                endPositionHeader = Math.Min(startPositionHeader + HeaderIdentifierBytes.Length, streamLength);
                header = ReadHeaderFooter(stream, startPositionHeader, endPositionHeader, HeaderIdentifierBytes, TagOrigin.Start);
                if (header != null)
                    return header;
            }
            else if (tagOrigin == TagOrigin.End)
            {
                // Look for a footer before the current position
                long startPositionHeader = Math.Max(startPosition - HeaderIdentifierBytes.Length, 0);
                long endPositionHeader = Math.Min(startPositionHeader + HeaderIdentifierBytes.Length, streamLength);
                MusicMatchHeader footer = ReadHeaderFooter(stream, startPositionHeader, endPositionHeader, HeaderIdentifierBytes, TagOrigin.End);
                if (footer != null)
                    return footer;

                // Look for a footer before the previous start position
                startPositionHeader = Math.Max(startPositionHeader - HeaderIdentifierBytes.Length, 0);
                endPositionHeader = Math.Min(startPositionHeader + HeaderIdentifierBytes.Length, streamLength);
                footer = ReadHeaderFooter(stream, startPositionHeader, endPositionHeader, HeaderIdentifierBytes, TagOrigin.End);
                if (footer != null)
                    return footer;
            }
            return null;
        }
예제 #21
0
        ////------------------------------------------------------------------------------------------------------------------------------
        private bool ReadFrame(StreamBuffer sb)
        {
            if (sb == null)
                throw new ArgumentNullException("sb");

            StartOffset = sb.Position;

            if (!ReadHeader(sb))
                return false;

            for (int channel = 0; channel < Channels; channel++)
            {
                FlacSubFrame subFrame = FlacSubFrame.ReadFrame(sb, channel, this);
                _subFrames.Add(subFrame);
            }

            _crc16 = sb.ReadBigEndianInt16();
            int crc16 = Crc16.Calculate(new byte[0]);
            if (_crc16 != crc16)
                throw new InvalidDataException("Corrupt CRC16.");

            EndOffset = sb.Position;
            return true;
        }
예제 #22
0
        /// <summary>
        /// Reads the header.
        /// </summary>
        /// <param name="sb">The <see cref="StreamBuffer"/>.</param>
        /// <returns>
        /// true if the header is read and valid; otherwise, false.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">Thrown if <paramref name="sb"/> is null.</exception>
        private bool ReadHeader(StreamBuffer sb)
        {
            if (sb == null)
                throw new ArgumentNullException("sb");

            long startPosition = sb.Position;

            // Sync code '11111111111110'
            _header = sb.ReadBigEndianInt32();
            if (((_header >> 18) & FrameSync) != FrameSync)
                return false;

            /*
                Blocking strategy:
                    •0 : fixed-block size stream; frame header encodes the frame number
                    •1 : variable-block size stream; frame header encodes the sample number
            */
            long num = ReadBigEndianUtf8Int64(sb, out _sampleFrameNumberBytes);
            switch (BlockingStrategy)
            {
                case FlacBlockingStrategy.FixedBlocksize:
                    Samples = num;
                    FrameNumber = num
                                  *
                                  (FlacStream.StreamInfoMetadataBlocks.Any()
                                       ? FlacStream.StreamInfoMetadataBlocks.First().MinimumBlockSize
                                       : 1);
                    break;

                case FlacBlockingStrategy.VariableBlocksize:
                    Samples = num;
                    FrameNumber = -1;
                break;
            }

            /*
                Block size in inter-channel samples:
                    •0000 : reserved
                    •0001 : 192 samples
                    •0010-0101 : 576 * (2 ^ (n - 2)) samples, i.e. 576/1152/2304/4608
                    •0110 : get 8 bit (block size - 1) from end of header
                    •0111 : get 16 bit (block size - 1) from end of header
                    •1000-1111 : 256 * (2 ^ (n - 8)) samples, i.e. 256/512/1024/2048/4096/8192/16384/3276
            */
            int blockSize = (_header >> 12) & 0xF;
            switch (blockSize)
            {
                case 0x01:
                    BlockSize = 192;
                    break;

                case 0x02:
                case 0x03:
                case 0x04:
                case 0x05:
                    BlockSize = 576 << (blockSize - 2);
                    break;

                case 0x06:
                    BlockSize = sb.ReadByte() + 1;
                    break;

                case 0x07:
                    BlockSize = sb.ReadBigEndianInt16() + 1;
                    break;

                default:
                    BlockSize = 256 << (blockSize - 8);
                    break;
            }

            /*
                Sample rate:
                    •0000 : get from STREAMINFO metadata block
                    •0001 : 88.2kHz
                    •0010 : 176.4kHz
                    •0011 : 192kHz
                    •0100 : 8kHz
                    •0101 : 16kHz
                    •0110 : 22.05kHz
                    •0111 : 24kHz
                    •1000 : 32kHz
                    •1001 : 44.1kHz
                    •1010 : 48kHz
                    •1011 : 96kHz
                    •1100 : get 8 bit sample rate (in kHz) from end of header
                    •1101 : get 16 bit sample rate (in Hz) from end of header
                    •1110 : get 16 bit sample rate (in tens of Hz) from end of header
                    •1111 : invalid, to prevent sync-fooling string of 1s
            */
            int samplingRate = (_header >> 8) & 0xF;
            if (samplingRate == 0x00)
            {
                SamplingRate = FlacStream.StreamInfoMetadataBlocks.Any()
                                   ? FlacStream.StreamInfoMetadataBlocks.First().SampleRate
                                   : 0;
            }
            else if (samplingRate <= 0x0B)
            {
                SamplingRate = SampleRates[samplingRate];
            }
            else
            {
                switch (samplingRate)
                {
                    case 0x0C:
                        // Sample rate in kHz
                        SamplingRate = sb.ReadByte() * 1000;
                        break;

                    case 0x0D:
                        // Sample rate in Hz
                        SamplingRate = sb.ReadBigEndianInt16();
                        break;

                    case 0x0E:
                        // Sample rate in 10s of Hz
                        SamplingRate = sb.ReadBigEndianInt16() * 10;
                        break;
                }
            }

            /*
                Channel assignment
                    •0000-0111 : (number of independent channels)-1. Where defined, the channel order follows SMPTE/ITU-R recommendations.
                    The assignments are as follows:
                        ◦1 channel: mono
                        ◦2 channels: left, right
                        ◦3 channels: left, right, center
                        ◦4 channels: front left, front right, back left, back right
                        ◦5 channels: front left, front right, front center, back/surround left, back/surround right
                        ◦6 channels: front left, front right, front center, LFE, back/surround left, back/surround right
                        ◦7 channels: front left, front right, front center, LFE, back center, side left, side right
                        ◦8 channels: front left, front right, front center, LFE, back left, back right, side left, side right
                    •1000 : left/side stereo: channel 0 is the left channel, channel 1 is the side(difference) channel
                    •1001 : right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel
                    •1010 : mid/side stereo: channel 0 is the mid(average) channel, channel 1 is the side(difference) channel
                    •1011-1111 : reserved
            */
            int channelAssignment = (_header >> 4) & 0xF;
            if (channelAssignment < 0x08)
            {
                ChannelAssignment = FlacChannelAssignment.Independent;
                Channels = channelAssignment + 1;
            }
            else
            {
                Channels = 2;
                switch (channelAssignment)
                {
                    case 0x08:
                        ChannelAssignment = FlacChannelAssignment.LeftSide;
                        break;

                    case 0x09:
                        ChannelAssignment = FlacChannelAssignment.RightSide;
                        break;

                    case 0x0A:
                        ChannelAssignment = FlacChannelAssignment.MidSide;
                        break;
                }
            }

            /*
                Sample size in bits:
                    •000 : get from STREAMINFO metadata block
                    •001 : 8 bits per sample
                    •010 : 12 bits per sample
                    •011 : reserved
                    •100 : 16 bits per sample
                    •101 : 20 bits per sample
                    •110 : 24 bits per sample
                    •111 : reserved
            */
            int sampleSize = (_header >> 0x01) & 0x07;
            SampleSize = (sampleSize == 0x00)
                             ? (FlacStream.StreamInfoMetadataBlocks.Any()
                                    ? FlacStream.StreamInfoMetadataBlocks.First().BitsPerSample
                                    : 0)
                             : SampleSizes[sampleSize];

            _crc8 = sb.ReadByte();

            long endPosition = sb.Position;
            long length = endPosition - startPosition;
            byte[] crcBytes = new byte[length];
            sb.Position -= length;
            sb.Read(crcBytes, (int)length);
            byte crc8 = Crc8.Calculate(crcBytes);
            if (_crc8 != crc8)
                throw new InvalidDataException("Corrupt CRC8.");

            return true;
        }
예제 #23
0
        ////------------------------------------------------------------------------------------------------------------------------------
        private static long ReadBigEndianUtf8Int64(StreamBuffer sb, out byte[] utf8Bytes)
        {
            //// Decoded long range              Coded value
            //// 0000 0000 ・00 0000 007F   0xxxxxxx
            //// 0000 0080 ・00 0000 07FF   110xxxxx 10xxxxxx
            //// 0000 0800 ・00 0000 FFFF    1110xxxx 10xxxxxx 10xxxxxx
            //// 0001 0000 ・00 001F FFFF    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
            //// 0020 0000 ・00 03FF FFFF     111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
            //// 0400 0000 ・00 7FFF FFFF     1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
            //// 8000 0000 ・0F FFFF FFFF     11111110 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
            // Where xxx represent the bits in the uncoded value, in the same order.
            const int ByteCountMask = 0x80;     // 10000000
            const int ByteMask = 0x3F;               // 00111111
            int byteCount = 1;
            long value = sb.ReadByte();
            if (value > ByteCountMask)
            {
                int bytes = 0;
                while (((value << bytes) & ByteCountMask) == ByteCountMask)
                    bytes++;

                value &= ByteMask >> (bytes - 1);
                for (int i = bytes - 1; i > 0; i--)
                    value = (value << (6 * i)) | ((long)sb.ReadByte() & ByteMask);

                byteCount += bytes - 1;
            }
            sb.Position -= byteCount;
            utf8Bytes = new byte[byteCount];
            sb.Read(utf8Bytes, byteCount);
            return value;
        }
예제 #24
0
        /// <inheritdoc/>
        public override byte[] ToByteArray()
        {
            using (StreamBuffer buffer = new StreamBuffer())
            {
                buffer.WriteString(Name);
                buffer.WriteBigEndianInt16(Version);
                buffer.WriteBigEndianInt16((short)_delay);
                buffer.WriteBigEndianInt16((short)Quality);
                buffer.WriteBigEndianInt32(FileSize);
                buffer.WriteBigEndianInt32(FrameCount);
                buffer.WriteBigEndianInt16(TableEntries);
                buffer.WriteBigEndianInt16(TableScale);
                buffer.WriteBigEndianInt16(TableEntrySize);
                buffer.WriteBigEndianInt16(FramesPerTableEntry);
                for (int i = 0; i <= TableEntries; i++)
                    buffer.WriteBigEndianBytes(Toc[i] / TableScale, TableEntrySize);

                return buffer.ToByteArray();
            }
        }
        ////------------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Reads the specified stream buffer.
        /// </summary>
        /// <param name="sb">The stream buffer.</param>
        /// <param name="sampeSize">Size of the sample.</param>
        /// <param name="blockSize">Size of the block.</param>
        protected override void Read(StreamBuffer sb, int sampeSize, int blockSize)
        {
            UnencodedWarmUpSamples = new int[Order];
            for (int i = 0; i < Order; i++)
                UnencodedWarmUpSamples[i] = sb.ReadBigEndianInt32();

            int other = sb.ReadBigEndianInt16();
            QuantizedCoefficientsPrecision = (other & 0xF) + 1;
            QuantizedCoefficientShift = (other >> 4) & 0x1F;

            UnencodedPredictorCoefficients = new int[Order];
            for (int i = 0; i < Order; i++)
                UnencodedPredictorCoefficients[i] = sb.ReadBigEndianInt32();

            Residual = FlacResidual.Read(sb, blockSize, Order);
        }
예제 #26
0
 /// <summary>
 /// Returns the frame in a byte array.
 /// </summary>
 /// <returns>The frame in a byte array.</returns>
 public byte[] ToByteArray()
 {
     using (StreamBuffer buffer = new StreamBuffer())
     {
         buffer.Write(_header);
         buffer.Write(AudioData);
         return buffer.ToByteArray();
     }
 }
예제 #27
0
        /// <summary>
        /// Returns the frame in a byte array.
        /// </summary>
        /// <returns>The frame in a byte array.</returns>
        public byte[] ToByteArray()
        {
            using (StreamBuffer sb = new StreamBuffer())
            {
                sb.WriteBigEndianInt32(_header);
                sb.Write(_sampleFrameNumberBytes);
                int blockSize = (_header >> 12) & 0xF;
                switch (blockSize)
                {
                    case 0x06:
                        sb.WriteByte((byte)(BlockSize - 1));
                        break;

                    case 0x07:
                        sb.WriteBigEndianInt16((short)(BlockSize - 1));
                        break;
                }
                int samplingRate = (_header >> 8) & 0xF;
                switch (samplingRate)
                {
                    case 0x0C:
                        sb.WriteByte((byte)(SamplingRate / 1000));
                        break;

                    case 0x0D:
                        sb.WriteBigEndianInt16((short)SamplingRate);
                        break;

                    case 0x0E:
                        sb.WriteBigEndianInt16((short)(SamplingRate / 10));
                        break;
                }
                sb.WriteByte((byte)_crc8);

                foreach (FlacSubFrame subFrame in SubFrames)
                    sb.Write(subFrame.ToByteArray());

                sb.WriteBigEndianInt16((short)_crc16);
                return sb.ToByteArray();
            }
        }
예제 #28
0
        private static MusicMatchHeader ReadHeaderFooter(StreamBuffer stream, long startHeaderPosition, long endHeaderPosition, IList<byte> identifierBytes, TagOrigin tagOrigin)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            stream.Position = startHeaderPosition;
            while (startHeaderPosition < endHeaderPosition)
            {
                int y = 0;
                while (stream.ReadByte() == identifierBytes[y++])
                {
                    startHeaderPosition++;
                    if (y != identifierBytes.Count)
                        continue;

                    if (tagOrigin == TagOrigin.Start)
                    {
                        MusicMatchHeader header = new MusicMatchHeader
                        {
                            Position = stream.Position - identifierBytes.Count,
                            Padding1 = new byte[2],
                            Padding2 = new byte[2],
                            Padding3 = new byte[2],
                            SpacePadding2 = new byte[226]
                        };

                        // 0x00 0x00 Padding
                        stream.Read(header.Padding1, header.Padding1.Length);

                        // <8-byte numerical ASCII string>
                        header.XingEncoderVersion = stream.ReadString(8);

                        // 0x00 0x00 Padding
                        stream.Read(header.Padding2, header.Padding2.Length);

                        // Xing encoder version <8-byte numerical ASCII string>
                        header.MusicMatchVersion = stream.ReadString(8);

                        // 0x00 0x00 Padding
                        stream.Read(header.Padding3, header.Padding3.Length);

                        // Space padding <226 * 0x20 >
                        stream.Read(header.SpacePadding2, header.SpacePadding2.Length);

                        ValidateHeader(header, null);
                        return header;
                    }

                    if (tagOrigin == TagOrigin.End)
                    {
                        MusicMatchHeader footer = new MusicMatchHeader
                        {
                            Position = stream.Position - identifierBytes.Count,
                            SpacePadding1 = new byte[13],
                            SpacePadding2 = new byte[12]
                        };

                        // Space padding <13 * 0x20>
                        stream.Read(footer.SpacePadding1, 13);

                        // version <4-byte numerical ASCII string> e.g. 3.05
                        footer.MusicMatchVersion = stream.ReadString(4);

                        // Space padding <12 * 0x20>
                        stream.Read(footer.SpacePadding2, 12);

                        ValidateHeader(null, footer);
                        return footer;
                    }
                }
                startHeaderPosition++;
            }
            return null;
        }
예제 #29
0
 ////------------------------------------------------------------------------------------------------------------------------------
 /// <summary>
 /// Reads the specified stream buffer.
 /// </summary>
 /// <param name="sb">The stream buffer.</param>
 /// <param name="sampeSize">Size of the sample.</param>
 /// <param name="blockSize">Size of the block.</param>
 protected override void Read(StreamBuffer sb, int sampeSize, int blockSize)
 {
     UnencodedSubblocks = new int[blockSize];
     for (int i = 0; i < blockSize; i++)
         UnencodedSubblocks[i] = sb.ReadBigEndianInt32();
 }
예제 #30
0
        ////------------------------------------------------------------------------------------------------------------------------------
        private static ApeHeader ReadHeader(StreamBuffer stream, TagOrigin tagOrigin)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            long startPosition = stream.Position;
            long streamLength = stream.Length;
            if (streamLength < ApeTag.HeaderSize)
                return null;

            // Look for a header at the current position
            if (tagOrigin == TagOrigin.Start)
            {
                // Look for a header at the current position
                long startPositionHeader = startPosition;
                long endPositionHeader = Math.Min(startPositionHeader + ApeTag.HeaderSize, streamLength);
                ApeHeader hdr = ReadHeader(stream, startPositionHeader, endPositionHeader);
                if (hdr != null)
                    return hdr;

                // Look for a header past the current position
                startPositionHeader = endPositionHeader;
                endPositionHeader = Math.Min(startPositionHeader + ApeTag.HeaderSize, streamLength);
                hdr = ReadHeader(stream, startPositionHeader, endPositionHeader);
                if (hdr != null)
                    return hdr;
            }
            else if (tagOrigin == TagOrigin.End)
            {
                // Look for a footer before the current position
                long startPositionHeader = Math.Max(startPosition - ApeTag.FooterSize, 0);
                long endPositionHeader = Math.Min(startPositionHeader + ApeTag.FooterSize, streamLength);
                ApeHeader hdr = ReadHeader(stream, startPositionHeader, endPositionHeader);
                if (hdr != null)
                    return hdr;

                // Look for a footer before the previous start position
                startPositionHeader = Math.Max(startPositionHeader - ApeTag.FooterSize, 0);
                endPositionHeader = Math.Min(startPositionHeader + ApeTag.FooterSize, streamLength);
                hdr = ReadHeader(stream, startPositionHeader, endPositionHeader);
                if (hdr != null)
                    return hdr;
            }
            return null;
        }