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 pNewTrack = track->EmptyCopy();
36 mWorkTracks->Add(pNewTrack);
37 }
38 for (const auto pNewTrack : mWorkTracks->Any<WaveTrack>()) {
39 pNewTrack->ConvertToSampleFormat(floatSample);
40 }
41
42 mTrackLists[0] = &outputs.Get();
44
45 bool bGoodResult = ProcessPass(settings);
46 if (bGoodResult && !mSecondPassDisabled) {
47 mPass = 1;
48 if (InitPass2())
49 bGoodResult = ProcessPass(settings);
50 }
51
52 mWorkTracks->Clear();
53 mWorkTracks.reset();
54
55 if (bGoodResult)
56 outputs.Commit();
57
58 return bGoodResult;
59}
60
62{
63 // Iterate over each track
64 mCurTrackNum = 0;
65
66 auto outTracks =
67 (*mTrackLists[1 - mPass]).Selected<WaveTrack>().begin();
68 for (auto track : (*mTrackLists[mPass]).Selected<WaveTrack>()) {
69 auto outTrack = *outTracks;
70
71 // Get start and end times from the orignal track
72 double trackStart = mPass == 0 ? track->GetStartTime() : (*outTracks)->GetStartTime();
73 double trackEnd = mPass == 0 ? track->GetEndTime() : (*outTracks)->GetEndTime();
74
75 // Set the current bounds to whichever left marker is
76 // greater and whichever right marker is less:
77 mCurT0 = std::max(trackStart, mT0);
78 mCurT1 = std::min(trackEnd, mT1);
79
80 // So that in ProcessOne(), when mPass == 0, samples are
81 // appended starting at mCurT0
82 if (!mSecondPassDisabled && mPass == 0 && mCurT0 > 0)
83 (*outTracks)->InsertSilence(0, mCurT0);
84
85 // Process only if the right marker is to the right of the left marker
86 if (mCurT1 > mCurT0) {
87 // Transform the marker timepoints to samples
88 auto start = track->TimeToLongSamples(mCurT0);
89 auto end = track->TimeToLongSamples(mCurT1);
90
91 // Get the track rate and samples
92 mCurRate = track->GetRate();
93
94 // NewTrackPass1/2() returns true by default
95 bool ret;
96 if (mPass == 0)
97 ret = NewTrackPass1();
98 else
99 ret = NewTrackPass2();
100 if (!ret)
101 return false;
102
103 // ProcessOne() (implemented below) processes a single track
104 auto outIter = outTrack->Channels().begin();
105 for (const auto pChannel : track->Channels())
106 if (!ProcessOne(*pChannel, **outIter++, start, end))
107 return false;
108 if (!mSecondPassDisabled && mPass == 0)
109 outTrack->Flush();
110 }
111
112 ++mCurTrackNum;
113 ++outTracks;
114 }
115
116 return true;
117}
118
119
120// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
121// and executes TwoBufferProcessPass1 or TwoBufferProcessPass2 on these blocks
123 WaveChannel &outTrack, sampleCount start, sampleCount end)
124{
125 bool ret;
126
127 // Get the length of the buffer (as double). len is
128 // used simple to calculate a progress meter, so it is easier
129 // to make it a double now than it is to do it later
130 auto len = (end - start).as_double();
131 auto maxblock = track.GetMaxBlockSize();
132
133 // Initiate a processing buffer. This buffer will (most likely)
134 // be shorter than the length of the track being processed.
135 Floats buffer1{ maxblock };
136 Floats buffer2{ maxblock };
137 auto samples1 = limitSampleBufferSize(
138 std::min(maxblock, track.GetBestBlockSize(start)), end - start);
139
140 // Get the samples from the track and put them in the buffer
141 track.GetFloats(buffer1.get(), start, samples1);
142
143 // Process the first buffer with a null previous buffer
144 if (mPass == 0)
145 ret = TwoBufferProcessPass1(nullptr, 0, buffer1.get(), samples1);
146 else
147 ret = TwoBufferProcessPass2(nullptr, 0, buffer1.get(), samples1);
148 if (!ret)
149 // Return false because the effect failed.
150 return false;
151
152 // Go through the track one buffer at a time. s counts which
153 // sample the current buffer starts at.
154 auto s = start + samples1;
155 while (s < end) {
156 // Get a block of samples (smaller than the size of the buffer)
157 // Adjust the block size if it is the final block in the track
158 auto samples2 = limitSampleBufferSize(
159 std::min(track.GetBestBlockSize(s), maxblock), end - s);
160
161 // Get the samples from the track and put them in the buffer
162 track.GetFloats(buffer2.get(), s, samples2);
163
164 // Process the buffer. If it fails, clean up and exit.
165 if (mPass == 0)
166 ret = TwoBufferProcessPass1(buffer1.get(), samples1, buffer2.get(),
167 samples2);
168 else
169 ret = TwoBufferProcessPass2(buffer1.get(), samples1, buffer2.get(),
170 samples2);
171 if (!ret)
172 // Return false because the effect failed.
173 return false;
174
175 // Processing succeeded. copy the newly-changed samples back
176 // onto the track.
177 if (mSecondPassDisabled || mPass != 0) {
178 if (!outTrack.SetFloats(buffer1.get(), s - samples1,
179 samples1))
180 return false;
181 }
182 else
183 outTrack.Append((samplePtr)buffer1.get(), floatSample, samples1);
184
185 // Increment s one blockfull of samples
186 s += samples2;
187
188 // Update the Progress meter
190 ret = TotalProgress(
191 (mCurTrackNum + (s - start).as_double() / len) /
193 else
194 ret = TotalProgress(
195 (mCurTrackNum + (s-start).as_double() / len +
197 (GetNumWaveTracks() * 2));
198 if (ret)
199 // Return false because the effect failed.
200 return false;
201
202 // Rotate the buffers
203 buffer1.swap(buffer2);
204 std::swap(samples1, samples2);
205 }
206
207 // Send the last buffer with a null pointer for the current buffer
208 if (mPass == 0)
209 ret = TwoBufferProcessPass1(buffer1.get(), samples1, nullptr, 0);
210 else
211 ret = TwoBufferProcessPass2(buffer1.get(), samples1, nullptr, 0);
212
213 if (!ret)
214 //Return false because the effect failed.
215 return false;
216
217 // Processing succeeded. copy the newly-changed samples back
218 // onto the track.
219 if (mSecondPassDisabled || mPass != 0) {
220 if (!outTrack.SetFloats(buffer1.get(), s - samples1,
221 samples1))
222 return false;
223 }
224 else
225 outTrack.Append((samplePtr)buffer1.get(), floatSample, samples1);
226
227 // Return true because the effect processing succeeded.
228 return true;
229}
230
232{
233 return true;
234}
235
237{
238 return true;
239}
240
241//Initialisations before the first pass
243{
244 return true;
245}
246
247//Initialisations before the second pass.
248//Return true if you actually want the second pass to go ahead
250{
251 return true;
252}
253
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:47
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:114
std::shared_ptr< TrackList > mTracks
Definition: EffectBase.h:107
double mT0
Definition: EffectBase.h:113
const AudacityProject * FindProject() const
Definition: EffectBase.cpp:220
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:330
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
bool SetFloats(const float *buffer, sampleCount start, size_t len, sampleFormat effectiveFormat=widestSampleFormat)
Random-access assignment of a range of samples.
Definition: WaveTrack.h:162
bool Append(constSamplePtr buffer, sampleFormat format, size_t len)
Definition: WaveTrack.cpp:2216
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:129
size_t GetBestBlockSize(sampleCount t) const
A hint for sizing of well aligned fetches.
Definition: WaveTrack.h:850
size_t GetMaxBlockSize() const
Definition: WaveTrack.h:858
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:628
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
Externalized state of a plug-in.