11#include "dsp/tempo_map.h"
12#include "utils/enum_utils.h"
13#include "utils/units.h"
15#include <fmt/format.h>
16#include <nlohmann/json_fwd.hpp>
24 std::numeric_limits<double>::is_iec559,
25 "Requires IEEE-754 doubles");
27 std::atomic<uint64_t>::is_always_lock_free,
28 "64-bit atomics not lock-free");
38class AtomicDoubleWithBool
40 std::atomic<uint64_t> packed_;
43 static constexpr uint64_t kValueMask = ~1ULL;
46 AtomicDoubleWithBool ()
noexcept =
default;
47 AtomicDoubleWithBool (
double d,
bool b)
noexcept { store (d, b); }
49 void store (
double d,
bool b)
noexcept
51 assert (std::isfinite (d) &&
"Only finite doubles supported");
52 const auto bits = std::bit_cast<uint64_t> (d);
53 packed_.store ((bits & kValueMask) | (b ? 1 : 0), std::memory_order_release);
56 std::pair<double, bool> load ()
const noexcept
58 const uint64_t bits = packed_.load (std::memory_order_acquire);
60 std::bit_cast<double> (bits & kValueMask),
61 static_cast<bool> (bits & 1)
96 std::function<units::precise_second_t (units::precise_tick_t)>
98 std::function<units::precise_tick_t (units::precise_second_t)>
100 std::function<units::precise_sample_t (units::precise_tick_t)>
102 std::function<units::precise_tick_t (units::precise_sample_t)>
105 static std::unique_ptr<TimeConversionFunctions>
106 from_tempo_map (
const dsp::TempoMap &tempo_map)
108 return std::make_unique<
109 dsp::AtomicPosition::
112 [&] (units::precise_tick_t ticks) {
116 [&] (units::precise_second_t seconds) {
120 [&] (units::precise_tick_t ticks) {
124 [&] (units::precise_sample_t samples) {
136 : conversion_funcs_ (conversion_funcs),
144 return bool_to_format (value_.load ().second);
190 set_seconds (conversion_funcs_.tick_to_seconds (ticks));
209 set_ticks (conversion_funcs_.seconds_to_tick (seconds));
216 const auto &[d, b] = value_.load ();
219 return units::ticks (d);
221 return conversion_funcs_.seconds_to_tick (units::seconds (d));
227 const auto &[d, b] = value_.load ();
230 return units::seconds (d);
232 return conversion_funcs_.tick_to_seconds (units::ticks (d));
238 const auto &[d, b] = value_.load ();
242 : conversion_funcs_.seconds_to_tick (units::seconds (d));
243 return au::round_as<std::int64_t> (
244 units::samples, conversion_funcs_.tick_to_samples (tick));
247 void set_samples (units::precise_sample_t samples)
249 set_ticks (conversion_funcs_.samples_to_tick (samples));
252 const auto &time_conversion_functions ()
const {
return conversion_funcs_; }
255 static constexpr bool format_to_bool (
TimeFormat format)
noexcept
259 static constexpr TimeFormat bool_to_format (
bool b)
noexcept
264 static constexpr std::string_view kMode =
"mode";
265 static constexpr std::string_view kValue =
"value";
266 friend void to_json (nlohmann::json &j,
const AtomicPosition &pos);
267 friend void from_json (
const nlohmann::json &j,
AtomicPosition &pos);
271 internal::AtomicDoubleWithBool value_;
278struct fmt::formatter<zrythm::dsp::AtomicPosition>
279 : fmt::formatter<std::string_view>
281 template <
typename FormatContext>
284 return fmt::formatter<std::string_view>{}.format (
286 "Ticks: {:.2f} | Seconds: {:.3f} | Samples: {} | [Mode: {}]",
Thread-safe position storage with automatic musical/absolute time conversion.
void set_seconds(units::precise_second_t seconds)
Set position in absolute seconds.
void set_mode(TimeFormat format)
Change storage format with automatic value conversion.
units::precise_second_t get_seconds() const
Get position in absolute seconds (converts if necessary).
@ Musical
Musical time (ticks).
@ Absolute
Absolute time (seconds).
auto get_current_mode() const
Get current storage format (musical ticks or absolute seconds).
void set_ticks(units::precise_tick_t ticks)
Set position in musical ticks.
AtomicPosition(const TimeConversionFunctions &conversion_funcs) noexcept
Construct a new AtomicPosition object.
units::precise_tick_t get_ticks() const
Get position in musical ticks (converts if necessary).
units::sample_t get_samples() const
Helper method to get the position as samples.
auto tick_to_seconds(units::precise_tick_t tick) const -> units::precise_second_t
Convert fractional ticks to seconds.
units::precise_tick_t samples_to_tick(units::precise_sample_t samples) const
Convert samples to fractional ticks.
units::precise_tick_t seconds_to_tick(units::precise_second_t seconds) const
Convert seconds to fractional ticks.
units::precise_sample_t tick_to_samples(units::precise_tick_t tick) const
Convert fractional ticks to samples.