Skip to content

Commit

Permalink
Merge pull request #680 from jpcima/importer
Browse files Browse the repository at this point in the history
Import foreign instruments
  • Loading branch information
jpcima authored Mar 8, 2021
2 parents 4d294dd + 0b27ef3 commit ca21566
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 7 deletions.
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

0 comments on commit ca21566

Please sign in to comment.