Book: The Art of VA Filter Design 2.1.2

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

Post

Ameyah wrote: Sat Jun 26, 2021 10:06 am To the diagrams, i am putting my own notes together, is this plain tikz or did you use some extra latex package? (i tried blox and i can not put the label y(n) to the right as intented by DSP diagrams.)
The block diagrams are xypic graph.

Post

I started looking at this book recently and I have a linear 2-pole allpass cascade with some shelf filters on the feedback path which is a good start for a phaser.

I have a mental block on how to proceed with the nonlinearities. The intent is to place some subtle nonlinearity (F(x)) on the feedback path after the gain.

The first two doubts are that the book is using as an example placing the f(x)/tanh nonlinearity after the negative feedback point junction, in series before the filter:

Code: Select all

         ________  __________
      u |        | |        |
x ------|  f(x)  |-| G*_x+S |------ y
   |-   |________| |________|     |
   |            ________          |
   |           |        |         |
   ------------|  * k   |----------
               |________|      

Code: Select all

u = x - k*(Gf(u)+S)
So for example the approximate method of the Secant line (attributed to Mystran, page.192) it says to draw a line from 0,0 to u[n-1], tanh(u[n-1]) and use that for linearization. I guess this leaves the next equation (being u1 u[n-1]):

Code: Select all

u = x - k*(G*u*tanh(u1)/u1)+S)
Is this right? What is u[n-1], the value guessed for the previous iteration or "u" computed taking in account the previous filter input and output (u = x - k*y)?

Then coming back to placing the nonlinearity on the feedback path, so the filter is linear without feedback (k = 0):

Code: Select all

        _________
      u|        |
x -----| G*_x+S |-------------- y
   |-  |________|             |
   |    ________    ________  |
   |   |        |  |        | |
   ----|  f(x)  |--|  * k   |--
       |________|  |________|    
So the equation for u becomes:

Code: Select all

u = x - f(k*(Gu+S))
So if using the secant again this would leave:

Code: Select all

u = x - u*tanh(k*(Gu1+S1))/k*(Gu1+S1)  
If I were to make the same question as above. In addition to the previous iteration "u" (U[n-1]), now the previous state is needed too. Where would that come from?
Last edited by rafa1981 on Sun Aug 28, 2022 8:47 am, edited 1 time in total.

Post

Mystran's method is basically, and in its simplest form, "replace a non-linearity by a factor F which is based on the result of the computation of the previous sample"

So for

y[n] = g * ( something( x[n] - y[n] ) ) + s[n]

you substitute "something" with F

y[n] = g * ( F[n] * ( x[n] - y[n] ) ) + s[n]

as F is a simple float variable, the above equation is linear and can be solved.

Once done, you calculate F for the next step as

F[n+1] = something( x[n] - y[n] )/( x[n] - y[n] )

Post

OK, so if I understand correctly, I have one state called "f", initialized on construction to 1. Then for each iteration:

-First I proceed to calculate the new guessed input (u) by using the "f" state/value I have prepared. So for the case with the nonlinearity just before the negative feedback junction which has its full formula as:

Code: Select all

u = x - u*tanh(k*(Gu1+S1))/k*(Gu1+S1)
I calculate "u" (which is the input guess that will be sent coming into the cascade, the one that makes each filter to update its states) as:

Code: Select all

u = x - u*f
-Then just before running the cascade (N * 2-pole allpasses + 2 * shelves) I compute the equivalent G and S (for the whole linear cascade) following the same procedure as described in the book for the linear case. Then I use the G and S variables to prepare "f" for the next round. So the "u" used on this stage/next formula is the one calculated just on the paragraph above (the one that is going to be entered into the cascade) instead of being taken from running the system (which was my doubt):

Code: Select all

f = tanh (kGu + S) /kGu + S 
If so it seems easy enough. I for some reason I have a much easier time to understand programs than the math descriptions.

To understand Fixed-point iteration (the easiest one illustrating the concept of iterative solvers) from Wikipedia or the book left more questions in my head than to search for "Fixed-point iteration python" on Google. I hope this to change in the future.

I plan to use a pretty soft nonlinearity: x / sqrt(n*x^2 +1), let's see if I don't need to go iterative.

Thanks a lot!

EDIT: now thinking about it, it seems that on this topology and using this solving method the states are also packed on "f", so there is so much packed on the previous "f" state that this can hardly be called a zero delay feedback filter. Probably the sigmoid would be better placed after the feedback junction but made softer, so having the y-axis limit around 2-3. I'll see tomorrow when I try...
Last edited by rafa1981 on Sun Aug 28, 2022 7:30 am, edited 1 time in total.

Post

Urs wrote: Sat Aug 27, 2022 7:18 pm Mystran's method is basically, and in its simplest form, "replace a non-linearity by a factor F which is based on the result of the computation of the previous sample"
I would actually recommend an alternative strategy: for each new sample, solve once with the factors from the previous sample, then update those factors based on the result, then solve again for the actual values you use for output and to update state.

If you allow for one sample of latency (not in the feedback loop, but overall) then you can reorder computations for something like LU so that even if you solve twice, you only need to do the LU factorization once (though whether it's profitable depends on the sparsity of the system).

Post

mystran wrote: Sat Aug 27, 2022 9:34 pm I would actually recommend an alternative strategy: for each new sample, solve once with the factors from the previous sample, then update those factors based on the result, then solve again for the actual values you use for output and to update state.
Hehehe, hence "simplest form".

I do the same, but then IIRC I average the resulting values between first pass and second pass, then update the state. That's what I think is close to Heun's method. I.e. if first pass overshoots, second pass will undershoot and vice versa.

Post

Thanks again! It seems to be working OK for intended the purpose, which is to tame the phaser resonances at high feedback ratios.

JSFX code just for the feedback loop below.

in = input, k = feedback ratio, h = sigmoid hardness, G_S_ptr = a memory address containing the G and S values of the instant response of each filter black box (explained in the book) interleaved, n_elems = number of black boxes on the whole feedback loop.

Code: Select all

//------------------------------------------------------------------------------
// global ZDF feedback loop with "x/sqrt(x**2*h + 1)" sigmoid with variable
// hardness (h parameter) solved with 2 rounds Mystran's linearization. See Urs
// Heckmann and Mystran's comments on this thread page:
//
// https://www.kvraudio.com/forum/viewtopic.php?start=375&t=350246&sid=eb35460aab9d1bda3038aa78018b5182
//
// Topology:
//         _________
//      u |        |
// x -----| G*_x+S |-------------- y
//    |-  |________|             |
//    |    ________    ________  |
//    |   |        |  |        | |
//    ----|  f(x)  |--|  * k   |--
//        |________|  |________|
//
// where:
// u = x - linramp * k * (Gu + S)
function get_zdf_sqrt_sigmoid_before_fb_junction (in, k, h, G_S_ptr, n_elems)
  global() local (i, G, S, gv, sv, u, l_in,linramp) (
  // The ART ov VA filter design (Vadim Zabalishin) 5.3
  i = 0;
  G = 1;
  S = 0;
  loop (n_elems,
    gv = G_S_ptr[i];
    sv = G_S_ptr[i + 1];
    G *= gv;
    S *= gv;
    S += sv;
    i += 2;
  );

  // 1 st round
  u = (in - k * S * this.linramp) / (k * G * this.linramp + 1);
  l_in = k * (G * u + S);
  this.linramp = 1 / sqrt (l_in * l_in * h + 1); // sqrt_sigmoid (u) / u
  // 2 st round (compensation)
  u += (in - k * S * this.linramp) / (k * G * this.linramp + 1);
  u *= 0.5;
  l_in = k * (G * u + S);
  this.linramp = 1 / sqrt (l_in * l_in * h + 1);
  u;
);
//------------------------------------------------------------------------------
Now porting to C++, this will end up being open source when I move it from my private branches to the master one.

Post

Urs wrote: Sun Aug 28, 2022 9:31 am I do the same, but then IIRC I average the resulting values between first pass and second pass, then update the state. That's what I think is close to Heun's method. I.e. if first pass overshoots, second pass will undershoot and vice versa.
There's a few possible variations, but the main point is that solving the linear part twice (so that you can update the non-linearities before computing the actual state) gives a fairly (audibly) obvious improvement at high frequencies.

Post

Is there a practical way to have a multinotch based on 2 pole sections to have the notch placements as input parameters independently of the damping? or at least to have center frequency and width (of the comb response) and to keep the notches (not necessarily peaks) at the same location independently of the damping?

Each stage "detunes" all other stages, not a very good property to makes things easy.

The formula for the (analog) phase response (k=damping, fc=f cutoff, f=freq) seems to require numerical solutions to get fc for a given f. Another bummer:

Code: Select all

             ⎛           ⎛ 2     2⎞  ⎞
             ⎜  2⋅f⋅fc⋅k⋅⎝f  - fc ⎠  ⎟
argAP = -atan⎜───────────────────────⎟
             ⎜                      2⎟
             ⎜ 2   2  2   ⎛ 2     2⎞ ⎟
             ⎝f ⋅fc ⋅k  - ⎝f  - fc ⎠ ⎠
Is this a researched problem? just a bad idea?

Seems out of my league. The naive way would probably be to use notch filters, but those won't behave well on feedback I guess.

Post

Generally, notch placements are dependent on all cutoffs and dampings, therefore you'd have to solve a system of nonlinear equations to obtain cutoffs and dampings from given notch placements (although you'd still have a bunch of free variables to play with, which could be the peak positions or whatever else you see fit). Maybe with some choice of those free parameters it'd be possible to have analytic rather than numerical solutions, but I don't know what that set would be.

