/// <summary> /// Constructs a MidiEvent from a BinaryStream /// </summary> /// <param name="reader">The binary stream of MIDI data</param> /// <param name="previous">The previous MIDI event (pass null for first event)</param> /// <returns>A new MidiEvent</returns> public static MIDIEvent ReadNextEvent(BinaryReader reader, MIDIEvent previous) { int deltaTime = ReadVariableLengthInt(reader); MIDICommandCodes commandCode; int channel = 1; byte nextByte = reader.ReadByte(); if ((nextByte & 0x80) == 0) { // a running command - command & channel are same as previous commandCode = previous.CommandCode; channel = previous.Channel; reader.BaseStream.Position--; // need to push this back } else { if ((nextByte & 0xF0) == 0xF0) { // both bytes are used for command code in this case commandCode = (MIDICommandCodes)nextByte; } else { commandCode = (MIDICommandCodes)(nextByte & 0xF0); channel = (nextByte & 0x0F) + 1; } } MIDIEvent midiEvent; switch (commandCode) { case MIDICommandCodes.NoteOn: midiEvent = NoteOnEvent.ReadNoteEvent(reader); break; case MIDICommandCodes.NoteOff: case MIDICommandCodes.KeyAfterTouch: midiEvent = NoteEvent.ReadNoteEvent(reader); break; case MIDICommandCodes.ControlChange: midiEvent = ControlChangeEvent.ReadControlChangeEvent(reader); break; case MIDICommandCodes.PatchChange: midiEvent = PatchChangeEvent.ReadPatchChangeEvent(reader); break; case MIDICommandCodes.ChannelAfterTouch: midiEvent = ChannelAfterTouchEvent.ReadChannelAfterTouchEvent(reader); break; case MIDICommandCodes.PitchWheelChange: midiEvent = PitchWheelChangeEvent.ReadPitchWheelChangeEvent(reader); break; case MIDICommandCodes.TimingClock: case MIDICommandCodes.StartSequence: case MIDICommandCodes.ContinueSequence: case MIDICommandCodes.StopSequence: midiEvent = new MIDIEvent(); break; case MIDICommandCodes.Sysex: midiEvent = SysexEvent.ReadSysexEvent(reader); break; case MIDICommandCodes.MetaEvent: midiEvent = MetaEvent.ReadMetaEvent(reader); break; default: throw new FormatException($"Unsupported MIDI Command Code {(byte)commandCode:X2}"); } midiEvent.Channel = channel; midiEvent.DeltaTime = deltaTime; midiEvent.CommandCode = commandCode; return midiEvent; }
public void AddEvent(MIDIEvent midiEvent) { // If MIDI event is a note off event, pair it with the corresponding note on event if(midiEvent is NoteEvent) { NoteEvent noteEvent = (NoteEvent)midiEvent; if((noteEvent.CommandCode == MIDICommandCodes.NoteOff) || (noteEvent.CommandCode == MIDICommandCodes.NoteOn && noteEvent.Velocity <= 0)) { PairWithNoteOnEvent(noteEvent); } } // Add event to the proper list if (midiEvent is ChannelAfterTouchEvent) { _track.ChannelAfterTouchEvents.Add((ChannelAfterTouchEvent)midiEvent); } else if (midiEvent is ControlChangeEvent) { _track.ControlChangeEvents.Add((ControlChangeEvent)midiEvent); } else if (midiEvent is KeySignatureEvent) { _track.KeySignatureEvents.Add((KeySignatureEvent)midiEvent); } else if (midiEvent is NoteOnEvent) { _track.NoteOnEvents.Add((NoteOnEvent)midiEvent); _outstandingNoteOnEvents.Add((NoteOnEvent)midiEvent); } else if (midiEvent is PatchChangeEvent) { _track.PatchChangeEvents.Add((PatchChangeEvent)midiEvent); } else if (midiEvent is PitchWheelChangeEvent) { _track.PitchWheelChangeEvents.Add((PitchWheelChangeEvent)midiEvent); } else if (midiEvent is SequencerSpecificEvent) { _track.SequencerSpecificEvents.Add((SequencerSpecificEvent)midiEvent); } else if (midiEvent is SmpteOffsetEvent) { _track.SmpteOffsetEvents.Add((SmpteOffsetEvent)midiEvent); } else if (midiEvent is SysexEvent) { _track.SysexEvents.Add((SysexEvent)midiEvent); } else if (midiEvent is TempoEvent) { _track.TempoEvents.Add((TempoEvent)midiEvent); } else if (midiEvent is TextEvent) { _track.TextEvents.Add((TextEvent)midiEvent); } else if (midiEvent is TimeSignatureEvent) { _track.TimeSignatureEvents.Add((TimeSignatureEvent)midiEvent); } else if (midiEvent is TrackSequenceNumberEvent) { _track.TrackSequenceNumberEvents.Add((TrackSequenceNumberEvent)midiEvent); } }