Metadata-Version: 2.3
Name: harmonica-amt
Version: 0.2.0
Summary: A reproduction of Harmonica: Accurate and Lightweight Instrument-Agnostic Music Transcription
Keywords: music transcription,amt,midi,audio,pytorch
Author: Zion Huang
Requires-Dist: loguru>=0.7
Requires-Dist: nnaudio>=0.3.4
Requires-Dist: numpy
Requires-Dist: omegaconf>=2.3
Requires-Dist: scipy
Requires-Dist: soundfile>=0.13
Requires-Dist: symusic>=0.6
Requires-Dist: torch
Requires-Dist: typer>=0.15
Requires-Dist: lightning>=2.6 ; extra == 'train'
Requires-Dist: mir-eval>=0.8 ; extra == 'train'
Requires-Dist: pyyaml ; extra == 'train'
Requires-Dist: remi-z>=0.7.4 ; extra == 'train'
Requires-Dist: wandb>=0.19 ; extra == 'train'
Requires-Python: >=3.12
Project-URL: Repository, https://github.com/z-huang/harmonica
Project-URL: Paper, https://arxiv.org/abs/2609.04640
Provides-Extra: train
Description-Content-Type: text/markdown

# Harmonica

An independent reproduction of *[Harmonica: Accurate and Lightweight
Instrument-Agnostic Music Transcription](https://arxiv.org/abs/2609.04640)* (Ou,
Martel, Hennessy-Priest, Cho; arXiv:2609.04640). Audio of one pitched instrument
goes in and its notes come out as MIDI, with no instrument label anywhere.

This is not the authors' code. Everything here was rebuilt from the paper.
Where the paper leaves a detail unspecified, we filled it in with our own
assumptions, so this implementation is not guaranteed to match the authors'
exactly.

## Transcribe a recording

```bash
uvx harmonica-amt song.wav                   # writes song.mid
uvx harmonica-amt song.flac -o out.mid       # choose where the MIDI goes
uvx harmonica-amt song.wav --model x-large   # the most accurate size; medium by default
```

Input can be WAV, FLAC, MP3, or OGG. Inference runs on a GPU if there is one,
otherwise on the CPU.

## Models

`--model` takes one of the sizes below or the path of a checkpoint. Each size
ships with the decoding thresholds its development-set sweep chose. Scores are
the mean **OnP / OnPOff / Frm** over the paper's eight test sets:


| Variant          | Params | Ours               | Paper              |
| ---------------- | ------ | ------------------ | ------------------ |
| nano             | 25K    | .791 / .524 / .763 | .808 / .547 / .773 |
| small            | 131K   | .835 / .603 / .804 | .854 / .638 / .815 |
| medium (default) | 654K   | .862 / .660 / .827 | .879 / .687 / .838 |
| large            | 3.1M   | .877 / .688 / .843 | .891 / .713 / .848 |
| x-large          | 14.7M  | .882 / .694 / .843 | .895 / .721 / .852 |


[docs/results.md](docs/results.md) breaks the scores down by test set.

## Python

```python
from harmonica import Harmonica

model = Harmonica()  # the bundled medium, on the GPU if there is one
notes = model.transcribe("song.wav")
notes.save_midi("song.mid")

for onset, offset, pitch in zip(notes.onsets, notes.offsets, notes.pitches):
    print(f"{onset:.2f}-{offset:.2f}s  MIDI {pitch}")
```

The model loads once, so reuse a `Harmonica` for many recordings. It also
takes a NumPy array with its sample rate, `model.transcribe(audio, 44100)`,
and `Harmonica(model, device=..., onset_threshold=..., frame_threshold=...)`
picks another model, device, or thresholds.

## Reproduce the paper

```bash
uv sync                                      # Python 3.12+, a CUDA GPU
source .venv/bin/activate                    # puts harmonica on PATH
harmonica prepare --workers 16               # index the eight corpora
harmonica train --size medium                # one row of the table above
harmonica eval --size medium \
    --checkpoint outputs/harmonica-medium/checkpoints/checkpoint_latest.ckpt
```

- [docs/data.md](docs/data.md): where each corpus goes, the cache, and the splits.
- [docs/training.md](docs/training.md): configuration, ablations, resuming, and
  exporting weights.
- [docs/evaluation.md](docs/evaluation.md): the threshold sweep, the metrics, and
  evaluating on many GPUs.

## Citation

This repository reproduces the following paper; please cite it:

```bibtex
@article{ou2026harmonica,
  title   = {Harmonica: Accurate and Lightweight Instrument-Agnostic Music Transcription},
  author  = {Longshen Ou and H{\'e}ctor Martel and Joe Hennessy-Priest and Taemin Cho},
  journal = {arXiv preprint arXiv:2609.04640},
  year    = {2026}
}
```
