# Faust Autodiff: Towards Audio Domain-Specific Machine Learning

Thomas Rushton, Yann Orlarey, Romain Michon, Tanguy Risset, Stéphane Letz

<figure><img src="image_1.png" /></figure>

To cite this version:

Thomas Rushton, Yann Orlarey, Romain Michon, Tanguy Risset, Stéphane Letz. Faust Autodiff: Towards Audio Domain-Specific Machine Learning. AES 2025 - AES International Conference on Machine Learning and Artificial Intelligence for Audio, Audio Engineering Society, Sep 2025, London, United Kingdom. hal-05345098

HAL Id: hal-05345098

https://inria.hal.science/hal-05345098v1

Submitted on 6 Feb 2026

HAL is a multi-disciplinary open access
archive for the deposit and dissemination of sci-
entific research documents, whether they are pub-
lished or not. The documents may come from
teaching and research institutions in France or
abroad, or from public or private research centers.

L'archive ouverte pluridisciplinaire HAL, est
destinée au dépôt et à la diffusion de documents
scientifiques de niveau recherche, publiés ou non,
émanant des établissements d'enseignement et de
recherche français ou étrangers, des laboratoires
publics ou privés.

<figure><img src="image_2.png" /></figure>

Distributed under a Creative Commons CC BY 4.0 - Attribution - International License
# FAUST AUTODIFF: TOWARDS AUDIO DOMAIN-SPECIFIC MACHINE LEARNING

Thomas RUSHTON (thomas.rushton@inria.fr)<fnref n="1" />, Yann ORLAREY<fnref n="1" />, Romain MICHON<fnref n="1" />, Tanguy RISSET<fnref n="1" />, and Stéphane LETZ<fnref n="2" />

## ABSTRACT

Differentiable programming via automatic differentiation (AD) is the foundation for gradient-based optimisation techniques, and forms the basis for many current approaches to machine learning. Though well catered-for in general-purpose programming languages, the availability of AD in a domain-specific language (DSL) could offer novel perspectives on optimisation problems in the field of audio. We present a general scheme for differentiable programming in the Faust programming language, a high-performance DSL tailored to audio synthesis and signal processing. Faust's rich ecosystem, coupled with a comprehensive AD implementation, can provide support for audio optimisation and machine learning applications on a multitude of platforms, from FPGAs to the web.

## 1. INTRODUCTION

Gradient-based methods are ubiquitous in tackling a wide variety of mathematical optimisation and machine learning problems, and the availability of such methods hinges on the possibility of computing the derivatives of computer programs. In the field of machine learning in particular, automatic differentiation (AD) [2] has emerged as the dominant differentiable programming paradigm. In AD, the primitive operations of a programming language are defined differentiably, thus programs composed from those operations are in turn differentiable end-to-end with respect to their input variables. In a gradient-based optimisation scenario, the partial derivatives of an algorithm terminating in a loss function constitute a gradient vector, which can be backpropagated, causing the algorithm's input variables, weights in a neural network perhaps, to approach optimal values. Techniques of this sort employed in the audio domain are referred to as *differentiable digital signal processing* (DDSP) [3], and find applications from least mean squares (LMS) filtering [4] to differentiable audio synthesis [5].

Building on previous work on AD in the Faust programming language [6], here we exploit Faust's pattern matching abstraction to extend to a more general AD syntax,

demonstrating that arbitrary compositions of signal processing blocks can be differentiated, and to higher order if desired. With AD in Faust, it is possible to create differentiable infinite impulse response (IIR) filters and neural network building blocks. Our work provides the basis for an audio-focused ecosystem for the development of solutions to problems based on machine learning.

## 2. THE FAUST PROGRAMMING LANGUAGE

Faust is a functional paradigm, domain specific language for audio digital signal processing [7]. It is built atop a domain-agnostic *block diagram algebra* [8,9] that describes primitive operations connected into graphs via a selection of *composition operators* (see Figure 1). A textual language, Faust can, for example, define a diagram consisting of two blocks, A and B, composed in sequence, with code of the form

process = A : B;

Listing 1: Sequential composition of two Faust blocks.

Conceptually, a given block diagram, *D*, may undergo semantic transformation, notated $[\cdot]$, into a signal processor [9]:<fnref n="1" />

$$ 
\begin{align} 
[\cdot] : \mathbb{S}^n &\to \mathbb{S}^m \nonumber \\ 
[\cdot](s_1, \dots, s_n) &\to (y_1, \dots, y_m) \tag{1} \\ 
y(t) &= f(s(t)), \nonumber 
\end{align} 
$$

where $\mathbb{S}$ is the set of all signals, $f$ is a mathematical function analogous to the primitive operations and compositions of $D$, and $t$ is time. The signal processor receives a vector of input signals, $s$, and produces a vector of output signals, $y$.

