VST音频插件架构分析

VST音频插件架构分析

前言

Virtual Studio Technology (VST),可以翻译为虚拟工作室技术,是一种音频插件软件接口,由德国Steinberg公司发布,用于在Digital Audio Workstation (DAW,可以译为数字音频工作站)中集成合成器和效果器。

现在主要还在用的是VST 2和VST 3这两个版本,VST 2是对VST 1的扩充,所以一块讲;但VST 3则是相当于一个全新的架构,所以要和VST 2分开来讲。

官方提供了VST的SDK,其中VST 2的已经没有了(但是可以在其他地方找到),只有VST 3的可以在官网找到。不过本文并不分析完整的SDK,而是分析其架构,所以只会分析SDK中关于VST的API部分。

你可以在这里找到VST 3的官方英文文档,也可以在这里找到VST 3 SDK的下载链接,其API也在SDK中;或者可以去他们的GitHub仓库去Clone完整SDK代码。

如果你需要VST 2 SDK,可以去这个GitHub仓库下载,有需要的建议还是下了,万一以后真没了也不好说。不过VST 2我是真的找不到文档了。

不得不说,Steinberg为了强推VST 3而抛弃VST 2,甚至下架其SDK以及停止授权等行为,确实饱受诟病,不过这是人家公司自己的选择,而我们依然可以接着用,甚至用竞争对手的技术,随他怎么搞呢,反正哪个流行用哪个就是了。只不过唯一的问题就是如果销售的插件或者DAW带有VST 2,估计得给人家告死,所以想拿来卖只能用VST 3,当然如果开源免费的话肯定无所谓。

本文要分析的所有代码均来自pluginterfaces文件夹。

目录

VST 2

核心文件就是在pluginterfaces/vst2.x文件夹下的aeffect.haeffectx.h,其中第一个是VST 1的,第二个是VST 2的补充,所以其整体架构就是延续了VST 1的,因此先分析一下aeffect.h的东西。

跳过前面无聊的部分,我们直奔主题——几个重要回调函数和核心结构体(删了部分注释和条件编译,同时不考虑VST 2.4不使用的内容,也就是标了DECLARE_VST_DEPRECATED的):

// 主机回调,这个是需要由主机实现一系列的opcode,然后给插件调用的
typedef VstIntPtr (VSTCALLBACK *audioMasterCallback) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);
// 调度函数,插件实现一系列的opcode,提供给主机调用的
typedef VstIntPtr (VSTCALLBACK *AEffectDispatcherProc) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);
// 音频处理函数,插件实现,由主机提供输入和输出缓冲区,以及要处理的采样数,通常在单独的线程调用
typedef void (VSTCALLBACK *AEffectProcessProc) (AEffect* effect, float** inputs, float** outputs, VstInt32 sampleFrames);
// 同上,但是缓冲区的double类型的浮点数,而不是float类型的,有更高的精度
typedef void (VSTCALLBACK *AEffectProcessDoubleProc) (AEffect* effect, double** inputs, double** outputs, VstInt32 sampleFrames);
// 参数设置函数,主机提供一个索引和一个参数值,插件负责保存对应的参数
typedef void (VSTCALLBACK *AEffectSetParameterProc) (AEffect* effect, VstInt32 index, float parameter);
// 参数获取函数,主机提供一个索引,插件返回该索引对应参数的值
typedef float (VSTCALLBACK *AEffectGetParameterProc) (AEffect* effect, VstInt32 index);

// 前面几个回调函数的第一个参数需要的结构体
struct AEffect
{
    VstInt32 magic; // "VstP",按32位整数保存,注意'V'是在地址高位的,即0x56737450
    AEffectDispatcherProc dispatcher; // AEffectDispatcherProc函数指针
    AEffectProcessProc DECLARE_VST_DEPRECATED (process);
    AEffectSetParameterProc setParameter; // AEffectSetParameterProc函数指针
    AEffectGetParameterProc getParameter; // AEffectGetParameterProc函数指针
    VstInt32 numPrograms; // 预设的数量
    VstInt32 numParams;   // 参数的数量
    VstInt32 numInputs;   // 输入通道数量
    VstInt32 numOutputs;  // 输出通道数量
    VstInt32 flags; // 见VstAEffectFlags
    VstIntPtr resvd1; // 给主机留着的,置0
    VstIntPtr resvd2; // 同上
    VstInt32 initialDelay; // 大概是某些算法有延迟,这个参数告诉主机延迟的采样数,一般就0
    VstInt32 DECLARE_VST_DEPRECATED (realQualities);
    VstInt32 DECLARE_VST_DEPRECATED (offQualities);
    float    DECLARE_VST_DEPRECATED (ioRatio);
    void* object; // 指针,指向SDK里的类,不用SDK的话可以自定义使用,每个实例都不一样
    void* user;   // 留给插件开发者自由分配的指针
    VstInt32 uniqueID; // 每个插件要一个独一无二的标志,得找Steinberg申请,现在也没啥用了,尽可能独一无二
    VstInt32 version;  // 插件的版本
    AEffectProcessProc processReplacing; // 替换模式的process函数,这个替换应该是指输入输出缓冲区是同一个
    AEffectProcessDoubleProc processDoubleReplacing; // 同上,但是使用double类型的采样
    char future[56]; // 留给未来的(然而没有了),置0
};

// 上面AEffect里flags需要的标志位
enum VstAEffectFlags
{
    effFlagsHasEditor     = 1 << 0, // 插件有编辑器(UI界面)
    effFlagsCanReplacing  = 1 << 4, // 支持processReplacing,必须要设置
    effFlagsProgramChunks = 1 << 5, // 没用过,感觉没啥用
    effFlagsIsSynth       = 1 << 8, // 合成器得设置这个
    effFlagsNoSoundInStop = 1 << 9, // 没用过,大概是说插件保证process的时候输入为0就不会输出声音
    effFlagsCanDoubleReplacing = 1 << 12, // 支持processDoubleReplacing,可选
    DECLARE_VST_DEPRECATED (effFlagsHasClip) = 1 << 1,
    DECLARE_VST_DEPRECATED (effFlagsHasVu)   = 1 << 2,
    DECLARE_VST_DEPRECATED (effFlagsCanMono) = 1 << 3,
    DECLARE_VST_DEPRECATED (effFlagsExtIsAsync)   = 1 << 10,
    DECLARE_VST_DEPRECATED (effFlagsExtHasBuffer) = 1 << 11
};

注意回调函数那边的VSTCALLBACK其实就是C语言默认的函数调用约定,前面有定义,但实际上用C开发的话没必要。这几个回调函数里,一般情况下除了音频处理的函数需要在单独的线程中进行,其它的都是在UI线程进行的。

结构体主要提供插件的基本信息以及一些回调函数的指针,根据需要设置就行了,还有这个flags必须设置effFlagsCanReplacing,因为大部分插件都是有界面的,所以基本上都要设置effFlagsHasEditor,如果是合成器就设置effFlagsIsSynth,不然默认是效果器,最后这个effFlagsCanDoubleReplacing看需不需要双精度浮点数吧,建议是要的,因为现在大部分软件和插件都是64位的,一般64位CPU处理double很快而且精度更高,大部分DAW内部也是用double类型的数据。

插件的入口函数一般是这么定义的:

AEffect *VSTPluginMain(audioMasterCallback hostCallback)
{
    new MyPlugin(hostCallback)->getAEffect();
}

这里的MyPlugin是一个C++的类,参数就是audioMasterCallback的回调,然后调用getAEffect获取该类对应的AEffect结构体指针,每个插件的实例都要这样,不然插件之间会影响。

入口函数的名称除了VSTPluginMain也可以是main,一般只要前者,记得要在DLL导出,不同编译器有不同的方法。

接着说几个关键opcode,插件必须要实现的或者是实现基本功能需要的,否则插件跑不起来,opcode的定义在aeffect.haeffectx.h里,分别是枚举AEffectOpcodesAudioMasterOpcodesX

  • effGetVstVersion,一定要实现,返回2400,不然主机(大概率)会认为这个插件是老版本的
  • effGetParamLabel、effGetParamDisplay、effGetParamName,可选,和参数的显示有关,可以在DAW看到
  • effSetSampleRate、effSetBlockSize,有些效果需要采样率、块大小之类的参数
  • effCanBeAutomated,参数是否可以被自动化,挺有用的
  • effEditGetRect、effEditOpen、effEditClose,界面相关的,有插件界面肯定要实现
  • effEditIdle,主机在UI线程调用,用来给插件更新界面用的
  • effGetChunk、effSetChunk,保存或设置所有参数的值,给主机用来实现插件参数状态的保存

除了插件要实现opcode,有些功能需要调用主机提供的回调函数,在枚举AudioMasterOpcodesAudioMasterOpcodesX中。

  • audioMasterAutomate,比如用户拖动界面的控件,调用这个告诉主机这个参数可以被自动化
  • audioMasterBeginEdit、audioMasterEndEdit,在用户开始修改参数到结束修改参数时调用,通常是鼠标按下到松开
  • audioMasterGetDirectory,向主机询问插件DLL的路径,一般用来加载资源用

所以你只要实现最基本的AEffect结构体,实现几个核心回调函数,就可以实现一个最简单的VST 2.4插件了。

至于其他没提到的opcode,还有一大堆结构体、常量,不在本文讨论之列。

这样看来,VST 2架构的本质就是用到了C风格的回调函数,这很像Windows的窗口机制(WndProc函数)。

VST 3

VST 3之于VST 2,和VST 2与VST 1的关系完全不同,前者更像是重写的架构,而不是后者一样的扩充。

VST 3是由一组类似于COM的接口和一系列数据结构组成的。

如果说详细点,VST 3是由VST MAVST 3 API组成的,分别在pluginterfaces/basepluginterfaces/vst这两个文件夹里。

熟悉COM的看这个应该没什么问题, 不熟悉的话建议先了解一下COM技术,会稍微好一点。

与COM的IUnknown不同,VST自己定义了FUnknown,不过其实是ABI兼容的,VST的所有和COM类似的部分都是自己定义的,目的就是去除对Windows平台(COM有关头文件)的依赖,实现跨平台。

class FUnknown
{
public:
    virtual tresult PLUGIN_API queryInterface (const TUID _iid, void** obj) = 0;
    virtual uint32 PLUGIN_API addRef () = 0;
    virtual uint32 PLUGIN_API release () = 0;

    static const FUID iid;
};
DECLARE_CLASS_IID (FUnknown, 0x00000000, 0x00000000, 0xC0000000, 0x00000046)

类型tresult类似于HRESULT,其实就是一个32位整数,0表示OK,其余都是一个负数,表示各种错误。

类型TUID是这么定义的typedef int8 TUID[16];,其实和GUID是兼容的。

类型FUID是一个类,但是没有虚函数,其实可以理解为仅有一个TUID成员的带方法的高级结构体。

调用约定是PLUGIN_API,在Windows我平台是stdcall,在其他平台是cdecl。

源代码文件里好多东西,真正有用的其实不多,当然用C++搞这个COM接口确实蛋疼,毕竟语言级别的支持没有,比如每个接口都有的静态常量iid,实际上Steinberg是自己实现了一个FObject对象来实现的各种功能,还有一堆宏。不过实现的方法有很多,如果说把VST 3的接口翻译到别的语言,有些功能实现起来可能会轻松不少。

接下来是VST MA里的重要接口,IPluginBase,这个接口可以说是VST 3所有插件的基础了。

class IPluginBase: public FUnknown
{
public:
    // 初始化,给的接口必须可以获取IHostApplication,同时插件应该在这个方法里实现内存分配等任务,而不是构造函数里
    virtual tresult PLUGIN_API initialize (FUnknown* context) = 0;
    // 终止,之前分配的内存在这里销毁
    virtual tresult PLUGIN_API terminate () = 0;

