private void Decode(byte[] message) { byte status = message[0]; switch (status & 0b1111_0000) { case Midi.Status.NoteOffBitmask: if (NoteOffMessage.TryDecode(message, out var noteOffMessage)) { NoteOff?.Invoke(this, in noteOffMessage); } break; case Midi.Status.NoteOnBitmask: if (NoteOnMessage.TryDecoce(message, out var noteOnMessage)) { NoteOn?.Invoke(this, in noteOnMessage); } break; case Midi.Status.PolyphonicKeyPressureBitmask: if (PolyphonicKeyPressureMessage.TryDecode(message, out var polyphonicKeyPressureMessage)) { PolyphonicKeyPressure?.Invoke(this, in polyphonicKeyPressureMessage); } break; case Midi.Status.ControlChangeBitmask: if (ControlChangeMessage.TryDecode(message, out var controlChangeMessage)) { _nrpnInterpreters[(int)controlChangeMessage.Channel].HandleControlChangeMessage(in controlChangeMessage); } break; case Midi.Status.ProgramChangeBitmask: if (ProgramChangeMessage.TryDecode(message, out var programChangeMessage)) { ProgramChange?.Invoke(this, in programChangeMessage); } break; case Midi.Status.ChannelPressureBitmask: if (ChannelPressureMessage.TryDecode(message, out var channelPressureMessage)) { ChannelPressure?.Invoke(this, in channelPressureMessage); } break; case Midi.Status.PitchBendChange: if (PitchBendMessage.TryDecode(message, out var pitchBendMessage)) { PitchBend?.Invoke(this, in pitchBendMessage); } break; default: Log.Error("Unknown message type {Bitmask}", $"{status & 0b1111_0000:X2}"); break; } }