/// <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; } } }
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; } }