Beispiel #1
0
        public void StreamUtils_BE24UintConverters()
        {
            uint intValue = 0x00873529;

            Assert.AreEqual((uint)0x00FFFFFF, StreamUtils.DecodeBEUInt24(new byte[3] {
                0xFF, 0xFF, 0xFF
            }));

            byte[] byteValue = StreamUtils.EncodeBEUInt24(intValue);
            Assert.AreEqual(intValue, StreamUtils.DecodeBEUInt24(byteValue));
        }
Beispiel #2
0
        // TODO : support for CUESHEET block
        public bool Read(BinaryReader source, ReadTagParams readTagParams)
        {
            bool result = false;

            if (readTagParams.ReadTag && null == vorbisTag)
            {
                vorbisTag = new VorbisTag(false, false, false, false);
            }

            initialPaddingOffset = -1;
            initialPaddingSize   = 0;

            byte[] aMetaDataBlockHeader;
            long   position;
            uint   blockLength;
            byte   blockType;
            int    blockIndex;
            bool   isLast;
            bool   paddingFound   = false;
            long   blockEndOffset = -1;

            readHeader(source);

            // Process data if loaded and header valid
            if (header.IsValid())
            {
                int channels = (header.Info[12] >> 1) & 0x7;
                switch (channels)
                {
                case 0b0000: channelsArrangement = MONO; break;

                case 0b0001: channelsArrangement = STEREO; break;

                case 0b0010: channelsArrangement = ISO_3_0_0; break;

                case 0b0011: channelsArrangement = QUAD; break;

                case 0b0100: channelsArrangement = ISO_3_2_0; break;

                case 0b0101: channelsArrangement = ISO_3_2_1; break;

                case 0b0110: channelsArrangement = LRCLFECrLssRss; break;

                case 0b0111: channelsArrangement = LRCLFELrRrLssRss; break;

                case 0b1000: channelsArrangement = JOINT_STEREO_LEFT_SIDE; break;

                case 0b1001: channelsArrangement = JOINT_STEREO_RIGHT_SIDE; break;

                case 0b1010: channelsArrangement = JOINT_STEREO_MID_SIDE; break;

                default: channelsArrangement = UNKNOWN; break;
                }

                sampleRate    = header.Info[10] << 12 | header.Info[11] << 4 | header.Info[12] >> 4;
                bitsPerSample = (byte)(((header.Info[12] & 1) << 4) | (header.Info[13] >> 4) + 1);
                samples       = header.Info[14] << 24 | header.Info[15] << 16 | header.Info[16] << 8 | header.Info[17];

                if (0 == (header.MetaDataBlockHeader[1] & FLAG_LAST_METADATA_BLOCK)) // metadata block exists
                {
                    blockIndex = 0;
                    vorbisTag.Clear();
                    if (readTagParams.PrepareForWriting)
                    {
                        if (null == zones)
                        {
                            zones = new List <Zone>();
                        }
                        else
                        {
                            zones.Clear();
                        }
                        blockEndOffset = source.BaseStream.Position;
                    }

                    do // Read all metadata blocks
                    {
                        aMetaDataBlockHeader = source.ReadBytes(4);
                        isLast = (aMetaDataBlockHeader[0] & FLAG_LAST_METADATA_BLOCK) > 0; // last flag ( first bit == 1 )

                        blockIndex++;
                        blockLength = StreamUtils.DecodeBEUInt24(aMetaDataBlockHeader, 1);

                        blockType = (byte)(aMetaDataBlockHeader[0] & 0x7F); // decode metablock type
                        position  = source.BaseStream.Position;

                        if (blockType == META_VORBIS_COMMENT) // Vorbis metadata
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(blockType + "", position - 4, (int)blockLength + 4, new byte[0], blockType));
                            }
                            vorbisTag.Read(source, readTagParams);
                        }
                        else if ((blockType == META_PADDING) && (!paddingFound))  // Padding block (skip any other padding block)
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(PADDING_ZONE_NAME, position - 4, (int)blockLength + 4, new byte[0], blockType));
                            }
                            initialPaddingSize   = blockLength;
                            initialPaddingOffset = position;
                            paddingFound         = true;
                            source.BaseStream.Seek(blockLength, SeekOrigin.Current);
                        }
                        else if (blockType == META_PICTURE) // Picture (NB: as per FLAC specs, pictures must be embedded at the FLAC level, not in the VorbisComment !)
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(blockType + "", position - 4, (int)blockLength + 4, new byte[0], blockType));
                            }
                            vorbisTag.ReadPicture(source.BaseStream, readTagParams);
                        }
                        else // Unhandled block; needs to be zoned anyway to be able to manage the 'isLast' flag at write-time
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(blockType + "", position - 4, (int)blockLength + 4, new byte[0], blockType));
                            }
                        }


                        if (blockType < 7)
                        {
                            source.BaseStream.Seek(position + blockLength, SeekOrigin.Begin);
                            blockEndOffset = position + blockLength;
                        }
                        else
                        {
                            // Abnormal header : incorrect size and/or misplaced last-metadata-block flag
                            break;
                        }
                    }while (!isLast);

                    if (readTagParams.PrepareForWriting)
                    {
                        bool vorbisTagFound = false;
                        bool pictureFound   = false;

                        foreach (Zone zone in zones)
                        {
                            if (zone.Flag == META_PICTURE)
                            {
                                pictureFound = true;
                            }
                            else if (zone.Flag == META_VORBIS_COMMENT)
                            {
                                vorbisTagFound = true;
                            }
                        }

                        if (!vorbisTagFound)
                        {
                            zones.Add(new Zone(META_VORBIS_COMMENT + "", blockEndOffset, 0, new byte[0], META_VORBIS_COMMENT));
                        }
                        if (!pictureFound)
                        {
                            zones.Add(new Zone(META_PICTURE + "", blockEndOffset, 0, new byte[0], META_PICTURE));
                        }
                        // Padding must be the last block for it to correctly absorb size variations of the other blocks
                        if (!paddingFound && Settings.AddNewPadding)
                        {
                            zones.Add(new Zone(PADDING_ZONE_NAME, blockEndOffset, 0, new byte[0], META_PADDING));
                        }
                    }
                }
            }

            if (isValid())
            {
                audioOffset = source.BaseStream.Position;  // we need that to calculate the bitrate
                result      = true;
            }

            return(result);
        }
        public void StreamUtils_Exceptions()
        {
            Assert.IsFalse(StreamUtils.ArrEqualsArr(new byte[1], new byte[2]));
            Assert.IsFalse(StreamUtils.StringEqualsArr(".", new char[2]));

            try
            {
                StreamUtils.DecodeBEUInt16(new byte[1]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.DecodeUInt16(new byte[1]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.DecodeInt16(new byte[1]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.DecodeBEInt16(new byte[1]);
                Assert.Fail();
            }
            catch { }


            try
            {
                StreamUtils.DecodeBEInt24(new byte[2]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.DecodeBEUInt24(new byte[2]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.EncodeBEUInt24(0x01FFFFFF);
                Assert.Fail();
            }
            catch { }


            try
            {
                StreamUtils.DecodeBEUInt32(new byte[3]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.DecodeUInt32(new byte[3]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.DecodeBEInt32(new byte[3]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.DecodeInt32(new byte[3]);
                Assert.Fail();
            }
            catch { }


            try
            {
                StreamUtils.DecodeUInt64(new byte[7]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.DecodeBEInt64(new byte[7]);
                Assert.Fail();
            }
            catch { }


            try
            {
                StreamUtils.DecodeSynchSafeInt(new byte[6]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.DecodeSynchSafeInt32(new byte[6]);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.EncodeSynchSafeInt(1, 0);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.EncodeSynchSafeInt(1, 6);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.ReadBits(new BinaryReader(new MemoryStream()), 0, 0);
                Assert.Fail();
            }
            catch { }

            try
            {
                StreamUtils.ReadBits(new BinaryReader(new MemoryStream()), 0, 33);
                Assert.Fail();
            }
            catch { }
        }
Beispiel #4
0
        public Boolean Read(BinaryReader source, ReadTagParams readTagParams)
        {
            var result = false;

            if (readTagParams.ReadTag && null == vorbisTag)
            {
                vorbisTag = new VorbisTag(false, false, false);
            }

            Byte[]  aMetaDataBlockHeader;
            Int64   position;
            UInt32  blockLength;
            Int32   blockType;
            Int32   blockIndex;
            Boolean isLast;
            var     bPaddingFound = false;

            readHeader(source);

            // Process data if loaded and header valid
            if (header.IsValid())
            {
                channels      = (Byte)(((header.Info[12] >> 1) & 0x7) + 1);
                sampleRate    = (header.Info[10] << 12 | header.Info[11] << 4 | header.Info[12] >> 4);
                bitsPerSample = (Byte)(((header.Info[12] & 1) << 4) | (header.Info[13] >> 4) + 1);
                samples       = (header.Info[14] << 24 | header.Info[15] << 16 | header.Info[16] << 8 | header.Info[17]);

                if (0 == (header.MetaDataBlockHeader[1] & 0x80))                   // metadata block exists
                {
                    blockIndex = 0;
                    if (readTagParams.PrepareForWriting)
                    {
                        if (null == zones)
                        {
                            zones = new List <Zone>();
                        }
                        else
                        {
                            zones.Clear();
                        }
                        firstBlockPosition = source.BaseStream.Position;
                    }

                    do // read more metadata blocks if available
                    {
                        aMetaDataBlockHeader = source.ReadBytes(4);
                        isLast = ((aMetaDataBlockHeader[0] & 0x80) > 0); // last flag ( first bit == 1 )

                        blockIndex++;
                        blockLength = StreamUtils.DecodeBEUInt24(aMetaDataBlockHeader, 1);

                        blockType = (aMetaDataBlockHeader[0] & 0x7F);                         // decode metablock type
                        position  = source.BaseStream.Position;

                        if (blockType == META_VORBIS_COMMENT)                           // Vorbis metadata
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(ZONE_VORBISTAG, position - 4, (Int32)blockLength + 4, new Byte[0], (Byte)(isLast ? 1 : 0)));
                            }
                            vorbisTag.Read(source, readTagParams);
                        }
                        else if ((blockType == META_PADDING) && (!bPaddingFound))                            // Padding block
                        {
                            padding       = blockLength;                                                     // if we find more skip & put them in metablock array
                            paddingLast   = ((aMetaDataBlockHeader[0] & 0x80) != 0);
                            paddingIndex  = blockIndex;
                            bPaddingFound = true;
                            source.BaseStream.Seek(padding, SeekOrigin.Current); // advance into file till next block or audio data start
                        }
                        else if (blockType == META_PICTURE)
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(ZONE_PICTURE, position - 4, (Int32)blockLength + 4, new Byte[0], (Byte)(isLast ? 1 : 0)));
                            }
                            vorbisTag.ReadPicture(source.BaseStream, readTagParams);
                        }
                        // TODO : support for CUESHEET block

                        if (blockType < 7)
                        {
                            source.BaseStream.Seek(position + blockLength, SeekOrigin.Begin);
                        }
                        else
                        {
                            // Abnormal header : incorrect size and/or misplaced last-metadata-block flag
                            break;
                        }
                    }while (!isLast);

                    if (readTagParams.PrepareForWriting)
                    {
                        var vorbisTagFound = false;
                        var pictureFound   = false;

                        foreach (var zone in zones)
                        {
                            if (zone.Name.Equals(ZONE_PICTURE))
                            {
                                pictureFound = true;
                            }
                            else if (zone.Name.Equals(ZONE_VORBISTAG))
                            {
                                vorbisTagFound = true;
                            }
                        }

                        if (!vorbisTagFound)
                        {
                            zones.Add(new Zone(ZONE_VORBISTAG, firstBlockPosition, 0, new Byte[0]));
                        }
                        if (!pictureFound)
                        {
                            zones.Add(new Zone(ZONE_PICTURE, firstBlockPosition, 0, new Byte[0]));
                        }
                    }
                }
            }

            if (isValid())
            {
                audioOffset = source.BaseStream.Position;  // we need that to rebuild the file if nedeed
                result      = true;
            }

            return(result);
        }
Beispiel #5
0
        public bool Read(BinaryReader source, ReadTagParams readTagParams)
        {
            bool result = false;

            if (readTagParams.ReadTag && null == vorbisTag)
            {
                vorbisTag = new VorbisTag(false, false, false);
            }

            byte[] aMetaDataBlockHeader;
            long   position;
            uint   blockLength;
            int    blockType;
            int    blockIndex;
            bool   isLast;
            bool   bPaddingFound = false;

            readHeader(source);

            // Process data if loaded and header valid
            if (header.IsValid())
            {
                int channels = (header.Info[12] >> 1) & 0x7;
                switch (channels)
                {
                case 0b0000: channelsArrangement = MONO; break;

                case 0b0001: channelsArrangement = STEREO; break;

                case 0b0010: channelsArrangement = ISO_3_0_0; break;

                case 0b0011: channelsArrangement = QUAD; break;

                case 0b0100: channelsArrangement = ISO_3_2_0; break;

                case 0b0101: channelsArrangement = ISO_3_2_1; break;

                case 0b0110: channelsArrangement = LRCLFECrLssRss; break;

                case 0b0111: channelsArrangement = LRCLFELrRrLssRss; break;

                case 0b1000: channelsArrangement = JOINT_STEREO_LEFT_SIDE; break;

                case 0b1001: channelsArrangement = JOINT_STEREO_RIGHT_SIDE; break;

                case 0b1010: channelsArrangement = JOINT_STEREO_MID_SIDE; break;

                default: channelsArrangement = UNKNOWN; break;
                }

                sampleRate    = (header.Info[10] << 12 | header.Info[11] << 4 | header.Info[12] >> 4);
                bitsPerSample = (byte)(((header.Info[12] & 1) << 4) | (header.Info[13] >> 4) + 1);
                samples       = (header.Info[14] << 24 | header.Info[15] << 16 | header.Info[16] << 8 | header.Info[17]);

                if (0 == (header.MetaDataBlockHeader[1] & 0x80)) // metadata block exists
                {
                    blockIndex = 0;
                    vorbisTag.Clear();
                    if (readTagParams.PrepareForWriting)
                    {
                        if (null == zones)
                        {
                            zones = new List <Zone>();
                        }
                        else
                        {
                            zones.Clear();
                        }
                        firstBlockPosition = source.BaseStream.Position;
                    }

                    do // read more metadata blocks if available
                    {
                        aMetaDataBlockHeader = source.ReadBytes(4);
                        isLast = ((aMetaDataBlockHeader[0] & 0x80) > 0); // last flag ( first bit == 1 )

                        blockIndex++;
                        blockLength = StreamUtils.DecodeBEUInt24(aMetaDataBlockHeader, 1);

                        blockType = (aMetaDataBlockHeader[0] & 0x7F); // decode metablock type
                        position  = source.BaseStream.Position;

                        if (blockType == META_VORBIS_COMMENT) // Vorbis metadata
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(ZONE_VORBISTAG, position - 4, (int)blockLength + 4, new byte[0], (byte)(isLast ? 1 : 0)));
                            }
                            vorbisTag.Read(source, readTagParams);
                        }
                        else if ((blockType == META_PADDING) && (!bPaddingFound))  // Padding block
                        {
                            padding       = blockLength;                           // if we find more skip & put them in metablock array
                            paddingLast   = ((aMetaDataBlockHeader[0] & 0x80) != 0);
                            paddingIndex  = blockIndex;
                            bPaddingFound = true;
                            source.BaseStream.Seek(padding, SeekOrigin.Current); // advance into file till next block or audio data start
                        }
                        else if (blockType == META_PICTURE)
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(ZONE_PICTURE, position - 4, (int)blockLength + 4, new byte[0], (byte)(isLast ? 1 : 0)));
                            }
                            vorbisTag.ReadPicture(source.BaseStream, readTagParams);
                        }
                        // TODO : support for CUESHEET block

                        if (blockType < 7)
                        {
                            source.BaseStream.Seek(position + blockLength, SeekOrigin.Begin);
                        }
                        else
                        {
                            // Abnormal header : incorrect size and/or misplaced last-metadata-block flag
                            break;
                        }
                    }while (!isLast);

                    if (readTagParams.PrepareForWriting)
                    {
                        bool vorbisTagFound = false;
                        bool pictureFound   = false;

                        foreach (Zone zone in zones)
                        {
                            if (zone.Name.Equals(ZONE_PICTURE))
                            {
                                pictureFound = true;
                            }
                            else if (zone.Name.Equals(ZONE_VORBISTAG))
                            {
                                vorbisTagFound = true;
                            }
                        }

                        if (!vorbisTagFound)
                        {
                            zones.Add(new Zone(ZONE_VORBISTAG, firstBlockPosition, 0, new byte[0]));
                        }
                        if (!pictureFound)
                        {
                            zones.Add(new Zone(ZONE_PICTURE, firstBlockPosition, 0, new byte[0]));
                        }
                    }
                }
            }

            if (isValid())
            {
                audioOffset = source.BaseStream.Position;  // we need that to rebuild the file if nedeed
                result      = true;
            }

            return(result);
        }