Skip to content

gpavelski/aubio-tuner-android

Repository files navigation

Aubio Tuner (Android)

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.


✨ Features

  • 🎵 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

🧱 Architecture Overview

┌──────────────────────┐
│   Android UI (Kotlin)│
│  MainActivity        │
│  Custom Views        │
│  Settings UI         │
└─────────┬────────────┘
          │ JNI
┌─────────▼────────────┐
│ NativeAudioEngine    │
│  (JNI bridge)        │
└─────────┬────────────┘
          │ C++
┌─────────▼────────────┐
│ AudioEngine (C++)    │
│  Oboe Input Stream   │
│  Aubio Pitch         │
│  Spectrum Analysis   │
└──────────────────────┘

Threading Model

  • 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.


📂 Project Structure

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/

🔊 Audio Input Modes

1. Microphone (Normal Operation)

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

2. WAV File Simulation (Testing)

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.


⚙️ Configuration

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.


🛠️ Build & Requirements

Requirements

  • Android Studio (Giraffe or newer recommended)
  • Android NDK
  • CMake
  • Android device with microphone support

Build

Directly from Android Studio.


🧪 Debug vs Release

  • 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/

📦 Third-Party Libraries

  • Oboe – Low-latency audio I/O
  • Aubio – Pitch detection & audio analysis

All DSP runs natively for performance and determinism.


📸 Screenshots


🚧 Known Limitations

  • 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

📜 License

MIT License.


🤝 Contributing

Contributions, bug reports, and improvements are welcome.

If contributing native code, please:

  • Avoid allocations in audio callbacks
  • Keep DSP deterministic
  • Maintain thread safety