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