keyboard stuff
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_music.h"
17#include "timer.h"
18
19#ifdef AUDIO_ENABLE
20# include "audio.h"
21# include "process_audio.h"
22#endif
23#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
24# include "process_midi.h"
25#endif
26
27#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
28
29bool music_activated = false;
30bool midi_activated = false;
31uint8_t music_starting_note = 0x0C;
32int music_offset = 7;
33uint8_t music_mode = MUSIC_MODE_MAJOR;
34
35// music sequencer
36static bool music_sequence_recording = false;
37static bool music_sequence_recorded = false;
38static bool music_sequence_playing = false;
39static uint8_t music_sequence[16] = {0};
40static uint8_t music_sequence_count = 0;
41static uint8_t music_sequence_position = 0;
42
43static uint16_t music_sequence_timer = 0;
44static uint16_t music_sequence_interval = 100;
45
46# ifdef AUDIO_ENABLE
47# ifndef MUSIC_ON_SONG
48# define MUSIC_ON_SONG SONG(MUSIC_ON_SOUND)
49# endif
50# ifndef MUSIC_OFF_SONG
51# define MUSIC_OFF_SONG SONG(MUSIC_OFF_SOUND)
52# endif
53# ifndef MIDI_ON_SONG
54# define MIDI_ON_SONG SONG(MUSIC_ON_SOUND)
55# endif
56# ifndef MIDI_OFF_SONG
57# define MIDI_OFF_SONG SONG(MUSIC_OFF_SOUND)
58# endif
59# ifndef CHROMATIC_SONG
60# define CHROMATIC_SONG SONG(CHROMATIC_SOUND)
61# endif
62# ifndef GUITAR_SONG
63# define GUITAR_SONG SONG(GUITAR_SOUND)
64# endif
65# ifndef VIOLIN_SONG
66# define VIOLIN_SONG SONG(VIOLIN_SOUND)
67# endif
68# ifndef MAJOR_SONG
69# define MAJOR_SONG SONG(MAJOR_SOUND)
70# endif
71float music_mode_songs[NUMBER_OF_MODES][5][2] = {CHROMATIC_SONG, GUITAR_SONG, VIOLIN_SONG, MAJOR_SONG};
72float music_on_song[][2] = MUSIC_ON_SONG;
73float music_off_song[][2] = MUSIC_OFF_SONG;
74float midi_on_song[][2] = MIDI_ON_SONG;
75float midi_off_song[][2] = MIDI_OFF_SONG;
76# endif
77
78static void music_noteon(uint8_t note) {
79# ifdef AUDIO_ENABLE
80 if (music_activated) process_audio_noteon(note);
81# endif
82# if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
83 if (midi_activated) process_midi_basic_noteon(note);
84# endif
85}
86
87static void music_noteoff(uint8_t note) {
88# ifdef AUDIO_ENABLE
89 if (music_activated) process_audio_noteoff(note);
90# endif
91# if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
92 if (midi_activated) process_midi_basic_noteoff(note);
93# endif
94}
95
96void music_all_notes_off(void) {
97# ifdef AUDIO_ENABLE
98 if (music_activated) process_audio_all_notes_off();
99# endif
100# if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
101 if (midi_activated) process_midi_all_notes_off();
102# endif
103}
104
105bool process_music(uint16_t keycode, keyrecord_t *record) {
106 if (keycode == QK_MUSIC_ON && record->event.pressed) {
107 music_on();
108 return false;
109 }
110
111 if (keycode == QK_MUSIC_OFF && record->event.pressed) {
112 music_off();
113 return false;
114 }
115
116 if (keycode == QK_MUSIC_TOGGLE && record->event.pressed) {
117 if (music_activated) {
118 music_off();
119 } else {
120 music_on();
121 }
122 return false;
123 }
124
125 if (keycode == QK_MIDI_ON && record->event.pressed) {
126 midi_on();
127 return false;
128 }
129
130 if (keycode == QK_MIDI_OFF && record->event.pressed) {
131 midi_off();
132 return false;
133 }
134
135 if (keycode == QK_MIDI_TOGGLE && record->event.pressed) {
136 if (midi_activated) {
137 midi_off();
138 } else {
139 midi_on();
140 }
141 return false;
142 }
143
144 if (keycode == QK_MUSIC_MODE_NEXT && record->event.pressed) {
145 music_mode_cycle();
146 return false;
147 }
148
149 if (music_activated || midi_activated) {
150 if (record->event.pressed) {
151 if (keycode == KC_LEFT_CTRL) { // Start recording
152 music_all_notes_off();
153 music_sequence_recording = true;
154 music_sequence_recorded = false;
155 music_sequence_playing = false;
156 music_sequence_count = 0;
157 return false;
158 }
159
160 if (keycode == KC_LEFT_ALT) { // Stop recording/playing
161 music_all_notes_off();
162 if (music_sequence_recording) { // was recording
163 music_sequence_recorded = true;
164 }
165 music_sequence_recording = false;
166 music_sequence_playing = false;
167 return false;
168 }
169
170 if (keycode == KC_LEFT_GUI && music_sequence_recorded) { // Start playing
171 music_all_notes_off();
172 music_sequence_recording = false;
173 music_sequence_playing = true;
174 music_sequence_position = 0;
175 music_sequence_timer = 0;
176 return false;
177 }
178
179 if (keycode == KC_UP) {
180 music_sequence_interval -= 10;
181 return false;
182 }
183
184 if (keycode == KC_DOWN) {
185 music_sequence_interval += 10;
186 return false;
187 }
188 }
189
190 uint8_t note = 36;
191# ifdef MUSIC_MAP
192 if (music_mode == MUSIC_MODE_CHROMATIC) {
193 note = music_starting_note + music_offset + 36 + music_map[record->event.key.row][record->event.key.col];
194 } else {
195 uint8_t position = music_map[record->event.key.row][record->event.key.col];
196 note = music_starting_note + music_offset + 36 + SCALE[position % 7] + (position / 7) * 12;
197 }
198# else
199 if (music_mode == MUSIC_MODE_CHROMATIC)
200 note = (music_starting_note + record->event.key.col + music_offset - 3) + 12 * (MATRIX_ROWS - record->event.key.row);
201 else if (music_mode == MUSIC_MODE_GUITAR)
202 note = (music_starting_note + record->event.key.col + music_offset + 32) + 5 * (MATRIX_ROWS - record->event.key.row);
203 else if (music_mode == MUSIC_MODE_VIOLIN)
204 note = (music_starting_note + record->event.key.col + music_offset + 32) + 7 * (MATRIX_ROWS - record->event.key.row);
205 else if (music_mode == MUSIC_MODE_MAJOR)
206 note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3) + 12 * (MATRIX_ROWS - record->event.key.row);
207 else
208 note = music_starting_note;
209# endif
210
211 if (record->event.pressed) {
212 music_noteon(note);
213 if (music_sequence_recording) {
214 music_sequence[music_sequence_count] = note;
215 music_sequence_count++;
216 }
217 } else {
218 music_noteoff(note);
219 }
220
221 if (music_mask(keycode)) return false;
222 }
223
224 return true;
225}
226
227bool music_mask(uint16_t keycode) {
228# ifdef MUSIC_MASK
229 return MUSIC_MASK;
230# else
231 return music_mask_kb(keycode);
232# endif
233}
234
235__attribute__((weak)) bool music_mask_kb(uint16_t keycode) {
236 return music_mask_user(keycode);
237}
238
239__attribute__((weak)) bool music_mask_user(uint16_t keycode) {
240 return keycode < 0xFF;
241}
242
243bool is_music_on(void) {
244 return (music_activated != 0);
245}
246
247void music_toggle(void) {
248 if (!music_activated) {
249 music_on();
250 } else {
251 music_off();
252 }
253}
254
255void music_on(void) {
256 music_activated = 1;
257# ifdef AUDIO_ENABLE
258 PLAY_SONG(music_on_song);
259# endif
260 music_on_user();
261}
262
263void music_off(void) {
264 music_all_notes_off();
265 music_activated = 0;
266# ifdef AUDIO_ENABLE
267 PLAY_SONG(music_off_song);
268# endif
269}
270
271bool is_midi_on(void) {
272 return (midi_activated != 0);
273}
274
275void midi_toggle(void) {
276 if (!midi_activated) {
277 midi_on();
278 } else {
279 midi_off();
280 }
281}
282
283void midi_on(void) {
284 midi_activated = 1;
285# ifdef AUDIO_ENABLE
286 PLAY_SONG(midi_on_song);
287# endif
288 midi_on_user();
289}
290
291void midi_off(void) {
292# if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
293 process_midi_all_notes_off();
294# endif
295 midi_activated = 0;
296# ifdef AUDIO_ENABLE
297 PLAY_SONG(midi_off_song);
298# endif
299}
300
301void music_mode_cycle(void) {
302 music_all_notes_off();
303 music_mode = (music_mode + 1) % NUMBER_OF_MODES;
304# ifdef AUDIO_ENABLE
305 PLAY_SONG(music_mode_songs[music_mode]);
306# endif
307}
308
309void music_task(void) {
310 if (music_sequence_playing) {
311 if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) {
312 music_sequence_timer = timer_read();
313 uint8_t prev_note = music_sequence[(music_sequence_position - 1 < 0) ? (music_sequence_position - 1 + music_sequence_count) : (music_sequence_position - 1)];
314 uint8_t next_note = music_sequence[music_sequence_position];
315 music_noteoff(prev_note);
316 music_noteon(next_note);
317 music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
318 }
319 }
320}
321
322__attribute__((weak)) void music_on_user(void) {}
323
324__attribute__((weak)) void midi_on_user(void) {}
325
326__attribute__((weak)) void music_scale_user(void) {}
327
328#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))