One line of music, written by moving a cursor measured in beats.
import TuningFork.Part
bass =
part(bpm: 112, synth: soft_bass)
|> play(:d2, 1.5)
|> play(:a2, 0.5)
Summary
Types
A voice for each note: called with the note, or nil for a hit with no pitch.
Functions
Put the cursor at an exact beat, forwards or back.
How far the part runs, in beats.
A number from low up to but not including high, and the part with its generator advanced.
Play every note of a chord at once, then move the cursor on by step beats.
Where the cursor is, in beats.
Change the part's level for everything after this point.
Call fun with the part with the given probability, and move on by step beats either
way.
The part's notes, as {beat, voice}, in the order they were played.
Move the part in the stereo field for everything after this point.
An empty part with its cursor at beat zero. Every part starts from its own beat zero; one
that comes in later begins with rest/2.
Play a run of notes, each step beats apart.
count independent choices from list, and the part with its generator advanced. The
result may repeat an element.
Play a note at the cursor and move the cursor on by step beats.
Play one of notes, chosen by the part's own generator, and move on by step beats.
Apply fun to the part times over, from wherever the cursor is.
Apply fun to the part times over, told which pass it is, counting from zero.
Move the cursor on by beats without playing anything.
Play a pattern of evenly spaced steps, each step beats apart.
Change the voice, or instrument/0, used for everything after this point.
Play a note without moving the cursor, for stacking a chord. Takes play/4's options.
Types
@type instrument() :: (atom() | number() | nil -> TuningFork.Voice.t())
A voice for each note: called with the note, or nil for a hit with no pitch.
@type step_entry() :: atom() | number() | TuningFork.Voice.t() | nil | {atom() | number() | TuningFork.Voice.t(), keyword()}
@type t() :: %TuningFork.Part{ bpm: float(), cursor: float(), fx: keyword(), gain: float(), notes: [{float(), TuningFork.Voice.t()}], pan: float(), rand: TuningFork.Rand.t(), synth: TuningFork.Voice.t() | instrument() | nil }
Functions
Put the cursor at an exact beat, forwards or back.
How far the part runs, in beats.
The later of the cursor and the end of its last-ringing note.
A number from low up to but not including high, and the part with its generator advanced.
Play every note of a chord at once, then move the cursor on by step beats.
notes is a list of note names or frequencies. opts are play/4's and apply to every
note of the chord.
Where the cursor is, in beats.
Change the part's level for everything after this point.
Call fun with the part with the given probability, and move on by step beats either
way.
probability runs 0.0 to 1.0 and is drawn from the part's own generator, which advances
whether or not fun is called.
@spec notes(t()) :: [{float(), TuningFork.Voice.t()}]
The part's notes, as {beat, voice}, in the order they were played.
Move the part in the stereo field for everything after this point.
Clamped to -1.0 to 1.0.
An empty part with its cursor at beat zero. Every part starts from its own beat zero; one
that comes in later begins with rest/2.
Options
:synth— the voice its notes are played with, or ainstrument/0asked for one per note; defaultnil, in which caseTuningFork.Voice.new/1is used per note:bpm— its tempo, default 120:gain— a level over everything in it, default 1.0:pan— where it sits,-1.0hard left to1.0hard right, default 0.0 centred:fx— effects applied to this part alone, as[echo: [...], reverb: [...]], default none:seed— seeds the part's own random generator, default 1
Play a run of notes, each step beats apart.
step may be a list, whose entries are used in turn and repeat: [0.5, 0.5, 1.0] is two
short and one long, over and over. opts are play/4's and apply to every note.
@spec pick(t(), [term()], non_neg_integer()) :: {[term()], t()}
count independent choices from list, and the part with its generator advanced. The
result may repeat an element.
Play a note at the cursor and move the cursor on by step beats.
note may be a note name, a frequency in Hz, or a whole TuningFork.Voice, which is
played as it stands without being pitched. step is how long until the next note, in beats,
independent of how long this note sounds.
Options
:release— how long the note sounds, in beats. Longer thanstepoverlaps the next:gain— this note's level, multiplied by the part's:pan— how far this note sits from where the part does,-1.0to1.0, added to the part's and clamped to that range:bend— semitones to arrive at by the end of the note;2bends up a tone:curves— modulation in full, asTuningFork.Voicetakes it. A:freqcurve given here supersedes:bend:synth— a voice, or ainstrument/0, for this note only, overriding the part's
Any option value of the form {:between, low, high} is drawn from the part's own generator
for each note.
|> play(:e4, 0.5, release: 3.0)
|> play(:e4, 1.0, bend: 2)
|> play(:e4, 1.0, curves: %{gain: Curve.linear(0.2, 1.0)})
Play one of notes, chosen by the part's own generator, and move on by step beats.
The same seed picks the same notes in the same order. opts are play/4's.
Apply fun to the part times over, from wherever the cursor is.
times may instead be a string of x and ., one per pass: fun is applied on an x,
and on a . the cursor moves on by as much as fun would have moved it, playing nothing.
|> repeat(4, &steps(&1, "x...x..."))
|> repeat("..xx", &steps(&1, "x...x..."))
@spec repeat_indexed(t(), pos_integer(), (t(), non_neg_integer() -> t())) :: t()
Apply fun to the part times over, told which pass it is, counting from zero.
Move the cursor on by beats without playing anything.
Play a pattern of evenly spaced steps, each step beats apart.
A string plays the part's own synth on x or X, plays at a ninth of full level on a digit
1 to 9 (multiplied into any :gain given), and rests on any other character. Spaces
are ignored. step defaults to 0.25.
|> steps("x..x..x.")
|> steps("x2x2x9x2", 0.25)A list places a different entry on each step. An entry is anything play/4 accepts, nil
for a rest, or {note, opts} for one step carrying its own options merged over opts:
|> steps([{:a3, release: 4.0}, nil, :c4, nil, :e4, nil, nil, nil])
@spec synth(t(), TuningFork.Voice.t() | instrument()) :: t()
Change the voice, or instrument/0, used for everything after this point.
Play a note without moving the cursor, for stacking a chord. Takes play/4's options.