11#include "dsp/tempo_map.h"
12#include "utils/format.h"
13#include "utils/types.h"
14#include "utils/units.h"
16#include <fmt/format.h>
17#include <nlohmann/json_fwd.hpp>
25 std::numeric_limits<double>::is_iec559,
26 "Requires IEEE-754 doubles");
28 std::atomic<uint64_t>::is_always_lock_free,
29 "64-bit atomics not lock-free");
34class AtomicDoubleWithBool
36 std::atomic<uint64_t> packed_;
39 static constexpr uint64_t kValueMask = ~1ULL;
42 AtomicDoubleWithBool ()
noexcept =
default;
43 AtomicDoubleWithBool (
double d,
bool b)
noexcept { store (d, b); }
45 void store (
double d,
bool b)
noexcept
47 assert (std::isfinite (d) &&
"Only finite doubles supported");
48 const auto bits = std::bit_cast<uint64_t> (d);
49 packed_.store ((bits & kValueMask) | (b ? 1 : 0), std::memory_order_release);
52 std::pair<double, bool> load ()
const noexcept
54 const uint64_t bits = packed_.load (std::memory_order_acquire);
56 std::bit_cast<double> (bits & kValueMask),
57 static_cast<bool> (bits & 1)
81 std::function<units::precise_second_t (units::precise_tick_t)>
83 std::function<units::precise_tick_t (units::precise_second_t)>
85 std::function<units::precise_sample_t (units::precise_tick_t)>
87 std::function<units::precise_tick_t (units::precise_sample_t)>
90 static std::unique_ptr<TimeConversionFunctions>
91 from_tempo_map (
const dsp::TempoMap &tempo_map)
93 return std::make_unique<
97 [&] (units::precise_tick_t ticks) {
101 [&] (units::precise_second_t seconds) {
105 [&] (units::precise_tick_t ticks) {
109 [&] (units::precise_sample_t samples) {
121 : conversion_funcs_ (conversion_funcs),
129 return bool_to_format (value_.load ().second);
175 set_seconds (conversion_funcs_.tick_to_seconds (ticks));
194 set_ticks (conversion_funcs_.seconds_to_tick (seconds));
201 const auto &[d, b] = value_.load ();
204 return units::ticks (d);
206 return conversion_funcs_.seconds_to_tick (units::seconds (d));
212 const auto &[d, b] = value_.load ();
215 return units::seconds (d);
217 return conversion_funcs_.tick_to_seconds (units::ticks (d));
223 const auto &[d, b] = value_.load ();
227 : conversion_funcs_.seconds_to_tick (units::seconds (d));
228 return au::round_as<std::int64_t> (
229 units::samples, conversion_funcs_.tick_to_samples (tick));
232 void set_samples (units::precise_sample_t samples)
234 set_ticks (conversion_funcs_.samples_to_tick (samples));
237 const auto &time_conversion_functions ()
const {
return conversion_funcs_; }
240 static constexpr bool format_to_bool (
TimeFormat format)
noexcept
244 static constexpr TimeFormat bool_to_format (
bool b)
noexcept
249 static constexpr auto kMode =
"mode"sv;
250 static constexpr auto kValue =
"value"sv;
251 friend void to_json (nlohmann::json &j,
const AtomicPosition &pos);
252 friend void from_json (
const nlohmann::json &j,
AtomicPosition &pos);
256 internal::AtomicDoubleWithBool value_;
264 : fmt::formatter<std::string_view>
266 template <
typename FormatContext>
269 return fmt::formatter<std::string_view>{}.format (
271 "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).
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.
@ Musical
Musical time (ticks).
@ Absolute
Absolute time (seconds).