voice_audio_multi/docs/models/ace_step.md
Fabio c36510c21e
Some checks failed
Linux Build / Linux cpu (push) Has been cancelled
Linux Build / Linux cpu-clang (push) Has been cancelled
Linux Build / Linux vulkan (push) Has been cancelled
mac-build / macOS CPU (push) Has been cancelled
Nix Build / Nix (cpu) (push) Has been cancelled
Nix Build / Nix (vulkan) (push) Has been cancelled
windows-build / Windows CPU (push) Has been cancelled
Initial import: audio.cpp with Orange Pi documentation
2026-11-04 19:05:22 +01:00

23 KiB

ACE-Step

ACE-Step is wired as --family ace_step --task gen. It generates and edits music from text, lyrics, and optional source audio. The route controls whether source audio is ignored, optional, or required. Supplied audio_codes can also satisfy the source-input requirement for routes that require audio.

Common CLI shape:

audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route <route> ...

Model

Field Value
Family ace_step
Model directory models/Ace-Step1.5
Task gen
Default DiT Inferred from model filename (base, sft, turbo, and xl); otherwise acestep-v15-turbo
Optional DiT acestep-v15-base, acestep-v15-xl-turbo, acestep-v15-xl-sft
Default LM acestep-5Hz-lm-1.7B
Prompt input --text
Lyrics input --lyrics
Source audio Route-dependent through --audio

Text To Music

Generate a full song or music clip from prompt text and optional lyrics. Source audio is ignored by this route.

Field Value
Route text2music
Source audio Ignored
Planner Used unless audio_codes are supplied
Duration --duration-seconds; -1 lets the planner/model choose
Metadata controls Optional bpm, keyscale, timesignature, and language
audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route text2music --text "cinematic synth pop with clear vocals" --lyrics "We rise with the morning light" --duration-seconds 60 --out song.wav

Use the base DiT instead of turbo:

audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route text2music --text "acoustic folk ballad" --lyrics "The river remembers our names" --duration-seconds 60 --load-option ace_step.dit_model_path=acestep-v15-base --out song.wav

Complete

Complete or continue a source audio track. Source audio is optional: if provided, it conditions the continuation; otherwise the route behaves like a completion prompt.

Field Value
Route complete
Source audio Optional
Planner Used
Duration Source duration is not locked unless requested metadata or planner output controls it
Track classes Optional complete_track_classes list changes the completion instruction
audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route complete --audio input.wav --text "finish this as a cinematic rock track" --out complete.wav

Lego

Compose or transform a track from source audio plus a prompt. Source audio is required and preserved as the repaint context.

Field Value
Route lego
Source audio Required
Planner Used
Duration Locked to source audio
Repaint window Used internally over the source context
Track name Optional track_name changes the generated instruction
audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route lego --audio input.wav --text "generate a brighter guitar layer" --request-option track_name=guitar --out lego.wav

Extract

Extract a target track from source audio. Source audio is required, and the route uses extraction-specific defaults for guidance and shift.

Field Value
Route extract
Source audio Required
Planner Not used
Duration Locked to source audio
Track name Optional track_name; when omitted, the default extract instruction is used
Route defaults guidance_scale=7.0, shift=3.0, planner chain-of-thought metadata disabled
audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route extract --audio song.wav --text "extract vocals" --request-option track_name=vocals --out vocals.wav

Cover

Generate a cover from source audio using cover-tokenizer conditioning. Source audio is required and duration is locked to the source.

Field Value
Route cover
Source audio Required
Planner Not used
Cover conditioning Uses the FSQ cover tokenizer
Duration Locked to source audio
audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route cover --audio source.wav --text "turn this into energetic pop vocals" --lyrics "We keep moving through the night" --out cover.wav

Cover Without FSQ

Generate a cover from source audio without the FSQ cover-tokenizer conditioning path.

Field Value
Route cover-nofsq
Source audio Required
Planner Not used
Cover conditioning Does not use the FSQ cover tokenizer
Duration Locked to source audio
audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route cover-nofsq --audio source.wav --text "make a softer acoustic cover" --lyrics "We keep moving through the night" --out cover_nofsq.wav

