예제 #1
0
        // Token: 0x06003227 RID: 12839 RVA: 0x00146D2C File Offset: 0x00144F2C
        internal void Read(MidiReader reader, ReadingSettings settings)
        {
            uint num      = reader.ReadDword();
            long position = reader.Position;

            this.ReadContent(reader, settings, num);
            long num2 = reader.Position - position;

            if (settings.InvalidChunkSizePolicy == InvalidChunkSizePolicy.Abort && num2 != (long)((ulong)num))
            {
                throw new InvalidChunkSizeException((long)((ulong)num), num2);
            }
            long num3 = (long)((ulong)num - (ulong)num2);

            if (num3 > 0L)
            {
                reader.Position += num3;
            }
        }
예제 #2
0
        /// <summary>
        /// Reads chunk from the <see cref="MidiReader"/>'s underlying stream according to
        /// specified <see cref="ReadingSettings"/>.
        /// </summary>
        /// <param name="reader">Reader to read the chunk's data with.</param>
        /// <param name="settings">Settings according to which the chunk's data must be read.</param>
        /// <exception cref="ObjectDisposedException">Method was called after <paramref name="reader"/>
        /// was disposed.</exception>
        /// <exception cref="IOException">An I/O error occurred on the <paramref name="reader"/>'s
        /// underlying stream.</exception>
        /// <exception cref="InvalidChunkSizeException">Actual chunk's size differs from the one declared
        /// in its header.</exception>
        /// <exception cref="NotEnoughBytesException">Size of the chunk cannot be read since the reader's
        /// underlying stream doesn't have enough bytes.</exception>
        internal void Read(MidiReader reader, ReadingSettings settings)
        {
            var size = reader.ReadDword();

            var readerPosition = reader.Position;

            ReadContent(reader, settings, size);

            var bytesRead = reader.Position - readerPosition;

            if (settings.InvalidChunkSizePolicy == InvalidChunkSizePolicy.Abort && bytesRead != size)
            {
                throw new InvalidChunkSizeException(size, bytesRead);
            }

            // Skip unread bytes

            var bytesUnread = size - bytesRead;

            if (bytesUnread > 0)
            {
                reader.Position += bytesUnread;
            }
        }
