summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Emmas <johne53@tiscali.co.uk>2015-08-27 12:24:21 +0100
committerJohn Emmas <johne53@tiscali.co.uk>2015-08-27 12:28:45 +0100
commitada32733c5168dd6b57244e995eef35d0841b49a (patch)
tree9a0f84d8925e74a8035e4e37ce25a116fc110ea1
parent1963c3ff10c483bd8e3dec9cbd88cce54656b029 (diff)
Modify some functions to alleviate overflow / precision errors
'session_frame_to_track_frame()' and its complement, 'track_frame_to_session_frame()' both accept a double and an ARDOUR::framepost_t (int64_t). For convenience these both get converted to long double. However, the functions are often called with very large values (ARDOUR::max_framepos). When this happens, rounding and precision errors can cause overflow issues. This is an attempt to alleviate that problem. Not sure if it's strictly necessary to accommodate negative values - but I'm assuming these could happen if 'speed' was negative (reverse play?) This is the reason why 'Select All Objects' (and similar functionality) don't work for some users.
-rw-r--r--libs/ardour/ardour/types.h21
1 files changed, 19 insertions, 2 deletions
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 17e0b0d7e4..08fe0ef75b 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -713,13 +713,30 @@ LIBARDOUR_API std::ostream& operator<<(std::ostream& o, const ARDOUR::MeterLineU
static inline ARDOUR::framepos_t
session_frame_to_track_frame (ARDOUR::framepos_t session_frame, double speed)
{
- return (ARDOUR::framepos_t) ((long double) session_frame * (long double) speed);
+ long double result = (long double) session_frame * (long double) speed;
+
+ if (result >= (long double) ARDOUR::max_framepos) {
+ return ARDOUR::max_framepos;
+ } else if (result <= (long double) (ARDOUR::max_framepos) * (ARDOUR::framepos_t)(-1)) {
+ return (ARDOUR::max_framepos * (ARDOUR::framepos_t)(-1));
+ } else {
+ return result;
+ }
}
static inline ARDOUR::framepos_t
track_frame_to_session_frame (ARDOUR::framepos_t track_frame, double speed)
{
- return (ARDOUR::framepos_t) ((long double) track_frame / (long double) speed);
+ /* NB - do we need a check for speed == 0 ??? */
+ long double result = (long double) track_frame / (long double) speed;
+
+ if (result >= (long double) ARDOUR::max_framepos) {
+ return ARDOUR::max_framepos;
+ } else if (result <= (long double) (ARDOUR::max_framepos) * (ARDOUR::framepos_t)(-1)) {
+ return (ARDOUR::max_framepos * (ARDOUR::framepos_t)(-1));
+ } else {
+ return result;
+ }
}
/* for now, break the rules and use "using" to make this "global" */