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