Вопрос

I've been trying to write a simple VST plugin. It doesn't need any fancy interfaces, just a few controls. But I don't know where to start. Begin huge wall of text.

I've been researching religiously around the net for information and guides on this topic, but the best I've found so far is this and this page. While they're good, I can't seem to recreate a program using those sources.

For reference, I'm using VST SDK 3.5.2 and MSVC 2010.

I added the folder \public.sdk\source\vst2.x to my project (which includes the source for audioeffect & vstplugmain). I really wish there was somewhere a simple bullet point list of what you need to do to get a working VST plugin effect working / exporting correctly etc.

The first two links I provided walk it through nicely, but it seems the method for creating a VST has changed since then. This is the skeleton of my program, which, while it compiles, won't get recognized by my VST host (error upon loading).

harmonicmodulator.h

#include "public.sdk\source\vst2.x\audioeffectx.h"
namespace Steinberg {
  namespace VST {
    class HarmonicModulator : public AudioEffectX {
      public:
        /* ?? what about createEffectInstance
        static FUnknown* createInstance (void* context) {
          return (IAudioProcessor*)new HarmonicModulator;
        }
        */
        HarmonicModulator(audioMasterCallback master);
        virtual ~HarmonicModulator(); //can't hurt
        /*
        virtuals
        */
        virtual void process (float **inputs, float **outputs, VstInt32 sampleFrames);
        virtual void processReplacing (float **inputs, float **outputs, VstInt32 sampleFrames);
        virtual void setProgramName (char *name);
        virtual void getProgramName (char *name);
        virtual void setParameter (VstInt32 index, float value);
        virtual float getParameter (VstInt32 index);
        virtual void getParameterLabel (VstInt32 index, char *label);
        virtual void getParameterName (VstInt32 index, char *label);
        virtual void getParameterDisplay (VstInt32 index, char *text);
        virtual bool getEffectName (char * name);
        virtual bool getVendorString (char * text);
        virtual bool getProductString (char * text);
        virtual VstInt32 getVendorVersion () { return 1000; }
        virtual VstPlugCategory getPlugCategory () { return kPlugCategEffect; }
        protected:
          char progname[64];
          float fparam;
    };
  }
}

harmonicmodulator.cpp

#include "HarmonicModulator.h"
namespace Steinberg {
  namespace VST {
    /*
    Implementation for the constructor.
    */
    HarmonicModulator::HarmonicModulator(audioMasterCallback cb) : AudioEffectX(cb, 1, 1), fparam(0.f) {
      setNumInputs (2); // stereo in
      setNumOutputs (2); // stereo out
      setUniqueID ('HMXX'); // identify
      canProcessReplacing (); // supports both accumulating and replacing output
      strcpy_s(progname, "Default");
    }
    /*
      Implementation for the destructor.
    */
    HarmonicModulator::~HarmonicModulator() {}
    /*
      ProcessReplacing
    */
    void HarmonicModulator::processReplacing (float **inputs, float **outputs, VstInt32 sampleFrames) {
      float *in1 = inputs[0];
      float *in2 = inputs[1];
      float *out1 = outputs[0];
      float *out2 = outputs[1];
      while (--sampleFrames >= 0) {
        (*out1++) += (*in1++);
        (*out2++) += (*in2++);
      }
    }
    /*
    Process
    */
    void HarmonicModulator::process (float **inputs, float **outputs, VstInt32 sampleFrames) {
      float *in1 = inputs[0];
      float *in2 = inputs[1];
      float *out1 = outputs[0];
      float *out2 = outputs[1];
      while (--sampleFrames >= 0) {
        (*out1++) += (*in1++);
        (*out2++) += (*in2++);
      }
    }
    /*
    Below seems to be needed to work
    */
    void HarmonicModulator::setProgramName (char *name){
      strcpy_s(progname, name);
    }
    void HarmonicModulator::getProgramName (char *name){
      strcpy_s(name, 32, progname);
    }
    void HarmonicModulator::setParameter (VstInt32 index, float value) {
      fparam = value;
    }
    void HarmonicModulator::getParameterLabel (VstInt32 index, char *label) {
      strcpy_s(label, 32, "dB");
    }
    void HarmonicModulator::getParameterName (VstInt32 index, char *label) {
      strcpy_s(label, 32, "Volume");
    }
    void HarmonicModulator::getParameterDisplay (VstInt32 index, char *text) {
      this->dB2string(fparam, text, 32);
    }
    //-----------------------------------------------------------------------------------------
    float HarmonicModulator::getParameter (VstInt32 index) {
      return fparam;
    }
    bool HarmonicModulator::getEffectName (char * name) {
      strcpy_s(name, 32, "Harmonic Modulator");
      return true;
    }
    bool HarmonicModulator::getVendorString (char * text) {
      strcpy_s(text, 32, "LightBridge");
      return true;
    }
    bool HarmonicModulator::getProductString (char * text) {
      strcpy_s(text, 32, "Harmonic Modulator");
      return true;
    }
  }
}
AudioEffect* createEffectInstance (audioMasterCallback audioMaster) {
  return new Steinberg::VST::HarmonicModulator (audioMaster);
}

