Audacity 3.2.0
EffectOutputTracks.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 EffectOutputTracks.cpp
6
7 Paul Licameli split from Effect.cpp and EffectBase.cpp
8
9**********************************************************************/
10#include "EffectOutputTracks.h"
11#include "BasicUI.h"
12#include "SyncLock.h"
13#include "UserException.h"
14#include "WaveTrack.h"
15#include "WaveTrackUtilities.h"
16
17// Effect application counter
19
21 TrackList& tracks, EffectType effectType,
22 std::optional<TimeInterval> effectTimeInterval, bool allSyncLockSelected,
23 bool stretchSyncLocked)
24 : mTracks { tracks }
25 , mEffectType { effectType }
26{
27 assert(
28 !effectTimeInterval.has_value() ||
29 effectTimeInterval->first <= effectTimeInterval->second);
30 // Reset map
31 mIMap.clear();
32 mOMap.clear();
34
35 auto trackRange = mTracks.Any() +
36 [&] (const Track *pTrack) {
37 return allSyncLockSelected
39 : dynamic_cast<const WaveTrack*>(pTrack) && pTrack->GetSelected();
40 };
41
42 for (auto aTrack : trackRange) {
43 auto list = aTrack->Duplicate();
44 mIMap.push_back(aTrack);
45 mOMap.push_back(*list->begin());
46 mOutputTracks->Append(std::move(*list));
47 }
48
49 if (
50 effectTimeInterval.has_value() &&
51 effectTimeInterval->second > effectTimeInterval->first)
52 {
54 [&](const ProgressReporter& parent)
55 {
56 const auto tracksToUnstretch =
57 (stretchSyncLocked ? mOutputTracks->Any<WaveTrack>() :
58 mOutputTracks->Selected<WaveTrack>()) +
59 [&](const WaveTrack* pTrack)
60 {
62 *pTrack, effectTimeInterval->first,
63 effectTimeInterval->second);
64 };
66 tracksToUnstretch.begin(), tracksToUnstretch.end(),
67 [&](WaveTrack* aTrack, const ProgressReporter& child) {
68 aTrack->ApplyStretchRatio(effectTimeInterval, child);
69 },
70 parent);
71 });
72 }
73
74 // Invariant is established
75 assert(mIMap.size() == mOutputTracks->Size());
76 assert(mIMap.size() == mOMap.size());
77}
78
80
81Track *EffectOutputTracks::AddToOutputTracks(const std::shared_ptr<Track> &t)
82{
83 assert(t && t->IsLeader() && t->NChannels() == 1);
84 mIMap.push_back(nullptr);
85 mOMap.push_back(t.get());
86 auto result = mOutputTracks->Add(t);
87 // Invariant is maintained
88 assert(mIMap.size() == mOutputTracks->Size());
89 assert(mIMap.size() == mOMap.size());
90 return result;
91}
92
94{
95 assert(list.Size() == 1);
96 mIMap.push_back(nullptr);
97 auto result = *list.begin();
98 mOMap.push_back(result);
99 mOutputTracks->Append(std::move(list));
100 // Invariant is maintained
101 assert(mIMap.size() == mOutputTracks->Size());
102 assert(mIMap.size() == mOMap.size());
103 return result;
104}
105
107{
108 const auto it = std::find(mOMap.begin(), mOMap.end(), &outTrack);
109 if (it == mOMap.end())
110 return nullptr;
111 const auto index = it - mOMap.begin();
112 return mIMap[index];
113}
114
115// Replace tracks with successfully processed mOutputTracks copies.
116// Else clear and delete mOutputTracks copies.
118{
119 if (!mOutputTracks) {
120 // Already committed, violating precondition. Maybe wrong intent...
121 assert(false);
122 // ... but harmless
123 return;
124 }
125
126 size_t cnt = mOMap.size();
127 size_t i = 0;
128
129 while (!mOutputTracks->empty()) {
130 const auto pOutputTrack = *mOutputTracks->begin();
131
132 // If tracks were removed from mOutputTracks, then there will be
133 // tracks in the map that must be removed from mTracks.
134 while (i < cnt && mOMap[i] != pOutputTrack) {
135 const auto t = mIMap[i];
136 // Class invariant justifies the assertion
137 assert(t && t->IsLeader());
138 ++i;
139 mTracks.Remove(*t);
140 }
141
142 // The output track, still in the list, must also have been placed in
143 // the map
144 assert(i < cnt);
145
146 // Find the input track it corresponds to
147 if (!mIMap[i])
148 // This track was an addition to output tracks; add it to mTracks
149 mTracks.AppendOne(std::move(*mOutputTracks));
150 else if (
152 // Replace mTracks entry with the new track
153 mTracks.ReplaceOne(*mIMap[i], std::move(*mOutputTracks));
154 else
155 // This output track was just a placeholder for pre-processing. Discard
156 // it.
157 mOutputTracks->Remove(*pOutputTrack);
158 ++i;
159 }
160
161 // If tracks were removed from mOutputTracks, then there may be tracks
162 // left at the end of the map that must be removed from mTracks.
163 while (i < cnt) {
164 const auto t = mIMap[i];
165 // Class invariant justifies the assertion
166 assert(t && t->IsLeader());
167 ++i;
168 mTracks.Remove(*t);
169 }
170
171 // Reset map
172 mIMap.clear();
173 mOMap.clear();
174
175 // Make sure we processed everything
176 assert(mOutputTracks->empty());
177
178 // The output list is no longer needed
179 mOutputTracks.reset();
180 ++nEffectsDone;
181}
Toolkit-neutral facade for basic user interface services.
EffectType
@ EffectTypeAnalyze
@ EffectTypeNone
const auto tracks
std::function< void(double)> ProgressReporter
Definition: Track.h:53
An AudacityException with no visible message.
const Track * GetMatchingInput(const Track &outTrack) const
Gets the matching input track for the given output track if it finds its match, else nullptr.
Track * AddToOutputTracks(const std::shared_ptr< Track > &t)
Use this to add an output track, not corresponding to an input.
const EffectType mEffectType
EffectOutputTracks(TrackList &tracks, EffectType effectType, std::optional< TimeInterval > effectTimeInterval, bool allSyncLockSelected=false, bool stretchSyncLocked=false)
std::vector< Track * > mOMap
std::vector< Track * > mIMap
std::shared_ptr< TrackList > mOutputTracks
void Commit()
Replace input tracks with temporaries only on commit.
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:112
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:122
bool GetSelected() const
Selectedness is always the same for all channels of a group.
Definition: Track.cpp:70
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:975
static TrackListHolder Create(AudacityProject *pOwner)
Definition: Track.cpp:365
void AppendOne(TrackList &&list)
Definition: Track.cpp:1470
void Remove(Track &track)
Remove a channel group, given the leader.
Definition: Track.cpp:745
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1079
TrackListHolder ReplaceOne(Track &t, TrackList &&with)
Definition: Track.cpp:637
AudacityProject * GetOwner()
Definition: Track.h:1014
A Track that contains audio waveform data.
Definition: WaveTrack.h:222
void SplitProgress(ItType first, ItType last, FnType action, ProgressReporter parent)
Helper for the update of a task's progress bar when this task is made of a range's subtasks.
Definition: BasicUI.h:329
WAVE_TRACK_API void WithStretchRenderingProgress(std::function< void(const ProgressReporter &)> action, TranslatableString title=defaultStretchRenderingTitle, TranslatableString message=XO("Rendering Time-Stretched Audio"))
WAVE_TRACK_API bool HasStretch(const WaveTrack &track, double t0, double t1)