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 }