Repository navigation
Conversation
Adds get_fft_vdsp<float>(), an FFTImpl using vDSP's DFT API
(vDSP_DFT_zrop), which handles n_fft = f * 2^k for f in {1, 3, 5, 15}
and falls back to KISS for any other even size. Output layout and
scaling match the KISS implementation exactly, so it is a drop-in
replacement for block_convolver. Built when EAR_USE_VDSP is on (default
on Apple), which defines EAR_HAS_VDSP publicly.
Tests: fft_vdsp_tests compares against KISS (sizes 64-4096, including
480, 960 and the 882 fallback); block_convolver_vdsp_tests reruns the
block convolver suite with the vDSP implementation. On Apple Silicon a
forward+inverse pair is 5.7x-8.3x faster than KISS.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Toh2Vz45TL5yTdDpYntg6d
Merely linking the Accelerate framework into the ear library measurably changes KissFFT's floating-point rounding elsewhere in the same process, even when get_fft_vdsp() is never called: it turned an exact-zero sample in bear's variable_block_size test into ~3e-8. Defaulting this ON for every Apple build of libear silently changed numeric behaviour for consumers who never asked for vDSP, such as bear's own render path. Consumers that do want the vDSP FFT (such as ear-production-suite's monitoring plugin) now force EAR_USE_VDSP=ON explicitly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Toh2Vz45TL5yTdDpYntg6d
The per-block direct/diffuse gain ramp mixing used by MonitoringAudioProcessor (EPS's loudspeaker monitoring plugin) was a plain scalar loop. LinearInterpMatrix::apply_interp/apply_constant now build the linear ramp with vDSP_vramp and accumulate with vDSP_vma/vDSP_vsma when EAR_HAS_VDSP is defined, keeping the original scalar loop as the fallback otherwise. Same output layout and exact values (verified below), just vectorised. Tests: gain_interpolator_matrix_tests compares against an independent scalar reference (not the header's own fallback code), for both apply_interp and apply_constant, with non-power-of-two block/channel sizes. Passes with EAR_USE_VDSP on and off. Apple Silicon micro-benchmark (8 in / 2 out channels, 2048-sample block): ~2.9x faster (12.4us -> 4.3us). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Toh2Vz45TL5yTdDpYntg6d
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.
Adds two optional implementations that use Apple's Accelerate framework, enabled with
EAR_USE_VDSP=ON(off by default, so nothing changes for existing users).get_fft_vdsp<float>(): anFFTImplbuilt onvDSP_DFT_zrop. It handlesn_fft = f * 2^kfor f in {1, 3, 5, 15} and falls back to KISS for other even sizes. Output layout and scaling match the KISS implementation, so it replaces it inblock_convolver. A forward+inverse pair was 5.7x-8.3x faster than KISS on Apple Silicon.LinearInterpMatrix::apply_interp/apply_constantusevDSP_vramp,vDSP_vmaandvDSP_vsmawhenEAR_HAS_VDSPis defined, and keep the scalar loop otherwise. About 2.9x faster (12.4 us to 4.3 us, 8 in / 2 out channels, 2048-sample block).It is off by default because linking Accelerate changed KissFFT's floating-point rounding elsewhere in the same process in our tests, even when the vDSP FFT is never called (an exact zero in
variable_block_sizebecame ~3e-8). I have not reproduced that on its own.Tests:
fft_vdsp_testscompares against KISS (sizes 64-4096, including 480, 960 and the 882 fallback);block_convolver_vdsp_testsreruns the block convolver suite with the vDSP FFT;gain_interpolator_matrix_testscompares against an independent scalar reference. All 18 tests pass with vDSP on and 16 with it off, on macOS with AppleClang 21.Do the tests fail when the code is wrong? Checked on a scratch copy, not committed:
masterwithout this change,fft_vdsp_testsdoes not build:use of undeclared identifier 'get_fft_vdsp'.fft_vdsp_testsandblock_convolver_vdsp_testsboth fail.gain_interpolator_matrix_testsfails (2559 assertions). That test guards equivalence with the scalar loop, so it passes onmaster; there is no behaviour that fails before the change.Note that the project's last commit is from April 2024, so I understand if this is out of scope.
🤖 Generated with Claude Code
https://claude.ai/code/session_011HCUWvPpbN7e6hcwuWBJjs