    static const FUID iid;
};
DECLARE_CLASS_IID (IPluginBase, 0x22888DDB, 0x156E45AE, 0x8358B348, 0x08190625)

主机保证会在需要的时候调用initialize,同时确保会调用terminate让插件释放资源。

之后会讲到的几个VST 3接口,都是在其基础之上的,不过在此之前,最后讲一下VST MA里最后一个关键接口——IPluginFactory,很显然,用的工厂模式。

class IPluginFactory : public FUnknown
{
public:
    // 获取插件工厂信息
    virtual tresult PLUGIN_API getFactoryInfo (PFactoryInfo* info) = 0;
    // 获取类的数量,一般都是2
    virtual int32 PLUGIN_API countClasses () = 0;
    // 获取索引index的类的信息
    virtual tresult PLUGIN_API getClassInfo (int32 index, PClassInfo* info) = 0;
    // 根据类的16位UID和接口的16位UID创建实例,FIDString就是char *
    virtual tresult PLUGIN_API createInstance (FIDString cid, FIDString _iid, void** obj) = 0;

    static const FUID iid;
};

DECLARE_CLASS_IID (IPluginFactory, 0x7A4D811C, 0x52114A1F, 0xAED9D2EE, 0x0B43BF9F)

其中PFactoryInfoPClassInfo如下:

struct PFactoryInfo
{
    enum FactoryFlags
    {
        kNoFlags                 = 0,
        kClassesDiscardable      = 1 << 0, // 工厂的类可变,主机得累死,一般不用
        kLicenseCheck            = 1 << 1, // 最新版已经弃用了,应该是检查许可证
        kComponentNonDiscardable = 1 << 3, // 组件不会被卸载,直到进程退出
        kUnicode                 = 1 << 4  // 组件支持Unicode,其实是UTF-16,基本都要支持,要国际化的嘛
    };
    enum
    {
        kURLSize = 256,
        kEmailSize = 128,
        kNameSize = 64
    };
    char8 vendor[kNameSize]; // 供应商名称
    char8 url[kURLSize];     // 供应商网站
    char8 email[kEmailSize]; // 供应商电子邮箱
    int32 flags; // 上面的FactoryFlags
};

struct PClassInfo
{
    enum ClassCardinality
    {
        kManyInstances = 0x7FFFFFFF // 允许多个实例,也就是加载好几个
    };
    enum
    {
        kCategorySize = 32,
        kNameSize = 64
    };
    TUID cid; // 这个类的UID,自己随机生成一个就行了,基本确保唯一性
    int32 cardinality; // 设置上面那个kManyInstances
    char8 category[kCategorySize]; // 类的类别,比如"Audio Module Class"、"Component Controller Class"这种
    char8 name[kNameSize]; // 类的名称,自己起一个
};

这个工厂后来还扩充了IPluginFactory2IPluginFactory3,接口如下:

class IPluginFactory2 : public IPluginFactory
{
public:
    // 获取PClassInfo2的类信息
    virtual tresult PLUGIN_API getClassInfo2 (int32 index, PClassInfo2* info) = 0;

    static const FUID iid;
};

DECLARE_CLASS_IID (IPluginFactory2, 0x0007B650, 0xF24B4C0B, 0xA464EDB9, 0xF00B2ABB)

struct PClassInfo2
{
    TUID cid; // 兼容PClassInfo结构体
    int32 cardinality; // 同上
    char8 category[PClassInfo::kCategorySize]; // 同上
    char8 name[PClassInfo::kNameSize]; // 同上
    enum {
        kVendorSize = 64,
        kVersionSize = 64,
        kSubCategoriesSize = 128
    };
    uint32 classFlags; // 目前仅针对"Audio Module Class",有kDistributable和kSimpleModeSupported
    char8 subCategories[kSubCategoriesSize]; // 子类别,比如"Fx"这种,有具体的常量定义
    char8 vendor[kVendorSize]; // 供应商名称
    char8 version[kVersionSize]; // 版本,比如"1.0.0.0"
    char8 sdkVersion[kVersionSize]; // VST版本,有常量定义,比如"VST 3.7.8"
};

