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 mTracks->Remove(*newTrack);
99 }
100 // On failure, restore the old duration setting
101 settings.extra.SetDuration(oldDuration);
102 }
103 else
104 trans.Commit();
105
106 mPresetNames.clear();
107 } );
108
109 // We don't yet know the effect type for code in the Nyquist Prompt, so
110 // assume it requires a track and handle errors when the effect runs.
111 if ((GetType() == EffectTypeGenerate || GetPath() == NYQUIST_PROMPT_ID) && (mNumTracks == 0)) {
112 auto track = mFactory->Create();
113 track->SetName(mTracks->MakeUniqueTrackName(WaveTrack::GetDefaultAudioTrackNamePreference()));
114 newTrack = mTracks->Add(track);
115 newTrack->SetSelected(true);
116 }
117
118 mT0 = selectedRegion.t0();
119 mT1 = selectedRegion.t1();
120 if (mT1 > mT0)
121 {
122 // there is a selection: let's fit in there...
123 // MJS: note that this is just for the TTC and is independent of the track rate
124 // but we do need to make sure we have the right number of samples at the project rate
125 double quantMT0 = QUANTIZED_TIME(mT0, mProjectRate);
126 double quantMT1 = QUANTIZED_TIME(mT1, mProjectRate);
127 duration = quantMT1 - quantMT0;
128 isSelection = true;
129 mT1 = mT0 + duration;
130 }
131
132 // This is happening inside EffectSettingsAccess::ModifySettings
133 auto newFormat = (isSelection
136 ).Internal();
137 auto updater = [&](EffectSettings &settings) {
138 settings.extra.SetDuration(duration);
139 settings.extra.SetDurationFormat(newFormat);
140 return nullptr;
141 };
142 // Update our copy of settings; update the EffectSettingsAccess too,
143 // if we are going to show a dialog
145 if (pAccess)
146 pAccess->ModifySettings(updater);
147
148 mF0 = selectedRegion.f0();
149 mF1 = selectedRegion.f1();
151 mPresetNames.push_back(L"control-f0");
153 mPresetNames.push_back(L"control-f1");
154
156
157 // Allow the dialog factory to fill this in, but it might not
158 std::shared_ptr<EffectInstance> pInstance;
159
160 if (IsInteractive()) {
161 if (!finder)
162 return false;
163 else if (auto result = finder(settings))
164 pInstance = *result;
165 else
166 return false;
167 }
168
169 auto pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(pInstance);
170 if (!pInstanceEx) {
171 // Path that skipped the dialog factory -- effect may be non-interactive
172 // or this is batch mode processing or repeat of last effect with stored
173 // settings.
174 pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(MakeInstance());
175 // Note: Init may read parameters from preferences
176 if (!pInstanceEx || !pInstanceEx->Init())
177 return false;
178 }
179
180
181 // If the dialog was shown, then it has been closed without errors or
182 // cancellation, and any change of duration has been saved in the config file
183
184 bool returnVal = true;
185 bool skipFlag = CheckWhetherSkipEffect(settings);
186 if (skipFlag == false)
187 {
188 using namespace BasicUI;
189 auto name = GetName();
190 auto progress = MakeProgress(
191 name,
192 XO("Applying %s...").Format( name ),
194 );
195 auto vr = valueRestorer( mProgress, progress.get() );
196
197 assert(pInstanceEx); // null check above
198 returnVal = pInstanceEx->Process(settings);
199 }
200
201 if (returnVal && (mT1 >= mT0 ))
202 {
203 selectedRegion.setTimes(mT0, mT1);
204 }
205
206 success = returnVal;
207 return returnVal;
208}
209
210void EffectBase::SetLinearEffectFlag(bool linearEffectFlag)
211{
212 mIsLinearEffect = linearEffectFlag;
213}
214
215void EffectBase::SetPreviewFullSelectionFlag(bool previewDurationFlag)
216{
217 mPreviewFullSelection = previewDurationFlag;
218}
219
221{
222 if (!inputTracks())
223 return nullptr;
224 return inputTracks()->GetOwner();
225}
226
228{
229 const auto range = mTracks->Selected<const WaveTrack>();
230 mNumTracks = range.sum(&WaveTrack::NChannels);
231 mNumGroups = range.size();
232}
233
235{
236 return {};
237}
238
240 -> std::optional<InstancePointer>
241{
242 auto result = plugin.MakeInstance();
243 if (auto pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(result)
244 ; pInstanceEx && pInstanceEx->Init())
245 return { pInstanceEx };
246 return {};
247}
248
250{
251 return [&plugin](auto&) { return FindInstance(plugin); };
252}
@ Internal
Indicates internal failure from Audacity.
static RegisteredToolbarFactory factory
Toolkit-neutral facade for basic user interface services.
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:253
#define QUANTIZED_TIME(time, rate)
Definition: MemoryX.h:336
#define NYQUIST_PROMPT_ID
wxString name
Definition: TagsEditor.cpp:166
static Settings & settings()
Definition: TrackInfo.cpp:51
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:117
double mT1
Definition: EffectBase.h:123
WaveTrackFactory * mFactory
Definition: EffectBase.h:121
~EffectBase() override
void CountWaveTracks()
Definition: EffectBase.cpp:227
void SetPreviewFullSelectionFlag(bool previewDurationFlag)
Definition: EffectBase.cpp:215
void SetLinearEffectFlag(bool linearEffectFlag)
Definition: EffectBase.cpp:210
const TrackList * inputTracks() const
Definition: EffectBase.h:102
virtual std::any BeginPreview(const EffectSettings &settings)
Called when Preview() starts, to allow temporary effect state changes.
Definition: EffectBase.cpp:234
virtual bool CheckWhetherSkipEffect(const EffectSettings &settings) const =0
After Init(), tell whether Process() should be skipped.
double mProjectRate
Definition: EffectBase.h:119
BasicUI::ProgressDialog * mProgress
Definition: EffectBase.h:118
int mNumGroups
Definition: EffectBase.h:134
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:116
bool mPreviewFullSelection
Definition: EffectBase.h:132
static std::optional< InstancePointer > FindInstance(EffectPlugin &plugin)
Definition: EffectBase.cpp:239
wxArrayString mPresetNames
Definition: EffectBase.h:108
double GetDefaultDuration()
Definition: EffectBase.cpp:48
double mF0
Definition: EffectBase.h:105
double mF1
Definition: EffectBase.h:106
static InstanceFinder DefaultInstanceFinder(EffectPlugin &plugin)
Definition: EffectBase.cpp:249
double mT0
Definition: EffectBase.h:122
unsigned mUIFlags
Definition: EffectBase.h:109
void SetTracks(TrackList *pTracks)
Definition: EffectBase.cpp:43
bool mIsLinearEffect
Definition: EffectBase.h:131
const AudacityProject * FindProject() const
Definition: EffectBase.cpp:220
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:850
AudacityProject * GetOwner()
Definition: Track.h:887
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:871
std::shared_ptr< WaveTrack > Create()
Creates an unnamed empty WaveTrack with default sample format and default rate.
Definition: WaveTrack.cpp:391
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
static wxString GetDefaultAudioTrackNamePreference()
Definition: WaveTrack.cpp:373
size_t NChannels() const override
A constant property.
Definition: WaveTrack.cpp:530
@ 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:302
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
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:175