Nodes/ComfyUI-AudioReactive/Harmonic (Audio Op)
ComfyUI Node

Harmonic (Audio Op)

Harmonic — peel the melodic layer off your audio with HPSS

By dmarx·Created 3 years ago·Updated 2 years ago· 11
Harmonic (Audio Op)
  • signal
  • SIGNAL

OpHarmonic (display name "Harmonic (Audio Op)") runs harmonic-percussive source separation (HPSS) and hands you the harmonic half: the sustained, tonal part of the signal - vocals, strings, pads, the melody - with the drums and other transient noise stripped out. It's the first half of a two-node pair; its sibling Percussive gives you everything it removed.

Why split a signal in the first place? Because different layers of a track want different treatment in an audio-reactive workflow. A string pad's energy envelope is slow and smooth; a hi-hat's is spiky. If you drive one animation parameter off the whole mix, the layers fight each other. Split them and each can drive its own thing. This is the same idea the stem-separation crowd leans on for audio-reactive music videos - the AnimateDiff audio-reactive work builds whole pipelines on "separate the layers, drive keyframe transitions and ControlNet strength from each." HPSS is the cheap, dependency-free version: no demucs, no models to download, one librosa call.

How it works

The implementation is librosa.effects.harmonic(y=y) - HPSS via the median-filtering approach in the classic Fitzgerald 2010 paper ("Harmonic/Percussive Separation Using Median Filtering"). In plain terms: harmonic content is continuous in frequency, so it survives a median filter along the time axis; percussive content is broadband and short, so it survives a median filter along the frequency axis. Filter the spectrogram both ways, subtract, reconstruct, done.

Two things worth knowing:

  • Unlike Rms, Novelty, or Predominant_Pulse, the output here is sample-level - same length as the input waveform, not a short feature curve. It's audio, not a control signal.
  • HPSS is a heuristic, not a separator model. It's impressively good at separating drums from tonal content on most music, and it does not do instrument-level separation (no "just the bass"). For that you'd want a proper stem separator. If your track is heavily synthesized or just weird, the separation will be imperfect - that's the technique, not a bug.

Inputs and outputs

  • signal (SIGNAL) - from ARReadAudio or upstream of another operator.
  • SIGNAL - y replaced by the harmonic (tonal) component. From here you can run more operators on it - the natural move is Rms on the harmonic layer to get a smooth melody-energy curve - or feed it to ARDrawSignal to see the layer.

Installing it

Manager (search "AudioReactive") or:

cd ComfyUI/custom_nodes
git clone https://github.com/dmarx/ComfyUI-AudioReactive

Restart. First load auto-installs scipy, scikit-learn, librosa, loguru (and librosa pulls numba), so give it a few minutes. If you see ModuleNotFoundError: No module named 'keyframed', pip install keyframed - it's imported at startup but not on the auto-install list.

Common issues

  • Output length matches the input - that's correct for this one; it's audio, not a feature curve. Don't be confused when it's much longer than Rms's output.
  • Drums still bleeding through - HPSS isn't a stem model. Accept it or reach for a real stem separator.
  • ARDrawSignal plot shows a dense mess - a full-res waveform of a harmonic layer looks like noise at plot scale; that's the plot, not the node.
  • Early-port caveats apply - this one is a working core op, but the pack is a single-commit port with the parameterized ops left as unwired stubs. Build on the working ops, plan around the stubs.
CategoryAudioReactive/Operators

Inputs (1)

NameTypeDefaultDescription
signalSIGNAL

Outputs (1)

NameTypeDescription
SIGNALSIGNAL