Skip to content
getsubwavePublic
forked from rauchg/vinyl

About

A record player simulated from the groove up

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

vinyl

A record player simulated "from the groove up" in the browser: vinyl-gl.vercel.app.

Instead of playing an audio file, the music is cut into a spiral groove, and a simulated stylus, cantilever, tonearm and cartridge read it back on the audio thread. What you hear is the voltage that motion would induce in the cartridge, after phono equalisation.

This is a physical simulation of a record player's mechanics, which happen to play sound.

Features

  • "Real", procedural flaws: hiss and crackle are roughness and dust on the groove walls. A scratch ticks once per turn because the needle crosses it once per turn. Treble dulls toward the label because the groove moves slower there. Knock the table and it skips.
  • Real physics, in real time: a 2 DOF stylus tip on Hertzian wall contacts with friction, oversampled inside an AudioWorklet, with platter inertia, arm kinematics, RIAA de-emphasis and three stylus shapes (conical, elliptical, micro-line).
  • Bring your own audio: Cut a file runs the lathe on anything you drop in, in a worker, in the browser. Press again makes a dirtier (or cleaner) copy of the same cut.
  • No dependencies, no bundler: plain ES modules, WebGL2 and Web Audio. The build copies files.

Running it

$ vercel dev

That's it. vercel dev runs the same build as production (node build.mjs, which writes dist/) and serves it on localhost:3000. It builds once, so restart it after editing.

There's nothing to install. Node 22+ is enough for the build and the tests:

$ npm run build   # dist/: index.html, src/, assets/, records/
$ npm test        # offline checks of the physics: response, distortion, surface noise, cue, skip
$ npm run bench   # CPU cost of the engine per second of audio

How it works

1️⃣ Cut. The lathe (src/cut.js) turns audio into the shape of the two walls of a 45/45 stereo groove at 33⅓ rpm: RIAA pre-emphasis, an acceleration limiter so the cutter could have cut it, and a spiral pitched so the side fits on a 12" disc.

2️⃣ Press. The pressing plant (src/press.js) changes the geometry itself: wall roughness, dust, scratches, warp, an off-centre hole, groove echo. Nothing in it is an audio effect. It's seeded, so the same record always presses the same way.

3️⃣ Play. The engine (src/engine.js, src/engine-core.js, src/groove.js) rides the stylus over those walls. A tip of finite radius can't follow the wall exactly, and that's where tracing distortion, pinch effect and inner-groove loss come from. Too little tracking force and it leaves the wall.

4️⃣ Draw. The deck (src/render.js, src/shaders.js) draws the disc from the cut itself: the actual spiral, lit by how hard each revolution is modulated.

Records

Cutting a whole side takes a while, so the records on the shelf are cut ahead of time and committed to assets/. The clean cut ships as 16-bit DPCM inside FLAC (within a quarter of a nanometre of the cut wall), and the page presses it with the seed. The source audio lives in records/, listed in src/records.js.

To add a record, or after changing the lathe, re-cut what's out of date (needs ffmpeg) and commit assets/:

$ npm run lathe           # every record that is out of date
$ node lathe.mjs toccata  # just this one

The build refuses to deploy a shelf record that was never cut.

Credits

Every recording is public domain or freely licensed:

  • Gershwin, Rhapsody in Blue: George Gershwin, piano, with Paul Whiteman's Concert Orchestra, Victor, 1924 (LOC)
  • Beethoven, Moonlight Sonata: Paul Pitman, piano, for Musopen
  • Satie, Gymnopédie No. 1: Robin Alciatore, piano, for Musopen
  • Chopin, Nocturne Op. 9 No. 2: Frank Lévy, piano, for Musopen
  • Debussy, Clair de lune: Laurens Goedhart, piano, 2011
  • Grieg, In the Hall of the Mountain King: Musopen Symphony
  • Tchaikovsky, 1812 Overture: US Marine Band, live at Wolf Trap, 2019
  • Bach, Toccata and Fugue: Ashtar Moïra, organ
  • Vivaldi, Summer: Presto: John Harrison, violin, with the Wichita State University Chamber Players (CC BY-SA 4.0)
  • HoliznaCC0, Summer Air (CC0, Free Music Archive)

Sources for each are linked in src/records.js. The Demo EP is synthesised by the page.

License

The code is MIT. The recordings in records/, and the records cut from them in assets/, keep their own licenses, listed above. Summer: Presto is CC BY-SA 4.0, so its cut is too.

About

A record player simulated from the groove up

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages