Initial release
This commit is contained in:
+196
@@ -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
|
||||
|
||||
+245
@@ -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
|
||||
Reference in New Issue
Block a user