BowedString Part 1: Digital Waveguide

In this series, I will walk through the process of building a bowed string model using a digital waveguide. If you are not familiar with the technique, Julius O. Smith wrote a great book on the subject: Physical Audio Signal Processing. The particular model I will build can also be found in this book here.

Bowed string model by Julius O. Smith

Bowed string model by Julius O. Smith

One possible way to implement this model would be to implement it exactly as presented using 4 distinct delay lines. This would work quite well for a static model, but since we want to be able to change the delay lines’ lengths in real-time, we will quickly run into some issues.

To understand, let’s look at a basic delay line implementation. The canonical delay line usually consists of a circular buffer and two pointers: one for reading and one for writing. Changing the delay length is as simple as changing the read pointer’s position. This looks something like this:

A delay line. The read pointer moves to the left as the delay length is decreased and to the right as the delay length is increased.

When the length of a delay line is changed in real-time, it is called a variable delay line. It is also possible to read between two sample points by doing an interpolated read. This would make the delay line a fractional delay line. Being able to read in between samples is important as it will allow us to smoothly change the delay length in real-time.

A simple waveguide can be implemented using two delay lines, one for the right traveling wave and one for the left traveling wave.

A simple waveguide

Notice how the delay lines are going in opposite directions. Now, if we were to change the waveguide length by reducing both delay line lengths this would look like this:

Reducing the waveguide length. The red parts indicate the samples that get discarded as the delay is decreased.

If the waveguide was modeling a string, we’ve now effectively removed a bit of the right traveling signal from the right end of the string and a bit of the left traveling signal from the left end of the string. This is physically impossible and can introduce discontinuities in the signal. Instead, what we want to achieve is something like this:

A more realistic waveguide.

Notice how the size of the waveguide does not change and instead, a reflection point is introduced at some point on the string, effectively splitting the waveguide in two. This is attempting to simulate a finger pressing on the string.

On top of being able to read at an arbitrary fractional point on the delay line, we will also need to be able to write into the delay line at a fractional point. To do this, we can use an algorithm presented in Vesa Välimäki’s paper Discrete-Time Modeling of Acoustic Tubes Using Fractional Delay Filters. While Välimäki is describing a way to implement a scattering junction, we can use the same system to implement our reflection point by changing some of the coefficients. Instead of using an allpass filter to interpolate the signal I have opted to use a simple linear interpolator. Since we want to be able to vary the position of the junction in real-time, we would need to perform extra work to avoid the transient that would be introduced by using an allpass interpolation. A method to eliminate these transients is presented in this paper by Vesa Välimäki, Timo I. Laakso and Jonathan MacKenzie. A C++ implementation can be found in libdsp.

Block diagram of the scattering junction by Vesa Välimäki

Block diagram of the scattering junction by Vesa Välimäki

Block diagram of the waveguide gate. The allpass interpolators were changed to linear interpolators and the coefficients were changed to conserve energy through the system.

The resulting system is what we will now call a waveguide gate. The coefficient ‘r’ is what I will call the gate coefficient. With a value of 1, the gate is fully closed and all the energy is reflected. With a value of 0, the gate is fully open and all the energy is transmitted. With a value between 0 and 1, the gate is partially open and some of the energy is reflected and some is transmitted.

Here it is in action when the gate coefficient is set to 1:

Waveguide gate with coefficient 1. The top graph shows the left and right traveling wave separetly and the bottom graph shows the sum of the two waves.

By setting the gate coefficient to < 1, we can simulate a light press on the string which can result in harmonics based on the position of the gate:

Waveguide gate with coefficient 0.5 at the midpoint of the string. The top graph shows the left and right traveling wave separetly and the bottom graph shows the sum of the two waves.

Waveguide gate with coefficient 0.5 at the 1/4 of the string. The top graph shows the left and right traveling wave separetly and the bottom graph shows the sum of the two waves.

Here are some audio examples of the gate in action using a waveguide with 200 samples of delay and a gate positioned in the middle of the string. A triangle pluck is used to excite the string.

Gate coefficient = 0 (open string):

Gate coefficient = 1 (full press):

Gate coefficient = 0.005 (The fundamental quickly morphs into the first harmonic):