Nodes/Nova Audio Player/Madow Inputs 🎚️
ComfyUI Node

Madow Inputs 🎚️

Every ACE-Step dial in one node β€” and a record of exactly what ran

By NovaFemmeΒ·Created 6 days agoΒ·Updated about 21 hours agoΒ· 0
Madow Inputs 🎚️
    • madow
    • file_path
    • context
    • validation
    β—„apg_eta0.45β–Ί
    β—„apg_norm_threshold4.00β–Ί
    β—„apg_momentum0.20β–Ί
    β—„sched_shift3.00β–Ί
    β—„ksampler_steps80β–Ί
    β—„ksampler_cfg2.80β–Ί
    β—„ksampler_sampler_nameer_sdeβ–Ί
    β—„ksampler_schedulerlinear_quadraticβ–Ί
    β—„ksampler_denoise1.00β–Ί
    β—„ksampler_seed0β–Ί
    β—„caption_promptβ–Ί
    β—„caption_lyricsβ–Ί
    β—„music_bpm120β–Ί
    β—„music_duration120.0β–Ί
    β—„music_timesignature4β–Ί
    β—„music_languageenβ–Ί
    β—„music_keyscaleE minorβ–Ί
    β—„text_cfg_scale2.00β–Ί
    β—„lm_temperature0.72β–Ί
    β—„lm_top_p0.90β–Ί
    β—„lm_top_k0β–Ί
    β—„lm_min_p0.00β–Ί
    β—„lm_generate_audio_codestrueβ–Ί
    β—„file_prefixβ–Ί
    β—„file_nameβ–Ί
    β—„file_folderβ–Ί
    β—„file_separator_β–Ί
    β—„preset_nameβ–Ί
    β—„latent_seconds0.00β–Ί

    You're three renders into an ACE-Step session and you've already lost track of which cfg, which seed, which lyrics produced the take you actually liked. That's the exact problem Madow Inputs exists to kill. It's the parameter-hub node from NovaFemme's Nova Audio Player pack: every ACE-Step generation parameter in one node, with named presets, warn-only validation, and a context output that records precisely what produced a take.

    Here's the context that makes it click. ACE-Step is the open local music model - genuinely good instrumentals on a modest card, weak vocals, the thing the community treats as the local Suno. But running it in ComfyUI means babysitting a whole constellation: a sampler, a text encoder, an empty-latent node, an APG sampler node, a sampling-model helper. Parameters that belong together live apart, and nothing downstream knows what actually ran. Madow Inputs collects the loose change: 27 parameters, namespaced so the two cfg-shaped ones can't collide - ksampler.cfg (the sampler's) versus text.cfg_scale (the text encoder's).

    How it works

    The widgets are grouped on the node - APG, Sampler, Text, File - but the clever part is what the node emits beyond the values. Four outputs: madow, file_path, context, and validation.

    The one you'll care about if you're logging runs is context. It's a JSON-ish blob carrying the exact parameters, plus two SHA-256 hashes: one seed-excluded (groups runs that differ only by seed - that's your seed-noise-floor question answered from a log) and one seed-included (did I already run this exact config?). The naming fields are deliberately kept out of both hashes, so renaming a file never splits identical renders into different groups. Wire context into the Nova Player node's optional context input and every measured take records what produced it. That's the whole point of the pack: listen to a generation and know, not guess, what made it.

    Presets load as one JSON file each from presets/, so they're shareable and hand-editable. Loading one writes the real widgets - the backend never substitutes values, which means a saved workflow records what actually ran, not a preset name. validation is a text output of cross-field checks that warn rather than block: a caption saying "98 BPM" against a bpm widget of 122, vocals without lyrics, a duration that disagrees with the latent you wired in, apg.eta above 1. Warnings also print to your console, because a conflict you don't see on the node body is a conflict that costs a render.

    The inputs that matter

    You will not touch all 27. The ones a beginner actually sets:

    • caption_prompt and caption_lyrics - multiline text; the actual song spec.
    • music_bpm, music_duration, music_timesignature, music_language, music_keyscale - the musical frame. The last three are ACE-Step's own combo domains, read live from ACE-Step's text-encode node when it's installed, so they connect without coercion.
    • ksampler_steps, ksampler_cfg, ksampler_seed, ksampler_sampler_name, ksampler_scheduler - the generation core, defaults already sensible for ACE-Step (er_sde, linear_quadratic, 80 steps, cfg 2.8).
    • The optional latent_seconds input: wire in EmptyAceStepLatentAudio's seconds here and Madow checks it against music_duration for you.

    The APG group (apg_eta, apg_norm_threshold, apg_momentum) belongs to the APG sampler node and shift to the sampling-model helper - leave them at defaults until you know why you're changing them. One aside: the player's "APG meter" is a different APG entirely (it measures artifacts). Same acronym, zero relationship, and yes, that's confusing.

    Install

    It's part of ComfyUI-NovaAudioPlayer, so you get the whole pack. ComfyUI Manager β†’ search "Nova Audio", or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/NovaFemme/ComfyUI-NovaAudioPlayer.git
    

    Then restart ComfyUI. No extra Python dependencies - nothing beyond what ComfyUI ships (scipy is only used for accurate LUFS in the player and degrades gracefully if missing). You do need the ACE-Step custom nodes installed for the actual music generation; this node is the control panel, not the engine.

    Where people trip

    The big one: this node doesn't generate anything. If you grab it without ACE-Step wired up, you get a very tidy dashboard and silence. Also worth knowing - the time-signature/language/key-scale dropdowns fall back to fixed lists when ACE-Step's encode node isn't present, which is fine until you try to connect them to nothing. And the hashes and presets only pay for themselves if you actually log context through the player or your own logger. Use it alone as a tidy parameter panel if you like; just know the provenance machinery is the headline, and it needs a downstream log to earn its keep.

    Category▢️ Nova Audio

    Inputs (29)

    NameTypeDefaultDescription
    apg_etaFLOAT0.45-10–10β€”
    apg_norm_thresholdFLOAT4.000–100β€”
    apg_momentumFLOAT0.20-5–5β€”
    sched_shiftFLOAT3.000–100β€”
    ksampler_stepsINT801–10000β€”
    ksampler_cfgFLOAT2.800–100β€”
    ksampler_sampler_nameCOMBOer_sde44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
    ksampler_schedulerCOMBOlinear_quadratic9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
    ksampler_denoiseFLOAT1.000–1β€”
    ksampler_seedINT00–18446744073709550000β€”
    caption_promptSTRINGβ€”
    caption_lyricsSTRINGβ€”
    music_bpmINT1201–400β€”
    music_durationFLOAT120.01–3600β€”
    music_timesignatureCOMBO44 options: 2, 3, 4, 6
    music_languageCOMBOen23 options: en, ja, zh, es, de, fr, +17
    music_keyscaleCOMBOE minor34 options: C major, C# major, Db major, D major, D# major, Eb major, +28
    text_cfg_scaleFLOAT2.000–100β€”
    lm_temperatureFLOAT0.720–10β€”
    lm_top_pFLOAT0.900–1β€”
    lm_top_kINT00–10000β€”
    lm_min_pFLOAT0.000–1β€”
    lm_generate_audio_codesBOOLEANtrueβ€”
    file_prefixSTRINGβ€”
    file_nameSTRINGβ€”
    file_folderSTRINGβ€”
    file_separatorSTRING_β€”
    preset_nameoptSTRINGSet by the preset bar. Recorded in context so a run can be traced to the preset it came from; never used to supply values.
    latent_secondsoptFLOAT0.000–3600Optional. Wire EmptyAceStepLatentAudio's seconds here to check it against duration.

    Outputs (4)

    NameTypeDescription
    madowMADOWβ€”
    file_pathSTRINGβ€”
    contextSTRINGβ€”
    validationSTRINGβ€”