Skip to content

Commit

Permalink
proof of concept for output parameters in DPF
Browse files Browse the repository at this point in the history
  • Loading branch information
dromer committed Dec 27, 2023
1 parent d5ee155 commit 5e3ac60
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 60 deletions.
1 change: 1 addition & 0 deletions hvcc/core/hv2ir/HIrSend.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def get_ir_control_list(self) -> List:
"id": self.id,
"onMessage": [on_message_list],
"extern": self.args["extern"],
"attributes": self.args["attributes"],
"hash": self.args["hash"],
"display": self.args["name"],
"name": ((f"_{self.args['name']}") if re.match(r"\d", self.args["name"]) else self.args["name"])
Expand Down
7 changes: 4 additions & 3 deletions hvcc/generators/c2dpf/c2dpf.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def compile(

out_dir = os.path.join(out_dir, "plugin")
receiver_list = externs['parameters']['in']
sender_list = externs["parameters"]["out"]

if patch_meta:
patch_name = patch_meta.get("name", patch_name)
Expand Down Expand Up @@ -87,6 +88,7 @@ def compile(
num_input_channels=num_input_channels,
num_output_channels=num_output_channels,
receivers=receiver_list,
senders=sender_list,
copyright=copyright_c))
dpf_cpp_path = os.path.join(source_dir, f"HeavyDPF_{patch_name}.cpp")
with open(dpf_cpp_path, "w") as f:
Expand All @@ -97,6 +99,7 @@ def compile(
num_input_channels=num_input_channels,
num_output_channels=num_output_channels,
receivers=receiver_list,
senders=sender_list,
pool_sizes_kb=externs["memoryPoolSizesKb"],
copyright=copyright_c))
if dpf_meta.get("enable_ui"):
Expand All @@ -106,9 +109,8 @@ def compile(
name=patch_name,
meta=dpf_meta,
class_name=f"HeavyDPF_{patch_name}",
num_input_channels=num_input_channels,
num_output_channels=num_output_channels,
receivers=receiver_list,
senders=sender_list,
copyright=copyright_c))
dpf_h_path = os.path.join(source_dir, "DistrhoPluginInfo.h")
with open(dpf_h_path, "w") as f:
Expand All @@ -118,7 +120,6 @@ def compile(
class_name=f"HeavyDPF_{patch_name}",
num_input_channels=num_input_channels,
num_output_channels=num_output_channels,
receivers=receiver_list,
pool_sizes_kb=externs["memoryPoolSizesKb"],
copyright=copyright_c))

Expand Down
76 changes: 27 additions & 49 deletions hvcc/generators/c2dpf/templates/HeavyDPF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <set>


#define HV_LV2_NUM_PARAMETERS {{receivers|length}}
#define HV_LV2_NUM_PARAMETERS {{receivers|length + senders|length}}

#define HV_HASH_NOTEIN 0x67E37CA3
#define HV_HASH_CTLIN 0x41BE0f9C
Expand Down Expand Up @@ -55,6 +55,7 @@ static void hvSendHookFunc(HeavyContextInterface *c, const char *sendName, uint3
{{class_name}}* plugin = ({{class_name}}*)c->getUserData();
if (plugin != nullptr)
{
plugin->setOutputParameter(sendName, m);
{%- if meta.midi_output is defined and meta.midi_output == 1 %}
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
plugin->handleMidiSend(sendHash, m);
Expand All @@ -80,8 +81,13 @@ static void hvPrintHookFunc(HeavyContextInterface *c, const char *printLabel, co
{{class_name}}::{{class_name}}()
: Plugin(HV_LV2_NUM_PARAMETERS, 0, 0)
{
{% for k, v in receivers -%}
{% if receivers|length > 0 -%}
{% for k, v in receivers -%}
_parameters[{{loop.index-1}}] = {{v.attributes.default}}f;
{% endfor -%}
{% endif %}
{% for k, v in senders -%}
_parameters[{{receivers|length + loop.index-1}}] = {{v.attributes.default}}f;
{% endfor %}

_context = hv_{{name}}_new_with_options(getSampleRate(), {{pool_sizes_kb.internal}}, {{pool_sizes_kb.inputQueue}}, {{pool_sizes_kb.outputQueue}});
Expand All @@ -107,56 +113,16 @@ static void hvPrintHookFunc(HeavyContextInterface *c, const char *printLabel, co

void {{class_name}}::initParameter(uint32_t index, Parameter& parameter)
{
{%- if receivers|length > 0 -%}
{%- if (receivers|length > 0) or (senders|length > 0) -%}
// initialise parameters with defaults
switch (index)
{
{% for k, v in receivers -%}
case param{{v.display}}:
parameter.name = "{{v.display.replace('_', ' ')}}";
parameter.symbol = "{{v.display|lower}}";
{%- if v.attributes.type == 'db': %}
parameter.unit = "dB";
{%- elif v.attributes.type in ['hz', 'log_hz']: %}
parameter.unit = "Hz";
{%- endif %}
parameter.hints = kParameterIsAutomatable
{%- if v.attributes.type == 'bool': %}
| kParameterIsBoolean
{%- elif v.attributes.type == 'trig': -%}
| kParameterIsTrigger
{%- elif v.attributes.type == 'int': -%}
| kParameterIsInteger
{%- elif v.attributes.type in ['log', 'log_hz']: -%}
| kParameterIsLogarithmic
{%- endif %};
parameter.ranges.min = {{v.attributes.min}}f;
parameter.ranges.max = {{v.attributes.max}}f;
parameter.ranges.def = {{v.attributes.default}}f;
{%- if v.attributes.type == 'db' and not (meta.enumerators is defined and meta.enumerators[v.display] is defined): %}
{
ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[1];
enumValues[0].value = {{v.attributes.min}}f;
enumValues[0].label = "-inf";
parameter.enumValues.count = 1;
parameter.enumValues.values = enumValues;
}
{%- endif %}
{%- if meta.enumerators is defined and meta.enumerators[v.display] is defined %}
{% set enums = meta.enumerators[v.display] %}
{% set enumlen = enums|length %}
if (ParameterEnumerationValue *values = new ParameterEnumerationValue[{{enumlen}}])
{
parameter.enumValues.restrictedMode = true;
{% for i in enums -%}
values[{{loop.index - 1}}].value = {{loop.index - 1}}.0f;
values[{{loop.index - 1}}].label = "{{i}}";
{% endfor -%}
parameter.enumValues.count = {{enumlen}};
parameter.enumValues.values = values;
}
{%- endif %}
break;
{% for k, v in receivers %}
{% include 'parameter.cpp' %}
{% endfor -%}
{% for k, v in senders -%}
{% set param_out = true %}
{% include 'parameter.cpp' %}
{% endfor %}
}
{% endif %}
Expand Down Expand Up @@ -194,6 +160,18 @@ void {{class_name}}::setParameterValue(uint32_t index, float value)
{%- endif %}
}

void {{class_name}}::setOutputParameter(const char *sendName, const HvMessage *m)
{
{%- if senders|length > 0 %}
{% for k, v in senders -%}
if (sendName == "{{v.display}}")
{
_parameters[param{{v.display}}] = hv_msg_getFloat(m, 0);;
}
{% endfor %}
{%- endif %}
}


// -------------------------------------------------------------------
// Process
Expand Down
8 changes: 6 additions & 2 deletions hvcc/generators/c2dpf/templates/HeavyDPF.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class {{class_name}} : public Plugin
{% for k, v in receivers -%}
param{{v.display}},
{% endfor %}
{% for k, v in senders -%}
param{{v.display}},
{% endfor %}
};

{% if meta.port_groups is defined %}
Expand All @@ -44,6 +47,7 @@ class {{class_name}} : public Plugin

void handleMidiInput(uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount);
void handleMidiSend(uint32_t sendHash, const HvMessage *m);
void setOutputParameter(const char *sendName, const HvMessage *m);

protected:
// -------------------------------------------------------------------
Expand Down Expand Up @@ -135,9 +139,9 @@ class {{class_name}} : public Plugin
// -------------------------------------------------------------------

private:
{%- if receivers|length > 0 %}
{%- if (receivers|length > 0) or senders|length > 0 %}
// parameters
float _parameters[{{receivers|length}}]; // in range of [0,1]
float _parameters[{{receivers|length + senders|length}}]; // in range of [0,1]
{%- endif %}

// transport values
Expand Down
15 changes: 9 additions & 6 deletions hvcc/generators/c2dpf/templates/HeavyDPF_UI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@
START_NAMESPACE_DISTRHO

// --------------------------------------------------------------------------------------------------------------------
{%- if receivers|length > 0 %}
{%- if (receivers|length > 0) or (senders|length > 0) %}
enum HeavyParams {
{%- for k, v in receivers %}
{{v.display|upper}},
{%- endfor %}
{%- for k, v in senders %}
{{v.display|upper}},
{%- endfor %}
};
{%- endif %}

class ImGuiPluginUI : public UI
{
{% for k, v in receivers -%}
{% for k, v in receivers + senders -%}
{%- if v.attributes.type == 'bool': %}
bool f{{v.display|lower}} = {{v.attributes.default}}f != 0.0f;
{%- elif v.attributes.type == 'int': %}
Expand Down Expand Up @@ -56,9 +59,9 @@ class ImGuiPluginUI : public UI
*/
void parameterChanged(uint32_t index, float value) override
{
{%- if receivers|length > 0 %}
{%- if (receivers|length > 0) or (senders|length > 0) %}
switch (index) {
{% for k, v in receivers -%}
{% for k, v in receivers + senders -%}
case {{v.display|upper}}:
{%- if v.attributes.type == 'bool': %}
f{{v.display|lower}} = value != 0.0f;
Expand Down Expand Up @@ -92,7 +95,7 @@ class ImGuiPluginUI : public UI

if (ImGui::Begin("{{name.replace('_', ' ')}}", nullptr, ImGuiWindowFlags_NoResize + ImGuiWindowFlags_NoCollapse))
{
{%- for k, v in receivers %}
{%- for k, v in receivers + senders %}
{%- set v_display = v.display|lower %}
{%- if meta.enumerators is defined and meta.enumerators[v.display] is defined -%}
{%- set enums = meta.enumerators[v.display] -%}
Expand Down Expand Up @@ -140,7 +143,7 @@ class ImGuiPluginUI : public UI
{% endfor %}
if (ImGui::IsItemDeactivated())
{
{%- for k, v in receivers -%}
{%- for k, v in receivers + senders -%}
editParameter({{v.display|upper}}, false);
{% endfor -%}
}
Expand Down
49 changes: 49 additions & 0 deletions hvcc/generators/c2dpf/templates/parameter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
case param{{v.display}}:
parameter.name = "{{v.display.replace('_', ' ')}}";
parameter.symbol = "{{v.display|lower}}";
{%- if v.attributes.type == 'db': %}
parameter.unit = "dB";
{%- elif v.attributes.type in ['hz', 'log_hz']: %}
parameter.unit = "Hz";
{%- endif %}
{%- if param_out %}
parameter.hints = kParameterIsOutput
{%- else %}
parameter.hints = kParameterIsAutomatable
{%- endif %}
{%- if v.attributes.type == 'bool': %}
| kParameterIsBoolean
{%- elif v.attributes.type == 'trig': -%}
| kParameterIsTrigger
{%- elif v.attributes.type == 'int': -%}
| kParameterIsInteger
{%- elif v.attributes.type in ['log', 'log_hz']: -%}
| kParameterIsLogarithmic
{%- endif %};
parameter.ranges.min = {{v.attributes.min}}f;
parameter.ranges.max = {{v.attributes.max}}f;
parameter.ranges.def = {{v.attributes.default}}f;
{%- if v.attributes.type == 'db' and not (meta.enumerators is defined and meta.enumerators[v.display] is defined): %}
{
ParameterEnumerationValue* const enumValues = new ParameterEnumerationValue[1];
enumValues[0].value = {{v.attributes.min}}f;
enumValues[0].label = "-inf";
parameter.enumValues.count = 1;
parameter.enumValues.values = enumValues;
}
{%- endif %}
{%- if meta.enumerators is defined and meta.enumerators[v.display] is defined %}
{% set enums = meta.enumerators[v.display] %}
{% set enumlen = enums|length %}
if (ParameterEnumerationValue *values = new ParameterEnumerationValue[{{enumlen}}])
{
parameter.enumValues.restrictedMode = true;
{% for i in enums -%}
values[{{loop.index - 1}}].value = {{loop.index - 1}}.0f;
values[{{loop.index - 1}}].label = "{{i}}";
{% endfor -%}
parameter.enumValues.count = {{enumlen}};
parameter.enumValues.values = values;
}
{%- endif %}
break;
31 changes: 31 additions & 0 deletions hvcc/interpreters/pd2hv/PdSendObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,37 @@ def __init__(
except Exception:
pass

if self.__extern_type == "param":
try:
self.__attributes = {
"min": 0.0,
"max": 1.0,
"default": 0.5,
"type": "float"
}
self.__attributes["min"] = float(self.obj_args[2])
self.__attributes["max"] = float(self.obj_args[3])
self.__attributes["default"] = float(self.obj_args[4])
self.__attributes["type"] = str(self.obj_args[5])
except ValueError:
self.add_warning(
f"Minimum, maximum, and default values for Parameter {self.__receiver_name} must be numbers.")
except Exception:
pass

if not (self.__attributes["min"] <= self.__attributes["default"]):
self.add_error("Default parameter value is less than the minimum. "
"Receiver will not be exported: {0:g} < {1:g}".format(
self.__attributes["default"],
self.__attributes["min"]))
self.__extern_type = None
if not (self.__attributes["default"] <= self.__attributes["max"]):
self.add_error("Default parameter value is greater than the maximum. "
"Receiver will not be exported: {0:g} > {1:g}".format(
self.__attributes["default"],
self.__attributes["max"]))
self.__extern_type = None

if '@raw' in self.obj_args or '@owl' in self.obj_args: # TODO(dromer): deprecate @owl on next stable release
try:
pd_raw_args = parse_pd_raw_args(self.obj_args)
Expand Down

0 comments on commit 5e3ac60

Please sign in to comment.