Fb1_ODE:
Filter:
Classes (extension) | Libraries > miSCellaneous > Nonlinear

Fb1_ODE : UGen : AbstractFunction : Object
ExtensionExtension

general ordinary differential equation integrator pseudo ugen
Source: Fb1_ODE.sc

Description

Pseudo ugen for integrating / audifying ordinary (systems of) differential equations with initial values in realtime, based on the Fb1 single sample feedback class. It makes use of Fb1_ODEdef and Fb1_ODEintdef, containers for ODEs and numerical solution methods, which provide an interface for adding new ODE systems or integration methods interactively. There exists a huge number of ODE models in different areas, e.g. have a look at the SIAM publication Exploring ODEs [1], it approaches the topic from an experimental point of view, which is quite related to the demands of practical audification / synthesis / processing. And of course it's fun to define your own ODEs, see this help file and Fb1_ODEdef.

HISTORY AND CREDITS: Big credit to David Pirrò from IEM Graz for pointing me to the symplectic integration methods, which are essential for audifying ODEs, as they help to ensure numeric stability in the long run (e.g. to avoid drifts of oscillations that are mathematically expected to be regular). See the chapter on integration in his dissertation [2], pp 135-146. You might also want check David Pirròs optimized ODE compiler named Henri [3]. Big credit also to Nathaniel Virgo who brought up the buffering strategy used in Fb1, which is Fb1_ODE's working horse.

WARNING: Especially with self-defined ODEs the usage of this class is – inherently – highly experimental. Be careful with amplitudes, as always with feedback it can become loud! Sudden blowups might result form the mathematical characteristics of the ODE systems or they might come from parameter changes on which ODEs can react extremely sensitive to, they can also stem from numerical accumulation effects. It is highly recommended to take precautionary measures, e.g. by limiting/distorting operators (tanh, clip, softclip, distort) with the compose option (See Examples 5) and/or external limiting and/or using MasterFX from the JITLibExtensions quark.
NOTE: Fb1_ODE in its plain form (without tMul modulation, use of compose etc.) produces audio data as a numerical integration of an ODE initial value problem, defined by Fb1_ODEdef and a numerical procedure, defined by Fb1_ODEintdef. This of course supposes well-defined ODE systems and it should be kept in mind that the Fb1_ODE framework doesn't perform any mathematical checks regarding the principal existence and uniqueness of a solution of a given Fb1_ODEdef.
NOTE: The convenience of direct definition of the ODE relation comes with the price of a large number of UGens involved. You might want to allow a higher number of UGens with the server option numWireBufs. For a nice workflow I'd recommended to take reduced blockSizes (e.g. 1, 2, 4, 8, 16) while experimenting as compile time is shorter, but once you have finished the design of a SynthDef it might pay going back to blocksize 32 or 64 for runtime efficiency, especially if many kr UGens are involved.

   

References

  1. Trefethen, Lloyd N.; Birkisson Ásgeir; Driscoll, Tobin A. (2017): Exploring ODEs. SIAM - Society for Industrial and Applied Mathematics. Free download from: https://people.maths.ox.ac.uk/trefethen/Exploring.pdf
  2. Pirrò, David (2017). Composing Interactions. Dissertation. Institute of Electronic Music and Acoustics, University of Music and Performing Arts Graz. Free download from: https://pirro.mur.at/media/pirro_david_composing_interactions_print.pdf
  3. https://git.iem.at/davidpirro/henri

Class Methods

Fb1_ODE.new(name, argList, tMul: 1, t0, y0, intType: 'sym2', compose, composeArIn, dt0, argList0, init_intType: 'sym8', withOutScale: true, withDiffChannels: false, withTimeChannel: false, blockSize, graphOrderType: 1, leakDC: true, leakCoef: 0.995)

Creates a new Fb1_ODE ar object.

Arguments:

name

The name of the ODE defined and stored via Fb1_ODEdef. Can be one of the predefined ODEs, for which wrappers exist, or a self-defined one. Expects a Symbol.

argList

The argList to be passed to the ODE. Can contain ar or kr UGens and SequenceableCollections thereof.

tMul

Time multiplier, which determines velocity of proceeding in the dynamic system. The default value 1 means that the step delta of time equals 1 / sample duration. For getting audible oscillations you might, depending on the ODE definition, have to pass much higher values. Can also be a kr / ar UGen and might also be negative.

t0

Initial time. Expects Number. If no value is passed, the default value of the referred Fb1_ODEdef is taken, usually 0.

y0

Initial value of the ODE. Expects number or array of correct size, which is determined by the Fb1_ODEdef. If no value is passed, the default value of the referred Fb1_ODEdef is taken.

intType

Integration type. Expects one of the Symbols, for which procedures are stored with Fb1_ODEintdef. The use of symplectic procedures (with prefix 'sym') is highly recommended. Defaults to \sym2. For more accurate integration you can try symplectic procedures of higher order like \sym4, \sym8 etc. Families of integration procedures:

  • Symplectic: \sym2, \sym2_d, \sym4, \sym4_d, \sym6, \sym6_d, \sym8, \sym8_d, \sym12, \sym12_d, \sym16, \sym16_d, \sym32, \sym32_d, \sym64, \sym64_d
  • Euler: \eu, \eu_d, \eum, \eum_d, \eui, \eui_d
  • Prediction-Evaluation-Correction: \pec, \pece, \pecec, \pecece
  • Runge-Kutta: \rk3, \rk3_d, \rk3h, \rk3h_d, \rk4, \rk4_d
  • Adams-Bashforth: \ab2, \ab3, \ab4, \ab5, \ab6
  • Adams-Bashforth-Moulton: \abm21, \abm22, \abm32, \abm33, \abm43, \abm44, \abm54, \abm55, \abm65, \abm66
compose

Operator(s) / Function(s) to be applied to the system value on a per-sample base. This of course blurs the numeric procedure but can be used for containing or in a creative way. Can be an operator Symbol, a Function or an arbitrarily mixed SequenceableCollection thereof. The Functions are in any case expected to take an array (the system state) as first argument. If only one Function is given it must output an array of same (system) size. Within a SequenceableCollection a Function must output a value of size 0. Within a SequenceableCollection an operator Symbol is applied only to the corresponding component. A Function can optionally take a second argument which is for ar UGens passed via composeArIn.

composeArIn

ar UGen or SequenceableCollection thereof or a SequenceableCollection that can contain both. This is the way to use ar UGens within a Function passed to compose. UGens are passed to the Function's second argument.

dt0

First time delta in seconds to be used for the language-side calculation of first values of a multi-step intType procedure. This will mostly be irrelevant as (single-step) symplectic procedures are to be preferred. In case of a multi-step procedure a dt0 value will be derived from the default server's properties (sample duration * tMul).

argList0

Initial argList value(s) to be used for the language-side calculation of first values of a multi-step intType procedure. This will mostly be irrelevant as (single-step) symplectic procedures are to be preferred. If no UGens are passed to argList, values will be assumed from passed argList Numbers.

init_intType

Integration type for language-side calculation of first values of a multi-step intType procedure. This will mostly be irrelevant as (single-step) symplectic procedures are to be preferred. Defaults to \sym8.

withOutScale

Boolean. Determines if the Fb1_ODEdef's default scaling values for integration and differential signals should be applied to the output. Defaults to true.

WARNING: withOutScale does not implement a general safety net functionality, withOutScale's default value true does by no means say that output is limited. The default scaling values of predefined Fb1_ODEdefs are average assumptions and can, under different circumstances, always lead to high out levels.
withDiffChannels

Boolean. Determines if channel(s) with differential value(s) should be returned. This is only applicable with integration types with a sizeFactor == 2, which means that for every sample the values of the differential are buffered. As by default this is not the case for all predefined numeric procedures, there exist variants with appendix '_d', e.g. \sym2_d. Defaults to false.

withTimeChannel

Boolean. Determines if accumulated time is output in an additional channel.

WARNING: with constant tMul it produces an ascending DC which is not affected by leakDC if this is set to true. Might especially be of interest if time is modulated. Defaults to false.
blockSize

