# `TuningFork.SonicPi.Thread`
[🔗](https://github.com/jaman/tuning_fork/blob/v0.1.11/tuning_fork/lib/tuning_fork/sonic_pi/thread.ex#L1)

What one Sonic Pi thread carries while its code runs, and the score it played.

# `event`

```elixir
@type event() :: %{
  at: float(),
  voice: TuningFork.Voice.t(),
  ref: reference(),
  midi: number() | nil,
  amp: float(),
  segments: [reference()],
  controls: [{float(), keyword()}]
}
```

# `t`

```elixir
@type t() :: %TuningFork.SonicPi.Thread{
  ambient: boolean(),
  bpm: float(),
  capture: boolean(),
  events: [event()],
  fx: %{
    required(reference()) =&gt; %{
      name: atom(),
      opts: keyword(),
      segment: reference()
    }
  },
  fx_stack: [reference()],
  loops: [{atom(), (-&gt; term()), map(), float()}],
  now: float(),
  rand: TuningFork.Rand.t(),
  sample_defaults: keyword(),
  segments: %{required(reference()) =&gt; keyword()},
  synth: atom() | String.t() | TuningFork.Voice.t(),
  synth_defaults: keyword(),
  transpose: integer()
}
```

# `add`

```elixir
@spec add(t(), TuningFork.Voice.t() | [TuningFork.Voice.t()], reference(), keyword()) ::
  t()
```

Put a voice, or several, at the thread's time under one node reference.

# `close_fx`

```elixir
@spec close_fx(t(), reference()) :: t()
```

Close the innermost effect.

# `control_fx`

```elixir
@spec control_fx(t(), reference(), keyword()) :: t()
```

Change an open effect's options for everything played after this moment.

# `control_note`

```elixir
@spec control_note(t(), reference(), keyword()) :: t()
```

Record a change to every note under `ref`, taking effect at the thread's time.

# `draw`

```elixir
@spec draw(t(), (TuningFork.Rand.t() -&gt; {value, TuningFork.Rand.t()})) :: {value, t()}
when value: term()
```

Draw from the thread's generator with `fun`, keeping the generator that comes back.

# `new`

```elixir
@spec new(term(), keyword()) :: t()
```

A thread at time zero, seeded from `seed`. `capture: true` collects loops; `ambient: true` marks a thread nobody started a round or a buffer for.

# `open_fx`

```elixir
@spec open_fx(t(), atom(), keyword()) :: {reference(), t()}
```

Open an effect around what is played until `close_fx/2`.

# `score`

```elixir
@spec score(t(), :loop | :once) :: {:ok, TuningFork.Score.t()} | {:error, String.t()}
```

What the thread played, as a score.

As a `:loop`, the default, the score is as long as the thread slept, and
`{:error, message}` comes back when it never slept. Played `:once`, the score runs to the
end of the last note if that is later, and only a thread that played nothing is an error.

# `seconds`

```elixir
@spec seconds(t(), number()) :: float()
```

Seconds for `beats` at the thread's tempo.

# `sleep`

```elixir
@spec sleep(t(), number()) :: t()
```

Move the thread on by `beats`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
