Skip to content

Acoustics

denfry edited this page Oct 13, 2026 · 1 revision

Acoustics

Note

Design stage. This page describes planned mechanics from the design document. Not implemented yet — see Roadmap (milestone M11).

In Prompt Critical sound is an information channel about the state of the plant. An experienced player "hears" the station the way a real plant rounds operator does: a change in pump noise means cavitation, a whistle means a leak, clicking means heat-up. The same physics drives vibration diagnostics, bearing wear and predictive maintenance.

Principles

  1. Every sound is a consequence of a physical variable. There are no ambient sounds without a cause. Loudness, pitch and timbre are computed from simulation parameters.
  2. Sound duplicates instruments; it does not replace them. Everything audible is measurable by instruments, and vice versa. Some faults invisible to normal sensors, such as an early-stage bearing defect, can be found only with a vibrometer or stethoscope.
  3. The server computes physics; the client synthesizes sound. The server sends a few bytes of emitter state; the client builds the sound from layered samples.
  4. Accessibility is mandatory. Every sound has a subtitle. Every sound that carries danger information has a visual duplicate.

Architecture

 pc-sim (server, FAST/SLOW)                                pc-mod (client)
 FluidNetwork, HeatStructure,                              AcousticClient
 PumpDrive, Turbine, Cascade --> AcousticField.stepFast() -->  EmitterVoice per emitter:
                                  EmitterState[] (SoA)          layers: base / modulation / one-shots
                                  VibrationSpectrum[]           Occlusion (rays through blocks, 4 Hz)
                                  SimEvent.AcousticOneShot      GeigerSynth (dosimeter clicks)
                                                                Subtitles / VisualCues
                AcousticSyncService -- AcousticStatePayload (4 Hz, deltas)
                                     -- AcousticOneShotPayload (on event)

AcousticField (domain, sim.acoustics) computes for each emitter its sound power level L_W (dB), pitch multiplier φ, roughness r ∈ [0, 1] (broadband share) and active layer mask, about 16 bytes per emitter with no allocations. VibrationSpectrum holds vibration velocity amplitudes per diagnostic band for rotating equipment.

Propagation

Level at the listener for a point source in free field:

L_p(d) = L_W − 20·log10(d / 1 m) − 11 − Σ TL_i   [dB]

The client does not trust Minecraft's linear attenuation. Each voice plays non-attenuated with a volume the client computes itself: g = clamp(10^((L_p − 100)/20) · g_user, 0, 1). The reference level is acoustics.reference_spl_db = 100. A ~1 MW pump at 2 m (≈ 83 dB) is clearly audible but not at full volume; a water hammer (> 120 dB) saturates. Voices below 30 dB are culled.

Block sound insulation (per block on the emitter–listener ray, capped at acoustics.max_occlusion_db = 45 so a faint hum through walls remains):

Material TL per block, dB
Air / plants / glass panes 0 / 2 / 4
Glass block 12
Wood 15
Stone, brick 22
Concrete (containment_wall, MC concrete) 25
Metal (iron blocks, casings) 18, plus structure-borne path
Water (source) 20

Structure-borne sound in pipes. Water hammer, cavitation and leak sounds are re-radiated by pipe / pipe_large blocks of the same hydraulic network within 24 m, at L_W − 10 − 0.5·s dB (s = path length along the pipe). Only the one pipe point nearest the player per network sounds.

Engine limits. Minecraft pitch is clamped to 0.5–2.0, so wide-range sources such as the turbine use 3 octave samples with crossfade. The mod limits itself to acoustics.max_voices = 24 voices, prioritized by level at the listener. All samples are short loops (≤ 4 s).

Pump cavitation and NPSH

Cavitation intensity index κ ∈ [0, 1]: 0 is silent, ≈ 0.67 corresponds to NPSH_a = NPSH_r (−3 % head), 1 is fully developed cavitation. Head drop is ΔH/H = min(1, 0.03·exp((NPSH_r − NPSH_a)/(0.15·NPSH_r))): 3 % at NPSH_a = NPSH_r, 22 % at 0.7·NPSH_r, total loss at ≈ 0.47·NPSH_r.

Impeller erosion: dW_imp/dt = κ³ / 200 h (acoustics.cavitation_erosion_hours). Wear lowers head by 0.25·W and raises required NPSH by 50 %·W, so a worn impeller cavitates more readily (positive feedback).

The cavitation sound is a broadband "gravel in the pump" layer (1–20 kHz): L_W,cav = L_W,pump + 15κ − 6. At κ → 1 it is 9 dB louder than the pump itself and impossible to miss; at small κ it is audible only up close or with the stethoscope.

