A single-deck DJ player for Android phones in landscape orientation. The project's top priority is minimal latency: tracks, CUE and hot cue start instantly, like on professional DJ equipment. The UI is written in Kotlin, the audio engine in C++ (Android NDK), working directly with AAudio without third-party libraries.
Within the project we delivered:
A C++ audio engine with AAudio in low-latency mode (MMAP, exclusive): the stream runs constantly, so play and pause add no latency; automatic buffer tuning on underruns and recovery when headphones or Bluetooth are disconnected
A lock-free command queue between the UI and the audio thread: CUE and hot cue are processed at the exact playback position, with no allocations or locks in the audio callback
CUE and hot cue logic like on a Pioneer CDJ: hold-to-preview, setting the point, jumps with a 4 ms crossfade without clicks; hot cue is recorded with output latency compensation — exactly what you hear at the moment of pressing
Pitch without keylock (like vinyl) with cubic interpolation: a pitch wheel with ±8, ±16 and ±50% ranges, pitch bend by finger speed, scratch seeking while paused
Decoding MP3, AAC, WAV and other formats via MediaCodec with progressive loading: a track can be played ~0.3 s after selection while it is still being decoded
A cache of decoded tracks with LRU eviction: reloading a 6-minute track takes about 150 ms instead of 25 s
Automatic BPM and beat grid detection: onset function, autocorrelation and a phase histogram with 0.01 BPM accuracy
TAP tempo refinement (linear regression over taps + waveform search) and manual marking of the 1st and 2nd beats; grids are stored in SQLite by the file's SHA-256
A waveform colored by frequency bands (bass, mids, highs) with a beat grid, pinch zoom and swipe seeking, an overview strip of the whole track
A 64- or 128-beat phrase indicator that blinks before the next section, a beat-in-bar indicator
A neon UI with zero-latency button response to touch, an app icon