qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

process_midi.c (10809B)


      1 /* Copyright 2016 Jack Humbert
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 2 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 #include "process_midi.h"
     17 
     18 #include <LUFA/Drivers/USB/USB.h>
     19 #include "midi.h"
     20 #include "qmk_midi.h"
     21 #include "timer.h"
     22 #include "debug.h"
     23 
     24 #ifdef MIDI_BASIC
     25 
     26 void process_midi_basic_noteon(uint8_t note) {
     27     midi_send_noteon(&midi_device, 0, note, 127);
     28 }
     29 
     30 void process_midi_basic_noteoff(uint8_t note) {
     31     midi_send_noteoff(&midi_device, 0, note, 0);
     32 }
     33 
     34 void process_midi_all_notes_off(void) {
     35     midi_send_cc(&midi_device, 0, 0x7B, 0);
     36 }
     37 
     38 #endif // MIDI_BASIC
     39 
     40 #ifdef MIDI_ADVANCED
     41 static uint8_t tone_status[MIDI_TONE_COUNT];
     42 
     43 static uint8_t  midi_modulation;
     44 static int8_t   midi_modulation_step;
     45 static uint16_t midi_modulation_timer;
     46 midi_config_t   midi_config;
     47 
     48 inline uint8_t compute_velocity(uint8_t setting) {
     49     return setting * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN));
     50 }
     51 
     52 void midi_init(void) {
     53     midi_config.octave              = QK_MIDI_OCTAVE_2 - MIDI_OCTAVE_MIN;
     54     midi_config.transpose           = 0;
     55     midi_config.velocity            = 127;
     56     midi_config.channel             = 0;
     57     midi_config.modulation_interval = 8;
     58 
     59     for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++) {
     60         tone_status[i] = MIDI_INVALID_NOTE;
     61     }
     62 
     63     midi_modulation       = 0;
     64     midi_modulation_step  = 0;
     65     midi_modulation_timer = 0;
     66 }
     67 
     68 uint8_t midi_compute_note(uint16_t keycode) {
     69     return 12 * midi_config.octave + (keycode - MIDI_TONE_MIN) + midi_config.transpose;
     70 }
     71 
     72 bool process_midi(uint16_t keycode, keyrecord_t *record) {
     73     switch (keycode) {
     74         case MIDI_TONE_MIN ... MIDI_TONE_MAX: {
     75             uint8_t channel  = midi_config.channel;
     76             uint8_t tone     = keycode - MIDI_TONE_MIN;
     77             uint8_t velocity = midi_config.velocity;
     78             if (record->event.pressed) {
     79                 if (tone_status[tone] == MIDI_INVALID_NOTE) {
     80                     uint8_t note = midi_compute_note(keycode);
     81                     midi_send_noteon(&midi_device, channel, note, velocity);
     82                     dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity);
     83                     tone_status[tone] = note;
     84                 }
     85             } else {
     86                 uint8_t note = tone_status[tone];
     87                 if (note != MIDI_INVALID_NOTE) {
     88                     midi_send_noteoff(&midi_device, channel, note, velocity);
     89                     dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity);
     90                 }
     91                 tone_status[tone] = MIDI_INVALID_NOTE;
     92             }
     93             return false;
     94         }
     95         case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX:
     96             if (record->event.pressed) {
     97                 midi_config.octave = keycode - MIDI_OCTAVE_MIN;
     98                 dprintf("midi octave %d\n", midi_config.octave);
     99             }
    100             return false;
    101         case QK_MIDI_OCTAVE_DOWN:
    102             if (record->event.pressed && midi_config.octave > 0) {
    103                 midi_config.octave--;
    104                 dprintf("midi octave %d\n", midi_config.octave);
    105             }
    106             return false;
    107         case QK_MIDI_OCTAVE_UP:
    108             if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) {
    109                 midi_config.octave++;
    110                 dprintf("midi octave %d\n", midi_config.octave);
    111             }
    112             return false;
    113         case MIDI_TRANSPOSE_MIN ... MIDI_TRANSPOSE_MAX:
    114             if (record->event.pressed) {
    115                 midi_config.transpose = keycode - QK_MIDI_TRANSPOSE_0;
    116                 dprintf("midi transpose %d\n", midi_config.transpose);
    117             }
    118             return false;
    119         case QK_MIDI_TRANSPOSE_DOWN:
    120             if (record->event.pressed && midi_config.transpose > (MIDI_TRANSPOSE_MIN - QK_MIDI_TRANSPOSE_0)) {
    121                 midi_config.transpose--;
    122                 dprintf("midi transpose %d\n", midi_config.transpose);
    123             }
    124             return false;
    125         case QK_MIDI_TRANSPOSE_UP:
    126             if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - QK_MIDI_TRANSPOSE_0)) {
    127                 const bool positive = midi_config.transpose > 0;
    128                 midi_config.transpose++;
    129                 if (positive && midi_config.transpose < 0) midi_config.transpose--;
    130                 dprintf("midi transpose %d\n", midi_config.transpose);
    131             }
    132             return false;
    133         case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX:
    134             if (record->event.pressed) {
    135                 midi_config.velocity = compute_velocity(keycode - MIDI_VELOCITY_MIN);
    136                 dprintf("midi velocity %d\n", midi_config.velocity);
    137             }
    138             return false;
    139         case QK_MIDI_VELOCITY_DOWN:
    140             if (record->event.pressed && midi_config.velocity > 0) {
    141                 if (midi_config.velocity == 127) {
    142                     midi_config.velocity -= 10;
    143                 } else if (midi_config.velocity > 12) {
    144                     midi_config.velocity -= 13;
    145                 } else {
    146                     midi_config.velocity = 0;
    147                 }
    148 
    149                 dprintf("midi velocity %d\n", midi_config.velocity);
    150             }
    151             return false;
    152         case QK_MIDI_VELOCITY_UP:
    153             if (record->event.pressed && midi_config.velocity < 127) {
    154                 if (midi_config.velocity < 115) {
    155                     midi_config.velocity += 13;
    156                 } else {
    157                     midi_config.velocity = 127;
    158                 }
    159                 dprintf("midi velocity %d\n", midi_config.velocity);
    160             }
    161             return false;
    162         case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX:
    163             if (record->event.pressed) {
    164                 midi_config.channel = keycode - MIDI_CHANNEL_MIN;
    165                 dprintf("midi channel %d\n", midi_config.channel);
    166             }
    167             return false;
    168         case QK_MIDI_CHANNEL_DOWN:
    169             if (record->event.pressed) {
    170                 midi_config.channel--;
    171                 dprintf("midi channel %d\n", midi_config.channel);
    172             }
    173             return false;
    174         case QK_MIDI_CHANNEL_UP:
    175             if (record->event.pressed) {
    176                 midi_config.channel++;
    177                 dprintf("midi channel %d\n", midi_config.channel);
    178             }
    179             return false;
    180         case QK_MIDI_ALL_NOTES_OFF:
    181             if (record->event.pressed) {
    182                 midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0);
    183                 dprintf("midi all notes off\n");
    184             }
    185             return false;
    186         case QK_MIDI_SUSTAIN:
    187             midi_send_cc(&midi_device, midi_config.channel, 0x40, record->event.pressed ? 127 : 0);
    188             dprintf("midi sustain %d\n", record->event.pressed);
    189             return false;
    190         case QK_MIDI_PORTAMENTO:
    191             midi_send_cc(&midi_device, midi_config.channel, 0x41, record->event.pressed ? 127 : 0);
    192             dprintf("midi portamento %d\n", record->event.pressed);
    193             return false;
    194         case QK_MIDI_SOSTENUTO:
    195             midi_send_cc(&midi_device, midi_config.channel, 0x42, record->event.pressed ? 127 : 0);
    196             dprintf("midi sostenuto %d\n", record->event.pressed);
    197             return false;
    198         case QK_MIDI_SOFT:
    199             midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
    200             dprintf("midi soft %d\n", record->event.pressed);
    201             return false;
    202         case QK_MIDI_LEGATO:
    203             midi_send_cc(&midi_device, midi_config.channel, 0x44, record->event.pressed ? 127 : 0);
    204             dprintf("midi legato %d\n", record->event.pressed);
    205             return false;
    206         case QK_MIDI_MODULATION:
    207             midi_modulation_step = record->event.pressed ? 1 : -1;
    208             return false;
    209         case QK_MIDI_MODULATION_SPEED_DOWN:
    210             if (record->event.pressed) {
    211                 midi_config.modulation_interval++;
    212                 // prevent overflow
    213                 if (midi_config.modulation_interval == 0) midi_config.modulation_interval--;
    214                 dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
    215             }
    216             return false;
    217         case QK_MIDI_MODULATION_SPEED_UP:
    218             if (record->event.pressed && midi_config.modulation_interval > 0) {
    219                 midi_config.modulation_interval--;
    220                 dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
    221             }
    222             return false;
    223         case QK_MIDI_PITCH_BEND_DOWN:
    224             if (record->event.pressed) {
    225                 midi_send_pitchbend(&midi_device, midi_config.channel, -0x2000);
    226                 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, -0x2000);
    227             } else {
    228                 midi_send_pitchbend(&midi_device, midi_config.channel, 0);
    229                 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0);
    230             }
    231             return false;
    232         case QK_MIDI_PITCH_BEND_UP:
    233             if (record->event.pressed) {
    234                 midi_send_pitchbend(&midi_device, midi_config.channel, 0x1fff);
    235                 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0x1fff);
    236             } else {
    237                 midi_send_pitchbend(&midi_device, midi_config.channel, 0);
    238                 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0);
    239             }
    240             return false;
    241     };
    242 
    243     return true;
    244 }
    245 
    246 #endif // MIDI_ADVANCED
    247 
    248 void midi_task(void) {
    249     midi_device_process(&midi_device);
    250 #ifdef MIDI_ADVANCED
    251     if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval) return;
    252     midi_modulation_timer = timer_read();
    253 
    254     if (midi_modulation_step != 0) {
    255         dprintf("midi modulation %d\n", midi_modulation);
    256         midi_send_cc(&midi_device, midi_config.channel, 0x1, midi_modulation);
    257 
    258         if (midi_modulation_step < 0 && midi_modulation < -midi_modulation_step) {
    259             midi_modulation      = 0;
    260             midi_modulation_step = 0;
    261             return;
    262         }
    263 
    264         midi_modulation += midi_modulation_step;
    265 
    266         if (midi_modulation > 127) midi_modulation = 127;
    267     }
    268 #endif
    269 }