TuningFork.Pattern.Control (TuningFork v0.1.11)

Copy Markdown View Source

Patterns of control maps, built as a chain of setters that TuningFork.Kit turns into voices.

import TuningFork.Pattern.Control

n("<0 4 0 9 7>*16") |> scale("g:minor") |> transpose(-12) |> octave(3) |> shape(:saw)

Summary

Functions

Set cutoff, resonance, lpenv, lpsustain and lpdecay together from one knob, amount from 0.0 to 1.0. Any of them set later in the chain wins.

Attack, decay, sustain and release in one go. Any of them may be nil to leave that part of the envelope as it was.

The note a voicing is placed against, as TuningFork.Pattern.Voicing.render/2's :anchor.

How long the note takes to reach full level, in seconds.

Which bank the sounds come from: s("bd") |> bank("crate") plays the recording registered as crate_bd once TuningFork.Sample.Bank has it, as Strudel does, and until then the kit's own drum, adjusted for a name in TuningFork.Kit.banks/0.

A bandpass at this frequency, in hertz. cutoff/2 and ftype/2 in one.

How narrow the bandpass is. See bpf/2.

A pattern of chord symbols, each as %{chord: symbol}, for voicing/1.

Hold every sample for every samples. 1 changes nothing.

How hard the bus is compressed, 0.0 for not at all and 1.0 for flat.

Round every sample to bits bits: 16 is untouched, 1 is a square.

Where the filter turns over, in hertz. Lower is darker.

How long it takes to fall from full level to sustain/2, in seconds.

How much of the note comes back as an echo, 0.0 to 1.0. delaytime/2 is how far behind, in cycles, and delayfeedback/2 how much of each repeat survives into the next. The echoes are the note played again, quieter; echoes/1 makes them.

How much of each echo survives into the next, 0.0 to 1.0. See delay/2.

How far behind the echoes fall, in cycles. Default an eighth. See delay/2.

How hard to drive into a soft clipper, 0.0 for clean.

What a pattern has asked to be drawn as, or nil for nothing.

Move pattern earlier by amount cycles; a pattern of amounts applies each over its own span.

Turn every event carrying a :delay above zero into itself plus four echoes: the same event :delaytime cycles later each time (default 0.125, capped at 0.5), with :gain scaled by :delay and then by :delayfeedback per repeat (default 0.5, capped at 0.95), and :delay removed. Any other event is passed straight through.

The four echoes an event carrying a :delay above zero makes, as echoes/1 places them, and [] for any other event.

Frequency modulation depth, 0.0 upwards. fmh/2 sets the modulator's ratio to the note.

How much of the note the FM modulation takes to arrive, 0.0 to 1.0 of its length. Left out, the modulation is there from the first sample.

How high the modulator sits against the note, 1.0 being in unison. See fm/2.

Which kind of filter cutoff/2 makes: :lowpass (the default), :highpass or :bandpass, as an atom or string.

How loud, 0.0 to 1.0.

Highpass filter amount, 0.0 to 1.0. Higher is thinner.

How much the highpass peaks at its corner. Applies to ftype(:highpass) with cutoff/2, not to highpass/2.

Stack the pattern panned hard left with fun of it panned hard right.

jux/2 with the pattern panned to -amount and fun of it to amount: 1.0 is hard left and right, 0.0 leaves both in the middle.

Move pattern later by amount cycles; a pattern of amounts applies each over its own span.

How long the filter sweep takes to open, in seconds. Default 0.002.

How long the filter sweep takes to fall back, in seconds. Default 0.2.

Octaves the filter sweeps above cutoff/2 over the note, falling away over lpdecay/2.

The same as cutoff/2.

How long the filter sweep takes to release. See lpenv/2.

Where the filter sweep settles, 0.0 to 1.0 of the way up. Default 0.0.

Keep only the events of pattern that fall where source is true.

A pattern from mini-notation: mini("bd*2 [~ sn]").

How a voicing sits against its anchor: :below, :above, :root or :duck, or a string such as "root:g2" naming the anchor too.

A pattern of scale degrees, 0 being the root of the scale/2 ("c:major" without one). source is as for s/1; each value becomes %{degree: value}.

Set the degree on an existing pattern's events, as set/3 does.

A pattern of notes, by name or by MIDI number. source is as for s/1; each value becomes %{note: value}.

Set the note on an existing pattern's events, as set/3 does.

Which octave the scale sits in. Without one it is 3.

How many voicings along the dictionary's list voicing/1 moves.

Which bus this goes to, counting from zero. room/2, postgain/2, xfade/2 and compressor/2 apply per bus.

Where in the stereo field, -1.0 left to 1.0 right.

Phaser rate: how many times a second the notches sweep. phaserdepth/2 says how far.

