示例#1
0
 /// <summary>
 /// Creates a new seekpoint.
 /// </summary>
 /// <param name="data"></param>
 public SeekPoint(byte[] data)
 {
     this.firstSampleNumber = BinaryDataHelper.GetUInt64(data, 0);
     this.byteOffset        = BinaryDataHelper.GetUInt64(data, 8);
     this.numberOfSamples   = BinaryDataHelper.GetUInt16(data, 16);
     ValidateIsPlaceholder();
 }
示例#2
0
文件: Picture.cs 项目: asimshah/Music
        /// <summary>
        /// Will write the data describing this metadata block to the given stream.
        /// </summary>
        /// <param name="targetStream">Stream to write the data to.</param>
        public override void WriteBlockData(Stream targetStream)
        {
            // This is where the header will come
            long headerPosition = targetStream.Position;

            // Moving along, we'll write the header last!
            targetStream.Seek(4, SeekOrigin.Current);

            // 32-bit picture type
            targetStream.Write(BinaryDataHelper.GetBytesUInt32((uint)this.pictureType), 0, 4);

            byte[] mimeTypeData = Encoding.ASCII.GetBytes(this.mimeType);
            // Length of the MIME type string (in bytes ...)
            targetStream.Write(BinaryDataHelper.GetBytesUInt32((uint)mimeTypeData.Length), 0, 4);
            // Only allows printable ascii characters (0x20 - 0x7e)
            for (int i = 0; i < mimeTypeData.Length; i++)
            {
                if (mimeTypeData[i] < 0x20 || mimeTypeData[i] > 0x7e)
                {
                    // Make sure we write the text correctly as specified by the format.
                    mimeTypeData[i] = 0x20;
                }
            }
            targetStream.Write(mimeTypeData, 0, mimeTypeData.Length);

            byte[] descriptionData = Encoding.UTF8.GetBytes(this.description);
            // Length of the description string (in bytes ...)
            targetStream.Write(BinaryDataHelper.GetBytesUInt32((uint)descriptionData.Length), 0, 4);
            // The description of the picture (in UTF-8)
            targetStream.Write(descriptionData, 0, descriptionData.Length);

            targetStream.Write(BinaryDataHelper.GetBytesUInt32((uint)this.width), 0, 4);
            targetStream.Write(BinaryDataHelper.GetBytesUInt32((uint)this.height), 0, 4);
            targetStream.Write(BinaryDataHelper.GetBytesUInt32((uint)this.colorDepth), 0, 4);
            targetStream.Write(BinaryDataHelper.GetBytesUInt32((uint)this.colors), 0, 4);

            // If --> is the mime type, the data contains the URL ...
            if (this.mimeType == "-->")
            {
                this.data = Encoding.ASCII.GetBytes(this.url);
            }

            if (this.data == null)
            {
                this.data = new byte[] { };
            }

            targetStream.Write(BinaryDataHelper.GetBytesUInt32((uint)this.data.Length), 0, 4);
            targetStream.Write(this.data, 0, this.data.Length);

            // Writing the header, now we have the required information on the variable length fields
            CalculateMetadataBlockLength((uint)mimeTypeData.Length, (uint)descriptionData.Length, (uint)this.data.Length);

            long currentPosition = targetStream.Position;

            targetStream.Position = headerPosition;
            this.Header.WriteHeaderData(targetStream);
            targetStream.Position = currentPosition;
        }
示例#3
0
        /// <summary>
        /// Will write the data representing this CueSheet track index point to the given stream.
        /// </summary>
        /// <param name="targetStream"></param>
        public void WriteBlockData(Stream targetStream)
        {
            targetStream.Write(BinaryDataHelper.GetBytesUInt64(this.offset), 0, 8);
            targetStream.WriteByte(this.indexPointNumber);

            byte[] nullData = new byte[RESERVED_NULLDATA_LENGTH];
            targetStream.Write(nullData, 0, nullData.Length);
        }
示例#4
0
        /// <summary>
        /// Will write the data describing this metadata block to the given stream.
        /// </summary>
        /// <param name="targetStream">Stream to write the data to.</param>
        public override void WriteBlockData(Stream targetStream)
        {
            this.Header.MetaDataBlockLength = 4 + (uint)this.applicationData.Length;
            this.Header.WriteHeaderData(targetStream);

            targetStream.Write(BinaryDataHelper.GetBytesUInt32(this.applicationID), 0, 4);
            targetStream.Write(this.applicationData, 0, this.applicationData.Length);
        }
示例#5
0
        /// <summary>
        /// Parses the given binary metadata to an ApplicationInfo block
        /// </summary>
        /// <param name="data"></param>
        public override void LoadBlockData(byte[] data)
        {
            this.applicationID   = BinaryDataHelper.GetUInt32(data, 0);
            this.applicationData = new byte[data.Length - 4];

            for (int i = 0; i < this.applicationData.Length; i++)
            {
                this.applicationData[i] = data[i + 4]; // + 4 because the first four bytes are the application ID!
            }
        }
示例#6
0
        /// <summary>
        /// Will write the data representing this header (as it is stored in the FLAC file) to the given stream.
        /// </summary>
        /// <param name="targetStream">The stream where the data will be written to.</param>
        public void WriteHeaderData(Stream targetStream)
        {
            byte data = this.isLastMetaDataBlock ? (byte)128 : (byte)0; // The 128 because the last metadata flag is the most significant bit set to 1 ...

            data += (byte)(this.typeID & 0x7F);                         // We make sure to chop off the last bit

            targetStream.WriteByte(data);

            // 24-bit metaDataBlockLength
            targetStream.Write(BinaryDataHelper.GetBytes((UInt64)this.metaDataBlockLength, 3), 0, 3);
        }
示例#7
0
        /// <summary>
        /// Creates a new SeekTable base on the provided binary data.
        /// </summary>
        /// <param name="data"></param>
        public override void LoadBlockData(byte[] data)
        {
            UInt32    numberOfSeekpoints;
            SeekPoint newSeekPoint;

            numberOfSeekpoints = this.Header.MetaDataBlockLength / SEEKPOINT_SIZE;
            for (int i = 0; i < numberOfSeekpoints; i++)
            {
                newSeekPoint = new SeekPoint(BinaryDataHelper.GetDataSubset(data, i * (int)SEEKPOINT_SIZE, (int)SEEKPOINT_SIZE));
                // We should keep in mind that the placeholder seekpoints aren't actually added to the list but are kept only as a
                // count in this.SeekPoints.Placeholders
                this.SeekPoints.Add(newSeekPoint);
            }
        }
示例#8
0
        /// <summary>
        /// Will write the data describing this metadata block to the given stream.
        /// </summary>
        /// <param name="targetStream">Stream to write the data to.</param>
        public override void WriteBlockData(Stream targetStream)
        {
            uint totalLength = 0;

            long headerPosition = targetStream.Position;

            this.Header.WriteHeaderData(targetStream);

            // Write the vendor string (first write the length as a 32-bit uint and then the actual bytes
            byte[] vendorData = System.Text.Encoding.UTF8.GetBytes(this.vendor);
            byte[] number     = BinaryDataHelper.GetBytesUInt32((uint)vendorData.Length);
            targetStream.Write(BinaryDataHelper.SwitchEndianness(number, 0, 4), 0, 4);
            targetStream.Write(vendorData, 0, vendorData.Length);
            totalLength += 4 + (uint)vendorData.Length;

            // Length of list of user comments (first a 32-bit uint, then the actual comments)
            number = BinaryDataHelper.GetBytesUInt32((uint)this.comments.Count);
            targetStream.Write(BinaryDataHelper.SwitchEndianness(number, 0, 4), 0, 4);
            totalLength += 4;

            foreach (var comment in this.comments)
            {
                foreach (var value in comment.Value)
                {
                    string commentText = string.Format("{0}={1}", comment.Key, value);
                    byte[] commentData = System.Text.Encoding.UTF8.GetBytes(commentText);
                    number = BinaryDataHelper.GetBytesUInt32((uint)commentData.Length);
                    targetStream.Write(BinaryDataHelper.SwitchEndianness(number, 0, 4), 0, 4);
                    targetStream.Write(commentData, 0, commentData.Length);
                    totalLength += 4 + (uint)commentData.Length;
                }
            }

            long endPosition = targetStream.Position;

            targetStream.Seek(headerPosition, SeekOrigin.Begin);

            this.Header.MetaDataBlockLength = totalLength;
            this.Header.WriteHeaderData(targetStream);

            targetStream.Seek(endPosition, SeekOrigin.Begin);

            // Note: FLAC does NOT have the framing bit for vorbis so we don't have to write this.
        }
