5e13ff069d
- Add VUServerProtocol struct with proper binary frame format - Header: '>' + cmd + reserved + data_type + reserved + len_h + len_l + reserved + len_l - Support commands: setDialPercentSingle (0x03), setDialPercentAll (0x04) - Support backlight control (RGB/RGBW) - Add device info queries (firmware/hardware version, UID) - Add response parsing for '<' responses from hardware - Show firmware/hardware version in UI when connected - Update protocol info display to reflect binary protocol
Audio VU Meter for macOS
A native macOS SwiftUI application that displays real-time audio levels from BlackHole (or any audio input device) as a classic VU meter, along with system resource monitoring. Now with physical VU meter hardware support!
Features
Audio VU Meter
- Real-time audio level monitoring - Displays Left and Right channel levels
- dB scale display - Shows audio levels in decibels (-60 dB to 0 dB)
- Peak hold indicators - Visual peak markers with configurable hold time
- BlackHole integration - Automatically detects and selects BlackHole virtual audio device
- Multi-device support - Switch between any available audio input device
System Resource Monitors
- CPU Usage - Real-time CPU utilization percentage
- RAM Usage - Memory consumption monitoring
- Disk Activity - Disk I/O activity indicator
- Network Activity - Network throughput monitoring
Physical VU Meter Hardware Support
- 4 Physical Dials - Support for up to 4 physical VU meter dials
- Flexible Channel Mapping - Assign any metric to any dial:
- Audio Left/Right channels
- Audio Peak or Mono (L+R)
- CPU, RAM, Disk, Network usage
- Multiple Serial Protocols:
- Raw Bytes:
[0xAA] [D1] [D2] [D3] [D4] [0x55] - Text Commands:
CH1:val;CH2:val;CH3:val;CH4:val\n - JSON:
{"dials":[d1,d2,d3,d4]} - VU-Server Compatible:
#0:val\n#1:val\n...
- Raw Bytes:
- Configurable per dial: Min/max values, inversion, smoothing
- Auto-detection of USB serial devices
Requirements
- macOS 13.0 (Ventura) or later
- Xcode 15.0 or later (for building)
- BlackHole virtual audio driver (recommended)
- USB/Serial VU meter hardware (optional)
Installation
Using BlackHole
- Install BlackHole from existential.audio/blackhole
- Configure BlackHole as a multi-output device in Audio MIDI Setup
- Build and run Audio VU Meter
- The app will automatically detect and select BlackHole
Building from Source
- Clone the repository
- Open
AudioVUMeter.xcodeprojin Xcode - Build and run (Cmd+R)
git clone <repository-url>
cd AudioVUMeter
open AudioVUMeter.xcodeproj
Usage
Main Window
- Audio Levels: The vertical VU meters show Left (L) and Right (R) channel audio levels
- dB Readings: Numeric display of current audio levels in decibels
- System Meters: Circular gauges showing CPU, RAM, Disk, and Network usage
- Hardware Output: Shows status of connected physical VU meters
Controls
- Start/Stop: Toggle audio capture on/off
- Reset: Clear peak hold indicators
- Settings (gear icon): Access device selection and preferences
- Hardware (cable icon): Configure physical VU meter connection
Hardware Setup
- Connect your USB/Serial VU meter hardware
- Click the cable icon or go to Settings -> Hardware
- Select your serial port from the dropdown
- Choose the appropriate baud rate (default: 115200)
- Select the communication protocol your hardware uses
- Assign channels to each dial (Audio L, R, CPU, RAM, etc.)
- Click "Connect"
Settings
- Input Device: Select audio input source (BlackHole, microphone, etc.)
- Reference Level: Adjust the 0 dB reference point
- Peak Hold Time: Configure how long peak indicators remain visible
- Hardware: Serial port, protocol, and dial assignments
Architecture
AudioVUMeter/
├── AudioVUMeterApp.swift # App entry point
├── ContentView.swift # Main UI layout
├── VUMeterView.swift # VU meter components
├── AudioEngine.swift # Core Audio capture engine
├── SystemMonitor.swift # System resource monitoring
├── SerialManager.swift # USB/Serial communication
├── HardwareView.swift # Hardware configuration UI
├── SettingsView.swift # Settings window
└── Assets.xcassets/ # App icons and colors
Key Components
- AudioEngine: Uses AVAudioEngine to capture audio from the selected input device, calculates RMS levels, and converts to dB
- SystemMonitor: Uses Mach kernel APIs to retrieve CPU, memory, disk, and network statistics
- SerialManager: Handles USB/Serial communication with physical VU meter hardware
- VUMeterView: SwiftUI views for classic vertical VU meters with segment-based display
- SystemMeterView: Circular gauge components for system metrics
Hardware Protocol Reference
Raw Bytes Protocol
Start: 0xAA
Data: [Dial1] [Dial2] [Dial3] [Dial4] (0-255 each)
End: 0x55
Text Command Protocol
CH1:128;CH2:64;CH3:200;CH4:32\n
JSON Protocol
{"dials":[128,64,200,32]}
VU-Server Compatible Protocol
#0:50
#1:75
#2:30
#3:90
Values are percentages (0-100)
BlackHole Setup Guide
-
Install BlackHole: Download and install from existential.audio
-
Create Multi-Output Device:
- Open Audio MIDI Setup (Applications -> Utilities)
- Click the
+button -> Create Multi-Output Device - Check both your speakers and BlackHole
- Set as default output
-
Route Audio:
- System audio will now go to both speakers and BlackHole
- Audio VU Meter captures from BlackHole input
Compatible Hardware
This app is designed to work with:
- VU Dials by Sasa Karanovic
- Arduino-based VU meters with serial interface
- Any USB/Serial device accepting the supported protocols
API Reference
AudioEngine
// Start/stop audio capture
audioEngine.start()
audioEngine.stop()
// Reset peak indicators
audioEngine.resetPeaks()
// Switch audio device
audioEngine.selectedDeviceID = deviceID
audioEngine.switchDevice()
// Access levels
audioEngine.leftLevel // 0.0 to 1.0
audioEngine.rightLevel // 0.0 to 1.0
audioEngine.leftLevelDB // -60 to 0 dB
audioEngine.rightLevelDB // -60 to 0 dB
SystemMonitor
// Start/stop monitoring
systemMonitor.startMonitoring()
systemMonitor.stopMonitoring()
// Access metrics (0-100%)
systemMonitor.cpuUsage
systemMonitor.memoryUsage
systemMonitor.diskActivity
systemMonitor.networkActivity
SerialManager
// Connection
serialManager.connect()
serialManager.disconnect()
// Configuration
serialManager.selectedPortPath = "/dev/cu.usbserial-XXX"
serialManager.baudRate = 115200
serialManager.selectedProtocol = .vuServer
// Dial assignment
serialManager.dialConfigs[0].dialChannel = .audioLeft
serialManager.dialConfigs[1].dialChannel = .audioRight
serialManager.dialConfigs[2].dialChannel = .cpu
serialManager.dialConfigs[3].dialChannel = .ram
License
MIT License - See LICENSE file for details.
Credits
Inspired by VU-Server by Sasa Karanovic.