Reconstructed chapter · 2026-07

The −101 was one capture, not the instrument

Reconstructed chapter: 2026-07-03 → 2026-07-25 · Sources: 49 parent commits, 16 app commits, 56 memory-file changes (in 33 commits), 125 of Chris's prompts · Claude's side of the conversation is lost; Chris's words are verbatim from the prompt history, the rest is rebuilt from commits and memory diffs.

Where we started

At the start of July, Cascade measured THD+N (total harmonic distortion plus noise: everything left after the test tone is notched out, as a ratio to the tone) with a decode formula validated in June. But one number would not agree. With no device under test, in GenMon (the analyzer listening to its own generator internally, no cables), Cascade read about −113 dB at 0 dBV. The reference for APWIN, the vendor's Windows software, was −101 dB. The memory file was named cascade-thd-reads-12-db-cleaner-than-apwin-at-same-setup.

Ruled out by July: the LP/HP filter (register 0x04), and register 0x33, the June "smoking gun". Next was FuncSettling, with three APWIN BASIC procedures (.apb scripts) ready to capture: T53–T55.

The working belief: Cascade's setup differed from APWIN's somewhere, so the 12 dB was a Cascade bug.

Chris opened with: "I have just switched this over from a different machine. did we preserve memory? What was the most recent stuff completed in this project and what is next to do?"

The question

Why does Cascade read 12 dB cleaner than APWIN? Then, once the GenMon number was settled: can Cascade measure THD on a real external device through the XLR inputs, on both channels?

What happened

Jul 3: the move to a new machine. The "transfer" in 4a76b11's title was Chris moving the project to a new computer. On the old one it bulk-committed 188 investigation scripts and synced memory. The app commit e70a711 added seven THD init blobs (blob: a block of USB commands captured from APWIN and replayed byte for byte), and 33c074b added .gitmodules so fresh clones got the app. Nine minutes later Chris opened the new machine with the question above. Then two weeks of silence.

Jul 17, late evening: missing captures, and FuncSettling ruled out. Chris came back: "starting up again after a long time." The first problem was data, not physics: "it looks like we lost all the pcaps when transferring to this new machine somehow." Chris had them backed up and pointed Claude at the Google Drive folder. With T53–T55 back on disk, they were diffed against the T50 baseline. The set of distinct write payloads was "byte-identical (344) across all four runs". FuncSettling never reaches the wire. APWIN does settling in software (63ae1d7).

Then a settling-knee theory, and a draft fix. Timing analysis of the T41 capture (analyze_eb08_timing.py, 61d0746) showed APWIN reading EB08, the distortion-residual register, about every 130 ms. The value decays over 4–6 reads, then holds near 293. Cascade read about 75. The memory description was rewritten to "ROOT CAUSE FOUND". Chris's answer was "yes draft it. think about long term foundational fixes", and a settle-until-stable read, _settledRead, was drafted and checked against T41's real decay. It converged to −100.88 dB (0cfefdb).

Jul 18, past midnight: the device test said no. On hardware the settled read was flat at −113 from the first sample. An early-sampling diagnostic showed Cascade's residual falling 733 → 77 in one 130 ms step and holding at 73–77. It never paused near 293. The fix was reverted: "THD floor is DSP state, not timing" (96539c7, app 50d8025).

Chris sends it back to the source. Rather than another round of captures, Chris pushed on the premise: "We have been chasing this for a very long time based on your tests. So, go back to why you thought the difference was so real." One commit then added four successive entries to the memory file (f097f90, 00:38):

The answer was already in a spreadsheet. At 00:45, e263aee closed it. APWIN's own exported results from the thd-0dbv run (its displayed "Anlr THD+N R" column) read −110 to −113 dB from 20 Hz to 20 kHz, and −112.6 at 1 kHz. Cascade read −111 to −113. The −101 had come only from T41, a one-off calibration capture. The memory now opened with "RESOLVED 2026-07-18 — no Cascade bug", and added a method note: APWIN's exported result log is the ground truth for what APWIN shows.

