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
21
22
23#include "FindClipping.h"
24#include "LoadEffects.h"
25
26#include <math.h>
27
28
29#include "../ShuttleGui.h"
30#include "../widgets/valnum.h"
31#include "../widgets/AudacityMessageBox.h"
32
33#include "../LabelTrack.h"
34#include "../WaveTrack.h"
35
37{
39 Start, Stop
40 > parameters;
41 return parameters;
42}
43
45{ XO("Find Clipping") };
46
48
50{
51 Parameters().Reset(*this);
52}
53
55{
56}
57
58// ComponentInterface implementation
59
61{
62 return Symbol;
63}
64
66{
67 return XO("Creates labels where clipping is detected");
68}
69
71{
72 return L"Find_Clipping";
73}
74
75// EffectDefinitionInterface implementation
76
78{
79 return EffectTypeAnalyze;
80}
81
82// Effect implementation
83
85{
86 std::shared_ptr<AddedAnalysisTrack> addedTrack;
87 std::optional<ModifiedAnalysisTrack> modifiedTrack;
88 const wxString name{ _("Clipping") };
89
90 auto clt = *inputTracks()->Any< const LabelTrack >().find_if(
91 [&]( const Track *track ){ return track->GetName() == name; } );
92
93 LabelTrack *lt{};
94 if (!clt)
95 addedTrack = (AddAnalysisTrack(name)), lt = addedTrack->get();
96 else
97 modifiedTrack.emplace(ModifyAnalysisTrack(clt, name)),
98 lt = modifiedTrack->get();
99
100 int count = 0;
101
102 // JC: Only process selected tracks.
103 for (auto t : inputTracks()->Selected< const WaveTrack >()) {
104 double trackStart = t->GetStartTime();
105 double trackEnd = t->GetEndTime();
106 double t0 = mT0 < trackStart ? trackStart : mT0;
107 double t1 = mT1 > trackEnd ? trackEnd : mT1;
108
109 if (t1 > t0) {
110 auto start = t->TimeToLongSamples(t0);
111 auto end = t->TimeToLongSamples(t1);
112 auto len = end - start;
113
114 if (!ProcessOne(lt, count, t, start, len)) {
115 return false;
116 }
117 }
118
119 count++;
120 }
121
122 // No cancellation, so commit the addition of the track.
123 if (addedTrack)
124 addedTrack->Commit();
125 if (modifiedTrack)
126 modifiedTrack->Commit();
127 return true;
128}
129
131 int count,
132 const WaveTrack * wt,
133 sampleCount start,
134 sampleCount len)
135{
136 bool bGoodResult = true;
137 size_t blockSize = (mStart * 1000);
138
139 if (len < mStart) {
140 return true;
141 }
142
143 Floats buffer;
144 try {
145 // mStart should be positive.
146 // if we are throwing bad_alloc and mStart is negative, find out why.
147 if (mStart < 0 || (int)blockSize < mStart)
148 // overflow
149 throw std::bad_alloc{};
150 buffer.reinit(blockSize);
151 }
152 catch( const std::bad_alloc & ) {
153 Effect::MessageBox( 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<EffectUIValidator> 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"))
const TranslatableString name
Definition: Distortion.cpp:74
EffectType
@ EffectTypeAnalyze
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define _(s)
Definition: Internat.h:75
#define MAX_AUDIO
Definition: MemoryX.h:546
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
@ eIsSettingToDialog
Definition: ShuttleGui.h:41
@ eIsGettingFromDialog
Definition: ShuttleGui.h:40
#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:109
const TrackList * inputTracks() const
Definition: EffectBase.h:104
double mT0
Definition: EffectBase.h:108
static constexpr EffectParameter Start
Definition: FindClipping.h:68
static const ComponentInterfaceSymbol Symbol
Definition: FindClipping.h:27
int mStop
Using int rather than sampleCount because values are only ever small numbers.
Definition: FindClipping.h:62
bool TransferDataToWindow(const EffectSettings &settings) override
Update controls for the settings.
bool ProcessOne(LabelTrack *lt, int count, const WaveTrack *wt, sampleCount start, sampleCount len)
void DoPopulateOrExchange(ShuttleGui &S, EffectSettingsAccess &access)
EffectSettingsAccessPtr mpAccess
Definition: FindClipping.h:64
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
wxWeakRef< wxWindow > mUIParent
Definition: FindClipping.h:59
bool Process(EffectInstance &instance, EffectSettings &settings) override
static constexpr EffectParameter Stop
Definition: FindClipping.h:70
bool TransferDataFromWindow(EffectSettings &settings) override
Update the given settings from controls.
const EffectParameterMethods & Parameters() const override
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
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:61
TranslatableString GetDescription() const override
virtual ~EffectFindClipping()
ComponentInterfaceSymbol GetSymbol() const override
int MessageBox(const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={}) const
Definition: Effect.cpp:807
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:627
ModifiedAnalysisTrack ModifyAnalysisTrack(const LabelTrack *pOrigTrack, const wxString &name=wxString())
Definition: Effect.cpp:791
std::shared_ptr< AddedAnalysisTrack > AddAnalysisTrack(const wxString &name=wxString())
Definition: Effect.cpp:740
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
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:71
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
Definition: SampleTrack.cpp:47
Defines a selected portion of a project.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
wxString GetName() const
Definition: Track.h:466
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1437
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1454
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
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.
Definition: Shuttle.h:30
Externalized state of a plug-in.