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