Audacity 3.2.0
FindClipping.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*******************************************************************//****************************************************************//*******************************************************************/
20#include "FindClipping.h"
21#include "AnalysisTracks.h"
22#include "EffectEditor.h"
23#include "LoadEffects.h"
24
25#include <math.h>
26
27
28#include "ShuttleGui.h"
29#include "../widgets/valnum.h"
30#include "AudacityMessageBox.h"
31
32#include "../LabelTrack.h"
33#include "WaveTrack.h"
34
36{
38 Start, Stop
39 > parameters;
40 return parameters;
41}
42
44{ XO("Find Clipping") };
45
47
49{
50 Parameters().Reset(*this);
51}
52
54{
55}
56
57// ComponentInterface implementation
58
60{
61 return Symbol;
62}
63
65{
66 return XO("Creates labels where clipping is detected");
67}
68
70{
71 return L"Find_Clipping";
72}
73
74// EffectDefinitionInterface implementation
75
77{
78 return EffectTypeAnalyze;
79}
80
81// Effect implementation
82
84{
85 std::shared_ptr<AddedAnalysisTrack> addedTrack;
86 std::optional<ModifiedAnalysisTrack> modifiedTrack;
87 const wxString name{ _("Clipping") };
88
89 auto clt = *inputTracks()->Any< const LabelTrack >().find_if(
90 [&]( const Track *track ){ return track->GetName() == name; } );
91
92 LabelTrack *lt{};
93 if (!clt)
94 addedTrack = (AddAnalysisTrack(*this, name)), lt = addedTrack->get();
95 else
96 modifiedTrack.emplace(ModifyAnalysisTrack(*this, clt, name)),
97 lt = modifiedTrack->get();
98
99 int count = 0;
100
101 // JC: Only process selected tracks.
102 for (auto t : inputTracks()->Selected< const WaveTrack >()) {
103 double trackStart = t->GetStartTime();
104 double trackEnd = t->GetEndTime();
105 double t0 = mT0 < trackStart ? trackStart : mT0;
106 double t1 = mT1 > trackEnd ? trackEnd : mT1;
107
108 if (t1 > t0) {
109 auto start = t->TimeToLongSamples(t0);
110 auto end = t->TimeToLongSamples(t1);
111 auto len = end - start;
112
113 if (!ProcessOne(lt, count, t, start, len)) {
114 return false;
115 }
116 }
117
118 count++;
119 }
120
121 // No cancellation, so commit the addition of the track.
122 if (addedTrack)
123 addedTrack->Commit();
124 if (modifiedTrack)
125 modifiedTrack->Commit();
126 return true;
127}
128
130 int count,
131 const WaveTrack * wt,
132 sampleCount start,
133 sampleCount len)
134{
135 bool bGoodResult = true;
136 size_t blockSize = (mStart * 1000);
137
138 if (len < mStart) {
139 return true;
140 }
141
142 Floats buffer;
143 try {
144 // mStart should be positive.
145 // if we are throwing bad_alloc and mStart is negative, find out why.
146 if (mStart < 0 || (int)blockSize < mStart)
147 // overflow
148 throw std::bad_alloc{};
149 buffer.reinit(blockSize);
150 }
151 catch( const std::bad_alloc & ) {
153 XO("Requested value exceeds memory capacity."));
154 return false;
155 }
156
157 float *ptr = buffer.get();
158
159 decltype(len) s = 0, startrun = 0, stoprun = 0, samps = 0;
160 decltype(blockSize) block = 0;
161 double startTime = -1.0;
162
163 while (s < len) {
164 if (block == 0) {
165 if (TrackProgress(count,
166 s.as_double() /
167 len.as_double() )) {
168 bGoodResult = false;
169 break;
170 }
171
172 block = limitSampleBufferSize( blockSize, len - s );
173
174 wt->GetFloats(buffer.get(), start + s, block);
175 ptr = buffer.get();
176 }
177
178 float v = fabs(*ptr++);
179 if (v >= MAX_AUDIO) {
180 if (startrun == 0) {
181 startTime = wt->LongSamplesToTime(start + s);
182 samps = 0;
183 }
184 else {
185 stoprun = 0;
186 }
187 startrun++;
188 samps++;
189 }
190 else {
191 if (startrun >= mStart) {
192 stoprun++;
193 samps++;
194
195 if (stoprun >= mStop) {
196 lt->AddLabel(SelectedRegion(startTime,
197 wt->LongSamplesToTime(start + s - mStop)),
198 wxString::Format(wxT("%lld of %lld"), startrun.as_long_long(), (samps - mStop).as_long_long()));
199 startrun = 0;
200 stoprun = 0;
201 samps = 0;
202 }
203 }
204 else {
205 startrun = 0;
206 }
207 }
208
209 s++;
210 block--;
211 }
212
213 return bGoodResult;
214}
215
216std::unique_ptr<EffectEditor> EffectFindClipping::PopulateOrExchange(
218 const EffectOutputs *)
219{
220 mUIParent = S.GetParent();
221 DoPopulateOrExchange(S, access);
222 return nullptr;
223}
224
227{
228 mpAccess = access.shared_from_this();
229 S.StartMultiColumn(2, wxALIGN_CENTER);
230 {
231 S
232 .Validator<IntegerValidator<int>>(
233 &mStart, NumValidatorStyle::DEFAULT, Start.min)
234 .TieTextBox(XXO("&Start threshold (samples):"), mStart, 10);
235
236 S
237 .Validator<IntegerValidator<int>>(
238 &mStop, NumValidatorStyle::DEFAULT, Stop.min)
239 .TieTextBox(XXO("St&op threshold (samples):"), mStop, 10);
240 }
241 S.EndMultiColumn();
242}
243
245{
247 // To do: eliminate this and just use validators for controls
249
250 return true;
251}
252
254{
255 if (!mUIParent->Validate())
256 {
257 return false;
258 }
259
261 // To do: eliminate this and just use validators for controls
263
264 return true;
265}
wxT("CloseDown"))
std::shared_ptr< AddedAnalysisTrack > AddAnalysisTrack(Effect &effect, const wxString &name)
ModifiedAnalysisTrack ModifyAnalysisTrack(Effect &effect, const LabelTrack *pOrigTrack, const wxString &name)
const TranslatableString name
Definition: Distortion.cpp:76
EffectType
@ EffectTypeAnalyze
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define _(s)
Definition: Internat.h:73
#define MAX_AUDIO
Definition: MemoryX.h:564
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
@ eIsSettingToDialog
Definition: ShuttleGui.h:39
@ eIsGettingFromDialog
Definition: ShuttleGui.h:38
#define S(N)
Definition: ToChars.cpp:64
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
double mT1
Definition: EffectBase.h:119
const TrackList * inputTracks() const
Definition: EffectBase.h:94
double mT0
Definition: EffectBase.h:118
static constexpr EffectParameter Start
Definition: FindClipping.h:69
static const ComponentInterfaceSymbol Symbol
Definition: FindClipping.h:28
int mStop
Using int rather than sampleCount because values are only ever small numbers.
Definition: FindClipping.h:63
bool TransferDataToWindow(const EffectSettings &settings) override
bool ProcessOne(LabelTrack *lt, int count, const WaveTrack *wt, sampleCount start, sampleCount len)
void DoPopulateOrExchange(ShuttleGui &S, EffectSettingsAccess &access)
EffectSettingsAccessPtr mpAccess
Definition: FindClipping.h:65
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
wxWeakRef< wxWindow > mUIParent
Definition: FindClipping.h:60
bool Process(EffectInstance &instance, EffectSettings &settings) override
std::unique_ptr< EffectEditor > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
static constexpr EffectParameter Stop
Definition: FindClipping.h:71
bool TransferDataFromWindow(EffectSettings &settings) override
const EffectParameterMethods & Parameters() const override
EffectType GetType() const override
Type determines how it behaves.
int mStart
Using int rather than sampleCount because values are only ever small numbers.
Definition: FindClipping.h:62
TranslatableString GetDescription() const override
virtual ~EffectFindClipping()
ComponentInterfaceSymbol GetSymbol() const override
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:350
Performs effect computation.
Hold values to send to effect output meters.
Interface for manipulations of an Effect's settings.
virtual void Reset(Effect &effect) const =0
static int DoMessageBox(const EffectPlugin &plugin, const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={})
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:87
double GetStartTime() const override
Definition: LabelTrack.cpp:338
int AddLabel(const SelectedRegion &region, const wxString &title)
Definition: LabelTrack.cpp:944
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
Retrieve samples from a track in floating-point format, regardless of the storage format.
Definition: SampleTrack.h:83
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
Definition: SampleTrack.cpp:59
Defines a selected portion of a project.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:625
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:161
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:1302
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1319
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:51
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
double as_double() const
Definition: SampleCount.h:46
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
BuiltinEffectsModule::Registration< EffectFindClipping > reg
const Type min
Minimum value.
Externalized state of a plug-in.