qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

process_music.c (9939B)


      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 
     29 bool    music_activated     = false;
     30 bool    midi_activated      = false;
     31 uint8_t music_starting_note = 0x0C;
     32 int     music_offset        = 7;
     33 uint8_t music_mode          = MUSIC_MODE_MAJOR;
     34 
     35 // music sequencer
     36 static bool    music_sequence_recording = false;
     37 static bool    music_sequence_recorded  = false;
     38 static bool    music_sequence_playing   = false;
     39 static uint8_t music_sequence[16]       = {0};
     40 static uint8_t music_sequence_count     = 0;
     41 static uint8_t music_sequence_position  = 0;
     42 
     43 static uint16_t music_sequence_timer    = 0;
     44 static 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
     71 float music_mode_songs[NUMBER_OF_MODES][5][2] = {CHROMATIC_SONG, GUITAR_SONG, VIOLIN_SONG, MAJOR_SONG};
     72 float music_on_song[][2]                      = MUSIC_ON_SONG;
     73 float music_off_song[][2]                     = MUSIC_OFF_SONG;
     74 float midi_on_song[][2]                       = MIDI_ON_SONG;
     75 float midi_off_song[][2]                      = MIDI_OFF_SONG;
     76 #    endif
     77 
     78 static 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 
     87 static 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 
     96 void 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 
    105 bool 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 
    227 bool 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 
    243 bool is_music_on(void) {
    244     return (music_activated != 0);
    245 }
    246 
    247 void music_toggle(void) {
    248     if (!music_activated) {
    249         music_on();
    250     } else {
    251         music_off();
    252     }
    253 }
    254 
    255 void 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 
    263 void 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 
    271 bool is_midi_on(void) {
    272     return (midi_activated != 0);
    273 }
    274 
    275 void midi_toggle(void) {
    276     if (!midi_activated) {
    277         midi_on();
    278     } else {
    279         midi_off();
    280     }
    281 }
    282 
    283 void 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 
    291 void 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 
    301 void 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 
    309 void 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))