mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
The audio renderer checked the game's RequestUpdate with about 80 rt_fatal and need() sites in audren.c, audio_mixer.c, audio_effects.c and audio_reverb.c, so a section size, a splitter or mix record or an effect setting out of range (a reverb3d whose delays add up past 0.4 s, a limiter attack outside 0 to 1, a mix buffer index past its mix, a filter coefficient that is not finite) ended the process. The tested route never reached one; dungeons and bosses were never run. Now an update whose sections do not match the renderer is refused whole with 0x5299 before anything of it is applied: the SDK's RequestUpdateAudioRenderer hands that result back to the game, which ignores it and sends its next update, where any other result makes the SDK abort. A record with an id the renderer does not have is left out of an update that is otherwise applied, a splitter destination id it does not have is stored as -1, which both render loops skip, and an effect or sink whose values cannot be used is passed through or skipped in the render pass, with every index checked before its first write. audio_bad logs the first of each kind per renderer with the game frame and counts the rest. rt_fatal stays for host allocations, OpenAudioRenderer's parameters and the checks the new ones turn into invariants. Two inputs that did not end the process before change too: a mix in use with a negative buffer count is refused (it laid the mixes after it out before buffer 0), and a limiter attack or release that is not a number passes the sound through instead of turning the mix into NaN. NX2NAVI_AUDIO_STRICT=1 (audio_strict, default 0) makes audio_bad end the process as before, for bug reports. Not reproduced before the change in the game; crafted updates reproduced the fatals. The new tests/audio_params_check sends 27 refused updates, 10 records and 38 effects and sinks the renderer cannot use through renderer_handler and runs the strict switch; 15 deliberate breakages of the change each made it fail. audio_mixer_check, cfg_rows_check, check_content, a compile of every runtime file with no new -Wall -Wextra warnings in the changed ones and the stability pass's test matrix (the two baseline environment failures only) passed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
41 lines
2.6 KiB
C
41 lines
2.6 KiB
C
/* Additional DSP effects. Contains code Copyright (c) Ryujinx Team and Contributors (MIT; see
|
|
third_party/licenses/Ryujinx-Audio.txt). No device or guest-memory access. */
|
|
#pragma once
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
typedef struct {
|
|
uint8_t input[6], output[6]; uint16_t channel_max, channels;
|
|
uint32_t delay_max, delay, sample_rate, in_gain, feedback, out_gain, dry_gain, spread, lowpass;
|
|
uint8_t status;
|
|
} AudrenDelayParam;
|
|
typedef struct {
|
|
uint8_t input[6], output[6]; uint16_t channel_max, channels;
|
|
int32_t sample_rate, early_mode, early_gain, pre_delay, late_mode, late_gain,
|
|
decay, hf_decay, coloration, reverb_gain, out_gain, dry_gain;
|
|
uint8_t status;
|
|
} AudrenReverbParam;
|
|
typedef struct {
|
|
uint8_t input[6], output[6]; uint16_t channel_max, channels; int32_t sample_rate;
|
|
float threshold, ratio; int32_t attack_time, release_time;
|
|
float input_gain, attack, release, output_gain;
|
|
uint8_t status, makeup, statistics, reset_statistics;
|
|
} AudrenCompressorParam;
|
|
typedef struct { uint8_t input[24], output[24]; float volume[24]; uint32_t count; } AudrenBufferMixParam;
|
|
typedef struct { uint8_t input[6], output[6]; int16_t numerator[3], denominator[2]; uint8_t channels, status; } AudrenBiquadEffectV1;
|
|
typedef struct { uint8_t input[6], output[6]; uint32_t padding; float numerator[3], denominator[2]; uint8_t channels, status; uint16_t reserved; } AudrenBiquadEffectV2;
|
|
_Static_assert(offsetof(AudrenDelayParam,status)==52,"delay wire layout");
|
|
_Static_assert(offsetof(AudrenReverbParam,status)==64,"reverb wire layout");
|
|
_Static_assert(offsetof(AudrenCompressorParam,status)==52,"compressor wire layout");
|
|
_Static_assert(sizeof(AudrenBufferMixParam)==148,"buffer-mix wire layout");
|
|
_Static_assert(sizeof(AudrenBiquadEffectV1)==24 && sizeof(AudrenBiquadEffectV2)==40,"biquad wire layouts");
|
|
typedef struct AudioEffectDsp AudioEffectDsp;
|
|
/* Why the game's parameter block `param` of a delay (3), reverb (4) or compressor (9) cannot be used, as a constant
|
|
string, or NULL when it can (and for any other type). create and update end the process on such a block, so the
|
|
caller asks first. */
|
|
const char *audio_effect_invalid(unsigned type, const void *param);
|
|
AudioEffectDsp *audio_effect_create(unsigned type, const void *param, unsigned revision);
|
|
void audio_effect_free(AudioEffectDsp *s);
|
|
void audio_effect_update(AudioEffectDsp *s, const void *param);
|
|
void audio_effect_process(AudioEffectDsp *s, float *const input[6], float *const output[6], int frames);
|
|
void audio_effect_statistics(AudioEffectDsp *s, void *output, unsigned bytes);
|