HISE Logo Forum
    • Categories
    • Register
    • Login

    template or tutorial for custom c++ scriptnode?

    Scheduled Pinned Locked Moved ScriptNode
    38 Posts 8 Posters 1.0k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • MorphoiceM
      Morphoice @griffinboy
      last edited by

      @griffinboy said in template or tutorial for custom c++ scriptnode?:

      Link Preview Image
      C++ Node Templates – Google Drive

      favicon

      Google Drive (drive.google.com)

      thanks so much! I'll use this wisely to make new nodes ;))

      https://instagram.com/morphoice - 80s inspired Synthwave Music, Arcade & Gameboy homebrew!

      1 Reply Last reply Reply Quote 0
      • MorphoiceM
        Morphoice @griffinboy
        last edited by

        @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
        

        https://instagram.com/morphoice - 80s inspired Synthwave Music, Arcade & Gameboy homebrew!

        griffinboyG 1 Reply Last reply Reply Quote 0
        • griffinboyG
          griffinboy @Morphoice
          last edited by griffinboy

          @Morphoice

          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

          MorphoiceM 1 Reply Last reply Reply Quote 0
          • MorphoiceM
            Morphoice @griffinboy
            last edited by

            @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));
                }
            

            https://instagram.com/morphoice - 80s inspired Synthwave Music, Arcade & Gameboy homebrew!

            griffinboyG 1 Reply Last reply Reply Quote 0
            • griffinboyG
              griffinboy @Morphoice
              last edited by

              @Morphoice

              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

              MorphoiceM 2 Replies Last reply Reply Quote 0
              • MorphoiceM
                Morphoice @griffinboy
                last edited by Morphoice

                @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 );
                

                https://instagram.com/morphoice - 80s inspired Synthwave Music, Arcade & Gameboy homebrew!

                1 Reply Last reply Reply Quote 0
                • MorphoiceM
                  Morphoice @griffinboy
                  last edited by

                  @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

                  https://instagram.com/morphoice - 80s inspired Synthwave Music, Arcade & Gameboy homebrew!

                  griffinboyG 1 Reply Last reply Reply Quote 0
                  • LindonL
                    Lindon @griffinboy
                    last edited by

                    @griffinboy said in template or tutorial for custom c++ scriptnode?:

                    @Morphoice Did a small fix there was an error in the template

                    Link Preview Image
                    C++ Node Templates – Google Drive

                    favicon

                    Google Drive (drive.google.com)

                    Sadly this is pretty unusable - as it blocks chrome from looking at it if adblockers are turned on...

                    HISE Development for hire.
                    www.channelrobot.com

                    griffinboyG 1 Reply Last reply Reply Quote 0
                    • griffinboyG
                      griffinboy @Lindon
                      last edited by

                      @Lindon

                      Thanks for the heads up

                      1 Reply Last reply Reply Quote 0
                      • griffinboyG
                        griffinboy @Morphoice
                        last edited by

                        @Morphoice

                        Doesn't even need to be used once. There are approximations or lookup tables that can be used.

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post

                        22

                        Online

                        1.7k

                        Users

                        11.8k

                        Topics

                        103.1k

                        Posts