Audacity 3.2.0
Classes | Public Member Functions | Static Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | List of all members
VST3Wrapper Class Reference

#include <VST3Wrapper.h>

Collaboration diagram for VST3Wrapper:
[legend]

Classes

struct  FactoryPresetDesc
 

Public Member Functions

 VST3Wrapper (VST3::Hosting::Module &module, const VST3::Hosting::ClassInfo &effectClassInfo)
 
 ~VST3Wrapper ()
 
 VST3Wrapper (const VST3Wrapper &)=delete
 
 VST3Wrapper (VST3Wrapper &&)=delete
 
VST3Wrapperoperator= (const VST3Wrapper &)=delete
 
VST3Wrapperoperator= (VST3Wrapper &&)=delete
 
void InitializeComponents ()
 Should be called once before almost any other method call. More...
 
VST3::Hosting::Module & GetModule () const
 
const VST3::Hosting::ClassInfo & GetEffectClassInfo () const
 
bool IsActive () const noexcept
 
void FetchSettings (EffectSettings &)
 Fetch state from settings object, may change internal runtime data. More...
 
void StoreSettings (EffectSettings &) const
 Saves current state inside settings object, clears all runtime data. More...
 
void LoadPreset (const wxString &presetId)
 
void SavePresetToFile (const wxString &filepath) const
 
bool Initialize (EffectSettings &settings, Steinberg::Vst::SampleRate sampleRate, Steinberg::int32 processMode, Steinberg::int32 maxSamplesPerBlock)
 Initializes effect for processing using settings. More...
 
void Finalize (EffectSettings *settings)
 
void ProcessBlockStart (const EffectSettings &settings)
 Prepares effect to process next block with changes written to the settings object. More...
 
void FlushParameters (EffectSettings &settings, bool *hasChanges=nullptr)
 
size_t Process (const float *const *inBlock, float *const *outBlock, size_t blockLen)
 
void SuspendProcessing ()
 
void ResumeProcessing ()
 
void BeginParameterEdit (EffectSettingsAccess &access)
 
void EndParameterEdit ()
 
std::vector< FactoryPresetDescFindFactoryPresets () const
 
Steinberg::int32 GetLatencySamples () const
 

Static Public Member Functions

static EffectSettings MakeSettings ()
 
static void LoadSettings (const CommandParameters &parms, EffectSettings &settings)
 
static void SaveSettings (const EffectSettings &settings, CommandParameters &parms)
 
static OptionalMessage LoadUserPreset (const EffectDefinitionInterface &effect, const RegistryPath &name, EffectSettings &settings)
 
static void SaveUserPreset (const EffectDefinitionInterface &effect, const RegistryPath &name, const EffectSettings &settings)
 
static void CopySettingsContents (const EffectSettings &src, EffectSettings &dst)
 

Public Attributes

Steinberg::IPtr< Steinberg::Vst::IAudioProcessor > mAudioProcessor
 
Steinberg::Vst::ProcessSetup mSetup
 
Steinberg::IPtr< Steinberg::Vst::IComponent > mEffectComponent
 
Steinberg::IPtr< Steinberg::Vst::IEditController > mEditController
 
Steinberg::IPtr< Steinberg::Vst::IConnectionPoint > mComponentConnectionProxy
 
Steinberg::IPtr< Steinberg::Vst::IConnectionPoint > mControllerConnectionProxy
 
Steinberg::IPtr< Steinberg::Vst::IComponentHandler > mComponentHandler
 
std::function< void(Steinberg::Vst::ParamID, Steinberg::Vst::ParamValue)> ParamChangedHandler
 

Private Member Functions

bool LoadPresetFromStream (Steinberg::IBStream *fileStream)
 
bool SavePresetToStream (Steinberg::IBStream *fileStream) const
 
void ConsumeChanges (const EffectSettings &settings)
 

Private Attributes

EffectSettings mDefaultSettings
 
VST3::Hosting::Module & mModule
 
const VST3::Hosting::ClassInfo & mEffectClassInfo
 
bool mActive {false}
 
std::vector< std::pair< Steinberg::Vst::ParamID, Steinberg::Vst::ParamValue > > mParameters
 
std::unique_ptr< SingleInputParameterValue[]> mParameterQueues
 
Steinberg::Vst::ProcessContext mProcessContext { }
 

Detailed Description

Definition at line 54 of file VST3Wrapper.h.

Constructor & Destructor Documentation

◆ VST3Wrapper() [1/3]

VST3Wrapper::VST3Wrapper ( VST3::Hosting::Module &  module,
const VST3::Hosting::ClassInfo &  effectClassInfo 
)

Definition at line 407 of file VST3Wrapper.cpp.

408 : mModule{ module }
409 , mEffectClassInfo { effectClassInfo }
410{
411 using namespace Steinberg;
412
413 const auto& pluginFactory = module.getFactory();
414
415 auto effectComponent = pluginFactory.createInstance<Vst::IComponent>(effectClassInfo.ID());
416 if(!effectComponent)
417 throw std::runtime_error("Cannot create VST3 effect component");
418 if(effectComponent->initialize(&AudacityVst3HostApplication::Get()) != kResultOk)
419 throw std::runtime_error("Cannot initialize VST3 effect component");
420
421 auto audioProcessor = FUnknownPtr<Vst::IAudioProcessor>(effectComponent);
422 if(!audioProcessor)
423 //It's stated that "This interface must always be supported by audio processing plug-ins."
424 throw std::runtime_error("VST3 plugin does not provide audio processor interface");
425
426 if(audioProcessor->canProcessSampleSize(Vst::kSample32) != kResultTrue)
427 throw std::runtime_error("32-bit sample size not supported");
428
429 mEffectComponent = effectComponent;
430 mAudioProcessor = audioProcessor;
431
432 auto editController = FUnknownPtr<Vst::IEditController>(mEffectComponent);
433 if(editController.get() == nullptr)
434 {
435 TUID controllerCID;
436
437 if (mEffectComponent->getControllerClassId (controllerCID) == kResultTrue)
438 editController = pluginFactory.createInstance<Vst::IEditController>(VST3::UID(controllerCID));
439 }
440
441 if(editController.get() == nullptr)
442 throw std::runtime_error("Failed to instantiate edit controller");
443
444 mEditController = editController;
445
447
448 mComponentHandler = owned(safenew ComponentHandler(*this));
449 mEditController->setComponentHandler(mComponentHandler);
450
451 const auto componentConnectionPoint = FUnknownPtr<Vst::IConnectionPoint>{ mEffectComponent };
452 const auto controllerConnectionPoint = FUnknownPtr<Vst::IConnectionPoint>{ mEditController };
453
454 if (componentConnectionPoint && controllerConnectionPoint)
455 {
456 mComponentConnectionProxy = owned(safenew internal::ConnectionProxy(componentConnectionPoint));
457 mControllerConnectionProxy = owned(safenew internal::ConnectionProxy(controllerConnectionPoint));
458
459 mComponentConnectionProxy->connect(controllerConnectionPoint);
460 mControllerConnectionProxy->connect(componentConnectionPoint);
461 }
462
463 if(GetCache(mEffectClassInfo.ID()) == nullptr)
464 {
465 //First time instantiation...
466 auto& cache = CreateCache(mEffectClassInfo.ID());
467
468 //Find root unit program change parameter ID (if any)
469 for(int32 parameterIndex = 0, parametersCount = mEditController->getParameterCount();
470 parameterIndex < parametersCount;
471 ++parameterIndex)
472 {
473 Vst::ParameterInfo parameterInfo {};
474 if(mEditController->getParameterInfo(parameterIndex, parameterInfo) != kResultOk)
475 continue;
476
477 if(parameterInfo.unitId != Vst::kRootUnitId)
478 continue;
479 if((parameterInfo.flags & Vst::ParameterInfo::kIsProgramChange) == 0)
480 continue;
481
482 auto unitInfoProvider = FUnknownPtr<Vst::IUnitInfo>(mEditController);
483 if(!unitInfoProvider)
484 //Sanity check...
485 break;
486
487 for(int32 unitIndex = 0, unitCount = unitInfoProvider->getUnitCount();
488 unitIndex < unitCount;
489 ++unitIndex)
490 {
491 Vst::UnitInfo unitInfo{};
492 if(unitInfoProvider->getUnitInfo(unitIndex, unitInfo) != kResultOk)
493 continue;
494
495 if(unitInfo.id != Vst::kRootUnitId)
496 continue;
497
498 for(int32 programListIndex = 0, programListCount = unitInfoProvider->getProgramListCount();
499 programListIndex < programListCount;
500 ++programListIndex)
501 {
502 Vst::ProgramListInfo programListInfo{};
503 if(unitInfoProvider->getProgramListInfo(programListIndex, programListInfo) != kResultOk)
504 continue;
505
506 if(programListInfo.id != unitInfo.programListId)//unitInfo.id == kRootUnitId
507 continue;
508
509 cache.rootUnitProgramListID = programListInfo.id;
510 cache.rootUnitProgramCount = programListInfo.programCount;
511 break;
512 }
513
514 if(cache.rootUnitProgramListID == Vst::kNoProgramListId)
515 cache.rootUnitProgramCount = parameterInfo.stepCount + 1;
516
517 cache.rootUnitProgramChangeParameterID = parameterInfo.id;
518
519 break;
520 }
521
522 break;
523 }
524 }
525}
#define safenew
Definition: MemoryX.h:9
Steinberg::IPtr< Steinberg::Vst::IConnectionPoint > mControllerConnectionProxy
Definition: VST3Wrapper.h:72
Steinberg::IPtr< Steinberg::Vst::IEditController > mEditController
Definition: VST3Wrapper.h:70
Steinberg::IPtr< Steinberg::Vst::IComponent > mEffectComponent
Definition: VST3Wrapper.h:69
Steinberg::IPtr< Steinberg::Vst::IComponentHandler > mComponentHandler
Definition: VST3Wrapper.h:73
const VST3::Hosting::ClassInfo & mEffectClassInfo
Definition: VST3Wrapper.h:58
VST3::Hosting::Module & mModule
Definition: VST3Wrapper.h:57
Steinberg::IPtr< Steinberg::Vst::IConnectionPoint > mComponentConnectionProxy
Definition: VST3Wrapper.h:71
Steinberg::IPtr< Steinberg::Vst::IAudioProcessor > mAudioProcessor
Definition: VST3Wrapper.h:67
Host's proxy object between connection points.
VST3PluginCache & CreateCache(const VST3::UID &effectUid)
Definition: VST3Wrapper.cpp:50
VST3PluginCache * GetCache(const VST3::UID &effectUid)
Definition: VST3Wrapper.cpp:41

References anonymous_namespace{VST3Wrapper.cpp}::CreateCache(), AudacityVst3HostApplication::Get(), anonymous_namespace{VST3Wrapper.cpp}::GetCache(), mAudioProcessor, mComponentConnectionProxy, mComponentHandler, mControllerConnectionProxy, mEditController, mEffectClassInfo, mEffectComponent, and safenew.

Here is the call graph for this function:

◆ ~VST3Wrapper()

VST3Wrapper::~VST3Wrapper ( )

Definition at line 527 of file VST3Wrapper.cpp.

528{
529 using namespace Steinberg;
530
532 mComponentConnectionProxy->disconnect(FUnknownPtr<Vst::IConnectionPoint>(mEditController));
534 mControllerConnectionProxy->disconnect(FUnknownPtr<Vst::IConnectionPoint>(mEffectComponent));
535
537 {
538 mEditController->setComponentHandler(nullptr);
539 mEditController->terminate();
540 }
542 mEffectComponent->terminate();
543}

References mComponentConnectionProxy, mControllerConnectionProxy, mEditController, and mEffectComponent.

◆ VST3Wrapper() [2/3]

VST3Wrapper::VST3Wrapper ( const VST3Wrapper )
delete

◆ VST3Wrapper() [3/3]

VST3Wrapper::VST3Wrapper ( VST3Wrapper &&  )
delete

Member Function Documentation

◆ BeginParameterEdit()

void VST3Wrapper::BeginParameterEdit ( EffectSettingsAccess access)

Definition at line 959 of file VST3Wrapper.cpp.

960{
961 static_cast<ComponentHandler*>(mComponentHandler.get())->SetAccess(&access);
962}

References mComponentHandler.

Referenced by VST3Editor::VST3Editor().

Here is the caller graph for this function:

◆ ConsumeChanges()

void VST3Wrapper::ConsumeChanges ( const EffectSettings settings)
private

Definition at line 803 of file VST3Wrapper.cpp.

804{
805 const auto& vst3settings = GetSettings(settings);
806 for(auto& p : vst3settings.parameterChanges)
807 {
808 auto it = std::find_if(mParameters.begin(), mParameters.end(), [&p](const auto& v) { return v.first == p.first; });
809 if(it != mParameters.end())
810 it->second = p.second;
811 else
812 mParameters.push_back(p);
813 }
814}
static Settings & settings()
Definition: TrackInfo.cpp:69
std::vector< std::pair< Steinberg::Vst::ParamID, Steinberg::Vst::ParamValue > > mParameters
Definition: VST3Wrapper.h:155
const VST3EffectSettings & GetSettings(const EffectSettings &settings)

References anonymous_namespace{VST3Wrapper.cpp}::GetSettings(), mParameters, and settings().

Referenced by Finalize(), FlushParameters(), Initialize(), and ProcessBlockStart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CopySettingsContents()

void VST3Wrapper::CopySettingsContents ( const EffectSettings src,
EffectSettings dst 
)
static

Definition at line 1103 of file VST3Wrapper.cpp.

1104{
1105 auto& from = GetSettings(*const_cast<EffectSettings*>(&src));
1106 auto& to = GetSettings(dst);
1107
1108 //Don't allocate in worker
1109 std::swap(from.parameterChanges, to.parameterChanges);
1110}
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:645
Externalized state of a plug-in.

References anonymous_namespace{VST3Wrapper.cpp}::GetSettings(), and anonymous_namespace{NoteTrack.cpp}::swap().

Referenced by VST3EffectBase::CopySettingsContents().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ EndParameterEdit()

void VST3Wrapper::EndParameterEdit ( )

Definition at line 964 of file VST3Wrapper.cpp.

965{
966 auto componentHandler = static_cast<ComponentHandler*>(mComponentHandler.get());
967 componentHandler->SetAccess(nullptr);
968}

References mComponentHandler.

Referenced by VST3Editor::OnClose().

Here is the caller graph for this function:

◆ FetchSettings()

void VST3Wrapper::FetchSettings ( EffectSettings settings)

Fetch state from settings object, may change internal runtime data.

Definition at line 593 of file VST3Wrapper.cpp.

594{
595 //TODO: perform version check
596 {
597 auto componentHandler = static_cast<ComponentHandler*>(mComponentHandler.get());
598 componentHandler->ResetCache();
599 componentHandler->BeginStateChange(settings);
600 auto cleanup = finally([&] { componentHandler->EndStateChange(); });
601
602 //Restore state
603 const auto* vst3settings = &GetSettings(settings);
604 if(!vst3settings->processorState.has_value())
606
607 if(vst3settings->processorState.has_value())
608 {
609 auto processorState = PresetsBufferStream::fromString(*vst3settings->processorState);
610 processorState->seek(0, Steinberg::IBStream::kIBSeekSet);
611 if(mEffectComponent->setState(processorState) == Steinberg::kResultOk)
612 {
613 processorState->seek(0, Steinberg::IBStream::kIBSeekSet);
614 if(mEditController->setComponentState(processorState) == Steinberg::kResultOk)
615 {
616 if(vst3settings->controllerState.has_value())
617 {
618 auto controllerState = PresetsBufferStream::fromString(*vst3settings->controllerState);
619 controllerState->seek(0, Steinberg::IBStream::kIBSeekSet);
620 mEditController->setState(controllerState);
621 }
622 }
623 }
624 }
625 }
626 //restore parameters if present
627 auto& vst3setting = GetSettings(settings);
628 for(auto& p : vst3setting.parameterChanges)
629 mEditController->setParamNormalized(p.first, p.second);
630}
static Steinberg::IPtr< PresetsBufferStream > fromString(const wxString &str)
Definition: VST3Utils.cpp:153

References anonymous_namespace{VST3Wrapper.cpp}::VST3PluginCache::defaultSettings, PresetsBufferStream::fromString(), anonymous_namespace{VST3Wrapper.cpp}::GetCache(), anonymous_namespace{VST3Wrapper.cpp}::GetSettings(), mComponentHandler, mEditController, mEffectClassInfo, mEffectComponent, and settings().

Referenced by Initialize(), and VST3Editor::UpdateUI().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Finalize()

void VST3Wrapper::Finalize ( EffectSettings settings)

Frees up resources allocated for processing, should be called after processing is complete. Optionally settings object may be passed to update runtime data with current internal state.

Definition at line 780 of file VST3Wrapper.cpp.

781{
782 //Could be FlushParameters but processor is already configured
783 //If no calls to process were performed deliver changes here
784 mProcessContext.state = 0;
785 if(settings != nullptr)
786 {
788 Process(nullptr, nullptr, 0);
789 }
790 mAudioProcessor->setProcessing(false);
791 mEffectComponent->setActive(false);
792 mActive = false;
793
794 if(settings != nullptr)
796}
size_t Process(const float *const *inBlock, float *const *outBlock, size_t blockLen)
Steinberg::Vst::ProcessContext mProcessContext
Definition: VST3Wrapper.h:162
void StoreSettings(EffectSettings &) const
Saves current state inside settings object, clears all runtime data.
void ConsumeChanges(const EffectSettings &settings)

References ConsumeChanges(), mActive, mAudioProcessor, mEffectComponent, mProcessContext, Process(), settings(), and StoreSettings().

Here is the call graph for this function:

◆ FindFactoryPresets()

