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,196 @@
//------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Examples
// Filename : public.sdk/samples/vst/panner/source/plugcontroller.cpp
// Created by : Steinberg, 02/2020
// Description : Panner Example for VST 3
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#include "../include/plugcontroller.h"
#include "../include/plugids.h"
#include "base/source/fstreamer.h"
#include "public.sdk/source/vst/utility/stringconvert.h"
#include "pluginterfaces/base/ibstream.h"
#include "pluginterfaces/base/ustring.h"
#include <string_view>
using namespace VSTGUI;
namespace Steinberg {
namespace Panner {
// example of custom parameter (overwriting to and fromString)
//------------------------------------------------------------------------
class PanParameter : public Vst::Parameter
{
public:
PanParameter (int32 flags, int32 id);
void toString (Vst::ParamValue normValue, Vst::String128 string) const SMTG_OVERRIDE;
bool fromString (const Vst::TChar* string, Vst::ParamValue& normValue) const SMTG_OVERRIDE;
};
//------------------------------------------------------------------------
// PanParameter Implementation
//------------------------------------------------------------------------
PanParameter::PanParameter (int32 flags, int32 id)
{
Steinberg::UString (info.title, USTRINGSIZE (info.title)).assign (USTRING ("Pan"));
Steinberg::UString (info.units, USTRINGSIZE (info.units)).assign (USTRING (""));
info.flags = flags;
info.id = id;
info.stepCount = 0;
info.defaultNormalizedValue = 0.5f;
info.unitId = Vst::kRootUnitId;
setNormalized (.5f);
}
//------------------------------------------------------------------------
void PanParameter::toString (Vst::ParamValue normValue, Vst::String128 string) const
{
char text[32];
if (normValue >= 0.505)
{
snprintf (text, 32, "R %d", int32 ((normValue - 0.5f) * 200 + 0.5f));
}
else if (normValue <= 0.495)
{
snprintf (text, 32, "L %d", int32 ((0.5f - normValue) * 200 + 0.5f));
}
else
{
strcpy (text, "C");
}
Steinberg::UString (string, 128).fromAscii (text);
}
//------------------------------------------------------------------------
bool PanParameter::fromString (const Vst::TChar* string, Vst::ParamValue& normValue) const
{
std::u16string_view stringView (string);
auto pos = stringView.find_first_of (u"C");
if (pos != std::string::npos)
{
normValue = 0.5;
return true;
}
else
{
bool left = stringView.find_first_of (u"L") == 0;
bool right = stringView.find_first_of (u"R") == 0;
if (left || right)
stringView = {stringView.data () + 1, stringView.size () - 1};
auto string8 = Vst::StringConvert::convert (stringView.data ());
char* end = nullptr;
double tmp = strtod (string8.data (), &end);
if (end != string8.data ())
{
if (tmp < 0)
{
left = true;
if (tmp < -100)
tmp = 100;
else
tmp = -tmp;
}
else if (tmp > 100.0)
{
normValue = 1;
return true;
}
if (!left)
normValue = tmp / 200 + 0.5;
else
normValue = 0.5 - tmp / 200;
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
tresult PLUGIN_API PlugController::initialize (FUnknown* context)
{
tresult result = EditController::initialize (context);
if (result == kResultTrue)
{
//---Create Parameters------------
parameters.addParameter (STR16 ("Bypass"), nullptr, 1, 0,
Vst::ParameterInfo::kCanAutomate | Vst::ParameterInfo::kIsBypass,
PannerParams::kBypassId);
auto* panParam = new PanParameter (Vst::ParameterInfo::kCanAutomate, PannerParams::kParamPanId);
parameters.addParameter (panParam);
}
return kResultTrue;
}
//------------------------------------------------------------------------
IPlugView* PLUGIN_API PlugController::createView (const char* _name)
{
std::string_view name (_name);
if (name == Vst::ViewType::kEditor)
{
auto* view = new VST3Editor (this, "view", "plug.uidesc");
return view;
}
return nullptr;
}
//------------------------------------------------------------------------
tresult PLUGIN_API PlugController::getParameterIDFromFunctionName (Vst::UnitID unitID,
FIDString functionName,
Vst::ParamID& paramID)
{
using namespace Vst;
paramID = kNoParamId;
if (unitID == kRootUnitId && FIDStringsEqual (functionName, FunctionNameType::kPanPosCenterX))
paramID = PannerParams::kParamPanId;
return (paramID != kNoParamId) ? kResultOk : kResultFalse;
}
//------------------------------------------------------------------------
tresult PLUGIN_API PlugController::setComponentState (IBStream* state)
{
// we receive the current state of the component (processor part)
// we read our parameters and bypass value...
if (!state)
return kResultFalse;
IBStreamer streamer (state, kLittleEndian);
float savedParam1 = 0.f;
if (streamer.readFloat (savedParam1) == false)
return kResultFalse;
setParamNormalized (PannerParams::kParamPanId, savedParam1);
// read the bypass
int32 bypassState;
if (streamer.readInt32 (bypassState) == false)
return kResultFalse;
setParamNormalized (kBypassId, bypassState ? 1 : 0);
return kResultOk;
}
//------------------------------------------------------------------------
} // namespace
} // namespace Steinberg
@@ -0,0 +1,49 @@
//------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Examples
// Filename : public.sdk/samples/vst/panner/source/plugfactory.cpp
// Created by : Steinberg, 02/2020
// Description : Panner Example for VST 3
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#include "public.sdk/source/main/pluginfactory.h"
#include "../include/plugcontroller.h" // for createInstance
#include "../include/plugprocessor.h" // for createInstance
#include "../include/plugids.h" // for uids
#include "../include/version.h" // for version and naming
#define stringSubCategory Vst::PlugType::kSpatialFx // Subcategory for this plug-in (to be changed if needed, see PlugType in ivstaudioprocessor.h)
BEGIN_FACTORY_DEF (stringCompanyName, stringCompanyWeb, stringCompanyEmail)
DEF_CLASS2 (INLINE_UID_FROM_FUID(Steinberg::Panner::MyProcessorUID),
PClassInfo::kManyInstances, // cardinality
kVstAudioEffectClass, // the component category (do not change this)
stringPluginName, // here the plug-in name (to be changed)
Vst::kDistributable, // means that component and controller could be distributed on different computers
stringSubCategory, // 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 change this, always use this define)
Steinberg::Panner::PlugProcessor::createInstance) // function pointer called when this component should be instantiated
DEF_CLASS2 (INLINE_UID_FROM_FUID(Steinberg::Panner::MyControllerUID),
PClassInfo::kManyInstances, // cardinality
kVstComponentControllerClass,// the Controller category (do not change this)
stringPluginName "Controller", // controller name (can be the same as the 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 change this, always use this define)
Steinberg::Panner::PlugController::createInstance)// function pointer called when this component should be instantiated
END_FACTORY
@@ -0,0 +1,245 @@
//------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Examples
// Filename : public.sdk/samples/vst/panner/source/plugprocessor.cpp
// Created by : Steinberg, 02/2020
// Description : Panner Example for VST 3
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#include "../include/plugprocessor.h"
#include "../include/plugids.h"
#include "public.sdk/source/vst/vstaudioprocessoralgo.h"
#include "base/source/fstreamer.h"
#include "pluginterfaces/base/ibstream.h"
#include "pluginterfaces/vst/ivstparameterchanges.h"
namespace Steinberg {
namespace Panner {
#ifndef kPI
#define kPI 3.14159265358979323846
#endif
#define kRampingTimeMs 10.0 // in ms
//-----------------------------------------------------------------------------
PlugProcessor::PlugProcessor ()
{
// register its editor class
setControllerClass (MyControllerUID);
// default init
processAudioPtr = &PlugProcessor::processAudio<float>;
}
//-----------------------------------------------------------------------------
tresult PLUGIN_API PlugProcessor::initialize (FUnknown* context)
{
//---always initialize the parent-------
tresult result = AudioEffect::initialize (context);
if (result != kResultTrue)
return kResultFalse;
//---create Audio In/Out busses------
// we want a Mono Input and a Stereo Output
addAudioInput (STR16 ("AudioInput"), Vst::SpeakerArr::kMono);
addAudioOutput (STR16 ("AudioOutput"), Vst::SpeakerArr::kStereo);
return kResultTrue;
}
//------------------------------------------------------------------------
tresult PLUGIN_API PlugProcessor::canProcessSampleSize (int32 symbolicSampleSize)
{
return ((symbolicSampleSize == Vst::kSample32) || (symbolicSampleSize == Vst::kSample64)) ?
kResultTrue :
kResultFalse;
}
//-----------------------------------------------------------------------------
tresult PLUGIN_API PlugProcessor::setBusArrangements (Vst::SpeakerArrangement* inputs, int32 numIns,
Vst::SpeakerArrangement* outputs,
int32 numOuts)
{
// we only support mono to stereo
if (numIns == 1 && numOuts == 1 && inputs[0] == Vst::SpeakerArr::kMono &&
outputs[0] == Vst::SpeakerArr::kStereo)
{
return AudioEffect::setBusArrangements (inputs, numIns, outputs, numOuts);
}
return kResultFalse;
}
//-----------------------------------------------------------------------------
tresult PLUGIN_API PlugProcessor::setupProcessing (Vst::ProcessSetup& setup)
{
if (setup.symbolicSampleSize == Vst::kSample64)
processAudioPtr = &PlugProcessor::processAudio<double>;
else
processAudioPtr = &PlugProcessor::processAudio<float>;
return AudioEffect::setupProcessing (setup);
}
//-----------------------------------------------------------------------------
tresult PLUGIN_API PlugProcessor::setActive (TBool state)
{
return AudioEffect::setActive (state);
}
//-----------------------------------------------------------------------------
tresult PLUGIN_API PlugProcessor::process (Vst::ProcessData& data)
{
//--- Read inputs parameter changes-----------
if (data.inputParameterChanges)
{
int32 numParamsChanged = data.inputParameterChanges->getParameterCount ();
for (int32 index = 0; index < numParamsChanged; index++)
{
if (Vst::IParamValueQueue* paramQueue =
data.inputParameterChanges->getParameterData (index))
{
Vst::ParamValue value;
int32 sampleOffset;
int32 numPoints = paramQueue->getPointCount ();
switch (paramQueue->getParameterId ())
{
case PannerParams::kParamPanId:
if (paramQueue->getPoint (numPoints - 1, sampleOffset, value) ==
kResultTrue)
mPanValue = value;
break;
case PannerParams::kBypassId:
if (paramQueue->getPoint (numPoints - 1, sampleOffset, value) ==
kResultTrue)
mBypass = (value > 0.5f);
break;
}
}
}
}
//--- Process Audio---------------------
//--- ----------------------------------
if (data.numInputs == 0 || data.numOutputs == 0 || data.numSamples == 0)
{
// nothing to do
return kResultOk;
}
return (this->*processAudioPtr) (data);
}
//------------------------------------------------------------------------
template <typename SampleType>
tresult PlugProcessor::processAudio (Vst::ProcessData& data)
{
int32 numFrames = data.numSamples;
uint32 sampleFramesSize = getSampleFramesSizeInBytes (processSetup, numFrames);
auto** currentInputBuffers =
(SampleType**)Vst::getChannelBuffersPointer (processSetup, data.inputs[0]);
auto** currentOutputBuffers =
(SampleType**)Vst::getChannelBuffersPointer (processSetup, data.outputs[0]);
// if we have only silence clear the output and do nothing.
data.outputs->silenceFlags = data.inputs->silenceFlags ? 0x7FFFF : 0;
if (data.inputs->silenceFlags)
{
memset (currentOutputBuffers[0], 0, sampleFramesSize);
memset (currentOutputBuffers[1], 0, sampleFramesSize);
return kResultOk;
}
float leftPan;
float rightPan;
if (mBypass)
getStereoPanCoef (kPanLawEqualPower, 0.f, leftPan, rightPan);
else
getStereoPanCoef (kPanLawEqualPower, static_cast<float> (mPanValue), leftPan, rightPan);
//---pan : 1 -> 2---------------------
SampleType tmp;
SampleType* inputMono = currentInputBuffers[0];
SampleType* outputLeft = currentOutputBuffers[0];
SampleType* outputRight = currentOutputBuffers[1];
for (int32 n = 0; n < numFrames; n++)
{
tmp = inputMono[n];
outputLeft[n] = tmp * leftPan;
outputRight[n] = tmp * rightPan;
}
return kResultOk;
}
//------------------------------------------------------------------------
void PlugProcessor::getStereoPanCoef (int32 panType, float pan, float& left, float& right) const
{
if (panType == kPanLawEqualPower)
{
pan = pan * static_cast<float> (kPI) * 0.5f;
left = cosf (pan);
right = sinf (pan);
}
else
{
left = 0.5f;
right = 0.5f;
}
}
//------------------------------------------------------------------------
tresult PLUGIN_API PlugProcessor::setState (IBStream* state)
{
if (!state)
return kResultFalse;
// called when we load a preset or project, the model has to be reloaded
IBStreamer streamer (state, kLittleEndian);
float savedPan= 0.f;
if (streamer.readFloat (savedPan) == false)
return kResultFalse;
int32 savedBypass = 0;
if (streamer.readInt32 (savedBypass) == false)
return kResultFalse;
mPanValue = savedPan;
mBypass = savedBypass > 0;
return kResultOk;
}
//------------------------------------------------------------------------
tresult PLUGIN_API PlugProcessor::getState (IBStream* state)
{
// here we need to save the model (preset or project)
float toSavePan = static_cast<float> (mPanValue);
int32 toSaveBypass = mBypass ? 1 : 0;
IBStreamer streamer (state, kLittleEndian);
streamer.writeFloat (toSavePan);
streamer.writeInt32 (toSaveBypass);
return kResultOk;
}
//------------------------------------------------------------------------
} // namespace
} // namespace Steinberg