A real bug Chris had been pointing at. Chris did not let the closure cover everything: "so are you saying then that cascade is correct? One major difference is that cascade always has the high THD part at the initial frequencies." And: "APWIN does not ahve that issue". The first sweep point read −90.8 at 20 Hz. Asked for "the most long term foundational fix", Chris chose: "yes do B. we are trying to get as close to the real APWIN as we can." So the _settledRead primitive, built for the wrong problem, was wired in as "Option B (settle-then-read)" at every point, with a timeout that grows at low frequency (9d9fd09). On the device 20 Hz settled to −111.6 dB. That took 66 polls and about 8.6 s. Every later point converged in 4 (1ad5602, app d7226ec).

Jul 18–24: Chris proposes a real device. That evening Chris asked "if this is a good time to test a device plugged into the AP unit." Six days later Chris offered a passive preamp: "i can test a schiit sys passive preamp. It won't add much noise or distortion. I can set it for unity gain." Path: generator → SYS (RCA) → the 2522's XLR input.

Jul 25, after midnight: Chris's observations break the level display. It was the first hardware check of the input switch 8A 01 24/25. The frequency response was flat 0 dB and Ch A tracked the SYS knob (b4f0f4f). But Chris kept noticing things that did not fit. Turning the volume down gave "a strange result. the channel a measurement went up." Then: "i do think it's odd that the scale shows so close to 0db when on the oscilloscope the measurement was not 0db." The cause: at quarter volume the raw level count fell from about 31825 to about 700, but the display said −7.5 dB. The level formula was linear in counts, so every small signal floored near −7.6. After the logarithmic fix Chris supplied the check: "one at approximately 1/4, which was in the area of -46dB, then I turned the volume up a little at about 2.5kHz and the line went up to around -41." (8c06473, 018b1fa). Chris also overruled blanking the empty channel: "the crosstalk is valuable to see."

A second layer under the first-sweep bug. On the first frequency sweep of a session the generator was never really switched on. Connect set the "on" flag without running the power-up, so sweep start skipped it. Forcing off-then-on fixed it. A thru-cal (a no-DUT reference sweep subtracted from later sweeps) came back, in Chris's reading, "a and b are close to 0". With the SYS inserted at full volume it read about −0.04 dB (1ddb425, app aaf4c20).

Ch B THD was a fake. The memory had called the Ch B decode a probable copy-paste bug: both channels decoded the same buffer. A survey of every capture showed the hardware design instead: EB08 is one residual register, muxed to whichever channel is armed (574a9ef). Chris asked for the evidence as a procedure: "Write an APWIN procedure that I launch in APWIN to do exactly what you want". That was T60, APWIN measuring Ch B. The selector was 8A 01 06 20, and the decode matched APWIN's logged −100.8 dB (6a81111, a1f8596).

DUT THD: three wrong turns, then Chris's idea. Chris's first run: "it looks like channel a was not separated out." The next build: "this test is a flat line, both channels at -999dB all the way across". The input switch had rewritten registers the GenMon blobs set up, so it was reverted (app e2b1791). A DUT setup blob cut from T60 got the signal through, but the residual froze. A port of APWIN's per-point register-0x48 sequence came next (d8ae77c, 393ddb5), and Chris caught a design slip: "why would the CHB switch only apply to the genmon path? that doesn't make sense." Then Chris asked the question that changed the method: "would it help you at all to connect directly to the machine to run small unit tests?" A Python harness drove the instrument over USB directly. The memory records "~6 experiments in ~20 min". The 0x48 drive was "a red herring all along": the setup blob alone read −99.9, and running the drive pushed the residual from 328 to 8500. The XLR arm value for Ch B was 0x30, not the 0x20 read from T60 that morning (c09beaf, app 6740635). The app reproduced −99.7 to −99.9 flat, and with stereo cabling Ch A's 0x10 was confirmed (4e79ace).

Stereo, and Chris refuses a noise penalty. Two channels read about −88.5. Chris: "that doesn't sound right - the unit should be able to drive 2 channels without a 10db noise penalty". T61 had APWIN run the same stereo sweep. Chris renamed it _v2, remembering APWIN loading stale .apb content (93482a2). APWIN read −90.3 and −89.5, so the floor was real (27cd79b). Chris then designed the next test: "Are you able to just send signal to one? if you can control the output that should in theory give you the ability to test it as if it is unplugged". In T62 Ch A's output was toggled off; Ch B moved only from −90.38 to −90.16. The penalty came from the physical Ch A connection, not its drive (4638f51).

