HISE Logo Forum
    • Categories
    • Register
    • Login

    template or tutorial for custom c++ scriptnode?

    Scheduled Pinned Locked Moved ScriptNode
    38 Posts 8 Posters 3.8k 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.
    • 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

                          14

                          Online

                          1.8k

                          Users

                          12.0k

                          Topics

                          104.5k

                          Posts