std::vector< VST3Wrapper::FactoryPresetDesc > VST3Wrapper::FindFactoryPresets ( ) const

Returns an array of factory preset ids. Safe to call before InitializeComponents

Definition at line 970 of file VST3Wrapper.cpp.

971{
972 using namespace Steinberg;
973
974 wxArrayString paths;
975 wxDir::GetAllFiles(VST3Utils::GetFactoryPresetsPath(mEffectClassInfo), &paths);
976
977 std::vector<FactoryPresetDesc> result;
978 for(auto& path : paths)
979 {
980 wxFileName filename(path);
981 result.push_back({ filename.GetFullPath(), filename.GetName() });
982 }
983
984 auto cache = GetCache(mEffectClassInfo.ID());
985 if(cache->rootUnitProgramChangeParameterID != Vst::kNoParamId &&
986 cache->rootUnitProgramCount > 0)
987 {
988 Vst::String128 programName;
989 if(cache->rootUnitProgramListID != Vst::kNoProgramListId)
990 {
991 auto unitInfoProvider = FUnknownPtr<Vst::IUnitInfo>(mEditController);
992
993 for(int32 programIndex = 0, programCount = cache->rootUnitProgramCount;
994 programIndex < programCount;
995 ++programIndex)
996 {
997 if(unitInfoProvider->getProgramName(cache->rootUnitProgramListID, programIndex, programName) != kResultOk)
998 programName[0] = 0;
999 auto presetDisplayName = VST3Utils::ToWxString(programName);
1000 if(presetDisplayName.empty())
1001 presetDisplayName = wxString::Format("Unit %03d - %04d", Vst::kRootUnitId, programIndex);
1002
1003 result.push_back({
1004 VST3Utils::MakeFactoryPresetID(Vst::kRootUnitId, programIndex),
1005 presetDisplayName
1006 });
1007 }
1008 }
1009 else
1010 {
1011 for(int32_t programIndex = 0; programIndex < cache->rootUnitProgramCount; ++programIndex)
1012 {
1013 auto normalizedValue = mEditController->plainParamToNormalized(cache->rootUnitProgramChangeParameterID, programIndex);
1014 if(mEditController->getParamStringByValue(cache->rootUnitProgramChangeParameterID, normalizedValue, programName) == kResultOk)
1015 {
1016 result.push_back({
1017 VST3Utils::MakeFactoryPresetID(Vst::kRootUnitId, programIndex),
1018 VST3Utils::ToWxString(programName)
1019 });
1020 }
1021 }
1022 }
1023 }
1024
1025 return result;
1026}
static wxString GetFactoryPresetsPath(const VST3::Hosting::ClassInfo &effectClassInfo)
Definition: VST3Utils.cpp:145
static wxString MakeFactoryPresetID(Steinberg::Vst::UnitID unitId, Steinberg::int32 programIndex)
Definition: VST3Utils.cpp:124
static wxString ToWxString(const Steinberg::Vst::TChar *str)
Definition: VST3Utils.cpp:93

References anonymous_namespace{VST3Wrapper.cpp}::GetCache(), VST3Utils::GetFactoryPresetsPath(), VST3Utils::MakeFactoryPresetID(), mEditController, mEffectClassInfo, and VST3Utils::ToWxString().

Referenced by VST3EffectBase::GetFactoryPresets().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ FlushParameters()

void VST3Wrapper::FlushParameters ( EffectSettings settings,
bool *  hasChanges = nullptr 
)
Parameters
hasChangesoptional output variable, set to true if flushing has changed the DSP model state

Definition at line 825 of file VST3Wrapper.cpp.

826{
827 if(!mActive)
828 {
829 auto componentHandler = static_cast<ComponentHandler*>(mComponentHandler.get());
830 componentHandler->FlushCache(settings);
831
832 const auto doProcessing = !GetSettings(settings).parameterChanges.empty();
833
834 if(hasChanges != nullptr)
835 *hasChanges = doProcessing;
836
837 if(!doProcessing)
838 return;
839
841 mActive = true;
842 if(mEffectComponent->setActive(true) == Steinberg::kResultOk)
843 {
845 if(mAudioProcessor->setProcessing(true) != Steinberg::kResultFalse)
846 {
847 mProcessContext.sampleRate = mSetup.sampleRate;
848 mProcessContext.state = 0;
849 Process(nullptr, nullptr, 0);
850 mAudioProcessor->setProcessing(false);
851 }
852 }
853 mEffectComponent->setActive(false);
854 mActive = false;
855 }
856 else if(hasChanges != nullptr)
857 *hasChanges = false;
858}
Steinberg::Vst::ProcessSetup mSetup
Definition: VST3Wrapper.h:68
bool SetupProcessing(Steinberg::Vst::IComponent &component, Steinberg::Vst::ProcessSetup &setup)
std::map< Steinberg::Vst::ParamID, Steinberg::Vst::ParamValue > parameterChanges
Holds the parameter that has been changed since last processing pass.
Definition: VST3Wrapper.cpp:70

References ConsumeChanges(), anonymous_namespace{VST3Wrapper.cpp}::GetSettings(), mActive, mAudioProcessor, mComponentHandler, mEffectComponent, mProcessContext, mSetup, anonymous_namespace{VST3Wrapper.cpp}::VST3EffectSettings::parameterChanges, Process(), settings(), and anonymous_namespace{VST3Wrapper.cpp}::SetupProcessing().

Referenced by VST3EffectBase::LoadFactoryPreset(), VST3Editor::OnClose(), VST3Editor::OnIdle(), and VST3Editor::ValidateUI().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetEffectClassInfo()

const VST3::Hosting::ClassInfo & VST3Wrapper::GetEffectClassInfo ( ) const

Definition at line 583 of file VST3Wrapper.cpp.

584{
585 return mEffectClassInfo;
586}

References mEffectClassInfo.

◆ GetLatencySamples()

Steinberg::int32 VST3Wrapper::GetLatencySamples ( ) const

Definition at line 1029 of file VST3Wrapper.cpp.

1030{
1031 return mAudioProcessor->getLatencySamples();
1032}

References mAudioProcessor.

