What a live-coding front end draws for a session row, as numbers rather than pictures.
View.sounding(row, cycle)
View.scope(row, cycle, cps)
Summary
Functions
How many columns wide a row of hits or notes is.
Every onset this cycle, as {column, value} with the value the pattern carried.
How tall a trace is drawn, cycles after the note that made it.
The columns a row strikes this cycle, for a row of drums. See notes/2.
The notes a row plays this cycle, as {column, midi note}.
Which column the playhead is in, from zero to columns/0 minus one.
A window of what this row alone sounds like, as samples from -1.0 to 1.0.
Where in a row's text the thing sounding right now was written, as {from, to}.
Where the last note before cycle began, in cycles. cycle itself when nothing has started
yet.
How long each note this cycle sounds for, as %{column => width in columns}. %{} for a
row that is off or will not parse.
Functions
@spec columns() :: pos_integer()
How many columns wide a row of hits or notes is.
@spec events(TuningFork.Session.row() | String.t(), number()) :: [ {non_neg_integer(), term()} ]
Every onset this cycle, as {column, value} with the value the pattern carried.
[] for a row that is parked or will not parse.
How tall a trace is drawn, cycles after the note that made it.
1.0 as the note lands, falling away over about 0.35 seconds to a floor of 0.12, quantised to 12 steps.
iex> TuningFork.Session.View.fade(0.0, 0.5)
1.0
iex> TuningFork.Session.View.fade(4.0, 0.5) == TuningFork.Session.View.fade(6.0, 0.5)
true
@spec hits(TuningFork.Session.row() | String.t(), number()) :: [non_neg_integer()]
The columns a row strikes this cycle, for a row of drums. See notes/2.
@spec notes(TuningFork.Session.row() | String.t(), number()) :: [ {non_neg_integer(), integer()} ]
The notes a row plays this cycle, as {column, midi note}.
column counts from zero up to columns/0. Values with no MIDI note, such as drum names,
are left out; hits/2 reports those.
@spec playhead(number()) :: non_neg_integer()
Which column the playhead is in, from zero to columns/0 minus one.
iex> TuningFork.Session.View.playhead(2.5)
16
@spec scope(TuningFork.Session.row() | String.t(), number(), number()) :: [float()]
A window of what this row alone sounds like, as samples from -1.0 to 1.0.
row is a map with a :source or a bare string. The window starts at the row's last note
before cycle (see struck/2) and is scaled by fade/2. [] for a row that is off or
will not parse.
@spec sounding(TuningFork.Session.row() | String.t(), number()) :: {non_neg_integer(), non_neg_integer()} | nil
Where in a row's text the thing sounding right now was written, as {from, to}.
Character offsets into the source. A row of plain notation is read as it stands; a row of
code has its first quoted string read, with the answer offset to where that string sits in
the line. nil for a row that is off, will not parse, or is sounding nothing at cycle.
iex> TuningFork.Session.View.sounding(%{source: "~ cp ~ cp"}, 0.3)
{2, 4}
@spec struck(TuningFork.Pattern.t(), number()) :: float()
Where the last note before cycle began, in cycles. cycle itself when nothing has started
yet.
@spec widths(TuningFork.Session.row() | String.t(), number()) :: %{ required(non_neg_integer()) => number() }
How long each note this cycle sounds for, as %{column => width in columns}. %{} for a
row that is off or will not parse.