예제 #1
0
        /// <summary>
        /// Sorts, removes empty tracks and adds end track markers
        /// </summary>
        public void PrepareForExport()
        {
            var comparer = new MidiEventComparer();

            // 1. sort each track
            foreach (List <MidiEvent> list in trackEvents)
            {
                MergeSort.Sort(list, comparer);

                // 2. remove all End track events except one at the very end
                int index = 0;
                while (index < list.Count - 1)
                {
                    if (MidiEvent.IsEndTrack(list[index]))
                    {
                        list.RemoveAt(index);
                    }
                    else
                    {
                        index++;
                    }
                }
            }

            int track = 0;

            // 3. remove empty tracks and add missing
            while (track < trackEvents.Count)
            {
                IList <MidiEvent> list = trackEvents[track];
                if (list.Count == 0)
                {
                    RemoveTrack(track);
                }
                else
                {
                    if (list.Count == 1 && MidiEvent.IsEndTrack(list[0]))
                    {
                        RemoveTrack(track);
                    }
                    else
                    {
                        if (!MidiEvent.IsEndTrack(list[list.Count - 1]))
                        {
                            list.Add(new MetaEvent(MetaEventType.EndTrack, 0, list[list.Count - 1].AbsoluteTime));
                        }
                        track++;
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Exports a MIDI file
        /// </summary>
        /// <param name="filename">Filename to export to</param>
        /// <param name="events">Events to export</param>
        public static void Export(string filename, MidiEventCollection events)
        {
            if (events.MidiFileType == 0 && events.Tracks > 1)
            {
                throw new ArgumentException("Can't export more than one track to a type 0 file");
            }
            using (var writer = new BinaryWriter(File.Create(filename)))
            {
                writer.Write(Encoding.UTF8.GetBytes("MThd"));
                writer.Write(SwapUInt32(6)); // chunk size
                writer.Write(SwapUInt16((ushort)events.MidiFileType));
                writer.Write(SwapUInt16((ushort)events.Tracks));
                writer.Write(SwapUInt16((ushort)events.DeltaTicksPerQuarterNote));

                for (int track = 0; track < events.Tracks; track++)
                {
                    IList <MidiEvent> eventList = events[track];

                    writer.Write(Encoding.UTF8.GetBytes("MTrk"));
                    long trackSizePosition = writer.BaseStream.Position;
                    writer.Write(SwapUInt32(0));

                    long absoluteTime = events.StartAbsoluteTime;

                    // use a stable sort to preserve ordering of MIDI events whose
                    // absolute times are the same
                    MergeSort.Sort(eventList, new MidiEventComparer());
                    if (eventList.Count > 0)
                    {
                        System.Diagnostics.Debug.Assert(MidiEvent.IsEndTrack(eventList[eventList.Count - 1]), "Exporting a track with a missing end track");
                    }
                    foreach (var midiEvent in eventList)
                    {
                        midiEvent.Export(ref absoluteTime, writer);
                    }

                    uint trackChunkLength = (uint)(writer.BaseStream.Position - trackSizePosition) - 4;
                    writer.BaseStream.Position = trackSizePosition;
                    writer.Write(SwapUInt32(trackChunkLength));
                    writer.BaseStream.Position += trackChunkLength;
                }
            }
        }