Quick clarification before diving in: Wavepunk is not an operating system. ByteWave MK.I runs Raspberry Pi OS underneath, like any other Pi. Wavepunk is the media player application I built from scratch on top of it — a fully custom DAP experience that runs on the Pi and takes over the screen when you want it to.
The OS question is something I’m still thinking through. Ideally I want both modes available: use ByteWave as a regular Pi desktop when you need it, and switch cleanly into the full DAP experience when you just want music. The exact implementation of that switching mechanism isn’t locked in yet — that’ll be a future DevLog. For now, Wavepunk launches on boot and runs as your primary interface.
With that out of the way — here’s how the UI actually got built.
Most media player UIs feel like an afterthought. A file browser, a progress bar, some buttons. Generic. I wanted Wavepunk to feel like the interface was physically part of the device — something you’d see in a high-end piece of audio hardware from a fictional 2077 product line.
The aesthetic direction: dark backgrounds, precise geometry, amber and red accents, UI elements that feel like a military-grade audio instrument. Not neon chaos — disciplined cyberpunk.
The glass card concept came from wanting depth without clutter. Track cards layered with gradients, subtle glowing borders, controlled visual weight. Everything hand-painted, nothing generated by a generic widget library.
Wavepunk has two operating modes. Ghost Mode is the one I get asked about most, and it’s more than just a minimal UI.
When you switch into Ghost Mode, several things happen simultaneously:
cpufreq-set — drops the Pi 4B from its full 1.8GHz down to a lower governor profile. Less processing power, significantly less heat and power draw.The result: meaningfully extended battery runtime in exchange for a stripped-back experience. Perfect for when you’ve got your playlist queued, headphones in, and just want music to run as long as possible.
Think of it as the equivalent of your phone’s Low Power Mode — except built specifically around audio playback, not general use.
Operative Mode is the full experience. CPU at full clock, all threads active, complete UI rendered:
Switching between modes is a single button press. The transition is animated — elements fade and slide, not a hard cut.
Standard Qt widgets look nothing like what Wavepunk needed. So I replaced them all. Every component is a custom-painted widget built using PyQt5’s QPainter API directly.
Custom paint events give me full control over every pixel — gradients, glow effects, borders, text layout, everything drawn exactly as designed. No stylesheets approximating the look. No compromises from trying to override default widget behaviour. Raw paint calls, full control.
This is more work upfront. But the result is a UI that looks and behaves exactly the same across any display resolution or DPI, because nothing is relying on the system’s default rendering.
One of the signature details in Wavepunk is how screens transition. Standard Qt swaps pages instantly. I built FadingStack — a custom widget stack that crossfades between views.
How it works: when switching views, the outgoing widget is rendered to a QPixmap cache. The incoming widget renders on top with decreasing opacity on a timer tick. When the animation completes, the outgoing pixmap is discarded. Runs at 60fps on the Pi 4B without frame drops — the compositing is lightweight, just alpha blending on cached bitmaps, no shaders involved.
Small detail, but it’s the kind of thing that makes the difference between software that feels like software and hardware that feels like a product.
The real-time beat visualiser is what gets attention in videos. Here’s exactly how it works:
numpy.fft on the latest sample window (1024 samples)QTimer at 60fps triggers repaints; paintEvent draws bars scaled to current band valuesTotal CPU overhead on a Pi 4B: 4–6%. In Ghost Mode, the visualiser thread is fully suspended — zero overhead, saving that headroom for the audio pipeline and battery.
Key lessons keeping Wavepunk smooth on constrained hardware:
QPixmap cache — don’t redraw backgrounds on every paint callsetUpdatesEnabled(False) during batch UI changes to prevent mid-update repaintsThe result in Operative Mode: 60fps UI, zero audio dropouts. In Ghost Mode: audio continues cleanly at reduced system load, battery runtime extended noticeably.
Next DevLog: how I taught ByteWave to understand your music taste — locally, privately, with no cloud and no ML frameworks beyond numpy.
— Gurteshwar Sandhu, Founder, IronLabs Tech
Leave a Reply