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