Skip to content

Fix LFE low-pass filter using a hardcoded 48 kHz sample rate - #15

Merged
trsonic merged 3 commits into
mainfrom
fix/lfe-filter-sample-rate
Jul 28, 2026
Merged

Fix LFE low-pass filter using a hardcoded 48 kHz sample rate#15
trsonic merged 3 commits into
mainfrom
fix/lfe-filter-sample-rate

Conversation

@trsonic

@trsonic trsonic commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

The 120 Hz LFE low-pass applied when rendering HOA to an LFE-bearing loudspeaker layout computed its biquad coefficients for a hardcoded 48 kHz rate (DEFAULT_SAMPLERATE in h2m_rdr.c) regardless of oar_config_t.sampling_rate. The effective cutoff therefore scaled with the output rate: ~240 Hz at 96 kHz (LFE ~2.7× too loud for content near the cutoff, with ~4 dB less stopband attenuation) and ~110 Hz at 44.1 kHz.

Changes:

  • Plumb the context sample rate into IAMF_element_renderer_render_H2M so the lazy filter init uses the actual rate.
  • Fix the eager init path in ear.c, which referenced an undeclared identifier (out_info) and prevented the DISABLE_LFE_HOA=0 configuration from compiling at all.
  • Since no build defined DISABLE_LFE_HOA, the LFE path was unreachable in every configuration; add an OAR_ENABLE_HOA_LFE CMake option (default OFF, preserving current behavior) so it can be built and tested.

Testing

New test_hoa_lfe_rendering (built when the option is ON) renders a 1OA W-channel tone to 5.1 at 44.1/48/96 kHz through the public API and verifies:

  • the LFE level is rate-invariant (the hardcoded-48k code fails this at 2.697× for 96 kHz), and
  • the low-pass attenuates a 1 kHz tone by more than 25 dB at every rate (measured ~29 dB).

Default builds (option OFF) are unchanged.

trsonic added 2 commits July 27, 2026 08:48
The 120 Hz LFE low-pass applied when rendering HOA to an LFE-bearing
loudspeaker layout computed its biquad coefficients for a hardcoded
48 kHz rate regardless of oar_config_t.sampling_rate, so the effective
cutoff scaled with the output rate (~240 Hz at 96 kHz, rendering the
LFE 2.7x too loud for content near the cutoff and with ~4 dB less
stopband attenuation; ~110 Hz at 44.1 kHz).

Plumb the context sample rate into IAMF_element_renderer_render_H2M so
the lazy init uses the actual rate, and fix the eager init in ear.c,
which referenced an undeclared identifier (out_info) and prevented the
DISABLE_LFE_HOA=0 configuration from compiling at all.

Since no build defined DISABLE_LFE_HOA, the LFE path was unreachable in
every configuration; add an OAR_ENABLE_HOA_LFE CMake option (default
OFF, preserving current behavior) so it can be built and tested.

Adds test_hoa_lfe_rendering (built when the option is ON): renders a
1OA W-channel tone to 5.1 at 44.1/48/96 kHz through the public API and
verifies the LFE level is rate-invariant (the hardcoded-48k bug fails
this at 2.697x for 96 kHz) and that the low-pass attenuates a 1 kHz
tone by more than 25 dB at every rate.

Fixes #1.

@jingbo-marquis jingbo-marquis left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great.

@trsonic

trsonic commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks @jingbo-marquis and @yilun-zhangs !

@trsonic
trsonic merged commit c772ef2 into main Jul 28, 2026
6 checks passed
@trsonic
trsonic deleted the fix/lfe-filter-sample-rate branch July 28, 2026 11:13
trsonic added a commit that referenced this pull request Aug 20, 2026
Dropping these includes was correct against the base this branch started
from, but the LFE filter added in #15 uses tanf(), M_PI, sqrt() and memset()
in this file, so a build with -DOAR_ENABLE_HOA_LFE=ON no longer compiles
without them. It also left `#define _USE_MATH_DEFINES` with no <math.h>
following it, which is what that define exists for on MSVC.
trsonic added a commit that referenced this pull request Aug 20, 2026
#15 added the OAR_ENABLE_HOA_LFE CMake option and a test that exercises the
120 Hz LFE low-pass, neither of which the Bazel build knew about.

`--define OAR_ENABLE_HOA_LFE=1` now sets DISABLE_LFE_HOA=0 on ae_rdr, whose
header defaults it to 1, matching what the CMake option does globally. The
test target is gated with target_compatible_with, so `bazel build //...`
skips it instead of building a test whose subject was compiled out.
trsonic added a commit that referenced this pull request Aug 20, 2026
Dropping these includes was correct against the base this branch started
from, but the LFE filter added in #15 uses tanf(), M_PI, sqrt() and memset()
in this file, so a build with -DOAR_ENABLE_HOA_LFE=ON no longer compiles
without them. It also left `#define _USE_MATH_DEFINES` with no <math.h>
following it, which is what that define exists for on MSVC.
trsonic added a commit that referenced this pull request Aug 20, 2026
#15 added the OAR_ENABLE_HOA_LFE CMake option and a test that exercises the
120 Hz LFE low-pass, neither of which the Bazel build knew about.

`--define OAR_ENABLE_HOA_LFE=1` now sets DISABLE_LFE_HOA=0 on ae_rdr, whose
header defaults it to 1, matching what the CMake option does globally. The
test target is gated with target_compatible_with, so `bazel build //...`
skips it instead of building a test whose subject was compiled out.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants