public bool Read(BinaryReader source, AudioDataManager.SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
 {
     return(true);
 }
Exemple #2
0
        protected override Boolean read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
        {
            var  result      = true;
            var  maxPatterns = -1;
            Byte nbSamples   = 31;

            String readString;
            var    comment = new StringBuilder("");

            Sample sample;
            IList <IList <Int32> > pattern;
            IList <Int32>          row;

            resetData();


            // == TITLE ==
            readString = Utils.Latin1Encoding.GetString(source.ReadBytes(4));
            if (readString.Equals(SIG_POWERPACKER))
            {
                result = false;
                throw new Exception("MOD files compressed with PowerPacker are not supported yet");
            }

            tagExists = true;

            // Restart from beginning, else parser might miss empty titles
            source.BaseStream.Seek(0, SeekOrigin.Begin);

            // Title = max first 20 chars; null-terminated
            var title = StreamUtils.ReadNullTerminatedStringFixed(source, System.Text.Encoding.ASCII, 20);

            if (readTagParams.PrepareForWriting)
            {
                structureHelper.AddZone(0, 20, new Byte[20] {
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                }, ZONE_TITLE);
            }
            tagData.IntegrateValue(TagData.TAG_FIELD_TITLE, title.Trim());

            // == SAMPLES ==
            nbSamples = detectNbSamples(source);
            var charOne = Utils.Latin1Encoding.GetString(new Byte[] { 1 });

            for (var i = 0; i < nbSamples; i++)
            {
                sample              = new Sample();
                sample.Name         = StreamUtils.ReadNullTerminatedStringFixed(source, System.Text.Encoding.ASCII, 22).Trim();
                sample.Name         = sample.Name.Replace("\0", "");
                sample.Name         = sample.Name.Replace(charOne, "");
                sample.Size         = StreamUtils.ReverseUInt16(source.ReadUInt16()) * 2;
                sample.Finetune     = source.ReadSByte();
                sample.Volume       = source.ReadByte();
                sample.RepeatOffset = StreamUtils.ReverseUInt16(source.ReadUInt16()) * 2;
                sample.RepeatLength = StreamUtils.ReverseUInt16(source.ReadUInt16()) * 2;
                FSamples.Add(sample);
            }


            // == SONG ==
            nbValidPatterns = source.ReadByte();
            source.BaseStream.Seek(1, SeekOrigin.Current); // Controversial byte; no real use here
            for (var i = 0; i < 128; i++)
            {
                FPatternTable.Add(source.ReadByte());                           // Pattern table
            }
            // File format tag
            formatTag = Utils.Latin1Encoding.GetString(source.ReadBytes(4)).Trim();
            if (modFormats.ContainsKey(formatTag))
            {
                nbChannels  = modFormats[formatTag].NbChannels;
                trackerName = modFormats[formatTag].Name;
            }
            else // Default
            {
                nbChannels = NB_CHANNELS_DEFAULT;
                LogDelegator.GetLogDelegate()(Log.LV_WARNING, "MOD format tag '" + formatTag + "'not recognized");
            }

            // == PATTERNS ==
            // Some extra information about the "FLT8" -type MOD's:
            //
            // These MOD's have 8 channels, still the format isn't the same as the
            // other 8 channel formats ("OCTA", "CD81", "8CHN"): instead of storing
            // ONE 8-track pattern, it stores TWO 4-track patterns per logical pattern.
            // i.e. The first 4 channels of the first logical pattern are stored in
            // the first physical 4-channel pattern (size 1kb) whereas channel 5 until
            // channel 8 of the first logical pattern are stored as the SECOND physical
            // 4-channel pattern. Got it? ;-).
            // If you convert all the 4 channel patterns to 8 channel patterns, do not
            // forget to divide each pattern nr by 2 in the pattern sequence table!

            foreach (var b in FPatternTable)
            {
                maxPatterns = Math.Max(maxPatterns, b);
            }

            for (var p = 0; p < maxPatterns + 1; p++) // Patterns loop
            {
                FPatterns.Add(new List <IList <Int32> >());
                pattern = FPatterns[FPatterns.Count - 1];
                // Rows loop
                for (var l = 0; l < MAX_ROWS; l++)
                {
                    pattern.Add(new List <Int32>());
                    row = pattern[pattern.Count - 1];
                    for (var c = 0; c < nbChannels; c++) // Channels loop
                    {
                        row.Add(StreamUtils.ReverseInt32(source.ReadInt32()));
                    } // end channels loop
                }     // end rows loop
            }         // end patterns loop


            // == Computing track properties

            duration = calculateDuration();

            foreach (var aSample in FSamples)
            {
                if (aSample.Name.Length > 0)
                {
                    comment.Append(aSample.Name).Append(Settings.InternalValueSeparator);
                }
            }
            if (comment.Length > 0)
            {
                comment.Remove(comment.Length - 1, 1);
            }

            tagData.IntegrateValue(TagData.TAG_FIELD_COMMENT, comment.ToString());

            bitrate = sizeInfo.FileSize / duration;

            return(result);
        }
Exemple #3
0
        protected override bool read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
        {
            bool result = true;

            ushort nbPatterns    = 0;
            ushort nbInstruments = 0;

            ushort trackerVersion;

            uint headerSize = 0;
            uint songLength = 0;

            StringBuilder comment = new StringBuilder("");

            resetData();
            BufferedBinaryReader bSource = new BufferedBinaryReader(source.BaseStream);

            // File format signature
            if (!XM_SIGNATURE.Equals(Utils.Latin1Encoding.GetString(bSource.ReadBytes(17))))
            {
                result = false;
                throw new Exception("Invalid XM file (file signature String mismatch)");
            }

            // Title = chars 17 to 37 (length 20)
            string title = StreamUtils.ReadNullTerminatedStringFixed(bSource, System.Text.Encoding.ASCII, 20);

            if (readTagParams.PrepareForWriting)
            {
                structureHelper.AddZone(17, 20, new byte[20] {
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                }, ZONE_TITLE);
            }
            tagData.IntegrateValue(TagData.TAG_FIELD_TITLE, title.Trim());

            // File format signature
            if (!0x1a.Equals(bSource.ReadByte()))
            {
                result = false;
                throw new Exception("Invalid XM file (file signature ID mismatch)");
            }

            tagExists = true;

            trackerName = StreamUtils.ReadNullTerminatedStringFixed(bSource, System.Text.Encoding.ASCII, 20).Trim();

            trackerVersion = bSource.ReadUInt16(); // hi-byte major and low-byte minor
            trackerName   += (trackerVersion << 8) + "." + (trackerVersion & 0xFF00);

            headerSize = bSource.ReadUInt32(); // Calculated FROM THIS OFFSET, not from the beginning of the file
            songLength = bSource.ReadUInt16();

            bSource.Seek(2, SeekOrigin.Current); // Restart position

            nbChannels    = (byte)Math.Min(bSource.ReadUInt16(), (ushort)0xFF);
            nbPatterns    = bSource.ReadUInt16();
            nbInstruments = bSource.ReadUInt16();

            bSource.Seek(2, SeekOrigin.Current); // Flags for frequency tables; useless for ATL

            initialSpeed = bSource.ReadUInt16();
            initialTempo = bSource.ReadUInt16();

            // Pattern table
            for (int i = 0; i < (headerSize - 20); i++) // 20 being the number of bytes read since the header size marker
            {
                if (i < songLength)
                {
                    FPatternTable.Add(bSource.ReadByte());
                }
                else
                {
                    bSource.Seek(1, SeekOrigin.Current);
                }
            }

            readPatterns(bSource, nbPatterns);
            readInstruments(bSource, nbInstruments);


            // == Computing track properties

            duration = calculateDuration();

            foreach (Instrument i in FInstruments)
            {
                if (i.DisplayName.Length > 0)
                {
                    comment.Append(i.DisplayName).Append(Settings.InternalValueSeparator);
                }
            }
            if (comment.Length > 0)
            {
                comment.Remove(comment.Length - 1, 1);
            }

            tagData.IntegrateValue(TagData.TAG_FIELD_COMMENT, comment.ToString());
            bitrate = sizeInfo.FileSize / duration;

            return(result);
        }
Exemple #4
0
        // ---------- SUPPORT METHODS

        /* Unused for now
         * private double getCompressionRatio()
         * {
         *  // Get compression ratio
         *  if (isValid)
         *      return (double)sizeInfo.FileSize / ((duration * sampleRate) * (channels * bits / 8) + 44) * 100;
         *  else
         *      return 0;
         * }
         */

        public Boolean Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            UInt16 signatureChunk;
            Byte   aByte;

            this.sizeInfo = sizeInfo;
            resetData();

            var result = false;

            source.BaseStream.Seek(0, SeekOrigin.Begin);
            signatureChunk = source.ReadUInt16();

            if (30475 == signatureChunk)
            {
                aByte = 0;

                source.BaseStream.Seek(2, SeekOrigin.Current);
                aByte = source.ReadByte();

                switch (aByte & 0xC0)
                {
                case 0: sampleRate = 48000; break;

                case 0x40: sampleRate = 44100; break;

                case 0x80: sampleRate = 32000; break;

                default: sampleRate = 0; break;
                }

                bitrate = BITRATES[(aByte & 0x3F) >> 1];

                aByte = 0;

                source.BaseStream.Seek(1, SeekOrigin.Current);
                aByte = source.ReadByte();

                /* unused for now
                 *              switch (aByte & 0xE0)
                 *              {
                 *                      case 0: channels = 2; break;
                 *                      case 0x20: channels = 1; break;
                 *                      case 0x40: channels = 2; break;
                 *                      case 0x60: channels = 3; break;
                 *                      case 0x80: channels = 3; break;
                 *                      case 0xA0: channels = 4; break;
                 *                      case 0xC0: channels = 4; break;
                 *                      case 0xE0: channels = 5; break;
                 *                      default : channels = 0; break;
                 *              }
                 *
                 *              bits = 16;
                 */

                duration = sizeInfo.FileSize * 8.0 / bitrate;

                result = true;
            }

            return(result);
        }
Exemple #5
0
        /****************************************************************************
        *                                                                           *
        *                              Public methods                               *
        *                                                                           *
        ****************************************************************************/

        //---------------------------------------------------------------
        // Imports Standard MIDI File (type 0 or 1) (and RMID)
        // (if optional parameter $tn set, only track $tn is imported)
        //---------------------------------------------------------------
        public bool Read(BinaryReader source, AudioDataManager.SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            this.sizeInfo = sizeInfo;

            return(read(source, readTagParams));
        }
Exemple #6
0
        private bool readFrames(BinaryReader source, TagInfo Tag, MetaDataIO.ReadTagParams readTagParams)
        {
            string frameName;
            string strValue;
            int    frameDataSize;
            long   valuePosition;
            int    frameFlags;

            source.BaseStream.Seek(Tag.FileSize - Tag.DataShift - Tag.Size, SeekOrigin.Begin);
            // Read all stored fields
            for (int iterator = 0; iterator < Tag.FrameCount; iterator++)
            {
                frameDataSize = source.ReadInt32();
                frameFlags    = source.ReadInt32();
                frameName     = StreamUtils.ReadNullTerminatedString(source, Utils.Latin1Encoding); // Slightly more permissive than what APE specs indicate in terms of allowed characters ("Space(0x20), Slash(0x2F), Digits(0x30...0x39), Letters(0x41...0x5A, 0x61...0x7A)")

                valuePosition = source.BaseStream.Position;

                if (frameDataSize < 0 || valuePosition + frameDataSize > Tag.FileSize)
                {
                    LogDelegator.GetLogDelegate()(Log.LV_ERROR, "Invalid value found while reading APEtag frame");
                    return(false);
                }

                if ((frameDataSize > 0) && (frameDataSize <= 1000))
                {
                    /*
                     * According to spec : "Items are not zero-terminated like in C / C++.
                     * If there's a zero character, multiple items are stored under the key and the items are separated by zero characters."
                     *
                     * => Values have to be splitted
                     */
                    strValue = Utils.StripEndingZeroChars(Encoding.UTF8.GetString(source.ReadBytes(frameDataSize)));
                    strValue = strValue.Replace('\0', Settings.InternalValueSeparator).Trim();
                    SetMetaField(frameName.Trim().ToUpper(), strValue, readTagParams.ReadAllMetaFrames);
                }
                else if (frameDataSize > 0 && !frameName.ToLower().Contains("lyrics")) // Size > 1000 => Probably an embedded picture
                {
                    int picturePosition;
                    PictureInfo.PIC_TYPE picType = decodeAPEPictureType(frameName);

                    if (picType.Equals(PictureInfo.PIC_TYPE.Unsupported))
                    {
                        addPictureToken(getImplementedTagType(), frameName);
                        picturePosition = takePicturePosition(getImplementedTagType(), frameName);
                    }
                    else
                    {
                        addPictureToken(picType);
                        picturePosition = takePicturePosition(picType);
                    }

                    if (readTagParams.ReadPictures)
                    {
                        // Description seems to be a null-terminated ANSI string containing
                        //    * The frame name
                        //    * A byte (0x2E)
                        //    * The picture type (3 characters; similar to the 2nd part of the mime-type)
                        string      description = StreamUtils.ReadNullTerminatedString(source, Utils.Latin1Encoding);
                        PictureInfo picInfo     = PictureInfo.fromBinaryData(source.BaseStream, frameDataSize - description.Length - 1, picType, getImplementedTagType(), frameName, picturePosition);
                        picInfo.Description = description;
                        tagData.Pictures.Add(picInfo);
                    }
                }
                source.BaseStream.Seek(valuePosition + frameDataSize, SeekOrigin.Begin);
            }

            return(true);
        }
Exemple #7
0
        private void readFrames(BinaryReader source, TagInfo Tag, MetaDataIO.ReadTagParams readTagParams)
        {
            String frameName;
            String strValue;
            Int32  frameDataSize;
            Int64  valuePosition;
            Int32  frameFlags;

            source.BaseStream.Seek(Tag.FileSize - Tag.DataShift - Tag.Size, SeekOrigin.Begin);
            // Read all stored fields
            for (var iterator = 0; iterator < Tag.FrameCount; iterator++)
            {
                frameDataSize = source.ReadInt32();
                frameFlags    = source.ReadInt32();
                frameName     = StreamUtils.ReadNullTerminatedString(source, Utils.Latin1Encoding); // Slightly more permissive than what APE specs indicate in terms of allowed characters ("Space(0x20), Slash(0x2F), Digits(0x30...0x39), Letters(0x41...0x5A, 0x61...0x7A)")

                valuePosition = source.BaseStream.Position;

                if ((frameDataSize > 0) && (frameDataSize <= 500))
                {
                    /*
                     * According to spec : "Items are not zero-terminated like in C / C++.
                     * If there's a zero character, multiple items are stored under the key and the items are separated by zero characters."
                     *
                     * => Values have to be splitted
                     */
                    strValue = Utils.StripEndingZeroChars(Encoding.UTF8.GetString(source.ReadBytes(frameDataSize)));
                    strValue = strValue.Replace('\0', Settings.InternalValueSeparator).Trim();
                    SetMetaField(frameName.Trim().ToUpper(), strValue, readTagParams.ReadAllMetaFrames);
                }
                else if (frameDataSize > 0) // Size > 500 => Probably an embedded picture
                {
                    Int32 picturePosition;
                    var   picType = decodeAPEPictureType(frameName);

                    if (picType.Equals(PictureInfo.PIC_TYPE.Unsupported))
                    {
                        addPictureToken(getImplementedTagType(), frameName);
                        picturePosition = takePicturePosition(getImplementedTagType(), frameName);
                    }
                    else
                    {
                        addPictureToken(picType);
                        picturePosition = takePicturePosition(picType);
                    }

                    if (readTagParams.ReadPictures || readTagParams.PictureStreamHandler != null)
                    {
                        // Description seems to be a null-terminated ANSI string containing
                        //    * The frame name
                        //    * A byte (0x2E)
                        //    * The picture type (3 characters; similar to the 2nd part of the mime-type)
                        var description = StreamUtils.ReadNullTerminatedString(source, Utils.Latin1Encoding);
                        var imgFormat   = ImageUtils.GetImageFormatFromMimeType(description.Substring(description.Length - 3, 3));

                        var picInfo = new PictureInfo(imgFormat, picType, getImplementedTagType(), frameName, picturePosition);
                        picInfo.Description = description;
                        picInfo.PictureData = new Byte[frameDataSize - description.Length - 1];
                        source.BaseStream.Read(picInfo.PictureData, 0, frameDataSize - description.Length - 1);

                        tagData.Pictures.Add(picInfo);

                        if (readTagParams.PictureStreamHandler != null)
                        {
                            var mem = new MemoryStream(picInfo.PictureData);
                            readTagParams.PictureStreamHandler(ref mem, picInfo.PicType, picInfo.NativeFormat, picInfo.TagType, picInfo.NativePicCode, picInfo.Position);
                            mem.Close();
                        }
                    }
                }
                source.BaseStream.Seek(valuePosition + frameDataSize, SeekOrigin.Begin);
            }
        }
