Post-processor that fixes bar / downbeat phase drift, beats-per-bar confusion, and doubletime in chord-JSON output without re-running audio models.
Project description
license: apache-2.0 library_name: onnx tags:
- music
- music-information-retrieval
- downbeat-tracking
- bar-tracking
- chord-recognition
- audio
- onnx pipeline_tag: audio-classification
livechord-bar-arbitrator
Post-processor that fixes bar / downbeat phase drift, beats-per-bar confusion, and doubletime/halftime mistakes in beat-tracker output, without re-running expensive audio models. Reads
chords[] + beats[] + downbeats[] + bpmfrom a chord JSON and emits a corrected grid.
๐น Try it live
This is the same arbitrator that fixes the bar grid before LiveChord's chord ribbon and 88-key piano waterfall lay out their cards. Try the full app at livechord.org.
Quickstart
pip install livechord-bar-arbitrator onnxruntime
from livechord_bar_arbitrator import arbitrate, apply_to_chord_json
chord_data = {
"chords": [{"time": 0.0, "end": 4.5, "chord": "Cm7"}, ...],
"beats": [0.0, 0.5, 1.0, ...],
"downbeats": [0.0, 2.0, 4.0, ...],
"bpm": 120.0,
}
result = arbitrate(chord_data)
if result["applied"]:
chord_data = apply_to_chord_json(chord_data, result)
The ONNX checkpoint is downloaded from this Hub repo on first call
(cached under ~/.cache/huggingface/hub). To use a local file, pass
arbitrate(chord_data, model_path="path/to/bar_arbitrator_v1.onnx").
What it does
The arbitrator operates on already-detected chords + beats โ it does not re-analyze audio. Three families of error get caught:
- Phase drift โ gaps in
downbeats[]like1.4s, 3.3s, 0.7s, ...when the bar should be 2.8s. - Bar-doubling โ every other bar marked, gaps = 2 ร bar duration.
- Beat-vs-bar confusion โ every beat marked as a downbeat,
gaps == beat_dur.
It chooses between a deterministic rule-based path (Phase 0, zero ML deps, ships always) and an optional ONNX Transformer (Phase 1, ~750 KB, downloaded from HF Hub) that uses chord-quality features to recover bar phase even when local beats are unreliable.
Architecture
Two-tier:
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
chord_dataโโโค arbitrate(chord_data) โ
โโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโดโโโโโโโโโโโ
โ โ
โผ โผ
[ rule-based ] [ ONNX Transformer ] โ Phase 1, optional
(Phase 0) (~750 KB, CPU only)
โข โ
โข โผ
โข [ confidence gate ]
โข โ
โโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ
โผ
ArbitrationResult dict
(downbeats_before/after, score_before/after,
beats_per_bar, applied, reason)
The Phase 1 model is a per-beat Transformer with a 28-dim feature input (chord root pitch class, quality bucket, distance-to-chord-change, beat regularity, ...). It outputs per-beat downbeat probability and beats-per-bar logits, then phase + bpb are decoded to a final grid.
Phase 0 is conservative by design โ it only acts when the candidate grid scores above an internal F1 threshold against chord changes. This avoids replacing raw downbeats with a worse grid when the underlying beat tracking is broken.
Files in this repo
| File | What | Required |
|---|---|---|
bar_arbitrator_v1.onnx |
Phase 1 ONNX-exported Transformer (~750 KB) | Optional |
| Source code in livechord-bar-arbitrator on GitHub | Arbitration pipeline | via pip install |
Combining with livechord-beat-refiner
For full audio-level refinement (re-pick beats given audio context) + bar arbitration in one call:
pip install livechord-bar-arbitrator livechord-beat-refiner
from livechord_bar_arbitrator import phase1_refine
result = phase1_refine(chord_data, audio_path="song.flac")
This pipes the audio through the Compact Transformer beat refiner first, then runs the bar arbitrator on the refined output. Recommended when you have access to the source audio file.
Limitations
- Phase 1 ONNX model is small and conservative. It refuses to act when its candidate grid scores below an internal F1 threshold against chord changes. So bad inputs sometimes pass through unchanged.
- No reggae / ska / 6/8 specialization. Phase 1 v1 was trained primarily on 4/4 pop and rock. Compound time is OK but rarely re-corrected.
- No real-time mode. Designed for offline / batch use after chord detection finishes.
Citation
@misc{livechord-bar-arbitrator,
title = {livechord-bar-arbitrator: rule-based + Transformer
post-processor for bar / downbeat grid arbitration},
author = {LiveChord Project},
year = {2026},
url = {https://huggingface.co/livechord-music/livechord-bar-arbitrator},
}
License
Apache License 2.0 โ code AND weights.
Related
- livechord-beat-refiner โ companion audio-level beat refiner.
- livechord.org โ full LiveChord product.
- CPJKU/beat_this โ recommended upstream beat tracker.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file livechord_bar_arbitrator-0.1.0.tar.gz.
File metadata
- Download URL: livechord_bar_arbitrator-0.1.0.tar.gz
- Upload date:
- Size: 30.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0aceaf2fb9a262dfc8dbce505eafa8a6189096a44678c8d8a02a09535ae65059
|
|
| MD5 |
47d7d084905fc0072c0078f027def057
|
|
| BLAKE2b-256 |
116aba4f008eb8c7e83451f03a048eb4dbb91e2c85c56a090464ef4743645088
|
File details
Details for the file livechord_bar_arbitrator-0.1.0-py3-none-any.whl.
File metadata
- Download URL: livechord_bar_arbitrator-0.1.0-py3-none-any.whl
- Upload date:
- Size: 27.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
977a3fd2e6f9be1f1e47bfac1e595a458a54923e2989e82546f8fc18a988e36d
|
|
| MD5 |
9af9c1cebda58194f91d396ad5e4ef4e
|
|
| BLAKE2b-256 |
080cffb63c200440164c4c3a6c47313e6aad237b7ffcc5e10e386364eeac4446
|