64 friend class PlayheadProcessingGuard;
71 Playhead (
const TempoMap &tempo_map) : tempo_map_ (tempo_map) { }
82 void prepare_for_processing () noexcept
86 position_samples_.load (std::memory_order_acquire).in (units::samples);
87 position_samples_at_start_of_processing_ = samples;
88 position_samples_processing_.store (samples, std::memory_order_release);
101 if (nframes >= units::samples (0)) [[likely]]
103 position_samples_processing_.fetch_add (
104 nframes.in<
double> (units::samples));
108 position_samples_processing_.fetch_sub (
109 -nframes.in<
double> (units::samples));
121 return position_samples_processing_.load (std::memory_order_acquire);
123 units::sample_t position_during_processing_rounded () const noexcept
125 return units::samples (
126 static_cast<int64_t
> (std::round (
127 position_samples_processing_.load (std::memory_order_acquire))));
137 void finalize_processing () noexcept
140 const auto processing_samples =
141 position_samples_processing_.load (std::memory_order_acquire);
146 auto expected = units::samples (position_samples_at_start_of_processing_);
147 position_samples_.compare_exchange_strong (
148 expected, units::samples (processing_samples), std::memory_order_acq_rel,
149 std::memory_order_acquire);
163 std::lock_guard lock (position_mutex_);
164 position_ticks_ = ticks;
165 position_samples_.store (
166 tempo_map_.tick_to_samples (ticks), std::memory_order_release);
175 std::lock_guard lock (position_mutex_);
176 return position_ticks_;
189 std::lock_guard lock (position_mutex_);
190 position_ticks_ = tempo_map_.samples_to_tick (
191 position_samples_.load (std::memory_order_acquire));
194 const auto &get_tempo_map ()
const {
return tempo_map_; }
202 return position_samples_.load (std::memory_order_acquire);
206 static constexpr auto kTicks =
"ticks"sv;
207 friend void to_json (nlohmann::json &j,
const Playhead &pos)
211 friend void from_json (
const nlohmann::json &j,
Playhead &pos)
214 j.at (kTicks).get_to (ticks);
215 pos.set_position_ticks (units::ticks (ticks));
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);