Exemple #8
0
        protected override bool read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
        {
            bool result = true;

            ushort nbOrders      = 0;
            ushort nbPatterns    = 0;
            ushort nbInstruments = 0;

            ushort flags;
            ushort trackerVersion;

            StringBuilder comment = new StringBuilder("");

            IList <ushort> patternPointers    = new List <ushort>();
            IList <ushort> instrumentPointers = new List <ushort>();

            resetData();
            BufferedBinaryReader bSource = new BufferedBinaryReader(source.BaseStream);

            // Title = first 28 chars
            string title = StreamUtils.ReadNullTerminatedStringFixed(bSource, System.Text.Encoding.ASCII, 28);

            if (readTagParams.PrepareForWriting)
            {
                structureHelper.AddZone(0, 28, new byte[28] {
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                }, ZONE_TITLE);
            }
            tagData.IntegrateValue(TagData.TAG_FIELD_TITLE, title.Trim());
            bSource.Seek(4, SeekOrigin.Current);

            nbOrders      = bSource.ReadUInt16();
            nbInstruments = bSource.ReadUInt16();
            nbPatterns    = bSource.ReadUInt16();

            flags          = bSource.ReadUInt16();
            trackerVersion = bSource.ReadUInt16();

            trackerName = getTrackerName(trackerVersion);

            bSource.Seek(2, SeekOrigin.Current); // sampleType (16b)
            if (!S3M_SIGNATURE.Equals(Utils.Latin1Encoding.GetString(bSource.ReadBytes(4))))
            {
                result = false;
                throw new Exception("Invalid S3M file (file signature mismatch)");
            }
            bSource.Seek(1, SeekOrigin.Current); // globalVolume (8b)

            tagExists = true;

            initialSpeed = bSource.ReadByte();
            initialTempo = bSource.ReadByte();

            bSource.Seek(1, SeekOrigin.Current); // masterVolume (8b)
            bSource.Seek(1, SeekOrigin.Current); // ultraClickRemoval (8b)
            bSource.Seek(1, SeekOrigin.Current); // defaultPan (8b)
            bSource.Seek(8, SeekOrigin.Current); // defaultPan (64b)
            bSource.Seek(2, SeekOrigin.Current); // ptrSpecial (16b)

            // Channel table
            for (int i = 0; i < 32; i++)
            {
                FChannelTable.Add(bSource.ReadByte());
                if (FChannelTable[FChannelTable.Count - 1] < 30)
                {
                    nbChannels++;
                }
            }

            // Pattern table
            for (int i = 0; i < nbOrders; i++)
            {
                FPatternTable.Add(bSource.ReadByte());
            }

            // Instruments pointers
            for (int i = 0; i < nbInstruments; i++)
            {
                instrumentPointers.Add(bSource.ReadUInt16());
            }

            // Patterns pointers
            for (int i = 0; i < nbPatterns; i++)
            {
                patternPointers.Add(bSource.ReadUInt16());
            }

            readInstruments(bSource, instrumentPointers);
            readPatterns(bSource, patternPointers);


            // == Computing track properties

            duration = calculateDuration() * 1000.0;

            foreach (Instrument i in FInstruments)
            {
                string displayName = i.DisplayName.Trim();
                if (displayName.Length > 0)
                {
                    comment.Append(displayName).Append(Settings.InternalValueSeparator);
                }
            }
            if (comment.Length > 0)
            {
                comment.Remove(comment.Length - 1, 1);
            }

            tagData.IntegrateValue(TagData.TAG_FIELD_COMMENT, comment.ToString());
            bitrate = sizeInfo.FileSize / duration;

            return(result);
        }
Exemple #9
0
        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            uint   signatureChunk;
            ushort aWord;

            byte[] specDTS;
            bool   result = false;

            this.sizeInfo = sizeInfo;

            resetData();

            signatureChunk = source.ReadUInt32();
            if (/*0x7FFE8001*/ 25230975 == signatureChunk)
            {
                source.BaseStream.Seek(3, SeekOrigin.Current);
                specDTS = source.ReadBytes(8);

                isValid = true;

                aWord = (ushort)(specDTS[1] | (specDTS[0] << 8));

                switch ((aWord & 0x0FC0) >> 6)
                {
                case 0: channels = 1; break;

                case 1:
                case 2:
                case 3:
                case 4: channels = 2; break;

                case 5:
                case 6: channels = 3; break;

                case 7:
                case 8: channels = 4; break;

                case 9: channels = 5; break;

                case 10:
                case 11:
                case 12: channels = 6; break;

                case 13: channels = 7; break;

                case 14:
                case 15: channels = 8; break;

                default: channels = 0; break;
                }

                switch ((aWord & 0x3C) >> 2)
                {
                case 1: sampleRate = 8000; break;

                case 2: sampleRate = 16000; break;

                case 3: sampleRate = 32000; break;

                case 6: sampleRate = 11025; break;

                case 7: sampleRate = 22050; break;

                case 8: sampleRate = 44100; break;

                case 11: sampleRate = 12000; break;

                case 12: sampleRate = 24000; break;

                case 13: sampleRate = 48000; break;

                default: sampleRate = 0; break;
                }

                aWord = 0;
                aWord = (ushort)(specDTS[2] | (specDTS[1] << 8));

                bitrate = (ushort)BITRATES[(aWord & 0x03E0) >> 5] * 1000;

                aWord = 0;
                aWord = (ushort)(specDTS[7] | (specDTS[6] << 8));

                switch ((aWord & 0x01C0) >> 6)
                {
                case 0:
                case 1: bits = 16; break;

                case 2:
                case 3: bits = 20; break;

                case 4:
                case 5: bits = 24; break;

                default: bits = 16; break;
                }

                duration = sizeInfo.FileSize * 8.0 / bitrate;

                result = true;
            }

            return(result);
        }
Exemple #10
0
        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            bool result = false;
            bool doLoop = true;
            long position;

            UInt16 readData16;
            UInt32 readData32;

            UInt32 metaType;
            UInt32 metaSize;
            long   sampleCount   = 0;
            int    frameSizeType = -1;

            this.sizeInfo = sizeInfo;
            resetData();
            source.BaseStream.Seek(sizeInfo.ID3v2Size, SeekOrigin.Begin);

            if (TAK_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
            {
                result   = true;
                position = source.BaseStream.Position;

                source.BaseStream.Seek(position, SeekOrigin.Begin);

                do // Loop metadata
                {
                    readData32 = source.ReadUInt32();

                    metaType = readData32 & 0x7F;
                    metaSize = readData32 >> 8;

                    position = source.BaseStream.Position;

                    if (0 == metaType)
                    {
                        doLoop = false;        // End of metadata
                    }
                    else if (0x01 == metaType) // Stream info
                    {
                        readData16    = source.ReadUInt16();
                        frameSizeType = readData16 & 0x003C; // bits 11 to 14
                        readData32    = source.ReadUInt32();
                        uint restOfData = source.ReadUInt32();

                        sampleCount = (readData16 >> 14) + (readData32 << 2) + ((restOfData & 0x00000080) << 34);

                        sampleRate          = ((restOfData >> 4) & 0x03ffff) + 6000;                                             // bits 4 to 21
                        channelsArrangement = ChannelsArrangements.GuessFromChannelNumber((int)((restOfData >> 27) & 0x0F) + 1); // bits 28 to 31

                        if (sampleCount > 0)
                        {
                            duration = (double)sampleCount * 1000.0 / sampleRate;
                            bitrate  = Math.Round(((double)(sizeInfo.FileSize - source.BaseStream.Position)) * 8 / duration); //time to calculate average bitrate
                        }
                    }
                    else if (0x04 == metaType) // Encoder info
                    {
                        readData32     = source.ReadUInt32();
                        formatVersion  = 100 * ((readData32 & 0x00ff0000) >> 16);
                        formatVersion += 10 * ((readData32 & 0x0000ff00) >> 8);
                        formatVersion += (readData32 & 0x000000ff);
                    }

                    source.BaseStream.Seek(position + metaSize, SeekOrigin.Begin);
                } while (doLoop); // End of metadata loop
            }

            return(result);
        }
