1 /**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Effect.h
6
7 Dominic Mazzoni
8 Vaughan Johnson
9
10 **********************************************************************/
11
12 #ifndef __AUDACITY_EFFECT__
13 #define __AUDACITY_EFFECT__
14
15
16
17 #include <functional>
18 #include <set>
19
20 #include <wx/defs.h>
21
22 class wxButton;
23 class wxCheckBox;
24 class wxChoice;
25 class wxListBox;
26 class wxWindow;
27
28 #include "ConfigInterface.h"
29 #include "EffectInterface.h"
30 #include "PluginInterface.h"
31
32 #include "SampleCount.h"
33 #include "SelectedRegion.h"
34
35 #include "../Track.h"
36
37 #include "../widgets/wxPanelWrapper.h" // to inherit
38
39 class wxArrayString;
40 class ShuttleGui;
41 class AudacityCommand;
42
43 #define BUILTIN_EFFECT_PREFIX wxT("Built-in Effect: ")
44
45 class AudacityProject;
46 class LabelTrack;
47 class NotifyingSelectedRegion;
48 class ProgressDialog;
49 class SelectedRegion;
50 class EffectUIHost;
51 class Track;
52 class TrackList;
53 class WaveTrackFactory;
54 class WaveTrack;
55
56 /* i18n-hint: "Nyquist" is an embedded interpreted programming language in
57 Audacity, named in honor of the Swedish-American Harry Nyquist (or Nyqvist).
58 In the translations of this and other strings, you may transliterate the
59 name into another alphabet. */
60 #define NYQUISTEFFECTS_FAMILY ( EffectFamilySymbol{ XO("Nyquist") } )
61
62 #define NYQUIST_WORKER_ID wxT("Nyquist Worker")
63
64 // TODO: Apr-06-2015
65 // TODO: Much more cleanup of old methods and variables is needed, but
66 // TODO: can't be done until after all effects are using the NEW API.
67
68 class AUDACITY_DLL_API Effect /* not final */ : public wxEvtHandler,
69 public EffectClientInterface,
70 public EffectUIClientInterface,
71 public EffectHostInterface
72 {
73 //
74 // public methods
75 //
76 // Used by the outside program to determine properties of an effect and
77 // apply the effect to one or more tracks.
78 //
79 public:
80 // The constructor is called once by each subclass at the beginning of the program.
81 // Avoid allocating memory or doing time-consuming processing here.
82 Effect();
83 virtual ~Effect();
84
85 // Type of a registered function that, if it returns true,
86 // causes ShowInterface to return early without making any dialog
87 using VetoDialogHook = bool (*) ( wxDialog* );
88 static VetoDialogHook SetVetoDialogHook( VetoDialogHook hook );
89
90 // ComponentInterface implementation
91
92 PluginPath GetPath() override;
93
94 ComponentInterfaceSymbol GetSymbol() override;
95
96 VendorSymbol GetVendor() override;
97 wxString GetVersion() override;
98 TranslatableString GetDescription() override;
99
100 // EffectDefinitionInterface implementation
101
102 EffectType GetType() override;
103 EffectFamilySymbol GetFamily() override;
104 bool IsInteractive() override;
105 bool IsDefault() override;
106 bool IsLegacy() override;
107 bool SupportsRealtime() override;
108 bool SupportsAutomation() override;
109
110 // EffectClientInterface implementation
111
112 bool SetHost(EffectHostInterface *host) override;
113
114 unsigned GetAudioInCount() override;
115 unsigned GetAudioOutCount() override;
116
117 int GetMidiInCount() override;
118 int GetMidiOutCount() override;
119
120 sampleCount GetLatency() override;
121 size_t GetTailSize() override;
122
123 void SetSampleRate(double rate) override;
124 size_t SetBlockSize(size_t maxBlockSize) override;
125 size_t GetBlockSize() const override;
126
127 bool IsReady() override;
128 bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap = NULL) override;
129 bool ProcessFinalize() override;
130 size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen) override;
131
132 bool RealtimeInitialize() override;
133 bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) override;
134 bool RealtimeFinalize() override;
135 bool RealtimeSuspend() override;
136 bool RealtimeResume() override;
137 bool RealtimeProcessStart() override;
138 size_t RealtimeProcess(int group,
139 float **inbuf,
140 float **outbuf,
141 size_t numSamples) override;
142 bool RealtimeProcessEnd() override;
143
144 bool ShowInterface( wxWindow &parent,
145 const EffectDialogFactory &factory, bool forceModal = false) override;
146
147 bool GetAutomationParameters(CommandParameters & parms) override;
148 bool SetAutomationParameters(CommandParameters & parms) override;
149
150 bool LoadUserPreset(const RegistryPath & name) override;
151 bool SaveUserPreset(const RegistryPath & name) override;
152
153 RegistryPaths GetFactoryPresets() override;
154 bool LoadFactoryPreset(int id) override;
155 bool LoadFactoryDefaults() override;
156
157 // EffectUIClientInterface implementation
158
159 void SetHostUI(EffectUIHostInterface *host) override;
160 bool PopulateUI(ShuttleGui &S) final;
161 bool IsGraphicalUI() override;
162 bool ValidateUI() override;
163 bool HideUI() override;
164 bool CloseUI() override;
165
166 bool CanExportPresets() override;
167 void ExportPresets() override;
168 void ImportPresets() override;
169
170 static CommandID GetSquashedName(wxString name);
171
172 bool HasOptions() override;
173 void ShowOptions() override;
174
175 // EffectHostInterface implementation
176
177 double GetDefaultDuration() override;
178 double GetDuration() override;
179 NumericFormatSymbol GetDurationFormat() override;
180 virtual NumericFormatSymbol GetSelectionFormat() /* not override? */; // time format in Selection toolbar
181 void SetDuration(double duration) override;
182
183 RegistryPath GetUserPresetsGroup(const RegistryPath & name) override;
184 RegistryPath GetCurrentSettingsGroup() override;
185 RegistryPath GetFactoryDefaultsGroup() override;
186 virtual wxString GetSavedStateGroup() /* not override? */;
187
188 // ConfigClientInterface implementation
189
190 bool HasSharedConfigGroup(const RegistryPath & group) override;
191 bool GetSharedConfigSubgroups(const RegistryPath & group, RegistryPaths &subgroups) override;
192
193 bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, wxString & value, const wxString & defval = {}) override;
194 bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, int & value, int defval = 0) override;
195 bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, bool & value, bool defval = false) override;
196 bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, float & value, float defval = 0.0) override;
197 bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, double & value, double defval = 0.0) override;
198
199 bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const wxString & value) override;
200 bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const int & value) override;
201 bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const bool & value) override;
202 bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const float & value) override;
203 bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const double & value) override;
204
205 bool RemoveSharedConfigSubgroup(const RegistryPath & group) override;
206 bool RemoveSharedConfig(const RegistryPath & group, const RegistryPath & key) override;
207
208 bool HasPrivateConfigGroup(const RegistryPath & group) override;
209 bool GetPrivateConfigSubgroups(const RegistryPath & group, RegistryPaths &paths) override;
210
211 bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, wxString & value, const wxString & defval = {}) override;
212 bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, int & value, int defval = 0) override;
213 bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, bool & value, bool defval = false) override;
214 bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, float & value, float defval = 0.0) override;
215 bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, double & value, double defval = 0.0) override;
216
217 bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const wxString & value) override;
218 bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const int & value) override;
219 bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const bool & value) override;
220 bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const float & value) override;
221 bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const double & value) override;
222
223 bool RemovePrivateConfigSubgroup(const RegistryPath & group) override;
224 bool RemovePrivateConfig(const RegistryPath & group, const RegistryPath & key) override;
225
226 // Effect implementation
227
228 // NEW virtuals
229 virtual PluginID GetID();
230
231 virtual bool Startup(EffectClientInterface *client);
232 virtual bool Startup();
233
234 virtual bool GetAutomationParameters(wxString & parms);
235 virtual bool SetAutomationParameters(const wxString & parms);
236
237 virtual RegistryPaths GetUserPresets();
238 virtual bool HasCurrentSettings();
239 virtual bool HasFactoryDefaults();
240
241 // Name of page in the Audacity alpha manual
242 virtual ManualPageID ManualPage();
243 // Fully qualified local help file name
244 virtual FilePath HelpPage();
245
246 virtual void SetUIFlags(unsigned flags);
247 virtual unsigned TestUIFlags(unsigned mask);
248 virtual bool IsBatchProcessing();
249 virtual void SetBatchProcessing(bool start);
250
SetPresetParameters(const wxArrayString * Names,const wxArrayString * Values)251 /* not virtual */ void SetPresetParameters( const wxArrayString * Names, const wxArrayString * Values ) {
252 if( Names ) mPresetNames = *Names;
253 if( Values ) mPresetValues = *Values;
254 }
255
256 // Returns true on success. Will only operate on tracks that
257 // have the "selected" flag set to true, which is consistent with
258 // Audacity's standard UI.
259 // Create a user interface only if the supplied function is not null.
260 /* not virtual */ bool DoEffect( double projectRate, TrackList *list,
261 WaveTrackFactory *factory, NotifyingSelectedRegion &selectedRegion,
262 // Prompt the user for input only if these arguments are both not null.
263 wxWindow *pParent = nullptr,
264 const EffectDialogFactory &dialogFactory = {} );
265
266 bool Delegate( Effect &delegate,
267 wxWindow &parent, const EffectDialogFactory &factory );
268
269 virtual bool IsHidden();
270
271 // Nonvirtual
272 // Display a message box, using effect's (translated) name as the prefix
273 // for the title.
274 enum : long { DefaultMessageBoxStyle = wxOK | wxCENTRE };
275 int MessageBox(const TranslatableString& message,
276 long style = DefaultMessageBoxStyle,
277 const TranslatableString& titleStr = {});
278
IncEffectCounter()279 static void IncEffectCounter(){ nEffectsDone++;};
280
281 //
282 // protected virtual methods
283 //
284 // Each subclass of Effect overrides one or more of these methods to
285 // do its processing.
286 //
287 protected:
288
289 // Called once each time an effect is called. Perform any initialization;
290 // make sure that the effect can be performed on the selected tracks and
291 // return false otherwise
292 virtual bool Init();
293
294 // Check whether effect should be skipped
295 // Typically this is only useful in automation, for example
296 // detecting that zero noise reduction is to be done,
297 // or that normalisation is being done without Dc bias shift
298 // or amplitude modification
CheckWhetherSkipEffect()299 virtual bool CheckWhetherSkipEffect() { return false; }
300
301 // Actually do the effect here.
302 virtual bool Process();
303 virtual bool ProcessPass();
304 virtual bool InitPass1();
305 virtual bool InitPass2();
306 virtual int GetPass();
307
308 // clean up any temporary memory, needed only per invocation of the
309 // effect, after either successful or failed or exception-aborted processing.
310 // Invoked inside a "finally" block so it must be no-throw.
311 virtual void End();
312
313 // Most effects just use the previewLength, but time-stretching/compressing
314 // effects need to use a different input length, so override this method.
315 virtual double CalcPreviewInputLength(double previewLength);
316
317 // The Effect class fully implements the Preview method for you.
318 // Only override it if you need to do preprocessing or cleanup.
319 virtual void Preview(bool dryOnly);
320
321 virtual void PopulateOrExchange(ShuttleGui & S);
322 virtual bool TransferDataToWindow() /* not override */;
323 virtual bool TransferDataFromWindow() /* not override */;
324 virtual bool EnableApply(bool enable = true);
325 virtual bool EnablePreview(bool enable = true);
326 virtual void EnableDebug(bool enable = true);
327
328 // No more virtuals!
329
330 // The Progress methods all return true if the user has cancelled;
331 // you should exit immediately if this happens (cleaning up memory
332 // is okay, but don't try to undo).
333
334 // Pass a fraction between 0.0 and 1.0
335 bool TotalProgress(double frac, const TranslatableString & = {});
336
337 // Pass a fraction between 0.0 and 1.0, for the current track
338 // (when doing one track at a time)
339 bool TrackProgress(int whichTrack, double frac, const TranslatableString & = {});
340
341 // Pass a fraction between 0.0 and 1.0, for the current track group
342 // (when doing stereo groups at a time)
343 bool TrackGroupProgress(int whichGroup, double frac, const TranslatableString & = {});
344
GetNumWaveTracks()345 int GetNumWaveTracks() { return mNumTracks; }
GetNumWaveGroups()346 int GetNumWaveGroups() { return mNumGroups; }
347
348 // Calculates the start time and length in samples for one or two channels
349 void GetBounds(
350 const WaveTrack &track, const WaveTrack *pRight,
351 sampleCount *start, sampleCount *len);
352
353 // Previewing linear effect can be optimised by pre-mixing. However this
354 // should not be used for non-linear effects such as dynamic processors
355 // To allow pre-mixing before Preview, set linearEffectFlag to true.
356 void SetLinearEffectFlag(bool linearEffectFlag);
357
358 // Most effects only need to preview a short selection. However some
359 // (such as fade effects) need to know the full selection length.
360 void SetPreviewFullSelectionFlag(bool previewDurationFlag);
361
362 // Use this if the effect needs to know if it is previewing
IsPreviewing()363 bool IsPreviewing() { return mIsPreview; }
364
365 // Most effects only require selected tracks to be copied for Preview.
366 // If IncludeNotSelectedPreviewTracks(true), then non-linear effects have
367 // preview copies of all wave tracks.
368 void IncludeNotSelectedPreviewTracks(bool includeNotSelected);
369
370 // Use this method to copy the input tracks to mOutputTracks, if
371 // doing the processing on them, and replacing the originals only on success (and not cancel).
372 // If not all sync-locked selected, then only selected wave tracks.
373 void CopyInputTracks(bool allSyncLockSelected = false);
374
375 // A global counter of all the successful Effect invocations.
376 static int nEffectsDone;
377
378 // For the use of analyzers, which don't need to make output wave tracks,
379 // but may need to add label tracks.
380 class AUDACITY_DLL_API AddedAnalysisTrack {
381 friend Effect;
382 AddedAnalysisTrack(Effect *pEffect, const wxString &name);
383 AddedAnalysisTrack(const AddedAnalysisTrack&) PROHIBITED;
384
385 public:
386
AddedAnalysisTrack()387 AddedAnalysisTrack() {}
388
389 // So you can have a vector of them
390 AddedAnalysisTrack(AddedAnalysisTrack &&that);
391
get()392 LabelTrack *get() const { return mpTrack; }
393
394 // Call this to indicate successful completion of the analyzer.
395 void Commit();
396
397 // Destructor undoes the addition of the analysis track if not committed.
398 ~AddedAnalysisTrack();
399
400 private:
401 Effect *mpEffect{};
402 LabelTrack *mpTrack{};
403 };
404
405 // Set name to given value if that is not empty, else use default name
406 std::shared_ptr<AddedAnalysisTrack> AddAnalysisTrack(const wxString &name = wxString());
407
408 // For the use of analyzers, which don't need to make output wave tracks,
409 // but may need to modify label tracks.
410 class AUDACITY_DLL_API ModifiedAnalysisTrack {
411 friend Effect;
412 ModifiedAnalysisTrack
413 (Effect *pEffect, const LabelTrack *pOrigTrack, const wxString &name);
414 ModifiedAnalysisTrack(const ModifiedAnalysisTrack&) PROHIBITED;
415
416 public:
417
418 ModifiedAnalysisTrack();
419
420 // So you can have a vector of them
421 ModifiedAnalysisTrack(ModifiedAnalysisTrack &&that);
422
get()423 LabelTrack *get() const { return mpTrack; }
424
425 // Call this to indicate successful completion of the analyzer.
426 void Commit();
427
428 // Destructor undoes the modification of the analysis track if not committed.
429 ~ModifiedAnalysisTrack();
430
431 private:
432 Effect *mpEffect{};
433 LabelTrack *mpTrack{};
434 std::shared_ptr<Track> mpOrigTrack{};
435 };
436
437 // Set name to given value if that is not empty, else use default name
438 ModifiedAnalysisTrack ModifyAnalysisTrack
439 (const LabelTrack *pOrigTrack, const wxString &name = wxString());
440
441 // If bGoodResult, replace mWaveTracks tracks in mTracks with successfully processed
442 // mOutputTracks copies, get rid of old mWaveTracks, and set mWaveTracks to mOutputTracks.
443 // Else clear and DELETE mOutputTracks copies.
444 void ReplaceProcessedTracks(const bool bGoodResult);
445
446 // Use this to append a NEW output track.
447 Track *AddToOutputTracks(const std::shared_ptr<Track> &t);
448
449 //
450 // protected data
451 //
452 // The Effect base class will set these variables, some or all of which
453 // may be needed by any particular subclass of Effect.
454 //
455 protected:
456
457 ProgressDialog *mProgress; // Temporary pointer, NOT deleted in destructor.
458 double mProjectRate; // Sample rate of the project - NEW tracks should
459 // be created with this rate...
460 double mSampleRate;
461 wxWeakRef<NotifyingSelectedRegion> mpSelectedRegion{};
462 WaveTrackFactory *mFactory;
inputTracks()463 const TrackList *inputTracks() const { return mTracks; }
464 const AudacityProject *FindProject() const;
465 std::shared_ptr<TrackList> mOutputTracks; // used only if CopyInputTracks() is called.
466 double mT0;
467 double mT1;
468 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
469 double mF0;
470 double mF1;
471 #endif
472 wxArrayString mPresetNames;
473 wxArrayString mPresetValues;
474 int mPass;
475
476 // UI
477 wxDialog *mUIDialog;
478 wxWindow *mUIParent;
479 int mUIResultID;
480 unsigned mUIFlags;
481
482 sampleCount mSampleCnt;
483
484 // Used only by the base Effect class
485 //
486 private:
487 void CountWaveTracks();
488
489 // Driver for client effects
490 bool ProcessTrack(int count,
491 ChannelNames map,
492 WaveTrack *left,
493 WaveTrack *right,
494 sampleCount start,
495 sampleCount len,
496 FloatBuffers &inBuffer,
497 FloatBuffers &outBuffer,
498 ArrayOf< float * > &inBufPos,
499 ArrayOf< float *> &outBufPos);
500
501 //
502 // private data
503 //
504 // Used only by the base Effect class
505 //
506 private:
507 TrackList *mTracks; // the complete list of all tracks
508
509 bool mIsBatch;
510 bool mIsLinearEffect;
511 bool mPreviewWithNotSelected;
512 bool mPreviewFullSelection;
513
514 double mDuration;
515 NumericFormatSymbol mDurationFormat;
516
517 bool mIsPreview;
518
519 bool mUIDebug;
520
521 std::vector<Track*> mIMap;
522 std::vector<Track*> mOMap;
523
524 int mNumTracks; //v This is really mNumWaveTracks, per CountWaveTracks() and GetNumWaveTracks().
525 int mNumGroups;
526
527 // For client driver
528 EffectClientInterface *mClient;
529 size_t mNumAudioIn;
530 size_t mNumAudioOut;
531
532 size_t mBufferSize;
533 size_t mBlockSize;
534 unsigned mNumChannels;
535
536 public:
537 const static wxString kUserPresetIdent;
538 const static wxString kFactoryPresetIdent;
539 const static wxString kCurrentSettingsIdent;
540 const static wxString kFactoryDefaultsIdent;
541
542 friend class EffectUIHost;
543 };
544
545 // FIXME:
546 // FIXME: Remove this once all effects are using the NEW dialog
547 // FIXME:
548
549 #define ID_EFFECT_PREVIEW ePreviewID
550
551 // Utility functions
552
TrapFloat(float x,float min,float max)553 inline float TrapFloat(float x, float min, float max)
554 {
555 if (x <= min)
556 return min;
557
558 if (x >= max)
559 return max;
560
561 return x;
562 }
563
TrapDouble(double x,double min,double max)564 inline double TrapDouble(double x, double min, double max)
565 {
566 if (x <= min)
567 return min;
568
569 if (x >= max)
570 return max;
571
572 return x;
573 }
574
TrapLong(long x,long min,long max)575 inline long TrapLong(long x, long min, long max)
576 {
577 if (x <= min)
578 return min;
579
580 if (x >= max)
581 return max;
582
583 return x;
584 }
585
586 // Helper macros for defining, reading and verifying effect parameters
587
588 #define Param(name, type, key, def, min, max, scale) \
589 static const wxChar * KEY_ ## name = (key); \
590 static const type DEF_ ## name = (def); \
591 static const type MIN_ ## name = (min); \
592 static const type MAX_ ## name = (max); \
593 static const type SCL_ ## name = (scale);
594
595 #define PBasic(name, type, key, def) \
596 static const wxChar * KEY_ ## name = (key); \
597 static const type DEF_ ## name = (def);
598
599 #define PRange(name, type, key, def, min, max) \
600 PBasic(name, type, key, def); \
601 static const type MIN_ ## name = (min); \
602 static const type MAX_ ## name = (max);
603
604 #define PScale(name, type, key, def, min, max, scale) \
605 PRange(name, type, key, def, min, max); \
606 static const type SCL_ ## name = (scale);
607
608 #define ReadParam(type, name) \
609 type name = DEF_ ## name; \
610 if (!parms.ReadAndVerify(KEY_ ## name, &name, DEF_ ## name, MIN_ ## name, MAX_ ## name)) \
611 return false;
612
613 #define ReadBasic(type, name) \
614 type name; \
615 wxUnusedVar(MIN_ ##name); \
616 wxUnusedVar(MAX_ ##name); \
617 wxUnusedVar(SCL_ ##name); \
618 if (!parms.ReadAndVerify(KEY_ ## name, &name, DEF_ ## name)) \
619 return false;
620
621 #define ReadAndVerifyEnum(name, list, listSize) \
622 int name; \
623 if (!parms.ReadAndVerify(KEY_ ## name, &name, DEF_ ## name, list, listSize)) \
624 return false;
625
626 #define ReadAndVerifyEnumWithObsoletes(name, list, listSize, obsoleteList, nObsolete) \
627 int name; \
628 if (!parms.ReadAndVerify(KEY_ ## name, &name, DEF_ ## name, \
629 list, listSize, obsoleteList, nObsolete)) \
630 return false;
631
632 #define ReadAndVerifyInt(name) ReadParam(int, name)
633 #define ReadAndVerifyDouble(name) ReadParam(double, name)
634 #define ReadAndVerifyFloat(name) ReadParam(float, name)
635 #define ReadAndVerifyBool(name) ReadBasic(bool, name)
636 #define ReadAndVerifyString(name) ReadBasic(wxString, name)
637
638 #endif
639