53template <
typename Sample>
56 for (std::size_t ch = 0; ch < out.
num_channels(); ++ch) {
58 for (std::size_t n = 0; n < frames; ++n) o[n] = Sample{0};
71template <
typename Sample>
76 for (std::size_t ch = 0; ch < channels; ++ch) {
79 for (std::size_t n = 0; n < frames; ++n) o[n] = i[n];
81 for (std::size_t ch = channels; ch < out.
num_channels(); ++ch) {
83 for (std::size_t n = 0; n < frames; ++n) o[n] = Sample{0};
98 const std::uint32_t prev = gate_->state_.fetch_sub(1, std::memory_order_acq_rel);
101 if ((prev & kRestoring) != 0)
102 gate_->state_.notify_all();
105 explicit operator bool() const noexcept {
106 return gate_ !=
nullptr;
122 gate_.state_.fetch_and(~kRestoring, std::memory_order_release);
128 : gate_(gate), writer_(std::move(writer)) {}
132 std::unique_lock<std::mutex> writer_;
139 const std::uint32_t prev = state_.fetch_add(1, std::memory_order_acquire);
140 if ((prev & kRestoring) != 0) {
141 state_.fetch_sub(1, std::memory_order_relaxed);
142 contended_blocks_.fetch_add(1, std::memory_order_relaxed);
153 std::unique_lock<std::mutex> writer(writer_mutex_);
154 std::uint32_t current = state_.fetch_or(kRestoring, std::memory_order_acq_rel) | kRestoring;
158 for (
int spin = 0; spin < kSpinsBeforeWait && (current & kRenderMask) != 0; ++spin) {
159 std::this_thread::yield();
160 current = state_.load(std::memory_order_acquire);
162 while ((current & kRenderMask) != 0) {
163 state_.wait(current, std::memory_order_acquire);
164 current = state_.load(std::memory_order_acquire);
173 return contended_blocks_.load(std::memory_order_relaxed);
177 static constexpr std::uint32_t kRestoring = 0x8000'0000u;
178 static constexpr std::uint32_t kRenderMask = ~kRestoring;
179 static constexpr int kSpinsBeforeWait = 64;
180 static_assert(std::atomic<std::uint32_t>::is_always_lock_free,
181 "the render side of the gate must be lock-free");
185 std::atomic<std::uint32_t> state_{0};
186 std::mutex writer_mutex_;
187 std::atomic<std::uint64_t> contended_blocks_{0};
Non-owning view over multi-channel audio sample data.
Definition buffer.hpp:30
std::size_t num_samples() const
Definition buffer.hpp:84
std::size_t num_channels() const
Definition buffer.hpp:83
std::span< SampleType > channel(std::size_t index)
Get a span over all samples in one channel.
Definition buffer.hpp:58