Exemple #11
0
        public Boolean Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            this.sizeInfo = sizeInfo;
            var result = false;

            resetData();

            source.BaseStream.Seek(0, SeekOrigin.Begin);
            if (DSD_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
            {
                source.BaseStream.Seek(16, SeekOrigin.Current);                 // Chunk size and file size
                id3v2Offset = source.ReadInt64();

                if (FMT_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
                {
                    source.BaseStream.Seek(8, SeekOrigin.Current); // Chunk size

                    formatVersion = source.ReadInt32();

                    if (formatVersion > 1)
                    {
                        LogDelegator.GetLogDelegate()(Log.LV_ERROR, "DSF format version " + formatVersion + " not supported");
                        return(result);
                    }

                    isValid = true;

                    source.BaseStream.Seek(8, SeekOrigin.Current); // Format ID (4), Channel type (4)

                    channels   = source.ReadUInt32();
                    sampleRate = source.ReadUInt32();
                    bits       = source.ReadUInt32();

                    var sampleCount = source.ReadUInt64();

                    duration = (Double)sampleCount * 1000.0 / sampleRate;
                    bitrate  = Math.Round(((Double)(sizeInfo.FileSize - source.BaseStream.Position)) * 8 / duration); //time to calculate average bitrate

                    result = true;
                }

                // Load tag if exists
                if (id3v2Offset > 0)
                {
                    if (readTagParams.PrepareForWriting)
                    {
                        id3v2StructureHelper.AddZone(id3v2Offset, (Int32)(source.BaseStream.Length - id3v2Offset));
                        id3v2StructureHelper.AddSize(12, source.BaseStream.Length);
                        id3v2StructureHelper.AddIndex(20, id3v2Offset);
                    }
                }
                else
                {
                    id3v2Offset = 0; // Switch status to "tried to read, but nothing found"

                    if (readTagParams.PrepareForWriting)
                    {
                        // Add EOF zone for future tag writing
                        id3v2StructureHelper.AddZone(source.BaseStream.Length, 0);
                        id3v2StructureHelper.AddSize(12, source.BaseStream.Length);
                        id3v2StructureHelper.AddIndex(20, source.BaseStream.Length);
                    }
                }
            }

            return(result);
        }
Exemple #12
0
        private void readHeaderExtended(BinaryReader source, long sizePosition1, ulong size1, long sizePosition2, ulong size2, MetaDataIO.ReadTagParams readTagParams)
        {
            byte[] headerExtensionObjectId;
            ulong  headerExtensionObjectSize = 0;
            long   position, framePosition, sizePosition3, dataPosition;
            ulong  limit;
            ushort streamNumber, languageIndex;

            source.BaseStream.Seek(16, SeekOrigin.Current); // Reserved field 1
            source.BaseStream.Seek(2, SeekOrigin.Current);  // Reserved field 2

            sizePosition3 = source.BaseStream.Position;
            uint headerExtendedSize = source.ReadUInt32(); // Size of actual data

            // Looping through header extension objects
            position = source.BaseStream.Position;
            limit    = (ulong)position + headerExtendedSize;
            while ((ulong)position < limit)
            {
                framePosition             = source.BaseStream.Position;
                headerExtensionObjectId   = source.ReadBytes(16);
                headerExtensionObjectSize = source.ReadUInt64();

                // Additional metadata (Optional frames)
                if (StreamUtils.ArrEqualsArr(WMA_METADATA_OBJECT_ID, headerExtensionObjectId) || StreamUtils.ArrEqualsArr(WMA_METADATA_LIBRARY_OBJECT_ID, headerExtensionObjectId))
                {
                    ushort nameSize;            // Length (in bytes) of Name field
                    ushort fieldDataType;       // Type of data stored in current field
                    int    fieldDataSize;       // Size of data stored in current field
                    string fieldName;           // Name of current field
                    ushort nbObjects       = source.ReadUInt16();
                    bool   isLibraryObject = StreamUtils.ArrEqualsArr(WMA_METADATA_LIBRARY_OBJECT_ID, headerExtensionObjectId);

                    string zoneCode = isLibraryObject ? ZONE_EXTENDED_HEADER_METADATA_LIBRARY : ZONE_EXTENDED_HEADER_METADATA;

                    structureHelper.AddZone(framePosition, (int)headerExtensionObjectSize, zoneCode);
                    // Store frame information for future editing, since current frame is optional
                    if (readTagParams.PrepareForWriting)
                    {
                        structureHelper.AddSize(sizePosition1, size1, zoneCode);
                        structureHelper.AddSize(sizePosition2, size2, zoneCode);
                        structureHelper.AddSize(sizePosition3, headerExtendedSize, zoneCode);
                    }

                    for (int i = 0; i < nbObjects; i++)
                    {
                        languageIndex = source.ReadUInt16();
                        streamNumber  = source.ReadUInt16();
                        nameSize      = source.ReadUInt16();
                        fieldDataType = source.ReadUInt16();
                        fieldDataSize = source.ReadInt32();
                        fieldName     = Utils.StripEndingZeroChars(Encoding.Unicode.GetString(source.ReadBytes(nameSize)));

                        dataPosition = source.BaseStream.Position;
                        readTagField(source, zoneCode, fieldName, fieldDataType, fieldDataSize, readTagParams, true, languageIndex, streamNumber);

                        source.BaseStream.Seek(dataPosition + fieldDataSize, SeekOrigin.Begin);
                    }
                }

                source.BaseStream.Seek(position + (long)headerExtensionObjectSize, SeekOrigin.Begin);
                position = source.BaseStream.Position;
            }

            // Add absent zone definitions for further editing
            if (readTagParams.PrepareForWriting)
            {
                if (!structureHelper.ZoneNames.Contains(ZONE_EXTENDED_HEADER_METADATA))
                {
                    structureHelper.AddZone(source.BaseStream.Position, 0, ZONE_EXTENDED_HEADER_METADATA);
                    structureHelper.AddSize(sizePosition1, size1, ZONE_EXTENDED_HEADER_METADATA);
                    structureHelper.AddSize(sizePosition2, size2, ZONE_EXTENDED_HEADER_METADATA);
                    structureHelper.AddSize(sizePosition3, headerExtendedSize, ZONE_EXTENDED_HEADER_METADATA);
                }
                if (!structureHelper.ZoneNames.Contains(ZONE_EXTENDED_HEADER_METADATA_LIBRARY))
                {
                    structureHelper.AddZone(source.BaseStream.Position, 0, ZONE_EXTENDED_HEADER_METADATA_LIBRARY);
                    structureHelper.AddSize(sizePosition1, size1, ZONE_EXTENDED_HEADER_METADATA_LIBRARY);
                    structureHelper.AddSize(sizePosition2, size2, ZONE_EXTENDED_HEADER_METADATA_LIBRARY);
                    structureHelper.AddSize(sizePosition3, headerExtendedSize, ZONE_EXTENDED_HEADER_METADATA_LIBRARY);
                }
            }
        }
Exemple #13
0
        public Boolean Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            this.sizeInfo = sizeInfo;

            return(read(source, readTagParams));
        }
