13
0

libtemporal: fix Beats::round_to_subdivision()

This commit is contained in:
Paul Davis 2020-12-18 11:31:46 -07:00
parent 0fa56402be
commit 8c22ade428

View File

@ -16,9 +16,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "pbd/integer_division.h"
#include "temporal/beats.h"
#include "temporal/debug.h"
#include "temporal/tempo.h"
using namespace PBD;
using namespace Temporal;
Beats
@ -53,6 +57,8 @@ Beats::round_to_subdivision (int subdivision, RoundMode dir) const {
uint32_t mod = ticks % ticks_one_subdivisions_worth;
uint32_t beats = _beats;
DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("%4 => round-nearest, ticks %1 1 div of ticks %2 mod %3\n", ticks, ticks_one_subdivisions_worth, mod, *this));
if (dir > 0) {
if (mod == 0 && dir == RoundUpMaybe) {
@ -78,63 +84,35 @@ Beats::round_to_subdivision (int subdivision, RoundMode dir) const {
} else if (dir < 0) {
/* round to previous (or same iff dir == RoundDownMaybe) */
/* round to previous (or same iff di == RoundDownMaybe) */
uint32_t difference = ticks % ticks_one_subdivisions_worth;
if (difference == 0 && dir == RoundDownAlways) {
if (mod == 0 && dir == RoundDownAlways) {
/* right on the subdivision, but force-rounding down,
so the difference is just the subdivision ticks */
difference = ticks_one_subdivisions_worth;
so the modulo (difference) is just the subdivision
ticks
*/
mod = ticks_one_subdivisions_worth;
}
if (ticks < difference) {
if (ticks < mod) {
ticks = ticks_per_beat - ticks;
} else {
ticks -= difference;
ticks -= mod;
}
} else {
/* round to nearest */
double rem;
/* compute the distance to the previous and next subdivision */
/* round to nearest, which happens to be precisely what
* PBD::int_div_round() does. Set beats to zero, since the
* Beats normalization will set the values correctly in the
* value we actually return
*/
if ((rem = fmod ((double) ticks, (double) ticks_one_subdivisions_worth)) > ticks_one_subdivisions_worth/2.0) {
ticks = int_div_round (ticks, ticks_one_subdivisions_worth) * ticks_one_subdivisions_worth;
beats = 0;
/* closer to the next subdivision, so shift forward */
ticks = lrint (ticks + (ticks_one_subdivisions_worth - rem));
//DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("moved forward to %1\n", ticks));
if (ticks > ticks_per_beat) {
++beats;
ticks -= ticks_per_beat;
//DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("fold beat to %1\n", beats));
}
} else if (rem > 0) {
/* closer to previous subdivision, so shift backward */
if (rem > ticks) {
if (beats == 0) {
/* can't go backwards past zero, so ... */
return *this;
}
/* step back to previous beat */
--beats;
ticks = lrint (ticks_per_beat - rem);
//DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("step back beat to %1\n", beats));
} else {
ticks = lrint (ticks - rem);
//DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("moved backward to %1\n", ticks));
}
} else {
/* on the subdivision, do nothing */
}
}
return Beats::ticks (ticks);
DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("return %1 from %2 : %3\n", Beats (beats, ticks), beats, ticks));
return Beats (beats, ticks);
}