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**********************************************************************/
10#include "StereoToMono.h"
11#include "BasicUI.h"
12#include "EffectOutputTracks.h"
13#include "Mix.h"
14#include "MixAndRender.h"
15#include "Project.h"
16#include "RealtimeEffectList.h"
17#include "WaveTrack.h"
18
19const ComponentInterfaceSymbol StereoToMono::Symbol { XO("Stereo To Mono") };
20
22{
23 return Symbol;
24}
25
27{
28 return XO("Converts stereo tracks to mono");
29}
30
31// EffectDefinitionInterface implementation
32
34{
35 // Really EffectTypeProcess, but this prevents it from showing in the Effect
36 // Menu
37 return EffectTypeHidden;
38}
39
41{
42 return false;
43}
44
46{
47 return 2;
48}
49
51{
52 return 1;
53}
54
55// Effect implementation
56
58{
59 // Do not use mWaveTracks here. We will possibly DELETE tracks,
60 // so we must use the "real" tracklist.
61 EffectOutputTracks outputs {
62 *mTracks,
63 GetType(),
64 // This effect ignores mT0 and mT1 but always mixes the entire tracks.
65 { { mTracks->GetStartTime(), mTracks->GetEndTime() } }
66 };
67 bool bGoodResult = true;
68
69 // Determine the total time (in samples) used by all of the target tracks
70 // only for progress dialog
71 sampleCount totalTime = 0;
72
73 auto trackRange = outputs.Get().Selected<WaveTrack>();
74 for (const auto left : trackRange)
75 {
76 if (left->Channels().size() > 1)
77 {
78 auto start = left->TimeToLongSamples(left->GetStartTime());
79 auto end = left->TimeToLongSamples(left->GetEndTime());
80 totalTime += (end - start);
81 }
82 }
83
84 // Process each stereo track
85 sampleCount curTime = 0;
86
87 mProgress->SetMessage(XO("Mixing down to mono"));
88
89 for (const auto track : trackRange)
90 {
91 if (track->Channels().size() > 1)
92 {
93 if (!ProcessOne(outputs.Get(), curTime, totalTime, *track))
94 break;
95 }
96 }
97
98 if (bGoodResult)
99 outputs.Commit();
100
101 return bGoodResult;
102}
103
105 TrackList& outputs, sampleCount& curTime, sampleCount totalTime,
106 WaveTrack& track)
107{
108 auto idealBlockLen = track.GetMaxBlockSize() * 2;
109 bool bResult = true;
110 sampleCount processed = 0;
111
112 const auto start = track.GetStartTime();
113 const auto end = track.GetEndTime();
114
116 tracks.emplace_back(
117 track.SharedPointer<const SampleTrack>(), GetEffectStages(track));
118
119 Mixer mixer(
120 move(tracks), std::nullopt,
121 true, // Throw to abort mix-and-render if read fails:
122 Mixer::WarpOptions { inputTracks()->GetOwner() }, start, end, 1,
123 idealBlockLen,
124 false, // Not interleaved
125 track.GetRate(), floatSample);
126
127 // Always make mono output; don't use EmptyCopy
128 auto outTrack = track.EmptyCopy(1);
129 auto tempList = TrackList::Temporary(nullptr, outTrack);
130 outTrack->ConvertToSampleFormat(floatSample);
131
132 double denominator = track.GetChannelVolume(0) + track.GetChannelVolume(1);
133 while (auto blockLen = mixer.Process())
134 {
135 auto buffer = mixer.GetBuffer();
136 for (auto i = 0; i < blockLen; i++)
137 ((float*)buffer)[i] /= denominator;
138
139 // If mixing channels that both had only 16 bit effective format
140 // (for example), and no gains or envelopes, still there should be
141 // dithering because of the averaging above, which may introduce samples
142 // lying between the quantization levels. So use widestSampleFormat.
143 outTrack->Append(0, buffer, floatSample, blockLen, 1, widestSampleFormat);
144
145 curTime += blockLen;
146 if (TotalProgress(curTime.as_double() / totalTime.as_double()))
147 return false;
148 }
149 outTrack->Flush();
150
151 track.Clear(start, end);
152 track.MakeMono();
153 track.Paste(start, *outTrack);
155
156 return bResult;
157}
158
160{
161 return true;
162}
Toolkit-neutral facade for basic user interface services.
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:102
BasicUI::ProgressDialog * mProgress
Definition: EffectBase.h:118
std::shared_ptr< TrackList > mTracks
Definition: EffectBase.h:116
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.
Functions for doing the mixdown of the tracks.
Definition: Mix.h:31
std::vector< Input > Inputs
Definition: Mix.h:49
static RealtimeEffectList & Get(AudacityProject &project)
void Clear()
Use only in the main thread. Sends Remove messages.
unsigned GetAudioInCount() const override
How many input buffers to allocate at once.
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.
ComponentInterfaceSymbol GetSymbol() const override
TranslatableString GetDescription() const override
static const ComponentInterfaceSymbol Symbol
Definition: StereoToMono.h:17
EffectType GetType() const override
Type determines how it behaves.
bool IsHiddenFromMenus() const override
Default is false.
bool Process(EffectInstance &instance, EffectSettings &settings) override
bool ProcessOne(TrackList &outputs, sampleCount &curTime, sampleCount totalTime, WaveTrack &track)
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:1039
double GetStartTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2603
float GetChannelVolume(int channel) const override
Takes volume and pan into account.
Definition: WaveTrack.cpp:888
void Clear(double t0, double t1) override
Definition: WaveTrack.cpp:1161
void Paste(double t0, const Track &src) override
Definition: WaveTrack.cpp:1986
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2613
double GetRate() const override
Definition: WaveTrack.cpp:821
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:2279
Holder EmptyCopy(size_t nChannels, const SampleBlockFactoryPtr &pFactory={}) const
Definition: WaveTrack.cpp:1012
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
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