]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/audio/audio.c
adds planck light keyboard
[qmk_firmware.git] / quantum / audio / audio.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 <stdio.h>
18 #include <string.h>
19 //#include <math.h>
20 #if defined(__AVR__)
21   #include <avr/pgmspace.h>
22   #include <avr/interrupt.h>
23   #include <avr/io.h>
24 #endif
25 #include "print.h"
26 #include "audio.h"
27 #include "keymap.h"
28 #include "wait.h"
29
30 #include "eeconfig.h"
31
32 #define CPU_PRESCALER 8
33
34 // -----------------------------------------------------------------------------
35 // Timer Abstractions
36 // -----------------------------------------------------------------------------
37
38 // TIMSK3 - Timer/Counter #3 Interrupt Mask Register
39 // Turn on/off 3A interputs, stopping/enabling the ISR calls
40 #ifdef C6_AUDIO
41     #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
42     #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
43 #endif
44
45 #ifdef B5_AUDIO
46     #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
47     #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
48 #endif
49
50 // TCCR3A: Timer/Counter #3 Control Register
51 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
52
53 #ifdef C6_AUDIO
54     #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
55     #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
56 #endif
57
58 #ifdef B5_AUDIO
59     #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
60     #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
61 #endif
62
63 // Fast PWM Mode Controls
64
65 #ifdef C6_AUDIO
66     #define TIMER_3_PERIOD     ICR3
67     #define TIMER_3_DUTY_CYCLE OCR3A
68 #endif
69
70 #ifdef B5_AUDIO
71     #define TIMER_1_PERIOD     ICR1
72     #define TIMER_1_DUTY_CYCLE OCR1A
73 #endif
74
75
76 // -----------------------------------------------------------------------------
77
78
79 int voices = 0;
80 int voice_place = 0;
81 float frequency = 0;
82 float frequency_alt = 0;
83 int volume = 0;
84 long position = 0;
85
86 float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
87 int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
88 bool sliding = false;
89
90 float place = 0;
91
92 uint8_t * sample;
93 uint16_t sample_length = 0;
94
95 bool     playing_notes = false;
96 bool     playing_note = false;
97 float    note_frequency = 0;
98 float    note_length = 0;
99 uint8_t  note_tempo = TEMPO_DEFAULT;
100 float    note_timbre = TIMBRE_DEFAULT;
101 uint16_t note_position = 0;
102 float (* notes_pointer)[][2];
103 uint16_t notes_count;
104 bool     notes_repeat;
105 bool     note_resting = false;
106
107 uint8_t current_note = 0;
108 uint8_t rest_counter = 0;
109
110 #ifdef VIBRATO_ENABLE
111 float vibrato_counter = 0;
112 float vibrato_strength = .5;
113 float vibrato_rate = 0.125;
114 #endif
115
116 float polyphony_rate = 0;
117
118 static bool audio_initialized = false;
119
120 audio_config_t audio_config;
121
122 uint16_t envelope_index = 0;
123 bool glissando = true;
124
125 #ifndef STARTUP_SONG
126     #define STARTUP_SONG SONG(STARTUP_SOUND)
127 #endif
128 #ifndef AUDIO_ON_SONG
129     #define AUDIO_ON_SONG SONG(AUDIO_ON_SOUND)
130 #endif
131 #ifndef AUDIO_OFF_SONG
132     #define AUDIO_OFF_SONG SONG(AUDIO_OFF_SOUND)
133 #endif
134 float startup_song[][2] = STARTUP_SONG;
135 float audio_on_song[][2] = AUDIO_ON_SONG;
136 float audio_off_song[][2] = AUDIO_OFF_SONG;
137
138 void audio_init()
139 {
140
141     // Check EEPROM
142     if (!eeconfig_is_enabled())
143     {
144         eeconfig_init();
145     }
146     audio_config.raw = eeconfig_read_audio();
147
148     if (!audio_initialized) {
149
150         // Set port PC6 (OC3A and /OC4A) as output
151
152         #ifdef C6_AUDIO
153             DDRC |= _BV(PORTC6);
154         #else
155             DDRC |= _BV(PORTC6);
156             PORTC &= ~_BV(PORTC6);
157         #endif
158
159         #ifdef B5_AUDIO
160             DDRB |= _BV(PORTB5);
161         #else
162             DDRB |= _BV(PORTB5);
163             PORTB &= ~_BV(PORTB5);
164         #endif
165
166         #ifdef C6_AUDIO
167             DISABLE_AUDIO_COUNTER_3_ISR;
168         #endif
169         
170         #ifdef B5_AUDIO
171             DISABLE_AUDIO_COUNTER_1_ISR;
172         #endif
173
174         // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
175         // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
176         // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
177         // Clock Select (CS3n) = 0b010 = Clock / 8
178
179         #ifdef C6_AUDIO
180             TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
181             TCCR3B = (1 << WGM33)  | (1 << WGM32)  | (0 << CS32)  | (1 << CS31) | (0 << CS30);
182         #endif
183
184         #ifdef B5_AUDIO
185             TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
186             TCCR1B = (1 << WGM13)  | (1 << WGM12)  | (0 << CS12)  | (1 << CS11) | (0 << CS10);
187
188             TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER));
189             TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre);
190         #endif
191
192         audio_initialized = true;
193     }
194
195     if (audio_config.enable) {
196         PLAY_SONG(startup_song);
197     }
198     
199 }
200
201 void stop_all_notes()
202 {
203     dprintf("audio stop all notes");
204
205     if (!audio_initialized) {
206         audio_init();
207     }
208     voices = 0;
209
210
211     #ifdef C6_AUDIO
212         DISABLE_AUDIO_COUNTER_3_ISR;
213         DISABLE_AUDIO_COUNTER_3_OUTPUT;
214     #endif
215
216     #ifdef B5_AUDIO
217         DISABLE_AUDIO_COUNTER_1_ISR;
218         DISABLE_AUDIO_COUNTER_1_OUTPUT;
219     #endif
220
221     playing_notes = false;
222     playing_note = false;
223     frequency = 0;
224     frequency_alt = 0;
225     volume = 0;
226
227     for (uint8_t i = 0; i < 8; i++)
228     {
229         frequencies[i] = 0;
230         volumes[i] = 0;
231     }
232 }
233
234 void stop_note(float freq)
235 {
236     dprintf("audio stop note freq=%d", (int)freq);
237
238     if (playing_note) {
239         if (!audio_initialized) {
240             audio_init();
241         }
242         for (int i = 7; i >= 0; i--) {
243             if (frequencies[i] == freq) {
244                 frequencies[i] = 0;
245                 volumes[i] = 0;
246                 for (int j = i; (j < 7); j++) {
247                     frequencies[j] = frequencies[j+1];
248                     frequencies[j+1] = 0;
249                     volumes[j] = volumes[j+1];
250                     volumes[j+1] = 0;
251                 }
252                 break;
253             }
254         }
255         voices--;
256         if (voices < 0)
257             voices = 0;
258         if (voice_place >= voices) {
259             voice_place = 0;
260         }
261         if (voices == 0) {
262             #ifdef C6_AUDIO
263                 DISABLE_AUDIO_COUNTER_3_ISR;
264                 DISABLE_AUDIO_COUNTER_3_OUTPUT;
265             #endif
266             #ifdef B5_AUDIO
267                 DISABLE_AUDIO_COUNTER_1_ISR;
268                 DISABLE_AUDIO_COUNTER_1_OUTPUT;
269             #endif
270             frequency = 0;
271             frequency_alt = 0;
272             volume = 0;
273             playing_note = false;
274         }
275     }
276 }
277
278 #ifdef VIBRATO_ENABLE
279
280 float mod(float a, int b)
281 {
282     float r = fmod(a, b);
283     return r < 0 ? r + b : r;
284 }
285
286 float vibrato(float average_freq) {
287     #ifdef VIBRATO_STRENGTH_ENABLE
288         float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
289     #else
290         float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
291     #endif
292     vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
293     return vibrated_freq;
294 }
295
296 #endif
297
298 #ifdef C6_AUDIO
299 ISR(TIMER3_COMPA_vect)
300 {
301     float freq;
302
303     if (playing_note) {
304         if (voices > 0) {
305
306             #ifdef B5_AUDIO
307             float freq_alt = 0;
308                 if (voices > 1) {
309                     if (polyphony_rate == 0) {
310                         if (glissando) {
311                             if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440/frequencies[voices - 2]/12/2)) {
312                                 frequency_alt = frequency_alt * pow(2, 440/frequency_alt/12/2);
313                             } else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) {
314                                 frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2);
315                             } else {
316                                 frequency_alt = frequencies[voices - 2];
317                             }
318                         } else {
319                             frequency_alt = frequencies[voices - 2];
320                         }
321
322                         #ifdef VIBRATO_ENABLE
323                             if (vibrato_strength > 0) {
324                                 freq_alt = vibrato(frequency_alt);
325                             } else {
326                                 freq_alt = frequency_alt;
327                             }
328                         #else
329                             freq_alt = frequency_alt;
330                         #endif
331                     }
332
333                     if (envelope_index < 65535) {
334                         envelope_index++;
335                     }
336
337                     freq_alt = voice_envelope(freq_alt);
338
339                     if (freq_alt < 30.517578125) {
340                         freq_alt = 30.52;
341                     }
342
343                     TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq_alt * CPU_PRESCALER));
344                     TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq_alt * CPU_PRESCALER)) * note_timbre);
345                 }
346             #endif
347
348             if (polyphony_rate > 0) {
349                 if (voices > 1) {
350                     voice_place %= voices;
351                     if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
352                         voice_place = (voice_place + 1) % voices;
353                         place = 0.0;
354                     }
355                 }
356
357                 #ifdef VIBRATO_ENABLE
358                     if (vibrato_strength > 0) {
359                         freq = vibrato(frequencies[voice_place]);
360                     } else {
361                         freq = frequencies[voice_place];
362                     }
363                 #else
364                     freq = frequencies[voice_place];
365                 #endif
366             } else {
367                 if (glissando) {
368                     if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
369                         frequency = frequency * pow(2, 440/frequency/12/2);
370                     } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
371                         frequency = frequency * pow(2, -440/frequency/12/2);
372                     } else {
373                         frequency = frequencies[voices - 1];
374                     }
375                 } else {
376                     frequency = frequencies[voices - 1];
377                 }
378
379                 #ifdef VIBRATO_ENABLE
380                     if (vibrato_strength > 0) {
381                         freq = vibrato(frequency);
382                     } else {
383                         freq = frequency;
384                     }
385                 #else
386                     freq = frequency;
387                 #endif
388             }
389
390             if (envelope_index < 65535) {
391                 envelope_index++;
392             }
393
394             freq = voice_envelope(freq);
395
396             if (freq < 30.517578125) {
397                 freq = 30.52;
398             }
399
400             TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
401             TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
402         }
403     }
404
405     if (playing_notes) {
406         if (note_frequency > 0) {
407             #ifdef VIBRATO_ENABLE
408                 if (vibrato_strength > 0) {
409                     freq = vibrato(note_frequency);
410                 } else {
411                     freq = note_frequency;
412                 }
413             #else
414                     freq = note_frequency;
415             #endif
416
417             if (envelope_index < 65535) {
418                 envelope_index++;
419             }
420             freq = voice_envelope(freq);
421
422             TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
423             TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
424         } else {
425             TIMER_3_PERIOD = 0;
426             TIMER_3_DUTY_CYCLE = 0;
427         }
428
429         note_position++;
430         bool end_of_note = false;
431         if (TIMER_3_PERIOD > 0) {
432             if (!note_resting) 
433                 end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF - 1));
434             else
435                 end_of_note = (note_position >= (note_length));
436         } else {
437             end_of_note = (note_position >= (note_length));
438         }
439
440         if (end_of_note) {
441             current_note++;
442             if (current_note >= notes_count) {
443                 if (notes_repeat) {
444                     current_note = 0;
445                 } else {
446                     DISABLE_AUDIO_COUNTER_3_ISR;
447                     DISABLE_AUDIO_COUNTER_3_OUTPUT;
448                     playing_notes = false;
449                     return;
450                 }
451             }
452             if (!note_resting) {
453                 note_resting = true;
454                 current_note--;
455                 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
456                     note_frequency = 0;
457                     note_length = 1;
458                 } else {
459                     note_frequency = (*notes_pointer)[current_note][0];
460                     note_length = 1;
461                 }
462             } else {
463                 note_resting = false;
464                 envelope_index = 0;
465                 note_frequency = (*notes_pointer)[current_note][0];
466                 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
467             }
468
469             note_position = 0;
470         }
471     }
472
473     if (!audio_config.enable) {
474         playing_notes = false;
475         playing_note = false;
476     }
477 }
478 #endif
479
480 #ifdef B5_AUDIO
481 ISR(TIMER1_COMPA_vect)
482 {
483     #if defined(B5_AUDIO) && !defined(C6_AUDIO)
484     float freq = 0;
485
486     if (playing_note) {
487         if (voices > 0) {
488             if (polyphony_rate > 0) {
489                 if (voices > 1) {
490                     voice_place %= voices;
491                     if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
492                         voice_place = (voice_place + 1) % voices;
493                         place = 0.0;
494                     }
495                 }
496
497                 #ifdef VIBRATO_ENABLE
498                     if (vibrato_strength > 0) {
499                         freq = vibrato(frequencies[voice_place]);
500                     } else {
501                         freq = frequencies[voice_place];
502                     }
503                 #else
504                     freq = frequencies[voice_place];
505                 #endif
506             } else {
507                 if (glissando) {
508                     if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
509                         frequency = frequency * pow(2, 440/frequency/12/2);
510                     } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
511                         frequency = frequency * pow(2, -440/frequency/12/2);
512                     } else {
513                         frequency = frequencies[voices - 1];
514                     }
515                 } else {
516                     frequency = frequencies[voices - 1];
517                 }
518
519                 #ifdef VIBRATO_ENABLE
520                     if (vibrato_strength > 0) {
521                         freq = vibrato(frequency);
522                     } else {
523                         freq = frequency;
524                     }
525                 #else
526                     freq = frequency;
527                 #endif
528             }
529
530             if (envelope_index < 65535) {
531                 envelope_index++;
532             }
533
534             freq = voice_envelope(freq);
535
536             if (freq < 30.517578125) {
537                 freq = 30.52;
538             }
539
540             TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
541             TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
542         }
543     }
544
545     if (playing_notes) {
546         if (note_frequency > 0) {
547             #ifdef VIBRATO_ENABLE
548                 if (vibrato_strength > 0) {
549                     freq = vibrato(note_frequency);
550                 } else {
551                     freq = note_frequency;
552                 }
553             #else
554                     freq = note_frequency;
555             #endif
556
557             if (envelope_index < 65535) {
558                 envelope_index++;
559             }
560             freq = voice_envelope(freq);
561
562             TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
563             TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
564         } else {
565             TIMER_1_PERIOD = 0;
566             TIMER_1_DUTY_CYCLE = 0;
567         }
568
569         note_position++;
570         bool end_of_note = false;
571         if (TIMER_1_PERIOD > 0) {
572             if (!note_resting) 
573                 end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF - 1));
574             else
575                 end_of_note = (note_position >= (note_length));
576         } else {
577             end_of_note = (note_position >= (note_length));
578         }
579
580         if (end_of_note) {
581             current_note++;
582             if (current_note >= notes_count) {
583                 if (notes_repeat) {
584                     current_note = 0;
585                 } else {
586                     DISABLE_AUDIO_COUNTER_1_ISR;
587                     DISABLE_AUDIO_COUNTER_1_OUTPUT;
588                     playing_notes = false;
589                     return;
590                 }
591             }
592             if (!note_resting) {
593                 note_resting = true;
594                 current_note--;
595                 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
596                     note_frequency = 0;
597                     note_length = 1;
598                 } else {
599                     note_frequency = (*notes_pointer)[current_note][0];
600                     note_length = 1;
601                 }
602             } else {
603                 note_resting = false;
604                 envelope_index = 0;
605                 note_frequency = (*notes_pointer)[current_note][0];
606                 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
607             }
608
609             note_position = 0;
610         }
611     }
612
613     if (!audio_config.enable) {
614         playing_notes = false;
615         playing_note = false;
616     }
617 #endif
618 }
619 #endif
620
621 void play_note(float freq, int vol) {
622
623     dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
624
625     if (!audio_initialized) {
626         audio_init();
627     }
628
629     if (audio_config.enable && voices < 8) {
630         #ifdef C6_AUDIO
631             DISABLE_AUDIO_COUNTER_3_ISR;
632         #endif
633         #ifdef B5_AUDIO
634             DISABLE_AUDIO_COUNTER_1_ISR;
635         #endif
636
637         // Cancel notes if notes are playing
638         if (playing_notes)
639             stop_all_notes();
640
641         playing_note = true;
642
643         envelope_index = 0;
644
645         if (freq > 0) {
646             frequencies[voices] = freq;
647             volumes[voices] = vol;
648             voices++;
649         }
650
651         #ifdef C6_AUDIO
652             ENABLE_AUDIO_COUNTER_3_ISR;
653             ENABLE_AUDIO_COUNTER_3_OUTPUT;
654         #endif
655         #ifdef B5_AUDIO
656             #ifdef C6_AUDIO
657             if (voices > 1) {
658                 ENABLE_AUDIO_COUNTER_1_ISR;
659                 ENABLE_AUDIO_COUNTER_1_OUTPUT;
660             }
661             #else
662             ENABLE_AUDIO_COUNTER_1_ISR;
663             ENABLE_AUDIO_COUNTER_1_OUTPUT;
664             #endif
665         #endif
666     }
667
668 }
669
670 void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
671 {
672
673     if (!audio_initialized) {
674         audio_init();
675     }
676
677     if (audio_config.enable) {
678
679         #ifdef C6_AUDIO
680             DISABLE_AUDIO_COUNTER_3_ISR;
681         #endif
682         #ifdef B5_AUDIO
683             DISABLE_AUDIO_COUNTER_1_ISR;
684         #endif
685
686         // Cancel note if a note is playing
687         if (playing_note)
688             stop_all_notes();
689
690         playing_notes = true;
691
692         notes_pointer = np;
693         notes_count = n_count;
694         notes_repeat = n_repeat;
695
696         place = 0;
697         current_note = 0;
698
699         note_frequency = (*notes_pointer)[current_note][0];
700         note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
701         note_position = 0;
702
703
704         #ifdef C6_AUDIO
705             ENABLE_AUDIO_COUNTER_3_ISR;
706             ENABLE_AUDIO_COUNTER_3_OUTPUT;
707         #endif
708         #ifdef B5_AUDIO
709             #ifndef C6_AUDIO
710             ENABLE_AUDIO_COUNTER_1_ISR;
711             ENABLE_AUDIO_COUNTER_1_OUTPUT;
712             #endif
713         #endif
714     }
715
716 }
717
718 bool is_playing_notes(void) {
719     return playing_notes;
720 }
721
722 bool is_audio_on(void) {
723     return (audio_config.enable != 0);
724 }
725
726 void audio_toggle(void) {
727     audio_config.enable ^= 1;
728     eeconfig_update_audio(audio_config.raw);
729     if (audio_config.enable)
730         audio_on_user();
731 }
732
733 void audio_on(void) {
734     audio_config.enable = 1;
735     eeconfig_update_audio(audio_config.raw);
736     audio_on_user();
737     PLAY_SONG(audio_on_song);
738 }
739
740 void audio_off(void) {
741     PLAY_SONG(audio_off_song);
742     wait_ms(100);
743     stop_all_notes();
744     audio_config.enable = 0;
745     eeconfig_update_audio(audio_config.raw);
746 }
747
748 #ifdef VIBRATO_ENABLE
749
750 // Vibrato rate functions
751
752 void set_vibrato_rate(float rate) {
753     vibrato_rate = rate;
754 }
755
756 void increase_vibrato_rate(float change) {
757     vibrato_rate *= change;
758 }
759
760 void decrease_vibrato_rate(float change) {
761     vibrato_rate /= change;
762 }
763
764 #ifdef VIBRATO_STRENGTH_ENABLE
765
766 void set_vibrato_strength(float strength) {
767     vibrato_strength = strength;
768 }
769
770 void increase_vibrato_strength(float change) {
771     vibrato_strength *= change;
772 }
773
774 void decrease_vibrato_strength(float change) {
775     vibrato_strength /= change;
776 }
777
778 #endif  /* VIBRATO_STRENGTH_ENABLE */
779
780 #endif /* VIBRATO_ENABLE */
781
782 // Polyphony functions
783
784 void set_polyphony_rate(float rate) {
785     polyphony_rate = rate;
786 }
787
788 void enable_polyphony() {
789     polyphony_rate = 5;
790 }
791
792 void disable_polyphony() {
793     polyphony_rate = 0;
794 }
795
796 void increase_polyphony_rate(float change) {
797     polyphony_rate *= change;
798 }
799
800 void decrease_polyphony_rate(float change) {
801     polyphony_rate /= change;
802 }
803
804 // Timbre function
805
806 void set_timbre(float timbre) {
807     note_timbre = timbre;
808 }
809
810 // Tempo functions
811
812 void set_tempo(uint8_t tempo) {
813     note_tempo = tempo;
814 }
815
816 void decrease_tempo(uint8_t tempo_change) {
817     note_tempo += tempo_change;
818 }
819
820 void increase_tempo(uint8_t tempo_change) {
821     if (note_tempo - tempo_change < 10) {
822         note_tempo = 10;
823     } else {
824         note_tempo -= tempo_change;
825     }
826 }