8d1eba7a3baf1f9295e70f95e2d756a12d90e7fa — Karl Schultheisz 2 months ago 284b066 master
Update README.md; add notes.md
2 files changed, 102 insertions(+), 8 deletions(-)

A notes.md
M README.md => README.md +14 -8
@@ 6,6 6,13 @@ the tedious and error-prone symbolic calculations involved in creating
a DSP model of an ODE.

## Status

The project is unmaintained. However, we welcome comments
and patches. Please send them to Karl Schultheisz's [public

## Features

- Support linear and nonlinear systems of ODEs

@@ 13,15 20,11 @@ a DSP model of an ODE.
- Approximate solutions of implicit equations using Newton's method
- Render finite difference equations (FDEs) to [Faust code][faust-syntax]
- Calculate stability of ODEs and FDEs at an operating point

[faust-syntax]: https://faustdoc.grame.fr/manual/syntax/

## Planned features

- Calculate stability of ODEs and FDEs at various operating conditions

## How it works

Specify your system of ODEs with a SymPy expression and select an integral

@@ 37,7 40,10 @@ terms of a finite number of iterations of Newton's method.
- [SymPy](https://www.sympy.org/en/index.html)

## Contributing
## Blog posts

- [Nonlinear DSP is good, fun, and hard](https://kdsch.org/post/nonlinear-dsp/)
- [Convert ODEs to DSP—with a tool](https://kdsch.org/post/ode2dsp/)
- [Knowledge is made in curious ways](https://kdsch.org/post/building-knowledge/)

We welcome patches. We are open to rendering to DSP languages other than
Faust, but our ability to support them is limited.

A notes.md => notes.md +88 -0
@@ 0,0 1,88 @@
I expect some time from now, I will take a break from this project,
and a bit later, might return to it wanting to know where I left off.

The basic idea of ode2dsp is to take differential equations in state-space
form and transform them into finite difference equations, and to transform
those into DSP code in languages like Faust. The math is well-established
and other people have written about it, particularly Julius Smith of
Stanford University.

ode2dsp was created to solve specific problems I was confronting while
designing nonlinear filters. The filters I wanted to design constituted
ode2dsp's very earliest test cases. While an attempt is made to keep the
implementation generic, the sheer diversity of nonlinear systems makes
it difficult to implement ode2dsp without making certain assumptions,
not all of which are necessarily explicit. The result? Bugs, unexpected

A brief overview of the math pipeline.

1. State the ODE. It must be in state-space form, where the left-hand side
   consists of the derivative of the state variable. The state variable can
   be a vector. The algorithms deal with higher-order systems through vector

2. A discretization method transforms the ODE into an FDE. The FDE is an
   implicit equation, which means the state variable is not isolated. It's
   not possible to generate code without first solving the equation for the
   state variable.

3. The implicit FDE is solved for the state variable. Where possible, the
   components of the state variable are isolated using algebra. If a component
   cannot be isolated using algebra, an approximate solution using a numerical
   method is calculated. The numerical method introduces error which is not
   controlled. Therefore, the explicit FDE represents a system different from
   the implicit FDE. It is an approximation that can be translated into
   executable code.

In practice, while it's easy to generate code that compiles, the
resulting system might diverge, oscillate unexpectedly, or introduce
aliasing artifacts. The challenge of nonlinear DSP design is to control
these flaws.

ode2dsp can calculate stability conditions at each stage in the pipeline.
It maps nonlinear systems to linear systems by linearizing at an
operating point, which allows it to describe stability as a function
of the solution value. This is useful, because many nonlinear systems
exhibit amplitude-dependent instabilities; they only oscillate when the
solution enters a certain region, and the oscillation dampens when the
solution exits this region.

But the stability conditions tend to be complicated expressions that
yield little intuition of behavior. They tend to be useful only for
evaluating stability at specific points in the parameter space.

Even when stability conditions provide a useful prediction of instability
issues, they do not necessarily suggest a way to control them. For
artistic purposes, instability can be useful; it is simply oscillation.
But it is not useful if it causes floating-point arithmetic to diverge
to infinity. Thus, strictly local instabilities surrounded by an infinite
region of stability are the most artistically useful.

To craft islands of instability, I developed a technique I call parameter
modulation. It modifies a linear system not by adding nonlinear feedback
or inserting static nonlinearities in the signal path of a linear system,
but by making gain blocks functions of state variables. Theoretically,
this provides orthogonal control over the influence of the operating
point on the parameters. In practice, these are the best-sounding and
behaving filters I have yet produced, and their timbre is easily tuned
over a wide range. However, they still have some unwanted artifacts,
particularly increasing Q as cutoff frequency increases and aliasing

ode2dsp tends to have difficulty handling parameter-modulated ODEs. The
main hazard is Newton's method, whose uncontrolled errors may entail
unwanted instabilities. One way around this is to apply parameter
modulation _after_ solving. This requires modulation to be in terms
of delayed state variables. That delay may introduce problems of its own.
Further investigation may yield clarity.

Problems remain which I am embarassed to admit have stumped me. Filters
designed with ode2dsp tend to exhibit increasing resonance as cutoff
frequency increases, defying expectations. FDEs created using the
trapezoidal discretization have received less attention, so ode2dsp has
some bugs in handling them downsteam of discretization.

Sometimes the design feels excessively magical and overoptimized for
a single use-case.