4ddcc1bCymbal simulator: shell-of-revolution modal model with a nonlinear energy cascade, numbl MATLAB reference, and interactive web appJeremy Magland 1% Render a cymbal crash with default parameters and print diagnostics.
7da0671Hammer the cymbal: hybridize near-degenerate modes, add the turbulent fluctuation about the mean cascade, and flatten the decay across the bandJeremy Magland 2% Set P.strike_count = 8 for a repeated ride figure, P.strike_r = 0.1 for the
3% bell, P.strike_velocity = 0.7 for a tap on the same instrument, or
4% P.cascade_gain = 0 to hear the plate as an exactly linear resonator. Setting
5% P.hammer_mix = 0 recovers the ideal axisymmetric plate, which is worth
6% hearing once: it is a bell, because only its lowest few nodal-diameter
7% orders can radiate at all.
4ddcc1bCymbal simulator: shell-of-revolution modal model with a nonlinear energy cascade, numbl MATLAB reference, and interactive web appJeremy Magland 8% Run with: numbl run cymbal_demo.m
10P = cymbal_defaults();
11tic;
12[y, basis, dinfo] = cymbal_render(P);
13elapsed = toc;
15fprintf('modes kept : %d up to n = %d nodal diameters (%.0f Hz to %.0f Hz)\n', ...
16 dinfo.modesKept, dinfo.maxN, basis.f(1), basis.f(end));
17fprintf('lowest : ');
18fprintf('%.0f ', basis.f(1:min(10, basis.n)));
19fprintf('Hz\n');
a136eacMake the contact point a first-class controlJeremy Magland 20fprintf('contact : r = %.1f cm (%.1f cm in from the rim, %s)', ...
21 dinfo.strikeRadiusM * 100, dinfo.strikeRimM * 100, cd_region(P, dinfo.strikeRadiusM));
22if dinfo.strikeCount > 1
23 fprintf(', alternating with r = %.1f cm (%s)', ...
24 dinfo.roll2RadiusM * 100, cd_region(P, dinfo.roll2RadiusM));
25end
26fprintf('\n');
4ddcc1bCymbal simulator: shell-of-revolution modal model with a nonlinear energy cascade, numbl MATLAB reference, and interactive web appJeremy Magland 27fprintf('strikes : %d at %.1f Hz (mean v %.2f m/s, mean contact %.0f us, peak force %.0f N)\n', ...
28 dinfo.strikeCount, P.strike_rate_hz, dinfo.meanV, dinfo.meanTauUs, dinfo.peakForceN);
29fprintf('cascade : peak w_rms %.1f um = %.2f thicknesses, %.1f%% of the injected energy left the top\n', ...
30 dinfo.peakWrmsUm, sqrt(dinfo.peakStrength), 100 * dinfo.cascadeLostJ / max(1e-30, dinfo.injectedJ));
31fprintf('peak press.: %.4f Pa (%.1f dB SPL) at %.0f cm\n', ...
32 dinfo.peakPa, dinfo.peakSplDb, dinfo.listenerDistM * 100);
33fprintf('length : %.2f s @ %d Hz\n', length(y) / P.sample_rate, P.sample_rate);
34fprintf('render time: %.2f s\n', elapsed);
35if dinfo.listenerInside
36 fprintf('WARNING : listener is at or inside the plate\n');
37end
a136eacMake the contact point a first-class controlJeremy Magland 38
39function s = cd_region(P, r)
40% Which part of the instrument a contact radius falls on.
41if r <= P.bell_radius_m
42 s = 'bell';
43elseif r >= P.radius_m - 0.045
44 s = 'edge';
45else
46 s = 'bow';
47end
48end