]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/audio/audio.c
Merge remote-tracking branch 'remotes/jackhumbert/master' into bépo
[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
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 bool is_audio_on(void) {
378     return (audio_config.enable != 0);
379 }
380
381 void audio_toggle(void) {
382     audio_config.enable ^= 1;
383     eeconfig_update_audio(audio_config.raw);
384     if (audio_config.enable)
385         audio_on_user();
386 }
387
388 void audio_on(void) {
389     audio_config.enable = 1;
390     eeconfig_update_audio(audio_config.raw);
391     audio_on_user();
392 }
393
394 void audio_off(void) {
395     audio_config.enable = 0;
396     eeconfig_update_audio(audio_config.raw);
397 }
398
399 #ifdef VIBRATO_ENABLE
400
401 // Vibrato rate functions
402
403 void set_vibrato_rate(float rate) {
404     vibrato_rate = rate;
405 }
406
407 void increase_vibrato_rate(float change) {
408     vibrato_rate *= change;
409 }
410
411 void decrease_vibrato_rate(float change) {
412     vibrato_rate /= change;
413 }
414
415 #ifdef VIBRATO_STRENGTH_ENABLE
416
417 void set_vibrato_strength(float strength) {
418     vibrato_strength = strength;
419 }
420
421 void increase_vibrato_strength(float change) {
422     vibrato_strength *= change;
423 }
424
425 void decrease_vibrato_strength(float change) {
426     vibrato_strength /= change;
427 }
428
429 #endif  /* VIBRATO_STRENGTH_ENABLE */
430
431 #endif /* VIBRATO_ENABLE */
432
433 // Polyphony functions
434
435 void set_polyphony_rate(float rate) {
436     polyphony_rate = rate;
437 }
438
439 void enable_polyphony() {
440     polyphony_rate = 5;
441 }
442
443 void disable_polyphony() {
444     polyphony_rate = 0;
445 }
446
447 void increase_polyphony_rate(float change) {
448     polyphony_rate *= change;
449 }
450
451 void decrease_polyphony_rate(float change) {
452     polyphony_rate /= change;
453 }
454
455 // Timbre function
456
457 void set_timbre(float timbre) {
458     note_timbre = timbre;
459 }
460
461 // Tempo functions
462
463 void set_tempo(uint8_t tempo) {
464     note_tempo = tempo;
465 }
466
467 void decrease_tempo(uint8_t tempo_change) {
468     note_tempo += tempo_change;
469 }
470
471 void increase_tempo(uint8_t tempo_change) {
472     if (note_tempo - tempo_change < 10) {
473         note_tempo = 10;
474     } else {
475         note_tempo -= tempo_change;
476     }
477 }