When the loop-range is defined in BeatTime, the disk-reader encounters
rounding issues due to time-domain mismatches.
With a simple session fixed BPM at 120, 48kHz.
looping 1 bar exactly 2 sec at the start of the session:
```
Range::squish start: b0 end: b7680 squish: a113554560
Range::squish using modulo: b45 = a661500
Range::squish using modulo in TD: a5760
Range::squish using earlier(): a658560
```
The correct answer is a113554560 - 2 * 56448000 [SC/sec] = a658560
Calculating the modulo iteratively is not great, however usually
only one iteration is required.
This expands significantly the maximum number of Beats that can be represented, which is a good
thing in itself. It slightly speeds up some Beats::operator methods, and slightly slows down
::get_beats() and ::get_ticks().
One minor change in an API user was required, and several tweaks to the unit tests due to the
macros being used by cppunit creating possible type confusion.
Units test pass
When TempoMap::copy_points() is called, the new points are intended to belong
to the (nascent) new map. But the copy constructor for the points leaves the
_map member of a Point unchanged, and so the new points reference the old
map (forever!). ::copy_points() must reset each Point to reference the new map.
Refactored the object that has the _map member, so that we could limit access
to its ::set_map() method to TempoMap.
Because a bartime point IS-A tempo point and IS-A meter point, we cannot just delete the tempo
point passed into core_add_tempo() if the new point replaces an existing one. Ditto for meter.
So, leave that logic up to the caller
timecnt_t and timepos_t constructors with the initial argument as an int64_t
are assumed to be using samples. We need to use the explicit factory methods
instead.
This uses boost::multiprecision::int512_t when multiplying and dividing by the numerator
and denominator of a ratio_t. 128 bits would be sufficient but for some reason, the boost
docs show the 512 bit variant being very slightly faster.
This is a better solution than using a double, which although it will prevent overflow
has fairly limited resolution.
Even if we start at time T, if the tempo point before T is ramped, we need to
adjust it's omega value based on the beat time of the following tempo point. If
we don't do this, then using that tempo to compute ::superclock_at() for
subsequent points will be incorrect.
Note: there may be an ordering issue here with Tempo/Meter points. We might
need to pass over all tempo points first, then process meters etc. Something
like that.