Voice Isolation
0.4.0 · GitHub
More about this app
On-device real-time voice isolation using Shizuku, GTCRN, and ONNX Runtime
Voice Isolation for Android
Android app that captures regular media and game audio through Shizuku, processes it with an on-device streaming ML model, and blends the original and isolated signals at an adjustable intensity.
What works
- One tap on START connects to the already running Shizuku service, loads GTCRN, and configures the audio route.
- A Quick Settings tile starts or stops isolation without opening the app; long-pressing the tile opens the app.
- A persistent notification shows the active service and provides intensity and stop actions.
- The intensity control ranges from the latency-aligned original signal at 0% to fully isolated audio at 100%.
- Podcast, Film, Gaming, Maximum, Custom, and named user presets persist across app restarts and appear in the notification and Quick Settings tile.
- An auto-off slider can stop isolation after 5–60 minutes without captured audio, or the feature can be disabled.
- An opt-in, token-protected automation API supports start, stop, preset, and intensity commands from Tasker or ADB.
- Full isolation compensates the model's measured 2.3 dB voice attenuation while retaining background suppression.
- Processing stays entirely on-device; the app intentionally has no internet permission.
- A privileged AOSP
AudioPolicyloopback route replaces the original mix without changing the global media volume. - Stopping releases
AudioRecord,AudioTrack, ONNX Runtime, and the dynamic audio policy.
Requirements
- Android 13 or newer.
- Install Shizuku.
- Start Shizuku. Without root, this is required again after every reboot; Android 11+ can use wireless debugging.
- Install the app and grant Shizuku access on first use.
- Start a media app and tap START in Voice Isolation.
- Optional: add Voice Isolation from the Quick Settings edit screen for one-tap access.
Once Shizuku is running and permission has been granted, starting the app is fully automatic. Without root, the app cannot start Shizuku by itself after a device reboot.
Tasker and automation
Enable Automation API in the app and copy its per-install token. The exported receiver has no intent filter; callers must target it explicitly and include that token. Keep the token private.
Actions:
| Action | Extra |
|---|---|
dev.sk2andy.voiceisolation.automation.START |
token |
dev.sk2andy.voiceisolation.automation.STOP |
token |
dev.sk2andy.voiceisolation.automation.SET_PRESET |
token, preset: podcast, film, gaming, maximum, custom, or a saved preset name |
dev.sk2andy.voiceisolation.automation.SET_INTENSITY |
token, intensity: number from 0.0 to 1.0 |
Configure Tasker's Send Intent action with target Broadcast Receiver, package dev.sk2andy.voiceisolation, class dev.sk2andy.voiceisolation.service.AutomationReceiver, and one action from the table. Example ADB commands:
adb shell am broadcast \
-n dev.sk2andy.voiceisolation/.service.AutomationReceiver \
-a dev.sk2andy.voiceisolation.automation.START \
--es token YOUR_TOKEN
adb shell am broadcast \
-n dev.sk2andy.voiceisolation/.service.AutomationReceiver \
-a dev.sk2andy.voiceisolation.automation.SET_PRESET \
--es token YOUR_TOKEN \
--es preset film
adb shell am broadcast \
-n dev.sk2andy.voiceisolation/.service.AutomationReceiver \
-a dev.sk2andy.voiceisolation.automation.SET_INTENSITY \
--es token YOUR_TOKEN \
--ef intensity 0.8
Android may reject automatic starts while the app is background-restricted. In that case, exempt Voice Isolation from battery restrictions or trigger start from a user-initiated Tasker action. Shizuku must already be running and authorized.
Languages
English is the default. The app also includes Spanish, Swedish, Polish, French, Portuguese, Russian, and Simplified Chinese translations. Android selects the language from the device or per-app language settings.
Technical limitations
| Area | Behavior |
|---|---|
| Regular media and game audio | Processes USAGE_MEDIA, USAGE_GAME, and USAGE_UNKNOWN |
| Calls, alarms, notifications | Intentionally not captured |
| DRM, hardware offload, tunneled playback | May bypass the framework mix route and remain unchanged |
| Vendor ROMs | Dynamic shell AudioPolicy is AOSP-based but not guaranteed on every OEM device |
| Model quality | GTCRN performs speech enhancement, not perfect vocal separation; music is usually attenuated strongly, but complete removal is not guaranteed |
| Shizuku through ADB | Must be restarted after every device reboot |
Architecture
Media apps
│
▼
AOSP AudioPolicy: pure LOOP_BACK (Shizuku UID shell/root)
│ 16 kHz mono PCM
▼
AudioRecord ─┬──────────────────── delayed dry ────────────────┐
└→ STFT → GTCRN/ONNX Runtime → iSTFT → +2.3 dB ─┤
▼
intensity mix → AudioTrack
The app excludes its own AudioTrack from the capture mix by Shizuku UID. Android 13+ also receives the correct com.android.shell attribution so AudioFlinger accepts the shell identity. On Android 12, the ADB shell lacks the required MODIFY_AUDIO_ROUTING permission, so that version is not listed as compatible.
Build
./gradlew assembleDebug
APK: app/build/outputs/apk/debug/app-debug.apk
Tests:
./gradlew testDebugUnitTest
./gradlew connectedDebugAndroidTest
./gradlew lintDebug
Verification
| Test | Coverage |
|---|---|
| JVM unit tests | PCM boundaries and STFT/iSTFT reconstruction |
| Android instrumentation | Real ONNX Runtime and gtcrn.onnx loading, followed by four streaming frames |
| Android 16 emulator | Shizuku UserService as UID 2000, policy registration, remote submix, 440 Hz USAGE_MEDIA capture, GTCRN processing, and stop/policy unregister |
| Speech/music vector | Pinned real GTCRN speech sample plus a deterministic music bed; requires at least 2 dB SI-SDR improvement and 6 dB speech-over-music selectivity |
On the emulator, the synthetic signal took about 0.9 ms of inference time per 16 ms frame (RTF ≈ 0.05). Actual performance depends on the device.
The reproducible model measurement runs separately so the Android app itself can remain offline:
python3 -m venv /tmp/voice-isolation-validation
/tmp/voice-isolation-validation/bin/pip install numpy onnxruntime
/tmp/voice-isolation-validation/bin/python tools/validate_gtcrn_music.py
The pinned vector measured +2.81 dB SI-SDR improvement, -2.30 dB speech gain, and -16.11 dB music gain. Speech therefore remained 13.80 dB above the music gain. This demonstrates strong attenuation for this test vector, not perfect separation for arbitrary music.
Acknowledgements and third-party software
Poise Android was used only as a product and architecture comparison. That project does not publish a license, so no Poise source code was copied. The GTCRN model comes directly from the MIT-licensed official upstream project. See THIRD_PARTY_NOTICES.md for details.
The app also uses ONNX Runtime and the Shizuku API. Thanks to their maintainers and contributors.
License
Original source code is available under the MIT License. Third-party components remain under their respective licenses; see THIRD_PARTY_NOTICES.md.
How Shizuku is used
Can isolate voices in playing media in real time via Shizuku using `AudioPolicy` loopback capture and playback
This is an AI-assisted analysis of Shizuku-related usages in the app's public source code. It is best effort, so it may not catch every single usage.
How this app uses Shizuku
Shizuku is used to run the audio cleaning engine with system privileges so it can tap into device playback, remove noise, and play back clean speech.
- Capture device playback: media, game and other entertainment audio playing on the device is rerouted through a privileged loopback audio route through Shizuku so it can be processed.
- Play isolated voice: the captured sound is cleaned on device with a noise removal model and played back right away through a low latency playback stream, with adjustable cleaning strength and live level and performance stats.
- Manage privileged session: starting, stopping and changing cleaning strength from the app, notification, quick tile or automation actions is forwarded to the privileged session through Shizuku.
Android APIs or commands used
AudioManager.registerAudioPolicyAudioManager.unregisterAudioPolicyandroid.media.audiopolicy.AudioPolicyandroid.media.audiopolicy.AudioMixandroid.media.audiopolicy.AudioMixingRuleAudioRecordAudioTrackAttributionSource.BuilderActivityThread.currentApplication()
Changelog
What's new for version 0.4.0
Persistent presets, automatic idle shutdown, and secure automation for power users.
What's new
Presets and persistent settings
- Add built-in Podcast (85%), Film (65%), Gaming (50%), Maximum (100%), and Custom presets
- Create, overwrite, select, and delete any number of named user presets
- Persist intensity, Custom intensity, selected preset, user presets, Auto-off, and Automation settings
- Show the active preset in the persistent notification and Quick Settings tile
- Apply preset and intensity changes made while the audio model is still loading
Auto-off
- Add an Auto-off slider with Off or 5–60 minute choices in five-minute steps
- Default Auto-off to 15 minutes and persist the choice across app and service restarts
- Reset the inactivity timer whenever captured media becomes audible
- Track peak input across each 240 ms statistics window so brief playback is not missed
- Stop foreground and privileged audio services cleanly after continuous silence
- Show a clear status message when Auto-off stops isolation
Tasker and automation
- Add explicit start, stop, preset, and intensity broadcast commands for Tasker and ADB
- Keep automation disabled by default and protect commands with a per-install 128-bit token
- Require explicit receiver targeting and avoid logging the secret token
- Mark copied tokens as sensitive clipboard content
- Document actions, extras, Tasker setup, and ADB examples in the README
Languages
- Add all new UI and status text in English, Spanish, Swedish, Polish, French, Portuguese, Russian, and Simplified Chinese
Quality
- Add JVM coverage for Auto-off boundaries, timer resets, preset mapping, setting normalization, and user-preset serialization
- Add Android settings persistence instrumentation coverage
- Pass all 23 JVM tests, Android lint, debug build, AndroidTest compilation, and minified release build
- Complete an independent lifecycle and automation-security review and address its findings
- Update the README with Auto-off, presets, persistence, and Automation API documentation
- Bump Android app version to 0.4.0 (version code 4)
Installation
Download the attached APK and install it over v0.3 or as a fresh installation. Android 13+ and Shizuku remain required.
Permissions
5 permissions requested