# `TuningFork.Voice.Live`
[🔗](https://github.com/jaman/tuning_fork/blob/v0.1.11/tuning_fork/lib/tuning_fork/voice/live.ex#L1)

A voice rendered block by block, changeable between blocks.

    live = Live.start(voice, 44_100)
    {pcm, live} = Live.advance(live, 512)
    live = Live.control(live, freq: 660.0)
    {more, live} = Live.advance(live, 512)

# `t`

```elixir
@type t() :: %TuningFork.Voice.Live{
  frames: pos_integer(),
  index: non_neg_integer(),
  mod: map(),
  rate: pos_integer(),
  state: tuple(),
  voice: TuningFork.Voice.t()
}
```

# `advance`

```elixir
@spec advance(t(), pos_integer()) :: {binary(), t()}
```

The next `frames` frames of mono PCM, and the voice advanced past them.

Short at the end: a voice with 100 frames left asked for 512 gives 100. A voice already
finished gives an empty binary.

# `advance`

```elixir
@spec advance(t(), pos_integer(), pos_integer()) :: {binary(), t()}
```

The next `frames` frames panned for `channels` channels, and the voice advanced past them.
The pan is read once per block.

# `control`

```elixir
@spec control(t(), keyword() | map()) :: t()
```

Change the voice from the next block on.

`changes` are `TuningFork.Voice`'s fields, as a keyword list or a map; an unknown key
raises `KeyError`. Phase, filter state, noise seed and the note's length are untouched.

# `done?`

```elixir
@spec done?(t()) :: boolean()
```

Whether the voice has finished sounding.

# `release`

```elixir
@spec release(t(), float()) :: t()
```

Stop a voice early, falling to silence over `seconds` from the level it has reached.

The returned voice has a length of `seconds` and starts at frame zero; its curves are held
at the values they had reached and `:sweep` is 1.0.

# `remaining`

```elixir
@spec remaining(t()) :: non_neg_integer()
```

How many frames are left before it finishes.

# `start`

```elixir
@spec start(TuningFork.Voice.t(), pos_integer()) :: t()
```

Begin sounding a voice at `rate` samples per second.

The note's length is fixed here from the voice's envelope; only `release/2` changes it
afterwards.

---

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