Okay, the "method" I'mm using is: According to both of the previous guides, to make a successful plugin, you at least need to derive your plugin from audio effectx and override process() and processReplacing() which do the actual processing.

The rest was added in hope that it would do something. Moreover, the exported function createEffectInstance() returns a new instance of the plugin. vstplugmain.cpp holds a dllmain and an exported function VstPlugMain that receives an audiomastercallback and returns createEffectInstance(callback).

IMO, that seems like a working method and a re-creation (as far as I can see) of the two guides provided earlier. The plugin is defined and there's an interface between plug and host that allows to create instances of it. What am I missing? The guide says that's all you need.

Is this a difference between different versions of VST? 2/3?

So I couldn't get the VstPluginTestHost bundled to work, it couldn't locate my VST. I tried the validator, and stepping through that, I found that since my program doesn't export a function called GetPluginFactory, it's discarded. Okay, understandable, but none of the guides tell anything about this.

Searching through endless amounts of source, it seems some VST sources add this cryptic passage at the bottom (code taken from AGainSimple.cpp):

BEGIN_FACTORY_DEF ("Steinberg Media Technologies",
  "http://www.steinberg.net",
  "mailto:info@steinberg.de")
  //---First Plugin included in this factory-------
  // its kVstAudioEffectClass component
  DEF_CLASS2 (INLINE_UID (0xB9F9ADE1, 0xCD9C4B6D, 0xA57E61E3, 0x123535FD),
    PClassInfo::kManyInstances, // cardinality
    kVstAudioEffectClass, // the component category (don't change this)
    "AGainSimple VST3", // here the Plug-in name (to be changed)
    0, // single component effects can not be destributed so this is zero
    "Fx", // Subcategory for this Plug-in (to be changed)
    FULL_VERSION_STR, // Plug-in version (to be changed)
    kVstVersionString, // the VST 3 SDK version (don't change this, use always this definition)
    Steinberg::Vst::AGainSimple::createInstance)// function pointer called when this component should be instantiated
END_FACTORY

Which seems to export an interface that gives the host some basic information and an interface for creating the plugin. BUT. I thought createEffectInstance did this. Now there's a new function called createInstance. Is there a difference? The function signatures suggest createInstance does NOT receive the audiomaster callback, and thus can't instantiate any derivation of AudioEffect (which takes this as an parameter in its constructor) - I provided the function, commented out, in harmonicmodulator.h.

Also, I noticed that many newer sources include another "main" cpp file (dllmain.cpp, in \public.sdk\source\main, that defines exports for InitModule and DeInitModule, but no createEffectInstance anymore. This is dizzying me. They also seem to derive from either AudioEffect (no x) or SingleComponentEffect (seems to be a lot more complicated? lol).

On top of this, I can't seem to get that begin_factory stuff working because of a lot of missing constants and defines that reside in many different files. Are you supposed to add the whole SDL to your project? Thats 6,000 files.

TL;DR

Nothing really works and I can't seem to get a clue. The bundled source samples work, but they all approach the "method" of creating a VST differently. Seriously, any guidance or help will be so appreciated. I'm trying to create this as part of an application, and I got everything else pretty much worked out.

Это было полезно?

Решение

I've been trying to write a simple VST plugin. It doesn't need any fancy interfaces, just a few controls. But I don't know where to start. Begin huge wall of text.

Start by compiling the example plugins that come with the SDK. Then duplicate that with your own bare bones plugin. Continue building up from there.

Is this a difference between different versions of VST? 2/3?

VST 2 and VST 3 are different formats. I would recommend building a VST 2.4 plugin unless you have a specific reason for building a VST 3 plguin. VST 2.4 is widely supported by many hosts and will likely continue to be for some years yet. VST 3 is a newer format but not so widely supported.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top