# AhSilence: an Android ANC engine built on a radix-2 FFT

> AhSilence is an open source Android active noise cancellation app that scans the room for a low frequency hum and emits phase-inverted audio to cancel it. It suits developers who want to read a real DSP pipeline implemented in Kotlin, and it needs a physical device and a foreground service permission to work at all.

**AhmadHassan-BTed/AhSilence** — An open-source Android Active Noise Cancellation (ANC) engine. Leveraging low-latency DSP to neutralize environmental hums and help you reclaim your quiet.

- Repository: https://github.com/AhmadHassan-BTed/AhSilence
- Stars: 2,757 · Forks: 4
- Language: Kotlin
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/ahmadhassan-bted-ahsilence

## A seven second scan finds one hum, then a manual dial lines it up

AhSilence is a native Android active noise cancellation engine, written in Kotlin with Jetpack Compose. The mechanism it implements is acoustic destructive interference: it listens to the room, finds the persistent low frequency sound that dominates it, such as an air conditioning unit or an electrical drone, and then plays back an inverted copy of that sound so the two cancel each other out.

The data flow is documented as a sequence, and the order matters. The microphone captures a raw PCM buffer, the engine computes a radix-2 FFT over it, and the dominant frequency in hertz is extracted from the result. That state is pushed to the dashboard as an acoustic state update. A seven second ambient scan is the window the sequence diagram names for this first stage, so the app is deliberately patient before it acts.

The second stage is the user, not the software. The dashboard injects a phase offset in degrees and an amplitude value into the engine, and the phase calibrator is a continuous 360 degree trigonometric dial bound to memory blocks. The README describes it as manual wave alignment to compensate for hardware and Bluetooth latency, which is the honest framing: the app cannot know the round trip delay between the microphone and the speaker, so it asks you to find it.

Only after that does the continuous emission loop start, where the engine synthesizes an inverted sine wave and pushes buffers to the speaker with a blocking write.

## The FFT is a custom Cooley-Tukey radix-2 implementation

The signal analysis is not delegated to a library. The feature table names the FFT engine as a custom Cooley-Tukey radix-2 algorithm running on real time PCM buffers, and the project structure puts it in a file called FastFourier.kt under the data layer, described as the radix-2 FFT math engine.

That choice has a clear justification in the surrounding text. The engine is a zero-allocation, garbage free hot loop, and a library that allocated buffers per call would fight that. Writing the transform by hand is what makes it possible to reuse the same memory across the analysis and the synthesis stages.

The audio I/O is standard Android. Capture is AudioRecord with PCM 16-bit at 44.1 kHz, and playback is AudioTrack in streaming mode. The NativeAudioDSP class is described as the AudioRecord and AudioTrack pipeline, and the sequence diagram shows the emission side pushing a buffer with a blocking write, which is the correct choice for a real time path because it lets the writer wait rather than drop frames.

The result is a pipeline where every stage is inspectable. A developer reading the project can follow the signal from the microphone buffer, through the transform, into the dominant frequency extraction, through the phase and gain the user set, and out to the speaker.

## Why the hot loop must not allocate

The most emphatic claim in the project is about memory, and it appears in several forms. The overview says the application runs a zero-allocation, garbage free hot loop, so the destructive interference continues without frame drops or OS throttling. The stateless UI row of the feature table gives the user facing reason, stating that StateFlow and hoisted Compose parameters mean zero battery drain from unnecessary recompositions. The contributing guide is described as containing non-negotiable architectural rules, and the rules are named: zero-allocation hot loops, domain isolation, and UI purity.

That is an unusually clear statement of constraints for a small project, and it explains a lot of the design choices. A foreground service with a persistent notification keeps the cancellation active while the screen is locked, which is what makes the app usable at all in a real setting, and the mediaPlayback foreground service type is what Android requires for that. A UI that recomposes constantly would be a battery problem on a phone that is playing continuous audio to cancel a hum.

The layering follows the same logic. The domain directory is labelled pure Kotlin with zero Android imports, containing an immutable single source of truth in AcousticState and a port that defines the DSP engine contract. The data layer holds the Android framework implementations, so the service and the engine satisfy an interface declared in the domain rather than the other way round.

## Three layers and a service locator instead of a framework

The architecture section describes Clean Architecture with strict unidirectional data flow and complete isolation of the Android framework from core business logic, and the diagram shows how the pieces connect.

The presentation layer holds the Compose UI and a ControlViewModel, and the domain layer holds the AcousticState and the AudioEngine port. The data layer holds ActiveHumService, NativeAudioDSP and FastFourier. The arrows show the UI observing state from the ViewModel, the UI sending an OS intent to the service, the ViewModel updating the state and injecting phase and gain through the port, the service shielding the DSP in the foreground, the DSP implementing the port, and the DSP doing its PCM buffer math through the FFT.

The dependency inversion is visible in the diagram, since the ViewModel injects through a port that the data layer implements. That is the mechanism that lets the domain layer carry no Android imports at all, and it is why the file layout can put an immutable state model and an interface in a directory with no framework dependency.

