Loading...
Searching...
No Matches
Inheritance diagram for Nodes::Looper::audio_layers:
Nodes::Looper::pass_stack< audio_layers, audio_layer, max_audio_layers >

Detailed Description

The audio of every pass of a loop, in buffers reserved before playback. The passes are a pass_stack; this is what the audio of each is.

slots buffers hold the passes, each capacity frames long for each channel, and spare_slots more are kept for merging: past slots passes, two layers are merged into a spare buffer a part per tick: the two oldest while the overdub that asked for room goes into the other one, or the newest and a pass that just ended over it. The memory is reserved without being written, so only what is recorded into is actually used. It is shared, so that a take of it written once the looper is gone still reads it.

Classes

struct  merge_state
 

Public Types

using pool_t = boost::container::vector< float >
 

Public Member Functions

void allocate (int chans, int layer_count, int64_t frames)
 Main thread only.
 
void passes_changed () noexcept
 
bool may_remove (int) const noexcept
 
void muting (int k) noexcept
 
void removing (int k) noexcept
 
void erased (int) noexcept
 
void aside_taken (int) noexcept
 
void aside_returned (int) noexcept
 
void aside_forgotten () noexcept
 
void redo_dropped (bool) noexcept
 
void unmerge_dropped () noexcept
 
void unmerged (int) noexcept
 
void cleared () noexcept
 
void undoing () noexcept
 
int buffers () const noexcept
 
bool allocated () const noexcept
 
bool empty () const noexcept
 
std::size_t peak_count () const noexcept
 
float * data (int slot, int chan) noexcept
 
const float * data (int slot, int chan) const noexcept
 
float * peaks_of (int slot) noexcept
 
int64_t index (const audio_layer &l, int64_t k) const noexcept
 
bool valid (const audio_layer &l, int64_t k) const noexcept
 
void update_gains () noexcept
 
float heard_gain (const audio_layer &l) const noexcept
 Gain pass l is heard with at frame now.
 
float mix (int c, int64_t k) const noexcept
 What the loop sounds like at position k of channel c.
 
void cover (audio_layer &l, int64_t k) noexcept
 
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.
 
bool extend (int64_t unit) noexcept
 
void begin_recording () noexcept
 Forgets every pass and starts a recording in a free buffer.
 
bool slot_used (int s) const noexcept
 
bool is_reserved (int s) const noexcept
 
int take_slot () noexcept
 A buffer no pass uses, one nothing else reads when there is one.
 
template<typename F >
void for_each_kept (F &&f) noexcept
 Every pass kept: heard, brought back by redo, set aside or merged.
 
int resolve (int s) const noexcept
 The buffer a merge forwarded buffer s to.
 
int heard_in (int s) const noexcept
 
void buffer_reused (int s) noexcept
 
float * kept_of (int slot, bool tail, bool part, int c) noexcept
 
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.
 
void open_seam (audio_layer &l, bool tail, int partner) noexcept
 
void weigh_seam (audio_layer &l, bool tail, float rho) noexcept
 Writes an end of pass l with weight rho next to its seam.
 
float settled_gain (const audio_layer &l) const noexcept
 
void update_seams () noexcept
 
void begin_overdub (int64_t start, bool oldest=true, int replace=-1) noexcept
 
int take_slot_count () const noexcept
 
void start_merge (int at=0, bool undoable=false) noexcept
 
void merge_step (int64_t frames) noexcept
 
void finish_merge () noexcept
 
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.
 
void merge_seams (audio_layer &into) noexcept
 
void decay (float feedback, int64_t glide=fade_frames) noexcept
 
void note_peak (int slot, int64_t k, float v) noexcept
 
void fade_out_top () noexcept
 
void shift_earlier (audio_layer &l, int64_t frames) noexcept
 
- Public Member Functions inherited from Nodes::Looper::pass_stack< audio_layers, audio_layer, max_audio_layers >
bool empty () const noexcept
 
audio_layer * top () noexcept
 
int64_t period_of (const audio_layer &l) const noexcept
 
int64_t period_of (int pass) const noexcept
 
int64_t merged_period (const audio_layer &a, const audio_layer &b) const noexcept
 The period two passes merged into one repeat with.
 
bool extend (int64_t unit, int64_t max_length, bool top_open=true) noexcept
 
bool set_muted (int k, bool m) noexcept
 Mutes or unmutes pass k, k being heard.
 
void clear () noexcept
 
audio_layer & begin_first_pass () noexcept
 Forgets every pass for a recording: its pass, the first one.
 
audio_layer & push_pass () noexcept
 Adds a pass over the ones heard, room having been made for it.
 
void drop_redo () noexcept
 
void forget_aside () noexcept
 Forgets the layer set aside.
 
void drop_unmerge () noexcept
 Undo is not to take the last merge apart: what it kept for that goes.
 
void set_aside (int k) noexcept
 