### 2.1 The Faust Ecosystem

Faust is a highly optimised, compiled language [10], with C++ as its default compilation target. One of the great strengths of the Faust ecosystem is its *write once, run anywhere* model; a variety of additional backends are supported, including LLVM [11], WebAssembly [12], and Rust [13], plus numerous software and hardware platforms. Faust code can be compiled for use in VST plugins [14], for embedded systems [15] and FPGAs [16]; it is used by artists

<footnote n="1">¹Inria, INSA Lyon, CITI, EA3720, 69621 Villeurbanne, France</footnote>

<footnote n="2">²Grame CNCM, CITI, EA3720, 69621 Villeurbanne, France</footnote>

<footnote>Copyright: © 2025. This is an open-access article distributed under the terms of the Creative Commons Attribution 4.0 International License (CC BY 4.0), which permits unrestricted use, distribution, and reproduction in any medium, provided the original author and source are credited. It was originally published in the Audio Engineering Society E-Library [1].</footnote>

<footnote n="1">¹ The colon symbol on the first line of Equation (1) introduces the type of the signal processor $[\cdot]D$ and is not to be confused with Faust's sequential composition operator.</footnote>
<figure><img src="image_3.png" /><figcaption>Figure 1: Example compositions of Faust blocks.</figcaption></figure>

and digital luthiers [17–19], and features sophisticated libraries for wave digital filter modelling [20] and physical modelling synthesis [21, 22], amongst others.

## 2.2 Differentiable Programming in Faust

In light of Faust’s versatility, efficiency, and strengths as a DSL in tackling audio problems it may come as little surprise that it has been turned to machine learning problems in the audio domain, via DawDreamer [23], which uses a Python backend to transpile Faust code for gradient-based optimisation with the JAX Python library. JAX, and other well-known machine learning frameworks, such as TensorFlow and PyTorch, enable gradient-based optimisation approaches by way of automatic differentiation, a technique for computing the numerical outputs of both a mathematical expression (or, more commonly, a computer program) and its derivatives in parallel [2, 24, 25].

Differentiable programming [26] is, broadly speaking, the creation of computer programs using primitive operations which are themselves differentiable; a computer program consisting of differentiable primitives may be differentiated automatically, producing the desired primal and gradient numerical outputs for use in a gradient-based optimisation algorithm. In this vein, a Faust-based LMS algorithm has been used for real-time acoustic control [4], though the DDSP aspect of this work was limited to the particular application. The feasibility of a more general approach to DDSP in the Faust language has been demonstrated via the implementation of forward-mode AD primitives [6].

One way of framing forward-mode AD is as an arithmetic of dual numbers [24,27] of the form $\langle u, \nabla u \rangle$, where $u$ is the aforementioned primal, and $\nabla u = [\frac{\partial u}{\partial x_1} \dots \frac{\partial u}{\partial x_N}]^T$, the gradient of $u$, its partial derivatives with respect to a vector of $N$ input variables, $x$. A dual number can be passed into a forward-mode differentiable primitive, $f$, yielding an output dual number, $\langle f(u), \nabla u f'(u) \rangle$. Faust is a language of signals and signal processors; consequently we will refer to the dual signal, $\langle s, \nabla s \rangle \in \mathbb{S}_d$, where $\mathbb{S}_d = \mathbb{S}^{N+1}$. The signal processor based on the differentiated block diagram $D$ has the following semantic scheme:

$$ \begin{aligned} \Delta_N[\mathbb{D}] : \mathbb{S}_d^M &\rightarrow \mathbb{S}_d^P \\ \Delta_N[\mathbb{D}] &\left( \langle s_1, \nabla s_1 \rangle, \dots, \langle s_M, \nabla s_M \rangle \right) \\ &\rightarrow (\langle y_1, \nabla y_1 \rangle, \dots, \langle y_P, \nabla y_P \rangle) \\ \langle \mathbf{y}(t), \mathbf{J}_\mathbf{y}(t) \rangle &= \langle f(\mathbf{s}(t)), \mathbf{J}_f(t) \mathbf{J}_\mathbf{s}(t) \rangle, \end{aligned} \quad (2) $$

where $\Delta_N[\cdot]$ indicates derivative transformation with respect to $N$ input variables, and $\mathbf{J}_\mathbf{y}, \mathbf{J}_f = \nabla f(\mathbf{s})$, and $\mathbf{J}_\mathbf{s} = \nabla s$ are, respectively, $P \times N, P \times M$ and $M \times N$ Jacobian matrices.

AD primitives have been demonstrated in Faust using the language’s pattern matching abstraction [6]. Pattern matching is a source code transformation mechanism, and exploits the fact that a Faust function may receive, as a parameter, a programmatic expression. For example, a differentiable addition primitive, acting on dual signals $\langle s_1, \nabla s_1 \rangle, \langle s_2, \nabla s_2 \rangle$, may be created by defining a function that accepts the addition operator as a parameter, and produces, in parallel, the addition primitive’s primal output, $s_1+s_2$, and its gradients, $\nabla s_1+\nabla s_2$. A dual-signal addition

```hsl
env (vars) = environment {
    // ...
    diff (+) = interleave (vars.N + 1, 2)
        : +, par (i, vars.N, +);
    // ...
};
```

Listing 2: Definition of a differentiable addition primitive in the Faust language.

operator implementation is given in Listing 2; the operator is defined within a differentiable environment, which receives and enumerates a vector of input variables, ensuring that all derivative transformations produce the appropriate number of partial derivatives; the function interleave delivers the primal signals and their respective partial derivatives to the addition operations in the appropriate order: $s_1, s_2, \frac{\partial s_1}{\partial x_1}, \frac{\partial s_2}{\partial x_1}, \dots, \frac{\partial s_1}{\partial x_N}, \frac{\partial s_2}{\partial x_N}$, as illustrated in Figure 2. One addition primitive is created for the primal operation, and a further $N$ additions in parallel, which we can notate $\|_{l=1}^N +$, for computing partial derivatives.

## 2.3 Motivation

Considering the plethora of existing approaches to DDSP [3], why pursue an implementation in Faust? The availability of the Faust-to-JAX transcompiler would appear to obviate such an initiative, but for the fact that the AD transformations facilitated by JAX lie the wrong side of the transpilation step. A comprehensive differentiable programming framework in the Faust language itself would allow DDSP algorithms to be written once, and run anywhere. A domain-specific approach to audio-oriented machine learning is not without precedent; indeed, a suite of ML-centric
<figure><img src="image_4.png" /><figcaption>Figure 2: Differentiable addition primitive applied to dual signals $\langle s_1, \nabla s_1 \rangle$, $\langle s_2, \nabla s_2 \rangle$; implicit input variable vector x of length N = 2.</figcaption></figure>

tools, with an emphasis on human computer interaction, exists for the ChucK programming language [28]. Faust, however, with its functional approach, and cross-platform capabilities, offers a unique point of vantage.

The observation has been made that the relative structures of neural networks and digital filters bear striking similarities [29]. There is a very real sense in which machine learning problems, and gradient-based optimisation problems in general, are signal processing problems. The possibility of turning a signal processing DSL to problems of this sort paves the way to novel approaches and fresh perspectives on this dynamic field of research.

### 3. A GENERAL SCHEME FOR DIFFERENTIATING FAUST PROGRAMS

In Faust's block diagram algebra, a given block diagram, D, is comprised of a primitive block, P, or the composition of two block diagrams via a composition operator according to the syntactic rule

$$D = P | (D_1 \diamond D_2), \quad (13)$$

where $\diamond$ is one of the sequential (.), parallel (.), split (<>), merge (<>), or recursive (~) composition operators. The creation of differentiable Faust programs has been shown to be possible by *undifferentiated* composition of differentiated primitive blocks [6], the syntactic rule being

$$\Delta_N[\!\!\left[\!\!D\!\!\right]\!\!] = \Delta_N[\!\!\left[P_1\!\right]\!\!] \diamond \Delta_N[\!\!\left[P_2\!\right]\!\!] \diamond \cdots \diamond \Delta_N[\!\!\left[P_n\!\right]\!\!] . \quad (14)$$

While effective in facilitating differentiable programming, this syntax imposed an undesirable verbosity. Our preferred syntactic rule should be a direct transformation of Equation (13):

$$\Delta_N[\!\!\left[\!\!D\!\!\right]\!\!] = \Delta_N[\!\!\left[P\!\right]\!\!] | \Delta_N[\!\!\left[D_1 \diamond D_2\!\right]\!\!] . \quad (15)$$

The ideal outcome is to permit the programmer to subject an entire Faust program to automatic differentiation in a single expression, minimising the amount of re-writing required to ready their code for transformation. This would render a great proportion of existing Faust code differentiable, and,

in doing so, prepare that wealth of material for prospective use in optimisation problems, and machine learning applications. In order to achieve such an outcome, it is necessary to provide differentiation rules for the five composition operators, taking into account their arithmetical significance, if any, in a block diagram to which they contribute.

#### 3.1 Differentiable Block-Diagram Compositions

To define syntactic rules for the derivatives of Faust's composition operators entails analysing them as if they were themselves primitive blocks. To do this, we must consider them in tandem with rules for some of Faust's fundamental primitive operators; these will assist us in achieving differentiable compositions.

##### 3.1.1 Identity Primitive

Faust's identity function, notated $_\cdot$, describes a connection between two blocks. Treated as a signal processor, it adheres to the following semantic scheme [9]:

$$\begin{align} \left[\!\!\left[\!\!\right]\!\!\right] : \mathcal{S} \to \mathcal{S} \tag{16} \\ \left[\!\!\left[\!\!\right]\!\!\right](s) \to (s) . \nonumber \end{align}$$

It receives one signal and returns that same signal unchanged, analogous to multiplying it by a constant signal of value 1. In dual signal arithmetic, this is

$$\langle s, \nabla s \rangle \langle 1, \nabla 1 \rangle = \langle 1s, 1\nabla s + s\nabla 1 \rangle = \langle s, \nabla s \rangle, \quad (17)$$

and the semantic rule for the derivative of the identity function is thus

$$\begin{align} \Delta_N[\!\!\left[\!\!\right]\!\!] : \mathcal{S}_d \to \mathcal{S}_d \tag{18} \\ \Delta_N[\!\!\left[\!\!\right]](\langle s, \nabla s \rangle) \to (\langle s, \nabla s \rangle) . \nonumber \end{align}$$

The dual signal $\langle s, \nabla s \rangle$ being composed of one primal signal and N gradient signals, we can further state that

$$\Delta_N[\!\!\left[\!\!\right]\!\!] = \left\|_{l=1}^{N+1} \right. . \quad (19)$$

##### 3.1.2 Parallel Composition

Blocks composed in parallel (see Figure 1a) do not influence one-another, arithmetically-speaking. The outputs of the program A, B, y₁, ..., y₀A and y₀A+1, ..., y₀A+oB, are essentially the outputs of separate block diagrams; thus $\Delta_N[\!\!\left[\!\!A, B\!\!\right]\!\!] = \Delta_N[\!\!\left[\!\!A\!\!\right]\!\!]$, $\Delta_N[\!\!\left[\!\!B\!\!\right]\!\!]$, and, more generally

$$\Delta_N \left[ \left\|_{l=1}^{L} D_l \right\| \right] = \left\|_{l=1}^{L} \Delta_N \left[ \left\|_{l=1}^{L} D_l \right\| \right] \right. . \quad (20)$$

##### 3.1.3 Sequential Composition

Implicit in Equations (1) and (2) are the input and output signals of the Faust block diagram, D, and the following equivalence applies:

$$D = \left\|_{l=1}^{i_D} : D \right. . \quad (21)$$

$$D = D : \left\|_{l=1}^{o_D} - \right. , \quad (22)$$

where $i_D$ and $o_D$ are, respectively, the number of input and output signals of D. Applying derivative transformation
interleave(r, c) = par(l, r * c, _)
<: par(m, r,
      par(n, c, cutpq(m, r - m - 1)))
with {
  cutpq(0, q) = -, par(l, q, !);
  cutpq(p, 0) = par(l, p, !), -;
  cutpq(p, q) =
    par(l, p, !), cutpq(0, q);
};

Listing 3: A Faust function, $\chi(r, c)$ (see Equation (9) for its mathematical definition), that interleaves $c$ groups of $r$ signals into $r$ groups of $c$ signals.

### 3.1.6 Delay Primitive

Faust provides two primitives for delaying signals; here we will focus on the mem primitive, which, when composed in sequence with a signal, applies a one-sample delay. In general, a fixed delay can be represented as the convolution of a signal, $s(x, t)$, with a time-shifted impulse [30],

$$s(x, t - \tau) = s(x, t) * h(t), \quad h(t) = \delta(t - \tau). \quad (30)$$

Taking the temporal-parametric Fourier transform of the derivative of the convolution with respect to $x$, then using the convolution and differentiation properties of the transform [30], yields

$$\mathcal{F} \left[ \frac{\partial}{\partial x} (s(x, t) * h(t)) \right] = j\omega_x S(j\omega_x, j\omega_t) H(j\omega_t) \quad (31)$$

$$= \mathcal{F} \left[ \frac{\partial}{\partial x} s(x, t) \right] \cdot \mathcal{F}[h(t)], \quad (32)$$

which demonstrates that differentiation is time-invariant, and allows us to deduce the convolution rule of differentiation — to differentiate a convolution we need only differentiate one of the functions being convolved. Applied to dual numbers,

$$\langle s, \nabla s \rangle * \langle h, \nabla h \rangle = \langle s * h, \nabla s * h \rangle, \quad (33)$$

giving us the following semantic scheme:

$$\begin{align}
\Delta_N[\mathbf{mem}] : \mathcal{S}_d \to \mathcal{S}_d \nonumber \\
\Delta_N[\mathbf{mem}](\langle s, \nabla s \rangle) \to (\langle y, \nabla y \rangle) \tag{34} \\
\langle y(t), \nabla y(t) \rangle = \langle s(t-1), \nabla s(t-1) \rangle. \nonumber
\end{align}$$

### 3.1.7 Recursive Composition

