📄 vsteffect.cpp
字号:
/********************************************************************** Audacity: A Digital Audio Editor VSTEffect.cpp Dominic Mazzoni This class implements a VST Plug-in effect. The plug-in must be loaded in a platform-specific way and passed into the constructor, but from here this class handles the interfacing. VST plug-ins are used in Cubase and other Steinberg products, and all of those files and the information within is copyrighted by Steinberg.**********************************************************************/#include "../../Audacity.h"#if USE_VST#include "AEffect.h" // VST API#include "AEffEditor.hpp"#include <wx/defs.h>#include <wx/button.h>#include <wx/dialog.h>#include <wx/frame.h>#include <wx/slider.h>#include <wx/sizer.h>#include <wx/msgdlg.h>#include "../Effect.h" // Audacity Effect base class#include "VSTEffect.h" // This class's header file#ifdef __MACOSX__#include <Carbon/Carbon.h>#endifconst int VSTEFFECT_SLIDER_ID = 13100;const int PREVIEW_ID = 13101;class VSTEffectGUIDialog : public wxDialog{public: VSTEffectGUIDialog(wxWindow * parent, wxWindowID id, const wxString & title, VSTEffect *effect, AEffect *aEffect); void OnOk(wxCommandEvent &event); void OnCancel(wxCommandEvent &event); void OnPreview(wxCommandEvent &event); void OnIdle(wxIdleEvent &event);private: VSTEffect *mEffect; AEffect *mAEffect; DECLARE_EVENT_TABLE()};BEGIN_EVENT_TABLE(VSTEffectGUIDialog,wxDialog) EVT_BUTTON( wxID_OK, VSTEffectGUIDialog::OnOk ) EVT_BUTTON( wxID_CANCEL, VSTEffectGUIDialog::OnCancel ) EVT_BUTTON( PREVIEW_ID, VSTEffectGUIDialog::OnPreview ) EVT_IDLE( VSTEffectGUIDialog::OnIdle )END_EVENT_TABLE()VSTEffectGUIDialog::VSTEffectGUIDialog(wxWindow *parent, wxWindowID id, const wxString & title, VSTEffect *effect, AEffect *aEffect): wxDialog(parent, id, title, wxDefaultPosition, wxDefaultSize, wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION), mEffect(effect), mAEffect(aEffect){ ERect *rect; mEffect->callDispatcher(mAEffect, effEditGetRect, 0, 0, &rect, 0.0); mEffect->callDispatcher(mAEffect, effEditOpen, 0, 0, (void *)GetHWND(), 0.0); wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL); mainSizer->Add(rect->right-rect->left, rect->bottom-rect->top); wxBoxSizer *hSizer = new wxBoxSizer(wxHORIZONTAL); wxButton *preview = new wxButton(this, PREVIEW_ID, mEffect->GetPreviewName()); hSizer->Add(preview, 0, wxALIGN_CENTRE|wxALL, 5); hSizer->Add(20, 10); // horizontal spacer wxButton *cancel = new wxButton(this, wxID_CANCEL, _("Cancel")); hSizer->Add(cancel, 0, wxALIGN_CENTRE|wxALL, 5); wxButton *ok = new wxButton(this, wxID_OK, _("OK")); ok->SetDefault(); ok->SetFocus(); hSizer->Add(ok, 0, wxALIGN_CENTRE|wxALL, 5); mainSizer->Add(hSizer, 0, wxALIGN_CENTRE|wxALIGN_CENTER_VERTICAL|wxALL, 5); SetAutoLayout(true); SetSizer(mainSizer); mainSizer->Fit(this); mainSizer->SetSizeHints(this);}void VSTEffectGUIDialog::OnIdle(wxIdleEvent &event){ mEffect->callDispatcher(mAEffect, effEditIdle, 0, 0, NULL, 0.0);}void VSTEffectGUIDialog::OnPreview(wxCommandEvent &event){ mEffect->Preview();}void VSTEffectGUIDialog::OnOk(wxCommandEvent &event){ mEffect->callDispatcher(mAEffect, effEditClose, 0, 0, NULL, 0.0); EndModal(true);}void VSTEffectGUIDialog::OnCancel(wxCommandEvent &event){ mEffect->callDispatcher(mAEffect, effEditClose, 0, 0, NULL, 0.0); EndModal(false);}VSTEffect::VSTEffect(wxString pluginName, AEffect * aEffect){ this->aEffect = aEffect; this->pluginName = pluginName; buffer = NULL; fInBuffer = NULL; fOutBuffer = NULL; isOpened = false;}VSTEffect::~VSTEffect(){}wxString VSTEffect::GetEffectName(){ return pluginName + "...";}wxString VSTEffect::GetEffectAction(){ return "Performing VST Effect: \""+pluginName+"\"";}bool VSTEffect::Init(){ inputs = aEffect->numInputs; outputs = aEffect->numOutputs; mBlockSize = 0; if (inputs > 1) { TrackListIterator iter(mWaveTracks); Track *left = iter.First(); while(left) { longSampleCount lstart, rstart; sampleCount llen, rlen; GetSamples((WaveTrack *)left, &lstart, &llen); if (left->GetLinked()) { Track *right = iter.Next(); GetSamples((WaveTrack *)right, &rstart, &rlen); if (llen != rlen || ((WaveTrack *)left)->GetRate() != ((WaveTrack *)right)->GetRate()) { wxMessageBox(_("Sorry, VST Effects cannot be performed on stereo tracks where " "the individual channels of the track do not match.")); return false; } } left = iter.Next(); } } return true;}bool VSTEffect::PromptUser(){ if (!(aEffect->flags & effFlagsCanReplacing)) { wxMessageBox(_("Can't process replacing")); return false; } if (aEffect->flags & effFlagsHasEditor) { // Show native GUI VSTEffectGUIDialog dlog(mParent, -1, pluginName, this, aEffect); dlog.CentreOnParent(); dlog.ShowModal(); return dlog.GetReturnCode(); } // Try to figure out how many parameters it takes by seeing how // many parameters have names char temp[8][256]; numParameters = 0; do { long result; temp[numParameters][0] = 0; result = callDispatcher(aEffect, effGetParamName, numParameters, 0, (void *) temp[numParameters], 0.0); if (temp[numParameters][0]==0) break; if (strstr(temp[numParameters], "ABOUT")) break; if (numParameters > 0 && !strcmp(temp[numParameters], temp[numParameters - 1])) break; numParameters++; } while (temp[0] != 0 && numParameters < 8); if (numParameters > 0) { VSTEffectDialog dlog(mParent, pluginName, numParameters, this, aEffect); dlog.CentreOnParent(); dlog.ShowModal(); if (!dlog.GetReturnCode()) return false; } return true;}void VSTEffect::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 VSTEffect::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); } // Reset the effect callDispatcher(aEffect, effOpen, 0, 0, NULL, 0.0); bool success = ProcessStereo(count, (WaveTrack *)left, (WaveTrack *)right, lstart, rstart, len); if (!success) return false; left = iter.Next(); count++; } return true;}bool VSTEffect::ProcessStereo(int count, WaveTrack *left, WaveTrack *right, longSampleCount lstart, longSampleCount rstart, sampleCount len){ if (mBlockSize == 0) { mBlockSize = left->GetMaxBlockSize() * 2; buffer = new float[mBlockSize]; fInBuffer = new float *[inputs]; int 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]; } callDispatcher(aEffect, effSetSampleRate, 0, 0, NULL, (float) left->GetRate()); callDispatcher(aEffect, effSetBlockSize, 0, mBlockSize * 2, NULL, 0.0); // Actually perform the effect here sampleCount originalLen = len; longSampleCount ls = lstart; longSampleCount rs = rstart; while (len) { int i; int block = mBlockSize; if (block > len) block = len; left->Get((samplePtr)buffer, floatSample, ls, block); for (i = 0; i < block; i++) fInBuffer[0][i] = buffer[i]; if (right) { right->Get((samplePtr)buffer, floatSample, rs, block); for (i = 0; i < block; i++) fInBuffer[1][i] = buffer[i]; } callProcessReplacing(aEffect, fInBuffer, fOutBuffer, block);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -