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;
            }
        }
        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.TryDecode(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;

            case Midi.Status.System:
                switch (status)
                {
                case Midi.Status.SysExStart:
                    if (SysExMessage.TryDecode(message, out var sysExMessage))
                    {
                        SysEx?.Invoke(this, in sysExMessage);
                    }
                    break;

                case Midi.Status.MidiTimeCodeQuarterFrame:
                    if (MidiTimeCodeQuarterFrameMessage.TryDecode(message, out var timeCodeQuarterFrameMessage))
                    {
                        MidiTimeCodeQuarterFrame?.Invoke(this, in timeCodeQuarterFrameMessage);
                    }
                    break;

                case Midi.Status.SongPositionPointer:
                    if (SongPositionPointerMessage.TryDecode(message, out var songPositionPointerMessage))
                    {
                        SongPositionPointer?.Invoke(this, in songPositionPointerMessage);
                    }
                    break;

                case Midi.Status.SongSelect:
                    if (SongSelectMessage.TryDecode(message, out var songSelectMessage))
                    {
                        SongSelect?.Invoke(this, in songSelectMessage);
                    }
                    break;

                case Midi.Status.TuneRequest:
                    if (TuneRequestMessage.TryDecode(message, out var tuneRequestMessage))
                    {
                        TuneRequest?.Invoke(this, in tuneRequestMessage);
                    }
                    break;

                default:
                    Log.Error("Unknown system message type {Status}", $"{status:X2}");
                    break;
                }
                break;

            default:
                Log.Error("Unknown message type {Bitmask}", $"{status & 0b1111_0000:X2}");
                break;
            }
        }