Repaint

Replace a time span inside source audio. Source audio and a repaint window are required.

Field Value
Route repaint
Source audio Required
Planner Not used
Duration Locked to source audio
Required window --repaint-start, --repaint-end
Repaint policy repaint_mode, repaint_strength, or direct repaint injection/crossfade options
audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route repaint --audio song.wav --text "replace the middle with a brighter chorus" --repaint-start 20 --repaint-end 35 --out repaint.wav

Common Options (use directly)

Option Values Default Meaning
--task-route text2music, complete, lego, extract, cover, cover-nofsq, repaint text2music ACE-Step operation.
--text text required Music prompt or edit instruction.
--lyrics text empty string Vocal lyrics.
--audio WAV path route-dependent Source audio for complete/edit/extract/cover routes.
--duration-seconds float, -1 for auto -1 Target duration. Source-locked routes use source duration.
--language language code text input language, then en Vocal language for lyrics; request-map language takes precedence.
--track-name text empty string Track name used by lego and extract instructions.
--repaint-start seconds required for repaint Start time for repaint.
--repaint-end seconds required for repaint End time for repaint.
--repaint-mode balanced, conservative, aggressive unset Preset repaint blending policy; supplying strength alone selects balanced.
--repaint-strength 0..1 0.5 when a preset is supplied Strength for balanced mode; values are clamped to this range.
--num-inference-steps integer 8 Denoising steps; turbo checkpoints cap this at 8.
--guidance-scale float 1.0; 7.0 for extract unless overridden Diffusion CFG; ignored by turbo checkpoints.
--seed integer random if omitted Generation seed.

Request Options (use with --request-option)

Option Values Default Meaning
complete_track_classes track class or JSON array empty list Track classes for complete, e.g. '["vocals","guitar"]'. A plain string is one class, not a comma-separated list.
bpm integer not set Force BPM metadata; otherwise the planner chooses it when used.
keyscale text not set Force key metadata; otherwise the planner chooses it when used.
timesignature text not set Force time signature metadata; otherwise the planner chooses it when used.
negative_prompt text NO USER INPUT Negative prompt.
audio_codes ACE semantic code text not set Skip planner token generation and use supplied audio codes.
audio_cover_strength float 1.0 Cover strength for cover/edit-style conditioning.
cover_noise_strength float 0.0 Noise strength for cover conditioning.
lm_temperature float 0.85 Planner sampling temperature.
lm_guidance_scale float 2.0 Planner CFG scale. Legacy lm_cfg_scale remains accepted.
duration_sec float -1.0 Target duration; non-positive leaves selection to the planner. Legacy duration_seconds remains accepted.
enable_thinking bool true Enable planner thinking when supported by the checkpoint. Legacy thinking remains accepted.
lm_top_k integer 0 Planner top-k; 0 disables top-k.
lm_top_p float 0.9 Planner top-p.
lm_repetition_penalty float 1.0 Planner repetition penalty.
sampler_mode euler, heun euler Diffusion sampler mode.
shift float 1.0; 3.0 for extract unless overridden Diffusion timestep schedule shift.
retake_seed integer, -1 to clear not set Optional retake noise seed.
retake_variance float 0.0 Retake noise mixing strength.
flow_edit_morph bool false Status: parsed for text2music, but not usable because the flow-edit diffusion overlay is not implemented.
dcw_enabled bool false Status: experimental dynamic-cfg wavelet path. Keep disabled unless validating that path.

Session Options (use with --session-option)

