Browse Source

Add kParameterDesignationReset, implement for AU, CLAP and LV2

Signed-off-by: falkTX <falktx@falktx.com>
pull/491/head
falkTX 4 months ago
parent
commit
576b507dc4
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
6 changed files with 135 additions and 47 deletions
  1. +28
    -4
      distrho/DistrhoDetails.hpp
  2. +52
    -36
      distrho/src/DistrhoPluginAU.cpp
  3. +37
    -6
      distrho/src/DistrhoPluginCLAP.cpp
  4. +10
    -0
      distrho/src/DistrhoPluginLV2export.cpp
  5. +6
    -0
      distrho/src/DistrhoPluginVST3.cpp
  6. +2
    -1
      distrho/src/lv2/lv2_kxstudio_properties.h

+ 28
- 4
distrho/DistrhoDetails.hpp View File

@@ -202,7 +202,7 @@ static constexpr const uint32_t kStateIsOnlyForUI = 0x20;

/**
Parameter designation.@n
Allows a parameter to be specially designated for a task, like bypass.
Allows a parameter to be specially designated for a task, like bypass and reset.

Each designation is unique, there must be only one parameter that uses it.@n
The use of designated parameters is completely optional.
@@ -214,13 +214,20 @@ enum ParameterDesignation {
/**
Null or unset designation.
*/
kParameterDesignationNull = 0,
kParameterDesignationNull,

/**
Bypass designation.@n
When on (> 0.5f), it means the plugin must run in a bypassed state.
*/
kParameterDesignationBypass = 1
kParameterDesignationBypass,

/**
Reset designation.@n
When on (> 0.5f), it means the plugin should reset its internal processing state
(like filters, oscillators, envelopes, lfos, etc) and kill all voices.
*/
kParameterDesignationReset,
};

/**
@@ -234,7 +241,12 @@ namespace ParameterDesignationSymbols {
static constexpr const char bypass[] = "dpf_bypass";

/**
Bypass designation symbol, inverted for LV2 so it becomes "enabled".
Reset designation symbol.
*/
static constexpr const char reset[] = "dpf_reset";

/**
LV2 bypass designation symbol, inverted for LV2 so it becomes "enabled".
*/
static constexpr const char bypass_lv2[] = "lv2_enabled";
};
@@ -728,6 +740,18 @@ struct Parameter {
ranges.min = 0.0f;
ranges.max = 1.0f;
break;
case kParameterDesignationReset:
hints = kParameterIsAutomatable|kParameterIsBoolean|kParameterIsInteger|kParameterIsTrigger;
name = "Reset";
shortName = "Reset";
symbol = ParameterDesignationSymbols::reset;
unit = "";
midiCC = 0;
groupId = kPortGroupNone;
ranges.def = 0.0f;
ranges.min = 0.0f;
ranges.max = 1.0f;
break;
}
}



+ 52
- 36
distrho/src/DistrhoPluginAU.cpp View File

