TuningFork.Session.View (TuningFork v0.1.0)

Copy Markdown View Source

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

columns()

@spec columns() :: pos_integer()

How many columns wide a row of hits or notes is.

events(row, cycle)

@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.

fade(cycles, cps)

@spec fade(number(), number()) :: float()

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

hits(row, cycle)

The columns a row strikes this cycle, for a row of drums. See notes/2.

notes(row, cycle)

@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.

playhead(cycle)

@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

scope(row, cycle, cps)

@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.

sounding(row, cycle)

@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}

struck(pattern, cycle)

@spec struck(TuningFork.Pattern.t(), number()) :: float()

Where the last note before cycle began, in cycles. cycle itself when nothing has started yet.

widths(row, cycle)

@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.