Not sure why you'd want to vary the damping to control the notch widths tho, if you simply intend to keep the notch positions fixed (IIUC this is what you're trying to achieve), the notch widths simply vary with the feedback amount.

Post

Yes, seems a bad idea. This was e.g to have deterministic way of placing notches (other than a notch filter of course) with different modulations.

Post

You can construct a traditional all-pass chain phaser in such a way that changing global feedback doesn't move the notches, but if you want to actually control the placement of the individual notches then you'll need to solve for them.

Post

So, there is a followup to The Art of VA Filter Design book, which is A Free Book About Math Intuition.

Historically it started as an attempt to extend the VA Filter Design book by some treatment of Fourier theory topics, but it quickly turned into a more general math text, covering a much wider range of topics. Still, the main focus audience are technical engineers and DSP engineers in particular. I'm really not sure where to announce it and would be grateful for any good suggestions. Please note that math forums would be IMHO inappropriate, as the book deviates a lot from the approach of conventional math texts and doesn't target mathematicians, but rather engineers. If you feel the book is valuable enough, announcements about this book in other forums are of course highly welcome.

The chapters which are of particular interest to DSP engineers, could be the one on the Fourier theory, as well as the one about exponentials (for those who'd like to deepen their understanding of differential equations and state-space form).

NB. Despite talking about intuition, the book is not an easy read and is somewhat hardcode. But it's supposed to make things a lot easier afterwards.

Best regads,
Z1202

PS. I'm not sure if the discussion about the second book, if any emerges, would be considered on-topic enough to qualify for the KVR DSP forum, therefore I didn't dare to create a dedicated thread. Maybe if we want to discuss this further, to avoid polluting the current thread we could create a thread in the OffTopic KVR forum? Or, it would be nice to get a statement from a moderator of the DSP forum, whether this is on-topic enough, and we could create a parallel thread in the DSP forum.

Post

Z1202 wrote: Wed Dec 13, 2023 9:32 pm PS. I'm not sure if the discussion about the second book, if any emerges, would be considered on-topic enough to qualify for the KVR DSP forum
Are you kidding? You are far too modest. A free book on this topic is beyond generous and pertinent as all hell to the visitors here. I'm not sure if my 50-year-old college engineering math isn't so dusty that my attempt at a go at it would be silly, but I'm intrigued beyond words. So, thank you even if I end up having to bail early on.

Post

Z1202 wrote: Wed Dec 13, 2023 9:32 pm PS. I'm not sure if the discussion about the second book, if any emerges, would be considered on-topic enough to qualify for the KVR DSP forum, therefore I didn't dare to create a dedicated thread. Maybe if we want to discuss this further, to avoid polluting the current thread we could create a thread in the OffTopic KVR forum?
It seems on-topic to me at least if it's a tool or document associated with engineering and mathematics. There are likely fewer than the majority with an interest in such subjects.

I personally do not invest much effort to study mathematics and I'd likely not be anything other than a passive "take a glance at" reader if at all. Such subjects are the domain of those with even more esoteric interests and intelligence. Since audio-DSP relating to music plug-ins as we have here on the KVR forum is already an extreme example of esotericism, a book that might be overlapping another 1/2 or such of the existing group may be even more infinitesimal in nature. :wink:

It may be best to actually create another thread and link that thread from a post here.That seems as far as I'm aware the only way to work around the feature limitation on such a forum. I've much liked confusing hierarchical forums with thread branches in the past but the flat thread style seems far more within reach for the vast majority of posters.

A great feature for thread owners via the OP might be not only linking KVR product pages "associated products" but also associated threads and such. In fact, you may want to get in contact with Ben or whomever and create a KVR product page for both books if that seems appropriate? Existing product pages here at KVR seem mostly intended for plug-ins, but, they have associated downloads, forum threads and web links just as would be ideal. So even if the available categorizations are somewhat limited (no "technical document" and such?) it seems 90% of the way toward a solution already. I'd personally simply create the product pages and then query about them and associated features on the forum features threads. It's likely much easier to do things roughly at first and fix them later than to bother anyone and create feature requests and unneeded fuss.
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 Reply

Return to “DSP and Plugin Development”