Audacity 3.2.0
TwoPassSimpleMono.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 TwoPassSimpleMono.cpp
6
7 Dominic Mazzoni
8
9*******************************************************************//*******************************************************************/
18#include "TwoPassSimpleMono.h"
19#include "EffectOutputTracks.h"
20#include "WaveTrack.h"
21
23
26{
27 mPass = 0;
28 mSecondPassDisabled = false;
29
30 InitPass1();
31 EffectOutputTracks outputs { *mTracks, GetType(), { { mT0, mT1 } } };
32
34 for (auto track : outputs.Get().Selected<WaveTrack>()) {
35 auto pNewTracks = track->WideEmptyCopy();
36 mWorkTracks->Append(std::move(*pNewTracks));
37 }
38 for (const auto pNewTrack : mWorkTracks->Any<WaveTrack>()) {
39 pNewTrack->ConvertToSampleFormat(floatSample);
40 if (mT0 > 0)
41 pNewTrack->InsertSilence(0, mT0);
42 }
43
44 mTrackLists[0] = &outputs.Get();
46
47 bool bGoodResult = ProcessPass(settings);
48 if (bGoodResult && !mSecondPassDisabled) {
49 mPass = 1;
50 if (InitPass2())
51 bGoodResult = ProcessPass(settings);
52 }
53
54 mWorkTracks->Clear();
55 mWorkTracks.reset();
56
57 if (bGoodResult)
58 outputs.Commit();
59
60 return bGoodResult;
61}
62
64{
65 // Iterate over each track
66 mCurTrackNum = 0;
67
68 auto outTracks =
69 (*mTrackLists[1 - mPass]).Selected<WaveTrack>().begin();
70 for (auto track : (*mTrackLists[mPass]).Selected<WaveTrack>()) {
71 auto outTrack = *outTracks;
72
73 // Get start and end times from track
74 double trackStart = track->GetStartTime();
75 double trackEnd = track->GetEndTime();
76
77 // Set the current bounds to whichever left marker is
78 // greater and whichever right marker is less:
79 mCurT0 = std::max(trackStart, mT0);
80 mCurT1 = std::min(trackEnd, mT1);
81
82 // Process only if the right marker is to the right of the left marker
83 if (mCurT1 > mCurT0) {
84 // Transform the marker timepoints to samples
85 auto start = track->TimeToLongSamples(mCurT0);
86 auto end = track->TimeToLongSamples(mCurT1);
87
88 // Get the track rate and samples
89 mCurRate = track->GetRate();
90
91 // NewTrackPass1/2() returns true by default
92 bool ret;
93 if (mPass == 0)
94 ret = NewTrackPass1();
95 else
96 ret = NewTrackPass2();
97 if (!ret)
98 return false;
99
100 // ProcessOne() (implemented below) processes a single track
101 auto outIter = outTrack->Channels().begin();
102 for (const auto pChannel : track->Channels())
103 if (!ProcessOne(*pChannel, **outIter++, start, end))
104 return false;
105 if (!mSecondPassDisabled && mPass == 0)
106 outTrack->Flush();
107 }
108
109 ++mCurTrackNum;
110 ++outTracks;
111 }
112
113 return true;
114}
115
116
117// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
118// and executes TwoBufferProcessPass1 or TwoBufferProcessPass2 on these blocks
120 WaveChannel &outTrack, sampleCount start, sampleCount end)
121{
122 bool ret;
123
124 // Get the length of the buffer (as double). len is
125 // used simple to calculate a progress meter, so it is easier
126 // to make it a double now than it is to do it later
127 auto len = (end - start).as_double();
128 auto maxblock = track.GetMaxBlockSize();
129
130 // Initiate a processing buffer. This buffer will (most likely)
131 // be shorter than the length of the track being processed.
132 Floats buffer1{ maxblock };
133 Floats buffer2{ maxblock };
134 auto samples1 = limitSampleBufferSize(
135 std::min(maxblock, track.GetBestBlockSize(start)), end - start);
136
137 // Get the samples from the track and put them in the buffer
138 track.GetFloats(buffer1.get(), start, samples1);
139
140 // Process the first buffer with a null previous buffer
141 if (mPass == 0)
142 ret = TwoBufferProcessPass1(nullptr, 0, buffer1.get(), samples1);
143 else
144 ret = TwoBufferProcessPass2(nullptr, 0, buffer1.get(), samples1);
145 if (!ret)
146 // Return false because the effect failed.
147 return false;
148
149 // Go through the track one buffer at a time. s counts which
150 // sample the current buffer starts at.
151 auto s = start + samples1;
152 while (s < end) {
153 // Get a block of samples (smaller than the size of the buffer)
154 // Adjust the block size if it is the final block in the track
155 auto samples2 = limitSampleBufferSize(
156 std::min(track.GetBestBlockSize(s), maxblock), end - s);
157
158 // Get the samples from the track and put them in the buffer
159 track.GetFloats(buffer2.get(), s, samples2);
160
161 // Process the buffer. If it fails, clean up and exit.
162 if (mPass == 0)
163 ret = TwoBufferProcessPass1(buffer1.get(), samples1, buffer2.get(),
164 samples2);
165 else
166 ret = TwoBufferProcessPass2(buffer1.get(), samples1, buffer2.get(),
167 samples2);
168 if (!ret)
169 // Return false because the effect failed.
170 return false;
171
172 // Processing succeeded. copy the newly-changed samples back
173 // onto the track.
174 if (mSecondPassDisabled || mPass != 0) {
175 if (!outTrack.Set((samplePtr)buffer1.get(), floatSample, s - samples1,
176 samples1))
177 return false;
178 }
179 else
180 outTrack.Append((samplePtr)buffer1.get(), floatSample, samples1);
181
182 // Increment s one blockfull of samples
183 s += samples2;
184
185 // Update the Progress meter
187 ret = TotalProgress(
188 (mCurTrackNum + (s - start).as_double() / len) /
190 else
191 ret = TotalProgress(
192 (mCurTrackNum + (s-start).as_double() / len +
194 (GetNumWaveTracks() * 2));
195 if (ret)
196 // Return false because the effect failed.
197 return false;
198
199 // Rotate the buffers
200 buffer1.swap(buffer2);
201 std::swap(samples1, samples2);
202 }
203
204 // Send the last buffer with a null pointer for the current buffer
205 if (mPass == 0)
206 ret = TwoBufferProcessPass1(buffer1.get(), samples1, nullptr, 0);
207 else
208 ret = TwoBufferProcessPass2(buffer1.get(), samples1, nullptr, 0);
209
210 if (!ret)
211 //Return false because the effect failed.
212 return false;
213
214 // Processing succeeded. copy the newly-changed samples back
215 // onto the track.
216 if (mSecondPassDisabled || mPass != 0) {
217 if (!outTrack.Set((samplePtr)buffer1.get(), floatSample, s - samples1,
218 samples1))
219 return false;
220 }
221 else
222 outTrack.Append((samplePtr)buffer1.get(), floatSample, samples1);
223
224 // Return true because the effect processing succeeded.
225 return true;
226}
227
229{
230 return true;
231}
232
234{
235 return true;
236}
237
238//Initialisations before the first pass
240{
241 return true;
242}
243
244//Initialisations before the second pass.
245//Return true if you actually want the second pass to go ahead
247{
248 return true;
249}
250
int min(int a, int b)
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
char * samplePtr
Definition: SampleFormat.h:57
static Settings & settings()
Definition: TrackInfo.cpp:69
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
double mT1
Definition: EffectBase.h:116
std::shared_ptr< TrackList > mTracks
Definition: EffectBase.h:109
double mT0
Definition: EffectBase.h:115
const AudacityProject * FindProject() const
Definition: EffectBase.cpp:225
virtual EffectType GetType() const =0
Type determines how it behaves.
bool TotalProgress(double frac, const TranslatableString &={}) const
Definition: Effect.cpp:335
int GetNumWaveTracks() const
Definition: Effect.h:139
Performs effect computation.
Use this object to copy the input tracks to tentative outputTracks.
virtual bool TwoBufferProcessPass2(float *buffer1, size_t len1, float *buffer2, size_t len2)
bool ProcessPass(EffectSettings &settings)
virtual bool TwoBufferProcessPass1(float *buffer1, size_t len1, float *buffer2, size_t len2)
bool Process(EffectInstance &instance, EffectSettings &settings) override
~EffectTwoPassSimpleMono() override
std::shared_ptr< TrackList > mWorkTracks
bool ProcessOne(WaveChannel &t, WaveChannel &outTrack, sampleCount start, sampleCount end)
static TrackListHolder Create(AudacityProject *pOwner)
Definition: Track.cpp:365
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:347
bool Set(constSamplePtr buffer, sampleFormat format, sampleCount start, size_t len, sampleFormat effectiveFormat=widestSampleFormat)
Random-access assignment of a range of samples.
Definition: WaveTrack.cpp:3506
bool Append(constSamplePtr buffer, sampleFormat format, size_t len)
Definition: WaveTrack.cpp:2656
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
"narrow" overload fetches from the unique channel
Definition: WaveTrack.h:154
size_t GetBestBlockSize(sampleCount t) const
A hint for sizing of well aligned fetches.
Definition: WaveTrack.h:1216
size_t GetMaxBlockSize() const
Definition: WaveTrack.h:1224
A Track that contains audio waveform data.
Definition: WaveTrack.h:222
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:645
Externalized state of a plug-in.