66 friend class PlayheadProcessingGuard;
73 Playhead (
const TempoMap &tempo_map) : tempo_map_ (tempo_map) { }
84 void prepare_for_processing () noexcept
88 position_samples_.load (std::memory_order_acquire).in (units::samples);
89 position_samples_at_start_of_processing_ = samples;
90 position_samples_processing_.store (samples, std::memory_order_release);
103 if (nframes >= units::samples (0)) [[likely]]
105 position_samples_processing_.fetch_add (
106 nframes.in<
double> (units::samples));
110 position_samples_processing_.fetch_sub (
111 -nframes.in<
double> (units::samples));
123 return position_samples_processing_.load (std::memory_order_acquire);
125 units::sample_t position_during_processing_rounded () const noexcept
127 return units::samples (
128 static_cast<int64_t
> (std::round (
129 position_samples_processing_.load (std::memory_order_acquire))));
139 void finalize_processing () noexcept
142 const auto processing_samples =
143 position_samples_processing_.load (std::memory_order_acquire);
148 auto expected = units::samples (position_samples_at_start_of_processing_);
149 position_samples_.compare_exchange_strong (
150 expected, units::samples (processing_samples), std::memory_order_acq_rel,
151 std::memory_order_acquire);
165 std::lock_guard lock (position_mutex_);
166 position_ticks_ = ticks;
167 position_samples_.store (
168 tempo_map_.tick_to_samples (TimelineTick{ ticks }),
169 std::memory_order_release);
178 std::lock_guard lock (position_mutex_);
179 return position_ticks_;
192 std::lock_guard lock (position_mutex_);
195 .samples_to_tick (position_samples_.load (std::memory_order_acquire))
199 const auto &get_tempo_map ()
const {
return tempo_map_; }
207 return position_samples_.load (std::memory_order_acquire);
213 static constexpr auto kMode =
"mode"sv;
214 static constexpr auto kValue =
"value"sv;
215 friend void to_json (nlohmann::json &j,
const Playhead &pos);
216 friend void from_json (
const nlohmann::json &j,
Playhead &pos);
219 const TempoMap &tempo_map_;
222 std::atomic<double> position_samples_processing_ = 0.0;
223 double position_samples_at_start_of_processing_{};
226 std::atomic<units::precise_sample_t> position_samples_;
227 units::precise_tick_t position_ticks_;
228 mutable std::mutex position_mutex_;
230 static_assert (
decltype (position_samples_)::is_always_lock_free);