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;
        }
예제 #2
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;
        }
예제 #3
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;
        }
예제 #4
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;
        }
예제 #5
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;
        }
예제 #6
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;
        }
예제 #7
0
        private bool ReadItem(ApeVersion version, int valueSize, StreamBuffer stream, long maximumItemSize)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            // Check if the item size indicated is really the size of the item.
            // Some files just aren't... properly written.
            byte[] data = new byte[valueSize];
            int dataBytesRead = stream.Read(data, valueSize);
            int bytesLeftInStream = (int)(maximumItemSize - dataBytesRead);
            if ((valueSize > 0) && (bytesLeftInStream > 0) && (dataBytesRead >= valueSize))
            {
                using (StreamBuffer dataBuffer = new StreamBuffer(data))
                {
                    // See if there's a next item.
                    // Try to find the start of the next item.
                    long startPositionNextItem = stream.Position;
                    long bytesUntilNextItem = GetBytesUntilNextItem(version, stream, maximumItemSize - valueSize);
                    stream.Position = startPositionNextItem;

                    // Seems that the size indicated by the item is not the total size of the item; read the extra bytes here.
                    if (bytesUntilNextItem > 0)
                    {
                        data = new byte[bytesUntilNextItem];
                        stream.Read(data, data.Length);
                        dataBuffer.Write(data);
                    }
                    data = dataBuffer.ToByteArray();
                }
            }
            Data = data;
            return true;
        }
예제 #8
0
        ////------------------------------------------------------------------------------------------------------------------------------
        private static FlacMetadataBlock ReadBlock(StreamBuffer stream)
        {
            int flags = stream.ReadByte();

            // Length
            int length = stream.ReadBigEndianInt(3);
            if (length >= stream.Length)
                return null;

            byte[] data = new byte[length];
            stream.Read(data, length);

            FlacMetadataBlock metadataBlock;
            FlacMetadataBlockType blockType = (FlacMetadataBlockType)(flags & HeaderFlags.BlockType);
            switch (blockType)
            {
                case FlacMetadataBlockType.Padding:
                    metadataBlock = new FlacPaddingMetadataBlock();
                    break;

                case FlacMetadataBlockType.Application:
                    metadataBlock = new FlacApplicationMetadataBlock();
                    break;

                case FlacMetadataBlockType.StreamInfo:
                    metadataBlock = new FlacStreamInfoMetadataBlock();
                    break;

                case FlacMetadataBlockType.SeekTable:
                    metadataBlock = new FlacSeekTableMetadataBlock();
                    break;

                case FlacMetadataBlockType.VorbisComment:
                    metadataBlock = new FlacVorbisCommentsMetadataBlock();
                    break;

                case FlacMetadataBlockType.CueSheet:
                    metadataBlock = new FlacCueSheetMetadataBlock();
                    break;

                case FlacMetadataBlockType.Picture:
                    metadataBlock = new FlacPictureMetadataBlock();
                    break;

                default:
                    metadataBlock = new FlacMetadataBlock();
                    break;
            }
            metadataBlock.Flags = flags;
            metadataBlock.Data = data;
            return metadataBlock;
        }
예제 #9
0
            /// <summary>
            /// Reads the <see cref="Id3v2FrameEncodingType"/> from the stream.
            /// </summary>
            /// <param name="streamBuffer">The stream buffer.</param>
            /// <returns>
            /// The <see cref="Id3v2FrameEncodingType"/>.
            /// </returns>
            /// <remarks>
            /// Since the encoding type is first read from the stream, the position should be set to the byte containing the encoding type.
            /// If the encoding type is <see cref="Id3v2FrameEncodingType.UTF16LittleEndian"/>, 
            /// it will try to read the byte order marker from the stream 
            /// to see if the encoding type is <see cref="Id3v2FrameEncodingType.UTF16BigEndian"/>.
            /// If no byte order marker is found or if the byte order marker is not recognized, 
            /// it will return <see cref="Id3v2FrameEncodingType.UTF16LittleEndian"/> as default encoding.
            /// <para />
            /// The position of the stream will not be modified.
            /// </remarks>
            public static Id3v2FrameEncodingType ReadEncodingTypeFromStream(StreamBuffer streamBuffer)
            {
                int encodingByte = streamBuffer.ReadByte();
                if ((encodingByte == -1) || !IsValidEncodingType(encodingByte))
                    return Id3v2FrameEncodingType.Default;

                if (encodingByte > (byte)Id3v2FrameEncodingType.UTF16LittleEndian)
                    encodingByte += 1;

                // Cast the encoding type.
                Id3v2FrameEncodingType encodingType = (Id3v2FrameEncodingType)encodingByte;

                // If it's not little endian, then we don't need to figure out if it's little or big; return here.
                if (encodingType != Id3v2FrameEncodingType.UTF16LittleEndian)
                    return encodingType;

                // See which byte order the frame encoding is.
                byte[] byteOrderMarker = new byte[2];

                // Not enough bytes available; probably little endian then.
                if (streamBuffer.Read(byteOrderMarker, 2, false) < 2)
                    return Id3v2FrameEncodingType.UTF16LittleEndian;

                // Little endian byte order marker?
                if (((byteOrderMarker[0] == 0xFF) && (byteOrderMarker[1] == 0xFE))
                    || ((byteOrderMarker[0] == 0x00) && (byteOrderMarker[1] == 0x00)))
                    return Id3v2FrameEncodingType.UTF16LittleEndian;

                // Big endian byte order marker?
                if ((byteOrderMarker[0] == 0xFE) && (byteOrderMarker[1] == 0xFF))
                    return Id3v2FrameEncodingType.UTF16BigEndian;

                // Default to little endian.
                return Id3v2FrameEncodingType.UTF16LittleEndian;
            }
예제 #10
0
 public void ReadTestMovePositionTrue()
 {
     byte[] msBuffer = { 0x90, 0x10, 0xAA, 0x02, 0xFF };
     StreamBuffer target = new StreamBuffer(msBuffer);
     byte[] buffer = new byte[msBuffer.Length];
     target.Read(buffer, msBuffer.Length);
     Assert.IsTrue(target.Position == msBuffer.Length);
 }
예제 #11
0
 public void ReadTestByteArraysAreEqualUsingMemoryStream()
 {
     byte[] msBuffer = { 0x90, 0x10, 0xAA, 0x02, 0xFF };
     MemoryStream ms = new MemoryStream(msBuffer);
     StreamBuffer target = new StreamBuffer(ms);
     byte[] buffer = new byte[msBuffer.Length];
     target.Read(buffer, 0, msBuffer.Length);
     Assert.IsTrue(msBuffer.SequenceEqual(buffer));
 }
예제 #12
0
 public void ReadTestAmountOfBytesReadUsingMemoryStream()
 {
     byte[] msBuffer = { 0x90, 0x10, 0xAA, 0x02, 0xFF };
     MemoryStream ms = new MemoryStream(msBuffer);
     StreamBuffer target = new StreamBuffer(ms);
     byte[] buffer = new byte[msBuffer.Length];
     int expected = msBuffer.Length;
     int actual = target.Read(buffer, 0, expected);
     Assert.AreEqual(expected, actual);
 }