# `Rockbox.Decoder`
[🔗](https://github.com/tsirysndr/rockboxd/blob/master/bindings/elixir/lib/rockbox/decoder.ex#L1)

Decode an audio file to interleaved-stereo S16LE PCM, one chunk at a time.

Wraps the Rockbox codec engine. The codec state is process-wide, so only one
decoder may decode at a time — opening a second one blocks until the first is
freed. The handle is a NIF resource, freed by the BEAM garbage collector (no
explicit close needed).

# `t`

```elixir
@opaque t()
```

Opaque decoder handle (a NIF resource).

# `elapsed_ms`

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

Playback position last reported by the codec, in milliseconds.

# `finished`

```elixir
@spec finished(t()) :: {boolean(), integer()}
```

`{done, code}`: `done` is `true` once the track has ended; `code` is the exit
status (`0` = clean end, negative = codec error), valid only when `done`.

# `metadata`

```elixir
@spec metadata(t()) :: map()
```

Tags and stream properties (same shape as `Rockbox.Metadata.read/1`).

Returns a map with atom keys (`:codec`, `:title`, `:duration_ms`,
`:sample_rate`, a nested `:replaygain` map, …).

# `next_chunk`

```elixir
@spec next_chunk(t()) :: {binary(), pos_integer()} | :eof
```

Next buffer of decoded PCM as `{samples, sample_rate}`, or `:eof` at end of
track (or after a codec error — see `finished/1`).

`samples` is a little-endian int16 binary of interleaved stereo PCM (use
`Rockbox.Dsp.binary_to_samples/1` to convert it to a list).

# `open`

```elixir
@spec open(Path.t()) :: t() | nil
```

Open a decoder for the local audio file at `path`. Returns the handle, or
`nil` if the file cannot be opened / no codec recognises it.

# `seek_ms`

```elixir
@spec seek_ms(t(), non_neg_integer()) :: :ok
```

Request a seek to `ms` milliseconds.

---

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