The first version of my bake-off document said my tool recovered 6 to 12 dB more of the clean
signal than either established declicker I could find. It also said, if you read it
carefully, that most of that lead came from being scored on its own click bank. I had
harvested clicks from real 78
transfers, trained on them, and then built the test corpus out of the same harvest with a
different split. Nobody else's detector had ever seen that kind of damage. Mine had seen
nothing else.
So I broadened the training damage model and measured again. This is what that bought, and
what it didn't.
The tool, briefly
grooveclean finds clicks in vinyl and 78rpm
transfers with a small dilated 1-D CNN, 84,865 parameters, 46 ms of receptive field, and
fills each one by least-squares autoregressive interpolation. It writes three files: the
cleaned audio, the exact difference, and a JSON report of every click it touched. That
difference file matters later, so: out + removed == in, sample for sample, and the test
suite checks it on every bit depth and sample rate the tool accepts.
Building a benchmark that isn't on my side
Three tools, same audio, same scoring: grooveclean,
Needledropper's Declicker (AR
prediction error over a wavelet decomposition) and Wave Corrector PE (closed source, still
the default answer in most transfer threads). 46 clips, 20 seconds each, 16-bit 44.1 kHz
stereo, built from the held-out test split.
Two of the corpus decisions go against me on purpose. My training mixer rolls the music off
between 4 and 16 kHz to imitate a shellac transfer, so the corpus is left full band, which is
the condition my detector is least tuned for. And it's stereo rather than mono, because both
competitors have cross-channel logic that mono would switch off.
The headline number is the SNR of each output against the true clean signal. No event
matching, no tolerance window, no argument about what counts as a click, and no way for a
tool to move it by reporting its work differently. Precision and recall come second and are
derived identically for all three: a sample the tool changed is a sample it claims was
damaged.
Seven sets, and the set is what decides what a result means. general and percussive use
clicks harvested from real transfers, which my detector trained on. resonant (synthesised
damped ringing) and gouge (the same, replacing samples rather than adding to them) were the
held-out families in version one. scratch (a shock then a decaying train of repeats) and
dropout (quiet noise replacing the music for up to 20 ms) were held out and stayed held
out. Plus a control set of music with nothing wrong with it.
Where version one fell over
On general and percussive, the sets built from harvested clicks, I recovered 6 to 12 dB
more than either of them. On resonant my detection F1 was 0.650 and the lead shrank to
about 4 dB. On gouge the F1 was 0.721 and all three tools finished within 0.6 dB of each
other. Two programs that know nothing about my click bank drew level the moment the damage
stopped coming out of it, which makes the headline a measurement of how close the test damage
was to the training damage and not much else.
So version 1.1 put both families in the mixer. A quarter of injected clicks became
synthesised damped resonances, and a fifth of all damage started replacing the samples
underneath it instead of adding to them.
Did that help
Gain in dB at each version's best setting, which is the whole answer:
| set | held out of training? | 1.0.1 | 1.1 |
|---|---|---|---|
| general | no | +16.8 | +17.3 |
| percussive | no | +18.9 | +17.4 |
| resonant | added to 1.1's mixer | +10.6 | +13.7 |
| gouge | added to 1.1's mixer | +6.7 | +11.3 |
| scratch | yes | +13.2 | +13.0 |
| dropout | yes | +0.0 | -0.0 |
On the two families the mixer gained, detection F1 went from around 0.7 to around 0.96 and
the recovered signal improved by 3 to 5 dB. On the one held-out family anything can repair at
all, it moved 0.2 dB in the wrong direction.
Writing more kinds of damage into the training set bought competence at those kinds of
damage. It did not buy generalisation. Those two sentences cost me a full retrain to be able
to write honestly, and I'd have guessed the opposite before running it.
The part that actually stung
resonant and gouge are no longer evidence about anything. They were held out, they showed
a weakness, I reacted to the weakness, and the moment I did that they became training sets
wearing the clothes of an evaluation. The improvement on them is real and it is also
unfalsifiable as a generalisation claim: of course the model got better at the thing I taught
it.
That leaves exactly two families in the document that can still say anything about unseen
damage, and I picked them to break the two assumptions every trained declicker shares: that
damage is one short event, and that damage is louder than the music it lands in. If I ever
train on those, I'm out of evidence and I need new ones.
The general version of this isn't about audio. Your held-out set survives one honest use. If
you look at it, change something, and look again, you've converted it into part of your
training loop and the number it prints is now a training-set number. Budget for that. Keep
families you promise yourself you'll never touch, and write down what you'd have to see
before you're allowed to spend one.
Detection improving while nothing improves
dropout is worth its own paragraph, because it's a shape that's easy to misread on a
dashboard. Between 1.0.1 and 1.1 my detection F1 there went from 0.638 to 0.907. The model
genuinely learned something about damage quieter than the music, transferred from being shown
destructive damage that was louder.
The recovered signal stayed at zero. Every tool in the bake-off is within 0.3 dB of doing
nothing on that set, including Wave Corrector, which finds 95% of the events. Detection isn't
what fails. Interpolating across 20 ms of lost groove from the music either side does not put
the music back, whoever asked for it.
An F1 that climbs while the outcome metric sits still is not always a step forward. Here it's
the model getting better at identifying something the rest of the pipeline can't act on.
What it cost
Retraining wasn't free. About 1.5 dB on percussive material, and roughly 4 dB of headroom on
the faintest ticks: the default now finds harvested clicks down to about 7 dB over the local
music level where the old weights reached about 4 dB.
What it bought, besides the two families, was a much quieter default. On two minutes of
undamaged music:
| tool | setting | frames touched | per minute |
|---|---|---|---|
| grooveclean 1.1 | 0.50 (default) | 151 | 76 |
| grooveclean 1.0.1 | 0.50 (default) | 471 | 236 |
| Wave Corrector | threshold 3 (default) | 4,232 | 2,116 |
| Needledropper's | sensitivity 30 (default) | 33,764 | 16,882 |
At the settings each ships with, that's 28x less disturbance to undamaged music than Wave
Corrector and 222x less than Needledropper's. It's also the slowest of the three and the only
one that wants a GPU.
The thing I'd keep
Every number above is me marking my own homework, which is why the tool is built so you don't
have to take any of it. The difference file is the input minus the output. Play it and you
hear only what was taken away, so if there's a marimba note in there the tool got it wrong
and you know in seconds instead of listening to a whole side twice hunting for a hole.
grooveclean audit cuts the twenty biggest repairs into a before and after pair, about
thirty seconds of audio off a twenty-five minute side, and revert --clicks 511,512 puts any
of them back exactly, because what goes back comes out of the difference file rather than a
second guess.
That was the design constraint from the start and it held up better than the benchmark did.
If your model's output is subjective, ship the diff alongside the result and make the
invariant a test. The benchmark tells someone whether to try it. The diff tells them whether
it worked on their record.
The corpus builder, the harness and every sweep are in
bench/, so you can disagree with
the method rather than with me. pipx install grooveclean. MIT, offline, nothing phones home.
If you know a declicker I should have included, or a damage family that would break all three
of these, I want to hear it. The two I picked are only the two I could think of.
Top comments (0)