◆ GetModule()

VST3::Hosting::Module & VST3Wrapper::GetModule ( ) const
inline

Definition at line 86 of file VST3Wrapper.h.

86{ return mModule; }

◆ Initialize()

bool VST3Wrapper::Initialize ( EffectSettings settings,
Steinberg::Vst::SampleRate  sampleRate,
Steinberg::int32  processMode,
Steinberg::int32  maxSamplesPerBlock 
)

Initializes effect for processing using settings.

Definition at line 744 of file VST3Wrapper.cpp.

745{
746 using namespace Steinberg;
747
748 Vst::ProcessSetup setup = {
749 processMode,
750 Vst::kSample32,
751 maxSamplesPerBlock,
753 };
754
755 if(!SetupProcessing(*mEffectComponent.get(), setup))
756 return false;
757
758 mSetup = setup;
759
761
762 if(mEffectComponent->setActive(true) == kResultOk)
763 {
764 if(mAudioProcessor->setProcessing(true) != kResultFalse)
765 {
766 mProcessContext.state = Vst::ProcessContext::kPlaying;
767 mProcessContext.sampleRate = sampleRate;
768
769 mActive = true;
771 //make zero-flush, to make sure parameters are delivered to the processor...
772 Process(nullptr, nullptr, 0);
774 return true;
775 }
776 }
777 return false;
778}
void FetchSettings(EffectSettings &)
Fetch state from settings object, may change internal runtime data.

References ConsumeChanges(), FetchSettings(), mActive, mAudioProcessor, mEffectComponent, mProcessContext, mSetup, Process(), anonymous_namespace{ClipSegmentTest.cpp}::sampleRate, settings(), anonymous_namespace{VST3Wrapper.cpp}::SetupProcessing(), and StoreSettings().

Here is the call graph for this function:

◆ InitializeComponents()

void VST3Wrapper::InitializeComponents ( )

Should be called once before almost any other method call.

Definition at line 545 of file VST3Wrapper.cpp.

546{
547 using namespace Steinberg;
548
549 //Preinitialize with some default values in case if parameters
550 //flush happens before processing initialized
551 mSetup.maxSamplesPerBlock = 512;
552 mSetup.processMode = Vst::kOffline;
553 mSetup.symbolicSampleSize = Vst::kSample32;
554 mSetup.sampleRate = 44100.0;
555
557 throw std::runtime_error("bus configuration not supported");
558
559 mParameterQueues = std::make_unique<SingleInputParameterValue[]>(mEditController->getParameterCount());
560 mParameters.reserve(mEditController->getParameterCount());
561
562 Steinberg::MemoryStream stateStream;
563 if(mEffectComponent->getState(&stateStream) == kResultOk)
564 {
565 int64 unused;
566 stateStream.seek(0, IBStream::kIBSeekSet, &unused);
567 mEditController->setComponentState(&stateStream);
568 }
569
570 {
571 auto cache = GetCache(mEffectClassInfo.ID());
572 if(!cache->defaultSettings.has_value())
573 {
574 cache->defaultSettings = MakeSettings();
575 StoreSettings(cache->defaultSettings);
576 }
577 }
578
579 static_cast<ComponentHandler*>(mComponentHandler.get())
580 ->LoadCurrentParamValues();
581}
tresult PLUGIN_API seek(int64 pos, int32 mode, int64 *result) SMTG_OVERRIDE
static EffectSettings MakeSettings()
std::unique_ptr< SingleInputParameterValue[]> mParameterQueues
Definition: VST3Wrapper.h:160

References anonymous_namespace{VST3Wrapper.cpp}::GetCache(), MakeSettings(), mComponentHandler, mEditController, mEffectClassInfo, mEffectComponent, mParameterQueues, mParameters, mSetup, Steinberg::MemoryStream::seek(), anonymous_namespace{VST3Wrapper.cpp}::SetupProcessing(), and StoreSettings().

Referenced by VST3EffectBase::LoadFactoryPreset(), and VST3PluginValidator::Validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsActive()

bool VST3Wrapper::IsActive ( ) const
noexcept

Definition at line 588 of file VST3Wrapper.cpp.

589{
590 return mActive;
591}

References mActive.

Referenced by VST3Editor::OnIdle(), and anonymous_namespace{VST3Wrapper.cpp}::ComponentHandler::performEdit().

Here is the caller graph for this function:

◆ LoadPreset()

void VST3Wrapper::LoadPreset ( const wxString &  presetId)

Definition at line 652 of file VST3Wrapper.cpp.

653{
654 using namespace Steinberg;
655
656 auto cache = GetCache(mEffectClassInfo.ID());
657
658 if(cache->rootUnitProgramChangeParameterID != Vst::kNoParamId &&
659 cache->rootUnitProgramCount > 0)
660 {
661 Vst::UnitID unitId;
662 int32 programIndex;
663 if(VST3Utils::ParseFactoryPresetID(presetId, unitId, programIndex) &&
664 programIndex >= 0 && programIndex < cache->rootUnitProgramCount)
665 {
666 auto paramValueNormalized = static_cast<Vst::ParamValue>(programIndex);
667 if(cache->rootUnitProgramCount > 1)
668 paramValueNormalized /= static_cast<Vst::ParamValue>(cache->rootUnitProgramCount - 1);
669
670 mEditController->setParamNormalized(
671 cache->rootUnitProgramChangeParameterID,
672 paramValueNormalized);
673
675 {
676 mComponentHandler->beginEdit(cache->rootUnitProgramChangeParameterID);
677 auto commit = finally([&] { mComponentHandler->endEdit(cache->rootUnitProgramChangeParameterID); });
678 mComponentHandler->performEdit(
679 cache->rootUnitProgramChangeParameterID,
680 paramValueNormalized);
681 }
682
683 return;
684 }
685 }
686
687 auto fileStream = owned(Vst::FileStream::open(presetId.c_str(), "rb"));
688 if(!fileStream)
690
691 if(!LoadPresetFromStream(fileStream))
692 {
695 XO("Unable to apply VST3 preset file %s").Format(presetId),
696 XO("Error"));
697 }
698}
@ BadEnvironment
Indicates problems with environment, such as a full disk.
XO("Cut/Copy/Paste")
Thrown for failure of file or database operations in deeply nested places.
Definition: FileException.h:19
Abstract base class used in importing a file.
A MessageBoxException that shows a given, unvarying string.
static bool ParseFactoryPresetID(const wxString &presetId, Steinberg::Vst::UnitID &unitId, Steinberg::int32 &programIndex)
Definition: VST3Utils.cpp:131
bool LoadPresetFromStream(Steinberg::IBStream *fileStream)

