On seven months of building a personal music journal in Rust, the bugs that taught me more than the features, and why “which pair of headphones” turned out to be a harder question than “which track”.
Since the 3rd of January this year I have been building a thing called
Tapedeck. It is a self-hosted personal music journal written in Rust —
one binary, SQLite underneath, a web UI baked into the executable — and it runs on
a Raspberry Pi Zero 2 W in my flat, quietly recording everything I listen to, for
about another week until I admit it has outgrown the hardware. The source lives at
codeberg.org/abksh/tapedeck, under AGPL-3.0.
On paying off the one warning notice in the last article, why measuring a decoder is harder than writing one, and how four separate measurement bugs each made a good decoder look bad — quietly.
The Warning Notice I Left Myself
The last article1 ended on an admission I did not enjoy writing:
On why every open-source DSD decoder ships coefficients without proof, what happens when you try to regenerate someone else’s filter tables from first principles, and the 44 dB of aliasing rejection nobody was collecting.
The Problem I Actually Had
I have been building crête, a dynamic-range meter. Measurement tools have one obligation above all others: the number they print has to be about the music, not about the tool. So when I pointed it at DSD material, I needed to know what the decode path was doing to the signal before the meter ever saw it.
On splitting the Weyl tensor into a tide and a twist, why a gyroscope knows the black hole is spinning when a speck of dust does not, and how every spacetime ends up a wave if you go far enough away.
Where Part II Left Us
Part II ended with a table. Six spacetimes, six rows, a Petrov type in the last column, and a moderately satisfying story about how a quartic has exactly six ways to collapse. Schwarzschild came out type D. Kerr came out type D. The pp-wave came out type N. And axisymmetric Kasner — a vacuum cosmology with nothing black-hole-shaped about it — also came out type D, which was the surprise the whole post was built around.
At the end of the last article, I showed that the divergence of the Weyl tensor obeys
$$C^{abcd}_{;d} = J^{abc}$$
which looks suspiciously like Maxwell’s $F^{ab}_{;b} = J^a$, and I promised more technical things about this tensor in upcoming articles. This is one of those articles.
The topic is the Petrov classification. I read Chapter 31 of Nastase’s General Relativity: A Graduate Course1, which is six pages long and presents the classification the way most textbooks do: here are six types, here is a table of which Weyl scalars vanish for each, here are some example metrics.
A null-test follow-up to The Sausage Waveform Epidemic, in which I set out to prove my own thesis with numbers, and the numbers had other plans.
The Hypothesis
In the previous article, I argued that modern masters are compressed and limited into “codec-safe” sausages — and that this is why new albums sound the same on AirPods and on a proper wired chain. The claim hiding inside that argument is testable: a heavily compressed master should lose less to a lossy Bluetooth codec than a dynamic master does, because the mastering already destroyed the fine detail the codec would have thrown away. Less to destroy, less destroyed. In exchange, the crushing kills micro-dynamics and, so the folklore goes, the codec smears the soundstage on top.
Most of what I write here is a record of how something was built. The wiring, the config files, the dead ends, the moment it finally worked. I like those posts. They are honest in a particular, mechanical way — you can follow the steps and arrive where I arrived.
This is not one of those.
This is the long version. And the strange thing about the long version is that it is not actually very long in calendar time. A seed was planted a couple of years ago, quietly, and then for over a year it just sat there doing nothing. The real thing — the obsession, the collection, the gear, the slow dismantling of everything I thought I knew about sound — happened fast, in a frantic burst across the back half of a single year, faster than I would like to admit. That is the part I want to tell you about. Not because the timeline is impressive, but because that is genuinely how it felt: years of nothing, and then a few months of falling.
On rediscovering dynamic range, the tragedy of codec-safe mastering, and why Hilary Hahn’s Chaconne sounds glorious at 16-bit/44.1kHz
I recently upgraded my listening setup. A Schiit Mimir multibit DAC, a Midgaard amplifier, and a pair of Sennheiser HD 650s — connected with XLR, playing local FLAC files on a Fedora Linux desktop. No streaming service in the chain. No Bluetooth. No codec deciding what I’m allowed to hear.
The first thing I did was revisit albums I’d been listening to for years — Ilaiyaraaja’s synth-laden Tamil film scores from the 1980s, Hilary Hahn’s recording of Bach’s Chaconne, some Radiohead, some Evanescence, Michael Jackson’s later work. Music I thought I knew intimately.
The Goal: Hi-Res Audio Without Bluetooth Limitations
I wanted to stream hi-res audio from my Fedora Sway desktop (or my Sony Xperia 1 V or M3 Pro Macbook Pro) to my living room soundbar, or in general any audio like YouTube—without the compression, dropouts, and latency of Bluetooth. Bluetooth’s bandwidth limitations (especially with A2DP) cap quality, and the 200-300ms latency makes it unusable for video.
The solution: a Raspberry Pi 4 with HiFiBerry Digi+ Pro hat feeding my soundbar via S/PDIF, using Snapcast for network streaming. This setup gives me:
Over the past few weeks, I’ve been developing audiocheckr - an advanced audio analysis tool designed to detect fake lossless files, transcodes, upsampled audio, and various audio quality issues. Unlike many audio analysis tools that rely on machine learning, audiocheckr uses pure digital signal processing (DSP) algorithms to identify subtle artifacts left behind by lossy compression.
The project has evolved significantly, currently sitting at v0.2.1 with a comprehensive test suite, Jenkins CI/CD pipeline, and detection capabilities spanning multiple codec types including MP3, AAC, Opus, and Vorbis.