audacia/src/effects/LoadEffects.cpp

374 lines
10 KiB
C++
Raw Normal View History

/**********************************************************************
Audacity: A Digital Audio Editor
LoadEffects.cpp
Dominic Mazzoni
2018-03-06 21:42:58 +00:00
**************************************************************************//**
Automation: AudacityCommand This is a squash of 50 commits. This merges the capabilities of BatchCommands and Effects using a new AudacityCommand class. AudacityCommand provides one function to specify the parameters, and then we leverage that one function in automation, whether by chains, mod-script-pipe or (future) Nyquist. - Now have AudacityCommand which is using the same mechanism as Effect - Has configurable parameters - Has data-entry GUI (built using shuttle GUI) - Registers with PluginManager. - Menu commands now provided in chains, and to python batch. - Tested with Zoom Toggle. - ShuttleParams now can set, get, set defaults, validate and specify the parameters. - Bugfix: Don't overwrite values with defaults first time out. - Add DefineParams function for all built-in effects. - Extend CommandContext to carry output channels for results. We abuse EffectsManager. It handles both Effects and AudacityCommands now. In time an Effect should become a special case of AudacityCommand and we'll split and rename the EffectManager class. - Don't use 'default' as a parameter name. - Massive renaming for CommandDefinitionInterface - EffectIdentInterface becomes EffectDefinitionInterface - EffectAutomationParameters becomes CommandAutomationParameters - PluginType is now a bit field. This way we can search for related types at the same time. - Most old batch commands made into AudacityCommands. The ones that weren't are for a reason. They are used by mod-script-pipe to carry commands and responses across from a non-GUI thread to the GUI thread. - Major tidy up of ScreenshotCommand - Reworking of SelectCommand - GetPreferenceCommand and SetPreferenceCommand - GetTrackInfo and SetTrackInfo - GetInfoCommand - Help, Open, Save, Import and Export commands. - Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo which are now better handled by other commands. - JSONify "GetInfo: Commands" output, i.e. commas in the right places. - General work on better Doxygen. - Lyrics -> LyricsPanel - Meter -> MeterPanel - Updated Linux makefile. - Scripting commands added into Extra menu. - Distinct names for previously duplicated find-clipping parameters. - Fixed longstanding error with erroneous status field number which previously caused an ASSERT in debug. - Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
2018-01-14 18:51:41 +00:00
\class BuiltinEffectsModule
\brief Internal module to auto register all built in effects.
2018-03-06 21:42:58 +00:00
*****************************************************************************/
#include "../Audacity.h"
#include "../Prefs.h"
#include "LoadEffects.h"
2016-03-31 13:24:26 +00:00
#include "../MemoryX.h"
#include "EffectManager.h"
#include "Amplify.h"
#include "AutoDuck.h"
#include "BassTreble.h"
#include "ChangeSpeed.h"
#include "ClickRemoval.h"
#include "Compressor.h"
2016-06-15 00:05:59 +00:00
#include "Distortion.h"
#include "DtmfGen.h"
#include "Echo.h"
#include "Paulstretch.h"
#include "Equalization.h"
#include "Fade.h"
#include "Invert.h"
#include "Noise.h"
#ifdef EXPERIMENTAL_NOISE_REDUCTION
#include "NoiseReduction.h"
#endif
#include "NoiseRemoval.h"
#include "Normalize.h"
#include "Phaser.h"
#include "Repair.h"
#include "Repeat.h"
#include "Reverb.h"
#include "Reverse.h"
#include "Silence.h"
2013-10-02 10:32:41 +00:00
#include "ScienFilter.h"
#include "StereoToMono.h"
2014-06-03 20:30:19 +00:00
#ifdef USE_SBSMS
#include "TimeScale.h"
#endif
#include "ToneGen.h"
#include "TruncSilence.h"
#include "Wahwah.h"
#include "FindClipping.h"
#ifdef USE_SOUNDTOUCH
#include "ChangePitch.h"
#include "ChangeTempo.h"
#endif
#include "../Experimental.h"
//
// Include the SoundTouch effects, if requested
//
#if defined(USE_SOUNDTOUCH)
#define SOUNDTOUCH_EFFECTS \
2016-03-31 13:24:26 +00:00
EFFECT( CHANGEPITCH, EffectChangePitch, () ) \
EFFECT( CHANGETEMPO, EffectChangeTempo, () )
#else
#define SOUNDTOUCH_EFFECTS
#endif
2014-06-03 20:30:19 +00:00
//
// Select the desired Noise Reduction/Removal effect
//
#if defined(EXPERIMENTAL_NOISE_REDUCTION)
#define NOISEREDUCTION_EFFECT \
2016-03-31 13:24:26 +00:00
EFFECT( NOISEREDUCTION, EffectNoiseReduction, () )
#else
#define NOISEREDUCTION_EFFECT \
2017-02-25 23:32:05 +00:00
EFFECT( NOISEREMOVAL, EffectNoiseRemoval, () )
#endif
2014-06-03 20:30:19 +00:00
//
// Include the Classic Filters effect, if requested
//
#if defined(EXPERIMENTAL_SCIENCE_FILTERS)
#define CLASSICFILTER_EFFECT \
2016-03-31 13:24:26 +00:00
EFFECT( CLASSICFILTERS, EffectScienFilter, () )
#else
#define CLASSICFILTER_EFFECT
#endif
//
// Include the SBSMS effect, if requested
//
#if defined(USE_SBSMS)
#define SBSMS_EFFECTS \
2016-03-31 13:24:26 +00:00
EFFECT( TIMESCALE, EffectTimeScale, () )
#else
#define SBSMS_EFFECTS
#endif
//
// Define the list of effects that will be autoregistered and how to instantiate each
//
#define EFFECT_LIST \
2016-03-31 13:24:26 +00:00
EFFECT( CHIRP, EffectToneGen, (true) ) \
EFFECT( DTMFTONES, EffectDtmf, () ) \
EFFECT( NOISE, EffectNoise, () ) \
EFFECT( SILENCE, EffectSilence, () ) \
EFFECT( TONE, EffectToneGen, (false) ) \
EFFECT( AMPLIFY, EffectAmplify, () ) \
EFFECT( BASSTREBLE, EffectBassTreble, () ) \
EFFECT( CHANGESPEED, EffectChangeSpeed, () ) \
EFFECT( CLICKREMOVAL, EffectClickRemoval, () ) \
EFFECT( COMPRESSOR, EffectCompressor, () ) \
2016-06-15 00:05:59 +00:00
EFFECT( DISTORTION, EffectDistortion, () ) \
2016-03-31 13:24:26 +00:00
EFFECT( ECHO, EffectEcho, () ) \
EFFECT( EQUALIZATION, EffectEqualization, () ) \
EFFECT( FADEIN, EffectFade, (true) ) \
EFFECT( FADEOUT, EffectFade, (false) ) \
EFFECT( INVERT, EffectInvert, () ) \
EFFECT( NORMALIZE, EffectNormalize, () ) \
EFFECT( PHASER, EffectPhaser, () ) \
EFFECT( REPAIR, EffectRepair, () ) \
EFFECT( REPEAT, EffectRepeat, () ) \
EFFECT( REVERB, EffectReverb, () ) \
EFFECT( REVERSE, EffectReverse, () ) \
EFFECT( STEREOTOMONO, EffectStereoToMono, () ) \
EFFECT( TRUNCATESILENCE, EffectTruncSilence, () ) \
EFFECT( WAHWAH, EffectWahwah, () ) \
EFFECT( FINDCLIPPING, EffectFindClipping, () ) \
NOISEREDUCTION_EFFECT \
SOUNDTOUCH_EFFECTS \
2016-03-31 13:24:26 +00:00
EFFECT( AUTODUCK, EffectAutoDuck, () ) \
EFFECT( PAULSTRETCH, EffectPaulstretch, () ) \
SBSMS_EFFECTS
//
// Define the list of effects that do not get autoregistered
//
#define EXCLUDE_LIST \
CLASSICFILTER_EFFECT
//
// Define the EFFECT() macro to generate enum names
//
2016-03-31 13:24:26 +00:00
#define EFFECT(n, i, args) ENUM_ ## n,
//
// Create the enum for the list of effects (will be used in a switch statement)
//
enum
{
EFFECT_LIST
EXCLUDE_LIST
};
//
// Redefine EFFECT() to add the effect's name to an array
//
#undef EFFECT
#define EFFECT(n, i, args) results.push_back((n ## _PLUGIN_SYMBOL).Internal());
//
// Create the effect name array
//
static const std::vector<wxString> kEffectNames() {
std::vector<wxString> results;
EFFECT_LIST;
return results;
}
//
// Create the effect name array of excluded effects
//
static const std::vector<wxString> kExcludedNames() {
std::vector<wxString> results;
EXCLUDE_LIST;
return results;
}
//
// Redefine EFFECT() to generate a case statement for the lookup switch
//
#undef EFFECT
2016-03-31 13:24:26 +00:00
#define EFFECT(n, i, args) case ENUM_ ## n: return std::make_unique<i> args;
// ============================================================================
// 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 BuiltinEffectsModule(moduleManager, path);
}
// ============================================================================
// Register this as a builtin module
// ============================================================================
DECLARE_BUILTIN_MODULE(BuiltinsEffectBuiltin);
///////////////////////////////////////////////////////////////////////////////
//
// BuiltinEffectsModule
//
///////////////////////////////////////////////////////////////////////////////
BuiltinEffectsModule::BuiltinEffectsModule(ModuleManagerInterface *moduleManager,
const wxString *path)
{
mModMan = moduleManager;
if (path)
{
mPath = *path;
}
}
BuiltinEffectsModule::~BuiltinEffectsModule()
{
mPath.clear();
}
// ============================================================================
// ComponentInterface implementation
// ============================================================================
wxString BuiltinEffectsModule::GetPath()
{
return mPath;
}
ComponentInterfaceSymbol BuiltinEffectsModule::GetSymbol()
{
return XO("Builtin Effects");
}
ComponentInterfaceSymbol BuiltinEffectsModule::GetVendor()
{
return XO("The Audacity Team");
}
wxString BuiltinEffectsModule::GetVersion()
{
// This "may" be different if this were to be maintained as a separate DLL
return AUDACITY_VERSION_STRING;
}
wxString BuiltinEffectsModule::GetDescription()
{
return _("Provides builtin effects to Audacity");
}
// ============================================================================
// ModuleInterface implementation
// ============================================================================
bool BuiltinEffectsModule::Initialize()
{
const auto &names = kEffectNames();
for (const auto &name : names)
{
mNames.push_back(wxString(BUILTIN_EFFECT_PREFIX) + name);
}
const auto &excluded = kExcludedNames();
for (const auto &name : excluded)
{
mNames.push_back(wxString(BUILTIN_EFFECT_PREFIX) + name);
}
return true;
}
void BuiltinEffectsModule::Terminate()
{
// Nothing to do here
return;
}
bool BuiltinEffectsModule::AutoRegisterPlugins(PluginManagerInterface & pm)
{
wxString ignoredErrMsg;
const auto &names = kEffectNames();
for (const auto &name : names)
{
wxString path(wxString(BUILTIN_EFFECT_PREFIX) + name);
2015-06-09 05:36:57 +00:00
if (!pm.IsPluginRegistered(path))
{
// No checking of error ?
DiscoverPluginsAtPath(path, ignoredErrMsg,
PluginManagerInterface::DefaultRegistrationCallback);
}
}
// We still want to be called during the normal registration process
return false;
}
wxArrayString BuiltinEffectsModule::FindPluginPaths(PluginManagerInterface & WXUNUSED(pm))
{
return mNames;
}
unsigned BuiltinEffectsModule::DiscoverPluginsAtPath(
const wxString & path, wxString &errMsg,
const RegistrationCallback &callback)
{
errMsg.clear();
2016-03-31 13:24:26 +00:00
auto effect = Instantiate(path);
if (effect)
{
2018-01-01 01:03:52 +00:00
if (callback)
callback(this, effect.get());
return 1;
}
errMsg = _("Unknown built-in effect name");
return 0;
}
bool BuiltinEffectsModule::IsPluginValid(const wxString & path, bool bFast)
{
// bFast is unused as checking in the list is fast.
static_cast<void>(bFast);
return make_iterator_range( mNames ).contains( path );
}
ComponentInterface *BuiltinEffectsModule::CreateInstance(const wxString & path)
{
// Acquires a resource for the application.
// Safety of this depends on complementary calls to DeleteInstance on the module manager side.
2016-03-31 13:24:26 +00:00
return Instantiate(path).release();
}
void BuiltinEffectsModule::DeleteInstance(ComponentInterface *instance)
{
// Releases the resource.
std::unique_ptr < Effect > {
dynamic_cast<Effect *>(instance)
};
}
// ============================================================================
// BuiltinEffectsModule implementation
// ============================================================================
2016-03-31 13:24:26 +00:00
std::unique_ptr<Effect> BuiltinEffectsModule::Instantiate(const wxString & path)
{
wxASSERT(path.StartsWith(BUILTIN_EFFECT_PREFIX));
auto index = make_iterator_range( mNames ).index( path );
wxASSERT( index != wxNOT_FOUND );
switch ( index )
{
EFFECT_LIST;
EXCLUDE_LIST;
}
return nullptr;
}