References BadEnvironment, anonymous_namespace{VST3Wrapper.cpp}::GetCache(), LoadPresetFromStream(), mComponentHandler, mEditController, mEffectClassInfo, FileException::Open, VST3Utils::ParseFactoryPresetID(), and XO().

Referenced by VST3EffectBase::LoadFactoryPreset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadPresetFromStream()

bool VST3Wrapper::LoadPresetFromStream ( Steinberg::IBStream *  fileStream)
private

Definition at line 716 of file VST3Wrapper.cpp.

717{
718 using namespace Steinberg;
719
720 return Vst::PresetFile::loadPreset
721 (
722 fileStream,
723 FUID::fromTUID(mEffectClassInfo.ID().data()),
724 mEffectComponent.get(),
725 mEditController.get()
726 );
727}

References mEditController, mEffectClassInfo, and mEffectComponent.

Referenced by LoadPreset().

Here is the caller graph for this function:

◆ LoadSettings()

void VST3Wrapper::LoadSettings ( const CommandParameters parms,
EffectSettings settings 
)
static

Definition at line 1039 of file VST3Wrapper.cpp.

1040{
1041 VST3EffectSettings vst3settings;
1042
1043 if(parms.HasEntry(processorStateKey))
1044 {
1045 vst3settings.processorState = parms.Read(processorStateKey);
1046 if(parms.HasEntry(controllerStateKey))
1047 vst3settings.controllerState = parms.Read(controllerStateKey);
1048 }
1049 if(parms.HasEntry(parametersKey))
1050 vst3settings.parameterChanges = ParametersFromString(parms.Read(parametersKey));
1051
1052 std::swap(vst3settings, GetSettings(settings));
1053}
virtual bool HasEntry(const wxString &strName) const override
std::map< Steinberg::Vst::ParamID, Steinberg::Vst::ParamValue > ParametersFromString(const wxString &str)
Definition: VST3Wrapper.cpp:78

References anonymous_namespace{VST3Wrapper.cpp}::controllerStateKey, anonymous_namespace{VST3Wrapper.cpp}::GetSettings(), CommandParameters::HasEntry(), anonymous_namespace{VST3Wrapper.cpp}::ParametersFromString(), anonymous_namespace{VST3Wrapper.cpp}::parametersKey, anonymous_namespace{VST3Wrapper.cpp}::processorStateKey, settings(), and anonymous_namespace{NoteTrack.cpp}::swap().

Referenced by VST3EffectBase::LoadSettings().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadUserPreset()

OptionalMessage VST3Wrapper::LoadUserPreset ( const EffectDefinitionInterface effect,
const RegistryPath name,
EffectSettings settings 
)
static

Definition at line 1067 of file VST3Wrapper.cpp.

1069{
1070 VST3EffectSettings vst3settings;
1071
1072 wxString processorStateStr;
1073 if(GetConfig(effect, PluginSettings::Private, name, processorStateKey, processorStateStr, wxEmptyString))
1074 {
1075 vst3settings.processorState = processorStateStr;
1076 wxString controllerStateStr;
1077 if(GetConfig(effect, PluginSettings::Private, name, controllerStateKey, controllerStateStr, wxEmptyString))
1078 vst3settings.controllerState = controllerStateStr;
1079 }
1080 wxString parametersStr;
1081 if(GetConfig(effect, PluginSettings::Private, name, parametersKey, parametersStr, wxEmptyString))
1082 vst3settings.parameterChanges = ParametersFromString(parametersStr);
1083
1084 std::swap(vst3settings, GetSettings(settings));
1085 return { nullptr };
1086}
const TranslatableString name
Definition: Distortion.cpp:76
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)

References anonymous_namespace{VST3Wrapper.cpp}::controllerStateKey, PluginSettings::GetConfig(), anonymous_namespace{VST3Wrapper.cpp}::GetSettings(), name, anonymous_namespace{VST3Wrapper.cpp}::ParametersFromString(), anonymous_namespace{VST3Wrapper.cpp}::parametersKey, PluginSettings::Private, anonymous_namespace{VST3Wrapper.cpp}::processorStateKey, settings(), and anonymous_namespace{NoteTrack.cpp}::swap().

Referenced by VST3EffectBase::LoadUserPreset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MakeSettings()

EffectSettings VST3Wrapper::MakeSettings ( )
static

Definition at line 1034 of file VST3Wrapper.cpp.

1035{
1036 return EffectSettings::Make<VST3EffectSettings>();
1037}

Referenced by InitializeComponents(), and VST3EffectBase::MakeSettings().

Here is the caller graph for this function:

◆ operator=() [1/2]

VST3Wrapper & VST3Wrapper::operator= ( const VST3Wrapper )
delete

◆ operator=() [2/2]

VST3Wrapper & VST3Wrapper::operator= ( VST3Wrapper &&  )
delete

◆ Process()

size_t VST3Wrapper::Process ( const float *const *  inBlock,
float *const *  outBlock,
size_t  blockLen 
)

Definition at line 860 of file VST3Wrapper.cpp.

