]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/audio/audio.c
Merge remote-tracking branch 'refs/remotes/qmk/master'
[qmk_firmware.git] / quantum / audio / audio.c
1 #include <stdio.h>
2 #include <string.h>
3 //#include <math.h>
4 #include <avr/pgmspace.h>
5 #include <avr/interrupt.h>
6 #include <avr/io.h>
7 #include "print.h"
8 #include "audio.h"
9 #include "keymap.h"
10
11 #include "eeconfig.h"
12
13 #define CPU_PRESCALER 8
14
15 // -----------------------------------------------------------------------------
16 // Timer Abstractions
17 // -----------------------------------------------------------------------------
18
19 // TIMSK3 - Timer/Counter #3 Interrupt Mask Register
20 // Turn on/off 3A interputs, stopping/enabling the ISR calls
21 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
22 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
23
24 // TCCR3A: Timer/Counter #3 Control Register
25 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
26 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
27 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
28
29 // Fast PWM Mode Controls
30 #define TIMER_3_PERIOD     ICR3
31 #define TIMER_3_DUTY_CYCLE OCR3A
32
33 // -----------------------------------------------------------------------------
34
35
36 int voices = 0;
37 int voice_place = 0;
38 float frequency = 0;
39 int volume = 0;
40 long position = 0;
41
42 float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
43 int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
44 bool sliding = false;
45
46 float place = 0;
47
48 uint8_t * sample;
49 uint16_t sample_length = 0;
50
51 bool     playing_notes = false;
52 bool     playing_note = false;
53 float    note_frequency = 0;
54 float    note_length = 0;
55 uint8_t  note_tempo = TEMPO_DEFAULT;
56 float    note_timbre = TIMBRE_DEFAULT;
57 uint16_t note_position = 0;
58 float (* notes_pointer)[][2];
59 uint16_t notes_count;
60 bool     notes_repeat;
61 float    notes_rest;
62 bool     note_resting = false;
63
64 uint8_t current_note = 0;
65 uint8_t rest_counter = 0;
66
67 #ifdef VIBRATO_ENABLE
68 float vibrato_counter = 0;
69 float vibrato_strength = .5;
70 float vibrato_rate = 0.125;
71 #endif
72
73 float polyphony_rate = 0;
74
75 static bool audio_initialized = false;
76
77 audio_config_t audio_config;
78
79 uint16_t envelope_index = 0;
80 bool glissando = true;
81
82 void audio_init()
83 {
84
85     // Check EEPROM
86     if (!eeconfig_is_enabled())
87     {
88         eeconfig_init();
89     }
90     audio_config.raw = eeconfig_read_audio();
91
92     // Set port PC6 (OC3A and /OC4A) as output
93     DDRC |= _BV(PORTC6);
94
95     DISABLE_AUDIO_COUNTER_3_ISR;
96
97     // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
98     // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
99     // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
100     // Clock Select (CS3n) = 0b010 = Clock / 8
101     TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
102     TCCR3B = (1 << WGM33)  | (1 << WGM32)  | (0 << CS32)  | (1 << CS31) | (0 << CS30);
103
104     audio_initialized = true;
105 }
106
107 void stop_all_notes()
108 {
109     dprintf("audio stop all notes");
110
111     if (!audio_initialized) {
112         audio_init();
113     }
114     voices = 0;
115
116     DISABLE_AUDIO_COUNTER_3_ISR;
117     DISABLE_AUDIO_COUNTER_3_OUTPUT;
118
119     playing_notes = false;
120     playing_note = false;
121     frequency = 0;
122     volume = 0;
123
124     for (uint8_t i = 0; i < 8; i++)
125     {
126         frequencies[i] = 0;
127         volumes[i] = 0;
128     }
129 }
130
131 void stop_note(float freq)
132 {
133     dprintf("audio stop note freq=%d", (int)freq);
134
135     if (playing_note) {
136         if (!audio_initialized) {
137             audio_init();
138         }
139         for (int i = 7; i >= 0; i--) {
140             if (frequencies[i] == freq) {
141                 frequencies[i] = 0;
142                 volumes[i] = 0;
143                 for (int j = i; (j < 7); j++) {
144                     frequencies[j] = frequencies[j+1];
145                     frequencies[j+1] = 0;
146                     volumes[j] = volumes[j+1];
147                     volumes[j+1] = 0;
148                 }
149                 break;
150             }
151         }
152         voices--;
153         if (voices < 0)
154             voices = 0;
155         if (voice_place >= voices) {
156             voice_place = 0;
157         }
158         if (voices == 0) {
159             DISABLE_AUDIO_COUNTER_3_ISR;
160             DISABLE_AUDIO_COUNTER_3_OUTPUT;
161             frequency = 0;
162             volume = 0;
163             playing_note = false;
164         }
165     }
166 }
167
168 #ifdef VIBRATO_ENABLE
169
170 float mod(float a, int b)
171 {
172     float r = fmod(a, b);
173     return r < 0 ? r + b : r;
174 }
175
176 float vibrato(float average_freq) {
177     #ifdef VIBRATO_STRENGTH_ENABLE
178         float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
179     #else
180         float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
181     #endif
182     vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
183     return vibrated_freq;
184 }
185
186 #endif
187
188 ISR(TIMER3_COMPA_vect)
189 {
190     float freq;
191
192     if (playing_note) {
193         if (voices > 0) {
194             if (polyphony_rate > 0) {
195                 if (voices > 1) {
196                     voice_place %= voices;
197                     if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
198                         voice_place = (voice_place + 1) % voices;
199                         place = 0.0;
200                     }
201                 }
202
203                 #ifdef VIBRATO_ENABLE
204                     if (vibrato_strength > 0) {
205                         freq = vibrato(frequencies[voice_place]);
206                     } else {
207                         freq = frequencies[voice_place];
208                     }
209                 #else
210                     freq = frequencies[voice_place];
211                 #endif
212             } else {
213                 if (glissando) {
214                     if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
215                         frequency = frequency * pow(2, 440/frequency/12/2);
216                     } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
217                         frequency = frequency * pow(2, -440/frequency/12/2);
218                     } else {
219                         frequency = frequencies[voices - 1];
220                     }
221                 } else {
222                     frequency = frequencies[voices - 1];
223                 }
224
225                 #ifdef VIBRATO_ENABLE
226                     if (vibrato_strength > 0) {
227                         freq = vibrato(frequency);
228                     } else {
229                         freq = frequency;
230                     }
231                 #else
232                     freq = frequency;
233                 #endif
234             }
235
236             if (envelope_index < 65535) {
237                 envelope_index++;
238             }
239
240             freq = voice_envelope(freq);
241
242             if (freq < 30.517578125) {
243                 freq = 30.52;
244             }
245
246             TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
247             TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
248         }
249     }
250
251     if (playing_notes) {
252         if (note_frequency > 0) {
253             #ifdef VIBRATO_ENABLE
254                 if (vibrato_strength > 0) {
255                     freq = vibrato(note_frequency);
256                 } else {
257                     freq = note_frequency;
258                 }
259             #else
260                     freq = note_frequency;
261             #endif
262
263             if (envelope_index < 65535) {
264                 envelope_index++;
265             }
266             freq = voice_envelope(freq);
267
268             TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
269             TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
270         } else {
271             TIMER_3_PERIOD = 0;
272             TIMER_3_DUTY_CYCLE = 0;
273         }
274
275         note_position++;
276         bool end_of_note = false;
277         if (TIMER_3_PERIOD > 0) {
278             end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF));
279         } else {
280             end_of_note = (note_position >= (note_length * 0x7FF));
281         }
282
283         if (end_of_note) {
284             current_note++;
285             if (current_note >= notes_count) {
286                 if (notes_repeat) {
287                     current_note = 0;
288                 } else {
289                     DISABLE_AUDIO_COUNTER_3_ISR;
290                     DISABLE_AUDIO_COUNTER_3_OUTPUT;
291                     playing_notes = false;
292                     return;
293                 }
294             }
295             if (!note_resting && (notes_rest > 0)) {
296                 note_resting = true;
297                 note_frequency = 0;
298                 note_length = notes_rest;
299                 current_note--;
300             } else {
301                 note_resting = false;
302                 envelope_index = 0;
303                 note_frequency = (*notes_pointer)[current_note][0];
304                 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
305             }
306
307             note_position = 0;
308         }
309     }
310
311     if (!audio_config.enable) {
312         playing_notes = false;
313         playing_note = false;
314     }
315 }
316
317 void play_note(float freq, int vol) {
318
319     dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
320
321     if (!audio_initialized) {
322         audio_init();
323     }
324
325     if (audio_config.enable && voices < 8) {
326         DISABLE_AUDIO_COUNTER_3_ISR;
327
328         // Cancel notes if notes are playing
329         if (playing_notes)
330             stop_all_notes();
331
332         playing_note = true;
333
334         envelope_index = 0;
335
336         if (freq > 0) {
337             frequencies[voices] = freq;
338             volumes[voices] = vol;
339             voices++;
340         }
341
342         ENABLE_AUDIO_COUNTER_3_ISR;
343         ENABLE_AUDIO_COUNTER_3_OUTPUT;
344     }
345
346 }
347
348 void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
349 {
350
351     if (!audio_initialized) {
352         audio_init();
353     }
354
355     if (audio_config.enable) {
356
357         DISABLE_AUDIO_COUNTER_3_ISR;
358
359         // Cancel note if a note is playing
360         if (playing_note)
361             stop_all_notes();
362
363         playing_notes = true;
364
365         notes_pointer = np;
366         notes_count = n_count;
367         notes_repeat = n_repeat;
368         notes_rest = n_rest;
369
370         place = 0;
371         current_note = 0;
372
373         note_frequency = (*notes_pointer)[current_note][0];
374         note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
375         note_position = 0;
376
377
378         ENABLE_AUDIO_COUNTER_3_ISR;
379         ENABLE_AUDIO_COUNTER_3_OUTPUT;
380     }
381
382 }
383
384 bool is_playing_notes(void) {
385     return playing_notes;
386 }
387
388 bool is_audio_on(void) {
389     return (audio_config.enable != 0);
390 }
391
392 void audio_toggle(void) {
393     audio_config.enable ^= 1;
394     eeconfig_update_audio(audio_config.raw);
395     if (audio_config.enable)
396         audio_on_user();
397 }
398
399 void audio_on(void) {
400     audio_config.enable = 1;
401     eeconfig_update_audio(audio_config.raw);
402     audio_on_user();
403 }
404
405 void audio_off(void) {
406     audio_config.enable = 0;
407     eeconfig_update_audio(audio_config.raw);
408 }
409
410 #ifdef VIBRATO_ENABLE
411
412 // Vibrato rate functions
413
414 void set_vibrato_rate(float rate) {
415     vibrato_rate = rate;
416 }
417
418 void increase_vibrato_rate(float change) {
419     vibrato_rate *= change;
420 }
421
422 void decrease_vibrato_rate(float change) {
423     vibrato_rate /= change;
424 }
425
426 #ifdef VIBRATO_STRENGTH_ENABLE
427
428 void set_vibrato_strength(float strength) {
429     vibrato_strength = strength;
430 }
431
432 void increase_vibrato_strength(float change) {
433     vibrato_strength *= change;
434 }
435
436 void decrease_vibrato_strength(float change) {
437     vibrato_strength /= change;
438 }
439
440 #endif  /* VIBRATO_STRENGTH_ENABLE */
441
442 #endif /* VIBRATO_ENABLE */
443
444 // Polyphony functions
445
446 void set_polyphony_rate(float rate) {
447     polyphony_rate = rate;
448 }
449
450 void enable_polyphony() {
451     polyphony_rate = 5;
452 }
453
454 void disable_polyphony() {
455     polyphony_rate = 0;
456 }
457
458 void increase_polyphony_rate(float change) {
459     polyphony_rate *= change;
460 }
461
462 void decrease_polyphony_rate(float change) {
463     polyphony_rate /= change;
464 }
465
466 // Timbre function
467
468 void set_timbre(float timbre) {
469     note_timbre = timbre;
470 }
471
472 // Tempo functions
473
474 void set_tempo(uint8_t tempo) {
475     note_tempo = tempo;
476 }
477
478 void decrease_tempo(uint8_t tempo_change) {
479     note_tempo += tempo_change;
480 }
481
482 void increase_tempo(uint8_t tempo_change) {
483     if (note_tempo - tempo_change < 10) {
484         note_tempo = 10;
485     } else {
486         note_tempo -= tempo_change;
487     }
488 }