]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/audio/audio.c
Clueboard 60% support (#1746)
[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         #endif
188
189         audio_initialized = true;
190     }
191
192     if (audio_config.enable) {
193         PLAY_SONG(startup_song);
194     }
195
196 }
197
198 void stop_all_notes()
199 {
200     dprintf("audio stop all notes");
201
202     if (!audio_initialized) {
203         audio_init();
204     }
205     voices = 0;
206
207
208     #ifdef C6_AUDIO
209         DISABLE_AUDIO_COUNTER_3_ISR;
210         DISABLE_AUDIO_COUNTER_3_OUTPUT;
211     #endif
212
213     #ifdef B5_AUDIO
214         DISABLE_AUDIO_COUNTER_1_ISR;
215         DISABLE_AUDIO_COUNTER_1_OUTPUT;
216     #endif
217
218     playing_notes = false;
219     playing_note = false;
220     frequency = 0;
221     frequency_alt = 0;
222     volume = 0;
223
224     for (uint8_t i = 0; i < 8; i++)
225     {
226         frequencies[i] = 0;
227         volumes[i] = 0;
228     }
229 }
230
231 void stop_note(float freq)
232 {
233     dprintf("audio stop note freq=%d", (int)freq);
234
235     if (playing_note) {
236         if (!audio_initialized) {
237             audio_init();
238         }
239         for (int i = 7; i >= 0; i--) {
240             if (frequencies[i] == freq) {
241                 frequencies[i] = 0;
242                 volumes[i] = 0;
243                 for (int j = i; (j < 7); j++) {
244                     frequencies[j] = frequencies[j+1];
245                     frequencies[j+1] = 0;
246                     volumes[j] = volumes[j+1];
247                     volumes[j+1] = 0;
248                 }
249                 break;
250             }
251         }
252         voices--;
253         if (voices < 0)
254             voices = 0;
255         if (voice_place >= voices) {
256             voice_place = 0;
257         }
258         if (voices == 0) {
259             #ifdef C6_AUDIO
260                 DISABLE_AUDIO_COUNTER_3_ISR;
261                 DISABLE_AUDIO_COUNTER_3_OUTPUT;
262             #endif
263             #ifdef B5_AUDIO
264                 DISABLE_AUDIO_COUNTER_1_ISR;
265                 DISABLE_AUDIO_COUNTER_1_OUTPUT;
266             #endif
267             frequency = 0;
268             frequency_alt = 0;
269             volume = 0;
270             playing_note = false;
271         }
272     }
273 }
274
275 #ifdef VIBRATO_ENABLE
276
277 float mod(float a, int b)
278 {
279     float r = fmod(a, b);
280     return r < 0 ? r + b : r;
281 }
282
283 float vibrato(float average_freq) {
284     #ifdef VIBRATO_STRENGTH_ENABLE
285         float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
286     #else
287         float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
288     #endif
289     vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
290     return vibrated_freq;
291 }
292
293 #endif
294
295 #ifdef C6_AUDIO
296 ISR(TIMER3_COMPA_vect)
297 {
298     float freq;
299
300     if (playing_note) {
301         if (voices > 0) {
302
303             #ifdef B5_AUDIO
304             float freq_alt = 0;
305                 if (voices > 1) {
306                     if (polyphony_rate == 0) {
307                         if (glissando) {
308                             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 if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) {
311                                 frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2);
312                             } else {
313                                 frequency_alt = frequencies[voices - 2];
314                             }
315                         } else {
316                             frequency_alt = frequencies[voices - 2];
317                         }
318
319                         #ifdef VIBRATO_ENABLE
320                             if (vibrato_strength > 0) {
321                                 freq_alt = vibrato(frequency_alt);
322                             } else {
323                                 freq_alt = frequency_alt;
324                             }
325                         #else
326                             freq_alt = frequency_alt;
327                         #endif
328                     }
329
330                     if (envelope_index < 65535) {
331                         envelope_index++;
332                     }
333
334                     freq_alt = voice_envelope(freq_alt);
335
336                     if (freq_alt < 30.517578125) {
337                         freq_alt = 30.52;
338                     }
339
340                     TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq_alt * CPU_PRESCALER));
341                     TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq_alt * CPU_PRESCALER)) * note_timbre);
342                 }
343             #endif
344
345             if (polyphony_rate > 0) {
346                 if (voices > 1) {
347                     voice_place %= voices;
348                     if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
349                         voice_place = (voice_place + 1) % voices;
350                         place = 0.0;
351                     }
352                 }
353
354                 #ifdef VIBRATO_ENABLE
355                     if (vibrato_strength > 0) {
356                         freq = vibrato(frequencies[voice_place]);
357                     } else {
358                         freq = frequencies[voice_place];
359                     }
360                 #else
361                     freq = frequencies[voice_place];
362                 #endif
363             } else {
364                 if (glissando) {
365                     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 if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
368                         frequency = frequency * pow(2, -440/frequency/12/2);
369                     } else {
370                         frequency = frequencies[voices - 1];
371                     }
372                 } else {
373                     frequency = frequencies[voices - 1];
374                 }
375
376                 #ifdef VIBRATO_ENABLE
377                     if (vibrato_strength > 0) {
378                         freq = vibrato(frequency);
379                     } else {
380                         freq = frequency;
381                     }
382                 #else
383                     freq = frequency;
384                 #endif
385             }
386
387             if (envelope_index < 65535) {
388                 envelope_index++;
389             }
390
391             freq = voice_envelope(freq);
392
393             if (freq < 30.517578125) {
394                 freq = 30.52;
395             }
396
397             TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
398             TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
399         }
400     }
401
402     if (playing_notes) {
403         if (note_frequency > 0) {
404             #ifdef VIBRATO_ENABLE
405                 if (vibrato_strength > 0) {
406                     freq = vibrato(note_frequency);
407                 } else {
408                     freq = note_frequency;
409                 }
410             #else
411                     freq = note_frequency;
412             #endif
413
414             if (envelope_index < 65535) {
415                 envelope_index++;
416             }
417             freq = voice_envelope(freq);
418
419             TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
420             TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
421         } else {
422             TIMER_3_PERIOD = 0;
423             TIMER_3_DUTY_CYCLE = 0;
424         }
425
426         note_position++;
427         bool end_of_note = false;
428         if (TIMER_3_PERIOD > 0) {
429             if (!note_resting) 
430                 end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF - 1));
431             else
432                 end_of_note = (note_position >= (note_length));
433         } else {
434             end_of_note = (note_position >= (note_length));
435         }
436
437         if (end_of_note) {
438             current_note++;
439             if (current_note >= notes_count) {
440                 if (notes_repeat) {
441                     current_note = 0;
442                 } else {
443                     DISABLE_AUDIO_COUNTER_3_ISR;
444                     DISABLE_AUDIO_COUNTER_3_OUTPUT;
445                     playing_notes = false;
446                     return;
447                 }
448             }
449             if (!note_resting) {
450                 note_resting = true;
451                 current_note--;
452                 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
453                     note_frequency = 0;
454                     note_length = 1;
455                 } else {
456                     note_frequency = (*notes_pointer)[current_note][0];
457                     note_length = 1;
458                 }
459             } else {
460                 note_resting = false;
461                 envelope_index = 0;
462                 note_frequency = (*notes_pointer)[current_note][0];
463                 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
464             }
465
466             note_position = 0;
467         }
468     }
469
470     if (!audio_config.enable) {
471         playing_notes = false;
472         playing_note = false;
473     }
474 }
475 #endif
476
477 #ifdef B5_AUDIO
478 ISR(TIMER1_COMPA_vect)
479 {
480     #if defined(B5_AUDIO) && !defined(C6_AUDIO)
481     float freq = 0;
482
483     if (playing_note) {
484         if (voices > 0) {
485             if (polyphony_rate > 0) {
486                 if (voices > 1) {
487                     voice_place %= voices;
488                     if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
489                         voice_place = (voice_place + 1) % voices;
490                         place = 0.0;
491                     }
492                 }
493
494                 #ifdef VIBRATO_ENABLE
495                     if (vibrato_strength > 0) {
496                         freq = vibrato(frequencies[voice_place]);
497                     } else {
498                         freq = frequencies[voice_place];
499                     }
500                 #else
501                     freq = frequencies[voice_place];
502                 #endif
503             } else {
504                 if (glissando) {
505                     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 if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
508                         frequency = frequency * pow(2, -440/frequency/12/2);
509                     } else {
510                         frequency = frequencies[voices - 1];
511                     }
512                 } else {
513                     frequency = frequencies[voices - 1];
514                 }
515
516                 #ifdef VIBRATO_ENABLE
517                     if (vibrato_strength > 0) {
518                         freq = vibrato(frequency);
519                     } else {
520                         freq = frequency;
521                     }
522                 #else
523                     freq = frequency;
524                 #endif
525             }
526
527             if (envelope_index < 65535) {
528                 envelope_index++;
529             }
530
531             freq = voice_envelope(freq);
532
533             if (freq < 30.517578125) {
534                 freq = 30.52;
535             }
536
537             TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
538             TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
539         }
540     }
541
542     if (playing_notes) {
543         if (note_frequency > 0) {
544             #ifdef VIBRATO_ENABLE
545                 if (vibrato_strength > 0) {
546                     freq = vibrato(note_frequency);
547                 } else {
548                     freq = note_frequency;
549                 }
550             #else
551                     freq = note_frequency;
552             #endif
553
554             if (envelope_index < 65535) {
555                 envelope_index++;
556             }
557             freq = voice_envelope(freq);
558
559             TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
560             TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
561         } else {
562             TIMER_1_PERIOD = 0;
563             TIMER_1_DUTY_CYCLE = 0;
564         }
565
566         note_position++;
567         bool end_of_note = false;
568         if (TIMER_1_PERIOD > 0) {
569             if (!note_resting) 
570                 end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF - 1));
571             else
572                 end_of_note = (note_position >= (note_length));
573         } else {
574             end_of_note = (note_position >= (note_length));
575         }
576
577         if (end_of_note) {
578             current_note++;
579             if (current_note >= notes_count) {
580                 if (notes_repeat) {
581                     current_note = 0;
582                 } else {
583                     DISABLE_AUDIO_COUNTER_1_ISR;
584                     DISABLE_AUDIO_COUNTER_1_OUTPUT;
585                     playing_notes = false;
586                     return;
587                 }
588             }
589             if (!note_resting) {
590                 note_resting = true;
591                 current_note--;
592                 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
593                     note_frequency = 0;
594                     note_length = 1;
595                 } else {
596                     note_frequency = (*notes_pointer)[current_note][0];
597                     note_length = 1;
598                 }
599             } else {
600                 note_resting = false;
601                 envelope_index = 0;
602                 note_frequency = (*notes_pointer)[current_note][0];
603                 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
604             }
605
606             note_position = 0;
607         }
608     }
609
610     if (!audio_config.enable) {
611         playing_notes = false;
612         playing_note = false;
613     }
614 #endif
615 }
616 #endif
617
618 void play_note(float freq, int vol) {
619
620     dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
621
622     if (!audio_initialized) {
623         audio_init();
624     }
625
626     if (audio_config.enable && voices < 8) {
627         #ifdef C6_AUDIO
628             DISABLE_AUDIO_COUNTER_3_ISR;
629         #endif
630         #ifdef B5_AUDIO
631             DISABLE_AUDIO_COUNTER_1_ISR;
632         #endif
633
634         // Cancel notes if notes are playing
635         if (playing_notes)
636             stop_all_notes();
637
638         playing_note = true;
639
640         envelope_index = 0;
641
642         if (freq > 0) {
643             frequencies[voices] = freq;
644             volumes[voices] = vol;
645             voices++;
646         }
647
648         #ifdef C6_AUDIO
649             ENABLE_AUDIO_COUNTER_3_ISR;
650             ENABLE_AUDIO_COUNTER_3_OUTPUT;
651         #endif
652         #ifdef B5_AUDIO
653             #ifdef C6_AUDIO
654             if (voices > 1) {
655                 ENABLE_AUDIO_COUNTER_1_ISR;
656                 ENABLE_AUDIO_COUNTER_1_OUTPUT;
657             }
658             #else
659             ENABLE_AUDIO_COUNTER_1_ISR;
660             ENABLE_AUDIO_COUNTER_1_OUTPUT;
661             #endif
662         #endif
663     }
664
665 }
666
667 void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
668 {
669
670     if (!audio_initialized) {
671         audio_init();
672     }
673
674     if (audio_config.enable) {
675
676         #ifdef C6_AUDIO
677             DISABLE_AUDIO_COUNTER_3_ISR;
678         #endif
679         #ifdef B5_AUDIO
680             DISABLE_AUDIO_COUNTER_1_ISR;
681         #endif
682
683         // Cancel note if a note is playing
684         if (playing_note)
685             stop_all_notes();
686
687         playing_notes = true;
688
689         notes_pointer = np;
690         notes_count = n_count;
691         notes_repeat = n_repeat;
692
693         place = 0;
694         current_note = 0;
695
696         note_frequency = (*notes_pointer)[current_note][0];
697         note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
698         note_position = 0;
699
700
701         #ifdef C6_AUDIO
702             ENABLE_AUDIO_COUNTER_3_ISR;
703             ENABLE_AUDIO_COUNTER_3_OUTPUT;
704         #endif
705         #ifdef B5_AUDIO
706             #ifndef C6_AUDIO
707             ENABLE_AUDIO_COUNTER_1_ISR;
708             ENABLE_AUDIO_COUNTER_1_OUTPUT;
709             #endif
710         #endif
711     }
712
713 }
714
715 bool is_playing_notes(void) {
716     return playing_notes;
717 }
718
719 bool is_audio_on(void) {
720     return (audio_config.enable != 0);
721 }
722
723 void audio_toggle(void) {
724     audio_config.enable ^= 1;
725     eeconfig_update_audio(audio_config.raw);
726     if (audio_config.enable)
727         audio_on_user();
728 }
729
730 void audio_on(void) {
731     audio_config.enable = 1;
732     eeconfig_update_audio(audio_config.raw);
733     audio_on_user();
734     PLAY_SONG(audio_on_song);
735 }
736
737 void audio_off(void) {
738     PLAY_SONG(audio_off_song);
739     wait_ms(100);
740     stop_all_notes();
741     audio_config.enable = 0;
742     eeconfig_update_audio(audio_config.raw);
743 }
744
745 #ifdef VIBRATO_ENABLE
746
747 // Vibrato rate functions
748
749 void set_vibrato_rate(float rate) {
750     vibrato_rate = rate;
751 }
752
753 void increase_vibrato_rate(float change) {
754     vibrato_rate *= change;
755 }
756
757 void decrease_vibrato_rate(float change) {
758     vibrato_rate /= change;
759 }
760
761 #ifdef VIBRATO_STRENGTH_ENABLE
762
763 void set_vibrato_strength(float strength) {
764     vibrato_strength = strength;
765 }
766
767 void increase_vibrato_strength(float change) {
768     vibrato_strength *= change;
769 }
770
771 void decrease_vibrato_strength(float change) {
772     vibrato_strength /= change;
773 }
774
775 #endif  /* VIBRATO_STRENGTH_ENABLE */
776
777 #endif /* VIBRATO_ENABLE */
778
779 // Polyphony functions
780
781 void set_polyphony_rate(float rate) {
782     polyphony_rate = rate;
783 }
784
785 void enable_polyphony() {
786     polyphony_rate = 5;
787 }
788
789 void disable_polyphony() {
790     polyphony_rate = 0;
791 }
792
793 void increase_polyphony_rate(float change) {
794     polyphony_rate *= change;
795 }
796
797 void decrease_polyphony_rate(float change) {
798     polyphony_rate /= change;
799 }
800
801 // Timbre function
802
803 void set_timbre(float timbre) {
804     note_timbre = timbre;
805 }
806
807 // Tempo functions
808
809 void set_tempo(uint8_t tempo) {
810     note_tempo = tempo;
811 }
812
813 void decrease_tempo(uint8_t tempo_change) {
814     note_tempo += tempo_change;
815 }
816
817 void increase_tempo(uint8_t tempo_change) {
818     if (note_tempo - tempo_change < 10) {
819         note_tempo = 10;
820     } else {
821         note_tempo -= tempo_change;
822     }
823 }