Audacity  2.2.2
CompareAudioCommand.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity - A Digital Audio Editor
4  Copyright 1999-2018 Audacity Team
5  License: wxwidgets
6 
7  Dan Horgan
8  James Crook
9 
10 ******************************************************************//*******************************************************************/
20 
21 #include "../Audacity.h"
22 #include "CompareAudioCommand.h"
23 #include "../MemoryX.h"
24 #include "../Project.h"
25 #include "../WaveTrack.h"
26 #include "Command.h"
27 
28 
29 #include <float.h>
30 #include <wx/intl.h>
31 
32 #include "../ShuttleGui.h"
33 #include "../widgets/ErrorDialog.h"
34 #include "../widgets/valnum.h"
35 #include "../SampleFormat.h"
36 #include "CommandContext.h"
37 
38 extern void RegisterCompareAudio( Registrar & R){
39  R.AddCommand( std::make_unique<CompareAudioCommand>() );
40 // std::unique_ptr<CommandOutputTargets> &&target
41 // return std::make_shared<CompareAudioCommand>(*this, std::move(target));
42 
43 }
44 
46  S.Define( errorThreshold, wxT("Threshold"), 0.0f, 0.0f, 0.01f, 1.0f );
47  return true;
48 }
49 
51  return true;
52 }
53 
55 {
56  S.AddSpace(0, 5);
57 
58  S.StartMultiColumn(2, wxALIGN_CENTER);
59  {
60  S.TieTextBox(_("Threshold:"),errorThreshold);
61  }
62  S.EndMultiColumn();
63 }
64 
65 // Update member variables with project selection data (and validate)
67 {
68  // Get the selected time interval
69  mT0 = proj.mViewInfo.selectedRegion.t0();
70  mT1 = proj.mViewInfo.selectedRegion.t1();
71  if (mT0 >= mT1)
72  {
73  context.Error(wxT("There is no selection!"));
74  return false;
75  }
76 
77  // Get the selected tracks and check that there are at least two to
78  // compare
80  mTrack0 = (WaveTrack*)(iter.First());
81  if (mTrack0 == NULL)
82  {
83  context.Error(wxT("No tracks selected! Select two tracks to compare."));
84  return false;
85  }
86  mTrack1 = (WaveTrack*)(iter.Next());
87  if (mTrack1 == NULL)
88  {
89  context.Error(wxT("Only one track selected! Select two tracks to compare."));
90  return false;
91  }
92  if (iter.Next() != NULL)
93  {
94  context.Status(wxT("More than two tracks selected - only the first two will be compared."));
95  }
96  return true;
97 }
98 
99 double CompareAudioCommand::CompareSample(double value1, double value2)
100 {
101  return fabs(value1 - value2);
102 }
103 
104 inline int min(int a, int b)
105 {
106  return (a < b) ? a : b;
107 }
108 
110 {
111  if (!GetSelection(context, *context.GetProject()))
112  {
113  return false;
114  }
115 
116  wxString msg = wxT("Comparing tracks '");
117  msg += mTrack0->GetName() + wxT("' and '")
118  + mTrack1->GetName() + wxT("'.");
119  context.Status(msg);
120 
121  long errorCount = 0;
122  // Initialize buffers for track data to be analyzed
123  auto buffSize = std::min(mTrack0->GetMaxBlockSize(), mTrack1->GetMaxBlockSize());
124 
125  Floats buff0{ buffSize };
126  Floats buff1{ buffSize };
127 
128  // Compare tracks block by block
129  auto s0 = mTrack0->TimeToLongSamples(mT0);
130  auto s1 = mTrack0->TimeToLongSamples(mT1);
131  auto position = s0;
132  auto length = s1 - s0;
133  while (position < s1)
134  {
135  // Get a block of data into the buffers
136  auto block = limitSampleBufferSize(
137  mTrack0->GetBestBlockSize(position), s1 - position
138  );
139  mTrack0->Get((samplePtr)buff0.get(), floatSample, position, block);
140  mTrack1->Get((samplePtr)buff1.get(), floatSample, position, block);
141 
142  for (decltype(block) buffPos = 0; buffPos < block; ++buffPos)
143  {
144  if (CompareSample(buff0[buffPos], buff1[buffPos]) > errorThreshold)
145  {
146  ++errorCount;
147  }
148  }
149 
150  position += block;
151  context.Progress(
152  (position - s0).as_double() /
153  length.as_double()
154  );
155  }
156 
157  // Output the results
158  double errorSeconds = mTrack0->LongSamplesToTime(errorCount);
159  context.Status(wxString::Format(wxT("%li"), errorCount));
160  context.Status(wxString::Format(wxT("%.4f"), errorSeconds));
161  context.Status(wxString::Format(wxT("Finished comparison: %li samples (%.3f seconds) exceeded the error threshold of %f."), errorCount, errorSeconds, errorThreshold));
162  return true;
163 }
AudacityProject * GetProject() const
double t0() const
const WaveTrack * mTrack1
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
SelectedRegion selectedRegion
Definition: ViewInfo.h:160
void PopulateOrExchange(ShuttleGui &S) override
double CompareSample(double value1, double value2)
bool DefineParams(ShuttleParams &S) override
void EndMultiColumn()
Contains declaration of Command base class.
virtual void Status(const wxString &message, bool bFlush=false) const
virtual void Progress(double d) const
CommandContext provides addiitonal information to an 'Apply()' command. It provides the project...
Shuttle that deals with parameters. This is a base class with lots of virtual functions that do nothi...
Definition: Shuttle.h:60
double t1() const
size_t GetBestBlockSize(sampleCount t) const
Definition: WaveTrack.cpp:1607
Contains declaration of CompareAudioCommand and CompareAudioCommandType classes.
Base class for registration callback. Audcaity will call providers RegisterNameOfThing() functions wi...
Definition: Registrar.h:31
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: Types.h:178
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:176
const WaveTrack * mTrack0
void RegisterCompareAudio(Registrar &R)
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
char * samplePtr
Definition: Types.h:203
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
virtual void Define(bool &var, const wxChar *key, const bool vdefault, const bool vmin=false, const bool vmax=false, const bool vscl=false)
Definition: Shuttle.cpp:339
ViewInfo mViewInfo
Definition: Project.h:558
int min(int a, int b)
wxString GetName() const
Definition: Track.h:270
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:1625
virtual void AddCommand(movable_ptr< AudacityCommand > &&WXUNUSED(command))
Definition: Registrar.h:45
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: WaveTrack.cpp:1843
virtual void Error(const wxString &message) const
wxSizerItem * AddSpace(int width, int height)
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumCopied=nullptr) const
Definition: WaveTrack.cpp:1971
TrackList * GetTracks()
Definition: Project.h:192
double LongSamplesToTime(sampleCount pos) const
Convert correctly between an number of samples and an (absolute) time in seconds. ...
Definition: WaveTrack.cpp:1848
bool GetSelection(const CommandContext &context, AudacityProject &proj)
wxTextCtrl * TieTextBox(const wxString &Prompt, WrappedType &WrappedRef, const int nChars)