2#include <Fx/Looper/PassStack.hpp>
4#include <boost/container/vector.hpp>
15inline constexpr int max_audio_layers = 32;
97 using pool_t = boost::container::vector<float>;
99 static constexpr int spare_slots = 2;
100 static constexpr int max_channels = 16;
101 static constexpr int fade_frames = 128;
105 std::shared_ptr<pool_t> pool;
106 boost::container::vector<float> peaks;
146 int a_slot{-1}, b_slot{-1};
159 int64_t a_len{}, b_len{};
165 void allocate(
int chans,
int layer_count, int64_t frames)
167 chans = std::clamp(chans, 1, max_channels);
169 layer_count = std::clamp(layer_count, 2,
max_layers);
170 frames = std::max<int64_t>(frames, 1);
171 if(chans == channels && layer_count == slots && frames == capacity)
178 pool = std::make_shared<pool_t>(
179 std::size_t(channels) * std::size_t(buffers()) * std::size_t(capacity),
180 boost::container::default_init);
182 peaks.shrink_to_fit();
183 peaks.resize(std::size_t(buffers()) * peak_count(), 0.f);
185 kept.shrink_to_fit();
186 kept.resize(std::size_t(buffers()) * 4 * std::size_t(channels) * fade_frames, 0.f);
202 void passes_changed() noexcept
207 bool may_remove(
int)
const noexcept {
return true; }
208 void muting(
int k)
noexcept
211 if(k == merging.at || k == merging.at + 1)
212 merging.active =
false;
214 void removing(
int k)
noexcept
216 if(k <= merging.at + 1)
217 merging.active =
false;
219 void erased(
int)
noexcept { }
220 void aside_taken(
int)
noexcept { }
221 void aside_returned(
int)
noexcept { }
222 void aside_forgotten() noexcept { }
223 void redo_dropped(
bool)
noexcept { }
224 void unmerge_dropped() noexcept { }
225 void unmerged(
int)
noexcept
227 for(
int s : {unmerge.a.slot, unmerge.b.slot})
228 if(s >= 0 && s < buffers())
231 void cleared() noexcept
233 merging.active =
false;
236 void undoing() noexcept { merging.active =
false; }
238 int buffers() const noexcept {
return slots + spare_slots; }
240 bool allocated() const noexcept {
return capacity > 0 && pool && !pool->empty(); }
241 bool empty() const noexcept {
return count == 0 ||
length == 0; }
242 std::size_t peak_count() const noexcept
250 data_in(pool_t& p,
int channels, int64_t capacity,
int slot,
int chan)
noexcept
253 + (std::size_t(slot) * std::size_t(channels) + std::size_t(chan))
254 * std::size_t(capacity);
256 float* data(
int slot,
int chan)
noexcept
258 return data_in(*pool, channels, capacity, slot, chan);
260 const float* data(
int slot,
int chan)
const noexcept
262 return const_cast<audio_layers*
>(
this)->data(slot, chan);
264 float* peaks_of(
int slot)
noexcept
266 return peaks.data() + std::size_t(slot) * peak_count();
273 const int64_t p =
period_in(l, loop_length);
274 return p > 0 ? k % p : 0;
276 static bool valid_in(
const audio_layer& l, int64_t k, int64_t loop_length)
noexcept
278 const int64_t p =
period_in(l, loop_length);
281 int64_t d = k % p - l.start;
284 return d < l.written;
287 int64_t index(
const audio_layer& l, int64_t k)
const noexcept
291 bool valid(
const audio_layer& l, int64_t k)
const noexcept
293 return valid_in(l, k,
length);
301 for(
int i =
count - 1; i >= 0; i--)
305 l.gain = l.muted ? 0.f : g;
316 return l.gain + (l.from - l.gain) *
float(
ramp_end -
now) / float(ramp_len);
320 float mix(
int c, int64_t k)
const noexcept
323 for(
int i = 0; i <
count; i++)
325 const auto& l =
layers[i];
326 if(l.muted || !valid(l, k))
328 const int64_t p = period_of(l);
329 float v = data(l.slot, c)[k % p];
339 static float seam_weight(
bool tail,
float rho, int64_t d,
int n)
noexcept
341 const float f = float(tail ? d + 1 : d) /
float(n);
342 return rho + (1.f - rho) * f;
353 for(
const bool tail : {
false,
true})
355 const auto& e = tail ? l.tail : l.head;
356 if(e.at < 0 || e.n <= 0 || e.rho <= 0.f || (tail && e.meet < 0))
358 int64_t d = ((k % p - e.at) * e.dir) % p;
363 int64_t seam = (k - e.dir * d) % len;
366 int64_t met = tail ? (e.meet + e.dir) % len : e.at;
380 const int64_t p = period_of(l);
381 if(p <= 0 || l.written >= p)
389 int64_t d = (k - l.start) % p;
394 const int64_t after = d - l.written;
395 const int64_t before = p - 1 - d;
398 silence(l, l.start + l.written, after);
405 l.written += before + 1;
407 l.written = std::min(l.written, p);
413 const int64_t p = period_of(l);
416 for(
int c = 0; c < channels; c++)
418 float* d = data(l.slot, c);
419 for(int64_t i = 0; i < n; i++)
420 d[(from + i) % p] = 0.f;
434 std::fill_n(peaks_of(l.slot), peak_count(), 0.f);
437 bool slot_used(
int s)
const noexcept
439 if(merging.active && merging.target == s)
441 if(unmerge.valid && (unmerge.a.slot == s || unmerge.b.slot == s))
443 if(aside.valid && !aside.
returned && aside.layer.slot == s)
445 for(
int i = 0; i <
count; i++)
451 bool is_reserved(
int s)
const noexcept {
return ((
reserved |
held) >> s) & 1u; }
457 for(
int s = 0; s < buffers(); s++)
478 template <
typename F>
481 for(
int i = 0; i <
total; i++)
495 for(
int i = 0; s >= 0 && s < buffers() &&
merged_into[s] >= 0 && i < buffers(); i++)
507 for(
int i = 0; i <
count; i++)
509 return layers[i].muted ? -1 : i;
518 for(
auto* e : {&l.head, &l.tail})
522 else if(e->partner >= 0 &&
resolve(e->partner) == s)
532 float* kept_of(
int slot,
bool tail,
bool part,
int c)
noexcept
535 + ((std::size_t(slot) * 4 + (tail ? 2 : 0) + (part ? 1 : 0)) *
std::size_t(channels)
543 const int64_t p = period_of(l);
544 int64_t k = (e.at + e.dir * d) % p;
545 return k < 0 ? k + p : k;
553 const int64_t p = period_of(l);
554 const int64_t written = std::min(l.written, p);
555 auto& e = tail ? l.tail : l.head;
557 if(p <= 0 || written <= 0 || !allocated() ||
kept.empty())
559 const int64_t first = l.start % p;
560 const int64_t last = (l.start + written - 1) % p;
563 const bool at_last = tail != l.backwards;
564 e.at = at_last ? last : first;
565 e.dir = at_last ? -1 : 1;
566 e.n = int(std::min<int64_t>(fade_frames, written));
569 for(
int c = 0; c < channels; c++)
571 const float* d = data(l.slot, c);
572 float* orig = kept_of(l.slot, tail,
false, c);
573 float* part = kept_of(l.slot, tail,
true, c);
574 for(
int i = 0; i < e.n; i++)
582 auto& e = tail ? l.tail : l.head;
584 for(
int c = 0; c < channels; c++)
586 float* d = data(l.slot, c);
587 const float* orig = kept_of(l.slot, tail,
false, c);
588 const float* part = kept_of(l.slot, tail,
true, c);
589 for(
int i = 0; i < e.n; i++)
608 for(
int i = 0; i <
count; i++)
613 for(
const bool tail : {
false,
true})
615 auto& e = tail ? l.tail : l.head;
618 const int j = e.partner >= 0 ?
heard_in(e.partner) : -1;
626 rho = mine > 0.f ? std::min(1.f, theirs / mine) : 1.f;
627 if(tail &&
layers[j].head.at >= 0)
628 e.meet =
layers[j].head.at;
630 if(std::abs(rho - e.rho) > 1e-6f)
642 void begin_overdub(int64_t start,
bool oldest =
true,
int replace = -1) noexcept
648 if(!oldest &&
count > slots)
658 if(oldest &&
count >= slots && !merging.active)
662 if(take_slot_count() == 0)
665 if(oldest &&
count >= slots)
674 std::fill_n(peaks_of(slot), peak_count(), 0.f);
677 int take_slot_count() const noexcept
680 for(
int s = 0; s < buffers(); s++)
692 if(at < 0 || at + 1 >=
count || merging.active)
697 const auto& a =
layers[at];
698 const auto& b =
layers[at + 1];
702 const bool lost_a = a.muted && !b.muted, lost_b = b.muted && !a.muted;
709 .a_gain = lost_a ? 0.f : lost_b ? 1.f : b.decay,
710 .b_gain = lost_b ? 0.f : 1.f,
711 .muted = a.muted && b.muted,
712 .undoable = undoable,
717 .a_len = std::max<int64_t>(1, period_of(a)),
718 .b_len = std::max<int64_t>(1, period_of(b)),
719 .merged = std::max(period_of(a), period_of(b)),
731 if(m.at + 1 >=
count ||
layers[m.at].slot != m.a_slot
732 ||
layers[m.at + 1].slot != m.b_slot)
740 const int64_t end = std::min(m.merged, m.pos + std::max<int64_t>(1, frames));
741 for(
int c = 0; c < channels; c++)
743 float* dst = data(m.target, c);
744 const float* da = data(m.a_slot, c);
745 const float* db = data(m.b_slot, c);
746 for(int64_t k = m.pos; k < end; k++)
750 float* pt = peaks_of(m.target);
751 const float* pa = peaks_of(m.a_slot);
752 const float* pb = peaks_of(m.b_slot);
756 pt[i] = m.a_gain * pa[i % a_bins] + m.b_gain * pb[i % b_bins];
767 a.from =
layers[m.at + 1].from;
769 a.decay = (m.lost_a ? 1.f : m.a.decay) * (m.lost_b ? 1.f : m.b.decay);
771 a.period = m.merged ==
length ? 0 : m.merged;
772 a.written = m.merged;
775 merged(m.at, a, m.undoable, m.a, m.b);
778 void finish_merge() noexcept
784 float merged_at(
const float* da,
const float* db, int64_t k)
const noexcept
786 const auto& m = merging;
787 const auto& a =
layers[m.at];
788 const auto& b =
layers[m.at + 1];
789 float va = 0.f, vb = 0.f;
790 if(valid_in(m.a, k, m.a_len))
792 va = da[k % m.a_len];
793 if(m.a_len < m.merged)
796 if(valid_in(m.b, k, m.b_len))
798 vb = db[k % m.b_len];
799 if(m.b_len < m.merged)
802 return m.a_gain * va + m.b_gain * vb;
811 const auto& a =
layers[m.at];
812 const auto& b =
layers[m.at + 1];
815 for(
int c = 0; c < channels; c++)
817 float* dst = data(m.target, c);
818 const float* da = data(m.a_slot, c);
819 const float* db = data(m.b_slot, c);
820 for(
const auto* l : {&a, &b})
822 const int64_t p = std::max<int64_t>(1, period_of(*l));
823 for(
const auto* e : {&l->head, &l->tail})
825 for(
int i = 0; i < e->n; i++)
826 for(int64_t k =
seam_index(*l, *e, i); k < m.merged; k += p)
834 int64_t len,
bool lost) {
835 const auto& e = tail ? l.tail : l.head;
836 return e.at >= 0 && !lost && len == m.merged
837 && (e.partner < 0 ||
resolve(e.partner) != other.slot);
839 const auto take = [&](
const audio_layer& l,
bool tail,
float gain) {
840 const auto& e = tail ? l.tail : l.head;
841 (tail ? into.tail : into.head) = e;
842 for(
int c = 0; c < channels; c++)
844 const float* dst = data(m.target, c);
845 const float* part = kept_of(l.
slot, tail,
true, c);
846 float* to_orig = kept_of(m.target, tail,
false, c);
847 float* to_part = kept_of(m.target, tail,
true, c);
848 for(
int i = 0; i < e.n; i++)
850 to_part[i] = gain * part[i];
852 + to_part[i] * (1.f -
seam_weight(tail, e.rho, i, e.n));
858 if(outer(a,
false, b, m.a_len, m.lost_a))
859 take(a,
false, m.a_gain);
860 else if(outer(b,
false, a, m.b_len, m.lost_b))
861 take(b,
false, m.b_gain);
862 if(outer(b,
true, a, m.b_len, m.lost_b))
863 take(b,
true, m.b_gain);
864 else if(outer(a,
true, b, m.a_len, m.lost_a))
865 take(a,
true, m.a_gain);
875 void decay(
float feedback, int64_t glide = fade_frames)
noexcept
877 if(count < 2 || feedback >= 1.f)
879 for(
int i = 0; i <
count; i++)
883 ramp_len = std::max<int64_t>(1, glide);
887 void note_peak(
int slot, int64_t k,
float v)
noexcept
889 float& p = peaks_of(slot)[std::size_t(k /
peak_frames)];
890 p = std::max(p, std::abs(v));
898 if(!l || length <= 0 || l->written <= 0)
900 const int64_t p = period_of(*l);
901 const int64_t n = std::min<int64_t>({fade_frames, l->written, p});
902 for(
int c = 0; c < channels; c++)
904 float* d = data(l->slot, c);
905 for(int64_t i = 0; i < n; i++)
907 int64_t k = l->backwards ? (l->start + i) % p
908 : (l->start + std::min(l->written, p) - 1 - i) % p;
911 d[k] *= float(i) / float(n);
921 const int64_t len = period_of(l);
931 for(
int c = 0; c < channels; c++)
933 float* d = data(l.slot, c);
934 std::rotate(d, d + frames, d + len);
936 float* p = peaks_of(l.slot);
939 if(bin_shift > 0 && bins > 0)
940 std::rotate(p, p + (bin_shift % bins), p + bins);
944 for(
auto* e : {&l.head, &l.tail})
946 e->at = ((e->at - frames) % len + len) % len;
952template <
typename Data>
954 Data&& data,
const audio_layer* passes,
int count,
int c, int64_t len, int64_t from,
955 int64_t to,
float* dst)
957 std::fill(dst + from, dst + to, 0.f);
958 for(
int i = 0; i < count; i++)
960 const auto& l = passes[i];
961 const float* src = data(l.slot, c);
963 for(int64_t k = from; k < to; k++)
964 if(audio_layers::valid_in(l, k, len))
976 std::shared_ptr<audio_layers::pool_t> pool;
977 std::array<audio_layer, audio_layers::max_passes> passes{};
986 template <
typename Out>
987 void flatten(
int out_channels, Out&& out,
int item = -1)
const
992 const auto data = [&](
int slot,
int c) ->
const float* {
995 for(
int c = 0; c < std::min(out_channels, channels); c++)
1000 mix_passes(data, passes.data(), count, c, length, 0, length, dst);
1003 const auto& l = passes[item];
1004 const float* src = data(l.slot, c);
1006 for(int64_t k = 0; k < length; k++)
1007 dst[k] = audio_layers::valid_in(l, k, length)
Definition AudioLayers.hpp:14
void mix_passes(Data &&data, const audio_layer *passes, int count, int c, int64_t len, int64_t from, int64_t to, float *dst)
Definition AudioLayers.hpp:953
Definition AudioLayers.hpp:46
int64_t start
Loop position of its first frame.
Definition AudioLayers.hpp:60
int64_t written
Definition AudioLayers.hpp:63
bool backwards
Definition AudioLayers.hpp:76
int64_t period
Definition AudioLayers.hpp:66
int64_t loop_before
Definition AudioLayers.hpp:69
float gain
Definition AudioLayers.hpp:51
float decay
Definition AudioLayers.hpp:58
float unmuted_gain
Definition AudioLayers.hpp:54
int slot
Which buffer of the pool holds it.
Definition AudioLayers.hpp:48
bool muted
Definition AudioLayers.hpp:73
float from
Gain it was heard with when the gains last started to glide.
Definition AudioLayers.hpp:78
Definition AudioLayers.hpp:142
bool lost_a
Definition AudioLayers.hpp:158
float a_gain
Definition AudioLayers.hpp:149
bool undoable
Kept for undo once merged: the pass merged into the newest one.
Definition AudioLayers.hpp:153
Definition AudioLayers.hpp:96
bool reserved_overwritten
Set when a new pass had to go into a reserved buffer after all.
Definition AudioLayers.hpp:122
void decay(float feedback, int64_t glide=fade_frames) noexcept
Definition AudioLayers.hpp:875
void update_gains() noexcept
Definition AudioLayers.hpp:298
static float * data_in(pool_t &p, int channels, int64_t capacity, int slot, int chan) noexcept
Definition AudioLayers.hpp:250
void start_merge(int at=0, bool undoable=false) noexcept
Definition AudioLayers.hpp:690
static float repeat_weight(const audio_layer &l, int64_t k, int64_t p, int64_t len) noexcept
Definition AudioLayers.hpp:350
std::array< int, max_layers+spare_slots > merged_into
Definition AudioLayers.hpp:133
void shift_earlier(audio_layer &l, int64_t frames) noexcept
Definition AudioLayers.hpp:919
void update_seams() noexcept
Definition AudioLayers.hpp:606
uint64_t reserved
Definition AudioLayers.hpp:117
int resolve(int s) const noexcept
The buffer a merge forwarded buffer s to.
Definition AudioLayers.hpp:493
float mix(int c, int64_t k) const noexcept
What the loop sounds like at position k of channel c.
Definition AudioLayers.hpp:320
void allocate(int chans, int layer_count, int64_t frames)
Main thread only.
Definition AudioLayers.hpp:165
uint64_t held
Definition AudioLayers.hpp:120
void fade_out_top() noexcept
Definition AudioLayers.hpp:895
void for_each_kept(F &&f) noexcept
Every pass kept: heard, brought back by redo, set aside or merged.
Definition AudioLayers.hpp:479
float settled_gain(const audio_layer &l) const noexcept
Definition AudioLayers.hpp:597
void weigh_seam(audio_layer &l, bool tail, float rho) noexcept
Writes an end of pass l with weight rho next to its seam.
Definition AudioLayers.hpp:580
void merge_seams(audio_layer &into) noexcept
Definition AudioLayers.hpp:808
float merged_at(const float *da, const float *db, int64_t k) const noexcept
Position k of the merged pass, from the buffers of the two.
Definition AudioLayers.hpp:784
uint64_t changes
Definition AudioLayers.hpp:113
float heard_gain(const audio_layer &l) const noexcept
Gain pass l is heard with at frame now.
Definition AudioLayers.hpp:312
void begin_recording() noexcept
Forgets every pass and starts a recording in a free buffer.
Definition AudioLayers.hpp:430
int64_t seam_index(const audio_layer &l, const audio_seam_end &e, int64_t d) const noexcept
Where frame d of an end of pass l is in its buffer.
Definition AudioLayers.hpp:541
void begin_overdub(int64_t start, bool oldest=true, int replace=-1) noexcept
Definition AudioLayers.hpp:642
void silence(audio_layer &l, int64_t from, int64_t n) noexcept
Zeroes n positions of a pass from position from on, round its period.
Definition AudioLayers.hpp:411
void buffer_reused(int s) noexcept
Definition AudioLayers.hpp:515
int64_t ramp_end
Gains glide from from to gain until ramp_end, over ramp_len frames.
Definition AudioLayers.hpp:138
static int64_t index_in(const audio_layer &l, int64_t k, int64_t loop_length) noexcept
Definition AudioLayers.hpp:271
static constexpr int peak_frames
Frames summed up into one point of the peak overview.
Definition AudioLayers.hpp:103
int64_t now
Frame counter of the processing: gains glide over frames of it.
Definition AudioLayers.hpp:136
int heard_in(int s) const noexcept
Definition AudioLayers.hpp:502
void merge_step(int64_t frames) noexcept
Definition AudioLayers.hpp:726
void open_seam(audio_layer &l, bool tail, int partner) noexcept
Definition AudioLayers.hpp:551
void cover(audio_layer &l, int64_t k) noexcept
Definition AudioLayers.hpp:378
static float seam_weight(bool tail, float rho, int64_t d, int n) noexcept
Definition AudioLayers.hpp:339
pool_t kept
Definition AudioLayers.hpp:130
bool extend(int64_t unit) noexcept
Definition AudioLayers.hpp:427
int take_slot() noexcept
A buffer no pass uses, one nothing else reads when there is one.
Definition AudioLayers.hpp:454
Definition AudioLayers.hpp:21
int64_t at
Index in the pass's buffer of its frame next to the seam, -1 for none.
Definition AudioLayers.hpp:26
int partner
Definition AudioLayers.hpp:31
float rho
Definition AudioLayers.hpp:37
int64_t meet
For a tail: loop position of the other side's frame next to the seam.
Definition AudioLayers.hpp:28
static constexpr int pending
The pass on the other side is not there yet.
Definition AudioLayers.hpp:23
int n
Frames from at on, going dir into the pass, that the seam weighs.
Definition AudioLayers.hpp:33
Definition AudioLayers.hpp:975
void flatten(int out_channels, Out &&out, int item=-1) const
Definition AudioLayers.hpp:987
bool returned
Definition PassStack.hpp:103
Definition PassStack.hpp:66
int total
Passes kept, the ones past count being what redo brings back.
Definition PassStack.hpp:77
static constexpr int max_layers
Most layers kept: Max layers is at most this.
Definition PassStack.hpp:68
void drop_unmerge() noexcept
Undo is not to take the last merge apart: what it kept for that goes.
Definition PassStack.hpp:218
void forget_aside() noexcept
Forgets the layer set aside.
Definition PassStack.hpp:208
int64_t length
Frames in the loop.
Definition PassStack.hpp:79
audio_layer & push_pass() noexcept
Adds a pass over the ones heard, room having been made for it.
Definition PassStack.hpp:180
int count
Passes heard.
Definition PassStack.hpp:75
void merged(int at, const audio_layer &merged, bool undoable, const audio_layer &a, const audio_layer &b) noexcept
Definition PassStack.hpp:354
bool extend(int64_t unit, int64_t max_length, bool top_open=true) noexcept
Definition PassStack.hpp:135
std::array< audio_layer, max_passes+1 > layers
The passes heard, then the ones redo brings back.
Definition PassStack.hpp:73
static int64_t period_in(const audio_layer &l, int64_t loop_length) noexcept
The length a pass repeats with in a loop of loop_length frames.
Definition PassStack.hpp:117
audio_layer merged_pass(const audio_layer &a, const audio_layer &b) const noexcept
Definition PassStack.hpp:370
void begin_merge() noexcept
A merge is about to be worked out: what it would make stale goes.
Definition PassStack.hpp:343
void drop_redo() noexcept
Definition PassStack.hpp:196
audio_layer & begin_first_pass() noexcept
Forgets every pass for a recording: its pass, the first one.
Definition PassStack.hpp:170
void set_aside(int k) noexcept
Definition PassStack.hpp:226