diff options
author | Max Kellermann <max@duempel.org> | 2014-08-23 15:27:21 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2014-08-23 15:27:21 +0200 |
commit | 8808aad5292208579410f6160de4bff387772d61 (patch) | |
tree | ecf2c35d70ae93288a931f2ab86ec854de4c70c9 | |
parent | 6d7eaba845e3b1896a5b57391482a3326a6f26bd (diff) |
decoder/dsdiff: implement seeking
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | src/decoder/plugins/DsdiffDecoderPlugin.cxx | 33 |
2 files changed, 33 insertions, 2 deletions
@@ -42,7 +42,7 @@ ver 0.19 (not yet released) - audiofile: support scanning remote files - audiofile: log libaudiofile errors - dsdiff, dsf: report bit rate - - dsf: implement seeking + - dsdiff, dsf: implement seeking - dsf: support DSD512 - dsf: support multi-channel files - dsf: fix big-endian bugs diff --git a/src/decoder/plugins/DsdiffDecoderPlugin.cxx b/src/decoder/plugins/DsdiffDecoderPlugin.cxx index de72a0644..37dabc72d 100644 --- a/src/decoder/plugins/DsdiffDecoderPlugin.cxx +++ b/src/decoder/plugins/DsdiffDecoderPlugin.cxx @@ -350,6 +350,18 @@ bit_reverse_buffer(uint8_t *p, uint8_t *end) *p = bit_reverse(*p); } +static offset_type +TimeToFrame(double t, unsigned sample_rate) +{ + return offset_type(t * sample_rate / 8); +} + +static offset_type +TimeToOffset(double t, unsigned channels, unsigned sample_rate) +{ + return TimeToFrame(t, sample_rate) * channels; +} + /** * Decode one "DSD" chunk. */ @@ -358,6 +370,8 @@ dsdiff_decode_chunk(Decoder &decoder, InputStream &is, unsigned channels, unsigned sample_rate, const offset_type total_bytes) { + const offset_type start_offset = is.GetOffset(); + uint8_t buffer[8192]; const size_t sample_size = sizeof(buffer[0]); @@ -368,6 +382,23 @@ dsdiff_decode_chunk(Decoder &decoder, InputStream &is, auto cmd = decoder_get_command(decoder); for (offset_type remaining_bytes = total_bytes; remaining_bytes >= frame_size && cmd != DecoderCommand::STOP;) { + if (cmd == DecoderCommand::SEEK) { + double t = decoder_seek_where(decoder); + offset_type offset = TimeToOffset(t, channels, + sample_rate); + if (offset >= total_bytes) { + decoder_command_finished(decoder); + break; + } + + if (dsdlib_skip_to(&decoder, is, + start_offset + offset)) { + decoder_command_finished(decoder); + remaining_bytes = total_bytes - offset; + } else + decoder_seek_error(decoder); + } + /* see how much aligned data from the remaining chunk fits into the local buffer */ size_t now_size = buffer_size; @@ -417,7 +448,7 @@ dsdiff_stream_decode(Decoder &decoder, InputStream &is) (float) metadata.sample_rate; /* success: file was recognized */ - decoder_initialized(decoder, audio_format, false, songtime); + decoder_initialized(decoder, audio_format, is.IsSeekable(), songtime); /* every iteration of the following loop decodes one "DSD" chunk from a DFF file */ |