Initial release

This commit is contained in:
civ
2026-08-16 18:24:52 +07:00
commit 876886a39a
13244 changed files with 2353959 additions and 0 deletions
@@ -0,0 +1,18 @@
//------------------------------------------------------------------------
// Copyright(c) 2023 Steinberg Media Technologies.
//------------------------------------------------------------------------
#pragma once
#include "pluginterfaces/base/funknown.h"
#include "pluginterfaces/vst/vsttypes.h"
namespace Steinberg::Tutorial {
//------------------------------------------------------------------------
static const Steinberg::FUID kDataExchangeProcessorUID (0xE35B96A9, 0x9BB353A9, 0x910130C1, 0x2C55EC26);
static const Steinberg::FUID kDataExchangeControllerUID (0xADFD02D2, 0x20525504, 0x90D96683, 0xFD2DDF86);
#define DataExchangeVST3Category "Fx"
//------------------------------------------------------------------------
} // namespace Steinberg::Tutorial
@@ -0,0 +1,51 @@
//------------------------------------------------------------------------
// Copyright(c) 2023 Steinberg Media Technologies.
//------------------------------------------------------------------------
#include "cids.h"
#include "controller.h"
namespace Steinberg::Tutorial {
//------------------------------------------------------------------------
// DataExchangeController Implementation
//------------------------------------------------------------------------
tresult PLUGIN_API DataExchangeController::notify (Vst::IMessage* message)
{
if (dataExchange.onMessage (message))
return kResultTrue;
return EditControllerEx1::notify (message);
}
//------------------------------------------------------------------------
void PLUGIN_API DataExchangeController::queueOpened (Vst::DataExchangeUserContextID userContextID,
uint32 blockSize,
TBool& dispatchOnBackgroundThread)
{
FDebugPrint ("Data Exchange Queue opened.\n");
}
//------------------------------------------------------------------------
void PLUGIN_API DataExchangeController::queueClosed (Vst::DataExchangeUserContextID userContextID)
{
FDebugPrint ("Data Exchange Queue closed.\n");
}
//------------------------------------------------------------------------
void PLUGIN_API DataExchangeController::onDataExchangeBlocksReceived (
Vst::DataExchangeUserContextID userContextID, uint32 numBlocks, Vst::DataExchangeBlock* blocks,
TBool onBackgroundThread)
{
for (auto index = 0u; index < numBlocks; ++index)
{
auto dataBlock = toDataBlock (blocks[index]);
FDebugPrint (
"Received Data Block: SampleRate: %d, SampleSize: %d, NumChannels: %d, NumSamples: %d\n",
dataBlock->sampleRate, static_cast<uint32_t> (dataBlock->sampleSize),
static_cast<uint32_t> (dataBlock->numChannels),
static_cast<uint32_t> (dataBlock->numSamples));
}
}
//------------------------------------------------------------------------
} // namespace Steinberg::Tutorial
@@ -0,0 +1,48 @@
//------------------------------------------------------------------------
// Copyright(c) 2023 Steinberg Media Technologies.
//------------------------------------------------------------------------
#pragma once
#include "dataexchange.h"
#include "public.sdk/source/vst/vsteditcontroller.h"
namespace Steinberg::Tutorial {
//------------------------------------------------------------------------
// DataExchangeController
//------------------------------------------------------------------------
class DataExchangeController : public Vst::EditControllerEx1, public Vst::IDataExchangeReceiver
{
public:
//------------------------------------------------------------------------
// Create function
static FUnknown* createInstance (void* /*context*/)
{
return (Vst::IEditController*)new DataExchangeController;
}
// EditController
tresult PLUGIN_API notify (Vst::IMessage* message) override;
// IDataExchangeReceiver
void PLUGIN_API queueOpened (Vst::DataExchangeUserContextID userContextID, uint32 blockSize,
TBool& dispatchOnBackgroundThread) override;
void PLUGIN_API queueClosed (Vst::DataExchangeUserContextID userContextID) override;
void PLUGIN_API onDataExchangeBlocksReceived (Vst::DataExchangeUserContextID userContextID,
uint32 numBlocks, Vst::DataExchangeBlock* blocks,
TBool onBackgroundThread) override;
//---Interface---------
DEFINE_INTERFACES
// Here you can add more supported VST3 interfaces
DEF_INTERFACE (Vst::IDataExchangeReceiver)
END_DEFINE_INTERFACES (EditController)
DELEGATE_REFCOUNT (EditController)
//------------------------------------------------------------------------
private:
Vst::DataExchangeReceiverHandler dataExchange {this};
};
//------------------------------------------------------------------------
} // namespace Steinberg::Tutorial
@@ -0,0 +1,32 @@
//------------------------------------------------------------------------
// Copyright(c) 2023 Steinberg Media Technologies.
//------------------------------------------------------------------------
#pragma once
#include "public.sdk/source/vst/utility/dataexchange.h"
#include <cstdint>
//------------------------------------------------------------------------
namespace Steinberg::Tutorial {
//------------------------------------------------------------------------
struct DataBlock
{
uint32_t sampleRate;
uint16_t sampleSize;
uint16_t numChannels;
uint32_t numSamples;
float samples[0];
};
//------------------------------------------------------------------------
inline DataBlock* toDataBlock (const Vst::DataExchangeBlock& block)
{
if (block.blockID != Vst::InvalidDataExchangeBlockID)
return reinterpret_cast<DataBlock*> (block.data);
return nullptr;
}
//------------------------------------------------------------------------
} // Steinberg::Tutorial
@@ -0,0 +1,53 @@
//------------------------------------------------------------------------
// Copyright(c) 2023 Steinberg Media Technologies.
//------------------------------------------------------------------------
#include "processor.h"
#include "controller.h"
#include "cids.h"
#include "version.h"
#include "public.sdk/source/main/pluginfactory.h"
#define stringPluginName "dataexchange-tutorial"
using namespace Steinberg::Vst;
using namespace Steinberg::Tutorial;
//------------------------------------------------------------------------
// VST Plug-in Entry
//------------------------------------------------------------------------
// Windows: do not forget to include a .def file in your project to export
// GetPluginFactory function!
//------------------------------------------------------------------------
BEGIN_FACTORY_DEF ("Steinberg Media Technologies",
"https://steinberg.net",
"mailto:info@steinberg.de")
//---First Plug-in included in this factory-------
// its kVstAudioEffectClass component
DEF_CLASS2 (INLINE_UID_FROM_FUID(kDataExchangeProcessorUID),
PClassInfo::kManyInstances, // cardinality
kVstAudioEffectClass, // the component category (do not changed this)
stringPluginName, // here the Plug-in name (to be changed)
Vst::kDistributable, // means that component and controller could be distributed on different computers
DataExchangeVST3Category, // Subcategory for this Plug-in (to be changed)
FULL_VERSION_STR, // Plug-in version (to be changed)
kVstVersionString, // the VST 3 SDK version (do not changed this, use always this define)
DataExchangeProcessor::createInstance) // function pointer called when this component should be instantiated
// its kVstComponentControllerClass component
DEF_CLASS2 (INLINE_UID_FROM_FUID (kDataExchangeControllerUID),
PClassInfo::kManyInstances, // cardinality
kVstComponentControllerClass,// the Controller category (do not changed this)
stringPluginName "Controller", // controller name (could be the same than component name)
0, // not used here
"", // not used here
FULL_VERSION_STR, // Plug-in version (to be changed)
kVstVersionString, // the VST 3 SDK version (do not changed this, use always this define)
DataExchangeController::createInstance)// function pointer called when this component should be instantiated
//----for others Plug-ins contained in this factory, put like for the first Plug-in different DEF_CLASS2---
END_FACTORY
@@ -0,0 +1,168 @@
//------------------------------------------------------------------------
// Copyright(c) 2023 Steinberg Media Technologies.
//------------------------------------------------------------------------
#include "cids.h"
#include "processor.h"
#include "base/source/fstreamer.h"
#include "pluginterfaces/vst/ivstparameterchanges.h"
namespace Steinberg::Tutorial {
//------------------------------------------------------------------------
static constexpr Vst::DataExchangeBlock kInvalidDataExchangeBlock = {
nullptr, 0, Vst::InvalidDataExchangeBlockID};
//------------------------------------------------------------------------
// DataExchangeProcessor
//------------------------------------------------------------------------
DataExchangeProcessor::DataExchangeProcessor ()
{
setControllerClass (kDataExchangeControllerUID);
}
//------------------------------------------------------------------------
DataExchangeProcessor::~DataExchangeProcessor () = default;
//------------------------------------------------------------------------
tresult PLUGIN_API DataExchangeProcessor::initialize (FUnknown* context)
{
tresult result = AudioEffect::initialize (context);
if (result != kResultOk)
{
return result;
}
addAudioInput (STR16 ("Stereo In"), Steinberg::Vst::SpeakerArr::kStereo);
addAudioOutput (STR16 ("Stereo Out"), Steinberg::Vst::SpeakerArr::kStereo);
return kResultOk;
}
//------------------------------------------------------------------------
tresult PLUGIN_API DataExchangeProcessor::connect (Vst::IConnectionPoint* other)
{
auto result = Vst::AudioEffect::connect (other);
if (result == kResultTrue)
{
auto configCallback = [this] (Vst::DataExchangeHandler::Config& config,
const Vst::ProcessSetup& setup) {
Vst::SpeakerArrangement arr;
getBusArrangement (Vst::BusDirections::kInput, 0, arr);
numChannels = static_cast<uint16_t> (Vst::SpeakerArr::getChannelCount (arr));
auto sampleSize = sizeof (float);
config.blockSize = setup.sampleRate * numChannels * sampleSize + sizeof (DataBlock);
config.numBlocks = 2;
config.alignment = 32;
config.userContextID = 0;
return true;
};
dataExchange = std::make_unique<Vst::DataExchangeHandler> (this, configCallback);
dataExchange->onConnect (other, getHostContext ());
}
return result;
}
//------------------------------------------------------------------------
tresult PLUGIN_API DataExchangeProcessor::disconnect (Vst::IConnectionPoint* other)
{
if (dataExchange)
{
dataExchange->onDisconnect (other);
dataExchange.reset ();
}
return AudioEffect::disconnect (other);
}
//------------------------------------------------------------------------
tresult PLUGIN_API DataExchangeProcessor::setActive (TBool state)
{
if (state)
dataExchange->onActivate (processSetup);
else
{
dataExchange->onDeactivate ();
currentExchangeBlock = kInvalidDataExchangeBlock;
}
return AudioEffect::setActive (state);
}
//------------------------------------------------------------------------
tresult PLUGIN_API DataExchangeProcessor::canProcessSampleSize (int32 symbolicSampleSize)
{
if (symbolicSampleSize == Vst::kSample32)
return kResultTrue;
return kResultFalse;
}
//------------------------------------------------------------------------
void DataExchangeProcessor::acquireNewExchangeBlock ()
{
currentExchangeBlock = dataExchange->getCurrentOrNewBlock ();
if (auto block = toDataBlock (currentExchangeBlock))
{
block->sampleRate = static_cast<uint32_t> (processSetup.sampleRate);
block->numChannels = numChannels;
block->sampleSize = sizeof (float);
block->numSamples = 0;
}
}
//------------------------------------------------------------------------
tresult PLUGIN_API DataExchangeProcessor::process (Vst::ProcessData& processData)
{
if (processData.numSamples <= 0)
return kResultTrue;
if (currentExchangeBlock.blockID == Vst::InvalidDataExchangeBlockID)
acquireNewExchangeBlock ();
auto input = processData.inputs[0];
auto output = processData.outputs[0];
if (auto block = toDataBlock (currentExchangeBlock))
{
auto numSamples = static_cast<uint32> (processData.numSamples);
while (numSamples > 0)
{
uint32 numSamplesFreeInBlock = block->sampleRate - block->numSamples;
uint32 numSamplesToCopy = std::min<uint32> (numSamplesFreeInBlock, numSamples);
for (auto channel = 0; channel < input.numChannels; ++channel)
{
const auto channelOffset = channel * block->sampleRate;
auto blockChannelData = &block->samples[0] + block->numSamples + channelOffset;
auto inputChannel =
input.channelBuffers32[channel] + (processData.numSamples - numSamples);
memcpy (blockChannelData, inputChannel, numSamplesToCopy * sizeof (float));
}
block->numSamples += numSamplesToCopy;
if (block->numSamples == block->sampleRate)
{
dataExchange->sendCurrentBlock ();
acquireNewExchangeBlock ();
block = toDataBlock (currentExchangeBlock);
if (block == nullptr)
break;
}
numSamples -= numSamplesToCopy;
}
}
for (auto channel = 0; channel < input.numChannels; ++channel)
{
if (output.channelBuffers32[channel] != input.channelBuffers32[channel])
{
memcpy (output.channelBuffers32[channel], input.channelBuffers32[channel],
processData.numSamples * sizeof (float));
}
output.silenceFlags = input.silenceFlags;
}
return kResultOk;
}
//------------------------------------------------------------------------
} // namespace Steinberg::Tutorial
@@ -0,0 +1,46 @@
//------------------------------------------------------------------------
// Copyright(c) 2023 Steinberg Media Technologies.
//------------------------------------------------------------------------
#pragma once
#include "dataexchange.h"
#include "public.sdk/source/vst/vstaudioeffect.h"
namespace Steinberg::Tutorial {
//------------------------------------------------------------------------
static constexpr Vst::DataExchangeBlock InvalidDataExchangeBlock = {
nullptr, 0, Vst::InvalidDataExchangeBlockID};
//------------------------------------------------------------------------
// DataExchangeProcessor
//------------------------------------------------------------------------
class DataExchangeProcessor : public Vst::AudioEffect
{
public:
DataExchangeProcessor ();
~DataExchangeProcessor () override;
static FUnknown* createInstance (void* /*context*/)
{
return (Vst::IAudioProcessor*)new DataExchangeProcessor;
}
tresult PLUGIN_API initialize (FUnknown* context) override;
tresult PLUGIN_API connect (Vst::IConnectionPoint* other) override;
tresult PLUGIN_API disconnect (Vst::IConnectionPoint* other) override;
tresult PLUGIN_API setActive (TBool state) override;
tresult PLUGIN_API canProcessSampleSize (int32 symbolicSampleSize) override;
tresult PLUGIN_API process (Vst::ProcessData& data) override;
//------------------------------------------------------------------------
protected:
void acquireNewExchangeBlock ();
std::unique_ptr<Vst::DataExchangeHandler> dataExchange;
Vst::DataExchangeBlock currentExchangeBlock {InvalidDataExchangeBlock};
uint16_t numChannels {0};
};
//------------------------------------------------------------------------
} // namespace Steinberg::Tutorial
@@ -0,0 +1,20 @@
//------------------------------------------------------------------------
// Copyright(c) 2023 Steinberg Media Technologies.
//------------------------------------------------------------------------
#pragma once
#include "pluginterfaces/base/fplatform.h"
// Plain project version file generated by cmake
#include "projectversion.h"
#define stringOriginalFilename "dataexchange-tutorial.vst3"
#if SMTG_PLATFORM_64
#define stringFileDescription "dataexchange-tutorial VST3 (64Bit)"
#else
#define stringFileDescription "dataexchange-tutorial VST3"
#endif
#define stringCompanyName "Steinberg Media Technologies\0"
#define stringLegalCopyright "Copyright(c) 2023 Steinberg Media Technologies."
#define stringLegalTrademarks "VST is a trademark of Steinberg Media Technologies GmbH"