remove (almost) all floating point operations from Beats, add DoubleableBeats
The latter is a "wrapper" around Beats that provides ::to_double() for those times when we absolutely need a floating point representation
This commit is contained in:
parent
3010bed4ef
commit
3e8f4d80fb
@ -422,9 +422,9 @@ TempoPoint::compute_omega (samplecnt_t sr, superclock_t end_scpqn, Temporal::Bea
|
||||
return;
|
||||
}
|
||||
|
||||
_omega = ((1.0/end_scpqn) - (1.0/superclocks_per_quarter_note())) / quarter_duration.to_double();
|
||||
_omega = ((1.0/end_scpqn) - (1.0/superclocks_per_quarter_note())) / DoubleableBeats (quarter_duration).to_double();
|
||||
|
||||
DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("computed omega = %1%2 dur was %3\n", std::setprecision(12),_omega, quarter_duration.to_double()));
|
||||
DEBUG_TRACE (DEBUG::TemporalMap, string_compose ("computed omega = %1%2 dur was %3\n", std::setprecision(12),_omega, DoubleableBeats (quarter_duration).to_double()));
|
||||
}
|
||||
|
||||
superclock_t
|
||||
@ -440,7 +440,7 @@ TempoPoint::superclock_at (Temporal::Beats const & qn) const
|
||||
return (spqn * qn.get_beats()) + int_div_round ((spqn * qn.get_ticks()), superclock_t (Temporal::ticks_per_beat));
|
||||
}
|
||||
|
||||
return _sclock + llrint (log1p (superclocks_per_quarter_note() * _omega * (qn - _quarters).to_double()) / _omega);
|
||||
return _sclock + llrint (log1p (superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double()) / _omega);
|
||||
}
|
||||
|
||||
superclock_t
|
||||
|
@ -157,6 +157,10 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
Beats snap_to (Temporal::Beats const & snap) const {
|
||||
return (*this / snap) * snap;
|
||||
}
|
||||
|
||||
Beats round_to_beat() const {
|
||||
return (_ticks >= (PPQN/2)) ? Beats (_beats + 1, 0) : Beats (_beats, 0);
|
||||
}
|
||||
@ -182,11 +186,6 @@ public:
|
||||
|
||||
Beats round_to_subdivision (int subdivision, RoundMode dir) const;
|
||||
|
||||
Beats snap_to (Temporal::Beats const & snap) const {
|
||||
const double snap_time = snap.to_double();
|
||||
return Beats::from_double (ceil(to_double() / snap_time) * snap_time);
|
||||
}
|
||||
|
||||
Beats abs () const {
|
||||
return Beats (::abs (_beats), ::abs (_ticks));
|
||||
}
|
||||
@ -202,11 +201,6 @@ public:
|
||||
return _beats == b._beats && _ticks == b._ticks;
|
||||
}
|
||||
|
||||
inline bool operator==(double t) const {
|
||||
/* Acceptable tolerance is 1 tick. */
|
||||
return fabs(to_double() - t) <= (1.0 / PPQN);
|
||||
}
|
||||
|
||||
inline bool operator==(int beats) const {
|
||||
return _beats == beats;
|
||||
}
|
||||
@ -231,34 +225,6 @@ public:
|
||||
return _beats > b._beats || (_beats == b._beats && _ticks >= b._ticks);
|
||||
}
|
||||
|
||||
inline bool operator<(double b) const {
|
||||
/* Acceptable tolerance is 1 tick. */
|
||||
const double time = to_double();
|
||||
if (fabs(time - b) <= (1.0 / PPQN)) {
|
||||
return false; /* Effectively identical. */
|
||||
} else {
|
||||
return time < b;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator<=(double b) const {
|
||||
return operator==(b) || operator<(b);
|
||||
}
|
||||
|
||||
inline bool operator>(double b) const {
|
||||
/* Acceptable tolerance is 1 tick. */
|
||||
const double time = to_double();
|
||||
if (fabs(time - b) <= (1.0 / PPQN)) {
|
||||
return false; /* Effectively identical. */
|
||||
} else {
|
||||
return time > b;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator>=(double b) const {
|
||||
return operator==(b) || operator>(b);
|
||||
}
|
||||
|
||||
Beats operator+(const Beats& b) const {
|
||||
return Beats(_beats + b._beats, _ticks + b._ticks);
|
||||
}
|
||||
@ -267,32 +233,6 @@ public:
|
||||
return Beats(_beats - b._beats, _ticks - b._ticks);
|
||||
}
|
||||
|
||||
Beats operator+(double d) const {
|
||||
return Beats(to_double() + d);
|
||||
}
|
||||
|
||||
Beats operator-(double d) const {
|
||||
return Beats(to_double() - d);
|
||||
}
|
||||
|
||||
Beats operator+(int b) const {
|
||||
return Beats (_beats + b, _ticks);
|
||||
}
|
||||
|
||||
Beats operator-(int b) const {
|
||||
return Beats (_beats - b, _ticks);
|
||||
}
|
||||
|
||||
Beats& operator+=(int b) {
|
||||
_beats += b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Beats& operator-=(int b) {
|
||||
_beats -= b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Beats operator-() const {
|
||||
/* must avoid normalization here, which will convert a negative
|
||||
value into a valid beat position before zero, which is not
|
||||
@ -317,10 +257,12 @@ public:
|
||||
_ticks = B._ticks;
|
||||
return *this;
|
||||
|
||||
/* avoids calling ::to_double() to compute ratios of two Beat distances
|
||||
*/
|
||||
double operator/ (Beats const & other) {
|
||||
return (double) to_ticks() / (double) other.to_ticks();
|
||||
Beats operator/ (Beats const & other) const {
|
||||
return Beats::ticks (int_div_round (to_ticks(), other.to_ticks()));
|
||||
}
|
||||
|
||||
Beats operator* (Beats const & other) const {
|
||||
return Beats::ticks (to_ticks () * other.to_ticks());
|
||||
}
|
||||
|
||||
Beats& operator+=(const Beats& b) {
|
||||
@ -342,25 +284,10 @@ public:
|
||||
|
||||
static Beats one_tick() { return Beats(0, 1); }
|
||||
|
||||
private:
|
||||
protected:
|
||||
int32_t _beats;
|
||||
int32_t _ticks;
|
||||
|
||||
/* almost nobody should ever be allowed to use this method */
|
||||
friend class TempoPoint;
|
||||
friend class ARDOUR::Track;
|
||||
friend class ARDOUR::Variant;
|
||||
friend class ARDOUR::MidiStretch;
|
||||
friend class ARDOUR::MidiModel;
|
||||
friend class ARDOUR::AutomationList;
|
||||
friend class ARDOUR::MidiSource;
|
||||
friend class ARDOUR::MidiRegion;
|
||||
friend class ARDOUR::Quantize;
|
||||
friend class ::QuantizeDialog;
|
||||
friend class ::NoteDrag;
|
||||
friend class ::NoteCreateDrag;
|
||||
double to_double() const { return (double)_beats + (_ticks / (double)PPQN); }
|
||||
|
||||
/* this needs to exist because Evoral::Sequence is templated, and some
|
||||
* other possible template types cannot provide ::from_double
|
||||
*/
|
||||
@ -375,6 +302,17 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
/* Only contexts that really, absolutely need a floating point representation
|
||||
* of a Beats value should ever use this.
|
||||
*/
|
||||
|
||||
class DoubleableBeats : public Beats
|
||||
{
|
||||
public:
|
||||
DoubleableBeats (Beats const & b) : Beats (b) {}
|
||||
double to_double() const { return (double)_beats + (_ticks / (double)PPQN); }
|
||||
};
|
||||
|
||||
/*
|
||||
TIL, several horrible hours later, that sometimes the compiler looks in the
|
||||
namespace of a type (Temporal::Beats in this case) for an operator, and
|
||||
|
Loading…
Reference in New Issue
Block a user