private void ParseEvents(int offset, int length, int trackNumber) { string s; int n = offset + length, i, j = 0; MidiEvent mtrkEvent = null; MidiMetaEvent metaEvent; /* A track chunk is a stream of MIDI (MTrk) events. Process each such * event in this part of the byte array comprising the track chunk. */ for (i = offset; i < n; i += mtrkEvent.Size) { /* In order to know what kind of event to instantiate, we must read the event's status * byte, which requires skipping past the delta-time (stored as a variable-length quantity). */ for (j = i; j < this.Bytes.Length && (this.Bytes[j] & 0x80) > 0; ++j) { if (j - i > 3) { s = string.Format("{0} (@ {1} {2})", Properties.Resources.InvalidVLQ, Properties.Resources.Byte, i); this.AddErrorText(s, trackNumber); return; } } if (++j >= this.Bytes.Length) { break; } /* Instantiate an event object of the appropriate type (based on the status byte). */ switch (this.Bytes[j]) { case 0xFF: mtrkEvent = new MidiMetaEvent(this, i); break; case 0xF7: mtrkEvent = new MidiSysExEvent(this, i); break; case 0xF0: mtrkEvent = new MidiSysExEvent(this, i); break; default: mtrkEvent = new MidiChannelEvent(this, i); break; } this.Items.Add(mtrkEvent); this.SetTotalTime(this.ItemCount - 1); /* If the event is a MIDI channel message/event that does not use * running status, use it to set the running status at this byte offset. */ if (++j >= this.Bytes.Length) { break; } MidiChannelEvent channelEvent = mtrkEvent as MidiChannelEvent; if (channelEvent != null && !channelEvent.RunningStatus) { this.SetRunningStatus(i, channelEvent.Status); } /* If the event is a meta-event representing a key signature, * use it to set the key signature at the appropriate time. */ if (++j >= this.Bytes.Length) { break; } metaEvent = MidiFile.ItemToKeySignatureEvent(mtrkEvent); if (metaEvent != null) { this.SetKeySignature(metaEvent); } } /* If we ran out of data, add an error message. */ if (j >= this.Bytes.Length) { s = string.Format(Properties.Resources.MismatchFormat, Properties.Resources.Byte, length, i - offset); this.AddErrorText(s, trackNumber); } /* The last event in a track chunk should be an End of Track meta-event. */ metaEvent = mtrkEvent as MidiMetaEvent; if (metaEvent == null || (metaEvent != null && metaEvent.Type != MidiMetaEvent.EndOfTrackType)) { this.AddErrorText(Properties.Resources.NoEndOfTrack, trackNumber); } }
/// <summary>Initializes a new instance of the MidiMetaEvent class.</summary> /// <param name="file">MidiFile object representing the MIDI file to which this item belongs.</param> /// <param name="offset">Offset into the file's byte array at which this item begins.</param> public MidiMetaEvent(MidiFile file, int offset) : base(file, offset) { }
/// <summary>Initializes a new instance of the MidiChannelEvent class.</summary> /// <param name="file">MidiFile object representing the MIDI file to which this item belongs.</param> /// <param name="offset">Offset into the file's byte array at which this item begins.</param> public MidiChannelEvent(MidiFile file, int offset) : base(file, offset) { }
/**************** * Constructors * ****************/ #region Public Constructors /// <summary>Initializes a new instance of the MidiItem class.</summary> /// <param name="file">MidiFile object representing the MIDI file to which this item belongs.</param> /// <param name="offset">Offset into the file's byte array at which this item begins.</param> public MidiItem(MidiFile file, int offset) { this._File = file; this.Offset = offset; }