/ proof-of-concept / steelsim21
Sign in
proof-of-concept / steelsim21
Gallery: fixed +20 dB playback gain matching the app
Jeremy Magland <jmagland@flatironinstitute.org> committed commit 25dba3d2db85 parent 45a31b0 Browse files
2 changed files+10−7
docs/gallery/manifest.jsonmodified+3−2View file
@@ -1,6 +1,6 @@
11 {
22 "title": "Steel sheet gong: how the parameters shape the sound",
3- "intro": "Each section varies one property of the simulated sheet or of the excitation while everything else stays at the simulator defaults: a 12 by 18 inch, 22 gauge (0.79 mm) stainless steel sheet hanging in portrait orientation with a 3 mm bow across its width, heard 1 m in front of its center, recorded for 4 s. The clips are computed on a 4 mm grid (the interactive app defaults to 8 mm for speed; the 'Open in simulator' links carry the 4 mm setting, so they reproduce the clip exactly but run slower). Click a player to hear a clip. Within a section the clips share one playback gain, so the loudness differences you hear are the ones the model predicts; between sections the gain differs. The numbers under each clip are the peak pressure and sound pressure level at the listener, the RMS pressure over the clip, the spectral centroid of the sound between 0.2 and 1.2 s (a measure of brightness), and fitted 60 dB decay times of a low and a high band.",
3+ "intro": "Each section varies one property of the simulated sheet or of the excitation while everything else stays at the simulator defaults: a 12 by 18 inch, 22 gauge (0.79 mm) stainless steel sheet hanging in portrait orientation with a 3 mm bow across its width, heard 1 m in front of its center, recorded for 4 s. The clips are computed on a 4 mm grid (the interactive app defaults to 8 mm for speed; the 'Open in simulator' links carry the 4 mm setting, so they reproduce the clip exactly but run slower). Click a player to hear a clip. Every clip is rendered at the simulator's default playback level (+20 dB relative to 1 Pa at full scale, with the same soft clipper), so loudness differences within and between sections are the ones the model predicts, and a clip sounds as it does in the app. The numbers under each clip are the peak pressure and sound pressure level at the listener, the RMS pressure over the clip, the spectral centroid of the sound between 0.2 and 1.2 s (a measure of brightness), and fitted 60 dB decay times of a low and a high band.",
44 "sweeps": [
55 {
66 "id": "strike-speed",
@@ -286,5 +286,6 @@
286286 100
287287 ]
288288 }
289- ]
289+ ],
290+ "gainDb": 20
290291 }
\ No newline at end of file
src/cli/main.tsmodified+7−5View file
@@ -120,7 +120,7 @@ interface ManifestSweep {
120120 clips?: ManifestClip[];
121121 gainDb?: number | "auto";
122122 }
123-interface Manifest { title: string; intro: string; sweeps: ManifestSweep[] }
123+interface Manifest { title: string; intro: string; gainDb?: number | "auto"; sweeps: ManifestSweep[] }
124124
125125 function sweepClips(sw: ManifestSweep): ManifestClip[] {
126126 if (sw.clips) return sw.clips;
@@ -176,12 +176,14 @@ async function gallery(): Promise<void> {
176176 }
177177 results.push({ clip, id, ov, r });
178178 }
179- // One gain per sweep so that loudness differences within it are preserved.
179+ // Playback gain: fixed (comparable across sweeps and with the app) or "auto"
180+ // (the loudest clip of the sweep peaks at +3 dBFS before the soft clipper).
180181 let gainDb: number;
181- if (sw.gainDb === undefined || sw.gainDb === "auto") {
182+ const gainSetting = sw.gainDb ?? manifest.gainDb ?? "auto";
183+ if (gainSetting === "auto") {
182184 const loudest = Math.max(...results.map((x) => peakDbfs(x.r.audio, 1)));
183185 gainDb = Math.round(3 - loudest);
184- } else gainDb = sw.gainDb;
186+ } else gainDb = gainSetting;
185187 const peakRef = Math.max(...results.map((x) => { const s = new Spectrogram(SPEC_OPTS); s.update(x.r.audio, x.r.audio.length); return s.data.peakDb; }));
186188 const records = results.map((x) => writeClip(clipsDir, x.id, x.clip.label, x.ov, x.r, gainDb, peakRef));
187189 writeFileSync(join(dir, `${sw.id}.json`), JSON.stringify({ sweep: sw, gainDb, clips: records }, null, 2));
@@ -230,7 +232,7 @@ function writeHtml(manifest: Manifest, dir: string): void {
230232 sections.push(`<section id="${sw.id}">
231233 <h2>${esc(sw.title)}</h2>
232234 <p>${esc(sw.text)}</p>
233-<p class="dim">All clips in this section share the same playback gain (${data.gainDb >= 0 ? "+" : ""}${data.gainDb} dB relative to 1 Pa = 0 dBFS), so their loudness differences are real. Spectrograms: 0 to 5 kHz over the clip, 80 dB range, shared color scale.</p>
235+<p class="dim">Playback gain ${data.gainDb >= 0 ? "+" : ""}${data.gainDb} dB relative to 1 Pa = 0 dBFS (the simulator's default is +20 dB); loud onsets are soft-clipped. Spectrograms: 0 to 5 kHz over the clip, 80 dB range, one color scale per section.</p>
234236 <div class="cards">${cards.join("\n")}</div>
235237 </section>`);
236238 }
↑↓ move↵openescclose