Spencer Hill

← Writing

July 11, 20263 min

Listening to my network

My home network has a mood. Mornings are a slow trickle of phones waking up. Evenings are a flood of streams and syncs. At 3am it hums to itself, running backups nobody watches. I spent a while staring at charts of this and then realized I didn’t want to see it. I wanted to hear it.

So I built Hum: a small self-hosted synthesizer that reads the live state of my network and turns it into an evolving ambient soundscape. Throughput, active connections, traffic spikes; drones, arpeggios, chimes. Nothing is a loop. It never plays the same thing twice.

The architecture argument I lost with myself

The obvious plan was server-side synthesis: SuperCollider on the mini PC, streamed over Icecast like a private radio station. I’d planned exactly that. Then I added knobs to the design and the plan fell apart, because a stream buffers for 5 to 30 seconds and a knob you turn now that responds in half a minute is not a knob, it’s a suggestion box.

The fix was to flip the whole thing: the server only serves numbers (a tiny Flask endpoint reading /proc once a second), and the synthesizer runs in the browser with Web Audio. Knobs respond instantly. No sound card, no audio drivers, no stream. Any device on my network opens a page and the network plays through it.

Making data musical (the hard part)

Mapping data to sound is easy. Making it musical is the entire project. Early versions had a problem I now think of as the meter you can hear: if throughput maps straight to pitch, you haven’t made music, you’ve made a dashboard for your ears, and it’s exhausting.

What worked was indirection. The network sets the weather, not the notes:

  • Connections set how wide the arpeggio ranges, throughput sets brightness and density
  • A traffic spike doesn’t beep, it rings a chime quantized to the next beat
  • The root key follows the time of day, bright at dawn, low and dark at night
  • A chord-progression engine plays real changes (the axis progression, a dorian vamp, a stretched ii-V-I) phrase by phrase, with occasional twists

On top of that sits a mood knob that crossfades between five full patches, each a vector of about 20 parameters: oscillator mixes, two reverb sizes, which instruments play, how restless the harmony is. Sweep it slowly and Deep’s sub-heavy drone becomes Aurora’s shimmer over about 10 seconds.

The bug I could hear

My favorite defect I’ve ever shipped: the plucked-string voice (a classic Karplus-Strong delay loop) used a lowpass filter with a default resonance just high enough that the loop gain crept over 1 at one frequency. Instead of decaying, plucks would die out and then swell back from the silence a second later, sharper each pass. A feedback loop, audibly compounding.

I’d read about loop gain a hundred times. Hearing it grow out of a quiet ambient bed at 11pm taught me more than all of it. The fix was three lines: kill the resonant peak, drop the feedback below unity with real headroom, and actively choke the loop before teardown. The string still rings; it just isn’t allowed to be immortal.

What’s next

Hum runs every day on a mini PC in my living room, playing the house to itself. Open source release soon: the collector is pluggable (anyone’s router can be an orchestra), there’s a synthetic mode for people without hardware, and a reference analyzer that listens to a track you like and generates a matching patch. The network deserves a soundtrack. Yours does too.