Accurate analog models with low cpu

No.

Both the Steiner Parker topology and the Transistor / Diode ladder are balanced / differential, but the Steiner Parker uses physically different capacitors to achieve this. The Steiner Parker filter is a balanced / differential form of the MS-20 mk1 type Sallen Key structure, where instead of providing the cutoff signal via the base of transistors, it’s provided differentially to a series of didoes:

The Moritz filter is a 3 pole extension of the regular 2 pole Steiner Parker filter, so let’s just call it a 3 pole Steiner Parker and leave it there, since this isn’t worth discussing further.

1 Like

Also in these sorts of structures when you have opposite polarity pn-junctions meeting you get a sinh(x) type non-linearity, which modulates the cutoff frequency upwards with increasing audio input amplitude, vs the regular long tail pair which modulates the frequency downwards:

Upwards is the direction of Nyquist, ie: danger.

1 Like

OK, just trying to learn. Here’s an explanation, that I’m trying to follow along. https://www.reddit.com/r/synthdiy/comments/m1614h/comment/gqbwf9n/?utm_source=reddit&utm_medium=web2x&context=3

1 Like

The explanation linked there is fine, it’s basically all the stuff I’ve already said. The Moritz filter is a 3 pole Steiner Parker structure, not a ladder.

Great, reassuringly I came to a similar conclusion whilst working on this: spiceworld - VCF: Part 3 - Diode Ladders (again forgive terminology, take it as read that I understand that it shouldn’t be called diode ladder). Although inputs should be dcblock(-vin/101), as the “diode string” needs much lower voltages.

I really like this idea, I’ll experiment and report back. My current solver substitutes as it goes so it’s hard to see these relationships, but if subsquent voltages are expressed in terms of previous ones then it would be clear (e.g. how it looks doing a Gaussian eliminiation solve by hand). Maybe there are also some tricks to re-order remaining pieces to preserve sparsity too.

I think is called Block Lower Triangular (BLT). What we do in System Modeler is to sort and simplify the blocks so we end up with a matrix where all the elements are below the diagonal (see the screenshot I attached before of the Equation Browser). Each block can be a single equation or a system of linear on nonlinear equations. Solving the complete system is done by executing block by block in order. When there is a linear or nonlinear block, the block is solved and execution continues. This approach has the advantage that instead of solving a large linear (or nonlinear) system of equations, we solve a bunch of small blocks. For each nonlinear block, there is a method called “Tearing” that is used to simplify solving them.

2 Likes

@hemmer @andy-cytomic

This chat makes me want to de-dust my old circuit simulator and improve it my using more symbolic processing.

4 Likes

Thanks for letting us know some terminology to look into. Do most of the operations on the matrix, for example the tearing, occur symbolically?

Definitely! I pretty much have all the “dumb” lines of gaussian elimination or LU decomp, and then brute force the symbolic simplification of those by pulling out whatever is pre-computable or common expressions as early as possible. It results in very lean code without any branches, and the compiler can really get to work crunching on all the parallel evaluation of expressions since they are all just one after the other inside the inner loop.

Yes, most of the operations are done symbolically (transformation into BLT form and Tearing). Some operations are not, like solving of linear systems (unless they are easy to solve symbolically). The main reason for not solving symbolically those linear systems is because doing it could slowdown the compilation process. Solving them numerically (at run-time) is fast enough. When solving nonlinear systems we do symbolic transformation (when possible), stuff like calculating symbolic Jacobians and CSE.

1 Like

There are some simplifications that we let to C++ compiler because we know that they are performed. For example, the C++ compiler does (to some capacity) CSE, branch removal, extraction of constant expressions out of loops, etc.

In my Vult language compiler I have some basic features for pre-calculation of expressions https://vult-dsp.github.io/vult/blog/tables/

In short, it is possible to create (at compile-time) 1D lookup tables out of functions. I have not implemented support for 2D tables yet.