Audacity  3.0.3
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 
22 #include "CompareAudioCommand.h"
23 
24 #include "LoadCommands.h"
25 #include "../ViewInfo.h"
26 #include "../WaveTrack.h"
27 
28 
29 #include <float.h>
30 #include <wx/intl.h>
31 
32 #include "../Shuttle.h"
33 #include "../ShuttleGui.h"
34 #include "../widgets/AudacityMessageBox.h"
35 #include "../widgets/valnum.h"
36 #include "CommandContext.h"
37 
39 { XO("Compare Audio") };
40 
42 
43 extern void RegisterCompareAudio( Registrar & R){
44  R.AddCommand( std::make_unique<CompareAudioCommand>() );
45 // std::unique_ptr<CommandOutputTargets> &&target
46 // return std::make_shared<CompareAudioCommand>(*this, std::move(target));
47 
48 }
49 
51  S.Define( errorThreshold, wxT("Threshold"), 0.0f, 0.0f, 0.01f, 1.0f );
52  return true;
53 }
54 
56 {
57  S.AddSpace(0, 5);
58 
59  S.StartMultiColumn(2, wxALIGN_CENTER);
60  {
61  S.TieTextBox(XXO("Threshold:"),errorThreshold);
62  }
63  S.EndMultiColumn();
64 }
65 
66 // Update member variables with project selection data (and validate)
68 {
69  // Get the selected time interval
70  auto &selectedRegion = ViewInfo::Get( proj ).selectedRegion;
71  mT0 = selectedRegion.t0();
72  mT1 = selectedRegion.t1();
73  if (mT0 >= mT1)
74  {
75  context.Error(wxT("There is no selection!"));
76  return false;
77  }
78 
79  // Get the selected tracks and check that there are at least two to
80  // compare
81  auto trackRange = TrackList::Get( proj ).Selected< const WaveTrack >();
82  mTrack0 = *trackRange.first;
83  if (mTrack0 == NULL)
84  {
85  context.Error(wxT("No tracks selected! Select two tracks to compare."));
86  return false;
87  }
88  mTrack1 = * ++ trackRange.first;
89  if (mTrack1 == NULL)
90  {
91  context.Error(wxT("Only one track selected! Select two tracks to compare."));
92  return false;
93  }
94  if ( * ++ trackRange.first )
95  {
96  context.Status(wxT("More than two tracks selected - only the first two will be compared."));
97  }
98  return true;
99 }
100 
101 double CompareAudioCommand::CompareSample(double value1, double value2)
102 {
103  return fabs(value1 - value2);
104 }
105 
106 inline int min(int a, int b)
107 {
108  return (a < b) ? a : b;
109 }
110 
112 {
113  if (!GetSelection(context, context.project))
114  {
115  return false;
116  }
117 
118  wxString msg = wxT("Comparing tracks '");
119  msg += mTrack0->GetName() + wxT("' and '")
120  + mTrack1->GetName() + wxT("'.");
121  context.Status(msg);
122 
123  long errorCount = 0;
124  // Initialize buffers for track data to be analyzed
125  auto buffSize = std::min(mTrack0->GetMaxBlockSize(), mTrack1->GetMaxBlockSize());
126 
127  Floats buff0{ buffSize };
128  Floats buff1{ buffSize };
129 
130  // Compare tracks block by block
131  auto s0 = mTrack0->TimeToLongSamples(mT0);
132  auto s1 = mTrack0->TimeToLongSamples(mT1);
133  auto position = s0;
134  auto length = s1 - s0;
135  while (position < s1)
136  {
137  // Get a block of data into the buffers
138  auto block = limitSampleBufferSize(
139  mTrack0->GetBestBlockSize(position), s1 - position
140  );
141  mTrack0->Get((samplePtr)buff0.get(), floatSample, position, block);
142  mTrack1->Get((samplePtr)buff1.get(), floatSample, position, block);
143 
144  for (decltype(block) buffPos = 0; buffPos < block; ++buffPos)
145  {
146  if (CompareSample(buff0[buffPos], buff1[buffPos]) > errorThreshold)
147  {
148  ++errorCount;
149  }
150  }
151 
152  position += block;
153  context.Progress(
154  (position - s0).as_double() /
155  length.as_double()
156  );
157  }
158 
159  // Output the results
160  double errorSeconds = mTrack0->LongSamplesToTime(errorCount);
161  context.Status(wxString::Format(wxT("%li"), errorCount));
162  context.Status(wxString::Format(wxT("%.4f"), errorSeconds));
163  context.Status(wxString::Format(wxT("Finished comparison: %li samples (%.3f seconds) exceeded the error threshold of %f."), errorCount, errorSeconds, errorThreshold));
164  return true;
165 }
166 
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:162
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:68
LoadCommands.h
CompareAudioCommand::mTrack1
const WaveTrack * mTrack1
Definition: CompareAudioCommand.h:46
CompareAudioCommand::mT0
double mT0
Definition: CompareAudioCommand.h:44
Track::GetName
wxString GetName() const
Definition: Track.h:409
CompareAudioCommand::Apply
bool Apply(const CommandContext &context) override
Definition: CompareAudioCommand.cpp:111
ShuttleGui::AddSpace
wxSizerItem * AddSpace(int width, int height, int prop=0)
Definition: ShuttleGui.cpp:2421
Registrar::AddCommand
virtual void AddCommand(std::unique_ptr< AudacityCommand > &&WXUNUSED(command))
Definition: Registrar.h:46
XO
#define XO(s)
Definition: Internat.h:32
CompareAudioCommand::errorThreshold
double errorThreshold
Definition: CompareAudioCommand.h:43
ShuttleParams
Shuttle that deals with parameters. This is a base class with lots of virtual functions that do nothi...
Definition: Shuttle.h:61
ShuttleGuiBase::EndMultiColumn
void EndMultiColumn()
Definition: ShuttleGui.cpp:1212
floatSample
@ floatSample
Definition: Types.h:714
RegisterCompareAudio
void RegisterCompareAudio(Registrar &R)
Definition: CompareAudioCommand.cpp:43
CompareAudioCommand::DefineParams
bool DefineParams(ShuttleParams &S) override
Definition: CompareAudioCommand.cpp:50
ComponentInterfaceSymbol
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Definition: ComponentInterface.h:60
ShuttleGuiBase::TieTextBox
wxTextCtrl * TieTextBox(const TranslatableString &Caption, wxString &Value, const int nChars=0)
Definition: ShuttleGui.cpp:1626
BuiltinCommandsModule::Registration
Definition: LoadCommands.h:41
WaveTrack::Get
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, fillFormat fill=fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
Definition: WaveTrack.cpp:1895
CompareAudioCommand::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S) override
Definition: CompareAudioCommand.cpp:55
limitSampleBufferSize
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: Types.h:698
CommandContext::Status
virtual void Status(const wxString &message, bool bFlush=false) const
Definition: CommandContext.cpp:63
CommandContext.h
samplePtr
char * samplePtr
Definition: Types.h:729
ViewInfo::selectedRegion
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:199
XXO
#define XXO(s)
Definition: Internat.h:45
CommandContext
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
Definition: CommandContext.h:22
WaveTrack::LongSamplesToTime
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
Definition: WaveTrack.cpp:1772
ShuttleGuiBase::StartMultiColumn
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:1203
Registrar
Base class for registration callback. Audacity will call providers RegisterNameOfThing() functions wi...
Definition: Registrar.h:33
CompareAudioCommand::mT1
double mT1
Definition: CompareAudioCommand.h:44
CompareAudioCommand::Symbol
static const ComponentInterfaceSymbol Symbol
Definition: CompareAudioCommand.h:29
CommandContext::Error
virtual void Error(const wxString &message) const
Definition: CommandContext.cpp:73
CommandContext::Progress
virtual void Progress(double d) const
Definition: CommandContext.cpp:83
WaveTrack::GetMaxBlockSize
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:1578
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
WaveTrack::TimeToLongSamples
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: WaveTrack.cpp:1767
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:495
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:112
CompareAudioCommand::mTrack0
const WaveTrack * mTrack0
Definition: CompareAudioCommand.h:45
WaveTrack::GetBestBlockSize
size_t GetBestBlockSize(sampleCount t) const
Definition: WaveTrack.cpp:1560
ShuttleParams::Define
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:332
CompareAudioCommand::GetSelection
bool GetSelection(const CommandContext &context, AudacityProject &proj)
Definition: CompareAudioCommand.cpp:67
CommandContext::project
AudacityProject & project
Definition: CommandContext.h:52
TrackList::Selected
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1371
anonymous_namespace{CompareAudioCommand.cpp}::reg
BuiltinCommandsModule::Registration< CompareAudioCommand > reg
Definition: CompareAudioCommand.cpp:41
ArrayOf< float >
CompareAudioCommand::CompareSample
double CompareSample(double value1, double value2)
Definition: CompareAudioCommand.cpp:101
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:638
CompareAudioCommand.h
Contains declaration of CompareAudioCommand and CompareAudioCommandType classes.