HISE Logo Forum
    • Categories
    • Register
    • Login

    Adventures in Script Node - performance...I think

    Scheduled Pinned Locked Moved General Questions
    8 Posts 3 Posters 204 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.
    • LindonL
      Lindon
      last edited by

      So I have my all new distortion SNEX node set up - I've compiled it (along with its co-stars) into a DLL, I've replaced it using HardCodedMasterFX, I've compiled my project -- all good....

      ..but....

      When I run my plug-in this fx introduces a considerable delay in the signal- such that mixing it back with the dry signal seems like its using an 0.5 second fixed delay (it isnt)

      .. what am I doing wrong?

      HISE Development for hire.
      www.channelrobot.com

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

        @Lindon said in Adventures in Script Node - performance...I think:

        So I have my all new distortion SNEX node set up - I've compiled it (along with its co-stars) into a DLL, I've replaced it using HardCodedMasterFX, I've compiled my project -- all good....

        ..but....

        When I run my plug-in this fx introduces a considerable delay in the signal- such that mixing it back with the dry signal seems like its using an 0.5 second fixed delay (it isnt)

        .. what am I doing wrong?

        Have you used Oversampling? If yes, this is normal. Firstly you need to find out empirically what is the delay amount in samples. You can do it with null test using free tools, I use: https://www.forward-audio.com/phase-alignment-plugin-free-fasampledelay/

        After you know the sample delay value, insert a Script FX at the end of your module tree. Then use that delay value in Engine.setLatencySamples(int latency); on the prepareToPlay function of the ScriptFX. This will apply the delay compensation for the DAW. It will declare to the DAW on initialization that this plugin have x sample delay, so the DAW will compensate it.

        develop Branch / XCode 13.1
        macOS Monterey / M1 Max

        Christoph HartC 1 Reply Last reply Reply Quote 1
        • Christoph HartC
          Christoph Hart @orange
          last edited by

          @orange yeah but 0.5 seconds is way too long for oversample delay which is usually a couple of samples. There must be something else.

          LindonL 1 Reply Last reply Reply Quote 0
          • LindonL
            Lindon @Christoph Hart
            last edited by Lindon

            @Christoph-Hart said in Adventures in Script Node - performance...I think:

            @orange yeah but 0.5 seconds is way too long for oversample delay which is usually a couple of samples. There must be something else.

            Yeah @orange - I'm not using oversampling, and the dry/wet mix is inside the plug so that wouldnt be it....

            @Christoph-Hart I've tried turning all teh other FX off and it seems its my Dist module, as theres no delay when I turn it off and use only one of the other FX...

            Here's my XML

            <?xml version="1.0" encoding="UTF-8"?>
            
            <Network ID="DistNode" Version="0.0.0" AllowCompilation="1">
              <Node FactoryPath="container.chain" ID="DistNode" Bypassed="0" ShowParameters="1">
                <Nodes>
                  <Node ID="xfader" FactoryPath="control.xfader" Bypassed="0">
                    <Properties>
                      <Property ID="NumParameters" Value="2"/>
                      <Property ID="Mode" Value="Switch"/>
                    </Properties>
                    <SwitchTargets>
                      <SwitchTarget>
                        <Connections>
                          <Connection NodeId="FuzzPre" ParameterId="Bypassed"/>
                          <Connection NodeId="FuzzPost" ParameterId="Bypassed"/>
                        </Connections>
                      </SwitchTarget>
                      <SwitchTarget>
                        <Connections>
                          <Connection NodeId="OverDrivePre" ParameterId="Bypassed"/>
                          <Connection NodeId="OverDrivePost" ParameterId="Bypassed"/>
                        </Connections>
                      </SwitchTarget>
                    </SwitchTargets>
                    <Parameters>
                      <Parameter MinValue="0.0" MaxValue="1.0" ID="Value" Automated="1"/>
                    </Parameters>
                  </Node>
                  <Node ID="FuzzPre" FactoryPath="container.soft_bypass" Bypassed="0">
                    <Nodes>
                      <Node ID="svf_eq" FactoryPath="filters.svf_eq" Bypassed="0">
                        <ComplexData>
                          <Filters>
                            <Filter Index="-1" EmbeddedData=""/>
                          </Filters>
                        </ComplexData>
                        <Parameters>
                          <Parameter MinValue="20.0" MaxValue="20000.0" SkewFactor="0.2299045622348785"
                                     ID="Frequency" Automated="1"/>
                          <Parameter MinValue="0.300000011920929" MaxValue="9.899999618530273" SkewFactor="0.2647178173065186"
                                     ID="Q" Value="1.0"/>
                          <Parameter MinValue="-18.0" MaxValue="18.0" ID="Gain" Value="12.384"/>
                          <Parameter MinValue="0.0" MaxValue="1.0" SkewFactor="0.3010300099849701"
                                     ID="Smoothing" Value="0.009999999776482582"/>
                          <Parameter MinValue="0.0" MaxValue="4.0" StepSize="1.0" ID="Mode" Value="2.0"/>
                          <Parameter MinValue="0.0" MaxValue="1.0" StepSize="1.0" ID="Enabled" Value="1.0"/>
                        </Parameters>
                      </Node>
                    </Nodes>
                    <Parameters/>
                  </Node>
                  <Node ID="OverDrivePre" FactoryPath="container.soft_bypass" Bypassed="0">
                    <Nodes>
                      <Node ID="svf_eq1" FactoryPath="filters.svf_eq" Bypassed="0">
                        <ComplexData>
                          <Filters>
                            <Filter Index="-1" EmbeddedData=""/>
                          </Filters>
                        </ComplexData>
                        <Parameters>
                          <Parameter MinValue="20.0" MaxValue="20000.0" SkewFactor="0.2299045622348785"
                                     ID="Frequency" Automated="1"/>
                          <Parameter MinValue="0.300000011920929" MaxValue="9.899999618530273" SkewFactor="0.2647178173065186"
                                     ID="Q" Value="1.0"/>
                          <Parameter MinValue="-18.0" MaxValue="18.0" ID="Gain" Value="-13.104"/>
                          <Parameter MinValue="0.0" MaxValue="1.0" SkewFactor="0.3010300099849701"
                                     ID="Smoothing" Value="0.009999999776482582"/>
                          <Parameter MinValue="0.0" MaxValue="4.0" StepSize="1.0" ID="Mode" Value="2.0"/>
                          <Parameter MinValue="0.0" MaxValue="1.0" StepSize="1.0" ID="Enabled" Value="1.0"/>
                        </Parameters>
                      </Node>
                    </Nodes>
                    <Parameters/>
                  </Node>
                  <Node ID="snex_shaper1" FactoryPath="core.snex_shaper" Bypassed="0">
                    <Properties>
                      <Property ID="ClassId" Value="ShaperCode01"/>
                    </Properties>
                    <ComplexData>
                      <Tables/>
                      <SliderPacks/>
                      <AudioFiles/>
                      <Filters/>
                      <DisplayBuffers>
                        <DisplayBuffer Index="-1" EmbeddedData=""/>
                      </DisplayBuffers>
                    </ComplexData>
                    <Parameters>
                      <Parameter MinValue="0.2" MaxValue="5.0" ID="Gain" Automated="1"/>
                      <Parameter MinValue="1.0" MaxValue="8.0" ID="Mode" Automated="1"/>
                      <Parameter MinValue="0.0" MaxValue="1.0" ID="Feedback" Automated="1"/>
                    </Parameters>
                  </Node>
                  <Node ID="FuzzPost" FactoryPath="container.soft_bypass" Bypassed="0">
                    <Nodes>
                      <Node ID="svf_eq2" FactoryPath="filters.svf_eq" Bypassed="0">
                        <ComplexData>
                          <Filters>
                            <Filter Index="-1" EmbeddedData=""/>
                          </Filters>
                        </ComplexData>
                        <Parameters>
                          <Parameter MinValue="20.0" MaxValue="20000.0" SkewFactor="0.2299045622348785"
                                     ID="Frequency" Automated="1"/>
                          <Parameter MinValue="0.300000011920929" MaxValue="9.899999618530273" SkewFactor="0.2647178173065186"
                                     ID="Q" Value="1.0"/>
                          <Parameter MinValue="-18.0" MaxValue="18.0" ID="Gain" Value="-10.512"/>
                          <Parameter MinValue="0.0" MaxValue="1.0" SkewFactor="0.3010300099849701"
                                     ID="Smoothing" Value="0.009999999776482582"/>
                          <Parameter MinValue="0.0" MaxValue="4.0" StepSize="1.0" ID="Mode" Value="2.0"/>
                          <Parameter MinValue="0.0" MaxValue="1.0" StepSize="1.0" ID="Enabled" Value="1.0"/>
                        </Parameters>
                      </Node>
                    </Nodes>
                    <Parameters/>
                  </Node>
                  <Node ID="OverDrivePost" FactoryPath="container.soft_bypass" Bypassed="0">
                    <Nodes>
                      <Node ID="svf_eq3" FactoryPath="filters.svf_eq" Bypassed="0">
                        <ComplexData>
                          <Filters>
                            <Filter Index="-1" EmbeddedData=""/>
                          </Filters>
                        </ComplexData>
                        <Parameters>
                          <Parameter MinValue="20.0" MaxValue="20000.0" SkewFactor="0.2299045622348785"
                                     ID="Frequency" Automated="1"/>
                          <Parameter MinValue="0.300000011920929" MaxValue="9.899999618530273" SkewFactor="0.2647178173065186"
                                     ID="Q" Value="1.0"/>
                          <Parameter MinValue="-18.0" MaxValue="18.0" ID="Gain" Value="13.824"/>
                          <Parameter MinValue="0.0" MaxValue="1.0" SkewFactor="0.3010300099849701"
                                     ID="Smoothing" Value="0.009999999776482582"/>
                          <Parameter MinValue="0.0" MaxValue="4.0" StepSize="1.0" ID="Mode" Value="2.0"/>
                          <Parameter MinValue="0.0" MaxValue="1.0" StepSize="1.0" ID="Enabled" Value="1.0"/>
                        </Parameters>
                      </Node>
                    </Nodes>
                    <Parameters/>
                  </Node>
                  <Node ID="gain" FactoryPath="core.gain" Bypassed="0">
                    <Parameters>
                      <Parameter MinValue="-100.0" MaxValue="24.0" StepSize="0.1000000014901161"
                                 SkewFactor="5.422270774841309" ID="Gain" Automated="1"/>
                      <Parameter MinValue="0.0" MaxValue="1000.0" StepSize="0.1000000014901161"
                                 SkewFactor="0.3010300099849701" ID="Smoothing" Value="20.0"/>
                      <Parameter MinValue="-100.0" MaxValue="0.0" StepSize="0.1000000014901161"
                                 SkewFactor="5.422270774841309" ID="ResetValue" Value="0.0"/>
                    </Parameters>
                  </Node>
                  <Node ID="limiter" FactoryPath="dynamics.limiter" Bypassed="0">
                    <ComplexData>
                      <DisplayBuffers>
                        <DisplayBuffer Index="-1"/>
                      </DisplayBuffers>
                    </ComplexData>
                    <Parameters>
                      <Parameter MinValue="-100.0" MaxValue="0.0" StepSize="0.1000000014901161"
                                 SkewFactor="5.422270774841309" ID="Threshhold" Value="-1.29999852925539"/>
                      <Parameter MinValue="0.0" MaxValue="250.0" StepSize="0.1000000014901161"
                                 SkewFactor="0.4306765496730804" ID="Attack" Value="0.0"/>
                      <Parameter MinValue="0.0" MaxValue="250.0" StepSize="0.1000000014901161"
                                 SkewFactor="0.4306765496730804" ID="Release" Value="84.90000126510859"/>
                      <Parameter MinValue="1.0" MaxValue="32.0" StepSize="0.1000000014901161"
                                 SkewFactor="0.2968033850193024" ID="Ratio" Value="1.100000001490116"/>
                    </Parameters>
                  </Node>
                </Nodes>
                <Parameters>
                  <Parameter ID="Frequency" MinValue="20.0" MaxValue="20000.0" SkewFactor="0.2299045622348785"
                             Value="761.679568885437">
                    <Connections>
                      <Connection NodeId="svf_eq" ParameterId="Frequency"/>
                      <Connection NodeId="svf_eq1" ParameterId="Frequency"/>
                      <Connection NodeId="svf_eq2" ParameterId="Frequency"/>
                      <Connection NodeId="svf_eq3" ParameterId="Frequency"/>
                    </Connections>
                  </Parameter>
                  <Parameter ID="MakeUp" MinValue="-100.0" MaxValue="24.0" StepSize="0.1000000014901161"
                             SkewFactor="5.422270774841309" Value="14.90000171214341">
                    <Connections>
                      <Connection NodeId="gain" ParameterId="Gain"/>
                    </Connections>
                  </Parameter>
                  <Parameter ID="Depth" MinValue="0.2" MaxValue="5.0" Value="4.5712">
                    <Connections>
                      <Connection NodeId="snex_shaper1" ParameterId="Gain"/>
                    </Connections>
                  </Parameter>
                  <Parameter ID="Mode" MinValue="1.0" MaxValue="8.0" StepSize="1" Value="5.0">
                    <Connections>
                      <Connection NodeId="snex_shaper1" ParameterId="Mode"/>
                    </Connections>
                  </Parameter>
                  <Parameter ID="Feedback" MinValue="0.0" MaxValue="0.8" Value="0.5312">
                    <Connections>
                      <Connection NodeId="snex_shaper1" ParameterId="Feedback"/>
                    </Connections>
                  </Parameter>
                  <Parameter ID="FuzzOverDrive" MinValue="0.0" MaxValue="1.0" StepSize="1"
                             Value="0.0">
                    <Connections>
                      <Connection NodeId="xfader" ParameterId="Value"/>
                    </Connections>
                  </Parameter>
                </Parameters>
              </Node>
            </Network>
            
            

            and the code I'm running in the SNEX shaper - where you can see I'm doing some fairly simple but "silly" stuff...it doenst matter which mode I use - they all introduce the delay...:

            template <int NumVoices> struct ShaperCode01
            {
            	SNEX_NODE(ShaperCode01);
            	float a = 0.0f;
            	float mode = 0.0f;
            	float q = 0.0f;
            	float spare = 0.0f;
            	float fback = 0.0f;
            	float fbacksig = 0.0f;
            	float tsig = 0.0f;
            	// Implement the Waveshaper here...
            	
            	float getSample(float input)
            	{
            		if(mode == 1)
            		{
            			// just abs
            			fbacksig = Math.abs(input*a)*fback;
            			tsig = Math.abs(input*a) + fbacksig;
            			tsig = tsig / (1.0+fback);
            			if(input < 0.0)
            			{
            				tsig = tsig * -1.0;
            			}
            			if(tsig > 1.0)
            			{
            				input = 0.9;
            			}else{
            				if(tsig < -1.0)
            				{
            					input = -0.9;
            				}else{
            					input = tsig;
            				};
            			};
            		};
            		if(mode == 2)
            		{
            			// attenuated sin
            			
            			
            			spare = 1.8 + (a*0.4);
            			//q = (a*a)/2;
            			//input = Math.sin(input*q);
            			q = (spare*spare)/2.0;
            			
            			fbacksig = Math.sin(input * q);
            			tsig = Math.sin(input * q) + fbacksig;
            			tsig = tsig / (1.0+fback);
            			if(tsig > 1.0)
            			{
            				input = 0.9;
            			}else{
            				if(tsig < -1.0)
            				{
            					input = -0.9;
            				}else{
            					input = tsig;
            				};
            			};
            
            		};	
            		if(mode == 3)
            		{
            			// attenuated sqr
            			spare = 1.0 + (a *0.8);
            				
            			fbacksig = Math.sqr(input*spare);
            			tsig = Math.sqr(input*spare) + fbacksig;
            			tsig = tsig / (1.0+fback);
            			if(input < 0.0)
            			{
            				tsig = tsig * -1.0;
            			}
            			if(tsig > 1.0)
            			{
            				input = 0.9;
            			}else{
            				if(tsig < -1.0)
            				{
            					input = -0.9;
            				}else{
            					input = tsig;
            				};
            			};
            			
            			
            			//input = Math.sqr(input*spare);
            			
            			
            			
            			//input = Math.sqr(input*a);
            		};	
            		if(mode == 4)
            		{
            			//attenuated sqr root	
            			spare = a * 0.6;
            			fbacksig = Math.sqrt(input*spare);
            			tsig = Math.sqrt(input*spare) + fbacksig;
            			tsig = tsig / (1.0+fback);
            			if(tsig > 1.0)
            			{
            				input = 0.9;
            			}else{
            				if(tsig < -1.0)
            				{
            					input = -0.9;
            				}else{
            					input = tsig;
            				}
            
            			}
            			
            			//input = Math.sqrt(input*spare);
            			//input = Math.sqrt(input*a);
            		};	
            		if(mode == 5)
            		{
            			//tanh		
            			fbacksig = Math.tanh(input*a);
            			tsig = Math.tanh(input*a) + fbacksig;
            			tsig = tsig / (1.0+fback);
            			if(tsig > 1.0)
            			{
            				input = 0.9;
            			}else{
            				if(tsig < -1.0)
            				{
            					input = -0.9;
            				}else{
            					input = tsig;
            				}
            			
            			}
            			
            			//input = Math.tanh(input*a);
            		};	
            		if(mode == 6)
            		{
            			//sat		
            			q = (a*0.2) + Math.tanh(input*input*input*input*input);
            			fbacksig = Math.tanh(input + q);
            			tsig = Math.tanh(input + q) + fbacksig;
            			tsig = tsig / (1.0+fback);
            			if(tsig > 1.0)
            			{
            				input = 0.9;
            			}else{
            				if(tsig < -1.0)
            				{
            					input = -0.9;
            				}else{
            					input = tsig;
            				}
            			
            			}			
            			//input = Math.tanh(input + q);
            		};
            		if(mode == 7)
            		{
            			// oversat
            
            			spare = Math.tanh(input*(1.1+ (a*0.1))*2.0);
            			fbacksig = fbacksig - Math.tanh(spare);
            			tsig = input - Math.tanh(spare) + fbacksig;
            			tsig = tsig / (1.0+fback);
            			if(tsig > 1.0)
            			{
            				input = 0.9;
            			}else{
            				if(tsig < -1.0)
            				{
            					input = -0.9;
            				}else{
            					input = tsig;
            				}
            			
            			}
            			//input = input - Math.tanh(spare); // - input;
            		};	
            		if(mode == 8)
            		{
            			// rect ifier		
            			if (input > 0.0)
            			{
            				spare = 1.0;
            			}else{
            				spare = -1.0;
            			};
            			fbacksig = input * spare;
            			if (fbacksig > 0.6)
            			{
            				q = (fbacksig - (a*0.2));
            		
            				fbacksig = (a*0.2) - q; 
            				
            				if(fbacksig < 0.0)
            				{
            					fbacksig = fbacksig * -1.0;
            				}
            			};
            			fbacksig = fbacksig * spare;
            			
            			input = input * spare;
            			if (input > 0.6)
            			{
            				q = (input - (a*0.2));
            		
            				input = (a*0.2) - q; 
            				
            				if(input < 0.0)
            				{
            					input = input * -1.0;
            				}
            			};
            			
            			input = input * spare;
            			
            			tsig = input + fbacksig;
            			tsig = tsig / (1.0+fback);
            			if(tsig > 1.0)
            			{
            				input =0.9;
            			}else{
            				if(tsig < -1.0)
            				{
            					input = -0.9;
            				}else{
            					input = tsig;
            				}
            			
            			}
            			
            		}
            
            		return input;
            	}
            	// These functions are the glue code that call the function above
            	template <typename T> void process(T& data)
            	{
            		for(auto ch: data)
            		{
            			for(auto& s: data.toChannelData(ch))
            			{
            				s = getSample(s);
            			}
            		}
            	}
            	template <typename T> void processFrame(T& data)
            	{
            		for(auto& s: data)
            			s = getSample(s);
            	}
            	void reset()
            	{
            		
            	}
            	void prepare(PrepareSpecs ps)
            	{
            		
            	}
            	
            	void setExternalData(const ExternalData& d, int index)
            	{
            	}
            	template <int P> void setParameter(double v)
            	{
            		if(P == 0)
            		{
            			a = (float)v;
            		};
            		if(P == 1)
            		{
            			mode = (float)v;
            		};
            		if(P == 2)
            		{
            			fback = (float)v;
            		};
            
            	}
            };
            

            any pointers appreciated....

            HISE Development for hire.
            www.channelrobot.com

            Christoph HartC 1 Reply Last reply Reply Quote 0
            • Christoph HartC
              Christoph Hart @Lindon
              last edited by

              Check the limiter attack time, I think if it's zero it goes into lookahead mode with a considerable delay.

              LindonL orangeO 2 Replies Last reply Reply Quote 0
              • LindonL
                Lindon @Christoph Hart
                last edited by

                @Christoph-Hart ok will do...

                HISE Development for hire.
                www.channelrobot.com

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

                  @Christoph-Hart Yes limiter's attack time causes latency since it has a lookahead mode.

                  develop Branch / XCode 13.1
                  macOS Monterey / M1 Max

                  LindonL 1 Reply Last reply Reply Quote 0
                  • LindonL
                    Lindon @orange
                    last edited by

                    @orange @Christoph-Hart

                    -- Yep that was it. Thanks to both of you.

                    LMP

                    HISE Development for hire.
                    www.channelrobot.com

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

                    48

                    Online

                    1.7k

                    Users

                    11.7k

                    Topics

                    101.8k

                    Posts