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.
    • griffinboyG
      griffinboy @ustk
      last edited by

      @ustk

      C++ has sfloat as well.
      But I'm actually finding issues with it when imbedded deep in a sctiptnode network that has oversampling / softbypass nodes.

      I need to do more tests and figure out what's up, but in general sfloat works.

      ustkU 2 Replies Last reply Reply Quote 1
      • 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