class IPluginFactory3 : public IPluginFactory2
{
public:
    // 没啥好说的
    virtual tresult PLUGIN_API getClassInfoUnicode (int32 index, PClassInfoW* info) = 0;
    // 主机提供一个上下文接口,应该也是实现了IHostApplication
    virtual tresult PLUGIN_API setHostContext (FUnknown* context) = 0;

    static const FUID iid;
};

DECLARE_CLASS_IID (IPluginFactory3, 0x4555A2AB, 0xC1234E57, 0x9B122910, 0x36878931)

// 相比于PClassInfo2,就一些char8换成了char16,没啥好说的
struct PClassInfoW
{
    TUID cid;
    int32 cardinality;
    char8 category[PClassInfo::kCategorySize]; // 这个没变,因为有常量定义,只能是ASCII字符串
    char16 name[PClassInfo::kNameSize];
    enum {
        kVendorSize = 64,
        kVersionSize = 64,
        kSubCategoriesSize = 128
    };
    uint32 classFlags;
    char8 subCategories[kSubCategoriesSize];
    char16 vendor[kVendorSize];
    char16 version[kVersionSize];
    char16 sdkVersion[kVersionSize];
};

实际开发中,一般只要自己设置PClassInfo2,然后转成PClassInfoW就行了,如果用Steinberg提供的工具的话,甚至都不用写这些代码。

作为插件,在动态链接库里需要导出名为GetPluginFactory的函数,用来获得工厂对象,一个可能的实现如下:

SMTG_EXPORT_SYMBOL IPluginFactory* PLUGIN_API GetPluginFactory ()
{
    static MyPluginFactory *gFactory = nullptr;
    if (!gFactory) {
        gFactory = new MyPluginFactory;
    }
    else {
        gFactory->addRef();
    }
    return gFactory;
}

在Windows平台,还有可选的InitDllExitDll,可选是因为Windows有DllMain,可以实现加载/卸载时的资源申请/释放操作,但是Linux和macOS就不这样了。在Linux平台,使用ModuleEntryModuleExit;而在macOS平台,使用BundleEntryBundleExit。主机必须在加载插件后调用XxxEntry,且在卸载前调用XxxExit

主机获取到了插件的工厂之后,就会去依次调用几个方法获取相关信息,同时还会尝试调用queryInterface来获取IPluginFatory2IPluginFactory3的对象,最后调用createInstance来创建IComponentIEditController的对象。

主机一般会先调用createInstance获取IComponent,然后通过queryInterface获取IAudioProcessor

Steinberg建议插件的音频处理部分和参数控制部分分离,这个需要在classFlags里设置kDistributable,如果没有设置,那么主机就会尝试通过IComponent对象接着获取IEditController,否则就重新调用createInstance。分离的好处是灵活,不分离好处是代码简单,因为这几个接口都可以在同一个类里面实现。

可以参考一下Audio Processor调用过程图Edit Controller调用过程图

关于IComponentIAudioProcessorIEditController就不多介绍了,和底层架构关系不大,已经是特定功能的接口了。

要实现其他功能的话,比如GUI,还得有IPlugViewIPlugFrame,如果要在GUI控制参数的话还要IComponentHandler,还有好多接口以及各种各样的结构体,反正突出一个字——乱。

其实到这里,我也只是讲了VST 3那么多机制的冰山一角,当然底层架构基本就算是说完了,剩下的就是在这套架构的基础上增加的各种各样的功能了。

VST 2和VST 3的对比

在开始对比之前,我想先说一下历史,来捋一下时间线。

COM是微软在1993年首次提出的,VST 1.0是在1996年推出的,在90年代那会,COM逐渐流行起来,然后在1999年推出了VST 2,接下来几年就不断更新,到了2006年的2.4就不动了,随后就是2008年的VST 3。2013年,Steinberg宣布不再维护VST 2 SDK,但是开发者基本不受影响,直到2018年,Steinberg准备停止VST 2的支持,也就意味着18年之后,任何开发者如果没有在之前和Steinberg签了协议的话,就不能开发商业的VST 2插件了。而到了2022年,Steinberg更是直接宣布他家软件将最后支持VST 2插件24个月,然后就会移除VST 2的支持,然后就引起了骂声一片。

奇怪的是,明明1993年就有了COM,为啥2008年的VST 3才用了这个呢?事实上并不奇怪,因为VST 1到VST 2那段时间,VST插件可以说是非常火爆的,即使Steinberg在自己的软件Cubase和Nuendo已经用了类似COM的技术,也就是VST MA,但是想要推广开来还是需要时间的,所以他们也只能硬着头皮先更新VST 2再说。不过由于VST 2不符合Steinberg的利益需要了,所以他们推出了新架构的VST 3,但是实际上如果接着扩充VST 2,未尝不可实现现在的一下新功能,只不过VST 2的架构势必会变得更加臃肿——增加更多opcode,弃用一些老的opcode,甚至增加新的回调函数。

但不论如何,对于广大开发者而言,VST 3相比于VST 2并没有什么升级,而是换了一种Steinberg喜欢的开发方式而已,插件该有的功能基本都有,没有的很多主机也不会去实现,而且给VST 2接着打补丁也是可以实现的,况且VST 3更庞大,更复杂。但是Steinberg偏不,强推新的VST 3,甚至到现在打算完全放弃支持旧的VST 2。

可以看看国外的这篇文章,或者国内有人发布的翻译版本,基本说了二者的一些区别与好坏。

国外也有人讨论关于VST 3为数不多的好功能——样本精确自动化(提供采样点和参数的列表,能提高参数自动化时的精度,同时性能损失较少),不过大部分DAW很难支持,因为其他的插件格式不一定有这个功能,况且目前也有DAW(说的就是某水果形状的软件)做了减小单次处理的样本数量这样的方法来提高参数自动化的精度(对有些插件来说这样会出现问题)。当然这个功能确实非常不错,但是实际上在VST 2的架构上扩充,未尝不能实现。

从技术架构的角度出发,显然VST 2更加通用,兼容性更好,因为插件的底层就是C风格的回调函数,这适用于绝大多数的语言,所以可以很轻松地在其他语言实现,比如现在比较火的Rust、Zig这类的。

而VST 3的SDK则是和C++深度绑定,虽然官方也提供了C风格的接口,实际上就是微软COM的早期模式,用C语言的结构体来模拟现在C++的虚函数表。但是和C++的过度耦合,使得其他语言很难实现,但是也不是没有,比如Rust也有人做过。

至于我为什么会对这俩玩意这么熟悉,那就得回到2021年,那会对VST 2插件的开发有些兴趣,又不想用C/C++这样的技术开发,想用我之前比较熟悉的Object Pascal开发,同时配合Delphi的VCL或者Lazarus的LCL库可以轻松实现GUI界面的开发,尤其是LCL可以轻松跨平台。

所以在那年陆陆续续花了几个月就搞清楚了VST 2的架构,就是用最基础的C风格的回调构建代码,写了一些基础的插件,当然是因为DSP那块不是很熟悉,也不会复杂的算法。

后来考虑到VST 2确实也比较老了,加上我又没赶上当时最后一波的机会(2018年之后就无法获取VST 2专用授权许可证了),所以也不可能再发布VST 2的任何插件了,所以就将目光转向了VST 3(在专用授权许可证之外,还可以选用GPLv3许可证),然后就断断续续花了两年时间,到最近(2023年7月)才终于完成最后一步——摸清架构,写出基础插件。花了这么久的时间,主要还是C++的代码翻起来太难受了,加上代码量巨大,光是翻译成Object Pascal的接口部分代码,就将近4000行,再加上还有实现一个基础插件还需要1000多行的代码,这和VST 2完全不能比(接口1000多行,基础插件几百行)。

如果你有兴趣,可以光顾一下我的GitHub,关于VST 2和VST 3的Pascal版本的链接就放这里了:

结语

