Nodes/ComfyUI-sonar/SonarWaveletCFG
ComfyUI Node

SonarWaveletCFG

Run different CFG strengths on different frequencies

By blepping·Created 3 years ago·Updated 14 days ago· 49
SonarWaveletCFG
  • model
  • operation_cond
  • operation_uncond
  • operation_fallback_cfg
  • operation_wavelet_cfg
  • operation_result
  • MODEL
start_sigma-1.000
end_sigma0.000
fallback_modeexisting
blend_modelerp
blend_strength1.000
yaml_parameters# YAML or JSON here. # I recommend reading the documentation at https://github.com/blepping/ComfyUI-sonar/docs/waveletcfg.md # For wavelet information, see: https://pytorch-wavelets.readthedocs.io/en/latest/index.html # You may override the fields from the node like start_sigma here. # This section is basically the CFG scale. (All scales sections use the same format.) difference: # Scale for the low frequency components. yl_scale: 5.0 # Scale (or scales) for high frequency components. # This can be scalar or a list or list of lists. # List example: # yh_scales: # - [1, 2, 3] # - fill # - 5 # You can separately apply a scale to items equal to the wavelet level. Levels go from fine to coarse. # If the item is a list, the three items correspond to horizontal, vertical, diagonal for DWT. (DTCWT has 6.) # You can have one "fill" item, this will replicate the item before it however many times is necessary to # match the wavelet level. yh_scales: 3.0 # You can optionally include a scales_end block with yl_scale/yh_scales. # to interpolate from the toplevel scales (can also be in a scales_start blockx if you prefer). # scales_end: # yl_scale: 1.0 # yh_scales: 1.0 # The following scheduling parameters only apply if scales_end exists. # One of linear, logarithmic, exponential, half_cosine, sine # Sine mode will hit the peak scales_after values in the middle of the range. schedule: linear # One of: sampling, enabled_sampling, sigmas, enabled_sigmas, step, enabled_steps schedule_mode: sampling # When enabled, flips the schedule percentage. This happens before the schedule is applied # or any offset/multiplier stuff. If you want to flip the final result you can do something like # schedule_offset_after: -1.0 and schedule_multiplier_after: -1.0 reverse_schedule: false # Added to the percentage before the schedule function is applied. schedule_offset: 0.0 # Applied to the percentage before the schedule function (but after the offset). schedule_multiplier: 1.0 # Added to the percentage after the schedule function is applied. schedule_offset_after: 0.0 # Applied to the percentage after the schedule function (but after the offset). schedule_multiplier_after: 1.0 # Min/max for the final calculated percent. Must be between 0 and 1. schedule_min: 0.0 schedule_max: 1.0 # If you're a crazy person, you can use non-standard blend modes for interpolating # the scales. Not recommended. blend_mode: lerp # Wavelet type wave: db4 # Wavelet level level: 5 ### Start of advanced options # Mode used for padding padding_mode: symmetric # Mutually exclusive with DTCWT mode. use_1d_dwt: false # Enables DTCWT mode. use_dtcwt: false # Configuration for DTCWT, only relevant when enabled. biort: near_sym_a qshift: qshift_a # It's also possible to set these wavelet options with an "inv_" # prefix: mode, biort, qshift, wave, padding_mode # One of: noise_norm, noise, denoised # Normal CFG uses denoised mode. noise_norm divides by the current sigma, noise just uses the raw noise prediction. target_mode: denoised # Can be used to scale cond before the difference is calculated. cond: yl_scale: 1.0 yh_scales: 1.0 # Can be used to scale uncond before the difference is calculated. uncond: yl_scale: 1.0 yh_scales: 1.0 # Can be used to scale the final result after blending. final: yl_scale: 1.0 yh_scales: 1.0 # Uses float64 for the wavelets/scaling/blending operations. # It doesn't seem to hurt performance much, but you can disable it if you want. high_precision_mode: true # Inject is just addition which is usually what you want. The normal CFG function is: # uncond + (cond - uncond) * cfg_scale difference_blend_mode: inject difference_blend_strength: 1.0 # Per-rule value, can be enabled to spam your console with information when # rules activate, dump exactly what high/low scales are used, etc. verbose: false # You may include a rules block which is a list of these configuration definitions. # Include start_sigma/end_sigma parameters. The first matching definition will be used. # rules: # - start_sigma: -1.0

