Audacity  2.2.2
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 #include "../Audacity.h"
23 #include "FindClipping.h"
24 
25 #include <math.h>
26 
27 #include <wx/intl.h>
28 
29 #include "../ShuttleGui.h"
30 #include "../widgets/valnum.h"
31 #include "../widgets/ErrorDialog.h"
32 
33 #include "../LabelTrack.h"
34 #include "../WaveTrack.h"
35 #include "../MemoryX.h"
36 
37 // Define keys, defaults, minimums, and maximums for the effect parameters
38 //
39 // Name Type Key Def Min Max Scale
40 Param( Start, int, wxT("Duty Cycle"), 3, 1, INT_MAX, 1 );
41 Param( Stop, int, wxT("Duty Cycle"), 3, 1, INT_MAX, 1 );
42 
44 {
45  mStart = DEF_Start;
46  mStop = DEF_Stop;
47 }
48 
50 {
51 }
52 
53 // IdentInterface implementation
54 
56 {
58 }
59 
61 {
62  return _("Creates labels where clipping is detected");
63 }
64 
66 {
67  return wxT("Find_Clipping");
68 }
69 
70 // EffectIdentInterface implementation
71 
73 {
74  return EffectTypeAnalyze;
75 }
76 
77 // EffectClientInterface implementation
78 
79 bool EffectFindClipping::GetAutomationParameters(EffectAutomationParameters & parms)
80 {
81  parms.Write(KEY_Start, mStart);
82  parms.Write(KEY_Stop, mStop);
83 
84  return true;
85 }
86 
87 bool EffectFindClipping::SetAutomationParameters(EffectAutomationParameters & parms)
88 {
89  ReadAndVerifyInt(Start);
90  ReadAndVerifyInt(Stop);
91 
92  mStart = Start;
93  mStop = Stop;
94 
95  return true;
96 }
97 
98 // Effect implementation
99 
101 {
102  std::shared_ptr<AddedAnalysisTrack> addedTrack;
103  Maybe<ModifiedAnalysisTrack> modifiedTrack;
104  const wxString name{ _("Clipping") };
105 
106  LabelTrack *lt = NULL;
108  for (Track *t = iter.First(); t; t = iter.Next()) {
109  if (t->GetName() == name) {
110  lt = (LabelTrack *)t;
111  break;
112  }
113  }
114 
115  if (!lt)
116  addedTrack = (AddAnalysisTrack(name)), lt = addedTrack->get();
117  else
118  modifiedTrack.create(ModifyAnalysisTrack(lt, name)), lt = modifiedTrack->get();
119 
120  int count = 0;
121 
122  // JC: Only process selected tracks.
124  WaveTrack *t = (WaveTrack *) waves.First();
125  while (t) {
126  double trackStart = t->GetStartTime();
127  double trackEnd = t->GetEndTime();
128  double t0 = mT0 < trackStart ? trackStart : mT0;
129  double t1 = mT1 > trackEnd ? trackEnd : mT1;
130 
131  if (t1 > t0) {
132  auto start = t->TimeToLongSamples(t0);
133  auto end = t->TimeToLongSamples(t1);
134  auto len = end - start;
135 
136  if (!ProcessOne(lt, count, t, start, len)) {
137  return false;
138  }
139  }
140 
141  count++;
142  t = (WaveTrack *) waves.Next();
143  }
144 
145  // No cancellation, so commit the addition of the track.
146  if (addedTrack)
147  addedTrack->Commit();
148  if (modifiedTrack)
149  modifiedTrack->Commit();
150  return true;
151 }
152 
154  int count,
155  const WaveTrack * wt,
156  sampleCount start,
157  sampleCount len)
158 {
159  bool bGoodResult = true;
160  size_t blockSize = (mStart * 1000);
161 
162  if (len < mStart) {
163  return true;
164  }
165 
166  Floats buffer;
167  try {
168  // mStart should be positive.
169  // if we are throwing bad_alloc and mStart is negative, find out why.
170  if (mStart < 0 || (int)blockSize < mStart)
171  // overflow
172  throw std::bad_alloc{};
173  buffer.reinit(blockSize);
174  }
175  catch( const std::bad_alloc & ) {
176  Effect::MessageBox(_("Requested value exceeds memory capacity."));
177  return false;
178  }
179 
180  float *ptr = buffer.get();
181 
182  decltype(len) s = 0, startrun = 0, stoprun = 0, samps = 0;
183  decltype(blockSize) block = 0;
184  double startTime = -1.0;
185 
186  while (s < len) {
187  if (block == 0) {
188  if (TrackProgress(count,
189  s.as_double() /
190  len.as_double() )) {
191  bGoodResult = false;
192  break;
193  }
194 
195  block = limitSampleBufferSize( blockSize, len - s );
196 
197  wt->Get((samplePtr)buffer.get(), floatSample, start + s, block);
198  ptr = buffer.get();
199  }
200 
201  float v = fabs(*ptr++);
202  if (v >= MAX_AUDIO) {
203  if (startrun == 0) {
204  startTime = wt->LongSamplesToTime(start + s);
205  samps = 0;
206  }
207  else {
208  stoprun = 0;
209  }
210  startrun++;
211  samps++;
212  }
213  else {
214  if (startrun >= mStart) {
215  stoprun++;
216  samps++;
217 
218  if (stoprun >= mStop) {
219  lt->AddLabel(SelectedRegion(startTime,
220  wt->LongSamplesToTime(start + s - mStop)),
221  wxString::Format(wxT("%lld of %lld"), startrun.as_long_long(), (samps - mStop).as_long_long()),
222  -2);
223  startrun = 0;
224  stoprun = 0;
225  samps = 0;
226  }
227  }
228  else {
229  startrun = 0;
230  }
231  }
232 
233  s++;
234  block--;
235  }
236 
237  return bGoodResult;
238 }
239 
241 {
242  S.StartMultiColumn(2, wxALIGN_CENTER);
243  {
244  IntegerValidator<int> vldStart(&mStart);
245  vldStart.SetMin(MIN_Start);
246  S.TieTextBox(_("Start threshold (samples):"),
247  mStart,
248  10)->SetValidator(vldStart);
249 
250  IntegerValidator<int> vldStop(&mStop);
251  vldStop.SetMin(MIN_Stop);
252  S.TieTextBox(_("Stop threshold (samples):"),
253  mStop,
254  10)->SetValidator(vldStop);
255  }
256  S.EndMultiColumn();
257 }
258 
260 {
263 
264  return true;
265 }
266 
268 {
269  if (!mUIParent->Validate())
270  {
271  return false;
272  }
273 
276 
277  return true;
278 }
double mT1
Definition: Effect.h:460
#define FINDCLIPPING_PLUGIN_SYMBOL
Definition: FindClipping.h:23
int MessageBox(const wxString &message, long style=DefaultMessageBoxStyle, const wxString &titleStr=wxString{})
Definition: Effect.cpp:2655
bool GetAutomationParameters(EffectAutomationParameters &parms) override
bool TrackProgress(int whichTrack, double frac, const wxString &=wxEmptyString)
Definition: Effect.cpp:1978
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:366
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true) const
Definition: WaveTrack.cpp:1950
int mStart
Using int rather than sampleCount because values are only ever small numbers.
Definition: FindClipping.h:60
EffectType GetType() override
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:499
int mStop
Using int rather than sampleCount because values are only ever small numbers.
Definition: FindClipping.h:61
void PopulateOrExchange(ShuttleGui &S) override
void EndMultiColumn()
Definition: MemoryX.h:585
std::shared_ptr< AddedAnalysisTrack > AddAnalysisTrack(const wxString &name=wxString())
Definition: Effect.cpp:2097
ModifiedAnalysisTrack ModifyAnalysisTrack(const LabelTrack *pOrigTrack, const wxString &name=wxString())
Definition: Effect.cpp:2153
TrackList * inputTracks() const
Definition: Effect.h:457
Track * Next(bool skiplinked=false) override
Definition: Track.cpp:513
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:114
virtual ~EffectFindClipping()
bool TransferDataToWindow() override
#define ReadAndVerifyInt(name)
Definition: Effect.h:786
Defines a selected portion of a project.
Param(Start, int, wxT("Duty Cycle"), 3, 1, INT_MAX, 1)
bool SetAutomationParameters(EffectAutomationParameters &parms) override
wxString GetDescription() override
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:998
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:67
bool TransferDataFromWindow() override
bool Process() override
wxWindow * mUIParent
Definition: Effect.h:471
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
bool ProcessOne(LabelTrack *lt, int count, const WaveTrack *wt, sampleCount start, sampleCount len)
const wxChar * name
Definition: Distortion.cpp:94
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: WaveTrack.cpp:1822
Track * First(TrackList *val=NULL) override
Definition: Track.cpp:502
double GetEndTime() const
Get the time at which the last clip in the track ends, plus recorded stuff.
Definition: WaveTrack.cpp:1852
wxString ManualPage() override
wxString GetSymbol() override
double LongSamplesToTime(sampleCount pos) const
Convert correctly between an number of samples and an (absolute) time in seconds. ...
Definition: WaveTrack.cpp:1827
int AddLabel(const SelectedRegion &region, const wxString &title=wxT(""), int restoreFocus=-1)
void create(Args &&...args)
Definition: MemoryX.h:632
#define MAX_AUDIO
Definition: Audacity.h:212
double mT0
Definition: Effect.h:459
wxTextCtrl * TieTextBox(const wxString &Prompt, WrappedType &WrappedRef, const int nChars)
double GetStartTime() const
Get the time at which the first clip in the track starts.
Definition: WaveTrack.cpp:1832
LabelTrack * get() const
Definition: Effect.h:418