5623b11Recorder simulator: MATLAB jet-drive model and interactive web appJeremy Magland 1function [y, basis, dinfo] = recorder_render(P)
2% RECORDER_RENDER Full render: notes -> basis + jet -> radiate -> output.
3% Convenience composition of the stage functions; the web app calls the
4% stages separately so it can cache intermediates (the bore basis per note,
5% and the jet integration, which is the expensive stage of this model).
6% Returns the basis of the first note (the demo prints its resonances).
8[noteIdx, tOn, spanS, ninfo] = recorder_notes(P);
9fsHi = P.sample_rate * P.oversample;
10T = floor(ninfo.durationS * fsHi);
11p = zeros(1, T);
13K = ninfo.count;
14fPlay = zeros(1, K);
15cents = zeros(1, K);
16vacRms = zeros(1, K);
17listenerInside = 0;
18listenerDistM = 0;
19basis = [];
20for i = 1:K
21 bi = recorder_basis(P, noteIdx(i));
22 if i == 1
23 basis = bi;
24 end
25 [Zr, Zi, Qin, jinfo] = recorder_jet(P, bi, spanS(i), i, fsHi);
26 [pn, radinfo] = recorder_radiate(P, bi, Zr, Zi, Qin, fsHi);
27 k0 = min(T, round(tOn(i) * fsHi) + 1);
28 len = min(length(pn), T - k0 + 1);
29 p(k0:k0 + len - 1) = p(k0:k0 + len - 1) + pn(1:len);
30 fPlay(i) = jinfo.fPlay;
31 cents(i) = jinfo.cents;
32 vacRms(i) = jinfo.vacRms;
33 listenerInside = listenerInside || radinfo.listenerInside;
34 listenerDistM = radinfo.listenerDistM;
35end
37[y, peakPa] = recorder_output(P, p, P.oversample);
39dinfo.noteCount = K;
40dinfo.noteIdx = noteIdx;
41dinfo.fPlay = fPlay;
42dinfo.cents = cents;
43dinfo.vacRms = vacRms;
44dinfo.durationS = ninfo.durationS;
45dinfo.peakPa = peakPa;
46dinfo.peakSplDb = 20 * log10(peakPa / 20e-6 + 1e-30);
47dinfo.listenerInside = listenerInside;
48dinfo.listenerDistM = listenerDistM;
49end