Beispiel #1
0
        private bool getInfo(BufferedBinaryReader source, FileInfo info, ReadTagParams readTagParams)
        {
            // Get info from file
            bool result        = false;
            bool isValidHeader = false;

            // Check for ID3v2 (NB : this case should not even exist since OGG has its own native tagging system, and is not deemed compatible with ID3v2 according to the ID3 FAQ)
            source.Seek(sizeInfo.ID3v2Size, SeekOrigin.Begin);

            // Read global file header
            info.IdentificationHeader.ReadFromStream(source);

            if (info.IdentificationHeader.IsValid())
            {
                source.Seek(sizeInfo.ID3v2Size + info.IdentificationHeader.Segments + 27, SeekOrigin.Begin); // 27 being the size from 'ID' to 'Segments'

                // Read Vorbis or Opus stream info
                long position = source.Position;

                String headerStart = Utils.Latin1Encoding.GetString(source.ReadBytes(3));
                source.Seek(position, SeekOrigin.Begin);
                if (VORBIS_HEADER_ID.StartsWith(headerStart))
                {
                    contents = CONTENTS_VORBIS;
                    info.VorbisParameters.ID = Utils.Latin1Encoding.GetString(source.ReadBytes(7));
                    isValidHeader            = VORBIS_HEADER_ID.Equals(info.VorbisParameters.ID);

                    info.VorbisParameters.BitstreamVersion = source.ReadBytes(4);
                    info.VorbisParameters.ChannelMode      = source.ReadByte();
                    info.VorbisParameters.SampleRate       = source.ReadInt32();
                    info.VorbisParameters.BitRateMaximal   = source.ReadInt32();
                    info.VorbisParameters.BitRateNominal   = source.ReadInt32();
                    info.VorbisParameters.BitRateMinimal   = source.ReadInt32();
                    info.VorbisParameters.BlockSize        = source.ReadByte();
                    info.VorbisParameters.StopFlag         = source.ReadByte();
                }
                else if (OPUS_HEADER_ID.StartsWith(headerStart))
                {
                    contents = CONTENTS_OPUS;
                    info.OpusParameters.ID = Utils.Latin1Encoding.GetString(source.ReadBytes(8));
                    isValidHeader          = OPUS_HEADER_ID.Equals(info.OpusParameters.ID);

                    info.OpusParameters.Version            = source.ReadByte();
                    info.OpusParameters.OutputChannelCount = source.ReadByte();
                    info.OpusParameters.PreSkip            = source.ReadUInt16();
                    //info.OpusParameters.InputSampleRate = source.ReadUInt32();
                    info.OpusParameters.InputSampleRate = 48000; // Actual sample rate is hardware-dependent. Let's assume for now that the hardware ATL runs on supports 48KHz
                    source.Seek(4, SeekOrigin.Current);
                    info.OpusParameters.OutputGain = source.ReadInt16();

                    info.OpusParameters.ChannelMappingFamily = source.ReadByte();

                    if (info.OpusParameters.ChannelMappingFamily > 0)
                    {
                        info.OpusParameters.StreamCount        = source.ReadByte();
                        info.OpusParameters.CoupledStreamCount = source.ReadByte();

                        info.OpusParameters.ChannelMapping = new byte[info.OpusParameters.OutputChannelCount];
                        for (int i = 0; i < info.OpusParameters.OutputChannelCount; i++)
                        {
                            info.OpusParameters.ChannelMapping[i] = source.ReadByte();
                        }
                    }
                }

                if (isValidHeader)
                {
                    info.CommentHeaderStart = source.Position;
                    IList <long> pagePos = new List <long>();

                    // Reads all related Vorbis pages that describe Comment and Setup headers
                    // and concatenate their content into a single, continuous data stream
                    bool loop  = true;
                    bool first = true;
                    using (MemoryStream s = new MemoryStream())
                    {
                        // Reconstruct the whole Comment header from OGG pages to a MemoryStream
                        while (loop)
                        {
                            info.SetupHeaderEnd              = source.Position; // When the loop stops, cursor is starting to read a brand new page located after Comment _and_ Setup headers
                            info.CommentHeader.ID            = Utils.Latin1Encoding.GetString(source.ReadBytes(4));
                            info.CommentHeader.StreamVersion = source.ReadByte();
                            info.CommentHeader.TypeFlag      = source.ReadByte();
                            // 0 marks a new page
                            if (0 == info.CommentHeader.TypeFlag)
                            {
                                loop = first;
                            }
                            if (loop)
                            {
                                info.CommentHeader.AbsolutePosition = source.ReadUInt64();
                                info.CommentHeader.Serial           = source.ReadInt32();
                                info.CommentHeader.PageNumber       = source.ReadInt32();
                                info.CommentHeader.Checksum         = source.ReadUInt32();
                                info.CommentHeader.Segments         = source.ReadByte();
                                info.CommentHeader.LacingValues     = source.ReadBytes(info.CommentHeader.Segments);
                                s.Write(source.ReadBytes(info.CommentHeader.GetPageLength()), 0, info.CommentHeader.GetPageLength());
                                pagePos.Add(info.SetupHeaderEnd);
                            }
                            first = false;
                        }

                        if (readTagParams.PrepareForWriting) // Metrics to prepare writing
                        {
                            if (pagePos.Count > 1)
                            {
                                source.Position = pagePos[pagePos.Count - 2];
                            }
                            else
                            {
                                source.Position = pagePos[0];
                            }

                            // Determine the boundaries of 3rd header (Setup header) by searching from last-but-one page
                            if (StreamUtils.FindSequence(source, Utils.Latin1Encoding.GetBytes(VORBIS_SETUP_ID)))
                            {
                                info.SetupHeaderStart = source.Position - VORBIS_SETUP_ID.Length;
                                info.CommentHeaderEnd = info.SetupHeaderStart;

                                if (pagePos.Count > 1)
                                {
                                    int firstSetupPage = -1;
                                    for (int i = 1; i < pagePos.Count; i++)
                                    {
                                        if (info.CommentHeaderEnd < pagePos[i])
                                        {
                                            info.CommentHeaderSpanPages = i - 1;
                                            firstSetupPage = i - 1;
                                        }
                                        if (info.SetupHeaderEnd < pagePos[i])
                                        {
                                            info.SetupHeaderSpanPages = i - firstSetupPage;
                                        }
                                    }
                                    /// Not found yet => comment header takes up all pages, and setup header is on the end of the last page
                                    if (-1 == firstSetupPage)
                                    {
                                        info.CommentHeaderSpanPages = pagePos.Count;
                                        info.SetupHeaderSpanPages   = 1;
                                    }
                                }
                                else
                                {
                                    info.CommentHeaderSpanPages = 1;
                                    info.SetupHeaderSpanPages   = 1;
                                }
                            }
                        }

                        // Get total number of samples
                        info.Samples = getSamples(source);

                        // Read metadata from the reconstructed Comment header inside the memoryStream
                        if (readTagParams.ReadTag)
                        {
                            BinaryReader msr = new BinaryReader(s);
                            s.Seek(0, SeekOrigin.Begin);

                            string tagId;
                            bool   isValidTagHeader = false;
                            if (contents.Equals(CONTENTS_VORBIS))
                            {
                                tagId            = Utils.Latin1Encoding.GetString(msr.ReadBytes(7));
                                isValidTagHeader = (VORBIS_TAG_ID.Equals(tagId));
                            }
                            else if (contents.Equals(CONTENTS_OPUS))
                            {
                                tagId            = Utils.Latin1Encoding.GetString(msr.ReadBytes(8));
                                isValidTagHeader = (OPUS_TAG_ID.Equals(tagId));
                            }

                            if (isValidTagHeader)
                            {
                                vorbisTag.Read(msr, readTagParams);
                            }
                        }
                    } // using MemoryStream

                    result = true;
                }
            }

            return(result);
        }