@@ -264,7 +264,7 @@ bool isNumChannelsComboValid(const uint16_t numInputs, const uint16_t numOutputs
// --------------------------------------------------------------------------------------------------------------------

struct PropertyListener {
AudioUnitPropertyID prop;
AudioUnitPropertyID prop;
AudioUnitPropertyListenerProc proc;
void* userData;
};
@@ -348,7 +348,8 @@ public:
fUsingRenderListeners(false),
fParameterCount(fPlugin.getParameterCount()),
fLastParameterValues(nullptr),
fBypassParameterIndex(UINT32_MAX)
fBypassParameterIndex(UINT32_MAX),
fResetParameterIndex(UINT32_MAX)
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
, fMidiEventCount(0)
#endif
@@ -365,7 +366,7 @@ public:
, fStateCount(fPlugin.getStateCount())
#endif
{
if (fParameterCount != 0)
if (fParameterCount != 0)
{
fLastParameterValues = new float[fParameterCount];
std::memset(fLastParameterValues, 0, sizeof(float) * fParameterCount);
@@ -374,8 +375,17 @@ public:
{
fLastParameterValues[i] = fPlugin.getParameterValue(i);

if (fPlugin.getParameterDesignation(i) == kParameterDesignationBypass)
switch (fPlugin.getParameterDesignation(i))
{
case kParameterDesignationNull:
break;
case kParameterDesignationBypass:
fBypassParameterIndex = i;
break;
case kParameterDesignationReset:
fResetParameterIndex = i;
break;
}
}
}

@@ -923,13 +933,13 @@ public:
case kAudioUnitProperty_FastDispatch:
switch (inElement)
{
case kAudioUnitGetParameterSelect:
case kAudioUnitGetParameterSelect:
*static_cast<AudioUnitGetParameterProc*>(outData) = FastDispatchGetParameter;
return noErr;
case kAudioUnitSetParameterSelect:
case kAudioUnitSetParameterSelect:
*static_cast<AudioUnitSetParameterProc*>(outData) = FastDispatchSetParameter;
return noErr;
case kAudioUnitRenderSelect:
case kAudioUnitRenderSelect:
*static_cast<AudioUnitRenderProc*>(outData) = FastDispatchRender;
return noErr;
}
@@ -1458,7 +1468,7 @@ public:
const float value = bypass ? 1.f : 0.f;
fLastParameterValues[fBypassParameterIndex] = value;
fPlugin.setParameterValue(fBypassParameterIndex, value);
notifyPropertyListeners(inProp, inScope, inElement);
notifyPropertyListeners(inProp, inScope, inElement);
}
}
return noErr;
@@ -1480,12 +1490,12 @@ public:
#if DISTRHO_PLUGIN_WANT_TIMEPOS
{
const UInt32 usableDataSize = std::min(inDataSize, static_cast<UInt32>(sizeof(HostCallbackInfo)));
const bool changed = std::memcmp(&fHostCallbackInfo, inData, usableDataSize) != 0;
const bool changed = std::memcmp(&fHostCallbackInfo, inData, usableDataSize) != 0;

std::memcpy(&fHostCallbackInfo, inData, usableDataSize);
std::memcpy(&fHostCallbackInfo, inData, usableDataSize);

if (sizeof(HostCallbackInfo) > usableDataSize)
std::memset(&fHostCallbackInfo + usableDataSize, 0, sizeof(HostCallbackInfo) - usableDataSize);
std::memset(&fHostCallbackInfo + usableDataSize, 0, sizeof(HostCallbackInfo) - usableDataSize);

if (changed)
notifyPropertyListeners(inProp, inScope, inElement);
@@ -1612,7 +1622,7 @@ public:
AUEventListenerNotify(NULL, NULL, &event);

if (fBypassParameterIndex == inElement)
notifyPropertyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
notifyPropertyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
}
return noErr;

@@ -1821,7 +1831,12 @@ public:
DISTRHO_SAFE_ASSERT_UINT_RETURN(scope == kAudioUnitScope_Global || scope == kAudioUnitScope_Input || scope == kAudioUnitScope_Output, scope, kAudioUnitErr_InvalidScope);
DISTRHO_SAFE_ASSERT_UINT_RETURN(elem == 0, elem, kAudioUnitErr_InvalidElement);

if (fPlugin.isActive())
if (fResetParameterIndex != UINT32_MAX)
{
fPlugin.setParameterValue(fResetParameterIndex, 1.f);
fPlugin.setParameterValue(fResetParameterIndex, 0.f);
}
else if (fPlugin.isActive())
{
fPlugin.deactivate();
fPlugin.activate();
@@ -2180,6 +2195,7 @@ private:
const uint32_t fParameterCount;
float* fLastParameterValues;
uint32_t fBypassParameterIndex;
uint32_t fResetParameterIndex;

#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
uint32_t fMidiEventCount;
@@ -2220,7 +2236,7 @@ private:
const PropertyListener& pl(*it);

if (pl.prop == prop)
pl.proc(pl.userData, fComponent, prop, scope, elem);
pl.proc(pl.userData, fComponent, prop, scope, elem);
}
}

@@ -2845,7 +2861,7 @@ private:
// --------------------------------------------------------------------------------------------------------------------

