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);
208 static constexpr auto kMode =
"mode"sv;
209 static constexpr auto kValue =
"value"sv;
210 friend void to_json (nlohmann::json &j,
const Playhead &pos);
211 friend void from_json (
const nlohmann::json &j,
Playhead &pos);
214 const TempoMap &tempo_map_;
217 std::atomic<double> position_samples_processing_ = 0.0;
218 double position_samples_at_start_of_processing_{};
221 std::atomic<units::precise_sample_t> position_samples_;
222 units::precise_tick_t position_ticks_;
223 mutable std::mutex position_mutex_;
225 static_assert (
decltype (position_samples_)::is_always_lock_free);