Our Community Plugin Format

DSP, Plugin and Host development discussion.
Locked New Topic

Poll 1 - Let's give it a name (Acronym)

HOT Plugins
0
No votes
WAR Plugins
0
No votes
TOP Plugins
0
No votes
OUR Plugins
0
No votes
PRO Plugins +1 Point
1
3%
EVE Plugins
3
10%
ION Plugins
3
10%
IVY Plugins
2
7%
MAN Plugins +1 Point
0
No votes
WTF Plugins +2 Points
1
3%
KVR Plugins (permission issue?)
2
7%
DIY Plugins
1
3%
COP Plugins
1
3%
API Plugins (Amazing Plugin Interface)
0
No votes
TPIA Plugins (This Plugin is Amazing)
0
No votes
OPI Plugins (Open Plugin Interface)
8
27%
OPS Plugins (Open Plugin Standard)
8
27%
 
Total votes: 30

RELATED
PRODUCTS

Post

BlitBit wrote: Wed Jul 08, 2020 3:49 pm While the plugin format does not have a name yet there's at least a name for that: it's called bikeshedding. ;)
It is probably funny to mock others but it does not help anyone but your ego. Take a look at mystran's interface example, it has Opi prefix everywhere. Do you know why?

Post

Community.h has been updated with mystran's OPI code.

Github:
https://github.com/The-Originator/CommunityPlugin

I updated the repository. Please contribute with your own ideas and code, the more we do, the better the interface will become.

I will reset the poll with the new suggestions, and remove the names with zero votes.
SLH - Yes, I am a woman, deal with it.

Post

Vokbuz wrote: Wed Jul 08, 2020 4:00 pm
BlitBit wrote: Wed Jul 08, 2020 3:49 pm While the plugin format does not have a name yet there's at least a name for that: it's called bikeshedding. ;)
It is probably funny to mock others but it does not help anyone but your ego. Take a look at mystran's interface example, it has Opi prefix everywhere. Do you know why?
Because as long as it's something sufficiently unique that you can do a search&replace job later, it ultimately doesn't really matter what the exact prefix happens to be.

edit: Also "Open Plugin Interface" didn't seem to return any useful Google results.

Post

Vokbuz wrote: Wed Jul 08, 2020 4:00 pm
BlitBit wrote: Wed Jul 08, 2020 3:49 pm While the plugin format does not have a name yet there's at least a name for that: it's called bikeshedding. ;)
It is probably funny to mock others but it does not help anyone but your ego.
Please mind the smiley! I assumed that not everybody knows that term and it might be interesting to learn about it.
Vokbuz wrote: Wed Jul 08, 2020 4:00 pm Take a look at mystran's interface example, it has Opi prefix everywhere. Do you know why?
Because it's a C interface and C does not have namespaces.
Passed 303 posts. Next stop: 808.

Post

A little more errata: entry point should also take "void*hostPtr" that the plugin should put into the OpiPlugin struct, so that the host can correctly identify the plugin even during initialization (ie. before the entrypoint returns).

Post

On a more productive note here's my request for the new plugin format. It would be great if it offered an implementation of real-time safe communication channels between the different threads (audio, GUI, etc.) so that developers would not have to reinvent the wheel over and over again (and potentially poorly).

There are many things one should/must not do when implementing audio plugins so it would be nice if the heavy lifting could be done by the plugin API/implementation.

In case people want the finer grained control it could be considered to provide a layered API, i.e. some developers could go the hardcore way and implement everything themselves while others would use the higher level communication channels.

On a related note it would also be great (if possible) to implement some of the protocol between the host and the plugins so that host developers can integrate the new API with as less effort as possible. This might also reduce the surface for problems a la "It works on that host X but does not work on host Y."
Passed 303 posts. Next stop: 808.

Post

Samplerate is still being represented as a float? Why not double?

I like the idea of automation being considered as another audio stream. With deltaTime serializing the automation buffer (I think I read that automation events would be buffered?), may there be some cases that the memory load presented to the system is increased by the addition of the deltaTime type?

Post

Minimal example of a gain plugin using the draft API. This compiles, but no idea if it actually works.

This is not an example of modern software development best-practice, but rather a minimal "hack" to try an implement a minimal plugin with support for the basics.

Code: Select all


#include "plugin-opi.h"

#include <vector>
#include <cstdio>

struct OpiGain : public OpiPlugin
{
    std::vector<char> stringBuffer;

    int nChannels = 0;
    float gain = 1;

    OpiGain(OpiCallback hostCallback, void * ptr)
    {
        dispatchToHost = hostCallback;
        dispatchToPlugin = &pluginDispatcher;
        ptrHost = ptr;
    }

    void process(OpiProcessInfo * procInfo)
    {
        assert(procInfo->processInfoSize == sizeof(OpiProcessInfo));
        
        int nFrames = procInfo->nFrames;

        uint64_t silenceMask = procInfo->inputs[0].silenceMask;
        uint64_t skipMask = silenceMask & procInfo->outputs[0].silenceMask;

        for(int c = 0; c < nChannels; ++c)
        {
            if((1<<c) & skipMask) continue;
            if((1<<c) & silenceMask)
            {
                for(int i = 0; i < nFrames; ++i)
                {
                    procInfo->outputs[0].channels[c][i] = 0;
                }
            }
            else
            {
                for(int i = 0; i < nFrames; ++i)
                {
                    procInfo->outputs[0].channels[c][i]
                        = gain * procInfo->inputs[0].channels[c][i];
                }
            }
        }
    }

    int configure(OpiConfig * config)
    {
        if(config->inBusChannels[0].nChannels
        == config->inBusChannels[1].nChannels)
        {
            nChannels = config->inBusChannels[0].nChannels;
            return 1;
        }
        else
        {
            return 0;
        }
    }

    void setStringBuffer(const char * data, int size = -1)
    {
        if(size == -1) size = strlen(data);
        
        stringBuffer.resize(size + 1);
        memcpy(stringBuffer.data(), data, size);
        stringBuffer[size] = 0;
    }

    static intptr_t pluginDispatcher(
        struct OpiPlugin * ptr, int32_t op, int32_t idx, void*data)
    {
        OpiGain * plug = (OpiGain*) ptr;

        if(!op)
        {
            plug->process((OpiProcessInfo*) data);
            return 1;
        }
        
        switch(op)
        {
        case opiPlugDestroy: delete plug; return 1;

        case opiPlugNumInputs: return 1;    // one input
        case opiPlugNumOutputs: return 1;   // one output
        case opiPlugMaxChannels: return 2;  // up to 2 channels

        case opiPlugInEventMask: return 0;  // don't want events
        case opiPlugOutEventMask: return 0; // don't emit events

        case opiPlugGetLatency: return 0;   // no latency

        case opiPlugConfig: return plug->configure((OpiConfig*) data);
        case opiPlugReset: return 1;    // no-op

        case opiPlugEnable: return 1;   // no-op
        case opiPlugDisable: return 1;  // no-op

        case opiPlugOpenEdit: return 0;     // don't have editor
        case opiPlugCloseEdit: return 0;    // don't have editor

        case opiPlugSaveChunk: return 0;    // not implemented
        case opiPlugLoadChunk: return 0;    // not implemented
            
        case opiPlugNumParam: return 1; // one parameter
        
        case opiPlugGetParam:
            switch(idx)
            {
            case 0: *((float*)data) = plug->gain; return 1;
            default: return 0;
            }
            
        case opiPlugSetParam:
            switch(idx)
            {
            case 0:
                plug->gain = *((float*)data);
                if(plug->gain < 0) plug->gain = 0;
                if(plug->gain > 1) plug->gain = 1;
                return 1;
            default: return 0;
            }

        case opiPlugGetParamName:
            switch(idx)
            {
            case 0: plug->setStringBuffer("Gain"); break;
            default: return 0;
            }
            ((OpiString*)data)->data = plug->stringBuffer.data();
            ((OpiString*)data)->size = plug->stringBuffer.size();
            return 1;

        case opiPlugValueToString:
            {
                switch(idx)
                {
                case 0:
                    // this is very naive
                    plug->stringBuffer.resize(32); // alloc "enough" space
                    plug->stringBuffer.resize(
                        sprintf(plug->stringBuffer.data(),
                            "%.2f", ((OpiParamString*)data)->value));
                    break;
                default: return 0;
                }
                ((OpiParamString*)data)->data = plug->stringBuffer.data();
                ((OpiParamString*)data)->size = plug->stringBuffer.size();
                return 1;
            }
        case opiPlugStringToValue:
            switch(idx)
            {
            case 0:
                plug->setStringBuffer(
                    ((OpiString*)data)->data,
                    ((OpiString*)data)->size);
                // this is even more naive, but .. whatever
                sscanf(plug->stringBuffer.data(),
                    "%f", &(((OpiParamString*)data)->value));
                break;
            default: return 0;
            }
            return 1;

        default: return 0;
        }
    }
};

DLLEXPORT OpiPlugin * OpiPluginEntrypoint(OpiCallback hostCallback, void * hostPtr)
{
    return new OpiGain(hostCallback, hostPtr);
}
To be honest, I feel like this is sort of pointless effort, but .. I was bored.

Post

GainExample.c added to repository.

Thank you Mystran! Excellent work!

I will close the naming poll this Friday at 11:59 PM EST, the most popular will be the name of our plugin format.

Let's keep marching forwards, once this builds momentum, more and more people will join us.

Every time I edit the poll it resets the vote count. I will simply look at thread posts for any additional votes for suggestions not on the poll. I really like:

CAT - Community Audio Technology
(Suggested by Chapelle)
SLH - Yes, I am a woman, deal with it.

Post

Vertion wrote: Wed Jul 08, 2020 6:25 pm GainExample.c added to repository.

Thank you Mystran! Excellent work!
You should probably also fix my errata with regards to the entry point.

Post

A function/opcode to return the plugin type from a predefined enum (reverb, filter, synth-wavetable, etc...) and optionally a list of strings (e.g. for a compressor: program-dependant, emulation, etc) would help DAWS presenting neat menus and offer plugin search functions. That could be added to the function that returns the plugin name and the author.

Post

More name suggestions:
OAX - Open Audio Extension
OAS - Open Audio Suite
OAP - Open Audio API
CAX - Community Audio Extension
CAS - Community Audio Suite
CAP - Community Audio API

Post

rafa1981 wrote: Wed Jul 08, 2020 9:00 pm A function/opcode to return the plugin type from a predefined enum (reverb, filter, synth-wavetable, etc...) and optionally a list of strings (e.g. for a compressor: program-dependant, emulation, etc) would help DAWS presenting neat menus and offer plugin search functions. That could be added to the function that returns the plugin name and the author.
I actually left this stuff out from my draft somewhat intentionally, because I feel like there should be a way to fetch that information without actually instantiating a plugin. Ideally you wouldn't even have to load the DLL (at least not all of it) since that alone can cause a couple of seconds worth of pointless delay if the required files are not in the cache... but I don't have a good answer for how to do it.

Post

Youlean wrote: Fri Jul 03, 2020 7:31 pm I am sure that DAW makers can't wait to add another plugin format to support. 😄
This!!
rsp
sound sculptist

Post

The None Such Community plugin format
www.solostuff.net
Advice is heavy. So don’t send it like a mountain.

Locked

Return to “DSP and Plugin Development”