Beispiel #2
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);
        }
Beispiel #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);
        }
Beispiel #4
0
        // ---------------------------------------------------------------------------

        // Read total samples of OGG file, which are located on the very last page of the file
        private ulong getSamples(BufferedBinaryReader source)
        {
            OggHeader header = new OggHeader();

            string headerId;
            byte   typeFlag;

            byte[] lacingValues   = new byte[255];
            byte   nbLacingValues = 0;
            long   nextPageOffset = 0;

            // TODO - fine tune seekSize value
            int seekSize = (int)Math.Round(MAX_PAGE_SIZE * 0.75);

            if (seekSize > source.Length)
            {
                seekSize = (int)Math.Round(source.Length * 0.5);
            }
            source.Seek(-seekSize, SeekOrigin.End);
            if (!StreamUtils.FindSequence(source, Utils.Latin1Encoding.GetBytes(OGG_PAGE_ID)))
            {
                LogDelegator.GetLogDelegate()(Log.LV_ERROR, "No OGG header found; aborting read operation"); // Throw exception ?
                return(0);
            }
            source.Seek(-4, SeekOrigin.Current);

            // Iterate until last page is encountered
            do
            {
                if (source.Position + nextPageOffset + 27 > source.Length) // End of stream about to be reached => last OGG header did not have the proper type flag
                {
                    break;
                }

                source.Seek(nextPageOffset, SeekOrigin.Current);

                headerId = Utils.Latin1Encoding.GetString(source.ReadBytes(4));

                if (headerId.Equals(OGG_PAGE_ID))
                {
                    source.Seek(1, SeekOrigin.Current);
                    typeFlag = source.ReadByte();
                    source.Seek(20, SeekOrigin.Current);
                    nbLacingValues = source.ReadByte();
                    nextPageOffset = 0;
                    source.Read(lacingValues, 0, nbLacingValues);
                    for (int i = 0; i < nbLacingValues; i++)
                    {
                        nextPageOffset += lacingValues[i];
                    }
                }
                else
                {
                    LogDelegator.GetLogDelegate()(Log.LV_ERROR, "Invalid OGG header found while looking for total samples; aborting read operation"); // Throw exception ?
                    return(0);
                }
            } while (0 == (typeFlag & 0x04)); // 0x04 marks the last page of the logical bitstream


            // Stream is positioned at the end of the last page header; backtracking to read AbsolutePosition field
            source.Seek(-nbLacingValues - 21, SeekOrigin.Current);

            return(source.ReadUInt64());
        }
