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