1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-13 23:49:03 +02:00
audacity/src/commands/CompareAudioCommand.cpp

154 lines
4.2 KiB
C++

/**********************************************************************
Audacity - A Digital Audio Editor
Copyright 1999-2009 Audacity Team
License: wxwidgets
Dan Horgan
******************************************************************//**
\file CompareAudioCommand.cpp
\brief Contains definitions for CompareAudioCommand class
\class CompareAudioCommand
\brief Returns information about the amount of audio that is about a certain
threshold of difference in two selected tracks
*//*******************************************************************/
#include "CompareAudioCommand.h"
#include "../Project.h"
#include "Command.h"
wxString CompareAudioCommandType::BuildName()
{
return wxT("CompareAudio");
}
void CompareAudioCommandType::BuildSignature(CommandSignature &signature)
{
DoubleValidator *thresholdValidator = new DoubleValidator();
signature.AddParameter(wxT("Threshold"), 0.0, thresholdValidator);
}
Command *CompareAudioCommandType::Create(CommandOutputTarget *target)
{
return new CompareAudioCommand(*this, target);
}
// Update member variables with project selection data (and validate)
bool CompareAudioCommand::GetSelection(AudacityProject &proj)
{
// Get the selected time interval
mT0 = proj.mViewInfo.sel0;
mT1 = proj.mViewInfo.sel1;
if (mT0 >= mT1)
{
Error(wxT("There is no selection!"));
return false;
}
// Get the selected tracks and check that there are at least two to
// compare
SelectedTrackListOfKindIterator iter(Track::Wave, proj.GetTracks());
mTrack0 = (WaveTrack*)(iter.First());
if (mTrack0 == NULL)
{
Error(wxT("No tracks selected! Select two tracks to compare."));
return false;
}
mTrack1 = (WaveTrack*)(iter.Next());
if (mTrack1 == NULL)
{
Error(wxT("Only one track selected! Select two tracks to compare."));
return false;
}
if (iter.Next() != NULL)
{
Status(wxT("More than two tracks selected - only the first two will be compared."));
}
return true;
}
double CompareAudioCommand::CompareSample(double value1, double value2)
{
return fabs(value1 - value2);
}
inline int min(int a, int b)
{
return (a < b) ? a : b;
}
bool CompareAudioCommand::Apply(CommandExecutionContext context)
{
if (!GetSelection(*context.proj))
{
return false;
}
wxString msg = wxT("Comparing tracks '");
msg += mTrack0->GetName() + wxT("' and '")
+ mTrack1->GetName() + wxT("'.");
Status(msg);
long errorCount = 0;
double errorThreshold = GetDouble(wxT("Threshold"));
// Initialize buffers for track data to be analyzed
int buffSize = min(mTrack0->GetMaxBlockSize(), mTrack1->GetMaxBlockSize());
float *buff0 = new float[buffSize];
float *buff1 = new float[buffSize];
// Compare tracks block by block
long s0 = mTrack0->TimeToLongSamples(mT0);
long s1 = mTrack0->TimeToLongSamples(mT1);
long position = s0;
long length = s1 - s0;
while (position < s1)
{
// Get a block of data into the buffers
sampleCount block = mTrack0->GetBestBlockSize(position);
if (position + block > s1)
{
block = s1 - position;
}
mTrack0->Get((samplePtr)buff0, floatSample, position, block);
mTrack1->Get((samplePtr)buff1, floatSample, position, block);
int buffPos = 0;
for (buffPos = 0; buffPos < block; ++buffPos)
{
if (CompareSample(buff0[buffPos], buff1[buffPos]) > errorThreshold)
{
++errorCount;
}
}
position += block;
Progress((position - mT0) / length);
}
delete [] buff0;
delete [] buff1;
// Output the results
double errorSeconds = mTrack0->LongSamplesToTime(errorCount);
Status(wxString::Format(wxT("%i"), errorCount));
Status(wxString::Format(wxT("%.4f"), errorSeconds));
Status(wxString::Format(wxT("Finished comparison: %i samples (%.3f seconds) exceeded the error threshold of %f."), errorCount, errorSeconds, errorThreshold));
return true;
}
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
// version control system. Please do not modify past this point.
//
// Local Variables:
// c-basic-offset: 3
// indent-tabs-mode: nil
// End:
//
// vim: et sts=3 sw=3
// arch-tag: TBD