An android music player with bit-perfect USB output and native (no electron!) Tidal integration
| app | ||
| build-ffmpeg | ||
| dependencies | ||
| gradle/wrapper | ||
| scripts | ||
| .gitignore | ||
| .gitmodules | ||
| build.gradle.kts | ||
| CLAUDE.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| README.md | ||
| settings.gradle.kts | ||
| shell.nix | ||
PlaceboPlayer
A minimalist Android music player focused on audio quality for USB DACs.
Key Features
- Bit-perfect audio output - Direct USB DAC support with no resampling or mixing
- Gapless playback - Seamless transitions between tracks
- Aggressive buffering - Pre-loads songs into memory for instant playback
- Folder-based navigation - No library, just browse your files
- Privacy-first - No tracking, no analytics, no network communication
- AOSP compatible - Works on pure Android without Google services
Technical Highlights
- Min SDK: API 34 (Android 14.0+) for advanced AudioTrack API
- Architecture: MVVM with Jetpack Compose
- Playback: Media3 fork with BitPerfectAudioOutputProvider for USB DACs
- Media Session: Lock screen controls and notification integration
- Data Architecture: Dual database design (persistent settings + regenerable cache)
- Persistent Database (userdata): Settings, playlists, playback history
- Cache Database (cache storage): Metadata, cover art (cleared by Android when storage low)
Known issues
- Gapless playback doesn't work correctly
Planned features
- Use cache to speed up folder navigation - populate immediately from cache, progressively update as directory listing is updated
- A "stats for nerds" screen with detailed debug info. A detailed display of buffer usage, etc.
- Display an amplitude waveform instead of the seek bar, allow sliding it back and forth to seek ("waveform seekbar")
Quick Start
# Build app
./gradlew assembleDebug
# Start emulator with GUI, install the built apk and run it
./scripts/emulator.sh --gui
Available Scripts
emulator.sh- Install APK and run app in emulator, starting the emulator if not already running.--gui- Enable graphical interface--install-apk <path>- Install specified APK instead of the default
app_restart.sh- Kill, reinstall and restart the app on emulatorapp_logcat.sh- Stream logs from the app (use with timeout)app_play_intent.sh- Trigger playback via intent (for automated testing)
Automated Testing & Debugging
The app supports intent-based playback triggering for automated testing:
# Trigger playback with test files
./scripts/app_play_intent.sh
# View logs (use timeout to limit output)
timeout 10 ./scripts/app_logcat.sh
# Reinstall and restart app
./scripts/app_restart.sh
The app_play_intent.sh script demonstrates how to:
- Send a
PLAY_AUDIOintent with a content:// URI - Provide an optional queue of tracks
- Trigger playback programmatically without UI interaction
See CLAUDE.md for technical details.
Documentation
- CLAUDE.md - Technical documentation for developers and AI agents
License
GPLv2+