/// <summary>Reads a MIDI stream into a new MidiSequence.</summary> /// <param name="inputStream">The stream containing the MIDI data.</param> /// <returns>A MidiSequence containing the parsed MIDI data.</returns> public static MidiSequence Import(Stream inputStream) { // Validate input if (inputStream == null) { throw new ArgumentNullException("inputStream"); } if (!inputStream.CanRead) { throw new ArgumentException("Stream must be readable.", "inputStream"); } // Read in the main MIDI header MThdChunkHeader mainHeader = MThdChunkHeader.Read(inputStream); // Read in all of the tracks MTrkChunkHeader [] trackChunks = new MTrkChunkHeader[mainHeader.NumberOfTracks]; for (int i = 0; i < mainHeader.NumberOfTracks; i++) { trackChunks[i] = MTrkChunkHeader.Read(inputStream); } // Create the MIDI sequence MidiSequence sequence = new MidiSequence(mainHeader.Format, mainHeader.Division); for (int i = 0; i < mainHeader.NumberOfTracks; i++) { sequence.AddTrack(MidiParser.ParseToTrack(trackChunks[i].Data)); } return(sequence); }
/// <summary>Trims a MIDI file to a specified length.</summary> /// <param name="sequence">The sequence to be copied and trimmed.</param> /// <param name="totalTime">The requested time length of the new MIDI sequence.</param> /// <returns>A MIDI sequence with only those events that fell before the requested time limit.</returns> public static MidiSequence Trim(MidiSequence sequence, long totalTime) { // Create a new sequence to mimic the old MidiSequence newSequence = new MidiSequence(sequence.Format, sequence.Division); // Copy each track up to the specified time limit foreach (MidiTrack track in sequence) { // Create a new track in the new sequence to match the old track in the old sequence MidiTrack newTrack = newSequence.AddTrack(); // Convert all times in the old track to deltas track.Events.ConvertDeltasToTotals(); // Copy over all events that fell before the specified time for (int i = 0; i < track.Events.Count && track.Events[i].DeltaTime < totalTime; i++) { newTrack.Events.Add(track.Events[i].Clone()); } // Convert all times back (on both new and old tracks; the new one inherited the totals) track.Events.ConvertTotalsToDeltas(); newTrack.Events.ConvertTotalsToDeltas(); // If the new track lacks an end of track, add one if (!newTrack.HasEndOfTrack) { newTrack.Events.Add(new EndOfTrack(0)); } } // Return the new sequence return(newSequence); }
/// <summary>Plays an individual MIDI track.</summary> /// <param name="track">The track to be played.</param> /// <param name="division">The MIDI division to use for playing the track.</param> public static void Play(MidiTrack track, int division) { // Wrap the track in a sequence and play it MidiSequence tempSequence = new MidiSequence(0, division); tempSequence.AddTrack(track); Play(tempSequence); }
/// <summary>Plays a collection of MIDI events.</summary> /// <param name="events">The events to be played.</param> /// <param name="division">The division to use for playing the events.</param> public static void Play(MidiEventCollection events, int division) { // Add all of the events to a temporary track and sequence, then play it MidiSequence tempSequence = new MidiSequence(0, division); MidiTrack tempTrack = tempSequence.AddTrack(); tempTrack.Events.Add(events); if (!tempTrack.HasEndOfTrack) { tempTrack.Events.Add(new EndOfTrack(0)); } Play(tempSequence); }
public static MidiSequence Convert(MidiSequence sequence, int format, FormatConversionOptions options) { if (sequence == null) { throw new ArgumentNullException("sequence"); } if ((format < 0) || (format > 2)) { throw new ArgumentOutOfRangeException("format", format, "The format must be 0, 1, or 2."); } if (sequence.Format == format) { return sequence; } if ((format != 0) || (sequence.NumberOfTracks == 1)) { sequence.SetFormat(format); return sequence; } MidiSequence sequence2 = new MidiSequence(format, sequence.Division); MidiTrack track = sequence2.AddTrack(); foreach (MidiTrack track2 in sequence) { track2.Events.ConvertDeltasToTotals(); } int num = 0; foreach (MidiTrack track3 in sequence) { foreach (MidiEvent event2 in track3.Events) { if ((((options & FormatConversionOptions.CopyTrackToChannel) > FormatConversionOptions.None) && (event2 is VoiceMidiEvent)) && ((num >= 0) && (num <= 15))) { ((VoiceMidiEvent) event2).Channel = (byte) num; } if (!(event2 is EndOfTrack)) { track.Events.Add(event2); } } num++; } track.Events.SortByTime(); track.Events.ConvertTotalsToDeltas(); track.Events.Add(new EndOfTrack(0L)); return sequence2; }
public static MidiSequence Trim(MidiSequence sequence, long totalTime) { MidiSequence sequence2 = new MidiSequence(sequence.Format, sequence.Division); foreach (MidiTrack track in sequence) { MidiTrack track2 = sequence2.AddTrack(); track.Events.ConvertDeltasToTotals(); for (int i = 0; (i < track.Events.Count) && (track.Events[i].DeltaTime < totalTime); i++) { track2.Events.Add(track.Events[i].Clone()); } track.Events.ConvertTotalsToDeltas(); track2.Events.ConvertTotalsToDeltas(); if (!track2.HasEndOfTrack) { track2.Events.Add(new EndOfTrack(0L)); } } return sequence2; }
public static MidiSequence Import(Stream inputStream) { if (inputStream == null) { throw new ArgumentNullException("inputStream"); } if (!inputStream.CanRead) { throw new ArgumentException("Stream must be readable.", "inputStream"); } MThdChunkHeader header = MThdChunkHeader.Read(inputStream); MTrkChunkHeader[] headerArray = new MTrkChunkHeader[header.NumberOfTracks]; for (int i = 0; i < header.NumberOfTracks; i++) { headerArray[i] = MTrkChunkHeader.Read(inputStream); } MidiSequence sequence = new MidiSequence(header.Format, header.Division); for (int j = 0; j < header.NumberOfTracks; j++) { sequence.AddTrack(MidiParser.ParseToTrack(headerArray[j].Data)); } return sequence; }
/// <summary>Converts a MIDI sequence from its current format to the specified format.</summary> /// <param name="sequence">The sequence to be converted.</param> /// <param name="format">The format to which we want to convert the sequence.</param> /// <param name="options">Options used when doing the conversion.</param> /// <returns>The converted sequence.</returns> /// <remarks> /// This may or may not return the same sequence as passed in. /// Regardless, the reference passed in should not be used after this call as the old /// sequence could be unusable if a different reference was returned. /// </remarks> public static MidiSequence Convert(MidiSequence sequence, int format, FormatConversionOptions options) { // Validate the parameters if (sequence == null) { throw new ArgumentNullException("sequence"); } if (format < 0 || format > 2) { throw new ArgumentOutOfRangeException("format", format, "The format must be 0, 1, or 2."); } // Handle the simple cases if (sequence.Format == format) { return(sequence); // already in requested format } if (format != 0 || sequence.NumberOfTracks == 1) // only requires change in format # { // Change the format and return the same sequence sequence.SetFormat(format); return(sequence); } // Now the hard one, converting to format 0. // We need to combine all tracks into 1. MidiSequence newSequence = new MidiSequence(format, sequence.Division); MidiTrack newTrack = newSequence.AddTrack(); // Iterate through all events in all tracks and change deltaTimes to actual times. // We'll then be able to sort based on time and change them back to deltas later foreach (MidiTrack track in sequence) { track.Events.ConvertDeltasToTotals(); } // Add all events to new track (except for end of track markers!) int trackNumber = 0; foreach (MidiTrack track in sequence) { foreach (MidiEvent midiEvent in track.Events) { // If this event has a channel, and if we're storing tracks as channels, copy to it if ((options & FormatConversionOptions.CopyTrackToChannel) > 0 && (midiEvent is VoiceMidiEvent) && trackNumber >= 0 && trackNumber <= 0xF) { ((VoiceMidiEvent)midiEvent).Channel = (byte)trackNumber; } // Add all events, except for end of track markers (we'll add our own) if (!(midiEvent is EndOfTrack)) { newTrack.Events.Add(midiEvent); } } trackNumber++; } // Sort the events newTrack.Events.SortByTime(); // Now go back through all of the events and update the times to be deltas newTrack.Events.ConvertTotalsToDeltas(); // Put an end of track on for good measure as we've already taken out // all of the ones that were in the original tracks. newTrack.Events.Add(new EndOfTrack(0)); // Return the new sequence return(newSequence); }
public static void Play(MidiEventCollection events, int division) { MidiSequence sequence = new MidiSequence(0, division); MidiTrack track = sequence.AddTrack(); track.Events.Add(events); if (!track.HasEndOfTrack) { track.Events.Add(new EndOfTrack(0L)); } Play(sequence); }
public static void Play(MidiTrack track, int division) { MidiSequence sequence = new MidiSequence(0, division); sequence.AddTrack(track); Play(sequence); }
/// <summary>Trims a MIDI file to a specified length.</summary> /// <param name="sequence">The sequence to be copied and trimmed.</param> /// <param name="totalTime">The requested time length of the new MIDI sequence.</param> /// <returns>A MIDI sequence with only those events that fell before the requested time limit.</returns> public static MidiSequence Trim(MidiSequence sequence, long totalTime) { // Create a new sequence to mimic the old MidiSequence newSequence = new MidiSequence(sequence.Format, sequence.Division); // Copy each track up to the specified time limit foreach(MidiTrack track in sequence) { // Create a new track in the new sequence to match the old track in the old sequence MidiTrack newTrack = newSequence.AddTrack(); // Convert all times in the old track to deltas track.Events.ConvertDeltasToTotals(); // Copy over all events that fell before the specified time for(int i=0; i<track.Events.Count && track.Events[i].DeltaTime < totalTime; i++) { newTrack.Events.Add(track.Events[i].Clone()); } // Convert all times back (on both new and old tracks; the new one inherited the totals) track.Events.ConvertTotalsToDeltas(); newTrack.Events.ConvertTotalsToDeltas(); // If the new track lacks an end of track, add one if (!newTrack.HasEndOfTrack) newTrack.Events.Add(new EndOfTrack(0)); } // Return the new sequence return newSequence; }
/// <summary>Reads a MIDI stream into a new MidiSequence.</summary> /// <param name="inputStream">The stream containing the MIDI data.</param> /// <returns>A MidiSequence containing the parsed MIDI data.</returns> public static MidiSequence Import(Stream inputStream) { // Validate input if (inputStream == null) throw new ArgumentNullException("inputStream"); if (!inputStream.CanRead) throw new ArgumentException("Stream must be readable.", "inputStream"); // Read in the main MIDI header MThdChunkHeader mainHeader = MThdChunkHeader.Read(inputStream); // Read in all of the tracks MTrkChunkHeader [] trackChunks = new MTrkChunkHeader[mainHeader.NumberOfTracks]; for(int i=0; i<mainHeader.NumberOfTracks; i++) { trackChunks[i] = MTrkChunkHeader.Read(inputStream); } // Create the MIDI sequence MidiSequence sequence = new MidiSequence(mainHeader.Format, mainHeader.Division); for(int i=0; i<mainHeader.NumberOfTracks; i++) { sequence.AddTrack(MidiParser.ParseToTrack(trackChunks[i].Data)); } return sequence; }
/// <summary>Converts a MIDI sequence from its current format to the specified format.</summary> /// <param name="sequence">The sequence to be converted.</param> /// <param name="format">The format to which we want to convert the sequence.</param> /// <param name="options">Options used when doing the conversion.</param> /// <returns>The converted sequence.</returns> /// <remarks> /// This may or may not return the same sequence as passed in. /// Regardless, the reference passed in should not be used after this call as the old /// sequence could be unusable if a different reference was returned. /// </remarks> public static MidiSequence Convert(MidiSequence sequence, int format, FormatConversionOptions options) { // Validate the parameters if (sequence == null) throw new ArgumentNullException("sequence"); if (format < 0 || format > 2) throw new ArgumentOutOfRangeException("format", format, "The format must be 0, 1, or 2."); // Handle the simple cases if (sequence.Format == format) return sequence; // already in requested format if (format != 0 || sequence.NumberOfTracks == 1) // only requires change in format # { // Change the format and return the same sequence sequence.SetFormat(format); return sequence; } // Now the hard one, converting to format 0. // We need to combine all tracks into 1. MidiSequence newSequence = new MidiSequence(format, sequence.Division); MidiTrack newTrack = newSequence.AddTrack(); // Iterate through all events in all tracks and change deltaTimes to actual times. // We'll then be able to sort based on time and change them back to deltas later foreach(MidiTrack track in sequence) track.Events.ConvertDeltasToTotals(); // Add all events to new track (except for end of track markers!) int trackNumber = 0; foreach(MidiTrack track in sequence) { foreach(MidiEvent midiEvent in track.Events) { // If this event has a channel, and if we're storing tracks as channels, copy to it if ((options & FormatConversionOptions.CopyTrackToChannel) > 0 && (midiEvent is VoiceMidiEvent) && trackNumber >= 0 && trackNumber <= 0xF) { ((VoiceMidiEvent)midiEvent).Channel = (byte)trackNumber; } // Add all events, except for end of track markers (we'll add our own) if (!(midiEvent is EndOfTrack)) newTrack.Events.Add(midiEvent); } trackNumber++; } // Sort the events newTrack.Events.SortByTime(); // Now go back through all of the events and update the times to be deltas newTrack.Events.ConvertTotalsToDeltas(); // Put an end of track on for good measure as we've already taken out // all of the ones that were in the original tracks. newTrack.Events.Add(new EndOfTrack(0)); // Return the new sequence return newSequence; }
/// <summary>Plays a collection of MIDI events.</summary> /// <param name="events">The events to be played.</param> /// <param name="division">The division to use for playing the events.</param> public static void Play(MidiEventCollection events, int division) { // Add all of the events to a temporary track and sequence, then play it MidiSequence tempSequence = new MidiSequence(0, division); MidiTrack tempTrack = tempSequence.AddTrack(); tempTrack.Events.Add(events); if (!tempTrack.HasEndOfTrack) tempTrack.Events.Add(new EndOfTrack(0)); Play(tempSequence); }