transcpybe 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- transcpybe-2.0.0/LICENSE +21 -0
- transcpybe-2.0.0/PKG-INFO +356 -0
- transcpybe-2.0.0/README.md +322 -0
- transcpybe-2.0.0/pyproject.toml +63 -0
- transcpybe-2.0.0/setup.cfg +4 -0
- transcpybe-2.0.0/src/transcpybe/__init__.py +63 -0
- transcpybe-2.0.0/src/transcpybe/__main__.py +8 -0
- transcpybe-2.0.0/src/transcpybe/audio.py +58 -0
- transcpybe-2.0.0/src/transcpybe/batch.py +359 -0
- transcpybe-2.0.0/src/transcpybe/cli.py +377 -0
- transcpybe-2.0.0/src/transcpybe/config.py +802 -0
- transcpybe-2.0.0/src/transcpybe/core.py +252 -0
- transcpybe-2.0.0/src/transcpybe/corpus.py +645 -0
- transcpybe-2.0.0/src/transcpybe/device.py +141 -0
- transcpybe-2.0.0/src/transcpybe/evaluate.py +152 -0
- transcpybe-2.0.0/src/transcpybe/f0.py +572 -0
- transcpybe-2.0.0/src/transcpybe/fragments.py +102 -0
- transcpybe-2.0.0/src/transcpybe/glide.py +258 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/__init__.py +129 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/features.py +66 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/infer.py +138 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/model.py +91 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/voicing.py +31 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/weights/LICENSE +438 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/weights/README.md +102 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/weights/seed0.pt +0 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/weights/seed1.pt +0 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/weights/seed2.pt +0 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/weights/voicing-pesto.json +235 -0
- transcpybe-2.0.0/src/transcpybe/landmarks/weights/voicing-pyin.json +131 -0
- transcpybe-2.0.0/src/transcpybe/midi_io.py +200 -0
- transcpybe-2.0.0/src/transcpybe/notes.py +543 -0
- transcpybe-2.0.0/src/transcpybe/onsets.py +627 -0
- transcpybe-2.0.0/src/transcpybe/progress.py +237 -0
- transcpybe-2.0.0/src/transcpybe/segment.py +377 -0
- transcpybe-2.0.0/src/transcpybe/synth.py +569 -0
- transcpybe-2.0.0/src/transcpybe.egg-info/PKG-INFO +356 -0
- transcpybe-2.0.0/src/transcpybe.egg-info/SOURCES.txt +49 -0
- transcpybe-2.0.0/src/transcpybe.egg-info/dependency_links.txt +1 -0
- transcpybe-2.0.0/src/transcpybe.egg-info/entry_points.txt +2 -0
- transcpybe-2.0.0/src/transcpybe.egg-info/requires.txt +18 -0
- transcpybe-2.0.0/src/transcpybe.egg-info/top_level.txt +1 -0
- transcpybe-2.0.0/tests/test_corpus.py +62 -0
- transcpybe-2.0.0/tests/test_front_ends.py +187 -0
- transcpybe-2.0.0/tests/test_landmark_short_notes.py +113 -0
- transcpybe-2.0.0/tests/test_landmarks.py +149 -0
- transcpybe-2.0.0/tests/test_note_ends.py +81 -0
- transcpybe-2.0.0/tests/test_pitch_after_moves.py +67 -0
- transcpybe-2.0.0/tests/test_progress.py +577 -0
- transcpybe-2.0.0/tests/test_sustain_merge.py +96 -0
- transcpybe-2.0.0/tests/test_transcribe.py +1486 -0
transcpybe-2.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 David Whyatt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: transcpybe
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Transcribe sung melody to MIDI: onsets and pitches from monophonic vocal audio
|
|
5
|
+
Author: David Whyatt
|
|
6
|
+
License-Expression: MIT AND CC-BY-NC-SA-4.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/dmwhyatt/transcpybe
|
|
8
|
+
Project-URL: Issues, https://github.com/dmwhyatt/transcpybe/issues
|
|
9
|
+
Keywords: music information retrieval,transcription,midi,singing,melody,pitch tracking
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
License-File: src/transcpybe/landmarks/weights/LICENSE
|
|
18
|
+
Requires-Dist: numpy>=1.24
|
|
19
|
+
Requires-Dist: scipy>=1.10
|
|
20
|
+
Requires-Dist: librosa>=0.10
|
|
21
|
+
Requires-Dist: soundfile>=0.12
|
|
22
|
+
Requires-Dist: pretty_midi>=0.2.10
|
|
23
|
+
Requires-Dist: mir_eval>=0.7
|
|
24
|
+
Requires-Dist: torch>=2.0
|
|
25
|
+
Provides-Extra: crepe
|
|
26
|
+
Requires-Dist: torchcrepe>=0.0.20; extra == "crepe"
|
|
27
|
+
Provides-Extra: pesto
|
|
28
|
+
Requires-Dist: pesto-pitch>=2.0; extra == "pesto"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
31
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
32
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# transcPybe
|
|
36
|
+
|
|
37
|
+
transcPybe transcribes monophonic singing into notes: onset and offset times in seconds, and pitches as MIDI note
|
|
38
|
+
numbers, with the measured pitch retained as a pitch bend. It is intended for solo vocal recordings and for lead vocals
|
|
39
|
+
separated from mixed recordings.
|
|
40
|
+
|
|
41
|
+
Version 2 places note onsets with three small neural networks, which detect where each syllable begins to sound and
|
|
42
|
+
where its vowel begins. Notes are then decoded from the pitch track by a hidden Markov model. Version 1, which relies on
|
|
43
|
+
the pitch track and a spectral-flux onset detector alone, remains available.
|
|
44
|
+
|
|
45
|
+
The code is released under the MIT licence. The weights of the version 2 networks are released under CC BY-NC-SA 4.0
|
|
46
|
+
(see [Licence](#licence)).
|
|
47
|
+
|
|
48
|
+
## Comparison to other models
|
|
49
|
+
|
|
50
|
+
| System | vocadito A1 | vocadito A2 | Molina | RWC-P dev | SSVD test | MIR-ST500 test | A cappella | Pop | Five-set mean [95% CI] | GPU s/min | CPU s/min |
|
|
51
|
+
|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
52
|
+
| Phoneme-informed\* | 0.450 | 0.593 | 0.712 | 0.317 | 0.688 | 0.372 | 0.641 | 0.345 | **0.522** [0.507, 0.537] | 13.4 | 12.4 |
|
|
53
|
+
| transcPybe v2, pYIN | 0.481 | 0.580 | 0.675 | 0.339 | 0.609 | 0.391 | 0.605 | 0.365 | **0.509** [0.495, 0.523] | 10.6 | 10.9 |
|
|
54
|
+
| transcPybe v2, PESTO | 0.467 | 0.574 | 0.693 | 0.348 | 0.601 | 0.348 | 0.605 | 0.348 | **0.502** [0.488, 0.516] | 2.1 | 4.4 |
|
|
55
|
+
| transcPybe v2, CREPE | 0.473 | 0.573 | 0.670 | 0.347 | 0.568 | 0.354 | 0.587 | 0.350 | **0.492** [0.479, 0.505] | 3.0 | 65.5 |
|
|
56
|
+
| CTC-CE\* | 0.312 | 0.433 | 0.629 | 0.359 | 0.504 | 0.538 | 0.502 | 0.449 | **0.481** [0.465, 0.496] | 6.8 | 3.6 |
|
|
57
|
+
| MIR-ST500 model\* | 0.320 | 0.443 | 0.534 | 0.371 | 0.453 | 0.474 | 0.456 | 0.422 | **0.443** [0.427, 0.458] | 5.9 | 3.3 |
|
|
58
|
+
| Tony † | 0.686 | 0.654 | 0.466 | 0.266 | 0.582 | 0.276 | 0.524 | 0.271 | **0.397**† [0.383, 0.412] | – | 1.1 |
|
|
59
|
+
| YourMT3+\* | 0.275 | 0.350 | 0.464 | 0.328 | 0.410 | 0.426 | 0.395 | 0.377 | **0.388** [0.373, 0.403] | 3.0 | 21.8 |
|
|
60
|
+
| GAME | 0.264 | 0.364 | 0.506 | 0.348 | 0.332 | 0.406 | 0.384 | 0.377 | **0.381** [0.366, 0.396] | – | 83.6 |
|
|
61
|
+
| Omnizart | 0.440 | 0.494 | 0.512 | 0.180 | 0.533 | 0.178 | 0.504 | 0.179 | **0.374** [0.361, 0.387] | – | 134.6 |
|
|
62
|
+
| transcPybe v1 | 0.496 | 0.480 | 0.419 | 0.231 | 0.449 | 0.237 | 0.452 | 0.234 | **0.365** [0.353, 0.376] | 3.0 | 60.7 |
|
|
63
|
+
| SOME | 0.278 | 0.349 | 0.441 | 0.242 | 0.272 | 0.311 | 0.342 | 0.276 | **0.316** [0.304, 0.327] | 3.9 | 5.7 |
|
|
64
|
+
| Kum et al. | 0.219 | 0.247 | 0.251 | 0.224 | 0.229 | 0.248 | 0.238 | 0.236 | **0.237** [0.227, 0.248] | – | 6.8 |
|
|
65
|
+
| Basic Pitch | 0.307 | 0.325 | 0.345 | 0.133 | 0.254 | 0.137 | 0.305 | 0.135 | **0.237** [0.224, 0.250] | – | 4.6 |
|
|
66
|
+
| Essentia | 0.318 | 0.263 | 0.289 | 0.120 | 0.360 | 0.117 | 0.313 | 0.118 | **0.235** [0.224, 0.247] | – | 1.8 |
|
|
67
|
+
| CREPE Notes | 0.310 | 0.283 | 0.275 | 0.167 | 0.256 | 0.158 | 0.276 | 0.162 | **0.230** [0.219, 0.242] | – | 29.9 |
|
|
68
|
+
| ROSVOT | 0.184 | 0.204 | 0.189 | 0.154 | 0.082 | 0.109 | 0.155 | 0.132 | **0.146** [0.137, 0.155] | 1.6 | – |
|
|
69
|
+
| aubio | 0.061 | 0.060 | 0.086 | 0.019 | 0.106 | 0.026 | 0.084 | 0.022 | **0.059** [0.055, 0.064] | – | 0.4 |
|
|
70
|
+
| STARS ‡ | 0.064 | 0.076 | 0.068 | 0.038 | 0.084 | 0.088 | 0.074 | 0.063 | **0.070** [0.062, 0.078] | – | – |
|
|
71
|
+
|
|
72
|
+
The table compares transcPybe with fifteen published singing transcription systems on five annotated datasets.
|
|
73
|
+
|
|
74
|
+
- **Runs.** Each system ran in its own pinned container on identical audio.
|
|
75
|
+
- **Metric.** COnPOff@50 at whole semitones: a note counts when its onset is within 50 ms, its pitch within 50 cents,
|
|
76
|
+
and its offset within 20% of the note's duration or 50 ms, whichever is larger.
|
|
77
|
+
- **Intervals.** The five-set mean has a 95% interval from a paired bootstrap over recordings, stratified by dataset.
|
|
78
|
+
- **Time.** Seconds of computation per minute of audio, on an NVIDIA RTX 3080 GPU and on eight CPU cores.
|
|
79
|
+
|
|
80
|
+
The methods, every system's reference and the per-recording scores are in the
|
|
81
|
+
[transcription-benchmarking](https://github.com/dmwhyatt/transcription-benchmarking#results) repository.
|
|
82
|
+
|
|
83
|
+
Notes to the table:
|
|
84
|
+
|
|
85
|
+
- \* Trained on other recordings from one of the evaluation datasets.
|
|
86
|
+
- † vocadito's reference annotations were produced by correcting Tony's output, so Tony's mean excludes vocadito.
|
|
87
|
+
- ‡ STARS requires lyrics. They were obtained by automatic speech recognition.
|
|
88
|
+
- transcPybe v2's settings were selected on vocadito, Molina and the RWC-P development set; SSVD test and MIR-ST500
|
|
89
|
+
test were held out.
|
|
90
|
+
|
|
91
|
+
For reference, vocadito's two annotators agree with each other at 0.64 COnPOff@50.
|
|
92
|
+
|
|
93
|
+
## Installation
|
|
94
|
+
|
|
95
|
+
```shell
|
|
96
|
+
pip install transcpybe # version 2 with the pYIN pitch tracker
|
|
97
|
+
pip install "transcpybe[crepe]" # adds the CREPE pitch tracker
|
|
98
|
+
pip install "transcpybe[pesto]" # adds the PESTO pitch tracker (LGPL-3.0)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
transcPybe requires Python 3.9 or later. PyTorch is a dependency, because the version 2 networks require it. On a
|
|
102
|
+
machine without a GPU, installing PyTorch's CPU build first avoids downloading the CUDA libraries:
|
|
103
|
+
`pip install torch --index-url https://download.pytorch.org/whl/cpu`. To install from a source checkout, use
|
|
104
|
+
`pip install -e ".[dev]"`.
|
|
105
|
+
|
|
106
|
+
## Usage
|
|
107
|
+
|
|
108
|
+
### Command line
|
|
109
|
+
|
|
110
|
+
```shell
|
|
111
|
+
# A lead vocal separated from a mix: writes lead-vocal.mid, .notes.json and .notes.csv
|
|
112
|
+
transcpybe lead-vocal.wav -o out/
|
|
113
|
+
|
|
114
|
+
# Solo singing, with nothing else in the recording
|
|
115
|
+
transcpybe solo.wav --preset acappella
|
|
116
|
+
|
|
117
|
+
# Version 1, without the networks
|
|
118
|
+
transcpybe lead-vocal.wav --preset rules
|
|
119
|
+
|
|
120
|
+
# Every audio file in a directory, with a log file
|
|
121
|
+
transcpybe stems/ -o midi/ --log-file transcribe.log
|
|
122
|
+
|
|
123
|
+
# Print the notes as a table
|
|
124
|
+
transcpybe lead-vocal.wav --print-notes
|
|
125
|
+
|
|
126
|
+
# Write whole equal-tempered semitones only, without pitch bends
|
|
127
|
+
transcpybe lead-vocal.wav --12tet
|
|
128
|
+
|
|
129
|
+
# Run the built-in synthetic test suite
|
|
130
|
+
transcpybe --self-test
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`transcpybe --help` lists every option.
|
|
134
|
+
|
|
135
|
+
### Presets
|
|
136
|
+
|
|
137
|
+
| Preset | Version | Intended input | Evaluated on |
|
|
138
|
+
|---|---|---|---|
|
|
139
|
+
| `pop` (default) | 2 | a lead vocal separated from a pop mix | 82 MIR-ST500 test songs |
|
|
140
|
+
| `acappella` | 2 | solo singing, with nothing else in the recording | 127 SSVD test recordings |
|
|
141
|
+
| `rules` | 1 | either; no neural networks besides the pitch tracker | |
|
|
142
|
+
|
|
143
|
+
The two version 2 presets were fixed on development sets and then evaluated once on recordings that had not been used
|
|
144
|
+
for tuning. Each preset also sets the decoder parameters with which it was evaluated: `--min-note`, `--p-self`,
|
|
145
|
+
`--note-level-floor`, `--onset-delta`, `--onset-split-strength` and `--release-drop`. The command line warns if one of
|
|
146
|
+
these is given with a version 2 preset. With `--preset rules`, every parameter takes the value given.
|
|
147
|
+
|
|
148
|
+
### Pitch trackers
|
|
149
|
+
|
|
150
|
+
| Tracker | Option | Requires | Notes |
|
|
151
|
+
|---|---|---|---|
|
|
152
|
+
| pYIN | `--f0-backend pyin` (default) | | Version 2's best five-set mean; runs on the CPU |
|
|
153
|
+
| CREPE | `--f0-backend crepe` | `transcpybe[crepe]` | Fastest on a GPU, slowest on a CPU. `--crepe-model tiny` is about 14 times faster on a CPU; version 2 has not been evaluated with it |
|
|
154
|
+
| PESTO | `--f0-backend pesto` | `transcpybe[pesto]` | A much smaller network than CREPE |
|
|
155
|
+
|
|
156
|
+
The version 2 networks were trained on CREPE's pitch tracks. pYIN and PESTO report lower confidence than CREPE. Their
|
|
157
|
+
tracks therefore pass through a voicing map before decoding: a quantile map onto CREPE's confidence scale, fitted on
|
|
158
|
+
the training data. Version 1's thresholds were set on CREPE. Further trackers can be added with
|
|
159
|
+
`transcpybe.f0.register_f0_backend`.
|
|
160
|
+
|
|
161
|
+
### Python
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from transcpybe import TranscriptionConfig, transcribe_file, write_midi
|
|
165
|
+
|
|
166
|
+
result = transcribe_file("solo.wav", TranscriptionConfig(preset="acappella"))
|
|
167
|
+
for note in result.notes:
|
|
168
|
+
print(note.onset, note.offset, note.pitch) # seconds, seconds, MIDI note number
|
|
169
|
+
|
|
170
|
+
write_midi(result.notes, "solo.mid", result.config)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`TranscriptionConfig` documents every parameter. The result also contains the pitch track (`f0_track`) and the onset
|
|
174
|
+
track (`onsets`) from which the notes were decoded.
|
|
175
|
+
|
|
176
|
+
### Output
|
|
177
|
+
|
|
178
|
+
- **`.mid`:** one track. Note times are absolute seconds; the tempo in the header affects only the bar grid displayed
|
|
179
|
+
by notation software. Each note's MIDI number is the semitone nearest the sung pitch. By default, the measured pitch
|
|
180
|
+
is also written as a pitch bend at the start of the note, using General MIDI's two-semitone range. `--12tet` omits
|
|
181
|
+
the bends.
|
|
182
|
+
- **`.notes.csv`:** onset, offset, duration, pitch, velocity, confidence, pitch in Hz, and the measured pitch as a
|
|
183
|
+
fractional MIDI number (`pitch_midi_float`).
|
|
184
|
+
- **`.notes.json`:** the same notes, with the complete configuration that produced them.
|
|
185
|
+
|
|
186
|
+
`transcpybe.midi_io.read_midi_notes` reads a MIDI file back with its pitch bends applied.
|
|
187
|
+
|
|
188
|
+
## Method
|
|
189
|
+
|
|
190
|
+
### Version 2: note onsets from neural networks
|
|
191
|
+
|
|
192
|
+
Three networks with the same architecture were trained with different random seeds:
|
|
193
|
+
|
|
194
|
+
- **Architecture:** a convolutional front end over an 80-band log-mel spectrogram, then a two-layer bidirectional GRU,
|
|
195
|
+
with 0.8 million parameters each.
|
|
196
|
+
- **Inputs:** the spectrogram and five features from the pitch track.
|
|
197
|
+
- **Outputs:** every 10 ms, the probability that a syllable begins to sound and the probability that its vowel
|
|
198
|
+
begins.
|
|
199
|
+
- **Training data:** singing from M4Singer and GTSinger, mixed with accompaniment from MUSDB18-HQ.
|
|
200
|
+
|
|
201
|
+
The three networks' outputs are averaged. Each vowel onset is paired with the nearest preceding syllable onset, and the
|
|
202
|
+
note onset is placed between them: at 0.5 of the interval in the `pop` preset, and at 0.875 in the `acappella` preset.
|
|
203
|
+
The decoder described below then forms notes from the pitch track, with these onsets.
|
|
204
|
+
|
|
205
|
+
The networks run on the CPU. On an Apple M-series laptop with PyTorch's default four threads, the three together take
|
|
206
|
+
about 3.6 s per minute of audio. The code is in `transcpybe.landmarks`. The weights, the voicing maps and their
|
|
207
|
+
provenance are in `src/transcpybe/landmarks/weights/`.
|
|
208
|
+
|
|
209
|
+
### The note decoder
|
|
210
|
+
|
|
211
|
+
Both versions share the following stages. Version 1 takes its onsets from stage 5. Version 2 takes them from the
|
|
212
|
+
networks and uses its preset's parameters throughout.
|
|
213
|
+
|
|
214
|
+
1. **Pitch and voicing.** The pitch tracker estimates a fundamental frequency and a periodicity confidence every
|
|
215
|
+
10 ms. The confidence is multiplied by a loudness gate set relative to the recording's 95th-percentile level, so
|
|
216
|
+
that periodic residue left by source separation in quiet passages is not transcribed.
|
|
217
|
+
2. **Note decoding.** A Viterbi decoder runs over pitch states spaced a third of a semitone apart, plus an unvoiced
|
|
218
|
+
state. Emissions favour states near the measured pitch, weighted by voicing. Transitions favour remaining on a
|
|
219
|
+
note, and penalise larger intervals. The design follows the note tracker of Tony (Mauch et al., 2015). The
|
|
220
|
+
sub-semitone states prevent a note sung between two semitones from alternating between them.
|
|
221
|
+
3. **Fragments.** Very short segments adjacent to a much longer note, within two semitones of it, are merged into
|
|
222
|
+
it. Such segments typically arise from wide vibrato at the end of a note.
|
|
223
|
+
4. **Glides.** Where the singer slides into a note, the transition is attributed to the note being approached. This
|
|
224
|
+
corrects the late onset the slide would otherwise produce, and removes the brief notes it would leave on each
|
|
225
|
+
semitone crossed.
|
|
226
|
+
5. **Onsets.** A spectral-flux onset envelope with a frequency-domain maximum filter (SuperFlux) splits repeated
|
|
227
|
+
notes at the same pitch, and aligns note onsets with audible attacks. The maximum filter prevents vibrato from
|
|
228
|
+
registering as onsets.
|
|
229
|
+
6. **Pitch and clean-up.** Each note's pitch is the confidence-weighted median of its pitch track, excluding the
|
|
230
|
+
start of the note, rounded to the nearest semitone. Notes shorter than the minimum duration, and notes far quieter
|
|
231
|
+
than the rest of the performance, are removed.
|
|
232
|
+
7. **Note ends.** A note ends where its level has fallen a set amount below its own sustained level: 15 dB by default,
|
|
233
|
+
20 dB in the `pop` preset. This excludes the release and room reverberation, which pitch trackers continue to
|
|
234
|
+
report as periodic.
|
|
235
|
+
8. **Tuning reference.** If the notes of a first pass show that the performance is consistently offset from the
|
|
236
|
+
A440 grid, decoding is repeated against the grid on which it was sung. Offsets beyond 40 cents are not applied,
|
|
237
|
+
because scattered intonation is otherwise better explained by a grid a quarter tone away.
|
|
238
|
+
`--no-tuning-estimate` disables the estimate.
|
|
239
|
+
|
|
240
|
+
## Processing large collections
|
|
241
|
+
|
|
242
|
+
Given a directory, `transcpybe` transcribes every audio file within it:
|
|
243
|
+
|
|
244
|
+
- **Existing outputs:** files whose outputs already exist are skipped, so an interrupted run resumes; `--overwrite`
|
|
245
|
+
transcribes them again.
|
|
246
|
+
- **Failures:** a file that cannot be read is logged and the run continues; `--stop-on-error` stops it instead.
|
|
247
|
+
- **Remaining time:** estimated from audio duration rather than file count.
|
|
248
|
+
|
|
249
|
+
Progress is shown on a single line in a terminal, and as periodic timestamped lines when output is redirected. The
|
|
250
|
+
following options control logging and the GPU:
|
|
251
|
+
|
|
252
|
+
| Option | Purpose |
|
|
253
|
+
|---|---|
|
|
254
|
+
| `--log-file PATH` | Append timestamped logs to a file as well as the console. |
|
|
255
|
+
| `--progress-interval N` | Seconds between progress lines when output is redirected (default 5). |
|
|
256
|
+
| `--no-progress` | Disable progress reporting. |
|
|
257
|
+
| `--device` | Torch device for CREPE and PESTO: `auto` (default; CUDA, then Apple MPS, then CPU), or an explicit device such as `cuda:1`. The device used is logged and recorded in the JSON output. |
|
|
258
|
+
| `--crepe-batch-size N` | CREPE frames per forward pass (default 512); lower it if GPU memory is limited. |
|
|
259
|
+
| `--gpu-memory-every N` | Log GPU memory every N CREPE batches. |
|
|
260
|
+
| `-v` | Include debugging detail. |
|
|
261
|
+
|
|
262
|
+
## Reproducibility
|
|
263
|
+
|
|
264
|
+
The JSON output records the complete configuration used. CREPE adds random dither of ±20 cents to its pitch estimates.
|
|
265
|
+
transcPybe seeds it (`--seed`, default 0) and restores the global random state afterwards, so repeated runs give
|
|
266
|
+
identical output. `--no-seed` restores CREPE's unseeded behaviour.
|
|
267
|
+
|
|
268
|
+
## Adjusting version 1
|
|
269
|
+
|
|
270
|
+
With `--preset rules`, the decoder's parameters may be adjusted. The most commonly used are:
|
|
271
|
+
|
|
272
|
+
| Symptom | Option | Direction |
|
|
273
|
+
|---|---|---|
|
|
274
|
+
| Short spurious notes | `--min-note` | increase (e.g. 0.08) |
|
|
275
|
+
| Sustained notes split into several | `--p-self` | increase (e.g. 0.995) |
|
|
276
|
+
| Fast passages merged into single notes | `--p-self` | decrease (e.g. 0.97) |
|
|
277
|
+
| Vibrato fragmenting notes | `--pitch-sigma` | increase (e.g. 0.7) |
|
|
278
|
+
| Notes in silent passages | `--note-level-floor` | decrease (e.g. 22) |
|
|
279
|
+
| Quiet sung notes discarded | `--note-level-floor` | increase |
|
|
280
|
+
| Repeated notes at one pitch merged | `--onset-split-strength` | decrease |
|
|
281
|
+
| Noisy recordings over-segmented | `--onset-delta` | increase |
|
|
282
|
+
| Note ends too late | `--release-drop` | decrease (e.g. 10) |
|
|
283
|
+
| Note ends too early | `--release-drop` | increase, or `--no-release-trim` |
|
|
284
|
+
| Voice outside the tracked range | `--fmin`, `--fmax` | widen |
|
|
285
|
+
|
|
286
|
+
## Tests
|
|
287
|
+
|
|
288
|
+
```shell
|
|
289
|
+
pytest tests/ # the test suite
|
|
290
|
+
pytest tests/ -m slow # the tests that run CREPE
|
|
291
|
+
transcpybe --self-test # the synthetic suite
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Limitations
|
|
295
|
+
|
|
296
|
+
- **Monophonic input.** Harmonies or overlapping voices in the same recording are transcribed as a single line.
|
|
297
|
+
- **Note ends follow a convention.** Annotators differ on where a sung note ends. The release threshold
|
|
298
|
+
(`--release-drop`) may need adjusting for a particular corpus.
|
|
299
|
+
- **Separation residue.** Loud residue from source separation can be transcribed as notes. With `--preset rules`,
|
|
300
|
+
lowering `--note-level-floor` reduces this, at the cost of quiet singing.
|
|
301
|
+
- **Tuning.** A performance sung more than 40 cents from A440 is decoded on the A440 grid.
|
|
302
|
+
- **No quantisation.** Output times are in seconds, without beat tracking or rhythmic quantisation.
|
|
303
|
+
|
|
304
|
+
## Acknowledgements
|
|
305
|
+
|
|
306
|
+
**Pitch estimation**
|
|
307
|
+
|
|
308
|
+
- **CREPE:** J. W. Kim, J. Salamon, P. Li and J. P. Bello, "CREPE: A Convolutional Representation for Pitch
|
|
309
|
+
Estimation", ICASSP 2018. Used through **torchcrepe** (M. Morrison; MIT licence), which supplies the weights.
|
|
310
|
+
- **pYIN:** M. Mauch and S. Dixon, "pYIN: A fundamental frequency estimator using probabilistic threshold
|
|
311
|
+
distributions", ICASSP 2014. Used through librosa's implementation.
|
|
312
|
+
- **PESTO:** A. Riou, S. Lattner, G. Hadjeres and G. Peeters, "PESTO: Pitch Estimation with Self-supervised
|
|
313
|
+
Transposition-equivariant Objective", ISMIR 2023. Used through the pesto-pitch package (LGPL-3.0).
|
|
314
|
+
|
|
315
|
+
**Note segmentation and onsets**
|
|
316
|
+
|
|
317
|
+
- **Tony:** M. Mauch, C. Cannam, R. Bittner, G. Fazekas, J. Salamon, J. Dai, J. Bello and S. Dixon, "Computer-aided
|
|
318
|
+
melody note transcription using the Tony software: Accuracy and efficiency", TENOR 2015. The pitch-state hidden
|
|
319
|
+
Markov model is a simplified form of Tony's note tracker.
|
|
320
|
+
- **SuperFlux:** S. Böck and G. Widmer, "Maximum filter vibrato suppression for onset detection", DAFx 2013. Used
|
|
321
|
+
through librosa's `onset_strength`.
|
|
322
|
+
|
|
323
|
+
**Training data for the version 2 networks**
|
|
324
|
+
|
|
325
|
+
- **M4Singer:** L. Zhang et al., "M4Singer: A Multi-Style, Multi-Singer and Musical Score Provided Mandarin Singing
|
|
326
|
+
Corpus", NeurIPS 2022 Datasets and Benchmarks. CC BY-NC-SA 4.0.
|
|
327
|
+
- **GTSinger:** Y. Zhang et al., "GTSinger: A Global Multi-Technique Singing Corpus with Realistic Music Scores for
|
|
328
|
+
All Singing Tasks", NeurIPS 2024 Datasets and Benchmarks. CC BY-NC-SA 4.0.
|
|
329
|
+
- **MUSDB18-HQ:** Z. Rafii, A. Liutkus, F.-R. Stöter, S. I. Mimilakis and R. Bittner, 2019. Accompaniment only;
|
|
330
|
+
educational and non-commercial use.
|
|
331
|
+
|
|
332
|
+
**Libraries**
|
|
333
|
+
|
|
334
|
+
- librosa (ISC licence)
|
|
335
|
+
- pretty_midi (MIT)
|
|
336
|
+
- mir_eval (MIT)
|
|
337
|
+
- NumPy (BSD-3-Clause)
|
|
338
|
+
- SciPy (BSD-3-Clause)
|
|
339
|
+
- soundfile (BSD-3-Clause)
|
|
340
|
+
- PyTorch (BSD-3-Clause)
|
|
341
|
+
|
|
342
|
+
## Licence
|
|
343
|
+
|
|
344
|
+
The code is released under the MIT licence (`LICENSE`).
|
|
345
|
+
|
|
346
|
+
The weights of the version 2 networks and the voicing maps, in `src/transcpybe/landmarks/weights/`, are released under
|
|
347
|
+
[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/), because the singing on which they were trained
|
|
348
|
+
is licensed on those terms:
|
|
349
|
+
|
|
350
|
+
- **Attribution:** use requires attribution.
|
|
351
|
+
- **Non-commercial:** commercial use is not permitted.
|
|
352
|
+
- **Share-alike:** derived weights must be shared under the same licence.
|
|
353
|
+
|
|
354
|
+
That folder's `LICENSE` and `README.md` give the full terms and the provenance. The `pop` and `acappella` presets use
|
|
355
|
+
these weights; `--preset rules` does not. The pitch trackers' weights are distributed with their own packages, under
|
|
356
|
+
their own licences.
|