From d365c5394308740f478fbdfbb23e2c5d972f19f0 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 24 Jun 2018 17:46:39 +0300 Subject: [PATCH] Implement seeking in sound decoders This also fixes a bug in Mp3Decoder where the input buffer was not cleared on rewind so playback didn't immediately restart from the beginning. --- source/mp3decoder.cpp | 25 ++++++++++++++++++++++++- source/mp3decoder.h | 2 +- source/oggdecoder.cpp | 5 +++-- source/oggdecoder.h | 2 +- source/sounddecoder.h | 3 ++- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/source/mp3decoder.cpp b/source/mp3decoder.cpp index ec08be7..34604e3 100644 --- a/source/mp3decoder.cpp +++ b/source/mp3decoder.cpp @@ -87,9 +87,32 @@ bool Mp3Decoder::detect(const string &sig) return !sig.compare(0, sizeof(id3_sig), id3_sig); } -void Mp3Decoder::rewind() +void Mp3Decoder::seek(unsigned pos) { + unsigned unit = get_unit_size(format); + pos /= unit; + in.seek(0, IO::S_BEG); + mad_stream_buffer(&priv->stream, 0, 0); + fill_input(); + if(!pos) + { + priv->synth.pcm.length = 0; + return; + } + + while(decode(false)) + { + unsigned frame_len = 32*MAD_NSBSAMPLES(&priv->frame.header); + if(frame_len>pos) + { + decode(true); + read_pos = pos; + break; + } + + pos -= frame_len; + } } unsigned Mp3Decoder::read(char *buf, unsigned len) diff --git a/source/mp3decoder.h b/source/mp3decoder.h index c026081..201d68f 100644 --- a/source/mp3decoder.h +++ b/source/mp3decoder.h @@ -35,7 +35,7 @@ public: static bool detect(const std::string &); - virtual void rewind(); + virtual void seek(unsigned); virtual unsigned read(char *, unsigned); private: diff --git a/source/oggdecoder.cpp b/source/oggdecoder.cpp index 78a2b5a..cd2def8 100644 --- a/source/oggdecoder.cpp +++ b/source/oggdecoder.cpp @@ -109,9 +109,10 @@ bool OggDecoder::detect(const std::string &sig) return !sig.compare(0, sizeof(ogg_sig), ogg_sig); } -void OggDecoder::rewind() +void OggDecoder::seek(unsigned pos) { - ov_pcm_seek(&priv->ovfile, 0); + pos /= get_unit_size(format); + ov_pcm_seek(&priv->ovfile, pos); } unsigned OggDecoder::read(char *buf, unsigned len) diff --git a/source/oggdecoder.h b/source/oggdecoder.h index aab8f5c..3bf33b8 100644 --- a/source/oggdecoder.h +++ b/source/oggdecoder.h @@ -31,7 +31,7 @@ public: static bool detect(const std::string &); - virtual void rewind(); + virtual void seek(unsigned); virtual unsigned read(char *, unsigned); }; diff --git a/source/sounddecoder.h b/source/sounddecoder.h index ee5b07d..37fddac 100644 --- a/source/sounddecoder.h +++ b/source/sounddecoder.h @@ -37,7 +37,8 @@ public: static SoundDecoder *open_file(const std::string &); static SoundDecoder *open_io(IO::Seekable &); - virtual void rewind() = 0; + virtual void rewind() { seek(0); } + virtual void seek(unsigned) = 0; virtual unsigned read(char *, unsigned) = 0; bool eof() const { return eof_flag; } -- 2.43.0