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