Exemple #14
0
        // ---------- SUPPORT METHODS

        /* Unused for now
         * private double getCompressionRatio()
         * {
         *  // Get compression ratio
         *  if (isValid)
         *      return (double)sizeInfo.FileSize / ((duration * sampleRate) * (channels * bits / 8) + 44) * 100;
         *  else
         *      return 0;
         * }
         */

        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            ushort signatureChunk;
            byte   aByte;

            this.sizeInfo = sizeInfo;
            resetData();

            bool result = false;

            source.BaseStream.Seek(0, SeekOrigin.Begin);
            signatureChunk = source.ReadUInt16();

            if (30475 == signatureChunk)
            {
                aByte = 0;

                source.BaseStream.Seek(2, SeekOrigin.Current);
                aByte = source.ReadByte();

                switch (aByte & 0xC0)
                {
                case 0: sampleRate = 48000; break;

                case 0x40: sampleRate = 44100; break;

                case 0x80: sampleRate = 32000; break;

                default: sampleRate = 0; break;
                }

                bitrate = BITRATES[(aByte & 0x3F) >> 1];

                aByte = 0;

                source.BaseStream.Seek(1, SeekOrigin.Current);
                aByte = source.ReadByte();

                switch (aByte & 0xE0)
                {
                case 0: channelsArrangement = DUAL_MONO; break;

                case 0x20: channelsArrangement = MONO; break;

                case 0x40: channelsArrangement = STEREO; break;

                case 0x60: channelsArrangement = ISO_3_0_0; break;

                case 0x80: channelsArrangement = ISO_2_1_0; break;

                case 0xA0: channelsArrangement = ISO_3_1_0; break;

                case 0xC0: channelsArrangement = ISO_2_2_0; break;

                case 0xE0: channelsArrangement = ISO_3_2_0; break;

                default: channelsArrangement = UNKNOWN; break;
                }


                //				bits = 16;

                duration = sizeInfo.FileSize * 8.0 / bitrate;

                result = true;
            }

            return(result);
        }
Exemple #15
0
        protected override bool read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
        {
            bool result = false;
            long position;

            resetData();
            source.BaseStream.Seek(0, SeekOrigin.Begin);

            if (AIFF_CONTAINER_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
            {
                // Container chunk size
                long containerChunkPos  = source.BaseStream.Position;
                int  containerChunkSize = StreamUtils.DecodeBEInt32(source.ReadBytes(4));

                if (containerChunkPos + containerChunkSize + 4 != source.BaseStream.Length)
                {
                    LogDelegator.GetLogDelegate()(Log.LV_WARNING, "Header size is incoherent with file size");
                }

                // Form type
                format = Utils.Latin1Encoding.GetString(source.ReadBytes(4));

                if (format.Equals(FORMTYPE_AIFF) || format.Equals(FORMTYPE_AIFC))
                {
                    isValid = true;

                    StringBuilder commentStr         = new StringBuilder("");
                    long          soundChunkPosition = 0;
                    long          soundChunkSize     = 0; // Header size included
                    bool          nameFound          = false;
                    bool          authorFound        = false;
                    bool          copyrightFound     = false;
                    bool          commentsFound      = false;
                    long          limit = Math.Min(containerChunkPos + containerChunkSize + 4, source.BaseStream.Length);

                    int annotationIndex = 0;
                    int commentIndex    = 0;

                    while (source.BaseStream.Position < limit)
                    {
                        ChunkHeader header = seekNextChunkHeader(source, limit);

                        position = source.BaseStream.Position;

                        if (header.ID.Equals(CHUNKTYPE_COMMON))
                        {
                            short channels = StreamUtils.DecodeBEInt16(source.ReadBytes(2));
                            switch (channels)
                            {
                            case 1: channelsArrangement = MONO; break;

                            case 2: channelsArrangement = STEREO; break;

                            case 3: channelsArrangement = ISO_3_0_0; break;

                            case 4: channelsArrangement = ISO_2_2_0; break;     // Specs actually allow both 2/2.0 and LRCS

                            case 6: channelsArrangement = LRLcRcCS; break;

                            default: channelsArrangement = UNKNOWN; break;
                            }

                            numSampleFrames = StreamUtils.DecodeBEUInt32(source.ReadBytes(4));
                            sampleSize      = (uint)StreamUtils.DecodeBEInt16(source.ReadBytes(2)); // This sample size is for uncompressed data only
                            byte[] byteArray = source.ReadBytes(10);
                            Array.Reverse(byteArray);
                            double aSampleRate = StreamUtils.ExtendedToDouble(byteArray);

                            if (format.Equals(FORMTYPE_AIFC))
                            {
                                compression = Utils.Latin1Encoding.GetString(source.ReadBytes(4));
                            }
                            else // AIFF <=> no compression
                            {
                                compression = COMPRESSION_NONE;
                            }

                            if (aSampleRate > 0)
                            {
                                sampleRate = (int)Math.Round(aSampleRate);
                                duration   = (double)numSampleFrames * 1000.0 / sampleRate;

                                if (!compression.Equals(COMPRESSION_NONE)) // Sample size is specific to selected compression method
                                {
                                    if (compression.ToLower().Equals("fl32"))
                                    {
                                        sampleSize = 32;
                                    }
                                    else if (compression.ToLower().Equals("fl64"))
                                    {
                                        sampleSize = 64;
                                    }
                                    else if (compression.ToLower().Equals("alaw"))
                                    {
                                        sampleSize = 8;
                                    }
                                    else if (compression.ToLower().Equals("ulaw"))
                                    {
                                        sampleSize = 8;
                                    }
                                }
                                if (duration > 0)
                                {
                                    bitrate = sampleSize * numSampleFrames * channelsArrangement.NbChannels / duration;
                                }
                            }
                        }
                        else if (header.ID.Equals(CHUNKTYPE_SOUND))
                        {
                            soundChunkPosition = source.BaseStream.Position - 8;
                            soundChunkSize     = header.Size + 8;
                        }
                        else if (header.ID.Equals(CHUNKTYPE_NAME) || header.ID.Equals(CHUNKTYPE_AUTHOR) || header.ID.Equals(CHUNKTYPE_COPYRIGHT))
                        {
                            structureHelper.AddZone(source.BaseStream.Position - 8, header.Size + 8, header.ID);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, header.ID);

                            tagExists = true;
                            if (header.ID.Equals(CHUNKTYPE_NAME))
                            {
                                nameFound = true;
                            }
                            if (header.ID.Equals(CHUNKTYPE_AUTHOR))
                            {
                                authorFound = true;
                            }
                            if (header.ID.Equals(CHUNKTYPE_COPYRIGHT))
                            {
                                copyrightFound = true;
                            }

                            SetMetaField(header.ID, Utils.Latin1Encoding.GetString(source.ReadBytes(header.Size)), readTagParams.ReadAllMetaFrames);
                        }
                        else if (header.ID.Equals(CHUNKTYPE_ANNOTATION))
                        {
                            annotationIndex++;
                            structureHelper.AddZone(source.BaseStream.Position - 8, header.Size + 8, header.ID + annotationIndex);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, header.ID + annotationIndex);

                            if (commentStr.Length > 0)
                            {
                                commentStr.Append(Settings.InternalValueSeparator);
                            }
                            commentStr.Append(Utils.Latin1Encoding.GetString(source.ReadBytes(header.Size)));
                            tagExists = true;
                        }
                        else if (header.ID.Equals(CHUNKTYPE_COMMENTS))
                        {
                            commentIndex++;
                            structureHelper.AddZone(source.BaseStream.Position - 8, header.Size + 8, header.ID + commentIndex);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, header.ID + commentIndex);

                            tagExists     = true;
                            commentsFound = true;

                            ushort numComs = StreamUtils.DecodeBEUInt16(source.ReadBytes(2));

                            for (int i = 0; i < numComs; i++)
                            {
                                CommentData cmtData = new CommentData();
                                cmtData.Timestamp = StreamUtils.DecodeBEUInt32(source.ReadBytes(4));
                                cmtData.MarkerId  = StreamUtils.DecodeBEInt16(source.ReadBytes(2));

                                // Comments length
                                ushort        comLength = StreamUtils.DecodeBEUInt16(source.ReadBytes(2));
                                MetaFieldInfo comment   = new MetaFieldInfo(getImplementedTagType(), header.ID + commentIndex);
                                comment.Value        = Utils.Latin1Encoding.GetString(source.ReadBytes(comLength));
                                comment.SpecificData = cmtData;
                                tagData.AdditionalFields.Add(comment);

                                // Only read general purpose comments, not those linked to a marker
                                if (0 == cmtData.MarkerId)
                                {
                                    if (commentStr.Length > 0)
                                    {
                                        commentStr.Append(Settings.InternalValueSeparator);
                                    }
                                    commentStr.Append(comment.Value);
                                }
                            }
                        }
                        else if (header.ID.Equals(CHUNKTYPE_ID3TAG))
                        {
                            id3v2Offset = source.BaseStream.Position;

                            // Zone is already added by Id3v2.Read
                            id3v2StructureHelper.AddZone(id3v2Offset - 8, header.Size + 8, CHUNKTYPE_ID3TAG);
                            id3v2StructureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_ID3TAG);
                        }

                        source.BaseStream.Position = position + header.Size;

                        if (header.ID.Equals(CHUNKTYPE_SOUND) && header.Size % 2 > 0)
                        {
                            source.BaseStream.Position += 1;                                                           // Sound chunk size must be even
                        }
                    }

                    tagData.IntegrateValue(TagData.TAG_FIELD_COMMENT, commentStr.ToString().Replace("\0", " ").Trim());

                    if (-1 == id3v2Offset)
                    {
                        id3v2Offset = 0; // Switch status to "tried to read, but nothing found"

                        if (readTagParams.PrepareForWriting)
                        {
                            id3v2StructureHelper.AddZone(soundChunkPosition + soundChunkSize, 0, CHUNKTYPE_ID3TAG);
                            id3v2StructureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_ID3TAG);
                        }
                    }

                    // Add zone placeholders for future tag writing
                    if (readTagParams.PrepareForWriting)
                    {
                        if (!nameFound)
                        {
                            structureHelper.AddZone(soundChunkPosition, 0, CHUNKTYPE_NAME);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_NAME);
                        }
                        if (!authorFound)
                        {
                            structureHelper.AddZone(soundChunkPosition, 0, CHUNKTYPE_AUTHOR);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_AUTHOR);
                        }
                        if (!copyrightFound)
                        {
                            structureHelper.AddZone(soundChunkPosition, 0, CHUNKTYPE_COPYRIGHT);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_COPYRIGHT);
                        }
                        if (!commentsFound)
                        {
                            structureHelper.AddZone(soundChunkPosition, 0, CHUNKTYPE_COMMENTS);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_COMMENTS);
                        }
                    }

                    result = true;
                }
            }

            return(result);
        }
Exemple #16
0
        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            uint   signatureChunk;
            ushort aWord;

            byte[] specDTS;
            bool   result = false;

            this.sizeInfo = sizeInfo;

            resetData();

            signatureChunk = source.ReadUInt32();
            if (/*0x7FFE8001*/ 25230975 == signatureChunk)
            {
                AudioDataOffset = source.BaseStream.Position - 4;
                AudioDataSize   = sizeInfo.FileSize - sizeInfo.APESize - sizeInfo.ID3v1Size - AudioDataOffset;

                source.BaseStream.Seek(3, SeekOrigin.Current);
                specDTS = source.ReadBytes(8);

                isValid = true;

                aWord = (ushort)(specDTS[1] | (specDTS[0] << 8));

                switch ((aWord & 0x0FC0) >> 6)
                {
                case 0: channelsArrangement = MONO; break;

                case 1: channelsArrangement = DUAL_MONO; break;

                case 2: channelsArrangement = STEREO; break;

                case 3: channelsArrangement = STEREO_SUM_DIFFERENCE; break;

                case 4: channelsArrangement = STEREO_LEFT_RIGHT_TOTAL; break;

                case 5: channelsArrangement = ISO_3_0_0; break;

                case 6: channelsArrangement = ISO_2_1_0; break;

                case 7: channelsArrangement = LRCS; break;

                case 8: channelsArrangement = QUAD; break;

                case 9: channelsArrangement = ISO_3_2_0; break;

                case 10: channelsArrangement = CLCRLRSLSR; break;

                case 11: channelsArrangement = CLRLRRRO; break;

                case 12: channelsArrangement = CFCRLFRFLRRR; break;

                case 13: channelsArrangement = CLCCRLRSLSR; break;

                case 14: channelsArrangement = CLCRLRSL1SL2SR1SR2; break;

                case 15: channelsArrangement = CLCCRLRSLSSR; break;

                default: channelsArrangement = UNKNOWN; break;
                }

                switch ((aWord & 0x3C) >> 2)
                {
                case 1: sampleRate = 8000; break;

                case 2: sampleRate = 16000; break;

                case 3: sampleRate = 32000; break;

                case 6: sampleRate = 11025; break;

                case 7: sampleRate = 22050; break;

                case 8: sampleRate = 44100; break;

                case 11: sampleRate = 12000; break;

                case 12: sampleRate = 24000; break;

                case 13: sampleRate = 48000; break;

                default: sampleRate = 0; break;
                }

                aWord   = (ushort)(specDTS[2] | (specDTS[1] << 8));
                bitrate = (ushort)BITRATES[(aWord & 0x03E0) >> 5];

                aWord = (ushort)(specDTS[7] | (specDTS[6] << 8));
                switch ((aWord & 0x01C0) >> 6)
                {
                case 0:
                case 1: bits = 16; break;

                case 2:
                case 3: bits = 20; break;

                case 4:
                case 5: bits = 24; break;

                default: bits = 16; break;
                }

                duration = sizeInfo.FileSize * 8.0 / bitrate;

                result = true;
            }

            return(result);
        }
Exemple #17
0
 /// <inheritdoc/>
 public bool Read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
 {
     throw new NotImplementedException();
 }
Exemple #18
0
        protected override bool read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
        {
            bool result = true;

            ushort nbOrders      = 0;
            ushort nbPatterns    = 0;
            ushort nbSamples     = 0;
            ushort nbInstruments = 0;

            ushort flags;
            ushort special;
            ushort trackerVersion;
            ushort trackerVersionCompatibility;

            bool useSamplesAsInstruments = false;

            ushort messageLength;
            uint   messageOffset;
            String message = "";

            IList <UInt32> patternPointers    = new List <UInt32>();
            IList <UInt32> instrumentPointers = new List <UInt32>();
            IList <UInt32> samplePointers     = new List <UInt32>();

            resetData();
            BufferedBinaryReader bSource = new BufferedBinaryReader(source.BaseStream);


            if (!IT_SIGNATURE.Equals(Utils.Latin1Encoding.GetString(bSource.ReadBytes(4))))
            {
                result = false;
                throw new Exception(sizeInfo.FileSize + " : Invalid IT file (file signature mismatch)"); // TODO - might be a compressed file -> PK header
            }

            tagExists = true;

            // Title = max first 26 chars after file signature; null-terminated
            string title = StreamUtils.ReadNullTerminatedStringFixed(bSource, Utils.Latin1Encoding, 26);

            if (readTagParams.PrepareForWriting)
            {
                structureHelper.AddZone(4, 26, new byte[26] {
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                }, ZONE_TITLE);
            }
            tagData.IntegrateValue(TagData.TAG_FIELD_TITLE, title.Trim());
            bSource.Seek(2, SeekOrigin.Current); // Pattern row highlight information

            nbOrders      = bSource.ReadUInt16();
            nbInstruments = bSource.ReadUInt16();
            nbSamples     = bSource.ReadUInt16();
            nbPatterns    = bSource.ReadUInt16();

            trackerVersion = bSource.ReadUInt16();
            trackerVersionCompatibility = bSource.ReadUInt16();

            flags = bSource.ReadUInt16();

            useSamplesAsInstruments = !((flags & 0x04) > 0);

            special = bSource.ReadUInt16();

            //            trackerName = "Impulse tracker"; // TODO use TrackerVersion to add version

            bSource.Seek(2, SeekOrigin.Current); // globalVolume (8b), masterVolume (8b)

            initialSpeed = bSource.ReadByte();
            initialTempo = bSource.ReadByte();

            bSource.Seek(2, SeekOrigin.Current); // panningSeparation (8b), pitchWheelDepth (8b)

            messageLength = bSource.ReadUInt16();
            messageOffset = bSource.ReadUInt32();
            bSource.Seek(132, SeekOrigin.Current); // reserved (32b), channel Pan (64B), channel Vol (64B)

            // Orders table
            for (int i = 0; i < nbOrders; i++)
            {
                patternTable.Add(bSource.ReadByte());
            }

            // Instruments pointers
            for (int i = 0; i < nbInstruments; i++)
            {
                instrumentPointers.Add(bSource.ReadUInt32());
            }

            // Samples pointers
            for (int i = 0; i < nbSamples; i++)
            {
                samplePointers.Add(bSource.ReadUInt32());
            }

            // Patterns pointers
            for (int i = 0; i < nbPatterns; i++)
            {
                patternPointers.Add(bSource.ReadUInt32());
            }

            if ((!useSamplesAsInstruments) && (instrumentPointers.Count > 0))
            {
                if (trackerVersionCompatibility < 0x200)
                {
                    readInstrumentsOld(bSource, instrumentPointers);
                }
                else
                {
                    readInstruments(bSource, instrumentPointers);
                }
            }
            else
            {
                readSamples(bSource, samplePointers);
            }
            readPatterns(bSource, patternPointers);

            // IT Message
            if ((special & 0x1) > 0)
            {
                bSource.Seek(messageOffset, SeekOrigin.Begin);
                //message = new String( StreamUtils.ReadOneByteChars(source, messageLength) );
                message = StreamUtils.ReadNullTerminatedStringFixed(bSource, Utils.Latin1Encoding, messageLength);
            }


            // == Computing track properties

            duration = calculateDuration() * 1000.0;

            string commentStr;

            if (messageLength > 0) // Get Comment from the "IT message" field
            {
                commentStr = message;
            }
            else // Get Comment from all the instrument names (common practice in the tracker community)
            {
                StringBuilder comment = new StringBuilder("");
                // NB : Whatever the value of useSamplesAsInstruments, FInstruments contain the right data
                foreach (Instrument i in instruments)
                {
                    if (i.DisplayName.Length > 0)
                    {
                        comment.Append(i.DisplayName).Append(Settings.InternalValueSeparator);
                    }
                }
                if (comment.Length > 0)
                {
                    comment.Remove(comment.Length - 1, 1);
                }
                commentStr = comment.ToString();
            }
            tagData.IntegrateValue(TagData.TAG_FIELD_COMMENT, commentStr);

            bitrate = (double)sizeInfo.FileSize / duration;

            return(result);
        }
