/ simulated_instruments / cymbal2
Sign in
simulated_instruments / cymbal2
cymbal2 / matlab / cymbal2_output.m
67 lines · 1.6 KBCodeBlameHistory
1793cecTime-domain nonlinear shell cymbal after Samejima (2021)Jeremy Magland 1function [y, peakAccel] = cymbal2_output(P, acc)
2% CYMBAL2_OUTPUT Output conditioning: DC blocker on the raw pickup
3% acceleration, Kaiser-windowed-sinc anti-alias decimation from the
4% simulation rate to the output rate, tail fade, and normalization. Same
5% structure as the sibling instruments' output stages.
7peakAccel = max(abs(acc));
8R = P.oversample;
9T = length(acc);
11% One-pole DC blocker (the pickup is an acceleration, but the contact
12% leaves a small quasi-static offset while the washer relaxes)
13fc = 15.0;
14a1 = exp(-2 * pi * fc / (P.sample_rate * R));
15p = zeros(1, T);
16xp = 0; yp = 0;
17for k = 1:T
18 yv = acc(k) - xp + a1 * yp;
19 xp = acc(k);
20 yp = yv;
21 p(k) = yv;
22end
24if R > 1
25 taps = 12 * R + 1;
26 M2 = (taps - 1) / 2;
27 fcNorm = 0.45 / R;
28 m = (0:taps - 1) - M2;
29 hh = sin(2 * pi * fcNorm * m) ./ (pi * m);
30 hh(M2 + 1) = 2 * fcNorm;
31 r = m / M2;
32 beta = 8;
33 hh = hh .* (c2_i0(beta * sqrt(max(0, 1 - r.^2))) / c2_i0(beta));
34 hh = hh / sum(hh);
35 pf = conv(p, hh);
36 outLen = floor(T / R);
37 y = reshape(pf((0:outLen - 1) * R + M2 + 1), 1, outLen);
38else
39 y = p;
40end
42% Squared fade on the tail
43fade = min(2048, floor(length(y) / 8));
44if fade > 1
45 y(end - fade + 1:end) = y(end - fade + 1:end) .* linspace(1, 0, fade).^2;
46end
48if P.normalize ~= 0
49 pk = max(abs(y));
50 if pk > 0
51 y = y / pk * 10^(P.peak_dbfs / 20);
52 end
53else
54 y = y / P.full_scale_accel;
55end
56end
58function v = c2_i0(x)
59% Modified Bessel function of the first kind, order zero (series)
60v = ones(size(x));
61term = ones(size(x));
62hx = x / 2;
63for k = 1:40
64 term = term .* (hx / k).^2;
65 v = v + term;
66end
67end
↑↓ move↵openescclose