Beispiel #5
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))))
            {
                throw new InvalidDataException(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

            AudioDataOffset = bSource.Position;
            AudioDataSize   = sizeInfo.FileSize - AudioDataOffset;

            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 = 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);
        }
Beispiel #6
0
        private void readPatterns(BufferedBinaryReader source, int nbPatterns)
        {
            byte                   firstByte;
            IList <Event>          aRow;
            IList <IList <Event> > aPattern;

            uint   headerLength;
            ushort nbRows;
            uint   packedDataSize;

            for (int i = 0; i < nbPatterns; i++)
            {
                aPattern = new List <IList <Event> >();

                headerLength = source.ReadUInt32();
                source.Seek(1, SeekOrigin.Current); // Packing type
                nbRows = source.ReadUInt16();

                packedDataSize = source.ReadUInt16();

                if (packedDataSize > 0) // The patterns is not empty
                {
                    for (int j = 0; j < nbRows; j++)
                    {
                        aRow = new List <Event>();

                        for (int k = 0; k < nbChannels; k++)
                        {
                            Event e = new Event();
                            e.Channel = k + 1;

                            firstByte = source.ReadByte();
                            if ((firstByte & 0x80) > 0) // Most Significant Byte (MSB) is set => packed data layout
                            {
                                if ((firstByte & 0x1) > 0)
                                {
                                    source.Seek(1, SeekOrigin.Current);                       // Note
                                }
                                if ((firstByte & 0x2) > 0)
                                {
                                    source.Seek(1, SeekOrigin.Current);                       // Instrument
                                }
                                if ((firstByte & 0x4) > 0)
                                {
                                    source.Seek(1, SeekOrigin.Current);                       // Volume
                                }
                                if ((firstByte & 0x8) > 0)
                                {
                                    e.Command = source.ReadByte();                                       // Effect type
                                }
                                if ((firstByte & 0x10) > 0)
                                {
                                    e.Info = source.ReadByte();                                          // Effect param
                                }
                            }
                            else     // No MSB set => standard data layout
                            // firstByte is the Note
                            {
                                source.Seek(1, SeekOrigin.Current); // Instrument
                                source.Seek(1, SeekOrigin.Current); // Volume
                                e.Command = source.ReadByte();
                                e.Info    = source.ReadByte();
                            }

                            aRow.Add(e);
                        }

                        aPattern.Add(aRow);
                    }
                }

                FPatterns.Add(aPattern);
            }
        }
