The looping layers under a TuningFork.Stage: named PCM buffers read from one
playhead, each at its own gain, replaceable at a bar boundary with a cross-fade.
A bed is nil when nothing loops. chunk/3 produces the next chunk of the mix and the
bed to carry forward; replace/3, gains/2 and drop/2 change what plays. A layer
reads from the playhead less the frame it started at: 0 unless it was added with
from_start: true, which starts it at its own beginning when it begins to sound.
Summary
Functions
The next frames frames of the mix, and the bed to carry forward.
The bed without the layers named in names; the others play on as they were.
Set the gain of the named layers; names not playing are ignored.
The playhead in frames, or nil for no bed.
Replace, or with keep: true extend, the playing set with pcms, a map of name to PCM.
Types
@type fade() :: %{ layers: %{required(term()) => layer()}, position: non_neg_integer(), left: non_neg_integer(), total: pos_integer() }
@type layer() :: %{pcm: binary(), gain: float(), start: non_neg_integer() | :fresh}
@type t() :: %TuningFork.Stage.Bed{ fade: nil | fade(), layers: %{required(term()) => layer()}, pending: nil | {%{required(term()) => layer()}, pos_integer(), non_neg_integer()}, position: non_neg_integer() }
Functions
@spec chunk(t() | nil, pos_integer(), pos_integer()) :: {binary(), t() | nil}
The next frames frames of the mix, and the bed to carry forward.
The bed without the layers named in names; the others play on as they were.
Set the gain of the named layers; names not playing are ignored.
@spec position(t() | nil) :: non_neg_integer() | nil
The playhead in frames, or nil for no bed.
Replace, or with keep: true extend, the playing set with pcms, a map of name to PCM.
opts are those of TuningFork.Stage.layers/3 plus :rate, needed to turn :fade_ms
into frames.