```

```

### Variable stiffness

Synthesizing a plucked string instrument sound, with variable stiffness.
Can generate sounds ranging from guitar strings to bells and metal bars.

```// A string/bell/bar with variable stiffness.
// ===========================================
//
// This code synthesizes metallic sounds based on the vibrational modes of a prestressed beam.
// It can generate sounds ranging from guitar strings to bells and metal bars.
//
// It uses an efficient recurrence formula to compute the sinusoidal modes
// using only two multiplications per time step.
// https://dittytoy.net/ditty/59300f01a0
//
// The modal frequencies, amplitudes and decay speeds are assumed to have
// a simplified dependence on the mode number;
// possible extensions of the code could improve on this.
//
// Feel free to reuse and customize this, and make music with it!
//
// ===========================================

// Set input parameters for the physical model
// Relative stiffness of the string, ranging from 0 to 1, 0 being an ideal string, and 1 an ideal beam.
input.stiffness = 0.5;
// Position of hammer impact/plucking along string length
input.hitPos = 0.21;
// Cutoff frequency of the impact
input.cutoff = 400; // min=100, max=3000, step=1

ditty.bpm = 60;

const stiffString = synth.def(class {
constructor(o) {
const freq = midi_to_hz(o.note);
const omega_1 = 2 * Math.PI * freq; // Fundamental frequency in radians per second
const omega_max = 2 * Math.PI * 20000; // Maximal frequency in radians per second
const omega_cutoff = 2*Math.PI*o.cutoff; // Cutoff frequency in radians per second
const T = ditty.dt;

let omega_n = omega_1;
this.c1 = [];
this.c2 = [];
this.s_nm1 = [];
this.s_n = [];
this.n_modes = 0;
for(let n=1; omega_n < omega_max; n++) {

// This is where the magic happens!
// We set here the frequency, amplitude and decay speed of each mode.

// Compute frequency of the nth mode
omega_n = omega_1 * Math.sqrt((1 - o.stiffness) * n**2 + o.stiffness * n**4);
// Compute initial amplitude of the nth mode based on hit position and cutoff frequency
let amp_n = Math.sin(n*Math.PI*o.hitPos) * (Math.min(1, omega_cutoff/omega_n));
// Compute damping coefficient for the nth mode based on duration and frequency
let gamma_n = 7/o.duration * (omega_n/omega_1)**0.5;

// Compute time stepping coefficients for the nth mode
this.c1.push(2 * Math.exp(-gamma_n * T) * Math.cos(omega_n * T));
this.c2.push(Math.exp(-2 * gamma_n * T));
// Set initial conditions for the nth mode:
//      s[-1] = exp(γT) sin(-ωT),
//      s = 0,
this.s_nm1.push(amp_n * Math.exp(gamma_n*T) * Math.sin(-omega_n*T));
this.s_n.push(0);
this.n_modes++;
}
}
// Process one sample of audio for the string model
process(p,e,t,o) {
let sig = 0;
// Update each mode and sum them up
for(let n=0; n<this.n_modes; n++) {
const s_np1 = this.c1[n] * this.s_n[n] - this.c2[n] * this.s_nm1[n];
this.s_nm1[n] = this.s_n[n];
this.s_n[n] = s_np1;
sig += s_np1;
}
return sig;
}
}, {env:one, hitPos:0.21, stiffness:0.5, cutoff:800, duration:5, amp:0.1});

loop( () => {
stiffString.play(c4, {stiffness: input.stiffness**4, hitPos: input.hitPos, cutoff:()=>input.cutoff});
sleep(1);
});
```