예제 #3
0
        // Token: 0x0600340E RID: 13326 RVA: 0x001488A0 File Offset: 0x00146AA0
        public static MidiFile Read(Stream stream, ReadingSettings settings = null)
        {
            if (settings == null)
            {
                settings = new ReadingSettings
                {
                    InvalidChannelEventParameterValuePolicy = InvalidChannelEventParameterValuePolicy.SnapToLimits,
                    InvalidChunkSizePolicy = InvalidChunkSizePolicy.Ignore,
                    NotEnoughBytesPolicy   = NotEnoughBytesPolicy.Ignore,
                    InvalidMetaEventParameterValuePolicy = InvalidMetaEventParameterValuePolicy.SnapToLimits,
                    UnexpectedTrackChunksCountPolicy     = UnexpectedTrackChunksCountPolicy.Ignore,
                    TextEncoding = Encoding.UTF8
                };
            }
            MidiFile midiFile = new MidiFile();
            int?     num      = null;
            int      num2     = 0;
            bool     flag     = false;

            try
            {
                using (MidiReader midiReader = new MidiReader(stream))
                {
                    long?  num3 = null;
                    string text = midiReader.ReadString("RIFF".Length);
                    if (text == "RIFF")
                    {
                        midiReader.Position += 12L;
                        uint num4 = midiReader.ReadDword();
                        num3 = new long?(midiReader.Position + (long)((ulong)num4));
                    }
                    else
                    {
                        midiReader.Position -= (long)text.Length;
                    }
                    while (!midiReader.EndReached)
                    {
                        if (num3 != null)
                        {
                            long position = midiReader.Position;
                            long?num5     = num3;
                            if (!(position < num5.GetValueOrDefault() & num5 != null))
                            {
                                break;
                            }
                        }
                        MidiChunk midiChunk = MidiFile.ReadChunk(midiReader, settings, num2, num);
                        if (midiChunk != null)
                        {
                            HeaderChunk headerChunk = midiChunk as HeaderChunk;
                            if (headerChunk != null)
                            {
                                if (!flag)
                                {
                                    num = new int?((int)headerChunk.TracksNumber);
                                    midiFile.TimeDivision    = headerChunk.TimeDivision;
                                    midiFile._originalFormat = new ushort?(headerChunk.FileFormat);
                                }
                                flag = true;
                            }
                            else
                            {
                                if (midiChunk is TrackChunk)
                                {
                                    num2++;
                                }
                                midiFile.Chunks.Add(midiChunk);
                            }
                        }
                    }
                    if (num != null)
                    {
                        int num6 = num2;
                        int?num7 = num;
                        if (!(num6 == num7.GetValueOrDefault() & num7 != null))
                        {
                            MidiFile.ReactOnUnexpectedTrackChunksCount(settings.UnexpectedTrackChunksCountPolicy, num2, num.Value);
                        }
                    }
                    if (!flag)
                    {
                        midiFile.TimeDivision = null;
                        if (settings.NoHeaderChunkPolicy == NoHeaderChunkPolicy.Abort)
                        {
                            throw new NoHeaderChunkException();
                        }
                    }
                }
            }
            catch (NotEnoughBytesException exception)
            {
                MidiFile.ReactOnNotEnoughBytes(settings.NotEnoughBytesPolicy, exception);
            }
            catch (EndOfStreamException exception2)
            {
                MidiFile.ReactOnNotEnoughBytes(settings.NotEnoughBytesPolicy, exception2);
            }
            return(midiFile);
        }
예제 #4
0
        // Token: 0x06003410 RID: 13328 RVA: 0x00148C28 File Offset: 0x00146E28
        private static MidiChunk ReadChunk(MidiReader reader, ReadingSettings settings, int actualTrackChunksCount, int?expectedTrackChunksCount)
        {
            MidiChunk midiChunk = null;

            try
            {
                string text = reader.ReadString(4);
                if (text.Length < 4)
                {
                    NotEnoughBytesPolicy notEnoughBytesPolicy = settings.NotEnoughBytesPolicy;
                    if (notEnoughBytesPolicy == NotEnoughBytesPolicy.Abort)
                    {
                        throw new NotEnoughBytesException("Chunk ID cannot be read since the reader's underlying stream doesn't have enough bytes.", 4L, (long)text.Length);
                    }
                    if (notEnoughBytesPolicy == NotEnoughBytesPolicy.Ignore)
                    {
                        return(null);
                    }
                }
                if (!(text == "MThd"))
                {
                    if (!(text == "MTrk"))
                    {
                        midiChunk = MidiFile.TryCreateChunk(text, settings.CustomChunkTypes);
                    }
                    else
                    {
                        midiChunk = new TrackChunk();
                    }
                }
                else
                {
                    midiChunk = new HeaderChunk();
                }
                if (midiChunk == null)
                {
                    switch (settings.UnknownChunkIdPolicy)
                    {
                    case UnknownChunkIdPolicy.ReadAsUnknownChunk:
                        midiChunk = new UnknownChunk(text);
                        break;

                    case UnknownChunkIdPolicy.Skip:
                    {
                        uint num = reader.ReadDword();
                        reader.Position += (long)((ulong)num);
                        return(null);
                    }

                    case UnknownChunkIdPolicy.Abort:
                        throw new UnknownChunkException("'" + text + "' chunk ID is unknown.", text);
                    }
                }
                if (midiChunk is TrackChunk && expectedTrackChunksCount != null)
                {
                    int?num2 = expectedTrackChunksCount;
                    if (actualTrackChunksCount >= num2.GetValueOrDefault() & num2 != null)
                    {
                        MidiFile.ReactOnUnexpectedTrackChunksCount(settings.UnexpectedTrackChunksCountPolicy, actualTrackChunksCount, expectedTrackChunksCount.Value);
                        ExtraTrackChunkPolicy extraTrackChunkPolicy = settings.ExtraTrackChunkPolicy;
                        if (extraTrackChunkPolicy != ExtraTrackChunkPolicy.Read && extraTrackChunkPolicy == ExtraTrackChunkPolicy.Skip)
                        {
                            uint num3 = reader.ReadDword();
                            reader.Position += (long)((ulong)num3);
                            return(null);
                        }
                    }
                }
                midiChunk.Read(reader, settings);
            }
            catch (NotEnoughBytesException exception)
            {
                MidiFile.ReactOnNotEnoughBytes(settings.NotEnoughBytesPolicy, exception);
            }
            catch (EndOfStreamException exception2)
            {
                MidiFile.ReactOnNotEnoughBytes(settings.NotEnoughBytesPolicy, exception2);
            }
            return(midiChunk);
        }
