<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[[Bug] Enabling NUM_HARDCODED_FX_MODS breaks custom C++ nodes.]]></title><description><![CDATA[<h1>Hardcoded Master FX parameter modslots can force c++ Third-party node parameters to max</h1>
<p dir="auto">*I used ChatGPT to help format this bug report so that it's written clearly and thoroughly.<br />
I apologize for the "Ai aesthetic" residue that leaves behind.</p>
<p dir="auto"><strong>Branch:</strong> I'm on the latest HISE develop branch, pulled and compiled today<br />
<strong>OS:</strong> Windows 11<br />
<strong>Juce:</strong> I'm using Juce 6 (version: 6.1.3)<br />
<strong>Project flags:</strong></p>
<pre><code>NUM_HARDCODED_FX_MODS=8
NUM_HARDCODED_POLY_FX_MODS=8
</code></pre>
<h2>Summary</h2>
<p dir="auto">I think there is a bug in the hardcoded Master FX "parameter-modslot" path.<br />
I didn't want to post a report until I was sure it wasn't my own mistake, but I've been reading the Hise source all day and testing different C+ nodes and in the end I concluded this might be a bug:</p>
<p dir="auto">If a third-party node exposes a parameter modslot with <code>ConnectionMode::Parameter</code> , loading that node into a hardcoded Master FX forces the modslot parameter values to get set to the top of their ranges (and stuck there).</p>
<p dir="auto">This is not a small issue. For DSP nodes it completely breaks effects, and means you can't use any c++ nodes that have modslots inside monophonic hardcoded master FX.</p>
<p dir="auto">I like almost all of my c++ nodes to have modslots so that they can work easily with hise modulation and the matrix modulator. This bug means I have to make modslot and non-modslot versions of every effect, so that I can load the modslot version into poly contexts and the non-modslot one into mono contexts. And then for the mono nodes I have to use a different modulation scheme. Messy.<br />
(unless I'm misunderstanding something).</p>
<h2>How I found it</h2>
<p dir="auto">I was testing a compiled third-party DSP node.</p>
<p dir="auto">The same node behaved normally in a ScriptFX context, but in a hardcoded Master FX it produced broken / glitchy / extremely wrong output.</p>
<p dir="auto">When I removed these project flags and rebuilt, the hardcoded Master FX version started behaving normally again:</p>
<pre><code>NUM_HARDCODED_FX_MODS=8
NUM_HARDCODED_POLY_FX_MODS=8
</code></pre>
<p dir="auto">So the issue appears to be tied to hardcoded FX modslots.</p>
<p dir="auto">Disabling those flags is not a usable workaround for me, because then hardcoded modslots would be unavailable project-wide.</p>
<h2>Minimal test</h2>
<p dir="auto">I made four tiny diagnostic third-party nodes.</p>
<p dir="auto">Each node has one parameter:</p>
<pre><code>Parameter_name: ProbeValue

Range:   0.0 to 1.0
Default: 0.25
</code></pre>
<p dir="auto">Each node outputs a tone whose gain follows <code>ProbeValue</code>.</p>
<p dir="auto">Expected result: quiet tone.<br />
Bug result if the parameter is forced to max: much louder tone.</p>
<p dir="auto">Each node exposes the same parameter slot:</p>
<pre><code>modulation::ConnectionInfo slot;
slot.connectedParameterIndex = ProbeValueParameter;
slot.connectionMode = modulation::ConnectionMode::Parameter;
slot.modulationMode = modulation::ParameterMode::ScaleAdd;
</code></pre>
<p dir="auto">I tested four variants:</p>
<pre><code>Griffin_ModSlotProbe_NoHandle
Griffin_ModSlotProbe_WithHandle
Griffin_ModSlotProbe_FrameHandle
Griffin_ModSlotProbe_ModNodeHandle
</code></pre>
<p dir="auto">These check whether adding the following details would fix or change the behavior:</p>
<ul>
<li>no <code>handleModulation()</code> function defined</li>
<li><code>handleModulation(double&amp;) { return 0; }</code></li>
<li>block processing forwarded through <code>processFrame()</code> from process()</li>
<li><code>isModNode() == true</code> (yeah, I know that's not going to do anything)</li>
</ul>
<h2>Result</h2>
<p dir="auto">In hardcoded Master FX:</p>
<pre><code>NoHandle       left loud, right silent
WithHandle     left loud, right silent
FrameHandle    left loud, right silent
ModNodeHandle  left loud, right silent
</code></pre>
<p dir="auto">The left channel becoming loud proves <code>ProbeValue</code> was driven from <code>0.25</code> to <code>1.0</code>.<br />
And the right channel staying silent means <code>handleModulation(double&amp;)</code> callback was not called.</p>
<h2>Expected behaviour</h2>
<p dir="auto">Ideally, a hardcoded Master FX parameter modslot should not push a node parameter to its maximum value simply because the slot exists.</p>
<p dir="auto">If no meaningful modulation value is active, the parameter should keep its current/default value, or the slot should not be treated as connected until there is an actual usable modulation connection.</p>
<h2>Current behaviour</h2>
<p dir="auto">Currently, with hardcoded FX modslots enabled, a third-party C++ node exposing <code>ConnectionMode::Parameter</code> can get seemingly spammed with max-range parameter values during rendering / stuck at max value (moving the parameter doesn't unstick us, the parameters are stuck to max).</p>
<h2>Why this matters</h2>
<p dir="auto">I'm assuming that HISE nodes are intended to be modular.<br />
If that's true, then a node that is poly-capable, or a node that exposes modslots, should be able to function in a mono hardcoded Master FX context too.</p>
<p dir="auto">This is also inconvenient for my shipped products. A HISE user can load one of my nodes into HISE and get broken DSP because the hardcoded Master FX modulation path corrupts parameter values.</p>
<p dir="auto">The result of all this is that <code>ConnectionMode::Parameter</code> becomes unsafe for third-party hardcoded Master FX products.</p>
<h2>Suspected source bug</h2>
<p dir="auto">The Hise algorithm seems to do something like this:</p>
<pre><code>HardcodedMasterFX::applyEffect()
  -&gt; extraMods.processChunkedWithModulation(rd)
  -&gt; ExtraModulatorRuntimeTargetSource::handleModulation(...)
  -&gt; ModChainWithBuffer::getOneModulationValue(startSample)
  -&gt; rd.handleModulation(pIndex, mv)
  -&gt; parameter range convertFrom0to1(mv)
  -&gt; p-&gt;callback.call(value)
</code></pre>
<p dir="auto">The important part is in the hardcoded Master FX context, with no active voice state, <code>getOneModulationValue()</code> can return an inactive/default modulation value of <code>1.0f</code>.</p>
<p dir="auto">That normalized <code>1.0</code> is then converted through the parameter range, so the node receives the parameter maximum.</p>
<h2>Request</h2>
<p dir="auto">Could the hardcoded Master FX parameter-modslot path be changed so inactive / unconnected / not-yet-valid modulation does not force parameter-mode slots to max?</p>
<hr />
<p dir="auto">post script: a similar / related bug exists in the Hise synth group, I will write a report on that after a bit more investigation.</p>
<hr />
<p dir="auto">Christoph, Thanks for all your hard work🫡</p>
]]></description><link>https://forum.hise.audio/topic/14903/bug-enabling-num_hardcoded_fx_mods-breaks-custom-c-nodes</link><generator>RSS for Node</generator><lastBuildDate>Sun, 05 Jul 2026 07:20:08 GMT</lastBuildDate><atom:link href="https://forum.hise.audio/topic/14903.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 05 Jul 2026 00:42:23 GMT</pubDate><ttl>60</ttl></channel></rss>