template or tutorial for custom c++ scriptnode?
-
@Morphoice Did a small fix there was an error in the template
https://drive.google.com/drive/folders/1bVj_MhnwYv5HSFpXa4-0ZUIknswYuRBX?usp=sharing
-
@griffinboy said in template or tutorial for custom c++ scriptnode?:
https://drive.google.com/drive/folders/1bVj_MhnwYv5HSFpXa4-0ZUIknswYuRBX?usp=sharing
thanks so much! I'll use this wisely to make new nodes ;))
-
@griffinboy btw just tried compiling the node on PC but that didnt work at all it's throwing a ton of errors. you wont happen to have any idea what I did wrong?
// ==========================| muLawBitCrusher v1.0 by Morphoice |========================== #pragma once #include <JuceHeader.h> #include <cmath> namespace project { using namespace juce; using namespace hise; using namespace scriptnode; template <typename T> int sgn(T val) { return (T(0) < val) - (val < T(0)); } template <int NV> // --- Replace with Name struct muLawBitCrusher : public data::base { // ------ Replace with Name SNEX_NODE(muLawBitCrusher); struct MetadataClass { // --------- Replace with "Name" SN_NODE_ID("muLawBitCrusher"); }; // ==========================| Node Properties |========================== 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; // ==========================| Global Variables |========================== // ==========================| Prepare |========================== // Called on init, and when sample rate changes void prepare(PrepareSpecs specs) { float sampleRate = specs.sampleRate; float numChannels = specs.numChannels; leftChannelEffect.prepare(sampleRate, 5.0); // 5ms smoothing on the gain parameter rightChannelEffect.prepare(sampleRate, 5.0); } // ==========================| Reset |========================== // Called when the plugin is reloaded void reset() {} // ==========================| Process |========================== // Blocks of audio enter the script here template <typename ProcessDataType> void process(ProcessDataType& data) { // Convert the audio data to a fixed-channel format for efficient processing auto& fixData = data.template as<ProcessData<getFixChannelAmount()>>(); // Get pointers to each channel's audio data // Changes to these variables will now directly modify the original audio buffer auto audioBlock = fixData.toAudioBlock(); auto* leftChannelData = audioBlock.getChannelPointer(0); auto* rightChannelData = audioBlock.getChannelPointer(1); // Get the number of samples (one channel) for this block int numSamples = data.getNumSamples(); // Pass each channel's audio to the appropriate AudioEffect class leftChannelEffect.process(leftChannelData, numSamples); rightChannelEffect.process(rightChannelData, numSamples); } // ==========================| AudioEffect Class |========================== class AudioEffect { public: AudioEffect(float initialGain = 1.0f) { smoothGain.set(initialGain); // Initialize sfloat with initial gain } void prepare(double sampleRate, double timeInMilliseconds) { smoothGain.prepare(sampleRate, timeInMilliseconds); } void process(float* samples, int numSamples) { for (int i = 0; i < numSamples; ++i) { float val = samples[i]; if (val!=0) { // mu-law compress signal int max = 255; float valmu = sgn(val) * log( 1.0f + max * abs(val) ) / log( 1.0f + max); // Quantize to 8 bits float valmu8 = valmu - fmodf(valmu, 1.0f / max); // mu-law expand signal float valex = sgn(valmu8) * (1.0f / max) * ( pow(max + 1.0f, abs(valmu8)) - 1.0f ); // Apply Demo Gain samples[i] = valex * smoothGain.advance(); } /* float rem = fmodf(val,1/max); // Linear quantized to 8 bits float val8 = val - rem; */ } } void updateGain(float newGain) { smoothGain.set(newGain); } private: sfloat smoothGain; // Declare smoothGain variable, using sfloat type for smoothing }; // ==========================| Set Parameter |========================== template <int P> void setParameter(double v) { if (P == 0) leftChannelEffect.updateGain(static_cast<float>(v)); // Update gain for left channel else if (P == 1) rightChannelEffect.updateGain(static_cast<float>(v)); // Update gain for right channel } // ==========================| Create Parameters |========================== void createParameters(ParameterDataList& data) { { // { min, max, step } { id } parameter::data p("LeftGain", { 0.1, 2.0, 0.01 }); registerCallback<0>(p); p.setDefaultValue(1.0); data.add(std::move(p)); } { parameter::data p("RightGain", { 0.1, 2.0, 0.01 }); registerCallback<1>(p); p.setDefaultValue(1.0); data.add(std::move(p)); } } // ==========================| External Data |========================== void setExternalData(const ExternalData& data, int index) {} // ==========================| Handle HISE Event |========================== void handleHiseEvent(HiseEvent& e) {} // ==========================| Modulation Slot |========================== // ( first enable isModNode() at the top of script ) /* ModValue modValue; int handleModulation(double& value) { return modValue.getChangedValue(value); } // Creates callback so that altering the 'modValue' var elsewhere will now update the mod slot modValue.setModValue(0); */ // processFrame: Needed for compiler, does nothing template <typename FrameDataType> void processFrame(FrameDataType& data) {} private: AudioEffect leftChannelEffect; AudioEffect rightChannelEffect; }; }
what works on mac doesn't on PC
error C3203: 'muLawBitCrusher': unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type
-
it compiles on my end.
Did you make sure to name the .h file as follows:muLawBitCrusher.h
The c++ file always needs to share the same name as the node.
Also by the way, your effect has a heck ton of aliasing.Edit: *facepalm, aliasing is the point, please ignore me lol
-
@griffinboy ;-))) yes it's named correctly, the VS compiler seems to take offense of my sgn function I got off the webs which is weird as it works fine on mac
template <typename T> int sgn(T val) { return (T(0) < val) - (val < T(0)); }
-
Yeah it works on my machine... try a fresh hise project.
You could also always try recompiling the latest hise.
If those two things don't fix it, then it's a tricky one -
@griffinboy i'm getting rid of that template thing for that stupid sign function, which is a syntax beyond my c++ knowledge
this should work too, at least on mac it compiles fine, gotta try on the pc later
// mu-law compress signal int max = 255; int sign = (0 < val) - (val < 0); float valmu = sign * log( 1.0f + max * abs(val) ) / log( 1.0f + max); // Quantize to 8 bits float valmu8 = valmu - fmodf(valmu, 1.0f / max); // mu-law expand signal float valex = sign * (1.0f / max) * ( pow(max + 1.0f, abs(valmu8)) - 1.0f );
-
@griffinboy on second thought sign probably only needs to calculate once and should be the same on compressing and expanding a sample so even more calculations can be avoided
-
@griffinboy said in template or tutorial for custom c++ scriptnode?:
@Morphoice Did a small fix there was an error in the template
https://drive.google.com/drive/folders/1bVj_MhnwYv5HSFpXa4-0ZUIknswYuRBX?usp=sharing
Sadly this is pretty unusable - as it blocks chrome from looking at it if adblockers are turned on...
-
Thanks for the heads up
-
Doesn't even need to be used once. There are approximations or lookup tables that can be used.