private void ReadHeader(BinaryReader reader) { if (BigEndianHelper.ReadInt32(reader) != 6) //midi header should be 6 bytes long { throw new Exception("Midi header is invalid."); } mTrackFormat = (TrackFormat)BigEndianHelper.ReadInt16(reader); mTracks = new MidiTrack[BigEndianHelper.ReadInt16(reader)]; int div = BigEndianHelper.ReadInt16(reader); mDivision = div & 0x7FFF; mTimeFormat = ((div & 0x8000) > 0) ? TimeFormat.FamesPerSecond : TimeFormat.TicksPerBeat; }
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); }