Okie, here's the wrapper if anyone else needs it:
// ==================================| Third Party Node Template |==================================
#pragma once
#include <JuceHeader.h>
namespace project
{
using namespace juce;
using namespace hise;
using namespace scriptnode;
// ==========================| The node class with all required callbacks |==========================
template <int NV> struct phaseNudge: public data::base
{
// Metadata Definitions ------------------------------------------------------------------------
SNEX_NODE(phaseNudge);
struct MetadataClass
{
SN_NODE_ID("phaseNudge");
};
static constexpr bool isModNode() { return false; };
static constexpr bool isPolyphonic() { return NV > 1; };
static constexpr bool hasTail() { return false; };
static constexpr bool isSuspendedOnSilence() { return false; };
static constexpr int getFixChannelAmount() { return 2; };
static constexpr int NumTables = 0;
static constexpr int NumSliderPacks = 0;
static constexpr int NumAudioFiles = 0;
static constexpr int NumFilters = 0;
static constexpr int NumDisplayBuffers = 0;
void prepare(PrepareSpecs specs)
{
}
void reset()
{
}
void handleHiseEvent(HiseEvent& e)
{
(void)e;
}
double dL[1503];
double dR[1503];
int one = 1;
int maxdelay = 9001;
double A = 0.0;
double B = 1.0;
uint32_t fpdL;
uint32_t fpdR;
int allpasstemp;
double outallpass = 0.618033988749894848204586;
int maxdelayTarget = (int)(pow(A,3)*1501.0);
double wet = B;
double bridgerectifier;
double inputSampleL;
double inputSampleR;
double drySampleL;
double drySampleR;
template <typename T> void process(T& data)
{
const int numSamples = data.getNumSamples();
const int numChannels = jmin(2, (int)data.getNumChannels());
maxdelayTarget = (int)(pow(A, 3) * 1501.0);
wet = B;
dyn<float> chL, chR;
int idx = 0;
for (auto ch : data)
{
if (idx == 0) chL = data.toChannelData(ch);
else if (idx == 1) chR = data.toChannelData(ch);
++idx;
}
if (numChannels == 1) chR = chL;
for (int s = 0; s < numSamples; ++s)
{
double dryL = chL[s];
double dryR = numChannels > 1 ? chR[s] : dryL;
double xL = chL[s];
double xR = numChannels > 1 ? chR[s] : xL;
// might add dithering later
// bridge rectifier
xL /= 4.0;
xR /= 4.0;
double br = std::fabs(xL);
br = std::sin(br);
if (xL > 0) xL = br;
else xL = -br;
br = std::fabs(xR);
br = std::sin(br);
if (xR > 0) xR = br;
else xR = -br;
// allpass
if (std::fabs(maxdelay - maxdelayTarget) > 1500) maxdelay = maxdelayTarget;
if (maxdelay < maxdelayTarget)
{
maxdelay++;
dL[maxdelay] = (dL[0] + dL[maxdelay-1]) / 2.0;
dR[maxdelay] = (dR[0] + dR[maxdelay-1]) / 2.0;
}
if (maxdelay > maxdelayTarget)
{
maxdelay--;
dL[maxdelay] = (dL[0] + dL[maxdelay]) / 2.0;
dR[maxdelay] = (dR[0] + dR[maxdelay]) / 2.0;
}
allpasstemp = one - 1;
if (allpasstemp < 0 || allpasstemp > maxdelay) allpasstemp = maxdelay;
xL -= dL[allpasstemp] * outallpass;
xR -= dR[allpasstemp] * outallpass;
dL[one] = xL;
dR[one] = xR;
xL *= outallpass;
xR *= outallpass;
one--;
if (one < 0 || one > maxdelay) { one = maxdelay; }
xL += (dL[one]);
xR += (dR[one]);
// second bridge rectifier stage
br = std::fabs(xL);
br = 1.0 - std::cos(br);
if (xL > 0) xL -= br;
else xL += br;
br = std::fabs(xR);
br = 1.0 - std::cos(br);
if (xR > 0) xR -= br;
else xR += br;
xL *= 4.0;
xR *= 4.0;
// apply dry / wet
if (wet < 1.0)
{
xL = (dryL * (1.0 - wet)) + (xL * wet);
xR = (dryR * (1.0 - wet)) + (xR * wet);
}
// apply dither goes here
// write back to channelData
chL[s] = xL;
chR[s] = xR;
}
}
template <typename T> void processFrame(T& data)
{
}
int handleModulation(double& value)
{
return 0;
}
void setExternalData(const ExternalData& data, int index)
{
}
template <int P> void setParameter(double v)
{
switch (P)
{
case 0: { A = v; break; }
case 1: { B = v; break; }
}
}
void createParameters(ParameterDataList& data)
{
{
parameter::data p("PhaseNudge", { 0.0, 1.0 });
registerCallback<0>(p);
p.setDefaultValue(0.5);
data.add(std::move(p));
}
{
parameter::data p("Dry/Wet", { 0.0, 1.0 });
registerCallback<1>(p);
p.setDefaultValue(0.5);
data.add(std::move(p));
}
}
}; // end struct
} // end namespace
It's missing the dithering stuff, but it sounds basically identical to the original implementation, just make sure to set up the third party node using the template and call it "phaseNudge.h"