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()
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 ).Internal();
140 auto updater = [&](EffectSettings &settings) {
141 settings.extra.SetDuration(duration);
142 settings.extra.SetDurationFormat(newFormat);
143 return nullptr;
144 };
145 // Update our copy of settings; update the EffectSettingsAccess too,
146 // if we are going to show a dialog
148 if (pAccess)
149 pAccess->ModifySettings(updater);
150
151#ifdef EXPERIMENTAL_SPECTRAL_EDITING
152 mF0 = selectedRegion.f0();
153 mF1 = selectedRegion.f1();
155 mPresetNames.push_back(L"control-f0");
157 mPresetNames.push_back(L"control-f1");
158
159#endif
161
162 // Allow the dialog factory to fill this in, but it might not
163 std::shared_ptr<EffectInstance> pInstance;
164
165 if (IsInteractive()) {
166 if (!finder)
167 return false;
168 else if (auto result = finder(settings))
169 pInstance = *result;
170 else
171 return false;
172 }
173
174 auto pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(pInstance);
175 if (!pInstanceEx) {
176 // Path that skipped the dialog factory -- effect may be non-interactive
177 // or this is batch mode processing or repeat of last effect with stored
178 // settings.
179 pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(MakeInstance());
180 // Note: Init may read parameters from preferences
181 if (!pInstanceEx || !pInstanceEx->Init())
182 return false;
183 }
184
185
186 // If the dialog was shown, then it has been closed without errors or
187 // cancellation, and any change of duration has been saved in the config file
188
189 bool returnVal = true;
190 bool skipFlag = CheckWhetherSkipEffect(settings);
191 if (skipFlag == false)
192 {
193 using namespace BasicUI;
194 auto name = GetName();
195 auto progress = MakeProgress(
196 name,
197 XO("Applying %s...").Format( name ),
199 );
200 auto vr = valueRestorer( mProgress, progress.get() );
201
202 assert(pInstanceEx); // null check above
203 returnVal = pInstanceEx->Process(settings);
204 }
205
206 if (returnVal && (mT1 >= mT0 ))
207 {
208 selectedRegion.setTimes(mT0, mT1);
209 }
210
211 success = returnVal;
212 return returnVal;
213}
214
215void EffectBase::SetLinearEffectFlag(bool linearEffectFlag)
216{
217 mIsLinearEffect = linearEffectFlag;
218}
219
220void EffectBase::SetPreviewFullSelectionFlag(bool previewDurationFlag)
221{
222 mPreviewFullSelection = previewDurationFlag;
223}
224
226{
227 if (!inputTracks())
228 return nullptr;
229 return inputTracks()->GetOwner();
230}
231
233{
234 const auto range = mTracks->Selected<const WaveTrack>();
235 mNumTracks = range.sum(&WaveTrack::NChannels);
236 mNumGroups = range.size();
237}
238
240{
241 return {};
242}
243
245 -> std::optional<InstancePointer>
246{
247 auto result = plugin.MakeInstance();
248 if (auto pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(result)
249 ; pInstanceEx && pInstanceEx->Init())
250 return { pInstanceEx };
251 return {};
252}
253
255{
256 return [&plugin](auto&) { return FindInstance(plugin); };
257}
@ Internal
Indicates internal failure from Audacity.
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:250
#define QUANTIZED_TIME(time, rate)
Definition: MemoryX.h:333
#define NYQUIST_PROMPT_ID
static Settings & settings()
Definition: TrackInfo.cpp:69
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:232
void SetPreviewFullSelectionFlag(bool previewDurationFlag)
Definition: EffectBase.cpp:220
void SetLinearEffectFlag(bool linearEffectFlag)
Definition: EffectBase.cpp:215
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:239
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:244
wxArrayString mPresetNames
Definition: EffectBase.h:99
double GetDefaultDuration()
Definition: EffectBase.cpp:48
static InstanceFinder DefaultInstanceFinder(EffectPlugin &plugin)
Definition: EffectBase.cpp:254
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:225
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:213
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:993
AudacityProject * GetOwner()
Definition: Track.h:1032
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:1279
std::shared_ptr< WaveTrack > Create()
Creates an unnamed empty WaveTrack with default sample format and default rate.
Definition: WaveTrack.cpp:761
A Track that contains audio waveform data.
Definition: WaveTrack.h:227
static wxString GetDefaultAudioTrackNamePreference()
Definition: WaveTrack.cpp:743
size_t NChannels() const override
May report more than one only when this is a leader track.
Definition: WaveTrack.cpp:836
@ ProgressShowCancel
Definition: BasicUI.h:142
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:292
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
auto finder(TrackId id, int &distance)
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:172