Qwen3-TTS Tokenizer 12 Hz (decoder)
Qwen3-TTS's own 12.5 Hz speech tokenizer, decode half, exported for loom.cpp. Family 11: codec tokens in, a 24 kHz waveform out -- and the family's first leaf with a transformer in it.
This is a loom.cpp export: a single self-describing GGUF that carries its own graph topologies, tokenizer (if any) and driver script, produced by loom-exporter.
Original model
Exported from Qwen/Qwen3-TTS-12Hz-0.6B-Base. Weights are unmodified; this repo packages the same parameters into
loom.cpp's GGUF format.
License
apache-2.0, inherited from the base model above.
Language(s)
(none tagged upstream)
a codec, not a language model: it carries no vocabulary and no language. The licence is the talker repo's, since this ships inside it.
Usage
Run it with loom-py -- loom-py-rt on PyPI:
pip install -U "loom-py-rt[hub]"
import loom
model = loom.Model.from_pretrained("loom-ai-org/qwen3-tts-tokenizer-12hz-loom")
# The geometry a caller needs, declared by the file rather than looked up in a paper:
n_codebooks = model.hparam("codec.n_codebooks") # code streams per frame
codebook_size = model.hparam("codec.codebook_size") # valid id range per stream
frame_rate = model.hparam("codec.frame_rate", "f32") # codes per second
print(n_codebooks, codebook_size, frame_rate, model.contract["sample_rate"])
# Codes are FRAME-MAJOR: all `n_codebooks` codes for frame 0, then frame 1, and so on. This file
# is the DECODE half -- real codes come from the matching encoder, or an AR model that emits them.
frames = round(frame_rate) # one second of audio
codes = [[0] * n_codebooks for _ in range(frames)]
audio = model.codes2speech.infer(codes)
print(len(audio), "samples at", audio.sample_rate, "Hz =", round(audio.duration, 3), "s")
audio.save("out.wav")
# A flat list works too, and is what a driver that emitted the codes hands over. One that is not a
# whole number of frames is refused rather than reinterpreted at a different width.
audio = model.codes2speech.infer([0] * (frames * n_codebooks))
The layer underneath
The call above is the high-level door: one per task, named for the modality pair it maps between, with
the windowing, sampling and assembly this model needs already applied. Under it, model.infer(...)
passes your arguments straight to the driver this GGUF embeds -- which is where you go for a knob the
door does not name.
model.driver_source prints that driver, including a header comment documenting every argument it
accepts for this model, and is the authority on it. See loom-py for the API and
loom.cpp for what the engine does between the two.
Known limitations
This is the DECODE half only, like every codec in this collection: encode is audio-in/codes-out, a different contract, and no model that decodes through this codec ever calls it.
It decodes in CHUNKS, because its reference does. chunked_decode(chunk_size=300, left_context_size=25) is what Qwen's own decode calls, so past 300 frames -- 24 seconds -- the model's answer is a sequence of bounded calls. Measured on real codes, a whole-sequence pass is bit-identical to the chunked one through 299 frames and then parts company: 1.1% relative RMS at 301 and 8.9% at 700. Matching it is also what keeps this runnable: the decoder attends over the frame axis, so one long call at a 4096-frame ceiling would build a 4096x4096 score matrix in each of 8 layers.
Feed it 16 codes per frame, frame-major, in codebook order. The talker that produces them is qwen3-tts-12hz-0.6b-loom; both files declare codec.n_codebooks, so a mismatched pair says so rather than producing audio of the wrong duration.
Files
qwen3-tts-tokenizer-12hz.gguf-- the model, exported with loom-exporter.