HISE Logo Forum
    • Categories
    • Register
    • Login

    SNEX Filters...

    Scheduled Pinned Locked Moved General Questions
    7 Posts 2 Posters 442 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.
    • FatMitchellF
      FatMitchell
      last edited by

      Attempting to make a filter using the core.SNEX node. Using ChatGPT to help me since I know nothing about code. I assume its out of date but maybe someone could explain if this is even possible or not...

      I want to start with a simple Low Pass filter.

      -I created a new file within a network within script fx.

      Here is my error:

      snex_node - Line 83(20): Parsing error: Expected:
      TypeActual: $identifier

      Here is my code that's not working:

      template <int NV> struct snex_lowpass_filter
      {
          SNEX_NODE(snex_lowpass_filter);
      
          // Parameters
          float cutoffFrequency = 1000.0f; // Initial cutoff frequency
      
          // Initialise the processing specs here
          void prepare(PrepareSpecs ps)
          {
              // Any initialization can be done here
          }
      
          // Reset the processing pipeline here
          void reset()
          {
              // Reset any internal state variables here
          }
      
          // Low-pass filter function
          float lowPassFilter(float input)
          {
              // Sampling period
              const float dt = 1.0f / Engine.getSampleRate();
              // Time constant
              const float RC = 1.0f / (2.0f * PI * cutoffFrequency);
              // Coefficient
              const float alpha = dt / (RC + dt);
      
              // Compute output
              float output = alpha * input + (1.0f - alpha) * prevOutput;
      
              // Update previous output
              prevOutput = output;
      
              return output;
          }
      
          // Process the signal here
          template <typename ProcessDataType> void process(ProcessDataType& data)
          {
              for (auto& sample : data)
              {
                  sample = lowPassFilter(sample);
              }
          }
      
          // Process the signal as frame here
          template <int C> void processFrame(span<float, C>& data)
          {
              // This function is used for processing audio frames (e.g., stereo signal)
              // You can implement a frame-based processing if needed
          }
      
          // Process the MIDI events here
          void handleHiseEvent(HiseEvent& e)
          {
              // This function is used for handling MIDI events
              // You can implement MIDI event processing if needed
          }
      
          // Use this function to setup the external data
          void setExternalData(const ExternalData& d, int index)
          {
              // This function can be used to set up any external data needed for processing
          }
      
          // Set the parameters here
          void setParameter(int parameterIndex, double value)
          {
              // You can set parameters dynamically during runtime
              if (parameterIndex == 0)
              {
                  cutoffFrequency = value;
              }
          }
      
      private:
          // Previous output sample
          float prevOutput = 0.0f;
      };
      
      ? 1 Reply Last reply Reply Quote 0
      • ?
        A Former User @FatMitchell
        last edited by A Former User

        @FatMitchell been a hot minute since i've used snex, but something like:

        template <int NV> struct snex_lowpass_filter
        {
            SNEX_NODE(snex_lowpass_filter);
        
            // Variables
            // Define these so you aren't constantly allocating new memory every buffer
            float cutoffFrequency = 1000.0f; 
            float prevOutput = 0.0f;
            float RC = 0.0f;
            float alpha = 0.0f;
        
            void prepare(PrepareSpecs ps)
            {
                // i'm not sure if these need to be const
                // but they should be defined here, since this is where we get the sampleRate
                const float sr = ps.SampleRate; // sampleRate is inside the ps variable, not Engine
                const float dt = 1.0f / sr;
                const float PI = Math.pi();
        
                // not sure if ps.SampleRate is the real syntax, but it's something similar
            }
        
            void reset(){}
        
            float lowPassFilter(float input)
            {
                // not sure if these need to be consts
                const float RC = 1.0f / (2.0f * PI * cutoffFrequency); // PI should work now since we defined it above
                const float alpha = dt / (RC + dt);
                float output = alpha * input + (1.0f - alpha) * prevOutput;
                prevOutput = output; // not sure why prevOutput was private
        
                return output;
            }
        
            // Process the signal here
            template <typename ProcessDataType> void process(ProcessDataType& data)
            {
                for (auto& sample : data)
                {
                    sample = lowPassFilter(sample);
                }
            }
        
            // Unused
            template <int C> void processFrame(span<float, C>& data){}
            void handleHiseEvent(HiseEvent& e){}
            void setExternalData(const ExternalData& d, int index){}
        
            // Set the parameters here
            void setParameter(int parameterIndex, double value)
            {
                // You can set parameters dynamically during runtime
                if (parameterIndex == 0)
                {
                    cutoffFrequency = value;
                }
            }
        };
        

        if you don't have much coding experience, jumping straight into a SNEX filter might be a bit too much to take on, i recommend searching the forum or the repos for simpler examples like a Gain or Saturation effect before taking on something as math-heavy as a filter

        i'm not sure if my code will work, but hopefully it points you a bit closer to a working node

        FatMitchellF 1 Reply Last reply Reply Quote 0
        • FatMitchellF
          FatMitchell @A Former User
          last edited by

          @iamlamprey thank you endlessly for this. It didn’t work but it’s probably user error. Trying to read through everything I can find but it’s not much in terms of a finished working example. Do you have any working examples (of any kind) that u could post/sendme so I can study how it works and more importantly how to implement it.

          Thanks!

          ? 1 Reply Last reply Reply Quote 0
          • ?
            A Former User @FatMitchell
            last edited by

            @FatMitchell Christoph's already made a bunch of SNEX examples here:

            Link Preview Image
            HISE/tools/snex_playground/test_files at develop · christophhart/HISE

            The open source framework for sample based instruments - HISE/tools/snex_playground/test_files at develop · christophhart/HISE

            favicon

            GitHub (github.com)

            i recommend checking out the "Node" folder as a lot of the other examples are specifically explaining individual syntax

            note: some things have probably changed since he made these, for example I don't think you need data.toFrameData() anymore since there's now a function specifically for processing frames

            ? 1 Reply Last reply Reply Quote 1
            • ?
              A Former User @A Former User
              last edited by

              and here's a simple gain example:

              template <int NV> struct snex_simple_gain
              {
                  SNEX_NODE(snex_simple_gain);
              
                  // Variables
                  float gain = 1.0f;     
              
                  void prepare(PrepareSpecs ps){}
                  void reset(){}
              
                  // This can be a function, or we can do the raw math below
                  float applyGain(float input)
                  {
                      float output = input * gain;
              
                      return output;
                  }
              
                  // chatGPT failed you here I think
                  void process(ProcessData<NumChannels>& data)
                  {
                      for (auto& s : data)
                      {
                          s = applyGain(s);
                      }        
                  }
              
                  // Unused
                  template <int C> void processFrame(span<float, C>& data){}
                  void handleHiseEvent(HiseEvent& e){}
                  void setExternalData(const ExternalData& d, int index){}
              
                  // Set the parameters here
                  // chatGPT also failed you here :P
                  template <int P> void setParameter(double v)
                  {
                      // this gain parameter is added in the Scriptnode tree, it should be ranged 0-1 (where 1.0 is 100% gain)
                      if (P ==0) // the index of our parameter
                      {
                          gain = v;
                      }
                  }
              };
              

              i cant test if it works right now but it's a pretty simple example so it should help clarify what's going on

              FatMitchellF 1 Reply Last reply Reply Quote 1
              • FatMitchellF
                FatMitchell @A Former User
                last edited by

                @iamlamprey wow epic. Is the SNEX documentation up to date? I have been getting some Frame errors but I didn't see anything in the docs. Seriously thank you so much for your time and effort on this.

                ? 1 Reply Last reply Reply Quote 0
                • ?
                  A Former User @FatMitchell
                  last edited by

                  @FatMitchell said in SNEX Filters...:

                  Is the SNEX documentation up to date?

                  no idea, i think it's pretty feature-complete at this point so I don't see christoph making too many changes

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

                  28

                  Online

                  1.7k

                  Users

                  11.8k

                  Topics

                  102.8k

                  Posts