Boomtect: Make your own thunder
Boomtect simulates the sound of lightning, blasts, and sonic booms from their physics. Shape
a flash or a whole storm in 3D above the ground, place microphones, and hear
how distance, height, layered air, terrain, and ground shape what arrives. Listen in mono, as a
spaced stereo pair, or binaurally on headphones, and export WAV or Ambisonics.
Made for sound design, built on physics.
Or ask an AI assistant for a sound in words: see Sounds from words.
See it live: https://janne-s.github.io/Boomtect/
How it works
Every source is a set of points, each with a position, an emission time, and a
pressure pulse. A lightning channel is thousands of them along a branching,
zigzagging path; a blast is one. Each pulse travels to each microphone with its
own delay and loss, and the microphone hears their sum.
Thunder, Blast, and Sonic keep their own emitters and acoustic settings. The
active place and terrain travel with you when switching modes. A
supersonic body's booms leave its flight path where the sound reaches a
microphone along the Mach cone.
Scene
- Box — The floor is the ground and the two far walls show the scene from
the side. The cross on the floor is the origin. The box measures the scene;
loaded terrain goes on beyond it and fades toward its own edge.
- Points and shadows — Drag a point to move it horizontally, or its shadow
on the floor or a wall to move it in that plane.
- View — Drag empty space to turn, pinch or wheel to zoom, two fingers,
Shift-drag, or the right button to pan, double-click to reset.
- Channel ends — A channel starts at the dark circle and ends at the white
one. A storm's edge handle sets its size, and its grey handles move the
cloud base and top up and down.
- Selection — Dashed lines lead from a selected microphone, blast, or channel
end to its shadows on the floor and walls. A click on empty space clears it.
- Speed of sound — A tick across a flight's, booster's, or meteor's path
where it passes the speed of sound of the air at its height.
- Shadow boundary — The line on the ground beyond which refraction lifts the
selected emitter's sound off the ground, for the microphone's height.
- Levels — A microphone shows its peak in pascals and decibels and its
loudest A-weighted Fast level (LAFmax, IEC 61672-1). A blast, barrage, or
volcano shows its pressure and level 1 km away.
Emitters
- Ground flash — A channel from the ground into the cloud, where it spreads
sideways. Later strokes follow the same channel or strike a new ground point.
- Cloud flash — A channel inside the cloud; its sound spreads out in time.
- Storm — Ground and cloud flashes over an area, a time span, and a cloud
layer.
- Blast — An explosion of a given charge: its shock, the secondary shock
that follows it, and the roar of its fireball and debris.
- Barrage — Rounds landing over an area in salvos, as artillery fires,
each a blast; some may burst in the air.
- Fireworks — Shells fired from mortars over an area in salvos: each
mortar's thump on the ground, the shell's burst high in the air a flight time
later, and, for a share of the shells, crackling stars as a swarm of tiny
pops around the burst. In the scene each shell bursts in its own color.
- Volcano — An explosion from a crater, on the ground or raised to a
summit's height above it: a long pressure pulse, sized as the
TNT charge that carries the same sound energy, and the roar and low thumps of the ash and gas that
follow it. Strombolian, Vulcanian, and strong Vulcanian types set it; the
rise time runs from a soft thump to a crack.
- Flight — A supersonic body: a reconnaissance aircraft, a bomber, a launch
vehicle, or a body of its own length and shape. It climbs, accelerates, and
turns as set; its booms focus where its rays converge, and the air can turn
them away before the ground. Supersonic at its start, it has flown straight
there, so the ground around the start hears it too.
Far downwind of the upper wind, 200 km or so away, its boom comes back from
the stratosphere a quarter of an hour later as a low rumble.
- Formation — Aircraft flying in a vee behind a leader, each with its own
booms.
- Meteor — A meteoroid entering the atmosphere down to the height where its
trail ends; its boom leaves the trail where its Mach cone reaches the
microphone. Its fragments break up in generations where the air's pressure on
them exceeds their strength, and it bursts where the trail ends, each a blast
high in the air. A new meteor follows the Chelyabinsk fireball's track of
2013, mirrored to fly east, as a 1 m body; its diameter takes it toward the 19 m original.
- Shower — Meteoroids from one radiant over an area and a time span.
- Whip — A bullwhip's crack: the boom of its tip, which passes the speed of
sound, speeds up, turns over as the lash rolls out, and slows down again,
all within about a millisecond and a metre. The crack is loudest ahead of
and above the turn and weak behind it.
- Booster — A rocket's first stage falling back to its landing pad, tail
first, slowed by the air as it thickens. Its boom is a triple boom: a front
shock, a middle shock from the grid fins and the folded landing legs, and a
rear shock.
Listening
- Actions — On narrow screens, ⋯ beside GitHub holds Open, Save, Export,
and the linked tect's controls. Its dot shows the connection state.
- Space — Runs the main Render / Play / Stop action outside controls and dialogs.
- Render and Play — The button renders the scene when it has changed,
then plays it: it lights the sources as they sound and plays what the
listening microphones hear. While a render runs, it stops it (the square beside the spinner).
- Pause — The button on the pressure plot holds playback where it is; Play
goes on from there, Stop starts over.
- Scrubbing — Press either plot or the small scene timeline to move playback
to that moment, and drag to move it further; on release it plays on from there,
including from pause. The scene timeline also supports arrow keys (one second),
Page Up / Down (one tenth of its duration), and Home / End. Sound fades in and
out as it starts and stops.
- Auto (circling arrows, beside Play) — Renders again soon after every
change. Off, changes wait for Render.
- In progress — Rendering and loading are listed in the corner of the
scene while they run, each with how far it has come, how long it has run, and
for requests over the network when it gives up. The last message stands above
them: a note fades, an error stays.
- Settings (gear beside Play, also on mobile) — How much of the sound a
render computes, kept with the scene: the cutoff level, the highest frequency, the flash detail (how many
segments one source stands for), the echo detail (the echo cells' size), a
scattered echo's arrivals, a coarse forest (on a coarse frequency grid), and
shared scatter (a frame's scattered echoes spread in a few groups), with the cost against the full computation and an
estimate of its time from the last render; the preview; and the threads this
device renders on. Its synthesis and coarse echoes apply to Rumbletect's
grain sources and rest here.
- Preview (turtle, beside Play or in the mobile view switches) — Renders a
lighter version of the scene's settings: a flash's sources merged in fours, echo cells twice as large, and
sound up to 2 kHz at most.
About as loud, as long, and as dark as the full render, a few times quicker
over terrain. An export is always rendered in full.
- Real delay (hourglass, beside Play) — On: the sound arrives as late as it would outdoors, and the
clock in the corner counts from the start (the flash when only flashes sound), its bar brightening when the sound
arrives. Off: the silence before the first sound is skipped, and the channel
glows where the sound being heard comes from.
- View switches — Down the scene's right edge, each icon lit while on, only
those that apply.
Air
- Lapse rate — How fast the temperature falls with height; 6.5 K/km is the
standard atmosphere, a negative value an inversion.
- Refraction — Sound bends toward slower air. Falling temperature
bends it up and leaves a shadow on the ground, where thunder fades out; an
inversion bends it down and carries it far. Off: homogeneous air, the
free-field reference.
- Shadow floor — How far below the unbent level the shadow can go, set by
turbulent scattering.
- Ground — What the ground is made of. Water reflects like rigid ground.
- Forest, Tree height, and Forest density — Trees around the scene:
sound under their canopy is muffled, and the forest answers every sound with a
reverberant tail; a sparser forest does both less.
- Surroundings — Over level ground, the long rumble the land around returns
of a loud sound. Over terrain with echoes, the echoes take its place.
- Wind, Wind from, and Wind shear — The wind at the ground, the
compass direction it comes from, and how much it strengthens with height.
Downwind, sound bends down and carries; upwind, the shadow comes closer.
- Upper wind and Upper wind from — In Sonic mode, the wind around the
stratopause, about 50 km up, that brings secondary booms back to the ground.
- Vapour height — How quickly the water vapour thins out with height,
which changes how much the upper air absorbs.
- Tropopause — Where the temperature stops falling; above it the air keeps
one temperature.
- Ground layer and Layer lapse — A layer of air next to the ground with
its own lapse rate, such as a low inversion on a calm night.
Use Reset app in Settings to return to the initial workspace.
After confirmation it removes Boomtect’s saved scenes and preferences from this
browser and reloads. Echotect’s data and downloaded files are kept. The reset
button works independently of the main application’s startup.
Terrain
- Place — Where the scene's origin lies, saved with the scene with or
without terrain. The map button opens a map to move under the centre mark,
with the area the scene needs around it. Load in this map dialog fetches
terrain immediately. Loaded terrain follows the place.
- Resolution — The spacing of the heights. A scene too large for the
terrain's budget takes a spacing two or more times as coarse.
- Find — Finds a place by name, or takes "latitude, longitude".
- Load terrain — Fetches the elevation the scene needs and saves it in the
scene, so the scene opens the same way later without a connection. Place
names load only while Names is on. The terrain is held in square patches:
those under the emitters and microphones and, around them, a quarter of the scene's size
(at least 1 km) for the slopes that echo. Move or add something past the
edge and the patches it now needs load a moment later; those no longer needed
are dropped.
- Terrain — Microphones, blasts, and ground points stand on the ground;
heights in the cloud are above the ground at the origin. The panel shows both
heights above the ground and above sea level, and the box's height lines are
above sea level.
- Shielding — Hills between a source and a microphone block the direct and
the reflected sound, and sound bends over their crests, more at low
frequencies.
- Echoes — Slopes the source and the microphone both see send the sound
back: sharply from where they mirror it, and scattered from everywhere else.
- Scattering — The share of the echo that scatters; the rest mirrors.
- Echo cells — Sources this close together share their echoes.
- Echoes per cell — The strongest echoes kept for each cell.
- Contours — Stripes the terrain by height.
Export
Export packs the chosen files, several of them in a ZIP:
- Scene (JSON) — The full scene as JSON, with the files, the time of their first
sample after the start, and the pascals at full scale. It opens as a scene.
- Stereo — What plays, in two channels: mono on both, a pair left and right,
more microphones panned, binaural as heard on headphones.
- Microphones — One file per microphone: an omni's pressure in mono, a
binaural microphone in stereo.
- Ambisonics — One AmbiX file per microphone (ACN, SN3D; front is north,
left is west), when the render is spatial.
- Terrain echoes — With, without, or only the terrain's echoes. Without
leaves out the surroundings' rumble too, which stands in for the echoes
where they are not traced, and Only is the render with echoes less the one
without.
All files are 32-bit float at one full scale. Files of more than two channels
are WAVE_FORMAT_EXTENSIBLE with no speaker positions. With per-microphone files,
every file starts at the same moment.
Below them, Echotect prepares a microphone's pressure in mono without
terrain echoes, and a handoff with the place, the air, the microphone, and the
direction and distance the sound comes from. Send to Echotect opens
Echotect with it in its own window, and Save file saves it as a package
(WAV and JSON).
- Microphone — Whose sound it is, when there are several.
- With — Place, so Echotect puts its Listener where the microphone was and
its Source the way the sound came from; Direction, so only its Source moves;
or Sound only, so a scene set up there stays as it is.
Calibration
Boomtect plays through the browser at the computer's volume, like any other
sound. Its levels are model values; with a fixed full scale they keep their
real relation, so a sound system can be set to play them at that level.
- Peak — The loudest moment plays at −3 dBFS whatever its pressure, so a
quiet scene plays as loud as a loud one.
- Fixed — Full scale is a pressure: at 20 Pa a sample of 1.0 is 20 Pa, and
0 dBFS is 120 dB SPL peak. Exported files keep the same scale.
- To calibrate — Choose Fixed, one omni microphone, and Ear reflex and
Loudness off. Play a 1 kHz sine at −20 dBFS from any tone generator and set
the speakers or headphones with a sound level meter to read the full scale's
level less 23 dB: 97 dB SPL at 20 Pa. Leave the volume there. Binaural
playback and mixes of several microphones are scaled down for headroom.
Echotect
For echoes from buildings and streets, place a Boomtect sound in an
Echotect echo field. In the export's
Echotect section, Send to Echotect opens Echotect with the chosen
microphone's sound, or Save file saves it to choose in Echotect as your own
sound. With decides where it lands: with Place, Echotect
puts its Listener where the microphone was and its Source the way the sound
came from; with Direction, only its Source moves; with Sound only, its scene
stays as it is. Echotect absorbs only the air beyond what the sound already
holds. One direction stands for sound that arrives from many.
Rumbletect
Open Rumbletect opens Rumbletect in its own
window and links the two windows. When Rumbletect is already open, the button
reads Link Rumbletect. Rumbletect makes the engines of jets, airliners, and
rockets, and the roar of an eruption.
- One scene — The place, terrain, air, ground, microphones, and render
settings are the same in both windows, and a change in either reaches the
other. A window the link opens starts with no emitters of its own, and its
saved scenes stay as they were; after Unlink the scene on screen stays.
- Heard together — Each window renders its own emitters, and the
microphones hear both: plots, levels, playback, the export, and Echotect get
the sum. With Auto render on, Rumbletect's new sound comes in at once;
with it off, the arrows beside Rumbletect's name take it in.
- Followers — Each supersonic jet or rocket in Rumbletect gets a flight here
on its path, named after it, whose booms and Mach cone Boomtect computes; each
Boomtect flight gets a jet in Rumbletect for its engines. A follower moves
with what it follows and keeps a copy of the path, so it still sounds without
the link. A rocket's visible path ends at burnout, as in Rumbletect; its
unpowered continuation still contributes booms. Its body is set in Details.
Removed, it stays away while both windows are open.
- Real and Balanced — Above the pressure plot while linked: Real plays
both tects at their real pressures; Balanced lifts the quieter one to the
louder one's loudest A-weighted level, turning nothing down. The plot shows
each tect in its own half, scaled to its own peak, with the lift beside its
name. The microphone's levels are always the real sum. The cross at the
right of the linked tect's half unlinks it.
- Tects — In the export while linked: Together exports the sum as heard;
Separately exports each tect's sound in its own files at its real level, on
one full scale and one time axis per microphone, with one scene file.
- Rumbletect's emitters — Dimmed in the scene; a click on one shows it in
Rumbletect. Rumbletect's name opens a button to bring its window forward and
Unlink.
Model
Every part of the model is marked with a class that says how far it can be
trusted, here and in the details of each parameter:
- A — Derived from first principles, such as travel time in uniform air.
- B — An approximation from the literature, valid in the range its source
gives.
- C — A heuristic or synthetic assumption, chosen to behave plausibly
rather than derived or measured.
B/C marks a part that combines the two.
| Part | Model | Class |
|---|
| Speed of sound | c = sqrt(γRT) | A |
| Temperature profile | layers: a ground layer, the troposphere, constant above the tropopause (ISO 2533) | B/C |
| Sound speed along a path | linear from the ground, matched to the layered speed's mean slowness over the path's heights | C |
| Travel time, rays, and spreading | circular rays in a linear c(z), ray tubes; 1/R without refraction | A |
| Wind | effective sound speed along each path, linear in height | B/C |
| Refraction shadow | grazing ray, creeping wave along the ground (Fock), softer over porous ground at high frequencies, floor; over terrain, heights above the mean ground plane between source and microphone (CNOSSOS-EU) | B/C |
| Segment directivity | straight line element | A |
| Lightning pulse | N-wave, period 2.81·R₀/c, R₀ = sqrt(E/(πp)) (Few, ReVelle) | B |
| Weak shock | period grows as x^¼, extra decay x^-¼ (ReVelle) | B |
| Strokes | lognormal intervals, new ground points | B/C |
| Return-stroke current | decays with height, e^(-z/λ) (MTLE); energy as its square | B/C |
| In-cloud channels | sideways channels from a ground flash's top, thinning out | C |
| Channel shape | seeded two-scale zigzag with branches of branches | C |
| Lightning level | acoustic share of channel energy | C |
| Blast | Friedlander pulse, Kinney & Graham overpressure and positive phase (3.98 ms·W^⅓ where the pulse turns linear, Z = 20 m/kg^⅓; adjustable in Details) | B |
| Blast aging | weak shock of a spherical wave: positive phase grows as √(1 + σ·ln(r/r₀)), peak falls by as much; a merged ground front ages as twice the pressure | B/C |
| Secondary shock | delay by the explosive's detonation velocity and density (Rigby & Gitterman); a 4 % charge's shock |
Not modelled: buildings, whose echoes Echotect makes; the engines of a flight
or a booster, which Rumbletect makes; a fireworks shell's whistle and hiss and
its stars' burning; and a whip's swish.
Boomtect is a creative tool. Where published models exist it follows them,
but a result is a plausible event, not a reconstruction or a measurement.
Levels are model values in pascals and are not calibrated.
Running locally
npm start
Open http://localhost:8000/. Run the tests with npm test.
The model's and the view's tuning values and limits are in src/domain/constants.js; the
parameters a scene sets, with their defaults and ranges, in src/domain/scene.js.
Sounds from words
Ask Claude or another AI assistant for a sound in words, such as "thunder three
kilometres away on a humid summer night" or "a sonic boom over the Grand
Canyon, heard from the South Rim". It places the source and the microphone from
your description, renders the sound on your machine, checks it by measurement,
and hands over the WAV files and the scene to open in the app. Nothing needs
starting by hand.
- Claude Desktop — Install
tect.mcpb and ask.
- Codex and ChatGPT desktop — Install
tect-openai.zip and ask.
- Claude Code and other coding agents — Open this repository and ask.
- Other MCP apps, such as Cursor or VS Code — Add
node src/shared/mcp/server.mjs from a clone to the app's MCP servers; it
needs Node 20 or later.
Writing a scene
A scene is a file saved from the app or a partial one written by hand: missing
fields take their defaults and values out of range are brought into range, as
when the app opens a file. examples/ holds three starting points: thunder three kilometres away, a blast across a forest, and a sonic boom from high overhead.
Begin from the nearest one and change what the request names; the macros of the app are not scene fields, so set the parameters they move.
What each change does to the sound:
| Change | Sound |
|---|
| Farther source | quieter, darker, and longer; air takes the highs first, a close flash cracks before it rumbles |
Lightning topMetres higher, longer channel | a longer rumble |
flashType intra-cloud (Cloud flash) | a channel inside the cloud, its sound spread out in time |
More branchCount, more tortuosityDegrees | more separate claps, a more ragged rumble |
Bigger chargeKilograms | deeper and longer; a blast's positionMetres.z high makes an air burst |
Shorter riseTimeSeconds | a sharper crack; longer, a softer thump |
| Flight higher | a weaker, slightly longer boom; faster mach, a wider carpet |
ground.type water or rigid | a strong reflection right after the direct sound |
grass, soil, forestFloor, snow | softer ground, the lows dip near it; snow the most muffled |
ground.forest | highs muffled on the way, a reverberant tail |
ground.surroundings | the long rumble the land around returns of a loud sound |
| Humid air | highs carry farther |
| Wind toward the microphone | louder; against it, a shadow at a distance |
Microphone type binaural with headingDegrees and pitchDegrees | a stereo file for headphones, facing that way (compass degrees); a higher render.ambisonicOrder sharpens the direction |
seed | another take of the same event |
Every parameter with its default and range is in src/domain/scene.js. The
same scene and seed give the same sound.
Place and terrain — place holds the scene's geographic point as latitude
and longitude; every position is metres east, north, and up from it.
"terrain": { "enabled": true } without heights loads the terrain around
the scene's sources and microphones from Terrain Tiles in 30 m cells (or
cellMetres), and the filled scene.json keeps the heights. Without terrain
the ground is flat. A named place takes the coordinates the agent knows; an
address is never sent to a search service unasked.
Boomtect and Rumbletect together — A supersonic jet's boom comes from Boomtect and its engine from Rumbletect. Write both scenes with the
same place, terrain, air, ground, and receivers, ids included. Each
tect renders its own emitters, and the mix puts them together in the scene's
time, with each part as its own file.
From the command line
Node 20 or later, no installed packages:
node tools/render.mjs examples/thunder-three-kilometres-away.json out
node tools/render.mjs my-scene.json out --ambix
The folder gets one WAV per microphone, the filled scene.json, and the
printed summary as summary.json. Each WAV is the omni pressure, or for a
binaural microphone a stereo file for headphones facing its heading and
elevation, as the app plays it. --ambix adds each microphone's full sound
field as <mic>-ambix.wav, the AmbiX channels of the scene's order in the
world frame. Files are 32-bit float at the app's export gain. The summary tells
an agent, which cannot listen, what came out: per microphone the length, the
time within 40 dB of the peak, the peak in dB SPL, the loudest A-weighted level
(fast), and the spectral centroid and octave shape of the loudest second.
For two tects, render the first with --cover <the other scene> so that its
terrain covers both, copy place and terrain from its filled scene.json
into the other scene and render that in its own tect, then mix:
node tools/mix.mjs mix boom rumble
The mix summary warns when the scenes do not share their place, terrain, air,
ground, or microphones.
Data
Terrain heights: Terrain Tiles
by Mapzen on AWS Open Data (SRTM, GMTED2010, NED, ETOPO1, EU-DEM, and national
datasets). Place search: OpenStreetMap Nominatim.
Map and place names: © OpenStreetMap
contributors. Optional place labels use OpenFreeMap
vector tiles with the © OpenMapTiles schema
(CC BY 4.0); no API key is required. This is a scale-dependent map label layer,
not a complete list of every named feature.
Both are fetched only when asked for.
Third-party code
Binaural decoding uses Omnitone
1.3.0 with its SADIE HRIRs, under the Apache License 2.0
(notice).
Icons are Font Awesome Free 7.3.1, solid style,
as in Echotect: font under the SIL OFL 1.1, CSS under the MIT License, icons
under CC BY 4.0 (license).
License
MIT
Support Boomtect
Support development through GitHub Sponsors
or Ko-fi. See
Sanara Creations for related work.