1
0
mirror of https://github.com/cookiengineer/audacity synced 2026-01-02 06:08:44 +01:00
Files
audacity/src/effects/Repeat.cpp
James Crook 466e9c179e Create ComponentInterface
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.
2018-11-02 17:04:43 +00:00

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();
}