Like I said my host successfuly load my VST3 on desktop version. They are very simple. Here is the Reverb for example:
CMakeList.txt:
project(Reverb VERSION 0.0.1)
set (BaseTargetName Reverb)
set(CMAKE_DEBUG_POSTFIX "")
juce_add_plugin("${BaseTargetName}"
# VERSION ... # Set this if the plugin version is different to the project version
# ICON_BIG ... # ICON_* arguments specify a path to an image file to use as an icon for the Standalone
# ICON_SMALL ...
COMPANY_NAME "MyCompany"
IS_SYNTH FALSE
NEEDS_MIDI_INPUT TRUE
NEEDS_MIDI_OUTPUT FALSE
IS_MIDI_EFFECT FALSE
EDITOR_WANTS_KEYBOARD_FOCUS FALSE
COPY_PLUGIN_AFTER_BUILD TRUE
PLUGIN_MANUFACTURER_CODE Juce
PLUGIN_CODE Dem0
FORMATS AU VST3 Standalone
PRODUCT_NAME "Reverb")
target_sources(${BaseTargetName} PRIVATE
Source/PluginProcessor.cpp)
target_compile_definitions(${BaseTargetName}
PUBLIC
JUCE_DISABLE_JUCE_VERSION_PRINTING=1
JUCE_WEB_BROWSER=0
JUCE_USE_CURL=0
JUCE_VST3_CAN_REPLACE_VST2=0)
target_link_libraries(${BaseTargetName} PRIVATE
juce::juce_core
juce::juce_dsp
juce::juce_audio_processors
juce::juce_audio_utils
juce::juce_audio_devices
juce::juce_audio_utils
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags
juce::juce_recommended_warning_flags)
PluginProcessor.cpp
#include "PluginProcessor.h"
//A little helper to get the parameter ID
juce::String getParamID(juce::AudioProcessorParameter *param) {
if (auto paramWithID = dynamic_cast<juce::AudioProcessorParameterWithID *>(param))
return paramWithID->paramID;
return param->getName(50);
}
ReverbAudioProcessor::ReverbAudioProcessor()
: juce::AudioProcessor(getBuses()),
_roomSizeParam(new juce::AudioParameterFloat("roomSize", "RoomSize",
juce::NormalisableRange<float>(0.0f, 1.0f), 0.5f)),
_dampingParam(new juce::AudioParameterFloat("damping", "Damping",
juce::NormalisableRange<float>(0.0f, 1.0f), 0.5f)),
_wetLevelParam(new juce::AudioParameterFloat("wetLevel", "WetLevel",
juce::NormalisableRange<float>(0.0f, 1.0f), 0.33f)),
_dryLevelParam(new juce::AudioParameterFloat("dryLevel", "DryLevel",
juce::NormalisableRange<float>(0.0f, 1.0f), 0.4f)),
_widthParam(new juce::AudioParameterFloat("width", "Width",
juce::NormalisableRange<float>(0.0f, 1.0f), 1.0f)),
_freezeModeParam(new juce::AudioParameterFloat("freezeMode", "FreezeMode",
juce::NormalisableRange<float>(0.0f, 1.0f), 0.0f)),
_reverb(std::make_unique<juce::dsp::Reverb>()) {
addParameter(_roomSizeParam);
addParameter(_dampingParam);
addParameter(_wetLevelParam);
addParameter(_dryLevelParam);
addParameter(_widthParam);
addParameter(_freezeModeParam);
updateReverb();
}
void ReverbAudioProcessor::processBlock(juce::AudioBuffer<float> &buffer,
juce::MidiBuffer & /*midiMessages*/) {
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; i++)
buffer.clear(i, 0, buffer.getNumSamples());
juce::dsp::AudioBlock<float> block(buffer);
updateReverb();
juce::dsp::ProcessContextReplacing<float> context(block);
this->_reverb->process(context);
}
void ReverbAudioProcessor::getStateInformation(juce::MemoryBlock &destData) {
//Serializes your parameters, and any other potential data into an XML:
juce::ValueTree params("Params");
for (auto ¶m: getParameters()) {
juce::ValueTree paramTree(getParamID(param));
paramTree.setProperty("Value", param->getValue(), nullptr);
params.appendChild(paramTree, nullptr);
}
juce::ValueTree pluginPreset("MyPlugin");
pluginPreset.appendChild(params, nullptr);
//This a good place to add any non-parameters to your preset
copyXmlToBinary(*pluginPreset.createXml(), destData);
}
void ReverbAudioProcessor::setStateInformation(const void *data,
int sizeInBytes) {
//Loads your parameters, and any other potential data from an XML:
auto xml = getXmlFromBinary(data, sizeInBytes);
if (xml != nullptr) {
auto preset = juce::ValueTree::fromXml(*xml);
auto params = preset.getChildWithName("Params");
for (auto ¶m: getParameters()) {
auto paramTree = params.getChildWithName(getParamID(param));
if (paramTree.isValid())
param->setValueNotifyingHost(paramTree["Value"]);
}
//Load your non-parameter data now
}
}
juce::AudioProcessorEditor *ReverbAudioProcessor::createEditor() {
return nullptr;
}
void ReverbAudioProcessor::reset() {
return this->_reverb.reset();
}
juce::AudioProcessor::BusesProperties ReverbAudioProcessor::getBuses() {
const auto stereo = juce::AudioChannelSet::stereo();
return BusesProperties()
.withInput("Input", stereo, true)
.withOutput("Output", stereo, true);
}
void ReverbAudioProcessor::updateReverb() {
juce::Reverb::Parameters params{};
params.roomSize = _roomSizeParam->get();
params.damping = _dampingParam->get();
params.wetLevel = _wetLevelParam->get();
params.dryLevel = _dryLevelParam->get();
params.width = _widthParam->get();
params.freezeMode = _freezeModeParam->get();
_reverb->setParameters(params);
}
juce::AudioProcessor *JUCE_CALLTYPE createPluginFilter() {
return new ReverbAudioProcessor();
}
PluginProcessor.h
#pragma once
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_dsp/juce_dsp.h>
class ReverbAudioProcessor : public juce::AudioProcessor {
public:
inline static const std::string NAME = "Reverb";
ReverbAudioProcessor();
void prepareToPlay(double /*sampleRate*/, int /*blockSize*/) override {}
void reset() override;
void releaseResources() override {}
void updateReverb();
bool isBusesLayoutSupported(const BusesLayout &) const override { return true; }
void processBlock(juce::AudioBuffer<float> &, juce::MidiBuffer &) override;
bool hasEditor() const override { return true; }
juce::AudioProcessorEditor *createEditor() override;
const juce::String getName() const override { return JucePlugin_Name; }
bool acceptsMidi() const override { return true; }
bool producesMidi() const override { return false; }
bool isMidiEffect() const override { return false; }
double getTailLengthSeconds() const override { return 0.0; }
int getNumPrograms() override { return 1; }
int getCurrentProgram() override { return 0; }
void setCurrentProgram(int) override {}
const juce::String getProgramName(int) override { return juce::String(); }
void changeProgramName(int, const juce::String & /*newName*/) override {}
void getStateInformation(juce::MemoryBlock &destData) override;
void setStateInformation(const void *data, int sizeInBytes) override;
private:
static BusesProperties getBuses();
juce::AudioParameterFloat *_roomSizeParam;
juce::AudioParameterFloat *_dampingParam;
juce::AudioParameterFloat *_wetLevelParam;
juce::AudioParameterFloat *_dryLevelParam;
juce::AudioParameterFloat *_widthParam;
juce::AudioParameterFloat *_freezeModeParam;
std::unique_ptr<juce::dsp::Reverb> _reverb;
};