alberto chord recognizer (CRNN, triads and sevenths)

A small convolutional-recurrent network that labels guitar audio with one of 73 classes per frame: no chord, or a major, minor, dominant-7th, major-7th, minor-7th or half-diminished-7th chord on any of the 12 roots. It is the neural recognizer of alberto, a guitar songwriting helper that listens to a progression, estimates the key, and suggests what to play next.

  • Parameters: 482,025 (checkpoint under 2.5 MB)
  • Input: log-magnitude constant-Q transform, C2 upward, 6 octaves, 24 bins per octave, hop 512 at 22.05 kHz (config.json has every value)
  • Output: per-frame logits over 73 classes (config.json lists them in order)
  • Decoding: alberto runs Viterbi over the frame posteriors with a bigram transition matrix stored in the checkpoint (transitions, estimated from the training labels); plain argmax works too, at a small accuracy cost
  • Runs comfortably on CPU: ~16 ms for model + Viterbi on an 8-second window on an M-series Mac

Training

Trained on GuitarSet (Xi, Bittner, Ye, Bello, ISMIR 2018; CC BY 4.0), mono-mic recordings, using the performed chord annotation mapped to the 73-class vocabulary (references with other qualities — 9ths, 6ths, sus — reduce to the triad their third implies). Players 00–04 (300 excerpts, strummed and solo) were used for training with random pitch shifts of up to ±5 semitones applied by rolling CQT bins; player 05 (60 excerpts) was held out. 30 epochs, Adam 1e-3 with cosine decay, 8-second chunks, cross-entropy.

Evaluation (mir_eval, held-out player 05, 30 strummed excerpts)

metric this model, viterbi this model, argmax binary-template baseline
root 0.729 0.724 0.541
majmin 0.689 0.675 0.516
triads 0.525 0.516 0.399
sevenths 0.575 0.566 0.400
mirex 0.721 0.721 0.506

Scored against the performed annotation. The previous 25-class version scored majmin 0.684 and sevenths 0.450, so the seventh vocabulary lifted sevenths by 12.5 points without costing majmin.

Usage

The model definition lives in the alberto repository (alberto/chords/model.py). With it on your path:

from huggingface_hub import hf_hub_download
from alberto.chords.model import recognize

weights = hf_hub_download("shawon/alberto-chord-crnn", "crnn_majmin.pt")
segments = recognize(y, sr, weights=weights)   # y: mono float32 numpy array
for seg in segments:
    print(f"{seg.start:6.2f} {seg.end:6.2f} {seg.chord}")

Or load the raw checkpoint into your own copy of the architecture:

import torch
ckpt = torch.load("crnn_majmin.pt", map_location="cpu", weights_only=True)
model = ChordCRNN(n_bins=ckpt["n_bins"], n_classes=ckpt.get("n_classes", 25)).eval()
model.load_state_dict(ckpt["state_dict"])
logits = model(torch.from_numpy(features).unsqueeze(0))   # (1, n_frames, 73)

Frames whose RMS is below -60 dBFS should be treated as no-chord regardless of the prediction; alberto decodes the posteriors with Viterbi (see transitions above).

Limitations

  • Six qualities only; sus, diminished and augmented chords map to the nearest class by their third, and extended chords (9ths, 6ths, 11ths) likewise.
  • Trained on one acoustic guitar recorded with one microphone. Expect lower accuracy on electric guitar, distortion, or full mixes.
  • Assumes the root is the lowest note, as in ordinary guitar voicings.
Downloads last month
43
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support