Longitudinal standing waves in a pipe, built with SceneryStack, Vite 8, TypeScript 7, and Biome 2.
Sound in a pipe is usually drawn as a wiggly line, which hides the three things that actually matter: that displacement, velocity and pressure peak in different places; that an open end and a closed end reflect a pulse in opposite ways; and that a pressure antinode sits exactly where the displacement has a node. This simulation makes all three something you manipulate rather than read.
- Reflection — a mass-spring chain terminated open or closed. Launch a pulse and watch it reflect; a closed end flips the displacement and preserves the pressure, an open end does the reverse. Both terminations can be shown side by side, stepped from one clock. The inversion is emergent from the boundary condition, not scripted.
- Phase — a travelling sinusoid with a draggable reference point carrying displacement and
velocity arrows. Reverse the direction and velocity and pressure go from in phase to 180° out of
phase, which is the whole content of
p = ±ρc·u. - Standing Waves — pick Closed–Closed, Open–Open or Closed–Open, then sweep the drive frequency to hunt for a resonance or snap straight to a harmonic. Node markers name both of each point's identities, so the quarter-wave displacement/pressure offset is unmissable.
- Instruments — open and stopped organ pipes, flute and clarinet, with the harmonic series as a bar chart. The flute and clarinet share a bore length, so the octave and the missing even harmonics are visibly the termination's doing.
- Real SI units throughout, with slow motion applied to the clock rather than to the physics
- Full keyboard and screen-reader support, with live state descriptions per screen
- English, Spanish, and French localization via
StringManager - Default and projector color profiles
- Progressive Web App (installable, offline-capable)
- Shared GitHub Actions CI via
OpenPhysics/Baton
The physics is documented for educators in doc/model.md and for developers in
doc/implementation-notes.md.
npm install
npm start # dev server → http://localhost:5173Use ?screens=1 … ?screens=4 to open a single screen directly, and
?showVelocityTrace=true to add the velocity curve on the screens where it is optional.
| Command | Description |
|---|---|
npm start / npm run dev |
Start Vite dev server |
npm run build |
Type-check + production build → dist/ |
npm run build:single |
Single-file build |
npm run preview |
Preview the production build locally |
npm test |
Run Vitest unit tests (includes memory-leak suite) |
npm run test:fuzz |
Optional Playwright fuzz smoke (?fuzz, default 15s) |
npm run test:fuzz:quick |
Shorter fuzz smoke (10s) |
npm run check |
TypeScript type check |
npm run lint |
Biome lint check |
npm run format |
Auto-format all files |
npm run fix |
Lint + auto-fix |
npm run icons |
Regenerate PNG icons from public/icons/icon.svg |
npm run release |
check && lint && build, then version patch + push tags |
npm run clean |
Remove dist/ |
npm run release does not run npm test; append && npm test before the version bump so a release
cannot ship a failing suite.
| Tool | Version | Purpose |
|---|---|---|
| SceneryStack | ^3.0.0 | Simulation framework |
| Vite | ^8 | Build tool + dev server |
| TypeScript | ^7 | Type-safe JavaScript |
| Biome | ^2.5 | Linting + formatting |
| vite-plugin-pwa | ^1 | PWA + service worker |
GNU Affero General Public License v3.0 — see OpenPhysics org license.
See OpenPhysics contributing guidelines. Report bugs via GitHub Issues; use org issue templates.