From 625cf2a93b32d4372a6e48c1f3bcb7c9e7ba1c87 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sun, 7 Mar 2021 17:21:37 +0100 Subject: [PATCH 1/5] Add import utilities for foreign instruments --- plugins/CMakeLists.txt | 9 +- plugins/common/plugin/ForeignInstrument.cpp | 39 +++++++++ plugins/common/plugin/ForeignInstrument.h | 83 +++++++++++++++++++ .../plugin/foreign_instruments/AudioFile.cpp | 63 ++++++++++++++ .../plugin/foreign_instruments/AudioFile.h | 30 +++++++ 5 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 plugins/common/plugin/ForeignInstrument.cpp create mode 100644 plugins/common/plugin/ForeignInstrument.h create mode 100644 plugins/common/plugin/foreign_instruments/AudioFile.cpp create mode 100644 plugins/common/plugin/foreign_instruments/AudioFile.h diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index a21053647..f69bbe0f4 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,10 +1,15 @@ add_library(plugins-common STATIC EXCLUDE_FROM_ALL "common/plugin/MessageUtils.h" - "common/plugin/MessageUtils.cpp") + "common/plugin/MessageUtils.cpp" + "common/plugin/ForeignInstrument.h" + "common/plugin/ForeignInstrument.cpp" + "common/plugin/foreign_instruments/AudioFile.h" + "common/plugin/foreign_instruments/AudioFile.cpp") target_include_directories(plugins-common PUBLIC "common") target_link_libraries(plugins-common PUBLIC sfizz::spin_mutex - PUBLIC absl::strings) + PUBLIC sfizz::filesystem absl::strings + PRIVATE sfizz::pugixml absl::memory) add_library(sfizz::plugins-common ALIAS plugins-common) if((SFIZZ_LV2 AND SFIZZ_LV2_UI) OR SFIZZ_VST) diff --git a/plugins/common/plugin/ForeignInstrument.cpp b/plugins/common/plugin/ForeignInstrument.cpp new file mode 100644 index 000000000..0508010e5 --- /dev/null +++ b/plugins/common/plugin/ForeignInstrument.cpp @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#include "ForeignInstrument.h" +#include "foreign_instruments/AudioFile.h" + +namespace sfz { + +InstrumentFormatRegistry::InstrumentFormatRegistry() + : formats_ { + &AudioFileInstrumentFormat::getInstance(), + } +{ +} + +InstrumentFormatRegistry& InstrumentFormatRegistry::getInstance() +{ + static InstrumentFormatRegistry registry; + return registry; +} + +const InstrumentFormat* InstrumentFormatRegistry::getMatchingFormat(const fs::path& path) const +{ + const InstrumentFormat* resultFormat = nullptr; + + for (const InstrumentFormat* currentFormat : formats_) { + if (currentFormat->matchesFilePath(path)) { + resultFormat = currentFormat; + break; + } + } + + return resultFormat; +} + +} // namespace sfz diff --git a/plugins/common/plugin/ForeignInstrument.h b/plugins/common/plugin/ForeignInstrument.h new file mode 100644 index 000000000..c48185fb0 --- /dev/null +++ b/plugins/common/plugin/ForeignInstrument.h @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#pragma once +#include +#include +#include +#include + +namespace sfz { + +class InstrumentFormat; +class InstrumentImporter; + +/** + * Registry of known non-SFZ instrument formats + */ +class InstrumentFormatRegistry { +private: + InstrumentFormatRegistry(); + +public: + /** + * @brief Get the single instance of the registry + */ + static InstrumentFormatRegistry& getInstance(); + + /** + * @brief Get a format which is able to handle a file which goes by the + * given path name, or null otherwise. + */ + const InstrumentFormat* getMatchingFormat(const fs::path& path) const; + +private: + std::vector formats_; +}; + +/** + * Description of a non-SFZ instrument format + */ +class InstrumentFormat { +public: + virtual ~InstrumentFormat() {} + + /** + * @brief Get the name of the instrument format + */ + virtual const char* name() const noexcept = 0; + + /** + * @brief Checks whether this importer matches files of the given path + * + * This should check for a pattern like such as a file extension, but not + * examine the contents of the file itself. + */ + virtual bool matchesFilePath(const fs::path& path) const = 0; + + /** + * @brief Create a new importer for instrument files of this format + */ + virtual std::unique_ptr createImporter() const = 0; +}; + +/** + * Importer of non-SFZ instruments + */ +class InstrumentImporter { +public: + /** + * @brief Get the format that this importer converts from + */ + virtual const InstrumentFormat* getFormat() const noexcept = 0; + + /** + * @brief Process the file and convert to an equivalent SFZ string + */ + virtual std::string convertToSfz(const fs::path& path) const = 0; +}; + +} // namespace sfz diff --git a/plugins/common/plugin/foreign_instruments/AudioFile.cpp b/plugins/common/plugin/foreign_instruments/AudioFile.cpp new file mode 100644 index 000000000..4fa897eaf --- /dev/null +++ b/plugins/common/plugin/foreign_instruments/AudioFile.cpp @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#include "AudioFile.h" +#include +#include +#include +#include +#include + +namespace sfz { + +static const char* kRecognizedAudioExtensions[] = { + ".wav", ".flac", ".ogg", ".mp3", ".aif", ".aiff", ".aifc", +}; + +/// +AudioFileInstrumentFormat& AudioFileInstrumentFormat::getInstance() +{ + static AudioFileInstrumentFormat format; + return format; +} + +const char* AudioFileInstrumentFormat::name() const noexcept +{ + return "Audio file"; +} + +bool AudioFileInstrumentFormat::matchesFilePath(const fs::path& path) const +{ + const std::string ext = path.extension().u8string(); + + for (absl::string_view knownExt : kRecognizedAudioExtensions) { + if (absl::EqualsIgnoreCase(ext, knownExt)) + return true; + } + + return false; +} + +std::unique_ptr AudioFileInstrumentFormat::createImporter() const +{ + return absl::make_unique(); +} + +/// +std::string AudioFileInstrumentImporter::convertToSfz(const fs::path& path) const +{ + std::ostringstream os; + os.imbue(std::locale::classic()); + os << "sample=" << path.filename().u8string(); + return os.str(); +} + +const InstrumentFormat* AudioFileInstrumentImporter::getFormat() const noexcept +{ + return &AudioFileInstrumentFormat::getInstance(); +} + +} // namespace sfz diff --git a/plugins/common/plugin/foreign_instruments/AudioFile.h b/plugins/common/plugin/foreign_instruments/AudioFile.h new file mode 100644 index 000000000..093451529 --- /dev/null +++ b/plugins/common/plugin/foreign_instruments/AudioFile.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#pragma once +#include "../ForeignInstrument.h" + +namespace sfz { + +class AudioFileInstrumentFormat : public InstrumentFormat { +private: + AudioFileInstrumentFormat() noexcept = default; + +public: + static AudioFileInstrumentFormat& getInstance(); + const char* name() const noexcept override; + bool matchesFilePath(const fs::path& path) const override; + std::unique_ptr createImporter() const override; +}; + +/// +class AudioFileInstrumentImporter : public InstrumentImporter { +public: + std::string convertToSfz(const fs::path& path) const override; + const InstrumentFormat* getFormat() const noexcept override; +}; + +} // namespace sfz From 37b5c3b1bc8682b4a6e4c402a4d3e9798653fc08 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sun, 7 Mar 2021 17:40:05 +0100 Subject: [PATCH 2/5] Add importer support in plugins --- plugins/editor/src/editor/Editor.cpp | 9 +++++++++ plugins/lv2/sfizz.cpp | 21 ++++++++++++++++++++- plugins/vst/SfizzVstProcessor.cpp | 15 +++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/plugins/editor/src/editor/Editor.cpp b/plugins/editor/src/editor/Editor.cpp index 71ae9d20b..9a6568c59 100644 --- a/plugins/editor/src/editor/Editor.cpp +++ b/plugins/editor/src/editor/Editor.cpp @@ -1069,6 +1069,15 @@ void Editor::Impl::chooseSfzFile() fs->setTitle("Load SFZ file"); fs->setDefaultExtension(CFileExtension("SFZ", "sfz")); + // also add extensions of importable files + fs->addFileExtension(CFileExtension("WAV", "wav")); + fs->addFileExtension(CFileExtension("FLAC", "flac")); + fs->addFileExtension(CFileExtension("OGG", "ogg")); + fs->addFileExtension(CFileExtension("MP3", "mp3")); + fs->addFileExtension(CFileExtension("AIF", "aif")); + fs->addFileExtension(CFileExtension("AIFF", "aiff")); + fs->addFileExtension(CFileExtension("AIFC", "aifc")); + std::string initialDir = getFileChooserInitialDir(currentSfzFile_); if (!initialDir.empty()) fs->setInitialDirectory(initialDir.c_str()); diff --git a/plugins/lv2/sfizz.cpp b/plugins/lv2/sfizz.cpp index 01ab0224b..16084aa5d 100644 --- a/plugins/lv2/sfizz.cpp +++ b/plugins/lv2/sfizz.cpp @@ -34,6 +34,8 @@ #include "sfizz_lv2.h" +#include "plugin/ForeignInstrument.h" + #include #include #include @@ -1173,6 +1175,8 @@ sfizz_lv2_update_file_info(sfizz_plugin_t* self, const char *file_path) static bool sfizz_lv2_load_file(sfizz_plugin_t *self, const char *file_path) { + bool status; + char buf[MAX_PATH_SIZE]; if (file_path[0] == '\0') { @@ -1180,7 +1184,22 @@ sfizz_lv2_load_file(sfizz_plugin_t *self, const char *file_path) file_path = buf; } - bool status = sfizz_load_file(self->synth, file_path); + // bool status = sfizz_load_file(self->synth, file_path); + + /// + const sfz::InstrumentFormatRegistry& formatRegistry = sfz::InstrumentFormatRegistry::getInstance(); + const sfz::InstrumentFormat* format = formatRegistry.getMatchingFormat(file_path); + + if (!format) + status = sfizz_load_file(self->synth, file_path); + else { + auto importer = format->createImporter(); + std::string virtual_path = std::string(file_path) + ".sfz"; + std::string sfz_text = importer->convertToSfz(file_path); + status = sfizz_load_string(self->synth, virtual_path.c_str(), sfz_text.c_str()); + } + + /// sfizz_lv2_update_file_info(self, file_path); return status; } diff --git a/plugins/vst/SfizzVstProcessor.cpp b/plugins/vst/SfizzVstProcessor.cpp index d2d308f3e..3701d13f2 100644 --- a/plugins/vst/SfizzVstProcessor.cpp +++ b/plugins/vst/SfizzVstProcessor.cpp @@ -9,6 +9,7 @@ #include "SfizzVstState.h" #include "SfizzVstParameters.h" #include "SfizzFileScan.h" +#include "plugin/ForeignInstrument.h" #include "base/source/fstreamer.h" #include "pluginterfaces/vst/ivstevents.h" #include "pluginterfaces/vst/ivstparameterchanges.h" @@ -621,8 +622,18 @@ void SfizzVstProcessor::receiveMessage(int delay, const char* path, const char* void SfizzVstProcessor::loadSfzFileOrDefault(sfz::Sfizz& synth, const std::string& filePath) { - if (!filePath.empty()) - synth.loadSfzFile(filePath); + if (!filePath.empty()) { + const sfz::InstrumentFormatRegistry& formatRegistry = sfz::InstrumentFormatRegistry::getInstance(); + const sfz::InstrumentFormat* format = formatRegistry.getMatchingFormat(filePath); + if (!format) + synth.loadSfzFile(filePath); + else { + auto importer = format->createImporter(); + std::string virtualPath = filePath + ".sfz"; + std::string sfzText = importer->convertToSfz(filePath); + synth.loadSfzString(virtualPath, sfzText); + } + } else synth.loadSfzString("default.sfz", defaultSfzText); } From 5803630c0dec82720c5337ef13f256b7eef1b609 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sun, 7 Mar 2021 17:58:06 +0100 Subject: [PATCH 3/5] Eliminate a leftover comment --- plugins/lv2/sfizz.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/lv2/sfizz.cpp b/plugins/lv2/sfizz.cpp index 16084aa5d..a1467ec20 100644 --- a/plugins/lv2/sfizz.cpp +++ b/plugins/lv2/sfizz.cpp @@ -1184,8 +1184,6 @@ sfizz_lv2_load_file(sfizz_plugin_t *self, const char *file_path) file_path = buf; } - // bool status = sfizz_load_file(self->synth, file_path); - /// const sfz::InstrumentFormatRegistry& formatRegistry = sfz::InstrumentFormatRegistry::getInstance(); const sfz::InstrumentFormat* format = formatRegistry.getMatchingFormat(file_path); From 9e362a5507961a42b9f06902df677fe10ff8d8bd Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sun, 7 Mar 2021 18:08:27 +0100 Subject: [PATCH 4/5] Ensure to not set vst libs to a lower standard --- plugins/editor/cmake/Vstgui.cmake | 4 +++- plugins/vst/cmake/Vst3.cmake | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/editor/cmake/Vstgui.cmake b/plugins/editor/cmake/Vstgui.cmake index 8c0d4ca55..51d1c26fc 100644 --- a/plugins/editor/cmake/Vstgui.cmake +++ b/plugins/editor/cmake/Vstgui.cmake @@ -208,7 +208,9 @@ endif() if(CMAKE_SYSTEM_NAME STREQUAL "Windows") # higher C++ requirement on Windows - set_property(TARGET sfizz_vstgui PROPERTY CXX_STANDARD 14) + if(NOT CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD LESS 14) + set_property(TARGET sfizz_vstgui PROPERTY CXX_STANDARD 14) + endif() # Windows 10 RS2 DDI for custom fonts target_compile_definitions(sfizz_vstgui PRIVATE "NTDDI_VERSION=0x0A000003") # disable custom fonts while dwrite3 API is unavailable in MinGW diff --git a/plugins/vst/cmake/Vst3.cmake b/plugins/vst/cmake/Vst3.cmake index 449467cea..eceaaf173 100644 --- a/plugins/vst/cmake/Vst3.cmake +++ b/plugins/vst/cmake/Vst3.cmake @@ -36,7 +36,9 @@ function(plugin_add_vst3sdk NAME) "${VST3SDK_BASEDIR}/public.sdk/source/common/threadchecker_win32.cpp" "${VST3SDK_BASEDIR}/public.sdk/source/vst/vstgui_win32_bundle_support.cpp" "${VST3SDK_BASEDIR}/public.sdk/source/main/dllmain.cpp") - set_property(TARGET "${NAME}" PROPERTY CXX_STANDARD 14) + if(NOT CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD LESS 14) + set_property(TARGET "${NAME}" PROPERTY CXX_STANDARD 14) + endif() elseif(APPLE) target_sources("${NAME}" PRIVATE "${VST3SDK_BASEDIR}/public.sdk/source/main/macmain.cpp") From 0b27ef38458c4216fc3db92af48df5abadef8aaa Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sun, 7 Mar 2021 18:12:33 +0100 Subject: [PATCH 5/5] Fix new MinGW problems after raising c++ standard --- plugins/vst/SfizzFileScan.cpp | 3 +++ plugins/vst/SfizzSettings.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/plugins/vst/SfizzFileScan.cpp b/plugins/vst/SfizzFileScan.cpp index 1dd313f64..f6ec9ee1f 100644 --- a/plugins/vst/SfizzFileScan.cpp +++ b/plugins/vst/SfizzFileScan.cpp @@ -11,6 +11,9 @@ #include #include #include +#if defined(_WIN32) +#include +#endif // wait at least this much before refreshing the file rescan // it permits to not repeat the operation many times if many searches are diff --git a/plugins/vst/SfizzSettings.cpp b/plugins/vst/SfizzSettings.cpp index 9560d16d7..b089cecf2 100644 --- a/plugins/vst/SfizzSettings.cpp +++ b/plugins/vst/SfizzSettings.cpp @@ -5,6 +5,7 @@ // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz #include "SfizzSettings.h" +#include #include std::string SfizzSettings::load_or(const char* key, absl::string_view defaultValue)