1
0
mirror of https://github.com/cookiengineer/audacity synced 2026-04-04 13:27:39 +02:00

Migrating the remaining effects

This brings the builtin, LV2, and VAMP effects inline with the
Audio Units, LADSPA, and VST effects.  All effects now share
a common UI.

This gives all effects (though not implemented for all):

User and factory preset capability
Preset import/export capability
Shared or private configuration options

Builtin effects can now be migrated to RTP, depending on algorithm.
LV2 effects now support graphical interfaces if the plugin supplies one.
Nyquist prompt enhanced to provide some features of the Nyquist Workbench.

It may not look like it, but this was a LOT of work, so trust me, there
WILL be problems and everything effect related should be suspect.  Keep
a sharp eye (or two) open.
This commit is contained in:
Leland Lucius
2015-04-16 22:53:42 -05:00
parent 40e6bcc56a
commit 8fbfa460c4
140 changed files with 17288 additions and 20367 deletions

View File

@@ -19,246 +19,150 @@
*//*******************************************************************/
#include "../Audacity.h"
#include <wx/defs.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/validate.h>
#include <wx/valtext.h>
#include <float.h>
#include <wx/generic/textdlgg.h>
#include <wx/intl.h>
#include <math.h>
#include "../widgets/valnum.h"
#include "Echo.h"
#include "../WaveTrack.h"
// Define keys, defaults, minimums, and maximums for the effect parameters
//
// Name Type Key Def Min Max Scale
Param( Delay, float, wxTRANSLATE("Delay"), 1.0, 0.0, FLT_MAX, 1 );
Param( Decay, float, wxTRANSLATE("Decay"), 0.5, 1.0, 1.0, 1 );
EffectEcho::EffectEcho()
{
delay = float(1.0);
decay = float(0.5);
delay = DEF_Delay;
decay = DEF_Decay;
}
wxString EffectEcho::GetEffectDescription() {
// Note: This is useful only after values have been set.
return wxString::Format(_("Applied effect: %s delay = %f seconds, decay factor = %f"),
this->GetEffectName().c_str(), delay, decay);
}
bool EffectEcho::PromptUser()
EffectEcho::~EffectEcho()
{
EchoDialog dlog(this, mParent);
dlog.delay = delay;
dlog.decay = decay;
dlog.CentreOnParent();
dlog.ShowModal();
}
if (dlog.GetReturnCode() == wxID_CANCEL)
return false;
// IdentInterface implementation
delay = dlog.delay;
decay = dlog.decay;
wxString EffectEcho::GetSymbol()
{
return ECHO_PLUGIN_SYMBOL;
}
wxString EffectEcho::GetDescription()
{
return wxTRANSLATE("Repeats the selected audio again and again");
}
// EffectIdentInterface implementation
EffectType EffectEcho::GetType()
{
return EffectTypeProcess;
}
// EffectClientInterface implementation
int EffectEcho::GetAudioInCount()
{
return 1;
}
int EffectEcho::GetAudioOutCount()
{
return 1;
}
bool EffectEcho::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames WXUNUSED(chanMap))
{
histPos = 0;
histLen = (sampleCount) (mSampleRate * delay);
history = new float[histLen];
memset(history, 0, sizeof(float) * histLen);
return history != NULL;
}
bool EffectEcho::ProcessFinalize()
{
delete [] history;
return true;
}
bool EffectEcho::TransferParameters( Shuttle & shuttle )
sampleCount EffectEcho::ProcessBlock(float **inBlock, float **outBlock, sampleCount blockLen)
{
shuttle.TransferFloat(wxT("Delay"),delay,1.0);
shuttle.TransferFloat(wxT("Decay"),decay,0.5);
return true;
}
float *ibuf = inBlock[0];
float *obuf = outBlock[0];
bool EffectEcho::Process()
{
this->CopyInputTracks(); // Set up mOutputTracks.
bool bGoodResult = true;
SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks);
WaveTrack *track = (WaveTrack *) iter.First();
int count = 0;
while (track) {
double trackStart = track->GetStartTime();
double trackEnd = track->GetEndTime();
double t0 = mT0 < trackStart? trackStart: mT0;
double t1 = mT1 > trackEnd? trackEnd: mT1;
if (t1 > t0) {
sampleCount start = track->TimeToLongSamples(t0);
sampleCount end = track->TimeToLongSamples(t1);
sampleCount len = (sampleCount)(end - start);
if (!ProcessOne(count, track, start, len))
{
bGoodResult = false;
break;
}
for (sampleCount i = 0; i < blockLen; i++, histPos++)
{
if (histPos == histLen)
{
histPos = 0;
}
track = (WaveTrack *) iter.Next();
count++;
history[histPos] = obuf[i] = ibuf[i] + history[histPos] * decay;
}
this->ReplaceProcessedTracks(bGoodResult);
return bGoodResult;
return blockLen;
}
bool EffectEcho::ProcessOne(int count, WaveTrack * track,
sampleCount start, sampleCount len)
bool EffectEcho::GetAutomationParameters(EffectAutomationParameters & parms)
{
sampleCount s = 0;
sampleCount blockSize = (sampleCount) (track->GetRate() * delay);
//do nothing if the delay is less than 1 sample or greater than
//the length of the selection
if (blockSize < 1 || blockSize > len)
return true;
float *buffer0 = new float[blockSize];
float *buffer1 = new float[blockSize];
float *ptr0 = buffer0;
float *ptr1 = buffer1;
bool first = true;
while (s < len) {
sampleCount block = blockSize;
if (s + block > len)
block = len - s;
track->Get((samplePtr)ptr0, floatSample, start + s, block);
if (!first) {
for (sampleCount i = 0; i < block; i++)
ptr0[i] += ptr1[i] * decay;
track->Set((samplePtr)ptr0, floatSample, start + s, block);
}
float *ptrtemp = ptr0;
ptr0 = ptr1;
ptr1 = ptrtemp;
first = false;
s += block;
if (TrackProgress(count, s / (double) len)) {
delete[]buffer0;
delete[]buffer1;
return false;
}
}
delete[]buffer0;
delete[]buffer1;
parms.WriteFloat(KEY_Delay, delay);
parms.WriteFloat(KEY_Decay, decay);
return true;
}
//----------------------------------------------------------------------------
// EchoDialog
//----------------------------------------------------------------------------
// event table for EchoDialog
BEGIN_EVENT_TABLE(EchoDialog, EffectDialog)
EVT_BUTTON(ID_EFFECT_PREVIEW, EchoDialog::OnPreview)
END_EVENT_TABLE()
EchoDialog::EchoDialog(EffectEcho * effect, wxWindow * parent)
: EffectDialog(parent, _("Echo"))
bool EffectEcho::SetAutomationParameters(EffectAutomationParameters & parms)
{
m_bLoopDetect = false;
m_pEffect = effect;
ReadAndVerifyFloat(Delay);
ReadAndVerifyFloat(Decay);
// NULL out these control members because there are some cases where the
// event table handlers get called during this method, and those handlers that
// can cause trouble check for NULL.
m_pTextCtrl_Delay = NULL;
m_pTextCtrl_Decay = NULL;
delay = Delay;
decay = Decay;
// effect parameters
delay = float(1.0);
decay = float(0.5);
// Initialize dialog
Init();
return true;
}
void EchoDialog::PopulateOrExchange(ShuttleGui & S)
void EffectEcho::PopulateOrExchange(ShuttleGui & S)
{
S.AddSpace(0, 5);
S.StartMultiColumn(2, wxALIGN_CENTER);
{
m_pTextCtrl_Delay = S.AddTextBox(_("Delay time (seconds):"),
wxT("1.0"),
10);
m_pTextCtrl_Delay->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
FloatingPointValidator<double> vldDelay(3, &delay, NUM_VAL_NO_TRAILING_ZEROES);
vldDelay.SetRange(MIN_Delay, MAX_Delay);
S.AddTextBox(_("Delay time (seconds):"), wxT(""), 10)->SetValidator(vldDelay);
m_pTextCtrl_Decay = S.AddTextBox(_("Decay factor:"),
wxT("0.5"),
10);
m_pTextCtrl_Decay->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
FloatingPointValidator<double> vldDecay(3, &decay, NUM_VAL_NO_TRAILING_ZEROES);
vldDecay.SetRange(MIN_Decay, MAX_Decay);
S.AddTextBox(_("Decay factor:"), wxT(""), 10)->SetValidator(vldDecay);
}
S.EndMultiColumn();
}
bool EchoDialog::TransferDataToWindow()
bool EffectEcho::TransferDataToWindow()
{
m_bLoopDetect = true;
wxString str;
if (m_pTextCtrl_Delay) {
str.Printf(wxT("%g"), delay);
m_pTextCtrl_Delay->SetValue(str);
}
if (m_pTextCtrl_Decay) {
str.Printf(wxT("%g"), decay);
m_pTextCtrl_Decay->SetValue(str);
if (!mUIParent->TransferDataToWindow())
{
return false;
}
m_bLoopDetect = false;
return true;
}
bool EchoDialog::TransferDataFromWindow()
bool EffectEcho::TransferDataFromWindow()
{
double newValue;
wxString str;
if (m_pTextCtrl_Delay) {
str = m_pTextCtrl_Delay->GetValue();
str.ToDouble(&newValue);
delay = (float)(newValue);
}
if (m_pTextCtrl_Decay) {
str = m_pTextCtrl_Decay->GetValue();
str.ToDouble(&newValue);
decay = (float)(newValue);
if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
{
return false;
}
return true;
}
// handler implementations for EchoDialog
void EchoDialog::OnPreview(wxCommandEvent & WXUNUSED(event))
{
TransferDataFromWindow();
// Save & restore parameters around Preview, because we didn't do OK.
float oldDelay = m_pEffect->delay;
float oldDecay = m_pEffect->decay;
m_pEffect->delay = delay;
m_pEffect->decay = decay;
m_pEffect->Preview();
m_pEffect->delay = oldDelay;
m_pEffect->decay = oldDecay;
}