Aubio Tuner is a real-time musical instrument tuner for Android, built with a Kotlin UI layer and a native C++ audio engine based on Oboe and Aubio. It provides low-latency pitch detection, note estimation, cents deviation, and a real-time frequency spectrum visualization.
The project is designed with a clear separation between:
- UI / Application logic (Kotlin)
- Audio processing and DSP (C++ / NDK)
This makes it suitable both as a production app and as a reference implementation for native audio + DSP on Android.
- 🎵 Real-time pitch detection (Hz)
- 🎼 Musical note detection with cents deviation
- 📊 Live frequency spectrum visualization
- 🎤 Low-latency microphone input via Oboe
- 📁 WAV file processing mode (for testing & debugging)
- ⚙️ Configurable Aubio parameters (buffer size, hop size, tolerance, silence threshold)
- 🧵 Thread-safe native ↔ UI data exchange
┌──────────────────────┐
│ Android UI (Kotlin)│
│ MainActivity │
│ Custom Views │
│ Settings UI │
└─────────┬────────────┘
│ JNI
┌─────────▼────────────┐
│ NativeAudioEngine │
│ (JNI bridge) │
└─────────┬────────────┘
│ C++
┌─────────▼────────────┐
│ AudioEngine (C++) │
│ Oboe Input Stream │
│ Aubio Pitch │
│ Spectrum Analysis │
└──────────────────────┘
-
Audio thread (Oboe callback or WAV simulation thread)
- Pitch detection
- Spectrum computation
-
UI thread
- Polls frequency and spectrum at ~30 FPS
- Renders tuner needle, note labels, and frequency bars
Atomic variables and mutexes are used to ensure thread safety.
app/
├─ src/main/java/
│ ├─ audio/ # NativeAudioEngine (JNI interface)
│ ├─ ui/ # Custom views (MeterView, NotesView, FrequencyBarsView)
│ ├─ settings/ # Settings UI & persistence
│ └─ MainActivity.kt
│
├─ src/main/cpp/
│ ├─ AudioEngine.h/.cpp
│ ├─ Spectrum.*
│ ├─ AubioSettings.*
│ └─ jni bindings
│
├─ src/main/assets/
│ └─ *.wav # Debug/testing audio (optional)
│
└─ src/main/res/
├─ layout/
├─ values/
└─ drawable/
Uses Oboe in low-latency input mode.
NativeAudioEngine.start(settings)- Audio callback performs pitch + spectrum computation
- Sample rate is queried from the actual device stream
Processes a WAV file from assets in real time, emulating live input.
NativeAudioEngine.startWithWav(assets, "chirp48k.wav")Useful for:
- Debugging DSP logic
- Reproducible testing
- UI development without microphone noise
⚠️ Debug WAV assets should not be packaged in release builds.
Pitch detection behavior is controlled via AubioSettings, including:
- Pitch detection mode
- Buffer size
- Hop size
- Silence threshold (dB)
- Detection tolerance
Settings persist across app restarts.
- Android Studio (Giraffe or newer recommended)
- Android NDK
- CMake
- Android device with microphone support
Directly from Android Studio.
- Debug builds may include WAV assets and logging
- Release builds should exclude debug assets to reduce APK size
Use variant-specific source sets:
src/debug/assets/
src/release/assets/
- Oboe – Low-latency audio I/O
- Aubio – Pitch detection & audio analysis
All DSP runs natively for performance and determinism.
- Mono input only
- Spectrum resolution tied to hop size
- UI polling is timer-based (not event-driven)
- Frequency Bars use silence threshold to only show spectrum above given value
- Harmonics may cause the note to be detected in wrong octave
MIT License.
Contributions, bug reports, and improvements are welcome.
If contributing native code, please:
- Avoid allocations in audio callbacks
- Keep DSP deterministic
- Maintain thread safety