|
|
@@ -510,9 +510,28 @@ static void onWrapperDeletion (AudioProcessorUnityWrapper* wrapperToRemove) |
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
namespace UnityCallbacks
|
|
|
|
static UnityAudioEffectDefinition getEffectDefinition()
|
|
|
|
{
|
|
|
|
static int UNITY_INTERFACE_API createCallback (UnityAudioEffectState* state)
|
|
|
|
const auto wrapper = std::make_unique<AudioProcessorUnityWrapper> (true);
|
|
|
|
const String originalName { JucePlugin_Name };
|
|
|
|
const auto name = (! originalName.startsWithIgnoreCase ("audioplugin") ? "audioplugin_" : "") + originalName;
|
|
|
|
|
|
|
|
UnityAudioEffectDefinition result{};
|
|
|
|
name.copyToUTF8 (result.name, (size_t) numElementsInArray (result.name));
|
|
|
|
|
|
|
|
result.structSize = sizeof (UnityAudioEffectDefinition);
|
|
|
|
result.parameterStructSize = sizeof (UnityAudioParameterDefinition);
|
|
|
|
|
|
|
|
result.apiVersion = UNITY_AUDIO_PLUGIN_API_VERSION;
|
|
|
|
result.pluginVersion = JucePlugin_VersionCode;
|
|
|
|
|
|
|
|
// effects must set this to 0, generators > 0
|
|
|
|
result.channels = (wrapper->getNumInputChannels() != 0 ? 0
|
|
|
|
: static_cast<uint32> (wrapper->getNumOutputChannels()));
|
|
|
|
|
|
|
|
wrapper->declareParameters (result);
|
|
|
|
|
|
|
|
result.create = [] (UnityAudioEffectState* state)
|
|
|
|
{
|
|
|
|
auto* pluginInstance = new AudioProcessorUnityWrapper (false);
|
|
|
|
pluginInstance->create (state);
|
|
|
@@ -522,9 +541,9 @@ namespace UnityCallbacks |
|
|
|
onWrapperCreation (pluginInstance);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int UNITY_INTERFACE_API releaseCallback (UnityAudioEffectState* state)
|
|
|
|
result.release = [] (UnityAudioEffectState* state)
|
|
|
|
{
|
|
|
|
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
|
|
|
|
pluginInstance->release();
|
|
|
@@ -536,32 +555,58 @@ namespace UnityCallbacks |
|
|
|
shutdownJuce_GUI();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int UNITY_INTERFACE_API resetCallback (UnityAudioEffectState* state)
|
|
|
|
result.reset = [] (UnityAudioEffectState* state)
|
|
|
|
{
|
|
|
|
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
|
|
|
|
pluginInstance->reset();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int UNITY_INTERFACE_API setPositionCallback (UnityAudioEffectState* state, unsigned int pos)
|
|
|
|
result.setPosition = [] (UnityAudioEffectState* state, unsigned int pos)
|
|
|
|
{
|
|
|
|
ignoreUnused (state, pos);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
result.process = [] (UnityAudioEffectState* state,
|
|
|
|
float* inBuffer,
|
|
|
|
float* outBuffer,
|
|
|
|
unsigned int bufferSize,
|
|
|
|
int numInChannels,
|
|
|
|
int numOutChannels)
|
|
|
|
{
|
|
|
|
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
|
|
|
|
|
|
|
|
if (pluginInstance != nullptr)
|
|
|
|
{
|
|
|
|
auto isPlaying = ((state->flags & stateIsPlaying) != 0);
|
|
|
|
auto isMuted = ((state->flags & stateIsMuted) != 0);
|
|
|
|
auto isPaused = ((state->flags & stateIsPaused) != 0);
|
|
|
|
|
|
|
|
static int UNITY_INTERFACE_API setFloatParameterCallback (UnityAudioEffectState* state, int index, float value)
|
|
|
|
const auto bypassed = ! isPlaying || (isMuted || isPaused);
|
|
|
|
pluginInstance->process (inBuffer, outBuffer, static_cast<int> (bufferSize), numInChannels, numOutChannels, bypassed);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FloatVectorOperations::clear (outBuffer, static_cast<int> (bufferSize) * numOutChannels);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
result.setFloatParameter = [] (UnityAudioEffectState* state, int index, float value)
|
|
|
|
{
|
|
|
|
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
|
|
|
|
pluginInstance->setParameter (index, value);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int UNITY_INTERFACE_API getFloatParameterCallback (UnityAudioEffectState* state, int index, float* value, char* valueStr)
|
|
|
|
result.getFloatParameter = [] (UnityAudioEffectState* state, int index, float* value, char* valueStr)
|
|
|
|
{
|
|
|
|
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
|
|
|
|
*value = pluginInstance->getParameter (index);
|
|
|
@@ -569,21 +614,21 @@ namespace UnityCallbacks |
|
|
|
pluginInstance->getParameterString (index).copyToUTF8 (valueStr, 15);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int UNITY_INTERFACE_API getFloatBufferCallback (UnityAudioEffectState* state, const char* name, float* buffer, int numSamples)
|
|
|
|
result.getFloatBuffer = [] (UnityAudioEffectState* state, const char* kind, float* buffer, int numSamples)
|
|
|
|
{
|
|
|
|
ignoreUnused (numSamples);
|
|
|
|
|
|
|
|
auto nameStr = String (name);
|
|
|
|
const StringRef kindStr { kind };
|
|
|
|
|
|
|
|
if (nameStr == "Editor")
|
|
|
|
if (kindStr == StringRef ("Editor"))
|
|
|
|
{
|
|
|
|
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
|
|
|
|
|
|
|
|
buffer[0] = pluginInstance->hasEditor() ? 1.0f : 0.0f;
|
|
|
|
}
|
|
|
|
else if (nameStr == "ID")
|
|
|
|
else if (kindStr == StringRef ("ID"))
|
|
|
|
{
|
|
|
|
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
|
|
|
|
|
|
|
@@ -598,7 +643,7 @@ namespace UnityCallbacks |
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (nameStr == "Size")
|
|
|
|
else if (kindStr == StringRef ("Size"))
|
|
|
|
{
|
|
|
|
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
|
|
|
|
|
|
|
@@ -613,87 +658,31 @@ namespace UnityCallbacks |
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int UNITY_INTERFACE_API processCallback (UnityAudioEffectState* state, float* inBuffer, float* outBuffer,
|
|
|
|
unsigned int bufferSize, int numInChannels, int numOutChannels)
|
|
|
|
{
|
|
|
|
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();
|
|
|
|
|
|
|
|
if (pluginInstance != nullptr)
|
|
|
|
{
|
|
|
|
auto isPlaying = ((state->flags & stateIsPlaying) != 0);
|
|
|
|
auto isMuted = ((state->flags & stateIsMuted) != 0);
|
|
|
|
auto isPaused = ((state->flags & stateIsPaused) != 0);
|
|
|
|
|
|
|
|
const auto bypassed = ! isPlaying || (isMuted || isPaused);
|
|
|
|
pluginInstance->process (inBuffer, outBuffer, static_cast<int> (bufferSize), numInChannels, numOutChannels, bypassed);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FloatVectorOperations::clear (outBuffer, static_cast<int> (bufferSize) * numOutChannels);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
static void declareEffect (UnityAudioEffectDefinition& definition)
|
|
|
|
{
|
|
|
|
memset (&definition, 0, sizeof (definition));
|
|
|
|
|
|
|
|
std::unique_ptr<AudioProcessorUnityWrapper> wrapper = std::make_unique<AudioProcessorUnityWrapper> (true);
|
|
|
|
|
|
|
|
String name (JucePlugin_Name);
|
|
|
|
if (! name.startsWithIgnoreCase ("audioplugin"))
|
|
|
|
name = "audioplugin_" + name;
|
|
|
|
|
|
|
|
name.copyToUTF8 (definition.name, (size_t) numElementsInArray (definition.name));
|
|
|
|
|
|
|
|
definition.structSize = sizeof (UnityAudioEffectDefinition);
|
|
|
|
definition.parameterStructSize = sizeof (UnityAudioParameterDefinition);
|
|
|
|
|
|
|
|
definition.apiVersion = UNITY_AUDIO_PLUGIN_API_VERSION;
|
|
|
|
definition.pluginVersion = JucePlugin_VersionCode;
|
|
|
|
};
|
|
|
|
|
|
|
|
// effects must set this to 0, generators > 0
|
|
|
|
definition.channels = (wrapper->getNumInputChannels() != 0 ? 0
|
|
|
|
: static_cast<uint32> (wrapper->getNumOutputChannels()));
|
|
|
|
|
|
|
|
wrapper->declareParameters (definition);
|
|
|
|
|
|
|
|
definition.create = UnityCallbacks::createCallback;
|
|
|
|
definition.release = UnityCallbacks::releaseCallback;
|
|
|
|
definition.reset = UnityCallbacks::resetCallback;
|
|
|
|
definition.setPosition = UnityCallbacks::setPositionCallback;
|
|
|
|
definition.process = UnityCallbacks::processCallback;
|
|
|
|
definition.setFloatParameter = UnityCallbacks::setFloatParameterCallback;
|
|
|
|
definition.getFloatParameter = UnityCallbacks::getFloatParameterCallback;
|
|
|
|
definition.getFloatBuffer = UnityCallbacks::getFloatBufferCallback;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace juce
|
|
|
|
|
|
|
|
// From reading the example code, it seems that the triple indirection indicates
|
|
|
|
// an out-value of an array of pointers. That is, after calling this function, definitionsPtr
|
|
|
|
// should point to a pre-existing/static array of pointer-to-effect-definition.
|
|
|
|
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API UnityGetAudioEffectDefinitions (UnityAudioEffectDefinition*** definitionsPtr)
|
|
|
|
{
|
|
|
|
if (juce::getWrapperMap().size() == 0)
|
|
|
|
juce::initialiseJuce_GUI();
|
|
|
|
|
|
|
|
static bool hasInitialised = false;
|
|
|
|
|
|
|
|
if (! hasInitialised)
|
|
|
|
static std::once_flag flag;
|
|
|
|
std::call_once (flag, []
|
|
|
|
{
|
|
|
|
juce::PluginHostType::jucePlugInClientCurrentWrapperType = juce::AudioProcessor::wrapperType_Unity;
|
|
|
|
juce::juce_createUnityPeerFn = juce::createUnityPeer;
|
|
|
|
});
|
|
|
|
|
|
|
|
hasInitialised = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* definition = new UnityAudioEffectDefinition();
|
|
|
|
juce::declareEffect (*definition);
|
|
|
|
|
|
|
|
*definitionsPtr = &definition;
|
|
|
|
static auto definition = juce::getEffectDefinition();
|
|
|
|
static UnityAudioEffectDefinition* definitions[] { &definition };
|
|
|
|
*definitionsPtr = definitions;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|