The differentiability of recursive filters is well-established [31] — in short, the derivative of a recursive expression is itself recursive. In the specific case of Faust's recursive composition operator (see Figure 1d), to establish a rule for derivative transformation we can take a similar approach to Equation (24), making $g$ an inner function that acts upon a vector of past output signals:

$$\langle \mathbf{y}(t), \mathbf{J}_{\mathbf{y}}(t) \rangle = \left\langle \frac{f(\mathbf{s}(t), g(\mathbf{y}(t-1)))}{\frac{\partial f}{\partial \mathbf{s}(t)} \mathbf{J}_{\mathbf{s}}(t) + \frac{\partial f}{\partial g(\mathbf{y}(t-1))} \mathbf{J}_{\mathbf{g}}(t-1) \mathbf{J}_{\mathbf{y}}(t-1)} \right\rangle. \quad (35)$$

In the absence of a feedforward component (notwithstanding the fact that such a system would produce constant output signals of value zero), the result simplifies to

$$\langle f(g(\mathbf{y}(t-1))), \mathbf{J}_f(t-1)\mathbf{J}_g(t-1)\mathbf{J}_y(t-1) \rangle, \quad (36)$$

which, comparing with Equation (24), tells us that recursive composition is simply sequential composition through time, and points to the implicit, and trivially-differentiable, one-sample delay introduced by Faust's recursive composition operator. We may conclude that

$$\Delta_N[\mathcal{A} \sim \mathcal{B}] = \Delta_N[\mathcal{A}] \sim \Delta_N[\mathcal{B}]. \quad (37)$$

### 3.1.8 Merge Composition

Merge composition (Figure 1e) entails summation [9], thus the addition rule of differentiation must be obeyed when merging dual signals. A merge $A :> B$, can be viewed as an interleaving of the outputs of $A$ into $i_B$ groups of $k = o_A/i_B$ signals, followed by a merging of each group into one signal path:

$$A :> B = A : \chi(i_B, k) : \left\|_{l=1}^{i_B} \left( \left\|_{m=1}^{k} \right. \right. :> \left. \left. \right)_- \right) : B. \quad (38)$$

Clearly $\Delta_N[\mathcal{A} :> B]$ cannot be defined recursively, however. Note that for $i_B = 1$ the right hand side of Equation (38) reduces to $A :> _-$, which is essentially the term in parenthesis, and can be handled thanks to the definitions in Equations (19) and (20),

$$\Delta_N[\left\|_{m=1}^{k} \right. \left. \right)_- :> \left. \left. \right)_-] = \left\|_{m=1}^{k} \Delta_N[\left. \right)_-] :> \Delta_N[\left. \right)_-] . \quad (39)$$

The order of signals is maintained, so the resulting dual signal is guaranteed to be of the desired form $\langle \sum_{m=1}^k s_m, \sum_{l=m}^k \nabla s_m \rangle$. For the full expression for differentiable merge composition, see Equation (7).

## 4. DISCUSSION

The rules for differentiating Faust's composition operators are collected in Figure 3. With the implementation of these rules via pattern matching, Faust programs can be recursively decomposed according to their composition operators, and re-composed in differentiable fashion, satisfying the syntactic rule in Equation (15). For example:

$$\begin{align}
\Delta_N[(A, C) : B] &= \Delta_N[A, C] : \Delta_N[B] \tag{40} \\
&= \Delta_N[A], \Delta_N[C] : \Delta_N[B]. \nonumber
\end{align}$$

An artificial neuron of the form $y = \sigma(\mathbf{w}\mathbf{x} + b)$, such as could be used in a binary classification problem, can be created as per Listing 4. The code describes a neuron and sigmoid activation function in primal form, in a library file, `diff.lib`; the dot function (line 14) makes use of the familiar `interleave` function to compute the dot product, `wx`; in neuron. `dsp`, differentiable weights and biases, `wb`, are created according to a network layer specification (line 27) — one pair of signals indicating one layer containing one neuron with NW weights; weights and biases are used to create a differentiable environment (d, line 28; described in
```python
1 // diff.lib
2 neuron(NINPUTS, activationFunction) =
3     WX + b : activationFunction
4 with {
5     WX = lalg dot(NINPUTS);
6     b = _;
7 };
8
9 activations = environment {
10    sigmoid = *(-1) : 1 / (1 + exp);
11 }
12
13 lalg = environment {
14    dot(N) = interleave(N, 2)
15    : par(i, N, *) :> _;
16 };
17
18 // neuron.dsp
19 NW = 3; // Number of weights.
20
21 // Send inputs, and weights/biases,
22 // to the differentiated neuron.
23 process = par(i, NW, _),
24     par(i, NW + 1, wb.var(i + 1))
25     : d.diffInN(neuron, NW)
26 with {
27     wb = weightsAndBiases((1, NW));
28     d = df.env(wb);
29     neuron = d.neuron(NW,
30                       d.activations.sigmoid);
31 };
```

<caption>Listing 4: Excerpt from a differentiable artificial neuron implementation. See Section 4 for detail.</caption>

Section 2.2 and Listing 2); the wrapper-function `diffInN` (line 25) enacts the recursive derivative transformation; its first `NW` inputs are considered input signals, `s`, the rest as input variables, `x`.

Worthy of reflection is that algorithms of this sort, consisting of differentiable primitives, plus our now-differentiable composition operators, can be automatically differentiated to arbitrary order, $\Delta_N[\Delta_N[\dots\Delta_N[1\dots1]]]$.

## 4.1 Limitations

Although the scheme presented here renders a great deal of existing Faust code differentiable, certain primitives and language constructs cannot, at present, be subjected to AD.

Faust's `route` primitive cannot be pattern-matched, which precludes the derivative transformation of arbitrary signal routing expressions based on that primitive, such as those in the `routes.lib` library.<fnref n="3" /> As described in Section 3.1.5, however, such expressions can be recreated with the identity and cut primitives; common routing tasks like interleaving can be achieved differentiably with code such as in Listing 3.

User interface primitives (sliders and buttons, for example) are matchable in principle, but in practice, `hslider("x1")`,

0, -1, 1, .01), whose parameters are a string identifier, initial value, minimum, maximum and step, must be matched verbatim; clearly, in the general case, this is not practical. The obvious derivative transformation of a user interface element is to an input variable, i.e. a parameter for optimisation such as a weight in a neural network. Input variables must be identifiable so as to create the appropriate corresponding dual signal, $\langle x_i, [0 \dots \frac{\partial x_i}{\partial x_i} \dots 0]^T \rangle$. The approach proposed is to move input variables out of the general AD transformation; a wrapper function is used to indicate the number of input signals (whose gradients are zero vectors) and input variables received by the main body of the differentiated block diagram (see Listings 4 and 5). Though imposing a certain coding convention, we consider this comparable with the particular requirements imposed by PyTorch, TensorFlow, and JAX, with their respective dedicated datatypes for learnable parameters.

Though not a frequently-employed feature of the language, unapplied lambda abstractions appear in some key definitions, the `iir` function in `filters.lib`, for example. Implemented in transposed-direct-form [32], `iir` is defined with the abstraction `ma.sub`, which accepts two arguments, `x` and `y`, and returns the result $y-x$. Attempting $\Delta_N[\text{sub}]$, the abstraction is essentially treated as a numerical constant, and given a vector of zeros as its gradient. Fortunately, constructions of this kind — in this case reversing signal order before applying some primitive operation — are effectively matters of signal-routing and, as described in Section 3.1.5, can be recreated using differentiable primitives.

## 4.2 Applications & Outlook

Despite the above limitations, and beyond the example given in Listing 4, the AD system described here can be put to practical use. A differentiable transposed-direct-form IIR filter implementation is given in Listing 5; though reliant on some careful signal routing, particularly for directing coefficients to the feedback (`fir(N)`, line 7) and feedforward (`fir(N + 1)`, line 9) portions of the filter, it overcomes the obstacles to differentiability posed by its counterpart in `filters.lib`. Structurally, it is similar to the neuron implementation in Listing 4; parameters, in this case learnable filter coefficients, are defined outside of the differentiable environment, and passed, along with an input signal, to the wrapper function `diffInN`. An expanded version of this example (plus that given in Listing 4) is available online<fnref n="4" /> and can be run in Faust's web IDE.<fnref n="5" /> Comparing, via a differentiable loss function, the output of the filter against that of an equivalent filter with fixed, *hidden* parameters, and backpropagating the resulting gradients, learnable parameters can be optimised in real time. This generalises to filters of higher order and those described by metaparameters such as cutoff frequency, and the length of multiple hidden delay lines can be found by optimisation against a differentiable FIR filterbank; these examples point the way to a variety of real-time adaptive processing applications.

<footnote n="3">³ https://github.com/grame-cncm/faustlibraries/blob/65594336a3476d9a82a4df71e88c92f3e4b94821 roules.lib</footnote>

<footnote n="4">⁴ https://codeberg.org/hatchjaw/aes-faust-ddsp</footnote>

<footnote n="5">⁵ https://faustide.grame.fr/</footnote>
1 N = 2; // filter order.
2
3 // ...Set up AD vars & environment...
4
5 // Differentiable TDF IIR filter.
6 iir = ((sub,par(l, N, _))
7 ~ (fir(N))),par(l, N + 1, _)
8 :_,par(l, N, !),par(l, N + 1, _)
9 : fir(N + 1)
10 with {
11 sub = _,_ <: !,_,-,! : -;
12 fir(n) =
13 (_ <: par(l, n, seq(m, l, mem))),
14 par(l, n, _)
15 : linalg.dot(n);
16 };
17
18 // Send a signal input, and coefficients to the differentiated filter.
19 //
20 process = _,-coeffs : d.diffInN(iir, 1)
21 with {
22     coefs = par(i, 2 * N + 1,
23                  vars.var(i + 1));
24 };

<caption>Listing 5: Excerpt from a differentiable IIR filter implementation.</caption>

Though demonstrated with *known* algorithms, in principle the above can be extended to optimisation against a target *black box* filter, granted that both target and estimate receive the same input signal. This hints, however, at another limitation of the current approach — Faust is primarily concerned with time-domain operations, thus loss is computed in the time domain on a per-sample basis (albeit with the possibility of taking a running-average of recent sample values, for example). For phase-invariant and perceptually-informed optimisation scenarios, frequency-domain loss computation is required; the recent introduction of multi-rate processing to the Faust language promises to enable spectral signal analysis. Developments of this sort will improve the feasibility of taking on larger-scale, typically deferred-time problems such neural audio synthesis. These call for generalisation to a corpus of training data (rather than optimisation to a small number of input variables); with that end in mind, the example in Listing 4 should be extended to a general neural network structure, and a supporting infrastructure created for delivering training data and capturing weights and biases for real-time inference.

## 5. CONCLUSION

In this paper we have described a general scheme for differentiating Faust programs, moving an important step toward providing the means with which to tackle audio optimisation and machine learning problems with the domain-specific and cross-platform benefits of the Faust language. A variety of time-domain, gradient-based optimisation problems can be tackled in Faust, with results produced in real-time.

Many challenges and opportunities remain as impetus for further development of the work presented here. Having only been put to informal use to-date, the proposed AD approach should be assessed for its efficacy and efficiency. Beyond the correctness of the semantic scheme, being based on forward-mode AD, which, on paper, compares unfavourably with reverse-mode in terms of computational expense, its combination with the optimisations of the Faust compiler should be explored. At the level of the Faust compiler, changes that would facilitate the transformation of elements of the language that currently elude pattern matching would be of benefit here, as would further development of Faust's adaptability to frequency domain processing.

## 6. REFERENCES

[1] T. Rushton, Y. Orlarey, R. Michon, T. Risset, and S. Letz, “Faust Autodiff: Towards Audio Domain-Specific Machine Learning,” in *Proceedings of the 2025 AES International Conference on Machine Learning and Artificial Intelligence for Audio*, London, United Kingdom, Sep. 2025.

[2] A. G. Baydin, B. A. Pearlmutter, A. A. Radul, and J. M. Siskind, “Automatic Differentiation in Machine Learning: A Survey,” *Journal of Machine Learning Research*, vol. 18, pp. 1–43, 2018.

[3] B. Hayes, J. Shier, G. Fazekas, A. McPherson, and C. Saitis, “A review of differentiable digital signal processing for music and speech synthesis,” *Frontiers in Signal Processing*, vol. 3, Jan. 2024.

[4] L. Alexandre, P. Lecomte, and M.-A. Galland, “Experimental Active Noise Control Using Faust On FPGA: Comparison Between A Multi-Point and Spherical Harmonics Method,” in *Forum Acusticum 2023 - 10th Convention of the European Acoustics Association*, Torino, Italy, Sep. 2023. [Online]. Available: https://hal.science/hal-04221590

[5] J. Engel, L. Hantrakul, C. Gu, and A. Roberts, “Differentiable Digital Signal Processing,” in *Proceedings of the Eighth International Conference on Learning Representations*, Online, 2020.

[6] T. A. Rushton, “Differentiable DSP in Faust,” in *Proceedings of the International Faust Conference (IFC-24)*, R. Michon, S. Letz, and a. F. Mulassano, Eds., Turin, Italy, Nov. 2024. [Online]. Available: https://hal.science/hal-04849619

[7] Y. Orlarey, D. Fober, and S. Letz, “FAUST: An Efficient Functional Approach to DSP Programming,” *New computational paradigms for computer music*, pp. 65–96, 2009.

[8] —, “An Algebra for Block Diagram Languages,” in *Proceedings of International Computer Music Conference*, ICMA, Ed., Gothenburg, Sweden, 2002, pp. 542–547. [Online]. Available: https://hal.science/hal-02158932
[9] —, "Syntactical and Semantical Aspects of Faust," *Soft Computing*, vol. 8, no. 9, pp. 623-632, 2004. [Online]. Available: https://hal.science/hal-02159011

[10] Y. Orlarey, S. Letz, D. Fober, and R. Michon, "A New Intermediate Representation for Compiling and Optimizing Faust Code," in *Proceedings of the 2nd International Faust Conference (IFC-20)*, Paris, France, Dec. 2020. [Online]. Available: https://hal.science/hal-03124677