int returns_on_undo () const noexcept
 Undoing the top pass puts back the layer it replaced: where it goes.
 
int leaves_on_redo () const noexcept
 
void put_back () noexcept
 
bool undo () noexcept
 
bool redo () noexcept
 
bool erase (int k) noexcept
 
void begin_merge () noexcept
 A merge is about to be worked out: what it would make stale goes.
 
void merged (int at, const audio_layer &merged, bool undoable, const audio_layer &a, const audio_layer &b) noexcept
 
audio_layer merged_pass (const audio_layer &a, const audio_layer &b) const noexcept
 
bool replaced (uint64_t by, int self_pass, bool taking) const noexcept
 

Static Public Member Functions

static float * data_in (pool_t &p, int channels, int64_t capacity, int slot, int chan) noexcept
 
static int64_t index_in (const audio_layer &l, int64_t k, int64_t loop_length) noexcept
 
static bool valid_in (const audio_layer &l, int64_t k, int64_t loop_length) noexcept
 
static float seam_weight (bool tail, float rho, int64_t d, int n) noexcept
 
static float repeat_weight (const audio_layer &l, int64_t k, int64_t p, int64_t len) noexcept
 
- Static Public Member Functions inherited from Nodes::Looper::pass_stack< audio_layers, audio_layer, max_audio_layers >
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.
 

Public Attributes

std::shared_ptr< pool_t > pool
 
boost::container::vector< float > peaks
 
int channels {}
 
int slots {}
 
int64_t capacity {}
 
uint64_t changes {}
 
uint64_t reserved {}
 
uint64_t held {}
 
bool reserved_overwritten {}
 Set when a new pass had to go into a reserved buffer after all.
 
pool_t kept
 
std::array< int, max_layers+spare_slots > merged_into {}
 
int64_t now {}
 Frame counter of the processing: gains glide over frames of it.
 
int64_t ramp_end {}
 Gains glide from from to gain until ramp_end, over ramp_len frames.
 
int64_t ramp_len {1}
 
struct Nodes::Looper::audio_layers::merge_state merging
 
- Public Attributes inherited from Nodes::Looper::pass_stack< audio_layers, audio_layer, max_audio_layers >
std::array< audio_layer, max_passes+1 > layers
 The passes heard, then the ones redo brings back.
 
int count
 Passes heard.
 
int total
 Passes kept, the ones past count being what redo brings back.
 
int64_t length
 Frames in the loop.
 
uint64_t pushes
 
struct Nodes::Looper::pass_stack::unmerge_state unmerge
 
struct Nodes::Looper::pass_stack::aside_state aside
 
merge_log merged_passes
 

Static Public Attributes

static constexpr int spare_slots = 2
 
static constexpr int max_channels = 16
 
static constexpr int fade_frames = 128
 
static constexpr int peak_frames = 256
 Frames summed up into one point of the peak overview.
 
- Static Public Attributes inherited from Nodes::Looper::pass_stack< audio_layers, audio_layer, max_audio_layers >
static constexpr int max_layers
 Most layers kept: Max layers is at most this.
 
static constexpr int max_passes
 A pass past Max layers is one more until it is merged.
 

Member Function Documentation

◆ begin_overdub()

void Nodes::Looper::audio_layers::begin_overdub ( int64_t  start,
bool  oldest = true,
int  replace = -1 
)
inlinenoexcept

Starts an overdub pass at position start. With slots passes kept and oldest set, the two oldest start merging into one, so the oldest undo is lost; the new pass is heard at once, the merge going on in the following ticks. Without, the pass is one more, merged into the newest once it ends. replace, a pass heard, makes room for it instead: it is set aside, undo putting it back.

◆ buffer_reused()

void Nodes::Looper::audio_layers::buffer_reused ( int  s)
inlinenoexcept

Buffer s takes a new pass: the one it held is gone for good, and the seams that met it meet nothing now.

◆ cover()

void Nodes::Looper::audio_layers::cover ( audio_layer &  l,
int64_t  k 
)
inlinenoexcept

Position k of the loop was written by the pass: the part it wrote, which the playhead goes over without a gap in either direction, takes it in. A playhead that jumped leaves silence between that part and k.

◆ data_in()

static float * Nodes::Looper::audio_layers::data_in ( pool_t &  p,
int  channels,
int64_t  capacity,
int  slot,
int  chan 
)
inlinestaticnoexcept

Channel chan of buffer slot of a pool of channels channels of capacity frames a buffer.

◆ decay()

void Nodes::Looper::audio_layers::decay ( float  feedback,
int64_t  glide = fade_frames 
)
inlinenoexcept

Applies feedback to every pass under the top one, as one overdub pass goes round the loop. A muted pass takes nothing, but keeps what it would take for when it is heard again. The gains glide to their new values over glide frames from now: a step would click.

◆ extend()

bool Nodes::Looper::audio_layers::extend ( int64_t  unit)
inlinenoexcept

The top pass goes on past the end of the loop: the loop grows by unit frames, and the passes under it play again over the new part. False when the buffers are full.

◆ fade_out_top()

void Nodes::Looper::audio_layers::fade_out_top ( )
inlinenoexcept

The positions of the top pass that were written last, faded to silence so that the end of a punch does not click.

◆ heard_in()

int Nodes::Looper::audio_layers::heard_in ( int  s) const
inlinenoexcept

Index of the pass heard in buffer s, or the buffer it was merged into; -1 for none.

◆ index_in()

static int64_t Nodes::Looper::audio_layers::index_in ( const audio_layer &  l,
int64_t  k,
int64_t  loop_length 
)
inlinestaticnoexcept

Where position k of a loop of loop_length frames is in the layer's own buffer, and whether the pass was written there.

◆ merge_seams()

void Nodes::Looper::audio_layers::merge_seams ( audio_layer &  into)
inlinenoexcept

The seams of the two passes merged into into, which takes their ends at a seam with another pass: the lower pass's head, the upper one's tail. Where they meet each other is in it as it is heard now.

◆ merge_step()

void Nodes::Looper::audio_layers::merge_step ( int64_t  frames)
inlinenoexcept

Merges up to frames more frames; the merged pass takes the place of the two once they are all done. Abandoned when the passes it merges are no longer where they were.

◆ open_seam()

void Nodes::Looper::audio_layers::open_seam ( audio_layer &  l,
bool  tail,
int  partner 
)
inlinenoexcept

The first frames (head) or last frames (tail) pass l wrote meet a seam with the pass in buffer partner: they are kept as they are now, as recorded, to be weighed from.

◆ repeat_weight()

static float Nodes::Looper::audio_layers::repeat_weight ( const audio_layer &  l,
int64_t  k,
int64_t  p,
int64_t  len 
)
inlinestaticnoexcept

A pass shorter than the loop plays again over the rest of it: its ends at a seam meet the other side only where they were played, and are faded wherever else they are heard. What position k of a loop of len frames is weighed with, p being the pass's period.

◆ seam_weight()

static float Nodes::Looper::audio_layers::seam_weight ( bool  tail,
float  rho,
int64_t  d,
int  n 
)
inlinestaticnoexcept

Weight of frame d of an end of n frames at a seam, d = 0 being the one next to it: rho there, one past the end.

◆ settled_gain()

float Nodes::Looper::audio_layers::settled_gain ( const audio_layer &  l) const
inlinenoexcept

Gain a pass is heard with once the gains stop gliding, or the one they glide from: a seam is weighed for what is heard over it, which only changes once the playhead has left it.

◆ shift_earlier()

void Nodes::Looper::audio_layers::shift_earlier ( audio_layer &  l,
int64_t  frames 
)
inlinenoexcept

Moves a pass earlier in the loop by frames: what was recorded at position p belongs at p - frames, the input having reached the looper that late.

◆ start_merge()

void Nodes::Looper::audio_layers::start_merge ( int  at = 0,
bool  undoable = false 
)
inlinenoexcept

Starts merging pass at and the one over it into a spare buffer, the lower one scaled by the decay of the upper one, so that the merged pass is heard as the two were with the gain of the upper one. The two passes are heard as they are until the merged one takes their place. undoable keeps them for undo once merged.

◆ update_gains()

void Nodes::Looper::audio_layers::update_gains ( )
inlinenoexcept

Gives every pass heard its gain: the decays of the passes heard over it. Called whenever a decay or the passes heard change.

◆ update_seams()

void Nodes::Looper::audio_layers::update_seams ( )
inlinenoexcept

Each end of a pass heard at a seam is faded when the other side is not heard, as recorded when it is; the louder side starts at the level of the other, so that a pass with feedback over the one it went on from goes on from it at its level.

Member Data Documentation

◆ changes

uint64_t Nodes::Looper::audio_layers::changes {}

Counts the passes erased, so that what shows them knows it is not looking at the same ones although there are as many.

◆ held

uint64_t Nodes::Looper::audio_layers::held {}

Buffers a take written from the looper's stop reads: kept from new passes while there are others.

◆ kept

pool_t Nodes::Looper::audio_layers::kept

Two passes heard one over the other, at and the one over it, being merged into a spare buffer. The samples of the ends of passes at a seam as recorded, for each buffer, end and channel: what the buffer holds there without weight (orig), and the part of it that the pass's own end is (part), which is all of it but in a merged pass. Allocated with the buffers.

◆ merged_into

std::array<int, max_layers + spare_slots> Nodes::Looper::audio_layers::merged_into {}

The buffer each buffer was merged into, -1 for none: a seam's partner is the merged pass, until the merge is undone.

◆ reserved

uint64_t Nodes::Looper::audio_layers::reserved {}

Buffers something else still reads, e.g. a take being written: a new pass goes into another one when there is one.


The documentation for this struct was generated from the following file: