Audacity 3.2.0
EffectBase.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 EffectBase.cpp
6
7 Dominic Mazzoni
8 Vaughan Johnson
9 Martyn Shaw
10
11 Paul Licameli split from Effect.cpp
12
13*******************************************************************//*******************************************************************/
19#include "EffectBase.h"
20
21#include <thread>
22#include "BasicUI.h"
23#include "ConfigInterface.h"
24#include "EffectOutputTracks.h"
25#include "PluginManager.h"
26#include "QualitySettings.h"
27#include "TransactionScope.h"
28#include "ViewInfo.h"
29#include "WaveTrack.h"
31
33{
34 // PRL: I think this initialization of mProjectRate doesn't matter
35 // because it is always reassigned in DoEffect before it is used
36 // STF: but can't call AudioIOBase::GetOptimalSupportedSampleRate() here.
37 // (Which is called to compute the default-default value.) (Bug 2280)
39}
40
41EffectBase::~EffectBase() = default;
42
44{
45 mTracks = pTracks ? pTracks->shared_from_this() : nullptr;
46}
47
49{
50 return 30.0;
51}
52
53// TODO: Lift the possible user-prompting part out of this function, so that
54// the recursive paths into this function via Effect::Delegate are simplified,
55// and we don't have both EffectSettings and EffectSettingsAccessPtr
56// If pAccess is not null, settings should have come from its Get()
58 const InstanceFinder &finder,
59 double projectRate,
60 TrackList *list,
62 NotifyingSelectedRegion &selectedRegion,
63 unsigned flags,
64 const EffectSettingsAccessPtr &pAccess)
65{
66 auto cleanup0 = valueRestorer(mUIFlags, flags);
67 wxASSERT(selectedRegion.duration() >= 0.0);
68
70 mProjectRate = projectRate;
71
72 SetTracks(list);
73 // Don't hold a dangling pointer when done
74 Finally Do([&]{ SetTracks(nullptr); });
75
76 // This is for performance purposes only, no additional recovery implied
77 auto &pProject = *const_cast<AudacityProject*>(FindProject()); // how to remove this const_cast?
78 TransactionScope trans(pProject, "Effect");
79
80 // Update track/group counts
82
83 bool isSelection = false;
84
85 auto duration = 0.0;
90
91 WaveTrack *newTrack{};
92 bool success = false;
93 auto oldDuration = duration;
94
95 auto cleanup = finally( [&] {
96 if (!success) {
97 if (newTrack) {
98 assert(newTrack->IsLeader());
99 mTracks->Remove(*newTrack);
100 }
101 // On failure, restore the old duration setting
102 settings.extra.SetDuration(oldDuration);
103 }
104 else
105 trans.Commit();
106
107 mPresetNames.clear();
108 } );
109
110 // We don't yet know the effect type for code in the Nyquist Prompt, so
111 // assume it requires a track and handle errors when the effect runs.
112 if ((GetType() == EffectTypeGenerate || GetPath() == NYQUIST_PROMPT_ID) && (mNumTracks == 0)) {
113 auto track = mFactory->Create();
114 track->SetName(mTracks->MakeUniqueTrackName(WaveTrack::GetDefaultAudioTrackNamePreference()));
115 newTrack = mTracks->Add(track);
116 // Expect that newly added tracks are always leaders
117 assert(newTrack->IsLeader());
118 newTrack->SetSelected(true);
119 }
120
121 mT0 = selectedRegion.t0();
122 mT1 = selectedRegion.t1();
123 if (mT1 > mT0)
124 {
125 // there is a selection: let's fit in there...
126 // MJS: note that this is just for the TTC and is independent of the track rate
127 // but we do need to make sure we have the right number of samples at the project rate
128 double quantMT0 = QUANTIZED_TIME(mT0, mProjectRate);
129 double quantMT1 = QUANTIZED_TIME(mT1, mProjectRate);
130 duration = quantMT1 - quantMT0;
131 isSelection = true;
132 mT1 = mT0 + duration;
133 }
134
135 // This is happening inside EffectSettingsAccess::ModifySettings
136 auto newFormat = isSelection
139 auto updater = [&](EffectSettings &settings) {
140 settings.extra.SetDuration(duration);
141 settings.extra.SetDurationFormat( newFormat );
142 return nullptr;
143 };
144 // Update our copy of settings; update the EffectSettingsAccess too,
145 // if we are going to show a dialog
147 if (pAccess)
148 pAccess->ModifySettings(updater);
149
150#ifdef EXPERIMENTAL_SPECTRAL_EDITING
151 mF0 = selectedRegion.f0();
152 mF1 = selectedRegion.f1();
154 mPresetNames.push_back(L"control-f0");
156 mPresetNames.push_back(L"control-f1");
157
158#endif
160
161 // Allow the dialog factory to fill this in, but it might not
162 std::shared_ptr<EffectInstance> pInstance;
163
164 if (IsInteractive()) {
165 if (!finder)
166 return false;
167 else if (auto result = finder(settings))
168 pInstance = *result;
169 else
170 return false;
171 }
172
173 auto pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(pInstance);
174 if (!pInstanceEx) {
175 // Path that skipped the dialog factory -- effect may be non-interactive
176 // or this is batch mode processing or repeat of last effect with stored
177 // settings.
178 pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(MakeInstance());
179 // Note: Init may read parameters from preferences
180 if (!pInstanceEx || !pInstanceEx->Init())
181 return false;
182 }
183
184
185 // If the dialog was shown, then it has been closed without errors or
186 // cancellation, and any change of duration has been saved in the config file
187
188 bool returnVal = true;
189 bool skipFlag = CheckWhetherSkipEffect(settings);
190 if (skipFlag == false)
191 {
192 using namespace BasicUI;
193 auto name = GetName();
194 auto progress = MakeProgress(
195 name,
196 XO("Applying %s...").Format( name ),
198 );
199 auto vr = valueRestorer( mProgress, progress.get() );
200
201 assert(pInstanceEx); // null check above
202 returnVal = pInstanceEx->Process(settings);
203 }
204
205 if (returnVal && (mT1 >= mT0 ))
206 {
207 selectedRegion.setTimes(mT0, mT1);
208 }
209
210 success = returnVal;
211 return returnVal;
212}
213
214void EffectBase::SetLinearEffectFlag(bool linearEffectFlag)
215{
216 mIsLinearEffect = linearEffectFlag;
217}
218
219void EffectBase::SetPreviewFullSelectionFlag(bool previewDurationFlag)
220{
221 mPreviewFullSelection = previewDurationFlag;
222}
223
225{
226 if (!inputTracks())
227 return nullptr;
228 return inputTracks()->GetOwner();
229}
230
232{
233 const auto range = mTracks->Selected<const WaveTrack>();
234 mNumTracks = range.sum(&WaveTrack::NChannels);
235 mNumGroups = range.size();
236}
237
239{
240 return {};
241}
242
244 -> std::optional<InstancePointer>
245{
246 auto result = plugin.MakeInstance();
247 if (auto pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(result)
248 ; pInstanceEx && pInstanceEx->Init())
249 return { pInstanceEx };
250 return {};
251}
252
254{
255 return [&plugin](auto&) { return FindInstance(plugin); };
256}
Toolkit-neutral facade for basic user interface services.
const TranslatableString name
Definition: Distortion.cpp:76
const RegistryPath & CurrentSettingsGroup()
Component of a configuration key path, for last-used destructive settings.
@ EffectTypeGenerate
XO("Cut/Copy/Paste")
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
Definition: MemoryX.h:251
#define QUANTIZED_TIME(time, rate)
Definition: MemoryX.h:559
#define NYQUIST_PROMPT_ID
static Settings & settings()
Definition: TrackInfo.cpp:83
static CustomUpdaterValue updater
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
virtual PluginPath GetPath() const =0
TranslatableString GetName() const
int mNumTracks
Definition: EffectBase.h:110
double mT1
Definition: EffectBase.h:116
WaveTrackFactory * mFactory
Definition: EffectBase.h:114
~EffectBase() override
void CountWaveTracks()
Definition: EffectBase.cpp:231
void SetPreviewFullSelectionFlag(bool previewDurationFlag)
Definition: EffectBase.cpp:219
void SetLinearEffectFlag(bool linearEffectFlag)
Definition: EffectBase.cpp:214
const TrackList * inputTracks() const
Definition: EffectBase.h:91
virtual std::any BeginPreview(const EffectSettings &settings)
Called when Preview() starts, to allow temporary effect state changes.
Definition: EffectBase.cpp:238
virtual bool CheckWhetherSkipEffect(const EffectSettings &settings) const =0
After Init(), tell whether Process() should be skipped.
double mProjectRate
Definition: EffectBase.h:112
BasicUI::ProgressDialog * mProgress
Definition: EffectBase.h:111
int mNumGroups
Definition: EffectBase.h:127
bool DoEffect(EffectSettings &settings, const InstanceFinder &finder, double projectRate, TrackList *list, WaveTrackFactory *factory, NotifyingSelectedRegion &selectedRegion, unsigned flags, const EffectSettingsAccessPtr &pAccess) override
Definition: EffectBase.cpp:57
std::shared_ptr< TrackList > mTracks
Definition: EffectBase.h:109
bool mPreviewFullSelection
Definition: EffectBase.h:125
static std::optional< InstancePointer > FindInstance(EffectPlugin &plugin)
Definition: EffectBase.cpp:243
wxArrayString mPresetNames
Definition: EffectBase.h:99
double GetDefaultDuration()
Definition: EffectBase.cpp:48
static InstanceFinder DefaultInstanceFinder(EffectPlugin &plugin)
Definition: EffectBase.cpp:253
double mT0
Definition: EffectBase.h:115
unsigned mUIFlags
Definition: EffectBase.h:100
void SetTracks(TrackList *pTracks)
Definition: EffectBase.cpp:43
bool mIsLinearEffect
Definition: EffectBase.h:124
const AudacityProject * FindProject() const
Definition: EffectBase.cpp:224
virtual EffectType GetType() const =0
Type determines how it behaves.
virtual bool IsInteractive() const =0
Whether the effect needs a dialog for entry of settings.
virtual std::shared_ptr< EffectInstance > MakeInstance() const =0
Make an object maintaining short-term state of an Effect.
Factory of instances of an effect.
Definition: EffectPlugin.h:36
std::function< std::optional< InstancePointer >(EffectSettings &settings) > InstanceFinder
Definition: EffectPlugin.h:72
std::shared_ptr< EffectSettingsAccess > EffectSettingsAccessPtr
Definition: EffectPlugin.h:38
virtual const EffectSettingsManager & GetDefinition() const =0
static const RegistryPath & DurationKey()
Abstract base class used in importing a file.
double t1() const
Definition: ViewInfo.h:36
double f1() const
Definition: ViewInfo.h:38
double duration() const
Definition: ViewInfo.h:41
bool setTimes(double t0, double t1)
Definition: ViewInfo.cpp:51
double f0() const
Definition: ViewInfo.h:37
double t0() const
Definition: ViewInfo.h:35
static const int UndefinedFrequency
bool ReadWithDefault(T *pVar, const T &defaultValue) const
overload of ReadWithDefault returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:211
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:987
AudacityProject * GetOwner()
Definition: Track.h:1026
RAII for a database transaction, possibly nested.
bool Commit()
Commit the transaction.
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
Definition: WaveTrack.h:1074
std::shared_ptr< WaveTrack > Create()
Creates an unnamed empty WaveTrack with default sample format and default rate.
Definition: WaveTrack.cpp:499
A Track that contains audio waveform data.
Definition: WaveTrack.h:221
static wxString GetDefaultAudioTrackNamePreference()
Definition: WaveTrack.cpp:481
size_t NChannels() const override
May report more than one only when this is a leader track.
Definition: WaveTrack.cpp:542
@ ProgressShowCancel
Definition: BasicUI.h:141
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
Definition: BasicUI.h:289
NUMERIC_FORMATS_API NumericFormatSymbol DefaultSelectionFormat()
NUMERIC_FORMATS_API NumericFormatSymbol TimeAndSampleFormat()
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
PROJECT_RATE_API IntSetting DefaultSampleRate
static RegisteredToolbarFactory factory
Externalized state of a plug-in.
"finally" as in The C++ Programming Language, 4th ed., p. 358 Useful for defining ad-hoc RAII actions...
Definition: MemoryX.h:173