예제 #5
0
        /// <summary>
        /// Reads a chunk from a MIDI-file.
        /// </summary>
        /// <param name="reader">Reader to read a chunk with.</param>
        /// <param name="settings">Settings according to which a chunk must be read.</param>
        /// <param name="actualTrackChunksCount">Actual count of track chunks at the moment.</param>
        /// <param name="expectedTrackChunksCount">Expected count of track chunks.</param>
        /// <returns>A MIDI-file chunk.</returns>
        /// <exception cref="ObjectDisposedException">Method was called after the reader was disposed.</exception>
        /// <exception cref="IOException">An I/O error occurred on the underlying stream.</exception>
        /// <exception cref="UnknownChunkException">Chunk to be read has unknown ID and that
        /// should be treated as error accordng to the specified <paramref name="settings"/>.</exception>
        /// <exception cref="UnexpectedTrackChunksCountException">Actual track chunks
        /// count is greater than expected one and that should be treated as error according to
        /// the specified <paramref name="settings"/>.</exception>
        /// <exception cref="InvalidChunkSizeException">Actual chunk's size differs from the one declared
        /// in its header and that should be treated as error according to the specified
        /// <paramref name="settings"/>.</exception>
        /// <exception cref="UnknownChannelEventException">Reader has encountered an unknown channel event.</exception>
        /// <exception cref="NotEnoughBytesException">Value cannot be read since the reader's underlying stream
        /// doesn't have enough bytes.</exception>
        /// <exception cref="UnexpectedRunningStatusException">Unexpected running status is encountered.</exception>
        /// <exception cref="MissedEndOfTrackEventException">Track chunk doesn't end with End Of Track event and that
        /// should be treated as error accordng to the specified <paramref name="settings"/>.</exception>
        /// <exception cref="InvalidChannelEventParameterValueException">Value of a channel event's parameter
        /// just read is invalid.</exception>
        /// <exception cref="InvalidMetaEventParameterValueException">Value of a meta event's parameter
        /// just read is invalid.</exception>
        private static MidiChunk ReadChunk(MidiReader reader, ReadingSettings settings, int actualTrackChunksCount, int?expectedTrackChunksCount)
        {
            MidiChunk chunk = null;

            try
            {
                var chunkId = reader.ReadString(MidiChunk.IdLength);
                if (chunkId.Length < MidiChunk.IdLength)
                {
                    switch (settings.NotEnoughBytesPolicy)
                    {
                    case NotEnoughBytesPolicy.Abort:
                        throw new NotEnoughBytesException("Chunk ID cannot be read since the reader's underlying stream doesn't have enough bytes.",
                                                          MidiChunk.IdLength,
                                                          chunkId.Length);

                    case NotEnoughBytesPolicy.Ignore:
                        return(null);
                    }
                }

                //

                switch (chunkId)
                {
                case HeaderChunk.Id:
                    chunk = new HeaderChunk();
                    break;

                case TrackChunk.Id:
                    chunk = new TrackChunk();
                    break;

                default:
                    chunk = TryCreateChunk(chunkId, settings.CustomChunkTypes);
                    break;
                }

                //

                if (chunk == null)
                {
                    switch (settings.UnknownChunkIdPolicy)
                    {
                    case UnknownChunkIdPolicy.ReadAsUnknownChunk:
                        chunk = new UnknownChunk(chunkId);
                        break;

                    case UnknownChunkIdPolicy.Skip:
                        var size = reader.ReadDword();
                        reader.Position += size;
                        return(null);

                    case UnknownChunkIdPolicy.Abort:
                        throw new UnknownChunkException($"'{chunkId}' chunk ID is unknown.", chunkId);
                    }
                }

                //

                if (chunk is TrackChunk && expectedTrackChunksCount != null && actualTrackChunksCount >= expectedTrackChunksCount)
                {
                    ReactOnUnexpectedTrackChunksCount(settings.UnexpectedTrackChunksCountPolicy, actualTrackChunksCount, expectedTrackChunksCount.Value);

                    switch (settings.ExtraTrackChunkPolicy)
                    {
                    case ExtraTrackChunkPolicy.Read:
                        break;

                    case ExtraTrackChunkPolicy.Skip:
                        var size = reader.ReadDword();
                        reader.Position += size;
                        return(null);
                    }
                }

                //

                chunk.Read(reader, settings);
            }
            catch (NotEnoughBytesException ex)
            {
                ReactOnNotEnoughBytes(settings.NotEnoughBytesPolicy, ex);
            }
            catch (EndOfStreamException ex)
            {
                ReactOnNotEnoughBytes(settings.NotEnoughBytesPolicy, ex);
            }

            return(chunk);
        }
