1
0
mirror of https://github.com/cookiengineer/audacity synced 2026-02-16 07:47:58 +01: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

@@ -9,75 +9,253 @@
******************************************************************//**
\class EffectLeveller
\brief An EffectSimpleMono
*//***************************************************************//**
\class LevellerDialog
\brief Dialog for EffectLeveller
\brief An Effect
*//*******************************************************************/
#include "../Audacity.h"
// For compilers that support precompilation, includes "wx.h".
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
// Include your minimal set of headers here, or wx.h
#include <wx/wx.h>
#endif
#include <math.h>
#include <wx/choice.h>
#include <wx/intl.h>
#include <wx/valgen.h>
#include "../Prefs.h"
#include "Leveller.h"
enum kPasses
{
kLight,
kModerate,
kHeavy,
kHeavier,
kHeaviest,
kNumPasses
};
static const wxString kPassStrings[kNumPasses] =
{
/* i18n-hint: Of strength of an effect. Not strongly.*/
wxTRANSLATE("Light"),
wxTRANSLATE("Moderate"),
/* i18n-hint: Of strength of an effect. Strongly.*/
wxTRANSLATE("Heavy"),
wxTRANSLATE("Heavier"),
wxTRANSLATE("Heaviest"),
};
// Define keys, defaults, minimums, and maximums for the effect parameters
//
// Name Type Key Def Min Max Scale
Param( Level, int, wxTRANSLATE("dB"), 10, 0, Enums::NumDbChoices - 1, 1 );
Param( Passes, int, wxTRANSLATE("Passes"), kModerate, 0, kNumPasses - 1, 1 );
//
// EffectLeveller
//
EffectLeveller::EffectLeveller()
{
Init();
mPassIndex = DEF_Passes;
mDbIndex = DEF_Level;
mNumPasses = mPassIndex + 1;
mDbSilenceThreshold = Enums::Db2Signal[mDbIndex];
CalcLevellerFactors();
}
#define NUM_PASSES_CHOICES 5
bool EffectLeveller::Init()
EffectLeveller::~EffectLeveller()
{
mLevellerNumPasses = gPrefs->Read(wxT("/Effects/Leveller/LevellerNumPasses"), 2L) ;
if ((mLevellerNumPasses <= 0) || (mLevellerNumPasses > NUM_PASSES_CHOICES)) { // corrupted Prefs?
mLevellerNumPasses = 1;
gPrefs->Write(wxT("/Effects/Leveller/LevellerNumPasses"), 1);
}
mLevellerDbChoiceIndex = gPrefs->Read(wxT("/Effects/Leveller/LevellerDbChoiceIndex"), 10L);
if ((mLevellerDbChoiceIndex < 0) || (mLevellerDbChoiceIndex >= Enums::NumDbChoices)) { // corrupted Prefs?
mLevellerDbChoiceIndex = 0; //Least dB
gPrefs->Write(wxT("/Effects/Leveller/LevellerDbChoiceIndex"), mLevellerDbChoiceIndex);
}
gPrefs->Flush();
}
mLevellerDbSilenceThreshold = Enums::Db2Signal[mLevellerDbChoiceIndex];
// IdentInterface implementation
wxString EffectLeveller::GetSymbol()
{
return LEVELLER_PLUGIN_SYMBOL;
}
wxString EffectLeveller::GetDescription()
{
return wxTRANSLATE("Leveler is a simple, combined compressor and limiter effect for reducing the dynamic range of audio");
}
// EffectIdentInterface implementation
EffectType EffectLeveller::GetType()
{
return EffectTypeProcess;
}
// EffectClientInterface implementation
int EffectLeveller::GetAudioInCount()
{
return 1;
}
int EffectLeveller::GetAudioOutCount()
{
return 1;
}
sampleCount EffectLeveller::ProcessBlock(float **inBlock, float **outBlock, sampleCount blockLen)
{
float *ibuf = inBlock[0];
float *obuf = outBlock[0];
for (sampleCount i = 0; i < blockLen; i++)
{
float frame = ibuf[i];
for (int pass = 0; pass < mNumPasses; pass++)
{
frame = LevelOneFrame(frame);
}
obuf[i] = frame;
}
return blockLen;
}
bool EffectLeveller::GetAutomationParameters(EffectAutomationParameters & parms)
{
parms.Write(KEY_Level, Enums::DbChoices[mDbIndex]);
parms.Write(KEY_Passes, kPassStrings[mPassIndex]);
return true;
}
bool EffectLeveller::SetAutomationParameters(EffectAutomationParameters & parms)
{
// Allow for 2.1.0 and before
wxArrayString passChoices(kNumPasses, kPassStrings);
passChoices.Insert(wxT("1"), 0);
passChoices.Insert(wxT("2"), 1);
passChoices.Insert(wxT("3"), 2);
passChoices.Insert(wxT("4"), 3);
passChoices.Insert(wxT("5"), 4);
ReadAndVerifyEnum(Level, wxArrayString(Enums::NumDbChoices,Enums::GetDbChoices()));
ReadAndVerifyEnum(Passes, passChoices);
mDbIndex = Level;
mPassIndex = Passes;
// Readjust for 2.1.0 or before
if (mPassIndex >= kNumPasses)
{
mPassIndex -= kNumPasses;
}
mNumPasses = mPassIndex + 1;
mDbSilenceThreshold = Enums::Db2Signal[mDbIndex];
CalcLevellerFactors();
return true;
}
bool EffectLeveller::CheckWhetherSkipEffect()
// Effect implementation
bool EffectLeveller::Startup()
{
return mLevellerNumPasses == 0;
wxString base = wxT("/Effects/Leveller/");
// Migrate settings from 2.1.0 or before
// Already migrated, so bail
if (gPrefs->Exists(base + wxT("Migrated")))
{
return true;
}
// Load the old "current" settings
if (gPrefs->Exists(base))
{
mNumPasses = gPrefs->Read(base + wxT("LevellerNumPasses"), 2L);
if ((mNumPasses <= 0) || (mNumPasses > kNumPasses))
{ // corrupted Pr
mNumPasses = 1;
}
mDbIndex = gPrefs->Read(base + wxT("LevellerDbChoiceIndex"), 10L);
if ((mDbIndex < 0) || (mDbIndex >= Enums::NumDbChoices))
{ // cor
mDbIndex = 0; //Least dB
}
SaveUserPreset(GetCurrentSettingsGroup());
// Do not migrate again
gPrefs->Write(base + wxT("Migrated"), true);
gPrefs->Flush();
}
return true;
}
void EffectLeveller::End()
void EffectLeveller::PopulateOrExchange(ShuttleGui & S)
{
int frameSum = (int)mFrameSum;
gPrefs->Write(wxT("/Validate/LevellerFrameSum"), frameSum);
gPrefs->Flush();
wxASSERT(kNumPasses == WXSIZEOF(kPassStrings));
wxArrayString passChoices;
for (int i = 0; i < kNumPasses; i++)
{
passChoices.Add(wxGetTranslation(kPassStrings[i]));
}
wxArrayString dBChoices(Enums::NumDbChoices,Enums::GetDbChoices());
S.SetBorder(5);
S.StartVerticalLay();
{
S.AddSpace(5);
S.StartMultiColumn(2, wxALIGN_CENTER);
{
S.AddChoice(_("Degree of Leveling:"),
wxT(""),
&passChoices)->SetValidator(wxGenericValidator(&mPassIndex));
S.AddChoice(_("Noise Threshold:"),
wxT(""),
&dBChoices)->SetValidator(wxGenericValidator(&mDbIndex));
}
S.EndMultiColumn();
}
S.EndVerticalLay();
return;
}
bool EffectLeveller::TransferDataToWindow()
{
if (!mUIParent->TransferDataToWindow())
{
return false;
}
return true;
}
bool EffectLeveller::TransferDataFromWindow()
{
if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow())
{
return false;
}
mNumPasses = mPassIndex + 1;
mDbSilenceThreshold = Enums::Db2Signal[mDbIndex];
CalcLevellerFactors();
return true;
}
// EffectLeveller implementation
#define LEVELER_FACTORS 6
static double gLimit[LEVELER_FACTORS] = { 0.0001, 0.0, 0.1, 0.3, 0.5, 1.0 };
static double gAdjLimit[LEVELER_FACTORS];
@@ -87,8 +265,7 @@ static double gAdjFactor[LEVELER_FACTORS] = { 0.80, 1.00, 1.20, 1.20, 1.00, 0.80
void EffectLeveller::CalcLevellerFactors()
{
mFrameSum = 0.0;
gLimit[1] = mLevellerDbSilenceThreshold;
gLimit[1] = mDbSilenceThreshold;
int prev = 0;
double addOnValue = 0.0;
double prevLimit = 0.0;
@@ -113,40 +290,6 @@ void EffectLeveller::CalcLevellerFactors()
}
}
bool EffectLeveller::PromptUser()
{
LevellerDialog dlog(this, mParent);
dlog.mLevellerDbChoiceIndex = mLevellerDbChoiceIndex;
dlog.mLevellerNumPassesChoiceIndex = mLevellerNumPasses-1;
dlog.TransferDataToWindow();
dlog.CentreOnParent();
dlog.ShowModal();
if (dlog.GetReturnCode() == wxID_CANCEL) {
return false;
}
mLevellerNumPasses = dlog.mLevellerNumPassesChoiceIndex+1;
mLevellerDbChoiceIndex = dlog.mLevellerDbChoiceIndex;
mLevellerDbSilenceThreshold = Enums::Db2Signal[mLevellerDbChoiceIndex];
gPrefs->Write(wxT("/Effects/Leveller/LevellerDbChoiceIndex"), mLevellerDbChoiceIndex);
gPrefs->Write(wxT("/Effects/Leveller/LevellerNumPasses"), mLevellerNumPasses);
gPrefs->Flush();
CalcLevellerFactors();
return true;
}
bool EffectLeveller::TransferParameters( Shuttle & shuttle )
{
shuttle.TransferEnum(wxT("dB"),mLevellerDbChoiceIndex,Enums::NumDbChoices,Enums::GetDbChoices());
shuttle.TransferInt(wxT("Passes"),mLevellerNumPasses,1);
return true;
}
float EffectLeveller::LevelOneFrame(float frameInBuffer)
{
float curFrame;
@@ -161,7 +304,6 @@ float EffectLeveller::LevelOneFrame(float frameInBuffer)
curSign = 1.0;
}
fabsCurFrame = (float)fabs(curFrame);
mFrameSum += fabsCurFrame;
for (int f = 0; f < LEVELER_FACTORS; ++f) {
if (fabsCurFrame <= gLimit[f]) {
@@ -173,74 +315,3 @@ float EffectLeveller::LevelOneFrame(float frameInBuffer)
return (float)0.99;
}
bool EffectLeveller::ProcessSimpleMono(float *buffer, sampleCount len)
{
for (int pass = 0; pass < mLevellerNumPasses; ++pass) {
for (int i = 0; i < len; ++i) {
buffer[i] = LevelOneFrame(buffer[i]);
}
}
return true;
}
//----------------------------------------------------------------------------
// LevellerDialog
//----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(LevellerDialog, EffectDialog)
EVT_BUTTON(ID_EFFECT_PREVIEW, LevellerDialog::OnPreview)
END_EVENT_TABLE()
LevellerDialog::LevellerDialog(EffectLeveller *effect, wxWindow *parent)
: EffectDialog(parent, _("Leveler"), PROCESS_EFFECT), // Lynn called it "Leveller", but preferred spelling is "Leveler".
mEffect(effect)
{
mLevellerNumPassesChoiceIndex = 0;//
mLevellerDbChoiceIndex = 0;
Init();
}
void LevellerDialog::PopulateOrExchange(ShuttleGui & S)
{
wxArrayString db(Enums::NumDbChoices, Enums::GetDbChoices());
wxArrayString numPasses;
/* i18n-hint: Of strength of an effect. Not strongly.*/
numPasses.Add(_("Light"));
numPasses.Add(_("Moderate"));
/* i18n-hint: Of strength of an effect. Strongly.*/
numPasses.Add(_("Heavy"));
numPasses.Add(_("Heavier"));
numPasses.Add(_("Heaviest"));
S.SetBorder(5);
S.AddSpace(5);
S.StartMultiColumn(2);
{
S.TieChoice(_("Degree of Leveling:"),
mLevellerNumPassesChoiceIndex,
&numPasses);
S.TieChoice(_("Noise Threshold:"),
mLevellerDbChoiceIndex,
&db);
}
S.EndMultiColumn();
}
void LevellerDialog::OnPreview(wxCommandEvent & WXUNUSED(event))
{
TransferDataFromWindow();
// Save & restore parameters around Preview.
int oldLevellerDbChoiceIndex = mEffect->mLevellerDbChoiceIndex;
int oldLevellerNumPasses = mEffect->mLevellerNumPasses;
mEffect->mLevellerDbChoiceIndex = mLevellerDbChoiceIndex;
mEffect->mLevellerNumPasses = mLevellerNumPassesChoiceIndex+1;
mEffect->Preview();
mEffect->mLevellerDbChoiceIndex = oldLevellerDbChoiceIndex;
mEffect->mLevellerNumPasses = oldLevellerNumPasses;
}