Cheap non-linear zero-delay filters

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

aciddose wrote:Ideally if you're modelling a common diode clamp you'll want a high-pass filter (single capacitor) leading into a resistor and diode pair. There are various ways to model this, all of them are horrifyingly complicated and expensive.
I did already a diode clip model, but I think this softclip should also be ok:

Code: Select all

function clamp(x) local(x2 y sg)
(
  sg = sign(x);
  x = abs(x);
  x2 = x - 0.6; 
  x <= 0.6 ? y = x : y = x2/3/(1/3+x2)+0.6 ; 
  y * sg; 
);
Is the highpass for stability or simply to make the model more accurate to the hardware?

Post

It's because of the dependency between the capacitor and the clamp model (because clamp is based actually on the intensity and not the voltage).
What you have is a waveshaper, which gives a symmetric output, but the real circuit would not.

Post

From my limited understanding in solving ultra simplistic diode-equations, diodes seem to have a much bigger linear region compared to tanh, doing it the 'proper' way with LambertW is horribly expensive, but if you think of each diode (in this instance) as simply a rectifier - there are some options, my preferred method(which I used in a ringmodulator):

Code: Select all

 float smoothABS ( float x, const float y) // y controls 'smoothness' usually between 0.002 -> 0.04
{
return (sqrtf((x * x)  + y)) - sqrtf(y);
}

float smoothclip (float x, const float a, const float b) // assuming symmetrical clipping
{
  float  x1 = smoothABS (x-a);
  float  x2 = smoothABS (x-b);
   x = x1 + (a+b);
   x = x - x2;
   x = x * 0.5;
   return (x);
}
Actually haven't thrown this into a filter yet, but will have to soon, working on a phaser with diode clipping in the feedback path and tanh messes with the notch depth of the phaser too much.

Regards
Andrew

Post

Something like cosine interpolation between two linear sections gives a good result too. Ideally the cosine can be replaced with a parabola for efficiency and very little harm in terms of spectrum.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Btw, has anyone tried mystran's method with 32-bit floats? Any caveats? I recently got Newton-Raphson to work with 32-bit floats but it required a few tweaks to get it right.

In case anyone wonders why- well it's slightly faster and can double the throughput in a suitable architecture.

Richard
Synapse Audio Software - www.synapse-audio.com

Post

Richard_Synapse wrote:Btw, has anyone tried mystran's method with 32-bit floats? Any caveats? I recently got Newton-Raphson to work with 32-bit floats but it required a few tweaks to get it right.

In case anyone wonders why- well it's slightly faster and can double the throughput in a suitable architecture.

Richard
It depends on the model. Once you go over the top with Resonance, like factor 10 or so instead of 4, and once you drive with an input of +30dB whatsoever, it's really hard to let Newton converge (in 32 bit float) and to keep this method stable (I think the output gain goes up a fair bit). Newton's method also depends on the quality of the tanh approximation and the derivative thereof, e.g. sometimes it's faster to use a weaker approximation at the expense of an extra iteration.

I had to run a 1-pole lowpass filter with Newton solver in double precision for an envelope generator with 20+ seconds Decay (arguably, using a non-linear filter for an envelope is Korinthenkackerei for lack of better word in English)

Post

Richard_Synapse wrote:Btw, has anyone tried mystran's method with 32-bit floats? Any caveats? I recently got Newton-Raphson to work with 32-bit floats but it required a few tweaks to get it right.

In case anyone wonders why- well it's slightly faster and can double the throughput in a suitable architecture.

Richard
I recommend using state space for 32-bit floats, the method Mystran has posted is nodal. The state space solution requires slightly more operations, but you get improved numerical performance with low cutoffs.
The Glue, The Drop, The Scream - www.cytomic.com

Post

I just came in to say that using this method with the Heun-like predictor-corrector method described in the first post performs amazingly well. I did a blind test on my current algorithm and had a hard time telling the difference in extreme settings (at 8x oversampling).
andy-cytomic wrote:I recommend using state space for 32-bit floats, the method Mystran has posted is nodal. The state space solution requires slightly more operations, but you get improved numerical performance with low cutoffs.
Is that the delta calculation for the states you've been describing in conjunction with sin-based coefficients?

Post

Urs wrote:I just came in to say that using this method with the Heun-like predictor-corrector method described in the first post performs amazingly well. I did a blind test on my current algorithm and had a hard time telling the difference in extreme settings (at 8x oversampling).
Cool, so you run a correction step afterwards? I have a few filter models around where NR does not seem to work right (or converges slowly), should give it a try :)

Richard
Synapse Audio Software - www.synapse-audio.com

Post

Richard_Synapse wrote:
Urs wrote:I just came in to say that using this method with the Heun-like predictor-corrector method described in the first post performs amazingly well. I did a blind test on my current algorithm and had a hard time telling the difference in extreme settings (at 8x oversampling).
Cool, so you run a correction step afterwards? I have a few filter models around where NR does not seem to work right (or converges slowly), should give it a try :)

