Skip to content

Commit

Permalink
Add kParameterDesignationReset, implement for AU, CLAP and LV2
Browse files Browse the repository at this point in the history
Signed-off-by: falkTX <falktx@falktx.com>
  • Loading branch information
falkTX committed Dec 30, 2024
1 parent 800583a commit 576b507
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 47 deletions.
32 changes: 28 additions & 4 deletions distrho/DistrhoDetails.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
};

/**
Expand All @@ -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";
};
Expand Down Expand Up @@ -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;
}
}

Expand Down
88 changes: 52 additions & 36 deletions distrho/src/DistrhoPluginAU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ bool isNumChannelsComboValid(const uint16_t numInputs, const uint16_t numOutputs
// --------------------------------------------------------------------------------------------------------------------

struct PropertyListener {
AudioUnitPropertyID prop;
AudioUnitPropertyID prop;
AudioUnitPropertyListenerProc proc;
void* userData;
};
Expand Down Expand Up @@ -348,7 +348,8 @@ class PluginAU
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
Expand All @@ -365,7 +366,7 @@ class PluginAU
, fStateCount(fPlugin.getStateCount())
#endif
{
if (fParameterCount != 0)
if (fParameterCount != 0)
{
fLastParameterValues = new float[fParameterCount];
std::memset(fLastParameterValues, 0, sizeof(float) * fParameterCount);
Expand All @@ -374,8 +375,17 @@ class PluginAU
{
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;
}
}
}

Expand Down Expand Up @@ -923,13 +933,13 @@ class PluginAU
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;
}
Expand Down Expand Up @@ -1458,7 +1468,7 @@ class PluginAU
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;
Expand All @@ -1480,12 +1490,12 @@ class PluginAU
#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);
Expand Down Expand Up @@ -1612,7 +1622,7 @@ class PluginAU
AUEventListenerNotify(NULL, NULL, &event);

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

Expand Down Expand Up @@ -1821,7 +1831,12 @@ class PluginAU
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();
Expand Down Expand Up @@ -2180,6 +2195,7 @@ class PluginAU
const uint32_t fParameterCount;
float* fLastParameterValues;
uint32_t fBypassParameterIndex;
uint32_t fResetParameterIndex;

#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
uint32_t fMidiEventCount;
Expand Down Expand Up @@ -2220,7 +2236,7 @@ class PluginAU
const PropertyListener& pl(*it);

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

Expand Down Expand Up @@ -2845,7 +2861,7 @@ class PluginAU
// --------------------------------------------------------------------------------------------------------------------

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

AudioComponentPlugInInstance() noexcept
Expand All @@ -2854,25 +2870,25 @@ 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()
{
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);

static_cast<AudioComponentPlugInInstance*>(self)->plugin = new PluginAU(component);
return noErr;
}

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

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down
43 changes: 37 additions & 6 deletions distrho/src/DistrhoPluginCLAP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ class PluginCLAP : ClapEventQueue
updateStateValueCallback),
fHost(host),
fOutputEvents(nullptr),
fResetParameterIndex(UINT32_MAX),
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0
fUsingCV(false),
#endif
Expand All @@ -763,7 +764,19 @@ class PluginCLAP : ClapEventQueue
#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);
Expand Down Expand Up @@ -823,7 +836,18 @@ class PluginCLAP : ClapEventQueue

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)
Expand Down Expand Up @@ -1119,14 +1143,19 @@ class PluginCLAP : ClapEventQueue
{
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);

Expand Down Expand Up @@ -1156,6 +1185,7 @@ class PluginCLAP : ClapEventQueue
}

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

info->id = index;
Expand Down Expand Up @@ -1791,6 +1821,7 @@ class PluginCLAP : ClapEventQueue
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
Expand Down
10 changes: 10 additions & 0 deletions distrho/src/DistrhoPluginLV2export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
Loading

0 comments on commit 576b507

Please sign in to comment.