-
snac24_int2wav_static.onnx — int → wav decoder
Inputs (int64):
codes0: [1, 12]
codes1: [1, 24]
codes2: [1, 48]
Output:
audio: float32 [1, 1, 24576] (24 kHz)
Shapes correspond to a 48-frame window. Each frame is 512 samples, so one window = 24576 samples ≈ 1.024 s at 24 kHz.
Token alignment: L0*4 = L1*2 = L2*1 = shared_frames.
-
snac24_latent2wav_static.onnx — latent → wav decoder
Input: z float32 [1, 768, 48] → Output: audio [1, 1, 24576]
Use this if you reconstruct the latent yourself (RVQ embeddings + 1×1 conv projections).
-
snac24_codes.json — sample codes (for testing)
-
snac24_quantizers.json — RVQ metadata/weights (stride + embeddings + 1×1 projections) to reconstruct z if needed.
Serve these files from a local server with cross-origin isolation for multithreaded WASM (e.g., COOP/COEP headers). If not isolated, WASM will typically run single-threaded.
1<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
2<script>
3(async () => {
4 // Prefer WebGPU if available; else WASM
5 const providers = (typeof navigator.gpu !== 'undefined') ? ['webgpu','wasm'] : ['wasm'];
6 // Enable SIMD; threads only if crossOriginIsolated
7 ort.env.wasm.simd = true;
8 ort.env.wasm.numThreads = crossOriginIsolated ? (navigator.hardwareConcurrency||4) : 1;
9
10 const session = await ort.InferenceSession.create('snac24_int2wav_static.onnx', {
11 executionProviders: providers,
12 graphOptimizationLevel: 'all',
13 });
14
15 // Example: one 48-frame window (12/24/48 tokens). Replace with real codes.
16 const T0=12, T1=24, T2=48;
17 const feed = {
18 codes0: new ort.Tensor('int64', BigInt64Array.from(new Array(T0).fill(0), x=>BigInt(x)), [1,T0]),
19 codes1: new ort.Tensor('int64', BigInt64Array.from(new Array(T1).fill(0), x=>BigInt(x)), [1,T1]),
20 codes2: new ort.Tensor('int64', BigInt64Array.from(new Array(T2).fill(0), x=>BigInt(x)), [1,T2]),
21 };
22
23 const t0 = performance.now();
24 const out = await session.run(feed);
25 const t1 = performance.now();
26 const audio = out.audio.data; // Float32Array [1,1,24576]
27
28 // Play it (24 kHz)
29 const ctx = new (window.AudioContext||window.webkitAudioContext)({sampleRate:24000});
30 const buf = ctx.createBuffer(1, audio.length, 24000);
31 buf.copyToChannel(audio, 0);
32 const src = ctx.createBufferSource(); src.buffer = buf; src.connect(ctx.destination); src.start();
33
34 console.log({ usedEP: providers[0], infer_ms: (t1-t0).toFixed(2), samples: audio.length });
35})();
36</script>
37Streaming note
38
39SNAC is streamable in principle. For practical low-latency TTS, emit ~200 ms of tokens, decode in ~100 ms,
40start playback, and continue decoding subsequent chunks; cross-fade a few ms to hide seams.
41
42Threads / GPU
43
44Multithreaded WASM requires cross-origin isolation (COOP/COEP). Without it, browsers typically run single-threaded.
45
46WebGPU can accelerate on desktop and mobile when kernels are supported; this model usually falls back to WASM if not.