Files
op-pedal/src/vst3/Vst3EffectImpl.hpp
2026-06-02 12:59:41 -04:00

302 lines
8.4 KiB
C++

/*
* MIT License
*
* Copyright (c) Robin E.R. Davies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "Vst3Effect.hpp"
#include <vector>
#include "RtInversionGuard.hpp"
#include "Vst3RtStream.hpp"
#pragma once
namespace pipedal
{
using namespace std;
using namespace pipedal;
using namespace VST3::Hosting;
using namespace Steinberg;
using namespace Steinberg::Vst;
enum
{
kMaxMidiMappingBusses = 4,
kMaxMidiChannels = 16
};
using Controllers = std::vector<int32>;
using Channels = std::array<Controllers, kMaxMidiChannels>;
using Busses = std::array<Channels, kMaxMidiMappingBusses>;
using MidiCCMapping = Busses;
class Vst3EffectImpl : public Vst3Effect,
public IAudioClient,
public IMidiClient
{
public:
//--------------------------------------------------------------------
using Name = std::string;
Vst3EffectImpl();
virtual ~Vst3EffectImpl();
void Load(uint64_t instanceId, const Vst3PluginInfo &info, IHost *pHost);
// IEffect
virtual bool IsVst3() const { return true; }
virtual uint64_t GetInstanceId() const { return instanceId; }
virtual int GetControlIndex(const std::string &symbol) const
{
for (size_t i = 0; i < info.pluginInfo_.controls().size(); ++i)
{
if (info.pluginInfo_.controls()[i].symbol() == symbol)
{
return (int)i;
}
}
return -1;
}
bool SupportsState() const { return supportsState; }
bool GetState(std::vector<uint8_t> *state);
void SetState(const std::vector<uint8_t> state);
const Lv2PluginUiInfo& GetCurrentPluginInfo();
virtual void CheckSync();
//- PluginHost Interfaces.
virtual void SetControl(int index, float value);
virtual float GetControlValue(int index) const
{
return this->parameterValues[index];
}
virtual std::vector<Vst3ProgramList> GetProgramList(int32_t programListId);
int bypassControl = -1;
bool bypassEnable = false;
virtual void SetBypass(bool enable)
{
if (bypassControl != -1)
{
SetControl(bypassControl, enable ? 1 : 0);
}
else
{
bypassEnable = enable;
}
}
virtual void Activate();
virtual void Deactivate();
virtual float GetOutputControlValue(int controlIndex) const
{
return this->parameterValues[controlIndex];
}
virtual int GetNumberOfInputAudioPorts() const
{
return info.pluginInfo_.audio_inputs();
}
virtual int GetNumberOfOutputAudioPorts() const
{
return info.pluginInfo_.audio_outputs();
}
virtual int GetNumberOfInputAudioBuffers() const { return buffers.inputs.size(); }
virtual int GetNumberOfOutputAudioPorts() const {return buffers.outputs.size(); }
virtual float *GetAudioInputBuffer(int index) const { return buffers.inputs[index]; }
virtual float *GetAudioOutputBuffer(int index) const { return buffers.outputs[index]; }
virtual int GetNumberOfInputAudioBuffers() const {
return buffers.inputs.size();
}
virtual int GetNumberOfInputAudioBuffers() const {
return buffers.outputs.size();
}
virtual void ResetAtomBuffers() {}
virtual void RequestParameter(LV2_URID uridUri) {} // no vst equivalent.
virtual void GatherPatchProperties(RealtimePatchPropertyRequest *pRequest) {} // no vst equivalent.
virtual void SetAudioInputBuffer(int index, float *buffer)
{
buffers.inputs[index] = buffer;
}
virtual void SetAudioOutputBuffer(int index, float *buffer)
{
buffers.outputs[index] = buffer;
}
virtual void Run(uint32_t samples, RealtimeRingBufferWriter *realtimeRingBufferWriter)
{
process(buffers, samples);
SendControlChanges(realtimeRingBufferWriter);
}
// Vst3Effect interfaces.
virtual void Prepare(int32_t sampleRate, size_t maxBufferSize, int inputChannels, int outputChannels);
virtual void Unprepare();
// IAudioClient
bool process(Buffers &buffers, int64_t continousFrames) override;
bool setSamplerate(SampleRate value) override;
bool setBlockSize(int32 value) override;
IAudioClient::IOSetup getIOSetup() const override;
// IMidiClient
bool onEvent(const Event &event, int32_t port) override;
IMidiClient::IOSetup getMidiIOSetup() const override;
// IParameterClient
//--------------------------------------------------------------------
private:
bool supportsState = false;
IHost *pHost;
Module::Ptr module;
IPtr<IMidiMapping> midiMapping;
IPtr<PlugProvider> plugProvider;
RtStreamPool streamPool;
void SendControlChanges(RealtimeRingBufferWriter *realtimeRingBufferWriter);
//--------------------------------------------------------------------
private:
std::mutex parameterMutex;
Buffers buffers;
std::vector<ParamID> lv2ToVstParam;
std::vector<float> parameterValues;
// void createLocalMediaServer(const Name &name);
uint64_t instanceId;
Vst3PluginInfo info;
void terminate();
void initProcessData();
void updateBusBuffers(Buffers &buffers, HostProcessData &processData);
void preprocess(Buffers &buffers, int64_t continousFrames);
void postprocess(Buffers &buffers);
bool isPortInRange(int32 port, int32 channel) const;
bool processVstEvent(const IMidiClient::Event &event, int32 port);
bool processParamChange(const IMidiClient::Event &event, int32 port);
SampleRate sampleRate = 0;
int32 blockSize = 0;
HostProcessData processData;
ProcessContext processContext;
EventList eventList;
ParameterChanges inputParameterChanges;
ParameterChanges outputParameterChanges;
IComponent *component = nullptr;
IEditController *controller = nullptr;
FUnknownPtr<IAudioProcessor> processor;
ParameterChangeTransfer paramTransferrer;
MidiCCMapping midiCCMapping;
// IMediaServerPtr mediaServer;
bool isProcessing = false;
Name name;
private:
ssize_t ParamIdToLv2Id(ParamID id) const;
class ComponentHandler : public IComponentHandler
{
private:
Vst3EffectImpl *pEffect = nullptr;
public:
ComponentHandler() { }
void setEffect(Vst3EffectImpl*effect)
{
pEffect = effect;
}
tresult PLUGIN_API beginEdit(ParamID id) override
{
return pEffect->beginEdit(id);
}
tresult PLUGIN_API performEdit(ParamID id, ParamValue valueNormalized) override
{
return pEffect->performEdit(id, valueNormalized);
}
tresult PLUGIN_API endEdit(ParamID id) override
{
return pEffect->endEdit(id);
}
tresult PLUGIN_API restartComponent(int32 flags) override
{
return pEffect->restartComponent(flags);
}
private:
tresult PLUGIN_API queryInterface(const TUID _iid, void ** obj) override
{
if (_iid == IComponentHandler_iid)
{
addRef();
*((FUnknown**)obj) = this;
return kResultOk;
}
return kNoInterface;
}
uint32 PLUGIN_API addRef() override { return 1000; }
uint32 PLUGIN_API release() override { return 1000; }
};
ComponentHandler componentHandler;
void transferControllerStateToComponent();
void refreshControlValues();
virtual tresult beginEdit(ParamID id);
virtual tresult performEdit(ParamID id, ParamValue valueNormalized);
virtual tresult endEdit(ParamID id);
virtual tresult restartComponent(int32 flags);
private:
ControlChangedHandler controlChangedHandler = [] (int control,float value) {};
void fireControlChanged(int control, float normalizedValue);
public:
virtual void SetControlChangedHandler(const ControlChangedHandler& handler)
{
controlChangedHandler = handler;
}
virtual void RemoveControlChangedHandler() {
controlChangedHandler = [] (int,float){};
}
};
}