Skip to content

Commit

Permalink
feat: add support for STEM
Browse files Browse the repository at this point in the history
The soundsource will ensure the file is a valid STEM file and load
manifest. It will however only expose the main mix to the sound engine
  • Loading branch information
acolombier committed Apr 11, 2024
1 parent 87d9cef commit e55e13d
Show file tree
Hide file tree
Showing 20 changed files with 1,038 additions and 38 deletions.
75 changes: 47 additions & 28 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2191,32 +2191,6 @@ target_link_libraries(mixxx-test PRIVATE mixxx-lib mixxx-gitinfostore GTest::gte
find_package(benchmark)
target_link_libraries(mixxx-test PRIVATE benchmark::benchmark)

# Test Suite
include(CTest)
include(GoogleTest)
enable_testing()
gtest_add_tests(
TARGET mixxx-test
EXTRA_ARGS --logLevel info
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
TEST_LIST testsuite
)
if (NOT WIN32)
# Default to offscreen rendering during tests.
# This is required if the build system like Fedora koji/mock does not
# allow to pass environment variables into the ctest macro expansion.
set_tests_properties(${testsuite} PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
endif()

# Benchmarking
add_custom_target(mixxx-benchmark
COMMAND $<TARGET_FILE:mixxx-test> --benchmark
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Mixxx Benchmarks"
VERBATIM
)
add_dependencies(mixxx-benchmark mixxx-test)

#
# Resources
#
Expand Down Expand Up @@ -3458,6 +3432,51 @@ if(FFMPEG)
target_include_directories(mixxx-lib PUBLIC "${FFMPEG_INCLUDE_DIRS}")
endif()

# STEM file support
default_option(STEM "STEM file support" "FFMPEG_FOUND;FFMPEG")
if (STEM)
if(NOT FFMPEG)
message(FATAL_ERROR "FFMPEG was not enabled")
endif()
target_compile_definitions(mixxx-lib PUBLIC __STEM__)
target_compile_definitions(mixxx-test PUBLIC __STEM__)
target_sources(mixxx-test PUBLIC
src/test/stemtest.cpp
src/test/steminfotest.cpp
)
target_sources(mixxx-lib PRIVATE
src/sources/soundsourcestem.cpp
src/track/steminfoimporter.cpp
src/track/steminfo.cpp # TODO precompiled header?
)
endif()

# Test Suite
include(CTest)
include(GoogleTest)
enable_testing()
gtest_add_tests(
TARGET mixxx-test
EXTRA_ARGS --logLevel info
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
TEST_LIST testsuite
)
if (NOT WIN32)
# Default to offscreen rendering during tests.
# This is required if the build system like Fedora koji/mock does not
# allow to pass environment variables into the ctest macro expansion.
set_tests_properties(${testsuite} PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
endif()

# Benchmarking
add_custom_target(mixxx-benchmark
COMMAND $<TARGET_FILE:mixxx-test> --benchmark
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Mixxx Benchmarks"
VERBATIM
)
add_dependencies(mixxx-benchmark mixxx-test)

# Google PerfTools
option(GPERFTOOLS "Google PerfTools libtcmalloc linkage" OFF)
option(GPERFTOOLSPROFILER "Google PerfTools libprofiler linkage" OFF)
Expand Down Expand Up @@ -3565,8 +3584,8 @@ if(OPUS)
src/encoder/encoderopussettings.cpp
)
target_compile_definitions(mixxx-lib PUBLIC __OPUS__)
target_link_libraries(mixxx-lib PRIVATE OpusFile::OpusFile)
target_link_libraries(mixxx-lib PRIVATE Opus::Opus)
target_link_libraries(mixxx-lib PRIVATE OpusFile::OpusFile Opus::Opus)
target_link_libraries(mixxx-test PRIVATE OpusFile::OpusFile Opus::Opus)
endif()

# MAD MP3 Decoder
Expand Down
10 changes: 9 additions & 1 deletion src/sources/soundsource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ QString SoundSource::getTypeFromUrl(const QUrl& url) {

//static
QString SoundSource::getTypeFromFile(const QFileInfo& fileInfo) {
const QString fileSuffix = fileInfo.suffix().toLower().trimmed();
const QString fileSuffix = fileInfo.completeSuffix().toLower().trimmed();

if (fileSuffix == QLatin1String("opus")) {
// Bypass the insufficient mime type lookup from content for opus files
Expand All @@ -52,6 +52,14 @@ QString SoundSource::getTypeFromFile(const QFileInfo& fileInfo) {
// https://mixxx.zulipchat.com/#narrow/stream/109171-development/topic/mimetype.20sometimes.20wrong
return fileSuffix;
}
if (fileSuffix == QLatin1String("stem.mp4")) {
// STEM suffix extends the ".mp4" suffix. This is because stem files are
// meant to fall back to MP4 decoder, in case a player doesn't have the
// capability to extract the different stem track. However, we need to
// detect that early as the file natively looks like a traditional MP4
// with multiple tracks (audio and video)
return fileSuffix;
}

QMimeType mimeType = QMimeDatabase().mimeTypeForFile(
fileInfo, QMimeDatabase::MatchContent);
Expand Down
15 changes: 15 additions & 0 deletions src/sources/soundsourceproxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
#ifdef __MEDIAFOUNDATION__
#include "sources/soundsourcemediafoundation.h"
#endif
#ifdef __STEM__
#include "sources/soundsourcestem.h"
#endif

#include "library/coverartutils.h"
#include "track/globaltrackcache.h"
Expand Down Expand Up @@ -177,6 +180,13 @@ QList<QMimeType> mimeTypesForFileType(const QString& fileType) {
}
}
}
if (fileType == "stem.mp4") {
// *.stem.mp4 suffix doesn't not have a specific MIME type associated
// with it, and simply falls back to MP4. To prevent conflicts with the
// MP4 decoder able to decode arbitrary MP4 file (such as video,
// extracting just the audio track), we don't return any MIME here
return {};
}
return mimeTypes;
}

Expand Down Expand Up @@ -223,6 +233,11 @@ bool SoundSourceProxy::registerProviders() {
registerSoundSourceProvider(
&s_soundSourceProviders,
std::make_shared<mixxx::SoundSourceProviderSndFile>());
#endif
#ifdef __STEM__
registerSoundSourceProvider(
&s_soundSourceProviders,
std::make_shared<mixxx::SoundSourceProviderSTEM>());
#endif
// Register the high-priority reference providers AFTER all other
// providers to verify that their priorities are correct.
Expand Down
Loading

0 comments on commit e55e13d

Please sign in to comment.