sfizz/plugins/vst/SfizzVstProcessor.h
Paul Fd bdc9522662 Add multiple output capabilities to the library and plugins
Add a fast path to effect busses

Get the number of outputs in the Synth

Duplicate effect buses and process outputs separately

Update the API wrappers to handle multichannel processing

Accomodate multiple outputs in the VST plugin

Publish a 8 stereo version of the LV2 plugin

Publish a 8 stereo version of the VST3 plugin

WIP

Remove the duplication of effects

Cleanups

Debugs

Tweaks

Windows free error

Port numbers change between plugin versions

Fix warning

Proper meter backgrounds
2021-11-09 19:40:06 +01:00

146 lines
4.7 KiB
C++

// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#pragma once
#include "SfizzVstState.h"
#include "SfizzVstUpdates.h"
#include "OrderedEventProcessor.h"
#include "plugin/RMSFollower.h"
#include "sfizz/RTSemaphore.h"
#include "ring_buffer/ring_buffer.h"
#include "public.sdk/source/vst/vstaudioeffect.h"
#include <sfizz.hpp>
#include <SpinMutex.h>
#include <array>
#include <thread>
#include <memory>
#include <cstdlib>
using namespace Steinberg;
class SfizzVstProcessor : public Vst::AudioEffect,
public OrderedEventProcessor<SfizzVstProcessor> {
public:
SfizzVstProcessor();
~SfizzVstProcessor();
tresult PLUGIN_API initialize(FUnknown* context) override;
tresult PLUGIN_API terminate() override;
tresult PLUGIN_API setBusArrangements(Vst::SpeakerArrangement* inputs, int32 numIns, Vst::SpeakerArrangement* outputs, int32 numOuts) override;
tresult PLUGIN_API connect(IConnectionPoint* other) override;
tresult PLUGIN_API setState(IBStream* stream) override;
tresult PLUGIN_API getState(IBStream* stream) override;
void syncStateToSynth();
tresult PLUGIN_API canProcessSampleSize(int32 symbolicSampleSize) override;
tresult PLUGIN_API setActive(TBool state) override;
tresult PLUGIN_API process(Vst::ProcessData& data) override;
// OrderedEventProcessor
void playOrderedParameter(int32 sampleOffset, Vst::ParamID id, Vst::ParamValue value);
void playOrderedEvent(const Vst::Event& event);
void processMessagesFromUi();
tresult PLUGIN_API notify(Vst::IMessage* message) override;
void PLUGIN_API update(FUnknown* changedUnknown, int32 message) override;
static FUnknown* createInstance(void*);
static FUID cid;
// --- Sfizz stuff here below ---
protected:
RMSFollower _rmsFollower {};
bool _multi { false };
private:
// synth state. acquire processMutex before accessing
std::unique_ptr<sfz::Sfizz> _synth;
bool _isActive = false;
SfizzVstState _state;
float _currentStretchedTuning = 0;
// whether allowed to perform events (owns the processing lock)
bool _canPerformEventsAndParameters {};
// level meters
bool _editorIsOpen = false;
// updates
IPtr<QueuedUpdates> _queuedMessages;
IPtr<PlayStateUpdate> _playStateUpdate;
IPtr<SfzUpdate> _sfzUpdate;
IPtr<SfzDescriptionUpdate> _sfzDescriptionUpdate;
IPtr<ScalaUpdate> _scalaUpdate;
IPtr<AutomationUpdate> _automationUpdate;
bool processUpdate(FUnknown* changedUnknown, int32 message);
// client
sfz::ClientPtr _client;
std::unique_ptr<uint8_t[]> _oscTemp;
void receiveOSC(int delay, const char* path, const char* sig, const sfizz_arg_t* args);
// misc
void loadSfzFileOrDefault(const std::string& filePath, bool initParametersFromState);
// note event tracking
std::array<float, 128> _noteEventsCurrentCycle; // 0: off, >0: on, <0: no change
// worker and thread sync
std::thread _worker;
volatile bool _workRunning = false;
Ring_Buffer _fifoToWorker;
RTSemaphore _semaToWorker;
Ring_Buffer _fifoMessageFromUi;
SpinMutex _processMutex;
// time info
int _timeSigNumerator = 0;
int _timeSigDenominator = 0;
void updateTimeInfo(const Vst::ProcessContext& context);
// messaging
struct RTMessage {
const char* type;
uintptr_t size;
// 32-bit aligned data after header
template <class T> const T* payload() const;
};
struct RTMessageDelete {
void operator()(RTMessage* x) const noexcept { std::free(x); }
};
typedef std::unique_ptr<RTMessage, RTMessageDelete> RTMessagePtr;
// worker
void doBackgroundWork();
void doBackgroundIdle(size_t idleCounter);
void startBackgroundWork();
void stopBackgroundWork();
// writer
bool writeWorkerMessage(const char* type, const void* data, uintptr_t size);
// reader
RTMessagePtr readWorkerMessage();
bool discardWorkerMessage();
// generic
static bool writeMessage(Ring_Buffer& fifo, const char* type, const void* data, uintptr_t size);
};
class SfizzVstProcessorMulti : public SfizzVstProcessor {
public:
tresult PLUGIN_API initialize(FUnknown* context) override;
static FUnknown* createInstance(void*);
static FUID cid;
};
//------------------------------------------------------------------------------
template <class T> const T* SfizzVstProcessor::RTMessage::payload() const
{
return reinterpret_cast<const T*>(
reinterpret_cast<const uint8*>(this) + sizeof(*this));
}