audio.c (21231B)
1 /* Copyright 2016-2020 Jack Humbert 2 * Copyright 2020 JohSchneider 3 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 #include "audio.h" 18 #include "eeconfig.h" 19 #include "timer.h" 20 #include "debug.h" 21 #include "wait.h" 22 #include "util.h" 23 #include "gpio.h" 24 25 /* audio system: 26 * 27 * audio.[ch] takes care of all overall state, tracking the actively playing 28 * notes/tones; the notes a SONG consists of; 29 * ... 30 * = everything audio-related that is platform agnostic 31 * 32 * driver_[avr|chibios]_[dac|pwm] take care of the lower hardware dependent parts, 33 * specific to each platform and the used subsystem/driver to drive 34 * the output pins/channels with the calculated frequencies for each 35 * active tone 36 * as part of this, the driver has to trigger regular state updates by 37 * calling 'audio_update_state' through some sort of timer - be it a 38 * dedicated one or piggybacking on for example the timer used to 39 * generate a pwm signal/clock. 40 * 41 * 42 * A Note on terminology: 43 * tone, pitch and frequency are used somewhat interchangeably, in a strict Wikipedia-sense: 44 * "(Musical) tone, a sound characterized by its duration, pitch (=frequency), 45 * intensity (=volume), and timbre" 46 * - intensity/volume is currently not handled at all, although the 'dac_additive' driver could do so 47 * - timbre is handled globally (TODO: only used with the pwm drivers at the moment) 48 * 49 * in musical_note.h a 'note' is the combination of a pitch and a duration 50 * these are used to create SONG arrays; during playback their frequencies 51 * are handled as single successive tones, while the durations are 52 * kept track of in 'audio_update_state' 53 * 54 * 'voice' as it is used here, equates to a sort of instrument with its own 55 * characteristics sound and effects 56 * the audio system as-is deals only with (possibly multiple) tones of one 57 * instrument/voice at a time (think: chords). since the number of tones that 58 * can be reproduced depends on the hardware/driver in use: pwm can only 59 * reproduce one tone per output/speaker; DACs can reproduce/mix multiple 60 * when doing additive synthesis. 61 * 62 * 'duration' can either be in the beats-per-minute related unit found in 63 * musical_notes.h, OR in ms; keyboards create SONGs with the former, while 64 * the internal state of the audio system does its calculations with the later - ms 65 */ 66 67 #ifndef AUDIO_DEFAULT_ON 68 # define AUDIO_DEFAULT_ON true 69 #endif 70 #ifndef AUDIO_DEFAULT_CLICKY_ON 71 # define AUDIO_DEFAULT_CLICKY_ON true 72 #endif 73 74 #ifndef AUDIO_TONE_STACKSIZE 75 # define AUDIO_TONE_STACKSIZE 8 76 #endif 77 uint8_t active_tones = 0; // number of tones pushed onto the stack by audio_play_tone - might be more than the hardware is able to reproduce at any single time 78 musical_tone_t tones[AUDIO_TONE_STACKSIZE]; // stack of currently active tones 79 80 bool playing_melody = false; // playing a SONG? 81 bool playing_note = false; // or (possibly multiple simultaneous) tones 82 bool state_changed = false; // global flag, which is set if anything changes with the active_tones 83 84 // melody/SONG related state variables 85 float (*notes_pointer)[][2]; // SONG, an array of MUSICAL_NOTEs 86 uint16_t notes_count; // length of the notes_pointer array 87 bool notes_repeat; // PLAY_SONG or PLAY_LOOP? 88 uint16_t melody_current_note_duration = 0; // duration of the currently playing note from the active melody, in ms 89 uint8_t note_tempo = TEMPO_DEFAULT; // beats-per-minute 90 uint16_t current_note = 0; // index into the array at notes_pointer 91 bool note_resting = false; // if a short pause was introduced between two notes with the same frequency while playing a melody 92 uint16_t last_timestamp = 0; 93 94 #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING 95 # ifndef AUDIO_MAX_SIMULTANEOUS_TONES 96 # define AUDIO_MAX_SIMULTANEOUS_TONES 3 97 # endif 98 uint16_t tone_multiplexing_rate = AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT; 99 uint8_t tone_multiplexing_index_shift = 0; // offset used on active-tone array access 100 #endif 101 102 // provided and used by voices.c 103 extern uint8_t note_timbre; 104 extern bool glissando; 105 extern bool vibrato; 106 extern uint16_t voices_timer; 107 108 #ifndef STARTUP_SONG 109 # define STARTUP_SONG SONG(STARTUP_SOUND) 110 #endif 111 #ifndef AUDIO_ON_SONG 112 # define AUDIO_ON_SONG SONG(AUDIO_ON_SOUND) 113 #endif 114 #ifndef AUDIO_OFF_SONG 115 # define AUDIO_OFF_SONG SONG(AUDIO_OFF_SOUND) 116 #endif 117 float startup_song[][2] = STARTUP_SONG; 118 float audio_on_song[][2] = AUDIO_ON_SONG; 119 float audio_off_song[][2] = AUDIO_OFF_SONG; 120 121 static bool audio_initialized = false; 122 static bool audio_driver_stopped = true; 123 audio_config_t audio_config; 124 125 #ifndef AUDIO_POWER_CONTROL_PIN_ON_STATE 126 # define AUDIO_POWER_CONTROL_PIN_ON_STATE 1 127 #endif 128 129 void audio_driver_initialize(void) { 130 #ifdef AUDIO_POWER_CONTROL_PIN 131 gpio_set_pin_output_push_pull(AUDIO_POWER_CONTROL_PIN); 132 gpio_write_pin(AUDIO_POWER_CONTROL_PIN, !AUDIO_POWER_CONTROL_PIN_ON_STATE); 133 #endif 134 audio_driver_initialize_impl(); 135 } 136 137 void audio_driver_stop(void) { 138 audio_driver_stop_impl(); 139 #ifdef AUDIO_POWER_CONTROL_PIN 140 gpio_write_pin(AUDIO_POWER_CONTROL_PIN, !AUDIO_POWER_CONTROL_PIN_ON_STATE); 141 #endif 142 } 143 144 void audio_driver_start(void) { 145 #ifdef AUDIO_POWER_CONTROL_PIN 146 gpio_write_pin(AUDIO_POWER_CONTROL_PIN, AUDIO_POWER_CONTROL_PIN_ON_STATE); 147 #endif 148 audio_driver_start_impl(); 149 } 150 151 void eeconfig_update_audio_current(void) { 152 eeconfig_update_audio(&audio_config); 153 } 154 155 void eeconfig_update_audio_default(void) { 156 audio_config.valid = true; 157 audio_config.enable = AUDIO_DEFAULT_ON; 158 audio_config.clicky_enable = AUDIO_DEFAULT_CLICKY_ON; 159 eeconfig_update_audio(&audio_config); 160 } 161 162 void audio_init(void) { 163 if (audio_initialized) { 164 return; 165 } 166 167 eeconfig_read_audio(&audio_config); 168 if (!audio_config.valid) { 169 dprintf("audio_init audio_config.valid = 0. Write default values to EEPROM.\n"); 170 eeconfig_update_audio_default(); 171 } 172 173 for (uint8_t i = 0; i < AUDIO_TONE_STACKSIZE; i++) { 174 tones[i] = (musical_tone_t){.time_started = 0, .pitch = -1.0f, .duration = 0}; 175 } 176 177 audio_driver_initialize(); 178 audio_initialized = true; 179 180 stop_all_notes(); 181 #ifndef AUDIO_INIT_DELAY 182 audio_startup(); 183 #endif 184 } 185 186 void audio_task(void) { 187 #ifdef AUDIO_INIT_DELAY 188 // startup song potentially needs to be run a little bit 189 // after keyboard startup, or else they will not work correctly 190 // because of interaction with the USB device state, which 191 // may still be in flux... 192 static bool delayed_tasks_run = false; 193 static uint16_t delayed_task_timer = 0; 194 if (!delayed_tasks_run) { 195 if (!delayed_task_timer) { 196 delayed_task_timer = timer_read(); 197 } else if (timer_elapsed(delayed_task_timer) > 300) { 198 audio_startup(); 199 delayed_tasks_run = true; 200 } 201 } 202 #endif 203 } 204 205 void audio_startup(void) { 206 if (audio_config.enable) { 207 PLAY_SONG(startup_song); 208 } 209 210 last_timestamp = timer_read(); 211 } 212 213 void audio_toggle(void) { 214 if (audio_config.enable) { 215 stop_all_notes(); 216 } 217 audio_config.enable ^= 1; 218 eeconfig_update_audio(&audio_config); 219 if (audio_config.enable) { 220 audio_on_user(); 221 } else { 222 audio_off_user(); 223 } 224 } 225 226 void audio_on(void) { 227 audio_config.enable = 1; 228 eeconfig_update_audio(&audio_config); 229 audio_on_user(); 230 PLAY_SONG(audio_on_song); 231 } 232 233 void audio_off(void) { 234 PLAY_SONG(audio_off_song); 235 audio_off_user(); 236 wait_ms(100); 237 audio_stop_all(); 238 audio_config.enable = 0; 239 eeconfig_update_audio(&audio_config); 240 } 241 242 bool audio_is_on(void) { 243 return (audio_config.enable != 0); 244 } 245 246 void audio_stop_all(void) { 247 if (audio_driver_stopped) { 248 return; 249 } 250 251 active_tones = 0; 252 253 audio_driver_stop(); 254 255 playing_melody = false; 256 playing_note = false; 257 258 melody_current_note_duration = 0; 259 260 for (uint8_t i = 0; i < AUDIO_TONE_STACKSIZE; i++) { 261 tones[i] = (musical_tone_t){.time_started = 0, .pitch = -1.0f, .duration = 0}; 262 } 263 264 audio_driver_stopped = true; 265 } 266 267 void audio_stop_tone(float pitch) { 268 if (pitch < 0.0f) { 269 pitch = -1 * pitch; 270 } 271 272 if (playing_note) { 273 if (!audio_initialized) { 274 audio_init(); 275 } 276 bool found = false; 277 for (int i = AUDIO_TONE_STACKSIZE - 1; i >= 0; i--) { 278 found = (tones[i].pitch == pitch); 279 if (found) { 280 for (int j = i; (j < AUDIO_TONE_STACKSIZE - 1); j++) { 281 tones[j] = tones[j + 1]; 282 } 283 tones[AUDIO_TONE_STACKSIZE - 1] = (musical_tone_t){.time_started = 0, .pitch = -1.0f, .duration = 0}; 284 break; 285 } 286 } 287 if (!found) { 288 return; 289 } 290 291 state_changed = true; 292 active_tones--; 293 if (active_tones < 0) active_tones = 0; 294 #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING 295 if (tone_multiplexing_index_shift >= active_tones) { 296 tone_multiplexing_index_shift = 0; 297 } 298 #endif 299 if (active_tones == 0) { 300 audio_driver_stop(); 301 audio_driver_stopped = true; 302 playing_note = false; 303 } 304 } 305 } 306 307 void audio_play_note(float pitch, uint16_t duration) { 308 if (!audio_config.enable) { 309 return; 310 } 311 312 if (!audio_initialized) { 313 audio_init(); 314 } 315 316 if (pitch < 0.0f) { 317 pitch = -1 * pitch; 318 } 319 320 // round-robin: shifting out old tones, keeping only unique ones 321 // if the new frequency is already amongst the active tones, shift it to the top of the stack 322 bool found = false; 323 for (int i = active_tones - 1; i >= 0; i--) { 324 found = (tones[i].pitch == pitch); 325 if (found) { 326 for (int j = i; (j < active_tones - 1); j++) { 327 tones[j] = tones[j + 1]; 328 tones[j + 1] = (musical_tone_t){.time_started = timer_read(), .pitch = pitch, .duration = duration}; 329 } 330 return; // since this frequency played already, the hardware was already started 331 } 332 } 333 334 // frequency/tone is actually new, so we put it on the top of the stack 335 active_tones++; 336 if (active_tones > AUDIO_TONE_STACKSIZE) { 337 active_tones = AUDIO_TONE_STACKSIZE; 338 // shift out the oldest tone to make room 339 for (int i = 0; i < active_tones - 1; i++) { 340 tones[i] = tones[i + 1]; 341 } 342 } 343 state_changed = true; 344 playing_note = true; 345 tones[active_tones - 1] = (musical_tone_t){.time_started = timer_read(), .pitch = pitch, .duration = duration}; 346 347 // TODO: needs to be handled per note/tone -> use its timestamp instead? 348 voices_timer = timer_read(); // reset to zero, for the effects added by voices.c 349 350 if (audio_driver_stopped) { 351 audio_driver_start(); 352 audio_driver_stopped = false; 353 } 354 } 355 356 void audio_play_tone(float pitch) { 357 audio_play_note(pitch, 0xffff); 358 } 359 360 void audio_play_melody(float (*np)[][2], uint16_t n_count, bool n_repeat) { 361 if (!audio_config.enable) { 362 audio_stop_all(); 363 return; 364 } 365 366 if (n_count == 0) { 367 return; 368 } 369 370 if (!audio_initialized) { 371 audio_init(); 372 } 373 374 // Cancel note if a note is playing 375 if (playing_note) audio_stop_all(); 376 377 playing_melody = true; 378 note_resting = false; 379 380 notes_pointer = np; 381 notes_count = n_count; 382 notes_repeat = n_repeat; 383 384 current_note = 0; // note in the melody-array/list at note_pointer 385 386 // start first note manually, which also starts the audio_driver 387 // all following/remaining notes are played by 'audio_update_state' 388 audio_play_note((*notes_pointer)[current_note][0], audio_duration_to_ms((*notes_pointer)[current_note][1])); 389 last_timestamp = timer_read(); 390 melody_current_note_duration = audio_duration_to_ms((*notes_pointer)[current_note][1]); 391 } 392 393 void audio_play_click(uint16_t delay, float pitch, uint16_t duration) { 394 static float click[2][2]; 395 396 uint16_t duration_tone = audio_ms_to_duration(duration); 397 uint16_t duration_delay = audio_ms_to_duration(delay); 398 399 if (delay <= 0.0f) { 400 click[0][0] = pitch; 401 click[0][1] = duration_tone; 402 click[1][0] = 0.0f; 403 click[1][1] = 0.0f; 404 audio_play_melody(&click, 1, false); 405 } else { 406 // first note is a rest/pause 407 click[0][0] = 0.0f; 408 click[0][1] = duration_delay; 409 // second note is the actual click 410 click[1][0] = pitch; 411 click[1][1] = duration_tone; 412 audio_play_melody(&click, 2, false); 413 } 414 } 415 416 bool audio_is_playing_note(void) { 417 return playing_note; 418 } 419 420 bool audio_is_playing_melody(void) { 421 return playing_melody; 422 } 423 424 uint8_t audio_get_number_of_active_tones(void) { 425 return active_tones; 426 } 427 428 float audio_get_frequency(uint8_t tone_index) { 429 if (tone_index >= active_tones) { 430 return 0.0f; 431 } 432 return tones[active_tones - tone_index - 1].pitch; 433 } 434 435 float audio_get_processed_frequency(uint8_t tone_index) { 436 if (tone_index >= active_tones) { 437 return 0.0f; 438 } 439 440 int8_t index = active_tones - tone_index - 1; 441 // new tones are stacked on top (= appended at the end), so the most recent/current is MAX-1 442 443 #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING 444 index = index - tone_multiplexing_index_shift; 445 if (index < 0) // wrap around 446 index += active_tones; 447 #endif 448 449 if (tones[index].pitch <= 0.0f) { 450 return 0.0f; 451 } 452 453 return voice_envelope(tones[index].pitch); 454 } 455 456 bool audio_update_state(void) { 457 if (!playing_note && !playing_melody) { 458 return false; 459 } 460 461 bool goto_next_note = false; 462 uint16_t current_time = timer_read(); 463 464 if (playing_melody) { 465 goto_next_note = timer_elapsed(last_timestamp) >= melody_current_note_duration; 466 if (goto_next_note) { 467 uint16_t delta = timer_elapsed(last_timestamp) - melody_current_note_duration; 468 last_timestamp = current_time; 469 uint16_t previous_note = current_note; 470 current_note++; 471 voices_timer = timer_read(); // reset to zero, for the effects added by voices.c 472 473 if (current_note >= notes_count) { 474 if (notes_repeat) { 475 current_note = 0; 476 } else { 477 audio_stop_all(); 478 return false; 479 } 480 } 481 482 if (!note_resting && (*notes_pointer)[previous_note][0] == (*notes_pointer)[current_note][0]) { 483 note_resting = true; 484 485 // special handling for successive notes of the same frequency: 486 // insert a short pause to separate them audibly 487 audio_play_note(0.0f, audio_duration_to_ms(2)); 488 current_note = previous_note; 489 melody_current_note_duration = audio_duration_to_ms(2); 490 491 } else { 492 note_resting = false; 493 494 // TODO: handle glissando here (or remember previous and current tone) 495 /* there would need to be a freq(here we are) -> freq(next note) 496 * and do slide/glissando in between problem here is to know which 497 * frequency on the stack relates to what other? e.g. a melody starts 498 * tones in a sequence, and stops expiring one, so the most recently 499 * stopped is the starting point for a glissando to the most recently started? 500 * how to detect and preserve this relation? 501 * and what about user input, chords, ...? 502 */ 503 504 // '- delta': Skip forward in the next note's length if we've over shot 505 // the last, so the overall length of the song is the same 506 uint16_t duration = audio_duration_to_ms((*notes_pointer)[current_note][1]); 507 508 // Skip forward past any completely missed notes 509 while (delta > duration && current_note < notes_count - 1) { 510 delta -= duration; 511 current_note++; 512 duration = audio_duration_to_ms((*notes_pointer)[current_note][1]); 513 } 514 515 if (delta < duration) { 516 duration -= delta; 517 } else { 518 // Only way to get here is if it is the last note and 519 // we have completely missed it. Play it for 1ms... 520 duration = 1; 521 } 522 523 audio_play_note((*notes_pointer)[current_note][0], duration); 524 melody_current_note_duration = duration; 525 } 526 } 527 } 528 529 if (playing_note) { 530 #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING 531 tone_multiplexing_index_shift = (int)(current_time / tone_multiplexing_rate) % MIN(AUDIO_MAX_SIMULTANEOUS_TONES, active_tones); 532 goto_next_note = true; 533 #endif 534 if (vibrato || glissando) { 535 // force update on each cycle, since vibrato shifts the frequency slightly 536 goto_next_note = true; 537 } 538 539 // housekeeping: stop notes that have no playtime left 540 for (int i = 0; i < active_tones; i++) { 541 if ((tones[i].duration != 0xffff) // indefinitely playing notes, started by 'audio_play_tone' 542 && (tones[i].duration != 0) // 'uninitialized' 543 ) { 544 if (timer_elapsed(tones[i].time_started) >= tones[i].duration) { 545 audio_stop_tone(tones[i].pitch); // also sets 'state_changed=true' 546 } 547 } 548 } 549 } 550 551 // state-changes have a higher priority, always triggering the hardware to update 552 if (state_changed) { 553 state_changed = false; 554 return true; 555 } 556 557 return goto_next_note; 558 } 559 560 // Tone-multiplexing functions 561 #ifdef AUDIO_ENABLE_TONE_MULTIPLEXING 562 void audio_set_tone_multiplexing_rate(uint16_t rate) { 563 tone_multiplexing_rate = rate; 564 } 565 void audio_enable_tone_multiplexing(void) { 566 tone_multiplexing_rate = AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT; 567 } 568 void audio_disable_tone_multiplexing(void) { 569 tone_multiplexing_rate = 0; 570 } 571 void audio_increase_tone_multiplexing_rate(uint16_t change) { 572 if ((0xffff - change) > tone_multiplexing_rate) { 573 tone_multiplexing_rate += change; 574 } 575 } 576 void audio_decrease_tone_multiplexing_rate(uint16_t change) { 577 if (change <= tone_multiplexing_rate) { 578 tone_multiplexing_rate -= change; 579 } 580 } 581 #endif 582 583 // Tempo functions 584 585 void audio_set_tempo(uint8_t tempo) { 586 if (tempo < 10) note_tempo = 10; 587 // else if (tempo > 250) 588 // note_tempo = 250; 589 else 590 note_tempo = tempo; 591 } 592 593 void audio_increase_tempo(uint8_t tempo_change) { 594 if (tempo_change > 255 - note_tempo) 595 note_tempo = 255; 596 else 597 note_tempo += tempo_change; 598 } 599 600 void audio_decrease_tempo(uint8_t tempo_change) { 601 if (tempo_change >= note_tempo - 10) 602 note_tempo = 10; 603 else 604 note_tempo -= tempo_change; 605 } 606 607 /** 608 * Converts from units of 1/64ths of a beat to milliseconds. 609 * 610 * Round-off error is at most 1 millisecond. 611 * 612 * Conversion will never overflow for duration_bpm <= 699, provided that 613 * note_tempo is at least 10. This is quite a long duration, over ten beats. 614 * 615 * Beware that for duration_bpm > 699, the result may overflow uint16_t range 616 * when duration_bpm is large compared to note_tempo: 617 * 618 * duration_bpm * 60 * 1000 / (64 * note_tempo) > UINT16_MAX 619 * 620 * duration_bpm > (2 * 65535 / 1875) * note_tempo 621 * = 69.904 * note_tempo. 622 */ 623 uint16_t audio_duration_to_ms(uint16_t duration_bpm) { 624 return ((uint32_t)duration_bpm * 1875) / ((uint_fast16_t)note_tempo * 2); 625 } 626 627 /** 628 * Converts from units of milliseconds to 1/64ths of a beat. 629 * 630 * Round-off error is at most 1/64th of a beat. 631 * 632 * This conversion never overflows: since duration_ms <= UINT16_MAX = 65535 633 * and note_tempo <= 255, the result is always in uint16_t range: 634 * 635 * duration_ms * 64 * note_tempo / 60 / 1000 636 * <= 65535 * 2 * 255 / 1875 637 * = 17825.52 638 * <= UINT16_MAX. 639 */ 640 uint16_t audio_ms_to_duration(uint16_t duration_ms) { 641 return ((uint32_t)duration_ms * 2 * note_tempo) / 1875; 642 } 643 644 __attribute__((weak)) void audio_on_user(void) {} 645 __attribute__((weak)) void audio_off_user(void) {}