mirror of
https://github.com/cookiengineer/audacity
synced 2025-12-12 15:46:25 +01:00
Locate and position the current Audacity source code, and clear a variety of old junk out of the way into junk-branches
This commit is contained in:
900
src/effects/ladspa/LadspaEffect.cpp
Normal file
900
src/effects/ladspa/LadspaEffect.cpp
Normal file
@@ -0,0 +1,900 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
LadspaEffect.cpp
|
||||
|
||||
Dominic Mazzoni
|
||||
|
||||
This class implements a Ladspa Plug-in effect.
|
||||
|
||||
*******************************************************************//**
|
||||
|
||||
\class LadspaEffect
|
||||
\brief An Effect that calls up a LADSPA plug in, i.e. many possible
|
||||
effects from this one class.
|
||||
|
||||
*//****************************************************************//**
|
||||
|
||||
\class LadspaEffectDialog
|
||||
\brief Dialog used with Effect
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
|
||||
#include "../Audacity.h"
|
||||
|
||||
#include "ladspa.h"
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/intl.h>
|
||||
#include <wx/scrolwin.h>
|
||||
|
||||
#include "../Effect.h" // Audacity Effect base class
|
||||
#include "LadspaEffect.h" // This class's header file
|
||||
#include "../Internat.h"
|
||||
|
||||
LadspaEffect::LadspaEffect(const LADSPA_Descriptor *data,
|
||||
const std::set<wxString>& categories)
|
||||
: mCategories(categories) {
|
||||
|
||||
mData = data;
|
||||
pluginName = LAT1CTOWX(mData->Name);
|
||||
|
||||
fInBuffer = NULL;
|
||||
fOutBuffer = NULL;
|
||||
|
||||
inputs = 0;
|
||||
outputs = 0;
|
||||
numInputControls = 0;
|
||||
mLength = 0;
|
||||
|
||||
unsigned long p;
|
||||
|
||||
inputPorts = new unsigned long [mData->PortCount];
|
||||
outputPorts = new unsigned long [mData->PortCount];
|
||||
inputControls = new float [mData->PortCount];
|
||||
outputControls = new float [mData->PortCount];
|
||||
|
||||
for(p=0; p<mData->PortCount; p++) {
|
||||
LADSPA_PortDescriptor d = mData->PortDescriptors[p];
|
||||
if (LADSPA_IS_PORT_AUDIO(d)) {
|
||||
if (LADSPA_IS_PORT_INPUT(d)) {
|
||||
inputPorts[inputs] = p;
|
||||
inputs++;
|
||||
}
|
||||
else if (LADSPA_IS_PORT_OUTPUT(d)) {
|
||||
outputPorts[outputs] = p;
|
||||
outputs++;
|
||||
}
|
||||
}
|
||||
if (LADSPA_IS_PORT_CONTROL(d) &&
|
||||
LADSPA_IS_PORT_INPUT(d)) {
|
||||
numInputControls++;
|
||||
|
||||
float val = float(1.0);
|
||||
LADSPA_PortRangeHint hint = mData->PortRangeHints[p];
|
||||
|
||||
if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) &&
|
||||
val < hint.LowerBound)
|
||||
val = hint.LowerBound;
|
||||
|
||||
if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) &&
|
||||
val > hint.UpperBound)
|
||||
val = hint.UpperBound;
|
||||
|
||||
if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint.HintDescriptor))
|
||||
val = hint.LowerBound;
|
||||
|
||||
if (LADSPA_IS_HINT_DEFAULT_LOW(hint.HintDescriptor))
|
||||
val = hint.LowerBound * 0.75f + hint.UpperBound * 0.25f;
|
||||
|
||||
if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint.HintDescriptor))
|
||||
val = hint.LowerBound * 0.5f + hint.UpperBound * 0.5f;
|
||||
|
||||
if (LADSPA_IS_HINT_DEFAULT_HIGH(hint.HintDescriptor))
|
||||
val = hint.LowerBound * 0.25f + hint.UpperBound * 0.75f;
|
||||
|
||||
if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint.HintDescriptor))
|
||||
val = hint.UpperBound;
|
||||
|
||||
if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor))
|
||||
val *= mProjectRate;
|
||||
|
||||
if (LADSPA_IS_HINT_DEFAULT_0(hint.HintDescriptor))
|
||||
val = 0.0f;
|
||||
|
||||
if (LADSPA_IS_HINT_DEFAULT_1(hint.HintDescriptor))
|
||||
val = 1.0f;
|
||||
|
||||
if (LADSPA_IS_HINT_DEFAULT_100(hint.HintDescriptor))
|
||||
val = 100.0f;
|
||||
|
||||
if (LADSPA_IS_HINT_DEFAULT_440(hint.HintDescriptor))
|
||||
val = 440.0f;
|
||||
|
||||
inputControls[p] = val;
|
||||
}
|
||||
}
|
||||
|
||||
int flags = PLUGIN_EFFECT;
|
||||
if (inputs == 0)
|
||||
flags |= INSERT_EFFECT;
|
||||
else if (outputs == 0)
|
||||
flags |= ANALYZE_EFFECT;
|
||||
else
|
||||
flags |= PROCESS_EFFECT;
|
||||
|
||||
SetEffectFlags(flags);
|
||||
}
|
||||
|
||||
LadspaEffect::~LadspaEffect()
|
||||
{
|
||||
delete[] inputPorts;
|
||||
delete[] outputPorts;
|
||||
delete[] inputControls;
|
||||
delete[] outputControls;
|
||||
}
|
||||
|
||||
wxString LadspaEffect::GetEffectName()
|
||||
{
|
||||
if (numInputControls > 0)
|
||||
return pluginName + wxT("...");
|
||||
else
|
||||
return pluginName;
|
||||
}
|
||||
|
||||
std::set<wxString> LadspaEffect::GetEffectCategories()
|
||||
{
|
||||
return mCategories;
|
||||
}
|
||||
|
||||
wxString LadspaEffect::GetEffectIdentifier()
|
||||
{
|
||||
wxStringTokenizer st(pluginName, wxT(" "));
|
||||
wxString id;
|
||||
|
||||
// CamelCase the name
|
||||
while (st.HasMoreTokens()) {
|
||||
wxString tok = st.GetNextToken();
|
||||
|
||||
id += tok.Left(1).MakeUpper() + tok.Mid(1);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
wxString LadspaEffect::GetEffectAction()
|
||||
{
|
||||
return wxString::Format(_("Performing Effect: %s"),
|
||||
pluginName.c_str());
|
||||
}
|
||||
|
||||
bool LadspaEffect::Init()
|
||||
{
|
||||
mBlockSize = 0;
|
||||
mainRate = 0;
|
||||
|
||||
TrackListOfKindIterator iter(Track::Wave, mTracks);
|
||||
Track *left = iter.First();
|
||||
while(left) {
|
||||
if (mainRate == 0)
|
||||
mainRate = (int)(((WaveTrack *)left)->GetRate() + 0.5);
|
||||
|
||||
if (left->GetLinked()) {
|
||||
Track *right = iter.Next();
|
||||
|
||||
if (((WaveTrack *)left)->GetRate() !=
|
||||
((WaveTrack *)right)->GetRate()) {
|
||||
wxMessageBox(_("Sorry, Plug-in Effects cannot be performed on stereo tracks where the individual channels of the track do not match."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
left = iter.Next();
|
||||
}
|
||||
|
||||
if (mainRate<=0)
|
||||
mainRate = (int)(mProjectRate + 0.5);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LadspaEffect::PromptUser()
|
||||
{
|
||||
if (numInputControls > 0) {
|
||||
double length = mT1 > mT0 ? mT1 - mT0 : sDefaultGenerateLen;
|
||||
|
||||
LadspaEffectDialog dlog(this, mParent, mData, inputControls, mainRate, length);
|
||||
dlog.CentreOnParent();
|
||||
dlog.ShowModal();
|
||||
|
||||
if (!dlog.GetReturnCode())
|
||||
return false;
|
||||
|
||||
mLength = dlog.GetLength();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LadspaEffect::Process()
|
||||
{
|
||||
this->CopyInputTracks(); // Set up mOutputTracks.
|
||||
bool bGoodResult = true;
|
||||
|
||||
TrackListIterator iter(mOutputTracks);
|
||||
int count = 0;
|
||||
Track *left = iter.First();
|
||||
Track *right;
|
||||
while(left) {
|
||||
sampleCount lstart = 0, rstart = 0;
|
||||
sampleCount len;
|
||||
GetSamples((WaveTrack *)left, &lstart, &len);
|
||||
|
||||
right = NULL;
|
||||
if (left->GetLinked() && inputs>1) {
|
||||
right = iter.Next();
|
||||
GetSamples((WaveTrack *)right, &rstart, &len);
|
||||
}
|
||||
|
||||
if (inputs < 2 && right) {
|
||||
// If the effect is mono, apply to each channel separately
|
||||
|
||||
bGoodResult = ProcessStereo(count, (WaveTrack *)left, NULL,
|
||||
lstart, 0, len) &&
|
||||
ProcessStereo(count, (WaveTrack *)right, NULL,
|
||||
rstart, 0, len);
|
||||
}
|
||||
else bGoodResult = ProcessStereo(count,
|
||||
(WaveTrack *)left, (WaveTrack *)right,
|
||||
lstart, rstart, len);
|
||||
if (!bGoodResult)
|
||||
break;
|
||||
|
||||
left = iter.Next();
|
||||
count++;
|
||||
}
|
||||
|
||||
this->ReplaceProcessedTracks(bGoodResult);
|
||||
return bGoodResult;
|
||||
}
|
||||
|
||||
bool LadspaEffect::ProcessStereo(int count, WaveTrack *left, WaveTrack *right,
|
||||
sampleCount lstart,
|
||||
sampleCount rstart,
|
||||
sampleCount len)
|
||||
{
|
||||
/* Allocate buffers */
|
||||
if (mBlockSize == 0) {
|
||||
mBlockSize = left->GetMaxBlockSize() * 2;
|
||||
|
||||
fInBuffer = new float *[inputs];
|
||||
unsigned long i;
|
||||
for (i = 0; i < inputs; i++)
|
||||
fInBuffer[i] = new float[mBlockSize];
|
||||
fOutBuffer = new float *[outputs];
|
||||
for (i = 0; i < outputs; i++)
|
||||
fOutBuffer[i] = new float[mBlockSize];
|
||||
}
|
||||
|
||||
/* Instantiate the plugin */
|
||||
|
||||
unsigned long rate = (unsigned long)(left->GetRate() + 0.5);
|
||||
LADSPA_Handle handle = mData->instantiate(mData, rate);
|
||||
|
||||
unsigned long p;
|
||||
for(p=0; p<inputs; p++) {
|
||||
mData->connect_port(handle, inputPorts[p], fInBuffer[p]);
|
||||
}
|
||||
for(p=0; p<outputs; p++) {
|
||||
mData->connect_port(handle, outputPorts[p], fOutBuffer[p]);
|
||||
}
|
||||
|
||||
for(p=0; p<mData->PortCount; p++) {
|
||||
LADSPA_PortDescriptor d = mData->PortDescriptors[p];
|
||||
if (LADSPA_IS_PORT_CONTROL(d)) {
|
||||
if (LADSPA_IS_PORT_INPUT(d)) {
|
||||
mData->connect_port(handle, p, &inputControls[p]);
|
||||
}
|
||||
else
|
||||
mData->connect_port(handle, p, &outputControls[p]);
|
||||
}
|
||||
}
|
||||
|
||||
if (mData->activate)
|
||||
mData->activate(handle);
|
||||
|
||||
// Actually perform the effect here
|
||||
|
||||
sampleCount originalLen = len;
|
||||
sampleCount ls = lstart;
|
||||
sampleCount rs = rstart;
|
||||
while (len) {
|
||||
int block = mBlockSize;
|
||||
if (block > len)
|
||||
block = len;
|
||||
|
||||
if (left && inputs > 0) {
|
||||
left->Get((samplePtr)fInBuffer[0], floatSample, ls, block);
|
||||
}
|
||||
if (right && inputs > 1) {
|
||||
right->Get((samplePtr)fInBuffer[1], floatSample, rs, block);
|
||||
}
|
||||
|
||||
mData->run(handle, block);
|
||||
|
||||
if (left && outputs > 0) {
|
||||
left->Set((samplePtr)fOutBuffer[0], floatSample, ls, block);
|
||||
}
|
||||
|
||||
if (right && outputs > 1) {
|
||||
right->Set((samplePtr)fOutBuffer[1], floatSample, rs, block);
|
||||
}
|
||||
|
||||
len -= block;
|
||||
ls += block;
|
||||
rs += block;
|
||||
|
||||
if (inputs > 1) {
|
||||
if (TrackGroupProgress(count, (ls-lstart)/(double)originalLen))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (TrackProgress(count, (ls-lstart)/(double)originalLen))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mData->deactivate)
|
||||
mData->deactivate(handle);
|
||||
|
||||
if (mData->cleanup)
|
||||
mData->cleanup(handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LadspaEffect::End()
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
if (fInBuffer) {
|
||||
for (i = 0; i < inputs; i++) {
|
||||
if (fInBuffer[i]) {
|
||||
delete [] fInBuffer[i];
|
||||
}
|
||||
}
|
||||
delete [] fInBuffer;
|
||||
fInBuffer = NULL;
|
||||
}
|
||||
|
||||
if (fOutBuffer) {
|
||||
for (i = 0; i < outputs; i++) {
|
||||
if (fOutBuffer[i]) {
|
||||
delete [] fOutBuffer[i];
|
||||
}
|
||||
}
|
||||
delete [] fOutBuffer;
|
||||
fOutBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
class Slider:public wxSlider
|
||||
{
|
||||
public:
|
||||
Slider(wxWindow *parent, wxWindowID id,
|
||||
int value, int minValue, int maxValue,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxSL_HORIZONTAL,
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxSliderNameStr)
|
||||
: wxSlider(parent, id, value, minValue, maxValue,
|
||||
pos, size, style, validator, name)
|
||||
{
|
||||
};
|
||||
|
||||
void OnSetFocus(wxFocusEvent &event)
|
||||
{
|
||||
wxScrolledWindow *p = (wxScrolledWindow *) GetParent();
|
||||
wxRect r = GetRect();
|
||||
wxRect rv = p->GetRect();
|
||||
rv.y = 0;
|
||||
|
||||
event.Skip();
|
||||
|
||||
int y;
|
||||
int yppu;
|
||||
p->GetScrollPixelsPerUnit(NULL, &yppu);
|
||||
|
||||
if (r.y >= rv.y && r.GetBottom() <= rv.GetBottom()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (r.y < rv.y) {
|
||||
p->CalcUnscrolledPosition(0, r.y, NULL, &r.y);
|
||||
y = r.y / yppu;
|
||||
}
|
||||
else {
|
||||
p->CalcUnscrolledPosition(0, r.y, NULL, &r.y);
|
||||
y = (r.GetBottom() - rv.GetBottom() + yppu) / yppu;
|
||||
}
|
||||
|
||||
p->Scroll(-1, y);
|
||||
};
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(Slider, wxSlider)
|
||||
EVT_SET_FOCUS(Slider::OnSetFocus)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
class TextCtrl:public wxTextCtrl
|
||||
{
|
||||
public:
|
||||
TextCtrl(wxWindow *parent, wxWindowID id,
|
||||
const wxString& value = wxEmptyString,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize, long style = 0,
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxTextCtrlNameStr)
|
||||
: wxTextCtrl(parent, id, value,
|
||||
pos, size, style, validator, name)
|
||||
{
|
||||
};
|
||||
|
||||
void OnSetFocus(wxFocusEvent &event)
|
||||
{
|
||||
wxScrolledWindow *p = (wxScrolledWindow *) GetParent();
|
||||
wxRect r = GetRect();
|
||||
wxRect rv = p->GetRect();
|
||||
rv.y = 0;
|
||||
|
||||
event.Skip();
|
||||
|
||||
int y;
|
||||
int yppu;
|
||||
p->GetScrollPixelsPerUnit(NULL, &yppu);
|
||||
|
||||
if (r.y >= rv.y && r.GetBottom() <= rv.GetBottom()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (r.y < rv.y) {
|
||||
p->CalcUnscrolledPosition(0, r.y, NULL, &r.y);
|
||||
y = r.y / yppu;
|
||||
}
|
||||
else {
|
||||
p->CalcUnscrolledPosition(0, r.y, NULL, &r.y);
|
||||
y = (r.GetBottom() - rv.GetBottom() + yppu) / yppu;
|
||||
}
|
||||
|
||||
p->Scroll(-1, y);
|
||||
};
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(TextCtrl, wxTextCtrl)
|
||||
EVT_SET_FOCUS(TextCtrl::OnSetFocus)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
const int LADSPA_SECONDS_ID = 13101;
|
||||
|
||||
BEGIN_EVENT_TABLE(LadspaEffectDialog, wxDialog)
|
||||
EVT_BUTTON(wxID_OK, LadspaEffectDialog::OnOK)
|
||||
EVT_BUTTON(wxID_CANCEL, LadspaEffectDialog::OnCancel)
|
||||
EVT_BUTTON(ID_EFFECT_PREVIEW, LadspaEffectDialog::OnPreview)
|
||||
EVT_SLIDER(wxID_ANY, LadspaEffectDialog::OnSlider)
|
||||
EVT_TEXT(wxID_ANY, LadspaEffectDialog::OnTextCtrl)
|
||||
EVT_CHECKBOX(wxID_ANY, LadspaEffectDialog::OnCheckBox)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
IMPLEMENT_CLASS(LadspaEffectDialog, wxDialog)
|
||||
|
||||
LadspaEffectDialog::LadspaEffectDialog(LadspaEffect *eff,
|
||||
wxWindow * parent,
|
||||
const LADSPA_Descriptor *data,
|
||||
float *inputControls,
|
||||
int sampleRate,
|
||||
double length)
|
||||
:wxDialog(parent, -1, LAT1CTOWX(data->Name),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||
effect(eff)
|
||||
{
|
||||
mLength = length;
|
||||
numParams = 0;
|
||||
this->mData = data;
|
||||
this->inputControls = inputControls;
|
||||
this->sampleRate = sampleRate;
|
||||
#ifdef __WXMSW__
|
||||
// On Windows, for some reason, wxWidgets calls OnTextCtrl during creation
|
||||
// of the text control, and LadspaEffectDialog::OnTextCtrl calls HandleText,
|
||||
// which assumes all the fields have been initialized.
|
||||
// This can give us a bad pointer crash, so manipulate inSlider to
|
||||
// no-op HandleText during creation.
|
||||
inSlider = true;
|
||||
#else
|
||||
inSlider = false;
|
||||
#endif
|
||||
inText = false;
|
||||
|
||||
toggles = new wxCheckBox*[mData->PortCount];
|
||||
sliders = new wxSlider*[mData->PortCount];
|
||||
fields = new wxTextCtrl*[mData->PortCount];
|
||||
labels = new wxStaticText*[mData->PortCount];
|
||||
ports = new unsigned long [mData->PortCount];
|
||||
|
||||
unsigned long p;
|
||||
for(p=0; p<mData->PortCount; p++) {
|
||||
LADSPA_PortDescriptor d = mData->PortDescriptors[p];
|
||||
if (LADSPA_IS_PORT_CONTROL(d) &&
|
||||
LADSPA_IS_PORT_INPUT(d)) {
|
||||
ports[numParams] = p;
|
||||
numParams++;
|
||||
}
|
||||
}
|
||||
|
||||
wxControl *item;
|
||||
|
||||
wxBoxSizer *vSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
if (mData->Maker &&
|
||||
mData->Maker[0] &&
|
||||
LAT1CTOWX(mData->Maker) != wxString(_("None"))) {
|
||||
item = new wxStaticText(this, 0,
|
||||
wxString(_("Author: "))+LAT1CTOWX(mData->Maker));
|
||||
vSizer->Add(item, 0, wxALL, 5);
|
||||
}
|
||||
|
||||
if (mData->Copyright &&
|
||||
mData->Copyright[0] &&
|
||||
LAT1CTOWX(mData->Copyright) != wxString(_("None"))) {
|
||||
|
||||
item = new wxStaticText(this, 0,
|
||||
LAT1CTOWX(mData->Copyright));
|
||||
vSizer->Add(item, 0, wxALL, 5);
|
||||
}
|
||||
|
||||
wxScrolledWindow *w = new wxScrolledWindow(this,
|
||||
wxID_ANY,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxVSCROLL | wxTAB_TRAVERSAL);
|
||||
|
||||
// Try to give the window a sensible default/minimum size
|
||||
w->SetMinSize(wxSize(
|
||||
wxMax(600, parent->GetSize().GetWidth() * 2/3),
|
||||
parent->GetSize().GetHeight() / 2));
|
||||
|
||||
w->SetScrollRate(0, 20);
|
||||
vSizer->Add(w, 1, wxEXPAND|wxALL, 5);
|
||||
|
||||
// Preview, OK, & Cancel buttons
|
||||
vSizer->Add(CreateStdButtonSizer(this, ePreviewButton|eCancelButton|eOkButton), 0, wxEXPAND);
|
||||
|
||||
SetSizer(vSizer);
|
||||
|
||||
wxSizer *paramSizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, w, _("Effect Settings"));
|
||||
|
||||
wxFlexGridSizer *gridSizer =
|
||||
new wxFlexGridSizer(5, 0, 0);
|
||||
gridSizer->AddGrowableCol(3);
|
||||
|
||||
for (p = 0; p < numParams; p++) {
|
||||
wxString labelText = LAT1CTOWX(mData->PortNames[ports[p]]);
|
||||
item = new wxStaticText(w, 0, labelText + wxT(":"));
|
||||
gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
|
||||
|
||||
wxString fieldText;
|
||||
LADSPA_PortRangeHint hint = mData->PortRangeHints[ports[p]];
|
||||
|
||||
if (LADSPA_IS_HINT_TOGGLED(hint.HintDescriptor)) {
|
||||
toggles[p] = new wxCheckBox(w, p, wxT(""));
|
||||
toggles[p]->SetName(labelText);
|
||||
toggles[p]->SetValue(inputControls[ports[p]] > 0);
|
||||
gridSizer->Add(toggles[p], 0, wxALL, 5);
|
||||
ConnectFocus(toggles[p]);
|
||||
|
||||
gridSizer->Add(1, 1, 0);
|
||||
gridSizer->Add(1, 1, 0);
|
||||
gridSizer->Add(1, 1, 0);
|
||||
}
|
||||
else {
|
||||
if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor))
|
||||
fieldText.Printf(wxT("%d"), (int)(inputControls[ports[p]] + 0.5));
|
||||
else
|
||||
fieldText = Internat::ToDisplayString(inputControls[ports[p]]);
|
||||
|
||||
fields[p] = new wxTextCtrl(w, p, fieldText);
|
||||
fields[p]->SetName(labelText);
|
||||
gridSizer->Add(fields[p], 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
ConnectFocus(fields[p]);
|
||||
|
||||
wxString bound;
|
||||
double lower = 0.0;
|
||||
double upper = 0.0;
|
||||
bool haslo = false;
|
||||
bool hashi = false;
|
||||
bool forceint = false;
|
||||
|
||||
if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) {
|
||||
lower = hint.LowerBound;
|
||||
haslo = true;
|
||||
}
|
||||
if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) {
|
||||
upper = hint.UpperBound;
|
||||
hashi = true;
|
||||
}
|
||||
if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor)) {
|
||||
lower *= sampleRate * 1000;
|
||||
upper *= sampleRate;
|
||||
forceint = true;
|
||||
}
|
||||
|
||||
wxString str;
|
||||
if (haslo) {
|
||||
if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
|
||||
str.Printf(wxT("%d"), (int)(lower + 0.5));
|
||||
else
|
||||
str = Internat::ToDisplayString(lower);
|
||||
item = new wxStaticText(w, 0, str);
|
||||
gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
|
||||
}
|
||||
else {
|
||||
gridSizer->Add(1, 1, 0);
|
||||
}
|
||||
|
||||
sliders[p] =
|
||||
new wxSlider(w, p,
|
||||
0, 0, 1000,
|
||||
wxDefaultPosition,
|
||||
wxSize(200, -1));
|
||||
sliders[p]->SetName(labelText);
|
||||
gridSizer->Add(sliders[p], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5);
|
||||
ConnectFocus(sliders[p]);
|
||||
|
||||
if (hashi) {
|
||||
if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
|
||||
str.Printf(wxT("%d"), (int)(upper + 0.5));
|
||||
else
|
||||
str = Internat::ToDisplayString(upper);
|
||||
item = new wxStaticText(w, 0, str);
|
||||
gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 5);
|
||||
}
|
||||
else {
|
||||
gridSizer->Add(1, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now add the length control
|
||||
if (effect->GetEffectFlags() & INSERT_EFFECT) {
|
||||
item = new wxStaticText(w, 0, _("Length (seconds)"));
|
||||
gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
mSeconds = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(length));
|
||||
mSeconds->SetName(_("Length (seconds)"));
|
||||
gridSizer->Add(mSeconds, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
gridSizer->Add(1, 1, 0);
|
||||
gridSizer->Add(1, 1, 0);
|
||||
gridSizer->Add(1, 1, 0);
|
||||
ConnectFocus(mSeconds);
|
||||
}
|
||||
|
||||
// Set all of the sliders based on the value in the
|
||||
// text fields
|
||||
inSlider = false; // Now we're ready for HandleText to actually do something.
|
||||
HandleText();
|
||||
|
||||
paramSizer->Add(gridSizer, 1, wxEXPAND | wxALL, 5);
|
||||
w->SetSizer(paramSizer);
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
SetSizeHints(GetSize());
|
||||
}
|
||||
|
||||
LadspaEffectDialog::~LadspaEffectDialog()
|
||||
{
|
||||
delete[]toggles;
|
||||
delete[]sliders;
|
||||
delete[]fields;
|
||||
delete[]labels;
|
||||
delete[]ports;
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::OnCheckBox(wxCommandEvent &event)
|
||||
{
|
||||
int p = event.GetId();
|
||||
|
||||
inputControls[ports[p]] = toggles[p]->GetValue();
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::OnSlider(wxCommandEvent &event)
|
||||
{
|
||||
int p = event.GetId();
|
||||
|
||||
// if we don't add the following three lines, changing
|
||||
// the value of the slider will change the text, which
|
||||
// will change the slider, and so on. This gets rid of
|
||||
// the implicit loop.
|
||||
if (inText)
|
||||
return;
|
||||
inSlider = true;
|
||||
|
||||
float val;
|
||||
float lower = float(0.0);
|
||||
float upper = float(10.0);
|
||||
float range;
|
||||
bool forceint = false;
|
||||
|
||||
LADSPA_PortRangeHint hint = mData->PortRangeHints[ports[p]];
|
||||
if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor))
|
||||
lower = hint.LowerBound;
|
||||
if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor))
|
||||
upper = hint.UpperBound;
|
||||
if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor)) {
|
||||
lower *= sampleRate;
|
||||
upper *= sampleRate;
|
||||
forceint = true;
|
||||
}
|
||||
|
||||
range = upper - lower;
|
||||
|
||||
val = (sliders[p]->GetValue() / 1000.0) * range + lower;
|
||||
|
||||
wxString str;
|
||||
if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
|
||||
str.Printf(wxT("%d"), (int)(val + 0.5));
|
||||
else
|
||||
str = Internat::ToDisplayString(val);
|
||||
|
||||
fields[p]->SetValue(str);
|
||||
|
||||
inputControls[ports[p]] = val;
|
||||
|
||||
inSlider = false;
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::OnTextCtrl(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
HandleText();
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::HandleText()
|
||||
{
|
||||
// if we don't add the following three lines, changing
|
||||
// the value of the slider will change the text, which
|
||||
// will change the slider, and so on. This gets rid of
|
||||
// the implicit loop.
|
||||
|
||||
if (inSlider)
|
||||
return;
|
||||
inText = true;
|
||||
for (unsigned long p = 0; p < numParams; p++) {
|
||||
double dval;
|
||||
float val;
|
||||
float lower = float(0.0);
|
||||
float upper = float(10.0);
|
||||
float range;
|
||||
|
||||
LADSPA_PortRangeHint hint = mData->PortRangeHints[ports[p]];
|
||||
if (LADSPA_IS_HINT_TOGGLED(hint.HintDescriptor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dval = Internat::CompatibleToDouble(fields[p]->GetValue());
|
||||
val = dval;
|
||||
|
||||
if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor))
|
||||
lower = hint.LowerBound;
|
||||
if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor))
|
||||
upper = hint.UpperBound;
|
||||
if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor)) {
|
||||
lower *= sampleRate;
|
||||
upper *= sampleRate;
|
||||
}
|
||||
range = upper - lower;
|
||||
|
||||
if (val < lower)
|
||||
val = lower;
|
||||
if (val > upper)
|
||||
val = upper;
|
||||
|
||||
inputControls[ports[p]] = val;
|
||||
|
||||
sliders[p]->SetValue((int)(((val-lower)/range) * 1000.0 + 0.5));
|
||||
}
|
||||
|
||||
inText = false;
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::OnOK(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
EndModal(TRUE);
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
EndModal(FALSE);
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::OnPreview(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
effect->Preview();
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::ConnectFocus(wxControl *c)
|
||||
{
|
||||
c->GetEventHandler()->Connect(wxEVT_SET_FOCUS,
|
||||
wxFocusEventHandler(LadspaEffectDialog::ControlSetFocus));
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::DisconnectFocus(wxControl *c)
|
||||
{
|
||||
c->GetEventHandler()->Disconnect(wxEVT_SET_FOCUS,
|
||||
wxFocusEventHandler(LadspaEffectDialog::ControlSetFocus));
|
||||
}
|
||||
|
||||
void LadspaEffectDialog::ControlSetFocus(wxFocusEvent &event)
|
||||
{
|
||||
wxControl *c = (wxControl *) event.GetEventObject();
|
||||
wxScrolledWindow *p = (wxScrolledWindow *) c->GetParent();
|
||||
wxRect r = c->GetRect();
|
||||
wxRect rv = p->GetRect();
|
||||
rv.y = 0;
|
||||
|
||||
event.Skip();
|
||||
|
||||
int y;
|
||||
int yppu;
|
||||
p->GetScrollPixelsPerUnit(NULL, &yppu);
|
||||
|
||||
if (r.y >= rv.y && r.GetBottom() <= rv.GetBottom()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (r.y < rv.y) {
|
||||
p->CalcUnscrolledPosition(0, r.y, NULL, &r.y);
|
||||
y = r.y / yppu;
|
||||
}
|
||||
else {
|
||||
p->CalcUnscrolledPosition(0, r.y, NULL, &r.y);
|
||||
y = (r.GetBottom() - rv.GetBottom() + yppu) / yppu;
|
||||
}
|
||||
|
||||
p->Scroll(-1, y);
|
||||
};
|
||||
|
||||
double LadspaEffectDialog::GetLength()
|
||||
{
|
||||
if (effect->GetEffectFlags() & INSERT_EFFECT) {
|
||||
mLength = Internat::CompatibleToDouble(mSeconds->GetValue());
|
||||
}
|
||||
|
||||
return mLength;
|
||||
}
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 7e4a0346-c3ec-45de-9f71-818c6e34a094
|
||||
|
||||
126
src/effects/ladspa/LadspaEffect.h
Normal file
126
src/effects/ladspa/LadspaEffect.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
LadspaEffect.h
|
||||
|
||||
Dominic Mazzoni
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
class wxSlider;
|
||||
class wxStaticText;
|
||||
class wxTextCtrl;
|
||||
class wxCheckBox;
|
||||
|
||||
#include <wx/dialog.h>
|
||||
|
||||
#include "../Effect.h"
|
||||
#include "ladspa.h"
|
||||
|
||||
void LoadLadspaPlugins();
|
||||
|
||||
class LadspaEffect:public Effect {
|
||||
|
||||
public:
|
||||
|
||||
LadspaEffect(const LADSPA_Descriptor *data,
|
||||
const std::set<wxString>& categories = std::set<wxString>());
|
||||
virtual ~LadspaEffect();
|
||||
|
||||
virtual wxString GetEffectName();
|
||||
|
||||
virtual std::set<wxString> GetEffectCategories();
|
||||
|
||||
virtual wxString GetEffectIdentifier();
|
||||
|
||||
virtual wxString GetEffectAction();
|
||||
|
||||
virtual bool Init();
|
||||
|
||||
virtual bool PromptUser();
|
||||
|
||||
virtual bool Process();
|
||||
|
||||
virtual void End();
|
||||
|
||||
private:
|
||||
bool ProcessStereo(int count, WaveTrack * left, WaveTrack *right,
|
||||
sampleCount lstart, sampleCount rstart,
|
||||
sampleCount len);
|
||||
|
||||
wxString pluginName;
|
||||
|
||||
const LADSPA_Descriptor *mData;
|
||||
sampleCount mBlockSize;
|
||||
float **fInBuffer;
|
||||
float **fOutBuffer;
|
||||
unsigned long inputs;
|
||||
unsigned long outputs;
|
||||
unsigned long numInputControls;
|
||||
unsigned long *inputPorts;
|
||||
unsigned long *outputPorts;
|
||||
float *inputControls;
|
||||
float *outputControls;
|
||||
int mainRate;
|
||||
|
||||
std::set<wxString> mCategories;
|
||||
};
|
||||
|
||||
class LadspaEffectDialog:public wxDialog {
|
||||
DECLARE_DYNAMIC_CLASS(LadspaEffectDialog)
|
||||
|
||||
public:
|
||||
LadspaEffectDialog(LadspaEffect *effect,
|
||||
wxWindow * parent,
|
||||
const LADSPA_Descriptor *data,
|
||||
float *inputControls,
|
||||
int sampleRate,
|
||||
double length);
|
||||
|
||||
~LadspaEffectDialog();
|
||||
|
||||
void OnCheckBox(wxCommandEvent & event);
|
||||
void OnSlider(wxCommandEvent & event);
|
||||
void OnTextCtrl(wxCommandEvent & event);
|
||||
void OnOK(wxCommandEvent & event);
|
||||
void OnCancel(wxCommandEvent & event);
|
||||
void OnPreview(wxCommandEvent & event);
|
||||
void ControlSetFocus(wxFocusEvent & event);
|
||||
|
||||
double GetLength();
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
void HandleText();
|
||||
void ConnectFocus(wxControl *c);
|
||||
void DisconnectFocus(wxControl *c);
|
||||
bool inSlider;
|
||||
bool inText;
|
||||
|
||||
double mLength;
|
||||
int sampleRate;
|
||||
const LADSPA_Descriptor *mData;
|
||||
wxSlider **sliders;
|
||||
wxTextCtrl **fields;
|
||||
wxStaticText **labels;
|
||||
wxCheckBox **toggles;
|
||||
unsigned long *ports;
|
||||
unsigned long numParams;
|
||||
float *inputControls;
|
||||
LadspaEffect *effect;
|
||||
wxTextCtrl *mSeconds;
|
||||
};
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: d8622b59-5c08-4e7f-a170-2502ff8af8e5
|
||||
|
||||
337
src/effects/ladspa/LoadLadspa.cpp
Normal file
337
src/effects/ladspa/LoadLadspa.cpp
Normal file
@@ -0,0 +1,337 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
LoadLadspa.cpp
|
||||
|
||||
Dominic Mazzoni
|
||||
|
||||
From the ladspa docs:
|
||||
"To allow multiple hosts to
|
||||
share plugin types, hosts may wish to check for environment
|
||||
variable LADSPA_PATH. If present, this should contain a
|
||||
colon-separated path indicating directories that should be searched
|
||||
(in order) when loading plugin types."
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#define descriptorFnName "ladspa_descriptor"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
#include <wx/dynlib.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/hashmap.h>
|
||||
#include <wx/list.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include "ladspa.h"
|
||||
|
||||
#include "../../Audacity.h"
|
||||
#include "../../AudacityApp.h"
|
||||
#include "../../Experimental.h"
|
||||
#include "../../Internat.h"
|
||||
#include "../EffectManager.h"
|
||||
#include "LadspaEffect.h"
|
||||
|
||||
#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES)
|
||||
#include <lrdf.h>
|
||||
#endif
|
||||
|
||||
WX_DEFINE_ARRAY(wxDynamicLibrary*, DL_Array);
|
||||
|
||||
static DL_Array ladspa_dls;
|
||||
|
||||
#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES)
|
||||
|
||||
#define LADSPA(S) wxT("http://ladspa.org/ontology#") wxT(S)
|
||||
#define LV2(S) wxT("http://lv2plug.in/ns/lv2core#") wxT(S)
|
||||
|
||||
static std::map<wxString, wxString> gCategoryMap;
|
||||
static std::multimap<unsigned long, wxString> gPluginCategories;
|
||||
|
||||
/** This function initialises the data structure that maps common LRDF
|
||||
category URIs to LV2 or internal Audacity category URIs. */
|
||||
static void InitCategoryMap()
|
||||
{
|
||||
gCategoryMap[LADSPA("UtilityPlugin")] = LV2("UtilityPlugin");
|
||||
gCategoryMap[LADSPA("GeneratorPlugin")] = LV2("GeneratorPlugin");
|
||||
gCategoryMap[LADSPA("SimulatorPlugin")] = LV2("SimulatorPlugin");
|
||||
gCategoryMap[LADSPA("OscillatorPlugin")] = LV2("OscillatorPlugin");
|
||||
gCategoryMap[LADSPA("TimePlugin")] = LV2("DelayPlugin");
|
||||
gCategoryMap[LADSPA("DelayPlugin")] = LV2("DelayPlugin");
|
||||
gCategoryMap[LADSPA("PhaserPlugin")] = LV2("PhaserPlugin");
|
||||
gCategoryMap[LADSPA("FlangerPlugin")] = LV2("FlangerPlugin");
|
||||
gCategoryMap[LADSPA("ChorusPlugin")] = LV2("ChorusPlugin");
|
||||
gCategoryMap[LADSPA("ReverbPlugin")] = LV2("ReverbPlugin");
|
||||
gCategoryMap[LADSPA("FrequencyPlugin")] = LV2("SpectralPlugin");
|
||||
gCategoryMap[LADSPA("FrequencyMeterPlugin")] = LV2("AnalyserPlugin");
|
||||
gCategoryMap[LADSPA("FilterPlugin")] = LV2("FilterPlugin");
|
||||
gCategoryMap[LADSPA("LowpassPlugin")] = LV2("LowpassPlugin");
|
||||
gCategoryMap[LADSPA("HighpassPlugin")] = LV2("HighpassPlugin");
|
||||
gCategoryMap[LADSPA("BandpassPlugin")] = LV2("BandpassPlugin");
|
||||
gCategoryMap[LADSPA("CombPlugin")] = LV2("CombPlugin");
|
||||
gCategoryMap[LADSPA("AllpassPlugin")] = LV2("AllpassPlugin");
|
||||
gCategoryMap[LADSPA("EQPlugin")] = LV2("EQPlugin");
|
||||
gCategoryMap[LADSPA("ParaEQPlugin")] = LV2("ParaEQPlugin");
|
||||
gCategoryMap[LADSPA("MultiEQPlugin")] = LV2("MultiEQPlugin");
|
||||
gCategoryMap[LADSPA("AmplitudePlugin")] = LV2("AmplifierPlugin");
|
||||
gCategoryMap[LADSPA("PitchPlugin")] = LV2("PitchPlugin");
|
||||
gCategoryMap[LADSPA("AmplifierPlugin")] = LV2("AmplifierPlugin");
|
||||
gCategoryMap[LADSPA("WaveshaperPlugin")] = LV2("WaveshaperPlugin");
|
||||
gCategoryMap[LADSPA("ModulatorPlugin")] = LV2("ModulatorPlugin");
|
||||
gCategoryMap[LADSPA("DistortionPlugin")] = LV2("DistortionPlugin");
|
||||
gCategoryMap[LADSPA("DynamicsPlugin")] = LV2("DynamicsPlugin");
|
||||
gCategoryMap[LADSPA("CompressorPlugin")] = LV2("CompressorPlugin");
|
||||
gCategoryMap[LADSPA("ExpanderPlugin")] = LV2("ExpanderPlugin");
|
||||
gCategoryMap[LADSPA("LimiterPlugin")] = LV2("LimiterPlugin");
|
||||
gCategoryMap[LADSPA("GatePlugin")] = LV2("GatePlugin");
|
||||
|
||||
// This isn't in ladspa.rdfs, it's added by the swh-plugins -
|
||||
// we add it here to avoid having multiple "Spectral" categories
|
||||
gCategoryMap[LADSPA("SpectralPlugin")] = LV2("SpectralPlugin");
|
||||
|
||||
}
|
||||
|
||||
/** This function maps a LADSPA category URI to the category URIs used
|
||||
by Audacity (LV2 ones). If there is no known mapping for the
|
||||
given LADSPA category URI it is returned unchanged. */
|
||||
static wxString MapCategoryUri(const wxString& ladspaCategory)
|
||||
{
|
||||
std::map<wxString, wxString>::const_iterator iter;
|
||||
iter = gCategoryMap.find(ladspaCategory);
|
||||
if (iter != gCategoryMap.end())
|
||||
return iter->second;
|
||||
return ladspaCategory;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void LoadLadspaEffect(wxSortedArrayString &uniq, wxString fname,
|
||||
DL_Array &dls)
|
||||
{
|
||||
wxLogNull logNo;
|
||||
LADSPA_Descriptor_Function mainFn = NULL;
|
||||
|
||||
// Since we now have builtin VST support, ignore the VST bridge as it
|
||||
// causes duplicate menu entries to appear.
|
||||
wxFileName f(fname);
|
||||
if (f.GetName().CmpNoCase(wxT("vst-bridge")) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// As a courtesy to some plug-ins that might be bridges to
|
||||
// open other plug-ins, we set the current working
|
||||
// directory to be the plug-in's directory.
|
||||
|
||||
wxString saveOldCWD = ::wxGetCwd();
|
||||
wxString prefix = ::wxPathOnly(fname);
|
||||
::wxSetWorkingDirectory(prefix);
|
||||
|
||||
wxDynamicLibrary* pDLL = new wxDynamicLibrary();
|
||||
dls.push_back(pDLL);
|
||||
if (pDLL && pDLL->Load(fname, wxDL_LAZY)) {
|
||||
mainFn = (LADSPA_Descriptor_Function)(pDLL->GetSymbol(wxT(descriptorFnName)));
|
||||
}
|
||||
|
||||
if (mainFn) {
|
||||
int index = 0;
|
||||
const LADSPA_Descriptor *data;
|
||||
|
||||
data = mainFn(index);
|
||||
while(data) {
|
||||
|
||||
wxString uniqid = wxString::Format(wxT("%08x-%s"), data->UniqueID, LAT1CTOWX(data->Label).c_str());
|
||||
if (uniq.Index(uniqid) == wxNOT_FOUND) {
|
||||
uniq.Add(uniqid);
|
||||
std::set<wxString> categories;
|
||||
|
||||
#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES)
|
||||
std::multimap<unsigned long, wxString>::const_iterator iter;
|
||||
iter = gPluginCategories.lower_bound(data->UniqueID);
|
||||
for ( ; (iter != gPluginCategories.end() &&
|
||||
iter->first == data->UniqueID); ++iter)
|
||||
categories.insert(iter->second);
|
||||
#endif
|
||||
|
||||
LadspaEffect *effect = new LadspaEffect(data, categories);
|
||||
EffectManager::Get().RegisterEffect(effect);
|
||||
}
|
||||
|
||||
// Get next plugin
|
||||
index++;
|
||||
data = mainFn(index);
|
||||
}
|
||||
}
|
||||
|
||||
::wxSetWorkingDirectory(saveOldCWD);
|
||||
}
|
||||
|
||||
void LoadLadspaPlugins()
|
||||
{
|
||||
wxArrayString audacityPathList = wxGetApp().audacityPathList;
|
||||
wxArrayString pathList;
|
||||
wxArrayString files;
|
||||
wxSortedArrayString uniq;
|
||||
wxString pathVar;
|
||||
unsigned int i;
|
||||
EffectManager& em = EffectManager::Get();
|
||||
|
||||
#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES)
|
||||
|
||||
wxArrayString rdfPathList;
|
||||
wxString rdfPathVar;
|
||||
wxArrayString rdfFiles;
|
||||
|
||||
InitCategoryMap();
|
||||
lrdf_init();
|
||||
|
||||
rdfPathVar = wxGetenv(wxT("LADSPA_RDF_PATH"));
|
||||
if (rdfPathVar != wxT(""))
|
||||
wxGetApp().AddMultiPathsToPathList(rdfPathVar, rdfPathList);
|
||||
|
||||
#ifdef __WXGTK__
|
||||
wxGetApp().AddUniquePathToPathList(wxT("/usr/share/ladspa/rdf"),
|
||||
rdfPathList);
|
||||
wxGetApp().AddUniquePathToPathList(wxT("/usr/local/share/ladspa/rdf"),
|
||||
rdfPathList);
|
||||
#endif
|
||||
|
||||
#ifdef __WXMAC__
|
||||
wxGetApp().AddUniquePathToPathList(wxT("/usr/share/ladspa/rdf"),
|
||||
rdfPathList);
|
||||
// XXX Maybe other Mac paths here?
|
||||
#endif
|
||||
|
||||
#ifdef __WXMSW__
|
||||
//wxGetApp().AddUniquePathToPathList(wxT("WINDOWS LRDF PATH"),
|
||||
// rdfPathList);
|
||||
// XXX Other Windows paths here.
|
||||
#endif
|
||||
|
||||
// Add the Audacity paths so we get ladspa.rdfs if we are using a local
|
||||
// liblrdf
|
||||
for(i=0; i<audacityPathList.GetCount(); i++) {
|
||||
wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("rdf"),
|
||||
rdfPathList);
|
||||
}
|
||||
|
||||
wxGetApp().FindFilesInPathList(wxT("*.rdf"), rdfPathList, rdfFiles);
|
||||
wxGetApp().FindFilesInPathList(wxT("*.rdfs"), rdfPathList, rdfFiles);
|
||||
for(size_t i = 0; i < rdfFiles.GetCount(); ++i) {
|
||||
wxString fileUri(wxT("file://"));
|
||||
fileUri += rdfFiles[i];
|
||||
lrdf_read_file(fileUri.mb_str(wxConvUTF8));
|
||||
}
|
||||
|
||||
|
||||
// Add all plugin categories found by LRDF
|
||||
lrdf_uris* cats =
|
||||
lrdf_get_all_subclasses("http://ladspa.org/ontology#Plugin");
|
||||
if (cats) {
|
||||
|
||||
// Add the categories and find the plugins belonging to them
|
||||
for (size_t i = 0; i < cats->count; ++i) {
|
||||
char* label = lrdf_get_label(cats->items[i]);
|
||||
if (!label)
|
||||
continue;
|
||||
wxString uri = MapCategoryUri(wxString::FromAscii(cats->items[i]));
|
||||
em.AddCategory(uri, wxString::FromUTF8(label));
|
||||
std::free(label);
|
||||
|
||||
lrdf_uris* plugs = lrdf_get_instances(cats->items[i]);
|
||||
if (plugs) {
|
||||
for (size_t j = 0; j < plugs->count; ++j) {
|
||||
unsigned long uid = lrdf_get_uid(plugs->items[j]);
|
||||
gPluginCategories.insert(std::make_pair(uid, uri));
|
||||
}
|
||||
lrdf_free_uris(plugs);
|
||||
}
|
||||
}
|
||||
|
||||
// And their relationships
|
||||
for (size_t i = 0; i < cats->count; ++i) {
|
||||
EffectCategory* p =
|
||||
em.LookupCategory(MapCategoryUri(wxString::FromAscii(cats->
|
||||
items[i])));
|
||||
if (!p)
|
||||
continue;
|
||||
lrdf_uris* subs = lrdf_get_subclasses(cats->items[i]);
|
||||
if (subs) {
|
||||
for (size_t j = 0; j < subs->count; ++j) {
|
||||
EffectCategory* c =
|
||||
em.LookupCategory(MapCategoryUri(wxString::FromAscii(subs->items[j])));
|
||||
if (c)
|
||||
em.AddCategoryParent(c, p);
|
||||
}
|
||||
lrdf_free_uris(subs);
|
||||
}
|
||||
}
|
||||
|
||||
lrdf_free_uris(cats);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
pathVar = wxGetenv(wxT("LADSPA_PATH"));
|
||||
if (pathVar != wxT(""))
|
||||
wxGetApp().AddMultiPathsToPathList(pathVar, pathList);
|
||||
|
||||
#ifdef __WXGTK__
|
||||
wxGetApp().AddUniquePathToPathList(wxT(INSTALL_PREFIX) wxT("/ladspa"), pathList);
|
||||
wxGetApp().AddUniquePathToPathList(wxT("/usr/local/lib/ladspa"), pathList);
|
||||
wxGetApp().AddUniquePathToPathList(wxT(LIBDIR) wxT("/ladspa"), pathList);
|
||||
#endif
|
||||
|
||||
#ifdef __WXMAC__
|
||||
wxGetApp().AddUniquePathToPathList(wxT("~/Library/Audio/Plug-Ins/LADSPA"), pathList);
|
||||
wxGetApp().AddUniquePathToPathList(wxT("/Library/Audio/Plug-Ins/LADSPA"), pathList);
|
||||
#endif
|
||||
|
||||
for(i=0; i<audacityPathList.GetCount(); i++) {
|
||||
wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("ladspa"),
|
||||
pathList);
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("plugins"),
|
||||
pathList);
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("plug-ins"),
|
||||
pathList);
|
||||
}
|
||||
|
||||
#ifdef __WXMSW__
|
||||
wxGetApp().FindFilesInPathList(wxT("*.dll"), pathList, files);
|
||||
#else
|
||||
wxGetApp().FindFilesInPathList(wxT("*.so"), pathList, files);
|
||||
#endif
|
||||
|
||||
for(i=0; i<files.GetCount(); i++)
|
||||
LoadLadspaEffect(uniq, files[i], ladspa_dls);
|
||||
}
|
||||
|
||||
void UnloadLadspaPlugins()
|
||||
{
|
||||
int count=ladspa_dls.GetCount();
|
||||
for (int i=0; i<count; i++)
|
||||
{
|
||||
delete ladspa_dls[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 2f903c43-d9fe-4875-bb10-b9ae843f36a8
|
||||
|
||||
24
src/effects/ladspa/LoadLadspa.h
Normal file
24
src/effects/ladspa/LoadLadspa.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
LoadLadspa.h
|
||||
|
||||
Dominic Mazzoni
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
void LoadLadspaPlugins();
|
||||
void UnloadLadspaPlugins();
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 21a6d3fe-1003-4cec-a44c-4a16335b5cda
|
||||
|
||||
615
src/effects/ladspa/ladspa.h
Normal file
615
src/effects/ladspa/ladspa.h
Normal file
@@ -0,0 +1,615 @@
|
||||
/* ladspa.h
|
||||
|
||||
Linux Audio Developer's Simple Plugin API Version 1.1[LGPL].
|
||||
Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis,
|
||||
Stefan Westerfeld.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License
|
||||
as published by the Free Software Foundation; either version 2.1 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA. */
|
||||
|
||||
#ifndef LADSPA_INCLUDED
|
||||
#define LADSPA_INCLUDED
|
||||
|
||||
#define LADSPA_VERSION "1.1"
|
||||
#define LADSPA_VERSION_MAJOR 1
|
||||
#define LADSPA_VERSION_MINOR 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Overview:
|
||||
|
||||
There is a large number of synthesis packages in use or development
|
||||
on the Linux platform at this time. This API (`The Linux Audio
|
||||
Developer's Simple Plugin API') attempts to give programmers the
|
||||
ability to write simple `plugin' audio processors in C/C++ and link
|
||||
them dynamically (`plug') into a range of these packages (`hosts').
|
||||
It should be possible for any host and any plugin to communicate
|
||||
completely through this interface.
|
||||
|
||||
This API is deliberately short and simple. To achieve compatibility
|
||||
with a range of promising Linux sound synthesis packages it
|
||||
attempts to find the `greatest common divisor' in their logical
|
||||
behaviour. Having said this, certain limiting decisions are
|
||||
implicit, notably the use of a fixed type (LADSPA_Data) for all
|
||||
data transfer and absence of a parameterised `initialisation'
|
||||
phase. See below for the LADSPA_Data typedef.
|
||||
|
||||
Plugins are expected to distinguish between control and audio
|
||||
data. Plugins have `ports' that are inputs or outputs for audio or
|
||||
control data and each plugin is `run' for a `block' corresponding
|
||||
to a short time interval measured in samples. Audio data is
|
||||
communicated using arrays of LADSPA_Data, allowing a block of audio
|
||||
to be processed by the plugin in a single pass. Control data is
|
||||
communicated using single LADSPA_Data values. Control data has a
|
||||
single value at the start of a call to the `run()' or `run_adding()'
|
||||
function, and may be considered to remain this value for its
|
||||
duration. The plugin may assume that all its input and output ports
|
||||
have been connected to the relevant data location (see the
|
||||
`connect_port()' function below) before it is asked to run.
|
||||
|
||||
Plugins will reside in shared object files suitable for dynamic
|
||||
linking by dlopen() and family. The file will provide a number of
|
||||
`plugin types' that can be used to instantiate actual plugins
|
||||
(sometimes known as `plugin instances') that can be connected
|
||||
together to perform tasks.
|
||||
|
||||
This API contains very limited error-handling. */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Fundamental data type passed in and out of plugin. This data type
|
||||
is used to communicate audio samples and control values. It is
|
||||
assumed that the plugin will work sensibly given any numeric input
|
||||
value although it may have a preferred range (see hints below).
|
||||
|
||||
For audio it is generally assumed that 1.0f is the `0dB' reference
|
||||
amplitude and is a `normal' signal level. */
|
||||
|
||||
typedef float LADSPA_Data;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Special Plugin Properties:
|
||||
|
||||
Optional features of the plugin type are encapsulated in the
|
||||
LADSPA_Properties type. This is assembled by ORing individual
|
||||
properties together. */
|
||||
|
||||
typedef int LADSPA_Properties;
|
||||
|
||||
/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a
|
||||
real-time dependency (e.g. listens to a MIDI device) and so its
|
||||
output must not be cached or subject to significant latency. */
|
||||
#define LADSPA_PROPERTY_REALTIME 0x1
|
||||
|
||||
/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin
|
||||
may cease to work correctly if the host elects to use the same data
|
||||
location for both input and output (see connect_port()). This
|
||||
should be avoided as enabling this flag makes it impossible for
|
||||
hosts to use the plugin to process audio `in-place.' */
|
||||
#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2
|
||||
|
||||
/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin
|
||||
is capable of running not only in a conventional host but also in a
|
||||
`hard real-time' environment. To qualify for this the plugin must
|
||||
satisfy all of the following:
|
||||
|
||||
(1) The plugin must not use malloc(), free() or other heap memory
|
||||
management within its run() or run_adding() functions. All new
|
||||
memory used in run() must be managed via the stack. These
|
||||
restrictions only apply to the run() function.
|
||||
|
||||
(2) The plugin will not attempt to make use of any library
|
||||
functions with the exceptions of functions in the ANSI standard C
|
||||
and C maths libraries, which the host is expected to provide.
|
||||
|
||||
(3) The plugin will not access files, devices, pipes, sockets, IPC
|
||||
or any other mechanism that might result in process or thread
|
||||
blocking.
|
||||
|
||||
(4) The plugin will take an amount of time to execute a run() or
|
||||
run_adding() call approximately of form (A+B*SampleCount) where A
|
||||
and B depend on the machine and host in use. This amount of time
|
||||
may not depend on input signals or plugin state. The host is left
|
||||
the responsibility to perform timings to estimate upper bounds for
|
||||
A and B. */
|
||||
#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4
|
||||
|
||||
#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME)
|
||||
#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN)
|
||||
#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Plugin Ports:
|
||||
|
||||
Plugins have `ports' that are inputs or outputs for audio or
|
||||
data. Ports can communicate arrays of LADSPA_Data (for audio
|
||||
inputs/outputs) or single LADSPA_Data values (for control
|
||||
input/outputs). This information is encapsulated in the
|
||||
LADSPA_PortDescriptor type which is assembled by ORing individual
|
||||
properties together.
|
||||
|
||||
Note that a port must be an input or an output port but not both
|
||||
and that a port must be a control or audio port but not both. */
|
||||
|
||||
typedef int LADSPA_PortDescriptor;
|
||||
|
||||
/* Property LADSPA_PORT_INPUT indicates that the port is an input. */
|
||||
#define LADSPA_PORT_INPUT 0x1
|
||||
|
||||
/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */
|
||||
#define LADSPA_PORT_OUTPUT 0x2
|
||||
|
||||
/* Property LADSPA_PORT_CONTROL indicates that the port is a control
|
||||
port. */
|
||||
#define LADSPA_PORT_CONTROL 0x4
|
||||
|
||||
/* Property LADSPA_PORT_AUDIO indicates that the port is a audio
|
||||
port. */
|
||||
#define LADSPA_PORT_AUDIO 0x8
|
||||
|
||||
#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT)
|
||||
#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT)
|
||||
#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL)
|
||||
#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Plugin Port Range Hints:
|
||||
|
||||
The host may wish to provide a representation of data entering or
|
||||
leaving a plugin (e.g. to generate a GUI automatically). To make
|
||||
this more meaningful, the plugin should provide `hints' to the host
|
||||
describing the usual values taken by the data.
|
||||
|
||||
Note that these are only hints. The host may ignore them and the
|
||||
plugin must not assume that data supplied to it is meaningful. If
|
||||
the plugin receives invalid input data it is expected to continue
|
||||
to run without failure and, where possible, produce a sensible
|
||||
output (e.g. a high-pass filter given a negative cutoff frequency
|
||||
might switch to an all-pass mode).
|
||||
|
||||
Hints are meaningful for all input and output ports but hints for
|
||||
input control ports are expected to be particularly useful.
|
||||
|
||||
More hint information is encapsulated in the
|
||||
LADSPA_PortRangeHintDescriptor type which is assembled by ORing
|
||||
individual hint types together. Hints may require further
|
||||
LowerBound and UpperBound information.
|
||||
|
||||
All the hint information for a particular port is aggregated in the
|
||||
LADSPA_PortRangeHint structure. */
|
||||
|
||||
typedef int LADSPA_PortRangeHintDescriptor;
|
||||
|
||||
/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field
|
||||
of the LADSPA_PortRangeHint should be considered meaningful. The
|
||||
value in this field should be considered the (inclusive) lower
|
||||
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
|
||||
specified then the value of LowerBound should be multiplied by the
|
||||
sample rate. */
|
||||
#define LADSPA_HINT_BOUNDED_BELOW 0x1
|
||||
|
||||
/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field
|
||||
of the LADSPA_PortRangeHint should be considered meaningful. The
|
||||
value in this field should be considered the (inclusive) upper
|
||||
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
|
||||
specified then the value of UpperBound should be multiplied by the
|
||||
sample rate. */
|
||||
#define LADSPA_HINT_BOUNDED_ABOVE 0x2
|
||||
|
||||
/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be
|
||||
considered a Boolean toggle. Data less than or equal to zero should
|
||||
be considered `off' or `false,' and data above zero should be
|
||||
considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in
|
||||
conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or
|
||||
LADSPA_HINT_DEFAULT_1. */
|
||||
#define LADSPA_HINT_TOGGLED 0x4
|
||||
|
||||
/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified
|
||||
should be interpreted as multiples of the sample rate. For
|
||||
instance, a frequency range from 0Hz to the Nyquist frequency (half
|
||||
the sample rate) could be requested by this hint in conjunction
|
||||
with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds
|
||||
at all must support this hint to retain meaning. */
|
||||
#define LADSPA_HINT_SAMPLE_RATE 0x8
|
||||
|
||||
/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the
|
||||
user will find it more intuitive to view values using a logarithmic
|
||||
scale. This is particularly useful for frequencies and gains. */
|
||||
#define LADSPA_HINT_LOGARITHMIC 0x10
|
||||
|
||||
/* Hint LADSPA_HINT_INTEGER indicates that a user interface would
|
||||
probably wish to provide a stepped control taking only integer
|
||||
values. Any bounds set should be slightly wider than the actual
|
||||
integer range required to avoid floating point rounding errors. For
|
||||
instance, the integer set {0,1,2,3} might be described as [-0.1,
|
||||
3.1]. */
|
||||
#define LADSPA_HINT_INTEGER 0x20
|
||||
|
||||
/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal'
|
||||
value for the port that is sensible as a default. For instance,
|
||||
this value is suitable for use as an initial value in a user
|
||||
interface or as a value the host might assign to a control port
|
||||
when the user has not provided one. Defaults are encoded using a
|
||||
mask so only one default may be specified for a port. Some of the
|
||||
hints make use of lower and upper bounds, in which case the
|
||||
relevant bound or bounds must be available and
|
||||
LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting
|
||||
default must be rounded if LADSPA_HINT_INTEGER is present. Default
|
||||
values were introduced in LADSPA v1.1. */
|
||||
#define LADSPA_HINT_DEFAULT_MASK 0x3C0
|
||||
|
||||
/* This default values indicates that no default is provided. */
|
||||
#define LADSPA_HINT_DEFAULT_NONE 0x0
|
||||
|
||||
/* This default hint indicates that the suggested lower bound for the
|
||||
port should be used. */
|
||||
#define LADSPA_HINT_DEFAULT_MINIMUM 0x40
|
||||
|
||||
/* This default hint indicates that a low value between the suggested
|
||||
lower and upper bounds should be chosen. For ports with
|
||||
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 +
|
||||
log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper
|
||||
* 0.25). */
|
||||
#define LADSPA_HINT_DEFAULT_LOW 0x80
|
||||
|
||||
/* This default hint indicates that a middle value between the
|
||||
suggested lower and upper bounds should be chosen. For ports with
|
||||
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 +
|
||||
log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper *
|
||||
0.5). */
|
||||
#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0
|
||||
|
||||
/* This default hint indicates that a high value between the suggested
|
||||
lower and upper bounds should be chosen. For ports with
|
||||
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 +
|
||||
log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper
|
||||
* 0.75). */
|
||||
#define LADSPA_HINT_DEFAULT_HIGH 0x100
|
||||
|
||||
/* This default hint indicates that the suggested upper bound for the
|
||||
port should be used. */
|
||||
#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140
|
||||
|
||||
/* This default hint indicates that the number 0 should be used. Note
|
||||
that this default may be used in conjunction with
|
||||
LADSPA_HINT_TOGGLED. */
|
||||
#define LADSPA_HINT_DEFAULT_0 0x200
|
||||
|
||||
/* This default hint indicates that the number 1 should be used. Note
|
||||
that this default may be used in conjunction with
|
||||
LADSPA_HINT_TOGGLED. */
|
||||
#define LADSPA_HINT_DEFAULT_1 0x240
|
||||
|
||||
/* This default hint indicates that the number 100 should be used. */
|
||||
#define LADSPA_HINT_DEFAULT_100 0x280
|
||||
|
||||
/* This default hint indicates that the Hz frequency of `concert A'
|
||||
should be used. This will be 440 unless the host uses an unusual
|
||||
tuning convention, in which case it may be within a few Hz. */
|
||||
#define LADSPA_HINT_DEFAULT_440 0x2C0
|
||||
|
||||
#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW)
|
||||
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE)
|
||||
#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED)
|
||||
#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE)
|
||||
#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC)
|
||||
#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER)
|
||||
|
||||
#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK)
|
||||
#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_MINIMUM)
|
||||
#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_LOW)
|
||||
#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_MIDDLE)
|
||||
#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_HIGH)
|
||||
#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_MAXIMUM)
|
||||
#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_0)
|
||||
#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_1)
|
||||
#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_100)
|
||||
#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \
|
||||
== LADSPA_HINT_DEFAULT_440)
|
||||
|
||||
typedef struct _LADSPA_PortRangeHint {
|
||||
|
||||
/* Hints about the port. */
|
||||
LADSPA_PortRangeHintDescriptor HintDescriptor;
|
||||
|
||||
/* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When
|
||||
LADSPA_HINT_SAMPLE_RATE is also active then this value should be
|
||||
multiplied by the relevant sample rate. */
|
||||
LADSPA_Data LowerBound;
|
||||
|
||||
/* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When
|
||||
LADSPA_HINT_SAMPLE_RATE is also active then this value should be
|
||||
multiplied by the relevant sample rate. */
|
||||
LADSPA_Data UpperBound;
|
||||
|
||||
} LADSPA_PortRangeHint;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Plugin Handles:
|
||||
|
||||
This plugin handle indicates a particular instance of the plugin
|
||||
concerned. It is valid to compare this to NULL (0 for C++) but
|
||||
otherwise the host should not attempt to interpret it. The plugin
|
||||
may use it to reference internal instance data. */
|
||||
|
||||
typedef void * LADSPA_Handle;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Descriptor for a Type of Plugin:
|
||||
|
||||
This structure is used to describe a plugin type. It provides a
|
||||
number of functions to examine the type, instantiate it, link it to
|
||||
buffers and workspaces and to run it. */
|
||||
|
||||
typedef struct _LADSPA_Descriptor {
|
||||
|
||||
/* This numeric identifier indicates the plugin type
|
||||
uniquely. Plugin programmers may reserve ranges of IDs from a
|
||||
central body to avoid clashes. Hosts may assume that IDs are
|
||||
below 0x1000000. */
|
||||
unsigned long UniqueID;
|
||||
|
||||
/* This identifier can be used as a unique, case-sensitive
|
||||
identifier for the plugin type within the plugin file. Plugin
|
||||
types should be identified by file and label rather than by index
|
||||
or plugin name, which may be changed in new plugin
|
||||
versions. Labels must not contain white-space characters. */
|
||||
const char * Label;
|
||||
|
||||
/* This indicates a number of properties of the plugin. */
|
||||
LADSPA_Properties Properties;
|
||||
|
||||
/* This member points to the null-terminated name of the plugin
|
||||
(e.g. "Sine Oscillator"). */
|
||||
const char * Name;
|
||||
|
||||
/* This member points to the null-terminated string indicating the
|
||||
maker of the plugin. This can be an empty string but not NULL. */
|
||||
const char * Maker;
|
||||
|
||||
/* This member points to the null-terminated string indicating any
|
||||
copyright applying to the plugin. If no Copyright applies the
|
||||
string "None" should be used. */
|
||||
const char * Copyright;
|
||||
|
||||
/* This indicates the number of ports (input AND output) present on
|
||||
the plugin. */
|
||||
unsigned long PortCount;
|
||||
|
||||
/* This member indicates an array of port descriptors. Valid indices
|
||||
vary from 0 to PortCount-1. */
|
||||
const LADSPA_PortDescriptor * PortDescriptors;
|
||||
|
||||
/* This member indicates an array of null-terminated strings
|
||||
describing ports (e.g. "Frequency (Hz)"). Valid indices vary from
|
||||
0 to PortCount-1. */
|
||||
const char * const * PortNames;
|
||||
|
||||
/* This member indicates an array of range hints for each port (see
|
||||
above). Valid indices vary from 0 to PortCount-1. */
|
||||
const LADSPA_PortRangeHint * PortRangeHints;
|
||||
|
||||
/* This may be used by the plugin developer to pass any custom
|
||||
implementation data into an instantiate call. It must not be used
|
||||
or interpreted by the host. It is expected that most plugin
|
||||
writers will not use this facility as LADSPA_Handle should be
|
||||
used to hold instance data. */
|
||||
void * ImplementationData;
|
||||
|
||||
/* This member is a function pointer that instantiates a plugin. A
|
||||
handle is returned indicating the new plugin instance. The
|
||||
instantiation function accepts a sample rate as a parameter. The
|
||||
plugin descriptor from which this instantiate function was found
|
||||
must also be passed. This function must return NULL if
|
||||
instantiation fails.
|
||||
|
||||
Note that instance initialisation should generally occur in
|
||||
activate() rather than here. */
|
||||
LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor,
|
||||
unsigned long SampleRate);
|
||||
|
||||
/* This member is a function pointer that connects a port on an
|
||||
instantiated plugin to a memory location at which a block of data
|
||||
for the port will be read/written. The data location is expected
|
||||
to be an array of LADSPA_Data for audio ports or a single
|
||||
LADSPA_Data value for control ports. Memory issues will be
|
||||
managed by the host. The plugin must read/write the data at these
|
||||
locations every time run() or run_adding() is called and the data
|
||||
present at the time of this connection call should not be
|
||||
considered meaningful.
|
||||
|
||||
connect_port() may be called more than once for a plugin instance
|
||||
to allow the host to change the buffers that the plugin is
|
||||
reading or writing. These calls may be made before or after
|
||||
activate() or deactivate() calls.
|
||||
|
||||
connect_port() must be called at least once for each port before
|
||||
run() or run_adding() is called. When working with blocks of
|
||||
LADSPA_Data the plugin should pay careful attention to the block
|
||||
size passed to the run function as the block allocated may only
|
||||
just be large enough to contain the block of samples.
|
||||
|
||||
Plugin writers should be aware that the host may elect to use the
|
||||
same buffer for more than one port and even use the same buffer
|
||||
for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN).
|
||||
However, overlapped buffers or use of a single buffer for both
|
||||
audio and control data may result in unexpected behaviour. */
|
||||
void (*connect_port)(LADSPA_Handle Instance,
|
||||
unsigned long Port,
|
||||
LADSPA_Data * DataLocation);
|
||||
|
||||
/* This member is a function pointer that initialises a plugin
|
||||
instance and activates it for use. This is separated from
|
||||
instantiate() to aid real-time support and so that hosts can
|
||||
reinitialise a plugin instance by calling deactivate() and then
|
||||
activate(). In this case the plugin instance must reset all state
|
||||
information dependent on the history of the plugin instance
|
||||
except for any data locations provided by connect_port() and any
|
||||
gain set by set_run_adding_gain(). If there is nothing for
|
||||
activate() to do then the plugin writer may provide a NULL rather
|
||||
than an empty function.
|
||||
|
||||
When present, hosts must call this function once before run() (or
|
||||
run_adding()) is called for the first time. This call should be
|
||||
made as close to the run() call as possible and indicates to
|
||||
real-time plugins that they are now live. Plugins should not rely
|
||||
on a prompt call to run() after activate(). activate() may not be
|
||||
called again unless deactivate() is called first. Note that
|
||||
connect_port() may be called before or after a call to
|
||||
activate(). */
|
||||
void (*activate)(LADSPA_Handle Instance);
|
||||
|
||||
/* This method is a function pointer that runs an instance of a
|
||||
plugin for a block. Two parameters are required: the first is a
|
||||
handle to the particular instance to be run and the second
|
||||
indicates the block size (in samples) for which the plugin
|
||||
instance may run.
|
||||
|
||||
Note that if an activate() function exists then it must be called
|
||||
before run() or run_adding(). If deactivate() is called for a
|
||||
plugin instance then the plugin instance may not be reused until
|
||||
activate() has been called again.
|
||||
|
||||
If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE
|
||||
then there are various things that the plugin should not do
|
||||
within the run() or run_adding() functions (see above). */
|
||||
void (*run)(LADSPA_Handle Instance,
|
||||
unsigned long SampleCount);
|
||||
|
||||
/* This method is a function pointer that runs an instance of a
|
||||
plugin for a block. This has identical behaviour to run() except
|
||||
in the way data is output from the plugin. When run() is used,
|
||||
values are written directly to the memory areas associated with
|
||||
the output ports. However when run_adding() is called, values
|
||||
must be added to the values already present in the memory
|
||||
areas. Furthermore, output values written must be scaled by the
|
||||
current gain set by set_run_adding_gain() (see below) before
|
||||
addition.
|
||||
|
||||
run_adding() is optional. When it is not provided by a plugin,
|
||||
this function pointer must be set to NULL. When it is provided,
|
||||
the function set_run_adding_gain() must be provided also. */
|
||||
void (*run_adding)(LADSPA_Handle Instance,
|
||||
unsigned long SampleCount);
|
||||
|
||||
/* This method is a function pointer that sets the output gain for
|
||||
use when run_adding() is called (see above). If this function is
|
||||
never called the gain is assumed to default to 1. Gain
|
||||
information should be retained when activate() or deactivate()
|
||||
are called.
|
||||
|
||||
This function should be provided by the plugin if and only if the
|
||||
run_adding() function is provided. When it is absent this
|
||||
function pointer must be set to NULL. */
|
||||
void (*set_run_adding_gain)(LADSPA_Handle Instance,
|
||||
LADSPA_Data Gain);
|
||||
|
||||
/* This is the counterpart to activate() (see above). If there is
|
||||
nothing for deactivate() to do then the plugin writer may provide
|
||||
a NULL rather than an empty function.
|
||||
|
||||
Hosts must deactivate all activated units after they have been
|
||||
run() (or run_adding()) for the last time. This call should be
|
||||
made as close to the last run() call as possible and indicates to
|
||||
real-time plugins that they are no longer live. Plugins should
|
||||
not rely on prompt deactivation. Note that connect_port() may be
|
||||
called before or after a call to deactivate().
|
||||
|
||||
Deactivation is not similar to pausing as the plugin instance
|
||||
will be reinitialised when activate() is called to reuse it. */
|
||||
void (*deactivate)(LADSPA_Handle Instance);
|
||||
|
||||
/* Once an instance of a plugin has been finished with it can be
|
||||
deleted using the following function. The instance handle passed
|
||||
ceases to be valid after this call.
|
||||
|
||||
If activate() was called for a plugin instance then a
|
||||
corresponding call to deactivate() must be made before cleanup()
|
||||
is called. */
|
||||
void (*cleanup)(LADSPA_Handle Instance);
|
||||
|
||||
} LADSPA_Descriptor;
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/* Accessing a Plugin: */
|
||||
|
||||
/* The exact mechanism by which plugins are loaded is host-dependent,
|
||||
however all most hosts will need to know is the name of shared
|
||||
object file containing the plugin types. To allow multiple hosts to
|
||||
share plugin types, hosts may wish to check for environment
|
||||
variable LADSPA_PATH. If present, this should contain a
|
||||
colon-separated path indicating directories that should be searched
|
||||
(in order) when loading plugin types.
|
||||
|
||||
A plugin programmer must include a function called
|
||||
"ladspa_descriptor" with the following function prototype within
|
||||
the shared object file. This function will have C-style linkage (if
|
||||
you are using C++ this is taken care of by the `extern "C"' clause
|
||||
at the top of the file).
|
||||
|
||||
A host will find the plugin shared object file by one means or
|
||||
another, find the ladspa_descriptor() function, call it, and
|
||||
proceed from there.
|
||||
|
||||
Plugin types are accessed by index (not ID) using values from 0
|
||||
upwards. Out of range indexes must result in this function
|
||||
returning NULL, so the plugin count can be determined by checking
|
||||
for the least index that results in NULL being returned. */
|
||||
|
||||
const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);
|
||||
|
||||
/* Datatype corresponding to the ladspa_descriptor() function. */
|
||||
typedef const LADSPA_Descriptor *
|
||||
(*LADSPA_Descriptor_Function)(unsigned long Index);
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LADSPA_INCLUDED */
|
||||
|
||||
/* EOF */
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 56fbe96a-2746-4896-b96f-51070e7a7842
|
||||
|
||||
Reference in New Issue
Block a user