M1: IR Blend, Distance emulation, inter-IR phase alignment, broadened tests, docs#8
Merged
Conversation
Pure, off-audio-thread onset-detection and time-shift helpers used to align a secondary impulse response's transient onset to a primary one's before the two are blended together, preventing comb-filtering from timing mismatches between independently captured IRs.
- CabConvolutionEngine now owns a second convolution slot (IR B) and
crossfades it against IR A via a new IR Blend parameter (default 0%,
bit-identical to the previous single-IR signal path). Loading IR B
phase-aligns it against IR A's onset first.
- Adds a Distance parameter emulating mic-to-cab distance via a
proximity-effect low-shelf and an air-absorption high-shelf, applied
post-convolution/pre-LoCut. Defaults to 0% ("off"), using the same
bypass-at-the-extreme pattern as LoCut/HiCut so the default state
stays a bit-exact passthrough.
- PluginProcessor/PluginEditor wire both new parameters end-to-end,
including IR B file load/default controls, state save/load, and
latency reporting across both convolution slots.
- Unit tests for IrAlignment (onset detection, sample shifting, cross-sample-rate alignment). - Engine-level tests for IR Blend (0%/50%/100%) and Distance (passthrough at 0%, measurable attenuation at 100%). - Parameter/state/latency test updates for the two new parameters and the IR B file path. - New CoverageTests.cpp: sample-rate sweep (44.1-192 kHz) null and finite-output tests, mono/stereo/unsupported bus-layout tests, and long-run (2000-block, and 300-block-with-loaded-IRs) NaN/Inf stability soak tests. 50 Catch2 test cases green (up from 22).
- New docs/manual.md: full user manual (what Nave is, signal flow, complete parameter reference, usage tips). - README.md: updated feature list, signal-flow diagram, parameter table, and roadmap to match the actual GitHub milestones (M1-M4). - docs/architecture.md: updated signal-flow diagram and added sections on IR Blend/inter-IR phase alignment and Distance emulation; latency/parameter-smoothing/real-time-safety sections updated for the two-slot convolution engine. - CLAUDE.md: Status/DSP sections updated to reflect the M1 DSP work and the deferred "bundled IR library" scope. - CHANGELOG.md: moved Unreleased content into a 0.1.0 section and documented everything added in this pass, including what was deferred and why.
CabConvolutionEngine::process() copied the scratch buffer for IR B's convolution *after* convolution.process() (IR A) had already mutated `block` in place, so the "B" side of the crossfade convolved IR A's already-processed output instead of the original dry input - IR_B(IR_A(input)) instead of the intended IR_B(input). This only stayed hidden while IR A was the untouched identity/delta IR, exactly the setup every prior IR Blend test used. Copy the pre-convolution samples into scratchBuffer before convolution.process() runs, so both convolution branches process the same original input. Add a regression test that loads two distinct, non-identity IRs into both slots (the plugin's headline use case) and verifies the blended output against references rendered independently of the blend code path - a naive reference derived from the buggy blend branch itself would stay linear in Blend and mask the defect.
Add an explicit note that both convolution branches process the same original dry input rather than being chained, and reference the regression test coverage - the docs already described this (correct) intended behaviour, but didn't call out the ordering that makes it true, which is exactly what the CabConvolutionEngine.cpp fix in the previous commit restores.
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.
Summary
Implements milestone M1 - DSP completion & test coverage for Nave and prepares the v0.1.0 release.
DSP (issue #1, partially - see below)
IR Blendparameter. Defaults to 0% (IR A only) - bit-identical to the pre-M1 single-IR signal path, so no existing preset's sound changes.src/dsp/IrAlignment.{h,cpp}) so its transient onset matches IR A's most recently loaded onset, before the two are ever blended - prevents comb-filtering from a timing mismatch between independently captured IRs. Alignment is computed in time, not raw samples, so it stays correct across differing IR sample rates.Convolution (IR A/IR B blend) -> Distance -> LoCut -> HiCut -> Mix -> Level.getStateInformation/setStateInformation.Deferred: the "IR browser + bundled IR library" part of issue #1 is not implemented in this pass - see the issue comment for the full rationale (asset-sourcing/licensing concern, not a DSP task; better scoped into M2/M3). Issue #1 is left open.
Test coverage (issue #2 - closes)
tests/IrAlignmentTests.cpp: onset detection, sample shifting, cross-sample-rate alignment.tests/CoverageTests.cpp: sample-rate sweep (44.1-192 kHz) null + finite-output tests, mono/stereo/unsupported bus-layout tests, and long-run (2000-block, and 300-block-with-loaded-IRs) NaN/Inf stability soak tests.50 Catch2 test cases green (up from 22), each well under a second locally.
Documentation
docs/manual.md: full user manual (what Nave is, signal flow, complete parameter reference, usage tips).README.md: updated feature list, signal-flow diagram, parameter table, and roadmap (now matching the actual GitHub milestones M1-M4).docs/architecture.md: updated signal-flow diagram, new sections on IR Blend/phase alignment and Distance emulation, updated latency/smoothing/real-time-safety sections for the two-slot convolution engine.CLAUDE.md: Status/DSP sections updated.Versioning
0.1.0(no change needed).CHANGELOG.md: movedUnreleasedcontent into a[0.1.0] - 2026-07-14section documenting everything above, including the deferral.Test evidence
TestsandNave_Standalonebuild cleanly (no warnings).ctest: 100% tests passed, 50/50, ~11s total wall time.Closes
Closes #2