Skip to content

Rootless: low-latency mode, Android EQ, Live EQ, per-channel PEQ and a song tonality analyzer - #350

Open
PEQHUB wants to merge 8 commits into
timschneeb:masterfrom
PEQHUB:rootless-features
Open

PEQHUB wants to merge 8 commits into
timschneeb:masterfrom
PEQHUB:rootless-features

Conversation

@PEQHUB

@PEQHUB PEQHUB commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

This bundles the rootless features I've been working on into one PR. It replaces #349 (low-latency mode and Android EQ), which is included here unchanged apart from dropping its measuring tools.

Per-channel PEQ needs a small libjamesdsp change: timschneeb/JamesDSPManager#6. The submodule is pinned to that commit. GitHub serves it through the existing .gitmodules URL, so the URL is unchanged. Merge the libjamesdsp PR first.

Low-latency mode (on by default)

Rootless capture added up to ~0.5 s of delay, so video went out of sync.

  • Reads in 960-frame blocks instead of the whole buffer.
  • Caps the output track queue and requests the low-latency output path.
  • Drops a block (with a short fade) when the output queue grows past its target, so latency can't stay high after a slow start.

Bluetooth, cold start: A/V offset about 340 ms before, about 120 ms after.

Android EQ (off by default)

Instead of capturing, the GEQ/PEQ curve runs inside each app with Android's DynamicsProcessing effect, so video stays in sync. The curve is fitted to the effect's pre-EQ, MBC and post-EQ stages (up to 380 bands) against its actual block response. Left and right curves are applied separately. Settings: latency (~10/20/40 ms) and a limiter. Other effects are off in this mode.

Measured on the speaker with a mic: 10/21/42 ms added depending on the latency setting, and a -10 dB preamp comes out at -9.4 dB.

Live EQ

A bottom sheet on the parametric EQ screen for editing bands while listening: a logarithmic frequency slider, gain and Q controls, and chips to pick the band. Changes are saved when a slider is released.

Per-channel parametric EQ

Each band applies to both channels, left only or right only. The engine sends separate left and right curves to the stereo arbitrary EQ, and the preview draws both. Equalizer APO import and export use Channel: lines, so per-channel presets round-trip.

Song tonality analyzer (off by default)

A card on the DSP page shows how the music you play compares with a reference spectrum. It measures the captured audio before JamesDSP processing, per song.

  • Songs are split by media session metadata (needs notification access), by silence, or by a lasting change of the spectrum.
  • Seven bands (sub to air) are each judged against a normal range. The graph shows the deviation (compensated) or the measured spectrum (raw).
  • A codec's cut-off and missing deep bass are detected and left out, instead of reading as a deficit.
  • References:
    • IEC 60268-1 programme simulation noise (default)
    • M-Noise
    • pink noise
    • a tilt of -3 to -6 dB/oct
    • the average spectrum of popular music, and of its least and most percussive tracks (Elowsson & Friberg, AES 142, 2017)
    • an average learned from the songs you play
    • a custom reference: the playing song, or an imported WAV. The official M-Noise file is recognized by its checksum; the file itself is never bundled.
  • It has its own settings page, which also opens from the card.

Testing

  • Unit tests: Android EQ fitter, APO Channel: import/export, the tonality analyzer (reference feed-back, codec cut-off, missing bass, resets, bad input), reference curves against the IEC table, the resampler and the WAV decoder.
  • On a OnePlus CPH2655 (Android 16): latency over Bluetooth and the speaker (numbers above), and the tonality card with streaming music.

The rootless capture loop added up to ~0.5 s of delay, which puts video
out of sync. The new "Low-latency mode" setting (on by default) reads in
small blocks, caps the output queue, uses the low-latency output path and
drops a block whenever the output queue grows past its target.
Runs the EQ curve (GEQ + PEQ) inside each app with Android's
DynamicsProcessing effect instead of capturing audio, so video stays in
sync. The curve is fitted to the effect's pre-EQ, MBC and post-EQ stages
(up to 380 bands) against its actual block response.

Settings: Android EQ on/off, latency (~10/20/40 ms) and a limiter.
- LiveEqBottomSheet edits the bands in real time: logarithmic frequency
  slider, gain and Q controls, and chips to pick the band. Changes are
  saved when a slider is released.
- A Live EQ button on the parametric EQ screen opens it.
- NumberInputBox clamps on focus loss instead of while typing, and Q is
  kept at 0.1 or more.
Points the submodule at the libjamesdsp commit that adds a stereo
arbitrary EQ entry point (separate left and right curves), which the
per-channel parametric EQ needs.
Each band can apply to both channels, the left or the right one. The
engine sends separate left and right curves to libjamesdsp's stereo
arbitrary EQ, and the preview draws both. The preamp applies to both
channels when only one side has bands.
Measures the long-term spectrum of the captured audio before JamesDSP
processing and compares it with a reference curve, per song.

- Analysis: stereo FFT into 1/12-octave bands, averaged in the power
  domain on a worker thread; the capture thread never blocks or allocates.
  Songs are split by media session metadata (with notification access),
  by silence, or by a sustained change of the spectrum.
- References: IEC 60268-1 programme simulation noise (default), M-Noise,
  pink noise, an adjustable tilt, average spectra of popular music overall
  and of its least and most percussive tracks (Elowsson & Friberg, AES
  2017), an average learned from the songs played, and a custom reference
  from the playing song or an imported WAV (the official M-Noise file is
  recognized by its checksum).
- Card on the DSP page: verdict, seven band values, song/live and
  compensated/raw graphs, hold, reset and a reference picker. Each band is
  judged against a normal range; a source's codec cut-off and missing deep
  bass are detected and left out.
- Settings get their own page, also opened from the card.
@1576-del

Copy link
Copy Markdown

Title: JamesDSP Full ARM64 – Play Protect warning and user experiences

Hello PEQHUB,

I'm interested in testing your JamesDSP Full ARM64 build ("JamesDSP-Full-arm64-v8a.apk") on my Samsung Galaxy S26 running Android 17.

However, Google Play Protect blocks the installation with a warning about access to sensitive data and possible identity theft or financial fraud.

Before installing it, I would appreciate some clarification:

  1. Has anyone successfully installed and used this exact APK?
  2. Have other users encountered the same Google Play Protect warning?
  3. Have users reported any security, stability, or compatibility problems?
  4. Why is this APK signed with an Android Debug certificate rather than a release certificate?
  5. Is there a security review or a reproducible build available to verify the APK?

I would also appreciate feedback from anyone who has personally tested this exact build, particularly on recent Samsung devices.

Thank you for your work and for any clarification.

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