VST 2和VST 3是两个独立的技术路线,只因创造者Steinberg换了他们的口味,导致VST 2这一简单好用且流行的格式被迫随着时间而逐渐淡出人们视野。当然VST 3也不是一无是处,毕竟COM技术也是微软多年实践验证过的,也没什么问题。而且Steinberg提供了高度封装的VST 3 SDK,以及AAX、AU等其他格式的包装器,还有一系列的工具,使得实际的开发得到了简化(当然大部分人可能用JUCE这种库)。

但是Steinberg做的不好的就是想要强行改变开发者习惯,在VST 2用的好好的情况下,居然用各种手段迫使开发者转换到VST 3来,而且甚至还想要放弃支持VST 2。强如微软也依然保持着基本的兼容性,甚至MIDI 2.0也是对MIDI 1.0的补充,要知道MIDI 1.0那是1983年的古老标准了。不是谁都是苹果,可以有那么强的实力随意破坏向后兼容性。

希望Steinberg好自为之,接着支持原有的VST 2,好好经营VST 3,同时不要再让未来可能的VST 4也这样了。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VST SDK 3.6.12 •The VST 3 API •VST 3 Implementation Helper Classes •AAX, AU and VST 2 wrappers •VST 3 Plug-ins Examples About VST 3 VST 3 is a general rework of the long-serving VST Plug-in interface. It is not compatible with the older VST versions, but it includes some new features and possibilities. We have redesigned the API to make it not only far easier and more reliable for developers to work with, but have also provided completely new possibilities for Plug-ins. These include: 1. Improved Performance with the Silence Flag Processing can optionally be applied to Plug-ins only when audio signals are present on their respective inputs, so VST 3 Plug-ins can apply their processing economically and only when it is needed. 2. Multiple Dynamic I/Os VST 3 Plug-ins are no longer limited to a fixed number of inputs and outputs, and their I/O configuration can dynamically adapt to the channel configuration. Side-chains are also very easily realizable. This includes the possibility to deactivate unused buses after loading and even reactivate those when needed. This cleans up the mixer and further helps to reduce CPU load. 3. Sample-accurate Automation VST 3 also features vastly improved parameter automation with sample accuracy and support for ramped automation data, allowing completely accurate and rapid parameter automation changes. 4. Logical Parameter Organization The VST 3 Plug-in parameters are displayed in a tree structure. Parameters are grouped into sections which represent the structure of the Plug-in. Plug-ins can communicate their internal structure for the purpose of overview, but also for some associated functionality (eg. program-lists). 5. Resizeable UI Editor VST 3 defines a way to allow resizing of the Plug-in editor by a user. 6. Mouse Over Support The Host could ask the Plug-in which parameter is under the mouse. 7. Context Menu Support VST 3 defines a way to allow the host to add its own entries in the Plug-in context menu of a specific parameter. 8. Channel Context Information A VST 3 Plug-in could access some channel information where it is instantiated: name, color,... 9. Note Expression VST 3 defines with Note Expression a new way of event controller editing. The Plug-in is able to break free from the limitations of MIDI controller events by providing access to new VST 3 controller events that circumvent the laws of MIDI and provide articulation information for each individual note (event) in a polyphonic arrangement according to its noteId. 10. 3D Support VST 3 supports new speaker configurations like Ambisonic, Atmos, Auro 3D or 22.2. 11. Factory Concept VST 3 Plug-in library could export multiple Plug-ins and in this way replaces the shell concept of VST 2 (kPlugCategShell). 12. Support Remote control Representation VST 3 Plug-in can deliver a specific parameter mapping for remote controls like Nuage. 13. Others While designing VST 3, we performed a careful analysis of the existing functionality of VST and rewrote the interfaces from scratch. In doing so, we focused a lot on providing clear interfaces and their documentation in order to avoid usage errors from the deepest possible layer. Some more features implemented specifically for developers include: - More stable technical Host/Plug-in environment - Advanced technical definition of the standard - Modular approach - Separation of UI and processing - Advanced Preset System - Multiple Plug-ins per Library - Test Host included - Automated Testing Environment - Validator (small command line Test Host) and Plug-in examples code included
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值