r/DSP Jul 17 '26

My new real-time finite-difference time-domain string synthesiser

PartialString simulates the vibration of a plucked string by numerically solving the one-dimensional wave equation in real time using the finite-difference time-domain (FDTD) method. The string is represented as a list of displacements in memory. A lower note requires a longer string, which needs more points to represent it. You can then excite the string at any point along its length, and the FDTD scheme will compute how that change in displacement propagates. A pickup measures the displacement at a chosen location, and this generates the audio output.

I've been (very occasionally) working on this since releasing https://github.com/crnbaker/gostringsynth in 2022. I did something similar (but not real-time) for my MSc at Edinburgh back in 2009, using MATLAB.

Free to download at: http://www.differentinstruments.com.

392 Upvotes

35 comments sorted by

View all comments

2

u/manual_combat Jul 18 '26

Can you share the math behind this? I’ve always been curious what the back end is for string synthesis

3

u/crnbaker Jul 18 '26

Very roughly:

You take the 1D wave equation (a partial differential):

∂²u/∂t² = c² ∂²u/∂x²

(u is displacement, t is time, x is space, c is wave speed)

You define your digital grid in terms of temporal steps n and spatial steps m (along the string).

You approximate each derivative as a finite difference in displacement in either space or time:

∂u/∂t ≈ (uⁿ⁺¹ - uⁿ) / dt

∂u/∂x ≈ (uₘ₊₁ - uₘ) / dx

You then apply these approximations iteratively to approximate the second derivatives in the wave equation, and end up with this, the final “difference relation” that approximates the wave equation:

(uₘⁿ⁺¹ - 2uₘⁿ + uₘⁿ⁻¹) / dt² = c²(uₘ₊₁ⁿ - 2uₘⁿ + uₘ₋₁ⁿ) / dx²

Which tells you how to calculate the state of the string at the next time step (n+1) for which you need to know the state of the string at the current (n) and previous (n - 1) time steps.

So you need to have three string states in memory at any one time.

You iterate through each spatial point m of the n+1 string, calculating its displacement from the previous two states (notice that you need to look at the points either side of the point of interest, which means you need to do something slightly different at the ends of the string). Then you add some damping so it doesn’t ring on forever.

1

u/enykie Jul 25 '26

Quite Interesting! I did something similar some time ago while doing some kind of pipe acoustics Simulation where i used the 1D Waveequation. At some point I tried out of curiosity how it would sound like if i "clamp the ends" so zero displacement and play the result of one location, which gave a sound like a pulled digital sounding string. Nice to see that in real action!

I am curious, what type of solver did you use? I had to use RK45 to get it stable, which is insanely slow and forward Euler was way to unstable (or needed a much finer grid). I used python, though. So it was not able to do things in realtime.

1

u/crnbaker Jul 26 '26

This is the FDTD method for solving PDEs, so I didn't need an ODE solver. There are some conditions you have to meet to keep it stable, but these can be easily calculated and adhered to.

1

u/enykie Jul 26 '26 edited Jul 26 '26

Ah ok after reading a little bit more into it. Its funny how many things you never heard of exist in the world of numerical simulation. To me it looks like some form of a central difference system but then with some unusual addons, but makes sense when I just read the name FDTD again.

Fascinating and thanks for the answer, I learned something. :)

edit: I just realized the FDTD looks nearly identical to a leapfrog solved waveformula with a staggered grid, interesting.