AuburnSounds / Dplug

Make VST2 / VST3 / AU / AAX / CLAP / LV2 / FLP plug-ins for Linux/macOS/Windows, using D.
https://dplug.org/
Other
490 stars 32 forks source link

effSetSpeakerArrangement return code does not seem to make sense #186

Open p0nce opened 7 years ago

p0nce commented 7 years ago

Which means that it might well say "no" everytime as of today. Whereas in Iplug it says always "yes". However this has the potential to break lots of compatibility, so let's be extra-careful here

(EDIT: actually in Audio Unit, we also say "no" everytime for speaker arrangement, so maybe there is this logic of not pretending to support it)

p0nce commented 7 years ago

Could it be the real fix for #113 ? Looks like we made a badfix for it, and we don't need the channel reassignment layer.

p0nce commented 7 years ago
p0nce commented 6 years ago

Generally the idea to accept more input/output combination that the algorithm strictly need is harmful, because input and output becomes untyped and might result in the wrong conversion. It's important not to break this semantic.

p0nce commented 5 years ago

Up !

This cause Panagement 2 to be mono-mono in Cubase

abaga129 commented 5 years ago

It seems to me that we should always return 1 in the case of effSetSpeakerArrangement opcode since we always accept the arrangement.

From the VST2 documentation

Set the plug-in's speaker arrangements. If a (VST >= 2.3) plug-in returns \e true, it means that it accepts this IO 
arrangement. The Host doesn't need to ask for getSpeakerArrangement(). If the plug-in returns \e false it means that it 
doesn't accept this arrangement, the Host should then ask for getSpeakerArrangement() and then can (optional)
recall setSpeakerArrangement().

I believe that if we return 0 then we need to look for effGetSpeakerArrangement opcode and respond to it accordingly.

p0nce commented 5 years ago

Ah it makes kind of sense with this bit of documentation! Indeed in that case we should, at the next effGetSpeakerArrangement, return the preferred computed I/O combination I guess (probably won't work with all hosts)

It seems to me that we should always return 1 in the case of effSetSpeakerArrangement opcode since we always accept the arrangement.

Essentially saying always "yes" is like dynamic typing, you loose semantic information of "this is a mono signal that will be expanded to stereo" and instead say "sure, I'll make a mono signal out of your mono input"

Currently how it works is:

The way other frameworks do it:

Unfortunately that fix can also breaks compatibility with hosts that can't do "mono to stereo", so perhaps there would be a need for an option?

p0nce commented 5 years ago

About the channel reassignment layer: I think it can stay, as a last resort strategy, the important thing being refusing unsupported I/O combinations (in hosts that can accept this refusal...).

abaga129 commented 5 years ago

I'm thinking we can set some sort of flags like _getSpeakerArrangementCalled and _setSpeakerArrangmentCalled and if we get effGetSpeakerArrangement at any point we can do something like

case effGetSpeakerArrangement: // opcode 76
{
    VstSpeakerArrangement* pInputArr = cast(VstSpeakerArrangement*) value;
    VstSpeakerArrangement* pOutputArr = cast(VstSpeakerArrangement*) ptr;
    if (pInputArr !is null && pOutputArr !is null )
    {
        choosePreferedIOArrangment();
        pInputArr.numChannels = preferredNumInputs;
        pOutputArr.numChannels = preferredNumOutputs;
    }
    _getSpeakerArrangementCalled;
    return 1;
}

And then handle it accordingly when we get _effSetSpeakerArrangement. If either _setSpeakerArrangementCalled or _getSpeakerArrangementCalled then we can go ahead and call chooseIOArrangement as normal. Otherwise we can check if the IO combination matches our preferred IO, if not we will return 0 and hope that we get effGetSpeakerArrangement from the host. If not on the next effSetSpeakerArrangment we will just default back to how we normally handle it.

abaga129 commented 5 years ago

I've started working on it in this commit. I still have to actually test it since Reaper doesnt seems to use these opcodes. I'll have to find an easily debuggable host to test on!

p0nce commented 5 years ago

Sorry I need a while to understand what needs to change... this is very delicate and might break lots of things so let's go extra-slowly. I'm busy until next week.

abaga129 commented 5 years ago

Okay I completely understand!

abaga129 commented 5 years ago

From my tests in Audition, it appears that my assumption was wrong. Returning 0 for effSetSpeakerArrangement doesn't cause effGetSpeakerArrangement to be called. Infact effGetSpeakerArrangement is never being called.

p0nce commented 5 years ago

Something that can also help is if you can log the actual number of buffers the host actually calls you with (this will be a surprise in one of the process calls)

p0nce commented 5 years ago

Helpful advice from Plogue: https://www.plogue.com/

From Seb: strategies more than a clean/direct answer :
- have VstSpeakerArrangement* members in your class for input and output
- in your ctor (or whenever else as long as it's before the host starts querying) set
them up for you max channels count
- in setSpeakerArrangement:
    - be prepared to be able to simply return false depending on any combo of
    audioMasterGetProductString/audioMasterGetVendorString/audioMasterGetVendorVersion
    - be prepared to be asked for more channels than your max and simply return false
    - call matchArrangement between pluginInput/your class member version, 
       pluginOutput/your class member version, if that works that would be
       the expected number of i/os to the processReplacing calls, return true if that works
       (it's possible that you might want to disable some matches or return true
       even if the match returned false)
    - if you need to deal/handle different VstSpeakerArrangementType/VstSpeakerProperties scenarios, good luck
- setSpeakerArrangement could be called again by the host with different values between a pair of suspend/resume calls
p0nce commented 5 years ago

Customer hit by the current behaviour:

I'm testing Panagement 2 Free in Cubase 10 Le, but I can't hear the binaural spectrum. I only hear the Reberb as it moves away and about. The volume drops and rises in both headphones (L and R) when I move Pan and Far.

abaga129 commented 5 years ago

It seems then that my assumption was completely off. That is very useful information indeed.