Nodes/ꘇ Genereti/ꘇ chop.arpeggiator
ComfyUI Node

ꘇ chop.arpeggiator

An arp that follows whatever chord you feed it

By languel·Created about a month ago·Updated 3 days ago· 1
ꘇ chop.arpeggiator
  • input
  • notes
  • value
◄notes60 64 67►
◄octaves1►
◄mode▾►
◄bpm120.00►
◄division2►
◄gate0.50►
◄velocity0.70►
◄samples1►
◄sample_rate60.00►
◄time0.00►

It's not generating music, it's generating musical signals

First, the thing that confuses people: ꘇ chop.arpeggiator doesn't make sound. It outputs control channels - note (a MIDI pitch), gate and velocity, plus the step index it's on - and a single FLOAT. In this pack that's a CHOP: a named sampled channel block, the same data type as an oscillator or an LFO, just carrying musical control values instead of a waveform.

Where it's genuinely handy: if you're doing audio-reactive visuals, or driving a browser instrument through the pack's mod.* nodes, you can have one node spit out a rhythmic pattern of note/gate/velocity that both sound and imagery read from. And the FLOAT output - last sample of the first channel - is enough to push a converted numeric widget somewhere else in the graph.

Contrast with what "music in ComfyUI" usually means: ACE-Step and friends are generators, text-in-audio-out. This is not that. When the KB says local tooling closed the music gap, that's about generation models. This node is the other job - sequencing control data - which is why it's model-free and costs nothing to run.

The arpeggio logic, and the bit people miss

Left alone, it's a straightforward arp: notes (default 60 64 67 - a C major triad), octaves (1–4) multiplies them upward in twelfths, mode picks the order (up, down, updown), and bpm × division decides how fast the steps advance. Pitches are deduplicated and sorted, and the octave stack is capped at 127 so you can't generate invalid MIDI. updown only mirrors the descent when there are more than two notes, and rests are written as - or ., which produce pitch 0 with the gate closed.

Now the part that's actually the interesting feature: wire a CHOP into input and the typed notes get replaced by whatever chord is currently arriving. Specifically, it looks for channels named note<digits> whose most recent sample is above zero, collects those pitches, and arpeggiates them instead. So a sequencer or a chord progression upstream turns this into a follower - change the chord, the arp changes with it, no rewiring.

The rest of the widgets are the usual CHOP timing block, and they're doing what you'd expect:

  • gate (0.01–0.99) is the fraction of each step the note is held - the difference between staccato and legato.
  • velocity scales the velocity channel.
  • samples and sample_rate define the sample block (1–4096 samples at up to 1000 Hz), and time is the explicit start time used on Queue.

Outputs are notes (GENERETI_CHOP) and value (FLOAT). Wire notes onward into a synth, a drum-ish endpoint, a MIDI-out node, or a CHOP reader; wire value into any converted numeric input if you just want a number that ticks.

Install

Genereti only. Manager → search Genereti (liuboto) → install → restart → refresh the browser. Manual:

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

Use ComfyUI's own Python (python_embeded\python.exe on Windows Portable). Requirements are one line - comfyui-frontend-package>=1.53.6 - and no audio libraries, models or inference servers get installed. ComfyUI 0.38.2+, Python 3.11+.

Gotchas

  • Nothing plays unless you start it. The pack's contract: browser audio begins only through its own button, and Queue evaluates and passes controls through without ever playing sound or sending MIDI. So a queued run legitimately produces channels and silence - that's not a bug.
  • MIDI notes must be 0..127 is a real, hard error, as is more than 256 note tokens. Nice, terse validation for once.
  • Typed notes are a fallback. Once an input with active note<N> channels is connected, your nicely curated notes string is ignored. That surprises people mid-session.
  • value is one number off the first channel. If you've wired a chop.select upstream to grab a different channel, that changes which channel the FLOAT reflects.
  • Alpha. The README is blunt - "super alpha - early classroom testing… back up your workflows before updating." There's no community discussion of this pack, so trust the bundled ꘇ-Modular-Audio and ꘇ-Sound-Analysis example workflows over any tutorial, including this one.
CategoryGenereti / CHOP

Inputs (11)

NameTypeDefaultDescription
notesSTRING60 64 67—
octavesINT11–4—
modeCOMBO3 options: up, down, updown
bpmFLOAT120.001–400—
divisionINT21–16—
gateFLOAT0.500.01–0.99—
velocityFLOAT0.700–1—
samplesINT11–4096—
sample_rateFLOAT60.001–1000—
timeFLOAT0.000–100000—
inputoptGENERETI_CHOP—

Outputs (2)

NameTypeDescription
notesGENERETI_CHOP—
valueFLOAT—