]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/audio/audio_arm.c
Clueboard 60% support (#1746)
[qmk_firmware.git] / quantum / audio / audio_arm.c
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
17 #include "audio.h"
18 #include "ch.h"
19 #include "hal.h"
20
21 #include <stdio.h>
22 #include <string.h>
23 #include "print.h"
24 #include "keymap.h"
25
26 #include "eeconfig.h"
27
28 // -----------------------------------------------------------------------------
29
30 int voices = 0;
31 int voice_place = 0;
32 float frequency = 0;
33 float frequency_alt = 0;
34 int volume = 0;
35 long position = 0;
36
37 float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
38 int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
39 bool sliding = false;
40
41 float place = 0;
42
43 uint8_t * sample;
44 uint16_t sample_length = 0;
45
46 bool     playing_notes = false;
47 bool     playing_note = false;
48 float    note_frequency = 0;
49 float    note_length = 0;
50 uint8_t  note_tempo = TEMPO_DEFAULT;
51 float    note_timbre = TIMBRE_DEFAULT;
52 uint16_t note_position = 0;
53 float (* notes_pointer)[][2];
54 uint16_t notes_count;
55 bool     notes_repeat;
56 bool     note_resting = false;
57
58 uint8_t current_note = 0;
59 uint8_t rest_counter = 0;
60
61 #ifdef VIBRATO_ENABLE
62 float vibrato_counter = 0;
63 float vibrato_strength = .5;
64 float vibrato_rate = 0.125;
65 #endif
66
67 float polyphony_rate = 0;
68
69 static bool audio_initialized = false;
70
71 audio_config_t audio_config;
72
73 uint16_t envelope_index = 0;
74 bool glissando = true;
75
76 #ifndef STARTUP_SONG
77     #define STARTUP_SONG SONG(STARTUP_SOUND)
78 #endif
79 float startup_song[][2] = STARTUP_SONG;
80
81 static void gpt_cb6(GPTDriver *gptp);
82 static void gpt_cb7(GPTDriver *gptp);
83 static void gpt_cb8(GPTDriver *gptp);
84
85 /*
86  * GPT6 configuration.
87  */
88 GPTConfig gpt6cfg1 = {
89   .frequency    = 440,
90   .callback     = gpt_cb6,
91   .cr2          = TIM_CR2_MMS_1,    /* MMS = 010 = TRGO on Update Event.    */
92   .dier         = 0U
93 };
94
95 GPTConfig gpt7cfg1 = {
96   .frequency    = 440,
97   .callback     = gpt_cb7,
98   .cr2          = TIM_CR2_MMS_1,    /* MMS = 010 = TRGO on Update Event.    */
99   .dier         = 0U
100 };
101
102 GPTConfig gpt8cfg1 = {
103   .frequency    = 10,
104   .callback     = gpt_cb8,
105   .cr2          = TIM_CR2_MMS_1,    /* MMS = 010 = TRGO on Update Event.    */
106   .dier         = 0U
107 };
108
109 static void gpt_cb6(GPTDriver *gptp) {
110     palTogglePad(GPIOA, 4);
111 }
112
113
114 static void gpt_cb7(GPTDriver *gptp) {
115     palTogglePad(GPIOA, 5);
116 }
117
118 void audio_init()
119 {
120
121     if (audio_initialized)
122         return;
123
124     // Check EEPROM
125     // if (!eeconfig_is_enabled())
126     // {
127     //     eeconfig_init();
128     // }
129     // audio_config.raw = eeconfig_read_audio();
130     audio_config.enable = true;
131
132     palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL);
133     palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL);
134
135     audio_initialized = true;
136
137     if (audio_config.enable) {
138         PLAY_SONG(startup_song);
139     }
140
141 }
142
143 void stop_all_notes()
144 {
145     dprintf("audio stop all notes");
146
147     if (!audio_initialized) {
148         audio_init();
149     }
150     voices = 0;
151
152     gptStopTimer(&GPTD6);
153     gptStopTimer(&GPTD7);
154     gptStopTimer(&GPTD8);
155
156     playing_notes = false;
157     playing_note = false;
158     frequency = 0;
159     frequency_alt = 0;
160     volume = 0;
161
162     for (uint8_t i = 0; i < 8; i++)
163     {
164         frequencies[i] = 0;
165         volumes[i] = 0;
166     }
167 }
168
169 void stop_note(float freq)
170 {
171     dprintf("audio stop note freq=%d", (int)freq);
172
173     if (playing_note) {
174         if (!audio_initialized) {
175             audio_init();
176         }
177         for (int i = 7; i >= 0; i--) {
178             if (frequencies[i] == freq) {
179                 frequencies[i] = 0;
180                 volumes[i] = 0;
181                 for (int j = i; (j < 7); j++) {
182                     frequencies[j] = frequencies[j+1];
183                     frequencies[j+1] = 0;
184                     volumes[j] = volumes[j+1];
185                     volumes[j+1] = 0;
186                 }
187                 break;
188             }
189         }
190         voices--;
191         if (voices < 0)
192             voices = 0;
193         if (voice_place >= voices) {
194             voice_place = 0;
195         }
196         if (voices == 0) {
197             gptStopTimer(&GPTD6);
198             gptStopTimer(&GPTD7);
199             gptStopTimer(&GPTD8);
200             frequency = 0;
201             frequency_alt = 0;
202             volume = 0;
203             playing_note = false;
204         }
205     }
206 }
207
208 #ifdef VIBRATO_ENABLE
209
210 float mod(float a, int b)
211 {
212     float r = fmod(a, b);
213     return r < 0 ? r + b : r;
214 }
215
216 float vibrato(float average_freq) {
217     #ifdef VIBRATO_STRENGTH_ENABLE
218         float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
219     #else
220         float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
221     #endif
222     vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
223     return vibrated_freq;
224 }
225
226 #endif
227
228 static void restart_gpt6(void) {
229     // gptStopTimer(&GPTD6);
230
231     gptStart(&GPTD6, &gpt6cfg1);
232     gptStartContinuous(&GPTD6, 2U);
233 }
234
235 static void restart_gpt7(void) {
236     // gptStopTimer(&GPTD7);
237
238     gptStart(&GPTD7, &gpt7cfg1);
239     gptStartContinuous(&GPTD7, 2U);
240 }
241
242 static void gpt_cb8(GPTDriver *gptp) {
243     float freq;
244
245     if (playing_note) {
246         if (voices > 0) {
247
248             float freq_alt = 0;
249                 if (voices > 1) {
250                     if (polyphony_rate == 0) {
251                         if (glissando) {
252                             if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440/frequencies[voices - 2]/12/2)) {
253                                 frequency_alt = frequency_alt * pow(2, 440/frequency_alt/12/2);
254                             } else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) {
255                                 frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2);
256                             } else {
257                                 frequency_alt = frequencies[voices - 2];
258                             }
259                         } else {
260                             frequency_alt = frequencies[voices - 2];
261                         }
262
263                         #ifdef VIBRATO_ENABLE
264                             if (vibrato_strength > 0) {
265                                 freq_alt = vibrato(frequency_alt);
266                             } else {
267                                 freq_alt = frequency_alt;
268                             }
269                         #else
270                             freq_alt = frequency_alt;
271                         #endif
272                     }
273
274                     if (envelope_index < 65535) {
275                         envelope_index++;
276                     }
277
278                     freq_alt = voice_envelope(freq_alt);
279
280                     if (freq_alt < 30.517578125) {
281                         freq_alt = 30.52;
282                     }
283
284                     if (gpt6cfg1.frequency != (uint16_t)freq_alt) {
285                         gpt6cfg1.frequency = freq_alt;
286                         restart_gpt6();
287                     }
288                     //note_timbre;
289                 } else {
290                     // gptStopTimer(&GPTD6);
291                 }
292
293             if (polyphony_rate > 0) {
294                 if (voices > 1) {
295                     voice_place %= voices;
296                     if (place++ > (frequencies[voice_place] / polyphony_rate)) {
297                         voice_place = (voice_place + 1) % voices;
298                         place = 0.0;
299                     }
300                 }
301
302                 #ifdef VIBRATO_ENABLE
303                     if (vibrato_strength > 0) {
304                         freq = vibrato(frequencies[voice_place]);
305                     } else {
306                         freq = frequencies[voice_place];
307                     }
308                 #else
309                     freq = frequencies[voice_place];
310                 #endif
311             } else {
312                 if (glissando) {
313                     if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
314                         frequency = frequency * pow(2, 440/frequency/12/2);
315                     } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
316                         frequency = frequency * pow(2, -440/frequency/12/2);
317                     } else {
318                         frequency = frequencies[voices - 1];
319                     }
320                 } else {
321                     frequency = frequencies[voices - 1];
322                 }
323
324                 #ifdef VIBRATO_ENABLE
325                     if (vibrato_strength > 0) {
326                         freq = vibrato(frequency);
327                     } else {
328                         freq = frequency;
329                     }
330                 #else
331                     freq = frequency;
332                 #endif
333             }
334
335             if (envelope_index < 65535) {
336                 envelope_index++;
337             }
338
339             freq = voice_envelope(freq);
340
341             if (freq < 30.517578125) {
342                 freq = 30.52;
343             }
344
345
346             if (gpt7cfg1.frequency != (uint16_t)freq) {
347                 gpt7cfg1.frequency = freq;
348                 restart_gpt7();
349             }
350             //note_timbre;
351         } else {
352             // gptStopTimer(&GPTD7);
353         }
354     }
355
356     if (playing_notes) {
357         if (note_frequency > 0) {
358             #ifdef VIBRATO_ENABLE
359                 if (vibrato_strength > 0) {
360                     freq = vibrato(note_frequency);
361                 } else {
362                     freq = note_frequency;
363                 }
364             #else
365                     freq = note_frequency;
366             #endif
367
368             if (envelope_index < 65535) {
369                 envelope_index++;
370             }
371             freq = voice_envelope(freq);
372
373
374             if (gpt6cfg1.frequency != (uint16_t)freq) {
375                 gpt6cfg1.frequency = freq;
376                 restart_gpt6();
377                 gpt7cfg1.frequency = freq;
378                 restart_gpt7();
379             }
380             //note_timbre;
381         } else {
382             // gptStopTimer(&GPTD6);
383             // gptStopTimer(&GPTD7);
384         }
385
386         note_position++;
387         bool end_of_note = false;
388         if (gpt6cfg1.frequency > 0) {
389             if (!note_resting) 
390                 end_of_note = (note_position >= (note_length*16 - 1));
391             else
392                 end_of_note = (note_position >= (note_length*16));
393         } else {
394             end_of_note = (note_position >= (note_length*16));
395         }
396
397         if (end_of_note) {
398             current_note++;
399             if (current_note >= notes_count) {
400                 if (notes_repeat) {
401                     current_note = 0;
402                 } else {
403                     gptStopTimer(&GPTD6);
404                     gptStopTimer(&GPTD7);
405                     // gptStopTimer(&GPTD8);
406                     playing_notes = false;
407                     return;
408                 }
409             }
410             if (!note_resting) {
411                 note_resting = true;
412                 current_note--;
413                 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
414                     note_frequency = 0;
415                     note_length = 1;
416                 } else {
417                     note_frequency = (*notes_pointer)[current_note][0];
418                     note_length = 1;
419                 }
420             } else {
421                 note_resting = false;
422                 envelope_index = 0;
423                 note_frequency = (*notes_pointer)[current_note][0];
424                 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
425             }
426
427             note_position = 0;
428         }
429     }
430
431     if (!audio_config.enable) {
432         playing_notes = false;
433         playing_note = false;
434     }
435 }
436
437 void play_note(float freq, int vol) {
438
439     dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
440
441     if (!audio_initialized) {
442         audio_init();
443     }
444
445     if (audio_config.enable && voices < 8) {
446
447         // Cancel notes if notes are playing
448         if (playing_notes)
449             stop_all_notes();
450
451         playing_note = true;
452
453         envelope_index = 0;
454
455         if (freq > 0) {
456             frequencies[voices] = freq;
457             volumes[voices] = vol;
458             voices++;
459         }
460
461         gptStart(&GPTD8, &gpt8cfg1);
462         gptStartContinuous(&GPTD8, 2U);
463             
464     }
465
466 }
467
468 void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
469 {
470
471     if (!audio_initialized) {
472         audio_init();
473     }
474
475     if (audio_config.enable) {
476
477         // Cancel note if a note is playing
478         if (playing_note)
479             stop_all_notes();
480
481         playing_notes = true;
482
483         notes_pointer = np;
484         notes_count = n_count;
485         notes_repeat = n_repeat;
486
487         place = 0;
488         current_note = 0;
489
490         note_frequency = (*notes_pointer)[current_note][0];
491         note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
492         note_position = 0;
493
494         gptStart(&GPTD8, &gpt8cfg1);
495         gptStartContinuous(&GPTD8, 2U);
496         restart_gpt6();
497         restart_gpt7();
498     }
499
500 }
501
502 bool is_playing_notes(void) {
503     return playing_notes;
504 }
505
506 bool is_audio_on(void) {
507     return (audio_config.enable != 0);
508 }
509
510 void audio_toggle(void) {
511     audio_config.enable ^= 1;
512     eeconfig_update_audio(audio_config.raw);
513     if (audio_config.enable)
514         audio_on_user();
515 }
516
517 void audio_on(void) {
518     audio_config.enable = 1;
519     eeconfig_update_audio(audio_config.raw);
520     audio_on_user();
521 }
522
523 void audio_off(void) {
524     audio_config.enable = 0;
525     eeconfig_update_audio(audio_config.raw);
526 }
527
528 #ifdef VIBRATO_ENABLE
529
530 // Vibrato rate functions
531
532 void set_vibrato_rate(float rate) {
533     vibrato_rate = rate;
534 }
535
536 void increase_vibrato_rate(float change) {
537     vibrato_rate *= change;
538 }
539
540 void decrease_vibrato_rate(float change) {
541     vibrato_rate /= change;
542 }
543
544 #ifdef VIBRATO_STRENGTH_ENABLE
545
546 void set_vibrato_strength(float strength) {
547     vibrato_strength = strength;
548 }
549
550 void increase_vibrato_strength(float change) {
551     vibrato_strength *= change;
552 }
553
554 void decrease_vibrato_strength(float change) {
555     vibrato_strength /= change;
556 }
557
558 #endif  /* VIBRATO_STRENGTH_ENABLE */
559
560 #endif /* VIBRATO_ENABLE */
561
562 // Polyphony functions
563
564 void set_polyphony_rate(float rate) {
565     polyphony_rate = rate;
566 }
567
568 void enable_polyphony() {
569     polyphony_rate = 5;
570 }
571
572 void disable_polyphony() {
573     polyphony_rate = 0;
574 }
575
576 void increase_polyphony_rate(float change) {
577     polyphony_rate *= change;
578 }
579
580 void decrease_polyphony_rate(float change) {
581     polyphony_rate /= change;
582 }
583
584 // Timbre function
585
586 void set_timbre(float timbre) {
587     note_timbre = timbre;
588 }
589
590 // Tempo functions
591
592 void set_tempo(uint8_t tempo) {
593     note_tempo = tempo;
594 }
595
596 void decrease_tempo(uint8_t tempo_change) {
597     note_tempo += tempo_change;
598 }
599
600 void increase_tempo(uint8_t tempo_change) {
601     if (note_tempo - tempo_change < 10) {
602         note_tempo = 10;
603     } else {
604         note_tempo -= tempo_change;
605     }
606 }