]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/process_keycode/process_midi.c
Split MIDI functionality into MIDI_BASIC and MIDI_ADVANCED
[qmk_firmware.git] / quantum / process_keycode / process_midi.c
1 #include "process_midi.h"
2
3 #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)
4
5 #include "timer.h"
6
7 static uint8_t tone_status[MIDI_TONE_COUNT];
8
9 static uint8_t midi_modulation;
10 static int8_t midi_modulation_step;
11 static uint16_t midi_modulation_timer;
12
13 inline uint8_t compute_velocity(uint8_t setting)
14 {
15     return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1));
16 }
17
18 void midi_init(void)
19 {
20     midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN;
21     midi_config.transpose = 0;
22     midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN);
23     midi_config.channel = 0;
24     midi_config.modulation_interval = 8;
25
26     for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++)
27     {
28         tone_status[i] = MIDI_INVALID_NOTE;
29     }
30
31     midi_modulation = 0;
32     midi_modulation_step = 0;
33     midi_modulation_timer = 0;
34 }
35
36 void midi_task(void)
37 {
38     if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval)
39         return;
40     midi_modulation_timer = timer_read();
41
42     if (midi_modulation_step != 0)
43     {
44         dprintf("midi modulation %d\n", midi_modulation);
45         midi_send_cc(&midi_device, midi_config.channel, 0x1, midi_modulation);
46
47         if (midi_modulation_step < 0 && midi_modulation < -midi_modulation_step) {
48             midi_modulation = 0;
49             midi_modulation_step = 0;
50             return;
51         }
52
53         midi_modulation += midi_modulation_step;
54
55         if (midi_modulation > 127)
56             midi_modulation = 127;
57     }
58 }
59
60 uint8_t midi_compute_note(uint16_t keycode)
61 {
62     return 12 * midi_config.octave + (keycode - MIDI_TONE_MIN) + midi_config.transpose;
63 }
64
65 bool process_midi(uint16_t keycode, keyrecord_t *record)
66 {
67     switch (keycode) {
68         case MIDI_TONE_MIN ... MIDI_TONE_MAX:
69         {
70             uint8_t channel = midi_config.channel;
71             uint8_t tone = keycode - MIDI_TONE_MIN;
72             uint8_t velocity = compute_velocity(midi_config.velocity);
73             if (record->event.pressed) {
74                 uint8_t note = midi_compute_note(keycode);
75                 midi_send_noteon(&midi_device, channel, note, velocity);
76                 dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity);
77                 tone_status[tone] = note;
78             }
79             else {
80                 uint8_t note = tone_status[tone];
81                 if (note != MIDI_INVALID_NOTE)
82                 {
83                     midi_send_noteoff(&midi_device, channel, note, velocity);
84                     dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity);
85                 }
86                 tone_status[tone] = MIDI_INVALID_NOTE;
87             }
88             return false;
89         }
90         case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX:
91             if (record->event.pressed) {
92                 midi_config.octave = keycode - MIDI_OCTAVE_MIN;
93                 dprintf("midi octave %d\n", midi_config.octave);
94             }
95             return false;
96         case MI_OCTD:
97             if (record->event.pressed && midi_config.octave > 0) {
98                 midi_config.octave--;
99                 dprintf("midi octave %d\n", midi_config.octave);
100             }
101             return false;
102         case MI_OCTU:
103             if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) {
104                 midi_config.octave++;
105                 dprintf("midi octave %d\n", midi_config.octave);
106             }
107             return false;
108         case MIDI_TRANSPOSE_MIN ... MIDI_TRANSPOSE_MAX:
109             if (record->event.pressed) {
110                 midi_config.transpose = keycode - MI_TRNS_0;
111                 dprintf("midi transpose %d\n", midi_config.transpose);
112             }
113             return false;
114         case MI_TRNSD:
115             if (record->event.pressed && midi_config.transpose > (MIDI_TRANSPOSE_MIN - MI_TRNS_0)) {
116                 midi_config.transpose--;
117                 dprintf("midi transpose %d\n", midi_config.transpose);
118             }
119             return false;
120         case MI_TRNSU:
121             if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - MI_TRNS_0)) {
122                 const bool positive = midi_config.transpose > 0;
123                 midi_config.transpose++;
124                 if (positive && midi_config.transpose < 0)
125                     midi_config.transpose--;
126                 dprintf("midi transpose %d\n", midi_config.transpose);
127             }
128             return false;
129         case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX:
130             if (record->event.pressed) {
131                 midi_config.velocity = keycode - MIDI_VELOCITY_MIN;
132                 dprintf("midi velocity %d\n", midi_config.velocity);
133             }
134             return false;
135         case MI_VELD:
136             if (record->event.pressed && midi_config.velocity > 0) {
137                 midi_config.velocity--;
138                 dprintf("midi velocity %d\n", midi_config.velocity);
139             }
140             return false;
141         case MI_VELU:
142             if (record->event.pressed) {
143                 midi_config.velocity++;
144                 dprintf("midi velocity %d\n", midi_config.velocity);
145             }
146             return false;
147         case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX:
148             if (record->event.pressed) {
149                 midi_config.channel = keycode - MIDI_CHANNEL_MIN;
150                 dprintf("midi channel %d\n", midi_config.channel);
151             }
152             return false;
153         case MI_CHD:
154             if (record->event.pressed) {
155                 midi_config.channel--;
156                 dprintf("midi channel %d\n", midi_config.channel);
157             }
158             return false;
159         case MI_CHU:
160             if (record->event.pressed) {
161                 midi_config.channel++;
162                 dprintf("midi channel %d\n", midi_config.channel);
163             }
164             return false;
165         case MI_ALLOFF:
166             if (record->event.pressed) {
167                 midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0);
168                 dprintf("midi off\n");
169             }
170             return false;
171         case MI_SUS:
172             midi_send_cc(&midi_device, midi_config.channel, 0x40, record->event.pressed ? 127 : 0);
173             dprintf("midi sustain %d\n", record->event.pressed);
174             return false;
175         case MI_PORT:
176             midi_send_cc(&midi_device, midi_config.channel, 0x41, record->event.pressed ? 127 : 0);
177             dprintf("midi portamento %d\n", record->event.pressed);
178             return false;
179         case MI_SOST:
180             midi_send_cc(&midi_device, midi_config.channel, 0x42, record->event.pressed ? 127 : 0);
181             dprintf("midi sostenuto %d\n", record->event.pressed);
182             return false;
183         case MI_SOFT:
184             midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
185             dprintf("midi soft %d\n", record->event.pressed);
186             return false;
187         case MI_LEG:
188             midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
189             dprintf("midi legato %d\n", record->event.pressed);
190             return false;
191         case MI_MOD:
192             midi_modulation_step = record->event.pressed ? 1 : -1;
193             return false;
194         case MI_MODSD:
195             if (record->event.pressed) {
196                 midi_config.modulation_interval++;
197                 // prevent overflow
198                 if (midi_config.modulation_interval == 0)
199                     midi_config.modulation_interval--;
200                 dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
201             }
202             return false;
203         case MI_MODSU:
204             if (record->event.pressed && midi_config.modulation_interval > 0) {
205                 midi_config.modulation_interval--;
206                 dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
207             }
208             return false;
209     };
210
211     return true;
212 }
213
214 #endif // MIDI_ADVANCED