aboutsummaryrefslogtreecommitdiff
path: root/quantum/audio/audio_avr.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/audio/audio_avr.c')
-rw-r--r--quantum/audio/audio_avr.c805
1 files changed, 805 insertions, 0 deletions
diff --git a/quantum/audio/audio_avr.c b/quantum/audio/audio_avr.c
new file mode 100644
index 000000000..781378788
--- /dev/null
+++ b/quantum/audio/audio_avr.c
@@ -0,0 +1,805 @@
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
17#include <stdio.h>
18#include <string.h>
19//#include <math.h>
20#if defined(__AVR__)
21# include <avr/pgmspace.h>
22# include <avr/interrupt.h>
23# include <avr/io.h>
24#endif
25#include "print.h"
26#include "audio.h"
27#include "keymap.h"
28#include "wait.h"
29
30#include "eeconfig.h"
31
32#define CPU_PRESCALER 8
33
34// -----------------------------------------------------------------------------
35// Timer Abstractions
36// -----------------------------------------------------------------------------
37
38// Currently we support timers 1 and 3 used at the sime time, channels A-C,
39// pins PB5, PB6, PB7, PC4, PC5, and PC6
40#if defined(C6_AUDIO)
41# define CPIN_AUDIO
42# define CPIN_SET_DIRECTION DDRC |= _BV(PORTC6);
43# define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
44# define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
45# define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
46# define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
47# define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
48# define TIMER_3_PERIOD ICR3
49# define TIMER_3_DUTY_CYCLE OCR3A
50# define TIMER3_AUDIO_vect TIMER3_COMPA_vect
51#endif
52#if defined(C5_AUDIO)
53# define CPIN_AUDIO
54# define CPIN_SET_DIRECTION DDRC |= _BV(PORTC5);
55# define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3B1) | (0 << COM3B0) | (1 << WGM31) | (0 << WGM30);
56# define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3B)
57# define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3B)
58# define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3B1);
59# define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3B1) | _BV(COM3B0));
60# define TIMER_3_PERIOD ICR3
61# define TIMER_3_DUTY_CYCLE OCR3B
62# define TIMER3_AUDIO_vect TIMER3_COMPB_vect
63#endif
64#if defined(C4_AUDIO)
65# define CPIN_AUDIO
66# define CPIN_SET_DIRECTION DDRC |= _BV(PORTC4);
67# define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3C1) | (0 << COM3C0) | (1 << WGM31) | (0 << WGM30);
68# define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3C)
69# define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3C)
70# define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3C1);
71# define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3C1) | _BV(COM3C0));
72# define TIMER_3_PERIOD ICR3
73# define TIMER_3_DUTY_CYCLE OCR3C
74# define TIMER3_AUDIO_vect TIMER3_COMPC_vect
75#endif
76
77#if defined(B5_AUDIO)
78# define BPIN_AUDIO
79# define BPIN_SET_DIRECTION DDRB |= _BV(PORTB5);
80# define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
81# define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
82# define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
83# define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
84# define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
85# define TIMER_1_PERIOD ICR1
86# define TIMER_1_DUTY_CYCLE OCR1A
87# define TIMER1_AUDIO_vect TIMER1_COMPA_vect
88#endif
89#if defined(B6_AUDIO)
90# define BPIN_AUDIO
91# define BPIN_SET_DIRECTION DDRB |= _BV(PORTB6);
92# define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1B1) | (0 << COM1B0) | (1 << WGM11) | (0 << WGM10);
93# define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1B)
94# define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1B)
95# define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1B1);
96# define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1B1) | _BV(COM1B0));
97# define TIMER_1_PERIOD ICR1
98# define TIMER_1_DUTY_CYCLE OCR1B
99# define TIMER1_AUDIO_vect TIMER1_COMPB_vect
100#endif
101#if defined(B7_AUDIO)
102# define BPIN_AUDIO
103# define BPIN_SET_DIRECTION DDRB |= _BV(PORTB7);
104# define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1C1) | (0 << COM1C0) | (1 << WGM11) | (0 << WGM10);
105# define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1C)
106# define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1C)
107# define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1C1);
108# define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1C1) | _BV(COM1C0));
109# define TIMER_1_PERIOD ICR1
110# define TIMER_1_DUTY_CYCLE OCR1C
111# define TIMER1_AUDIO_vect TIMER1_COMPC_vect
112#endif
113// -----------------------------------------------------------------------------
114
115int voices = 0;
116int voice_place = 0;
117float frequency = 0;
118float frequency_alt = 0;
119int volume = 0;
120long position = 0;
121
122float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
123int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
124bool sliding = false;
125
126float place = 0;
127
128uint8_t* sample;
129uint16_t sample_length = 0;
130
131bool playing_notes = false;
132bool playing_note = false;
133float note_frequency = 0;
134float note_length = 0;
135uint8_t note_tempo = TEMPO_DEFAULT;
136float note_timbre = TIMBRE_DEFAULT;
137uint16_t note_position = 0;
138float (*notes_pointer)[][2];
139uint16_t notes_count;
140bool notes_repeat;
141bool note_resting = false;
142
143uint16_t current_note = 0;
144uint8_t rest_counter = 0;
145
146#ifdef VIBRATO_ENABLE
147float vibrato_counter = 0;
148float vibrato_strength = .5;
149float vibrato_rate = 0.125;
150#endif
151
152float polyphony_rate = 0;
153
154static bool audio_initialized = false;
155
156audio_config_t audio_config;
157
158uint16_t envelope_index = 0;
159bool glissando = true;
160
161#ifndef STARTUP_SONG
162# define STARTUP_SONG SONG(STARTUP_SOUND)
163#endif
164#ifndef AUDIO_ON_SONG
165# define AUDIO_ON_SONG SONG(AUDIO_ON_SOUND)
166#endif
167#ifndef AUDIO_OFF_SONG
168# define AUDIO_OFF_SONG SONG(AUDIO_OFF_SOUND)
169#endif
170float startup_song[][2] = STARTUP_SONG;
171float audio_on_song[][2] = AUDIO_ON_SONG;
172float audio_off_song[][2] = AUDIO_OFF_SONG;
173
174void audio_init() {
175 // Check EEPROM
176 if (!eeconfig_is_enabled()) {
177 eeconfig_init();
178 }
179 audio_config.raw = eeconfig_read_audio();
180
181 if (!audio_initialized) {
182// Set audio ports as output
183#ifdef CPIN_AUDIO
184 CPIN_SET_DIRECTION
185 DISABLE_AUDIO_COUNTER_3_ISR;
186#endif
187#ifdef BPIN_AUDIO
188 BPIN_SET_DIRECTION
189 DISABLE_AUDIO_COUNTER_1_ISR;
190#endif
191
192// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers TCCR3A/TCCR3B, TCCR1A/TCCR1B
193// Compare Output Mode (COM3An and COM1An) = 0b00 = Normal port operation
194// OC3A -- PC6
195// OC3B -- PC5
196// OC3C -- PC4
197// OC1A -- PB5
198// OC1B -- PB6
199// OC1C -- PB7
200
201// Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14. Period = ICR3, Duty Cycle OCR3A)
202// OCR3A - PC6
203// OCR3B - PC5
204// OCR3C - PC4
205// OCR1A - PB5
206// OCR1B - PB6
207// OCR1C - PB7
208
209// Clock Select (CS3n) = 0b010 = Clock / 8
210#ifdef CPIN_AUDIO
211 INIT_AUDIO_COUNTER_3
212 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
213 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER));
214 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre);
215#endif
216#ifdef BPIN_AUDIO
217 INIT_AUDIO_COUNTER_1
218 TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
219 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER));
220 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre);
221#endif
222
223 audio_initialized = true;
224 }
225
226 if (audio_config.enable) {
227 PLAY_SONG(startup_song);
228 }
229}
230
231void stop_all_notes() {
232 dprintf("audio stop all notes");
233
234 if (!audio_initialized) {
235 audio_init();
236 }
237 voices = 0;
238
239#ifdef CPIN_AUDIO
240 DISABLE_AUDIO_COUNTER_3_ISR;
241 DISABLE_AUDIO_COUNTER_3_OUTPUT;
242#endif
243
244#ifdef BPIN_AUDIO
245 DISABLE_AUDIO_COUNTER_1_ISR;
246 DISABLE_AUDIO_COUNTER_1_OUTPUT;
247#endif
248
249 playing_notes = false;
250 playing_note = false;
251 frequency = 0;
252 frequency_alt = 0;
253 volume = 0;
254
255 for (uint8_t i = 0; i < 8; i++) {
256 frequencies[i] = 0;
257 volumes[i] = 0;
258 }
259}
260
261void stop_note(float freq) {
262 dprintf("audio stop note freq=%d", (int)freq);
263
264 if (playing_note) {
265 if (!audio_initialized) {
266 audio_init();
267 }
268 for (int i = 7; i >= 0; i--) {
269 if (frequencies[i] == freq) {
270 frequencies[i] = 0;
271 volumes[i] = 0;
272 for (int j = i; (j < 7); j++) {
273 frequencies[j] = frequencies[j + 1];
274 frequencies[j + 1] = 0;
275 volumes[j] = volumes[j + 1];
276 volumes[j + 1] = 0;
277 }
278 break;
279 }
280 }
281 voices--;
282 if (voices < 0) voices = 0;
283 if (voice_place >= voices) {
284 voice_place = 0;
285 }
286 if (voices == 0) {
287#ifdef CPIN_AUDIO
288 DISABLE_AUDIO_COUNTER_3_ISR;
289 DISABLE_AUDIO_COUNTER_3_OUTPUT;
290#endif
291#ifdef BPIN_AUDIO
292 DISABLE_AUDIO_COUNTER_1_ISR;
293 DISABLE_AUDIO_COUNTER_1_OUTPUT;
294#endif
295 frequency = 0;
296 frequency_alt = 0;
297 volume = 0;
298 playing_note = false;
299 }
300 }
301}
302
303#ifdef VIBRATO_ENABLE
304
305float mod(float a, int b) {
306 float r = fmod(a, b);
307 return r < 0 ? r + b : r;
308}
309
310float vibrato(float average_freq) {
311# ifdef VIBRATO_STRENGTH_ENABLE
312 float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
313# else
314 float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
315# endif
316 vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0 / average_freq)), VIBRATO_LUT_LENGTH);
317 return vibrated_freq;
318}
319
320#endif
321
322#ifdef CPIN_AUDIO
323ISR(TIMER3_AUDIO_vect) {
324 float freq;
325
326 if (playing_note) {
327 if (voices > 0) {
328# ifdef BPIN_AUDIO
329 float freq_alt = 0;
330 if (voices > 1) {
331 if (polyphony_rate == 0) {
332 if (glissando) {
333 if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440 / frequencies[voices - 2] / 12 / 2)) {
334 frequency_alt = frequency_alt * pow(2, 440 / frequency_alt / 12 / 2);
335 } else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440 / frequencies[voices - 2] / 12 / 2)) {
336 frequency_alt = frequency_alt * pow(2, -440 / frequency_alt / 12 / 2);
337 } else {
338 frequency_alt = frequencies[voices - 2];
339 }
340 } else {
341 frequency_alt = frequencies[voices - 2];
342 }
343
344# ifdef VIBRATO_ENABLE
345 if (vibrato_strength > 0) {
346 freq_alt = vibrato(frequency_alt);
347 } else {
348 freq_alt = frequency_alt;
349 }
350# else
351 freq_alt = frequency_alt;
352# endif
353 }
354
355 if (envelope_index < 65535) {
356 envelope_index++;
357 }
358
359 freq_alt = voice_envelope(freq_alt);
360
361 if (freq_alt < 30.517578125) {
362 freq_alt = 30.52;
363 }
364
365 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq_alt * CPU_PRESCALER));
366 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq_alt * CPU_PRESCALER)) * note_timbre);
367 }
368# endif
369
370 if (polyphony_rate > 0) {
371 if (voices > 1) {
372 voice_place %= voices;
373 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
374 voice_place = (voice_place + 1) % voices;
375 place = 0.0;
376 }
377 }
378
379# ifdef VIBRATO_ENABLE
380 if (vibrato_strength > 0) {
381 freq = vibrato(frequencies[voice_place]);
382 } else {
383 freq = frequencies[voice_place];
384 }
385# else
386 freq = frequencies[voice_place];
387# endif
388 } else {
389 if (glissando) {
390 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440 / frequencies[voices - 1] / 12 / 2)) {
391 frequency = frequency * pow(2, 440 / frequency / 12 / 2);
392 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440 / frequencies[voices - 1] / 12 / 2)) {
393 frequency = frequency * pow(2, -440 / frequency / 12 / 2);
394 } else {
395 frequency = frequencies[voices - 1];
396 }
397 } else {
398 frequency = frequencies[voices - 1];
399 }
400
401# ifdef VIBRATO_ENABLE
402 if (vibrato_strength > 0) {
403 freq = vibrato(frequency);
404 } else {
405 freq = frequency;
406 }
407# else
408 freq = frequency;
409# endif
410 }
411
412 if (envelope_index < 65535) {
413 envelope_index++;
414 }
415
416 freq = voice_envelope(freq);
417
418 if (freq < 30.517578125) {
419 freq = 30.52;
420 }
421
422 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
423 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
424 }
425 }
426
427 if (playing_notes) {
428 if (note_frequency > 0) {
429# ifdef VIBRATO_ENABLE
430 if (vibrato_strength > 0) {
431 freq = vibrato(note_frequency);
432 } else {
433 freq = note_frequency;
434 }
435# else
436 freq = note_frequency;
437# endif
438
439 if (envelope_index < 65535) {
440 envelope_index++;
441 }
442 freq = voice_envelope(freq);
443
444 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
445 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
446 } else {
447 TIMER_3_PERIOD = 0;
448 TIMER_3_DUTY_CYCLE = 0;
449 }
450
451 note_position++;
452 bool end_of_note = false;
453 if (TIMER_3_PERIOD > 0) {
454 if (!note_resting)
455 end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF - 1));
456 else
457 end_of_note = (note_position >= (note_length));
458 } else {
459 end_of_note = (note_position >= (note_length));
460 }
461
462 if (end_of_note) {
463 current_note++;
464 if (current_note >= notes_count) {
465 if (notes_repeat) {
466 current_note = 0;
467 } else {
468 DISABLE_AUDIO_COUNTER_3_ISR;
469 DISABLE_AUDIO_COUNTER_3_OUTPUT;
470 playing_notes = false;
471 return;
472 }
473 }
474 if (!note_resting) {
475 note_resting = true;
476 current_note--;
477 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
478 note_frequency = 0;
479 note_length = 1;
480 } else {
481 note_frequency = (*notes_pointer)[current_note][0];
482 note_length = 1;
483 }
484 } else {
485 note_resting = false;
486 envelope_index = 0;
487 note_frequency = (*notes_pointer)[current_note][0];
488 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
489 }
490
491 note_position = 0;
492 }
493 }
494
495 if (!audio_config.enable) {
496 playing_notes = false;
497 playing_note = false;
498 }
499}
500#endif
501
502#ifdef BPIN_AUDIO
503ISR(TIMER1_AUDIO_vect) {
504# if defined(BPIN_AUDIO) && !defined(CPIN_AUDIO)
505 float freq = 0;
506
507 if (playing_note) {
508 if (voices > 0) {
509 if (polyphony_rate > 0) {
510 if (voices > 1) {
511 voice_place %= voices;
512 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
513 voice_place = (voice_place + 1) % voices;
514 place = 0.0;
515 }
516 }
517
518# ifdef VIBRATO_ENABLE
519 if (vibrato_strength > 0) {
520 freq = vibrato(frequencies[voice_place]);
521 } else {
522 freq = frequencies[voice_place];
523 }
524# else
525 freq = frequencies[voice_place];
526# endif
527 } else {
528 if (glissando) {
529 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440 / frequencies[voices - 1] / 12 / 2)) {
530 frequency = frequency * pow(2, 440 / frequency / 12 / 2);
531 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440 / frequencies[voices - 1] / 12 / 2)) {
532 frequency = frequency * pow(2, -440 / frequency / 12 / 2);
533 } else {
534 frequency = frequencies[voices - 1];
535 }
536 } else {
537 frequency = frequencies[voices - 1];
538 }
539
540# ifdef VIBRATO_ENABLE
541 if (vibrato_strength > 0) {
542 freq = vibrato(frequency);
543 } else {
544 freq = frequency;
545 }
546# else
547 freq = frequency;
548# endif
549 }
550
551 if (envelope_index < 65535) {
552 envelope_index++;
553 }
554
555 freq = voice_envelope(freq);
556
557 if (freq < 30.517578125) {
558 freq = 30.52;
559 }
560
561 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
562 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
563 }
564 }
565
566 if (playing_notes) {
567 if (note_frequency > 0) {
568# ifdef VIBRATO_ENABLE
569 if (vibrato_strength > 0) {
570 freq = vibrato(note_frequency);
571 } else {
572 freq = note_frequency;
573 }
574# else
575 freq = note_frequency;
576# endif
577
578 if (envelope_index < 65535) {
579 envelope_index++;
580 }
581 freq = voice_envelope(freq);
582
583 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
584 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
585 } else {
586 TIMER_1_PERIOD = 0;
587 TIMER_1_DUTY_CYCLE = 0;
588 }
589
590 note_position++;
591 bool end_of_note = false;
592 if (TIMER_1_PERIOD > 0) {
593 if (!note_resting)
594 end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF - 1));
595 else
596 end_of_note = (note_position >= (note_length));
597 } else {
598 end_of_note = (note_position >= (note_length));
599 }
600
601 if (end_of_note) {
602 current_note++;
603 if (current_note >= notes_count) {
604 if (notes_repeat) {
605 current_note = 0;
606 } else {
607 DISABLE_AUDIO_COUNTER_1_ISR;
608 DISABLE_AUDIO_COUNTER_1_OUTPUT;
609 playing_notes = false;
610 return;
611 }
612 }
613 if (!note_resting) {
614 note_resting = true;
615 current_note--;
616 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
617 note_frequency = 0;
618 note_length = 1;
619 } else {
620 note_frequency = (*notes_pointer)[current_note][0];
621 note_length = 1;
622 }
623 } else {
624 note_resting = false;
625 envelope_index = 0;
626 note_frequency = (*notes_pointer)[current_note][0];
627 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
628 }
629
630 note_position = 0;
631 }
632 }
633
634 if (!audio_config.enable) {
635 playing_notes = false;
636 playing_note = false;
637 }
638# endif
639}
640#endif
641
642void play_note(float freq, int vol) {
643 dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
644
645 if (!audio_initialized) {
646 audio_init();
647 }
648
649 if (audio_config.enable && voices < 8) {
650#ifdef CPIN_AUDIO
651 DISABLE_AUDIO_COUNTER_3_ISR;
652#endif
653#ifdef BPIN_AUDIO
654 DISABLE_AUDIO_COUNTER_1_ISR;
655#endif
656
657 // Cancel notes if notes are playing
658 if (playing_notes) stop_all_notes();
659
660 playing_note = true;
661
662 envelope_index = 0;
663
664 if (freq > 0) {
665 frequencies[voices] = freq;
666 volumes[voices] = vol;
667 voices++;
668 }
669
670#ifdef CPIN_AUDIO
671 ENABLE_AUDIO_COUNTER_3_ISR;
672 ENABLE_AUDIO_COUNTER_3_OUTPUT;
673#endif
674#ifdef BPIN_AUDIO
675# ifdef CPIN_AUDIO
676 if (voices > 1) {
677 ENABLE_AUDIO_COUNTER_1_ISR;
678 ENABLE_AUDIO_COUNTER_1_OUTPUT;
679 }
680# else
681 ENABLE_AUDIO_COUNTER_1_ISR;
682 ENABLE_AUDIO_COUNTER_1_OUTPUT;
683# endif
684#endif
685 }
686}
687
688void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) {
689 if (!audio_initialized) {
690 audio_init();
691 }
692
693 if (audio_config.enable) {
694#ifdef CPIN_AUDIO
695 DISABLE_AUDIO_COUNTER_3_ISR;
696#endif
697#ifdef BPIN_AUDIO
698 DISABLE_AUDIO_COUNTER_1_ISR;
699#endif
700
701 // Cancel note if a note is playing
702 if (playing_note) stop_all_notes();
703
704 playing_notes = true;
705
706 notes_pointer = np;
707 notes_count = n_count;
708 notes_repeat = n_repeat;
709
710 place = 0;
711 current_note = 0;
712
713 note_frequency = (*notes_pointer)[current_note][0];
714 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
715 note_position = 0;
716
717#ifdef CPIN_AUDIO
718 ENABLE_AUDIO_COUNTER_3_ISR;
719 ENABLE_AUDIO_COUNTER_3_OUTPUT;
720#endif
721#ifdef BPIN_AUDIO
722# ifndef CPIN_AUDIO
723 ENABLE_AUDIO_COUNTER_1_ISR;
724 ENABLE_AUDIO_COUNTER_1_OUTPUT;
725# endif
726#endif
727 }
728}
729
730bool is_playing_notes(void) { return playing_notes; }
731
732bool is_audio_on(void) { return (audio_config.enable != 0); }
733
734void audio_toggle(void) {
735 audio_config.enable ^= 1;
736 eeconfig_update_audio(audio_config.raw);
737 if (audio_config.enable) audio_on_user();
738}
739
740void audio_on(void) {
741 audio_config.enable = 1;
742 eeconfig_update_audio(audio_config.raw);
743 audio_on_user();
744 PLAY_SONG(audio_on_song);
745}
746
747void audio_off(void) {
748 PLAY_SONG(audio_off_song);
749 wait_ms(100);
750 stop_all_notes();
751 audio_config.enable = 0;
752 eeconfig_update_audio(audio_config.raw);
753}
754
755#ifdef VIBRATO_ENABLE
756
757// Vibrato rate functions
758
759void set_vibrato_rate(float rate) { vibrato_rate = rate; }
760
761void increase_vibrato_rate(float change) { vibrato_rate *= change; }
762
763void decrease_vibrato_rate(float change) { vibrato_rate /= change; }
764
765# ifdef VIBRATO_STRENGTH_ENABLE
766
767void set_vibrato_strength(float strength) { vibrato_strength = strength; }
768
769void increase_vibrato_strength(float change) { vibrato_strength *= change; }
770
771void decrease_vibrato_strength(float change) { vibrato_strength /= change; }
772
773# endif /* VIBRATO_STRENGTH_ENABLE */
774
775#endif /* VIBRATO_ENABLE */
776
777// Polyphony functions
778
779void set_polyphony_rate(float rate) { polyphony_rate = rate; }
780
781void enable_polyphony() { polyphony_rate = 5; }
782
783void disable_polyphony() { polyphony_rate = 0; }
784
785void increase_polyphony_rate(float change) { polyphony_rate *= change; }
786
787void decrease_polyphony_rate(float change) { polyphony_rate /= change; }
788
789// Timbre function
790
791void set_timbre(float timbre) { note_timbre = timbre; }
792
793// Tempo functions
794
795void set_tempo(uint8_t tempo) { note_tempo = tempo; }
796
797void decrease_tempo(uint8_t tempo_change) { note_tempo += tempo_change; }
798
799void increase_tempo(uint8_t tempo_change) {
800 if (note_tempo - tempo_change < 10) {
801 note_tempo = 10;
802 } else {
803 note_tempo -= tempo_change;
804 }
805}