Merge pull request #680 from jpcima/importer
Import foreign instruments
This commit is contained in:
commit
ca21566724
12 changed files with 272 additions and 7 deletions
|
|
@ -1,10 +1,15 @@
|
||||||
add_library(plugins-common STATIC EXCLUDE_FROM_ALL
|
add_library(plugins-common STATIC EXCLUDE_FROM_ALL
|
||||||
"common/plugin/MessageUtils.h"
|
"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_include_directories(plugins-common PUBLIC "common")
|
||||||
target_link_libraries(plugins-common
|
target_link_libraries(plugins-common
|
||||||
PUBLIC sfizz::spin_mutex
|
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)
|
add_library(sfizz::plugins-common ALIAS plugins-common)
|
||||||
|
|
||||||
if((SFIZZ_LV2 AND SFIZZ_LV2_UI) OR SFIZZ_VST)
|
if((SFIZZ_LV2 AND SFIZZ_LV2_UI) OR SFIZZ_VST)
|
||||||
|
|
|
||||||
39
plugins/common/plugin/ForeignInstrument.cpp
Normal file
39
plugins/common/plugin/ForeignInstrument.cpp
Normal file
|
|
@ -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
|
||||||
83
plugins/common/plugin/ForeignInstrument.h
Normal file
83
plugins/common/plugin/ForeignInstrument.h
Normal file
|
|
@ -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 <ghc/fs_std.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
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<const InstrumentFormat*> 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<InstrumentImporter> 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
|
||||||
63
plugins/common/plugin/foreign_instruments/AudioFile.cpp
Normal file
63
plugins/common/plugin/foreign_instruments/AudioFile.cpp
Normal file
|
|
@ -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 <absl/strings/match.h>
|
||||||
|
#include <absl/strings/string_view.h>
|
||||||
|
#include <absl/memory/memory.h>
|
||||||
|
#include <locale>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
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<InstrumentImporter> AudioFileInstrumentFormat::createImporter() const
|
||||||
|
{
|
||||||
|
return absl::make_unique<AudioFileInstrumentImporter>();
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
std::string AudioFileInstrumentImporter::convertToSfz(const fs::path& path) const
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os.imbue(std::locale::classic());
|
||||||
|
os << "<region>sample=" << path.filename().u8string();
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const InstrumentFormat* AudioFileInstrumentImporter::getFormat() const noexcept
|
||||||
|
{
|
||||||
|
return &AudioFileInstrumentFormat::getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sfz
|
||||||
30
plugins/common/plugin/foreign_instruments/AudioFile.h
Normal file
30
plugins/common/plugin/foreign_instruments/AudioFile.h
Normal file
|
|
@ -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<InstrumentImporter> 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
|
||||||
|
|
@ -208,7 +208,9 @@ endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
# higher C++ requirement on 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
|
# Windows 10 RS2 DDI for custom fonts
|
||||||
target_compile_definitions(sfizz_vstgui PRIVATE "NTDDI_VERSION=0x0A000003")
|
target_compile_definitions(sfizz_vstgui PRIVATE "NTDDI_VERSION=0x0A000003")
|
||||||
# disable custom fonts while dwrite3 API is unavailable in MinGW
|
# disable custom fonts while dwrite3 API is unavailable in MinGW
|
||||||
|
|
|
||||||
|
|
@ -1069,6 +1069,15 @@ void Editor::Impl::chooseSfzFile()
|
||||||
fs->setTitle("Load SFZ file");
|
fs->setTitle("Load SFZ file");
|
||||||
fs->setDefaultExtension(CFileExtension("SFZ", "sfz"));
|
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_);
|
std::string initialDir = getFileChooserInitialDir(currentSfzFile_);
|
||||||
if (!initialDir.empty())
|
if (!initialDir.empty())
|
||||||
fs->setInitialDirectory(initialDir.c_str());
|
fs->setInitialDirectory(initialDir.c_str());
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@
|
||||||
|
|
||||||
#include "sfizz_lv2.h"
|
#include "sfizz_lv2.h"
|
||||||
|
|
||||||
|
#include "plugin/ForeignInstrument.h"
|
||||||
|
|
||||||
#include <lv2/atom/atom.h>
|
#include <lv2/atom/atom.h>
|
||||||
#include <lv2/atom/forge.h>
|
#include <lv2/atom/forge.h>
|
||||||
#include <lv2/atom/util.h>
|
#include <lv2/atom/util.h>
|
||||||
|
|
@ -1173,6 +1175,8 @@ sfizz_lv2_update_file_info(sfizz_plugin_t* self, const char *file_path)
|
||||||
static bool
|
static bool
|
||||||
sfizz_lv2_load_file(sfizz_plugin_t *self, const char *file_path)
|
sfizz_lv2_load_file(sfizz_plugin_t *self, const char *file_path)
|
||||||
{
|
{
|
||||||
|
bool status;
|
||||||
|
|
||||||
char buf[MAX_PATH_SIZE];
|
char buf[MAX_PATH_SIZE];
|
||||||
if (file_path[0] == '\0')
|
if (file_path[0] == '\0')
|
||||||
{
|
{
|
||||||
|
|
@ -1180,7 +1184,20 @@ sfizz_lv2_load_file(sfizz_plugin_t *self, const char *file_path)
|
||||||
file_path = buf;
|
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);
|
||||||
|
|
||||||
|
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);
|
sfizz_lv2_update_file_info(self, file_path);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@
|
||||||
#include <absl/strings/ascii.h>
|
#include <absl/strings/ascii.h>
|
||||||
#include <absl/algorithm/container.h>
|
#include <absl/algorithm/container.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// wait at least this much before refreshing the file rescan
|
// wait at least this much before refreshing the file rescan
|
||||||
// it permits to not repeat the operation many times if many searches are
|
// it permits to not repeat the operation many times if many searches are
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
#include "SfizzSettings.h"
|
#include "SfizzSettings.h"
|
||||||
|
#include <memory>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
std::string SfizzSettings::load_or(const char* key, absl::string_view defaultValue)
|
std::string SfizzSettings::load_or(const char* key, absl::string_view defaultValue)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include "SfizzVstState.h"
|
#include "SfizzVstState.h"
|
||||||
#include "SfizzVstParameters.h"
|
#include "SfizzVstParameters.h"
|
||||||
#include "SfizzFileScan.h"
|
#include "SfizzFileScan.h"
|
||||||
|
#include "plugin/ForeignInstrument.h"
|
||||||
#include "base/source/fstreamer.h"
|
#include "base/source/fstreamer.h"
|
||||||
#include "pluginterfaces/vst/ivstevents.h"
|
#include "pluginterfaces/vst/ivstevents.h"
|
||||||
#include "pluginterfaces/vst/ivstparameterchanges.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)
|
void SfizzVstProcessor::loadSfzFileOrDefault(sfz::Sfizz& synth, const std::string& filePath)
|
||||||
{
|
{
|
||||||
if (!filePath.empty())
|
if (!filePath.empty()) {
|
||||||
synth.loadSfzFile(filePath);
|
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
|
else
|
||||||
synth.loadSfzString("default.sfz", defaultSfzText);
|
synth.loadSfzString("default.sfz", defaultSfzText);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,9 @@ function(plugin_add_vst3sdk NAME)
|
||||||
"${VST3SDK_BASEDIR}/public.sdk/source/common/threadchecker_win32.cpp"
|
"${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/vst/vstgui_win32_bundle_support.cpp"
|
||||||
"${VST3SDK_BASEDIR}/public.sdk/source/main/dllmain.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)
|
elseif(APPLE)
|
||||||
target_sources("${NAME}" PRIVATE
|
target_sources("${NAME}" PRIVATE
|
||||||
"${VST3SDK_BASEDIR}/public.sdk/source/main/macmain.cpp")
|
"${VST3SDK_BASEDIR}/public.sdk/source/main/macmain.cpp")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue