Conversation
…one-3000#89) Replaces the duration-derived short/long IR classification with an explicit, persisted IrCategory (Cab / IrPlayer) as the sole source of the -18 dB cab pad and default mix. Raw/trimmed file length is unreliable for this: catalog content includes cabs manually trimmed to seconds of file length around tens of ms of real content, so two versions of the same cabinet IR (one padded past the old 1 s cutoff) could land on wildly different perceived levels despite identical audible content. - Site-loaded tones resolve category synchronously from catalog `gear` metadata (loadTone), before the download even starts. Local file loads (no gear tag) seed it from a one-shot load-time duration guess instead - a real, editable value from the start, never re-derived afterward. - Engine selection (uniform vs non-uniform convolution) is fully decoupled from category and no longer duration-based on raw file length either: a known Cab is unconditionally the uniform engine, hard-capped to its first 500 ms at load (a real truncation, not just an engine hint); IrPlayer's engine choice comes from a fresh load-time RMS content scan instead. - setBlockIrCategory lets a block's category be changed at any time (V1: resets mix/pad to the new category's fixed default, no memory of a prior per-category setting). - Persisted through the existing ValueTree save/restore path; state saved before this field existed backfills via the same duration guess local loads use, without touching the mix the user actually saved. - UI: Cab / IR Player toggle on the IR block's detail view. New test/src/ir_category_tests.cpp exercises the actual tone-3000#89 regression (same content, different trailing silence, now produces bit-identical processed audio), the gear->category mapping, the category setter, and that engine selection stays content-based and decoupled from category. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01URpcSgm9HiuypH6TfWfqMg
This branch has not been deployed
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
Fixes #89.
ChainBlock::irIsLongwas doing two unrelated jobs: picking theconvolution engine (a CPU decision) and driving every audible IR default -
the -18 dB cab pad and the block's default mix (a perceptual/content
decision). Both read the same signal:
irLengthBaseSamples, which isjuce::dsp::Convolution::getCurrentIRSize()afterTrim::yes- JUCE trimstrailing samples below an absolute -80 dBFS threshold and reports what's
left. That threshold exists to save CPU on a convolution kernel; it was never
designed to answer "is this a cab or a reverb/space," and it doesn't: a cab
manually trimmed to a few seconds of file length around tens of ms of real
content reports a long post-trim size, while a genuinely short slap-delay or
small-room IR reports a short one. Two versions of the same cabinet capture
(one with more trailing silence than the other) could land on opposite sides
of the classification and get wildly different perceived level - the
reported bug.
This isn't fixable by tuning the threshold or the trim mechanism: short
reverbs/spaces and short cabs are both legitimately short, and long-file-
length cabs and long reverbs are both legitimately long. Duration - raw or
trimmed - doesn't encode which one a file is; nothing downstream of it can
either.
The fix replaces duration with an explicit, persisted per-block
IrCategory(Cab/IrPlayer) as the sole source of the pad and thedefault mix:
catalog's
gearmetadata (cab-> Cab, everything else -> IrPlayer),before the download even starts.
geartag, so category is seeded once from aload-time RMS content scan instead (a real, editable value from the
moment it loads, not authoritative going forward) - the split drop-zone
UX that makes local-load category known up front too is tracked
separately.
file length either: a load already known to be Cab is unconditionally
the uniform engine and hard-capped to its first 500 ms at load (a real
truncation - the actual size limit passed to
loadImpulseResponse- notjust an engine hint), so it's safe regardless of what the source file
contains. IrPlayer's engine choice (uniform vs. two-stage non-uniform)
comes from that same RMS content scan, never raw length.
setBlockIrCategorylets a block's category be changed at any time(V1: resets mix/pad to the new category's fixed default; no memory of a
prior per-category setting - a tracked fast-follow). The cab pad is now
a smoothed value pulled every block instead of a load-time constant, so
this glides instead of clicking.
this field existed backfills via the same content scan local loads use,
without touching the mix the user actually saved.
See the demo video and root-cause comment thread on #89 for the audible
before/after and the empirical trace that led here.
Test plan
CI does not run on pull requests.
./script/test-dsp.sh- 147/147 passing, including a newir_category_tests.cppthat reproduces the original bug scenariobit-for-bit: the same cab content, one copy with extra trailing
silence past the old cutoff, now produces identical processed audio
(max sample diff < 1e-5) instead of a different pad/mix. Also covers
the
gear-> category mapping,setBlockIrCategory, the local-fileduration guess, engine selection staying content-based and decoupled
from category, and the state round-trip (including pre-migration
backfill).
cd ui && npm run lint && npm run buildsurface changed - only per-block IR classification/gain staging)
Compatibility
Processor.cppare not reused or renumberedplugin/CMakeLists.txtare unchangedirCategoryis a new, optional per-blockproperty; its absence is handled explicitly - see the backfill above)
plugin/docs/updated if the public build or behavior changed🤖 Generated with Claude Code