Steve Hatch

I Called It Genetic. It's 30 Random Numbers and an Easing Curve.

I Called It Genetic. It’s 30 Random Numbers and an Easing Curve.

yourmom.com is a full-screen hallucination that never repeats and, if you let it, listens to your music. I built it, and I’ve been calling it “genetic.” Then I went back through the code, and the word doesn’t hold up.

There is a genome. There is no evolution, because nothing competes or breeds and nothing gets selected. What’s on screen is 30 random numbers, an easing curve and a feedback loop. I think that’s the better story anyway.

Quick roadmap:

  • What the genome is, and why “genetic” is the wrong word for it
  • Why random numbers still look like they’re going somewhere
  • How it hears a song instead of a volume level
  • Why the whole site is one 35 KB file
  • What I’d change to earn the word
  • How to poke at it yourself

Drift, not evolution

Each visit starts by rolling a genome of 30 floats, seeded from the browser’s crypto RNG, so no two visits match.

Genes What they control
0 to 3 Mix of four patterns: warped noise, metaballs, Voronoi cells, ripples
4 to 6 Kaleidoscope fold, tunnel projection, number of segments
7 to 9 Scale, warp strength, speed
10 to 13 Feedback: how much of the last frame survives, plus its zoom, rotation and hue shift
14 to 26 Color palette, drawn from one of six moods (neon, acid, pastel, jewel, dusk, wildcard)
27 to 29 Saturation, hue drift, kaleidoscope spin

Then it rolls a second genome and spends 20 to 90 seconds easing toward it. It holds there for 4 to 20 seconds, rolls a third, and keeps going. Tap the screen and it makes the same trip in about ten seconds.

A genetic algorithm needs a population, a fitness function and selection, and this has none of them. Every “mutation” is a fresh roll, so the child shares nothing with the parent. A biologist would call that drift with no selection. (A statistician would call it random, and be right.)

Why it still looks alive

Two things make random numbers look like they’re going somewhere.

One is the easing. The morph runs on a quintic curve that starts and stops with zero velocity and zero acceleration, so you never catch a parameter starting to move. All 30 change together, and slow coordinated change looks like intent to a human eye.

The other is feedback. Each frame is drawn over a zoomed, rotated, hue-shifted copy of the one before, which gives the picture a memory. The old genome is still dissolving while the new one arrives, and that overlap is the part that feels like dreaming.

I suspect most “generative” magic works this way: a small parameter space, walked smoothly. A latent-space walk in an image model is the same trick with more dimensions. It’s worth remembering the next time a demo feels alive.

Listening for the drop

Most audio visualizers map volume to brightness and stop there, which gets you a strobe with opinions. I wanted this one to follow the song. Most of that work turned out to be deciding what to ignore.

Tap the ear icon and it asks for the microphone. Audio is analysed in the browser and never recorded or sent. The first thing the code does is switch off echo cancellation, noise suppression and auto gain, because call-quality processing flattens music into mush.

You can hear it work without handing a blog post your microphone. The track below is synthesized in your browser and run through the same analysis.

Press play. No microphone needed.

Listen along: 34 seconds of music, heard the way the site hears it

The track is synthesized in your browser and loops. It grooves, goes quiet, then drops.

0:00 of 0:34
HearsFour bands, each against its own recent peak
Bass20 to 150 Hz
Low mids150 to 500 Hz
Mids500 Hz to 2 kHz
Highs2 to 8 kHz
Finds beatsA jump in the bass, above a moving threshold

Bars are the change in bass from one frame to the next. The line is the threshold. 0 beats so far.

Tracks sectionsLast second or two against the last 20
quiet belowdrop above

Quiet for 0.0 of 6 seconds.

MovesWhat each signal pushes on
  • Bass shrinks the pattern scale 1.00×
  • Bass lifts brightness, slew-limited +0.0%
  • Mids speed up the drift 1.00×
  • Highs agitate the warp 1.00×
  • Loudness raises saturation 1.00×
  • Each beat pushes hue and ripple phase 0%

The picture is a simplified 2D stand-in for the real shader. The analysis constants are the ones the site uses. Detection lags the music on purpose: a breakdown only counts after six quiet seconds.

Levels are relative. The spectrum is split into four bands and each is measured against its own recent peak, so a phone on a quiet desk and a laptop next to a PA both give a usable signal.

Beats come from change. The code tracks spectral flux below 150 Hz and fires when the jump clears an adaptive threshold, which means a steady bass pad doesn’t tick. A kick adds momentum to the ripple, cell and hue phases for a fraction of a second, so nothing jumps.

It also tracks sections. If short-term energy sits well below the long-term average for six seconds, that’s a breakdown, and everything slows to a float. The surge after it is the drop, which triggers a fast mutation, a bloom of light and a full-strength ghost of the wordmark, at most once every 30 seconds.

Between drops the music only nudges the picture. Bass throbs the scale and lifts the brightness, mids speed up the drift, and highs agitate the warp. The genome being nudged is still a random roll, so music picks when the dream changes, never what it changes into.

Then there’s what it won’t do. Beats are capped at three per second. Brightness follows the bass through a slew limiter, so it can’t flash faster than about 3 Hz, the WCAG threshold for flashing content. Color inversions show up now and then in silent mode, and they’re switched off while listening, because projected on a wall at a party they’d be a strobe.

35 KB, on purpose

The entire site is one HTML file of about 35 KB: a few shaders, some JavaScript and an inline SVG favicon. There’s no framework, no build step, no analytics and no calls home.

That buys a few things. With no dependencies there’s nothing to upgrade and no supply chain. The microphone promise is checkable, because you can view source and look for a network call (there isn’t one).

The file also looks after itself. Render resolution drops when the frame rate dips below 46 fps. It honors prefers-reduced-motion by running at quarter speed. Without WebGL2 you get a slow CSS gradient instead of a blank page.

None of this is useful, which is roughly what you’d expect from the domain. But a useless project is where I get to practice things that are hard to justify on a roadmap, like accessibility nobody asked for, and finishing.

What would earn the word

The missing piece is a fitness signal. Right now a tap means “next,” which is selection pressure of a sort, but the code doesn’t remember it. If a tap meant “more like this” and the next genome were bred from the survivors, “genetic” would be accurate.

That would be a different site, and probably a worse screensaver. This one just dreams, and now and then your music wakes it up.

Try it

Go to yourmom.com and leave it running. Tap the ear in the corner to let it listen. Space or a tap forces a mutation, L toggles listening and F goes fullscreen. Add ?seed=42 to the URL and the dream becomes reproducible, which is how you test something that’s random by design.

The page’s meta description reads “you’ve been here before.” No further comment.