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 (ticks), std::memory_order_release);
177 std::lock_guard lock (position_mutex_);
178 return position_ticks_;
191 std::lock_guard lock (position_mutex_);
192 position_ticks_ = tempo_map_.samples_to_tick (
193 position_samples_.load (std::memory_order_acquire));
196 const auto &get_tempo_map ()
const {
return tempo_map_; }
204 return position_samples_.load (std::memory_order_acquire);
210 static constexpr auto kMode =
"mode"sv;
211 static constexpr auto kValue =
"value"sv;
212 friend void to_json (nlohmann::json &j,
const Playhead &pos);
213 friend void from_json (
const nlohmann::json &j,
Playhead &pos);
216 const TempoMap &tempo_map_;
219 std::atomic<double> position_samples_processing_ = 0.0;
220 double position_samples_at_start_of_processing_{};
223 std::atomic<units::precise_sample_t> position_samples_;
224 units::precise_tick_t position_ticks_;
225 mutable std::mutex position_mutex_;
227 static_assert (
decltype (position_samples_)::is_always_lock_free);