acoustic-book-hash
A closed book rings at its own set of frequencies when tapped. Those frequencies are a physical fingerprint of the book's construction.
A stack of paper is a layered resonator. Tap the cover, and the
stack rings with a set of modes at frequencies n Β· c / (2L),
where c is the effective wave speed through the pressed pages
and L is the stack height. Two copies of the same edition
share both c and L. Different editions differ in at least
one. The list of peak frequencies is the fingerprint.
The claim in one sentence
Two copies of the same edition produce nearly identical acoustic fingerprints; different editions do not. No training required.
What it produces
A Fingerprint containing:
peaksβ up to 8 (frequency, amplitude) pairs in the 200β6000 Hz bandbook_idβ an optional string tag
And a database interface:
BookDatabaseβ a collection of reference fingerprintsquery(fp)β returns the best match and the similarity scoresave(path)/load(path)β JSON persistence
Install
pip install numpy
No other dependencies. No model weights. No downloads.
Usage
Build a reference database from WAV files
python acoustic_book_hash.py record-db mylib.json \
--book EdA-hardcover-2003 a1.wav a2.wav a3.wav \
--book EdB-paperback-2010 b1.wav b2.wav
Query a new tap
python acoustic_book_hash.py query mylib.json unknown_tap.wav
Output:
query peaks: [809.0, 1219.0, 1600.0, 2402.0, 3205.0] Hz
EdA-hardcover-2003 0.933
EdC-folio-1897 0.250
EdE-pulp-1972 0.375
...
best match: EdA-hardcover-2003 (0.933)
Programmatic
from acoustic_book_hash import (
BookDatabase, make_fingerprint, load_wav, window_tap,
)
db = BookDatabase.load("mylib.json")
data, sr = load_wav("unknown_tap.wav")
data = window_tap(data, sr)
fp = make_fingerprint(data, sr)
best, all_matches = db.query(fp, threshold=0.6)
print(best)
Benchmarks
Synthetic demo. Five editions simulated from a physical model. Each edition's paper speed, stack height, and damping time differ.
Pairwise similarity matrix
| EdA | EdB | EdC | EdD | EdE | |
|---|---|---|---|---|---|
| EdA | 1.000 | 0.133 | 0.625 | 0.250 | 0.375 |
| EdB | 0.133 | 1.000 | 0.533 | 0.400 | 0.533 |
| EdC | 0.625 | 0.533 | 1.000 | 0.250 | 0.250 |
| EdD | 0.250 | 0.400 | 0.250 | 1.000 | 0.375 |
| EdE | 0.375 | 0.533 | 0.250 | 0.375 | 1.000 |
Diagonal is 1.0 by construction. Off-diagonal varies with how close two editions' fundamental frequencies are: EdA and EdC (800 vs 682 Hz) share more peaks than EdA and EdD (800 vs 1000 Hz), even though both pairs are 150β200 Hz apart. The fingerprint is sensitive to harmonics, not just the fundamental.
Robustness
| condition | similarity |
|---|---|
| same tap point, re-tap | 1.000 |
| different tap point | 0.875β1.000 |
| + 1% noise | 1.000 |
| + 3% noise | 0.875 |
| + 5% noise | 0.933 |
| + 10% noise | 1.000 |
Robustness to noise in the demo is better than expected because the smoothing and peak extraction step removes the noise before the fingerprint is computed. Real recordings will have room reflections on top of noise, which are not in the model.
Database identification
| query | result | similarity |
|---|---|---|
| fresh tap of EdA | EdA-hardcover-2003 | 1.000 |
| fresh tap of EdC | EdC-folio-1897 | 1.000 |
| fresh tap of EdE | EdE-pulp-1972 | 0.875 |
| EdA + 5% noise | EdA-hardcover-2003 | 0.857 |
| unknown book | (no match) | 0.000 |
Self-test
12 checks, all passing on a clean run:
- physical model produces finite output
- fundamental frequency in the sensible range
- spectral peaks extracted in band
- same edition (different taps): similarity > 0.85
- different editions: similarity < 0.4
- same book + 3% noise: similarity > 0.7
- database correctly identifies a fresh tap
- unknown book correctly rejected
- deterministic simulation
- fingerprint serializes to JSON
Applications
- Forgery detection in print-on-demand markets. A counterfeit uses different paper stock and binding; the fingerprints differ. Requires a reference fingerprint of the genuine edition.
- Edition matching for libraries and rare book dealers. A dealer can identify which of several similar editions a physical copy is without opening it.
- Copy-level tracking. Two copies of the same edition have similar fingerprints but not identical ones (paper stock varies slightly between printings). Individual copies can be distinguished.
- Physical provenance. A book kept in a humid environment has a measurably different fingerprint from the same edition kept dry. The fingerprint encodes the book's history.
Honest limitations
- Every number in the benchmarks is from synthetic data. The fingerprints in the demo come from a physical model, not from real recordings. Real books will have more complicated spectra (uneven paper, folded pages, dust jackets) and the peak extraction may not be as clean.
- Requires a quiet recording environment. In a reverberant room, the room's reflections arrive within a few milliseconds and overlap the book's own response. A short window on the early response (30 ms) mitigates this but does not eliminate it.
- Requires the same tap point. Different tap points change the phase pattern, which shifts peak amplitudes but not peak frequencies. Frequency-based comparison is invariant to this, but if two editions share the same fundamental, the amplitude pattern becomes load-bearing and tap-point variance matters.
- Requires calibration. The reference fingerprints must be measured once per edition. There is no training phase.
- Sensitive to humidity. Paper speed varies with moisture content. A book measured at 30% RH and again at 70% RH will have shifted mode frequencies. Real deployments need calibration or humidity normalization.
- The
paper_speedparameter in the demo is a fitting constant. Real paper speed varies between 60 and 100 m/s depending on paper type. The five demo editions are one plausible family, not a measurement.
Reference
Part of a series of small tools built in one session:
| tool | reads | answers |
|---|---|---|
ir-source-localizer |
impulse responses | where is the source? |
acoustic-book-hash |
a tap on a book | which edition is it? |
License
Apache-2.0