Switch out minimp3 with the dr_mp3 implementation

This commit is contained in:
Lukas Dürrenberger 2024-05-13 00:16:24 +02:00 committed by Lukas Dürrenberger
parent e39f48742b
commit 5646e05e8a
9 changed files with 4869 additions and 3333 deletions

View File

@ -180,13 +180,13 @@ if(SFML_USE_SYSTEM_DEPS)
foreach(DEP_FILE ${DEP_LIBS} ${DEP_BINS} ${DEP_HEADERS}) foreach(DEP_FILE ${DEP_LIBS} ${DEP_BINS} ${DEP_HEADERS})
get_filename_component(DEP_DIR ${DEP_FILE} PATH) get_filename_component(DEP_DIR ${DEP_FILE} PATH)
if(NOT DEP_DIR MATCHES "/(stb_image|minimp3)(/|$)") if(NOT DEP_DIR MATCHES "/(stb_image|dr_mp3)(/|$)")
list(APPEND CMAKE_IGNORE_PATH "${DEP_DIR}") list(APPEND CMAKE_IGNORE_PATH "${DEP_DIR}")
endif() endif()
get_filename_component(DEP_PARENT_DIR ${DEP_DIR} PATH) get_filename_component(DEP_PARENT_DIR ${DEP_DIR} PATH)
while(NOT DEP_PARENT_DIR STREQUAL "${CMAKE_SOURCE_DIR}/extlibs") while(NOT DEP_PARENT_DIR STREQUAL "${CMAKE_SOURCE_DIR}/extlibs")
if(NOT DEP_DIR MATCHES "/(stb_image|minimp3)(/|$)") if(NOT DEP_DIR MATCHES "/(stb_image|dr_mp3)(/|$)")
list(APPEND CMAKE_IGNORE_PATH "${DEP_PARENT_DIR}") list(APPEND CMAKE_IGNORE_PATH "${DEP_PARENT_DIR}")
endif() endif()

4837
extlibs/headers/dr_mp3/dr_mp3.h vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -66,11 +66,6 @@ public:
/// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC, MP3. /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC, MP3.
/// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit.
/// ///
/// Because of minimp3_ex limitation, for MP3 files with big (>16kb) APEv2 tag,
/// it may not be properly removed, tag data will be treated as MP3 data
/// and there is a low chance of garbage decoded at the end of file.
/// See also: https://github.com/lieff/minimp3
///
/// \param filename Path of the sound file to load /// \param filename Path of the sound file to load
/// ///
/// \return True if the file was successfully opened /// \return True if the file was successfully opened

View File

@ -18,4 +18,4 @@ Permission is granted to anyone to use this software for any purpose, including
* _libogg_ is under the BSD license * _libogg_ is under the BSD license
* _libvorbis_ is under the BSD license * _libvorbis_ is under the BSD license
* _libflac_ is under the BSD license * _libflac_ is under the BSD license
* _minimp3_ is under the CC0 license * _dr\_mp3_ is public domain

View File

@ -83,8 +83,8 @@ sfml_add_library(sfml-audio
# setup dependencies # setup dependencies
target_link_libraries(sfml-audio PRIVATE OpenAL) target_link_libraries(sfml-audio PRIVATE OpenAL)
# minimp3 sources # dr_mp3 sources
target_include_directories(sfml-audio SYSTEM PRIVATE "${PROJECT_SOURCE_DIR}/extlibs/headers/minimp3") target_include_directories(sfml-audio SYSTEM PRIVATE "${PROJECT_SOURCE_DIR}/extlibs/headers/dr_mp3")
if(SFML_OS_ANDROID) if(SFML_OS_ANDROID)
target_link_libraries(sfml-audio PRIVATE android OpenSLES) target_link_libraries(sfml-audio PRIVATE android OpenSLES)

View File

@ -25,30 +25,10 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#define MINIMP3_IMPLEMENTATION // Minimp3 control define, places implementation in this file. #define DR_MP3_IMPLEMENTATION
#ifndef NOMINMAX #define DR_MP3_NO_STDIO
#define NOMINMAX // To avoid windows.h and std::min issue #include <dr_mp3.h>
#endif #undef DR_MP3_NO_STDIO
#define MINIMP3_NO_STDIO // Minimp3 control define, eliminate file manipulation code which is useless here
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4242 4244 4267 4456 4706)
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#include <minimp3_ex.h>
#ifdef _MSC_VER
#pragma warning(pop)
#else
#pragma GCC diagnostic pop
#endif
#undef NOMINMAX
#undef MINIMP3_NO_STDIO
#include <SFML/Audio/SoundFileReaderMp3.hpp> #include <SFML/Audio/SoundFileReaderMp3.hpp>
#include <SFML/System/InputStream.hpp> #include <SFML/System/InputStream.hpp>
@ -60,17 +40,17 @@
namespace namespace
{ {
std::size_t readCallback(void* ptr, std::size_t size, void* data) std::size_t readCallback(void* userData, void* bufferOut, std::size_t bytesToRead)
{ {
sf::InputStream* stream = static_cast<sf::InputStream*>(data); sf::InputStream* stream = static_cast<sf::InputStream*>(userData);
return static_cast<std::size_t>(stream->read(ptr, static_cast<sf::Int64>(size))); return static_cast<std::size_t>(stream->read(bufferOut, static_cast<sf::Int64>(bytesToRead)));
} }
int seekCallback(uint64_t offset, void* data) drmp3_bool32 seekCallback(void* userData, int offset, drmp3_seek_origin /* origin */)
{ {
sf::InputStream* stream = static_cast<sf::InputStream*>(data); sf::InputStream* stream = static_cast<sf::InputStream*>(userData);
sf::Int64 position = stream->seek(static_cast<sf::Int64>(offset)); const sf::Int64 position = stream->seek(static_cast<sf::Int64>(offset));
return position < 0 ? -1 : 0; return position >= 0;
} }
bool hasValidId3Tag(const sf::Uint8* header) bool hasValidId3Tag(const sf::Uint8* header)
@ -94,7 +74,7 @@ bool SoundFileReaderMp3::check(InputStream& stream)
if (hasValidId3Tag(header)) if (hasValidId3Tag(header))
return true; return true;
if (hdr_valid(header)) if (drmp3_hdr_valid(header))
return true; return true;
return false; return false;
@ -106,36 +86,27 @@ SoundFileReaderMp3::SoundFileReaderMp3() :
m_numSamples(0), m_numSamples(0),
m_position(0) m_position(0)
{ {
std::memset(&m_io, 0, sizeof(m_io));
std::memset(&m_decoder, 0, sizeof(m_decoder));
m_io.read = readCallback;
m_io.seek = seekCallback;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundFileReaderMp3::~SoundFileReaderMp3() SoundFileReaderMp3::~SoundFileReaderMp3()
{ {
mp3dec_ex_close(&m_decoder); drmp3_uninit(&m_decoder);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool SoundFileReaderMp3::open(InputStream& stream, Info& info) bool SoundFileReaderMp3::open(InputStream& stream, Info& info)
{ {
// Init IO callbacks
m_io.read_data = &stream;
m_io.seek_data = &stream;
// Init mp3 decoder // Init mp3 decoder
mp3dec_ex_open_cb(&m_decoder, &m_io, MP3D_SEEK_TO_SAMPLE); if (drmp3_init(&m_decoder, readCallback, seekCallback, &stream, NULL) != 1)
if (!m_decoder.samples)
return false; return false;
// Retrieve the music attributes // Retrieve the music attributes
info.channelCount = static_cast<unsigned int>(m_decoder.info.channels); info.channelCount = static_cast<unsigned int>(m_decoder.channels);
info.sampleRate = static_cast<unsigned int>(m_decoder.info.hz); info.sampleRate = static_cast<unsigned int>(m_decoder.sampleRate);
info.sampleCount = m_decoder.samples; info.sampleCount = drmp3_get_pcm_frame_count(&m_decoder) * m_decoder.channels;
m_numSamples = info.sampleCount; m_numSamples = info.sampleCount;
return true; return true;
@ -146,15 +117,16 @@ bool SoundFileReaderMp3::open(InputStream& stream, Info& info)
void SoundFileReaderMp3::seek(Uint64 sampleOffset) void SoundFileReaderMp3::seek(Uint64 sampleOffset)
{ {
m_position = std::min(sampleOffset, m_numSamples); m_position = std::min(sampleOffset, m_numSamples);
mp3dec_ex_seek(&m_decoder, m_position); drmp3_seek_to_pcm_frame(&m_decoder, m_position);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Uint64 SoundFileReaderMp3::read(Int16* samples, Uint64 maxCount) Uint64 SoundFileReaderMp3::read(Int16* samples, Uint64 maxCount)
{ {
Uint64 toRead = std::min(maxCount, m_numSamples - m_position); // dr_mp3's PCM frame contains one sample per channel
toRead = static_cast<Uint64>(mp3dec_ex_read(&m_decoder, samples, static_cast<std::size_t>(toRead))); Uint64 toRead = std::min(maxCount, m_numSamples - m_position) / m_decoder.channels;
toRead = static_cast<Uint64>(drmp3_read_pcm_frames_s16(&m_decoder, toRead, samples)) * m_decoder.channels;
m_position += toRead; m_position += toRead;
return toRead; return toRead;
} }

View File

@ -28,24 +28,9 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#ifndef NOMINMAX #define DR_MP3_NO_STDIO
#define NOMINMAX // To avoid windows.h and std::min issue #include <dr_mp3.h>
#endif #undef DR_MP3_NO_STDIO
#define MINIMP3_NO_STDIO // Minimp3 control define, eliminate file manipulation code which is useless here
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4242 4244 4267 4456 4706)
#endif
#include <minimp3_ex.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#undef NOMINMAX
#undef MINIMP3_NO_STDIO
#include <SFML/Audio/SoundFileReader.hpp> #include <SFML/Audio/SoundFileReader.hpp>
#include <vector> #include <vector>
@ -129,8 +114,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
mp3dec_io_t m_io; drmp3 m_decoder;
mp3dec_ex_t m_decoder;
Uint64 m_numSamples; // Decompressed audio storage size Uint64 m_numSamples; // Decompressed audio storage size
Uint64 m_position; // Position in decompressed audio buffer Uint64 m_position; // Position in decompressed audio buffer
}; };