示例#9
0
        /// <summary>
        /// Loads a new stream info block from the provided data.
        /// </summary>
        /// <param name="data"></param>
        public override void LoadBlockData(byte[] data)
        {
            //throw new Exception("The method or operation is not implemented.");

            // "All numbers are big-endian coded and unsigned".

            // 1: Minimum Block Size (first 16-bit)
            this.minimumBlockSize = BinaryDataHelper.GetUInt16(data, 0);
            this.maximumBlockSize = BinaryDataHelper.GetUInt16(data, 2);
            this.minimumFrameSize = BinaryDataHelper.GetUInt24(data, 4);
            this.maximumFrameSize = BinaryDataHelper.GetUInt24(data, 7);
            // Interpret 20 bits starting from byte 10 as a UInt
            this.sampleRateHz  = (UInt32)BinaryDataHelper.GetUInt64(data, 10, 20);
            this.channels      = (short)(BinaryDataHelper.GetUInt64(data, 12, 3, 4) + 1);
            this.bitsPerSample = (short)(BinaryDataHelper.GetUInt64(data, 12, 5, 7) + 1);
            this.samples       = (long)BinaryDataHelper.GetUInt64(data, 13, 36, 4);
            this.md5Signature  = new byte[16];
            Array.Copy(data, 18, this.md5Signature, 0, 16);
        }
示例#10
0
        /// <summary>
        /// Will write the data describing this metadata block to the given stream.
        /// </summary>
        /// <param name="targetStream">Stream to write the data to.</param>
        public override void WriteBlockData(Stream targetStream)
        {
            if (this.Tracks.Count > 0)
            {
                var lastTrack = this.Tracks[this.Tracks.Count - 1];
                if (!lastTrack.IsLeadOut)
                {
                    throw new Exception(string.Format("CueSheet is invalid, last track (nr {0}) is not the lead-out track.", lastTrack.TrackNumber));
                }
            }
            else
            {
                throw new Exception("CueSheet is invalid as it has no tracks, it must have at least one track (the lead-out track).");
            }

            // TODO: this value in the header should also update when someone add/removes tracks or track index points ...
            this.Header.MetaDataBlockLength = CalculateMetaDataBlockLength();
            this.Header.WriteHeaderData(targetStream);

            targetStream.Write(BinaryDataHelper.GetPaddedAsciiBytes(this.MediaCatalog, MEDIACATALOG_MAX_LENGTH), 0, MEDIACATALOG_MAX_LENGTH);
            targetStream.Write(BinaryDataHelper.GetBytesUInt64(this.LeadInSampleCount), 0, 8);

            byte isCDCueSheet = 0;

            if (this.isCDCueSheet)
            {
                isCDCueSheet = 0x80; // Most significant bit should be 1
            }
            targetStream.WriteByte(isCDCueSheet);

            // Now we need to write 258 bytes of 0 data ("reserved")
            byte[] nullData = new byte[RESERVED_NULLDATA_LENGTH];
            targetStream.Write(nullData, 0, nullData.Length);

            // The number of tracks i 1 byte in size ...
            targetStream.WriteByte(this.TrackCount);

            foreach (var track in Tracks)
            {
                track.WriteBlockData(targetStream);
            }
        }
