summaryrefslogtreecommitdiff
path: root/quantum/audio
diff options
context:
space:
mode:
authorPascal Getreuer <50221757+getreuer@users.noreply.github.com>2023-07-07 08:47:16 -0600
committerGitHub <noreply@github.com>2023-07-08 00:47:16 +1000
commita8a87a0922a33d38ed80165ee62f9dc35bd08a3d (patch)
treeb590d46212c06e92f1683e08d9ebf12784eabd32 /quantum/audio
parente648b84da3db022ba308163f21c3cf8165c45e09 (diff)
[Core] Simplify audio_duration_to_ms() and audio_ms_to_duration(), reduce firmware size by a few bytes. (#21427)
Diffstat (limited to 'quantum/audio')
-rw-r--r--quantum/audio/audio.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c
index 2570ad9cd1..0300483a93 100644
--- a/quantum/audio/audio.c
+++ b/quantum/audio/audio.c
@@ -547,20 +547,39 @@ void audio_decrease_tempo(uint8_t tempo_change) {
547 note_tempo -= tempo_change; 547 note_tempo -= tempo_change;
548} 548}
549 549
550// TODO in the int-math version are some bugs; songs sometimes abruptly end - maybe an issue with the timer/system-tick wrapping around? 550/**
551 * Converts from units of 1/64ths of a beat to milliseconds.
552 *
553 * Round-off error is at most 1 millisecond.
554 *
555 * Conversion will never overflow for duration_bpm <= 699, provided that
556 * note_tempo is at least 10. This is quite a long duration, over ten beats.
557 *
558 * Beware that for duration_bpm > 699, the result may overflow uint16_t range
559 * when duration_bpm is large compared to note_tempo:
560 *
561 * duration_bpm * 60 * 1000 / (64 * note_tempo) > UINT16_MAX
562 *
563 * duration_bpm > (2 * 65535 / 1875) * note_tempo
564 * = 69.904 * note_tempo.
565 */
551uint16_t audio_duration_to_ms(uint16_t duration_bpm) { 566uint16_t audio_duration_to_ms(uint16_t duration_bpm) {
552#if defined(__AVR__) 567 return ((uint32_t)duration_bpm * 1875) / ((uint_fast16_t)note_tempo * 2);
553 // doing int-math saves us some bytes in the overall firmware size, but the intermediate result is less accurate before being cast to/returned as uint
554 return ((uint32_t)duration_bpm * 60 * 1000) / (64 * note_tempo);
555 // NOTE: beware of uint16_t overflows when note_tempo is low and/or the duration is long
556#else
557 return ((float)duration_bpm * 60) / (64 * note_tempo) * 1000;
558#endif
559} 568}
569
570/**
571 * Converts from units of milliseconds to 1/64ths of a beat.
572 *
573 * Round-off error is at most 1/64th of a beat.
574 *
575 * This conversion never overflows: since duration_ms <= UINT16_MAX = 65535
576 * and note_tempo <= 255, the result is always in uint16_t range:
577 *
578 * duration_ms * 64 * note_tempo / 60 / 1000
579 * <= 65535 * 2 * 255 / 1875
580 * = 17825.52
581 * <= UINT16_MAX.
582 */
560uint16_t audio_ms_to_duration(uint16_t duration_ms) { 583uint16_t audio_ms_to_duration(uint16_t duration_ms) {
561#if defined(__AVR__) 584 return ((uint32_t)duration_ms * 2 * note_tempo) / 1875;
562 return ((uint32_t)duration_ms * 64 * note_tempo) / 60 / 1000;
563#else
564 return ((float)duration_ms * 64 * note_tempo) / 60 / 1000;
565#endif
566} 585}