Foundation-1 KSampler
The BPM-aware KSampler that finally makes your Foundation-1 loops the right length
- model
- positive
- negative
- latent_audio
- LATENT
The first time you generate audio with Foundation-1 you learn the hard way that the model thinks in seconds while everyone else thinks in bars and BPM. Ask for 8 bars at 120 BPM, feed it a latent built for something else, and the generation comes back wonky - the model's own creator has said exactly that. Foundation-1 KSampler exists to make the length problem disappear: it's a wrapper around ComfyUI's stock KSampler that sizes the audio latent from your BPM and bars, stamps the duration into the conditioning, and hands the result to the sampler you already know.
The whole pack is Aero-Ex's lightweight take on running Foundation-1 - RoyalCities' text-to-sample music model, itself a finetune of Stable Audio 1.0. Where other ports pull in the model's bundled stable-audio-tools inference code (old dependencies, monkey-patching required), this node just reuses core ComfyUI. Fewer moving parts, same output.
How it works
Two paths, both ending in the same core KSampler.sample() call:
- Fresh generation (no
latent_audio): it computesseconds = (60/bpm) × 4 × bars, then allocates an empty audio latent on the intermediate device with shape[1, 64, length], wherelength = round(seconds × 44100 / 2048 / 2) × 2. That 2048 is Stable Audio's VAE hop - 44.1 kHz audio, one latent frame per 2048 samples - so the buffer's duration matches your BPM/bars exactly. - Audio-to-audio (
latent_audiowired in fromLoadAudio → VAEEncodeAudio): it reads the duration straight off the incoming latent (length × 2048 / 44100) instead of trusting bpm/bars. This is the remix/style-transfer path, anddenoiseis your intensity knob - the pack's example workflow runs this at 0.5.
Either way it then injects seconds_start: 0.0 and seconds_total: <seconds> into both positive and negative conditioning. That stamping is the bit that's "critical for Foundation-1/Stable Audio" per the source - it's how the model knows how long the generation is supposed to be. Then everything else is plain KSampler.
The inputs
Mostly familiar faces, since it's a pass-through: model (from CheckpointLoaderSimple), positive/negative (CONDITIONING from CLIPTextEncode), seed, steps (50), cfg (5.0), sampler_name, scheduler, denoise (1.0). The new ones:
- bpm (1–500) and bars (1–128) - used to size the latent when you're generating from scratch. Defaults 120 and 8. Keep them consistent with whatever your prompt claims.
- latent_audio (optional LATENT) - the only optional input. Leave it unplugged for text-to-audio; plug in a VAE-encoded clip for remixing.
Output is a LATENT, not an AUDIO - remember VAEDecodeAudio before SaveAudio, or you'll stare at a tensor while your ears hear nothing.
Installing it
Via ComfyUI Manager (search "Foundation1"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/Aero-Ex/ComfyUI-Foundation1
Then restart and restart again after grabbing the model files the README demands: Foundation_1.safetensors into models/checkpoints/ and t5-base.safetensors into models/text_encoders/. In the graph, load the T5 with a CLIPLoader set to the stable_audio type - that's the ComfyUI-native way to get conditioning for this model family.
Common issues
- Silent or wrong-length output: nine times out of ten the prompt's BPM/bars and the sampler's bpm/bars disagree, or the incoming
latent_audiois wildly shorter than what the prompt implies. RoyalCities warned that feeding a few seconds of audio against a "4 bars @ 120 BPM" prompt gets wonky - this node fixes the latent side, but it can't fix a prompt lying about the duration. - Load errors before you even sample: a missing
t5-base.safetensorsor the wrong CLIPLoader type will fail at conditioning time. Check both model folders first. - Expecting audio out of the sampler itself: the output is a latent; chain
VAEDecodeAudio→SaveAudio.
It's a thin node - essentially core KSampler with a BPM-sized latent and correct duration conditioning bolted on. But that thinness is the point: it's the difference between fighting Stable Audio's quirks and just sampling.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| seed | INT | 00–18446744073709550000 | — |
| steps | INT | 501–10000 | — |
| cfg | FLOAT | 5.00–100 | — |
| sampler_name | COMBO | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 | |
| scheduler | COMBO | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 | |
| positive | CONDITIONING | — | |
| negative | CONDITIONING | — | |
| denoise | FLOAT | 1.000–1 | — |
| bpm | INT | 1201–500 | — |
| bars | INT | 81–128 | — |
| latent_audioopt | LATENT | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | — |