/// <summary> /// Constructs a MidiEvent from a BinaryStream /// </summary> /// <param name="br">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 br, MidiEvent previous) { int deltaTime = MidiEvent.ReadVarInt(br); MidiCommandCode commandCode; int channel = 1; byte b = br.ReadByte(); if ((b & 0x80) == 0) { // a running command - command & channel are same as previous commandCode = previous.CommandCode; channel = previous.Channel; br.BaseStream.Position--; // need to push this back } else { if ((b & 0xF0) == 0xF0) { // both bytes are used for command code in this case commandCode = (MidiCommandCode)b; } else { commandCode = (MidiCommandCode)(b & 0xF0); channel = (b & 0x0F) + 1; } } MidiEvent me; switch (commandCode) { case MidiCommandCode.NoteOn: me = new NoteOnEvent(br); break; case MidiCommandCode.NoteOff: case MidiCommandCode.KeyAfterTouch: me = new NoteEvent(br); break; case MidiCommandCode.ControlChange: me = new ControlChangeEvent(br); break; case MidiCommandCode.PatchChange: me = new PatchChangeEvent(br); break; case MidiCommandCode.ChannelAfterTouch: me = new ChannelAfterTouchEvent(br); break; case MidiCommandCode.PitchWheelChange: me = new PitchWheelChangeEvent(br); break; case MidiCommandCode.TimingClock: case MidiCommandCode.StartSequence: case MidiCommandCode.ContinueSequence: case MidiCommandCode.StopSequence: me = new MidiEvent(); break; case MidiCommandCode.Sysex: me = SysexEvent.ReadSysexEvent(br); break; case MidiCommandCode.MetaEvent: me = MetaEvent.ReadMetaEvent(br); break; default: throw new FormatException(String.Format("Unsupported MIDI Command Code {0:X2}", (byte)commandCode)); } me.channel = channel; me.deltaTime = deltaTime; me.commandCode = commandCode; return(me); }
/// <summary> /// Creates a MidiEvent from a raw message received using /// the MME MIDI In APIs /// </summary> /// <param name="rawMessage">The short MIDI message</param> /// <returns>A new MIDI Event</returns> public static MidiEvent FromRawMessage(int rawMessage) { long absoluteTime = 0; int b = rawMessage & 0xFF; int data1 = (rawMessage >> 8) & 0xFF; int data2 = (rawMessage >> 16) & 0xFF; MidiCommandCode commandCode; int channel = 1; if ((b & 0xF0) == 0xF0) { // both bytes are used for command code in this case commandCode = (MidiCommandCode)b; } else { commandCode = (MidiCommandCode)(b & 0xF0); channel = (b & 0x0F) + 1; } MidiEvent me; switch (commandCode) { case MidiCommandCode.NoteOn: case MidiCommandCode.NoteOff: case MidiCommandCode.KeyAfterTouch: if (data2 > 0 && commandCode == MidiCommandCode.NoteOn) { me = new NoteOnEvent(absoluteTime, channel, data1, data2, 0); } else { me = new NoteEvent(absoluteTime, channel, commandCode, data1, data2); } break; case MidiCommandCode.ControlChange: me = new ControlChangeEvent(absoluteTime, channel, (MidiController)data1, data2); break; case MidiCommandCode.PatchChange: me = new PatchChangeEvent(absoluteTime, channel, data1); break; case MidiCommandCode.ChannelAfterTouch: me = new ChannelAfterTouchEvent(absoluteTime, channel, data1); break; case MidiCommandCode.PitchWheelChange: me = new PitchWheelChangeEvent(absoluteTime, channel, data1 + (data2 << 7)); break; case MidiCommandCode.TimingClock: case MidiCommandCode.StartSequence: case MidiCommandCode.ContinueSequence: case MidiCommandCode.StopSequence: case MidiCommandCode.AutoSensing: me = new MidiEvent(absoluteTime, channel, commandCode); break; case MidiCommandCode.MetaEvent: case MidiCommandCode.Sysex: default: throw new FormatException(String.Format("Unsupported MIDI Command Code for Raw Message {0}", commandCode)); } return(me); }