Audacity 3.2.0
Typedefs | Functions
MixAndRender.h File Reference
#include "Mix.h"
#include "SampleFormat.h"
#include "Track.h"
#include <memory>
Include dependency graph for MixAndRender.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

using ChannelNames = const ChannelName *
 

Functions

EFFECTS_API TrackListHolder MixAndRender (const TrackIterRange< const WaveTrack > &trackRange, const Mixer::WarpOptions &warpOptions, const wxString &newTrackName, WaveTrackFactory *factory, double rate, sampleFormat format, double startTime, double endTime)
 Mixes together all input tracks, applying any envelopes, amplitude gain, panning, and real-time effects in the process. More...
 
EFFECTS_API std::vector< MixerOptions::StageSpecificationGetEffectStages (const WaveTrack &track)
 

Typedef Documentation

◆ ChannelNames

using ChannelNames = const ChannelName *

Definition at line 51 of file MixAndRender.h.

Function Documentation

◆ GetEffectStages()

EFFECTS_API std::vector< MixerOptions::StageSpecification > GetEffectStages ( const WaveTrack track)

Definition at line 173 of file MixAndRender.cpp.

174{
175 auto &effects = RealtimeEffectList::Get(track);
176 if (!effects.IsActive())
177 return {};
178 std::vector<MixerOptions::StageSpecification> result;
179 for (size_t i = 0, count = effects.GetStatesCount(); i < count; ++i) {
180 const auto pState = effects.GetStateAt(i);
181 if (!pState->IsEnabled())
182 continue;
183 const auto pEffect = pState->GetEffect();
184 if (!pEffect)
185 continue;
186 const auto &settings = pState->GetSettings();
187 if (!settings.has_value())
188 continue;
189 auto &stage = result.emplace_back(MixerOptions::StageSpecification{
190 [pEffect]{ return pEffect->MakeInstance(); },
191 settings });
192 }
193 return result;
194}
static Settings & settings()
Definition: TrackInfo.cpp:69
static RealtimeEffectList & Get(AudacityProject &project)

References RealtimeEffectList::Get(), and settings().

Referenced by ExportPluginHelpers::CreateMixer(), MixAndRender(), and EffectStereoToMono::ProcessOne().

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

◆ MixAndRender()

EFFECTS_API TrackListHolder MixAndRender ( const TrackIterRange< const WaveTrack > &  trackRange,
const Mixer::WarpOptions warpOptions,
const wxString &  newTrackName,
WaveTrackFactory factory,
double  rate,
sampleFormat  format,
double  startTime,
double  endTime 
)

Mixes together all input tracks, applying any envelopes, amplitude gain, panning, and real-time effects in the process.

Takes one or more tracks as input; of all the WaveTrack s, it mixes them together, applying any envelopes, amplitude gain, panning, and real-time effects in the process. The resulting pair of tracks (stereo) are "rendered" and have no effects, gain, panning, or envelopes. Other sorts of tracks are ignored. If the start and end times passed are the same this is taken as meaning no explicit time range to process, and the whole occupied length of the input tracks is processed. Channel group properties of the result are copied from the first input track.

Parameters
newTrackNameused only when there is more than one input track (one mono channel or a stereo pair); else the unique track's name is copied
Precondition
trackRange iterates over leaders only

Definition at line 22 of file MixAndRender.cpp.

28{
29 if (trackRange.empty())
30 return {};
31
32 // This function was formerly known as "Quick Mix".
33 bool mono = false; /* flag if output can be mono without losing anything*/
34 bool oneinput = false; /* flag set to true if there is only one input track
35 (mono or stereo) */
36
37 auto first = *trackRange.begin();
38 assert(first); // because the range is known to be nonempty
39 assert(first->IsLeader()); // precondition on trackRange
40
41 // this only iterates tracks which are relevant to this function, i.e.
42 // selected WaveTracks. The tracklist is (confusingly) the list of all
43 // tracks in the project
44
45 int numWaves = 0; /* number of wave tracks in the selection */
46 int numMono = 0; /* number of mono, centre-panned wave tracks in selection*/
47 for (auto wt : trackRange) {
48 numWaves += wt->NChannels();
49 if (IsMono(*wt) && wt->GetPan() == 0)
50 numMono++;
51 }
52
53 if (numMono == numWaves)
54 mono = true;
55
56 /* the next loop will do two things at once:
57 * 1. build an array of all the wave tracks were are trying to process
58 * 2. determine when the set of WaveTracks starts and ends, in case we
59 * need to work out for ourselves when to start and stop rendering.
60 */
61
62 double mixStartTime = 0.0; /* start time of first track to start */
63 bool gotstart = false; // flag indicates we have found a start time
64 double mixEndTime = 0.0; /* end time of last track to end */
65 double tstart, tend; // start and end times for one track.
66
67 Mixer::Inputs waveArray;
68
69 for (auto wt : trackRange) {
70 const auto stretchingSequence =
71 StretchingSequence::Create(*wt, wt->GetClipInterfaces());
72 waveArray.emplace_back(stretchingSequence, GetEffectStages(*wt));
73 tstart = wt->GetStartTime();
74 tend = wt->GetEndTime();
75 if (tend > mixEndTime)
76 mixEndTime = tend;
77 // try and get the start time. If the track is empty we will get 0,
78 // which is ambiguous because it could just mean the track starts at
79 // the beginning of the project, as well as empty track. The give-away
80 // is that an empty track also ends at zero.
81
82 if (tstart != tend) {
83 // we don't get empty tracks here
84 if (!gotstart) {
85 // no previous start, use this one unconditionally
86 mixStartTime = tstart;
87 gotstart = true;
88 } else if (tstart < mixStartTime)
89 mixStartTime = tstart; // have a start, only make it smaller
90 } // end if start and end are different
91 }
92
93 /* create the destination track (NEW track) */
94 if (numWaves == (int)TrackList::NChannels(*first))
95 oneinput = true;
96 // only one input track (either 1 mono or one linked stereo pair)
97
98 auto result = trackFactory->Create(mono ? 1 : 2, *first);
99 auto mix = static_cast<WaveTrack*>(*result->begin());
100 mix->SetPan(0);
101 mix->SetGain(1.0f);
102 mix->SetRate(rate);
103 mix->ConvertToSampleFormat(format);
104 if(!oneinput)
105 mix->SetName(newTrackName);
106 mix->MoveTo(mixStartTime);
107
108 auto maxBlockLen = mix->GetIdealBlockSize();
109
110 // If the caller didn't specify a time range, use the whole range in which
111 // any input track had clips in it.
112 if (startTime == endTime) {
113 startTime = mixStartTime;
114 endTime = mixEndTime;
115 }
116
117 Mixer mixer(move(waveArray),
118 // Throw to abort mix-and-render if read fails:
119 true, warpOptions,
120 startTime, endTime, mono ? 1 : 2, maxBlockLen, false,
121 rate, format);
122
123 using namespace BasicUI;
124 auto updateResult = ProgressResult::Success;
125 {
126 auto effectiveFormat = mixer.EffectiveFormat();
127 auto pProgress = MakeProgress(XO("Mix and Render"),
128 XO("Mixing and rendering tracks"));
129
130 while (updateResult == ProgressResult::Success) {
131 auto blockLen = mixer.Process();
132
133 if (blockLen == 0)
134 break;
135
136 for(auto channel : mix->Channels())
137 {
138 auto buffer = mixer.GetBuffer(channel->ReallyGetChannelIndex());
139 channel->AppendBuffer(buffer, format, blockLen, 1, effectiveFormat);
140 }
141
142 updateResult = pProgress->Poll(
143 mixer.MixGetCurrentTime() - startTime, endTime - startTime);
144 }
145 }
146 mix->Flush();
147 if (updateResult == ProgressResult::Cancelled ||
148 updateResult == ProgressResult::Failed)
149 return {};
150 else {
151#if 0
152 int elapsedMS = wxGetElapsedTime();
153 double elapsedTime = elapsedMS * 0.001;
154 double maxTracks = totalTime / (elapsedTime / numWaves);
155
156 // Note: these shouldn't be translated - they're for debugging
157 // and profiling only.
158 wxPrintf(" Tracks: %d\n", numWaves);
159 wxPrintf(" Mix length: %f sec\n", totalTime);
160 wxPrintf("Elapsed time: %f sec\n", elapsedTime);
161 wxPrintf("Max number of tracks to mix in real time: %f\n", maxTracks);
162#endif
164 }
165
166 return result;
167}
XO("Cut/Copy/Paste")
std::vector< MixerOptions::StageSpecification > GetEffectStages(const WaveTrack &track)
Functions for doing the mixdown of the tracks.
Definition: Mix.h:27
std::vector< Input > Inputs
Definition: Mix.h:45
void Clear()
Use only in the main thread. Sends Remove messages.
static std::shared_ptr< StretchingSequence > Create(const PlayableSequence &, const ClipHolders &clips)
size_t NChannels() const
Definition: Track.cpp:960
A Track that contains audio waveform data.
Definition: WaveTrack.h:227
void SetPan(float newPan)
Definition: WaveTrack.cpp:1183
bool IsMono(const Channel &channel)
Whether the channel is mono.
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
Definition: BasicUI.h:292
bool empty() const
Definition: IteratorX.h:58
Iterator begin() const
Definition: IteratorX.h:52

References IteratorRange< Iterator >::begin(), BasicUI::Cancelled, RealtimeEffectList::Clear(), WaveTrackFactory::Create(), StretchingSequence::Create(), Mixer::EffectiveFormat(), IteratorRange< Iterator >::empty(), anonymous_namespace{ExportPCM.cpp}::format, RealtimeEffectList::Get(), Mixer::GetBuffer(), GetEffectStages(), AudioGraph::IsMono(), BasicUI::MakeProgress(), Mixer::MixGetCurrentTime(), TrackList::NChannels(), Mixer::Process(), WaveTrack::SetPan(), BasicUI::Success, and XO().

Referenced by anonymous_namespace{TrackMenus.cpp}::DoMixAndRender(), EffectPreview(), and WaveTrackMenuTable::OnMergeStereo().

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