Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import foreign instruments #680

Merged
merged 5 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
39 changes: 39 additions & 0 deletions plugins/common/plugin/ForeignInstrument.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 83 additions & 0 deletions plugins/common/plugin/ForeignInstrument.h
Original file line number Diff line number Diff line change
@@ -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 changes: 63 additions & 0 deletions plugins/common/plugin/foreign_instruments/AudioFile.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 30 additions & 0 deletions plugins/common/plugin/foreign_instruments/AudioFile.h
Original file line number Diff line number Diff line change
@@ -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
4 changes: 3 additions & 1 deletion plugins/editor/cmake/Vstgui.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions plugins/editor/src/editor/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
19 changes: 18 additions & 1 deletion plugins/lv2/sfizz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

#include "sfizz_lv2.h"

#include "plugin/ForeignInstrument.h"

#include <lv2/atom/atom.h>
#include <lv2/atom/forge.h>
#include <lv2/atom/util.h>
Expand Down Expand Up @@ -1173,14 +1175,29 @@ 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')
{
sfizz_lv2_get_default_sfz_path(self, buf, MAX_PATH_SIZE);
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);
return status;
}
Expand Down
3 changes: 3 additions & 0 deletions plugins/vst/SfizzFileScan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include <absl/strings/ascii.h>
#include <absl/algorithm/container.h>
#include <memory>
#if defined(_WIN32)
#include <windows.h>
#endif

// wait at least this much before refreshing the file rescan
// it permits to not repeat the operation many times if many searches are
Expand Down
1 change: 1 addition & 0 deletions plugins/vst/SfizzSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz

#include "SfizzSettings.h"
#include <memory>
#include <cstdlib>

std::string SfizzSettings::load_or(const char* key, absl::string_view defaultValue)
Expand Down
15 changes: 13 additions & 2 deletions plugins/vst/SfizzVstProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 3 additions & 1 deletion plugins/vst/cmake/Vst3.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down