mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
add new sample_aligned_superclock() method and use it when converting Beats to superclock
There can never be fractional audio time, and since superclock_t is used to represent audio time, when we convert from Beat time, we should never, ever return a superclock value that does not correspond to an integer number of samples. This fixes a number of bugs, including any use of ARDOUR::Filter which writes a new (audio) file to disk that must be an integer number of samples long, but may be derived from and later used by a region that had an audio-time duration that is slightly longer (less than one sample) than the audio file
This commit is contained in:
parent
99ba22a4a4
commit
12ed9899ee
2 changed files with 38 additions and 33 deletions
|
|
@ -513,49 +513,53 @@ TempoPoint::superclock_at (Temporal::Beats const & qn) const
|
||||||
TEMPO_MAP_ASSERT (qn >= _quarters);
|
TEMPO_MAP_ASSERT (qn >= _quarters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
superclock_t r;
|
||||||
|
|
||||||
if (!actually_ramped()) {
|
if (!actually_ramped()) {
|
||||||
/* not ramped, use linear */
|
/* not ramped, use linear */
|
||||||
const Beats delta = qn - _quarters;
|
const Beats delta = qn - _quarters;
|
||||||
const superclock_t spqn = superclocks_per_quarter_note ();
|
const superclock_t spqn = superclocks_per_quarter_note ();
|
||||||
return _sclock + (spqn * delta.get_beats()) + muldiv_round (spqn, delta.get_ticks(), superclock_t (Temporal::ticks_per_beat));
|
r = _sclock + (spqn * delta.get_beats()) + muldiv_round (spqn, delta.get_ticks(), superclock_t (Temporal::ticks_per_beat));
|
||||||
}
|
|
||||||
|
|
||||||
superclock_t r;
|
|
||||||
const double log_expr = superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double();
|
|
||||||
|
|
||||||
// std::cerr << "logexpr " << log_expr << " from " << superclocks_per_quarter_note() << " * " << _omega << " * " << (qn - _quarters) << std::endl;
|
|
||||||
|
|
||||||
if (log_expr < -1) {
|
|
||||||
|
|
||||||
r = _sclock + llrint (log (-log_expr - 1.0) / -_omega);
|
|
||||||
|
|
||||||
if (r < 0) {
|
|
||||||
std::cerr << "CASE 1: " << *this << endl << " scpqn = " << superclocks_per_quarter_note() << std::endl;
|
|
||||||
std::cerr << " for " << qn << " @ " << _quarters << " | " << _sclock << " + log (" << log_expr << ") "
|
|
||||||
<< log (-log_expr - 1.0)
|
|
||||||
<< " - omega = " << -_omega
|
|
||||||
<< " => "
|
|
||||||
<< r << std::endl;
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
r = _sclock + llrint (log1p (log_expr) / _omega);
|
|
||||||
|
|
||||||
// std::cerr << "r = " << _sclock << " + " << log1p (log_expr) / _omega << " => " << r << std::endl;
|
const double log_expr = superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double();
|
||||||
|
|
||||||
if (r < 0) {
|
// std::cerr << "logexpr " << log_expr << " from " << superclocks_per_quarter_note() << " * " << _omega << " * " << (qn - _quarters) << std::endl;
|
||||||
std::cerr << "CASE 2: scpqn = " << superclocks_per_quarter_note() << std::endl;
|
|
||||||
std::cerr << " for " << qn << " @ " << _quarters << " | " << _sclock << " + log1p (" << superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double() << " = "
|
if (log_expr < -1) {
|
||||||
<< log1p (superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double())
|
|
||||||
<< " => "
|
r = _sclock + llrint (log (-log_expr - 1.0) / -_omega);
|
||||||
<< r << std::endl;
|
|
||||||
_map->dump (std::cerr);
|
if (r < 0) {
|
||||||
abort ();
|
std::cerr << "CASE 1: " << *this << endl << " scpqn = " << superclocks_per_quarter_note() << std::endl;
|
||||||
|
std::cerr << " for " << qn << " @ " << _quarters << " | " << _sclock << " + log (" << log_expr << ") "
|
||||||
|
<< log (-log_expr - 1.0)
|
||||||
|
<< " - omega = " << -_omega
|
||||||
|
<< " => "
|
||||||
|
<< r << std::endl;
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
r = _sclock + llrint (log1p (log_expr) / _omega);
|
||||||
|
|
||||||
|
// std::cerr << "r = " << _sclock << " + " << log1p (log_expr) / _omega << " => " << r << std::endl;
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
std::cerr << "CASE 2: scpqn = " << superclocks_per_quarter_note() << std::endl;
|
||||||
|
std::cerr << " for " << qn << " @ " << _quarters << " | " << _sclock << " + log1p (" << superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double() << " = "
|
||||||
|
<< log1p (superclocks_per_quarter_note() * _omega * DoubleableBeats (qn - _quarters).to_double())
|
||||||
|
<< " => "
|
||||||
|
<< r << std::endl;
|
||||||
|
_map->dump (std::cerr);
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
/* Now round up to the nearest sample-equivalent superclock value */
|
||||||
|
|
||||||
|
return sample_aligned_superclock (r, TEMPORAL_SAMPLE_RATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
superclock_t
|
superclock_t
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ static inline superclock_t superclock_ticks_per_second() { return _superclock_ti
|
||||||
|
|
||||||
static inline superclock_t superclock_to_samples (superclock_t s, int sr) { return PBD::muldiv_floor (s, sr, superclock_ticks_per_second()); }
|
static inline superclock_t superclock_to_samples (superclock_t s, int sr) { return PBD::muldiv_floor (s, sr, superclock_ticks_per_second()); }
|
||||||
static inline superclock_t samples_to_superclock (int64_t samples, int sr) { return PBD::muldiv_round (samples, superclock_ticks_per_second(), superclock_t (sr)); }
|
static inline superclock_t samples_to_superclock (int64_t samples, int sr) { return PBD::muldiv_round (samples, superclock_ticks_per_second(), superclock_t (sr)); }
|
||||||
|
static inline superclock_t sample_aligned_superclock (superclock_t s, int sr) { return PBD::muldiv_floor (s, sr, sr); }
|
||||||
|
|
||||||
LIBTEMPORAL_API extern int most_recent_engine_sample_rate;
|
LIBTEMPORAL_API extern int most_recent_engine_sample_rate;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue