HISE Logo Forum
    • Categories
    • Register
    • Login

    C++/SNEX smooth parameter

    Scheduled Pinned Locked Moved C++ Development
    12 Posts 4 Posters 597 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.
    • ustkU
      ustk @griffinboy
      last edited by

      @griffinboy oh ok! I need this in an oversampling context too, because the more the DSP processing required, the more the crackles...

      Can't help pressing F5 in the forum...

      1 Reply Last reply Reply Quote 0
      • orangeO
        orange @ustk
        last edited by

        @ustk Math.smoothstep maybe?

        develop Branch / XCode 13.1
        macOS Monterey / M1 Max

        ustkU 1 Reply Last reply Reply Quote 0
        • ustkU
          ustk @griffinboy
          last edited by

          @griffinboy What kind of issues? Compile errors?

          Can't help pressing F5 in the forum...

          griffinboyG 1 Reply Last reply Reply Quote 0
          • ustkU
            ustk @orange
            last edited by ustk

            @orange Smooth step is to "de-linearise" a value and make it more "sigmoid like" curve

            Can't help pressing F5 in the forum...

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

              @ustk

              No, it just becomes "not smooth" anymore.
              I need to look into the code for sfloat because maybe I'm just using it wrong, but it works fine in a simpler context.

              Perhaps do a custom implementation for now, or look at how to use the one in Juce.

              ustkU 1 Reply Last reply Reply Quote 0
              • ustkU
                ustk @griffinboy
                last edited by

                @griffinboy I used this a few days ago but I am confused about set

                The doc says

                Sets a new target value and resets the ramp position to the beginning.

                The beginning of what? If the value has not yet reached the target, would that cause a jump?
                Or the new ramp is always calculated between the current position and the new target?

                Can't help pressing F5 in the forum...

                Christoph HartC griffinboyG 2 Replies Last reply Reply Quote 0
                • Christoph HartC
                  Christoph Hart @ustk
                  last edited by

                  Or the new ramp is always calculated between the current position and the new target

                  Yes this.

                  There‘s no reason why it shouldn‘t work within oversampling but you have to adjust the smoothing rate in the prepare callback.

                  griffinboyG ustkU 2 Replies Last reply Reply Quote 2
                  • griffinboyG
                    griffinboy @Christoph Hart
                    last edited by

                    @Christoph-Hart

                    Bingo that's probably what I missed. I had a teeny tiny smoothing rate.
                    With oversampling that now becomes very short!
                    Thx

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

                      @ustk

                      Here is one of my older c++ templates. Take a look at sfloat here:

                      // This is an example template. The functions that appear in this code must not be deleted, many of these are templated and as such are expected by the compiler. Other programs connected to this one supply each of the functions with data. 
                      // When taking this template and adapting it for our unique program we are trying to code, feel free to change the EFFECT class into one that is specific for our effect! That class is not templated and can be changed. 
                      // Block processing is preferred, and using a class like this for it is also good practice. Feel free to remove the gain effect, as that is only there to show you proper usage of the framework. 
                      
                      #pragma once
                      #include <JuceHeader.h>
                      
                      namespace project
                      {
                          using namespace juce;
                          using namespace hise;
                          using namespace scriptnode;
                      
                          template <int NV>
                          // Name 
                          struct ExternalNodeTemplate : public data::base
                          {          // Name
                              SNEX_NODE(ExternalNodeTemplate);
                      
                              struct MetadataClass
                              {            // Name
                                  SN_NODE_ID("ExternalNodeTemplate");
                              };
                      
                              // 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;
                      
                              // 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: Audioblocks enter the script here
                              template <typename ProcessDataType>
                              void process(ProcessDataType& data)
                              {
                                  auto& fixData = data.template as<ProcessData<getFixChannelAmount()>>();
                                  auto audioBlock = fixData.toAudioBlock();
                      
                                  // Get pointers to channel data
                                  auto* leftChannelData = audioBlock.getChannelPointer(0);
                                  auto* rightChannelData = audioBlock.getChannelPointer(1);
                      
                                  float blockSize = data.getNumSamples();
                      
                                  // Send each channel to the appropiate AudioEffect class
                                  leftChannelEffect.process(leftChannelData, blockSize);
                                  rightChannelEffect.process(rightChannelData, blockSize);
                                  // We use blocks rather than frames becuase there are more samples than channels (Better SIMD)
                              }
                      
                      
                      
                              // AudioEffect class: Handles audio processing
                              class AudioEffect
                              {
                              public:
                                  // Constructor to initialize gain
                                  AudioEffect(float initialGain = 1.0f)
                                  {
                                      smoothGain.set(initialGain); // Initialize sfloat with initial gain
                                  }
                      
                                  // Prepare the smoothedFloat with sample rate and time
                                  void prepare(double sampleRate, double timeInMilliseconds)
                                  {
                                      smoothGain.prepare(sampleRate, timeInMilliseconds);
                                  }
                      
                                  // Process function: Recieves a block of samples
                                  void process(float* samples, int numSamples)
                                  {
                                      // Iterate over each sample in the block
                                      for (int i = 0; i < numSamples; ++i)
                                      {
                                          samples[i] *= smoothGain.advance(); // Apply the effect using the smoothed parameter
                                      }
                      
                                  }
                      
                                  // Update Gain: Called by setParameter function
                                  void updateGain(float newGain)
                                  {
                                      smoothGain.set(newGain);
                                  }
                      
                              private:
                                  sfloat smoothGain; // Instance of sfloat for smooth gain
                              };
                      
                      
                              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 on the GUI
                              void createParameters(ParameterDataList& data)
                              {
                                  {                              //  { min, max,  step }                   < id >
                                      parameter::data p("Left Gain", { 0.1, 2.0,  0.01 }); registerCallback< 0 >(p);
                                      p.setDefaultValue(1.0);
                                      data.add(std::move(p));
                                  }
                                  {
                                      parameter::data p("Right Gain", { 0.1, 2.0,  0.01 }); registerCallback< 1 >(p);
                                      p.setDefaultValue(1.0);
                                      data.add(std::move(p));
                                  }
                              }
                      
                              // // Interact with external data (eg. an external buffer)
                              void setExternalData(const ExternalData& data, int index) {}
                      
                              // Handle HISE events: Process MIDI or other events
                              void handleHiseEvent(HiseEvent& e) {}
                      
                              // Handle external modulation slot ( first enable isModNode() )  
                              /*
                                  ModValue modValue;
                                  int handleModulation(double& value)
                                  {
                                      return modValue.getChangedValue(value);
                                  }
                                  // setting modValue updates the external modulation
                                  modValue.setModValue(0);
                              */
                      
                              // processFrame: Needed for compiler, does nothing
                              template <typename FrameDataType>
                              void processFrame(FrameDataType& data) {}
                      
                      
                          private:
                              // Create instances of AudioEffect for left and right channels
                              AudioEffect leftChannelEffect;
                              AudioEffect rightChannelEffect;
                          };
                      }
                      
                      
                      1 Reply Last reply Reply Quote 1
                      • ustkU
                        ustk @Christoph Hart
                        last edited by

                        @Christoph-Hart Yeah I have noticed it was necessary to update the timing as samplerate changes

                        @griffinboy Perfect thanks mate!

                        Can't help pressing F5 in the forum...

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

                        20

                        Online

                        1.7k

                        Users

                        11.9k

                        Topics

                        103.4k

                        Posts