Beispiel #7
0
        private void readPatterns(BufferedBinaryReader source, IList <UInt32> patternPointers)
        {
            ushort                  nbRows;
            byte                    rowNum;
            byte                    what;
            byte                    maskVariable = 0;
            IList <Event>           aRow;
            IList <IList <Event> >  aPattern;
            IDictionary <int, byte> maskVariables = new Dictionary <int, byte>();

            foreach (UInt32 pos in patternPointers)
            {
                aPattern = new List <IList <Event> >();
                if (pos > 0)
                {
                    source.Seek(pos, SeekOrigin.Begin);
                    aRow   = new List <Event>();
                    rowNum = 0;
                    source.Seek(2, SeekOrigin.Current); // patternSize
                    nbRows = source.ReadUInt16();
                    source.Seek(4, SeekOrigin.Current); // unused data

                    do
                    {
                        what = source.ReadByte();

                        if (what > 0)
                        {
                            Event theEvent = new Event();
                            theEvent.Channel = (what - 1) & 63;
                            if ((what & 128) > 0)
                            {
                                maskVariable = source.ReadByte();
                                maskVariables[theEvent.Channel] = maskVariable;
                            }
                            else if (maskVariables.ContainsKey(theEvent.Channel))
                            {
                                maskVariable = maskVariables[theEvent.Channel];
                            }
                            else
                            {
                                maskVariable = 0;
                            }

                            if ((maskVariable & 1) > 0)
                            {
                                source.Seek(1, SeekOrigin.Current);                         // Note
                            }
                            if ((maskVariable & 2) > 0)
                            {
                                source.Seek(1, SeekOrigin.Current);                         // Instrument
                            }
                            if ((maskVariable & 4) > 0)
                            {
                                source.Seek(1, SeekOrigin.Current);                         // Volume/panning
                            }
                            if ((maskVariable & 8) > 0)
                            {
                                theEvent.Command = source.ReadByte();
                                theEvent.Info    = source.ReadByte();
                            }

                            aRow.Add(theEvent);
                        }
                        else // what = 0 => end of row
                        {
                            aPattern.Add(aRow);
                            aRow = new List <Event>();
                            rowNum++;
                        }
                    } while (rowNum < nbRows);
                }

                patterns.Add(aPattern);
            }
        }