Integer, this should be the server blockSize. If no Integer is passed, the current default server's blockSize is assumed (in contrast to Fb1). So explicitely passing a blockSize should only be necessary in special cases, e.g. when compiling before booting. However for a pleasant workflow for ar usage it's recommended to use Fb1_ODE with a reduced server blockSize in order to reduce SynthDef compile time.

graphOrderType

0, 1 or 2. Determines if topological order of generated BufRd and BufWr instances in the SynthDef graph is forced by additional UGens.

  • Type 0: forced graph order is turned off.
  • Type 1 (default): graph order is forced by summation and <!.
  • Type 2: graph order is forced by <! operators only.

Default 1 is recommended, but with CPU-intense SynthDefs it might be worth trying it with the value 0. This saves a lot of UGens though there might be exceptional cases with different results. Type 2 can shorten the SynthDef compilation time for certain graphs with a large number of UGens, which can be lengthy with type 1. However, CPU usage doesn't directly correspond to the number of UGens.

leakDC

Boolean. Determines if a LeakDC is applied to the output (except time channel). Defaults to true.

leakCoef

Number, the leakDC coefficient. Defaults to 0.995.

Fb1_ODE.ar(name, argList, tMul: 1, t0, y0, intType: 'sym2', compose, composeArIn, dt0, argList0, init_intType: 'sym8', withOutScale: true, withDiffChannels: false, withTimeChannel: false, blockSize, graphOrderType: 1, leakDC: true, leakCoef: 0.995)

Equivalent to *new.

Fb1_ODE.kr(name, argList, tMul: 1, t0, y0, intType: 'sym4', compose, dt0, argList0, init_intType: 'sym8', withOutScale: true, withDiffChannels: false, withTimeChannel: false, graphOrderType: 1, leakDC: true, leakCoef: 0.995)

Creates a new Fb1_ODE kr object.

Arguments:

name

The name of the ODE defined and stored via Fb1_ODEdef. Can be one of the predefined ODEs, for which wrappers exist, or a self-defined one. Expects a Symbol.

argList

The argList to be passed to the ODE. Can contain kr UGens and SequenceableCollections thereof.

tMul

Time multiplier, which determines velocity of proceeding in the dynamic system. The default value 1 means that the step delta of time equals 1 / control duration. For getting audible oscillations you might, depending on the ODE definition, have to pass much higher values. Can also be a kr UGen and might also be negative.

t0

Initial time. Expects Number. If no value is passed, the default value of the referred Fb1_ODEdef is taken, usually 0.

y0

Initial value of the ODE. Expects number or array of correct size, which is determined by the Fb1_ODEdef. If no value is passed, the default value of the referred Fb1_ODEdef is taken.

intType

Integration type. Expects one of the Symbols, for which procedures are stored with Fb1_ODEintdef. The use of symplectic procedures (with prefix 'sym') is highly recommended. Defaults to \sym4. For more accurate integration you can try symplectic procedures of higher order like \sym4, \sym8 etc. Families of integration procedures:

  • Symplectic: \sym2, \sym2_d, \sym4, \sym4_d, \sym6, \sym6_d, \sym8, \sym8_d, \sym12, \sym12_d, \sym16, \sym16_d, \sym32, \sym32_d, \sym64, \sym64_d
  • Euler: \eu, \eu_d, \eum, \eum_d, \eui, \eui_d
  • Prediction-Evaluation-Correction: \pec, \pece, \pecec, \pecece
  • Runge-Kutta: \rk3, \rk3_d, \rk3h, \rk3h_d, \rk4, \rk4_d
  • Adams-Bashforth: \ab2, \ab3, \ab4, \ab5, \ab6
  • Adams-Bashforth-Moulton: \abm21, \abm22, \abm32, \abm33, \abm43, \abm44, \abm54, \abm55, \abm65, \abm66
compose

