```

```

### Church bell

A church bell in C.

```// A simple bell sound

// Partial frequencies of the bell
// in semitones relative to middle C
var partials = [-12,0,3,7,12,16.5,17,19,20.8,23,24.5,26,26.5,26.25,27.5,28.25,29,30,30.8];

const recurrentSine = synth.def(class {
constructor(options) {
const freq = midi_to_hz(options.note);
const omega = 2 * Math.PI * freq;
const gamma = 7/options.duration; // --> 60 dB decay in "duration"
const T = ditty.dt;
this.c1 = 2 * Math.exp(-gamma * T) * Math.cos(omega * T);
this.c2 = Math.exp(-2 * gamma * T);
// Initial conditions:
//      s[-1] = exp(γT) sin(-ωT),
//      s[0] = 0,
this.s_nm1 = Math.exp(gamma*T) * Math.sin(-omega*T);
this.s_n = 0;
}
process(phase,env,tick,options) {
const s_np1 = this.c1 * this.s_n - this.c2 * this.s_nm1;
this.s_nm1 = this.s_n;
this.s_n = s_np1;
return s_np1;
}
}, {env:one, duration:3, amp:0.1});

// Add a delayline for a slight Doppler/chorus effect due to the bell's side-to-side motion

class Delayline {
constructor(n) {
this.n = ~~n;
this.p = 0;
this.lastOut = 0;
this.data = new Float32Array(n);
}
clock(input) {
this.lastOut = this.data[this.p];
this.data[this.p] = input;
if(++this.p >= this.n) {
this.p = 0;
}
}
tap(offset) {
var x = this.p - offset - 1;
x %= this.n;
if(x < 0) {
x += this.n;
}
let ix = Math.floor(x), fx = x%1;
return (1-fx) * this.data[ix] + fx * this.data[(ix+1)%this.n];
}
}

// A variable delay
const oscDelay = filter.def(class {
constructor(options) {
this.n = Math.floor(options.maxDelay / ditty.dt);
this.dline = new Delayline(this.n);
this.phase = options.initPhase;
}

process(input, options) {
this.phase += 6.28 * options.lfoHz * ditty.dt;
let x = 0.5 + 0.4 * Math.cos(this.phase); // current delay
x *= this.n; // current delay in samples

this.dline.clock(input[0]);
let sig = this.dline.tap(x);

return [sig,sig];
}
}, { maxDelay: 6e-3, initPhase: 0, lfoHz: 0.3});

loop((i) => {
if(i==0) {
sleep(1);
}
if(i < 10) {
for(let j=0; j<partials.length; j++) {
let r = Math.random();
let a0 = 0.1 * 2**(-0.6*partials[j]/12);
recurrentSine.play(69+partials[j], {duration:a0*100, curve:-10, amp:(t)=>a0*Math.cos(t+6.3*r)});
}
}
sleep(5 + 0.3*Math.random());
}).connect(oscDelay.create());```