Audacity 3.2.0
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
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
50template<bool Const>
52 S.Define( errorThreshold, wxT("Threshold"), 0.0f, 0.0f, 0.01f, 1.0f );
53 return true;
54}
56 { return VisitSettings<false>(S); }
57
59 { return VisitSettings<true>(S); }
60
62{
63 S.AddSpace(0, 5);
64
65 S.StartMultiColumn(2, wxALIGN_CENTER);
66 {
67 S.TieTextBox(XXO("Threshold:"),errorThreshold);
68 }
69 S.EndMultiColumn();
70}
71
72// Update member variables with project selection data (and validate)
74{
75 // Get the selected time interval
76 auto &selectedRegion = ViewInfo::Get( proj ).selectedRegion;
77 mT0 = selectedRegion.t0();
78 mT1 = selectedRegion.t1();
79 if (mT0 >= mT1)
80 {
81 context.Error(wxT("There is no selection!"));
82 return false;
83 }
84
85 // Get the selected tracks and check that there are at least two to
86 // compare
87 auto trackRange = TrackList::Get( proj ).Selected< const WaveTrack >();
88 mTrack0 = *trackRange.first;
89 if (mTrack0 == NULL)
90 {
91 context.Error(wxT("No tracks selected! Select two tracks to compare."));
92 return false;
93 }
94 mTrack1 = * ++ trackRange.first;
95 if (mTrack1 == NULL)
96 {
97 context.Error(wxT("Only one track selected! Select two tracks to compare."));
98 return false;
99 }
100 if ( * ++ trackRange.first )
101 {
102 context.Status(wxT("More than two tracks selected - only the first two will be compared."));
103 }
104 return true;
105}
106
107double CompareAudioCommand::CompareSample(double value1, double value2)
108{
109 return fabs(value1 - value2);
110}
111
112inline int min(int a, int b)
113{
114 return (a < b) ? a : b;
115}
116
118{
119 if (!GetSelection(context, context.project))
120 {
121 return false;
122 }
123
124 wxString msg = wxT("Comparing tracks '");
125 msg += mTrack0->GetName() + wxT("' and '")
126 + mTrack1->GetName() + wxT("'.");
127 context.Status(msg);
128
129 long errorCount = 0;
130 // Initialize buffers for track data to be analyzed
132
133 Floats buff0{ buffSize };
134 Floats buff1{ buffSize };
135
136 // Compare tracks block by block
137 auto s0 = mTrack0->TimeToLongSamples(mT0);
138 auto s1 = mTrack0->TimeToLongSamples(mT1);
139 auto position = s0;
140 auto length = s1 - s0;
141 while (position < s1)
142 {
143 // Get a block of data into the buffers
144 auto block = limitSampleBufferSize(
145 mTrack0->GetBestBlockSize(position), s1 - position
146 );
147 mTrack0->GetFloats(buff0.get(), position, block);
148 mTrack1->GetFloats(buff1.get(), position, block);
149
150 for (decltype(block) buffPos = 0; buffPos < block; ++buffPos)
151 {
152 if (CompareSample(buff0[buffPos], buff1[buffPos]) > errorThreshold)
153 {
154 ++errorCount;
155 }
156 }
157
158 position += block;
159 context.Progress(
160 (position - s0).as_double() /
161 length.as_double()
162 );
163 }
164
165 // Output the results
166 double errorSeconds = mTrack0->LongSamplesToTime(errorCount);
167 context.Status(wxString::Format(wxT("%li"), errorCount));
168 context.Status(wxString::Format(wxT("%.4f"), errorSeconds));
169 context.Status(wxString::Format(wxT("Finished comparison: %li samples (%.3f seconds) exceeded the error threshold of %f."), errorCount, errorSeconds, errorThreshold));
170 return true;
171}
172
void RegisterCompareAudio(Registrar &R)
int min(int a, int b)
Contains declaration of CompareAudioCommand and CompareAudioCommandType classes.
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:23
#define S(N)
Definition: ToChars.cpp:64
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
virtual void Progress(double d) const
virtual void Error(const wxString &message) const
virtual void Status(const wxString &message, bool bFlush=false) const
AudacityProject & project
double CompareSample(double value1, double value2)
void PopulateOrExchange(ShuttleGui &S) override
const WaveTrack * mTrack1
bool Apply(const CommandContext &context) override
bool GetSelection(const CommandContext &context, AudacityProject &proj)
static const ComponentInterfaceSymbol Symbol
const WaveTrack * mTrack0
bool VisitSettings(SettingsVisitorBase< Const > &S)
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Base class for registration callback. Audacity will call providers RegisterNameOfThing() functions wi...
Definition: Registrar.h:33
virtual void AddCommand(std::unique_ptr< AudacityCommand > &&WXUNUSED(command))
Definition: Registrar.h:46
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
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: SampleTrack.cpp:42
Visitor of effect or command parameters. This is a base class with lots of virtual functions that do ...
Definition: Shuttle.h:115
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
wxString GetName() const
Definition: Track.h:466
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:486
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1452
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:216
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
size_t GetMaxBlockSize() const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1806
size_t GetBestBlockSize(sampleCount t) const override
This returns a nonnegative number of samples meant to size a memory buffer.
Definition: WaveTrack.cpp:1788
BuiltinCommandsModule::Registration< CompareAudioCommand > reg