Skip to content

Commit 3d08a03

Browse files
committed
Fix AHSA hearing aid support
The issue was that steam-audio spatializer doesn't work at sample rates less than 44.1kHz. The iplHRTFCreate function was failing which resulted in no audio. I did consider adding code so that if this failed again it would default to no spatialization, but that would be a much more hidden failure and it would be better to fail with no audio.
1 parent 74bb5d1 commit 3d08a03

4 files changed

Lines changed: 119 additions & 1 deletion

File tree

app/src/main/cpp/AudioMixer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace soundscape {
2323
->setSharingMode(oboe::SharingMode::Shared)
2424
->setFormat(oboe::AudioFormat::Float)
2525
->setChannelCount(oboe::ChannelCount::Stereo)
26+
->setSampleRate(48000)
2627
->setFramesPerDataCallback(FRAME_SIZE)
2728
->setUsage(oboe::Usage::Media)
2829
->setContentType(oboe::ContentType::Music)

app/src/main/cpp/SteamAudioSpatializer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace soundscape {
2727
hrtfSettings.normType = IPL_HRTFNORMTYPE_NONE;
2828
err = iplHRTFCreate(m_Context, &m_AudioSettings, &hrtfSettings, &m_Hrtf);
2929
if (err != IPL_STATUS_SUCCESS) {
30-
TRACE("SteamAudio: iplHRTFCreate failed: %d", err);
30+
TRACE("SteamAudio: iplHRTFCreate failed: %d, sample rate %d, frameSize %d", err, sampleRate, frameSize);
3131
iplContextRelease(&m_Context);
3232
m_Context = nullptr;
3333
return;
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
---
2+
title: ASHA hearing aid simulation
3+
layout: page
4+
parent: Information for developers
5+
has_toc: true
6+
---
7+
8+
# ASHA hearing aid simulation with Bumble
9+
10+
[ASHA (Audio Streaming for Hearing Aids)](https://source.android.com/docs/core/connect/bluetooth/asha) is the Google protocol used by Android to stream audio to BLE hearing aids. Soundscape uses ASHA to send navigation audio directly to a user's hearing aids. This page explains how to run a simulated hearing aid on a Linux PC using [Google Bumble](https://github.com/google/bumble), so that you can test the ASHA connection path without needing a real hearing aid device.
11+
12+
## Hardware requirements
13+
14+
You need a Bluetooth **4.0 or later** USB dongle with LE support on the Linux machine running the simulation. ASHA requires BLE; BT 1.x/2.x/3.x dongles will not work.
15+
16+
A dongle that has been confirmed to work is the **BT820** (`USB ID 0a12:0001`, reports `BLUETOOTH_CORE_4_0`). Dongles reporting BT 5.0 should also work.
17+
18+
## Setting up Bumble
19+
20+
Clone the Bumble repository and create a virtual environment:
21+
22+
```bash
23+
git clone https://github.com/google/bumble.git
24+
cd bumble
25+
python3 -m venv .venv
26+
.venv/bin/pip install -e ".[development]"
27+
```
28+
29+
### Required patch to `run_asha_sink.py`
30+
31+
The upstream `examples/run_asha_sink.py` uses the extended advertising API (`create_advertising_set`), which requires a BT 5.0 controller and is also not recognised as legacy advertising by Android's ASHA scanner. Apply the following change before running:
32+
33+
In `examples/run_asha_sink.py`, replace the import line:
34+
35+
```python
36+
from bumble.device import AdvertisingEventProperties, AdvertisingParameters, Device
37+
```
38+
39+
with:
40+
41+
```python
42+
from bumble.device import Device
43+
```
44+
45+
And replace the `create_advertising_set` call:
46+
47+
```python
48+
await device.create_advertising_set(
49+
auto_restart=True,
50+
advertising_data=advertising_data,
51+
advertising_parameters=AdvertisingParameters(
52+
primary_advertising_interval_min=100,
53+
primary_advertising_interval_max=100,
54+
),
55+
)
56+
```
57+
58+
with:
59+
60+
```python
61+
await device.start_advertising(
62+
auto_restart=True,
63+
advertising_data=advertising_data,
64+
advertising_interval_min=100,
65+
advertising_interval_max=100,
66+
)
67+
```
68+
69+
`start_advertising` automatically falls back to legacy HCI advertising commands when the controller does not support extended advertising, and produces legacy advertising PDUs that Android's hearing aid scanner can discover.
70+
71+
## Running the simulation
72+
73+
Bumble takes direct control of the USB dongle, bypassing the kernel Bluetooth stack, so it needs root (or a udev rule granting access to the device). From the `bumble` directory:
74+
75+
```bash
76+
sudo .venv/bin/python3 examples/run_asha_sink.py examples/device1.json usb:0
77+
```
78+
79+
`usb:0` selects the first USB Bluetooth dongle. If you have more than one, use `usb:1`, `usb:2`, etc. The `device1.json` config gives the simulated device a fixed random address (`F0:F1:F2:F3:F4:F5`) and name (`Bumble`).
80+
81+
A successful start looks like:
82+
83+
```
84+
D bumble.host: ### CONTROLLER -> HOST: HCI_COMMAND_COMPLETE_EVENT:
85+
command_opcode: HCI_LE_SET_ADVERTISE_ENABLE_COMMAND
86+
return_parameters:
87+
status: SUCCESS
88+
```
89+
90+
The device is now advertising and waiting for a connection.
91+
92+
## Connecting from an Android phone
93+
94+
Soundscape targets Android 10+. ASHA device discovery is handled by the Android OS, not by a regular Bluetooth scan. To pair:
95+
96+
1. Go to **Settings → Accessibility → Hearing devices** (the exact path varies slightly between Android versions and OEM skins — search for "Hearing" in Settings if you can't find it).
97+
2. Tap **Add device** or **Pair new hearing aid**.
98+
3. The phone will scan and should find **Bumble**. Tap it to pair.
99+
100+
Once paired, the phone will reconnect automatically whenever the simulation is running and Soundscape will be able to stream audio to it via the ASHA profile.
101+
102+
## Troubleshooting
103+
104+
**Device not found during scan**
105+
- Confirm the simulation started cleanly and reached the `HCI_LE_SET_ADVERTISE_ENABLE_COMMAND SUCCESS` line.
106+
- Make sure you are looking in **Accessibility → Hearing devices**, not the regular Bluetooth settings — ASHA devices do not appear in the standard Bluetooth device list.
107+
- If you previously attempted to pair before applying the patch above, clear any cached entry in the Android hearing device list and try again.
108+
109+
**`UNKNOWN_HCI_COMMAND_ERROR` on startup**
110+
- Your dongle does not support extended advertising (it is BT 4.x). Make sure the patch above has been applied — `start_advertising` handles this automatically.
111+
112+
**`INVALID_COMMAND_PARAMETERS_ERROR` on `HCI_SET_EVENT_MASK_COMMAND` and immediate crash**
113+
- Your dongle is Bluetooth 1.2 (or earlier) and cannot support ASHA. Replace it with a BT 4.0+ LE-capable dongle.
114+
115+
**`usb:0` picks the wrong device**
116+
- Run `lsusb` to list USB devices and identify which bus/device number your Bluetooth dongle is. Then use `usb:<index>` to select it (Bumble numbers dongles starting from 0 in the order they appear on the bus).

docs/developers/developers.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ If you would like access to the main Soundscape tile provider for development, g
6161
* [Photon server configuration]({% link developers/photon-server-configuration.md %}) — how the search backend is deployed on EC2.
6262

6363
## Build, test and CI
64+
* [ASHA hearing aid simulation]({% link developers/asha-hearing-aid-simulation.md %}) — run a simulated BLE hearing aid on Linux using Google Bumble, for testing Soundscape's ASHA audio streaming without a real device.
6465
* [Branch strategy]({% link developers/branch-strategy.md %}) — which branches are active, where to send PRs, and the upcoming KMP cutover that will replace `main`.
6566
* [Build types and analytics]({% link developers/build-types.md %}) — `debug` / `release` / `releaseTest`, the variant-specific source sets that swap in real or no-op analytics, and the `BuildConfig` values read from `local.properties`.
6667
* [GitHub actions]({% link developers/actions.md %}) — the CI workflows and the secrets they consume.

0 commit comments

Comments
 (0)