示例#11
0
文件: Picture.cs 项目: asimshah/Music
        /// <summary>
        /// Loads the picture data from a Metadata block.
        /// </summary>
        /// <param name="data"></param>
        public override void LoadBlockData(byte[] data)
        {
            // First 32-bit: picture type according to the ID3v2 APIC frame
            pictureType = (PictureType)(int)BinaryDataHelper.GetUInt32(data, 0);

            // Then the length of the MIME type text (32-bit) and the mime type
            int mimeTypeLength = (int)BinaryDataHelper.GetUInt32(data, 4);

            byte[] mimeData = BinaryDataHelper.GetDataSubset(data, 8, mimeTypeLength);
            this.mimeType = Encoding.ASCII.GetString(mimeData);

            int byteOffset = 8 + mimeTypeLength;

            // Then the description (in UTF-8)
            int descriptionLength = (int)BinaryDataHelper.GetUInt32(data, byteOffset);

            byte[] descriptionData = BinaryDataHelper.GetDataSubset(data, byteOffset + 4, descriptionLength);
            this.description = Encoding.UTF8.GetString(descriptionData);

            byteOffset += 4 + descriptionLength;

            this.width      = BinaryDataHelper.GetUInt32(data, byteOffset);
            this.height     = BinaryDataHelper.GetUInt32(data, byteOffset + 4);
            this.colorDepth = BinaryDataHelper.GetUInt32(data, byteOffset + 8);
            this.colors     = BinaryDataHelper.GetUInt32(data, byteOffset + 12);

            byteOffset += 16;

            int dataLength = (int)BinaryDataHelper.GetUInt32(data, byteOffset);

            this.data = BinaryDataHelper.GetDataSubset(data, byteOffset + 4, dataLength);

            // According to the FLAC format, if the mimeType is the string -->, the data contains
            // a URL, pointing to the image. A URL should be ASCII encoded, but using UTF-8 seems
            // more sensible.
            if (mimeType == "-->")
            {
                this.url = Encoding.UTF8.GetString(this.data);
            }
        }
示例#12
0
        /// <summary>
        /// Parses the binary metadata from the flac file into a CueSheet object.
        /// </summary>
        /// <param name="data">The binary data from the flac file.</param>
        public override void LoadBlockData(byte[] data)
        {
            this.mediaCatalog      = Encoding.ASCII.GetString(data, 0, 128).Trim(new char[] { '\0' });
            this.leadInSampleCount = BinaryDataHelper.GetUInt64(data, 128);
            this.isCDCueSheet      = BinaryDataHelper.GetBoolean(data, 136, 0);
            // We're skipping 7 bits + 258 bytes which is reserved null data
            byte trackCount = data[395];

            if (trackCount > 100)
            {
                // Do we really need to throw an exception here?
                throw new Exception(string.Format("CueSheet has invalid track count {0}. Cannot be more than 100.", trackCount));
            }

            int cueSheetTrackOffset = 396;

            for (int i = 0; i < trackCount; i++)
            {
                CueSheetTrack newTrack = new CueSheetTrack(data, cueSheetTrackOffset);
                cueSheetTrackOffset += 36 + (12 * newTrack.IndexPointCount); // 36 bytes for the cueSheetTrack and 12 bytes per index point ...
                this.Tracks.Add(newTrack);
            }
        }
示例#13
0
        /// <summary>
        /// When overridden in a derived class, will write the data describing this metadata block to the given stream.
        /// </summary>
        /// <param name="targetStream">Stream to write the data to.</param>
        public override void WriteBlockData(Stream targetStream)
        {
            this.Header.WriteHeaderData(targetStream);

            targetStream.Write(BinaryDataHelper.GetBytesUInt16(this.minimumBlockSize), 0, 2);
            targetStream.Write(BinaryDataHelper.GetBytesUInt16(this.maximumBlockSize), 0, 2);
            targetStream.Write(BinaryDataHelper.GetBytes(this.minimumFrameSize, 3), 0, 3);
            targetStream.Write(BinaryDataHelper.GetBytes(this.maximumFrameSize, 3), 0, 3);

            // next are 64 bits containing:
            // * sample rate in Hz (20-bits)
            // * number of channels (3 bits)
            // * bits per sample (5 bits)
            // * total samples per stream (36 bits)
            UInt64 combinedData = (UInt64)this.SampleRateHz << 44;

            combinedData = combinedData + ((UInt64)(this.channels - 1) << 41);
            combinedData = combinedData + ((UInt64)(this.bitsPerSample - 1) << 36);
            combinedData = combinedData + (UInt64)this.samples;

            targetStream.Write(BinaryDataHelper.GetBytes(combinedData, 8), 0, 8);
            targetStream.Write(this.md5Signature, 0, 16);
        }