Here's the problem plain CFG can't solve: you want strong prompt adherence for the composition - the shapes, the layout, the broad structure - but that same aggressive CFG is what burns your detail. Crank CFG and low-frequency composition snaps into focus while the high-frequency texture oversaturates and artifacts. SonarWaveletCFG is a drop-in replacement CFG function that separates those two and applies a different CFG scale to each: one scale for the low-frequency part of the latent, another for the high-frequency part. It even lets you go further and treat horizontal versus vertical detail differently.

Mechanically, it works like this: the normal CFG function is uncond + (cond - uncond) * cfg_scale - one scalar applied to the whole difference. Wavelet CFG decomposes both cond and uncond into frequency bands, computes the difference per band, and applies a per-band scale before recombining. Your difference.yl_scale governs the coarse structure; yh_scales governs the fine detail. That's the whole trick, and it's why this node is a model patch: it replaces the CFG calculation that would otherwise run in your guider or sampler.

The honest warning: it's YAML-configurable and proud of it

The one input you can't avoid is yaml_parameters, and the author's own docs open with "this isn't very user-friendly and needs to be configured with YAML." The node ships with a big default block you can start from, and the key settings are:

  • difference.yl_scale (default 5.0) - CFG scale for low-frequency (composition) components.
  • difference.yh_scales (default 3.0) - scale for high-frequency components. This can be a scalar, or a list of lists for per-wavelet-level and even per-orientation control - for DWT, a 3-item list is horizontal, vertical, diagonal. That's where the "different CFG for horizontal vs vertical" trick lives.
  • wave (db4) and level (5) - the wavelet family and decomposition depth.
  • Scheduling - add a scales_end block with yl_scale/yh_scales and a schedule (linear, sine, etc.) to interpolate the scales across sampling, so early steps get composition-heavy CFG and later steps ease off.
  • rules - a list of config blocks, each with its own start_sigma/end_sigma; the first matching rule applies. Combined with the node's own start_sigma (default -1) and end_sigma (default 0) you can gate wavelet CFG to a slice of the denoising range.

The fallback_mode input (existing/own) decides what runs outside the sigma window: existing keeps whatever CFG function was already set when the patch applied; own does the calculation itself at your guider's scale. blend_mode (lerp/inject/subtract_b) with blend_strength (default 1.0) controls how the wavelet result blends with normal CFG - at the defaults it's 100% wavelet CFG. There are also five optional LATENT_OPERATION inputs (cond, uncond, fallback, wavelet result, final) if you want to poke at the pieces mid-stream.

Output is a patched MODEL - wire it into your KSampler like any model-patching node. This is a model_patches category node, not a noise node, and it's the same family of frequency-splitting idea that RES4LYF pushed into the sampler mainstream, so the concept has real pedigree even if the ergonomics here are rough.

Requirements and installing

It needs pytorch_wavelets in the same Python environment ComfyUI runs in (install into a venv/portable build, not system Python):

/path/to/your/python -m pip install pytorch_wavelets

Then install the pack via ComfyUI Manager (search "ComfyUI-sonar") or git clone https://github.com/blepping/ComfyUI-sonar into custom_nodes/, restart. No model files. There's a full example YAML in the node's default text and the pack's docs/waveletcfg.md, and verbose: true in the YAML will dump exactly what scales the node is applying - use that when a rule isn't doing what you expect. And the standard pack caveat: the author calls this whole repo janky and warns inputs change between versions, so pin the git revision if you tune something you love.

Categorymodel_patches

Inputs (12)