Richard
Yep, here's what Mystran wrote at the bottom of the first post:
mystran wrote:Anyway, if you're NOT happy with the results (remember we're only first order as far as the non-linearities go), we can treat the calculated value as a prediction, and apply a correction step. Sensible approach would be a variation of Heun's method take the new state (and x[n+0.5]; you need one step lookahead) and recalculate the "transconductances" then redo the linear solver, then average the resulting state with the original prediction (and likewise for outputs). Since the error of the "correction" step should be opposite to the error of the "prediction" step, they should mostly cancel. As far as I can tell, this is sufficient to make it a true second-order method (don't feel like doing formal error analysis, sorry).
In the lingo of the example I posted in my blog:

Code: Select all

float onePoleLowpass::tickHeunishPivotal( float inSample )
{
	runOneStep( inSample, Pivotal, State ); // 1st pass on State ("z^-0.5")
	float VoutTmp = Vout;
	runOneStep( inSample, Pivotal, PreviousVout ); // 2nd pass on result of 1st pass
	Vout = 0.5f * (Vout + VoutTmp);
	updateState();
	return Vout;	
}
It isn't quite Heun I guess, but like Heun it uses the previous result to create an initial guess, then use the guess to create an implicit result, then middle the two. I still update the state using the trapezoidal rule.

I'm not sure if proceeding the input by half a sample is an improvement, I'll check that out later maybe.

Post

Urs wrote:I just came in to say that using this method with the Heun-like predictor-corrector method described in the first post performs amazingly well. I did a blind test on my current algorithm and had a hard time telling the difference in extreme settings (at 8x oversampling).
andy-cytomic wrote:I recommend using state space for 32-bit floats, the method Mystran has posted is nodal. The state space solution requires slightly more operations, but you get improved numerical performance with low cutoffs.
Is that the delta calculation for the states you've been describing in conjunction with sin-based coefficients?
Yes, you should end up with a trapezoidal state update:

iceq += 2*gc*vc

PS: using all sine based coefficients adds another level of numerical accuracy to the filter, but you don't need to do that for state space representations, just using the regular tan pre-warping is fine

PPS: the full state space representation involves four matrices A, B, C, D, and x(t) and u(t) as state and input vectors. Aaron from iZotope has written a great paper of the state space SVF here: http://www.dafx14.fau.de/papers/dafx14_ ... s_for_.pdf

PPPS: after having just re-read Aaron's paper it looks like the state space representation is orthogonal to the integration type, as he mentions he uses TDFII where other state space people use DF1. TDFII gives you state += 2*gc*vc, which works out best in my experience, and conceptually is elegant since you are directly integrating the voltage over the capacitor to update the state.
The Glue, The Drop, The Scream - www.cytomic.com

Post

Thanks Andy!

I read your papers a few weeks ago and at first I didn't catch the drift until I realised that the sin calculation is not directly linked to the delta update. I'll check it out - a numerically more accurate method should converge faster.

Post

Urs: I'm not sure it will help with non-linear convergence, but in the linear case it reduces distortion, and also has more accurate effective cutoff and damping.

I've read through Aaron's State Space linear TDFII SVF paper and have written a technical paper with my workings. I solved the system slightly differently from how how Aaron did, and then also show how to use a simple substitution into the regular differential equation formulation to get the same results without having to go through the state space matrix setup:

www.cytomic.com/files/dsp/state-space-linear-tr-svf.pdf
The Glue, The Drop, The Scream - www.cytomic.com

Post

andy-cytomic wrote:Urs: I'm not sure it will help with non-linear convergence, but in the linear case it reduces distortion, and also has more accurate effective cutoff and damping.
In my experiments vectorial Newton Raphson solvers converge faster the more accurate the methods. For example, it helps to use a more accurate tanh approximation if one uses 1-tanh^2(x) as the derivative. Likewise, pivoting helps when using LU decomposition to solve for the matrix representation of the residual term. Alternatively, when solving the matrix as a linear system it helps to solve for each variable and calculate the result independently instead of solving for just one variable and substituting into the remaining terms.

Each of these steps which make the calculation more accurate, reduces the average number of iterations required by a few percent. Whether or not it's faster is a different story since the steps each add computation per each iteration. One needs to make a case-by-case decision as to what's best.

Hence I'd presume that numerical accuracy in the computation itself may help to reduce CPU as well.
I've read through Aaron's State Space linear TDFII SVF paper and have written a technical paper with my workings. I solved the system slightly differently from how how Aaron did, and then also show how to use a simple substitution into the regular differential equation formulation to get the same results without having to go through the state space matrix setup:

http://www.cytomic.com/files/dsp/state- ... tr-svf.pdf
Thanks again!

You might need to remove "forumation" from your spell checker and add "formulation" instead. It was used consistently though :)

Post

Urs wrote:...
...through the state space matrix setup:

http://www.cytomic.com/files/dsp/state- ... tr-svf.pdf
Thanks again!

You might need to remove "forumation" from your spell checker and add "formulation" instead. It was used consistently though :)
Thanks for spotting this, my touch typing fingers sometimes invent their own spelling :) I've now run a spellchecker on it, and corrected a couple of other spelling mistakes as well.
The Glue, The Drop, The Scream - www.cytomic.com

Post Reply

Return to “DSP and Plugin Development”