Audacity 3.2.0
FindClippingBase.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 FindClipping.cpp
6
7 Leland Lucius
8
9*******************************************************************//*******************************************************************/
15#include "FindClippingBase.h"
16#include "AnalysisTracks.h"
17#include "BasicUI.h"
18#include "EffectOutputTracks.h"
19#include "LabelTrack.h"
20#include "WaveTrack.h"
21#include <cmath>
22
24{
26 return parameters;
27}
28
30
32{
33 Parameters().Reset(*this);
34}
35
37{
38}
39
40// ComponentInterface implementation
41
43{
44 return Symbol;
45}
46
48{
49 return XO("Creates labels where clipping is detected");
50}
51
53{
54 return L"Find_Clipping";
55}
56
57// EffectDefinitionInterface implementation
58
60{
61 return EffectTypeAnalyze;
62}
63
64// Effect implementation
65
67{
68 std::shared_ptr<AddedAnalysisTrack> addedTrack;
69 std::optional<ModifiedAnalysisTrack> modifiedTrack;
70 const wxString name { _("Clipping") };
71
72 auto clt = *inputTracks()->Any<const LabelTrack>().find_if(
73 [&](const Track* track) { return track->GetName() == name; });
74
75 LabelTrack* lt {};
76 if (!clt)
77 addedTrack = (AddAnalysisTrack(*this, name)), lt = addedTrack->get();
78 else
79 modifiedTrack.emplace(ModifyAnalysisTrack(*this, *clt, name)),
80 lt = modifiedTrack->get();
81
82 int count = 0;
83
84 // JC: Only process selected tracks.
85 // PRL: Compute the strech into temporary tracks. Don't commit the stretch.
86 EffectOutputTracks temp { *mTracks, GetType(), { { mT0, mT1 } } };
87 for (auto t : temp.Get().Selected<const WaveTrack>())
88 {
89 double trackStart = t->GetStartTime();
90 double trackEnd = t->GetEndTime();
91 double t0 = std::max(trackStart, mT0);
92 double t1 = std::min(trackEnd, mT1);
93 if (t1 > t0)
94 {
95 auto start = t->TimeToLongSamples(t0);
96 auto end = t->TimeToLongSamples(t1);
97 auto len = end - start;
98
99 for (const auto pChannel : t->Channels())
100 if (!ProcessOne(*lt, count++, *pChannel, start, len))
101 return false;
102 }
103 }
104
105 // No cancellation, so commit the addition of the track.
106 if (addedTrack)
107 addedTrack->Commit();
108 if (modifiedTrack)
109 modifiedTrack->Commit();
110 return true;
111}
112
114 LabelTrack& lt, int count, const WaveChannel& wt, sampleCount start,
115 sampleCount len)
116{
117 bool bGoodResult = true;
118 size_t blockSize = (mStart * 1000);
119
120 if (len < mStart)
121 return true;
122
123 Floats buffer;
124 try
125 {
126 // mStart should be positive.
127 // if we are throwing bad_alloc and mStart is negative, find out why.
128 if (mStart < 0 || (int)blockSize < mStart)
129 // overflow
130 throw std::bad_alloc {};
131 buffer.reinit(blockSize);
132 }
133 catch (const std::bad_alloc&)
134 {
135 BasicUI::ShowMessageBox(XO("Requested value exceeds memory capacity."));
136 return false;
137 }
138
139 float* ptr = buffer.get();
140
141 decltype(len) s = 0, startrun = 0, stoprun = 0, samps = 0;
142 decltype(blockSize) block = 0;
143 double startTime = -1.0;
144
145 while (s < len)
146 {
147 if (block == 0)
148 {
149 if (TrackProgress(count, s.as_double() / len.as_double()))
150 {
151 bGoodResult = false;
152 break;
153 }
154 block = limitSampleBufferSize(blockSize, len - s);
155 wt.GetFloats(buffer.get(), start + s, block);
156 ptr = buffer.get();
157 }
158
159 float v = fabs(*ptr++);
160 if (v >= MAX_AUDIO)
161 {
162 if (startrun == 0)
163 {
164 startTime = wt.LongSamplesToTime(start + s);
165 samps = 0;
166 }
167 else
168 stoprun = 0;
169 startrun++;
170 samps++;
171 }
172 else
173 {
174 if (startrun >= mStart)
175 {
176 stoprun++;
177 samps++;
178 if (stoprun >= mStop)
179 {
180 lt.AddLabel(
182 startTime, wt.LongSamplesToTime(start + s - mStop)),
189 XC("%lld of %lld", "find clipping")
190 .Format(
191 startrun.as_long_long(), (samps - mStop).as_long_long())
192 .Translation());
193 startrun = 0;
194 stoprun = 0;
195 samps = 0;
196 }
197 }
198 else
199 startrun = 0;
200 }
201 s++;
202 block--;
203 }
204 return bGoodResult;
205}
std::shared_ptr< AddedAnalysisTrack > AddAnalysisTrack(Effect &effect, const wxString &name)
ModifiedAnalysisTrack ModifyAnalysisTrack(Effect &effect, const LabelTrack &origTrack, const wxString &name)
Toolkit-neutral facade for basic user interface services.
int min(int a, int b)
EffectType
@ EffectTypeAnalyze
XO("Cut/Copy/Paste")
#define XC(s, c)
Definition: Internat.h:37
#define _(s)
Definition: Internat.h:73
#define MAX_AUDIO
Definition: MemoryX.h:341
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
wxString name
Definition: TagsEditor.cpp:166
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:59
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
double mT1
Definition: EffectBase.h:123
const TrackList * inputTracks() const
Definition: EffectBase.h:102
std::shared_ptr< TrackList > mTracks
Definition: EffectBase.h:116
double mT0
Definition: EffectBase.h:122
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:343
Performs effect computation.
Use this object to copy the input tracks to tentative outputTracks.
Interface for manipulations of an Effect's settings.
virtual void Reset(Effect &effect) const =0
virtual ~FindClippingBase()
const EffectParameterMethods & Parameters() const override
bool Process(EffectInstance &instance, EffectSettings &settings) override
EffectType GetType() const override
Type determines how it behaves.
TranslatableString GetDescription() const override
ComponentInterfaceSymbol GetSymbol() const override
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
bool ProcessOne(LabelTrack &lt, int count, const WaveChannel &wt, sampleCount start, sampleCount len)
static const ComponentInterfaceSymbol Symbol
Abstract base class used in importing a file.
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:98
int AddLabel(const SelectedRegion &region, const wxString &title)
Defines a selected portion of a project.
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
const wxString & GetName() const
Name is always the same for all channels of a group.
Definition: Track.cpp:64
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:950
Holds a msgid for the translation catalog; may also bind format arguments.
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
"narrow" overload fetches from the unique channel
Definition: WaveTrack.h:129
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
double LongSamplesToTime(sampleCount pos) const
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
double as_double() const
Definition: SampleCount.h:46
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
Definition: BasicUI.h:287
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
Externalized state of a plug-in.