Skip to content

Fix the visualisers, add a notification icon, bump to v0.11.6 / android-v0.11.5 - #26

Merged
Shik3i merged 1 commit into
mainfrom
fix/visualizer-and-notification-icon
Aug 15, 2026
Merged

Fix the visualisers, add a notification icon, bump to v0.11.6 / android-v0.11.5#26
Shik3i merged 1 commit into
mainfrom
fix/visualizer-and-notification-icon

Conversation

@Shik3i

@Shik3i Shik3i commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Why the web visualiser looked dead

It carried three mis-tunings that the Android client had already diagnosed and fixed. Each one is described in Android's own source comments; none was ported back.

Android (tuned) Web (was) Android's comment
FFT size 2048 1024 "at 512 the bins are 86 Hz apart — wider than the bottom third of a log-spaced display, so those bands collapse onto each other and eighteen bars end up drawing the same number"
dB window −78 … −4 never set (defaults −100 … −30) "the ceiling was −14, which ordinary mastered speech passes for most of a sentence: nearly every band pinned at full height"
Tilt 0.8 1.6 "at 1.6 the top bands were lifted by 2.6x and clipped on their own"

A clipped bar cannot move. At 43 Hz per bin the lowest dozen bars draw the same number. That is the "only the first 10% moves, the rest is static" report.

What both clients were missing

Normalisation against what the display has been hearing, rather than against full scale. It is why a quietly mastered episode drew a flat display while a loud one drew a lively one — and podcast audio makes this worse than music does, because levelling between shows is far less consistent. Bounded on both ends: never more than 3×, and never lifts silence, so a pause stays empty instead of becoming a wall of room tone.

Measured, not asserted

Run in a real browser against a synthetic voice (harmonics + sibilance), old configuration vs new, 120 frames, average peak-to-trough movement per band:

                   low bands   top bands
before                 0.783       1.000
after                  0.942       0.465

The top bands were not static in the old configuration — they were slamming between the rails, which reads as noise rather than as a spectrum. The bottom third moved less than it does now.

Counter-evidence, included deliberately: an earlier run against a source with no content above 1.7 kHz showed the opposite for the top bands (before 0.559, after 0.104). The reason is that the old settings were amplifying the noise floor into something that looked like signal, and the new window correctly reports an empty band as empty. I am reporting both numbers rather than the flattering one.

The mapping moved to lib/audio/spectrum.ts so it can be tested without a browser. That is also how the tilt regression is pinned: restoring 1.6 makes more than a third of the bands clip on a speech-shaped input and fails the test — verified by putting the old value back.

The notification icon

New-episode notifications used android.R.drawable.stat_sys_download_done — a download tick, for something that is not a download. There was no suitable glyph in the project, so this adds one.

The feed mark rather than a bell: it is what "new items in a show you follow" means, and it survives 24dp in a status bar where a bell's clapper and shoulders do not. Built from exact geometry (a dot plus two annular quarter-sectors sharing an origin) rather than traced by hand, and checked by rasterising the paths before wiring it in. Confirmed compiled into the APK via aapt2 dump resources.

Verification

  • Web: 155 tests, svelte-check clean, translations/docs/release-policy gates pass.
  • Android: testDebugUnitTest and testReleaseUnitTest both green — the two tasks the release workflow runs.
  • On an emulator: playback runs with the new gain stage on the audio thread with no crash and no audio-track error.

Versions

apps/web0.11.6, Android → versionCode 45 / 0.11.5. This also carries the audit fixes merged in #25, which have not been in a release yet.

🤖 Generated with Claude Code

…s an icon

The web display carried three mis-tunings the Android client had already found
and fixed, each recorded in Android's own comments and never ported back:

- fftSize was 1024, so bins are 43 Hz apart. That is wider than the bottom
  bands of a log-spaced display, and the lowest dozen bars all landed on the
  same one or two bins and drew the same number. 2048 resolves them, which is
  most of what "only the left edge moves" was.
- minDecibels/maxDecibels were never set, so the AnalyserNode defaults applied:
  -100 to -30. Ordinary mastered speech spends most of a sentence above a -30
  ceiling, so band after band sat pinned at 255 — and a clipped bar cannot move.
  The window is now -78 to -4, matching Android exactly.
- The tilt was 1.6, the value Android's comment records as lifting the top
  bands by 2.6x until they clipped on their own. It is 0.8 here too now.

Both clients also gained the thing neither had: normalisation against what the
display has been hearing rather than against full scale. It is why a quietly
mastered episode drew a flat display while a loud one drew a lively one, and
podcast audio makes it worse than music does — levelling between shows is far
less consistent. Bounded on both ends: it never exceeds 3x and never lifts
silence, so a pause stays empty instead of becoming a wall of room tone.

Measured in a real browser against a synthetic voice with harmonics and
sibilance, comparing the old configuration with the new one over 120 frames:

                       low bands   top bands
    before                 0.783       1.000
    after                  0.942       0.465

The top bands were not static there, they were slamming between the rails,
which reads as noise rather than as a spectrum; the bottom moved less than it
does now. An earlier run against a source with no content above 1.7 kHz showed
the opposite for the top bands, because the old settings were amplifying the
noise floor into something that looked like signal. Both numbers are in the
pull request rather than only the flattering one.

The mapping now lives in lib/audio/spectrum.ts so it can be tested without a
browser, which is also how the tilt regression is pinned: at 1.6 more than a
third of the bands clip on a speech-shaped input, and the test fails.

Separately, new-episode notifications used android.R.drawable
.stat_sys_download_done — a download tick for something that is not a download.
There was no suitable glyph in the project, so this adds one: the feed mark,
which is what "new items in a show you follow" means and which survives being
drawn at 24dp. Constructed from exact geometry rather than traced by hand, and
checked by rasterising the paths.

Verified on an emulator: playback runs with the new gain stage on the audio
thread without a crash or an audio-track error, and the drawable is compiled
into the APK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Shik3i
Shik3i merged commit f13ded9 into main Aug 15, 2026
4 checks passed
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.

1 participant