]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/audio/audio.c
Merge branch 'master' of github.com:jackhumbert/qmk_firmware
[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     if (!audio_initialized) {
110         audio_init();
111     }
112     voices = 0;
113
114     DISABLE_AUDIO_COUNTER_3_ISR;
115     DISABLE_AUDIO_COUNTER_3_OUTPUT;
116
117     playing_notes = false;
118     playing_note = false;
119     frequency = 0;
120     volume = 0;
121
122     for (uint8_t i = 0; i < 8; i++)
123     {
124         frequencies[i] = 0;
125         volumes[i] = 0;
126     }
127 }
128
129 void stop_note(float freq)
130 {
131     if (playing_note) {
132         if (!audio_initialized) {
133             audio_init();
134         }
135         for (int i = 7; i >= 0; i--) {
136             if (frequencies[i] == freq) {
137                 frequencies[i] = 0;
138                 volumes[i] = 0;
139                 for (int j = i; (j < 7); j++) {
140                     frequencies[j] = frequencies[j+1];
141                     frequencies[j+1] = 0;
142                     volumes[j] = volumes[j+1];
143                     volumes[j+1] = 0;
144                 }
145                 break;
146             }
147         }
148         voices--;
149         if (voices < 0)
150             voices = 0;
151         if (voice_place >= voices) {
152             voice_place = 0;
153         }
154         if (voices == 0) {
155             DISABLE_AUDIO_COUNTER_3_ISR;
156             DISABLE_AUDIO_COUNTER_3_OUTPUT;
157             frequency = 0;
158             volume = 0;
159             playing_note = false;
160         }
161     }
162 }
163
164 #ifdef VIBRATO_ENABLE
165
166 float mod(float a, int b)
167 {
168     float r = fmod(a, b);
169     return r < 0 ? r + b : r;
170 }
171
172 float vibrato(float average_freq) {
173     #ifdef VIBRATO_STRENGTH_ENABLE
174         float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
175     #else
176         float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
177     #endif
178     vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
179     return vibrated_freq;
180 }
181
182 #endif
183
184 ISR(TIMER3_COMPA_vect)
185 {
186         float freq;
187
188         if (playing_note) {
189                 if (voices > 0) {
190                         if (polyphony_rate > 0) {
191                                 if (voices > 1) {
192                                         voice_place %= voices;
193                                         if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
194                                                 voice_place = (voice_place + 1) % voices;
195                                                 place = 0.0;
196                                         }
197                                 }
198
199                                 #ifdef VIBRATO_ENABLE
200                                         if (vibrato_strength > 0) {
201                                                 freq = vibrato(frequencies[voice_place]);
202                                         } else {
203                                                 freq = frequencies[voice_place];
204                                         }
205                                 #else
206                                         freq = frequencies[voice_place];
207                                 #endif
208                         } else {
209                                 if (glissando) {
210                                         if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
211                                                 frequency = frequency * pow(2, 440/frequency/12/2);
212                                         } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
213                                                 frequency = frequency * pow(2, -440/frequency/12/2);
214                                         } else {
215                                                 frequency = frequencies[voices - 1];
216                                         }
217                                 } else {
218                                         frequency = frequencies[voices - 1];
219                                 }                               
220
221                                 #ifdef VIBRATO_ENABLE
222                                         if (vibrato_strength > 0) {
223                                                 freq = vibrato(frequency);
224                                         } else {
225                                                 freq = frequency;
226                                         }
227                                 #else
228                                         freq = frequency;
229                                 #endif
230                         }
231
232                         if (envelope_index < 65535) {
233                                 envelope_index++;
234                         }
235
236                         freq = voice_envelope(freq);
237
238                         if (freq < 30.517578125) {
239                                 freq = 30.52;
240                         }
241
242                         TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
243                         TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
244                 }
245         }
246
247         if (playing_notes) {
248                 if (note_frequency > 0) {
249                         #ifdef VIBRATO_ENABLE
250                                 if (vibrato_strength > 0) {
251                                         freq = vibrato(note_frequency);
252                                 } else {
253                                         freq = note_frequency;
254                                 }
255                         #else
256                                         freq = note_frequency;
257                         #endif
258
259                         if (envelope_index < 65535) {
260                                 envelope_index++;
261                         }
262                         freq = voice_envelope(freq);
263
264                         TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
265                         TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
266                 } else {
267                         TIMER_3_PERIOD = 0;
268                         TIMER_3_DUTY_CYCLE = 0;
269                 }
270
271                 note_position++;
272                 bool end_of_note = false;
273                 if (TIMER_3_PERIOD > 0) {
274                         end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF));
275                 } else {
276                         end_of_note = (note_position >= (note_length * 0x7FF));
277                 }
278
279                 if (end_of_note) {
280                         current_note++;
281                         if (current_note >= notes_count) {
282                                 if (notes_repeat) {
283                                         current_note = 0;
284                                 } else {
285                                         DISABLE_AUDIO_COUNTER_3_ISR;
286                                         DISABLE_AUDIO_COUNTER_3_OUTPUT;
287                                         playing_notes = false;
288                                         return;
289                                 }
290                         }
291                         if (!note_resting && (notes_rest > 0)) {
292                                 note_resting = true;
293                                 note_frequency = 0;
294                                 note_length = notes_rest;
295                                 current_note--;
296                         } else {
297                                 note_resting = false;
298                                 envelope_index = 0;
299                                 note_frequency = (*notes_pointer)[current_note][0];
300                                 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
301                         }
302
303                         note_position = 0;
304                 }
305         }
306
307         if (!audio_config.enable) {
308                 playing_notes = false;
309                 playing_note = false;
310         }
311 }
312
313 void play_note(float freq, int vol) {
314
315     if (!audio_initialized) {
316         audio_init();
317     }
318
319         if (audio_config.enable && voices < 8) {
320             DISABLE_AUDIO_COUNTER_3_ISR;
321
322             // Cancel notes if notes are playing
323             if (playing_notes)
324                 stop_all_notes();
325
326             playing_note = true;
327
328             envelope_index = 0;
329
330             if (freq > 0) {
331                 frequencies[voices] = freq;
332                 volumes[voices] = vol;
333                 voices++;
334             }
335
336         ENABLE_AUDIO_COUNTER_3_ISR;
337         ENABLE_AUDIO_COUNTER_3_OUTPUT;
338         }
339
340 }
341
342 void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
343 {
344
345     if (!audio_initialized) {
346         audio_init();
347     }
348
349         if (audio_config.enable) {
350
351             DISABLE_AUDIO_COUNTER_3_ISR;
352
353                 // Cancel note if a note is playing
354             if (playing_note)
355                 stop_all_notes();
356
357             playing_notes = true;
358
359             notes_pointer = np;
360             notes_count = n_count;
361             notes_repeat = n_repeat;
362             notes_rest = n_rest;
363
364             place = 0;
365             current_note = 0;
366
367         note_frequency = (*notes_pointer)[current_note][0];
368         note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
369             note_position = 0;
370
371
372         ENABLE_AUDIO_COUNTER_3_ISR;
373         ENABLE_AUDIO_COUNTER_3_OUTPUT;
374         }
375
376 }
377
378 bool is_playing_notes(void) {
379         return playing_notes;
380 }
381
382 bool is_audio_on(void) {
383     return (audio_config.enable != 0);
384 }
385
386 void audio_toggle(void) {
387     audio_config.enable ^= 1;
388     eeconfig_update_audio(audio_config.raw);
389     if (audio_config.enable)
390         audio_on_user();
391 }
392
393 void audio_on(void) {
394     audio_config.enable = 1;
395     eeconfig_update_audio(audio_config.raw);
396     audio_on_user();
397 }
398
399 void audio_off(void) {
400     audio_config.enable = 0;
401     eeconfig_update_audio(audio_config.raw);
402 }
403
404 #ifdef VIBRATO_ENABLE
405
406 // Vibrato rate functions
407
408 void set_vibrato_rate(float rate) {
409     vibrato_rate = rate;
410 }
411
412 void increase_vibrato_rate(float change) {
413     vibrato_rate *= change;
414 }
415
416 void decrease_vibrato_rate(float change) {
417     vibrato_rate /= change;
418 }
419
420 #ifdef VIBRATO_STRENGTH_ENABLE
421
422 void set_vibrato_strength(float strength) {
423     vibrato_strength = strength;
424 }
425
426 void increase_vibrato_strength(float change) {
427     vibrato_strength *= change;
428 }
429
430 void decrease_vibrato_strength(float change) {
431     vibrato_strength /= change;
432 }
433
434 #endif  /* VIBRATO_STRENGTH_ENABLE */
435
436 #endif /* VIBRATO_ENABLE */
437
438 // Polyphony functions
439
440 void set_polyphony_rate(float rate) {
441     polyphony_rate = rate;
442 }
443
444 void enable_polyphony() {
445     polyphony_rate = 5;
446 }
447
448 void disable_polyphony() {
449     polyphony_rate = 0;
450 }
451
452 void increase_polyphony_rate(float change) {
453     polyphony_rate *= change;
454 }
455
456 void decrease_polyphony_rate(float change) {
457     polyphony_rate /= change;
458 }
459
460 // Timbre function
461
462 void set_timbre(float timbre) {
463     note_timbre = timbre;
464 }
465
466 // Tempo functions
467
468 void set_tempo(uint8_t tempo) {
469     note_tempo = tempo;
470 }
471
472 void decrease_tempo(uint8_t tempo_change) {
473     note_tempo += tempo_change;
474 }
475
476 void increase_tempo(uint8_t tempo_change) {
477     if (note_tempo - tempo_change < 10) {
478         note_tempo = 10;
479     } else {
480         note_tempo -= tempo_change;
481     }
482 }