HISE Logo Forum
    • Categories
    • Register
    • Login

    template or tutorial for custom c++ scriptnode?

    Scheduled Pinned Locked Moved ScriptNode
    38 Posts 8 Posters 1.1k 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 thanks man! a simpler template would be awesome, I also figured It would make sense to do the calculations only if samples[i] isnt zero, that should take most of the load in my case.

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

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

        @Morphoice

        Yep that makes sense, since you don't need to process the zero crossings for your effect.

        Link Preview Image
        C++ Node Templates – Google Drive

        favicon

        Google Drive (drive.google.com)

        Here's a more up to date version of the template. You'll have to wait until I've got time, for me to release the official version of this, which will have many more improvements

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

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

          MorphoiceM LindonL 3 Replies Last reply Reply Quote 0
          • 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

                              17

                              Online

                              1.7k

                              Users

                              11.8k

                              Topics

                              103.2k

                              Posts