35 constexpr std::size_t per_line = 64 /
sizeof(
value_type);
36 return (
bins + per_line - 1) / per_line * per_line;
53 constexpr std::size_t per_line = 64 /
sizeof(
value_type);
57 storage_.assign(count_ * stride_ + per_line,
value_type{});
58 const auto address =
reinterpret_cast<std::uintptr_t
>(storage_.data());
59 offset_ = ((64u - address % 64u) % 64u) /
sizeof(
value_type);
62 std::size_t
size() const noexcept {
68 std::size_t
bins() const noexcept {
71 std::size_t
stride() const noexcept {
80 return {storage_.data() + offset_ +
i * stride_, bins_};
82 std::span<const value_type>
operator[](std::size_t
i)
const noexcept {
83 return {storage_.data() + offset_ +
i * stride_, bins_};
88 std::fill(storage_.begin(), storage_.end(),
value_type{});
92 std::vector<value_type> storage_;
93 std::size_t offset_ = 0, count_ = 0, bins_ = 0, stride_ = 0;
115template <
typename SampleType =
float>
136 std::vector<std::complex<SampleType>>
overlap;
165template <
typename SampleType =
float>
171 std::unique_ptr<FftT<SampleType>>
fft;
175 std::vector<std::complex<SampleType>>
accum;
176 std::unique_ptr<ConvolverInputHistoryT<SampleType>>
history;
190 while (pot < block_size && pot <= (
static_cast<std::size_t
>(-1) >> 1))
197template <
typename SampleType =
float>
198inline std::unique_ptr<ConvolverIrStateT<SampleType>>
200 std::size_t ir_length,
201 std::size_t block_size) {
202 if (ir ==
nullptr || ir_length == 0)
207 auto state = std::make_unique<ConvolverIrStateT<SampleType>>();
208 state->block_size =
static_cast<int>(block_size);
210 state->fft = std::make_unique<FftT<SampleType>>(
state->fft_size);
211 state->num_partitions = (ir_length + block_size - 1) / block_size;
213 const auto bins =
static_cast<std::size_t
>(
state->fft_size / 2 + 1);
214 state->ir_spectra.assign(
state->num_partitions, bins);
215 std::vector<std::complex<SampleType>> padded(
216 state->fft_size, {SampleType{0.0f}, SampleType{0.0f}});
218 for (std::size_t p = 0; p <
state->num_partitions; ++p) {
219 const std::size_t offset = p * block_size;
220 const std::size_t count = std::min(block_size, ir_length - offset);
222 std::fill(padded.begin(), padded.end(),
223 std::complex<SampleType>{SampleType{0.0f}, SampleType{0.0f}});
224 for (std::size_t
i = 0;
i < count; ++
i)
225 padded[
i] = {ir[offset +
i], SampleType{0.0f}};
227 state->fft->forward(padded.data());
228 std::copy_n(padded.begin(), bins, state->ir_spectra[p].begin());
231 state->accum.assign(state->fft_size,
232 {SampleType{0.0f}, SampleType{0.0f}});
233 state->history = std::make_unique<ConvolverInputHistoryT<SampleType>>();
234 state->history->block_size = state->block_size;
235 state->history->fft_size = state->fft_size;
236 state->history->overlap.assign(state->fft_size, {0.0f, 0.0f});
237 state->history->spectra.assign(state->num_partitions, bins);
264template <
typename SampleType =
float>
269 const std::size_t old_capacity = from.
spectra.size();
270 const std::size_t new_capacity = to.
spectra.size();
271 if (old_capacity == 0 || new_capacity == 0)
return;
272 const std::size_t carried = std::min(old_capacity, new_capacity);
276 for (std::size_t a = 0; a < carried; ++a) {
277 const std::size_t oldi = (from.
write_pos + old_capacity - 1 - a) % old_capacity;
278 const std::size_t newi = (new_capacity - 1 - a) % new_capacity;
279 const auto source = from.
spectra[oldi];
280 std::copy(source.begin(), source.end(), to.
spectra[newi].begin());
313template <
typename SampleType =
float>
329 std::size_t ir_length,
330 std::size_t block_size) {
339 return handoff_.publish(std::move(next));
346 return handoff_.try_consume();
361 return handoff_.retire(displaced);
379 std::size_t
drain_old() {
return handoff_.drain_retired(); }
384 return handoff_.drain_retired_one();
399 static constexpr std::size_t kRetireRingCapacity = 8;
Lock-free transfer of ownership to a reader that must never block, plus a ring for handing the displa...
Definition slot.hpp:254
Lock-free background-IR shuttle for PartitionedConvolver.
Definition convolver_messages.hpp:314
std::unique_ptr< ConvolverIrStateT< SampleType > > drain_old_one()
UI / worker thread: pop ONE retired IR for test inspection.
Definition convolver_messages.hpp:383
std::unique_ptr< ConvolverIrStateT< SampleType > > try_consume()
Audio-thread-callable: atomically claim the most recently staged IR, if any.
Definition convolver_messages.hpp:345
bool has_retire_capacity(std::size_t n) const
Room to park at least n IRs — for a caller that must retire more than one in a single audio-thread st...
Definition convolver_messages.hpp:374
bool retire(std::unique_ptr< ConvolverIrStateT< SampleType > > &displaced)
Audio-thread-callable: park the IR that the audio thread is displacing so a non-RT thread can free it...
Definition convolver_messages.hpp:360
bool has_pending() const
True if a freshly-staged IR is awaiting consumption.
Definition convolver_messages.hpp:388
std::size_t drain_old()
UI / worker thread: reclaim ALL retired IRs the audio thread has parked.
Definition convolver_messages.hpp:379
ConvolverIrSwapperT()=default
bool stage_ir(std::unique_ptr< ConvolverIrStateT< SampleType > > next)
Publish a pre-built state. Same semantics as the raw overload.
Definition convolver_messages.hpp:338
bool has_retire_capacity() const
True if there's room in the retire ring for one more displaced IR.
Definition convolver_messages.hpp:368
ConvolverIrSwapperT(const ConvolverIrSwapperT &)=delete
static constexpr std::size_t retire_capacity()
Compile-time capacity of the retired-IR ring.
Definition convolver_messages.hpp:396
bool stage_ir(const SampleType *ir, std::size_t ir_length, std::size_t block_size)
Build a fresh IR state off the audio thread and publish it for the audio thread to pick up.
Definition convolver_messages.hpp:328
ConvolverIrSwapperT & operator=(const ConvolverIrSwapperT &)=delete
bool has_retired() const
True if any retired IR is awaiting drain.
Definition convolver_messages.hpp:391
A fixed number of equal-length spectra in one contiguous, 64-byte-aligned block, each starting on a 6...
Definition convolver_messages.hpp:28
std::span< const value_type > operator[](std::size_t i) const noexcept
Definition convolver_messages.hpp:82
void fill_zero() noexcept
Zero every spectrum. Allocation-free.
Definition convolver_messages.hpp:87
bool empty() const noexcept
Definition convolver_messages.hpp:65
std::size_t footprint_bytes() const noexcept
Bytes this arena holds, including its alignment slack.
Definition convolver_messages.hpp:75
static constexpr std::size_t stride_for(std::size_t bins) noexcept
Distance between consecutive spectra in value_types: bins rounded up to a whole number of 64-byte lin...
Definition convolver_messages.hpp:34
ConvolverSpectrumArenaT(std::size_t count, std::size_t bins)
Definition convolver_messages.hpp:40
ConvolverSpectrumArenaT()=default
ConvolverSpectrumArenaT(ConvolverSpectrumArenaT &&) noexcept=default
ConvolverSpectrumArenaT & operator=(const ConvolverSpectrumArenaT &)=delete
ConvolverSpectrumArenaT(const ConvolverSpectrumArenaT &)=delete
std::size_t stride() const noexcept
Definition convolver_messages.hpp:71
std::complex< SampleType > value_type
Definition convolver_messages.hpp:30
std::span< value_type > operator[](std::size_t i) noexcept
Definition convolver_messages.hpp:79
void assign(std::size_t count, std::size_t bins)
Allocate count zeroed spectra of bins values each.
Definition convolver_messages.hpp:52
std::size_t bins() const noexcept
Definition convolver_messages.hpp:68
std::size_t size() const noexcept
Definition convolver_messages.hpp:62
Round-2 effect-wave vocabulary.
Definition analysis_frontends.hpp:50
constexpr std::size_t convolver_block_size(std::size_t block_size) noexcept
The block size a convolver prepared for block_size accepts: the request rounded up to the next power ...
Definition convolver_messages.hpp:188
void migrate_input_history(ConvolverInputHistoryT< SampleType > &from, ConvolverInputHistoryT< SampleType > &to)
Migrate the recorded input history from from into to, age-aligned.
Definition convolver_messages.hpp:265
std::unique_ptr< ConvolverIrStateT< SampleType > > build_convolver_ir_state(const SampleType *ir, std::size_t ir_length, std::size_t block_size)
Build a ConvolverIrState from a raw IR.
Definition convolver_messages.hpp:199
Definition additive_bank.hpp:218
ConvolverIrStateT< double > ConvolverIrState64
Definition convolver_messages.hpp:180
ConvolverInputHistoryT< float > ConvolverInputHistory
Definition convolver_messages.hpp:140
ConvolverInputHistoryT< double > ConvolverInputHistory64
Definition convolver_messages.hpp:141
ConvolverIrSwapperT< float > ConvolverIrSwapper
Definition convolver_messages.hpp:409
@ i
Definition formant_filter_bank.hpp:20
ConvolverIrSwapperT< double > ConvolverIrSwapper64
Definition convolver_messages.hpp:410
ConvolverIrStateT< float > ConvolverIrState
Definition convolver_messages.hpp:179
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
Publishing a value built off the audio thread, and reclaiming the old one without ever calling a dest...
The convolver's input-side overlap-save history.
Definition convolver_messages.hpp:116
ConvolverSpectrumArenaT< float > spectra
Definition convolver_messages.hpp:132
std::vector< std::complex< float > > overlap
Definition convolver_messages.hpp:136
int block_size
Definition convolver_messages.hpp:117
int fft_size
Definition convolver_messages.hpp:118
std::size_t write_pos
Definition convolver_messages.hpp:137
Pre-computed, audio-thread-ready state for a single impulse response.
Definition convolver_messages.hpp:166
std::size_t num_partitions
Definition convolver_messages.hpp:169
int fft_size
Definition convolver_messages.hpp:168
std::vector< std::complex< float > > accum
Definition convolver_messages.hpp:175
std::unique_ptr< FftT< float > > fft
Definition convolver_messages.hpp:171
std::unique_ptr< ConvolverInputHistoryT< float > > history
Definition convolver_messages.hpp:176
ConvolverSpectrumArenaT< float > ir_spectra
Definition convolver_messages.hpp:174
int block_size
Definition convolver_messages.hpp:167