diff --git a/src/audio/audio_source.cpp b/src/audio/audio_source.cpp index b9262b45..44de1d1b 100644 --- a/src/audio/audio_source.cpp +++ b/src/audio/audio_source.cpp @@ -34,6 +34,10 @@ auto TaggedStream::CurrentPosition() -> int64_t { return wrapped_->CurrentPosition(); } +auto TaggedStream::Size() -> std::optional { + return wrapped_->Size(); +} + auto TaggedStream::SetPreambleFinished() -> void { wrapped_->SetPreambleFinished(); } diff --git a/src/audio/fatfs_source.cpp b/src/audio/fatfs_source.cpp index f682cd0d..4fc5adbb 100644 --- a/src/audio/fatfs_source.cpp +++ b/src/audio/fatfs_source.cpp @@ -5,6 +5,7 @@ */ #include "fatfs_source.hpp" +#include #include #include @@ -66,4 +67,9 @@ auto FatfsSource::SeekTo(int64_t destination, SeekFrom from) -> void { auto FatfsSource::CurrentPosition() -> int64_t { return f_tell(file_.get()); } + +auto FatfsSource::Size() -> std::optional { + return f_size(file_.get()); +} + } // namespace audio diff --git a/src/audio/include/audio_source.hpp b/src/audio/include/audio_source.hpp index a54cb260..68145f5b 100644 --- a/src/audio/include/audio_source.hpp +++ b/src/audio/include/audio_source.hpp @@ -28,6 +28,8 @@ class TaggedStream : public codecs::IStream { auto CurrentPosition() -> int64_t override; + auto Size() -> std::optional override; + auto SetPreambleFinished() -> void override; private: diff --git a/src/audio/include/fatfs_source.hpp b/src/audio/include/fatfs_source.hpp index e4187d60..45ab34c6 100644 --- a/src/audio/include/fatfs_source.hpp +++ b/src/audio/include/fatfs_source.hpp @@ -34,6 +34,8 @@ class FatfsSource : public codecs::IStream { auto CurrentPosition() -> int64_t override; + auto Size() -> std::optional override; + FatfsSource(const FatfsSource&) = delete; FatfsSource& operator=(const FatfsSource&) = delete; @@ -41,4 +43,4 @@ class FatfsSource : public codecs::IStream { std::unique_ptr file_; }; -} // namespace audio \ No newline at end of file +} // namespace audio diff --git a/src/audio/include/readahead_source.hpp b/src/audio/include/readahead_source.hpp index bbc0da12..58076350 100644 --- a/src/audio/include/readahead_source.hpp +++ b/src/audio/include/readahead_source.hpp @@ -38,6 +38,8 @@ class ReadaheadSource : public codecs::IStream { auto CurrentPosition() -> int64_t override; + auto Size() -> std::optional override; + auto SetPreambleFinished() -> void override; ReadaheadSource(const ReadaheadSource&) = delete; @@ -55,4 +57,4 @@ class ReadaheadSource : public codecs::IStream { int64_t tell_; }; -} // namespace audio \ No newline at end of file +} // namespace audio diff --git a/src/audio/readahead_source.cpp b/src/audio/readahead_source.cpp index 35c5314f..aae878f8 100644 --- a/src/audio/readahead_source.cpp +++ b/src/audio/readahead_source.cpp @@ -47,8 +47,8 @@ auto ReadaheadSource::Read(cpp::span dest) -> ssize_t { // Fill the destination from our buffer, until either the buffer is drained // or the destination is full. while (!dest.empty() && (is_refilling_ || !xStreamBufferIsEmpty(buffer_))) { - size_t bytes_read = xStreamBufferReceive(buffer_, dest.data(), - dest.size_bytes(), 1); + size_t bytes_read = + xStreamBufferReceive(buffer_, dest.data(), dest.size_bytes(), 1); tell_ += bytes_read; bytes_written += bytes_read; dest = dest.subspan(bytes_read); @@ -102,6 +102,10 @@ auto ReadaheadSource::CurrentPosition() -> int64_t { return tell_; } +auto ReadaheadSource::Size() -> std::optional { + return wrapped_->Size(); +} + auto ReadaheadSource::SetPreambleFinished() -> void { readahead_enabled_ = true; BeginReadahead(); diff --git a/src/codecs/include/codec.hpp b/src/codecs/include/codec.hpp index 36dda8ff..8aa391b6 100644 --- a/src/codecs/include/codec.hpp +++ b/src/codecs/include/codec.hpp @@ -49,6 +49,8 @@ class IStream { virtual auto CurrentPosition() -> int64_t = 0; + virtual auto Size() -> std::optional = 0; + /* * Called by codecs to indicate that they've finished parsing any header data * within this stream, and are about to begin decoding. diff --git a/src/codecs/mad.cpp b/src/codecs/mad.cpp index 247e33bc..f36636a1 100644 --- a/src/codecs/mad.cpp +++ b/src/codecs/mad.cpp @@ -109,8 +109,9 @@ auto MadMp3Decoder::OpenStream(std::shared_ptr input) auto vbr_length = GetVbrLength(header); if (vbr_length) { output.total_samples = vbr_length.value() * channels; - } else { - // FIXME: calculate length using the filesize, assuming CBR. + } else if (input->Size() && header.bitrate > 0) { + auto cbr_length = input->Size().value() / (header.bitrate / 8); + output.total_samples = cbr_length * output.sample_rate_hz * channels; } return output; }