audio: optional float pipeline end-to-end (opt-in, s16 default)#1116
Closed
bassdr wants to merge 3 commits into
Closed
audio: optional float pipeline end-to-end (opt-in, s16 default)#1116bassdr wants to merge 3 commits into
bassdr wants to merge 3 commits into
Conversation
Author
|
Close #1106 |
3638656 to
e220260
Compare
c5705b9 to
57defdc
Compare
Add AudioResampler, a polyphase windowed-sinc resampler supporting arbitrary integer ratios. Designed for N64 audio upsampling from 32000 Hz to 48000 Hz (exact ratio 3/2, P=3 Q=2, 8 taps/phase, Kaiser window beta=6, ~60 dB stopband attenuation). - AudioSettings gains SourceSampleRate (default 0 = passthrough) - AudioPlayer::Play() resamples transparently before DoPlay() when SourceSampleRate != SampleRate - GetDesiredBuffered() scales from source rate to output rate so OTRAudio_Thread fill logic remains coherent - Resample output uses a fixed std::array<int16_t, 16384> — no heap allocation on the audio hot path - Default SampleRate changed from 44100 to 48000 Hz - AudioPlayer destructor made virtual to fix UB in derived class dtors
AudioPlayer gains a parallel float-precision pipeline that consumers can opt into via AudioSettings::UseFloatPipeline. The s16 path is unchanged and remains the default, so existing libultraship consumers keep their byte-exact contract; SoH flips to float when FluidSynth is enabled. New entry points - AudioPlayer::Play(const float*, size_t frames) alongside the legacy Play(const uint8_t*, size_t len). Each Play asserts it's called in the matching mode and drops the buffer with a warning otherwise. - AudioPlayer::SetUseFloatPipeline(bool) — runtime mode switch via DoClose → flip → DoInit. Reverts on failure. - AudioPlayer::SetMixSource(std::function<void(float*, int)>) — a secondary stereo source mixed in *after* the resampler so its contribution skips the rate-conversion step entirely. Returns false in s16 mode. AudioPlayer sums the source with a tanh-style soft-clip before any surround decode. - audiobridge: AudioPlayerPlayFrame (legacy uint8_t) preserved; AudioPlayerPlayFrameF32 added for the float path. DSP layer - AudioResampler::Process gains a float overload that operates on interleaved float [-1, 1]. The original int16_t overload is preserved and wraps the float core with boundary conversions and clamping. - SoundMatrixDecoder::Process likewise: native float overload plus a legacy uint8_t (s16) overload that converts at the boundaries. Both reuse the float-internal filter / phase / delay state. Backends - SDL / PipeWire / WASAPI / CoreAudio DoInit reads IsUsingFloatPipeline() and configures the device format (F32 vs S16). Buffered() divides by the matching sample size. - PipeWire's ring init, sample width in OnProcess, and underrun fade-out math all branch on the same flag. AudioPlayer reorder in float mode - Stages: resample stereo → optional MixSource sum + soft-clip → surround decode (matrix-5.1) → DoPlay. Lets a secondary source produced at GetSampleRate() bypass the resampler. - Resampler channel count differs between modes: stereo (2) in float mode (mix + surround decode follow), GetNumOutputChannels() in s16 mode (legacy decode-first order preserved). RebuildResampler() picks the right value on Init / SetUseFloatPipeline / SetAudioChannels. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…en switching audio backends
57defdc to
a913932
Compare
Author
|
Changes moved in HarbourMasters/Shipwright#6668, now self-contained, not needed in LUS anymore. |
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.
AudioPlayer gains a parallel float-precision pipeline that consumers can
opt into via AudioSettings::UseFloatPipeline. The s16 path is unchanged
and remains the default, so existing libultraship consumers keep their
byte-exact contract; SoH flips to float when FluidSynth is enabled.
Based on top of #1106
Closes #1106
New entry points
Play(const uint8_t*, size_t len). Each Play asserts it's called in
the matching mode and drops the buffer with a warning otherwise.
DoClose → flip → DoInit. Reverts on failure.
secondary stereo source mixed in after the resampler so its
contribution skips the rate-conversion step entirely. Returns false
in s16 mode. AudioPlayer sums the source with a tanh-style soft-clip
before any surround decode.
AudioPlayerPlayFrameF32 added for the float path.
DSP layer
interleaved float [-1, 1]. The original int16_t overload is preserved
and wraps the float core with boundary conversions and clamping.
legacy uint8_t (s16) overload that converts at the boundaries. Both
reuse the float-internal filter / phase / delay state.
Backends
IsUsingFloatPipeline() and configures the device format (F32 vs S16).
Buffered() divides by the matching sample size.
fade-out math all branch on the same flag.
AudioPlayer reorder in float mode
surround decode (matrix-5.1) → DoPlay. Lets a secondary source
produced at GetSampleRate() bypass the resampler.
mode (mix + surround decode follow), GetNumOutputChannels() in s16
mode (legacy decode-first order preserved). RebuildResampler() picks
the right value on Init / SetUseFloatPipeline / SetAudioChannels.