Exemple #19
0
        public bool Read(BinaryReader source, AudioDataManager.SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            this.sizeInfo = sizeInfo;
            bool result = false;

            resetData();

            source.BaseStream.Seek(0, SeekOrigin.Begin);
            if (DSD_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
            {
                source.BaseStream.Seek(16, SeekOrigin.Current); // Chunk size and file size
                id3v2Offset = source.ReadInt64();

                if (FMT_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
                {
                    source.BaseStream.Seek(8, SeekOrigin.Current); // Chunk size

                    formatVersion = source.ReadInt32();

                    if (formatVersion > 1)
                    {
                        LogDelegator.GetLogDelegate()(Log.LV_ERROR, "DSF format version " + formatVersion + " not supported");
                        return(result);
                    }

                    isValid = true;

                    source.BaseStream.Seek(8, SeekOrigin.Current); // Format ID (4), Channel type (4)

                    uint channels = source.ReadUInt32();
                    switch (channels)
                    {
                    case 1: channelsArrangement = MONO; break;

                    case 2: channelsArrangement = STEREO; break;

                    case 3: channelsArrangement = ISO_3_0_0; break;

                    case 4: channelsArrangement = QUAD; break;

                    case 5: channelsArrangement = LRCLFE; break;

                    case 6: channelsArrangement = ISO_3_2_0; break;

                    case 7: channelsArrangement = ISO_3_2_1; break;

                    default: channelsArrangement = UNKNOWN; break;
                    }

                    sampleRate = source.ReadUInt32();
                    bits       = source.ReadUInt32();

                    ulong sampleCount = source.ReadUInt64();

                    duration = (double)sampleCount * 1000.0 / sampleRate;
                    bitrate  = Math.Round(((double)(sizeInfo.FileSize - source.BaseStream.Position)) * 8 / duration); //time to calculate average bitrate

                    result = true;
                }

                // Load tag if exists
                if (id3v2Offset > 0)
                {
                    if (readTagParams.PrepareForWriting)
                    {
                        id3v2StructureHelper.AddZone(id3v2Offset, (int)(source.BaseStream.Length - id3v2Offset));
                        id3v2StructureHelper.AddSize(12, source.BaseStream.Length);
                        id3v2StructureHelper.AddIndex(20, id3v2Offset);
                    }
                }
                else
                {
                    id3v2Offset = 0; // Switch status to "tried to read, but nothing found"

                    if (readTagParams.PrepareForWriting)
                    {
                        // Add EOF zone for future tag writing
                        id3v2StructureHelper.AddZone(source.BaseStream.Length, 0);
                        id3v2StructureHelper.AddSize(12, source.BaseStream.Length);
                        id3v2StructureHelper.AddIndex(20, source.BaseStream.Length);
                    }
                }
            }

            return(result);
        }
Exemple #20
0
        /// <inheritdoc/>
        protected override bool read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
        {
            byte[] header;
            string trigger;

            IList <MidiTrack> tracks = new List <MidiTrack>();

            resetData();

            // Ignores everything (comments) written before the MIDI header
            StreamUtils.FindSequence(source.BaseStream, Utils.Latin1Encoding.GetBytes(MIDI_FILE_HEADER));

            // Ready to read header data...
            header = source.ReadBytes(10);
            if ((header[0] != 0) ||
                (header[1] != 0) ||
                (header[2] != 0) ||
                (header[3] != 6)
                )
            {
                Logging.LogDelegator.GetLogDelegate()(Log.LV_ERROR, "Wrong MIDI header");
                return(false);
            }
            type = header[5];

            // MIDI STRUCTURE TYPE
            // 0 - single-track
            // 1 - multiple tracks, synchronous
            // 2 - multiple tracks, asynchronous
            if (type > 1)
            {
                Logging.LogDelegator.GetLogDelegate()(Log.LV_WARNING, "SMF type 2 MIDI files are partially supported; results may be approximate");
            }

            tagExists = true;

            timebase = (header[8] << 8) + header[9];

            tempo = 0; // maybe (hopefully!) overwritten by parseTrack

            int trackSize;
            int nbTrack = 0;

            comment = new StringBuilder("");

            AudioDataOffset = source.BaseStream.Position;
            AudioDataSize   = sizeInfo.FileSize - AudioDataOffset;

            // Ready to read track data...
            while (source.BaseStream.Position < sizeInfo.FileSize - 4)
            {
                trigger = Utils.Latin1Encoding.GetString(source.ReadBytes(4));

                if (trigger != MIDI_TRACK_HEADER)
                {
                    source.BaseStream.Seek(-3, SeekOrigin.Current);
                    if (!StreamUtils.FindSequence(source.BaseStream, Utils.Latin1Encoding.GetBytes(MIDI_TRACK_HEADER)))
                    {
                        break;
                    }
                }

                // trackSize is stored in big endian -> needs inverting
                trackSize = StreamUtils.DecodeBEInt32(source.ReadBytes(4));

                tracks.Add(parseTrack(source.ReadBytes(trackSize), nbTrack));
                nbTrack++;
            }

            this.tracks = tracks;

            if (comment.Length > 0)
            {
                comment.Remove(comment.Length - 1, 1);
            }
            tagData.IntegrateValue(TagData.TAG_FIELD_COMMENT, comment.ToString());

            duration = getDuration();
            bitrate  = (double)sizeInfo.FileSize / duration;

            return(true);
        }
Exemple #21
0
        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            ApeHeaderOld  APE_OLD  = new ApeHeaderOld();  // old header   <= 3.97
            ApeHeaderNew  APE_NEW  = new ApeHeaderNew();  // new header   >= 3.98
            ApeDescriptor APE_DESC = new ApeDescriptor(); // extra header >= 3.98

            int  BlocksPerFrame;
            bool LoadSuccess;
            bool result = false;

            this.sizeInfo = sizeInfo;
            resetData();

            // Read data from file
            readCommonHeader(source);

            if (StreamUtils.StringEqualsArr("MAC ", header.cID))
            {
                isValid         = true;
                version         = header.nVersion;
                AudioDataOffset = source.BaseStream.Position - 6;
                AudioDataSize   = sizeInfo.FileSize - sizeInfo.APESize - sizeInfo.ID3v1Size - AudioDataOffset;

                versionStr = ((double)version / 1000).ToString().Substring(0, 4); //Str(FVersion / 1000 : 4 : 2, FVersionStr);

                // Load New Monkey's Audio Header for version >= 3.98
                if (header.nVersion >= 3980)
                {
                    APE_DESC.padded                 = 0;
                    APE_DESC.nDescriptorBytes       = 0;
                    APE_DESC.nHeaderBytes           = 0;
                    APE_DESC.nSeekTableBytes        = 0;
                    APE_DESC.nHeaderDataBytes       = 0;
                    APE_DESC.nAPEFrameDataBytes     = 0;
                    APE_DESC.nAPEFrameDataBytesHigh = 0;
                    APE_DESC.nTerminatingDataBytes  = 0;
                    Array.Clear(APE_DESC.cFileMD5, 0, APE_DESC.cFileMD5.Length);

                    APE_DESC.padded                 = source.ReadUInt16();
                    APE_DESC.nDescriptorBytes       = source.ReadUInt32();
                    APE_DESC.nHeaderBytes           = source.ReadUInt32();
                    APE_DESC.nSeekTableBytes        = source.ReadUInt32();
                    APE_DESC.nHeaderDataBytes       = source.ReadUInt32();
                    APE_DESC.nAPEFrameDataBytes     = source.ReadUInt32();
                    APE_DESC.nAPEFrameDataBytesHigh = source.ReadUInt32();
                    APE_DESC.nTerminatingDataBytes  = source.ReadUInt32();
                    APE_DESC.cFileMD5               = source.ReadBytes(16);

                    // seek past description header
                    if (APE_DESC.nDescriptorBytes != 52)
                    {
                        source.BaseStream.Seek(APE_DESC.nDescriptorBytes - 52, SeekOrigin.Current);
                    }
                    // load new ape_header
                    if (APE_DESC.nHeaderBytes > 24 /*sizeof(APE_NEW)*/)
                    {
                        APE_DESC.nHeaderBytes = 24 /*sizeof(APE_NEW)*/;
                    }

                    APE_NEW.nCompressionLevel = 0;
                    APE_NEW.nFormatFlags      = 0;
                    APE_NEW.nBlocksPerFrame   = 0;
                    APE_NEW.nFinalFrameBlocks = 0;
                    APE_NEW.nTotalFrames      = 0;
                    APE_NEW.nBitsPerSample    = 0;
                    APE_NEW.nChannels         = 0;
                    APE_NEW.nSampleRate       = 0;

                    APE_NEW.nCompressionLevel = source.ReadUInt16();
                    APE_NEW.nFormatFlags      = source.ReadUInt16();
                    APE_NEW.nBlocksPerFrame   = source.ReadUInt32();
                    APE_NEW.nFinalFrameBlocks = source.ReadUInt32();
                    APE_NEW.nTotalFrames      = source.ReadUInt32();
                    APE_NEW.nBitsPerSample    = source.ReadUInt16();
                    APE_NEW.nChannels         = source.ReadUInt16();
                    APE_NEW.nSampleRate       = source.ReadUInt32();

                    // based on MAC SDK 3.98a1 (APEinfo.h)
                    sampleRate          = (int)APE_NEW.nSampleRate;
                    channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(APE_NEW.nChannels);
                    formatFlags         = APE_NEW.nFormatFlags;
                    bits            = APE_NEW.nBitsPerSample;
                    compressionMode = APE_NEW.nCompressionLevel;
                    // calculate total uncompressed samples
                    if (APE_NEW.nTotalFrames > 0)
                    {
                        totalSamples = (long)(APE_NEW.nBlocksPerFrame) *
                                       (long)(APE_NEW.nTotalFrames - 1) +
                                       (long)(APE_NEW.nFinalFrameBlocks);
                    }
                    LoadSuccess = true;
                }
                else
                {
                    // Old Monkey <= 3.97

                    APE_OLD.nCompressionLevel = 0;
                    APE_OLD.nFormatFlags      = 0;
                    APE_OLD.nChannels         = 0;
                    APE_OLD.nSampleRate       = 0;
                    APE_OLD.nHeaderBytes      = 0;
                    APE_OLD.nTerminatingBytes = 0;
                    APE_OLD.nTotalFrames      = 0;
                    APE_OLD.nFinalFrameBlocks = 0;
                    APE_OLD.nInt = 0;

                    APE_OLD.nCompressionLevel = source.ReadUInt16();
                    APE_OLD.nFormatFlags      = source.ReadUInt16();
                    APE_OLD.nChannels         = source.ReadUInt16();
                    APE_OLD.nSampleRate       = source.ReadUInt32();
                    APE_OLD.nHeaderBytes      = source.ReadUInt32();
                    APE_OLD.nTerminatingBytes = source.ReadUInt32();
                    APE_OLD.nTotalFrames      = source.ReadUInt32();
                    APE_OLD.nFinalFrameBlocks = source.ReadUInt32();
                    APE_OLD.nInt = source.ReadInt32();

                    compressionMode     = APE_OLD.nCompressionLevel;
                    sampleRate          = (int)APE_OLD.nSampleRate;
                    channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(APE_OLD.nChannels);
                    formatFlags         = APE_OLD.nFormatFlags;
                    bits = 16;
                    if ((APE_OLD.nFormatFlags & MONKEY_FLAG_8_BIT) != 0)
                    {
                        bits = 8;
                    }
                    if ((APE_OLD.nFormatFlags & MONKEY_FLAG_24_BIT) != 0)
                    {
                        bits = 24;
                    }

                    hasSeekElements = ((APE_OLD.nFormatFlags & MONKEY_FLAG_PEAK_LEVEL) != 0);
                    wavNotStored    = ((APE_OLD.nFormatFlags & MONKEY_FLAG_SEEK_ELEMENTS) != 0);
                    hasPeakLevel    = ((APE_OLD.nFormatFlags & MONKEY_FLAG_WAV_NOT_STORED) != 0);

                    if (hasPeakLevel)
                    {
                        peakLevel      = (uint)APE_OLD.nInt;
                        peakLevelRatio = (peakLevel / (1 << bits) / 2.0) * 100.0;
                    }

                    // based on MAC_SDK_397 (APEinfo.cpp)
                    if (version >= 3950)
                    {
                        BlocksPerFrame = 73728 * 4;
                    }
                    else if ((version >= 3900) || ((version >= 3800) && (MONKEY_COMPRESSION_EXTRA_HIGH == APE_OLD.nCompressionLevel)))
                    {
                        BlocksPerFrame = 73728;
                    }
                    else
                    {
                        BlocksPerFrame = 9216;
                    }

                    // calculate total uncompressed samples
                    if (APE_OLD.nTotalFrames > 0)
                    {
                        totalSamples = (APE_OLD.nTotalFrames - 1) * BlocksPerFrame + APE_OLD.nFinalFrameBlocks;
                    }

                    LoadSuccess = true;
                }
                if (LoadSuccess)
                {
                    // compression profile name
                    if ((0 == (compressionMode % 1000)) && (compressionMode <= 6000))
                    {
                        compressionModeStr = MONKEY_COMPRESSION[compressionMode / 1000]; // int division
                    }
                    else
                    {
                        compressionModeStr = compressionMode.ToString();
                    }
                    // length
                    if (sampleRate > 0)
                    {
                        duration = totalSamples * 1000.0 / sampleRate;
                    }
                    // average bitrate
                    if (duration > 0)
                    {
                        bitrate = 8 * (sizeInfo.FileSize - sizeInfo.TotalTagSize) / (duration);
                    }
                    // some extra sanity checks
                    isValid = ((bits > 0) && (sampleRate > 0) && (totalSamples > 0) && (channelsArrangement.NbChannels > 0));
                    result  = isValid;
                }
            }

            return(result);
        }