861{
862 using namespace Steinberg;
863
864 InputParameterChanges inputParameterChanges(mParameters, mParameterQueues.get());
865 mParameters.clear();
866
867 Vst::ProcessData data;
868 data.processMode = mSetup.processMode;
869 data.symbolicSampleSize = mSetup.symbolicSampleSize;
870 data.inputParameterChanges = &inputParameterChanges;
871 data.processContext = &mProcessContext;
872
873 static_assert(std::numeric_limits<decltype(blockLen)>::max()
874 >= std::numeric_limits<decltype(data.numSamples)>::max());
875
876 data.numSamples = static_cast<decltype(data.numSamples)>(std::min(
877 blockLen,
878 static_cast<decltype(blockLen)>(mSetup.maxSamplesPerBlock)
879 ));
880
881 data.numInputs = inBlock == nullptr ? 0 : mEffectComponent->getBusCount(Vst::kAudio, Vst::kInput);
882 data.numOutputs = outBlock == nullptr ? 0 : mEffectComponent->getBusCount(Vst::kAudio, Vst::kOutput);
883
884 if(data.numInputs > 0)
885 {
886 int inputBlocksOffset {0};
887
888 data.inputs = static_cast<Vst::AudioBusBuffers*>(
889 alloca(sizeof(Vst::AudioBusBuffers) * data.numInputs));
890
891 for(int busIndex = 0; busIndex < data.numInputs; ++busIndex)
892 {
893 Vst::BusInfo busInfo { };
894 if(mEffectComponent->getBusInfo(Vst::kAudio, Vst::kInput, busIndex, busInfo) != kResultOk)
895 {
896 return 0;
897 }
898 if(busInfo.busType == Vst::kMain)
899 {
900 data.inputs[busIndex].numChannels = busInfo.channelCount;
901 data.inputs[busIndex].channelBuffers32 = const_cast<float**>(inBlock + inputBlocksOffset);
902 inputBlocksOffset += busInfo.channelCount;
903 }
904 else
905 {
906 //aux is not yet supported
907 data.inputs[busIndex].numChannels = 0;
908 data.inputs[busIndex].channelBuffers32 = nullptr;
909 }
910 data.inputs[busIndex].silenceFlags = 0UL;
911 }
912 }
913 if(data.numOutputs > 0)
914 {
915 int outputBlocksOffset {0};
916
917 data.outputs = static_cast<Vst::AudioBusBuffers*>(
918 alloca(sizeof(Vst::AudioBusBuffers) * data.numOutputs));
919 for(int busIndex = 0; busIndex < data.numOutputs; ++busIndex)
920 {
921 Vst::BusInfo busInfo { };
922 if(mEffectComponent->getBusInfo(Vst::kAudio, Vst::kOutput, busIndex, busInfo) != kResultOk)
923 {
924 return 0;
925 }
926 if(busInfo.busType == Vst::kMain)
927 {
928 data.outputs[busIndex].numChannels = busInfo.channelCount;
929 data.outputs[busIndex].channelBuffers32 = const_cast<float**>(outBlock + outputBlocksOffset);
930 outputBlocksOffset += busInfo.channelCount;
931 }
932 else
933 {
934 //aux is not yet supported
935 data.outputs[busIndex].numChannels = 0;
936 data.outputs[busIndex].channelBuffers32 = nullptr;
937 }
938 data.outputs[busIndex].silenceFlags = 0UL;
939 }
940 }
941
942 const auto processResult = mAudioProcessor->process(data);
943
944 return processResult == kResultOk ?
945 data.numSamples : 0;
946}
int min(int a, int b)

References mAudioProcessor, mEffectComponent, min(), mParameterQueues, mParameters, mProcessContext, and mSetup.

Referenced by Finalize(), FlushParameters(), and Initialize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProcessBlockStart()

void VST3Wrapper::ProcessBlockStart ( const EffectSettings settings)

Prepares effect to process next block with changes written to the settings object.

Definition at line 798 of file VST3Wrapper.cpp.

799{
801}

References ConsumeChanges(), and settings().

Here is the call graph for this function:

◆ ResumeProcessing()

void VST3Wrapper::ResumeProcessing ( )

Definition at line 954 of file VST3Wrapper.cpp.

955{
956 mAudioProcessor->setProcessing(true);
957}

References mAudioProcessor.

◆ SavePresetToFile()

void VST3Wrapper::SavePresetToFile ( const wxString &  filepath) const

Definition at line 700 of file VST3Wrapper.cpp.

701{
702 using namespace Steinberg;
703
704 auto fileStream = owned(Vst::FileStream::open(filepath.c_str(), "wb"));
705 if(!fileStream)
707
708 if(!SavePresetToStream(fileStream))
711 XO("Failed to save VST3 preset to file"),
712 XO("Error"));
713}
bool SavePresetToStream(Steinberg::IBStream *fileStream) const

References BadEnvironment, FileException::Open, SavePresetToStream(), and XO().

Here is the call graph for this function:

◆ SavePresetToStream()

bool VST3Wrapper::SavePresetToStream ( Steinberg::IBStream *  fileStream) const
private

Definition at line 730 of file VST3Wrapper.cpp.

731{
732 using namespace Steinberg;
733
734 return Vst::PresetFile::savePreset
735 (
736 fileStream,
737 FUID::fromTUID(mEffectClassInfo.ID().data()),
738 mEffectComponent.get(),
739
740 mEditController.get()
741 );
742}

References mEditController, mEffectClassInfo, and mEffectComponent.

Referenced by SavePresetToFile().

Here is the caller graph for this function:

◆ SaveSettings()

void VST3Wrapper::SaveSettings ( const EffectSettings settings,
CommandParameters parms 
)
static

Definition at line 1055 of file VST3Wrapper.cpp.

1056{
1057 const auto& vst3settings = GetSettings(settings);
1058
1059 if(vst3settings.processorState.has_value())
1060 parms.Write(processorStateKey, *vst3settings.processorState);
1061 if(vst3settings.controllerState.has_value())
1062 parms.Write(controllerStateKey, *vst3settings.controllerState);
1063 if(!vst3settings.parameterChanges.empty())
1064 parms.Write(parametersKey, ParametersToString(vst3settings.parameterChanges));
1065}
wxString ParametersToString(const std::map< Steinberg::Vst::ParamID, Steinberg::Vst::ParamValue > &params)

