private static IEnumerable <TrackChunk> ConvertTrackChunks(IEnumerable <TrackChunk> trackChunks, MidiFileFormat format)
        {
            var chunksConverter = ChunksConverterFactory.GetConverter(format);

            return(chunksConverter.Convert(trackChunks)
                   .OfType <TrackChunk>());
        }
Beispiel #2
0
        /// <summary>
        /// Writes current <see cref="MidiFile"/> to the stream.
        /// </summary>
        /// <param name="stream">Stream to write file's data to.</param>
        /// <param name="format">Format of the file to be written.</param>
        /// <param name="settings">Settings according to which the file must be written. Specify <c>null</c> to use
        /// default settings.</param>
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="stream"/> doesn't support writing.</exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="format"/> specified an invalid value.</exception>
        /// <exception cref="InvalidOperationException">Time division is <c>null</c>.</exception>
        /// <exception cref="IOException">An I/O error occurred while writing to the stream.</exception>
        /// <exception cref="ObjectDisposedException"><paramref name="stream"/> is disposed.</exception>
        /// <exception cref="TooManyTrackChunksException">Count of track chunks presented in the file
        /// exceeds maximum value allowed for MIDI file.</exception>
        public void Write(Stream stream, MidiFileFormat format = MidiFileFormat.MultiTrack, WritingSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(stream), stream);
            ThrowIfArgument.IsInvalidEnumValue(nameof(format), format);

            if (TimeDivision == null)
            {
                throw new InvalidOperationException("Time division is null.");
            }

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

            //

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

            if (settings.WriterSettings == null)
            {
                settings.WriterSettings = new WriterSettings();
            }

            using (var writer = new MidiWriter(stream, settings.WriterSettings))
            {
                var chunksConverter = ChunksConverterFactory.GetConverter(format);
                var chunks          = chunksConverter.Convert(Chunks);

                if (settings.WriteHeaderChunk)
                {
                    var trackChunksCount = chunks.Count(c => c is TrackChunk);
                    if (trackChunksCount > ushort.MaxValue)
                    {
                        throw new TooManyTrackChunksException(trackChunksCount);
                    }

                    var headerChunk = new HeaderChunk
                    {
                        FileFormat   = (ushort)format,
                        TimeDivision = TimeDivision,
                        TracksNumber = (ushort)trackChunksCount
                    };
                    headerChunk.Write(writer, settings);
                }

                foreach (var chunk in chunks)
                {
                    if (chunk is UnknownChunk && settings.DeleteUnknownChunks)
                    {
                        continue;
                    }

                    chunk.Write(writer, settings);
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Writes current <see cref="MidiFile"/> to the stream.
        /// </summary>
        /// <param name="stream">Stream to write file's data to.</param>
        /// <param name="format">Format of the file to be written.</param>
        /// <param name="settings">Settings according to which the file must be written.</param>
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="stream"/> doesn't support writing.</exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="format"/> specified an invalid value.</exception>
        /// <exception cref="InvalidOperationException">Time division is null.</exception>
        /// <exception cref="IOException">An I/O error occurred while writing to the stream.</exception>
        /// <exception cref="ObjectDisposedException"><paramref name="stream"/> is disposed. -or-
        /// Underlying stream writer is disposed.</exception>
        /// <exception cref="TooManyTrackChunksException">Count of track chunks presented in the file
        /// exceeds maximum value allowed for MIDI file.</exception>
        public void Write(Stream stream, MidiFileFormat format = MidiFileFormat.MultiTrack, WritingSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(stream), stream);
            ThrowIfArgument.IsInvalidEnumValue(nameof(format), format);

            if (TimeDivision == null)
            {
                throw new InvalidOperationException("Time division is null.");
            }

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

            //

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

            ValidateCustomMetaEventsStatusBytes(settings.CustomMetaEventTypes);
            ValidateCustomChunksIds(Chunks.Where(c => !(c is TrackChunk) && !(c is HeaderChunk)));

            using (var writer = new MidiWriter(stream))
            {
                var chunksConverter = ChunksConverterFactory.GetConverter(format);
                var chunks          = chunksConverter.Convert(Chunks);

                var trackChunksCount = chunks.Count(c => c is TrackChunk);
                if (trackChunksCount > ushort.MaxValue)
                {
                    throw new TooManyTrackChunksException(
                              $"Count of track chunks to be written ({trackChunksCount}) is greater than the valid maximum ({ushort.MaxValue}).",
                              trackChunksCount);
                }

                var headerChunk = new HeaderChunk
                {
                    FileFormat   = (ushort)format,
                    TimeDivision = TimeDivision,
                    TracksNumber = (ushort)trackChunksCount
                };
                headerChunk.Write(writer, settings);

                foreach (var chunk in chunks)
                {
                    if (settings.CompressionPolicy.HasFlag(CompressionPolicy.DeleteUnknownChunks) && chunk is UnknownChunk)
                    {
                        continue;
                    }

                    chunk.Write(writer, settings);
                }
            }
        }
Beispiel #4
0
        public IEnumerable <MidiChunk> Convert(IEnumerable <MidiChunk> chunks)
        {
            ThrowIfArgument.IsNull(nameof(chunks), chunks);

            var trackChunks = chunks.OfType <TrackChunk>().ToArray();

            if (trackChunks.Length == 0)
            {
                return(chunks);
            }

            var sequenceNumbers = trackChunks.Select((c, i) => new { Chunk = c, Number = GetSequenceNumber(c) ?? i })
                                  .ToArray();

            var singleTrackChunksConverter = ChunksConverterFactory.GetConverter(MidiFileFormat.SingleTrack);

            return(sequenceNumbers.GroupBy(n => n.Number)
                   .SelectMany(g => singleTrackChunksConverter.Convert(g.Select(n => n.Chunk)))
                   .Concat(chunks.Where(c => !(c is TrackChunk))));
        }