diff options
| author | Pascal Getreuer <50221757+getreuer@users.noreply.github.com> | 2023-07-07 08:47:16 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-08 00:47:16 +1000 |
| commit | a8a87a0922a33d38ed80165ee62f9dc35bd08a3d (patch) | |
| tree | b590d46212c06e92f1683e08d9ebf12784eabd32 /quantum/audio | |
| parent | e648b84da3db022ba308163f21c3cf8165c45e09 (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.c | 45 |
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 | */ | ||
| 551 | uint16_t audio_duration_to_ms(uint16_t duration_bpm) { | 566 | uint16_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 | */ | ||
| 560 | uint16_t audio_ms_to_duration(uint16_t duration_ms) { | 583 | uint16_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 | } |
