Files
reasampler/docs/verify-track-scope-multitrack.md
T

138 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DAW verification — track-scope capture over a multi-track selection
What a DAW pass must establish for the multi-track track capture, and the exact numbers
or strings to read off. Nothing below can be closed by a unit test: every item depends on
what REAPER actually does with a render request.
**Build to use.** Release, installed into `UserPlugins/`, REAPER restarted — extensions
load at startup only. Set the docked panel's tail toggle to **None** before every cell;
Auto adds an 8 s window and Manual a fixed one, and both would invalidate the frame-count
readings.
**Project to use.** One saved project, project sample rate pinned to 48000. Two audio
tracks, `A` and `B`, each holding one item at least 30 s long, with *audibly different*
content (a tone on `A`, a drum loop on `B`). One folder track `F` with `A` and `B` as its
children, used only in §5.
---
## 1. The regression floor — single-track track capture is unchanged
Select **track `A` only**. Make a time selection from **10.000 s to 12.000 s**. Run
*ReaSampler: capture selected track(s)*.
Read off:
- A file appears in the project's bank folder, and one new card appears on the panel.
- The card's length reads **2.000 s**; its frame count is **96000** (`round(12.0 × 48000)
round(10.0 × 48000)`). The backend refuses the capture with `BoundsMismatch` if the
render is more than one frame off that, so a landed capture already proves the number
to ±1 — what you are confirming here is that it landed at all.
- The REAPER console shows **no** `ReaSampler capture failed:` line.
- Track `A` is still the only selected track afterwards.
Repeat with a **razor area** on `A` over the same 1012 s span and no time selection: same
three readings.
**This is the byte-identical floor.** If either cell now refuses, the change is wrong —
the refusal must fire only above one track.
## 2. The defect cell — two selected tracks now refuse
Select **`A` and `B` together**. Time selection 10.00012.000 s. Run *capture selected
track(s)*.
Read off:
- The console prints exactly:
`ReaSampler capture failed: A track capture renders the selected tracks through the
master, and more than one track cannot land as a single file. Capture one track at a
time, or route them into a folder/bus track and capture that (a folder's own output is
its children summed).`
- **No** new card on the panel, and **no** new `.wav` in the bank folder (check the folder
directly — a stray file with nothing indexing it would mean the refusal fired too late).
- `A` and `B` are both still selected, both still unmuted, and neither track's fader, pan,
or FX-bypass state changed. The refusal returns before any guard is constructed, so
there should be nothing to restore — this reading is what confirms that.
Repeat with a **razor area spanning both tracks** and no time selection: identical
readings. Note that the track *selection* is what the refusal counts — a razor over two
tracks with only `A` selected is a one-track capture and must still succeed (§1).
## 3. The decisive observation — what `&128` actually writes
**This is the one that retires an inference, and it is the reason `docs/TODO.md` still
carries an entry.** The refusal in §2 rests on reading the SDK header's single-file bit
`&(4<<16)` as applying to item/razor sources only, never to `&128` — so N selected tracks
are believed to produce N files. That has never been observed.
Drive REAPER's own Render dialog by hand, with the extension out of the loop:
1. Select `A` and `B`.
2. File → Render. **Source:** *Selected tracks (stems)* — the dialog wording for `&128`.
**Bounds:** *Custom time range*, 10.000 to 12.000 s.
3. **File name:** a literal stem with **no wildcards at all** — e.g. `stemprobe`. Clear
`$track` / `$item` / anything else from the pattern; the extension writes exactly one
literal stem, so the probe must too.
4. Render to an empty scratch folder.
Read off — **the file count in that folder**:
- **Two files** (however REAPER disambiguated them, or one file that visibly got
overwritten): the inference holds, the §2 refusal is correct, and the `docs/TODO.md`
entry can be closed by writing this observation into `src/shell/capture/CLAUDE.md` as
fact.
- **One file containing `A` and `B` summed** (confirm by ear, or by nulling it against a
master render of the same range with only `A` and `B` unmuted): the inference is wrong,
the §2 refusal costs a working capture, and the track-scope half should be narrowed back
per the `docs/TODO.md` entry. The item-scope half stays either way.
Also record **what REAPER named the files** — that decides whether a future correct
multi-track capture could ever be built on this source at all.
## 4. Recapture replays the same answer
Take a **single-track** track capture that carries provenance (capture a range on `A`
whose source item is itself a bank sample, so `detectParent` fires), select its card, and
run *re-capture from source*. It must regenerate — same audio, same 96000 frames.
Then construct the multi-track case: a recorded recipe whose `trackGuids` names two
tracks. The reachable way to get one is to have captured it before this change; if no such
entry exists in any project, record that this cell was **not exercised** rather than
inventing one. When it is exercised, read off:
- `ReaSampler re-capture failed:` followed by the **same** message text as §2.
- The bank entry is untouched — same file, same hash, same card.
## 5. The way out actually works
Route `A` and `B` into folder `F`. Select **`F` only**, time selection 10.00012.000 s,
capture track scope.
Read off: one card, 2.000 s, and the audio contains **both** `A` and `B`. This is what the
refusal message tells the user to do, so it has to be true.
## 6. Realtime still accepts a multi-track selection
Select `A` and `B`. Run *ReaSampler: capture selected track(s) in realtime* over the same
range. Read off: **one** card, and its audio contains both tracks. Realtime taps each
source track with a send into one temp track, so it sums where the offline render cannot —
the divergence from §2 is deliberate and this cell is what confirms it is real.
## 7. Mono collapse — what is and is not reachable
Capture a range on a track whose content is dead-center (a mono source panned center, or
a duplicated-channel file). Read off:
- The panel card reports **1 channel**.
- The console shows **no** `the lossless mono collapse ... landed intact, as captured.`
line.
**Not DAW-reachable:** the collapse's *failure* branch. It fires only if the captured file
cannot be read, or its temporary rewrite cannot be written or renamed, inside the same
call that just rendered the file — there is no manual way to inject that fault between the
render and the rename. The branch is covered only at its reporting seam
(`tests/test_wav_codec.cpp`, `testCollapseOutcomesReportDistinctly`), and its console line
has never been seen in a running REAPER. If you ever do see it, the capture in question is
intact and correctly measured — only the size win was lost.