Option Values Default Meaning
ace_step.lora adapter path none DiT decoder adapter file or PEFT directory; merged during weight loading.
ace_step.lora_scale finite float 1.0 Adapter strength multiplied by metadata scaling; zero disables it.
ace_step.weight_type native, f32, f16, bf16, q8_0 native Shared weight storage type.
ace_step.dit_weight_type same as above inherits ace_step.weight_type DiT override; f16 is promoted to bf16.
ace_step.dit_attention auto, eager, flash auto DiT attention implementation. Auto selects flash on supported GPUs and eager on CPU.
ace_step.planner_weight_type same as above inherits ace_step.weight_type Planner LM override.
ace_step.planner_prefix_bucketing bool true Bucket planner CFG attention to the valid prefix. Set false for full-capacity attention; other optimizations remain enabled.
ace_step.planner_fused_projections bool false; true in cuda_perf CUDA packed QKV and gate/up projections with fused SwiGLU. Can change generated codes.
ace_step.planner_f16_decode bool false; true in cuda_perf CUDA F16 KV and prefix-bucketed decoding for metadata and CFG-off codes. CFG-on code decoding already uses F16 KV. Can change generated codes.
ace_step.planner_independent_cfg_prefill bool false; true in cuda_perf Prefill CUDA CFG branches at their actual lengths instead of left-padding them to a shared length. Can change generated codes.
ace_step.text_encoder_weight_type same as above inherits ace_step.weight_type Text encoder override.
ace_step.vae_weight_type same as above inherits ace_step.weight_type VAE override.
ace_step.perf_mode off, cuda_perf off cuda_perf enables the three CUDA planner options above and selects VAE tiles of 1024 latent frames with 64-frame overlap per side. Explicit options override the preset.
ace_step.vae_tile_frames positive integer backend policy Maximum latent frames evaluated per VAE tile. cuda_perf sets 1024.
ace_step.vae_tile_overlap_frames non-negative integer backend policy Context per side, in latent frames; must be less than half the tile capacity. cuda_perf sets 64.
ace_step.mem_saver bool false Release staged graph/cache state after request phases to reduce resident VRAM. Later requests may rebuild released graphs.

DiT Performance

Static conditioning, attention masks and cross-attention K/V stay resident during a diffusion pass and refresh when conditioning changes. They are not rebuilt and uploaded at every solver step.

ace_step.dit_attention=auto uses flash attention on supported GPUs and eager attention on CPU. Set it to eager to retain the previous attention lowering. Flash preserves the model's full/sliding masks and F32 accumulation, but can change floating-point results. This option does not convert model weights.

Planner Performance

Planner decoding reads K/V cache views directly. CFG decoding stores K/V in F16 and reuses cached graphs sized to the valid prefix, rounded up to 256 steps. The complete history remains visible; this is not sliding-window attention. Model weights are not converted by these optimizations. Different cache precision or attention shapes can change sampled output at a fixed seed. Disable prefix bucketing with --session-option ace_step.planner_prefix_bucketing=false.

The default leaves projection packing, F16 metadata/CFG-off decoding and independent CFG prefill disabled. Enable them individually with the planner options above, or together with ace_step.perf_mode=cuda_perf. These change floating-point execution and can produce different generated codes and WAVs, even at the same seed. Explicit false values override the preset. The preset does not change planner weight precision; ace_step.planner_weight_type remains a separate explicit choice.

Each planner control works independently; enabling one does not enable the others. Independent CFG prefill is ignored when planner CFG is off. Requests can switch CFG on/off within one session; their prefill precision and decode batch-size graphs are cached separately.

Prefill/decode graphs are session-owned and reused when mem_saver=false. This avoids rebuilding them on later requests but retains their GPU memory.

VAE Performance

The Snake activation uses a broadcast graph that allows existing CUDA fusion, without changing weight precision. This fix is independent of perf_mode.

With perf_mode=off and no tile overrides, tiling is unchanged: long GPU requests use 128-frame tiles with 32-frame overlap per side (stride 64), and long CPU requests use 256/64. Requests up to 512 latent frames on GPU or 256 on CPU retain the existing single-graph decode path.

For larger tiles, add:

--session-option ace_step.perf_mode=cuda_perf

This selects 1024/64 and enables the CUDA planner optimizations described above, without changing weight precision or DiT attention selection. Larger tiles reduce redundant overlap computation but use more peak VRAM and can change floating-point results. The preset does not select a backend; use --backend separately.

Explicit values override the preset, for example to retain the smaller tiles:

--session-option ace_step.perf_mode=cuda_perf \
--session-option ace_step.vae_tile_frames=128 \
--session-option ace_step.vae_tile_overlap_frames=32

An explicit tile capacity also applies to short requests. If only the tile capacity is set in off mode, overlap is derived from the existing 64-frame policy, reduced to fit the tile. Explicit overlap is never silently reduced: 2 * overlap < tile_frames must hold. When reducing the preset's tile size, override its overlap too if necessary.

Weight Adapters

DiT LoRA/LoKr adapters can be selected with --session-option ace_step.lora=/path/to/adapter. PEFT directories use adapter_model.safetensors and adapter_config.json; SafeTensors files may use native A/B, ComfyUI up/down, or ordinary matrix LoKr factors. Only decoder targets are adapted; the planner, conditioning encoders, and VAE remain unchanged. Paths relative to the model root are accepted. Adapter changes require a new session. Merging a quantized base dequantizes and requantizes the adapted weights; it is not equivalent to adapting the original full-precision checkpoint first.

Load Options (use with --load-option)

Option Values Default Meaning
ace_step.dit_model_path acestep-v15-turbo, acestep-v15-base, acestep-v15-xl-turbo, acestep-v15-xl-sft filename-derived; otherwise acestep-v15-turbo Override DiT variant selection inside the model root.

Spec Scope And Compatibility

The spec lists generation, musical metadata, planner, editing, retake, and semantic-code controls, plus weight storage, memory saving, and DiT selection. Request names are unprefixed; session and load names use ace_step. in CLI/server configuration. Prompt text and source audio remain structured inputs.

The following legacy names remain accepted:

Scope Canonical Legacy
Request duration_sec duration_seconds
Request lm_guidance_scale lm_cfg_scale
Request enable_thinking thinking
Request audio_codes audio_code_string
Session ace_step.mem_saver mem_saver

The shared parser rejects conflicting values supplied under both spellings. audio_codes is the existing exception: it takes precedence over audio_code_string.

Older standalone GGUFs do not need re-emission or a local spec override to use these controls: ACE-Step parses them directly, without an embedded-spec option whitelist. The spec expansion does not introduce stricter runtime validation.

To keep the embedded spec compact, it omits debug noise inputs, graph arenas, individual planner CoT switches, low-level velocity/repaint tuning, experimental dcw_*, and the unimplemented flow_edit_morph path. Existing runtime support for omitted controls is unchanged. Repaint preset fields have no spec default because supplying a preset changes behavior compared with leaving both unset.

ACE-Step GGUF packages are variant-specific. The model filename selects the DiT variant by default. Use --load-option ace_step.dit_model_path=<variant> when the filename does not identify the packaged variant.

XL variants

acestep-v15-xl-turbo and acestep-v15-xl-sft are the larger DiT: 32 layers of 2560 against turbo's 24 of 2048, with 32 attention heads of 128 (so the attention width is 4096, wider than the model). The condition encoder, audio tokenizer and detokenizer stay at 2048 — the encoder_hidden_size group in the XL config — and the DiT's condition embedder bridges the two. The XL timbre encoder also prepends a CLS token to the reference frames and reads that position back, where earlier variants read the first audio frame.

Both are optional package resources: they are only loadable when their weights are present, and a package without them loads and runs exactly as before. Selecting one that is not installed reports which directory is missing. The upstream snapshots ship four safetensors shards plus a model.safetensors.index.json, which the package spec points at directly.

The two differ only in is_turbo: XL Turbo is guidance-distilled and ignores guidance_scale, XL SFT takes the CFG path the way acestep-v15-base does. Their dimensions, encoder group and head configuration are identical.

ace_step_xl_turbo_bf16 and ace_step_xl_sft_bf16 install them as GGUFs (14.2 GiB each), self-contained the way the Turbo and Base GGUFs are — XL DiT, planner LM, text encoder and VAE in one file. ace_step_xl_turbo_q8dit and ace_step_xl_sft_q8dit are the same packages with the DiT at q8_0 and the planner LM, text encoder and VAE left at bf16 (9.97 GiB); see the measurements at the end of this section for what that costs:

audiocpp_cli --task gen --family ace_step --model models/ACE-Step1.5-GGUF/xl-turbo --backend cuda --task-route text2music --text "warm lo-fi hip hop with a soft rhodes piano" --duration-seconds 60 --load-option ace_step.dit_model_path=acestep-v15-xl-turbo --out song.wav

