FCPE β ONNX
FCPE (Fast Context-based Pitch Estimation, CNChTu) from torchfcpe 0.0.4, bundled model fcpe_c_v001: a conformer on a 128-band log-mel.
Exported to ONNX with the model's own front end inside the graph: feed 16 kHz mono audio, get the model's own output β no torch, librosa or reimplemented STFT/mel needed, and nothing that can quietly differ from the original. Every export was checked frame by frame against the original PyTorch pipeline (below), and measured on PTDB-TUG speech against the other exports in this family and against pyin.
| file | model | parameters | size |
|---|---|---|---|
fcpe.onnx |
FCPE | 10.8 M | 47.8 MB |
Same family: rmvpe-onnx Β· fcpe-onnx Β· crepe-onnx Β· pesto-onnx.
Use
# pip install onnxruntime numpy soundfile soxr huggingface_hub
import soundfile as sf, soxr
from huggingface_hub import hf_hub_download
import importlib.util
repo = "Scicom-intl/fcpe-onnx"
spec = importlib.util.spec_from_file_location("pitch_onnx", hf_hub_download(repo, "pitch_onnx.py"))
pitch_onnx = importlib.util.module_from_spec(spec); spec.loader.exec_module(pitch_onnx)
model = pitch_onnx.PitchModel(hf_hub_download(repo, "fcpe.onnx")) # threshold= to override voicing
y, sr = sf.read("speech.wav", dtype="float32", always_2d=True)
y = soxr.resample(y.mean(1), sr, 16000)
f0, voiced, confidence = model(y) # one per 10 ms frame (frame i at i * 10 ms; FCPE + 5 ms); f0 = 0 unvoiced
pitch_onnx.py is numpy + onnxruntime only: it cuts CREPE's frames, decodes the 360-bin salience
the way the models ship (salience-weighted mean of the 9 bins around the peak; CREPE/RMVPE bins are
20 cents from 32.70 Hz, FCPE's are evenly spaced 32.7β1975.5 Hz) and applies the voicing threshold.
Details
FCPE
- Input:
audiofloat32 [1, N] β 16 kHz mono - Output:
saliencefloat32 [1, T, 360], T = N // 160 + 1 frames, frame i centred at i Γ 10 ms + 5 ms (torchfcpe's uncentred STFT: a 432-sample pad before a 1024-sample window). - Front end: torchfcpe's mel (432-sample reflect pad, uncentred STFT n_fft 1024 hop 160, 128 Slaney mels 0β8000 Hz, log clamp 1e-5, last frame repeated) is inside the graph.
- Exactness vs the original PyTorch pipeline: 4 clips (speech of three lengths + 3 s of noise, 2696 frames): max |ONNX β PyTorch| salience 3.84e-06, max pitch difference 0.00029 cents (1 cent = 1/100 semitone), voicing agreement 100.0 %.
- Voicing threshold: 0.33 (chosen on PTDB-TUG's dev speakers, lowest F0 frame error; the upstream default is 0.006).
Accuracy on PTDB-TUG's 16 test speakers (400 utterances per condition), in %:
| condition | RPA β | RCA β | GPE β | VDE β | FFE β | VR β | VFA β |
|---|---|---|---|---|---|---|---|
| clean | 91.83 | 92.57 | 1.14 | 2.51 | 2.77 | 94.49 | 1.58 |
| white noise 10 dB | 90.95 | 91.79 | 1.26 | 2.67 | 2.95 | 93.74 | 1.55 |
| white noise 0 dB | 89.10 | 90.02 | 1.43 | 3.07 | 3.39 | 92.46 | 1.67 |
| pink noise 10 dB | 90.04 | 91.12 | 1.56 | 2.95 | 3.30 | 93.48 | 1.83 |
| pink noise 0 dB | 84.69 | 85.99 | 1.97 | 4.36 | 4.78 | 89.63 | 2.47 |
CPU speed (onnxruntime, x86 server CPU; RTF = compute seconds per second of audio; peak RSS is the whole Python process, librosa and numpy included):
| threads | audio | RTF (compute s / audio s) | peak RSS |
|---|---|---|---|
| 1 | 10 s | 0.0219 | 358 MB |
| 4 | 10 s | 0.0068 | 357 MB |
| 1 | 30 s | 0.0214 | 427 MB |
Comparison on PTDB-TUG (F0 frame error, %, lower is better)
FFE = (voicing-decision errors + gross pitch errors > 20 %) / all frames β the single number that counts both "is this frame voice" and "how wrong is the pitch". Reference: PTDB-TUG's laryngograph-derived f0 (RAPT, 10 ms). Speakers F01 F02 M01 M02 were used ONLY to pick each method's voicing threshold and frame lag (clean audio, lowest FFE); the table is the other 16 speakers, 400 utterances per condition, scored once. Noise is added at the stated SNR over the whole utterance. Best per row in bold.
| condition | RMVPE | FCPE | CREPE full | CREPE tiny | PESTO | pyin (librosa 0.11) |
|---|---|---|---|---|---|---|
| clean | 3.09 | 2.77 | 6.43 | 6.33 | 5.58 | 7.72 |
| white noise 10 dB | 3.18 | 2.95 | 5.98 | 6.07 | 5.99 | 8.32 |
| white noise 0 dB | 3.56 | 3.39 | 6.92 | 7.21 | 7.46 | 16.92 |
| pink noise 10 dB | 3.48 | 3.30 | 6.59 | 6.41 | 6.54 | 8.36 |
| pink noise 0 dB | 4.47 | 4.78 | 9.48 | 9.31 | 8.99 | 17.18 |
Metrics per condition for every method, the chosen thresholds/lags and the CPU timings are in
benchmark.json; the harness is export/evaluate.py.
How it was exported
export/export.py (torch 2.8, legacy ONNX exporter, opset 17). The STFT is two conv1ds with
fixed DFT kernels (torch.stft's complex output doesn't export), equal to torch.stft to float32
rounding. export/decode.py is the decoder the parity check uses.
License and credits
Weights and model: CNChTu/FCPE (MIT, Copyright (c) 2023 CN_ChiTu). ONNX conversion, evaluation and packaging by Scicom.