struct AudioComponentPlugInInstance {
AudioComponentPlugInInterface acpi;
AudioComponentPlugInInterface acpi;
PluginAU* plugin;

AudioComponentPlugInInstance() noexcept
@@ -2854,9 +2870,9 @@ struct AudioComponentPlugInInstance {
{
std::memset(&acpi, 0, sizeof(acpi));
acpi.Open = Open;
acpi.Close = Close;
acpi.Lookup = Lookup;
acpi.reserved = nullptr;
acpi.Close = Close;
acpi.Lookup = Lookup;
acpi.reserved = nullptr;
}

~AudioComponentPlugInInstance()
@@ -2864,7 +2880,7 @@ struct AudioComponentPlugInInstance {
delete plugin;
}

static OSStatus Open(void* const self, const AudioUnit component)
static OSStatus Open(void* const self, const AudioUnit component)
{
d_debug("AudioComponentPlugInInstance::Open(%p)", self);

@@ -2872,7 +2888,7 @@ struct AudioComponentPlugInInstance {
return noErr;
}

static OSStatus Close(void* const self)
static OSStatus Close(void* const self)
{
d_debug("AudioComponentPlugInInstance::Close(%p)", self);

@@ -2964,15 +2980,15 @@ struct AudioComponentPlugInInstance {
d_debug("AudioComponentPlugInInstance::GetPropertyInfo(%p, %d:%x:%s, %d:%s, %d, ...)",
self, inProp, inProp, AudioUnitPropertyID2Str(inProp), inScope, AudioUnitScope2Str(inScope), inElement);

UInt32 dataSize = 0;
Boolean writable = false;
UInt32 dataSize = 0;
Boolean writable = false;
const OSStatus res = self->plugin->auGetPropertyInfo(inProp, inScope, inElement, dataSize, writable);

if (outDataSize != nullptr)
*outDataSize = dataSize;
if (outDataSize != nullptr)
*outDataSize = dataSize;

if (outWritable != nullptr)
*outWritable = writable;
if (outWritable != nullptr)
*outWritable = writable;

return res;
}
@@ -3016,24 +3032,24 @@ struct AudioComponentPlugInInstance {
if (res != noErr)
return res;

void* outBuffer;
void* outBuffer;
uint8_t* tmpBuffer;
if (inDataSize < outDataSize)
{
tmpBuffer = new uint8_t[outDataSize];
outBuffer = tmpBuffer;
}
{
tmpBuffer = new uint8_t[outDataSize];
outBuffer = tmpBuffer;
}
else
{
tmpBuffer = nullptr;
outBuffer = outData;
}
tmpBuffer = nullptr;
outBuffer = outData;
}

res = self->plugin->auGetProperty(inProp, inScope, inElement, outBuffer);

if (res != noErr)
if (res != noErr)
{
*ioDataSize = 0;
*ioDataSize = 0;
return res;
}



+ 37
- 6
distrho/src/DistrhoPluginCLAP.cpp View File

@@ -751,6 +751,7 @@ public:
updateStateValueCallback),
fHost(host),
fOutputEvents(nullptr),
fResetParameterIndex(UINT32_MAX),
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0
fUsingCV(false),
#endif
@@ -763,7 +764,19 @@ public:
#endif
fHostExtensions(host)
{
fCachedParameters.setup(fPlugin.getParameterCount());
if (const uint32_t paramCount = fPlugin.getParameterCount())
{
fCachedParameters.setup(paramCount);

for (uint32_t i=0; i<paramCount; ++i)
{
if (fPlugin.getParameterDesignation(i) == kParameterDesignationReset)
{
fResetParameterIndex = i;
break;
}
}
}

#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT
fNotesRingBuffer.setRingBuffer(&fNotesBuffer, true);
@@ -823,7 +836,18 @@ public:

void reset()
{
fHost->request_restart(fHost);
if (fResetParameterIndex != UINT32_MAX)
{
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
fMidiEventCount = 0;
#endif
fPlugin.setParameterValue(fResetParameterIndex, 1.f);
fPlugin.setParameterValue(fResetParameterIndex, 0.f);
}
else
{
fHost->request_restart(fHost);
}
}

bool process(const clap_process_t* const process)
@@ -1119,14 +1143,19 @@ public:
{
const ParameterRanges& ranges(fPlugin.getParameterRanges(index));

if (fPlugin.getParameterDesignation(index) == kParameterDesignationBypass)
switch (fPlugin.getParameterDesignation(index))
{
case kParameterDesignationBypass:
info->flags = CLAP_PARAM_IS_STEPPED|CLAP_PARAM_IS_BYPASS|CLAP_PARAM_IS_AUTOMATABLE;
std::strcpy(info->name, "Bypass");
std::strcpy(info->module, "dpf_bypass");
}
else
{
break;
case kParameterDesignationReset:
info->flags = CLAP_PARAM_IS_STEPPED|CLAP_PARAM_IS_READONLY;
std::strcpy(info->name, "Reset");
std::strcpy(info->module, "dpf_reset");
break;
default:
const uint32_t hints = fPlugin.getParameterHints(index);
const uint32_t groupId = fPlugin.getParameterGroupId(index);

@@ -1156,6 +1185,7 @@ public:
}

d_strncpy(info->module + wrtn, fPlugin.getParameterSymbol(index), CLAP_PATH_SIZE - wrtn);
break;
}

info->id = index;
@@ -1791,6 +1821,7 @@ private:
const clap_host_t* const fHost;
const clap_output_events_t* fOutputEvents;

uint32_t fResetParameterIndex;
#if DISTRHO_PLUGIN_NUM_INPUTS != 0
const float* fAudioInputs[DISTRHO_PLUGIN_NUM_INPUTS];
#endif


+ 10
- 0
distrho/src/DistrhoPluginLV2export.cpp View File

@@ -758,6 +758,16 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n";
pluginString += " lv2:designation lv2:enabled ;\n";
break;
case kParameterDesignationReset:
designated = true;
pluginString += " lv2:name \"Reset\" ;\n";
pluginString += " lv2:symbol \"" + String(ParameterDesignationSymbols::reset) + "\" ;\n";
pluginString += " lv2:default 0 ;\n";
pluginString += " lv2:minimum 0 ;\n";
pluginString += " lv2:maximum 1 ;\n";
pluginString += " lv2:portProperty lv2:toggled , lv2:integer , <" LV2_PORT_PROPS__trigger "> ;\n";
pluginString += " lv2:designation <" LV2_KXSTUDIO_PROPERTIES__Reset "> ;\n";
break;
}
}



+ 6
- 0
distrho/src/DistrhoPluginVST3.cpp View File

@@ -1747,6 +1747,12 @@ public:
case kParameterDesignationBypass:
flags |= V3_PARAM_IS_BYPASS;
break;
case kParameterDesignationReset:
info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN;
info->step_count = 1;
strncpy_utf16(info->title, "Reset", 128);
strncpy_utf16(info->short_title, "Reset", 128);
return V3_OK;
}

if (hints & kParameterIsOutput)


+ 2
- 1
distrho/src/lv2/lv2_kxstudio_properties.h View File

@@ -1,6 +1,6 @@
/*
LV2 KXStudio Properties Extension
Copyright 2014-2021 Filipe Coelho <falktx@falktx.com>
Copyright 2014-2024 Filipe Coelho <falktx@falktx.com>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -27,6 +27,7 @@
#define LV2_KXSTUDIO_PROPERTIES_PREFIX LV2_KXSTUDIO_PROPERTIES_URI "#"

#define LV2_KXSTUDIO_PROPERTIES__NonAutomatable LV2_KXSTUDIO_PROPERTIES_PREFIX "NonAutomatable"
#define LV2_KXSTUDIO_PROPERTIES__Reset LV2_KXSTUDIO_PROPERTIES_PREFIX "Reset"
#define LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat LV2_KXSTUDIO_PROPERTIES_PREFIX "TimePositionTicksPerBeat"
#define LV2_KXSTUDIO_PROPERTIES__TransientWindowId LV2_KXSTUDIO_PROPERTIES_PREFIX "TransientWindowId"



Loading…
Cancel
Save