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