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