Beispiel #8
0
        private static FrameHeader findFrame(BufferedBinaryReader source, ref VBRData oVBR, SizeInfo sizeInfo)
        {
            byte[]      headerData = new byte[4];
            FrameHeader result     = new FrameHeader();

            source.Read(headerData, 0, 4);
            result.Found = isValidFrameHeader(headerData);

            /*
             * Many things can actually be found before a proper MP3 header :
             *    - Padding with 0x55, 0xAA and even 0xFF bytes
             *    - RIFF header declaring either MP3 or WAVE data
             *    - Xing encoder-specific frame
             *    - One of the above with a few "parasite" bytes before their own header
             *
             * The most solid way to deal with all of them is to "scan" the file until proper MP3 header is found.
             * This method may not the be fastest, but ensures audio data is actually detected, whatever garbage lies before
             */

            if (!result.Found)
            {
                // "Quick win" for files starting with padding bytes
                // 4 identical bytes => MP3 starts with padding bytes => Skip padding
                if ((headerData[0] == headerData[1]) && (headerData[1] == headerData[2]) && (headerData[2] == headerData[3]))
                {
                    // Scan the whole padding until it stops
                    while (headerData[0] == source.ReadByte())
                    {
                        ;
                    }

                    source.Seek(-1, SeekOrigin.Current);

                    // If padding uses 0xFF bytes, take one step back in case MP3 header lies there
                    if (0xFF == headerData[0])
                    {
                        source.Seek(-1, SeekOrigin.Current);
                    }

                    source.Read(headerData, 0, 4);
                    result.Found = isValidFrameHeader(headerData);
                }

                // Blindly look for the MP3 header
                if (!result.Found)
                {
                    source.Seek(-4, SeekOrigin.Current);
                    long limit = sizeInfo.ID3v2Size + (long)Math.Round((source.Length - sizeInfo.ID3v2Size) * 0.3);

                    // Look for the beginning of the MP3 header (2nd byte is variable, so it cannot be searched that way)
                    while (!result.Found && source.Position < limit)
                    {
                        while (0xFF != source.ReadByte() && source.Position < limit)
                        {
                            ;
                        }

                        source.Seek(-1, SeekOrigin.Current);
                        source.Read(headerData, 0, 4);
                        result.Found = isValidFrameHeader(headerData);

                        // Valid header candidate found
                        // => let's see if it is a legit MP3 header by using its Size descriptor to find the next header
                        if (result.Found)
                        {
                            result.LoadFromByteArray(headerData);

                            result.Position = source.Position - 4;
                            result.Size     = getFrameSize(result);

                            byte[] nextHeaderData = new byte[4];
                            source.Seek(result.Position + result.Size, SeekOrigin.Begin);
                            source.Read(nextHeaderData, 0, 4);
                            result.Found = isValidFrameHeader(nextHeaderData);

                            if (result.Found)
                            {
                                source.Seek(result.Position + 4, SeekOrigin.Begin); // Go back to header candidate position
                                break;
                            }
                            else
                            {
                                // Restart looking for a candidate
                                source.Seek(result.Position + 1, SeekOrigin.Begin);
                            }
                        }
                        else
                        {
                            source.Seek(-3, SeekOrigin.Current);
                        }
                    }
                }
            }

            if (result.Found)
            {
                result.LoadFromByteArray(headerData);

                result.Position = source.Position - 4;

                // result.Xing = isXing(i + 4, Data); // Will look into it when encoder ID is needed by upper interfaces

                // Look for VBR signature
                oVBR = findVBR(source, result.Position + getVBRDeviation(result));
            }

            return(result);
        }
Beispiel #9
0
    public new VigObject FUN_2C344(XOBF_DB param1, ushort param2, uint param3)
    {
        VigMesh              mVar1;
        int                  iVar2;
        VigObject            oVar3;
        BufferedBinaryReader brVar4;
        ConfigContainer      puVar5;

        puVar5 = param1.ini.configContainers[param2];

        if ((puVar5.flag & 0x7ff) == 0x7ff)
        {
            vMesh = null;
        }
        else
        {
            mVar1 = param1.FUN_1FD18(gameObject, puVar5.flag & 0x7ffU, true);
            vMesh = mVar1;
        }

        if (puVar5.colliderID < 0)
        {
            vCollider = null;
        }
        else
        {
            VigCollider collider = param1.cbbList[puVar5.colliderID];
            vCollider = new VigCollider(collider.buffer);
        }

        vData  = param1;
        DAT_1A = (short)param2;

        if ((param3 & 8) == 0)
        {
            vAnim = null;
        }
        else
        {
            brVar4 = new BufferedBinaryReader(param1.animations);

            if (brVar4.GetBuffer() != null)
            {
                iVar2 = brVar4.ReadInt32(param2 * 4 + 4);

                if (iVar2 != 0)
                {
                    brVar4.Seek(iVar2, SeekOrigin.Begin);
                }
                else
                {
                    brVar4 = null;
                }
            }
            else
            {
                brVar4 = null;
            }

            vAnim = brVar4;
        }

        DAT_4A = GameManager.instance.timer;

        if ((param3 & 2) == 0 && puVar5.next != 0xffff)
        {
            oVar3  = param1.ini.FUN_2C17C_3(puVar5.next, typeof(WheelChild), param3 | 0x21);
            child2 = oVar3;

            if (oVar3 != null)
            {
                oVar3.ApplyTransformation();
                child2.parent = this;
            }
        }
        else
        {
            child2 = null;
        }

        return(this);
    }
    public VigObject FUN_2C17C(ushort param1, Dictionary <int, Type> param2, uint param3)
    {
        VigObject oVar1;
        int       iVar2;
        VigObject oVar3;

        byte[] aVar3;
        BufferedBinaryReader brVar4;
        ConfigContainer      psVar5;

        psVar5 = configContainers[param1];

        if ((short)psVar5.flag < 0 || (255 < (short)psVar5.objID && (param3 & 0x20) != 0))
        {
            if ((param3 & 1) == 0 || (short)psVar5.previous == -1)
            {
                oVar1 = null;
            }
            else
            {
                oVar1 = FUN_2C17C(psVar5.previous, param2, param3);
            }
        }
        else
        {
            if (param2.ContainsKey(param1))
            {
                oVar1 = FUN_2BF44(psVar5, param2[param1]);
            }
            else
            {
                oVar1 = FUN_2BF44(psVar5, typeof(VigObject));
            }

            oVar1.DAT_1A = (short)param1;
            oVar1.id     = (short)psVar5.objID;

            if ((param3 & 8) == 0)
            {
                oVar1.vAnim = null;
            }
            else
            {
                aVar3  = xobf.animations;
                brVar4 = null;

                if (aVar3.Length > 0)
                {
                    brVar4 = new BufferedBinaryReader(aVar3);
                    iVar2  = brVar4.ReadInt32(param1 * 4 + 4);

                    if (iVar2 != 0)
                    {
                        brVar4.Seek(iVar2, SeekOrigin.Begin);
                    }
                    else
                    {
                        brVar4 = null;
                    }
                }

                oVar1.vAnim = brVar4;
            }

            oVar1.DAT_4A = GameManager.instance.timer;

            if ((param3 & 1) != 0 && (short)psVar5.previous != -1)
            {
                oVar3       = FUN_2C17C(psVar5.previous, param2, param3);
                oVar1.child = oVar3;

                if (oVar3 != null)
                {
                    oVar3.parent = oVar1;
                    oVar1.child.ApplyTransformation();
                }
            }

            if ((param3 & 2) == 0 && (short)psVar5.next != -1)
            {
                oVar3        = FUN_2C17C(psVar5.next, param2, param3 | 33);
                oVar1.child2 = oVar3;

                if (oVar3 != null)
                {
                    oVar3.parent = oVar1;
                    oVar1.child2.ApplyTransformation();
                }
            }
        }

        return(oVar1);
    }
Beispiel #11
0
 internal IEnumerable <float> EnumerateDataValues(BufferedBinaryReader reader, DataSection dataSection, long dataPointsNumber)
 {
     reader.Seek(dataSection.DataOffset, SeekOrigin.Begin);
     return(DoEnumerateDataValues(reader, dataSection, dataPointsNumber));
 }