Skip to content

MIDI

Usage

First, enable MIDI by adding the following to your rules.mk:

make
MIDI_ENABLE = yes

There are two MIDI systems in QMK: basic and advanced. With basic MIDI you will only be able to send Note On and Note Off messages using the note keycodes, meaning that keycodes like MI_OCTU and MI_OCTD will not work. Advanced MIDI allows you to do things like octave shifts, channel changes, velocity changes, modulation, and more.

Caveats

MIDI requires 2 USB endpoints and as such may not work on some hardware such as V-USB controllers.

Basic MIDI

To enable basic MIDI, add the following to your config.h:

c
#define MIDI_BASIC

Advanced MIDI

To enable advanced MIDI, add the following to your config.h:

c
#define MIDI_ADVANCED

Sending Control Change (CC) Messages

If you're aiming to emulate the features of something like a Launchpad or other MIDI controller you'll need to access the internal MIDI device directly.

Because there are so many possible CC messages, not all of them are implemented as keycodes. Additionally, you might need to provide more than just two values that you would get from a keycode (pressed and released) - for example, the analog values from a fader or a potentiometer. So, you will need to implement custom keycodes if you want to use them in your keymap directly using process_record_user().

For reference of all the possible control code numbers see MIDI Specification

Example code for using Generic On Off Switches as per MIDI Specification.

c
#include QMK_KEYBOARD_H

extern MidiDevice midi_device;

// MIDI CC codes for generic on/off switches (80, 81, 82, 83)
// Off: 0-63
// On:  64-127

#define MIDI_CC_OFF 0
#define MIDI_CC_ON  127

enum custom_keycodes {
    MIDI_CC80 = SAFE_RANGE,
};

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    switch (keycode) {
        case MIDI_CC80:
            if (record->event.pressed) {
                midi_send_cc(&midi_device, midi_config.channel, 80, MIDI_CC_ON);
            } else {
                midi_send_cc(&midi_device, midi_config.channel, 80, MIDI_CC_OFF);
            }
            return true;
    }
    return true;
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    LAYOUT(
        // ...
        MIDI_CC80,
        // ...
    )
};

Keycodes

