# Physical Modeling: Waveguides - Implementation

import numpy as np
from   numpy import linspace, sin, zeros
from   math import pi
%matplotlib notebook
import matplotlib.pyplot as plt
from   tikzplotlib import save as tikz_save

from   IPython.display import display, Markdown, clear_output
import IPython.display as ipd
import ipywidgets as widgets
from   ipywidgets import *

fs          = 48000

###################################################################
# function for plucking the string

def pluck(L,P):

x_L = np.zeros(L);
x_R = np.zeros(L);

x_L[1:P] = np.linspace(0,1,P-1)
x_R[1:P] = np.linspace(0,1,P-1)

x_L[P:L-1] = np.linspace(1,0,L-P-1)
x_R[P:L-1] = np.linspace(1,0,L-P-1)

return x_L, x_R

###################################################################
# function: - get the next output sample
#           - shift all buffers

def next_step(x_L, x_R, filt, g, pick):

# delay line outputs
l_out = x_L[0]
r_out = x_R[len(x_R)-1]

# filter output
f_out = sum(filt)/len(filt)

# shift all arrays
x_L   = np.roll(x_L,-1)
x_R   = np.roll(x_R,1)
filt  = np.roll(filt,1)

# insert output values
x_L[len(x_L)-1] = -f_out
x_R[0]          = -l_out * g
filt[0]         = r_out

out =  x_L[pick] + x_L[pick]

return x_L, x_R, filt, out

###################################################################

# length of the delay line:
L = 300
# feedback gain:
g = 0.95
# pluck position:
pluck_pos = 3
# pickup position:
pick = 5
# filter length:
N = 20

###################################################################
# the update function offers control over all parameters
# - wait for the process to be finished
# - it can take a couple of seconds until the new sound is ready

def update(L     = widgets.IntSlider(min = 100, max= 500, step=1, value=300, continuous_update=False),
g     = widgets.FloatSlider(min = 0.5, max= 1, step=0.01, value=0.95, continuous_update=False),
pluck_pos = widgets.IntSlider(min = 0, max= 99, step=1, value=3, continuous_update=False),
pick_pos  = widgets.IntSlider(min = 0, max= 99, step=1, value=5, continuous_update=False),
N     = widgets.IntSlider(min = 1, max= 50, step=1, value=20, continuous_update=False)):

x_L, x_R = pluck(L,pluck_pos)

y = np.array([])

# the filter is a simple moving average
filt = np.zeros(N)

for idx in range(2*fs):

x_L, x_R, filt, out = next_step(x_L, x_R, filt, g, pick_pos)
y = np.append(y,out)

ipd.display(ipd.Audio(y, rate=fs))

interact(update);

interactive(children=(IntSlider(value=300, continuous_update=False, description='L', max=500, min=100), FloatS…


## References

• Vesa Välimäki. Discrete-time modeling of acoustic tubes using fractional delay filters. Helsinki University of Technology, 1995.
[BibTeX▼]
• Gijs de Bruin and Maarten van Walstijn. Physical models of wind instruments: A generalized excitation coupled with a modular tube simulation platform*. Journal of New Music Research, 24(2):148–163, 1995.
[BibTeX▼]
• Matti Karjalainen, Vesa Välimäki, and Zoltán Jánosy. Towards High-Quality Sound Synthesis of the Guitar and String Instruments. In Computer Music Association, 56–63. 1993.
[BibTeX▼]
• Julius O Smith. Physical modeling using digital waveguides. Computer music journal, 16(4):74–91, 1992.
[BibTeX▼]
• Lejaren Hiller and Pierre Ruiz. Synthesizing musical sounds by solving the wave equation for vibrating objects: part 1. Journal of the Audio Engineering Society, 19(6):462–470, 1971.
[BibTeX▼]
• Lejaren Hiller and Pierre Ruiz. Synthesizing musical sounds by solving the wave equation for vibrating objects: part 2. Journal of the Audio Engineering Society, 19(7):542–551, 1971.
[BibTeX▼]

• Contents © Henrik von Coler 2020 - Contact