fix: copy albums whole when a re-level changes only their tags
Build and publish container / build (pull_request) Successful in 1m43s
Build and publish container / build (pull_request) Successful in 1m43s
A ReplayGain album gain belongs to the whole record, so a track arriving or leaving rewrites the tags on every one of its siblings. rsgain fits the new values into the padding its previous write left behind, which changes neither the file's size nor its mtime: before: 277757 bytes, mtime 1577880000, album gain 3.75 dB after: 277757 bytes, mtime 1577880000, album gain 6.25 dB Those are the two things rsync's quick check compares, so the siblings are invisible to it and the device keeps the old gains indefinitely. The track that arrived or left is always visible. So sync-to-ipod.sh now runs a second pass over the albums the first one touched, with --ignore-times to defeat the same quick check. touched_albums.py derives the list from rsync's own report of what it moved, which costs no extra traversal of either tree, and leaves out the tracks the first pass has already copied so a whole-album quality upgrade is not sent twice. Albums whose file set has not changed are left alone. A dry run reports how many further tracks are involved. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c63115f246
commit
9a3b4f9955
@@ -197,6 +197,16 @@ flight; only the two figures that needed the second walk are missing.
|
||||
Piped to a log it prints a plain line every thirty seconds instead, with no
|
||||
carriage returns, and a summary at the end either way.
|
||||
|
||||
### Albums that changed are copied whole
|
||||
|
||||
After the main pass, any album that gained or lost a track has the rest of its
|
||||
tracks copied again with `--ignore-times`. Their ReplayGain tags were rewritten
|
||||
in place when the album was re-levelled, which changes neither their size nor
|
||||
their mtime — the only two things rsync compares — so nothing else would ever
|
||||
send them. `touched_albums.py` works out the list from rsync's own report of
|
||||
what it moved, so this costs no extra traversal, and tracks the main pass has
|
||||
already copied are left out of it. See [Volume levelling](#volume-levelling).
|
||||
|
||||
### The Rockbox database
|
||||
|
||||
Point `MUSIC_MIRROR_DATABASE_TOOL` at Rockbox's host-side builder and the sync
|
||||
@@ -471,11 +481,16 @@ one.
|
||||
Turn it on at the player end under **Settings → Playback Settings →
|
||||
Replaygain**:
|
||||
|
||||
| Setting | Suggested | Why |
|
||||
| ---------------- | -------------------- | --------------------------------------------------------- |
|
||||
| Replaygain type | `Album Gain`, or `Track Gain if Shuffling` | Keeps a record's own dynamics; the second switches per mode |
|
||||
| Prevent clipping | `Yes` | Uses the peak tags to back off rather than distort |
|
||||
| Pre-amp | `0 dB` | The reference level is already −18 LUFS; move it only if the result is too quiet |
|
||||
| Setting | Suggested | Why |
|
||||
| ---------------- | ---------------------------- | ---------------------------------------------------------- |
|
||||
| Replaygain type | `Track Gain if Shuffling` | Album gain while playing a record, track gain once shuffle is on — the only setting that is right in both cases |
|
||||
| Prevent clipping | `Yes` | Backs the gain off using the peak tags rather than distorting |
|
||||
| Pre-amp | `0 dB` | The reference is already −18 LUFS; raise it only if everything ends up too quiet |
|
||||
|
||||
`Track Gain if Shuffling` is not a compromise between the other two — Rockbox
|
||||
reads the shuffle setting and picks whole-hog album or track gain from it
|
||||
(`apps/misc.c`, `replaygain_setting_mode`). It is also Rockbox's default, so on
|
||||
a fresh install there may be nothing to change but `Prevent clipping`.
|
||||
|
||||
Measuring costs a full decode of every track, so the first pass after enabling
|
||||
it takes roughly as long as the original encode did. After that only albums
|
||||
@@ -488,6 +503,25 @@ Tagging rewrites the file, and staleness here is an mtime comparison, so
|
||||
look newer than its source and the next pass would re-encode the entire
|
||||
library.
|
||||
|
||||
That has a consequence for the sync, and it is not obvious. The first time a
|
||||
track is levelled its tag grows by about a kilobyte, so its size changes and
|
||||
rsync copies it — the whole library goes across once, and there is no way
|
||||
around that; the tag sits at the head of the file and every byte after it
|
||||
moves. But `rsgain` leaves padding behind, so a *later* re-level fits inside it
|
||||
and changes neither the size nor the mtime:
|
||||
|
||||
```
|
||||
before re-level: 277757 bytes, mtime 1577880000, album gain 3.75 dB
|
||||
after re-level: 277757 bytes, mtime 1577880000, album gain 6.25 dB
|
||||
```
|
||||
|
||||
Those are the two things rsync's quick check compares, so it would see nothing
|
||||
to do and the device would keep the old gains. `sync-to-ipod.sh` handles it: the
|
||||
track that arrived or left is always visible, so any album the main pass
|
||||
touched has the rest of its tracks copied again with `--ignore-times`. Albums
|
||||
whose file set has not changed are not touched, which is what keeps this from
|
||||
being a full re-copy.
|
||||
|
||||
## Getting the result onto an iPod
|
||||
|
||||
The mirror is just a directory of MP3s, so any client will do:
|
||||
|
||||
Reference in New Issue
Block a user