Audacity 3.2.0
LadspaEffectBase.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 LadspaEffectBase.cpp
6
7 Dominic Mazzoni
8
9 Paul Licameli split from LadspaEffect.cpp
10
11 This class implements a LADSPA Plug-in effect.
12
13*******************************************************************//*******************************************************************/
20#include "LadspaEffectBase.h" // This class's header file
21#include "ConfigInterface.h"
22
23#include <wx/log.h>
24#include <wx/utils.h>
25
26// Don't use the template-generated MakeSettings(), which default-constructs
27// the structure. Instead allocate a number of values chosen by the plug-in
29{
30 auto result = EffectSettings::Make<LadspaEffectSettings>( mData->PortCount );
32 return result;
33}
34
36 const EffectSettings &src, EffectSettings &dst) const
37{
38 // Do not use the copy constructor of std::vector. Do an in-place rewrite
39 // of the destination vector, which will not allocate memory if dstControls
40 // began with sufficient capacity.
41 const auto portCount = mData->PortCount;
42
43 auto &srcControls = GetSettings(src).controls;
44 auto &dstControls = GetSettings(dst).controls;
45
46 assert(srcControls.size() == portCount);
47 assert(dstControls.size() == portCount);
48
49 const auto portValuesCount =
50 std::min(srcControls.size(), dstControls.size());
51
52 if (portValuesCount != portCount)
53 return false;
54
55 for (unsigned long p = 0; p < portCount; ++p)
56 {
58
59 if (!(LADSPA_IS_PORT_CONTROL(d)))
60 continue;
61
63 dstControls[p] = srcControls[p];
64 }
65
66 return true;
67}
68
70{
71 auto result = std::make_unique<LadspaEffectOutputs>();
72 result->controls.resize(mData->PortCount);
73 return result;
74}
75
76LadspaEffectBase::LadspaEffectBase(const wxString & path, int index)
77 : mPath{ path }
78 , mIndex{ index }
79{
80}
81
83
84// ============================================================================
85// ComponentInterface implementation
86// ============================================================================
87
89{
90 return wxString::Format(wxT("%s;%d"), mPath, mIndex);
91}
92
94{
95 return LAT1CTOWX(mData->Name);
96}
97
99{
100 return { LAT1CTOWX(mData->Maker) };
101}
102
104{
105 return "n/a";
106}
107
109{
110 return Verbatim( LAT1CTOWX(mData->Copyright) );
111}
112
113// ============================================================================
114// EffectDefinitionInterface implementation
115// ============================================================================
116
118{
119 if (mAudioIns == 0 && mAudioOuts == 0)
120 {
121 return EffectTypeTool;
122 }
123
124 if (mAudioIns == 0)
125 {
126 return EffectTypeGenerate;
127 }
128
129 if (mAudioOuts == 0)
130 {
131 return EffectTypeAnalyze;
132 }
133
134 return EffectTypeProcess;
135}
136
138{
140}
141
143{
144 return mInteractive;
145}
146
148{
149 return false;
150}
151
153{
154 return GetType() == EffectTypeProcess
157}
158
160{
161 return mNumInputControls > 0;
162}
163
164namespace {
165std::pair<float, float>
167{
168 // Find lower and upper bound values for ths hint
169 const auto multiplier =
171 return { hint.LowerBound * multiplier, hint.UpperBound * multiplier };
172}
174 const LADSPA_PortRangeHint &hint, float val, float lower, float upper)
175{
176 if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) && val < lower)
177 val = lower;
178 if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) && val > upper)
179 val = upper;
180 return val;
181}
183 const LADSPA_PortRangeHint &hint, double sampleRate)
184{
185 // See comments in library header ladspa.h about interpretation of macros
186 const auto bounds = InputControlPortBounds(hint, sampleRate);
187
188 // Function to find low, middle, or high default values
189 const auto combine = [bounds,
191 ](float lowWeight, float highWeight){
192 auto [lower, upper] = bounds;
193 return logarithmic
194 ? exp(log(lower) * lowWeight + log(upper) * highWeight)
195 : lower * lowWeight + upper * highWeight;
196 };
197
198 auto [lower, upper] = bounds;
199 auto val = 1.0f;
200 // Four bits of the descriptor describe mutually exclusive cases
203 default:
204 break;
206 val = lower; break;
208 val = combine(0.75, 0.25); break;
210 val = combine(0.5, 0.5); break;
212 val = combine(0.25, 0.75); break;
214 val = upper; break;
216 val = 0.0f; break;
218 val = 1.0f; break;
220 val = 100.0f; break;
222 val = 440.0f; break;
223 }
224
225 return ClampInputControlValue(hint, val, lower, upper);
226}
227}
228
230{
231 if (!Load())
232 return false;
233
236 for (unsigned long p = 0; p < mData->PortCount; p++) {
238
239 // Collect the audio ports
240 if (LADSPA_IS_PORT_AUDIO(d)) {
242 mInputPorts[mAudioIns++] = p;
243 else if (LADSPA_IS_PORT_OUTPUT(d))
245 }
246 // Count control ports
247 else if (LADSPA_IS_PORT_CONTROL(d)) {
248 if (LADSPA_IS_PORT_INPUT(d)) {
249 mInteractive = true;
251 }
252 else if (LADSPA_IS_PORT_OUTPUT(d)) {
253 // LADSPA effects have a convention of providing latency on an output
254 // control port whose name is "latency".
255 if (strcmp(mData->PortNames[p], "latency") == 0)
256 mLatencyPort = p;
257 else {
258 mInteractive = true;
260 }
261 }
262 }
263 }
264 return true;
265}
266
268{
269 auto &controls = settings.controls;
270 // (Re-)initialize with right-sized vector
271 std::vector<float>(mData->PortCount).swap(controls);
272
273 for (unsigned long p = 0; p < mData->PortCount; ++p) {
276 // Determine the port's default value
277 controls[p] = InputControlPortDefaultValue(
279 else
280 controls[p] = 0;
281 }
282 return true;
283}
284
285std::shared_ptr<EffectInstance> LadspaEffectBase::MakeInstance() const
286{
287 return std::make_shared<LadspaInstance>(*this, mData,
290}
291
293 const EffectSettings &settings, CommandParameters & parms) const
294{
295 const auto &controls = GetSettings(settings).controls;
296 for (unsigned long p = 0; p < mData->PortCount; p++) {
299 if (!parms.Write(LAT1CTOWX(mData->PortNames[p]), controls[p]))
300 return false;
301 }
302 return true;
303}
304
306 const CommandParameters & parms, EffectSettings &settings) const
307{
308 auto &controls = GetSettings(settings).controls;
309 for (unsigned long p = 0; p < mData->PortCount; p++) {
311
312 if (LADSPA_IS_PORT_CONTROL(descriptor) &&
313 LADSPA_IS_PORT_INPUT(descriptor)) {
314 wxString labelText = LAT1CTOWX(mData->PortNames[p]);
315 double d = 0.0;
316 if (!parms.Read(labelText, &d))
317 return false;
318 controls[p] = d;
319 }
320 }
321 return true;
322}
323
326{
328}
329
331 const RegistryPath & name, const EffectSettings &settings) const
332{
334}
335
337{
338 return {};
339}
340
342{
343 return { nullptr };
344}
345
347{
348 return false;
349}
350
352{
353 return true;
354}
355
356// ============================================================================
357// LadspaEffect Implementation
358// ============================================================================
359
361{
362 if (mLib.IsLoaded())
363 {
364 return true;
365 }
366
367 wxFileName ff = mPath;
368 wxString envpath;
369 bool hadpath = wxGetEnv(wxT("PATH"), &envpath);
370 wxSetEnv(wxT("PATH"), ff.GetPath() + wxFILE_SEP_PATH + envpath);
371 wxString saveOldCWD = ff.GetCwd();
372 ff.SetCwd();
373
374 LADSPA_Descriptor_Function mainFn = NULL;
375
376 if (mLib.Load(mPath, wxDL_NOW))
377 {
378 wxLogNull logNo;
379
380 mainFn = (LADSPA_Descriptor_Function) mLib.GetSymbol(wxT("ladspa_descriptor"));
381 if (mainFn)
382 {
383 mData = mainFn(mIndex);
384 return true;
385 }
386 }
387
388 if (mLib.IsLoaded())
389 {
390 mLib.Unload();
391 }
392
393 wxSetWorkingDirectory(saveOldCWD);
394 hadpath ? wxSetEnv(wxT("PATH"), envpath) : wxUnsetEnv(wxT("PATH"));
395
396 return false;
397}
398
400{
401 if (mLib.IsLoaded())
402 {
403 mLib.Unload();
404 }
405}
406
408 const RegistryPath & group, EffectSettings &settings) const
409{
410 wxString parms;
411 if (!GetConfig(*this, PluginSettings::Private, group, wxT("Parameters"),
412 parms, wxEmptyString))
413 {
414 return {};
415 }
416
418 if (!eap.SetParameters(parms))
419 {
420 return {};
421 }
422
423 if (!LoadSettings(eap, settings))
424 return {};
425 return { nullptr };
426}
427
429 const RegistryPath & group, const EffectSettings &settings) const
430{
432 if (!SaveSettings(settings, eap))
433 {
434 return false;
435 }
436
437 wxString parms;
438 if (!eap.GetParameters(parms))
439 {
440 return false;
441 }
442
444 group, wxT("Parameters"), parms);
445}
wxT("CloseDown"))
int min(int a, int b)
EffectType
@ EffectTypeAnalyze
@ EffectTypeGenerate
@ EffectTypeTool
@ EffectTypeProcess
std::optional< std::unique_ptr< EffectSettingsAccess::Message > > OptionalMessage
wxString RegistryPath
Definition: Identifier.h:218
wxString PluginPath
type alias for identifying a Plugin supplied by a module, each module defining its own interpretation...
Definition: Identifier.h:214
std::vector< RegistryPath > RegistryPaths
Definition: Identifier.h:219
#define LAT1CTOWX(X)
Definition: Internat.h:158
#define LADSPAEFFECTS_FAMILY
wxString name
Definition: TagsEditor.cpp:166
static Settings & settings()
Definition: TrackInfo.cpp:51
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:59
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the SettingsVis...
bool GetParameters(wxString &parms)
bool SetParameters(const wxString &parms)
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
double mProjectRate
Definition: EffectBase.h:119
RealtimeSince
In which versions of Audacity was an effect realtime capable?
Hold values to send to effect output meters.
static LadspaEffectSettings & GetSettings(EffectSettings &settings)
Assume settings originated from MakeSettings() and copies thereof.
Definition: Effect.h:166
bool SaveParameters(const RegistryPath &group, const EffectSettings &settings) const
LadspaEffectBase(const wxString &path, int index)
EffectType GetType() const override
Type determines how it behaves.
EffectFamilySymbol GetFamily() const override
Report identifier and user-visible name of the effect protocol.
const wxString mPath
PluginPath GetPath() const override
bool IsDefault() const override
Whether the effect sorts "above the line" in the menus.
VendorSymbol GetVendor() const override
~LadspaEffectBase() override
bool CanExportPresets() const override
Whether the effect supports export of presets to files, and importing too.
bool HasOptions() const override
wxDynamicLibrary mLib
std::unique_ptr< EffectOutputs > MakeOutputs() const override
Produce an object to hold values to send to effect output meters.
unsigned mNumInputControls
OptionalMessage LoadUserPreset(const RegistryPath &name, EffectSettings &settings) const override
ArrayOf< unsigned long > mInputPorts
bool CopySettingsContents(const EffectSettings &src, EffectSettings &dst) const override
Update one settings object from another.
RealtimeSince RealtimeSupport() const override
Since which version of Audacity has the effect supported realtime?
const LADSPA_Descriptor * mData
ArrayOf< unsigned long > mOutputPorts
bool InitializeControls(LadspaEffectSettings &settings) const
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
bool IsInteractive() const override
Whether the effect needs a dialog for entry of settings.
EffectSettings MakeSettings() const override
unsigned mNumOutputControls
bool SaveSettings(const EffectSettings &settings, CommandParameters &parms) const override
Store settings as keys and values.
OptionalMessage LoadFactoryPreset(int id, EffectSettings &settings) const override
wxString GetVersion() const override
ComponentInterfaceSymbol GetSymbol() const override
RegistryPaths GetFactoryPresets() const override
Report names of factory presets.
bool SupportsAutomation() const override
Whether the effect has any automatable controls.
TranslatableString GetDescription() const override
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
bool SaveUserPreset(const RegistryPath &name, const EffectSettings &settings) const override
Save settings in the configuration file as a user-named preset.
OptionalMessage LoadParameters(const RegistryPath &group, EffectSettings &settings) const
Holds a msgid for the translation catalog; may also bind format arguments.
#define LADSPA_HINT_DEFAULT_100
Definition: ladspa.h:303
#define LADSPA_IS_HINT_BOUNDED_BELOW(x)
Definition: ladspa.h:310
#define LADSPA_HINT_DEFAULT_MAXIMUM
Definition: ladspa.h:290
#define LADSPA_HINT_DEFAULT_440
Definition: ladspa.h:308
#define LADSPA_HINT_DEFAULT_LOW
Definition: ladspa.h:272
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x)
Definition: ladspa.h:311
#define LADSPA_HINT_DEFAULT_0
Definition: ladspa.h:295
#define LADSPA_IS_HINT_LOGARITHMIC(x)
Definition: ladspa.h:314
#define LADSPA_HINT_DEFAULT_HIGH
Definition: ladspa.h:286
#define LADSPA_HINT_DEFAULT_MASK
Definition: ladspa.h:258
#define LADSPA_HINT_DEFAULT_MIDDLE
Definition: ladspa.h:279
int LADSPA_PortDescriptor
Definition: ladspa.h:152
#define LADSPA_HINT_DEFAULT_1
Definition: ladspa.h:300
#define LADSPA_HINT_DEFAULT_MINIMUM
Definition: ladspa.h:265
const LADSPA_Descriptor *(* LADSPA_Descriptor_Function)(unsigned long Index)
Definition: ladspa.h:593
#define LADSPA_IS_PORT_INPUT(x)
Definition: ladspa.h:168
#define LADSPA_IS_PORT_AUDIO(x)
Definition: ladspa.h:171
#define LADSPA_IS_PORT_CONTROL(x)
Definition: ladspa.h:170
#define LADSPA_IS_PORT_OUTPUT(x)
Definition: ladspa.h:169
#define LADSPA_HINT_DEFAULT_NONE
Definition: ladspa.h:261
#define LADSPA_IS_HINT_SAMPLE_RATE(x)
Definition: ladspa.h:313
bool SetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, const Value &value)
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
std::pair< float, float > InputControlPortBounds(const LADSPA_PortRangeHint &hint, double sampleRate)
float ClampInputControlValue(const LADSPA_PortRangeHint &hint, float val, float lower, float upper)
float InputControlPortDefaultValue(const LADSPA_PortRangeHint &hint, double sampleRate)
STL namespace.
const char *const * PortNames
Definition: ladspa.h:415
const char * Copyright
Definition: ladspa.h:402
const LADSPA_PortDescriptor * PortDescriptors
Definition: ladspa.h:410
unsigned long PortCount
Definition: ladspa.h:406
const char * Name
Definition: ladspa.h:393
const char * Maker
Definition: ladspa.h:397
const LADSPA_PortRangeHint * PortRangeHints
Definition: ladspa.h:419
_LADSPA_PortRangeHint is a structure that gives parameter validation information for a LADSPA (Linux ...
Definition: ladspa.h:337
LADSPA_PortRangeHintDescriptor HintDescriptor
Definition: ladspa.h:340
LADSPA_Data LowerBound
Definition: ladspa.h:345
LADSPA_Data UpperBound
Definition: ladspa.h:350
Externalized state of a plug-in.
std::vector< float > controls