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