Fairbuds
Tool for the reverse-engineered Fairbuds GATT protocol with AutoEq presets
Install / Use
/learn @jurf/FairbudsREADME
Fairbuds EQ Tool
Test tool for the reverse-engineered Fairbuds GATT protocol.
At least subjectively, the expanded EQ capabilities significantly improve the sound compared to what's possible with the app itself, especially in the high end.
Now available as a web app (thanks @zyberspace).
Features
- Set EQ presets (Main, Bass, Flat, Studio)
- More EQ control
- −12 to +13.5 dB per band (vs. app limited ±10 dB)
- Customisable Q-factor (vs. app hardcoded 0.7)
- Load parametric EQ files generated by AutoEQ
- Battery level monitoring
- Interactive CLI with command history
Quick start
Clone the repository
git clone --recurse-submodules https://github.com/user/fairbuds.git
cd fairbuds
If you already cloned without --recurse-submodules:
git submodule update --init --recursive
Install with uv
This project uses the uv Python package manager. To install it, run:
# Linux/macOS
curl -LsSf https://astral.sh/uv/install.sh | sh
# macOS with brew
brew install uv
# Or with pipx
pipx install uv
Then install the dependencies:
uv sync
Finding Your Fairbuds BLE Address
The BLE address might be different to the audio (BR/EDR) address shown in Bluetooth settings.
# Start BLE scan
uv run fairbuds --scan
# Look for your Fairbuds in the list, e.g.:
# 00:11:22:33:44:55 -96 dBm Fairbuds
# macOS:
# A1F7C2D9-4B8E-9A3F-16D2-7C5B8E0F4A12 ?? dBm Fairbuds
Usage
uv run fairbuds 00:11:22:33:44:55 # Replace with your Fairbuds BLE address
Type help in the interactive CLI for more details on available commands. If you just want to try the best preset, type:
load rtings_treble
Command-line options
uv run fairbuds --help # Show help
uv run fairbuds --version # Show version
uv run fairbuds --scan # Scan and list BLE devices
uv run fairbuds --list-presets # List available AutoEQ presets
Project structure
AutoEq/– AutoEQ (submodule)notebooks/– Jupyter notebooks for data analysis and visualisationpex/– Parametric EQ configs for AutoEQfairbuds.yaml– uses the full EQ capabilitiesfairbuds-app.yaml– equivalent to the official app
presets/– Parametric EQ presetspresets_app/– App-compatible versions of the presetsmeasurements/– Useful Fairbuds response curve measurementssrc/– Source code for this projecttargets/– Useful target curves for AutoEQ
Please keep in mind that this project is a quick-and-dirty experiment and most of the Python code was vibe-coded. There is not much point in making it more robust; it served only to test the protocol before attempting Gadgetbridge support.
Don't read too much into the code. The AI reads a bit too much into instructions and is very eager to change them into code with even more helpful comments. But the core implementation (EQ switching, custom EQ's battery info) should be correct.
Measurements
RTINGS (main eq, ANC Off).csv contains RTINGS measurement of the “Main” preset on the 5128. SoundGuys (main eq, ANC Off).csv contains SoundGuys measurement on the same preset and sim. These seem to be the best base for experimentation. Use the “JM-1 with Harman treble filter” target for best results with the reconstructed.csv signature to account for the Studio EQ.
The rest are from DHRME on the 711 for use with the “AutoEq in-ear” target. I had mixed results even though they also measured the “Studio” EQ, possibly due to differences in the firmware.
Some of these measurements are from AutoEq's database, the missing ones I preprocessed myself from the raw CSV files.
Presets
My current favourite one is presets/soundguys.txt. I recommend you experiment with others, as it might depend on your firmware or hardware specifics.
Q-values
The Q-values in the app are hardcoded to 7.
The actual interpretation is undocumented (if any calculations were present, they were most likely optimised out). This tool assumes the final Q-value is n/10.
This would mean the default is 0.7 with a range of 0.1–25.5, which is reasonable. It would also match the Fairbuds XL's 2023 default value (which is directly visible in the decompiled code).
Changing this value manually seems to affect the sound seemingly linearly, with the full range affecting the sound, and seems to match a software emulation with the same settings. But ultimately, it results in a meaningful improvement to the sound, so for now it's good enough.
It is worth mentioning though that manually calculating the value for the given bands would bring it closer to 1.2.
Generating AutoEQ presets
Follow the setup in the AutoEq README. Then use the parametric equalizer presets in pex/.
cd AutoEq
uv pip install -U -e .
. .venv/bin/activate
python -m autoeq \
--input-file="../measurements/RTINGS (main eq, ANC Off).csv" \
--output-dir="../results" \
--target="targets/JM-1 with Harman treble filter.csv" \
--max-gain=16 \
--parametric-eq \
--parametric-eq-config=../pex/fairbuds.yaml \
--fs=44100 \
--bass-boost=6.5 \
--preamp=-4
For bass boost, I use the default on the AutoEq web app for the given target – 6.5 dB for the JM-1 target and 8 dB for the AutoEq in-ear target.
The max gain and preamp settings significantly affect the output of the optimiser. I got best results by brute-forcing all reasonable values and keeping the one with the lowest loss reported by the optimiser; see preamp_optimiser.py.
Regenerating built-in presets
Modify AutoEq based on the comment on PATCHED_AUTOEQ in preamp_optimiser.py, then run:
python scripts/preamp_optimiser.py
Protocol
TBD
