Skip to content

Repository files navigation

Bendr

Real-time pitch and formant shifting with spectral freeze and a pitched feedback delay. Built entirely from public pulp::signal primitives — no third-party DSP — with a native GPU editor in Pulp's Ink & Signal design language.

Bendr

What it does

  • Pitch ±12 semitones in real time, with formant control that can track the pitch (Link) or stand free, and a preservation mode that keeps the vocal character intact as the pitch moves.
  • Freeze holds the current spectrum as a stationary resynthesis — averaged magnitudes, phases advancing at each bin's instantaneous frequency — so there is no loop seam to hear, and pitch and formant keep bending the held sound. Play it chromatically over MIDI.
  • Pitched feedback delay, tempo-syncable, with a second pitch shifter inside the feedback loop so repeats climb or fall.
  • Dry/wet with latency compensation, so the dry path stays aligned.

The XY pad drives pitch (horizontal) and formant (vertical) together. The spectrum below is the wet signal on a log-frequency axis.

Bendr with Freeze engaged

Built from Pulp primitives

Bendr is a worked example of composing Pulp's own DSP into a shipping plugin. Every processing block is a public primitive from core/signal/:

Primitive Role
RealtimePitchTimeProcessor pitch / formant shift, with built-in FreezeHold and TransientPhasePolicy
PitchedFeedbackDelay tempo-syncable delay with an in-loop pitch shifter
DryWetMixer latency-compensated dry/wet

The editor is likewise assembled from stock pulp::view widgets — Panel, Toggle, ToggleButton, Label — over a single theme_from_preset("ink-signal") call at the root. Only the XY pad and the spectrum are custom canvas, because no stock widget models a semitone grid or a log-frequency magnitude plot.

Click any numeric field to type a value. The caret is Pulp's shared pulp::view::CaretBlink + paint_caret, so it holds solid while you type and resumes blinking when you stop, at a rate independent of your display's refresh.

Bendr with the PITCH type-in open

Install

Download Bendr-<version>.pkg from Releases. It is signed and notarized. The installer's Customize pane lets you pick only the formats your host scans.

Requires macOS on Apple silicon (arm64). The published build is not universal and does not run on Intel Macs.

Format Installs to
Audio Unit (AU) /Library/Audio/Plug-Ins/Components
VST3 /Library/Audio/Plug-Ins/VST3
CLAP /Library/Audio/Plug-Ins/CLAP
Standalone /Applications

Build from source

Bendr consumes an installed Pulp SDK through find_package(Pulp CONFIG); no Pulp source tree is required.

# Install the SDK once, from a Pulp checkout:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DSKIA_DIR="$PWD/external/skia-build"
cmake --build build -j8
cmake --install build --prefix ~/pulp-sdk

# Then build Bendr:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DPULP_SDK_PREFIX=~/pulp-sdk
cmake --build build -j8
ctest --test-dir build --output-on-failure

Artifacts land in build/{AU,VST3,CLAP} and build/Bendr.app.

Package a signed, notarized installer (requires Developer ID credentials in ~/.config/pulp/secrets):

./scripts/package.sh                 # sign → pkg → notarize → staple
SKIP_NOTARIZE=1 ./scripts/package.sh # local testing only

Capture the editor headlessly — the editor requires a GPU host, so capture routes through the offscreen Dawn + Skia backend:

./build/bendr-ui-screenshot docs/bendr-ink-signal.png 760 560
BENDR_SHOT_FROZEN=1 ./build/bendr-ui-screenshot docs/bendr-frozen.png 760 560
BENDR_SHOT_CARET=0  ./build/bendr-ui-screenshot docs/bendr-caret.png 760 560

BENDR_SHOT_CARET=<field> opens that field's type-in before capturing. A caret is only painted while its field is being edited, so a plain capture can never show one.

Notes

  • The design language names Jost for display type; no Jost binary ships with Pulp, so the bundled Inter and JetBrains Mono stand in.
  • Right-click on the XY pad or FREEZE arms MIDI learn for that parameter. In a DAW this needs a Pulp SDK newer than 0.626.0: before that, the macOS plugin view host had no right-button dispatch at all, so no context menu reached any view. The standalone has always worked.

License

MIT — see LICENSE. Same as Pulp.

About

Real-time pitch/formant shifting with spectral freeze and a pitched feedback delay, built from public pulp::signal primitives.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages