Audacity 3.2.0
StereoToMono.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 StereoToMono.cpp
6
7 Lynn Allan
8
9*******************************************************************//*******************************************************************/
15
16
17#include "StereoToMono.h"
18#include "EffectOutputTracks.h"
19#include "LoadEffects.h"
20
21#include "Mix.h"
22#include "MixAndRender.h"
23#include "Project.h"
24#include "RealtimeEffectList.h"
25#include "WaveTrack.h"
26#include "ProgressDialog.h"
27
29{ XO("Stereo To Mono") };
30
32
34{
35}
36
38{
39}
40
41// ComponentInterface implementation
42
44{
45 return Symbol;
46}
47
49{
50 return XO("Converts stereo tracks to mono");
51}
52
53// EffectDefinitionInterface implementation
54
56{
57 // Really EffectTypeProcess, but this prevents it from showing in the Effect Menu
58 return EffectTypeHidden;
59}
60
62{
63 return false;
64}
65
67{
68 return 2;
69}
70
72{
73 return 1;
74}
75
76// Effect implementation
77
79{
80 // Do not use mWaveTracks here. We will possibly DELETE tracks,
81 // so we must use the "real" tracklist.
82 EffectOutputTracks outputs {
83 *mTracks,
84 GetType(),
85 // This effect ignores mT0 and mT1 but always mixes the entire tracks.
86 { { mTracks->GetStartTime(), mTracks->GetEndTime() } }
87 };
88 bool bGoodResult = true;
89
90 // Determine the total time (in samples) used by all of the target tracks
91 // only for progress dialog
92 sampleCount totalTime = 0;
93
94 auto trackRange = outputs.Get().Selected<WaveTrack>();
95 for (const auto left : trackRange) {
96 if (left->Channels().size() > 1) {
97 auto start = left->TimeToLongSamples(left->GetStartTime());
98 auto end = left->TimeToLongSamples(left->GetEndTime());
99 totalTime += (end - start);
100 }
101 }
102
103 // Process each stereo track
104 sampleCount curTime = 0;
105
106 mProgress->SetMessage(XO("Mixing down to mono"));
107
108 for (const auto track : trackRange) {
109 if (track->Channels().size() > 1) {
110 if (!ProcessOne(outputs.Get(), curTime, totalTime, *track))
111 break;
112 }
113 }
114
115 if (bGoodResult)
116 outputs.Commit();
117
118 return bGoodResult;
119}
120
122 sampleCount & curTime, sampleCount totalTime, WaveTrack &track)
123{
124 auto idealBlockLen = track.GetMaxBlockSize() * 2;
125 bool bResult = true;
126 sampleCount processed = 0;
127
128 const auto start = track.GetStartTime();
129 const auto end = track.GetEndTime();
130
132 tracks.emplace_back(
133 track.SharedPointer<const SampleTrack>(), GetEffectStages(track));
134
135 Mixer mixer(move(tracks),
136 true, // Throw to abort mix-and-render if read fails:
138 start,
139 end,
140 1,
141 idealBlockLen,
142 false, // Not interleaved
143 track.GetRate(),
145
146 // Always make mono output; don't use EmptyCopy
147 auto outTrack = track.EmptyCopy(1);
148 auto tempList = TrackList::Temporary(nullptr, outTrack);
149 outTrack->ConvertToSampleFormat(floatSample);
150
151 double denominator = track.GetChannelGain(0) + track.GetChannelGain(1);
152 while (auto blockLen = mixer.Process()) {
153 auto buffer = mixer.GetBuffer();
154 for (auto i = 0; i < blockLen; i++)
155 ((float *)buffer)[i] /= denominator;
156
157 // If mixing channels that both had only 16 bit effective format
158 // (for example), and no gains or envelopes, still there should be
159 // dithering because of the averaging above, which may introduce samples
160 // lying between the quantization levels. So use widestSampleFormat.
161 outTrack->Append(0,
162 buffer, floatSample, blockLen, 1, widestSampleFormat);
163
164 curTime += blockLen;
165 if (TotalProgress(curTime.as_double() / totalTime.as_double()))
166 return false;
167 }
168 outTrack->Flush();
169
170 track.Clear(start, end);
171 track.MakeMono();
172 track.Paste(start, *outTrack);
174
175 return bResult;
176}
177
179{
180 return true;
181}
EffectType
@ EffectTypeHidden
XO("Cut/Copy/Paste")
std::vector< MixerOptions::StageSpecification > GetEffectStages(const WaveTrack &track)
const auto tracks
virtual void SetMessage(const TranslatableString &message)=0
Change an existing dialog's message.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
const TrackList * inputTracks() const
Definition: EffectBase.h:91
BasicUI::ProgressDialog * mProgress
Definition: EffectBase.h:109
std::shared_ptr< TrackList > mTracks
Definition: EffectBase.h:107
bool TotalProgress(double frac, const TranslatableString &={}) const
Definition: Effect.cpp:335
Performs effect computation.
Use this object to copy the input tracks to tentative outputTracks.
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
bool IsInteractive() const override
Whether the effect needs a dialog for entry of settings.
unsigned GetAudioInCount() const override
How many input buffers to allocate at once.
ComponentInterfaceSymbol GetSymbol() const override
static const ComponentInterfaceSymbol Symbol
Definition: StereoToMono.h:19
bool Process(EffectInstance &instance, EffectSettings &settings) override
TranslatableString GetDescription() const override
bool ProcessOne(TrackList &outputs, sampleCount &curTime, sampleCount totalTime, WaveTrack &track)
bool IsHiddenFromMenus() const override
Default is false.
EffectType GetType() const override
Type determines how it behaves.
virtual ~EffectStereoToMono()
Functions for doing the mixdown of the tracks.
Definition: Mix.h:27
std::vector< Input > Inputs
Definition: Mix.h:45
static RealtimeEffectList & Get(AudacityProject &project)
void Clear()
Use only in the main thread. Sends Remove messages.
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:146
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:850
AudacityProject * GetOwner()
Definition: Track.h:887
static TrackListHolder Temporary(AudacityProject *pProject, const Track::Holder &pTrack={})
Definition: Track.cpp:858
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
void MakeMono()
Simply discard any right channel.
Definition: WaveTrack.cpp:1016
double GetStartTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2576
void Clear(double t0, double t1) override
Definition: WaveTrack.cpp:1138
void Paste(double t0, const Track &src) override
Definition: WaveTrack.cpp:1965
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2586
double GetRate() const override
Definition: WaveTrack.cpp:798
float GetChannelGain(int channel) const override
Takes gain and pan into account.
Definition: WaveTrack.cpp:865
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:2258
Holder EmptyCopy(size_t nChannels, const SampleBlockFactoryPtr &pFactory={}) const
Definition: WaveTrack.cpp:989
sampleCount TimeToLongSamples(double t0) const
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
double as_double() const
Definition: SampleCount.h:46
BuiltinEffectsModule::Registration< EffectStereoToMono > reg
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
Externalized state of a plug-in.
Immutable structure is an argument to Mixer's constructor.
Definition: MixerOptions.h:56