High-Performance Canvas Rendering
Relevant source files
The following files were used as context for generating this wiki page:
High-Performance Canvas Rendering in the BT Speaker project refers to the specialized implementation of the audio visualizer within the pi_app. This system is designed to drive a live audio visualizer on a Raspberry Pi Zero 2 W using Flutter's CustomPainter API. The rendering engine bypasses standard animation controllers to achieve the necessary performance for real-time FFT (Fast Fourier Transform) data visualization at high refresh rates.
The scope of this rendering module includes the translation of incoming BeatData into visual elements—specifically frequency bars—drawn directly to a Canvas. This approach is optimized for the flutter-pi runtime, which utilizes DRM/KMS for direct hardware rendering without an X server.
Sources: README.md:38-42, CLAUDE.md:10-15
Architecture and Data Flow
The rendering architecture is reactive, driven by a stream of WebSocket events originating from a companion mobile application. Data flows through a BLoC layer that manages the state of the visualizer before reaching the specialized UI components.
Rendering Pipeline
The rendering pipeline is optimized to handle high-frequency updates (~30–60 Hz) by feeding data directly from the WebSocket stream to the CustomPainter. This minimizes the overhead of the Flutter widget tree by isolating the drawing logic.
The diagram shows the flow from network data reception to physical HDMI output on the Raspberry Pi.
Sources: README.md:38-42, CLAUDE.md:23-28
Components and Classes
High-performance rendering is achieved through the interaction of several key components across the monorepo.
VisualizerPainter
The VisualizerPainter is the core class responsible for the actual rendering logic. It extends Flutter's CustomPainter and is invoked every time the VisualizerBloc emits a new state containing fresh BeatData. Unlike standard Flutter animations, it does not use an AnimationController to avoid unnecessary scheduling overhead on the Pi's quad-core ARM Cortex-A53.
Sources: README.md:40-42, CLAUDE.md:14-16
Data Models
Rendering is dependent on the BeatData model provided by the bt_speaker_core package. This model encapsulates the raw frequency information required to draw the visualizer.
| Field | Description | Source |
|---|---|---|
FFT Bars | A list of frequency magnitudes used to determine bar height | README.md:33-35 |
BPM | Beats per minute used for timing-based visual cues | README.md:33-35 |
Intensity | A scalar value representing the overall loudness/energy | README.md:33-35 |
Core Infrastructure Components
| Component | Responsibility | File Path |
|---|---|---|
VisualizerBloc | Subscribes to shared WebSocket events; exposes typed state | apps/pi_app/lib/features/visualizer/bloc/ |
bt_speaker_core | Defines shared models like BeatData and EqSettings | packages/bt_speaker_core/ |
flutter-pi | Low-level embedder providing DRM/KMS rendering | CLAUDE.md:18-20 |
Hardware-Specific Optimizations
The rendering engine is specifically tuned for the Raspberry Pi Zero 2 W. Because this hardware lacks a traditional windowing system (X server/Wayland), the project uses flutter-pi to target the DRM/KMS subsystem directly.
Execution Context
The following configuration is critical for maintaining performance:
- Architecture:
armv7(32-bit). - CPU: Generic quad-core ARM Cortex-A53 @ 1 GHz.
- Build Mode: Release builds are mandatory for fluid canvas performance (
flutterpi_tool build --release). - Direct Rendering: The UI is rendered directly to the HDMI display, bypasssing standard Linux display managers.
Sources: CLAUDE.md:14-20, README.md:11-14
WebSocket Integration for Rendering
The rendering loop is synchronized with the incoming WebSocket data rate. The sequence below illustrates how a rendering frame is triggered.
This diagram demonstrates the event-driven nature of the canvas updates.
Sources: README.md:28-35, CLAUDE.md:23-28
Conclusion
High-Performance Canvas Rendering in BT Speaker is a specialized implementation designed to overcome the resource constraints of the Raspberry Pi Zero 2 W. By utilizing an event-driven CustomPainter and the flutter-pi embedder, the system provides a smooth, real-time audio visualization experience without the overhead of standard Flutter animation controllers.