The last dB. Single-channel Cascade read −99.5 to −99.9 against APWIN's −100.8. Chris wanted the gap gone: "i am interested in getting it really close. this is a lab grade thing after all." Replaying APWIN's 176-packet integration loop 20 times moved EB08 only from 345 to 338 (c940347). The decision to stop was Chris's: "we can close that for now."

Late: off the blobs, and a wedged device. Chris set the next direction: "i would like to get to a place where we do not need to load in a packet capture for each amplitude." The blobs had been temporary: "it seems like you started to rely on them longer term." A probe found that the 8A amplitude bytes left the output near 0 dBV at every level tried. The commit concluded that amplitude lives in the generator DSP gain (ED 40/E6 40) (da9c3e8), and T63 was written to characterize it (1c08cf3). Then Chris: "the device is not responding right now on Windows." The probes had ended without a full generator-off. reset_ap.py was written and committed as having "Recovered the device" (02cd485). It had not, and Chris said so: "i don't think that's correct, because plugging it in on the windows side, it still could not connect." The memory was corrected a minute later (f3f2b2d).

The turns

  1. Jul 18, 00:32: "go back to why you thought the difference was so real." Chris questioned the premise, and within 13 minutes APWIN's own export closed what weeks of register diffs had not.
  2. Jul 18, 00:48: "cascade always has the high THD part at the initial frequencies." Chris kept the first-point bug from being swept up in "no Cascade bug".
  3. Jul 25: "the channel a measurement went up." Chris's doubt about a 0 dB reading exposed the linear level formula, which no internal-loop test had.
  4. Jul 25, 14:21: "would it help you at all to connect directly to the machine" Chris proposed the direct probe; six experiments showed the 0x48 drive was making things worse.
  5. Jul 25, 21:32: "Are you able to just send signal to one?" Chris designed T62, which separated drive crosstalk from the physical connection.

Beliefs that changed

BelievedThenWhat overturned it
FuncSettling is a missing device register (Jun 27)it is host-side; no wire writes (Jul 17)T53–T55: 344 distinct payloads, identical
Gap = APWIN catches the settling knee (Jul 17)not timing (Jul 18)Chris's hardware run: 733 → 77, no dwell near 293
−101 vs −113 is two APWIN flows, 0x33 the switch (Jul 18)retracted within the hourboth captures have 8715 writes to 0x33
Cascade reads 12 dB too clean (Jun 19)no Cascade bug (Jul 18)Chris asked why the gap was believed; APWIN's exported thd-0dbv: −110 to −113 dB
First sweep's −7.5 dBV is a settling problemlinear level-cal floor, plus generator never powered (Jul 25)Chris's SYS knob runs: count ~700 shown as −7.5
Ch B THD duplicate is a copy-paste bugEB08 is one muxed residual (Jul 25)corpus audit, then T60 arm-B capture
XLR THD needs APWIN's 0x48 drive (Jul 25, 13:18)the drive corrupts the residual (Jul 25, 16:17)direct probe Chris proposed: 328 → 8500
Stereo −90 is the Ch A drive leakingthe Ch A connection itself (Jul 25)T62, Chris's output-off test: moved 0.2 dB
The 1 dB single-channel gap is integration depthnot; Chris closed it for now (Jul 25)176-packet loop ×20: 345 → 338
reset_ap.py recovers a wedged unit (Jul 25, 23:21)not on Windows (23:28)Chris: it still could not connect

What we learned about the instrument

What we learned about working together

Evidence

Where we ended

GenMon THD+N was closed. External-DUT THD worked on one or two channels at 0 dBV only, with about 1 dB left at the noise floor, closed for now at Chris's call. The level formula and the first-sweep generator were fixed and verified on the device. Open: other output levels (only a 0 dBV DUT blob existed) and Chris's goal of getting off per-amplitude blobs; continuous amplitude (T63 written but not yet captured, blocked by the wedged unit); what made T41 read −101. The ED 40 amplitude conclusion did not last. A later memory index marks it SUPERSEDED, calling the ED40-gain claim "a GenMon artifact".