예제 #6
0
        /// <summary>
        /// Reads a MIDI file from the stream.
        /// </summary>
        /// <param name="stream">Stream to read file from.</param>
        /// <param name="settings">Settings according to which the file must be read.</param>
        /// <returns>An instance of the <see cref="MidiFile"/> representing a MIDI file was read from the stream.</returns>
        /// <remarks>
        /// Stream must be readable, seekable and be able to provide its position and length via <see cref="Stream.Position"/>
        /// and <see cref="Stream.Length"/> properties.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="stream"/> doesn't support reading. -or
        /// <paramref name="stream"/> doesn't support seeking. -or- <paramref name="stream"/> is already read.</exception>
        /// <exception cref="IOException">An I/O error occurred while reading from the stream.</exception>
        /// <exception cref="ObjectDisposedException"><paramref name="stream"/> is disposed. -or-
        /// Underlying stream reader is disposed.</exception>
        /// <exception cref="NotSupportedException">Unable to get position of the <paramref name="stream"/>. -or
        /// Unable to get length of the <paramref name="stream"/>.</exception>
        /// <exception cref="NoHeaderChunkException">There is no header chunk in a file.</exception>
        /// <exception cref="InvalidChunkSizeException">Actual header or track chunk's size differs from the one declared
        /// in its header and that should be treated as error according to the <paramref name="settings"/>.</exception>
        /// <exception cref="UnknownChunkException">Chunk to be read has unknown ID and that
        /// should be treated as error accordng to the <paramref name="settings"/>.</exception>
        /// <exception cref="UnexpectedTrackChunksCountException">Actual track chunks
        /// count differs from the expected one and that should be treated as error according to
        /// the specified <paramref name="settings"/>.</exception>
        /// <exception cref="UnknownFileFormatException">The header chunk contains unknown file format and
        /// <see cref="ReadingSettings.UnknownFileFormatPolicy"/> property of the <paramref name="settings"/> set to
        /// <see cref="UnknownFileFormatPolicy.Abort"/>.</exception>
        /// <exception cref="NotEnoughBytesException">MIDI file cannot be read since the reader's underlying stream doesn't
        /// have enough bytes.</exception>
        /// <exception cref="UnexpectedRunningStatusException">Unexpected running status is encountered.</exception>
        /// <exception cref="MissedEndOfTrackEventException">Track chunk doesn't end with End Of Track event and that
        /// should be treated as error accordng to the specified <paramref name="settings"/>.</exception>
        /// <exception cref="InvalidChannelEventParameterValueException">Value of a channel event's parameter
        /// just read is invalid.</exception>
        /// <exception cref="InvalidMetaEventParameterValueException">Value of a meta event's parameter
        /// just read is invalid.</exception>
        public static MidiFile Read(Stream stream, ReadingSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(stream), stream);

            if (!stream.CanRead)
            {
                throw new ArgumentException("Stream doesn't support reading.", nameof(stream));
            }

            if (!stream.CanSeek)
            {
                throw new ArgumentException("Stream doesn't support seeking.", nameof(stream));
            }

            if (stream.Position >= stream.Length)
            {
                throw new ArgumentException("Stream is already read.", nameof(stream));
            }

            //

            if (settings == null)
            {
                settings = new ReadingSettings();
            }

            var file = new MidiFile();

            int? expectedTrackChunksCount = null;
            int  actualTrackChunksCount   = 0;
            bool headerChunkIsRead        = false;

            //

            try
            {
                using (var reader = new MidiReader(stream))
                {
                    // Read RIFF header

                    long?smfEndPosition = null;

                    var chunkId = reader.ReadString(RiffChunkId.Length);
                    if (chunkId == RiffChunkId)
                    {
                        reader.Position += RmidPreambleSize;
                        var smfSize = reader.ReadDword();
                        smfEndPosition = reader.Position + smfSize;
                    }
                    else
                    {
                        reader.Position -= chunkId.Length;
                    }

                    // Read SMF

                    while (!reader.EndReached && (smfEndPosition == null || reader.Position < smfEndPosition))
                    {
                        // Read chunk

                        var chunk = ReadChunk(reader, settings, actualTrackChunksCount, expectedTrackChunksCount);
                        if (chunk == null)
                        {
                            continue;
                        }

                        // Process header chunk

                        var headerChunk = chunk as HeaderChunk;
                        if (headerChunk != null)
                        {
                            if (!headerChunkIsRead)
                            {
                                expectedTrackChunksCount = headerChunk.TracksNumber;
                                file.TimeDivision        = headerChunk.TimeDivision;
                                file._originalFormat     = headerChunk.FileFormat;
                            }

                            headerChunkIsRead = true;
                            continue;
                        }

                        // Process track chunk

                        if (chunk is TrackChunk)
                        {
                            actualTrackChunksCount++;
                        }

                        // Add chunk to chunks collection of the file

                        file.Chunks.Add(chunk);
                    }

                    if (expectedTrackChunksCount != null && actualTrackChunksCount != expectedTrackChunksCount)
                    {
                        ReactOnUnexpectedTrackChunksCount(settings.UnexpectedTrackChunksCountPolicy, actualTrackChunksCount, expectedTrackChunksCount.Value);
                    }
                }

                // Process header chunks count

                if (!headerChunkIsRead)
                {
                    file.TimeDivision = null;

                    if (settings.NoHeaderChunkPolicy == NoHeaderChunkPolicy.Abort)
                    {
                        throw new NoHeaderChunkException();
                    }
                }
            }
            catch (NotEnoughBytesException ex)
            {
                ReactOnNotEnoughBytes(settings.NotEnoughBytesPolicy, ex);
            }
            catch (EndOfStreamException ex)
            {
                ReactOnNotEnoughBytes(settings.NotEnoughBytesPolicy, ex);
            }

            //

            return(file);
        }