Repository navigation
Optional native 44.1 kHz engine rate (GameSampleRate=44100) - #648
Merged
Merged
Conversation
Interfaces that are hardware-locked to 44.1 kHz cannot run the game, which only accepts 48 kHz. [Config] GameSampleRate=44100 makes the game's audio engine itself run at 44.1 kHz, so no resampling is needed: nine sites per supported build (Sept 2022 and Dec 2024 Learn & Play) are verified as a set and written only if all of them match. Unset, 0 or 48000 changes nothing. Known limitation: at 44.1 kHz the amp-cabinet impulse-response effect fails to initialise, so tones lack cabinet colouring; a follow-up addresses it.
At 44.1 kHz Wwise's partitioned convolution engine refuses the game's 48 kHz cabinet impulse responses, so tones lose their cabinet colouring. With GameSampleRate=44100, hook CAkPartitionedConvolutionEngine::Init right after its media fetch and resample each IR to the engine rate before the engine parses it (windowed-sinc, at media load, never in the audio callback). The five stolen bytes are verified per build (Sept 2022 and Dec 2024 LP); on mismatch the cabinet stays unhooked and the rate patch is unaffected.
…erfaces, and why only 44.1 - dist/RS_ASIO.ini lists GameSampleRate under [Config], blank by default. - When the driver refuses 48000 Hz but accepts 44100 Hz, log once that GameSampleRate=44100 is available. No behaviour change. - README: higher rates shorten the note detector's sample-sized window, so 96 kHz cannot detect a bass low E.
The direct-DFT branch used for tapered partitions (e.g. 58 bins -> 116-point transform) skipped the 1/n inverse scaling the radix-2 path applies, so those partitions were decoded n times too loud before resampling. Only the few cabinets with variable partition sizes take this branch. Also tone down two claims: README no longer says 'without resampling' (the cabinet IRs are resampled), and the 48 kHz log hint says the driver could not use 48000 Hz rather than implying a hardware limit.
A malformed header could size allocations and reads from unchecked fields: partCount = 0x80000000 wraps the x86 payload offset and requests a 4 GiB table. Before any allocation or read, check: - partCount against the media size; - that the padded table fits; - each table entry is 1..128 bins (the supported transform size); - the payload total in 64-bit; - the authored rate is plausible. An offline test with canary-guarded buffers covers these, and fails without the partCount bound. README: the December 2024 build is byte-checked only, and cabinet resampling depends on the hook installing (the log reports both). Comments drop dated session history, say a cache hash hit is not a proof of equality, and describe the FFT's direct-DFT fallback.
Owner
|
This looks pretty good, but I would change one small thing. I would rather have: Since if I understand correctly that's the only real alternative sample rate we support. |
Contributor
Author
|
Yes, going up in 96 kHz territory is moot, going 44.1 kHz improves bass detection range. I'll drop the rename in a sec. |
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.
Optional native 44.1 kHz engine rate
Some interfaces cannot run at 48 kHz (hardware locked to 44.1 kHz, or a driver that refuses 48000).
This adds an opt-in
GameSampleRate=44100under[Config]that makes the game's audio engine runnatively at 44.1 kHz, so a 44.1 kHz interface needs no external sample-rate conversion.
What it does
d1b38fcb) and December 2024 Learn & Play(
6ea6d1ba) builds:double;All 9 sites are byte-verified before anything is written. If any site doesn't match, nothing is patched
and the game keeps 48 kHz. A memory-protection or write failure after that check is logged and stops further
patching; earlier sites, and possibly the failing one, may already have changed. There is no rollback.
The third supported build logs "not supported for this game version" and is left alone.
cabinet coloring. A hook in the convolution engine's init resamples each IR to 44.1 kHz with a
windowed-sinc filter inside the engine's init when the cabinet media loads (about 40 ms per cabinet).
It runs once per cabinet load, not on every audio block. The hook's stolen bytes are
verified first; on a mismatch the cabinet is left unhooked and the rate patch still applies.
The media header is bounds-checked against the media size before any allocation or read (partition count,
table entries of 1..128 bins, 64-bit payload total, plausible authored rate); anything else is left untouched.
0or48000keeps the existing 48 kHz audio behaviour; only startup log lines are added. Other valuesare rejected with a log line.
Why 44.1 kHz only: the note detector's analysis window is a fixed number of samples. At 96 kHz the
window is half as long, which raises the lowest detectable pitch to about 47 Hz, so a bass low E
(41.2 Hz) could no longer be detected.
Testing
September 2022 build, MOTU M Series, Int32LSB, 128 frames. A 110 Hz test tone was fed into the input,
and the in-game tuner was read:
GameSampleRate=44100If the capture rate did not match the engine rate, the tone would read about 147 cents sharp, so the two
readings agreeing within 1 cent shows the input path runs at the engine rate. The cabinet log showed the
IR resampled 48000 -> 44100 (31 partitions, about 40 ms, at load), and the cabinet effect was active.
In-game pitch and tone checked by ear.
An offline test fed the cabinet parser 11 malformed and valid headers, inside buffers with canary bytes after the
media. Every malformed header was refused, nothing was read or written past the media, and no exception escaped;
both valid cases behaved correctly. With the new partition-count bound removed, a 4 GiB partition-count case escapes
as
vector too long, so the test does catch the bug.Not tested: