Browse Source

Plug-In wrappers and hosting code now support infinite tail times

tags/2021-05-28
hogliux 7 years ago
parent
commit
9b81643aa9
6 changed files with 67 additions and 12 deletions
  1. +19
    -0
      BREAKING-CHANGES.txt
  2. +18
    -4
      modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  3. +3
    -0
      modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  4. +7
    -0
      modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
  5. +6
    -5
      modules/juce_audio_processors/format_types/juce_VSTInterface.h
  6. +14
    -3
      modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp

+ 19
- 0
BREAKING-CHANGES.txt View File

@@ -4,6 +4,25 @@ JUCE breaking changes
Develop Develop
======= =======
Change
------
AudioProcessor::getTailLengthSeconds can now return infinity for VST/VST3/AU/AUv3
Possible Issues
---------------
If you are using the result of getTailLengthSeconds to allocate a buffer in your host,
then your host will now likely crash when loading a plug-in with an infinite tail time.
Workaround
----------
Re-write your code to not use the result of getTailLengthSeconds directly to allocate
a buffer.
Rationale
---------
Before this change there was no way for a JUCE plug-in to report an infinite tail time.
Version 5.3.2 Version 5.3.2
============= =============


+ 18
- 4
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp View File

@@ -317,12 +317,15 @@ public:
if (processor->supportsDoublePrecisionProcessing()) if (processor->supportsDoublePrecisionProcessing())
vstEffect.flags |= vstEffectFlagInplaceDoubleAudio; vstEffect.flags |= vstEffectFlagInplaceDoubleAudio;
vstEffect.flags |= vstEffectFlagDataInChunks;
#if JucePlugin_IsSynth #if JucePlugin_IsSynth
vstEffect.flags |= vstEffectFlagIsSynth; vstEffect.flags |= vstEffectFlagIsSynth;
#else
if (processor->getTailLengthSeconds() == 0.0)
vstEffect.flags |= vstEffectFlagSilenceInProducesSilenceOut;
#endif #endif
vstEffect.flags |= vstEffectFlagDataInChunks;
activePlugins.add (this); activePlugins.add (this);
} }
@@ -588,7 +591,7 @@ public:
if (getHostType().isAbletonLive() if (getHostType().isAbletonLive()
&& hostCallback != nullptr && hostCallback != nullptr
&& processor->getTailLengthSeconds() == std::numeric_limits<double>::max())
&& processor->getTailLengthSeconds() == std::numeric_limits<double>::infinity())
{ {
AbletonLiveHostSpecific hostCmd; AbletonLiveHostSpecific hostCmd;
@@ -2046,7 +2049,18 @@ private:
pointer_sized_int handleGetTailSize (VstOpCodeArguments) pointer_sized_int handleGetTailSize (VstOpCodeArguments)
{ {
if (processor != nullptr) if (processor != nullptr)
return (pointer_sized_int) (processor->getTailLengthSeconds() * sampleRate);
{
int32 result;
auto tailSeconds = processor->getTailLengthSeconds();
if (tailSeconds == std::numeric_limits<double>::infinity())
result = std::numeric_limits<int32>::max();
else
result = static_cast<int32> (tailSeconds * sampleRate);
return result; // Vst2 expects an int32 upcasted to a intptr_t here
}
return 0; return 0;
} }


+ 3
- 0
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -2033,6 +2033,9 @@ public:
if (tailLengthSeconds <= 0.0 || processSetup.sampleRate <= 0.0) if (tailLengthSeconds <= 0.0 || processSetup.sampleRate <= 0.0)
return Vst::kNoTail; return Vst::kNoTail;
if (tailLengthSeconds == std::numeric_limits<double>::infinity())
return Vst::kInfiniteTail;
return (Steinberg::uint32) roundToIntAccurate (tailLengthSeconds * processSetup.sampleRate); return (Steinberg::uint32) roundToIntAccurate (tailLengthSeconds * processSetup.sampleRate);
} }


+ 7
- 0
modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp View File

@@ -2296,7 +2296,14 @@ struct VST3PluginInstance : public AudioPluginInstance
auto sampleRate = getSampleRate(); auto sampleRate = getSampleRate();
if (sampleRate > 0.0) if (sampleRate > 0.0)
{
auto tailSamples = processor->getTailSamples();
if (tailSamples == Vst::kInfiniteTail)
return std::numeric_limits<double>::infinity();
return jlimit (0, 0x7fffffff, (int) processor->getTailSamples()) / sampleRate; return jlimit (0, 0x7fffffff, (int) processor->getTailSamples()) / sampleRate;
}
} }
return 0.0; return 0.0;


+ 6
- 5
modules/juce_audio_processors/format_types/juce_VSTInterface.h View File

@@ -83,11 +83,12 @@ typedef pointer_sized_int (VSTINTERFACECALL* VstHostCallback) (VstEffectInterfac
enum VstEffectInterfaceFlags enum VstEffectInterfaceFlags
{ {
vstEffectFlagHasEditor = 1,
vstEffectFlagInplaceAudio = 16,
vstEffectFlagDataInChunks = 32,
vstEffectFlagIsSynth = 256,
vstEffectFlagInplaceDoubleAudio = 4096
vstEffectFlagHasEditor = 1,
vstEffectFlagInplaceAudio = 16,
vstEffectFlagDataInChunks = 32,
vstEffectFlagIsSynth = 256,
vstEffectFlagSilenceInProducesSilenceOut = 512,
vstEffectFlagInplaceDoubleAudio = 4096
}; };
//============================================================================== //==============================================================================


+ 14
- 3
modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp View File

@@ -1283,12 +1283,23 @@ struct VSTPluginInstance : public AudioPluginInstance,
if (vstEffect == nullptr) if (vstEffect == nullptr)
return 0.0; return 0.0;
if ((vstEffect->flags & vstEffectFlagSilenceInProducesSilenceOut) != 0)
return 0.0;
auto tailSize = dispatch (plugInOpcodeGetTailSize, 0, 0, 0, 0);
auto sampleRate = getSampleRate(); auto sampleRate = getSampleRate();
if (sampleRate <= 0)
return 0.0;
// remain backward compatible with old JUCE plug-ins: anything larger
// than INT32_MAX is an invalid tail time but old JUCE 64-bit plug-ins
// would return INT64_MAX for infinite tail time. So treat anything
// equal or greater than INT32_MAX as infinite tail time.
if (tailSize >= std::numeric_limits<int32>::max())
return std::numeric_limits<double>::infinity();
if (tailSize >= 0 && sampleRate > 0)
return static_cast<double> (tailSize) / sampleRate;
return dispatch (plugInOpcodeGetTailSize, 0, 0, 0, 0) / sampleRate;
return 0.0;
} }
bool acceptsMidi() const override { return wantsMidiMessages; } bool acceptsMidi() const override { return wantsMidiMessages; }


Loading…
Cancel
Save