Skip to content

spectrum: a spectrum analyzer meter, on the desktop and beside the P4's sound card - #151

Merged
bdbarnett merged 6 commits into
mainfrom
spike/audio-meter
Sep 26, 2026
Merged

bdbarnett merged 6 commits into
mainfrom
spike/audio-meter

Conversation

@bdbarnett

Copy link
Copy Markdown
Collaborator

Lands the spectrum meter example (lib/examples/spectrum). It draws with pygraphics from a timer, and the levels come from one of three sources. fake is generated music, for any host. loopback is what the computer is playing, through WASAPI loopback, on CPython with numpy and soundcard. pump is levels computed in C inside usbif's sound-card pump on the ESP32-P4 panel, and needs usbif#50. SPECTRUM_SOURCE picks one. start(bands, height, y, style) sets the resolution; the default is half the bars at half the height, along the bottom.

Proven here, on pydevices 0.6.2: the example test kit runs it OK on micropython, circuitpython and micropython.exe. Run directly, CPython draws 62.5 fps with fake music. python.exe runs clean with the installed pygraphics. From the pygraphics source tree it hits a tuple-source blit bug, fixed in pygraphics#34. The kit's pyscript row wasn't run, because another session's server held port 8000.

Proven on the P4 on 2026-09-25 (spike): meter on versus off costs no USB sound-card packets once the panel's cache writeback is sliced (micropython-pydevices#23). The fps and cost numbers are in the README.

Tidy-ups while landing it: the P4 measurement scripts move to tools/spectrum; the ported timer call drops App.timer_async, which 0.6 removed; the kit's manifest gains spectrum; and test_browser_url finds the sibling pydevices checkout from a worktree too.

…usic

Log-spaced bars 20 Hz-20 kHz in a blue-cyan-violet gradient, peak-hold caps,
a keyed reflection, and Hz/kHz labels at their log positions. Each bar is one
blit from a prebuilt gradient column; only the touched row strip is redrawn
and sent to the panel. Stills at 800x480 and 320x170 and an 8 s loop in
docs/screenshots. Kept out of the browser gallery while it is a spike.
… for the P4

pump_levels.PumpLevels is the real source behind FakeMusic's interface: it
asks usbif's UAC pump for band levels (uac_pump_meter) and reads them each
frame (uac_pump_levels). spectrum.py uses it whenever the firmware has it.

SpectrumView.render_columns draws each bar from two prebuilt packed columns
(background and fully lit) and sends only the rows that moved; on the P4 they
go straight into the panel's framebuffer and one dirty band is presented per
frame instead of appdev's whole-frame refresh. Pixel-identical to render();
6 fps became 27-50 on the P4. capture() reads the panel's own framebuffer.

The README records the spike's numbers, including the cache-sync setting
(spike/sdkconfig.msync_chunked) without which drawing cost USB packets; spike/
has the board and host scripts that measured them.
…music

On the P4 panel this takes loud music from 18-19 fps to 35-45, and pink noise
from 25-28 to 44-46; silence stays at 48-50. Only the view's existing bands
and height arguments change.
- app.every without async_: pydevices 0.6 removed App.timer_async.
- The measurement scripts move to tools/spectrum; the sdkconfig fragment
  goes, since the P4 board definition carries it (micropython-pydevices#23).
- The README points at usbif#50 for the C meter.
- The example test kit runs spectrum.
- test_browser_url finds the sibling pydevices checkout from a worktree too.
@bdbarnett
bdbarnett merged commit 8d4a4d0 into main Sep 26, 2026
4 checks passed
@bdbarnett
bdbarnett deleted the spike/audio-meter branch September 26, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant