2#include <ossia/detail/flicks.hpp>
4#include <ossia/editor/scenario/time_signature.hpp>
12using quarter_note = double;
16 constexpr token_request() noexcept = default;
17 constexpr token_request(const token_request&) noexcept = default;
18 constexpr token_request(token_request&&) noexcept = default;
19 constexpr token_request& operator=(const token_request&) noexcept = default;
20 constexpr token_request& operator=(token_request&&) noexcept = default;
22 constexpr token_request(
23 ossia::time_value prev_d,
ossia::time_value d,
ossia::time_value parent_duration,
24 ossia::time_value off,
double s, time_signature sig,
double tempo) noexcept
27 , parent_duration{parent_duration}
39 [[nodiscard]]
constexpr token_request add_offset(
ossia::time_value t)
const noexcept
41 token_request other = *
this;
47 template <
typename Exec,
typename Transport>
50 Transport transport)
const noexcept
52 ossia::token_request other = *
this;
56 while(tick_amount > 0_tv)
58 const time_value cur_from{orig_from % loop_duration};
59 if(cur_from + tick_amount < loop_duration)
61 other.prev_date = cur_from + start_offset;
62 other.date = other.prev_date + tick_amount;
68 auto this_tick = loop_duration - cur_from;
70 tick_amount -= this_tick;
71 orig_from += this_tick;
72 other.prev_date = cur_from + start_offset;
73 other.date = other.prev_date + this_tick;
77 transport(start_offset);
78 other.offset += this_tick;
84 [[nodiscard]]
constexpr time_value model_read_duration() const noexcept
86 return date - prev_date;
92 [[nodiscard]]
constexpr physical_time
93 start_date_to_physical(
double ratio)
const noexcept
97 return this->prev_date.impl * ratio / speed;
101 [[nodiscard]]
constexpr physical_time physical_start(
double ratio)
const noexcept
105 return this->offset.impl * ratio / speed;
111 [[nodiscard]]
constexpr physical_time
112 physical_read_duration(
double ratio)
const noexcept
114 return constexpr_ceil(abs(date - prev_date).impl * ratio);
119 [[nodiscard]]
constexpr physical_time
120 physical_write_duration(
double ratio)
const noexcept
124 return constexpr_ceil(abs(date - prev_date).impl * ratio / speed);
128 [[nodiscard]]
constexpr physical_time
129 safe_physical_write_duration(
double ratio,
int bufferSize)
const noexcept
133 return constexpr_floor(bufferSize - offset.impl * ratio / speed);
137 [[nodiscard]]
constexpr bool in_range(
ossia::time_value global_time)
const noexcept
139 return global_time.impl >= prev_date.impl && global_time.impl < date.impl;
144 [[nodiscard]]
constexpr physical_time
145 to_physical_time_in_tick(
ossia::time_value global_time,
double ratio)
const noexcept
147 return (global_time - prev_date + offset).impl * ratio / speed;
152 [[nodiscard]]
constexpr physical_time
153 to_physical_time_in_tick(int64_t global_time,
double ratio)
const noexcept
160 [[nodiscard]]
constexpr time_value
161 from_physical_time_in_tick(ossia::physical_time phys_time,
double ratio)
const noexcept
164 constexpr_floor(phys_time * (speed / ratio) + prev_date.impl - offset.impl)};
169 [[nodiscard]]
constexpr double position() const noexcept
171 return parent_duration.impl > 0 ? date.impl / double(parent_duration.impl) : 0.;
175 [[nodiscard]]
constexpr bool forward() const noexcept {
return date > prev_date; }
178 [[nodiscard]]
constexpr bool paused() const noexcept {
return date == prev_date; }
181 [[nodiscard]]
constexpr bool backward() const noexcept {
return date < prev_date; }
186 [[nodiscard]]
constexpr std::optional<time_value>
187 get_quantification_date(
double rate)
const noexcept
189 std::optional<time_value> quantification_date;
194 const double musical_tick_duration = musical_end_position - musical_start_position;
195 if(musical_tick_duration <= 0.)
201 if(musical_end_last_bar != musical_start_last_bar)
204 const double musical_bar_duration
205 = musical_end_last_bar - musical_start_last_bar;
208 const double quantif_duration = musical_bar_duration / rate;
212 const double rem = std::fmod(
213 musical_end_last_bar - musical_start_last_signature, quantif_duration);
218 const double musical_bar_start = musical_end_last_bar - musical_start_position;
220 const double ratio = musical_bar_start / musical_tick_duration;
221 const time_value dt = date - prev_date;
223 quantification_date = prev_date + dt * ratio;
233 const double start_quarter = (musical_start_position - musical_start_last_bar);
234 const double end_quarter = (musical_end_position - musical_start_last_bar);
237 const double musical_quant_dur = rate / 4.;
238 const double start_quant = std::floor(start_quarter * musical_quant_dur);
239 const double end_quant = std::floor(end_quarter * musical_quant_dur);
241 if(start_quant != end_quant)
243 if(end_quant == end_quarter * musical_quant_dur)
249 const double musical_tick_duration
250 = musical_end_position - musical_start_position;
251 const double quantified_duration
252 = (musical_start_last_bar + (start_quant + 1) * 4. / rate)
253 - musical_start_position;
254 const double ratio = (date - prev_date).impl / musical_tick_duration;
256 quantification_date = prev_date + quantified_duration * ratio;
258 else if(start_quant == start_quarter * musical_quant_dur)
265 return quantification_date;
269 [[nodiscard]]
constexpr std::optional<physical_time>
270 get_physical_quantification_date(
double rate,
double modelToSamples)
const noexcept
272 if(
auto d = get_quantification_date(rate))
273 return to_physical_time_in_tick(*d, modelToSamples);
277 template <
typename Tick,
typename Tock>
279 metronome(
double modelToSamplesRatio, Tick tick, Tock tock)
const noexcept
281 if((musical_end_last_bar != musical_start_last_bar) || musical_start_position == 0.)
284 const double musical_tick_duration = musical_end_position - musical_start_position;
285 if(musical_tick_duration != 0)
287 const double musical_bar_start = musical_end_last_bar - musical_start_position;
288 const int64_t samples_tick_duration
289 = physical_write_duration(modelToSamplesRatio);
290 if(samples_tick_duration > 0)
292 const double ratio = musical_bar_start / musical_tick_duration;
293 const int64_t hi_start_sample = samples_tick_duration * ratio;
294 tick(hi_start_sample);
300 const int64_t start_quarter
301 = std::floor(musical_start_position - musical_start_last_bar);
302 const int64_t end_quarter
303 = std::floor(musical_end_position - musical_start_last_bar);
304 if(start_quarter != end_quarter)
309 const double musical_tick_duration
310 = musical_end_position - musical_start_position;
311 if(musical_tick_duration != 0)
313 const double musical_bar_start
314 = (end_quarter + musical_start_last_bar) - musical_start_position;
315 const int64_t samples_tick_duration
316 = physical_write_duration(modelToSamplesRatio);
317 if(samples_tick_duration > 0)
319 const double ratio = musical_bar_start / musical_tick_duration;
320 const int64_t lo_start_sample = samples_tick_duration * ratio;
321 tock(lo_start_sample);
328 [[nodiscard]]
constexpr bool unexpected_bar_change() const noexcept
330 double bar_difference = musical_end_last_bar - musical_start_last_bar;
331 if(bar_difference != 0.)
339 double quarters_sig = 4. * double(signature.upper) / signature.lower;
340 double div = bar_difference / quarters_sig;
341 bool unexpected = div - int64_t(div) > 0.000001;
347 constexpr void set_end_time(time_value t)
noexcept
350 const auto old_date = date;
353 if(old_date.impl > 0)
355 double ratio = t.impl / double(old_date.impl);
356 musical_end_position *= ratio;
362 constexpr void set_start_time(time_value t)
noexcept
365 const auto old_date = prev_date;
368 if(old_date.impl > 0)
370 double ratio = t.impl / double(old_date.impl);
371 musical_start_position *= ratio;
398 double tempo{ossia::root_tempo};
399 time_signature signature{};
401 ossia::quarter_note musical_start_last_signature{};
404 ossia::quarter_note musical_start_last_bar{};
406 ossia::quarter_note musical_start_position{};
407 ossia::quarter_note musical_end_last_bar{};
409 ossia::quarter_note musical_end_position{};
410 bool start_discontinuous{};
411 bool end_discontinuous{};
414inline bool operator==(
const token_request& lhs,
const token_request& rhs)
416 return lhs.prev_date == rhs.prev_date && lhs.date == rhs.date
417 && lhs.parent_duration == rhs.parent_duration && lhs.offset == rhs.offset
418 && lhs.speed == rhs.speed && lhs.tempo == rhs.tempo
419 && lhs.signature == rhs.signature
420 && lhs.musical_start_last_bar == rhs.musical_start_last_bar
421 && lhs.musical_start_position == rhs.musical_start_position
422 && lhs.musical_end_last_bar == rhs.musical_end_last_bar
423 && lhs.musical_end_position == rhs.musical_end_position
424 && lhs.start_discontinuous == rhs.start_discontinuous
425 && lhs.end_discontinuous == rhs.end_discontinuous;
428inline bool operator!=(
const token_request& lhs,
const token_request& rhs)
430 return !(lhs == rhs);
434struct simple_token_request
436 time_value prev_date{};
438 time_value parent_duration{};
441 operator token_request() const noexcept
443 return ossia::token_request{prev_date, date, parent_duration, offset, 1.0,
447 friend bool operator==(
const token_request& lhs,
const simple_token_request& self)
449 return lhs.prev_date == self.prev_date && lhs.date == self.date
450 && lhs.offset == self.offset;
452 friend bool operator==(
const simple_token_request& self,
const token_request& rhs)
456 friend bool operator!=(
const token_request& lhs,
const simple_token_request& self)
458 return !(lhs == self);
460 friend bool operator!=(
const simple_token_request& self,
const token_request& rhs)
462 return !(rhs == self);
The time_value class.
Definition ossia/editor/scenario/time_value.hpp:30