Current section
Files
Jump to
Current section
Files
src/rockbox@decoder.erl
-module(rockbox@decoder).
-compile([no_auto_import, nowarn_ignored, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-export([open/1, metadata/1, next_chunk/1, seek_ms/2, elapsed_ms/1, finished/1]).
-export_type([decoder/0]).
-moduledoc(~" 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. It is a NIF resource, freed by the BEAM garbage collector —
no explicit close.").
-type decoder() :: any().
-file("src/rockbox/decoder.gleam", 18).
-spec open(binary()) -> decoder().
-doc(~" Open a decoder for the local audio file at `path`.").
open(Path) ->
rockbox_ffi_nif:decoder_open(Path).
-file("src/rockbox/decoder.gleam", 21).
-spec metadata(decoder()) -> rockbox@metadata:metadata().
-doc(~" Tags and stream properties (same shape as `metadata.read`).").
metadata(Decoder) ->
case gleam@dynamic@decode:run(json:decode(rockbox_ffi_nif:decoder_metadata_json(Decoder)), rockbox@metadata:decoder()) of
{ok, Meta} ->
Meta;
_value ->
erlang:error(#{
gleam_error => let_assert,
message => ~"Pattern match failed, no pattern matched the value.",
file => ~"src/rockbox/decoder.gleam",
module => ~"rockbox/decoder",
function => ~"metadata",
line => 22,
value => _value,
start => 826,
'end' => 923,
pattern_start => 837,
pattern_end => 845
})
end.
-file("src/rockbox/decoder.gleam", 55).
-spec chunk_decoder() -> gleam@dynamic@decode:decoder({bitstring(), integer()}).
chunk_decoder() ->
gleam@dynamic@decode:field(0, {decoder, fun gleam@dynamic@decode:decode_bit_array/1}, fun(Samples) ->
gleam@dynamic@decode:field(1, {decoder, fun gleam@dynamic@decode:decode_int/1}, fun(Rate) ->
gleam@dynamic@decode:success({Samples, Rate})
end)
end).
-file("src/rockbox/decoder.gleam", 30).
-spec next_chunk(decoder()) -> gleam@option:option({bitstring(), integer()}).
-doc(~" Next buffer of decoded PCM as `#(samples, sample_rate)`, where `samples` is
a little-endian int16 buffer of interleaved stereo PCM. `None` at end of
track (or after a codec error — see `finished`).").
next_chunk(Decoder) ->
case gleam@dynamic@decode:run(rockbox_ffi_nif:decoder_next_chunk(Decoder), chunk_decoder()) of
{ok, Chunk} ->
{some, Chunk};
{error, _} ->
none
end.
-file("src/rockbox/decoder.gleam", 39).
-spec seek_ms(decoder(), integer()) -> nil.
-doc(~" Request a seek to `ms` milliseconds.").
seek_ms(Decoder, Ms) ->
rockbox_ffi_nif:decoder_seek_ms(Decoder, Ms).
-file("src/rockbox/decoder.gleam", 43).
-spec elapsed_ms(decoder()) -> integer().
-doc(~" Playback position last reported by the codec, in milliseconds.").
elapsed_ms(Decoder) ->
rockbox_ffi_nif:decoder_elapsed_ms(Decoder).
-file("src/rockbox/decoder.gleam", 49).
-spec finished(decoder()) -> {boolean(), integer()}.
-doc(~" `#(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`.").
finished(Decoder) ->
rockbox_ffi_nif:decoder_finished(Decoder).