8.28.26 four-mic master
Eight mics down to four channels, four separate 4.97 GB files off Google Drive, stacked into one time-synced master and verified bit-exact against every source.
The four sources
All four came off Drive as separate stereo files. The recorder wrote them on one clock, which shows in four identical durations.
| Ch | Local file | Drive title | Bytes | Duration s |
|---|---|---|---|---|
| 1 | mic1_4-40PM.wav | 4.40 PM | 4,966,484,332 | 18745.373515 |
| 2 | mic2_4-48PM.wav | 4.48 PM 3 | 4,966,484,332 | 18745.373515 |
| 3 | mic3_4-53PM.wav | 4.53 PM | 4,960,025,948 | 18745.373515 |
| 4 | mic4_4-44PM.wav | 4.44 PM II | 4,966,484,332 | 18745.373515 |
One file carries one mic
Every source is true dual-mono. Sampled 20 s at 30, 90 and 180 minutes into each file, the left and right channels are bit-identical:
Correlation
+1.000000 in every one. Half of each 4.97 GB file is a duplicate of the
other half, so four files give four real channels, which is exactly the four-channel submix off
eight mics. The merge takes one channel per file and discards the duplicate.The lags between mics are acoustic, not clock drift
GCC-PHAT against mic1. If these were clock offsets they would hold steady or drift in one direction. They move with the window instead, because the loudest source moves.
| Window | mic2 samples | mic2 | mic3 samples | mic3 |
|---|---|---|---|---|
| 30 min | +539 | 12.222 ms | +626 | 14.195 ms |
| 90 min | +541 | 12.268 ms | +636 | 14.422 ms |
| 180 min | +551 | 12.494 ms | +643 | 14.580 ms |
| 240 min | -207 | -4.694 ms | -161 | -3.651 ms |
12 ms of air is about 4.1 m and 14.5 ms about 5 m, both plausible room distances. So the master stacks at zero offset. Correcting these lags would smear the room image, which is the failure the multi-mic tooling exists to prevent.
The phone tape shares the recorder's clock
The song timecodes were derived from the 24 kbps AAC that Messages produced. Rather than assume they transfer, the phone tape was cross-correlated against mic1 at six windows:
| Window | Offset | peak / median |
|---|---|---|
| 10 min | +0.0697 s | 521.6 |
| 45 min | +0.0697 s | 1008.6 |
| 90 min | +0.0697 s | 832.2 |
| 150 min | +0.0697 s | 192.2 |
| 210 min | +0.0697 s | 357.2 |
| 270 min | +0.0697 s | 356.9 |
No drift at all. The phone runs 69.7 ms late, so
mic_time = phone_time − 0.0697
converts every song boundary onto the mic feeds.Bit-exact verification
Each master channel read against its own source, raw channel to raw channel, no downmix anywhere in the path:
| Window | ch0 vs mic1 | ch1 vs mic2 | ch2 vs mic3 | ch3 vs mic4 |
|---|---|---|---|---|
| 20 min | 0.000e+00 | 0.000e+00 | 0.000e+00 | 0.000e+00 |
| 120 min | 0.000e+00 | 0.000e+00 | 0.000e+00 | 0.000e+00 |
| 260 min | 0.000e+00 | 0.000e+00 | 0.000e+00 | 0.000e+00 |
Twelve of twelve bit-exact, RMS ratio 1.000000 in every cell. The FLAC master is
a lossless container around the same samples the recorder wrote.
Expanding to WAV
ffmpeg -i practice-8-28-4ch.flac -c:a pcm_s24le -rf64 auto practice-8-28-4ch.wav
FLAC was chosen because a 4-channel 24-bit WAV of this runtime is 9.9 GB and the drive had
13.4 GB free at that moment. Measured FLAC ratio on real content was 0.468.
Eight things that went wrong
The candidate filenames used a plain space. Google Drive writes
U+202F, a narrow no-break space, before PM. Proven from manifest.json on all three feeds that had already landed. The watcher sat silent for hours on a name that does not exist on disk.An interactive shell enumerates it fine. A background job gets nothing from a glob, and a permission-bit test still reports the directory readable, so the check has to be a real probe. The daemon logs
glob=BLOCKED exact-stat=yes every tick. Detection by exact path works, and reading the bytes is a separate capability that fails on its own.The first watcher and merger ran as children of a chat process and vanished silently when it exited, losing about three hours. Everything now runs under a launchd agent.
pgrep -f practice-8-28-4ch matched any process merely naming the file, so the daemon logged “merge in progress” and skipped every tick while the fourth mic sat ready on disk. Now scoped to ffmpeg.*.The log line ran outside the
&& chain, so a failed copy still printed “imported” with an empty byte count. The copy result and the resulting size are both checked now.A 5 GB copy takes about 40 s, long enough for a daemon tick to begin during an interactive import and write into the same fixed
.part path. The temp path carries the PID now. The file was verified clean anyway, cmp against the Drive original returned 0.The first merge died with
Invalid argument before writing a byte. The format is explicit now and the temp file carries a real extension.A first pass compared master channels against sources decoded with
-ac 1 and every channel read 0.70711, exactly 1/√2, which looks precisely like a pan-filter downmix normalization. pan=mono|c0=c0, pan=1c|c0=c0 and channelsplit all produced the identical figure, and a filter difference cannot survive channelsplit, which applies no gain. Reading the raw interleaved channel instead gave bit-exact agreement. -ac 1 inflates dual-mono by √2.The 27 complete songs
Out of 120 takes: 27 songs, 7 false starts, 13 workshop passes, 59 fragments, 14 noodles. The last column is the corrected start on the mic master.
| # | Start | End | Sec | Score | BPM | Mic start s | 4-ch cut |
|---|---|---|---|---|---|---|---|
| 1 | 0:00:00 | 0:07:41 | 461 | 87.4 | 118 | -0.0697 | 127 MB |
| 2 | 0:53:01 | 0:58:46 | 345 | 86.3 | 118 | 3180.9303 | 104 MB |
| 3 | 1:00:54 | 1:07:19 | 385 | 82.6 | 102 | 3653.9303 | 116 MB |
| 4 | 1:08:14 | 1:11:39 | 205 | 81.9 | 133 | 4093.9303 | 64 MB |
| 5 | 1:19:21 | 1:25:49 | 388 | 89.0 | 102 | 4760.9303 | 121 MB |
| 6 | 1:36:40 | 1:39:13 | 153 | 72.4 | 133 | 5799.9303 | 47 MB |
| 7 | 1:39:26 | 1:44:05 | 279 | 91.2 | 54 | 5965.9303 | 87 MB |
| 8 | 1:44:28 | 1:46:00 | 92 | 75.1 | 129 | 6267.9303 | 30 MB |
| 9 | 1:51:29 | 1:53:49 | 140 | 73.7 | 110 | 6688.9303 | 40 MB |
| 10 | 1:59:59 | 2:02:02 | 123 | 88.4 | 76 | 7198.9303 | 40 MB |
| 11 | 2:02:20 | 2:11:13 | 533 | 91.8 | 118 | 7339.9303 | 174 MB |
| 12 | 2:12:33 | 2:14:32 | 119 | 80.5 | 118 | 7952.9303 | 36 MB |
| 13 | 2:21:16 | 2:31:50 | 634 | 84.5 | 100 | 8475.9303 | 199 MB |
| 14 | 2:46:42 | 2:49:25 | 163 | 79.3 | 113 | 10001.9303 | 46 MB |
| 15 | 2:52:01 | 3:00:03 | 482 | 88.8 | 120 | 10320.9303 | 151 MB |
| 16 | 3:01:21 | 3:08:07 | 406 | 81.0 | 98 | 10880.9303 | 129 MB |
| 17 | 3:10:51 | 3:23:23 | 752 | 81.0 | 81 | 11450.9303 | 219 MB |
| 18 | 3:23:56 | 3:30:06 | 370 | 83.2 | 113 | 12235.9303 | 114 MB |
| 19 | 3:35:51 | 3:45:22 | 571 | 80.9 | 107 | 12950.9303 | 155 MB |
| 20 | 3:47:38 | 3:50:53 | 195 | 77.3 | 107 | 13657.9303 | 60 MB |
| 21 | 3:55:09 | 3:59:44 | 275 | 84.3 | 100 | 14108.9303 | 82 MB |
| 22 | 4:00:08 | 4:04:42 | 274 | 83.5 | 92 | 14407.9303 | 83 MB |
| 23 | 4:04:58 | 4:07:17 | 139 | 80.5 | 143 | 14697.9303 | 42 MB |
| 24 | 4:10:07 | 4:20:27 | 620 | 91.2 | 125 | 15006.9303 | 197 MB |
| 25 | 4:22:11 | 4:32:09 | 598 | 83.6 | 128 | 15730.9303 | 165 MB |
| 26 | 4:32:15 | 4:54:04 | 1309 | 90.1 | 69 | 16334.9303 | 394 MB |
| 27 | 5:01:47 | 5:08:19 | 392 | 71.2 | 118 | 18106.9303 | 127 MB |
Per-song cuts
Written to
~/Music/Band-Practice/songs-8-28-4ch/, 3.15 GB total, each one
carrying the same four mics in the same order as the master. Every cut applies the 69.7 ms phone
correction, uses a sample-accurate seek in place of -c copy, and is checked for length
and channel count before it is kept. Spot-checked against the master at the same instant:
all four channels 0.000e+00.