Operator(s) / Function(s) to be applied to the system value on a per-sample base. This of course blurs the numeric procedure but can be used for containing or in a creative way. Can be an operator Symbol, a Function or an arbitrarily mixed SequenceableCollection thereof. The Functions are in any case expected to take an array (the system state) as first argument. If only one Function is given it must output an array of same (system) size. Within a SequenceableCollection a Function must output a value of size 0. Within a SequenceableCollection an operator Symbol is applied only to the corresponding component.

dt0

First time delta in seconds to be used for the language-side calculation of first values of a multi-step intType procedure. This will mostly be irrelevant as (single-step) symplectic procedures are to be preferred. In case of a multi-step procedure a dt0 value will be derived from the default server's properties (control duration * tMul).

argList0

Initial argList value(s) to be used for the language-side calculation of first values of a multi-step intType procedure. This will mostly be irrelevant as (single-step) symplectic procedures are to be preferred. If no UGens are passed to argList, values will be assumed from passed argList Numbers.

init_intType

Integration type for language-side calculation of first values of a multi-step intType procedure. This will mostly be irrelevant as (single-step) symplectic procedures are to be preferred. Defaults to \sym8.

withOutScale

Boolean. Determines if the Fb1_ODEdef's default scaling values for integration and differential signals should be applied to the output. Defaults to true.

WARNING: withOutScale does not implement a general safety net functionality, withOutScale's default value true does by no means say that output is limited. The default scaling values of predefined Fb1_ODEdefs are average assumptions and can, under different circumstances, always lead to high out levels.
withDiffChannels

Boolean. Determines if channel(s) with differential value(s) should be returned. This is only applicable with integration types with a sizeFactor == 2, which means that for every sample the values of the differential are buffered. As by default this is not the case for all predefined numeric procedures, there exist variants with appendix '_d', e.g. \sym2_d. Defaults to false.

withTimeChannel

Boolean. Determines if accumulated time is output in an additional channel.

WARNING: with constant tMul it produces an ascending DC which is not affected by leakDC if this is set to true. Might especially be of interest if time is modulated. Defaults to false.
graphOrderType

0, 1 or 2. Determines if topological order of generated BufRd and BufWr instances in the SynthDef graph is forced by additional UGens.

  • Type 0: forced graph order is turned off.
  • Type 1 (default): graph order is forced by summation and <!.
  • Type 2: graph order is forced by <! operators only.

Default 1 is recommended, but with CPU-intense SynthDefs it might be worth trying it with the value 0. This saves a lot of UGens though there might be exceptional cases with different results. Type 2 can shorten the SynthDef compilation time for certain graphs with a large number of UGens, which can be lengthy with type 1. However, CPU usage doesn't directly correspond to the number of UGens.

leakDC

Boolean. Determines if a LeakDC is applied to the output (except time channel). Defaults to true.

leakCoef

Number, the leakDC coefficient. Defaults to 0.995.

Inherited class methods

Instance Methods

Inherited instance methods

Examples 1: Proof of concept

 

Ex. 1a: The harmonic oscillator

 

Ex. 1b: Extending the harmonic oscillator to the mass-spring-damper model

 

Ex. 2: Numeric integration type

Examples 3: Modulations

All optional arguments of the Fb1_ODE can take UGens at audio or control rate, tMul can be modulated at both rates as well.

 

Ex. 3a: Argument modulation

 

Ex. 3b: Time modulation

 

Ex. 4: Initial values

 

Examples 5: The 'compose' argument

This allows to build an additional Function into the Fb1 feedback loop. It is applied to every array of samples that is result and next input of the numeric integration procedure. Obviously then correct integration of the ODE cannot be performed anymore, but the option has still its value.

 

Ex. 5a: Handling instable systems

 

Ex. 5b: Other options of the 'compose' argument

Examples 6: Channels with additional information

 

Ex. 6a: The differential channels

 

Ex. 6b: The time channel

 

Ex. 7: The 'withOutScale' argument

Examples 8: ODEs from mechanics

 

Ex. 8a: The driven pendulum

 

Ex. 8b: The reduced two body problem

Examples 9: ODEs from population dynamics

 

Ex. 9a: The Lotka-Volterra equations

 

Ex. 9b: The Hastings-Powell equations