Back-of-envelope examples:

  • Main coolant pump at rated conditions (15.5 MPa, 290 °C): NPSH_a ≈ 1101 m, so cavitation is impossible in normal operation. It appears only on loss of primary pressure. At 7.8 MPa the margin is 49 m, and the change in pump sound becomes the first audible sign of boiling. With a small primary leak, the operator hears the pump before some alarms fire.
  • Condensate pump (condenser at 5 kPa, condensate at saturation): all NPSH comes from the liquid column. With NPSH_r = 2.5 m and 0.5 m suction losses, the pump must sit at least 3 blocks below the hotwell level or it cavitates from the first start.

Sound catalog

Network class: S = emitter state (loop, 4 Hz deltas), E = one-shot event, C = synthesized entirely on the client.

Sound ID (promptcritical:<id>) Source Driven by L_W, dB Class
pump.run any pump ω, shaft power 70 + 10·log10(P/1 kW) + off-BEP term S
pump.cavitation pump κ see above S
pump.bearing pump bearing wear, ω see bearings S
pipe.hammer flow link Δp 120 + 20·log10(Δp/1 MPa) E
pipe.boil.subcooled / .nucleate / .film heat structure boiling regime, heat flux — S
pipe.thermal_click heat structure dT/dt 75 E (bursts)
pipe.singing dead-leg branch flow velocity, branch length — S
pipe.leak leak leak flow, jet velocity — S
valve.relief.pop / .blow / .chatter relief valve / PORV lift, flow, chatter 125 / jet / 115 E / S / S
valve.stroke, valve.torque_seat MOV / gate valve travel, seating 70 / 85 S / E
rod.drive, rod.scram, rod.dashpot rod drives speed, drop, dashpot impact 72 / 110 / 100 S / E / E
turbine.run, turbine.overspeed, turbine.trip turbine ω, P 80 + 10·log10(P/1 MW); +6 dB above 105 %; 120 S / S / E
generator.hum generator electrical frequency, load 70 + 10·log10(1 + 9·P/P_nom) S
centrifuge.run, .resonance, .crash cascade ω, resonance amplitude 70 + 10·log10(N); 70–100; 125 S / S / E
geiger.click player's dosimeter / monitor observed count rate client C
alarm.p1 / p2 / p3, alarm.return alarms priority 95 / 90 / 85, 80 E
alarm.evacuation CAAS / containment — 110 S
alarm.scram_horn scram — 100 E
containment.creak containment at p > 0.8 P_design p / P_design 80–100 E (bursts)
h2.recombiner passive recombiner reaction rate 65 S

Event levels are of the real order (main steam relief valve ≥ 120 dB at 1 m, water hammer 110–140 dB) and live in assets/promptcritical/acoustics/emitters.json, which a resource pack can override.

Water hammer

  • Fast closure (closing time < 2L/a), Joukowsky: Δp = ρ·a·Δv, with the wave speed in an elastic pipe from the Korteweg formula.
  • Slow closure, Michaud: Δp ≈ 2ρ·L·Δv / T_c.

Example: feedwater line at 220 °C, 7 MPa, D = 0.3 m, wall 0.02 m, v = 3 m/s, L = 50 m (a = 1222 m/s). A check valve slamming in one tick gives 3.1 MPa; a gate valve closing over 2 s gives 0.13 MPa. The same pipe with cold water (20 °C) gives 4.1 MPa.

