📄 ladspaeffect.cpp
字号:
/********************************************************************** Audacity: A Digital Audio Editor LadspaEffect.cpp Dominic Mazzoni This class implements a Ladspa Plug-in effect.**********************************************************************/#include "ladspa.h"#include <wx/wxprec.h>#include <wx/button.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/intl.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){ mData = data; pluginName = LAT1CTOWX(data->Name); buffer = NULL; fInBuffer = NULL; fOutBuffer = NULL; inputs = 0; outputs = 0; numInputControls = 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; } } flags = PLUGIN_EFFECT; if (inputs == 0) flags |= INSERT_EFFECT; else if (outputs == 0) flags |= ANALYZE_EFFECT; else flags |= PROCESS_EFFECT; }LadspaEffect::~LadspaEffect(){ delete[] inputPorts; delete[] outputPorts; delete[] inputControls; delete[] outputControls;}wxString LadspaEffect::GetEffectName(){ if (numInputControls > 0) return pluginName + wxT("..."); else return pluginName;}wxString LadspaEffect::GetEffectAction(){ return wxString::Format(_("Performing Effect: %s"), pluginName.c_str());}bool LadspaEffect::Init(){ mBlockSize = 0; mainRate = 0; TrackListIterator iter(mWaveTracks); 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) { LadspaEffectDialog dlog(this, mParent, mData, inputControls, mainRate); dlog.CentreOnParent(); dlog.ShowModal(); if (!dlog.GetReturnCode()) return false; } return true;}void LadspaEffect::GetSamples(WaveTrack *track, longSampleCount *start, sampleCount *len){ double trackStart = track->GetStartTime(); double trackEnd = track->GetEndTime(); double t0 = mT0 < trackStart? trackStart: mT0; double t1 = mT1 > trackEnd? trackEnd: mT1; if (t1 > t0) { *start = track->TimeToLongSamples(t0); longSampleCount end = track->TimeToLongSamples(t1); *len = (sampleCount)(end - *start); } else { *start = 0; *len = 0; }}bool LadspaEffect::Process(){ TrackListIterator iter(mWaveTracks); int count = 0; Track *left = iter.First(); Track *right; while(left) { longSampleCount lstart, rstart; sampleCount len; GetSamples((WaveTrack *)left, &lstart, &len); right = NULL; if (left->GetLinked() && inputs>1) { right = iter.Next(); GetSamples((WaveTrack *)right, &rstart, &len); } bool success = false; if (inputs < 2 && right) { // If the effect is mono, apply to each channel separately success = ProcessStereo(count, (WaveTrack *)left, NULL, lstart, 0, len); if (success) success = ProcessStereo(count, (WaveTrack *)right, NULL, rstart, 0, len); } else success = ProcessStereo(count, (WaveTrack *)left, (WaveTrack *)right, lstart, rstart, len); if (!success) return false; left = iter.Next(); count++; } return true;}bool LadspaEffect::ProcessStereo(int count, WaveTrack *left, WaveTrack *right, longSampleCount lstart, longSampleCount rstart, sampleCount len){ /* Allocate buffers */ if (mBlockSize == 0) { mBlockSize = left->GetMaxBlockSize() * 2; buffer = new float[mBlockSize]; 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; longSampleCount ls = lstart; longSampleCount rs = rstart; while (len) { int block = mBlockSize; int i; if (block > len) block = len; if (left && inputs > 0) { left->Get((samplePtr)buffer, floatSample, ls, block); for (i = 0; i < block; i++) fInBuffer[0][i] = buffer[i]; } if (right && inputs > 1) { right->Get((samplePtr)buffer, floatSample, rs, block); for (i = 0; i < block; i++) fInBuffer[1][i] = buffer[i]; } mData->run(handle, block); if (left && outputs > 0) { for (i = 0; i < block; i++) buffer[i] = fOutBuffer[0][i]; left->Set((samplePtr)buffer, floatSample, ls, block); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -