Skip to content

audio: honor the float voice biquad parameter ABI - #669

Merged
NotRexed merged 5 commits into
NotRexed:mainfrom
monsterlag:fix/voice-float-biquad
Nov 9, 2026
Merged

NotRexed merged 5 commits into
NotRexed:mainfrom
monsterlag:fix/voice-float-biquad

Conversation

@monsterlag

@monsterlag monsterlag commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

The voice setter for TBiquadFilterParameter<float> falls through to the unimplemented-import handler, so it queues no filter. The legacy Q14 voice setter is already implemented.

Add the distinct float overload and copy its enabled flag and coefficients into the existing queued voice-filter command. The 24-byte parameter has the flag at offset 0, three float numerator coefficients at offset 4 and two additive-feedback coefficients at offset 16. Floats are copied as supplied; Q14 scaling, sign flipping and a0 normalization do not apply. The existing commit and biquad processing/state handling are reused. The legacy overload and splitter filters are unchanged.

Validation uses authored packets, handles and sample buffers around the actual setters, submit/apply/commit, and the biquad loop extracted from render_voice. It covers identity/attenuation, fixed analytic additive-feedback responses, cross-frame history, disable/re-enable reset, filter/voice/channel isolation, invalid indices/handles/nulls and caller-packet reuse before commit. The legacy Q14 path is exercised too. The released-source negative compiles and invokes the actual public a64_unimplemented body, then fails the intended missing queued-filter assertion. The fixed fixture passes with audited GNU-target Clang 23.1.5 at -O2 -Wall -Wextra -Werror.

No device, real audio, game, resampler or private SDK instructions are included or run. Lock and output/allocator boundaries are not integration-tested; there is no physical-audibility, full-DSP equivalence, scene/distance or #599 causality claim. The targeted strict automatic runner passes locally on Linux/GCC; the audited Windows Clang result is retained with byte-identical production/fixture inputs.

Refreshed through a normal merge of main b1799142, retaining its complete automatic CI workflow and current staged-output fixture. The new voice test is registered with the strict runner for both OS jobs. All five actual DSP source/fixture inputs remain byte-identical; current-head hosted checks are pending.

Refs #599.

@NotRexed
NotRexed merged commit a53cb75 into NotRexed:main Nov 9, 2026
9 checks passed
blushOFF added a commit to blushOFF/Hookshot that referenced this pull request Nov 9, 2026
…e splitter destinations' filters

OoT calls nn::audio effects the import handler took until now, so the mixes they sit on came out dry. AddReverb and its
setters run on the I3DL2 network from the plain reverb's linear gains, early and late modes, pre-delay, decay and HF
ratio; AddDelay is a delay line per channel with feedback, low-pass and channel spread (HOS_AUDIO_NO_DELAY=1: left out);
AddBiquadFilter filters a mix's buffers from the float TBiquadFilterParameter; SetSplitterBiquadFilterParameter filters
a splitter destination's copy of the voice. The aux enable and input/output calls, the output device notification and
volume calls, the virtual input device list and the voice-drop parameter are accepted. Effects on a mix run in the order
the game added them; each logs its wet level the first few times.

The voices' float biquad parameter is left to NotRexed#669.

Measured (Windows 11, RTX 3070, Kokiri Forest): the log shows the filter on mix 2, the delay on mix 4 and the reverbs
on mixes 7-9; the low pass the game keeps on mix 2 now filters; 142 s of dumped output without clipping. A scripted
tour of 29 teleport destinations with this in: no crash, no flicker. tests/test_audio_effects.py compiles the real
delay and mix-filter section with synthetic signals (echo times and feedback, dry gain, spread, NaN, low pass, unstable
coefficients).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
blushOFF added a commit to blushOFF/Hookshot that referenced this pull request Nov 9, 2026
…e splitter destinations' filters

OoT calls nn::audio effects the import handler took until now, so the mixes they sit on came out dry. AddReverb and its
setters run on the I3DL2 network from the plain reverb's linear gains, early and late modes, pre-delay, decay and HF
ratio; AddDelay is a delay line per channel with feedback, low-pass and channel spread (HOS_AUDIO_NO_DELAY=1: left out);
AddBiquadFilter filters a mix's buffers from the float TBiquadFilterParameter; SetSplitterBiquadFilterParameter filters
a splitter destination's copy of the voice. The aux enable and input/output calls, the output device notification and
volume calls, the virtual input device list and the voice-drop parameter are accepted. Effects on a mix run in the order
the game added them; each logs its wet level the first few times.

The voices' float biquad parameter is left to NotRexed#669.

Measured (Windows 11, RTX 3070, Kokiri Forest): the log shows the filter on mix 2, the delay on mix 4 and the reverbs
on mixes 7-9; the low pass the game keeps on mix 2 now filters; 142 s of dumped output without clipping. A scripted
tour of 29 teleport destinations with this in: no crash, no flicker. tests/test_audio_effects.py compiles the real
delay and mix-filter section with synthetic signals (echo times and feedback, dry gain, spread, NaN, low pass, unstable
coefficients).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
blushOFF added a commit to blushOFF/Hookshot that referenced this pull request Nov 11, 2026
…e splitter destinations' filters

OoT calls nn::audio effects the import handler took until now, so the mixes they sit on came out dry. AddReverb and its
setters run on the I3DL2 network from the plain reverb's linear gains, early and late modes, pre-delay, decay and HF
ratio; AddDelay is a delay line per channel with feedback, low-pass and channel spread (HOS_AUDIO_NO_DELAY=1: left out);
AddBiquadFilter filters a mix's buffers from the float TBiquadFilterParameter; SetSplitterBiquadFilterParameter filters
a splitter destination's copy of the voice. The aux enable and input/output calls, the output device notification and
volume calls, the virtual input device list and the voice-drop parameter are accepted. Effects on a mix run in the order
the game added them; each logs its wet level the first few times.

The voices' float biquad parameter is left to NotRexed#669.

Measured (Windows 11, RTX 3070, Kokiri Forest): the log shows the filter on mix 2, the delay on mix 4 and the reverbs
on mixes 7-9; the low pass the game keeps on mix 2 now filters; 142 s of dumped output without clipping. A scripted
tour of 29 teleport destinations with this in: no crash, no flicker. tests/test_audio_effects.py compiles the real
delay and mix-filter section with synthetic signals (echo times and feedback, dry gain, spread, NaN, low pass, unstable
coefficients).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants