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