From b0d85fc0d6ede34e4310d7d4fa69b8b94b8571b1 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 10 Oct 2023 13:13:41 +1100 Subject: [PATCH] Skip ID3 tags in the mad decoder; mad itself sometimes chokes on them --- src/codecs/include/mad.hpp | 1 + src/codecs/mad.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/codecs/include/mad.hpp b/src/codecs/include/mad.hpp index 2a8813e9..ef4e91f8 100644 --- a/src/codecs/include/mad.hpp +++ b/src/codecs/include/mad.hpp @@ -38,6 +38,7 @@ class MadMp3Decoder : public ICodec { MadMp3Decoder& operator=(const MadMp3Decoder&) = delete; private: + auto SkipID3Tags(IStream &stream) -> void; auto GetVbrLength(const mad_header& header) -> std::optional; auto GetBytesUsed() -> std::size_t; diff --git a/src/codecs/mad.cpp b/src/codecs/mad.cpp index 9f1655e9..224f7391 100644 --- a/src/codecs/mad.cpp +++ b/src/codecs/mad.cpp @@ -48,6 +48,8 @@ auto MadMp3Decoder::OpenStream(std::shared_ptr input) -> cpp::result { input_ = input; + SkipID3Tags(*input); + // To get the output format for MP3 streams, we simply need to decode the // first frame header. mad_header header; @@ -178,6 +180,32 @@ auto MadMp3Decoder::SeekTo(std::size_t target_sample) return {}; } +auto MadMp3Decoder::SkipID3Tags(IStream& stream) -> void { + // First check that the file actually does start with ID3 tags. + std::array magic_buf{}; + if (stream.Read(magic_buf) != 3) { + return; + } + if (std::memcmp(magic_buf.data(), "ID3", 3) != 0) { + stream.SeekTo(0, IStream::SeekFrom::kStartOfStream); + return; + } + + // The size of the tags (*not* including the 10-byte header) is located 6 + // bytes in. + std::array size_buf{}; + stream.SeekTo(6, IStream::SeekFrom::kStartOfStream); + if (stream.Read(size_buf) != 4) { + return; + } + // Size is encoded with 7-bit ints for some reason. + uint32_t tags_size = (static_cast(size_buf[0]) << (7 * 3)) | + (static_cast(size_buf[1]) << (7 * 2)) | + (static_cast(size_buf[2]) << 7) | + static_cast(size_buf[3]); + stream.SeekTo(10 + tags_size, IStream::SeekFrom::kStartOfStream); +} + /* * Implementation taken from SDL_mixer and modified. Original is zlib-licensed, * copyright (C) 1997-2022 Sam Lantinga