Skip to main content

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[] + bpm from 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:

  1. Phase drift โ€” gaps in downbeats[] like 1.4s, 3.3s, 0.7s, ... when the bar should be 2.8s.
  2. Bar-doubling โ€” every other bar marked, gaps = 2 ร— bar duration.
  3. 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

livechord_bar_arbitrator-0.1.0.tar.gz (30.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

livechord_bar_arbitrator-0.1.0-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

File details

Details for the file livechord_bar_arbitrator-0.1.0.tar.gz.

File metadata

File hashes

Hashes for livechord_bar_arbitrator-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0aceaf2fb9a262dfc8dbce505eafa8a6189096a44678c8d8a02a09535ae65059
MD5 47d7d084905fc0072c0078f027def057
BLAKE2b-256 116aba4f008eb8c7e83451f03a048eb4dbb91e2c85c56a090464ef4743645088

See more details on using hashes here.

File details

Details for the file livechord_bar_arbitrator-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for livechord_bar_arbitrator-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 977a3fd2e6f9be1f1e47bfac1e595a458a54923e2989e82546f8fc18a988e36d
MD5 9af9c1cebda58194f91d396ad5e4ef4e
BLAKE2b-256 080cffb63c200440164c4c3a6c47313e6aad237b7ffcc5e10e386364eeac4446

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page