From ee52dc6261b4ba863e78390ae1722bae15bff312 Mon Sep 17 00:00:00 2001 From: Anders Pistol Date: Wed, 28 Feb 2024 15:10:01 +0100 Subject: [PATCH] Traktor: Replaced mpg123 with minimp3. --- code/Sound/Decoders/Mp3StreamDecoder.cpp | 223 ++++++----------------- resources/build/ExternLinux.xms | 38 +++- resources/build/TraktorAndroid.xms | 8 +- resources/build/TraktorLinux.xms | 22 ++- resources/build/TraktorOSX.xms | 10 +- resources/build/TraktorRPi.xms | 10 +- resources/build/TraktorWin64.xms | 16 +- scripts/config.bat | 1 + scripts/config.sh | 1 + scripts/misc/update-3rdp.run | 8 + 10 files changed, 132 insertions(+), 205 deletions(-) diff --git a/code/Sound/Decoders/Mp3StreamDecoder.cpp b/code/Sound/Decoders/Mp3StreamDecoder.cpp index 6d520de48b..4c035e0ee7 100644 --- a/code/Sound/Decoders/Mp3StreamDecoder.cpp +++ b/code/Sound/Decoders/Mp3StreamDecoder.cpp @@ -1,6 +1,6 @@ /* * TRAKTOR - * Copyright (c) 2022 Anders Pistol. + * Copyright (c) 2022-2024 Anders Pistol. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -9,8 +9,7 @@ #include #include #include -// #include -#include "Core/Io/IStream.h" +#include "Core/Io/BufferedStream.h" #include "Core/Log/Log.h" #include "Core/Memory/Alloc.h" #include "Core/Misc/Align.h" @@ -18,94 +17,56 @@ #include "Core/Serialization/ISerializable.h" #include "Sound/Decoders/Mp3StreamDecoder.h" -namespace traktor +#define MINIMP3_FLOAT_OUTPUT +#define MINIMP3_IMPLEMENTATION +#include "minimp3.h" +#include "minimp3_ex.h" + +namespace traktor::sound { - namespace sound - { -/* + class Mp3StreamDecoderImpl : public Object { public: - enum + static size_t callbackRead(void* buf, size_t size, void* userData) { - DecodedBufferSamples = 32768, - DecodedBufferSize = DecodedBufferSamples * sizeof(float), - ReadBufferSize = 4096 - }; - - Mp3StreamDecoderImpl() - : m_handle(0) - , m_decodedCount(0) - , m_consumedCount(0) - , m_sampleRate(0) - , m_channels(0) - , m_encoding(0) + auto this_ = (Mp3StreamDecoderImpl*)userData; + return this_->m_stream->read(buf, size); + } + + static int callbackSeek(uint64_t position, void* userData) { + auto this_ = (Mp3StreamDecoderImpl*)userData; + return this_->m_stream->seek(IStream::SeekSet, position) < 0 ? 1 : 0; } bool create(IStream* stream) { - size_t nrates; - const long* rates; - int ret; - - m_stream = stream; - - m_decoded[0] = (float*)Alloc::acquireAlign(DecodedBufferSize, 16, T_FILE_LINE); - m_decoded[1] = (float*)Alloc::acquireAlign(DecodedBufferSize, 16, T_FILE_LINE); - - if (!m_decoded[0] || !m_decoded[1]) - return false; - - if (ms_instances++ <= 0) - mpg123_init(); + m_stream = new BufferedStream(stream); - m_handle = mpg123_new(0, &ret); - if (!m_handle) - return false; - - ret = mpg123_format_none(m_handle); - if (ret != MPG123_OK) - return false; + m_io.read = &callbackRead; + m_io.read_data = this; + m_io.seek = &callbackSeek; + m_io.seek_data = this; - mpg123_rates(&rates, &nrates); - for (size_t i = 0; i < nrates; i++) + const int result = mp3dec_ex_open_cb(&m_dec, &m_io, MP3D_SEEK_TO_BYTE); + if (result < 0) { - ret = mpg123_format(m_handle, rates[i], MPG123_MONO | MPG123_STEREO, MPG123_ENC_FLOAT_32); - if (ret != MPG123_OK) - return false; - } - - ret = mpg123_open_feed(m_handle); - if (ret != MPG123_OK) + log::error << L"MP3 decoder failed to open, error " << result << Endl; return false; + } return true; } void destroy() { - mpg123_delete(m_handle); - - if (--ms_instances <= 0) - mpg123_exit(); - - Alloc::freeAlign(m_decoded[0]); - Alloc::freeAlign(m_decoded[1]); + mp3dec_ex_close(&m_dec); } void reset() { - // Inform mpg123 that we're seeking to the beginning. - off_t offset = 0; - mpg123_feedseek(m_handle, 0, SEEK_SET, &offset); - - // Move to correct position in our stream. - m_stream->seek(IStream::SeekSet, int(offset)); - - // Flush buffers. - m_decodedCount = 0; - m_consumedCount = 0; + mp3dec_ex_seek(&m_dec, 0); } double getDuration() const @@ -115,140 +76,76 @@ class Mp3StreamDecoderImpl : public Object bool getBlock(AudioBlock& outBlock) { - // Discard consumed samples; those are lingering in the decoded buffer since last call. - if (m_consumedCount) - { - T_ASSERT(m_consumedCount <= m_decodedCount); - std::memmove(m_decoded[SbcLeft], &m_decoded[SbcLeft][m_consumedCount], (m_decodedCount - m_consumedCount) * sizeof(float)); - std::memmove(m_decoded[SbcRight], &m_decoded[SbcRight][m_consumedCount], (m_decodedCount - m_consumedCount) * sizeof(float)); - m_decodedCount -= m_consumedCount; - m_consumedCount = 0; - } + T_FATAL_ASSERT(outBlock.samplesCount * m_dec.info.channels <= sizeof_array(m_buffer)); - // Read and decode until desired amount of samples have been decoded. - while (m_decodedCount < outBlock.samplesCount || m_sampleRate == 0) - { - int64_t nread = m_stream->read(m_readBuffer, sizeof(m_readBuffer)); - if (nread <= 0) - { - // No more bytes from source stream; if we have encoded some samples lets output them - // and return success. - if (m_decodedCount > 0) - break; - return false; - } + const size_t samplesRead = mp3dec_ex_read(&m_dec, m_buffer, outBlock.samplesCount * m_dec.info.channels); + if (samplesRead == 0) + return false; - int32_t ret = mpg123_feed(m_handle, m_readBuffer, nread); - if (ret == MPG123_NEED_MORE) - continue; - if (ret == MPG123_ERR) - return false; + outBlock.maxChannel = m_dec.info.channels; + outBlock.sampleRate = m_dec.info.hz; + outBlock.samplesCount = samplesRead / m_dec.info.channels; - while (ret != MPG123_NEED_MORE) + for (int32_t i = 0; i < outBlock.maxChannel; ++i) + { + for (int32_t j = 0; j < outBlock.samplesCount; ++j) { - uint8_t* audio; - size_t bytes; - off_t num; - - ret = mpg123_decode_frame(m_handle, &num, &audio, &bytes); - if (ret == MPG123_ERR) - return false; - if (ret == MPG123_NEW_FORMAT) - { - mpg123_getformat(m_handle, &m_sampleRate, &m_channels, &m_encoding); - if (m_encoding != MPG123_ENC_FLOAT_32) - return false; - } - - if (m_channels > 0) - { - int32_t sampleCount = int32_t(bytes / (m_channels * sizeof(float))); - int32_t channels = std::min(m_channels, 2); - for (int32_t i = 0; i < sampleCount * m_channels; i += m_channels) - { - for (int32_t j = 0; j < channels; ++j) - { - float s = ((const float*)audio)[i + j]; - m_decoded[j][m_decodedCount] = s; - } - if (++m_decodedCount >= DecodedBufferSize) - break; - } - } + const float s = m_buffer[j * outBlock.maxChannel + i]; + m_samples[i][j] = s; } + outBlock.samples[i] = m_samples[i]; } - outBlock.samples[SbcLeft] = m_decoded[SbcLeft]; - outBlock.samples[SbcRight] = m_decoded[SbcRight]; - outBlock.samplesCount = alignDown(std::min(m_decodedCount, outBlock.samplesCount), 4); - outBlock.sampleRate = uint32_t(m_sampleRate); - outBlock.maxChannel = m_channels; - - m_consumedCount = outBlock.samplesCount; - - if (!outBlock.samplesCount || !outBlock.sampleRate) - return false; - return true; } private: - static int32_t ms_instances; Ref< IStream > m_stream; - mpg123_handle* m_handle; - uint8_t m_readBuffer[ReadBufferSize]; - float* m_decoded[2]; - uint32_t m_decodedCount; - uint32_t m_consumedCount; - long m_sampleRate; - int32_t m_channels; - int32_t m_encoding; + mp3dec_io_t m_io; + mp3dec_ex_t m_dec; + mp3d_sample_t m_buffer[2 * 4096]; + float m_samples[2][4096]; }; -int32_t Mp3StreamDecoderImpl::ms_instances = 0; -*/ T_IMPLEMENT_RTTI_FACTORY_CLASS(L"traktor.sound.Mp3StreamDecoder", 0, Mp3StreamDecoder, IStreamDecoder) bool Mp3StreamDecoder::create(IStream* stream) { - if ((m_stream = stream) == 0) + if ((m_stream = stream) == nullptr) return false; - // m_decoderImpl = new Mp3StreamDecoderImpl(); - // if (!m_decoderImpl->create(m_stream)) - // { - // m_decoderImpl = 0; - // m_stream = 0; - // return false; - // } + m_decoderImpl = new Mp3StreamDecoderImpl(); + if (!m_decoderImpl->create(m_stream)) + { + m_decoderImpl = nullptr; + m_stream = nullptr; + return false; + } return true; } void Mp3StreamDecoder::destroy() { - // safeDestroy(m_decoderImpl); + safeDestroy(m_decoderImpl); } double Mp3StreamDecoder::getDuration() const { - // T_ASSERT(m_decoderImpl); - // return m_decoderImpl->getDuration(); - return 0.0; + T_ASSERT(m_decoderImpl); + return m_decoderImpl->getDuration(); } bool Mp3StreamDecoder::getBlock(AudioBlock& outBlock) { - // T_ASSERT(m_decoderImpl); - // return m_decoderImpl->getBlock(outBlock); - return false; + T_ASSERT(m_decoderImpl); + return m_decoderImpl->getBlock(outBlock); } void Mp3StreamDecoder::rewind() { - // T_ASSERT(m_decoderImpl); - // m_decoderImpl->reset(); + T_ASSERT(m_decoderImpl); + m_decoderImpl->reset(); } - } } diff --git a/resources/build/ExternLinux.xms b/resources/build/ExternLinux.xms index f8b8941cf5..bfd4ecfbcb 100644 --- a/resources/build/ExternLinux.xms +++ b/resources/build/ExternLinux.xms @@ -3076,7 +3076,7 @@ false - Extern.mpg123-1.13.2 + Extern.mpg123 $(MPG123_SDK) @@ -3086,13 +3086,18 @@ $(MPG123_SDK)/src + $(MPG123_SDK)/src/include $(MPG123_SDK)/src/compat $(MPG123_SDK)/src/libmpg123 + $(TRAKTOR_HOME)/resources/build/patch/mpg123 T_MPG123_EXPORT _DEBUG - OPT_I386 + OPT_MULTI + OPT_GENERIC + OPT_GENERIC_DITHER + REAL_IS_FLOAT @@ -3113,13 +3118,18 @@ $(MPG123_SDK)/src + $(MPG123_SDK)/src/include $(MPG123_SDK)/src/compat $(MPG123_SDK)/src/libmpg123 + $(TRAKTOR_HOME)/resources/build/patch/mpg123 T_MPG123_EXPORT NDEBUG - OPT_I386 + OPT_MULTI + OPT_GENERIC + OPT_GENERIC_DITHER + REAL_IS_FLOAT @@ -3140,13 +3150,17 @@ $(MPG123_SDK)/src + $(MPG123_SDK)/src/include $(MPG123_SDK)/src/compat $(MPG123_SDK)/src/libmpg123 + $(TRAKTOR_HOME)/resources/build/patch/mpg123 - T_STATIC _DEBUG - OPT_I386 + OPT_MULTI + OPT_GENERIC + OPT_GENERIC_DITHER + REAL_IS_FLOAT @@ -3159,7 +3173,7 @@ - libExtern.mpg123-1.13.2.a + libExtern.mpg123.a debugstatic @@ -3172,13 +3186,17 @@ $(MPG123_SDK)/src + $(MPG123_SDK)/src/include $(MPG123_SDK)/src/compat $(MPG123_SDK)/src/libmpg123 + $(TRAKTOR_HOME)/resources/build/patch/mpg123 - T_STATIC NDEBUG - OPT_I386 + OPT_MULTI + OPT_GENERIC + OPT_GENERIC_DITHER + REAL_IS_FLOAT @@ -3191,7 +3209,7 @@ - libExtern.mpg123-1.13.2.a + libExtern.mpg123.a releasestatic @@ -3204,7 +3222,7 @@ src/libmpg123/*.c - + *altivec*;*_arm*;*_i486* diff --git a/resources/build/TraktorAndroid.xms b/resources/build/TraktorAndroid.xms index b0158bf7b4..c0526a32da 100644 --- a/resources/build/TraktorAndroid.xms +++ b/resources/build/TraktorAndroid.xms @@ -2546,6 +2546,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) __ANDROID__ @@ -2579,6 +2580,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) __ANDROID__ @@ -2718,12 +2720,6 @@ ExternAndroid.xms Extern.flac - - true - LnkYes - ExternAndroid.xms - Extern.mpg123-1.13.2 - true LnkYes diff --git a/resources/build/TraktorLinux.xms b/resources/build/TraktorLinux.xms index adbe3bbfba..34cba52345 100644 --- a/resources/build/TraktorLinux.xms +++ b/resources/build/TraktorLinux.xms @@ -6591,7 +6591,9 @@ TfSharedLibrary TpDebug - + + $(MINIMP3_SDK) + T_SOUND_EXPORT _DEBUG @@ -6620,7 +6622,9 @@ TfSharedLibrary TpRelease - + + $(MINIMP3_SDK) + T_SOUND_EXPORT NDEBUG @@ -6649,7 +6653,9 @@ TfStaticLibrary TpDebug - + + $(MINIMP3_SDK) + T_STATIC _DEBUG @@ -6678,7 +6684,9 @@ TfStaticLibrary TpRelease - + + $(MINIMP3_SDK) + T_STATIC NDEBUG @@ -6817,12 +6825,6 @@ ExternLinux.xms Extern.flac - - true - LnkYes - ExternLinux.xms - Extern.mpg123-1.13.2 - true LnkYes diff --git a/resources/build/TraktorOSX.xms b/resources/build/TraktorOSX.xms index 206bdabf23..0a59280351 100644 --- a/resources/build/TraktorOSX.xms +++ b/resources/build/TraktorOSX.xms @@ -6511,6 +6511,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) T_SOUND_EXPORT @@ -6543,6 +6544,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) T_SOUND_EXPORT @@ -6575,6 +6577,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) T_STATIC @@ -6606,6 +6609,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) T_STATIC @@ -6748,12 +6752,6 @@ LnkYes - - true - LnkYes - ExternOSX.xms - Extern.mpg123-1.13.2 - true LnkYes diff --git a/resources/build/TraktorRPi.xms b/resources/build/TraktorRPi.xms index 8ad92083c7..5d0bd3b221 100644 --- a/resources/build/TraktorRPi.xms +++ b/resources/build/TraktorRPi.xms @@ -5737,6 +5737,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) T_SOUND_EXPORT @@ -5769,6 +5770,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) T_SOUND_EXPORT @@ -5801,6 +5803,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) T_STATIC @@ -5833,6 +5836,7 @@ $(TRAKTOR_HOME)/code $(TRAKTOR_HOME)/3rdp/flac-1.2.1/include $(STB_SDK) + $(MINIMP3_SDK) T_STATIC @@ -5971,12 +5975,6 @@ ExternRPi.xms Extern.flac - - true - LnkYes - ExternRPi.xms - Extern.mpg123-1.13.2 - true LnkYes diff --git a/resources/build/TraktorWin64.xms b/resources/build/TraktorWin64.xms index 00fcbbc88f..d01ac9b14c 100644 --- a/resources/build/TraktorWin64.xms +++ b/resources/build/TraktorWin64.xms @@ -6546,7 +6546,9 @@ TfSharedLibrary TpDebug - + + $(MINIMP3_SDK) + T_SOUND_EXPORT T_SOUND_USE_AVX_MIXER @@ -6582,7 +6584,9 @@ TfSharedLibrary TpRelease - + + $(MINIMP3_SDK) + T_SOUND_EXPORT T_SOUND_USE_AVX_MIXER @@ -6618,7 +6622,9 @@ TfStaticLibrary TpDebug - + + $(MINIMP3_SDK) + T_STATIC T_SOUND_USE_AVX_MIXER @@ -6650,7 +6656,9 @@ TfStaticLibrary TpRelease - + + $(MINIMP3_SDK) + T_STATIC T_SOUND_USE_AVX_MIXER diff --git a/scripts/config.bat b/scripts/config.bat index b88305246b..b5218b36dc 100755 --- a/scripts/config.bat +++ b/scripts/config.bat @@ -38,6 +38,7 @@ set XATLAS_SDK=%TRAKTOR_HOME%\3rdp\xatlas set ZLIB_SDK=%TRAKTOR_HOME%\3rdp\zlib set DOXYGEN_SDK=%TRAKTOR_HOME%\3rdp\doxygen set BC6H_ENC_SDK=%TRAKTOR_HOME%\3rdp\bc6h_enc +set MINIMP3_SDK=%TRAKTOR_HOME%\3rdp\minimp3 :: Vulkan SDK set VULKAN_SDK=%TRAKTOR_HOME%\3rdp\vulkan-windows\vulkan-sdk diff --git a/scripts/config.sh b/scripts/config.sh index 2aaedd1228..7d4c902137 100755 --- a/scripts/config.sh +++ b/scripts/config.sh @@ -42,6 +42,7 @@ export VORBIS_SDK=$TRAKTOR_HOME/3rdp/vorbis export XATLAS_SDK=$TRAKTOR_HOME/3rdp/xatlas export ZLIB_SDK=$TRAKTOR_HOME/3rdp/zlib export BC6H_ENC_SDK=$TRAKTOR_HOME/3rdp/bc6h_enc +export MINIMP3_SDK=$TRAKTOR_HOME/3rdp/minimp3 # Vulkan SDK # - cleanup Extern and add Extern.vulkan which contain all paths, diff --git a/scripts/misc/update-3rdp.run b/scripts/misc/update-3rdp.run index 29deeb96fd..5de5d0f2a8 100644 --- a/scripts/misc/update-3rdp.run +++ b/scripts/misc/update-3rdp.run @@ -502,6 +502,14 @@ local PACKAGES = url = "https://github.com/0xc0de/bc6h_enc.git", license = "MIT" }, + + -- minimp3 + { + type = "GIT", + name = "minimp3", + url = "https://github.com/lieff/minimp3.git", + license = "CC0" + }, } --[[