/// <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++;
                    }
                }
            }
        }
Example #2
0
        public void PrepareForExport()
        {
            MidiEventComparer comparer = new MidiEventComparer();

            foreach (IList <MidiEvent> list in this.trackEvents)
            {
                List <MidiEvent> list2 = (List <MidiEvent>)list;
                MergeSort.Sort <MidiEvent>(list2, comparer);
                int i = 0;
                while (i < list2.Count - 1)
                {
                    if (MidiEvent.IsEndTrack(list2[i]))
                    {
                        list2.RemoveAt(i);
                    }
                    else
                    {
                        i++;
                    }
                }
            }
            int j = 0;

            while (j < this.trackEvents.Count)
            {
                IList <MidiEvent> list3 = this.trackEvents[j];
                if (list3.Count == 0)
                {
                    this.RemoveTrack(j);
                }
                else if (list3.Count == 1 && MidiEvent.IsEndTrack(list3[0]))
                {
                    this.RemoveTrack(j);
                }
                else
                {
                    if (!MidiEvent.IsEndTrack(list3[list3.Count - 1]))
                    {
                        list3.Add(new MetaEvent(MetaEventType.EndTrack, 0, list3[list3.Count - 1].AbsoluteTime));
                    }
                    j++;
                }
            }
        }
Example #3
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 (BinaryWriter writer = new BinaryWriter(File.Create(filename)))
            {
                writer.Write(Encoding.ASCII.GetBytes("MThd"));
                writer.Write(SwapUInt32((uint)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.ASCII.GetBytes("MTrk"));
                    long trackSizePosition = writer.BaseStream.Position;
                    writer.Write(SwapUInt32((uint)0));

                    long absoluteTime = events.StartAbsoluteTime;

                    // use a stable sort to preserve ordering of MIDI events whose
                    // absolute times are the same
                    //eventList.Sort(new MidiEventComparer());
                    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 (MidiEvent 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;
                }
            }
        }
Example #4
0
        private static void ExportBinary(BinaryWriter writer, MidiEventCollection events)
        {
            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;
            }
        }