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

The words of `TuningFork.SonicPi` that take a block, as functions taking a `fn`.

# `at`

```elixir
@spec at([number()] | number(), [term()], (-&gt; term()) | (term() -&gt; term())) :: :ok
```

Run `fun` once for each of `times`, each `time` beats from now, alongside the thread.

# `density`

```elixir
@spec density(pos_integer(), (-&gt; term())) :: :ok
```

Run `fun` `count` times at `count` times the tempo, so the passes fit the time one took.

# `first_round`

```elixir
@spec first_round((-&gt; term()), map(), number()) ::
  {:ok, TuningFork.Score.t()} | {:error, String.t()}
```

The first round of a loop: `delay` seconds of silence when there is a delay, else the round itself.

# `in_thread`

```elixir
@spec in_thread((-&gt; term())) :: :ok
```

Run `fun` alongside: it starts now and the thread's own time does not move.

# `live_loop`

```elixir
@spec live_loop(atom(), keyword(), (-&gt; term())) ::
  :ok | {:error, String.t()} | :collected
```

Start `fun` as loop `name` on a stage, worked out again every time round.

`:ok` once it is started, or `{:error, message}` when the first round will not run. Inside
`TuningFork.SonicPi.run/1` the loop is collected instead and `:collected` is returned.
`opts` may name a `:stage`, default `TuningFork.Stage`.

# `loop`

```elixir
@spec loop((-&gt; term())) :: :ok | {:error, String.t()} | :collected
```

Start `fun` as a loop named `loop_N`, the way `live_loop/3` does.

# `run_round`

```elixir
@spec run_round((-&gt; term()), map()) ::
  {:ok, TuningFork.Score.t()} | {:error, String.t()}
```

Run `fun` as one round of a loop and give the score it played.

`{:ok, score}` in seconds at 60 bpm, as long as the round's sleeps. `{:error, message}` when
the round never slept, was waiting on a `sync`, or returned something that is neither a
`TuningFork.Part` nor a `TuningFork.Score` while playing nothing. A round that returns a
part or a score gives that instead.

# `settings`

```elixir
@spec settings(TuningFork.SonicPi.Thread.t()) :: map()
```

The settings a loop started inside `thread` inherits: tempo, synth, defaults, transposition and open effects.

# `times`

```elixir
@spec times(non_neg_integer(), (-&gt; term()) | (non_neg_integer() -&gt; term())) :: :ok
```

Run `fun` `count` times, passing which pass it is from zero when it takes an argument.

# `with_bpm`

```elixir
@spec with_bpm(number(), (-&gt; result)) :: result when result: term()
```

Run `fun` at `bpm`, then go back to the tempo before.

# `with_fx`

```elixir
@spec with_fx(
  atom(),
  keyword(),
  (-&gt; term()) | (TuningFork.SonicPi.Handle.t() -&gt; term())
) :: term()
```

Run `fun` with everything it plays going through effect `name` with `opts`.

`fun` may take the effect's `TuningFork.SonicPi.Handle`, for `TuningFork.SonicPi.control/2`.

# `with_random_seed`

```elixir
@spec with_random_seed(term(), (-&gt; result)) :: result when result: term()
```

Run `fun` with the generator seeded from `seed`, then carry on from where it was.

# `with_synth`

```elixir
@spec with_synth(atom() | TuningFork.Voice.t(), (-&gt; result)) :: result
when result: term()
```

Run `fun` with `synth` as the synth, then go back to the one before.

# `with_synth_defaults`

```elixir
@spec with_synth_defaults(keyword(), (-&gt; result)) :: result when result: term()
```

Run `fun` with `opts` as the synth defaults, then go back.

# `with_transpose`

```elixir
@spec with_transpose(integer(), (-&gt; result)) :: result when result: term()
```

Run `fun` transposed by `semitones`, then go back.

---

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