63 constexpr explicit operator bool() const noexcept {
78constexpr EventCompensationResult
80 int ceiling_samples)
noexcept {
82 if (ceiling_samples < 0) {
84 result.
limit = ceiling_samples;
87 const auto limit =
static_cast<std::int64_t
>(ceiling_samples);
89 std::int64_t total = 0;
90 for (std::size_t index = 0; index < device_latency_samples.size(); ++index) {
91 const auto latency =
static_cast<std::int64_t
>(device_latency_samples[index]);
98 if (latency > limit) {
101 result.
index = index;
110 result.
index = index;
114 result.
shift = {total};
128 constexpr auto maximum = std::numeric_limits<std::int64_t>::max();
129 constexpr auto minimum = std::numeric_limits<std::int64_t>::min();
130 const auto origin = range.timeline_sample_start.value;
131 if (shift.samples > 0 && origin > maximum - shift.samples)
133 if (shift.samples < 0 && origin < minimum - shift.samples)
135 return {origin + shift.samples};
147 return !shift.compensating() || !range.host_beat_mapping;
162 if (!shift.compensating())
165 const auto frames =
static_cast<std::int64_t
>(range.frame_count);
166 return origin.value <= loop_end_samples.value - frames;
223constexpr CompensatedReadPlan
229 const auto length = loop_end_samples.value - loop_start_samples.value;
232 const auto span =
static_cast<std::uint64_t
>(length);
233 std::uint64_t pass_offset = 0;
234 if (start.value >= loop_end_samples.value) {
235 const auto past =
static_cast<std::uint64_t
>(start.value - loop_start_samples.value);
236 pass_offset = past / span;
237 start = {loop_start_samples.value +
static_cast<std::int64_t
>(past % span)};
239 auto head = range.frame_count;
240 if (start.value < loop_end_samples.value) {
241 const auto until_wrap =
static_cast<std::uint64_t
>(loop_end_samples.value - start.value);
242 if (until_wrap < head)
243 head =
static_cast<std::uint32_t
>(until_wrap);
245 plan.
segments[0] = {start, head, 0, pass_offset};
247 if (head < range.frame_count) {
248 plan.
segments[1] = {loop_start_samples, range.frame_count - head, head, pass_offset + 1};
Definition audio_renderer.hpp:20
constexpr bool loop_admits_event_compensation(const TransportRange &range, EventCompensationShift shift, timebase::SamplePosition loop_end_samples) noexcept
Whether a compensating shift's read-ahead stays inside an enabled loop.
Definition event_compensation.hpp:159
constexpr CompensatedReadPlan plan_compensated_read(const TransportRange &range, EventCompensationShift shift) noexcept
The one run a window that no loop bounds resolves to.
Definition event_compensation.hpp:207
constexpr timebase::SamplePosition shifted_range_origin(const TransportRange &range, EventCompensationShift shift) noexcept
The sample position an event stream at a compensated injection point must be read from for range.
Definition event_compensation.hpp:126
@ ExternalInput
Definition program.hpp:46
@ Ok
Definition automation_cursor.hpp:29
constexpr EventCompensationResult accumulate_event_chain_shift(std::span< const int > device_latency_samples, int ceiling_samples) noexcept
Accumulates the event-domain latency of one chain into a scheduling shift.
Definition event_compensation.hpp:79
EventCompensationCode
Definition event_compensation.hpp:42
@ ChainShiftOutOfRange
The accumulated chain shift exceeds the ceiling the caller supplied.
Definition event_compensation.hpp:50
@ NegativeDeviceLatency
A device reported a negative latency.
Definition event_compensation.hpp:46
@ DeviceLatencyOutOfRange
A device's own reported latency exceeds the ceiling the caller supplied.
Definition event_compensation.hpp:48
@ Ok
Definition event_compensation.hpp:43
constexpr bool range_admits_event_compensation(const TransportRange &range, EventCompensationShift shift) noexcept
Whether a compensating shift has a defined meaning for range.
Definition event_compensation.hpp:145
constexpr bool event_compensation_admits_live_input(EventCompensationShift shift, ProviderSelectorProgram provider) noexcept
Whether a track may offer live input while its event chain is compensated.
Definition event_compensation.hpp:265
How a compensated read window resolves against an enabled loop.
Definition event_compensation.hpp:194
std::uint8_t segment_count
Definition event_compensation.hpp:196
std::array< CompensatedReadSegment, 2 > segments
Definition event_compensation.hpp:195
bool wraps_inside_range
True when the loop point falls INSIDE this window.
Definition event_compensation.hpp:201
One contiguous run of a compensated read window after an enabled loop has been applied to it.
Definition event_compensation.hpp:171
std::uint64_t pass_offset
Loop passes between range.loop_pass_index and the pass this run reads.
Definition event_compensation.hpp:182
timebase::SamplePosition document_start
Document sample the run reads the program from.
Definition event_compensation.hpp:173
std::uint32_t frame_count
Length of the run, in frames.
Definition event_compensation.hpp:175
std::uint32_t range_offset
Where the run starts inside its TransportRange.
Definition event_compensation.hpp:178
Definition event_compensation.hpp:53
std::size_t index
Index into the supplied latencies for a per-device failure.
Definition event_compensation.hpp:61
std::int64_t limit
Definition event_compensation.hpp:59
std::int64_t actual
The offending value and the ceiling that rejected it, so a caller can report the exact number rather ...
Definition event_compensation.hpp:58
EventCompensationShift shift
Definition event_compensation.hpp:55
EventCompensationCode code
Definition event_compensation.hpp:54
One event-injection point's prepared scheduling shift, counted in samples at the program's compiled s...
Definition event_compensation.hpp:33
std::int64_t samples
Definition event_compensation.hpp:34
constexpr bool operator==(const EventCompensationShift &) const noexcept=default
constexpr bool compensating() const noexcept
Definition event_compensation.hpp:36
Definition program.hpp:48
Definition transport.hpp:45
Definition rational_time.hpp:9