feat(LTX25-AUDIO-RESAMPLE): resample the take instead of refusing it, and the window is hann - #2585
Open
localai-org-maint-bot wants to merge 4 commits into
Open
feat(LTX25-AUDIO-RESAMPLE): resample the take instead of refusing it, and the window is hann#2585localai-org-maint-bot wants to merge 4 commits into
localai-org-maint-bot wants to merge 4 commits into
Conversation
…s window is hann (#2583) `ltx25-completion-scope.md` places A19 at order 7 because it gates A3 and A18: `Ltx2WaveformToLogMel` refuses every rate but the audio VAE's own, so any real take has to arrive pre-resampled. Upstream refuses nothing here; `ops.py:44-49` calls `resample_audio` before the mel transform, unconditionally. The reason written beside that refusal, in nine places across this tree, is wrong. It calls `torchaudio.functional.resample` "an arbitrary-ratio polyphase kaiser resampler". `resample` defaults `resampling_method="sinc_interp_hann"` (torchaudio 2.11 functional.py:1441) and only the `sinc_interp_kaiser` branch builds a kaiser window (:1384-1391); `ops.py:40` passes neither that argument nor `beta`. The window is hann -- the same family `Ltx2HannSincResampleFilter1d` already ports for the vocoder's BWE stage, which is this kernel at `orig_freq == 1`. What is missing is the rational ratio, not the filter. The spec's §4 records the measurement that decides the dtype, because it is the one place this port could quietly go wrong in a way no gate would see. Upstream resamples in float32 all the way down, kernel included, and building the same filter in double lands 1.03e-05 from the oracle where float lands 1.79e-07 -- a wider dtype reading as a looser gate rather than as an error. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
… and the window is hann (#2583) Closes #2583. Order 7 of `ltx25-completion-scope.md` §8, gap A19. `Ltx2WaveformToLogMel` refused every sample rate but the audio VAE's own, and `Ltx2DecodeAudioWav` refused it one hop earlier so the message could name the file. Between them, an audio-to-video render only accepted a take the caller had already resampled with some other tool. Upstream refuses nothing here: `waveform_to_mel` calls `resample_audio` before the mel transform (ops.py:44-49) and `resample_audio` filters whenever the rates differ (ops.py:36-42). `Ltx2ResampleWaveform` is `torchaudio.functional.resample` at the arguments ops.py:40 passes, which is to say at every default: gcd-reduced rational ratio, `lowpass_filter_width = 6`, `rolloff = 0.99`, one kernel row per output phase, conv with stride `orig`, and truncation to `ceil(new * length / orig)`. It is called from `Ltx2WaveformToLogMel` unconditionally, because upstream's rate test lives inside `resample_audio` and guarding at the call site would move that early return off the production path. The filter is HANN, and nine statements in this tree said kaiser. `resample` defaults `resampling_method="sinc_interp_hann"` (torchaudio 2.11 functional.py:1441) and only the kaiser branch (:1386-1391) builds i0-weighted taps; ops.py:40 passes neither that argument nor `beta`. It is the same window `Ltx2HannSincResampleFilter1d` already builds for the vocoder's BWE stage, which is this kernel at `orig_freq == 1`. What was missing was the rational ratio. All nine are repaired here, including the two in `ltx25-a2v-audio-input.md`, which is the row that wrote them. THE DTYPE IS f32 AND THAT IS THE MIRROR, NOT A SHORTCUT. Upstream's waveform is float32 from the decoder on (decode.py:173-176), `encode_audio` moves it without casting (audio_vae.py:271), and the kernel is built with `dtype=waveform.dtype`, so the filter itself is f32 (:1376-1397). Measured against the pinned oracle at four rate pairs, a `double`-built kernel narrowed to `float` lands 1.03e-05 away; the f32 one lands 1.79e-07. Widening would not have improved the port, it would have loosened the gate by fifty-seven and read as care. The gate is 2.5e-07, twice the measured floor: at 0.0 three of the four arms red at 5.96e-08, 5.96e-08 and 1.19e-07, and the equal-rate arm passes because it is a copy. Sections 8d and 8e of the golden generator run upstream's own `AudioProcessor` at those four ratios and through `waveform_to_mel` at a non-target rate, riding the existing revision anchor. Both reds were the refusal itself. `test_ltx2_video`'s case enters through `LoadVideoEngine` + `Generate` and pairs a 44.1 kHz take with the same PCM bytes relabelled 24 kHz, which is the wrong answer the refusal existed to prevent: deleting the production call site makes those two carry the SAME latent digest while the unit case over `Ltx2ResampleWaveform` stays green. One assertion was written, run, and removed rather than loosened. `audio_latent_absmax` reads 1.07194 / 1.07293 / 1.07208 across three genuinely different takes, so it cannot order them; the reason is recorded where the assertion was and the values are gated at the VAE level instead. This file's own scope note claimed the analysis half was not ported. The mel front-end has lived here since the A2V input row, so that sentence was already false; repaired in flow. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
…TX-2 file `origin/main` moved 21 commits ahead while this row built and gated. The only overlap is `docs/FEATURES.md`, where both sides edited different rows; the resolution keeps both, and `git diff origin/main -- docs/FEATURES.md` shows exactly one changed line, the A2V row this row owns. No source, header, test or golden this row touches appears in the incoming set, so nothing it measured moved under it. Re-verified after the merge: `polyphase kaiser` and `kaiser resampler` return ZERO hits across `src`, `include`, `tests`, `docs` and `.agents`, which is the claim the implementation commit makes about all nine sites. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
… could falsify `origin/main` moved another eight commits while this row finished its gate. The overlap is `docs/FEATURES.md` alone, on different rows; `git diff origin/main -- docs/FEATURES.md` is the one A2V line this row owns. Nothing in the incoming set touches an LTX-2 source, header, test or golden. Re-checked rather than assumed, because merging main has falsified a branch's own prose here before: `polyphase kaiser` and `kaiser resampler` still return ZERO hits across `src`, `include`, `tests`, `docs` and `.agents`, which is the claim the implementation commit makes about all nine sites. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(LTX25-AUDIO-RESAMPLE): resample the take instead of refusing it, and the window is hann
Closes #2583. Order 7 of
.agents/specs/ltx25-completion-scope.md§8, gap A19, which that plan places before A3 and A18 because it gates both.The gap
Ltx2WaveformToLogMelrefused every sample rate but the audio VAE's own (ltx2_audio_vae.cpp:1051-1060), andLtx2DecodeAudioWavrefused it one hop earlier so the message could name the file (ltx2_audio_input.cpp:96-105). Between them, an audio-to-video render only accepted a take the caller had already resampled with some other tool.Upstream refuses nothing here.
waveform_to_melcallsresample_audiobefore the mel transform (ops.py:44-49) andresample_audiofilters whenever the rates differ (ops.py:36-42).The reason written beside that refusal was wrong, in nine places
The message and eight sibling comments called
torchaudio.functional.resample"an arbitrary-ratio polyphase kaiser resampler". It is not one.resampledefaultsresampling_method="sinc_interp_hann"(torchaudio 2.11functional/functional.py:1441) and only the kaiser branch (:1386-1391) buildsi0-weighted taps;ops.py:40passes neither that argument norbeta. The window is the same hann this tree already builds for the vocoder's BWE stage —Ltx2HannSincResampleFilter1dis this kernel atorig_freq == 1. What was missing was the rational ratio, not the filter.All nine are repaired, including the two in
ltx25-a2v-audio-input.md, the row that wrote them.polyphase kaiserandkaiser resamplernow return zero hits acrosssrc,include,tests,docsand.agents.The port
Ltx2ResampleWaveformmirrorsresampleat every default: gcd-reduced ratio,lowpass_filter_width = 6,rolloff = 0.99, one kernel row per output phase, convolution with strideorig, and truncation toceil(new * length / orig). It is called fromLtx2WaveformToLogMelunconditionally, because upstream's rate test lives insideresample_audio(ops.py:38-39); guarding at the call site would have moved that early return off the production path.Ltx2DecodeAudioWavloses itswant_sample_rateparameter. Upstream's decoder has no target rate, and the parameter existed only to raise.The dtype is f32, and that is the mirror
Upstream's waveform is float32 from the decoder on (
decode.py:173-176),encode_audiomoves it without casting (audio_vae.py:271), and the kernel is built withdtype=waveform.dtype, so the filter itself is f32 (:1376-1397). Measured against the pinned oracle at four rate pairs:double, narrowed tofloatfloat, mirroring upstreamThe
doublefilter is more accurate than upstream and therefore fifty-seven times further from it. It would have passed a gate written around it and read as care. This is AGENTS.md's "a token gate cannot detect a dtype that is too wide" in its exact shape.The gate is 2.5e-07, twice the measured floor: at
0.0three of the four arms red at 5.96e-08, 5.96e-08 and 1.19e-07, and the equal-rate arm passes because it is a copy. A double-built kernel fails it by forty.Tests
Upstream ships none at this pin, so sections 8d and 8e of
gen-ltx2-vae-goldens.pyEXECUTE upstream's ownAudioProcessor— at four ratios chosen for arms rather than coverage (o = 1,n = 1,o = 441withwidth = 17, and the equal-rate early return), and throughwaveform_to_melat a non-target rate. They ride the generator's existing revision anchor, and regeneration is byte-identical.Red before, green after. Both reds were the refusal itself:
test_ltx2_vaeltx2_audio_vae.cpp:1053test_ltx2_video'high.wav' is sampled at 44100 Hz ...Reachability. The video case enters through
LoadVideoEngine+Generateand pairs a 44.1 kHz take with the same PCM bytes relabelled 24 kHz — the wrong answer the refusal existed to prevent. Deleting the production call site makes those two carry the same latent digest (18285287296143238670) while the unit case overLtx2ResampleWaveformstays green, which is the whole point of the mutation. The tree was restored byte-for-byte and both suites re-run green.One assertion was written, run, and removed rather than loosened.
audio_latent_absmaxreads 1.07194 / 1.07293 / 1.07208 across three genuinely different takes, a 0.1% spread, because the trace's absmax is dominated by the encoder's per-channel statistics. It cannot order them. The reason is recorded where the assertion was, and the values are gated at the VAE level instead.Also
This file's own scope note claimed the analysis half was not ported. The mel front-end has lived here since the A2V input row, so that sentence was already false; repaired in flow.
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [claude-code]