DeviceCallback applies the context's ramp to the stereo float it just filled, which is the only place the AudioOut2 main mix reaches the speakers; the title's own volumes and the mastering stay before it. At the default volume the ramp is at unity and the call returns without touching the stream. The controller sound card keeps its own path and is not touched.
Every non-vibration port goes through HostGainFilter just before SDL_QueueAudio, after the title's volume and channel order. With the default volume the filter returns the title's buffer untouched. Vibration ports go to the controller's sound card and are not touched.
Register audio_out_host_volume_state. Covers the unity default, each command publishing its gain, focus acting only with the option on, initial values, a refused configuration leaving the state alone, both variables read from the environment with the invalid one named, and readers never seeing a gain above unity while commands run.
The state sits behind a mutex and publishes its gain through an atomic, so the audio threads read it without locking. HostVolumeConfigure replaces the state, parsing ANYPS5_VOLUME and ANYPS5_MUTE_ON_FOCUS_LOSS before changing anything, so an invalid value leaves it untouched and throws an error naming the variable.
Accepts 0 and 1 for the flag and 0 to 100 for the level; refuses empty, padded, signed, fractional, out-of-range and overflowing values with the variable named.
A flag is exactly 0 or 1 and a level a whole number from 0 to 100. Anything else, including an empty value, throws an error that names the variable and quotes the value.
At unity the title's pointer comes back and nothing is copied, a changed gain works on a copy and leaves the title's buffer as it was, and the scratch buffer is processed in place.
HostGainFilter returns the title's own pointer when the ramp is at unity with a unity target, so the default path copies nothing and multiplies nothing. Otherwise it applies the ramp to a scratch copy, or in place when the data already is the scratch buffer, and never writes the title's memory.
Covers the byte-for-byte bypass at unity, the first sample and landing frame matching the 16-bit ramp, no step above the slope, a ramp split across buffers, and the absence of clamping.
The float overload uses the same per-frame gain as the 16-bit one, converted exactly from the fixed-point value, and does not clamp. At unity with a unity target it touches nothing.
Register audio_out_host_gain. Covers the byte-for-byte bypass at unity, the exact first sample and landing frame of a ramp, no step larger than the ramp slope, a ramp split across buffers equal to one buffer, saturation above unity, one gain per frame on every channel, a silent gain, and the return to bypass.
HostGainRamp moves a 16.16 fixed-point gain toward its target by a constant step per frame, so the ramp is exact, continues across buffers and applies one gain to every channel of a frame. 16-bit samples are rounded and saturate. At unity with a unity target nothing is touched.
Covers the option off, a focus loss and gain with it on, the user's own mute and volume surviving a round trip, and the option changing while the window is unfocused.
With the option on, a window without focus counts as muted and gaining focus ends it. The focus mute is derived from the focus and the option, so it never replaces the user's own mute. With the option off, focus changes change nothing.