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#include <wx/intl.h>
29
30#include "../ShuttleGui.h"
31#include "../widgets/valnum.h"
32#include "../widgets/AudacityMessageBox.h"
33
34#include "../LabelTrack.h"
35#include "../WaveTrack.h"
36
38{
40 Start, Stop
41 > parameters;
42 return parameters;
43}
44
46{ XO("Find Clipping") };
47
49
51{
52 Parameters().Reset(*this);
53}
54
56{
57}
58
59// ComponentInterface implementation
60
62{
63 return Symbol;
64}
65
67{
68 return XO("Creates labels where clipping is detected");
69}
70
72{
73 return L"Find_Clipping";
74}
75
76// EffectDefinitionInterface implementation
77
79{
80 return EffectTypeAnalyze;
81}
82
83// Effect implementation
84
86{
87 std::shared_ptr<AddedAnalysisTrack> addedTrack;
88 std::optional<ModifiedAnalysisTrack> modifiedTrack;
89 const wxString name{ _("Clipping") };
90
91 auto clt = *inputTracks()->Any< const LabelTrack >().find_if(
92 [&]( const Track *track ){ return track->GetName() == name; } );
93
94 LabelTrack *lt{};
95 if (!clt)
96 addedTrack = (AddAnalysisTrack(name)), lt = addedTrack->get();
97 else
98 modifiedTrack.emplace(ModifyAnalysisTrack(clt, name)),
99 lt = modifiedTrack->get();
100
101 int count = 0;
102
103 // JC: Only process selected tracks.
104 for (auto t : inputTracks()->Selected< const WaveTrack >()) {
105 double trackStart = t->GetStartTime();
106 double trackEnd = t->GetEndTime();
107 double t0 = mT0 < trackStart ? trackStart : mT0;
108 double t1 = mT1 > trackEnd ? trackEnd : mT1;
109
110 if (t1 > t0) {
111 auto start = t->TimeToLongSamples(t0);
112 auto end = t->TimeToLongSamples(t1);
113 auto len = end - start;
114
115 if (!ProcessOne(lt, count, t, start, len)) {
116 return false;
117 }
118 }
119
120 count++;
121 }
122
123 // No cancellation, so commit the addition of the track.
124 if (addedTrack)
125 addedTrack->Commit();
126 if (modifiedTrack)
127 modifiedTrack->Commit();
128 return true;
129}
130
132 int count,
133 const WaveTrack * wt,
134 sampleCount start,
135 sampleCount len)
136{
137 bool bGoodResult = true;
138 size_t blockSize = (mStart * 1000);
139
140 if (len < mStart) {
141 return true;
142 }
143
144 Floats buffer;
145 try {
146 // mStart should be positive.
147 // if we are throwing bad_alloc and mStart is negative, find out why.
148 if (mStart < 0 || (int)blockSize < mStart)
149 // overflow
150 throw std::bad_alloc{};
151 buffer.reinit(blockSize);
152 }
153 catch( const std::bad_alloc & ) {
154 Effect::MessageBox( XO("Requested value exceeds memory capacity.") );
155 return false;
156 }
157
158 float *ptr = buffer.get();
159
160 decltype(len) s = 0, startrun = 0, stoprun = 0, samps = 0;
161 decltype(blockSize) block = 0;
162 double startTime = -1.0;
163
164 while (s < len) {
165 if (block == 0) {
166 if (TrackProgress(count,
167 s.as_double() /
168 len.as_double() )) {
169 bGoodResult = false;
170 break;
171 }
172
173 block = limitSampleBufferSize( blockSize, len - s );
174
175 wt->GetFloats(buffer.get(), start + s, block);
176 ptr = buffer.get();
177 }
178
179 float v = fabs(*ptr++);
180 if (v >= MAX_AUDIO) {
181 if (startrun == 0) {
182 startTime = wt->LongSamplesToTime(start + s);
183 samps = 0;
184 }
185 else {
186 stoprun = 0;
187 }
188 startrun++;
189 samps++;
190 }
191 else {
192 if (startrun >= mStart) {
193 stoprun++;
194 samps++;
195
196 if (stoprun >= mStop) {
197 lt->AddLabel(SelectedRegion(startTime,
198 wt->LongSamplesToTime(start + s - mStop)),
199 wxString::Format(wxT("%lld of %lld"), startrun.as_long_long(), (samps - mStop).as_long_long()));
200 startrun = 0;
201 stoprun = 0;
202 samps = 0;
203 }
204 }
205 else {
206 startrun = 0;
207 }
208 }
209
210 s++;
211 block--;
212 }
213
214 return bGoodResult;
215}
216
217std::unique_ptr<EffectUIValidator> EffectFindClipping::PopulateOrExchange(
219{
220 DoPopulateOrExchange(S, access);
221 return nullptr;
222}
223
226{
227 mpAccess = access.shared_from_this();
228 S.StartMultiColumn(2, wxALIGN_CENTER);
229 {
230 S
231 .Validator<IntegerValidator<int>>(
232 &mStart, NumValidatorStyle::DEFAULT, Start.min)
233 .TieTextBox(XXO("&Start threshold (samples):"), mStart, 10);
234
235 S
236 .Validator<IntegerValidator<int>>(
237 &mStop, NumValidatorStyle::DEFAULT, Stop.min)
238 .TieTextBox(XXO("St&op threshold (samples):"), mStop, 10);
239 }
240 S.EndMultiColumn();
241}
242
244{
246 // To do: eliminate this and just use validators for controls
248
249 return true;
250}
251
253{
255 // To do: eliminate this and just use validators for controls
257
258 return true;
259}
const TranslatableString name
Definition: Distortion.cpp:82
EffectType
@ EffectTypeAnalyze
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define _(s)
Definition: Internat.h:75
#define MAX_AUDIO
Definition: MemoryX.h:538
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:23
@ 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:107
const TrackList * inputTracks() const
Definition: EffectBase.h:102
double mT0
Definition: EffectBase.h:106
static constexpr EffectParameter Start
Definition: FindClipping.h:66
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:60
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:62
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
bool Process(EffectInstance &instance, EffectSettings &settings) override
Actually do the effect here.
static constexpr EffectParameter Stop
Definition: FindClipping.h:68
bool TransferDataFromWindow(EffectSettings &settings) override
Update the given settings from controls.
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:59
TranslatableString GetDescription() const override
virtual ~EffectFindClipping()
ComponentInterfaceSymbol GetSymbol() const override
std::unique_ptr< EffectUIValidator > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access) override
Add controls to effect panel; always succeeds.
int MessageBox(const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={}) const
Definition: Effect.cpp:871
wxWindow * mUIParent
Definition: Effect.h:270
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
Definition: Effect.cpp:693
ModifiedAnalysisTrack ModifyAnalysisTrack(const LabelTrack *pOrigTrack, const wxString &name=wxString())
Definition: Effect.cpp:855
std::shared_ptr< AddedAnalysisTrack > AddAnalysisTrack(const wxString &name=wxString())
Definition: Effect.cpp:804
Performs effect computation.
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:89
double GetStartTime() const override
Definition: LabelTrack.cpp:346
int AddLabel(const SelectedRegion &region, const wxString &title)
Definition: LabelTrack.cpp:952
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:67
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:1435
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1452
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:18
double as_double() const
Definition: SampleCount.h:45
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.