Nodes/ꘇ Genereti/ꘇ chop.constant
ComfyUI Node

ꘇ chop.constant

One number, everywhere, changing never

By languel·Created about a month ago·Updated 3 days ago· 1
ꘇ chop.constant
    • channels
    • value
    ◄value1.00►
    ◄channels1►
    ◄samples1►
    ◄sample_rate60.00►
    ◄time0.00►

    ꘇ chop.constant holds a value and hands it out as a sampled control signal. On the face of it that's ComfyUI's PrimitiveFloat with extra steps - a node that stores a number and gives it back. The difference is the channel structure and the sample rate, and if you've ever needed five nodes to agree on one value, that difference is the whole point.

    What it is

    Genereti's chop.* family is a control-signal layer - TouchDesigner's vocabulary, deliberately. A CHOP here is a named block of channel samples: a dictionary of float arrays, a sample rate, and a start time. Instruments and parameters accept these blocks, and any numeric widget on any node can receive one of their scalar value outputs.

    Control-layer nodes are the least glamorous part of any graph and the ones you end up using most. The plumbing doc behind this article puts it well: these nodes exist to fight two problems, repetition (the same value wired to five places) and illegibility. chop.constant is the purest expression of the first one.

    How it works

    The node generates a block of samples values per channel, at sample_rate samples per second, starting at time. For a constant, every sample in the block is just value - so the interesting machinery is the delivery rate, and this is where the two widgets get confused constantly.

    Read the author's own tooltips, because they're unusually clear about it:

    • samples - "Samples per delivered block. Live updates/s = sample_rate / samples, limited by browser frames. Use 1 for responsive scalar control; 8 at 60 Hz delivers 7.5 blocks/s."
    • sample_rate - "Samples per second, not blocks per second. A block contains samples values; use samples=1 for updates near this rate."

    In other words: sample_rate is the resolution of the signal, and samples is how much of it arrives per delivery. If you're driving a slider, you want samples = 1. If you're generating a block for something that wants a chunk of signal - a waveform for a CHOP consumer - you raise samples.

    There's a second behaviour worth knowing, and it's in the node description: the CHOP is live in the browser, but Queue evaluates explicit samples and time. The time widget is the start time for a queued evaluation, and when you queue, nothing drifts or reads a wall clock. Determinism, in a node that seems too simple to need it.

    The inputs and outputs that matter

    Inputs, all widgets, no sockets: value (default 1, huge ±100000 range - this is a generic control value, not a normalised one), channels (1 to 64, default 1), samples, sample_rate (default 60) and time (default 0).

    Outputs: channels (the CHOP block, with channels named chan0, chan1, …) and value (a FLOAT, the last sample of the first channel).

    Practical use is almost always the second output. Right-click any numeric widget elsewhere in the graph, pick Convert widget to input, drop a chop.constant in front of it, and now one number drives several nodes. Bumping channels above 1 is how you fan out different constants along one wire - the block carries them all, and a chop.select downstream pulls the ones you want by name.

    If you need the value to change, this is the wrong node. Reach for chop.lfo (oscillating), chop.expression (computed) or chop.lag (smoothed).

    Install

    Manager → search Genereti, or:

    git clone https://github.com/languel/genereti.git custom_nodes/genereti
    ./.venv/bin/python -m pip install -r custom_nodes/genereti/requirements.txt
    

    Restart ComfyUI and reload the browser page so the schemas register. The CHOP family needs nothing exotic: requirements.txt is a single line (comfyui-frontend-package>=1.53.6), with NumPy, torch and Pillow already present in ComfyUI, and no models are involved anywhere in this pack's control or audio layers. Comfy ≥ 0.38.2, Python ≥ 3.11.

    Common issues

    The value doesn't update live while the workflow is running. For a constant, that's the expected reading - the number is fixed. But it's also the general rule for this family: live behaviour happens in the browser, and a queued run evaluates the node's explicit samples and time rather than any live state.

    channels output counts look wrong. channels is the number of channels in the block, not a channel index. Setting it to 8 gives you chan0–chan7 in one signal.

    Wiring the value into a text or seed field does nothing. The scalar output is a float, so it belongs on numeric widgets. Convert-to-input on a string or combo won't take it.

    You need repeatability. Set time explicitly and don't rely on live updates; that's what queue evaluation is for.

    Finally, the pack's own warning stands for all of this: solo MIT alpha by Liuboto, v0.1.4, "super alpha - early classroom testing. Back up your workflows before updating."

    CategoryGenereti / CHOP

    Inputs (5)

    NameTypeDefaultDescription
    valueFLOAT1.00-100000–100000—
    channelsINT11–64—
    samplesINT11–4096Samples per delivered block. Live updates/s = sample_rate / samples, limited by browser frames. Use 1 for responsive scalar control; 8 at 60 Hz delivers 7.5 blocks/s.
    sample_rateFLOAT60.001–1000Samples per second, not blocks per second. A block contains samples values; use samples=1 for updates near this rate.
    timeFLOAT0.00-100000–100000—

    Outputs (2)

    NameTypeDescription
    channelsGENERETI_CHOP—
    valueFLOAT—