[11] S. Letz, Y. Orlarey, and D. Fober, "An Overview of the FAUST Developer Ecosystem," in *Proceedings of the 1st International Faust Conference (IFC-18)*, Mainz, Germany, Jul. 2018.

[12] —, "Compiling Faust audio DSP code to WebAssembly," in *Web Audio Conference*, London, United Kingdom, Aug. 2017. [Online]. Available: https://hal.science/hal-03162898

[13] B. R. Gaster and M. Cole, "Audio Anywhere with Faust," in *Proceedings of the 2nd International Faust Conference (IFC-20)*, Paris, France, 2020.

[14] A. Albouy and S. Letz, "Faust audio DSP language for JUCE," in *Proceedings of the Linux Audio Conference*, Saint-Etienne, France, May 2017. [Online]. Available: https://hal.science/hal-02158740

[15] R. Michon, Y. Orlarey, S. Letz, D. Fober, and D. Roosenburg, "Embedded Real-Time Audio Signal Processing With Faust," in *Proceedings of the 2nd International Faust Conference (IFC-20)*, Paris, France, Dec. 2020.

[16] P. Cochard, M. Popoff, R. Michon, and T. Risset, "Programming FPGA Platforms for Real-Time Audio Signal Processing In C++," in *Proceedings of the 2024 Sound and Music Computing Conference (SMC-24)*, Porto, Portugal, Jul. 2024. [Online]. Available: https://hal.science/hal-04714563

[17] R. Michon, Y. Orlarey, S. Letz, and D. Fober, "The Faust Programming Language As a Platform for Creating Hybrid Acoustical and Digital Musical Instruments," in *Forum Acusticum 2020 Proceedings*, Lyon, France, Dec. 2020.

[18] M. Caren, R. Michon, and M. Wright, "The KeyWI: An Expressive and Accessible Electronic Wind Instrument," in *Proceedings of The International Conference on New Interfaces for Musical Expression (NIME '20)*, Birmingham, UK, Jul. 2020.

[19] M. Hansen, "Weather Organ: A Sparse Stochastic Synthesizer in Faust," in *Proceedings of the 1st International Faust Conference (IFC-18)*, Mainz, Germany, Jul. 2018.

[20] D. Roosenburg and R. Michon, "A Wave Digital Filter Modeling Library for the Faust Programming Language," in *Proceedings of the 18th Sound and Music Computing Conference*, Online, Jun. 2021.

[21] R. Russo, S. Serafin, R. Michon, Y. Orlarey, and S. Letz, "Introducing Finite Difference Schemes Synthesis in Faust: A Cellular Automata Approach," in *Proceedings of the 18th Sound and Music Computing Conference*, Online, Jun. 2021.

[22] R. Michon, J. Smith, C. Chafe, G. Wang, and M. Wright, "The Faust Physical Modeling Library: A Modular Playground for the Digital Luthier," in *Proceedings of the 1st International Faust Conference (IFC-18)*, Mainz, Germany, 2018.

[23] D. Braun, "DawDreamer: Bridging the Gap Between Digital Audio Workstations and Python Interfaces," Nov. 2021.

[24] L. B. Rall, "The Arithmetic of Differentiation," *Mathematics Magazine*, vol. 59, no. 5, pp. 275-282, Dec. 1986.

[25] D. Harrison, "A Brief Introduction to Automatic Differentiation for Machine Learning," Oct. 2021.

[26] F. Wang, D. Zheng, J. Decker, X. Wu, G. M. Esser-tel, and T. Rompf, "Demystifying differentiable programming: Shift/reset the penultimate backpropagator," *Proceedings of the ACM on Programming Languages*, vol. 3, no. ICFP, pp. 1-31, Jul. 2019.

[27] W. Yu and M. Blair, "DNAD, a simple tool for automatic differentiation of Fortran codes using dual numbers," *Computer Physics Communications*, vol. 184, no. 5, pp. 1446-1452, May 2013.

[28] Y. Li and G. Wang, "ChAI => Interactive AI Tools in ChucK," in *The International Conference on New Interfaces for Musical Expression (NIME '24)*, Utrecht, The Netherlands, Sep. 2024.

[29] B. Kuznetsov, J. D. Parker, and F. Esqueda, "Differentiable IIR filters for machine learning applications," in *Proceedings of the 23rd International Conference on Digital Audio Effects (DAFx-20)*, Vienna, Austria, 2020.

[30] J. H. McClellan, R. W. Schafer, and M. A. Yoder, *Signal Processing First*, international ed. Pearson, 2003.

[31] J. J. Shynk, "Adaptive IIR filtering," *IEEE ASSP Magazine*, vol. 6, no. 2, pp. 4-21, Apr. 1989.

[32] J. O. Smith, *Introduction to Digital Filters: With Audio Applications*. W3K Publishing, 2008.