Running one from a safetensors tree instead is worth a dit_weight_type=bf16, because the XL snapshots are stored in float32 and native puts 19.9 GB of weights on the card:

audiocpp_cli --task gen --family ace_step --model models/Ace-Step1.5 --backend cuda --task-route text2music --text "warm lo-fi hip hop with a soft rhodes piano" --duration-seconds 60 --load-option ace_step.dit_model_path=acestep-v15-xl-sft --session-option ace_step.dit_weight_type=bf16 --out song.wav

Measured on an RTX 5090, 20 s of audio, weight loading included and the weights warm in the page cache: 87 s from safetensors at native, 25 s from safetensors at bf16, 15 s from the bf16 GGUF, both variants alike (turbo, for reference: 11 s). Reading the weights off disk adds roughly 10 s either way.

Building an XL GGUF yourself still names every namespace the spec requires, because audiocpp_gguf validates the conversion against all of them — but the turbo and base entries only have to exist. --exclude-prefix drops their tensors before any data is read, so a 76-byte placeholder stands in for the 9 GB of weights that would otherwise be downloaded and thrown away:

python -c "import json,struct; h=json.dumps({'x':{'dtype':'F32','shape':[1,1],'data_offsets':[0,4]}}).encode(); h+=b' '*((8-len(h)%8)%8); open('placeholder.safetensors','wb').write(struct.pack('<Q',len(h))+h+bytes(4))"
audiocpp_gguf --root models/Ace-Step1.5 --family ace_step \
  --input dit_turbo_weights=placeholder.safetensors \
  --input dit_turbo_silence_latent=placeholder.safetensors \
  --input dit_base_weights=placeholder.safetensors \
  --input dit_base_silence_latent=placeholder.safetensors \
  --input dit_xl_turbo_weights=models/Ace-Step1.5/acestep-v15-xl-turbo/model.safetensors.index.json \
  --input dit_xl_turbo_silence_latent=models/Ace-Step1.5/acestep-v15-xl-turbo/silence_latent.safetensors \
  --input lm_weights=models/Ace-Step1.5/acestep-5Hz-lm-1.7B/model.safetensors \
  --input text_encoder_weights=models/Ace-Step1.5/Qwen3-Embedding-0.6B/model.safetensors \
  --input vae_weights=models/Ace-Step1.5/vae/diffusion_pytorch_model.safetensors \
  --exclude-prefix dit_turbo_ --exclude-prefix dit_base_ \
  --type bf16 --output ace-step-1.5-xl-turbo-bf16.gguf

Swap dit_xl_turbo_* for dit_xl_sft_* to build the SFT one. Upstream ships silence_latent.pt where the spec wants safetensors; tests/ace_step/convert_silence_latent.py --input <variant>/silence_latent.pt converts it. Of the turbo and base snapshots only config.json is genuinely needed — those are required sidecars, a few KB each.

ace_step is graded No (planner sampling can fail) for q8_0 in gguf.md, and that grade is about the planner LM, not the DiT: at a fixed seed a fully quantised build samples a different token path and returns an unrelated song. Quantising the DiT alone keeps the planner exact, which --keep-type expresses:

  --keep-type "lm_weights*=bf16" \
  --keep-type "text_encoder_weights*=bf16" \
  --keep-type "vae_weights*=bf16" \
  --keep-type "dit_xl_turbo_silence_latent*=bf16" \
  --type q8_0 --output ace-step-1.5-xl-turbo-q8dit.gguf

Measured on an RTX 5090 against the bf16 build at the same seed and prompt, 20 s of audio: 9.97 GiB against 14.2 GiB and 9.3 s against 14.2 s, with a 0.989 waveform correlation against the bf16 output — 0.997 on a sung 40 s take, 0.999 for XL SFT. A fully quantised build of the same weights correlates 0.09, and its ASR transcript is a different lyric line.

Re-quantising a finished GGUF works too, since a GGUF input carries its own namespaces, package spec and sidecars:

audiocpp_gguf --input ace-step-1.5-xl-turbo-bf16.gguf --type q8_0 \
  --keep-type "lm_weights*=bf16" --output ace-step-1.5-xl-turbo-q8dit.gguf