aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--NEWS1
-rw-r--r--src/decoder/plugins/DsfDecoderPlugin.cxx26
2 files changed, 26 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 350206b1b..26dbce533 100644
--- a/NEWS
+++ b/NEWS
@@ -42,6 +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
- dsf: support DSD512
- dsf: support multi-channel files
- dsf: fix big-endian bugs
diff --git a/src/decoder/plugins/DsfDecoderPlugin.cxx b/src/decoder/plugins/DsfDecoderPlugin.cxx
index 2e8bc4f2a..b85f7ce4f 100644
--- a/src/decoder/plugins/DsfDecoderPlugin.cxx
+++ b/src/decoder/plugins/DsfDecoderPlugin.cxx
@@ -243,6 +243,12 @@ InterleaveDsfBlock(uint8_t *gcc_restrict dest, const uint8_t *gcc_restrict src,
InterleaveDsfBlockGeneric(dest, src, channels);
}
+static offset_type
+TimeToBlock(double t, unsigned sample_rate)
+{
+ return offset_type(t * sample_rate / DSF_BLOCK_BITS);
+}
+
/**
* Decode one complete DSF 'data' chunk i.e. a complete song
*/
@@ -253,9 +259,27 @@ dsf_decode_chunk(Decoder &decoder, InputStream &is,
bool bitreverse)
{
const size_t block_size = channels * DSF_BLOCK_SIZE;
+ const offset_type start_offset = is.GetOffset();
auto cmd = decoder_get_command(decoder);
for (offset_type i = 0; i < n_blocks && cmd != DecoderCommand::STOP;) {
+ if (cmd == DecoderCommand::SEEK) {
+ double t = decoder_seek_where(decoder);
+ offset_type block = TimeToBlock(t, sample_rate);
+ if (block >= n_blocks) {
+ decoder_command_finished(decoder);
+ break;
+ }
+
+ offset_type offset =
+ start_offset + block * block_size;
+ if (dsdlib_skip_to(&decoder, is, offset)) {
+ decoder_command_finished(decoder);
+ i = block;
+ } else
+ decoder_seek_error(decoder);
+ }
+
/* worst-case buffer size */
uint8_t buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
if (!decoder_read_full(&decoder, is, buffer, block_size))
@@ -298,7 +322,7 @@ dsf_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);
dsf_decode_chunk(decoder, is, metadata.channels,
metadata.sample_rate,