mirror of
https://github.com/cookiengineer/audacity
synced 2026-01-02 06:08:44 +01:00
It combines the old IdentInterface with the ParamsInterface, providing an identifier and parameters (if needed). The main purpose of the change is to make the class hierarchy (as viewed via doxygen) much easier to follow.
249 lines
5.7 KiB
C++
249 lines
5.7 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 "../Audacity.h"
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <wx/intl.h>
|
|
|
|
#include "../LabelTrack.h"
|
|
#include "../ShuttleGui.h"
|
|
#include "../WaveTrack.h"
|
|
#include "../widgets/NumericTextCtrl.h"
|
|
#include "../widgets/valnum.h"
|
|
|
|
#include "Repeat.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 );
|
|
|
|
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 REPEAT_PLUGIN_SYMBOL;
|
|
}
|
|
|
|
wxString EffectRepeat::GetDescription()
|
|
{
|
|
return _("Repeats the selection the specified number of times");
|
|
}
|
|
|
|
wxString EffectRepeat::ManualPage()
|
|
{
|
|
return wxT("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);
|
|
{
|
|
IntegerValidator<int> vldRepeatCount(&repeatCount);
|
|
vldRepeatCount.SetRange(MIN_Count, 2147483647 / mProjectRate);
|
|
mRepeatCount = S.AddTextBox(_("Number of repeats to add:"), wxT(""), 12);
|
|
mRepeatCount->SetValidator(vldRepeatCount);
|
|
}
|
|
S.EndHorizontalLay();
|
|
|
|
S.StartMultiColumn(1, wxCENTER);
|
|
{
|
|
mCurrentTime = S.AddVariableText(_("Current selection length: dd:hh:mm:ss"));
|
|
mTotalTime = S.AddVariableText(_("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();
|
|
}
|