示例#14
0
        /// <summary>
        /// Loads the Vorbis from a block of data.
        /// </summary>
        /// <param name="data"></param>
        public override void LoadBlockData(byte[] data)
        {
            UInt32 vendorLength = BinaryDataHelper.GetUInt32(BinaryDataHelper.SwitchEndianness(data, 0, 4), 0);

            this.vendor = Encoding.UTF8.GetString(BinaryDataHelper.GetDataSubset(data, 4, (int)vendorLength));

            int    startOfComments       = 4 + (int)vendorLength;
            UInt32 userCommentListLength = BinaryDataHelper.GetUInt32(BinaryDataHelper.SwitchEndianness(data, startOfComments, 4), 0);

            // Start of comments actually four bytes further (first piece is the count of items in the list)
            startOfComments += 4;
            for (UInt32 i = 0; i < userCommentListLength; i++)
            {
                UInt32 commentLength = BinaryDataHelper.GetUInt32(BinaryDataHelper.SwitchEndianness(data, startOfComments, 4), 0);
                string comment       = Encoding.UTF8.GetString(BinaryDataHelper.GetDataSubset(data, startOfComments + 4, (int)commentLength));
                // We're moving on in the array ...
                startOfComments += 4 + (int)commentLength;

                AddComment(comment);
            }

            // All done, note that FLAC doesn't have the "fraiming bit" for vorbis ...
        }
示例#15
0
        /// <summary>
        /// Interprets the meta data block header.
        /// </summary>
        /// <param name="data"></param>
        protected void ParseData(byte[] data)
        {
            // Parses the 4 byte header data:
            // Bit 1:   Last-metadata-block flag: '1' if this block is the last metadata block before the audio blocks, '0' otherwise.
            // Bit 2-8: Block Type,
            //  0 : STREAMINFO
            //  1 : PADDING
            //  2 : APPLICATION
            //  3 : SEEKTABLE
            //  4 : VORBIS_COMMENT
            //  5 : CUESHEET
            //  6 : PICTURE
            //  7-126 : reserved
            //  127 : invalid, to avoid confusion with a frame sync code
            // Next 3 bytes: Length (in bytes) of metadata to follow (does not include the size of the METADATA_BLOCK_HEADER)

            this.isLastMetaDataBlock = BinaryDataHelper.GetBoolean(data, 0, 0);

            typeID = data[0] & 0x7F;
            switch (typeID)
            {
            case 0:
                this.type = MetadataBlockType.StreamInfo;
                this.metaDataBlockLength = 34;
                break;

            case 1:
                this.type = MetadataBlockType.Padding;
                break;

            case 2:
                this.type = MetadataBlockType.Application;
                break;

            case 3:
                this.type = MetadataBlockType.Seektable;
                break;

            case 4:
                this.type = MetadataBlockType.VorbisComment;
                break;

            case 5:
                this.type = MetadataBlockType.CueSheet;
                break;

            case 6:
                this.type = MetadataBlockType.Picture;
                break;
            }
            if (typeID > 6 && typeID < 127)
            {
                this.type = MetadataBlockType.None;
            }
            else if (typeID >= 127)
            {
                this.type = MetadataBlockType.Invalid;
            }

            this.metaDataBlockLength = (BinaryDataHelper.GetUInt24(data, 1));
        }
示例#16
0
 /// <summary>
 /// Creates a new Cue Sheet Track Index based on the binary data provided.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="dataOffset">Where in the data array to start reading.</param>
 public CueSheetTrackIndex(byte[] data, int dataOffset)
 {
     this.offset           = BinaryDataHelper.GetUInt64(data, dataOffset);
     this.indexPointNumber = (byte)BinaryDataHelper.GetUInt64(data, dataOffset + 8, 8);
 }
示例#17
0
 /// <summary>
 /// Will write the data representing this SeekPoint to the given stream.
 /// </summary>
 /// <param name="targetStream"></param>
 public void WriteData(Stream targetStream)
 {
     targetStream.Write(BinaryDataHelper.GetBytesUInt64(this.firstSampleNumber), 0, 8);
     targetStream.Write(BinaryDataHelper.GetBytesUInt64(this.byteOffset), 0, 8);
     targetStream.Write(BinaryDataHelper.GetBytesUInt16(this.numberOfSamples), 0, 2);
 }