Refine (48 kHz)
Refine (48 kHz) invents the top octave — and tells you exactly what it invented
- audio
- model
- audio
- report
Refine (48 kHz) is audio super-resolution with an escape hatch. It brings your render to 48 kHz and - if you give it a model - extends the top octaves that aren't there. Same mental model as an image upscaler: it adds plausible high frequencies, it cannot recover what was never recorded, and the pack is honest about which of those two happened.
Where it sits
Render ─► Refine (48 kHz) ─► Plenio · Master ─► Export Release
In the Plenio templates it's a two-node block (this node plus Load Audio Model) that is on by default in the MiniMax template and bypassed in the YuE2 ones - YuE2 already decodes at 48 kHz, so there's nothing to rescue. Switch it on anywhere by selecting the block and hitting Ctrl+B. The other place it earns its keep is the 4 · Enhance & Master template, on material you didn't generate: old MP3s, phone recordings, YouTube rips. That whole template runs on the CPU except for this stage.
How the mechanism actually works
Six steps, and the order matters more than the model does:
- Measure the input's bandwidth - the highest frequency within 60 dB of the 1–4 kHz level. That's what decides the default crossover.
- Condition what the model sees (PRE): a steep low-pass, then a resample to the model's rate. PRE never touches the band you keep.
- Run the model chunk by chunk - 5 s chunks with 0.5 s overlap, Hann-weighted overlap-add, one derived seed per chunk.
- Join original and model with a complementary crossover:
LP(original) + HP(model). The two filters sum to a pure delay, so below the crossover the output is your original sample for sample. - Optional POST roll-off (linear phase) to tame harsh added air.
- Contract: 48 kHz, exactly the input's duration, no normalisation.
The report output names the engine, the parameters, and the bandwidth before and after - so "it ran but did nothing audible" is a claim you can check rather than guess.
The resample only engine is a Kaiser band-edge resampler with a ≥100 dB stop band: no model, no new content, bit-exact level. The model engine is UniverSR (229 MB, models/audio_sr) - vocoder-free flow matching on complex STFT coefficients, four ODE steps, feeding 8/12/16/24 kHz conditions up to 48 kHz. It's mono inside: each channel is enhanced on its own, so your stereo image is untouched.
The inputs you'll actually touch
engine is the first decision and it's not a hidden fallback - it's a visible combo. Set model with no model wired in and the node stops with a message telling you what to connect, which beats the classic audio-node move of quietly degrading.
Then preset, which sets PRE, POST and the crossover in one shot - the crossover always sits 500 Hz below PRE, so the model's transition band never lands where you're keeping original content.
| Preset | PRE | Crossover | POST | |---|---|---|---| | 1 | 6 kHz | 5.5 kHz | 16 kHz | | 2 | 8 kHz | 7.5 kHz | 19 kHz | | 3 - MiniMax | 10 kHz | 9.5 kHz | 19 kHz | | 4 | 12 kHz | 11.5 kHz | 19 kHz | | 5 | 14 kHz | 13.5 kHz | 21 kHz |
3 · MiniMax · Song ships preset 3 and the matching numbers in the pre_hz / crossover_hz / post_hz fields, so flipping to custom doesn't change the sound. sr_gain is the level of the added band - back it off if the air turns glassy. crossover_hz at 0 means "500 Hz below the measured edge".
Two defaults worth not fighting: pre_hz 0 means use the model's own training condition - the good choice, leave it - and seed ships as fixed, not randomize. Same seed, same result, and ComfyUI reuses the refined audio when nothing upstream changed. Randomize only to compare takes deliberately.
Outputs are audio (48 kHz, same duration → Plenio · Master) and report (engine, parameters, bandwidth before/after).
Installing it
Install the pack first - Manager → search Plenio Music Production System, or:
cd ComfyUI/custom_nodes
git clone https://github.com/jplenio/Plenio-Music-Production-System
Plenio installs no Python packages; the UniverSR inference code is vendored in the repo. The only thing you add for this node is the 229 MB pytorch_model.bin in ComfyUI/models/audio_sr - ComfyUI's missing-model dialog offers it when you open the MiniMax template. resample only needs nothing.
Where people get burned
The model always runs when it's connected. On an input that already reaches 20 kHz, you still pay the compute - the report will tell you that only the content above the crossover changed. Nothing below it moves, so it's safe, just not free.
It's the slowest stage in the chain. On a 16 GB card expect roughly real-time to a few times faster than real-time with UniverSR. If a 5-minute song feels like it's hanging, it isn't.
Peaks rise, and Refine doesn't care. There is no loudness or peak management here, on purpose. Keep Plenio · Master after it, or you'll clip on export.
It's marked experimental, and that's not false modesty. The guarantees are tested; the defaults are provisional until the owner's listening verdict (study L1) lands. On the two real takes measured so far, both counted as full-band: the model ran and changed nothing below the crossover. You lost some minutes and nothing else - a better failure mode than a pack that guessed.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| audio | AUDIO | The rendered song (any sample rate). | |
| engine | COMBO | resample only | model: the connected Load Audio Model (super-resolution); resample only: no model. |
| crossover_hz | FLOAT | 00–23000 | Where the model takes over; 0: 500 Hz below the measured bandwidth. |
| sr_gain | FLOAT | 1.000–2 | Level of what the model adds above the crossover: 1 as the model made it, 0 none (the original only), up to 2. |
| modelopt | PLENIO_AUDIO_MODEL | Load Audio Model (super-resolution); only for 'model'. | |
| presetopt | COMBO | custom - the three fields below | A prepared stage template: one choice sets PRE, POST and the crossover (500 Hz below PRE); template 3 suits MiniMax renders. *custom* uses the three fields below, which stay editable. |
| pre_hzopt | FLOAT | 0-1–23000 | Low-pass before the model (it shapes only what the model sees): 0 = the model's training condition, -1 = no PRE, else Hz (6000, 8000, 10000, 12000, 14000). |
| post_hzopt | FLOAT | 00–23900 | Linear-phase roll-off of the result: 0 = off, else Hz (16000, 19000, 21000 tame added air that sounds harsh). |
| seedopt | INT | 00–4294967295 | Seed of the model: the same seed gives the same result. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | 48 kHz, same duration. |
| report | PLENIO_REPORT | Engine, parameters, bandwidth before/after. |