A preliminary view of the Zen API’s

Note: A more recent version of this draft is available here

With Zen becoming more stable (especially with the 1.4 release), it is now time to start on opening it up to other developers. I am going to release 2 Zen API’s:
- the ZenAwareAudioFX API is a small extension to AudioEffectX, designed for cooperation between Zen and its hosted plugins.
- the ZenDB API will provide access to the local Zen database, and will allow developers to run searches to implement their own presets browser/manager.

Let me focus on the first API, which is the one I have mostly been working on lately. The need for this API stemmed from the need to deal with complex presets, with dependencies on data files (typically, samples) managed outside of the plugin. Absynth is a good example, and if you try to load a preset into Absynth without having the required .wav files in the proper folder, you will be greeted by an error message.

The ZenAwareAudioFX class aims to correct this, by enabling the plugin to communicate information about the required external files (that I call “assets”) it needs for the current preset. Everything is based on the existing mechanisms in the VST SDK, namely:

  • The host (e.g, Zen) will send requests to the Zen-aware plugin using vendorSpecific calls
  • The plugin will query the host using hostVendorSpecific calls

The ZenAwareAudioFX class takes care of all these calls, and leaves you with a few high level methods. These methods are pure virtual, so you simply have to inherit from ZenAwareAudioFX instead of AudioEffectX, and implement these methods in your plugin.

The methods you will need to implement are explained below:

virtual bool hasExternalAssets() const;This tells Zen if your plugin uses external assets. Usually this will return true, as you wouldn’t be here otherwise !

virtual unsigned int zenGetNumberOfAssets() const;This tells how many assets are used by the current preset.

virtual Zen::ZenErrorCode zenGetAssetName(unsigned int idx, char* assetName) const;This returns the name of the nth asset in the current preset. The host (Zen) will provide a char[128] buffer in assetName for you to write in. This name will be used to uniquely identify your asset among others for the same plugin, so if you use numeric ID’s for your assets, you can use itoa or equivalent to fill in the name.

virtual unsigned int zenGetAssetDataSize(unsigned int idx) const;As far as Zen is concerned, assets are opaque blocks of data with a name and a size. Zen will call this to know the required size, so that it can allocate it before calling the next method.

virtual Zen::ZenErrorCode zenGetAssetData(unsigned int idx, void* data) const;This sends the nth asset data to Zen. You just need to write into the provided data area (which has been allocated by Zen according to the size you declared in the previous method), using whatever serialization mechanism you want. Zen will associate this data block with the preset, upload it to the server, and distribute it to the clients.

typedef struct {
const char *assetName;
unsigned int assetSize;
void* data;
} ZenAssetData;
Zen::ZenErrorCode zenQueryAssetData(Zen::ZenAssetData* data);
This is used by the plugin to retrieve the asset from Zen. You will actually have to call this twice: first fill in assetName and set data to NULL. The call will return assetSize. Then allocate your memory area according to assetSize, set the data pointer in the ZenAssetData structure, and call this method again – Zen will then fill the area with the asset data.

6 Responses to “A preliminary view of the Zen API’s”

  1. Matt Says:

    I don’t like that I have to call zenQueryAssetData twice. If your problem is the memory allocation you could ask for a allocator as a callback:

    Something like

    typedef void * (*AllocateCallback)(std::size_t assetSize);

    Zen::ZenErrorCode zenQueryAssetData(Zen::ZenAssetData* data, AllocateCallback callback);

    So I pass in a ZenAssetData filled with only the assetName and I get back a filled ZenAssetData with both assetSize and data set using my provided memory allocation function.

    Or you simply provide a zenGetAssetDataSizeByName(const char * assetName) so I can first query the size, allocate the memory and then pass the struct in.

    BTW, why the typedef? this is C++ not C, right?

  2. Big Tick Says:

    Yes this is a pretty good suggestion !

    It is C++, yes, but think you need the typedef if you want to refer to it as “ZenAssetData” and not “struct ZenAssetData”. I might be wrong though.

  3. Matt Says:

    In C++ struct and class is the same besides that members and inheritance defaults to public in struct and private in class.

    So you can write

    struct ZenAssetData {
    const char *assetName;
    unsigned int assetSize;
    void* data;


    class ZenAssetData {
    const char *assetName;
    unsigned int assetSize;
    void* data;

    and they do the exact same thing.

  4. Hanzen Says:


    Are there any plans to support VST3? Probably an interface like “IZenInfo” the plugin has to implement?


  5. Big Tick Says:

    I don’t use VST3 personally, and don’t plan too unless someone convinces me of the advantages – I don’t see any. So yes, I could define the extensions for VST3 too, but Zen is not going to support VST3 any time soon.

  6. Big Tick Says:

    I think I took the habit of using typedef because of some issues in MSVC++, where defining
    enum {
    ZERO = 0,
    ONE = 1
    would give “multiple defined” linker error, while
    typedef enum {
    ZERO = 0,
    ONE = 1
    would not.

Leave a Reply

  • What users say

    "Angelina is the only vsti that could make the ambient sounds to go over my acid and guitar leads and sound good, so if this synth works for my hardhouse and industrial tracks, think of what it can do for you, great vsti Bigtick, two thumbs up !" - Rob (Phatt Commando)
  • Register

  • Welcome !

    Welcome to Big Tick web site ! Please login or register.

    Registration is free, and will enable you to download additional instruments and effects.