In two-phase mixtures the wave speed drops sharply (Wood's formula: at 7 MPa saturation, 735 m/s at 1 % void, 211 m/s at 50 %). But condensation-induced water hammer, when a steam bubble collapses in subcooled water, accelerates a liquid slug to tens of m/s and produces the strongest blows. It is a classic cause of steam line damage during warm-up.

The 0.05 s hydraulic step cannot resolve acoustic waves, so water hammer is an analytical estimate per event, triggered by valve closure, check valve slam on flow reversal, steam void collapse (void > 0.2 → < 0.01 within 2 ticks at > 10 K subcooling) or pump start into a drained line. The result is SimEvent.WaterHammer(linkId, deltaP, position); pipe strength and consequences are handled by the accident models. No event is generated below acoustics.hammer_min_dp_pa = 2e5 (0.2 MPa).

Centrifuge resonance

Gas centrifuge rotors are supercritical: they must pass through one or two bending critical speeds during spin-up. With damping ζ = 0.02 the resonance gain is 25, and amplitude builds with time constant 1/(ζ·ω_c), so a fast pass does not let it develop. With the default crash clearance of 12 × the unbalance response, a machine crashes if it accelerates through resonance slower than 1.22·10⁻³·ω_c² (12 rad/s² for ω_c = 100 rad/s). pc_cascade.startRamp(target, rate) must jump the resonance zone. The centrifuge.resonance howl rises at ω_c as a warning. A cascade of hundreds of machines sounds as one emitter; individual voices exist only for machines in resonance or failure (≤ 4 at a time).

Turbine and generator

Turbine noise combines blade-pass frequency and broadband steam noise, with 3 samples (0–40 %, 40–80 %, 80–120 % speed). The generator has a magnetostriction hum at twice the electrical frequency (100 Hz for a 2-pole machine at 3000 rpm), louder with load. Above 105 % speed a "howl" layer adds +6 dB; at the overspeed trip (110–112 %) the stop valve slams and a long coast-down follows.

Dosimeter clicks

Clicks are synthesized on the client from the observed count rate the server sends (1 Hz). The Geiger-Müller model is paralyzable (dead time 190 µs, sensitivity 2.9 s⁻¹ per µSv/h, background 0.2 s⁻¹), so in a strong field the counter chokes and goes quiet. Its maximum is ≈ 1936 s⁻¹ at a true ≈ 1.8 mSv/h. That lesson has to be audible. Clicks form a Poisson process with irregular intervals, like a real counter.

Observed rate, s⁻¹ Rendering Heard as
< 30 Individual 20 ms clicks, ±10 % pitch Sparse crackle
30–300 Dense crackle loop + clicks Continuous crackle
> 300 Hiss loop, pitch rising with log rate Hiss
Past the maximum Hiss fades with observed rate Alarming "silence"

Only the dosimeter's owner hears it. Accessibility modes: TONE (pitch ∝ log dose rate, no fold-over) and VISUAL.

Vibration diagnostics (VibrationSpectrum)

Band Frequency Indicates
1x f_r (running speed) Unbalance
2x 2·f_r Misalignment, looseness
BPF z·f_r (z = vanes) Hydraulic pulsation, off-BEP operation
BPFO (n/2)·f_r·(1 − (d/D)·cos φ) Outer race defect
BPFI (n/2)·f_r·(1 + (d/D)·cos φ) Inner race defect
BSF (D/2d)·f_r·(1 − ((d/D)·cos φ)²) Rolling element defect
FTF (f_r/2)·(1 − (d/D)·cos φ) Cage defect
HF 5–20 kHz acceleration envelope Early bearing defect, cavitation

Example: n = 10 rolling elements, d/D = 0.2 at 1000 rpm gives BPFO = 66.7 Hz and BPFI = 100 Hz. Defaults put a healthy large pump at 1.27 mm/s overall, zone A of class III.

Causes of rising amplitudes: impeller erosion and deposits (1x), thermal growth after cold alignment (2x), off-BEP operation (BPF), bearing wear (bearing bands, HF, later 1x), loosening from a nearby explosion (SEISMIC: harmonics, broadband).

ISO 10816-1 zones (overall RMS velocity, mm/s)

Machine class A/B B/C C/D In game
I (small, ≤ 15 kW) 0.71 1.8 4.5 Auxiliary pumps, valve actuators
II (medium, 15–75 kW) 1.12 2.8 7.1 Makeup pumps
III (large, rigid foundation) 1.8 4.5 11.2 Main coolant pumps, feedwater pumps
IV (large, flexible foundation) 2.8 7.1 18.0 Turbine-generator

Zone A is a new machine, B unrestricted operation, C restricted (plan repair), D dangerous (stop). Vibration protection: pumps and turbines trip in hardware when overall vibration exceeds the C/D boundary × 1.25 for more than 5 s. A main coolant pump trip then produces a LOW_COOLANT_FLOW scram, a cascade the player must anticipate.

Bearing wear and predictive maintenance

Bearing life follows ISO 281 (L10 = (C/P)^p revolutions, p = 3 ball / 10/3 roller), with a default rated life of 50 000 h. Load grows with unbalance and cavitation. Damage accumulates by the Palmgren-Miner rule in the SLOW domain. Each installed bearing gets an individual Weibull life multiplier (shape 1.5); lubrication factor is 1 normally, 0.2 when overheated (> 363 K) or with overdue oil, 0.05 when running dry. With acoustics.bearing_wear_multiplier = 20, a bearing lasts about 35 hours of real play, enough for a few repairs over a long playthrough.

Stage Damage D_b Symptoms Detected by
0 < 0.6 — —
1 0.6–0.8 HF rises ×2…×20 Stethoscope, vib.hf
2 0.8–0.9 BPFO/BPFI peaks 0.5–1 mm/s Vibrometer spectrum, vib.bpfo/bpfi
3 0.9–0.97 Harmonics, sidebands; pump.bearing audible; bearing +10 K Ear, bearing thermometer
4 0.97–1.0 Broadband noise, 1x rises, bearing +30 K, zone D Everything, including protection
Failure ≥ 1 Seizure: shaft stops instantly —

From stage 1 to failure takes 40 % of life (the P-F interval), enough time to plan a repair. A main coolant pump seizure is the design-basis "locked rotor" accident (SimEvent.PumpSeized). Bearing damage is never published as a tag; you estimate it from symptoms.

Maintenance Item / condition Effect Time
Oil change lubricant, running or stopped Lubrication factor → 1 for 2000 physics h 10 s
Bearing replacement bearing_kit, pump stopped, clutch open, MAINTENANCE Damage → 0, new life multiplier 60 s
Balancing vibrometer + balancing_weights, running at rated speed Unbalance → 20 % 3 trial-weight runs of 10 s
Alignment alignment_tool, pump stopped hot Misalignment → 0.05 mm 30 s
Impeller replacement impeller_kit, stopped Erosion → 0 120 s

A main coolant pump bearing inside containment cannot be changed at power, and single-loop operation limits power, so "fix now or run to the outage" is a real economic decision.

Instruments and tags

Instrument models

  • Hand vibrometer (vibrometer item): right-click a machine to see overall level, ISO zone with machine class, an 8-band bar spectrum (1x, 2x, BPF, BPFO, BPFI, BSF, FTF, HF), running frequency and bearing housing temperature (IR pyrometer). One reading per second, and the last 32 readings per machine are stored on the item for route-based diagnostics. Accuracy class 5 %.
  • Mechanic's stethoscope (mechanic_stethoscope): while holding right-click on a machine or pipe, all other voices drop by 20 dB and the target's FAULT and HF layers rise by 15 dB. Inaudible stage 1–2 bearing noise, incipient cavitation and structure-borne leak noise become audible.
  • instrument_vibration mounts against a machine and publishes vibration tags through pc_sensor.
  • instrument_acoustic mounts on a pipe and reports leak and cavitation indices. A pair on the same network, distance L apart, locates a leak by arrival-time difference: x = (L + c_s·Δt) / 2, accurate to about ±1.4 m in water.
Tag template Description Unit Scale
<equip>.vib.overall RMS velocity 10–1000 Hz m/s 0–0.02
<equip>.vib.1x, .2x, .bpf Band amplitudes m/s 0–0.02
<equip>.vib.bpfo, .bpfi, .bsf Bearing bands m/s 0–0.01
<equip>.vib.hf Acceleration envelope 5–20 kHz m/s² 0–50
<equip>.vib.peak_freq Frequency of largest component Hz 0–2000
<equip>.bearing.temp Bearing temperature K 273–423
<equip>.speed Speed from vibration signal rad/s 0–1.2·ω_n
<pipe>.acoustic.level Structure-borne RMS sound pressure Pa 0–200
<pipe>.acoustic.cavitation Cavitation index 1 0–1
<pipe>.acoustic.leak Leak index 1 0–1
<pipe>.acoustic.leak_position Distance to leak from sensor 1 (pair) m 0–L

Networking budget

Packet Direction When Size
AcousticStatePayload S→C 4 Hz, only changed emitters within 48 m ~4.5 B per emitter
AcousticOneShotPayload S→C On event ~18 B
EmitterRemovedPayload S→C On event ~2 B

An emitter is sent only if its level changed by ≥ 1 dB or its pitch by ≈ 1 %. A typical machine hall (~20 emitters) costs about 230 B/s, worst case 480 B/s. The acoustics budget is net.budget.acoustics = 400 B/s out of 2 KB/s per player; above it, emitters beyond 16 m drop to 2 Hz. One-shots are limited to 10/s per player. Dosimeter clicks, alarm sounds, modulation and randomization are not sent; the client derives them from data it already has.

Subtitles and accessibility

Every sound event has a subtitle key subtitles.promptcritical.<id> (ru_ru and en_us). Urgent sounds (alarm.*, pipe.hammer, centrifuge.crash, turbine.overspeed, alarm.evacuation) get a "⚠" prefix. Client settings in promptcritical-client.toml:

Key Default Purpose
acoustics.visual_cues true Screen-edge indicator toward loud or alarm sounds (colour = priority, shape = type)
acoustics.screen_shake true Camera shake ≤ 0.3 s on water hammer or explosion
acoustics.dosimeter_mode CLICKS CLICKS / TONE / VISUAL
acoustics.max_loudness 1.0 Limiter for all mod sounds
acoustics.alarm_volume 1.0 Separate alarm volume
acoustics.reference_spl_db 100 dB level mapped to full volume
acoustics.max_voices 24 Voice limit

See also

Clone this wiki locally