94{
95 const auto duration =
settings.extra.GetDuration();
96 bool bGoodResult = true;
99
102 size_t prevBufferSize = 0;
103 int count = 0;
104 bool clear = false;
105
106
107
108 const auto numAudioIn = instance.GetAudioInCount();
109 const auto numAudioOut = instance.GetAudioOutCount();
110 if (numAudioOut < 1)
111 return false;
112
113
114 std::vector<std::shared_ptr<EffectInstance>> recycledInstances{
115
116
117 std::dynamic_pointer_cast<EffectInstanceEx>(instance.shared_from_this())
118 };
119
120 const bool multichannel = numAudioIn > 1;
123 const auto waveTrackVisitor =
125 if (isLeader)
127
131
132 const int channel = (multichannel ? -1 :
iChannel++);
134 if (multichannel) {
135 assert(numAudioIn > 1);
136 if (numChannels == 2) {
137
138 pRight = (*leader.
Channels().rbegin()).get();
139 clear = false;
140 }
141 }
142
143 if (!isGenerator) {
146 if (len > 0 && numAudioIn < 1) {
147 bGoodResult = false;
148 return;
149 }
150 }
151 else
153
155
156
158 const auto blockSize = instance.SetBlockSize(max);
159 if (blockSize == 0) {
160 bGoodResult = false;
161 return;
162 }
163
164
165
166 const auto bufferSize =
167 ((max + (blockSize - 1)) / blockSize) * blockSize;
168 if (bufferSize == 0) {
169 bGoodResult = false;
170 return;
171 }
172
173
174
175
176
177
178 if (len > 0)
179 assert(numAudioIn > 0);
180 inBuffers.Reinit(
181
182
183
184 std::max(1u, numAudioIn),
185 blockSize,
186 std::max<size_t>(1, bufferSize / blockSize));
187 if (len > 0)
188
189 assert(inBuffers.Channels() > 0);
190
191 if (prevBufferSize != bufferSize) {
192
193
194
195 for (size_t i = 2; i < numAudioIn; i++)
196 inBuffers.ClearBuffer(i, bufferSize);
197 }
198 prevBufferSize = bufferSize;
199
200
201
202
203
204
205 assert(numAudioOut > 0);
206 outBuffers.Reinit(numAudioOut, blockSize,
207 (bufferSize / blockSize) + 1);
208
209 assert(outBuffers.Channels() > 0);
210
211
212 inBuffers.Rewind();
213
214
215 if (!pRight && !clear && numAudioIn > 1) {
216 inBuffers.ClearBuffer(1, bufferSize);
217 clear = true;
218 }
219
220 const auto genLength = [
this, &
settings, &leader, isGenerator](
221 ) -> std::optional<sampleCount> {
222 double genDur = 0;
223 if (isGenerator) {
224 const auto duration =
settings.extra.GetDuration();
226 gPrefs->
Read(
wxT(
"/AudioIO/EffectsPreviewLen"), &genDur, 6.0);
228 }
229 else
230 genDur = duration;
231
232 return sampleCount{ (leader.GetRate() * genDur) + 0.5 };
233 }
234 else
235 return {};
236 }();
237
238 const auto pollUser = [this, numChannels, count, start,
239 length = (genLength ? *genLength : len).as_double()
241 if (numChannels > 1) {
243 count, (inPos - start).as_double() / length)
244 )
245 return false;
246 }
247 else {
248 if (
TrackProgress(count, (inPos - start).as_double() / length))
249 return false;
250 }
251 return true;
252 };
253
254
255 assert(len == 0 || inBuffers.Channels() > 0);
256
257
258 if (len == 0 && genLength)
259 len = *genLength;
261 chan, size_t(pRight ? 2 : 1), start, len, pollUser };
262
263 assert(source.AcceptsBuffers(inBuffers));
264 assert(source.AcceptsBlockSize(inBuffers.BlockSize()));
265
266
267
268 auto wideTrack =
269 (pRight && isGenerator) ? leader.WideEmptyCopy() : nullptr;
270 auto narrowTrack =
271 (!pRight && isGenerator) ? leader.EmptyCopy() : nullptr;
272 const auto pGenerated = wideTrack
274 : narrowTrack.get();
275 const auto tempList =
276 wideTrack ? move(wideTrack)
277 : narrowTrack ?
TrackList::Temporary(nullptr, narrowTrack, nullptr)
278 : nullptr;
279
280 WaveTrackSink sink{ chan, pRight, pGenerated, start, isProcessor,
282 };
283 assert(sink.AcceptsBuffers(outBuffers));
284
285
287 [this, &recycledInstances, counter = 0]() mutable {
288 auto index = counter++;
289 if (index < recycledInstances.size())
290 return recycledInstances[index];
291 else
293 };
295 genLength,
sampleRate, leader, inBuffers, outBuffers);
296 if (bGoodResult) {
297 sink.Flush(outBuffers);
298 bGoodResult = sink.IsOk();
299 if (bGoodResult && tempList) {
300 if (!results)
301 results = tempList;
302 else
303 results->Append(std::move(*tempList));
304 }
305 }
306 if (!bGoodResult)
307 return;
308 ++count;
309 };
310 const auto defaultTrackVisitor =
313 t.SyncLockAdjust(
mT1,
mT0 + duration);
314 };
315
316 outputs.
Any().VisitWhile(bGoodResult,
317 [&](
auto &&fallthrough){
return [&](
WaveTrack &wt) {
318 if (!wt.GetSelected())
319 return fallthrough();
320 const auto channels = wt.Channels();
321 if (multichannel)
322 waveTrackVisitor(wt, **channels.begin(), true);
323 else {
324 bool first = true;
325 for (const auto pChannel : channels) {
326 waveTrackVisitor(wt, *pChannel, first);
327 first = false;
328 }
329 }
330 if (results) {
333 mT0 + (*results->begin())->GetEndTime() };
334 wt.ClearAndPaste(
mT0, t1, *results,
true,
true, &warper);
335 results.reset();
336 }
337 }; },
338 defaultTrackVisitor
339 );
340
343
344 return bGoodResult;
345}
unsigned MakeChannelMap(const WideSampleSequence &sequence, int channel, ChannelName map[3])
audacity::BasicSettings * gPrefs
std::shared_ptr< TrackList > TrackListHolder
bool IsPreviewing() const
const AudacityProject * FindProject() const
bool TrackGroupProgress(int whichGroup, double frac, const TranslatableString &={}) const
void GetBounds(const WaveTrack &track, sampleCount *start, sampleCount *len)
double CalcPreviewInputLength(const EffectSettings &settings, double previewLength) const override
Default implementation returns previewLength
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
virtual std::shared_ptr< EffectInstance > MakeInstance() const =0
Make an object maintaining short-term state of an Effect.
Unit slope but with either a jump (pasting more) or a flat interval (pasting less)
static bool ProcessTrack(int channel, const Factory &factory, EffectSettings &settings, AudioGraph::Source &source, AudioGraph::Sink &sink, std::optional< sampleCount > genLength, double sampleRate, const SampleTrack &leader, Buffers &inBuffers, Buffers &outBuffers)
AudioGraph::Buffers Buffers
static bool IsSyncLockSelected(const Track *pTrack)
Abstract base class for an object holding data associated with points on a time axis.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
auto Any() -> TrackIterRange< TrackType >
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
A Track that contains audio waveform data.
double GetRate() const override
size_t GetMaxBlockSize() const
sampleCount TimeToLongSamples(double t0) const
Adapts WideSampleSequence to the interface AudioGraph::Source.
virtual bool Read(const wxString &key, bool *value) const =0
Positions or offsets within audio files need a wide type.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
constexpr auto sampleRate
static RegisteredToolbarFactory factory