43 friend class TempoMapWrapper;
70 constexpr auto quarters_per_bar ()
const
75 constexpr auto ticks_per_bar ()
const
80 constexpr auto ticks_per_beat ()
const
86 is_different_time_signature (
const TimeSignatureEvent &other)
const
91 NLOHMANN_DEFINE_TYPE_INTRUSIVE (
116 : sample_rate_ (sampleRate)
123 sample_rate_ = sampleRate;
140 throw std::invalid_argument (
"BPM must be positive");
141 if (tick < units::ticks (0))
142 throw std::invalid_argument (
"Tick must be non-negative");
145 if (events_.empty () && tick != units::ticks (0))
147 events_.push_back (default_tempo_);
151 auto it = std::ranges::find (events_, tick, [] (
const TempoEvent &e) {
154 if (it != events_.end ())
159 events_.push_back ({ tick, bpm, curve });
160 rebuild_cumulative_times ();
166 if (events_.size () > 1 && tick == units::ticks (0))
167 throw std::invalid_argument (
168 "Cannot remove first tempo event - remove other tempo event first");
170 auto it = std::ranges::find (events_, tick, [] (
const TempoEvent &e) {
173 if (it != events_.end ())
176 rebuild_cumulative_times ();
197 if (tick < units::ticks (0))
198 throw std::invalid_argument (
"Tick must be non-negative");
199 if (numerator <= 0 || denominator <= 0)
200 throw std::invalid_argument (
"Invalid time signature");
201 if (!events_.empty ())
202 throw std::logic_error (
203 "Time signature events must be added before tempo events");
206 if (time_sig_events_.empty () && tick != units::ticks (0))
208 time_sig_events_.push_back (default_time_sig_);
212 auto it = std::ranges::find (
213 time_sig_events_, tick,
214 [] (
const TimeSignatureEvent &e) {
return e.tick; });
215 if (it != time_sig_events_.end ())
217 time_sig_events_.erase (it);
220 time_sig_events_.push_back ({ tick, numerator, denominator });
227 if (time_sig_events_.size () > 1 && tick == units::ticks (0))
228 throw std::invalid_argument (
229 "Cannot remove time signature event at tick 0 - remove other events first");
231 auto it = std::ranges::find (
232 time_sig_events_, tick,
233 [] (
const TimeSignatureEvent &e) {
return e.tick; });
234 if (it != time_sig_events_.end ())
236 time_sig_events_.erase (it);
244 const auto &[events, cumulative_seconds] = get_events_or_default ();
249 if (it == events.begin ())
251 return units::seconds (0.0);
254 size_t index = std::distance (events.begin (), it) - 1;
255 const auto &startEvent = events[index];
256 const units::tick_t segmentStart = startEvent.tick;
257 const auto ticksFromStart =
258 tick -
static_cast<units::precise_tick_t
> (segmentStart);
259 const auto baseSeconds = cumulative_seconds[index];
262 if (index == events.size () - 1)
266 (ticksFromStart.in (units::ticks)
267 /
static_cast<double> (
get_ppq ()))
268 * (60.0 / startEvent.bpm));
271 const auto &endEvent = events[index + 1];
272 const units::tick_t segmentTicks = endEvent.tick - segmentStart;
273 const auto dSegmentTicks =
static_cast<units::precise_tick_t
> (segmentTicks);
280 (ticksFromStart.in (units::ticks)
281 /
static_cast<double> (
get_ppq ()))
282 * (60.0 / startEvent.bpm));
287 const double bpm0 = startEvent.bpm;
288 const double bpm1 = endEvent.bpm;
290 if (std::abs (bpm1 - bpm0) < 1e-5)
294 (ticksFromStart.in (units::ticks)
295 /
static_cast<double> (
get_ppq ()))
299 const auto fraction = ticksFromStart / dSegmentTicks;
300 const double currentBpm = bpm0 + (fraction * (bpm1 - bpm0));
304 (60.0 * dSegmentTicks.in (units::ticks))
305 / (
get_ppq () * (bpm1 - bpm0)) * std::log (currentBpm / bpm0));
317 units::sample_t tick_to_samples_rounded (units::precise_tick_t tick)
const
325 if (seconds <= units::seconds (0.0))
326 return units::ticks (0.0);
328 const auto &[events, cumulative_seconds] = get_events_or_default ();
331 auto it = std::ranges::upper_bound (cumulative_seconds, seconds);
333 (it == cumulative_seconds.begin ())
335 : std::distance (cumulative_seconds.begin (), it) - 1;
337 const auto baseSeconds = cumulative_seconds[index];
338 const auto timeInSegment = seconds - baseSeconds;
339 const TempoEvent &startEvent = events[index];
342 if (index == events.size () - 1)
345 timeInSegment.in (units::seconds) * (startEvent.bpm / 60.0);
346 return static_cast<units::precise_tick_t
> (startEvent.tick)
347 + units::ticks (beats *
get_ppq ());
350 const TempoEvent &endEvent = events[index + 1];
351 const units::tick_t segmentTicks = endEvent.tick - startEvent.tick;
352 const auto dSegmentTicks =
static_cast<units::precise_tick_t
> (segmentTicks);
358 timeInSegment.in (units::seconds) * (startEvent.bpm / 60.0);
359 return static_cast<units::precise_tick_t
> (startEvent.tick)
360 + units::ticks (beats *
get_ppq ());
365 const double bpm0 = startEvent.bpm;
366 const double bpm1 = endEvent.bpm;
368 if (std::abs (bpm1 - bpm0) < 1e-5)
371 timeInSegment.in (units::seconds) * (bpm0 / 60.0);
372 return static_cast<units::precise_tick_t
> (startEvent.tick)
373 + units::ticks (beats *
get_ppq ());
378 / (60.0 * dSegmentTicks.in (units::ticks));
379 const double expVal = std::exp (A * timeInSegment.in (units::seconds));
380 const double f = (expVal - 1.0) * (bpm0 / (bpm1 - bpm0));
382 return static_cast<units::precise_tick_t
> (startEvent.tick)
386 return static_cast<units::precise_tick_t
> (startEvent.tick);
392 const auto seconds = samples / sample_rate_;
403 if (time_sig_events_.empty ())
404 return default_time_sig_;
407 auto it = std::ranges::upper_bound (
409 if (it == time_sig_events_.begin ())
412 return default_time_sig_;
426 if (events_.empty ())
427 return default_tempo_.bpm;
431 if (it == events_.begin ())
434 return default_tempo_.bpm;
445 const auto &startEvent = *it;
446 const auto &endEvent = *(it + 1);
447 const units::tick_t segmentTicks = endEvent.tick - startEvent.tick;
448 const double fraction =
449 static_cast<units::precise_tick_t
> (tick - startEvent.tick)
450 /
static_cast<units::precise_tick_t
> (segmentTicks);
451 const double currentBpm =
452 startEvent.bpm + fraction * (endEvent.bpm - startEvent.bpm);
464 const auto &time_sig_events = get_time_signature_events_or_default ();
466 if (time_sig_events.empty ())
467 return { 1, 1, 1, 0 };
470 auto it = std::ranges::upper_bound (
472 if (it == time_sig_events.begin ())
474 it = time_sig_events.end ();
481 if (it == time_sig_events.end ())
483 return { 1, 1, 1, 0 };
486 const auto &sigEvent = *it;
487 const int numerator = sigEvent.numerator;
488 const int denominator = sigEvent.denominator;
491 const double quarters_per_bar = numerator * (4.0 / denominator);
492 const int64_t ticks_per_bar =
493 static_cast<int64_t
> (quarters_per_bar *
get_ppq ());
494 const int64_t ticks_per_beat = ticks_per_bar / numerator;
497 int64_t cumulative_bars = 1;
501 for (
auto prev = time_sig_events.begin (); prev != it; ++prev)
503 const int prev_numerator = prev->numerator;
504 const int prev_denominator = prev->denominator;
505 const double prev_quarters_per_bar =
506 prev_numerator * (4.0 / prev_denominator);
507 const int64_t prev_ticks_per_bar =
508 static_cast<int64_t
> (prev_quarters_per_bar *
get_ppq ());
511 auto next = std::next (prev);
512 const auto end_tick =
513 (next != time_sig_events.end ()) ? next->tick : sigEvent.tick;
514 const auto segment_ticks = end_tick - prev->tick;
517 (segment_ticks / prev_ticks_per_bar).in (units::ticks);
522 const auto ticks_since_sig = tick - sigEvent.tick;
523 const int64_t bars_since_sig =
524 ticks_since_sig.in (units::ticks) / ticks_per_bar;
525 const auto bar = cumulative_bars + bars_since_sig;
528 const int64_t ticks_in_bar =
529 ticks_since_sig.in (units::ticks) % ticks_per_bar;
530 const auto beat = 1 + (ticks_in_bar / ticks_per_beat);
533 const int64_t ticks_in_beat = ticks_in_bar % ticks_per_beat;
534 const auto sixteenth =
535 1 + (ticks_in_beat / ticks_per_sixteenth_.in (units::ticks));
536 const auto tick_in_sixteenth =
537 (ticks_in_beat % ticks_per_sixteenth_.in (units::ticks));
540 static_cast<int> (bar),
static_cast<int> (beat),
541 static_cast<int> (sixteenth),
static_cast<int> (tick_in_sixteenth)
545 MusicalPosition samples_to_musical_position (units::sample_t samples)
const
549 const auto tick = au::floor_as<int64_t> (
564 const auto &time_sig_events = get_time_signature_events_or_default ();
567 if (pos.bar < 1 || pos.beat < 1 || pos.sixteenth < 1 || pos.tick < 0)
569 throw std::invalid_argument (
"Invalid musical position");
572 auto cumulative_ticks = units::ticks (0);
576 for (
size_t i = 0; i < time_sig_events.size (); ++i)
578 const auto &
event = time_sig_events[i];
579 const int numerator =
event.numerator;
580 const int denominator =
event.denominator;
581 const double quarters_per_bar = numerator * (4.0 / denominator);
582 const int64_t ticks_per_bar =
583 static_cast<int64_t
> (quarters_per_bar *
get_ppq ());
586 auto bars_in_this_sig = units::ticks (0);
587 if (i < time_sig_events.size () - 1)
589 const units::tick_t next_tick = time_sig_events[i + 1].tick;
590 bars_in_this_sig = (next_tick -
event.tick) / ticks_per_bar;
594 bars_in_this_sig = units::ticks (pos.bar - current_bar + 1);
598 if (pos.bar < current_bar + bars_in_this_sig.in (units::ticks))
600 const int bar_in_seg = pos.bar - current_bar;
601 const auto bar_ticks =
602 event.tick + units::ticks (bar_in_seg * ticks_per_bar);
603 const int64_t ticks_per_beat = ticks_per_bar / numerator;
608 static_cast<int64_t
> (pos.beat - 1) * ticks_per_beat)
610 static_cast<int64_t
> (pos.sixteenth - 1)
611 * ticks_per_sixteenth_.in (units::ticks))
612 + units::ticks (pos.tick);
616 cumulative_ticks += bars_in_this_sig * ticks_per_bar;
617 current_bar += bars_in_this_sig.in (units::ticks);
620 return cumulative_ticks;
624 static consteval int get_ppq () {
return from_nttp (PPQ).in (units::ticks); }
629 return sample_rate_.in (units::sample_rate);
632 void set_default_bpm (
double bpm) { default_tempo_.
bpm = bpm; }
633 void set_default_time_signature (
int numerator,
int denominator)
635 default_tempo_.numerator = numerator;
636 default_tempo_.denominator = denominator;
641 const std::vector<TempoEvent> &get_tempo_events ()
const {
return events_; }
644 const std::vector<TimeSignatureEvent> &get_time_signature_events ()
const
646 return time_sig_events_;
650 void rebuild_cumulative_times ()
652 if (events_.empty ())
658 cumulative_seconds_.resize (events_.size ());
659 cumulative_seconds_[0] = units::seconds (0.0);
662 for (
size_t i = 0; i < events_.size () - 1; ++i)
664 const units::tick_t segmentTicks = events_[i + 1].tick - events_[i].tick;
665 cumulative_seconds_[i + 1] =
666 cumulative_seconds_[i]
667 + compute_segment_time (events_[i], events_[i + 1], segmentTicks);
672 units::precise_second_t compute_segment_time (
675 units::tick_t segmentTicks)
const
679 return units::seconds (
680 (
static_cast<units::precise_tick_t
> (segmentTicks).in (units::ticks)
681 /
static_cast<double> (
get_ppq ()))
682 * (60.0 / start.bpm));
686 const double bpm0 = start.bpm;
687 const double bpm1 = end.bpm;
689 if (std::abs (bpm1 - bpm0) < 1e-5)
691 return units::seconds (
692 (
static_cast<units::precise_tick_t
> (segmentTicks).in (units::ticks)
693 /
static_cast<double> (
get_ppq ()))
697 return units::seconds (
699 *
static_cast<units::precise_tick_t
> (segmentTicks).in (units::ticks))
700 / (
get_ppq () * (bpm1 - bpm0)) * std::log (bpm1 / bpm0));
702 return units::seconds (0.0);
705 auto get_events_or_default ()
const
707 if (events_.empty ())
709 return std::make_pair (
710 std::span{ &default_tempo_, 1 },
711 std::span{ &DEFAULT_CUMULATIVE_SECONDS, 1 });
714 return std::make_pair (
715 std::span{ events_.data (), events_.size () },
716 std::span{ cumulative_seconds_.data (), cumulative_seconds_.size () });
718 auto get_time_signature_events_or_default ()
const
720 if (time_sig_events_.empty ())
722 return std::span{ &default_time_sig_, 1 };
725 return std::span{ time_sig_events_.data (), time_sig_events_.size () };
729 void clear_tempo_events ()
732 cumulative_seconds_.clear ();
736 void clear_time_signature_events () { time_sig_events_.clear (); }
738 static constexpr auto kEventsKey =
"events"sv;
739 static constexpr auto kTimeSigEventsKey =
"timeSigEvents"sv;
742 j[kTimeSigEventsKey] = tempo_map.time_sig_events_;
743 j[kEventsKey] = tempo_map.events_;
745 friend void from_json (
const nlohmann::json &j,
FixedPpqTempoMap &tempo_map)
747 j.at (kTimeSigEventsKey).get_to (tempo_map.time_sig_events_);
748 j.at (kEventsKey).get_to (tempo_map.events_);
749 tempo_map.rebuild_cumulative_times ();
753 units::precise_sample_rate_t sample_rate_;
754 static constexpr auto ticks_per_sixteenth_ =
757 static constexpr auto DEFAULT_BPM_EVENT =
TempoEvent{
760 static constexpr auto DEFAULT_TIME_SIG_EVENT =
762 static constexpr auto DEFAULT_CUMULATIVE_SECONDS = units::seconds (0.0);
765 TempoEvent default_tempo_{ DEFAULT_BPM_EVENT };
768 std::vector<TempoEvent> events_;
769 std::vector<TimeSignatureEvent> time_sig_events_;
770 std::vector<units::precise_second_t>