Project Overview
Player (Lyrune) is an Android audio application and digital signal processing (DSP) laboratory engineered around real-time PCM audio manipulation, adaptive Compose visual architectures, and synchronized lyrics resolution. The engine bypasses high-level platform effect wrappers by intercepting decoded PCM audio buffers directly through AndroidX Media3 BaseAudioProcessor, applying parametric Biquad equalization, 8D binaural spatialization, and delay reverb before feeding a lock-free post-DSP tap for real-time Fourier spectrum visualization.
Problem and Motivation
Standard mobile audio players rely on high-level Android system Equalizer APIs, which suffer from vendor-dependent audio latency, unpredictable buffer sizes, lack of custom spatial orbit effects, and decorative 'fake' visualizers that display random animations rather than true frequency energy. Furthermore, mobile stem separation is typically outsourced to remote cloud APIs, sacrificing user privacy and requiring constant internet connectivity. Player was architected to give developers and audiophiles direct, deterministic control over the raw PCM audio stream entirely on local silicon.
Requirements and Constraints
- ■Zero-allocation hot render loop: eliminate object instantiation inside audio processing buffers to prevent garbage collection frame drops.
- ■Deterministic post-DSP spectrum tap: frequency visualizer must reflect real, processed audio energy rather than mock animations.
- ■Off-main-thread FFT computation: calculate 2048-point Hann-windowed Fast Fourier Transforms on background coroutines without UI thread jank.
- ■Background MediaSession lifecycle: maintain robust playback under aggressive Android OS process management via foreground services.
- ■Air-gapped on-device stem separation: support optional UVR-MDX-NET model execution with LiteRT CPU/XNNPACK without cloud dependencies.
My Role & Contributions
- ›Primary Android developer: designed the Jetpack Compose architecture, Media3 service integration, and custom DSP audio pipeline.
- ›Implemented StudioAudioProcessor extending BaseAudioProcessor with Biquad filter chains and 8D binaural orbit spatialization.
- ›Engineered lock-free PcmAudioTap and Hann-windowed FFT spectrum analyzer with logarithmic frequency binning.
- ›Built LRCLIB synchronized lyrics resolver with binary search timestamp lookup and user-adjustable timing offsets.
System Architecture
Four-stage real-time audio pipeline and visualization architecture.
1. Media Source & Decoder
AndroidX Media3 ExoPlayer decodes local media files into 16-bit / 32-bit float PCM buffers.
2. Studio Audio Processor (DSP Chain)
Applies preamp gain, Biquad graphic EQ, stereo matrix crossfeed, 8D binaural panning, and safe peak limiting.
3. Lock-Free Post-DSP PCM Tap
Atomic circular buffer extracts post-filter PCM samples to background analyzer without render thread contention.
4. Hann FFT & Compose Visualizer
2048-point Hann-windowed FFT maps 24/48/64 logarithmic frequency bands interpolated smoothly in Jetpack Compose.
Technical Implementation
Low-Allocation PCM Audio Processing & Tap
The StudioAudioProcessor intercepts raw audio buffers via Media3 BaseAudioProcessor, executing in-place Biquad filtering and dispatching samples to the spectrum analyzer without triggering garbage collector pauses.
@UnstableApi
class StudioAudioProcessor(
private val pcmTap: PcmAudioTap = PcmAudioTap(),
) : BaseAudioProcessor() {
private val requestedConfig = AtomicReference(AudioConfig())
private var activeConfig = AudioConfig()
override fun queueInput(inputBuffer: ByteBuffer) {
if (!inputBuffer.hasRemaining()) return
val count = inputBuffer.remaining() / 2
val outputBuffer = replaceOutputBuffer(count * 2)
// Process PCM samples through Biquad EQ & 8D spatial orbit
processPcmBuffer(inputBuffer, outputBuffer, count)
// Submit post-DSP PCM tap for truthful 2048-pt FFT analysis
pcmTap.submit(outputBuffer)
}
}Important Algorithms & Decisions
Biquad Direct Form II Transposed Filters
Rationale: Direct Form II transposed structures provide superior numerical stability for audio equalization with minimal memory footprint on ARM processors.
Trade-off: Requires careful floating-point coefficient precalculation on sample rate changes.
Lock-Free Circular Audio Tap
Rationale: Decoupling the high-priority real-time audio thread from the 60/120 Hz UI visualizer thread using lock-free atomic references prevents audio buffer underruns.
Trade-off: Visualizer renders with a minimal, deterministic ~20ms latency offset, imperceptible to human eyes.
Engineering Challenges
Issue: Real-Time Audio Glitches During Parameter Tweaking
Root Cause: Reallocating filter coefficients or locking mutexes inside queueInput() caused Android audio render buffer starvation.
Resolution: Implemented AtomicReference config swaps and pre-allocated float buffer pools, achieving zero allocations in the active audio loop.
Testing & Evaluation
Automated Android CI workflow with Gradle unit tests, PCM buffer integrity checks, and UI component tests.
Results & Known Limitations
- ✓Engineered a fully functional, open-source Android audio player with genuine real-time DSP and spectrum analysis.
- ✓Published complete Kotlin 2.0 source code to GitHub with comprehensive architectural documentation.
- ⚠On-device neural stem separation requires modern multi-core ARM hardware for fast chunk inference.
Future Improvements
- →Develop custom C++ AAudio / Oboe native audio pipeline for sub-5ms professional monitoring.
- →Add extended spatial impulse response (IR) convolution reverb engine.
Repository & Verification
Public open-source repository on GitHub with full Kotlin source code and architecture documentation.