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