References anonymous_namespace{VST3Wrapper.cpp}::controllerStateKey, anonymous_namespace{VST3Wrapper.cpp}::GetSettings(), anonymous_namespace{VST3Wrapper.cpp}::parametersKey, anonymous_namespace{VST3Wrapper.cpp}::ParametersToString(), anonymous_namespace{VST3Wrapper.cpp}::processorStateKey, and settings().

Referenced by VST3EffectBase::SaveSettings().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SaveUserPreset()

void VST3Wrapper::SaveUserPreset ( const EffectDefinitionInterface effect,
const RegistryPath name,
const EffectSettings settings 
)
static

Definition at line 1088 of file VST3Wrapper.cpp.

1089{
1090 using namespace Steinberg;
1091
1092 const auto& vst3settings = GetSettings(settings);
1093 if(vst3settings.processorState.has_value())
1094 {
1095 SetConfig(effect, PluginSettings::Private, name, processorStateKey, *vst3settings.processorState);
1096 if(vst3settings.controllerState.has_value())
1097 SetConfig(effect, PluginSettings::Private, name, controllerStateKey, *vst3settings.controllerState);
1098 }
1099 if(!vst3settings.parameterChanges.empty())
1100 SetConfig(effect, PluginSettings::Private, name, parametersKey, ParametersToString(vst3settings.parameterChanges));
1101}
bool SetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, const Value &value)

References anonymous_namespace{VST3Wrapper.cpp}::controllerStateKey, anonymous_namespace{VST3Wrapper.cpp}::GetSettings(), name, anonymous_namespace{VST3Wrapper.cpp}::parametersKey, anonymous_namespace{VST3Wrapper.cpp}::ParametersToString(), PluginSettings::Private, anonymous_namespace{VST3Wrapper.cpp}::processorStateKey, PluginSettings::SetConfig(), and settings().

Referenced by VST3EffectBase::SaveUserPreset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StoreSettings()

void VST3Wrapper::StoreSettings ( EffectSettings settings) const

Saves current state inside settings object, clears all runtime data.

Definition at line 632 of file VST3Wrapper.cpp.

633{
634 using namespace Steinberg;
635
636 VST3EffectSettings vst3settings;
637
638 {
639 PresetsBufferStream processorState;
640 if(mEffectComponent->getState(&processorState) == kResultOk)
641 vst3settings.processorState = processorState.toString();
642 }
643 {
644 PresetsBufferStream controllerState;
645 if(mEditController->getState(&controllerState) == kResultOk)
646 vst3settings.controllerState = controllerState.toString();
647 }
648
649 std::swap(vst3settings, GetSettings(settings));
650}
wxString toString() const
Definition: VST3Utils.cpp:167

References anonymous_namespace{VST3Wrapper.cpp}::GetSettings(), mEditController, mEffectComponent, settings(), anonymous_namespace{NoteTrack.cpp}::swap(), and PresetsBufferStream::toString().

Referenced by Finalize(), Initialize(), InitializeComponents(), VST3EffectBase::LoadFactoryPreset(), VST3Editor::OnClose(), VST3Editor::OnIdle(), and VST3Editor::ValidateUI().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SuspendProcessing()

void VST3Wrapper::SuspendProcessing ( )

Definition at line 949 of file VST3Wrapper.cpp.

950{
951 mAudioProcessor->setProcessing(false);
952}

References mAudioProcessor.

Member Data Documentation

◆ mActive

bool VST3Wrapper::mActive {false}
private

Definition at line 153 of file VST3Wrapper.h.

Referenced by Finalize(), FlushParameters(), Initialize(), and IsActive().

◆ mAudioProcessor

Steinberg::IPtr<Steinberg::Vst::IAudioProcessor> VST3Wrapper::mAudioProcessor

◆ mComponentConnectionProxy

Steinberg::IPtr<Steinberg::Vst::IConnectionPoint> VST3Wrapper::mComponentConnectionProxy

Definition at line 71 of file VST3Wrapper.h.

Referenced by VST3Wrapper(), and ~VST3Wrapper().

◆ mComponentHandler

Steinberg::IPtr<Steinberg::Vst::IComponentHandler> VST3Wrapper::mComponentHandler

◆ mControllerConnectionProxy

Steinberg::IPtr<Steinberg::Vst::IConnectionPoint> VST3Wrapper::mControllerConnectionProxy

Definition at line 72 of file VST3Wrapper.h.

Referenced by VST3Wrapper(), and ~VST3Wrapper().

◆ mDefaultSettings

EffectSettings VST3Wrapper::mDefaultSettings
private

Definition at line 56 of file VST3Wrapper.h.

◆ mEditController

Steinberg::IPtr<Steinberg::Vst::IEditController> VST3Wrapper::mEditController

◆ mEffectClassInfo

const VST3::Hosting::ClassInfo& VST3Wrapper::mEffectClassInfo
private

◆ mEffectComponent

Steinberg::IPtr<Steinberg::Vst::IComponent> VST3Wrapper::mEffectComponent

◆ mModule

VST3::Hosting::Module& VST3Wrapper::mModule
private

Definition at line 57 of file VST3Wrapper.h.

◆ mParameterQueues

std::unique_ptr<SingleInputParameterValue[]> VST3Wrapper::mParameterQueues
private

Definition at line 160 of file VST3Wrapper.h.

Referenced by InitializeComponents(), and Process().

◆ mParameters

std::vector<std::pair<Steinberg::Vst::ParamID, Steinberg::Vst::ParamValue> > VST3Wrapper::mParameters
private

Definition at line 155 of file VST3Wrapper.h.

Referenced by ConsumeChanges(), InitializeComponents(), and Process().

◆ mProcessContext

Steinberg::Vst::ProcessContext VST3Wrapper::mProcessContext { }
private

Definition at line 162 of file VST3Wrapper.h.

Referenced by Finalize(), FlushParameters(), Initialize(), and Process().

◆ mSetup

Steinberg::Vst::ProcessSetup VST3Wrapper::mSetup

◆ ParamChangedHandler

std::function<void (Steinberg::Vst::ParamID, Steinberg::Vst::ParamValue)> VST3Wrapper::ParamChangedHandler

The documentation for this class was generated from the following files: