diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index a2105364..f69bbe0f 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 00000000..0508010e --- /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 00000000..c48185fb --- /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 00000000..4fa897ea --- /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 00000000..09345152 --- /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