v2.0.0 — Transkun transformer-only ONNX export + decode spec (from audio-claudio)
Browse files- .gitattributes +4 -0
- DECODE_SPEC.md +68 -0
- LICENSE +21 -0
- README.md +62 -0
- export_transkun.py +198 -0
- export_transkun_heads.py +100 -0
- freq2mels.f32 +3 -0
- manifest.json +59 -0
- params.json +14 -0
- ref3b_audio.f32 +3 -0
- ref3b_features.f32 +3 -0
- ref3c_S.f32 +3 -0
- ref3c_forced_intervals.json +1 -0
- ref3c_intervals.json +1 -0
- ref3c_syn_S.f32 +0 -0
- ref3c_syn_intervals.json +1 -0
- symbols.i32 +0 -0
- transkun-heads.onnx +3 -0
- transkun.onnx +3 -0
- windows.f32 +0 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
freq2mels.f32 filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
ref3b_audio.f32 filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
ref3b_features.f32 filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
ref3c_S.f32 filter=lfs diff=lfs merge=lfs -text
|
DECODE_SPEC.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Transkun — self-contained ONNX export (v2 Stage 4)
|
| 2 |
+
|
| 3 |
+
A transformer-only ONNX export of **Transkun** (Yujia Yan's Neural Semi-CRF piano transcriber, 0.984
|
| 4 |
+
MAESTRO F1), plus the frozen front-end buffers and the decode spec needed to run it **in-process with no
|
| 5 |
+
Python/torch at runtime** behind `audio-claudio`'s `ITranscriber` port.
|
| 6 |
+
|
| 7 |
+
- **Upstream:** <https://github.com/Yujia-Yan/Skipping-The-Frame-Level> — Yujia Yan, Frank Cwitkowitz,
|
| 8 |
+
Zhiyao Duan. Package `transkun` 2.0.1, checkpoint `pretrained/2.0.pt`.
|
| 9 |
+
- **License:** MIT (© 2021 Yujia Yan) — see [`LICENSE.transkun`](LICENSE.transkun). audio-claudio is UNLICENSE;
|
| 10 |
+
MIT is compatible.
|
| 11 |
+
- This is a **transformer-only export + a decode spec**, not a drop-in `.onnx` transcriber: the mel front
|
| 12 |
+
end and the semi-CRF Viterbi decode are reimplemented in C# (Stages 4b/4c), because `torch.fft.rfft` and
|
| 13 |
+
the custom semi-CRF backtracking are not ONNX-exportable.
|
| 14 |
+
|
| 15 |
+
## What the ONNX computes
|
| 16 |
+
|
| 17 |
+
`transkun.onnx` maps **`featuresBatch` → (`S`, `ctx`)**:
|
| 18 |
+
|
| 19 |
+
- input `featuresBatch` `[nBatch, T, 229, 6]` — log-mel features (229 mel bins × 6 windows), `T` dynamic.
|
| 20 |
+
- output `S` `[T, T, nBatch*90]` — the semi-CRF pairwise interval scores. `S[e, b, k]` scores a note on
|
| 21 |
+
track `k` spanning frames `b→e` (diagonal `e==b` = a single-frame note). The 90 tracks are
|
| 22 |
+
`symbols = [-64, -67, 21..108]`: index 0 = sustain pedal (CC64), 1 = soft pedal (CC67), 2–89 = MIDI
|
| 23 |
+
21–108. (The `S_skip` "no-event" score is provably 0 and is hardcoded in C#.)
|
| 24 |
+
- output `ctx` `[90, T, 256]` (Stage 4e) — the backbone features, gathered at decoded interval endpoints to
|
| 25 |
+
drive the attribute heads. `S` is byte-for-byte the same as the S-only 4a export (corr 1.0).
|
| 26 |
+
|
| 27 |
+
**`transkun-heads.onnx`** (Stage 4e) maps the gathered interval features **`attr` `[N, 768]`**
|
| 28 |
+
(`[ctx_a, ctx_b, ctx_a·ctx_b]`) → **`velLogits` `[N, 128]`** (`velocityPredictor`; velocity = argmax) and
|
| 29 |
+
**`ofRaw` `[N, 4]`** (`refinedOFPredictor`: two sub-frame onset/offset value logits → a ContinuousBernoulli
|
| 30 |
+
mean in `[-0.5, 0.5]` frames, + two presence logits). This adds real velocity + sub-frame timing on top of
|
| 31 |
+
the frame-level decode — validated note-identical to the native CLI (velocity exact, onsets ~1 ms).
|
| 32 |
+
|
| 33 |
+
Two ops needed care in export (see `export_transkun.py`): the backbone's **5-D `scaled_dot_product_attention`**
|
| 34 |
+
is reshaped to 4-D (a mathematical identity — SDPA batches all but the last two dims) because the ONNX
|
| 35 |
+
exporter only supports 4-D SDPA. `diag_embed` exported cleanly on this stack (torch 2.13 / onnx 1.22 /
|
| 36 |
+
onnxruntime 1.27, opset 17), contrary to an earlier assumption. Validated **`corr = 1.000000`,
|
| 37 |
+
maxRelErr ≈ 5e-6** vs PyTorch on random and dynamic-`T` inputs.
|
| 38 |
+
|
| 39 |
+
## Files
|
| 40 |
+
|
| 41 |
+
| File | What |
|
| 42 |
+
|---|---|
|
| 43 |
+
| `transkun.onnx` | the main export `featuresBatch → (S, ctx)` (opset 17, weights inlined, ~53 MB) |
|
| 44 |
+
| `transkun-heads.onnx` | the velocity + onset/offset attribute heads `attr → (velLogits, ofRaw)` (~3.4 MB) |
|
| 45 |
+
| `export_transkun_heads.py` | Stage-4e regeneration (main graph with `ctx` + the heads) |
|
| 46 |
+
| `freq2mels.f32` `[2049, 229]` | mel filterbank (`torchaudio.melscale_fbanks`, 30–8000 Hz) — Stage 4b |
|
| 47 |
+
| `windows.f32` `[6, 4096]` | analysis windows (row 0 Hann, rows 1–5 learned Gaussian) — Stage 4b |
|
| 48 |
+
| `symbols.i32` `[90]` | the track→symbol map `[-64, -67, 21..108]` |
|
| 49 |
+
| `params.json` | fs 44100, windowSize 4096, hopSize 1024, nMels 229, eps 1e-5, segment 16 s / hop 8 s |
|
| 50 |
+
| `ref3b_audio.f32`, `ref3b_features.f32` | Stage-4b TDD fixture: 1.5 s of `two-bar.wav` → its `featuresBatch` `[66,229,6]` |
|
| 51 |
+
| `ref3c_S.f32`, `ref3c_intervals.json` | Stage-4c TDD fixture: a real model `S` `[66,66,90]` → Viterbi intervals |
|
| 52 |
+
| `ref3c_syn_S.f32`, `ref3c_syn_intervals.json` | hand-built multi-track `S` `[6,6,90]` → known intervals |
|
| 53 |
+
| `ref3c_forced_intervals.json` | the same synthetic `S` with a `forcedStartPos` (Stage-4d stitching) |
|
| 54 |
+
| `manifest.json` | shape/dtype/file for every raw `.f32`/`.i32` array (raw little-endian) |
|
| 55 |
+
| `export_transkun.py` | the regeneration script (needs the transkun venv; see below) |
|
| 56 |
+
|
| 57 |
+
## Regenerating
|
| 58 |
+
|
| 59 |
+
Not needed for the build (everything above is committed). To reproduce, in a venv with
|
| 60 |
+
`transkun==2.0.1`, `torch`, `onnx`, `onnxruntime`, `numpy`:
|
| 61 |
+
|
| 62 |
+
```
|
| 63 |
+
python export_transkun.py <output-dir>
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
It loads the model **from `2.0.conf`** (not class defaults — `baseSize=64`, `nHead=8`), wraps
|
| 67 |
+
`backbone + scorer`, exports, validates against PyTorch, extracts the buffers, and regenerates the ref
|
| 68 |
+
fixtures. Deterministic (seed 0).
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2021 Yujia Yan
|
| 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.
|
README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
library_name: onnxruntime
|
| 4 |
+
tags:
|
| 5 |
+
- audio
|
| 6 |
+
- music
|
| 7 |
+
- piano-transcription
|
| 8 |
+
- amt
|
| 9 |
+
- onnx
|
| 10 |
+
- transkun
|
| 11 |
+
- semi-crf
|
| 12 |
+
pipeline_tag: audio-to-audio
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# Transkun — transformer-only ONNX export + decode spec
|
| 16 |
+
|
| 17 |
+
A **self-contained ONNX export of [Transkun](https://github.com/Yujia-Yan/Skipping-The-Frame-Level)**
|
| 18 |
+
(Yujia Yan's Neural Semi-CRF piano transcriber, 0.984 MAESTRO note F1) that runs the full model **in-process
|
| 19 |
+
with no Python/PyTorch at runtime**. This is **not** a drop-in `.onnx` transcriber: `torch.fft.rfft` and the
|
| 20 |
+
custom semi-CRF backtracking are not ONNX-exportable, so the mel front end and the Viterbi decode are provided
|
| 21 |
+
as a **documented decode spec** + a **reference decoder**.
|
| 22 |
+
|
| 23 |
+
> **Attribution.** The model, weights and architecture are the work of **Yujia Yan, Frank Cwitkowitz and
|
| 24 |
+
> Zhiyao Duan** (*"Skipping the Frame-Level: Event-Based Piano Transcription with Neural Semi-CRFs"*, NeurIPS
|
| 25 |
+
> 2021). This is an independent export + decode spec, not affiliated with or endorsed by the authors. Upstream:
|
| 26 |
+
> <https://github.com/Yujia-Yan/Skipping-The-Frame-Level>. License: **MIT** (© 2021 Yujia Yan).
|
| 27 |
+
|
| 28 |
+
## What's in the package
|
| 29 |
+
|
| 30 |
+
| File | Role |
|
| 31 |
+
|---|---|
|
| 32 |
+
| `transkun.onnx` (~53 MB, opset 17) | `featuresBatch [1,T,229,6] → (S [T,T,90], ctx [90,T,256])` — the transformer + semi-CRF scorer + backbone features |
|
| 33 |
+
| `transkun-heads.onnx` (~3.4 MB) | `attr [N,768] → (velLogits [N,128], ofRaw [N,4])` — velocity + sub-frame onset/offset heads |
|
| 34 |
+
| `freq2mels.f32 [2049,229]`, `windows.f32 [6,4096]`, `symbols.i32 [90]`, `params.json` | frozen front-end constants |
|
| 35 |
+
| `LICENSE.transkun` | upstream MIT license |
|
| 36 |
+
| `export_transkun.py`, `export_transkun_heads.py` | regeneration scripts (need the `transkun` PyTorch package) |
|
| 37 |
+
|
| 38 |
+
The **decode spec** (`DECODE_SPEC.md`) documents the mel front end, the `S` layout, the 90-track
|
| 39 |
+
symbol map (`[-64, -67, 21..108]` = sustain/soft pedal + MIDI 21–108), the semi-CRF `viterbiBackward`, the
|
| 40 |
+
16 s/8 s segment stitching, and the attribute heads (velocity = argmax; `ofValue` = ContinuousBernoulli mean).
|
| 41 |
+
|
| 42 |
+
## Reference decoder + validation
|
| 43 |
+
|
| 44 |
+
The reference decoder is the C# implementation in **[audio-claudio](https://github.com/TuesdayCrowd/audio-claudio)**
|
| 45 |
+
(mel front end, `SemiCrfViterbi`, `TranskunTranscriber`). It is validated **note-identical to the native
|
| 46 |
+
`transkun` CLI (PyTorch)**: on the test clips it reaches **100% note-level F1 at ±25 ms** with **exact
|
| 47 |
+
velocity** on every note — the export + decode spec reproduce the reference implementation, not merely
|
| 48 |
+
approximate it.
|
| 49 |
+
|
| 50 |
+
## Pipeline (how to run)
|
| 51 |
+
|
| 52 |
+
```
|
| 53 |
+
audio (mono, 44.1 kHz)
|
| 54 |
+
→ mel front end (framing 4096/1024, 6 windows, rfft ortho, freq2mels, log-norm) → featuresBatch
|
| 55 |
+
→ transkun.onnx → (S, ctx)
|
| 56 |
+
→ semi-CRF viterbiBackward(S) → per-track note intervals, over 16 s/8 s stitched segments
|
| 57 |
+
→ gather ctx at interval endpoints → transkun-heads.onnx → velocity + sub-frame onset/offset
|
| 58 |
+
→ notes (+ sustain/soft pedal from tracks 0/1)
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
See the repo's decode spec and `TranskunTranscriber` for the exact arithmetic (segment padding, `forcedStartPos`
|
| 62 |
+
carry, merge, `resolveOverlapping`).
|
export_transkun.py
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
"""v2 Stage 4a — re-derive the Transkun ONNX export + frozen buffers + TDD fixtures.
|
| 3 |
+
|
| 4 |
+
Boundary: featuresBatch -> S (backbone + inner-product CRF scorer). The mel front end (audio ->
|
| 5 |
+
featuresBatch) and the Viterbi decode (S -> intervals) are ported to C# (4b/4c); this script also emits
|
| 6 |
+
their reference fixtures. All outputs are written raw little-endian + a manifest.json for trivial C# reads.
|
| 7 |
+
"""
|
| 8 |
+
import json, math, os, sys
|
| 9 |
+
import numpy as np
|
| 10 |
+
import torch
|
| 11 |
+
|
| 12 |
+
TK_DIR = "/private/tmp/claude-501/-Users-lawls-Development-TuesdayCrowd-Projects-audio-claudio/37748a9b-31e0-48a1-896e-7a25c1faf008/scratchpad/transkun-env/lib/python3.14/site-packages/transkun"
|
| 13 |
+
OUT = sys.argv[1] if len(sys.argv) > 1 else os.path.dirname(os.path.abspath(__file__)) + "/artifacts"
|
| 14 |
+
os.makedirs(OUT, exist_ok=True)
|
| 15 |
+
torch.manual_seed(0)
|
| 16 |
+
np.random.seed(0)
|
| 17 |
+
|
| 18 |
+
manifest = {}
|
| 19 |
+
def save(name, arr, dtype):
|
| 20 |
+
a = np.ascontiguousarray(arr).astype(dtype)
|
| 21 |
+
fn = name + (".f32" if dtype == "<f4" else ".i32")
|
| 22 |
+
a.tofile(os.path.join(OUT, fn))
|
| 23 |
+
manifest[name] = {"file": fn, "shape": list(a.shape), "dtype": "f32" if dtype == "<f4" else "i32"}
|
| 24 |
+
print(f" saved {name:22} shape={list(a.shape)} dtype={manifest[name]['dtype']}")
|
| 25 |
+
|
| 26 |
+
# ---------------------------------------------------------------- 1. load model from the .conf ----------
|
| 27 |
+
print("[1] loading model from 2.0.conf + 2.0.pt")
|
| 28 |
+
import moduleconf
|
| 29 |
+
conf_path = os.path.join(TK_DIR, "pretrained", "2.0.conf")
|
| 30 |
+
pt_path = os.path.join(TK_DIR, "pretrained", "2.0.pt")
|
| 31 |
+
confManager = moduleconf.parseFromFile(conf_path)
|
| 32 |
+
TransKun = confManager["Model"].module.TransKun
|
| 33 |
+
conf = confManager["Model"].config
|
| 34 |
+
checkpoint = torch.load(pt_path, map_location="cpu")
|
| 35 |
+
model = TransKun(conf=conf)
|
| 36 |
+
key = "best_state_dict" if "best_state_dict" in checkpoint else "state_dict"
|
| 37 |
+
missing = model.load_state_dict(checkpoint[key], strict=False)
|
| 38 |
+
model.eval(); torch.set_grad_enabled(False)
|
| 39 |
+
print(f" loaded ({key}); missing={len(missing.missing_keys)} unexpected={len(missing.unexpected_keys)}")
|
| 40 |
+
print(f" fs={model.fs} windowSize={model.windowSize} hopSize={model.hopSize} "
|
| 41 |
+
f"nSym={len(model.targetMIDIPitch)} params={sum(p.numel() for p in model.parameters())/1e6:.2f}M")
|
| 42 |
+
|
| 43 |
+
# ---------------------------------------------------------------- 2. export wrapper: featuresBatch -> S -
|
| 44 |
+
class ExportWrapper(torch.nn.Module):
|
| 45 |
+
def __init__(self, m):
|
| 46 |
+
super().__init__()
|
| 47 |
+
self.backbone = m.backbone
|
| 48 |
+
self.scorer = m.scorer
|
| 49 |
+
self.register_buffer("outputIndices", torch.tensor(m.targetMIDIPitch))
|
| 50 |
+
def forward(self, featuresBatch): # [nBatch, T, 229, 6]
|
| 51 |
+
ctx = self.backbone(featuresBatch, outputIndices=self.outputIndices)
|
| 52 |
+
S_batch, _ = self.scorer(ctx) # S_batch: [T, T, nBatch, 90]; skip is provably 0
|
| 53 |
+
return S_batch.flatten(-2, -1) # [T, T, nBatch*90]
|
| 54 |
+
|
| 55 |
+
wrapper = ExportWrapper(model).eval()
|
| 56 |
+
onnx_path = os.path.join(OUT, "model.onnx")
|
| 57 |
+
T0 = 64
|
| 58 |
+
feat_example = torch.randn(1, T0, 229, 6)
|
| 59 |
+
|
| 60 |
+
# The backbone's axial attention calls SDPA on 5-D q/k/v ([B, T', H, L, D]); the ONNX exporter's SDPA only
|
| 61 |
+
# supports 4-D. SDPA treats every dim before the last two as batch, so collapsing the two leading dims to
|
| 62 |
+
# one 4-D batch is a mathematical identity (validated by corr below). Patch for the duration of the export.
|
| 63 |
+
import torch.nn.functional as F
|
| 64 |
+
_orig_sdpa = F.scaled_dot_product_attention
|
| 65 |
+
def _sdpa_4d(q, k, v, *a, **kw):
|
| 66 |
+
if q.ndim == 5:
|
| 67 |
+
B, X, H, L, D = q.shape
|
| 68 |
+
rs = lambda t: t.reshape(B * X, H, L, D)
|
| 69 |
+
return _orig_sdpa(rs(q), rs(k), rs(v), *a, **kw).reshape(B, X, H, L, D)
|
| 70 |
+
return _orig_sdpa(q, k, v, *a, **kw)
|
| 71 |
+
F.scaled_dot_product_attention = _sdpa_4d
|
| 72 |
+
torch.nn.functional.scaled_dot_product_attention = _sdpa_4d
|
| 73 |
+
|
| 74 |
+
print(f"[2] exporting featuresBatch{list(feat_example.shape)} -> S, opset 17 (SDPA reshaped 5D->4D)")
|
| 75 |
+
try:
|
| 76 |
+
torch.onnx.export(
|
| 77 |
+
wrapper, (feat_example,), onnx_path, opset_version=17,
|
| 78 |
+
input_names=["featuresBatch"], output_names=["S"],
|
| 79 |
+
dynamic_axes={"featuresBatch": {1: "T"}, "S": {0: "T", 1: "T"}})
|
| 80 |
+
print(f" export OK: {os.path.getsize(onnx_path)/1e6:.1f} MB (+ external .data)")
|
| 81 |
+
except Exception as e:
|
| 82 |
+
print(f" STOCK EXPORT FAILED: {type(e).__name__}: {e}\n (would apply eye-multiply patch)")
|
| 83 |
+
raise
|
| 84 |
+
|
| 85 |
+
# Consolidate the external-data weights into ONE self-contained .onnx for committing.
|
| 86 |
+
import onnx
|
| 87 |
+
m_full = onnx.load(onnx_path) # pulls in model.onnx.data
|
| 88 |
+
single_path = os.path.join(OUT, "transkun.onnx")
|
| 89 |
+
onnx.save(m_full, single_path, save_as_external_data=False)
|
| 90 |
+
os.remove(onnx_path)
|
| 91 |
+
if os.path.exists(onnx_path + ".data"):
|
| 92 |
+
os.remove(onnx_path + ".data")
|
| 93 |
+
print(f" consolidated -> transkun.onnx {os.path.getsize(single_path)/1e6:.1f} MB (single file)")
|
| 94 |
+
|
| 95 |
+
# ---------------------------------------------------------------- 3. validate ONNX == PyTorch -----------
|
| 96 |
+
print("[3] validating single-file ONNX vs PyTorch")
|
| 97 |
+
import onnxruntime as ort
|
| 98 |
+
sess = ort.InferenceSession(single_path, providers=["CPUExecutionProvider"])
|
| 99 |
+
def check(feat, tag):
|
| 100 |
+
s_torch = wrapper(feat).numpy()
|
| 101 |
+
s_onnx = sess.run(None, {"featuresBatch": feat.numpy()})[0]
|
| 102 |
+
corr = np.corrcoef(s_torch.ravel(), s_onnx.ravel())[0, 1]
|
| 103 |
+
denom = np.abs(s_torch).max() + 1e-9
|
| 104 |
+
relerr = np.abs(s_torch - s_onnx).max() / denom
|
| 105 |
+
print(f" {tag:14} shape={list(s_onnx.shape)} corr={corr:.6f} maxRelErr={relerr:.2e}")
|
| 106 |
+
return corr, relerr, s_onnx
|
| 107 |
+
check(feat_example, "random T=64")
|
| 108 |
+
check(torch.randn(1, 100, 229, 6), "random T=100") # dynamic-T sanity
|
| 109 |
+
|
| 110 |
+
# ---------------------------------------------------------------- 4. frozen buffers ---------------------
|
| 111 |
+
print("[4] extracting frozen buffers")
|
| 112 |
+
fe = model.framewiseFeatureExtractor
|
| 113 |
+
freq2mels = fe.freq2mels.numpy() # [2049, 229]
|
| 114 |
+
win = fe.spectrogramExtractor.win # [4096] Hann
|
| 115 |
+
wins = torch.cat([win.unsqueeze(0), fe.spectrogramExtractor.winGen.get().t()], dim=0).numpy() # [6, 4096]
|
| 116 |
+
save("freq2mels", freq2mels, "<f4")
|
| 117 |
+
save("windows", wins, "<f4")
|
| 118 |
+
save("symbols", np.array(model.targetMIDIPitch), "<i4")
|
| 119 |
+
params = {
|
| 120 |
+
"fs": int(model.fs), "windowSize": int(model.windowSize), "hopSize": int(model.hopSize),
|
| 121 |
+
"nMels": int(fe.outputDim), "nWindows": int(wins.shape[0]), "eps": float(fe.eps),
|
| 122 |
+
"fMin": 30.0, "fMax": 8000.0, "rfftBins": int(model.windowSize // 2 + 1),
|
| 123 |
+
"segmentSizeSeconds": 16.0, "segmentHopSeconds": 8.0, "nSymbols": len(model.targetMIDIPitch),
|
| 124 |
+
}
|
| 125 |
+
print(" params:", params)
|
| 126 |
+
|
| 127 |
+
# ---------------------------------------------------------------- 5. ref3b: audio -> featuresBatch ------
|
| 128 |
+
print("[5] ref3b (mel front end reference)")
|
| 129 |
+
fs, hop, wsz, eps, nmel = model.fs, model.hopSize, model.windowSize, fe.eps, fe.outputDim
|
| 130 |
+
# The first 1.5 s of the committed two-bar MeltySynth piano render (44100 Hz mono int16) — a real piano
|
| 131 |
+
# signal (attack + timbre) that fires the MAESTRO-trained model, fully reproducible from a committed WAV.
|
| 132 |
+
import wave
|
| 133 |
+
wf = wave.open("/Users/lawls/Development/TuesdayCrowd/Projects/audio-claudio/fixtures/golden/two-bar.wav")
|
| 134 |
+
assert wf.getframerate() == fs and wf.getnchannels() == 1 and wf.getsampwidth() == 2
|
| 135 |
+
nread = int(1.5 * fs)
|
| 136 |
+
audio = (np.frombuffer(wf.readframes(nread), dtype="<i2").astype(np.float32) / 32768.0)
|
| 137 |
+
wf.close()
|
| 138 |
+
|
| 139 |
+
def make_frame(x, hopSize, windowSize): # mirrors Util.makeFrame (leftPaddingHalfFrame=True)
|
| 140 |
+
n = x.shape[-1]
|
| 141 |
+
nFrame = math.ceil(n / hopSize) + 1
|
| 142 |
+
lPad = windowSize // 2
|
| 143 |
+
rPad = (nFrame - 1) * hopSize + windowSize // 2 - n
|
| 144 |
+
xp = torch.nn.functional.pad(torch.tensor(x), (lPad, rPad))
|
| 145 |
+
return xp.unfold(-1, windowSize, hopSize) # [nFrame, windowSize]
|
| 146 |
+
|
| 147 |
+
frames = make_frame(audio, hop, wsz).unsqueeze(0).unsqueeze(0) # [1,1,nFrame,windowSize] (nBatch,nChan,..)
|
| 148 |
+
mean = frames.mean(dim=[1, 2, 3], keepdim=True)
|
| 149 |
+
std = frames.std(dim=[1, 2, 3], keepdim=True)
|
| 150 |
+
framesN = (frames - mean) / (std + 1e-8)
|
| 151 |
+
features = fe(framesN).contiguous() # [1,1,nFrame,229,6]
|
| 152 |
+
features = features.view(1, *features.shape[-3:]) # [1,nFrame,229,6]
|
| 153 |
+
save("ref3b_audio", audio, "<f4")
|
| 154 |
+
save("ref3b_features", features.squeeze(0).numpy(), "<f4") # [nFrame,229,6]
|
| 155 |
+
print(f" audio={len(audio)} samples -> features {list(features.shape)}")
|
| 156 |
+
|
| 157 |
+
# ---------------------------------------------------------------- 6. ref3c: S -> intervals --------------
|
| 158 |
+
print("[6] ref3c (Viterbi decode reference)")
|
| 159 |
+
from transkun.CRF.NeuralSemiCRFInterval import viterbiBackward
|
| 160 |
+
S_real = wrapper(features).squeeze() # [nFrame,nFrame,90] (nBatch=1 -> flatten gives 90)
|
| 161 |
+
T = S_real.shape[0]
|
| 162 |
+
noise = torch.zeros(T - 1, S_real.shape[2])
|
| 163 |
+
intervals_real = viterbiBackward(S_real, noise, None) # per-track list of (begin,end)
|
| 164 |
+
save("ref3c_S", S_real.numpy(), "<f4")
|
| 165 |
+
json.dump({str(k): v for k, v in enumerate(intervals_real)},
|
| 166 |
+
open(os.path.join(OUT, "ref3c_intervals.json"), "w"))
|
| 167 |
+
nnotes = sum(len(v) for v in intervals_real)
|
| 168 |
+
print(f" real S {list(S_real.shape)} -> {nnotes} intervals across 90 tracks")
|
| 169 |
+
|
| 170 |
+
# Hand-checkable synthetic S, multi-track (score[end, begin, track]): track 5 = interval (1,3) + singleton
|
| 171 |
+
# (5,5); track 10 = interval (0,4); track 20 = singleton (2,2). Decoded with default forcedStartPos.
|
| 172 |
+
Tsyn, nSym = 6, 90
|
| 173 |
+
Ssyn = torch.full((Tsyn, Tsyn, nSym), -5.0)
|
| 174 |
+
Ssyn[3, 1, 5] = 4.0
|
| 175 |
+
Ssyn[5, 5, 5] = 2.0
|
| 176 |
+
Ssyn[4, 0, 10] = 6.0
|
| 177 |
+
Ssyn[2, 2, 20] = 3.0
|
| 178 |
+
noise_syn = torch.zeros(Tsyn - 1, nSym)
|
| 179 |
+
intervals_syn = viterbiBackward(Ssyn, noise_syn, None)
|
| 180 |
+
save("ref3c_syn_S", Ssyn.numpy(), "<f4")
|
| 181 |
+
json.dump({str(k): v for k, v in enumerate(intervals_syn)},
|
| 182 |
+
open(os.path.join(OUT, "ref3c_syn_intervals.json"), "w"))
|
| 183 |
+
print(f" synthetic S {list(Ssyn.shape)} -> t5={intervals_syn[5]} t10={intervals_syn[10]} t20={intervals_syn[20]}")
|
| 184 |
+
|
| 185 |
+
# A forcedStartPos case (used by 4d segment stitching): same S, but track 5 forced to start at frame 4,
|
| 186 |
+
# so its interval (1,3) is skipped and only the singleton (5,5) survives.
|
| 187 |
+
forced = [0] * nSym
|
| 188 |
+
forced[5] = 4
|
| 189 |
+
intervals_forced = viterbiBackward(Ssyn, noise_syn, forced)
|
| 190 |
+
json.dump({"forcedStartPos": forced, "intervals": {str(k): v for k, v in enumerate(intervals_forced)}},
|
| 191 |
+
open(os.path.join(OUT, "ref3c_forced_intervals.json"), "w"))
|
| 192 |
+
print(f" forced(t5->4) -> t5={intervals_forced[5]} (interval (1,3) skipped)")
|
| 193 |
+
|
| 194 |
+
# ---------------------------------------------------------------- 7. write manifest + params ------------
|
| 195 |
+
json.dump(manifest, open(os.path.join(OUT, "manifest.json"), "w"), indent=2)
|
| 196 |
+
json.dump(params, open(os.path.join(OUT, "params.json"), "w"), indent=2)
|
| 197 |
+
print(f"[7] wrote manifest.json + params.json to {OUT}")
|
| 198 |
+
print("DONE")
|
export_transkun_heads.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
"""v2 Stage 4e — re-export the main graph to ALSO output ctx, and export the two attribute heads
|
| 3 |
+
(velocityPredictor, refinedOFPredictor) so the C# engine can add real velocity + sub-frame onset/offset
|
| 4 |
+
refinement. Overwrites transkun.onnx (S is byte-for-byte the same; ctx is an added output) and adds
|
| 5 |
+
transkun-heads.onnx. Deterministic (seed 0)."""
|
| 6 |
+
import json, os, sys
|
| 7 |
+
import numpy as np
|
| 8 |
+
import torch
|
| 9 |
+
|
| 10 |
+
TK_DIR = "/private/tmp/claude-501/-Users-lawls-Development-TuesdayCrowd-Projects-audio-claudio/37748a9b-31e0-48a1-896e-7a25c1faf008/scratchpad/transkun-env/lib/python3.14/site-packages/transkun"
|
| 11 |
+
OUT = sys.argv[1] if len(sys.argv) > 1 else os.path.dirname(os.path.abspath(__file__)) + "/artifacts4e"
|
| 12 |
+
os.makedirs(OUT, exist_ok=True)
|
| 13 |
+
torch.manual_seed(0); np.random.seed(0)
|
| 14 |
+
|
| 15 |
+
print("[1] load model from 2.0.conf")
|
| 16 |
+
import moduleconf
|
| 17 |
+
cm = moduleconf.parseFromFile(os.path.join(TK_DIR, "pretrained", "2.0.conf"))
|
| 18 |
+
model = cm["Model"].module.TransKun(conf=cm["Model"].config)
|
| 19 |
+
ckpt = torch.load(os.path.join(TK_DIR, "pretrained", "2.0.pt"), map_location="cpu")
|
| 20 |
+
model.load_state_dict(ckpt["best_state_dict" if "best_state_dict" in ckpt else "state_dict"], strict=False)
|
| 21 |
+
model.eval(); torch.set_grad_enabled(False)
|
| 22 |
+
|
| 23 |
+
# SDPA 5D->4D (identity) so the backbone exports; same as the 4a export.
|
| 24 |
+
import torch.nn.functional as F
|
| 25 |
+
_sdpa = F.scaled_dot_product_attention
|
| 26 |
+
def _sdpa4d(q, k, v, *a, **kw):
|
| 27 |
+
if q.ndim == 5:
|
| 28 |
+
B, X, H, L, D = q.shape
|
| 29 |
+
r = lambda t: t.reshape(B * X, H, L, D)
|
| 30 |
+
return _sdpa(r(q), r(k), r(v), *a, **kw).reshape(B, X, H, L, D)
|
| 31 |
+
return _sdpa(q, k, v, *a, **kw)
|
| 32 |
+
F.scaled_dot_product_attention = _sdpa4d
|
| 33 |
+
torch.nn.functional.scaled_dot_product_attention = _sdpa4d
|
| 34 |
+
|
| 35 |
+
import onnx, onnxruntime as ort
|
| 36 |
+
def consolidate(split_path, single_path):
|
| 37 |
+
m = onnx.load(split_path)
|
| 38 |
+
onnx.save(m, single_path, save_as_external_data=False)
|
| 39 |
+
os.remove(split_path)
|
| 40 |
+
if os.path.exists(split_path + ".data"):
|
| 41 |
+
os.remove(split_path + ".data")
|
| 42 |
+
|
| 43 |
+
# ---- main graph: featuresBatch -> (S, ctx) --------------------------------------------------------------
|
| 44 |
+
print("[2] export main graph featuresBatch -> (S, ctx)")
|
| 45 |
+
class MainWrapper(torch.nn.Module):
|
| 46 |
+
def __init__(self, m):
|
| 47 |
+
super().__init__()
|
| 48 |
+
self.backbone = m.backbone
|
| 49 |
+
self.scorer = m.scorer
|
| 50 |
+
self.register_buffer("outputIndices", torch.tensor(m.targetMIDIPitch))
|
| 51 |
+
def forward(self, featuresBatch):
|
| 52 |
+
ctx = self.backbone(featuresBatch, outputIndices=self.outputIndices) # [1,90,T,256]
|
| 53 |
+
S_batch, _ = self.scorer(ctx)
|
| 54 |
+
S = S_batch.flatten(-2, -1) # [T,T,90]
|
| 55 |
+
return S, ctx.squeeze(0) # ctx -> [90,T,256]
|
| 56 |
+
|
| 57 |
+
main = MainWrapper(model).eval()
|
| 58 |
+
feat = torch.randn(1, 64, 229, 6)
|
| 59 |
+
split = os.path.join(OUT, "_main.onnx")
|
| 60 |
+
torch.onnx.export(main, (feat,), split, opset_version=17,
|
| 61 |
+
input_names=["featuresBatch"], output_names=["S", "ctx"],
|
| 62 |
+
dynamic_axes={"featuresBatch": {1: "T"}, "S": {0: "T", 1: "T"}, "ctx": {1: "T"}})
|
| 63 |
+
main_path = os.path.join(OUT, "transkun.onnx")
|
| 64 |
+
consolidate(split, main_path)
|
| 65 |
+
print(f" transkun.onnx {os.path.getsize(main_path)/1e6:.1f} MB")
|
| 66 |
+
|
| 67 |
+
sess = ort.InferenceSession(main_path, providers=["CPUExecutionProvider"])
|
| 68 |
+
S_t, ctx_t = main(feat)
|
| 69 |
+
S_o, ctx_o = sess.run(None, {"featuresBatch": feat.numpy()})
|
| 70 |
+
print(f" S corr={np.corrcoef(S_t.numpy().ravel(), S_o.ravel())[0,1]:.6f} shape={list(S_o.shape)}")
|
| 71 |
+
print(f" ctx corr={np.corrcoef(ctx_t.numpy().ravel(), ctx_o.ravel())[0,1]:.6f} shape={list(ctx_o.shape)}")
|
| 72 |
+
|
| 73 |
+
# ---- heads: attr[N,768] -> (velLogits[N,128], ofRaw[N,4]) -----------------------------------------------
|
| 74 |
+
print("[3] export heads attr -> (velLogits, ofRaw)")
|
| 75 |
+
class HeadWrapper(torch.nn.Module):
|
| 76 |
+
def __init__(self, m):
|
| 77 |
+
super().__init__()
|
| 78 |
+
self.vel = m.velocityPredictor
|
| 79 |
+
self.of = m.refinedOFPredictor
|
| 80 |
+
def forward(self, attr):
|
| 81 |
+
return self.vel(attr), self.of(attr)
|
| 82 |
+
|
| 83 |
+
heads = HeadWrapper(model).eval()
|
| 84 |
+
attr = torch.randn(7, 768)
|
| 85 |
+
hsplit = os.path.join(OUT, "_heads.onnx")
|
| 86 |
+
torch.onnx.export(heads, (attr,), hsplit, opset_version=17,
|
| 87 |
+
input_names=["attr"], output_names=["velLogits", "ofRaw"],
|
| 88 |
+
dynamic_axes={"attr": {0: "N"}, "velLogits": {0: "N"}, "ofRaw": {0: "N"}})
|
| 89 |
+
heads_path = os.path.join(OUT, "transkun-heads.onnx")
|
| 90 |
+
consolidate(hsplit, heads_path)
|
| 91 |
+
print(f" transkun-heads.onnx {os.path.getsize(heads_path)/1e3:.0f} KB")
|
| 92 |
+
|
| 93 |
+
hsess = ort.InferenceSession(heads_path, providers=["CPUExecutionProvider"])
|
| 94 |
+
v_t, o_t = heads(attr)
|
| 95 |
+
v_o, o_o = hsess.run(None, {"attr": attr.numpy()})
|
| 96 |
+
print(f" velLogits corr={np.corrcoef(v_t.numpy().ravel(), v_o.ravel())[0,1]:.6f} shape={list(v_o.shape)}")
|
| 97 |
+
print(f" ofRaw corr={np.corrcoef(o_t.numpy().ravel(), o_o.ravel())[0,1]:.6f} shape={list(o_o.shape)}")
|
| 98 |
+
|
| 99 |
+
print(f"[4] wrote {main_path} + {heads_path}")
|
| 100 |
+
print("DONE")
|
freq2mels.f32
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:449f2a5269cde41f6705cfde7157240ce7c8930f20b50909d57e633395bbf0f4
|
| 3 |
+
size 1876884
|
manifest.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"freq2mels": {
|
| 3 |
+
"file": "freq2mels.f32",
|
| 4 |
+
"shape": [
|
| 5 |
+
2049,
|
| 6 |
+
229
|
| 7 |
+
],
|
| 8 |
+
"dtype": "f32"
|
| 9 |
+
},
|
| 10 |
+
"windows": {
|
| 11 |
+
"file": "windows.f32",
|
| 12 |
+
"shape": [
|
| 13 |
+
6,
|
| 14 |
+
4096
|
| 15 |
+
],
|
| 16 |
+
"dtype": "f32"
|
| 17 |
+
},
|
| 18 |
+
"symbols": {
|
| 19 |
+
"file": "symbols.i32",
|
| 20 |
+
"shape": [
|
| 21 |
+
90
|
| 22 |
+
],
|
| 23 |
+
"dtype": "i32"
|
| 24 |
+
},
|
| 25 |
+
"ref3b_audio": {
|
| 26 |
+
"file": "ref3b_audio.f32",
|
| 27 |
+
"shape": [
|
| 28 |
+
66150
|
| 29 |
+
],
|
| 30 |
+
"dtype": "f32"
|
| 31 |
+
},
|
| 32 |
+
"ref3b_features": {
|
| 33 |
+
"file": "ref3b_features.f32",
|
| 34 |
+
"shape": [
|
| 35 |
+
66,
|
| 36 |
+
229,
|
| 37 |
+
6
|
| 38 |
+
],
|
| 39 |
+
"dtype": "f32"
|
| 40 |
+
},
|
| 41 |
+
"ref3c_S": {
|
| 42 |
+
"file": "ref3c_S.f32",
|
| 43 |
+
"shape": [
|
| 44 |
+
66,
|
| 45 |
+
66,
|
| 46 |
+
90
|
| 47 |
+
],
|
| 48 |
+
"dtype": "f32"
|
| 49 |
+
},
|
| 50 |
+
"ref3c_syn_S": {
|
| 51 |
+
"file": "ref3c_syn_S.f32",
|
| 52 |
+
"shape": [
|
| 53 |
+
6,
|
| 54 |
+
6,
|
| 55 |
+
90
|
| 56 |
+
],
|
| 57 |
+
"dtype": "f32"
|
| 58 |
+
}
|
| 59 |
+
}
|
params.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"fs": 44100,
|
| 3 |
+
"windowSize": 4096,
|
| 4 |
+
"hopSize": 1024,
|
| 5 |
+
"nMels": 229,
|
| 6 |
+
"nWindows": 6,
|
| 7 |
+
"eps": 1e-05,
|
| 8 |
+
"fMin": 30.0,
|
| 9 |
+
"fMax": 8000.0,
|
| 10 |
+
"rfftBins": 2049,
|
| 11 |
+
"segmentSizeSeconds": 16.0,
|
| 12 |
+
"segmentHopSeconds": 8.0,
|
| 13 |
+
"nSymbols": 90
|
| 14 |
+
}
|
ref3b_audio.f32
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:805fabae442dc3262a3d28fe670f541ad157d6c72d3a9ce5e9403661eca6d587
|
| 3 |
+
size 264600
|
ref3b_features.f32
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ca43f2677f53ba60d175e0c401b163be66ef70932e303c5d03e7e444c7c99620
|
| 3 |
+
size 362736
|
ref3c_S.f32
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a2cbcdcb7d1567dbf29c48d2f9cef420a1de61d8d819b4ebfc921639bc9c9a0e
|
| 3 |
+
size 1568160
|
ref3c_forced_intervals.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"forcedStartPos": [0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "intervals": {"0": [], "1": [], "2": [], "3": [], "4": [], "5": [[5, 5]], "6": [], "7": [], "8": [], "9": [], "10": [[0, 4]], "11": [], "12": [], "13": [], "14": [], "15": [], "16": [], "17": [], "18": [], "19": [], "20": [[2, 2]], "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": [], "72": [], "73": [], "74": [], "75": [], "76": [], "77": [], "78": [], "79": [], "80": [], "81": [], "82": [], "83": [], "84": [], "85": [], "86": [], "87": [], "88": [], "89": []}}
|
ref3c_intervals.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"0": [], "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": [[43, 63]], "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": [], "72": [], "73": [], "74": [], "75": [], "76": [], "77": [], "78": [], "79": [], "80": [], "81": [], "82": [], "83": [], "84": [], "85": [], "86": [], "87": [], "88": [], "89": []}
|
ref3c_syn_S.f32
ADDED
|
Binary file (13 kB). View file
|
|
|
ref3c_syn_intervals.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"0": [], "1": [], "2": [], "3": [], "4": [], "5": [[1, 3], [5, 5]], "6": [], "7": [], "8": [], "9": [], "10": [[0, 4]], "11": [], "12": [], "13": [], "14": [], "15": [], "16": [], "17": [], "18": [], "19": [], "20": [[2, 2]], "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": [], "72": [], "73": [], "74": [], "75": [], "76": [], "77": [], "78": [], "79": [], "80": [], "81": [], "82": [], "83": [], "84": [], "85": [], "86": [], "87": [], "88": [], "89": []}
|
symbols.i32
ADDED
|
Binary file (360 Bytes). View file
|
|
|
transkun-heads.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f609f53fbb4df0a2165f941aff1d5a1c1063ba40aaa699365448dca5d9f3544d
|
| 3 |
+
size 3422740
|
transkun.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6d6960ecbce5c3d51051ebc1ebdeec4d3018ea6cfd360fb1ae96359aa7a075a3
|
| 3 |
+
size 53391226
|
windows.f32
ADDED
|
Binary file (98.3 kB). View file
|
|
|