One detail departs from the usual pattern. Instead of a dependency injection framework, the project uses a lightweight service locator, AudioEngineLocator, in the core directory alongside the constants and the logging facade. For an application this size that is a reasonable trade, since the alternative adds an annotation processor and a graph for a single engine, and the cost is that construction is resolved at runtime rather than compile time.

## Building it needs a physical phone, not an emulator

The getting started section is short and honest about the one thing that trips people up. The prerequisites are Android Studio Ladybug at 2024.2.1 or newer, JDK 21 or newer, and a physical Android device, with the reason given plainly: emulators do not support low-latency hardware microphone FFT testing. That is a hardware requirement, not a preference, and it means the entire test procedure depends on a real audio path.

The build steps are the standard Gradle ones:

```bash
# Clone
git clone https://github.com/ahmadhassan-bted/ahsilence.git
cd ahsilence

# Build debug APK
./gradlew clean assembleDebug

# Run unit tests
./gradlew test

# Lint check
./gradlew lint
```

and the install step for a connected device:

```bash
# Install on connected device
./gradlew installDebug
```

The stack is Kotlin 2.0.21, Jetpack Compose, StateFlow with a ViewModel, and a Gradle build with the Kotlin DSL and a version catalog. The minimum SDK is API 26, Android 8.0.

The project structure is worth reading before you start, because it tells you where to put things. The app module holds core, domain, data, presentation, ui and MainActivity, and the ui directory carries the theme files for an OLED Black and Neon Amber design system along with the two interactive components, the CalibratorRing and the GainSlider. There is also a separate ancengine/ directory at the top level of the repository alongside the app module, and docs/, a ROADMAP.md, a SECURITY.md, a CHANGELOG.md and a SUPPORT.md.

## Offline by design, and honest about what is still missing

The security note is one line and worth repeating. AhSilence is fully offline, with zero network calls, zero data collection and zero telemetry, and the project points at a SECURITY.md for the detail. For an app whose whole job is to listen to a room continuously through the microphone, that claim is the first thing a reviewer would ask about, and the answer is that nothing leaves the device.

The roadmap is where the project is candid about the limits of the current implementation. It lists multi-frequency cancellation, adaptive algorithms and Bluetooth latency compensation as planned features. Those three items are exactly the three things that a user of the current version would ask for: cancel more than one hum at a time, adjust automatically instead of by hand, and account for the delay of a Bluetooth speaker.

The last of those connects back to the phase calibrator. The dial exists because the engine cannot measure the latency of the microphone to speaker path, and Bluetooth adds to it. A manual 360 degree dial is a workable answer for a phone with a built-in speaker and a poor one for a pair of wireless earbuds.

There are no GitHub releases for the project, so the last push to the master branch on 2026-09-15 is the only public signal of activity, and the version is carried in the source rather than in a tag. The licence is Apache 2.0, with the copyright line naming Ahmad Hassan, and the project describes itself as fully open source with a code of conduct and a support document alongside the contribution guide.

## Conclusion

Adopt AhSilence if you want to study or extend a real time DSP pipeline on Android, since the FFT, the calibration dial and the foreground service are all in Kotlin with a documented layer structure, and the project is Apache 2.0 with an offline, telemetry free design. Do not adopt it expecting a consumer noise cancelling product, because the cancellation is limited to a dominant low frequency hum with manual phase alignment, and the roadmap lists multi-frequency cancellation as future work. Before you build, get a physical device, because the project states that emulators do not support low-latency hardware microphone FFT testing, and plan the calibration step into your workflow since the phase offset is set by hand.

## FAQ

### How does AhSilence cancel noise?

It captures a raw PCM buffer from the microphone, computes a radix-2 FFT to extract the dominant frequency of the ambient hum, and then synthesizes a phase-inverted sine wave at that frequency and plays it through AudioTrack, so the two wavefronts cancel. The amplitude and phase offset are set manually through the calibrator dial and gain slider.

### Can I test AhSilence on an Android emulator?

No. The prerequisites state that a physical Android device is required because emulators do not support low-latency hardware microphone FFT testing. The build itself is a standard Gradle build with assembleDebug, test and lint targets.

### Does AhSilence send any data over the network?

No. The project states it is fully offline with zero network calls, zero data collection and zero telemetry, and points to a SECURITY.md file in the repository for details.

### What is the minimum Android version for AhSilence?

The minimum SDK is API 26, which is Android 8.0. The build needs JDK 21 or newer and Android Studio Ladybug 2024.2.1 or newer, and the project is written in Kotlin 2.0.21 with Jetpack Compose.

## Sources

- [AhmadHassan-BTed/AhSilence on GitHub](https://github.com/AhmadHassan-BTed/AhSilence)
- [Issues](https://github.com/AhmadHassan-BTed/AhSilence/issues)
- [License: Apache-2.0](https://github.com/AhmadHassan-BTed/AhSilence/blob/master/LICENSE)
- [README](https://github.com/AhmadHassan-BTed/AhSilence/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ahmadhassan-bted-ahsilence
