Audacity  3.2.0
Typedefs | Functions
MixAndRender.cpp File Reference
#include "MixAndRender.h"
#include "BasicUI.h"
#include "Mix.h"
#include "WaveTrack.h"
Include dependency graph for MixAndRender.cpp:

Go to the source code of this file.

Typedefs

using WaveTrackConstArray = std::vector< std::shared_ptr< const WaveTrack > >
 

Functions

void MixAndRender (TrackList *tracks, WaveTrackFactory *trackFactory, double rate, sampleFormat format, double startTime, double endTime, WaveTrack::Holder &uLeft, WaveTrack::Holder &uRight)
 Mixes together all input tracks, applying any envelopes, amplitude gain, panning, and real-time effects in the process. More...
 

Typedef Documentation

◆ WaveTrackConstArray

using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >

Definition at line 17 of file MixAndRender.cpp.

Function Documentation

◆ MixAndRender()

void MixAndRender ( TrackList tracks,
WaveTrackFactory factory,
double  rate,
sampleFormat  format,
double  startTime,
double  endTime,
std::shared_ptr< WaveTrack > &  uLeft,
std::shared_ptr< WaveTrack > &  uRight 
)

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 that are selected, 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.

Definition at line 20 of file MixAndRender.cpp.

24 {
25  uLeft.reset(), uRight.reset();
26 
27  // This function was formerly known as "Quick Mix".
28  bool mono = false; /* flag if output can be mono without losing anything*/
29  bool oneinput = false; /* flag set to true if there is only one input track
30  (mono or stereo) */
31 
32  const auto trackRange = tracks->Selected< const WaveTrack >();
33  auto first = *trackRange.begin();
34  // this only iterates tracks which are relevant to this function, i.e.
35  // selected WaveTracks. The tracklist is (confusingly) the list of all
36  // tracks in the project
37 
38  int numWaves = 0; /* number of wave tracks in the selection */
39  int numMono = 0; /* number of mono, centre-panned wave tracks in selection*/
40  for(auto wt : trackRange) {
41  numWaves++;
42  float pan = wt->GetPan();
43  if (wt->GetChannel() == Track::MonoChannel && pan == 0)
44  numMono++;
45  }
46 
47  if (numMono == numWaves)
48  mono = true;
49 
50  /* the next loop will do two things at once:
51  * 1. build an array of all the wave tracks were are trying to process
52  * 2. determine when the set of WaveTracks starts and ends, in case we
53  * need to work out for ourselves when to start and stop rendering.
54  */
55 
56  double mixStartTime = 0.0; /* start time of first track to start */
57  bool gotstart = false; // flag indicates we have found a start time
58  double mixEndTime = 0.0; /* end time of last track to end */
59  double tstart, tend; // start and end times for one track.
60 
61  SampleTrackConstArray waveArray;
62 
63  for(auto wt : trackRange) {
64  waveArray.push_back( wt->SharedPointer< const SampleTrack >() );
65  tstart = wt->GetStartTime();
66  tend = wt->GetEndTime();
67  if (tend > mixEndTime)
68  mixEndTime = tend;
69  // try and get the start time. If the track is empty we will get 0,
70  // which is ambiguous because it could just mean the track starts at
71  // the beginning of the project, as well as empty track. The give-away
72  // is that an empty track also ends at zero.
73 
74  if (tstart != tend) {
75  // we don't get empty tracks here
76  if (!gotstart) {
77  // no previous start, use this one unconditionally
78  mixStartTime = tstart;
79  gotstart = true;
80  } else if (tstart < mixStartTime)
81  mixStartTime = tstart; // have a start, only make it smaller
82  } // end if start and end are different
83  }
84 
85  /* create the destination track (NEW track) */
86  if (numWaves == (int)TrackList::Channels(first).size())
87  oneinput = true;
88  // only one input track (either 1 mono or one linked stereo pair)
89 
90  auto mixLeft = trackFactory->NewWaveTrack(format, rate);
91  if (oneinput)
92  mixLeft->SetName(first->GetName()); /* set name of output track to be the same as the sole input track */
93  else
94  /* i18n-hint: noun, means a track, made by mixing other tracks */
95  mixLeft->SetName(_("Mix"));
96  mixLeft->SetOffset(mixStartTime);
97 
98  // TODO: more-than-two-channels
99  decltype(mixLeft) mixRight{};
100  if ( !mono ) {
101  mixRight = trackFactory->NewWaveTrack(format, rate);
102  if (oneinput) {
103  auto channels = TrackList::Channels(first);
104  if (channels.size() > 1)
105  mixRight->SetName((*channels.begin().advance(1))->GetName()); /* set name to match input track's right channel!*/
106  else
107  mixRight->SetName(first->GetName()); /* set name to that of sole input channel */
108  }
109  else
110  mixRight->SetName(_("Mix"));
111  mixRight->SetOffset(mixStartTime);
112  }
113 
114 
115  auto maxBlockLen = mixLeft->GetIdealBlockSize();
116 
117  // If the caller didn't specify a time range, use the whole range in which
118  // any input track had clips in it.
119  if (startTime == endTime) {
120  startTime = mixStartTime;
121  endTime = mixEndTime;
122  }
123 
124  Mixer mixer(waveArray,
125  // Throw to abort mix-and-render if read fails:
126  true,
127  Mixer::WarpOptions{*tracks},
128  startTime, endTime, mono ? 1 : 2, maxBlockLen, false,
129  rate, format);
130 
131  using namespace BasicUI;
132  auto updateResult = ProgressResult::Success;
133  {
134  auto pProgress = MakeProgress(XO("Mix and Render"),
135  XO("Mixing and rendering tracks"));
136 
137  while (updateResult == ProgressResult::Success) {
138  auto blockLen = mixer.Process(maxBlockLen);
139 
140  if (blockLen == 0)
141  break;
142 
143  if (mono) {
144  auto buffer = mixer.GetBuffer();
145  mixLeft->Append(buffer, format, blockLen);
146  }
147  else {
148  auto buffer = mixer.GetBuffer(0);
149  mixLeft->Append(buffer, format, blockLen);
150  buffer = mixer.GetBuffer(1);
151  mixRight->Append(buffer, format, blockLen);
152  }
153 
154  updateResult = pProgress->Poll(
155  mixer.MixGetCurrentTime() - startTime, endTime - startTime);
156  }
157  }
158 
159  mixLeft->Flush();
160  if (!mono)
161  mixRight->Flush();
162  if (updateResult == ProgressResult::Cancelled || updateResult == ProgressResult::Failed)
163  {
164  return;
165  }
166  else {
167  uLeft = mixLeft, uRight = mixRight;
168 #if 0
169  int elapsedMS = wxGetElapsedTime();
170  double elapsedTime = elapsedMS * 0.001;
171  double maxTracks = totalTime / (elapsedTime / numWaves);
172 
173  // Note: these shouldn't be translated - they're for debugging
174  // and profiling only.
175  wxPrintf(" Tracks: %d\n", numWaves);
176  wxPrintf(" Mix length: %f sec\n", totalTime);
177  wxPrintf("Elapsed time: %f sec\n", elapsedTime);
178  wxPrintf("Max number of tracks to mix in real time: %f\n", maxTracks);
179 #endif
180  }
181 }

References _, BasicUI::Cancelled, TrackList::Channels(), BasicUI::Failed, format, Mixer::GetBuffer(), Track::GetName(), WaveTrack::GetPan(), BasicUI::MakeProgress(), Mixer::MixGetCurrentTime(), Track::MonoChannel, WaveTrackFactory::NewWaveTrack(), Mixer::Process(), TrackList::Selected(), BasicUI::Success, and XO.

Referenced by anonymous_namespace{TrackMenus.cpp}::DoMixAndRender(), and Effect::Preview().

Here is the call graph for this function:
Here is the caller graph for this function:
BasicUI::MakeProgress
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:271
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:75
BasicUI::ProgressResult::Success
@ Success
SampleTrackConstArray
std::vector< std::shared_ptr< const SampleTrack > > SampleTrackConstArray
Definition: Mix.h:33
Track::GetName
wxString GetName() const
Definition: Track.h:423
SampleTrack
Definition: SampleTrack.h:21
Mixer::WarpOptions
Definition: Mix.h:63
TrackList::Channels
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1483
XO
#define XO(s)
Definition: Internat.h:31
BasicUI::ProgressResult::Failed
@ Failed
format
int format
Definition: ExportPCM.cpp:56
BasicUI::ProgressResult::Cancelled
@ Cancelled
BasicUI
Definition: Effect.h:47
Mixer::MixGetCurrentTime
double MixGetCurrentTime()
Definition: Mix.cpp:550
_
#define _(s)
Definition: Internat.h:75
Track::MonoChannel
@ MonoChannel
Definition: Track.h:263
Mixer::GetBuffer
constSamplePtr GetBuffer()
Retrieve the main buffer or the interleaved buffer.
Definition: Mix.cpp:540
WaveTrack::GetPan
float GetPan() const
Definition: WaveTrack.cpp:525
TrackList::Selected
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1396
Mixer
Functions for doing the mixdown of the tracks.
Definition: Mix.h:58
WaveTrackFactory::NewWaveTrack
std::shared_ptr< WaveTrack > NewWaveTrack(sampleFormat format=(sampleFormat) 0, double rate=0)
Definition: WaveTrack.cpp:126
Mixer::Process
size_t Process(size_t maxSamples)
Definition: Mix.cpp:454