private static MidiTrack ReadTrack(BinaryReader reader)
 {
     List<byte> instList = new List<byte>();
     List<byte> drumList = new List<byte>();
     List<MidiEvent> eventList = new List<MidiEvent>();
     int channelList = 0;
     int noteOnCount = 0;
     int totalTime = 0;
     while (!new string(IOHelper.Read8BitChars(reader, 4)).Equals("MTrk"))
     {
         int length = BigEndianHelper.ReadInt32(reader);
         while (length > 0)
         {
             length--;
             reader.ReadByte();
         }
     }
     long endPosition = BigEndianHelper.ReadInt32(reader) + reader.BaseStream.Position;
     byte prevStatus = 0;
     while (reader.BaseStream.Position < endPosition)
     {
         int delta = ReadVariableLength(reader);
         totalTime += delta;
         byte status = reader.ReadByte();
         if (status >= 0x80 && status <= 0xEF)
         {//voice message
             prevStatus = status;
             eventList.Add(ReadVoiceMessage(reader, delta, status, reader.ReadByte()));
             TrackVoiceStats(eventList[eventList.Count - 1], instList, drumList, ref channelList, ref noteOnCount);
         }
         else if (status >= 0xF0 && status <= 0xF7)
         {//system common message
             prevStatus = 0;
             eventList.Add(ReadSystemCommonMessage(reader, delta, status));
         }
         else if (status >= 0xF8 && status <= 0xFF)
         {//realtime message
             eventList.Add(ReadRealTimeMessage(reader, delta, status));
         }
         else
         {//data bytes
             if (prevStatus == 0)
             {//if no running status continue to next status byte
                 while ((status & 0x80) != 0x80)
                     status = reader.ReadByte();
                 if (status >= 0x80 && status <= 0xEF)
                 {//voice message
                     prevStatus = status;
                     eventList.Add(ReadVoiceMessage(reader, delta, status, reader.ReadByte()));
                     TrackVoiceStats(eventList[eventList.Count - 1], instList, drumList, ref channelList, ref noteOnCount);
                 }
                 else if (status >= 0xF0 && status <= 0xF7)
                 {//system common message
                     eventList.Add(ReadSystemCommonMessage(reader, delta, status));
                 }
                 else if (status >= 0xF8 && status <= 0xFF)
                 {//realtime message
                     eventList.Add(ReadRealTimeMessage(reader, delta, status));
                 }
             }
             else
             {//otherwise apply running status
                 eventList.Add(ReadVoiceMessage(reader, delta, prevStatus, status));
                 TrackVoiceStats(eventList[eventList.Count - 1], instList, drumList, ref channelList, ref noteOnCount);
             }
         }
     }
     if (reader.BaseStream.Position != endPosition)
         throw new Exception("The track length was invalid for the current MTrk chunk.");
     if (((channelList >> MidiHelper.DrumChannel) & 1) == 1)
     {
         if(!drumList.Contains(0))
             drumList.Add(0);
     }
     else
     {
         if(!instList.Contains(0))
             instList.Add(0);
     }
     MidiTrack track = new MidiTrack(instList.ToArray(), drumList.ToArray(), eventList.ToArray());
     track.NoteOnCount = noteOnCount;
     track.EndTime = totalTime;
     track.ActiveChannels = channelList;
     return track;
 }
        private MidiTrack MergeTracks()
        {
            int eventCount = 0;
            int notesPlayed = 0;
            int activeChannels = 0;
            List<byte> programsUsed = new List<byte>();
            List<byte> drumprogramsUsed = new List<byte>();
            //Loop to get track info
            for (int x = 0; x < mTracks.Length; x++)
            {
                eventCount += mTracks[x].MidiEvents.Length;
                notesPlayed += mTracks[x].NoteOnCount;

                foreach (byte p in mTracks[x].Instruments)
                {
                    if (!programsUsed.Contains(p))
                        programsUsed.Add(p);
                }
                foreach (byte p in mTracks[x].DrumInstruments)
                {
                    if (!drumprogramsUsed.Contains(p))
                        drumprogramsUsed.Add(p);
                }
                activeChannels |= mTracks[x].ActiveChannels;
            }
            MidiTrack track = new MidiTrack(programsUsed.ToArray(), drumprogramsUsed.ToArray(), new MidiEvent[eventCount]);
            track.NoteOnCount = notesPlayed;
            track.ActiveChannels = activeChannels;
            return track;
        }
 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);
         }
     }
 }