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.c812
1 files changed, 0 insertions, 812 deletions
diff --git a/quantum/audio/audio_avr.c b/quantum/audio/audio_avr.c
deleted file mode 100644
index 1bac43bb4..000000000
--- a/quantum/audio/audio_avr.c
+++ /dev/null
@@ -1,812 +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
232void audio_startup() {
233 if (audio_config.enable) {
234 PLAY_SONG(startup_song);
235 }
236}
237
238void stop_all_notes() {
239 dprintf("audio stop all notes");
240
241 if (!audio_initialized) {
242 audio_init();
243 }
244 voices = 0;
245
246#ifdef CPIN_AUDIO
247 DISABLE_AUDIO_COUNTER_3_ISR;
248 DISABLE_AUDIO_COUNTER_3_OUTPUT;
249#endif
250
251#ifdef BPIN_AUDIO
252 DISABLE_AUDIO_COUNTER_1_ISR;
253 DISABLE_AUDIO_COUNTER_1_OUTPUT;
254#endif
255
256 playing_notes = false;
257 playing_note = false;
258 frequency = 0;
259 frequency_alt = 0;
260 volume = 0;
261
262 for (uint8_t i = 0; i < 8; i++) {
263 frequencies[i] = 0;
264 volumes[i] = 0;
265 }
266}
267
268void stop_note(float freq) {
269 dprintf("audio stop note freq=%d", (int)freq);
270
271 if (playing_note) {
272 if (!audio_initialized) {
273 audio_init();
274 }
275 for (int i = 7; i >= 0; i--) {
276 if (frequencies[i] == freq) {
277 frequencies[i] = 0;
278 volumes[i] = 0;
279 for (int j = i; (j < 7); j++) {
280 frequencies[j] = frequencies[j + 1];
281 frequencies[j + 1] = 0;
282 volumes[j] = volumes[j + 1];
283 volumes[j + 1] = 0;
284 }
285 break;
286 }
287 }
288 voices--;
289 if (voices < 0) voices = 0;
290 if (voice_place >= voices) {
291 voice_place = 0;
292 }
293 if (voices == 0) {
294#ifdef CPIN_AUDIO
295 DISABLE_AUDIO_COUNTER_3_ISR;
296 DISABLE_AUDIO_COUNTER_3_OUTPUT;
297#endif
298#ifdef BPIN_AUDIO
299 DISABLE_AUDIO_COUNTER_1_ISR;
300 DISABLE_AUDIO_COUNTER_1_OUTPUT;
301#endif
302 frequency = 0;
303 frequency_alt = 0;
304 volume = 0;
305 playing_note = false;
306 }
307 }
308}
309
310#ifdef VIBRATO_ENABLE
311
312float mod(float a, int b) {
313 float r = fmod(a, b);
314 return r < 0 ? r + b : r;
315}
316
317float vibrato(float average_freq) {
318# ifdef VIBRATO_STRENGTH_ENABLE
319 float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
320# else
321 float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
322# endif
323 vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0 / average_freq)), VIBRATO_LUT_LENGTH);
324 return vibrated_freq;
325}
326
327#endif
328
329#ifdef CPIN_AUDIO
330ISR(TIMER3_AUDIO_vect) {
331 float freq;
332
333 if (playing_note) {
334 if (voices > 0) {
335# ifdef BPIN_AUDIO
336 float freq_alt = 0;
337 if (voices > 1) {
338 if (polyphony_rate == 0) {
339 if (glissando) {
340 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 if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440 / frequencies[voices - 2] / 12 / 2)) {
343 frequency_alt = frequency_alt * pow(2, -440 / frequency_alt / 12 / 2);
344 } else {
345 frequency_alt = frequencies[voices - 2];
346 }
347 } else {
348 frequency_alt = frequencies[voices - 2];
349 }
350
351# ifdef VIBRATO_ENABLE
352 if (vibrato_strength > 0) {
353 freq_alt = vibrato(frequency_alt);
354 } else {
355 freq_alt = frequency_alt;
356 }
357# else
358 freq_alt = frequency_alt;
359# endif
360 }
361
362 if (envelope_index < 65535) {
363 envelope_index++;
364 }
365
366 freq_alt = voice_envelope(freq_alt);
367
368 if (freq_alt < 30.517578125) {
369 freq_alt = 30.52;
370 }
371
372 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq_alt * CPU_PRESCALER));
373 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq_alt * CPU_PRESCALER)) * note_timbre);
374 }
375# endif
376
377 if (polyphony_rate > 0) {
378 if (voices > 1) {
379 voice_place %= voices;
380 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
381 voice_place = (voice_place + 1) % voices;
382 place = 0.0;
383 }
384 }
385
386# ifdef VIBRATO_ENABLE
387 if (vibrato_strength > 0) {
388 freq = vibrato(frequencies[voice_place]);
389 } else {
390 freq = frequencies[voice_place];
391 }
392# else
393 freq = frequencies[voice_place];
394# endif
395 } else {
396 if (glissando) {
397 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 if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440 / frequencies[voices - 1] / 12 / 2)) {
400 frequency = frequency * pow(2, -440 / frequency / 12 / 2);
401 } else {
402 frequency = frequencies[voices - 1];
403 }
404 } else {
405 frequency = frequencies[voices - 1];
406 }
407
408# ifdef VIBRATO_ENABLE
409 if (vibrato_strength > 0) {
410 freq = vibrato(frequency);
411 } else {
412 freq = frequency;
413 }
414# else
415 freq = frequency;
416# endif
417 }
418
419 if (envelope_index < 65535) {
420 envelope_index++;
421 }
422
423 freq = voice_envelope(freq);
424
425 if (freq < 30.517578125) {
426 freq = 30.52;
427 }
428
429 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
430 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
431 }
432 }
433
434 if (playing_notes) {
435 if (note_frequency > 0) {
436# ifdef VIBRATO_ENABLE
437 if (vibrato_strength > 0) {
438 freq = vibrato(note_frequency);
439 } else {
440 freq = note_frequency;
441 }
442# else
443 freq = note_frequency;
444# endif
445
446 if (envelope_index < 65535) {
447 envelope_index++;
448 }
449 freq = voice_envelope(freq);
450
451 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
452 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
453 } else {
454 TIMER_3_PERIOD = 0;
455 TIMER_3_DUTY_CYCLE = 0;
456 }
457
458 note_position++;
459 bool end_of_note = false;
460 if (TIMER_3_PERIOD > 0) {
461 if (!note_resting)
462 end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF - 1));
463 else
464 end_of_note = (note_position >= (note_length));
465 } else {
466 end_of_note = (note_position >= (note_length));
467 }
468
469 if (end_of_note) {
470 current_note++;
471 if (current_note >= notes_count) {
472 if (notes_repeat) {
473 current_note = 0;
474 } else {
475 DISABLE_AUDIO_COUNTER_3_ISR;
476 DISABLE_AUDIO_COUNTER_3_OUTPUT;
477 playing_notes = false;
478 return;
479 }
480 }
481 if (!note_resting) {
482 note_resting = true;
483 current_note--;
484 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
485 note_frequency = 0;
486 note_length = 1;
487 } else {
488 note_frequency = (*notes_pointer)[current_note][0];
489 note_length = 1;
490 }
491 } else {
492 note_resting = false;
493 envelope_index = 0;
494 note_frequency = (*notes_pointer)[current_note][0];
495 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
496 }
497
498 note_position = 0;
499 }
500 }
501
502 if (!audio_config.enable) {
503 playing_notes = false;
504 playing_note = false;
505 }
506}
507#endif
508
509#ifdef BPIN_AUDIO
510ISR(TIMER1_AUDIO_vect) {
511# if defined(BPIN_AUDIO) && !defined(CPIN_AUDIO)
512 float freq = 0;
513
514 if (playing_note) {
515 if (voices > 0) {
516 if (polyphony_rate > 0) {
517 if (voices > 1) {
518 voice_place %= voices;
519 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
520 voice_place = (voice_place + 1) % voices;
521 place = 0.0;
522 }
523 }
524
525# ifdef VIBRATO_ENABLE
526 if (vibrato_strength > 0) {
527 freq = vibrato(frequencies[voice_place]);
528 } else {
529 freq = frequencies[voice_place];
530 }
531# else
532 freq = frequencies[voice_place];
533# endif
534 } else {
535 if (glissando) {
536 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 if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440 / frequencies[voices - 1] / 12 / 2)) {
539 frequency = frequency * pow(2, -440 / frequency / 12 / 2);
540 } else {
541 frequency = frequencies[voices - 1];
542 }
543 } else {
544 frequency = frequencies[voices - 1];
545 }
546
547# ifdef VIBRATO_ENABLE
548 if (vibrato_strength > 0) {
549 freq = vibrato(frequency);
550 } else {
551 freq = frequency;
552 }
553# else
554 freq = frequency;
555# endif
556 }
557
558 if (envelope_index < 65535) {
559 envelope_index++;
560 }
561
562 freq = voice_envelope(freq);
563
564 if (freq < 30.517578125) {
565 freq = 30.52;
566 }
567
568 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
569 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
570 }
571 }
572
573 if (playing_notes) {
574 if (note_frequency > 0) {
575# ifdef VIBRATO_ENABLE
576 if (vibrato_strength > 0) {
577 freq = vibrato(note_frequency);
578 } else {
579 freq = note_frequency;
580 }
581# else
582 freq = note_frequency;
583# endif
584
585 if (envelope_index < 65535) {
586 envelope_index++;
587 }
588 freq = voice_envelope(freq);
589
590 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
591 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
592 } else {
593 TIMER_1_PERIOD = 0;
594 TIMER_1_DUTY_CYCLE = 0;
595 }
596
597 note_position++;
598 bool end_of_note = false;
599 if (TIMER_1_PERIOD > 0) {
600 if (!note_resting)
601 end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF - 1));
602 else
603 end_of_note = (note_position >= (note_length));
604 } else {
605 end_of_note = (note_position >= (note_length));
606 }
607
608 if (end_of_note) {
609 current_note++;
610 if (current_note >= notes_count) {
611 if (notes_repeat) {
612 current_note = 0;
613 } else {
614 DISABLE_AUDIO_COUNTER_1_ISR;
615 DISABLE_AUDIO_COUNTER_1_OUTPUT;
616 playing_notes = false;
617 return;
618 }
619 }
620 if (!note_resting) {
621 note_resting = true;
622 current_note--;
623 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
624 note_frequency = 0;
625 note_length = 1;
626 } else {
627 note_frequency = (*notes_pointer)[current_note][0];
628 note_length = 1;
629 }
630 } else {
631 note_resting = false;
632 envelope_index = 0;
633 note_frequency = (*notes_pointer)[current_note][0];
634 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
635 }
636
637 note_position = 0;
638 }
639 }
640
641 if (!audio_config.enable) {
642 playing_notes = false;
643 playing_note = false;
644 }
645# endif
646}
647#endif
648
649void play_note(float freq, int vol) {
650 dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
651
652 if (!audio_initialized) {
653 audio_init();
654 }
655
656 if (audio_config.enable && voices < 8) {
657#ifdef CPIN_AUDIO
658 DISABLE_AUDIO_COUNTER_3_ISR;
659#endif
660#ifdef BPIN_AUDIO
661 DISABLE_AUDIO_COUNTER_1_ISR;
662#endif
663
664 // Cancel notes if notes are playing
665 if (playing_notes) stop_all_notes();
666
667 playing_note = true;
668
669 envelope_index = 0;
670
671 if (freq > 0) {
672 frequencies[voices] = freq;
673 volumes[voices] = vol;
674 voices++;
675 }
676
677#ifdef CPIN_AUDIO
678 ENABLE_AUDIO_COUNTER_3_ISR;
679 ENABLE_AUDIO_COUNTER_3_OUTPUT;
680#endif
681#ifdef BPIN_AUDIO
682# ifdef CPIN_AUDIO
683 if (voices > 1) {
684 ENABLE_AUDIO_COUNTER_1_ISR;
685 ENABLE_AUDIO_COUNTER_1_OUTPUT;
686 }
687# else
688 ENABLE_AUDIO_COUNTER_1_ISR;
689 ENABLE_AUDIO_COUNTER_1_OUTPUT;
690# endif
691#endif
692 }
693}
694
695void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) {
696 if (!audio_initialized) {
697 audio_init();
698 }
699
700 if (audio_config.enable) {
701#ifdef CPIN_AUDIO
702 DISABLE_AUDIO_COUNTER_3_ISR;
703#endif
704#ifdef BPIN_AUDIO
705 DISABLE_AUDIO_COUNTER_1_ISR;
706#endif
707
708 // Cancel note if a note is playing
709 if (playing_note) stop_all_notes();
710
711 playing_notes = true;
712
713 notes_pointer = np;
714 notes_count = n_count;
715 notes_repeat = n_repeat;
716
717 place = 0;
718 current_note = 0;
719
720 note_frequency = (*notes_pointer)[current_note][0];
721 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
722 note_position = 0;
723
724#ifdef CPIN_AUDIO
725 ENABLE_AUDIO_COUNTER_3_ISR;
726 ENABLE_AUDIO_COUNTER_3_OUTPUT;
727#endif
728#ifdef BPIN_AUDIO
729# ifndef CPIN_AUDIO
730 ENABLE_AUDIO_COUNTER_1_ISR;
731 ENABLE_AUDIO_COUNTER_1_OUTPUT;
732# endif
733#endif
734 }
735}
736
737bool is_playing_notes(void) { return playing_notes; }
738
739bool is_audio_on(void) { return (audio_config.enable != 0); }
740
741void audio_toggle(void) {
742 audio_config.enable ^= 1;
743 eeconfig_update_audio(audio_config.raw);
744 if (audio_config.enable) audio_on_user();
745}
746
747void audio_on(void) {
748 audio_config.enable = 1;
749 eeconfig_update_audio(audio_config.raw);
750 audio_on_user();
751 PLAY_SONG(audio_on_song);
752}
753
754void audio_off(void) {
755 PLAY_SONG(audio_off_song);
756 wait_ms(100);
757 stop_all_notes();
758 audio_config.enable = 0;
759 eeconfig_update_audio(audio_config.raw);
760}
761
762#ifdef VIBRATO_ENABLE
763
764// Vibrato rate functions
765
766void set_vibrato_rate(float rate) { vibrato_rate = rate; }
767
768void increase_vibrato_rate(float change) { vibrato_rate *= change; }
769
770void decrease_vibrato_rate(float change) { vibrato_rate /= change; }
771
772# ifdef VIBRATO_STRENGTH_ENABLE
773
774void set_vibrato_strength(float strength) { vibrato_strength = strength; }
775
776void increase_vibrato_strength(float change) { vibrato_strength *= change; }
777
778void decrease_vibrato_strength(float change) { vibrato_strength /= change; }
779
780# endif /* VIBRATO_STRENGTH_ENABLE */
781
782#endif /* VIBRATO_ENABLE */
783
784// Polyphony functions
785
786void set_polyphony_rate(float rate) { polyphony_rate = rate; }
787
788void enable_polyphony() { polyphony_rate = 5; }
789
790void disable_polyphony() { polyphony_rate = 0; }
791
792void increase_polyphony_rate(float change) { polyphony_rate *= change; }
793
794void decrease_polyphony_rate(float change) { polyphony_rate /= change; }
795
796// Timbre function
797
798void set_timbre(float timbre) { note_timbre = timbre; }
799
800// Tempo functions
801
802void set_tempo(uint8_t tempo) { note_tempo = tempo; }
803
804void decrease_tempo(uint8_t tempo_change) { note_tempo += tempo_change; }
805
806void increase_tempo(uint8_t tempo_change) {
807 if (note_tempo - tempo_change < 10) {
808 note_tempo = 10;
809 } else {
810 note_tempo -= tempo_change;
811 }
812}