Fix div/zero, allow switching backends

When switching backends, the effective sample-rate is zero.
This only affects the butler thread (the only active thread when
stopped). The actual issue here is the butler calling
"non-realtime-stop" without a backend. However fixing 0/0
generally seems appropriate.
```
#0 in int_div_round<long>(long, long) (x=0, y=0) at ../libs/pbd/pbd/integer_division.h:36
#1 in Temporal::samples_to_superclock(int64_t, int) (samples=0, sr=0) at ../libs/temporal/temporal/superclock.h:39
#2 in Temporal::timepos_t::timepos_t(long) (this=0x7f94bc0a5890, s=0) at ../libs/temporal/temporal/timeline.h:55
#3 in ARDOUR::Automatable::non_realtime_locate(long) (this=0x55a12a980cc8, now=0) at ../libs/ardour/automatable.cc:421
#4 in ARDOUR::Route::non_realtime_locate(long) (this=0x55a12a980ae0, pos=0) at ../libs/ardour/route.cc:5462
#5 in ARDOUR::Session::non_realtime_stop(bool, int, bool&) (this=0x55a12e0cd000, abort=false, on_entry=1, finished=@0x7f94bc0a5e0f: true) at ../libs/ardour/session_transport.cc:1487
#6 in ARDOUR::Session::butler_transport_work(bool) (this=0x55a12e0cd000, have_process_lock=false) at ../libs/ardour/session_transport.cc:1153
#7 in ARDOUR::Butler::thread_work() (this=0x55a12f3b7000) at ../libs/ardour/butler.cc:222
#8 in ARDOUR::Butler::_thread_work(void*) (arg=0x55a12f3b7000) at ../libs/ardour/butler.cc:16
```
This commit is contained in:
Robin Gareus 2021-09-11 04:54:40 +02:00
parent a8092461f7
commit 1288262ca7
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 5 additions and 1 deletions

View File

@ -32,6 +32,10 @@
template<typename T>
T int_div_round (T x, T y)
{
if (y == 0) {
/* usually `y' is sample-rate, or beats/bar */
return (x == 0) ? 0 : 1;
}
/* essentially ((x + (y/2)) / y) but handles signed/negative values correcvtly */
return (x + PBD_IDIV_ROUNDING(x,y)) / y ;
}

View File

@ -35,7 +35,7 @@ typedef int64_t superclock_t;
static superclock_t superclock_ticks_per_second = 508032000; // 2^10 * 3^4 * 5^3 * 7^2
#endif
static inline superclock_t superclock_to_samples (superclock_t s, int sr) { return int_div_round (s * sr, superclock_ticks_per_second); }
static inline superclock_t superclock_to_samples (superclock_t s, int sr) { return sr == 0 ? 0 : int_div_round (s * sr, superclock_ticks_per_second); }
static inline superclock_t samples_to_superclock (int64_t samples, int sr) { return int_div_round (samples * superclock_ticks_per_second, superclock_t (sr)); }
extern int (*sample_rate_callback)();