KeycodeAliasesDescription
QK_MIDI_ONMI_ONTurn MIDI on
QK_MIDI_OFFMI_OFFTurn MIDI off
QK_MIDI_TOGGLEMI_TOGGToggle MIDI enabled
QK_MIDI_NOTE_C_0MI_CC octave 0
QK_MIDI_NOTE_C_SHARP_0MI_Cs, MI_DbC♯/D♭ octave 0
QK_MIDI_NOTE_D_0MI_DD octave 0
QK_MIDI_NOTE_D_SHARP_0MI_Ds, MI_EbD♯/E♭ octave 0
QK_MIDI_NOTE_E_0MI_EE octave 0
QK_MIDI_NOTE_F_0MI_FF octave 0
QK_MIDI_NOTE_F_SHARP_0MI_Fs, MI_GbF♯/G♭ octave 0
QK_MIDI_NOTE_G_0MI_GG octave 0
QK_MIDI_NOTE_G_SHARP_0MI_Gs, MI_AbG♯/A♭ octave 0
QK_MIDI_NOTE_A_0MI_AA octave 0
QK_MIDI_NOTE_A_SHARP_0MI_As, MI_BbA♯/B♭ octave 0
QK_MIDI_NOTE_B_0MI_BB octave 0
QK_MIDI_NOTE_C_1MI_C1C octave 1
QK_MIDI_NOTE_C_SHARP_1MI_Cs1, MI_Db1C♯/D♭ octave 1
QK_MIDI_NOTE_D_1MI_D1D octave 1
QK_MIDI_NOTE_D_SHARP_1MI_Ds1, MI_Eb1D♯/E♭ octave 1
QK_MIDI_NOTE_E_1MI_E1E octave 1
QK_MIDI_NOTE_F_1MI_F1F octave 1
QK_MIDI_NOTE_F_SHARP_1MI_Fs1, MI_Gb1F♯/G♭ octave 1
QK_MIDI_NOTE_G_1MI_G1G octave 1
QK_MIDI_NOTE_G_SHARP_1MI_Gs1, MI_Ab1G♯/A♭ octave 1
QK_MIDI_NOTE_A_1MI_A1A octave 1
QK_MIDI_NOTE_A_SHARP_1MI_As1, MI_Bb1A♯/B♭ octave 1
QK_MIDI_NOTE_B_1MI_B1B octave 1
QK_MIDI_NOTE_C_2MI_C2C octave 2
QK_MIDI_NOTE_C_SHARP_2MI_Cs2, MI_Db2C♯/D♭ octave 2
QK_MIDI_NOTE_D_2MI_D2D octave 2
QK_MIDI_NOTE_D_SHARP_2MI_Ds2, MI_Eb2D♯/E♭ octave 2
QK_MIDI_NOTE_E_2MI_E2E octave 2
QK_MIDI_NOTE_F_2MI_F2F octave 2
QK_MIDI_NOTE_F_SHARP_2MI_Fs2, MI_Gb2F♯/G♭ octave 2
QK_MIDI_NOTE_G_2MI_G2G octave 2
QK_MIDI_NOTE_G_SHARP_2MI_Gs2, MI_Ab2G♯/A♭ octave 2
QK_MIDI_NOTE_A_2MI_A2A octave 2
QK_MIDI_NOTE_A_SHARP_2MI_As2, MI_Bb2A♯/B♭ octave 2
QK_MIDI_NOTE_B_2MI_B2B octave 2
QK_MIDI_NOTE_C_3MI_C3C octave 3
QK_MIDI_NOTE_C_SHARP_3MI_Cs3, MI_Db3C♯/D♭ octave 3
QK_MIDI_NOTE_D_3MI_D3D octave 3
QK_MIDI_NOTE_D_SHARP_3MI_Ds3, MI_Eb3D♯/E♭ octave 3
QK_MIDI_NOTE_E_3MI_E3E octave 3
QK_MIDI_NOTE_F_3MI_F3F octave 3
QK_MIDI_NOTE_F_SHARP_3MI_Fs3, MI_Gb3F♯/G♭ octave 3
QK_MIDI_NOTE_G_3MI_G3G octave 3
QK_MIDI_NOTE_G_SHARP_3MI_Gs3, MI_Ab3G♯/A♭ octave 3
QK_MIDI_NOTE_A_3MI_A3A octave 3
QK_MIDI_NOTE_A_SHARP_3MI_As3, MI_Bb3A♯/B♭ octave 3
QK_MIDI_NOTE_B_3MI_B3B octave 3
QK_MIDI_NOTE_C_4MI_C4C octave 4
QK_MIDI_NOTE_C_SHARP_4MI_Cs4, MI_Db4C♯/D♭ octave 4
QK_MIDI_NOTE_D_4MI_D4D octave 4
QK_MIDI_NOTE_D_SHARP_4MI_Ds4, MI_Eb4D♯/E♭ octave 4
QK_MIDI_NOTE_E_4MI_E4E octave 4
QK_MIDI_NOTE_F_4MI_F4F octave 4
QK_MIDI_NOTE_F_SHARP_4MI_Fs4, MI_Gb4F♯/G♭ octave 4
QK_MIDI_NOTE_G_4MI_G4G octave 4
QK_MIDI_NOTE_G_SHARP_4MI_Gs4, MI_Ab4G♯/A♭ octave 4
QK_MIDI_NOTE_A_4MI_A4A octave 4
QK_MIDI_NOTE_A_SHARP_4MI_As4, MI_Bb4A♯/B♭ octave 4
QK_MIDI_NOTE_B_4MI_B4B octave 4
QK_MIDI_NOTE_C_5MI_C5C octave 5
QK_MIDI_NOTE_C_SHARP_5MI_Cs5, MI_Db5C♯/D♭ octave 5
QK_MIDI_NOTE_D_5MI_D5D octave 5
QK_MIDI_NOTE_D_SHARP_5MI_Ds5, MI_Eb5D♯/E♭ octave 5
QK_MIDI_NOTE_E_5MI_E5E octave 5
QK_MIDI_NOTE_F_5MI_F5F octave 5
QK_MIDI_NOTE_F_SHARP_5MI_Fs5, MI_Gb5F♯/G♭ octave 5
QK_MIDI_NOTE_G_5MI_G5G octave 5
QK_MIDI_NOTE_G_SHARP_5MI_Gs5, MI_Ab5G♯/A♭ octave 5
QK_MIDI_NOTE_A_5MI_A5A octave 5
QK_MIDI_NOTE_A_SHARP_5MI_As5, MI_Bb5A♯/B♭ octave 5
QK_MIDI_NOTE_B_5MI_B5B octave 5
QK_MIDI_OCTAVE_N2MI_OCN2Set octave to -2
QK_MIDI_OCTAVE_N1MI_OCN1Set octave to -1
QK_MIDI_OCTAVE_0MI_OC0Set octave to 0
QK_MIDI_OCTAVE_1MI_OC1Set octave to 1
QK_MIDI_OCTAVE_2MI_OC2Set octave to 2
QK_MIDI_OCTAVE_3MI_OC3Set octave to 3
QK_MIDI_OCTAVE_4MI_OC4Set octave to 4
QK_MIDI_OCTAVE_5MI_OC5Set octave to 5
QK_MIDI_OCTAVE_6MI_OC6Set octave to 6
QK_MIDI_OCTAVE_7MI_OC7Set octave to 7
QK_MIDI_OCTAVE_DOWNMI_OCTDMove down an octave
QK_MIDI_OCTAVE_UPMI_OCTUMove up an octave
QK_MIDI_TRANSPOSE_N6MI_TRN6Set transposition to -6 semitones
QK_MIDI_TRANSPOSE_N5MI_TRN5Set transposition to -5 semitones
QK_MIDI_TRANSPOSE_N4MI_TRN4Set transposition to -4 semitones
QK_MIDI_TRANSPOSE_N3MI_TRN3Set transposition to -3 semitones
QK_MIDI_TRANSPOSE_N2MI_TRN2Set transposition to -2 semitones
QK_MIDI_TRANSPOSE_N1MI_TRN1Set transposition to -1 semitone
QK_MIDI_TRANSPOSE_0MI_TR0No transposition
QK_MIDI_TRANSPOSE_1MI_TR1Set transposition to +1 semitone
QK_MIDI_TRANSPOSE_2MI_TR2Set transposition to +2 semitones
QK_MIDI_TRANSPOSE_3MI_TR3Set transposition to +3 semitones
QK_MIDI_TRANSPOSE_4MI_TR4Set transposition to +4 semitones
QK_MIDI_TRANSPOSE_5MI_TR5Set transposition to +5 semitones
QK_MIDI_TRANSPOSE_6MI_TR6Set transposition to +6 semitones
QK_MIDI_TRANSPOSE_DOWNMI_TRSDDecrease transposition
QK_MIDI_TRANSPOSE_UPMI_TRSUIncrease transposition
QK_MIDI_VELOCITY_0MI_VL0Set velocity to 0
QK_MIDI_VELOCITY_1MI_VL1Set velocity to 12
QK_MIDI_VELOCITY_2MI_VL2Set velocity to 25
QK_MIDI_VELOCITY_3MI_VL3Set velocity to 38
QK_MIDI_VELOCITY_4MI_VL4Set velocity to 51
QK_MIDI_VELOCITY_5MI_VL5Set velocity to 64
QK_MIDI_VELOCITY_6MI_VL6Set velocity to 76
QK_MIDI_VELOCITY_7MI_VL7Set velocity to 89
QK_MIDI_VELOCITY_8MI_VL8Set velocity to 102
QK_MIDI_VELOCITY_9MI_VL9Set velocity to 114
QK_MIDI_VELOCITY_10MI_VL10Set velocity to 127
QK_MIDI_VELOCITY_DOWNMI_VELDDecrease velocity
QK_MIDI_VELOCITY_UPMI_VELUIncrease velocity
QK_MIDI_CHANNEL_1MI_CH1Set channel to 1
QK_MIDI_CHANNEL_2MI_CH2Set channel to 2
QK_MIDI_CHANNEL_3MI_CH3Set channel to 3
QK_MIDI_CHANNEL_4MI_CH4Set channel to 4
QK_MIDI_CHANNEL_5MI_CH5Set channel to 5
QK_MIDI_CHANNEL_6MI_CH6Set channel to 6
QK_MIDI_CHANNEL_7MI_CH7Set channel to 7
QK_MIDI_CHANNEL_8MI_CH8Set channel to 8
QK_MIDI_CHANNEL_9MI_CH9Set channel to 9
QK_MIDI_CHANNEL_10MI_CH10Set channel to 10
QK_MIDI_CHANNEL_11MI_CH11Set channel to 11
QK_MIDI_CHANNEL_12MI_CH12Set channel to 12
QK_MIDI_CHANNEL_13MI_CH13Set channel to 13
QK_MIDI_CHANNEL_14MI_CH14Set channel to 14
QK_MIDI_CHANNEL_15MI_CH15Set channel to 15
QK_MIDI_CHANNEL_16MI_CH16Set channel to 16
QK_MIDI_CHANNEL_DOWNMI_CHNDDecrease channel
QK_MIDI_CHANNEL_UPMI_CHNUIncrease channel
QK_MIDI_ALL_NOTES_OFFMI_AOFFStop all notes
QK_MIDI_SUSTAINMI_SUSTSustain
QK_MIDI_PORTAMENTOMI_PORTPortmento
QK_MIDI_SOSTENUTOMI_SOSTSostenuto
QK_MIDI_SOFTMI_SOFTSoft Pedal
QK_MIDI_LEGATOMI_LEGLegato
QK_MIDI_MODULATIONMI_MODModulation
QK_MIDI_MODULATION_SPEED_DOWNMI_MODDDecrease modulation speed
QK_MIDI_MODULATION_SPEED_UPMI_MODUIncrease modulation speed
QK_MIDI_PITCH_BEND_DOWNMI_BNDDBend pitch down
QK_MIDI_PITCH_BEND_UPMI_BNDUBend pitch up

Configuration

Certain values are stored in the midi_config struct. This configuration is not persisted to EEPROM. By default, these values are:

ConfigurationValueComments
Octave4Corresponds to MI_OC2
Transposition0
Velocity127
Channel0
Modulation Interval8

For the above, the MI_C keycode will produce a C3 (note number 48), and so on.

References

MIDI Specification

QMK C Files

  • quantum/process_keycode/process_midi.c
  • quantum/quantum_keycodes.h
  • quantum/midi/midi.h
  • quantum/midi/midi.c
  • quantum/midi/qmk_midi.c
  • quantum/midi/midi_device.h