259 lines
5.9 KiB
C++
259 lines
5.9 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
Repeat.cpp
|
|
|
|
Dominic Mazzoni
|
|
Vaughan Johnson
|
|
|
|
*******************************************************************//**
|
|
|
|
\class EffectRepeat
|
|
\brief An Effect that repeats audio several times over.
|
|
|
|
*//****************************************************************//**
|
|
|
|
\class RepeatDialog
|
|
\brief Dialog used with EffectRepeat
|
|
|
|
*//*******************************************************************/
|
|
|
|
|
|
|
|
#include "Repeat.h"
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <wx/intl.h>
|
|
#include <wx/stattext.h>
|
|
|
|
#include "../LabelTrack.h"
|
|
#include "../Shuttle.h"
|
|
#include "../ShuttleGui.h"
|
|
#include "../WaveTrack.h"
|
|
#include "../widgets/NumericTextCtrl.h"
|
|
#include "../widgets/valnum.h"
|
|
|
|
#include "LoadEffects.h"
|
|
|
|
// Define keys, defaults, minimums, and maximums for the effect parameters
|
|
//
|
|
// Name Type Key Def Min Max Scale
|
|
Param( Count, int, wxT("Count"), 1, 1, INT_MAX, 1 );
|
|
|
|
const ComponentInterfaceSymbol EffectRepeat::Symbol
|
|
{ XO("Repeat") };
|
|
|
|
namespace{ BuiltinEffectsModule::Registration< EffectRepeat > reg; }
|
|
|
|
BEGIN_EVENT_TABLE(EffectRepeat, wxEvtHandler)
|
|
EVT_TEXT(wxID_ANY, EffectRepeat::OnRepeatTextChange)
|
|
END_EVENT_TABLE()
|
|
|
|
EffectRepeat::EffectRepeat()
|
|
{
|
|
repeatCount = DEF_Count;
|
|
|
|
SetLinearEffectFlag(true);
|
|
}
|
|
|
|
EffectRepeat::~EffectRepeat()
|
|
{
|
|
}
|
|
|
|
// ComponentInterface implementation
|
|
|
|
ComponentInterfaceSymbol EffectRepeat::GetSymbol()
|
|
{
|
|
return Symbol;
|
|
}
|
|
|
|
TranslatableString EffectRepeat::GetDescription()
|
|
{
|
|
return XO("Repeats the selection the specified number of times");
|
|
}
|
|
|
|
ManualPageID EffectRepeat::ManualPage()
|
|
{
|
|
return L"Repeat";
|
|
}
|
|
|
|
// EffectDefinitionInterface implementation
|
|
|
|
EffectType EffectRepeat::GetType()
|
|
{
|
|
return EffectTypeProcess;
|
|
}
|
|
|
|
// EffectClientInterface implementation
|
|
bool EffectRepeat::DefineParams( ShuttleParams & S ){
|
|
S.SHUTTLE_PARAM( repeatCount, Count );
|
|
return true;
|
|
}
|
|
|
|
bool EffectRepeat::GetAutomationParameters(CommandParameters & parms)
|
|
{
|
|
parms.Write(KEY_Count, repeatCount);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool EffectRepeat::SetAutomationParameters(CommandParameters & parms)
|
|
{
|
|
ReadAndVerifyInt(Count);
|
|
|
|
repeatCount = Count;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Effect implementation
|
|
|
|
bool EffectRepeat::Process()
|
|
{
|
|
// Set up mOutputTracks.
|
|
// This effect needs all for sync-lock grouping.
|
|
CopyInputTracks(true);
|
|
|
|
int nTrack = 0;
|
|
bool bGoodResult = true;
|
|
double maxDestLen = 0.0; // used to change selection to generated bit
|
|
|
|
mOutputTracks->Any().VisitWhile( bGoodResult,
|
|
[&](LabelTrack *track)
|
|
{
|
|
if (track->GetSelected() || track->IsSyncLockSelected())
|
|
{
|
|
if (!track->Repeat(mT0, mT1, repeatCount))
|
|
bGoodResult = false;
|
|
}
|
|
},
|
|
[&](WaveTrack *track, const Track::Fallthrough &fallthrough)
|
|
{
|
|
if (!track->GetSelected())
|
|
return fallthrough(); // Fall through to next lambda
|
|
auto start = track->TimeToLongSamples(mT0);
|
|
auto end = track->TimeToLongSamples(mT1);
|
|
auto len = end - start;
|
|
double tLen = track->LongSamplesToTime(len);
|
|
double tc = mT0 + tLen;
|
|
|
|
if (len <= 0)
|
|
return;
|
|
|
|
auto dest = track->Copy(mT0, mT1);
|
|
for(int j=0; j<repeatCount; j++)
|
|
{
|
|
if (TrackProgress(nTrack, j / repeatCount)) // TrackProgress returns true on Cancel.
|
|
{
|
|
bGoodResult = false;
|
|
return;
|
|
}
|
|
track->Paste(tc, dest.get());
|
|
tc += tLen;
|
|
}
|
|
if (tc > maxDestLen)
|
|
maxDestLen = tc;
|
|
nTrack++;
|
|
},
|
|
[&](Track *t)
|
|
{
|
|
if( t->IsSyncLockSelected() )
|
|
t->SyncLockAdjust(mT1, mT1 + (mT1 - mT0) * repeatCount);
|
|
}
|
|
);
|
|
|
|
if (bGoodResult)
|
|
{
|
|
// Select the NEW bits + original bit
|
|
mT1 = maxDestLen;
|
|
}
|
|
|
|
ReplaceProcessedTracks(bGoodResult);
|
|
return bGoodResult;
|
|
}
|
|
|
|
void EffectRepeat::PopulateOrExchange(ShuttleGui & S)
|
|
{
|
|
S.StartHorizontalLay(wxCENTER, false);
|
|
{
|
|
mRepeatCount = S.Validator<IntegerValidator<int>>(
|
|
&repeatCount, NumValidatorStyle::DEFAULT,
|
|
MIN_Count, 2147483647 / mProjectRate
|
|
)
|
|
.AddTextBox(XXO("&Number of repeats to add:"), wxT(""), 12);
|
|
}
|
|
S.EndHorizontalLay();
|
|
|
|
S.StartMultiColumn(1, wxCENTER);
|
|
{
|
|
mCurrentTime = S.AddVariableText(
|
|
XO("Current selection length: dd:hh:mm:ss"));
|
|
mTotalTime = S.AddVariableText(XO("New selection length: dd:hh:mm:ss"));
|
|
}
|
|
S.EndMultiColumn();
|
|
}
|
|
|
|
bool EffectRepeat::TransferDataToWindow()
|
|
{
|
|
mRepeatCount->ChangeValue(wxString::Format(wxT("%d"), repeatCount));
|
|
|
|
DisplayNewTime();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool EffectRepeat::TransferDataFromWindow()
|
|
{
|
|
if (!mUIParent->Validate())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
long l;
|
|
|
|
mRepeatCount->GetValue().ToLong(&l);
|
|
|
|
repeatCount = (int) l;
|
|
|
|
return true;
|
|
}
|
|
|
|
void EffectRepeat::DisplayNewTime()
|
|
{
|
|
long l;
|
|
wxString str;
|
|
mRepeatCount->GetValue().ToLong(&l);
|
|
|
|
NumericConverter nc(NumericConverter::TIME,
|
|
GetSelectionFormat(),
|
|
mT1 - mT0,
|
|
mProjectRate);
|
|
|
|
str = wxString::Format( _("Current selection length: %s"), nc.GetString() );
|
|
|
|
mCurrentTime->SetLabel(str);
|
|
mCurrentTime->SetName(str); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
|
|
|
if (l > 0) {
|
|
EnableApply(true);
|
|
repeatCount = l;
|
|
|
|
nc.SetValue((mT1 - mT0) * (repeatCount + 1));
|
|
str = wxString::Format( _("New selection length: %s"), nc.GetString() );
|
|
}
|
|
else {
|
|
str = _("Warning: No repeats.");
|
|
EnableApply(false);
|
|
}
|
|
mTotalTime->SetLabel(str);
|
|
mTotalTime->SetName(str); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
|
}
|
|
|
|
void EffectRepeat::OnRepeatTextChange(wxCommandEvent & WXUNUSED(evt))
|
|
{
|
|
DisplayNewTime();
|
|
}
|