NameTypeDefaultDescription
modelMODEL
start_sigmaFLOAT-1.000-1–10000First sigma wavelet CFG will be used.
end_sigmaFLOAT0.0000–10000Last sigma wavelet CFG will be used.
fallback_modeCOMBOexistingExisting mode uses whatever CFG function existed set when this model patch was applied. Own mode does the CFG calculation on its own. The scale will be whatever you set in your guider or sampler.
blend_modeCOMBOlerpControls how the result from wavelet CFG is blended with normal CFG. The default of LERP with strength 1.0 uses 100% wavelet CFG.
blend_strengthFLOAT1.000-10000–10000Controls how the result from wavelet CFG is blended with normal CFG. The default of LERP with strength 1.0 uses 100% wavelet CFG.
yaml_parametersSTRING# YAML or JSON here. # I recommend reading the documentation at https://github.com/blepping/ComfyUI-sonar/docs/waveletcfg.md # For wavelet information, see: https://pytorch-wavelets.readthedocs.io/en/latest/index.html # You may override the fields from the node like start_sigma here. # This section is basically the CFG scale. (All scales sections use the same format.) difference: # Scale for the low frequency components. yl_scale: 5.0 # Scale (or scales) for high frequency components. # This can be scalar or a list or list of lists. # List example: # yh_scales: # - [1, 2, 3] # - fill # - 5 # You can separately apply a scale to items equal to the wavelet level. Levels go from fine to coarse. # If the item is a list, the three items correspond to horizontal, vertical, diagonal for DWT. (DTCWT has 6.) # You can have one "fill" item, this will replicate the item before it however many times is necessary to # match the wavelet level. yh_scales: 3.0 # You can optionally include a scales_end block with yl_scale/yh_scales. # to interpolate from the toplevel scales (can also be in a scales_start blockx if you prefer). # scales_end: # yl_scale: 1.0 # yh_scales: 1.0 # The following scheduling parameters only apply if scales_end exists. # One of linear, logarithmic, exponential, half_cosine, sine # Sine mode will hit the peak scales_after values in the middle of the range. schedule: linear # One of: sampling, enabled_sampling, sigmas, enabled_sigmas, step, enabled_steps schedule_mode: sampling # When enabled, flips the schedule percentage. This happens before the schedule is applied # or any offset/multiplier stuff. If you want to flip the final result you can do something like # schedule_offset_after: -1.0 and schedule_multiplier_after: -1.0 reverse_schedule: false # Added to the percentage before the schedule function is applied. schedule_offset: 0.0 # Applied to the percentage before the schedule function (but after the offset). schedule_multiplier: 1.0 # Added to the percentage after the schedule function is applied. schedule_offset_after: 0.0 # Applied to the percentage after the schedule function (but after the offset). schedule_multiplier_after: 1.0 # Min/max for the final calculated percent. Must be between 0 and 1. schedule_min: 0.0 schedule_max: 1.0 # If you're a crazy person, you can use non-standard blend modes for interpolating # the scales. Not recommended. blend_mode: lerp # Wavelet type wave: db4 # Wavelet level level: 5 ### Start of advanced options # Mode used for padding padding_mode: symmetric # Mutually exclusive with DTCWT mode. use_1d_dwt: false # Enables DTCWT mode. use_dtcwt: false # Configuration for DTCWT, only relevant when enabled. biort: near_sym_a qshift: qshift_a # It's also possible to set these wavelet options with an "inv_" # prefix: mode, biort, qshift, wave, padding_mode # One of: noise_norm, noise, denoised # Normal CFG uses denoised mode. noise_norm divides by the current sigma, noise just uses the raw noise prediction. target_mode: denoised # Can be used to scale cond before the difference is calculated. cond: yl_scale: 1.0 yh_scales: 1.0 # Can be used to scale uncond before the difference is calculated. uncond: yl_scale: 1.0 yh_scales: 1.0 # Can be used to scale the final result after blending. final: yl_scale: 1.0 yh_scales: 1.0 # Uses float64 for the wavelets/scaling/blending operations. # It doesn't seem to hurt performance much, but you can disable it if you want. high_precision_mode: true # Inject is just addition which is usually what you want. The normal CFG function is: # uncond + (cond - uncond) * cfg_scale difference_blend_mode: inject difference_blend_strength: 1.0 # Per-rule value, can be enabled to spam your console with information when # rules activate, dump exactly what high/low scales are used, etc. verbose: false # You may include a rules block which is a list of these configuration definitions. # Include start_sigma/end_sigma parameters. The first matching definition will be used. # rules: # - start_sigma: -1.0 Allows specifying custom parameters via YAML. Note: When specifying paramaters this way, there is generally not much error checking.
operation_condoptLATENT_OPERATIONOptional latent operation that will be applied to cond. Note: Latent operations only apply if a rule matches.
operation_uncondoptLATENT_OPERATIONOptional latent operation that will be applied to uncond. Note: Latent operations only apply if a rule matches.
operation_fallback_cfgoptLATENT_OPERATIONOptional latent operation that will be applied to the fallback (non-wavelet) CFG result. Note: Latent operations only apply if a rule matches.
operation_wavelet_cfgoptLATENT_OPERATIONOptional latent operation that will be applied to wavelet CFG result. Note: Latent operations only apply if a rule matches.
operation_resultoptLATENT_OPERATIONOptional latent operation that will be applied to the final result, after wavelet and normal CFG are potentially blended. Note: Latent operations only apply if a rule matches.

Outputs (1)

NameTypeDescription
MODELMODEL