File size: 2,715 Bytes
20e8d8e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
---
license: mit
tags:
  - onnx
  - pitch-tracking
  - f0-estimation
  - audio
  - swift-f0
library_name: onnxruntime
---

# SwiftF0 (ONNX)

Re-hosted ONNX graph from [lars76/swift-f0](https://github.com/lars76/swift_f0) (PyPI: `swift-f0`,
v0.1.2), a fast STFT + 2D-CNN fundamental frequency (F0) detector. In the
[pitch-benchmark](https://github.com/lars76/pitch-benchmark/) suite it beats CREPE on both speed
and accuracy.

Upstream ships the model **already exported to ONNX**`swift_f0/model.onnx` — and the Python
package is itself just a thin `onnxruntime.InferenceSession` wrapper (see `swift_f0/core.py`).
This is that exact graph, unmodified, re-hosted for direct download (e.g. by
[superassp](https://github.com/), an R package for acoustic phonetic analysis).

## Files

| File | Precision | Size |
|---|---|---|
| `onnx/model.onnx` | fp32 | 398 KB |

## I/O spec

```
input:  "input_audio"  float32 [1, audio_length]   # raw 16kHz mono waveform, dynamic length
output: "pitch_hz"      float32 [1, num_frames]      # per-frame F0 estimate, Hz
output: "confidence"    float32 [1, num_frames]      # per-frame voicing confidence, 0-1
```

Framing (STFT: 1024-sample window, 256-sample hop, 384-sample symmetric padding) is done
**inside the graph** via an ONNX `STFT` op (opset ≥17) — unlike CREPE, you feed raw audio
directly, no manual windowing.

- Native frame rate: fixed 62.5 Hz (16 ms hop), not configurable without re-exporting the graph.
- Frame `i` timestamp: `t[i] = (i * 256 + 127.5) / 16000` seconds.
- Model strictly supports **46.875–2093.75 Hz** (G1–C7); values outside this range are not
  meaningful.
- Minimum input length: 256 samples (shorter audio must be zero-padded).
- Voicing decision (applied outside the graph, in upstream's Python wrapper): frame is voiced iff
  `confidence > threshold` (default 0.9) `and fmin <= pitch_hz <= fmax`.

## Quick start (Python, onnxruntime)

```python
import numpy as np
import onnxruntime as ort

sess = ort.InferenceSession("onnx/model.onnx", providers=["CPUExecutionProvider"])
audio = np.zeros((1, 16000), dtype=np.float32)  # replace with real 16kHz mono waveform
pitch_hz, confidence = sess.run(["pitch_hz", "confidence"], {"input_audio": audio})
voiced = (confidence[0] > 0.9) & (pitch_hz[0] >= 46.875) & (pitch_hz[0] <= 2093.75)
```

## Validation

Unmodified upstream artifact — no conversion step performed, so no PyTorch-vs-ONNX drift check
applies (there is no separate PyTorch checkpoint upstream; the ONNX graph *is* the shipped model).
Confirmed to load and run under onnxruntime 1.24.x CPU EP with no unsupported ops.

## License

MIT, inherited from upstream `lars76/swift-f0` (© Lars Nieradzik). See `LICENSE`.