How far the phaser's notches travel, 0.0 to 1.0. Default 0.5. See phaser/2.

Mark this row to be drawn as a pianoroll. A row not marked is not drawn.

How loud the bus is after everything else, 0.0 upwards.

How long the note takes to fall silent after it ends, in seconds.

How much the filter peaks at its cutoff: 0.707 is flat, 8 is a howl.

How much reverb the bus is heard through, 0.0 to 1.0. The reverb is shared by every event on the bus, and the loudest room asked for is the one applied. roomsize/2 says how big it is.

How long the room rings, in seconds to silence; 2 unless set. See room/2.

A pattern of sounds. source is mini-notation, a pattern, or a bare value; each value becomes %{sound: value} unless it is already a map.

Set the sound on an existing pattern's events, as set/3 does: n("0 1") |> s("hh").

Which scale n/1's degrees are in, as "root:name"; TuningFork.Scale lists the roots and names. Like every setter here, scale may be a plain value or a pattern; see set/3.

Mark this row to be drawn as an oscilloscope of the whole mix.

Merge the controls of other onto every event of pattern, keeping pattern's wholes: an event is cut into parts where other changes inside it, each part carrying other's map merged over the event's. Where other has nothing, the event is left alone.

Set control key on every event of a pattern.

The waveform: :sine, :saw, :square, :triangle or :noise. A number is Strudel's shape, a waveshaper from 0.0 to below 1.0, and goes on :waveshape instead.

roomsize/2 under Strudel's shorter name.

How fast a sample or oscillator runs, 1.0 being as written: 2.0 is an octave up and half as long. A negative value is taken as its absolute value.

Keep the values of pattern but the structure of source: an event for every true step of source, carrying the value pattern holds at that moment. x, t, 1 are true; ~, f, 0 are not.

The level the note holds at after its decay, 0.0 to 1.0.

Move every note by semitones, up or down.

How hard the note is struck, 0.0 to 1.0. Multiplies gain/2.

Vibrato rate, in hertz. vibmod/2 says how far.

Vibrato depth, in semitones. Default half a semitone. See vib/2.

Turn a pattern of chord symbols into their notes, one event per note with the symbol's timing and its other controls, as TuningFork.Pattern.Voicing.render/2 voices them under the event's :dict, :anchor, :mode, :offset and :degree. A string is chord/1 first. A symbol the dictionary does not know is silent.

Filter the sound into a vowel: "a", "e", "i", "o" or "u", as a string or atom.

Fade between this bus and the rest: 0.0 none of it, 0.5 equal, 1.0 all of it.

Functions

acid(pattern, amount)

Set cutoff, resonance, lpenv, lpsustain and lpdecay together from one knob, amount from 0.0 to 1.0. Any of them set later in the chain wins.

n("<0 4 0 9 7>*16") |> scale("g:minor") |> transpose(-12) |> shape(:saw) |> acid(0.55)

adsr(pattern, attack, decay, sustain, release)

@spec adsr(
  TuningFork.Pattern.t(),
  number() | nil,
  number() | nil,
  number() | nil,
  number() | nil
) ::
  TuningFork.Pattern.t()

Attack, decay, sustain and release in one go. Any of them may be nil to leave that part of the envelope as it was.

n("0 4") |> adsr(0.01, 0.1, 0.4, 0.2)

anchor(pattern, note)

The note a voicing is placed against, as TuningFork.Pattern.Voicing.render/2's :anchor.

attack(pattern, attack)

How long the note takes to reach full level, in seconds.

bank(pattern, name)

Which bank the sounds come from: s("bd") |> bank("crate") plays the recording registered as crate_bd once TuningFork.Sample.Bank has it, as Strudel does, and until then the kit's own drum, adjusted for a name in TuningFork.Kit.banks/0.

bpf(pattern, hz)

A bandpass at this frequency, in hertz. cutoff/2 and ftype/2 in one.

bpq(pattern, q)

How narrow the bandpass is. See bpf/2.

chord(source)

A pattern of chord symbols, each as %{chord: symbol}, for voicing/1.

chord("<Bbm9 Fm9>/4") |> voicing()

coarse(pattern, every)

Hold every sample for every samples. 1 changes nothing.

compressor(pattern, amount)

How hard the bus is compressed, 0.0 for not at all and 1.0 for flat.

crush(pattern, bits)

Round every sample to bits bits: 16 is untouched, 1 is a square.

cutoff(pattern, cutoff)

Where the filter turns over, in hertz. Lower is darker.

decay(pattern, decay)

How long it takes to fall from full level to sustain/2, in seconds.

delay(pattern, amount)

How much of the note comes back as an echo, 0.0 to 1.0. delaytime/2 is how far behind, in cycles, and delayfeedback/2 how much of each repeat survives into the next. The echoes are the note played again, quieter; echoes/1 makes them.

s("bd rim") |> delay(0.5) |> delaytime(0.125) |> delayfeedback(0.6)

delayfeedback(pattern, amount)

How much of each echo survives into the next, 0.0 to 1.0. See delay/2.

delaytime(pattern, cycles)

How far behind the echoes fall, in cycles. Default an eighth. See delay/2.

dict(pattern, name)

Which voicing dictionary voicing/1 reads: one of TuningFork.Pattern.Voicing.dictionaries/0.

distort(pattern, amount)

How hard to drive into a soft clipper, 0.0 for clean.

drawing(pattern)

@spec drawing(TuningFork.Pattern.t()) :: :pianoroll | :scope | nil

What a pattern has asked to be drawn as, or nil for nothing.

iex> TuningFork.Pattern.Control.drawing(TuningFork.Pattern.Control.s("bd"))
nil
iex> TuningFork.Pattern.Control.drawing(TuningFork.Pattern.Control.scope(TuningFork.Pattern.Control.s("bd")))
:scope

early(pattern, amounts)

Move pattern earlier by amount cycles; a pattern of amounts applies each over its own span.

echoes(pattern)

Turn every event carrying a :delay above zero into itself plus four echoes: the same event :delaytime cycles later each time (default 0.125, capped at 0.5), with :gain scaled by :delay and then by :delayfeedback per repeat (default 0.5, capped at 0.95), and :delay removed. Any other event is passed straight through.

echoes_of(event)

The four echoes an event carrying a :delay above zero makes, as echoes/1 places them, and [] for any other event.

fm(pattern, index)

Frequency modulation depth, 0.0 upwards. fmh/2 sets the modulator's ratio to the note.

note("c3") |> fm(3) |> fmh(2)

fmattack(pattern, portion)

How much of the note the FM modulation takes to arrive, 0.0 to 1.0 of its length. Left out, the modulation is there from the first sample.

fmh(pattern, ratio)

How high the modulator sits against the note, 1.0 being in unison. See fm/2.

ftype(pattern, kind)

Which kind of filter cutoff/2 makes: :lowpass (the default), :highpass or :bandpass, as an atom or string.

gain(pattern, gain)

How loud, 0.0 to 1.0.

highpass(pattern, highpass)

Highpass filter amount, 0.0 to 1.0. Higher is thinner.

hpf(pattern, amount)

The same as highpass/2.

hpq(pattern, q)

How much the highpass peaks at its corner. Applies to ftype(:highpass) with cutoff/2, not to highpass/2.

jux(pattern, fun)

Stack the pattern panned hard left with fun of it panned hard right.

s("bd*4") |> jux(&rev/1)

jux_by(pattern, amount, fun)

jux/2 with the pattern panned to -amount and fun of it to amount: 1.0 is hard left and right, 0.0 leaves both in the middle.

late(pattern, amounts)

Move pattern later by amount cycles; a pattern of amounts applies each over its own span.

lpattack(pattern, seconds)

How long the filter sweep takes to open, in seconds. Default 0.002.

lpdecay(pattern, seconds)

How long the filter sweep takes to fall back, in seconds. Default 0.2.

lpenv(pattern, octaves)

Octaves the filter sweeps above cutoff/2 over the note, falling away over lpdecay/2.

lpf(pattern, hz)

The same as cutoff/2.

lpq(pattern, q)

The same as resonance/2.

lprelease(pattern, seconds)

How long the filter sweep takes to release. See lpenv/2.

lpsustain(pattern, level)

Where the filter sweep settles, 0.0 to 1.0 of the way up. Default 0.0.

mask(pattern, source)

Keep only the events of pattern that fall where source is true.

s("bd*8") |> mask("1 0 1 1")

mini(source)

@spec mini(String.t()) :: TuningFork.Pattern.t()

A pattern from mini-notation: mini("bd*2 [~ sn]").

mode(pattern, mode)

How a voicing sits against its anchor: :below, :above, :root or :duck, or a string such as "root:g2" naming the anchor too.

n(source)

A pattern of scale degrees, 0 being the root of the scale/2 ("c:major" without one). source is as for s/1; each value becomes %{degree: value}.

iex> TuningFork.Pattern.first_cycle(TuningFork.Pattern.Control.n("0 4"))
[{0.0, 0.5, %{degree: 0}}, {0.5, 1.0, %{degree: 4}}]

n(pattern, source)

Set the degree on an existing pattern's events, as set/3 does.

note(source)

A pattern of notes, by name or by MIDI number. source is as for s/1; each value becomes %{note: value}.

iex> TuningFork.Pattern.first_cycle(TuningFork.Pattern.Control.note("c3 g3"))
[{0.0, 0.5, %{note: "c3"}}, {0.5, 1.0, %{note: "g3"}}]

note(pattern, source)

Set the note on an existing pattern's events, as set/3 does.

octave(pattern, octave)

Which octave the scale sits in. Without one it is 3.

offset(pattern, offset)

How many voicings along the dictionary's list voicing/1 moves.

orbit(pattern, bus)

Which bus this goes to, counting from zero. room/2, postgain/2, xfade/2 and compressor/2 apply per bus.

pan(pattern, pan)

Where in the stereo field, -1.0 left to 1.0 right.

phaser(pattern, hz)

Phaser rate: how many times a second the notches sweep. phaserdepth/2 says how far.

phaserdepth(pattern, depth)

How far the phaser's notches travel, 0.0 to 1.0. Default 0.5. See phaser/2.

pianoroll(pattern)

@spec pianoroll(TuningFork.Pattern.t()) :: TuningFork.Pattern.t()

Mark this row to be drawn as a pianoroll. A row not marked is not drawn.

n("<0 4 0 9 7>*16") |> scale("g:minor") |> acid(0.55) |> pianoroll()

postgain(pattern, gain)

How loud the bus is after everything else, 0.0 upwards.

release(pattern, release)

How long the note takes to fall silent after it ends, in seconds.

resonance(pattern, resonance)

How much the filter peaks at its cutoff: 0.707 is flat, 8 is a howl.

room(pattern, amount)

How much reverb the bus is heard through, 0.0 to 1.0. The reverb is shared by every event on the bus, and the loudest room asked for is the one applied. roomsize/2 says how big it is.

roomsize(pattern, size)

How long the room rings, in seconds to silence; 2 unless set. See room/2.

s(source)

A pattern of sounds. source is mini-notation, a pattern, or a bare value; each value becomes %{sound: value} unless it is already a map.

iex> TuningFork.Pattern.first_cycle(TuningFork.Pattern.Control.s("bd sn"))
[{0.0, 0.5, %{sound: "bd"}}, {0.5, 1.0, %{sound: "sn"}}]

s(pattern, source)

Set the sound on an existing pattern's events, as set/3 does: n("0 1") |> s("hh").

scale(pattern, scale)

Which scale n/1's degrees are in, as "root:name"; TuningFork.Scale lists the roots and names. Like every setter here, scale may be a plain value or a pattern; see set/3.

scope(pattern)

Mark this row to be drawn as an oscilloscope of the whole mix.

s("bd!4") |> scope()

set(pattern, other)

Merge the controls of other onto every event of pattern, keeping pattern's wholes: an event is cut into parts where other changes inside it, each part carrying other's map merged over the event's. Where other has nothing, the event is left alone.

n("0 4") |> set(chord("Bbm9")) |> voicing()

set(pattern, key, values)

Set control key on every event of a pattern.

value is a plain term, a pattern, or a mini-notation string. A pattern keeps the event's whole and cuts it into parts where the pattern changes inside it, as Pattern.app_left/3; where it has nothing the event is left out. An event whose value is not yet a map becomes %{key => value, sound: old_value}.

shape(pattern, amount)

The waveform: :sine, :saw, :square, :triangle or :noise. A number is Strudel's shape, a waveshaper from 0.0 to below 1.0, and goes on :waveshape instead.

size(pattern, size)

roomsize/2 under Strudel's shorter name.

speed(pattern, speed)

How fast a sample or oscillator runs, 1.0 being as written: 2.0 is an octave up and half as long. A negative value is taken as its absolute value.

struct(pattern, source)

Keep the values of pattern but the structure of source: an event for every true step of source, carrying the value pattern holds at that moment. x, t, 1 are true; ~, f, 0 are not.

s("bd") |> struct("x ~ x ~")

sustain(pattern, sustain)

The level the note holds at after its decay, 0.0 to 1.0.

transpose(pattern, semitones)

Move every note by semitones, up or down.

velocity(pattern, velocity)

How hard the note is struck, 0.0 to 1.0. Multiplies gain/2.

vib(pattern, hz)

Vibrato rate, in hertz. vibmod/2 says how far.

vibmod(pattern, semitones)

Vibrato depth, in semitones. Default half a semitone. See vib/2.

voicing(source)

Turn a pattern of chord symbols into their notes, one event per note with the symbol's timing and its other controls, as TuningFork.Pattern.Voicing.render/2 voices them under the event's :dict, :anchor, :mode, :offset and :degree. A string is chord/1 first. A symbol the dictionary does not know is silent.

chord("<C^7 Dm7 G7>") |> voicing() |> shape(:saw)

vowel(pattern, vowel)

Filter the sound into a vowel: "a", "e", "i", "o" or "u", as a string or atom.

xfade(pattern, amount)

Fade between this bus and the rest: 0.0 none of it, 0.5 equal, 1.0 all of it.