Loading...
Searching...
No Matches
AudioLayers.hpp
1#pragma once
2#include <Fx/Looper/PassStack.hpp>
3
4#include <boost/container/vector.hpp>
5
6#include <algorithm>
7#include <array>
8#include <cmath>
9#include <cstdint>
10#include <memory>
11#include <utility>
12
14{
15inline constexpr int max_audio_layers = 32;
16
21{
23 static constexpr int pending = -2;
24
26 int64_t at{-1};
28 int64_t meet{-1};
31 int partner{-1};
33 int n{};
34 int dir{1};
37 float rho{1.f};
38};
39
46{
48 int slot{-1};
51 float gain{1.f};
54 float unmuted_gain{1.f};
58 float decay{1.f};
60 int64_t start{};
63 int64_t written{};
66 int64_t period{};
69 int64_t loop_before{};
70 int64_t loop_after{};
73 bool muted{};
76 bool backwards{};
78 float from{1.f};
79 audio_seam_end head, tail;
80};
81
95struct audio_layers : pass_stack<audio_layers, audio_layer, max_audio_layers>
96{
97 using pool_t = boost::container::vector<float>;
98
99 static constexpr int spare_slots = 2;
100 static constexpr int max_channels = 16;
101 static constexpr int fade_frames = 128;
103 static constexpr int peak_frames = 256;
104
105 std::shared_ptr<pool_t> pool;
106 boost::container::vector<float> peaks;
107 int channels{};
108 int slots{};
109 int64_t capacity{};
110
113 uint64_t changes{};
114
117 uint64_t reserved{};
120 uint64_t held{};
123
130 pool_t kept;
133 std::array<int, max_layers + spare_slots> merged_into{};
134
136 int64_t now{};
138 int64_t ramp_end{};
139 int64_t ramp_len{1};
140
142 {
143 bool active{};
144 int at{};
145 int target{-1};
146 int a_slot{-1}, b_slot{-1};
149 float a_gain{};
150 float b_gain{1.f};
151 bool muted{};
153 bool undoable{};
154 audio_layer a{};
155 audio_layer b{};
158 bool lost_a{}, lost_b{};
159 int64_t a_len{}, b_len{};
160 int64_t merged{};
161 int64_t pos{};
162 } merging;
163
165 void allocate(int chans, int layer_count, int64_t frames)
166 {
167 chans = std::clamp(chans, 1, max_channels);
168 // One buffer for the recording and one at least for an overdub.
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)
172 return;
173
174 channels = chans;
175 slots = layer_count;
176 capacity = frames;
177 // A take still being written keeps the old memory.
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);
181 peaks.clear();
182 peaks.shrink_to_fit();
183 peaks.resize(std::size_t(buffers()) * peak_count(), 0.f);
184 kept.clear();
185 kept.shrink_to_fit();
186 kept.resize(std::size_t(buffers()) * 4 * std::size_t(channels) * fade_frames, 0.f);
187 merged_into.fill(-1);
188 ramp_end = 0;
189 count = 0;
190 total = 0;
191 length = 0;
192 reserved = 0;
193 held = 0;
194 merging = {};
195 unmerge = {};
196 aside = {};
197 merged_passes = {};
198 }
199
200 // pass_stack's hooks: the buffers of the passes move with them, and a
201 // merge going on is abandoned when the passes it merges move.
202 void passes_changed() noexcept
203 {
204 changes++;
205 update_gains();
206 }
207 bool may_remove(int) const noexcept { return true; }
208 void muting(int k) noexcept
209 {
210 // The merged pass is worked out with the mutes the two passes had.
211 if(k == merging.at || k == merging.at + 1)
212 merging.active = false;
213 }
214 void removing(int k) noexcept
215 {
216 if(k <= merging.at + 1)
217 merging.active = false;
218 }
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
226 {
227 for(int s : {unmerge.a.slot, unmerge.b.slot})
228 if(s >= 0 && s < buffers())
229 merged_into[s] = -1;
230 }
231 void cleared() noexcept
232 {
233 merging.active = false;
234 merged_into.fill(-1);
235 }
236 void undoing() noexcept { merging.active = false; }
237
238 int buffers() const noexcept { return slots + spare_slots; }
239
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
243 {
244 return std::size_t((capacity + peak_frames - 1) / peak_frames);
245 }
246
249 static float*
250 data_in(pool_t& p, int channels, int64_t capacity, int slot, int chan) noexcept
251 {
252 return p.data()
253 + (std::size_t(slot) * std::size_t(channels) + std::size_t(chan))
254 * std::size_t(capacity);
255 }
256 float* data(int slot, int chan) noexcept
257 {
258 return data_in(*pool, channels, capacity, slot, chan);
259 }
260 const float* data(int slot, int chan) const noexcept
261 {
262 return const_cast<audio_layers*>(this)->data(slot, chan);
263 }
264 float* peaks_of(int slot) noexcept
265 {
266 return peaks.data() + std::size_t(slot) * peak_count();
267 }
268
271 static int64_t index_in(const audio_layer& l, int64_t k, int64_t loop_length) noexcept
272 {
273 const int64_t p = period_in(l, loop_length);
274 return p > 0 ? k % p : 0;
275 }
276 static bool valid_in(const audio_layer& l, int64_t k, int64_t loop_length) noexcept
277 {
278 const int64_t p = period_in(l, loop_length);
279 if(l.written >= p)
280 return true;
281 int64_t d = k % p - l.start;
282 if(d < 0)
283 d += p;
284 return d < l.written;
285 }
286
287 int64_t index(const audio_layer& l, int64_t k) const noexcept
288 {
289 return index_in(l, k, length);
290 }
291 bool valid(const audio_layer& l, int64_t k) const noexcept
292 {
293 return valid_in(l, k, length);
294 }
295
298 void update_gains() noexcept
299 {
300 float g = 1.f;
301 for(int i = count - 1; i >= 0; i--)
302 {
303 auto& l = layers[i];
304 l.unmuted_gain = g;
305 l.gain = l.muted ? 0.f : g;
306 if(!l.muted)
307 g *= l.decay;
308 }
309 }
310
312 float heard_gain(const audio_layer& l) const noexcept
313 {
314 if(now >= ramp_end)
315 return l.gain;
316 return l.gain + (l.from - l.gain) * float(ramp_end - now) / float(ramp_len);
317 }
318
320 float mix(int c, int64_t k) const noexcept
321 {
322 float sum = 0.f;
323 for(int i = 0; i < count; i++)
324 {
325 const auto& l = layers[i];
326 if(l.muted || !valid(l, k))
327 continue;
328 const int64_t p = period_of(l);
329 float v = data(l.slot, c)[k % p];
330 if(p < length)
331 v *= repeat_weight(l, k, p, length);
332 sum += heard_gain(l) * v;
333 }
334 return sum;
335 }
336
339 static float seam_weight(bool tail, float rho, int64_t d, int n) noexcept
340 {
341 const float f = float(tail ? d + 1 : d) / float(n);
342 return rho + (1.f - rho) * f;
343 }
344
349 static float
350 repeat_weight(const audio_layer& l, int64_t k, int64_t p, int64_t len) noexcept
351 {
352 float w = 1.f;
353 for(const bool tail : {false, true})
354 {
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))
357 continue;
358 int64_t d = ((k % p - e.at) * e.dir) % p;
359 if(d < 0)
360 d += p;
361 if(d >= e.n)
362 continue;
363 int64_t seam = (k - e.dir * d) % len;
364 if(seam < 0)
365 seam += len;
366 int64_t met = tail ? (e.meet + e.dir) % len : e.at;
367 if(met < 0)
368 met += len;
369 if(seam != met)
370 w *= seam_weight(tail, 0.f, d, e.n) / seam_weight(tail, e.rho, d, e.n);
371 }
372 return w;
373 }
374
378 void cover(audio_layer& l, int64_t k) noexcept
379 {
380 const int64_t p = period_of(l);
381 if(p <= 0 || l.written >= p)
382 return;
383 if(l.written == 0)
384 {
385 l.start = k;
386 l.written = 1;
387 return;
388 }
389 int64_t d = (k - l.start) % p;
390 if(d < 0)
391 d += p;
392 if(d < l.written)
393 return;
394 const int64_t after = d - l.written;
395 const int64_t before = p - 1 - d;
396 if(after <= before)
397 {
398 silence(l, l.start + l.written, after);
399 l.written = d + 1;
400 }
401 else
402 {
403 silence(l, k + 1, before);
404 l.start = k;
405 l.written += before + 1;
406 }
407 l.written = std::min(l.written, p);
408 }
409
411 void silence(audio_layer& l, int64_t from, int64_t n) noexcept
412 {
413 const int64_t p = period_of(l);
414 if(p <= 0 || n <= 0)
415 return;
416 for(int c = 0; c < channels; c++)
417 {
418 float* d = data(l.slot, c);
419 for(int64_t i = 0; i < n; i++)
420 d[(from + i) % p] = 0.f;
421 }
422 }
423
427 bool extend(int64_t unit) noexcept { return pass_stack::extend(unit, capacity); }
428
430 void begin_recording() noexcept
431 {
432 auto& l = begin_first_pass();
433 l.slot = std::max(0, take_slot());
434 std::fill_n(peaks_of(l.slot), peak_count(), 0.f);
435 }
436
437 bool slot_used(int s) const noexcept
438 {
439 if(merging.active && merging.target == s)
440 return true;
441 if(unmerge.valid && (unmerge.a.slot == s || unmerge.b.slot == s))
442 return true;
443 if(aside.valid && !aside.returned && aside.layer.slot == s)
444 return true;
445 for(int i = 0; i < count; i++)
446 if(layers[i].slot == s)
447 return true;
448 return false;
449 }
450
451 bool is_reserved(int s) const noexcept { return ((reserved | held) >> s) & 1u; }
452
454 int take_slot() noexcept
455 {
456 int fallback = -1;
457 for(int s = 0; s < buffers(); s++)
458 {
459 if(slot_used(s))
460 continue;
461 if(!is_reserved(s))
462 {
463 buffer_reused(s);
464 return s;
465 }
466 if(fallback < 0)
467 fallback = s;
468 }
469 if(fallback >= 0)
470 {
472 buffer_reused(fallback);
473 }
474 return fallback;
475 }
476
478 template <typename F>
479 void for_each_kept(F&& f) noexcept
480 {
481 for(int i = 0; i < total; i++)
482 f(layers[i]);
483 if(aside.valid)
484 f(aside.layer);
485 if(unmerge.valid)
486 {
487 f(unmerge.a);
488 f(unmerge.b);
489 }
490 }
491
493 int resolve(int s) const noexcept
494 {
495 for(int i = 0; s >= 0 && s < buffers() && merged_into[s] >= 0 && i < buffers(); i++)
496 s = merged_into[s];
497 return s;
498 }
499
502 int heard_in(int s) const noexcept
503 {
504 s = resolve(s);
505 if(s < 0)
506 return -1;
507 for(int i = 0; i < count; i++)
508 if(layers[i].slot == s)
509 return layers[i].muted ? -1 : i;
510 return -1;
511 }
512
515 void buffer_reused(int s) noexcept
516 {
517 for_each_kept([&](audio_layer& l) {
518 for(auto* e : {&l.head, &l.tail})
519 {
520 if(e->partner == s)
521 e->partner = merged_into[s];
522 else if(e->partner >= 0 && resolve(e->partner) == s)
523 e->partner = -1;
524 }
525 });
526 for(auto& m : merged_into)
527 if(m == s)
528 m = -1;
529 merged_into[s] = -1;
530 }
531
532 float* kept_of(int slot, bool tail, bool part, int c) noexcept
533 {
534 return kept.data()
535 + ((std::size_t(slot) * 4 + (tail ? 2 : 0) + (part ? 1 : 0)) * std::size_t(channels)
536 + std::size_t(c))
537 * fade_frames;
538 }
539
541 int64_t seam_index(const audio_layer& l, const audio_seam_end& e, int64_t d) const noexcept
542 {
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;
546 }
547
551 void open_seam(audio_layer& l, bool tail, int partner) noexcept
552 {
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;
556 e = {};
557 if(p <= 0 || written <= 0 || !allocated() || kept.empty())
558 return;
559 const int64_t first = l.start % p;
560 const int64_t last = (l.start + written - 1) % p;
561 // Backwards, the part written grows towards the loop's start: its first
562 // frame is its last position.
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));
567 e.partner = partner;
568 e.rho = 1.f;
569 for(int c = 0; c < channels; c++)
570 {
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++)
575 orig[i] = part[i] = d[seam_index(l, e, i)];
576 }
577 }
578
580 void weigh_seam(audio_layer& l, bool tail, float rho) noexcept
581 {
582 auto& e = tail ? l.tail : l.head;
583 e.rho = rho;
584 for(int c = 0; c < channels; c++)
585 {
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++)
590 d[seam_index(l, e, i)] = orig[i] - part[i] * (1.f - seam_weight(tail, rho, i, e.n));
591 }
592 }
593
597 float settled_gain(const audio_layer& l) const noexcept
598 {
599 return now < ramp_end ? l.from : l.gain;
600 }
601
606 void update_seams() noexcept
607 {
608 for(int i = 0; i < count; i++)
609 {
610 auto& l = layers[i];
611 if(l.muted)
612 continue;
613 for(const bool tail : {false, true})
614 {
615 auto& e = tail ? l.tail : l.head;
616 if(e.at < 0 || e.partner == audio_seam_end::pending)
617 continue;
618 const int j = e.partner >= 0 ? heard_in(e.partner) : -1;
619 if(j == i)
620 continue;
621 float rho = 0.f;
622 if(j >= 0)
623 {
624 const float mine = settled_gain(l);
625 const float theirs = settled_gain(layers[j]);
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;
629 }
630 if(std::abs(rho - e.rho) > 1e-6f)
631 weigh_seam(l, tail, rho);
632 }
633 }
634 }
635
642 void begin_overdub(int64_t start, bool oldest = true, int replace = -1) noexcept
643 {
644 drop_redo();
645 forget_aside();
646 if(replace >= 0)
647 set_aside(replace);
648 if(!oldest && count > slots)
649 {
650 // The pass before it was not merged yet. Once merged, it can no more
651 // be taken out than when its merge ended before this pass: the two
652 // buffers kept for that are free for this one.
653 if(!merging.active)
654 start_merge(count - 2, true);
655 finish_merge();
656 drop_unmerge();
657 }
658 if(oldest && count >= slots && !merging.active)
659 start_merge(0);
660 // No buffer left for the pass, e.g. one more overdub while the last merge
661 // is not done: it is finished at once, which makes room.
662 if(take_slot_count() == 0)
663 {
664 finish_merge();
665 if(oldest && count >= slots)
666 start_merge(0);
667 }
668 const int slot = take_slot();
669 if(slot < 0)
670 return;
671 auto& l = push_pass();
672 l.slot = slot;
673 l.start = start;
674 std::fill_n(peaks_of(slot), peak_count(), 0.f);
675 }
676
677 int take_slot_count() const noexcept
678 {
679 int n = 0;
680 for(int s = 0; s < buffers(); s++)
681 n += !slot_used(s);
682 return n;
683 }
684
690 void start_merge(int at = 0, bool undoable = false) noexcept
691 {
692 if(at < 0 || at + 1 >= count || merging.active)
693 return;
694 const int target = take_slot();
695 if(target < 0)
696 return;
697 const auto& a = layers[at];
698 const auto& b = layers[at + 1];
699 // A muted pass merged with one that is not is left out of the merged one,
700 // and takes nothing from the pass under it: merging is where it is lost.
701 // Two muted passes make a muted one that has both.
702 const bool lost_a = a.muted && !b.muted, lost_b = b.muted && !a.muted;
703 merging = merge_state{
704 .active = true,
705 .at = at,
706 .target = target,
707 .a_slot = a.slot,
708 .b_slot = b.slot,
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,
713 .a = a,
714 .b = b,
715 .lost_a = lost_a,
716 .lost_b = lost_b,
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)),
720 .pos = 0};
721 }
722
726 void merge_step(int64_t frames) noexcept
727 {
728 auto& m = merging;
729 if(!m.active)
730 return;
731 if(m.at + 1 >= count || layers[m.at].slot != m.a_slot
732 || layers[m.at + 1].slot != m.b_slot)
733 {
734 m.active = false;
735 return;
736 }
737
738 // The merged pass is as long as the longer of the two: the shorter one
739 // repeats into it.
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++)
742 {
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++)
747 dst[k] = merged_at(da, db, k);
748 }
749 {
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);
753 const int64_t a_bins = std::max<int64_t>(1, (m.a_len + peak_frames - 1) / peak_frames);
754 const int64_t b_bins = std::max<int64_t>(1, (m.b_len + peak_frames - 1) / peak_frames);
755 for(int64_t i = m.pos / peak_frames; i < (end + peak_frames - 1) / peak_frames; i++)
756 pt[i] = m.a_gain * pa[i % a_bins] + m.b_gain * pb[i % b_bins];
757 }
758 m.pos = end;
759 if(m.pos < m.merged)
760 return;
761
762 m.active = false;
763 begin_merge();
764 // What the two took from the passes under them, the merged one takes.
765 audio_layer a = merged_pass(layers[m.at], layers[m.at + 1]);
766 merge_seams(a);
767 a.from = layers[m.at + 1].from;
768 a.slot = m.target;
769 a.decay = (m.lost_a ? 1.f : m.a.decay) * (m.lost_b ? 1.f : m.b.decay);
770 a.start = 0;
771 a.period = m.merged == length ? 0 : m.merged;
772 a.written = m.merged;
773 a.muted = m.muted;
774 a.backwards = false;
775 merged(m.at, a, m.undoable, m.a, m.b);
776 }
777
778 void finish_merge() noexcept
779 {
780 merge_step(merging.merged);
781 }
782
784 float merged_at(const float* da, const float* db, int64_t k) const noexcept
785 {
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))
791 {
792 va = da[k % m.a_len];
793 if(m.a_len < m.merged)
794 va *= repeat_weight(a, k, m.a_len, length);
795 }
796 if(valid_in(m.b, k, m.b_len))
797 {
798 vb = db[k % m.b_len];
799 if(m.b_len < m.merged)
800 vb *= repeat_weight(b, k, m.b_len, length);
801 }
802 return m.a_gain * va + m.b_gain * vb;
803 }
804
808 void merge_seams(audio_layer& into) noexcept
809 {
810 auto& m = merging;
811 const auto& a = layers[m.at];
812 const auto& b = layers[m.at + 1];
813 // The ends of the two are merged again from their buffers as they are
814 // now: a seam may have been weighed while the merge went on.
815 for(int c = 0; c < channels; c++)
816 {
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})
821 {
822 const int64_t p = std::max<int64_t>(1, period_of(*l));
823 for(const auto* e : {&l->head, &l->tail})
824 if(e->at >= 0)
825 for(int i = 0; i < e->n; i++)
826 for(int64_t k = seam_index(*l, *e, i); k < m.merged; k += p)
827 dst[k] = merged_at(da, db, k);
828 }
829 }
830
831 into.head = {};
832 into.tail = {};
833 const auto outer = [&](const audio_layer& l, bool tail, const audio_layer& other,
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);
838 };
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++)
843 {
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++)
849 {
850 to_part[i] = gain * part[i];
851 to_orig[i] = dst[seam_index(l, e, i)]
852 + to_part[i] * (1.f - seam_weight(tail, e.rho, i, e.n));
853 }
854 }
855 };
856 // One end a side: another one there is kept in the merged pass as it is
857 // heard now.
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);
866
867 merged_into[m.a_slot] = m.lost_a ? -1 : m.target;
868 merged_into[m.b_slot] = m.lost_b ? -1 : m.target;
869 }
870
875 void decay(float feedback, int64_t glide = fade_frames) noexcept
876 {
877 if(count < 2 || feedback >= 1.f)
878 return;
879 for(int i = 0; i < count; i++)
880 layers[i].from = heard_gain(layers[i]);
881 layers[count - 1].decay *= feedback;
882 update_gains();
883 ramp_len = std::max<int64_t>(1, glide);
884 ramp_end = now + ramp_len;
885 }
886
887 void note_peak(int slot, int64_t k, float v) noexcept
888 {
889 float& p = peaks_of(slot)[std::size_t(k / peak_frames)];
890 p = std::max(p, std::abs(v));
891 }
892
895 void fade_out_top() noexcept
896 {
897 auto* l = top();
898 if(!l || length <= 0 || l->written <= 0)
899 return;
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++)
903 {
904 float* d = data(l->slot, c);
905 for(int64_t i = 0; i < n; i++)
906 {
907 int64_t k = l->backwards ? (l->start + i) % p
908 : (l->start + std::min(l->written, p) - 1 - i) % p;
909 if(k < 0)
910 k += p;
911 d[k] *= float(i) / float(n);
912 }
913 }
914 }
915
919 void shift_earlier(audio_layer& l, int64_t frames) noexcept
920 {
921 const int64_t len = period_of(l);
922 if(len <= 0)
923 return;
924 // A negative count moves it later: the input of a pass the playhead went
925 // over backwards belongs further on in the loop.
926 frames %= len;
927 if(frames < 0)
928 frames += len;
929 if(frames <= 0)
930 return;
931 for(int c = 0; c < channels; c++)
932 {
933 float* d = data(l.slot, c);
934 std::rotate(d, d + frames, d + len);
935 }
936 float* p = peaks_of(l.slot);
937 const int64_t bins = (len + peak_frames - 1) / peak_frames;
938 const int64_t bin_shift = frames / peak_frames;
939 if(bin_shift > 0 && bins > 0)
940 std::rotate(p, p + (bin_shift % bins), p + bins);
941 l.start -= frames;
942 if(l.start < 0)
943 l.start += len;
944 for(auto* e : {&l.head, &l.tail})
945 if(e->at >= 0)
946 e->at = ((e->at - frames) % len + len) % len;
947 }
948};
949
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)
956{
957 std::fill(dst + from, dst + to, 0.f);
958 for(int i = 0; i < count; i++)
959 {
960 const auto& l = passes[i];
961 const float* src = data(l.slot, c);
962 const int64_t p = audio_layers::period_in(l, len);
963 for(int64_t k = from; k < to; k++)
964 if(audio_layers::valid_in(l, k, len))
965 dst[k] += l.gain * src[audio_layers::index_in(l, k, len)]
966 * (p < len ? audio_layers::repeat_weight(l, k, p, len) : 1.f);
967 }
968}
969
975{
976 std::shared_ptr<audio_layers::pool_t> pool;
977 std::array<audio_layer, audio_layers::max_passes> passes{};
978 int count{};
979 int channels{};
980 int64_t capacity{};
981 int64_t length{};
982
986 template <typename Out>
987 void flatten(int out_channels, Out&& out, int item = -1) const
988 {
989 if(!pool)
990 return;
991 auto& p = *pool;
992 const auto data = [&](int slot, int c) -> const float* {
993 return audio_layers::data_in(p, channels, capacity, slot, c);
994 };
995 for(int c = 0; c < std::min(out_channels, channels); c++)
996 {
997 float* dst = out(c);
998 if(item < 0)
999 {
1000 mix_passes(data, passes.data(), count, c, length, 0, length, dst);
1001 continue;
1002 }
1003 const auto& l = passes[item];
1004 const float* src = data(l.slot, c);
1005 const int64_t p = audio_layers::period_in(l, length);
1006 for(int64_t k = 0; k < length; k++)
1007 dst[k] = audio_layers::valid_in(l, k, length)
1008 ? l.unmuted_gain * src[audio_layers::index_in(l, k, length)]
1009 * (p < length ? audio_layers::repeat_weight(l, k, p, length) : 1.f)
1010 : 0.f;
1011 }
1012 }
1013};
1014}
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
STL namespace.
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
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
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