audacia/src/effects/Repair.cpp

155 lines
4.7 KiB
C++
Raw Normal View History

/**********************************************************************
Audacity: A Digital Audio Editor
Repair.cpp
Dominic Mazzoni
*******************************************************************//**
\class EffectRepair
\brief Use the interpolation code to fill in damaged audio.
Damage can include pops, clicks, or clipping. As long as the
damaged section is short and surrounded by lots of good audio,
it is usually quite successful.
This was formerly the PopClickRemoval effect, but it was
renamed and focused on the smaller subproblem of repairing
the audio, rather than actually finding the clicks.
*//*******************************************************************/
#include "Repair.h"
#include <math.h>
#include <wx/intl.h>
#include "../InterpolateAudio.h"
#include "../WaveTrack.h"
#include "../widgets/AudacityMessageBox.h"
#include "LoadEffects.h"
const ComponentInterfaceSymbol EffectRepair::Symbol
{ XO("Repair") };
namespace{ BuiltinEffectsModule::Registration< EffectRepair > reg; }
EffectRepair::EffectRepair()
{
}
EffectRepair::~EffectRepair()
{
}
// ComponentInterface implementation
ComponentInterfaceSymbol EffectRepair::GetSymbol()
{
return Symbol;
}
TranslatableString EffectRepair::GetDescription()
{
return XO("Sets the peak amplitude of a one or more tracks");
}
Automation: AudacityCommand This is a squash of 50 commits. This merges the capabilities of BatchCommands and Effects using a new AudacityCommand class. AudacityCommand provides one function to specify the parameters, and then we leverage that one function in automation, whether by chains, mod-script-pipe or (future) Nyquist. - Now have AudacityCommand which is using the same mechanism as Effect - Has configurable parameters - Has data-entry GUI (built using shuttle GUI) - Registers with PluginManager. - Menu commands now provided in chains, and to python batch. - Tested with Zoom Toggle. - ShuttleParams now can set, get, set defaults, validate and specify the parameters. - Bugfix: Don't overwrite values with defaults first time out. - Add DefineParams function for all built-in effects. - Extend CommandContext to carry output channels for results. We abuse EffectsManager. It handles both Effects and AudacityCommands now. In time an Effect should become a special case of AudacityCommand and we'll split and rename the EffectManager class. - Don't use 'default' as a parameter name. - Massive renaming for CommandDefinitionInterface - EffectIdentInterface becomes EffectDefinitionInterface - EffectAutomationParameters becomes CommandAutomationParameters - PluginType is now a bit field. This way we can search for related types at the same time. - Most old batch commands made into AudacityCommands. The ones that weren't are for a reason. They are used by mod-script-pipe to carry commands and responses across from a non-GUI thread to the GUI thread. - Major tidy up of ScreenshotCommand - Reworking of SelectCommand - GetPreferenceCommand and SetPreferenceCommand - GetTrackInfo and SetTrackInfo - GetInfoCommand - Help, Open, Save, Import and Export commands. - Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo which are now better handled by other commands. - JSONify "GetInfo: Commands" output, i.e. commas in the right places. - General work on better Doxygen. - Lyrics -> LyricsPanel - Meter -> MeterPanel - Updated Linux makefile. - Scripting commands added into Extra menu. - Distinct names for previously duplicated find-clipping parameters. - Fixed longstanding error with erroneous status field number which previously caused an ASSERT in debug. - Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
2018-01-14 18:51:41 +00:00
// EffectDefinitionInterface implementation
EffectType EffectRepair::GetType()
{
return EffectTypeProcess;
}
bool EffectRepair::IsInteractive()
2014-06-03 20:30:19 +00:00
{
return false;
}
// Effect implementation
bool EffectRepair::Process()
{
//v This may be too much copying for EffectRepair. To support Cancel, may be able to copy much less.
// But for now, Cancel isn't supported without this.
this->CopyInputTracks(); // Set up mOutputTracks. //v This may be too much copying for EffectRepair.
bool bGoodResult = true;
int count = 0;
for( auto track : mOutputTracks->Selected< WaveTrack >() ) {
const
double trackStart = track->GetStartTime();
const double repair_t0 = std::max(mT0, trackStart);
const
double trackEnd = track->GetEndTime();
const double repair_t1 = std::min(mT1, trackEnd);
const
double repair_deltat = repair_t1 - repair_t0;
if (repair_deltat > 0) { // selection is within track audio
const auto repair0 = track->TimeToLongSamples(repair_t0);
const auto repair1 = track->TimeToLongSamples(repair_t1);
const auto repairLen = repair1 - repair0;
if (repairLen > 128) {
::Effect::MessageBox(
XO(
"The Repair effect is intended to be used on very short sections of damaged audio (up to 128 samples).\n\nZoom in and select a tiny fraction of a second to repair.") );
bGoodResult = false;
break;
}
2014-06-03 20:30:19 +00:00
const double rate = track->GetRate();
const double spacing = std::max(repair_deltat * 2, 128. / rate);
const double t0 = std::max(repair_t0 - spacing, trackStart);
const double t1 = std::min(repair_t1 + spacing, trackEnd);
const auto s0 = track->TimeToLongSamples(t0);
const auto s1 = track->TimeToLongSamples(t1);
// The difference is at most 2 * 128:
const auto repairStart = (repair0 - s0).as_size_t();
const auto len = s1 - s0;
if (s0 == repair0 && s1 == repair1) {
::Effect::MessageBox(
XO(
"Repair works by using audio data outside the selection region.\n\nPlease select a region that has audio touching at least one side of it.\n\nThe more surrounding audio, the better it performs.") );
/// The Repair effect needs some data to go on.\n\nPlease select an area to repair with some audio on at least one side (the more the better).") );
bGoodResult = false;
break;
}
2014-06-03 20:30:19 +00:00
if (!ProcessOne(count, track, s0,
// len is at most 5 * 128.
len.as_size_t(),
repairStart,
// repairLen is at most 128.
repairLen.as_size_t() )) {
bGoodResult = false;
break;
}
}
count++;
}
2014-06-03 20:30:19 +00:00
this->ReplaceProcessedTracks(bGoodResult);
return bGoodResult;
}
bool EffectRepair::ProcessOne(int count, WaveTrack * track,
sampleCount start,
size_t len,
size_t repairStart, size_t repairLen)
{
2016-04-14 16:35:15 +00:00
Floats buffer{ len };
track->GetFloats(buffer.get(), start, len);
2016-04-14 16:35:15 +00:00
InterpolateAudio(buffer.get(), len, repairStart, repairLen);
track->Set((samplePtr)&buffer[repairStart], floatSample,
start + repairStart, repairLen);
return !TrackProgress(count, 1.0); // TrackProgress returns true on Cancel.
}