Nodes/ꘇ Genereti/ꘇ chop.select
ComfyUI Node

ꘇ chop.select

Pick the one channel you actually meant

By languel·Created about a month ago·Updated 3 days ago· 1
ꘇ chop.select
  • input
  • channels
  • value
◄pattern*►

Every CHOP in this pack has two outputs: a named block of channels, and one FLOAT that is the last sample of whichever channel happens to be first. ꘇ chop.select is how you stop guessing which one that is. Give it a glob pattern and it keeps the matching channels and drops the rest.

What it is

Once a block has four channels - rms, peak, low, mid out of ꘇ mod.analyze, or note, gate, velocity out of a sequencer - most downstream consumers want exactly one of them. Without a select, you're relying on dict insertion order, which is stable but invisible, and your graph becomes a magic trick. With a select, the channel you use is written down on the canvas.

It's the CHOP analogue of the plumbing-doc's reroute and bookmark nodes: it moves no data in any interesting sense, it just makes the graph readable and the intent explicit. The author's own audio-to-visual demo runs ꘇ mod.analyze → chop.select (rms) → chop.math ×12 → a filter amount, precisely so the chain says what it means.

How it works

pattern is whitespace-separated globs. * matches any run of characters, ? matches one, and the live matching is case-sensitive. rms keeps only rms; *cc7* keeps MIDI control channels for CC 7 on any channel; rms peak keeps both; the default * keeps everything and the node becomes a pass-through.

The filtered block keeps the input's sample rate and start time, and channel names are untouched - this node never renames anything. Its behaviour when nothing matches is the part that catches people: an unmatched pattern doesn't error, it just passes through zero channels. Downstream, a zero-channel block looks like "no signal", and the FLOAT output reports 0. If a chain has gone mysteriously dead, chop.select with a stale pattern is a prime suspect - especially after a ꘇ chop.merge renamed a colliding channel with a trailing underscore.

The inputs and outputs that matter

  • input - the GENERETI_CHOP to filter.
  • pattern - STRING, default *. One pattern or several, space-separated. No regex, no slashes, no quoting: just globs. (chop.oscin uses the same matching style against OSC addresses, which is a nice consistency to lean on.)
  • channels out - the surviving channels, names intact.
  • value out - FLOAT, last sample of the first surviving channel. This is the socket you wire to a converted numeric widget, so a select directly upstream is how you control which number drives your parameter.

No samples, no sample_rate, no time: this node inherits its timeline from the input rather than defining one. If you need to change the delivery rate, that's an upstream generator's samples field.

Install

One pack, every operator. Manager → search genereti (title "ꘇ Genereti") → install → restart ComfyUI → hard-refresh the browser tab. Manual:

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

Install with your ComfyUI's Python (.venv on a source checkout, python_embeded\python.exe on Windows Portable). Requirements are just comfyui-frontend-package>=1.53.6 - no models, no extra server, no torch changes. Workflows → Genereti → ꘇ-Sound-Analysis is the demo that uses select for real, and ꘇ-Inspect-Values lets you watch which channels are present before and after filtering.

Common issues

The pattern matches nothing and nothing complains. Zero channels flow downstream, the waveform goes flat, value reads 0. Widen the pattern (*) to confirm the block exists at all, then narrow it back.

Names changed upstream. ꘇ chop.merge renames a colliding channel by appending underscores, so a select written before the merge may be looking for a name that no longer exists. Nothing warns you.

Case and spelling matter. RMS won't match rms. Channel names also include digits for note channels - ch1.note60, not ch1.note.

Select is a filter, not a mixer. Keeping two channels gives you two channels; it never averages or sums them. If you wanted a combined value, that's ꘇ chop.math for a constant operation or ꘇ chop.switch in float mode to blend between two whole sources.

Queue the graph and you get one frozen block. Live CHOP nodes run in the browser; the queue evaluates an explicit block. Fine for reproducibility, surprising the first time.

CategoryGenereti / CHOP

Inputs (2)

NameTypeDefaultDescription
inputGENERETI_CHOP—
patternSTRING*—

Outputs (2)

NameTypeDescription
channelsGENERETI_CHOP—
valueFLOAT—