330 lines
9.1 KiB
C++
330 lines
9.1 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
LoadVamp.cpp
|
|
|
|
Chris Cannam
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#if defined(USE_VAMP)
|
|
#include "LoadVamp.h"
|
|
#include "../../ModuleManager.h"
|
|
|
|
#include <wx/filename.h>
|
|
|
|
#include "VampEffect.h"
|
|
|
|
#include <iostream>
|
|
#include <map>
|
|
|
|
using namespace Vamp;
|
|
using namespace Vamp::HostExt;
|
|
using namespace Vamp::HostExt;
|
|
|
|
// ============================================================================
|
|
// Module registration entry point
|
|
//
|
|
// This is the symbol that Audacity looks for when the module is built as a
|
|
// dynamic library.
|
|
//
|
|
// When the module is builtin to Audacity, we use the same function, but it is
|
|
// declared static so as not to clash with other builtin modules.
|
|
// ============================================================================
|
|
DECLARE_MODULE_ENTRY(AudacityModule)
|
|
{
|
|
// Create and register the importer
|
|
// Trust the module manager not to leak this
|
|
return safenew VampEffectsModule();
|
|
}
|
|
|
|
// ============================================================================
|
|
// Register this as a builtin module
|
|
// ============================================================================
|
|
DECLARE_BUILTIN_MODULE(VampsEffectBuiltin);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// VampEffectsModule
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
VampEffectsModule::VampEffectsModule()
|
|
{
|
|
}
|
|
|
|
VampEffectsModule::~VampEffectsModule()
|
|
{
|
|
}
|
|
|
|
// ============================================================================
|
|
// ComponentInterface implementation
|
|
// ============================================================================
|
|
|
|
PluginPath VampEffectsModule::GetPath()
|
|
{
|
|
return {};
|
|
}
|
|
|
|
ComponentInterfaceSymbol VampEffectsModule::GetSymbol()
|
|
{
|
|
return XO("Vamp Effects");
|
|
}
|
|
|
|
VendorSymbol VampEffectsModule::GetVendor()
|
|
{
|
|
return XO("The Audacity Team");
|
|
}
|
|
|
|
wxString VampEffectsModule::GetVersion()
|
|
{
|
|
// This "may" be different if this were to be maintained as a separate DLL
|
|
return VAMPEFFECTS_VERSION;
|
|
}
|
|
|
|
TranslatableString VampEffectsModule::GetDescription()
|
|
{
|
|
return XO("Provides Vamp Effects support to Audacity");
|
|
}
|
|
|
|
// ============================================================================
|
|
// ModuleInterface implementation
|
|
// ============================================================================
|
|
|
|
bool VampEffectsModule::Initialize()
|
|
{
|
|
// Nothing to do here
|
|
return true;
|
|
}
|
|
|
|
void VampEffectsModule::Terminate()
|
|
{
|
|
// Nothing to do here
|
|
return;
|
|
}
|
|
|
|
EffectFamilySymbol VampEffectsModule::GetOptionalFamilySymbol()
|
|
{
|
|
#if USE_VAMP
|
|
return VAMPEFFECTS_FAMILY;
|
|
#else
|
|
return {};
|
|
#endif
|
|
}
|
|
|
|
const FileExtensions &VampEffectsModule::GetFileExtensions()
|
|
{
|
|
static FileExtensions empty;
|
|
return empty;
|
|
}
|
|
|
|
bool VampEffectsModule::AutoRegisterPlugins(PluginManagerInterface & WXUNUSED(pm))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
PluginPaths VampEffectsModule::FindPluginPaths(PluginManagerInterface & WXUNUSED(pm))
|
|
{
|
|
PluginPaths names;
|
|
|
|
PluginLoader *loader = PluginLoader::getInstance();
|
|
|
|
PluginLoader::PluginKeyList keys = loader->listPlugins();
|
|
|
|
for (PluginLoader::PluginKeyList::iterator i = keys.begin(); i != keys.end(); ++i)
|
|
{
|
|
std::unique_ptr<Plugin> vp{ PluginLoader::getInstance()->loadPlugin(*i, 48000) }; // rate doesn't matter here
|
|
if (!vp)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// We limit the listed plugin outputs to those whose results can
|
|
// readily be displayed in an Audacity label track.
|
|
//
|
|
// - Any output whose features have no values (time instants only),
|
|
// with or without duration, is fine
|
|
//
|
|
// - Any output whose features have more than one value, or an
|
|
// unknown or variable number of values, is right out
|
|
//
|
|
// - Any output whose features have exactly one value, with
|
|
// variable sample rate or with duration, should be OK --
|
|
// this implies a sparse feature, of which the time and/or
|
|
// duration are significant aspects worth displaying
|
|
//
|
|
// - An output whose features have exactly one value, with
|
|
// fixed sample rate and no duration, cannot be usefully
|
|
// displayed -- the value is the only significant piece of
|
|
// data there and we have no good value plot
|
|
|
|
Plugin::OutputList outputs = vp->getOutputDescriptors();
|
|
|
|
int output = 0;
|
|
|
|
for (Plugin::OutputList::iterator j = outputs.begin(); j != outputs.end(); ++j)
|
|
{
|
|
if (j->sampleType == Plugin::OutputDescriptor::FixedSampleRate ||
|
|
j->sampleType == Plugin::OutputDescriptor::OneSamplePerStep ||
|
|
!j->hasFixedBinCount ||
|
|
j->binCount > 1)
|
|
{
|
|
// All of these qualities disqualify (see notes above)
|
|
|
|
++output;
|
|
continue;
|
|
}
|
|
|
|
wxString name = wxString::FromUTF8(vp->getName().c_str());
|
|
|
|
if (outputs.size() > 1)
|
|
{
|
|
// This is not the plugin's only output.
|
|
// Use "plugin name: output name" as the effect name,
|
|
// unless the output name is the same as the plugin name
|
|
wxString outputName = wxString::FromUTF8(j->name.c_str());
|
|
if (outputName != name)
|
|
{
|
|
name = wxString::Format(wxT("%s: %s"),
|
|
name, outputName);
|
|
}
|
|
}
|
|
|
|
wxString path = wxString::FromUTF8(i->c_str()) + wxT("/") + name;
|
|
names.push_back(path);
|
|
|
|
++output;
|
|
}
|
|
}
|
|
|
|
return names;
|
|
}
|
|
|
|
unsigned VampEffectsModule::DiscoverPluginsAtPath(
|
|
const PluginPath & path, TranslatableString &errMsg,
|
|
const RegistrationCallback &callback)
|
|
{
|
|
errMsg = {};
|
|
int output;
|
|
bool hasParameters;
|
|
|
|
auto vp = FindPlugin(path, output, hasParameters);
|
|
if (vp)
|
|
{
|
|
VampEffect effect(std::move(vp), path, output, hasParameters);
|
|
if (callback)
|
|
callback( this, &effect );
|
|
|
|
return 1;
|
|
}
|
|
|
|
errMsg = XO("Could not load the library");
|
|
return 0;
|
|
}
|
|
|
|
bool VampEffectsModule::IsPluginValid(const PluginPath & path, bool bFast)
|
|
{
|
|
int output;
|
|
bool hasParameters;
|
|
if( bFast )
|
|
return true;
|
|
|
|
auto vp = FindPlugin(path, output, hasParameters);
|
|
return bool(vp);
|
|
}
|
|
|
|
std::unique_ptr<ComponentInterface>
|
|
VampEffectsModule::CreateInstance(const PluginPath & path)
|
|
{
|
|
// Acquires a resource for the application.
|
|
int output;
|
|
bool hasParameters;
|
|
|
|
if (auto vp = FindPlugin(path, output, hasParameters))
|
|
return std::make_unique<VampEffect>(std::move(vp), path, output, hasParameters);
|
|
return nullptr;
|
|
}
|
|
|
|
// VampEffectsModule implementation
|
|
|
|
std::unique_ptr<Vamp::Plugin> VampEffectsModule::FindPlugin(const PluginPath & path,
|
|
int & output,
|
|
bool & hasParameters)
|
|
{
|
|
PluginLoader::PluginKey key = path.BeforeLast(wxT('/')).ToUTF8().data();
|
|
|
|
std::unique_ptr<Plugin> vp{ PluginLoader::getInstance()->loadPlugin(key, 48000) }; // rate doesn't matter here
|
|
if (!vp)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
// We limit the listed plugin outputs to those whose results can
|
|
// readily be displayed in an Audacity label track.
|
|
//
|
|
// - Any output whose features have no values (time instants only),
|
|
// with or without duration, is fine
|
|
//
|
|
// - Any output whose features have more than one value, or an
|
|
// unknown or variable number of values, is right out
|
|
//
|
|
// - Any output whose features have exactly one value, with
|
|
// variable sample rate or with duration, should be OK --
|
|
// this implies a sparse feature, of which the time and/or
|
|
// duration are significant aspects worth displaying
|
|
//
|
|
// - An output whose features have exactly one value, with
|
|
// fixed sample rate and no duration, cannot be usefully
|
|
// displayed -- the value is the only significant piece of
|
|
// data there and we have no good value plot
|
|
|
|
Plugin::OutputList outputs = vp->getOutputDescriptors();
|
|
|
|
output = 0;
|
|
|
|
hasParameters = !vp->getParameterDescriptors().empty();
|
|
|
|
for (Plugin::OutputList::iterator j = outputs.begin(); j != outputs.end(); ++j)
|
|
{
|
|
if (j->sampleType == Plugin::OutputDescriptor::FixedSampleRate ||
|
|
j->sampleType == Plugin::OutputDescriptor::OneSamplePerStep ||
|
|
!j->hasFixedBinCount ||
|
|
j->binCount > 1)
|
|
{
|
|
// All of these qualities disqualify (see notes above)
|
|
|
|
++output;
|
|
continue;
|
|
}
|
|
|
|
wxString name = wxString::FromUTF8(vp->getName().c_str());
|
|
|
|
if (outputs.size() > 1)
|
|
{
|
|
// This is not the plugin's only output.
|
|
// Use "plugin name: output name" as the effect name,
|
|
// unless the output name is the same as the plugin name
|
|
wxString outputName = wxString::FromUTF8(j->name.c_str());
|
|
if (outputName != name)
|
|
{
|
|
name = wxString::Format(wxT("%s: %s"),
|
|
name, outputName);
|
|
}
|
|
}
|
|
|
|
if (wxString::FromUTF8(key.c_str()) + wxT("/") + name == path)
|
|
{
|
|
return vp;
|
|
}
|
|
|
|
++output;
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
#endif
|