Audacity 3.2.0
Classes | Public Member Functions | Protected Member Functions | Protected Attributes | Private Member Functions | List of all members
PerTrackEffect Class Reference

Base class for many of the effects in Audacity. More...

#include <PerTrackEffect.h>

Inheritance diagram for PerTrackEffect:
[legend]
Collaboration diagram for PerTrackEffect:
[legend]

Classes

class  Instance
 

Public Member Functions

 ~PerTrackEffect () override
 
- Public Member Functions inherited from Effect
 Effect ()
 
virtual ~Effect ()
 
PluginPath GetPath () const override
 
bool VisitSettings (SettingsVisitor &visitor, EffectSettings &settings) override
 
bool VisitSettings (ConstSettingsVisitor &visitor, const EffectSettings &settings) const override
 
ComponentInterfaceSymbol GetSymbol () const override
 
VendorSymbol GetVendor () const override
 
wxString GetVersion () const override
 
TranslatableString GetDescription () const override
 
EffectType GetType () const override
 Type determines how it behaves. More...
 
EffectFamilySymbol GetFamily () const override
 Report identifier and user-visible name of the effect protocol. More...
 
bool IsInteractive () const override
 Whether the effect needs a dialog for entry of settings. More...
 
bool IsDefault () const override
 Whether the effect sorts "above the line" in the menus. More...
 
bool SupportsRealtime () const override
 Whether the effect supports realtime previewing (while audio is playing). More...
 
bool SupportsAutomation () const override
 Whether the effect has any automatable controls. More...
 
bool SaveSettings (const EffectSettings &settings, CommandParameters &parms) const override
 Store settings as keys and values. More...
 
bool LoadSettings (const CommandParameters &parms, EffectSettings &settings) const override
 Restore settings from keys and values. More...
 
bool LoadUserPreset (const RegistryPath &name, EffectSettings &settings) const override
 Change settings to a user-named preset. More...
 
bool SaveUserPreset (const RegistryPath &name, const EffectSettings &settings) const override
 Save settings in the configuration file as a user-named preset. More...
 
RegistryPaths GetFactoryPresets () const override
 Report names of factory presets. More...
 
bool LoadFactoryPreset (int id, EffectSettings &settings) const override
 Change settings to the preset whose name is GetFactoryPresets()[id] More...
 
bool LoadFactoryDefaults (EffectSettings &settings) const override
 Change settings back to "factory default". More...
 
unsigned GetAudioInCount () const override
 How many input buffers to allocate at once. More...
 
unsigned GetAudioOutCount () const override
 How many output buffers to allocate at once. More...
 
virtual const EffectParameterMethodsParameters () const
 
int ShowClientInterface (wxWindow &parent, wxDialog &dialog, bool forceModal=false) override
 
std::unique_ptr< EffectUIValidatorPopulateUI (ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access) override
 Adds controls to a panel that is given as the parent window of S More...
 
bool IsGraphicalUI () override
 
bool ValidateUI (EffectSettings &) override
 
bool CloseUI () override
 
bool CanExportPresets () override
 
void ExportPresets (const EffectSettings &settings) const override
 
void ImportPresets (EffectSettings &settings) override
 
bool HasOptions () override
 
void ShowOptions () override
 
const EffectSettingsManagerGetDefinition () const override
 
virtual NumericFormatSymbol GetSelectionFormat ()
 
int ShowHostInterface (wxWindow &parent, const EffectDialogFactory &factory, EffectInstance &instance, EffectSettingsAccess &access, bool forceModal=false) override
 Usually applies factory to self and given access. More...
 
bool SaveSettingsAsString (const EffectSettings &settings, wxString &parms) const override
 
bool LoadSettingsFromString (const wxString &parms, EffectSettings &settings) const override
 
bool IsBatchProcessing () const override
 
void SetBatchProcessing () override
 
void UnsetBatchProcessing () override
 
bool TransferDataToWindow (const EffectSettings &settings) override
 Update controls for the settings. More...
 
bool TransferDataFromWindow (EffectSettings &settings) override
 Update the given settings from controls. More...
 
unsigned TestUIFlags (unsigned mask)
 
bool Delegate (Effect &delegate, EffectSettings &settings)
 Re-invoke DoEffect on another Effect object that implements the work. More...
 
int MessageBox (const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={}) const
 
bool EnableApply (bool enable=true)
 
wxWindow * GetUIParent ()
 
- Public Member Functions inherited from EffectBase
 EffectBase ()
 
 ~EffectBase () override
 
- Public Member Functions inherited from EffectUIClientInterface
virtual ~EffectUIClientInterface ()
 
virtual int ShowClientInterface (wxWindow &parent, wxDialog &dialog, bool forceModal=false)=0
 
virtual bool IsGraphicalUI ()=0
 
virtual std::unique_ptr< EffectUIValidatorPopulateUI (ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access)=0
 Adds controls to a panel that is given as the parent window of S More...
 
virtual bool CanExportPresets ()=0
 
virtual void ExportPresets (const EffectSettings &settings) const =0
 
virtual void ImportPresets (EffectSettings &settings)=0
 
virtual bool HasOptions ()=0
 
virtual void ShowOptions ()=0
 
- Public Member Functions inherited from EffectPlugin
EffectPluginoperator= (EffectPlugin &)=delete
 
virtual ~EffectPlugin ()
 
virtual const EffectSettingsManagerGetDefinition () const =0
 
virtual int ShowHostInterface (wxWindow &parent, const EffectDialogFactory &factory, EffectInstance &instance, EffectSettingsAccess &access, bool forceModal=false)=0
 Usually applies factory to self and given access. More...
 
virtual void Preview (EffectSettingsAccess &access, bool dryOnly)=0
 
virtual bool SaveSettingsAsString (const EffectSettings &settings, wxString &parms) const =0
 
virtual bool LoadSettingsFromString (const wxString &parms, EffectSettings &settings) const =0
 
virtual bool IsBatchProcessing () const =0
 
virtual void SetBatchProcessing ()=0
 
virtual void UnsetBatchProcessing ()=0
 
virtual bool DoEffect (EffectSettings &settings, double projectRate, TrackList *list, WaveTrackFactory *factory, NotifyingSelectedRegion &selectedRegion, unsigned flags, wxWindow *pParent=nullptr, const EffectDialogFactory &dialogFactory={}, const EffectSettingsAccessPtr &pAccess=nullptr)=0
 Unfortunately complicated dual-use function. More...
 
virtual bool TransferDataToWindow (const EffectSettings &settings)=0
 Update controls for the settings. More...
 
virtual bool TransferDataFromWindow (EffectSettings &settings)=0
 Update the given settings from controls. More...
 
- Public Member Functions inherited from EffectInstanceFactory
virtual ~EffectInstanceFactory ()
 
virtual std::shared_ptr< EffectInstanceMakeInstance () const =0
 Make an object maintaining short-term state of an Effect. More...
 
virtual unsigned GetAudioInCount () const =0
 How many input buffers to allocate at once. More...
 
virtual unsigned GetAudioOutCount () const =0
 How many output buffers to allocate at once. More...
 
virtual int GetMidiInCount () const
 Function that has not yet found a use. More...
 
virtual int GetMidiOutCount () const
 Function that has not yet found a use. More...
 
- Public Member Functions inherited from EffectSettingsManager
virtual ~EffectSettingsManager ()
 
virtual bool VisitSettings (SettingsVisitor &visitor, EffectSettings &settings)
 
virtual bool VisitSettings (ConstSettingsVisitor &visitor, const EffectSettings &settings) const
 
virtual EffectSettings MakeSettings () const
 
virtual bool CopySettingsContents (const EffectSettings &src, EffectSettings &dst) const
 Update one settings object from another. More...
 
- Public Member Functions inherited from EffectDefinitionInterface
virtual ~EffectDefinitionInterface ()
 
virtual EffectType GetType () const =0
 Type determines how it behaves. More...
 
virtual EffectType GetClassification () const
 Determines which menu it appears in; default same as GetType(). More...
 
virtual EffectFamilySymbol GetFamily () const =0
 Report identifier and user-visible name of the effect protocol. More...
 
virtual bool IsInteractive () const =0
 Whether the effect needs a dialog for entry of settings. More...
 
virtual bool IsDefault () const =0
 Whether the effect sorts "above the line" in the menus. More...
 
virtual bool SupportsRealtime () const =0
 Whether the effect supports realtime previewing (while audio is playing). More...
 
virtual bool SupportsAutomation () const =0
 Whether the effect has any automatable controls. More...
 
virtual bool EnablesDebug () const
 Whether the effect dialog should have a Debug button; default, always false. More...
 
virtual ManualPageID ManualPage () const
 Name of a page in the Audacity alpha manual, default is empty. More...
 
virtual FilePath HelpPage () const
 Fully qualified local help file name, default is empty. More...
 
virtual bool IsHiddenFromMenus () const
 Default is false. More...
 
- Public Member Functions inherited from ComponentInterface
virtual ~ComponentInterface ()
 
virtual PluginPath GetPath () const =0
 
virtual ComponentInterfaceSymbol GetSymbol () const =0
 
virtual VendorSymbol GetVendor () const =0
 
virtual wxString GetVersion () const =0
 
virtual TranslatableString GetDescription () const =0
 
TranslatableString GetName () const
 

Protected Member Functions

bool DoPass1 () const
 
bool DoPass2 () const
 
bool Process (EffectInstance &instance, EffectSettings &settings) const
 
- Protected Member Functions inherited from Effect
bool EnablePreview (bool enable=true)
 
bool CheckWhetherSkipEffect (const EffectSettings &settings) const override
 Default implementation returns false. More...
 
double CalcPreviewInputLength (const EffectSettings &settings, double previewLength) const override
 Default implementation returns previewLength More...
 
virtual std::unique_ptr< EffectUIValidatorPopulateOrExchange (ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access)
 Add controls to effect panel; always succeeds. More...
 
bool TotalProgress (double frac, const TranslatableString &={}) const
 
bool TrackProgress (int whichTrack, double frac, const TranslatableString &={}) const
 
bool TrackGroupProgress (int whichGroup, double frac, const TranslatableString &={}) const
 
int GetNumWaveTracks () const
 
int GetNumWaveGroups () const
 
void GetBounds (const WaveTrack &track, const WaveTrack *pRight, sampleCount *start, sampleCount *len)
 
void CopyInputTracks (bool allSyncLockSelected=false)
 
std::shared_ptr< AddedAnalysisTrackAddAnalysisTrack (const wxString &name=wxString())
 
ModifiedAnalysisTrack ModifyAnalysisTrack (const LabelTrack *pOrigTrack, const wxString &name=wxString())
 
TrackAddToOutputTracks (const std::shared_ptr< Track > &t)
 
- Protected Member Functions inherited from EffectBase
void Preview (EffectSettingsAccess &access, bool dryOnly) override
 
bool DoEffect (EffectSettings &settings, double projectRate, TrackList *list, WaveTrackFactory *factory, NotifyingSelectedRegion &selectedRegion, unsigned flags, wxWindow *pParent, const EffectDialogFactory &dialogFactory, const EffectSettingsAccessPtr &pAccess) override
 Unfortunately complicated dual-use function. More...
 
virtual bool CheckWhetherSkipEffect (const EffectSettings &settings) const =0
 After Init(), tell whether Process() should be skipped. More...
 
virtual double CalcPreviewInputLength (const EffectSettings &settings, double previewLength) const =0
 
void SetLinearEffectFlag (bool linearEffectFlag)
 
void SetPreviewFullSelectionFlag (bool previewDurationFlag)
 
bool IsPreviewing () const
 
void IncludeNotSelectedPreviewTracks (bool includeNotSelected)
 
void ReplaceProcessedTracks (const bool bGoodResult)
 
const TrackListinputTracks () const
 
const AudacityProjectFindProject () const
 
virtual bool ValidateUI (EffectSettings &settings)=0
 
virtual bool CloseUI ()=0
 

Protected Attributes

sampleCount mSampleCnt {}
 
- Protected Attributes inherited from Effect
wxWeakRef< wxDialog > mHostUIDialog
 This smart pointer tracks the lifetime of the dialog. More...
 
wxWindow * mUIParent {}
 
- Protected Attributes inherited from EffectBase
BasicUI::ProgressDialogmProgress {}
 
double mProjectRate {}
 
WaveTrackFactorymFactory {}
 
std::shared_ptr< TrackListmOutputTracks
 
double mT0 {}
 
double mT1 {}
 
wxArrayString mPresetNames
 
unsigned mUIFlags { 0 }
 
- Protected Attributes inherited from EffectUIClientInterface
friend EffectUIValidator
 
friend DefaultEffectUIValidator
 

Private Member Functions

bool ProcessPass (Instance &instance, EffectSettings &settings)
 
bool ProcessTrack (Instance &instance, EffectSettings &settings, int count, ChannelNames map, WaveTrack *left, WaveTrack *right, sampleCount start, sampleCount len, FloatBuffers &inBuffer, FloatBuffers &outBuffer, ArrayOf< float * > &inBufPos, ArrayOf< float * > &outBufPos, size_t bufferSize, size_t blockSize, unsigned mNumChannels) const
 

Additional Inherited Members

- Public Types inherited from Effect
enum  : long { DefaultMessageBoxStyle = wxOK | wxCENTRE }
 
- Public Types inherited from EffectPlugin
using EffectSettingsAccessPtr = std::shared_ptr< EffectSettingsAccess >
 
- Static Public Member Functions inherited from Effect
static EffectFetchParameters (Effect &e, EffectSettings &)
 
static void IncEffectCounter ()
 
- Static Public Member Functions inherited from EffectDefinitionInterface
static Identifier GetSquashedName (const Identifier &ident)
 A utility that strips spaces and CamelCases a name. More...
 
- Static Public Attributes inherited from EffectPlugin
static const wxString kUserPresetIdent = wxT("User Preset:")
 
static const wxString kFactoryPresetIdent = wxT("Factory Preset:")
 
static const wxString kCurrentSettingsIdent = wxT("<Current Settings>")
 
static const wxString kFactoryDefaultsIdent = wxT("<Factory Defaults>")
 
- Static Protected Attributes inherited from EffectBase
static int nEffectsDone = 0
 

Detailed Description

Base class for many of the effects in Audacity.

Base class for Effects that treat each (mono or stereo) track independently of other tracks.

Its override of Effect::Process() uses ProcessInitialize(), ProcessBlock(), and ProcessFinalize() methods of its instance made by MakeInstance(), which must be a subclass of PerTrackEffect::Instance. Also uses GetLatency() to determine how many leading output samples to discard and how many extra samples to produce.

Definition at line 31 of file PerTrackEffect.h.

Constructor & Destructor Documentation

◆ ~PerTrackEffect()

PerTrackEffect::~PerTrackEffect ( )
overridedefault

Member Function Documentation

◆ DoPass1()

bool PerTrackEffect::DoPass1 ( ) const
protected

Definition at line 53 of file PerTrackEffect.cpp.

54{
55 return true;
56}

Referenced by Process().

Here is the caller graph for this function:

◆ DoPass2()

bool PerTrackEffect::DoPass2 ( ) const
protected

Definition at line 58 of file PerTrackEffect.cpp.

59{
60 return false;
61}

Referenced by Process().

Here is the caller graph for this function:

◆ Process()

bool PerTrackEffect::Process ( EffectInstance instance,
EffectSettings settings 
) const
protected

Definition at line 63 of file PerTrackEffect.cpp.

65{
66 auto pThis = const_cast<PerTrackEffect *>(this);
67 pThis->CopyInputTracks(true);
68 bool bGoodResult = true;
69 // mPass = 1;
70 if (DoPass1()) {
71 auto &myInstance = dynamic_cast<Instance&>(instance);
72 bGoodResult = pThis->ProcessPass(myInstance, settings);
73 // mPass = 2;
74 if (bGoodResult && DoPass2())
75 bGoodResult = pThis->ProcessPass(myInstance, settings);
76 }
77 pThis->ReplaceProcessedTracks(bGoodResult);
78 return bGoodResult;
79}
static Settings & settings()
Definition: TrackInfo.cpp:87
void CopyInputTracks(bool allSyncLockSelected=false)
Definition: Effect.cpp:739
Base class for many of the effects in Audacity.
bool DoPass2() const
bool DoPass1() const

References Effect::CopyInputTracks(), DoPass1(), DoPass2(), and settings().

Referenced by StatefulPerTrackEffect::Process(), and PerTrackEffect::Instance::Process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProcessPass()

bool PerTrackEffect::ProcessPass ( Instance instance,
EffectSettings settings 
)
private

Definition at line 81 of file PerTrackEffect.cpp.

82{
83 const auto duration = settings.extra.GetDuration();
84 bool bGoodResult = true;
85 bool isGenerator = GetType() == EffectTypeGenerate;
86
87 FloatBuffers inBuffer, outBuffer;
88 ArrayOf<float *> inBufPos, outBufPos;
89 ChannelName map[3];
90 size_t bufferSize = 0;
91 size_t blockSize = 0;
92 int count = 0;
93 bool clear = false;
94
95 // It's possible that the number of channels the effect expects changed based on
96 // the parameters (the Audacity Reverb effect does when the stereo width is 0).
97 const auto numAudioIn = GetAudioInCount();
98 const auto numAudioOut = GetAudioOutCount();
99 const bool multichannel = numAudioIn > 1;
100 auto range = multichannel
101 ? mOutputTracks->Leaders()
102 : mOutputTracks->Any();
103 range.VisitWhile( bGoodResult,
104 [&](WaveTrack *left, const Track::Fallthrough &fallthrough) {
105 if (!left->GetSelected())
106 return fallthrough();
107
108 sampleCount len = 0;
109 sampleCount start = 0;
110 unsigned numChannels = 0;
111 WaveTrack *right{};
112
113 // Iterate either over one track which could be any channel,
114 // or if multichannel, then over all channels of left,
115 // which is a leader.
116 for (auto channel :
117 TrackList::Channels(left).StartingWith(left)) {
118 if (channel->GetChannel() == Track::LeftChannel)
119 map[numChannels] = ChannelNameFrontLeft;
120 else if (channel->GetChannel() == Track::RightChannel)
121 map[numChannels] = ChannelNameFrontRight;
122 else
123 map[numChannels] = ChannelNameMono;
124 ++ numChannels;
125 map[numChannels] = ChannelNameEOL;
126 if (! multichannel)
127 break;
128 if (numChannels == 2) {
129 // TODO: more-than-two-channels
130 right = channel;
131 clear = false;
132 // Ignore other channels
133 break;
134 }
135 }
136
137 if (!isGenerator) {
138 GetBounds(*left, right, &start, &len);
139 mSampleCnt = len;
140 }
141 else
142 mSampleCnt = left->TimeToLongSamples(duration);
143
144 // Let the client know the sample rate
145 instance.SetSampleRate(left->GetRate());
146
147 // Get the block size the client wants to use
148 auto max = left->GetMaxBlockSize() * 2;
149 blockSize = instance.SetBlockSize(max);
150
151 // Calculate the buffer size to be at least the max rounded up to the clients
152 // selected block size.
153 const auto prevBufferSize = bufferSize;
154 bufferSize = ((max + (blockSize - 1)) / blockSize) * blockSize;
155
156 // If the buffer size has changed, then (re)allocate the buffers
157 if (prevBufferSize != bufferSize) {
158 // Always create the number of input buffers the client expects even if we don't have
159 // the same number of channels.
160 inBufPos.reinit( numAudioIn );
161 inBuffer.reinit( numAudioIn, bufferSize );
162
163 // We won't be using more than the first 2 buffers, so clear the rest (if any)
164 for (size_t i = 2; i < numAudioIn; i++)
165 for (size_t j = 0; j < bufferSize; j++)
166 inBuffer[i][j] = 0.0;
167
168 // Always create the number of output buffers the client expects even if we don't have
169 // the same number of channels.
170 outBufPos.reinit( numAudioOut );
171 // Output buffers get an extra blockSize worth to give extra room if
172 // the plugin adds latency
173 outBuffer.reinit( numAudioOut, bufferSize + blockSize );
174 }
175
176 // (Re)Set the input buffer positions
177 for (size_t i = 0; i < numAudioIn; i++)
178 inBufPos[i] = inBuffer[i].get();
179
180 // (Re)Set the output buffer positions
181 for (size_t i = 0; i < numAudioOut; i++)
182 outBufPos[i] = outBuffer[i].get();
183
184 // Clear unused input buffers
185 if (!right && !clear && numAudioIn > 1) {
186 for (size_t j = 0; j < bufferSize; j++)
187 inBuffer[1][j] = 0.0;
188 clear = true;
189 }
190
191 // Go process the track(s)
192 bGoodResult = ProcessTrack(instance, settings,
193 count, map, left, right, start, len,
194 inBuffer, outBuffer, inBufPos, outBufPos, bufferSize, blockSize,
195 numChannels);
196 if (!bGoodResult)
197 return;
198
199 count++;
200 },
201 [&](Track *t) {
203 t->SyncLockAdjust(mT1, mT0 + duration);
204 }
205 );
206
207 if (bGoodResult && GetType() == EffectTypeGenerate)
208 mT1 = mT0 + duration;
209
210 return bGoodResult;
211}
@ EffectTypeGenerate
ChannelName
@ ChannelNameFrontLeft
@ ChannelNameEOL
@ ChannelNameMono
@ ChannelNameFrontRight
Memory.h template class for making an array of float, bool, etc.
Definition: MemoryX.h:27
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
void reinit(Integral count)
Definition: MemoryX.h:109
double mT1
Definition: EffectBase.h:107
std::shared_ptr< TrackList > mOutputTracks
Definition: EffectBase.h:105
double mT0
Definition: EffectBase.h:106
unsigned GetAudioInCount() const override
How many input buffers to allocate at once.
Definition: Effect.cpp:137
EffectType GetType() const override
Type determines how it behaves.
Definition: Effect.cpp:96
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
Definition: Effect.cpp:142
void GetBounds(const WaveTrack &track, const WaveTrack *pRight, sampleCount *start, sampleCount *len)
Definition: Effect.cpp:709
bool ProcessTrack(Instance &instance, EffectSettings &settings, int count, ChannelNames map, WaveTrack *left, WaveTrack *right, sampleCount start, sampleCount len, FloatBuffers &inBuffer, FloatBuffers &outBuffer, ArrayOf< float * > &inBufPos, ArrayOf< float * > &outBufPos, size_t bufferSize, size_t blockSize, unsigned mNumChannels) const
sampleCount mSampleCnt
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: SampleTrack.cpp:35
static bool IsSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:43
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
bool GetSelected() const
Definition: Track.h:461
@ LeftChannel
Definition: Track.h:275
@ RightChannel
Definition: Track.h:276
Continuation<> Fallthrough
Type of arguments passed as optional second parameter to TypeSwitch<void>() cases.
Definition: Track.h:533
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1533
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
size_t GetMaxBlockSize() const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1806
double GetRate() const override
Definition: WaveTrack.cpp:481
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18

References ChannelNameEOL, ChannelNameFrontLeft, ChannelNameFrontRight, ChannelNameMono, TrackList::Channels(), EffectTypeGenerate, Effect::GetAudioInCount(), Effect::GetAudioOutCount(), Effect::GetBounds(), WaveTrack::GetMaxBlockSize(), WaveTrack::GetRate(), Track::GetSelected(), Effect::GetType(), SyncLock::IsSyncLockSelected(), Track::LeftChannel, EffectBase::mOutputTracks, mSampleCnt, EffectBase::mT0, EffectBase::mT1, ProcessTrack(), ArraysOf< X >::reinit(), ArrayOf< X >::reinit(), Track::RightChannel, EffectInstance::SetBlockSize(), EffectInstance::SetSampleRate(), settings(), and SampleTrack::TimeToLongSamples().

Here is the call graph for this function:

◆ ProcessTrack()

bool PerTrackEffect::ProcessTrack ( Instance instance,
EffectSettings settings,
int  count,
ChannelNames  map,
WaveTrack left,
WaveTrack right,
sampleCount  start,
sampleCount  len,
FloatBuffers inBuffer,
FloatBuffers outBuffer,
ArrayOf< float * > &  inBufPos,
ArrayOf< float * > &  outBufPos,
size_t  bufferSize,
size_t  blockSize,
unsigned  mNumChannels 
) const
private

Definition at line 213 of file PerTrackEffect.cpp.

225{
226 bool rc = true;
227
228 // Give the plugin a chance to initialize
229 if (!instance.ProcessInitialize(settings, len, map))
230 return false;
231
232 { // Start scope for cleanup
233 auto cleanup = finally( [&] {
234 // Allow the plugin to cleanup
235 if (!instance.ProcessFinalize())
236 // In case of non-exceptional flow of control, set rc
237 rc = false;
238 } );
239
240 // For each input block of samples, we pass it to the effect along with a
241 // variable output location. This output location is simply a pointer into a
242 // much larger buffer. This reduces the number of calls required to add the
243 // samples to the output track.
244 //
245 // Upon return from the effect, the output samples are "moved to the left" by
246 // the number of samples in the current latency setting, effectively removing any
247 // delay introduced by the effect.
248 //
249 // At the same time the total number of delayed samples are gathered and when
250 // there is no further input data to process, the loop continues to call the
251 // effect with an empty input buffer until the effect has had a chance to
252 // return all of the remaining delayed samples.
253 auto inPos = start;
254 auto outPos = start;
255 auto inputRemaining = len;
256 decltype(instance.GetLatency(settings)) curDelay = 0, delayRemaining = 0;
257 decltype(blockSize) curBlockSize = 0;
258 decltype(bufferSize) inputBufferCnt = 0;
259 decltype(bufferSize) outputBufferCnt = 0;
260 bool cleared = false;
261 auto chans = std::min<unsigned>(GetAudioOutCount(), numChannels);
262 std::shared_ptr<WaveTrack> genLeft, genRight;
263 decltype(len) genLength = 0;
264 bool isGenerator = GetType() == EffectTypeGenerate;
265 bool isProcessor = GetType() == EffectTypeProcess;
266 double genDur = 0;
267 if (isGenerator) {
268 const auto duration = settings.extra.GetDuration();
269 if (IsPreviewing()) {
270 gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &genDur, 6.0);
271 genDur = std::min(duration, CalcPreviewInputLength(settings, genDur));
272 }
273 else
274 genDur = duration;
275 genLength = sampleCount((left->GetRate() * genDur) + 0.5); // round to nearest sample
276 delayRemaining = genLength;
277 cleared = true;
278
279 // Create temporary tracks
280 genLeft = left->EmptyCopy();
281
282 if (right)
283 genRight = right->EmptyCopy();
284 }
285
286 // Call the effect until we run out of input or delayed samples
287 while (inputRemaining != 0 || delayRemaining != 0) {
288 // Still working on the input samples
289 if (inputRemaining != 0) {
290 // Need to refill the input buffers
291 if (inputBufferCnt == 0) {
292 // Calculate the number of samples to get
293 inputBufferCnt =
294 limitSampleBufferSize( bufferSize, inputRemaining );
295
296 // Fill the input buffers
297 left->GetFloats(inBuffer[0].get(), inPos, inputBufferCnt);
298 if (right)
299 right->GetFloats(inBuffer[1].get(), inPos, inputBufferCnt);
300
301 // Reset the input buffer positions
302 for (size_t i = 0; i < numChannels; i++)
303 inBufPos[i] = inBuffer[i].get();
304 }
305
306 // Calculate the number of samples to process
307 curBlockSize = blockSize;
308 if (curBlockSize > inputRemaining) {
309 // We've reached the last block...set current block size to what's left
310 // inputRemaining is positive and bounded by a size_t
311 curBlockSize = inputRemaining.as_size_t();
312 inputRemaining = 0;
313
314 // Clear the remainder of the buffers so that a full block can be passed
315 // to the effect
316 auto cnt = blockSize - curBlockSize;
317 for (size_t i = 0; i < numChannels; i++)
318 for (decltype(cnt) j = 0 ; j < cnt; j++)
319 inBufPos[i][j + curBlockSize] = 0.0;
320
321 // Might be able to use up some of the delayed samples
322 if (delayRemaining != 0) {
323 // Don't use more than needed
324 cnt = limitSampleBufferSize(cnt, delayRemaining);
325 delayRemaining -= cnt;
326 curBlockSize += cnt;
327 }
328 }
329 }
330 // We've exhausted the input samples and are now working on the delay
331 else if (delayRemaining != 0) {
332 // Calculate the number of samples to process
333 curBlockSize = limitSampleBufferSize( blockSize, delayRemaining );
334 delayRemaining -= curBlockSize;
335
336 // From this point on, we only want to feed zeros to the plugin
337 if (!cleared) {
338 // Reset the input buffer positions
339 for (size_t i = 0; i < numChannels; i++) {
340 inBufPos[i] = inBuffer[i].get();
341 // And clear
342 for (size_t j = 0; j < blockSize; j++)
343 inBuffer[i][j] = 0.0;
344 }
345 cleared = true;
346 }
347 }
348
349 // Finally call the plugin to process the block
350 decltype(curBlockSize) processed;
351 try {
352 processed = instance.ProcessBlock(
353 settings, inBufPos.get(), outBufPos.get(), curBlockSize);
354 }
355 catch( const AudacityException & WXUNUSED(e) ) {
356 // PRL: Bug 437:
357 // Pass this along to our application-level handler
358 throw;
359 }
360 catch(...) {
361 // PRL:
362 // Exceptions for other reasons, maybe in third-party code...
363 // Continue treating them as we used to, but I wonder if these
364 // should now be treated the same way.
365 return false;
366 }
367 wxASSERT(processed == curBlockSize);
368 wxUnusedVar(processed);
369
370 // Bump to next input buffer position
371 if (inputRemaining != 0) {
372 for (size_t i = 0; i < numChannels; i++)
373 inBufPos[i] += curBlockSize;
374 inputRemaining -= curBlockSize;
375 inputBufferCnt -= curBlockSize;
376 }
377
378 // "ls" and "rs" serve as the input sample index for the left and
379 // right channels when processing the input samples. If we flip
380 // over to processing delayed samples, they simply become counters
381 // for the progress display.
382 inPos += curBlockSize;
383
384 // Get the current number of delayed samples and accumulate
385 if (isProcessor) {
386 {
387 auto delay = instance.GetLatency(settings);
388 curDelay += delay;
389 delayRemaining += delay;
390 }
391
392 // If the plugin has delayed the output by more samples than our current
393 // block size, then we leave the output pointers alone. This effectively
394 // removes those delayed samples from the output buffer.
395 if (curDelay >= curBlockSize) {
396 curDelay -= curBlockSize;
397 curBlockSize = 0;
398 }
399 // We have some delayed samples, at the beginning of the output samples,
400 // so overlay them by shifting the remaining output samples.
401 else if (curDelay > 0) {
402 // curDelay is bounded by curBlockSize:
403 auto delay = curDelay.as_size_t();
404 curBlockSize -= delay;
405 for (size_t i = 0; i < chans; i++)
406 memmove(outBufPos[i], outBufPos[i] + delay, sizeof(float) * curBlockSize);
407 curDelay = 0;
408 }
409 }
410
411 // Adjust the number of samples in the output buffers
412 outputBufferCnt += curBlockSize;
413
414 // Still have room in the output buffers
415 if (outputBufferCnt < bufferSize) {
416 // Bump to next output buffer position
417 for (size_t i = 0; i < chans; i++)
418 outBufPos[i] += curBlockSize;
419 }
420 // Output buffers have filled
421 else {
422 if (isProcessor) {
423 // Write them out
424 left->Set((samplePtr) outBuffer[0].get(), floatSample, outPos, outputBufferCnt);
425 if (right) {
426 if (chans >= 2)
427 right->Set((samplePtr) outBuffer[1].get(), floatSample, outPos, outputBufferCnt);
428 else
429 right->Set((samplePtr) outBuffer[0].get(), floatSample, outPos, outputBufferCnt);
430 }
431 }
432 else if (isGenerator) {
433 genLeft->Append((samplePtr) outBuffer[0].get(), floatSample, outputBufferCnt);
434 if (genRight)
435 genRight->Append((samplePtr) outBuffer[1].get(), floatSample, outputBufferCnt);
436 }
437
438 // Reset the output buffer positions
439 for (size_t i = 0; i < chans; i++)
440 outBufPos[i] = outBuffer[i].get();
441
442 // Bump to the next track position
443 outPos += outputBufferCnt;
444 outputBufferCnt = 0;
445 }
446
447 if (numChannels > 1) {
448 if (TrackGroupProgress(count,
449 (inPos - start).as_double() /
450 (isGenerator ? genLength : len).as_double())) {
451 rc = false;
452 break;
453 }
454 }
455 else {
456 if (TrackProgress(count,
457 (inPos - start).as_double() /
458 (isGenerator ? genLength : len).as_double())) {
459 rc = false;
460 break;
461 }
462 }
463 }
464
465 // Put any remaining output
466 if (rc && outputBufferCnt) {
467 if (isProcessor) {
468 left->Set((samplePtr) outBuffer[0].get(), floatSample, outPos, outputBufferCnt);
469 if (right) {
470 if (chans >= 2)
471 right->Set((samplePtr) outBuffer[1].get(), floatSample, outPos, outputBufferCnt);
472 else
473 right->Set((samplePtr) outBuffer[0].get(), floatSample, outPos, outputBufferCnt);
474 }
475 }
476 else if (isGenerator) {
477 genLeft->Append((samplePtr) outBuffer[0].get(), floatSample, outputBufferCnt);
478 if (genRight)
479 genRight->Append((samplePtr) outBuffer[1].get(), floatSample, outputBufferCnt);
480 }
481 }
482
483 if (rc && isGenerator) {
484 auto pProject = FindProject();
485
486 // Transfer the data from the temporary tracks to the actual ones
487 genLeft->Flush();
488 // mT1 gives us the NEW selection. We want to replace up to GetSel1().
489 auto &selectedRegion = ViewInfo::Get( *pProject ).selectedRegion;
490 auto t1 = selectedRegion.t1();
491 PasteTimeWarper warper{ t1, mT0 + genLeft->GetEndTime() };
492 left->ClearAndPaste(mT0, t1, genLeft.get(), true, true,
493 &warper);
494
495 if (genRight) {
496 genRight->Flush();
497 right->ClearAndPaste(mT0, selectedRegion.t1(),
498 genRight.get(), true, true, nullptr /* &warper */);
499 }
500 }
501
502 } // End scope for cleanup
503 return rc;
504}
int min(int a, int b)
@ EffectTypeProcess
FileConfig * gPrefs
Definition: Prefs.cpp:71
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:23
@ floatSample
Definition: SampleFormat.h:34
char * samplePtr
Definition: SampleFormat.h:49
Base class for exceptions specially processed by the application.
bool IsPreviewing() const
Definition: EffectBase.h:83
const AudacityProject * FindProject() const
Definition: EffectBase.cpp:303
bool TrackGroupProgress(int whichGroup, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:700
double CalcPreviewInputLength(const EffectSettings &settings, double previewLength) const override
Default implementation returns previewLength
Definition: Effect.cpp:863
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:691
double t1() const
Definition: ViewInfo.h:35
Unit slope but with either a jump (pasting more) or a flat interval (pasting less)
Definition: TimeWarper.h:181
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
Retrieve samples from a track in floating-point format, regardless of the storage format.
Definition: SampleTrack.h:65
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:216
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
void Set(constSamplePtr buffer, sampleFormat format, sampleCount start, size_t len)
Definition: WaveTrack.cpp:2195
Holder EmptyCopy(const SampleBlockFactoryPtr &pFactory={}) const
Definition: WaveTrack.cpp:707
void ClearAndPaste(double t0, double t1, const Track *src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=NULL)
Definition: WaveTrack.cpp:915

References sampleCount::as_size_t(), Effect::CalcPreviewInputLength(), WaveTrack::ClearAndPaste(), EffectTypeGenerate, EffectTypeProcess, WaveTrack::EmptyCopy(), EffectBase::FindProject(), floatSample, ViewInfo::Get(), Effect::GetAudioOutCount(), SampleTrack::GetFloats(), PerTrackEffect::Instance::GetLatency(), WaveTrack::GetRate(), Effect::GetType(), gPrefs, EffectBase::IsPreviewing(), limitSampleBufferSize(), min(), EffectBase::mT0, PerTrackEffect::Instance::ProcessBlock(), PerTrackEffect::Instance::ProcessFinalize(), PerTrackEffect::Instance::ProcessInitialize(), ViewInfo::selectedRegion, WaveTrack::Set(), settings(), NotifyingSelectedRegion::t1(), Effect::TrackGroupProgress(), and Effect::TrackProgress().

Referenced by ProcessPass().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mSampleCnt

sampleCount PerTrackEffect::mSampleCnt {}
protected

The documentation for this class was generated from the following files: