]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/process_keycode/process_music.c
Merge remote-tracking branch 'upstream/master'
[qmk_firmware.git] / quantum / process_keycode / process_music.c
1 #include "process_music.h"
2
3 bool music_activated = false;
4 uint8_t music_starting_note = 0x0C;
5 int music_offset = 7;
6
7 // music sequencer
8 static bool music_sequence_recording = false;
9 static bool music_sequence_recorded = false;
10 static bool music_sequence_playing = false;
11 static float music_sequence[16] = {0};
12 static uint8_t music_sequence_count = 0;
13 static uint8_t music_sequence_position = 0;
14
15 static uint16_t music_sequence_timer = 0;
16 static uint16_t music_sequence_interval = 100;
17
18 bool process_music(uint16_t keycode, keyrecord_t *record) {
19
20     if (keycode == AU_ON && record->event.pressed) {
21       audio_on();
22       return false;
23     }
24
25     if (keycode == AU_OFF && record->event.pressed) {
26       audio_off();
27       return false;
28     }
29
30     if (keycode == AU_TOG && record->event.pressed) {
31         if (is_audio_on())
32         {
33             audio_off();
34         }
35         else
36         {
37             audio_on();
38         }
39       return false;
40     }
41
42     if (keycode == MU_ON && record->event.pressed) {
43         music_on();
44         return false;
45     }
46
47     if (keycode == MU_OFF && record->event.pressed) {
48         music_off();
49         return false;
50     }
51
52     if (keycode == MU_TOG && record->event.pressed) {
53         if (music_activated)
54         {
55             music_off();
56         }
57         else
58         {
59             music_on();
60         }
61         return false;
62     }
63
64     if (keycode == MUV_IN && record->event.pressed) {
65         voice_iterate();
66         music_scale_user();
67         return false;
68     }
69
70     if (keycode == MUV_DE && record->event.pressed) {
71         voice_deiterate();
72         music_scale_user();
73         return false;
74     }
75
76     if (music_activated) {
77
78       if (keycode == KC_LCTL && record->event.pressed) { // Start recording
79         stop_all_notes();
80         music_sequence_recording = true;
81         music_sequence_recorded = false;
82         music_sequence_playing = false;
83         music_sequence_count = 0;
84         return false;
85       }
86
87       if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing
88         stop_all_notes();
89         if (music_sequence_recording) { // was recording
90           music_sequence_recorded = true;
91         }
92         music_sequence_recording = false;
93         music_sequence_playing = false;
94         return false;
95       }
96
97       if (keycode == KC_LGUI && record->event.pressed && music_sequence_recorded) { // Start playing
98         stop_all_notes();
99         music_sequence_recording = false;
100         music_sequence_playing = true;
101         music_sequence_position = 0;
102         music_sequence_timer = 0;
103         return false;
104       }
105
106       if (keycode == KC_UP) {
107         if (record->event.pressed)
108             music_sequence_interval-=10;
109         return false;
110       }
111
112       if (keycode == KC_DOWN) {
113         if (record->event.pressed)
114             music_sequence_interval+=10;
115         return false;
116       }
117       #define MUSIC_MODE_GUITAR
118
119       #ifdef MUSIC_MODE_CHROMATIC
120       float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(MATRIX_ROWS - record->event.key.row));
121       #elif defined(MUSIC_MODE_GUITAR)
122       float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(float)(MATRIX_ROWS - record->event.key.row + 7)*5.0/12);
123       #elif defined(MUSIC_MODE_VIOLIN)
124       float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(float)(MATRIX_ROWS - record->event.key.row + 5)*7.0/12);
125       #else
126       float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + SCALE[record->event.key.col + music_offset])/12.0+(MATRIX_ROWS - record->event.key.row));
127       #endif
128
129       if (record->event.pressed) {
130         play_note(freq, 0xF);
131         if (music_sequence_recording) {
132           music_sequence[music_sequence_count] = freq;
133           music_sequence_count++;
134         }
135       } else {
136         stop_note(freq);
137       }
138
139       if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
140         return false;
141     }
142   return true;
143 }
144
145 bool is_music_on(void) {
146     return (music_activated != 0);
147 }
148
149 void music_toggle(void) {
150     if (!music_activated) {
151         music_on();
152     } else {
153         music_off();
154     }
155 }
156
157 void music_on(void) {
158     music_activated = 1;
159     music_on_user();
160 }
161
162 void music_off(void) {
163     music_activated = 0;
164     stop_all_notes();
165 }
166
167
168 __attribute__ ((weak))
169 void music_on_user() {}
170
171 __attribute__ ((weak))
172 void audio_on_user() {}
173
174 __attribute__ ((weak))
175 void music_scale_user() {}
176
177 void matrix_scan_music(void) {
178   if (music_sequence_playing) {
179     if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) {
180       music_sequence_timer = timer_read();
181       stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]);
182       play_note(music_sequence[music_sequence_position], 0xF);
183       music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
184     }
185   }
186 }