public MidiTrack(byte[] instPrograms, byte[] drumPrograms, MidiEvent[] midiEvents)
 {
     this.instPrograms = instPrograms;
     this.drumPrograms = drumPrograms;
     this.midiEvents = midiEvents;
     this.notesPlayed = 0;
     this.totalTime = 0;
     this.activeChannels = 0;
 }
 public void CombineTracks()
 {
     //create a new track of the appropriate size
     MidiTrack finalTrack = MergeTracks();
     MidiEvent[][] absevents = new MidiEvent[mTracks.Length][];
     //we have to convert delta times to absolute delta times
     for (int x = 0; x < absevents.Length; x++)
     {
         absevents[x] = new MidiEvent[mTracks[x].MidiEvents.Length];
         for (int x2 = 0, totalDeltaTime = 0; x2 < absevents[x].Length; x2++)
         {//create copies
             absevents[x][x2] = mTracks[x].MidiEvents[x2];
             totalDeltaTime += absevents[x][x2].DeltaTime;
             absevents[x][x2].DeltaTime = totalDeltaTime;
         }
     }
     //sort by absolute delta time also makes sure events occur in order of track and when they are recieved. 
     int eventcount = 0;
     int delta = 0;
     int nextdelta = int.MaxValue;
     int[] counters = new int[absevents.Length];
     while (eventcount < finalTrack.MidiEvents.Length)
     {
         for (int x = 0; x < absevents.Length; x++)
         {
             while (counters[x] < absevents[x].Length && absevents[x][counters[x]].DeltaTime == delta)
             {
                 finalTrack.MidiEvents[eventcount] = absevents[x][counters[x]];
                 eventcount++;
                 counters[x]++;
             }
             if (counters[x] < absevents[x].Length && absevents[x][counters[x]].DeltaTime < nextdelta)
                 nextdelta = absevents[x][counters[x]].DeltaTime;
         }
         delta = nextdelta;
         nextdelta = int.MaxValue;
     }
     //set total time
     finalTrack.EndTime = finalTrack.MidiEvents[finalTrack.MidiEvents.Length - 1].DeltaTime;
     //put back into regular delta time
     for (int x = 0, deltadiff = 0; x < finalTrack.MidiEvents.Length; x++)
     {
         int oldtime = finalTrack.MidiEvents[x].DeltaTime;
         finalTrack.MidiEvents[x].DeltaTime -= deltadiff;
         deltadiff = oldtime;
     }
     this.mTracks = new MidiTrack[] { finalTrack };
     this.mTrackFormat = TrackFormat.SingleTrack;
 }
 private static void TrackVoiceStats(MidiEvent midiEvent, List<byte> instList, List<byte> drumList, ref int channelList, ref int noteOnCount)
 {
     if (midiEvent.Command == 0x90) //note on
     {
         channelList |= 1 << midiEvent.Channel;
         noteOnCount++;
     }
     else if (midiEvent.Command == 0xC0) //prog change
     {
         byte prog = (byte)midiEvent.Data1;
         if (midiEvent.Channel == MidiHelper.DrumChannel && !drumList.Contains(prog))
         {
             drumList.Add(prog);
         }
         else if (!instList.Contains(prog))
         {
             instList.Add(prog);
         }
     }
 }
 private void LoadStream(BinaryReader reader)
 {
     if (!FindHead(reader, 500))
         throw new Exception("Invalid midi file : MThd chunk could not be found.");
     ReadHeader(reader);
     try
     {
         for (int x = 0; x < mTracks.Length; x++)
         {
             mTracks[x] = ReadTrack(reader);
         }
     }
     catch(EndOfStreamException ex)
     {
         System.Diagnostics.Debug.WriteLine(ex.Message + "\nWarning: the midi file may not have one or more invalid tracks.");
         byte[] emptyByte = new byte[0];
         MidiEvent[] emptyEvents = new MidiEvent[0];
         for (int x = 0; x < mTracks.Length; x++)
         {
             if (mTracks[x] == null)
                 mTracks[x] = new MidiTrack(emptyByte, emptyByte, emptyEvents);
         }
     }
 }