Skip to content

About

A vocoder written in Rust that uses the input pitch to generate the carrier signal

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

autovocoder

A Rust auto-vocoder: pitch-detects the input voice, quantizes it to a scale, synthesizes a carrier (single note, triad, or fixed "Soundwave" pitch), and drives a classic 16-band channel vocoder. Ships as:

  • An LV2 plugin with 25 named presets (Ardour on Linux)
  • A standalone CLI for offline WAV rendering and live audio (Mac / Linux)
  • A WASM build for running in a webpage via AudioWorklet
  • A shell wrapper for routing a robot voice into Teams/Zoom/Discord on Mac

Quick demos

Intergalactic-style robot voice, live on Mac, into any meeting app:

./scripts/robot-voice.sh intergalactic

Vocode a WAV file:

autovocoder render --input vocal.wav --output robot.wav --mode fixed --fixed-note 48

In Ardour (AVLinux or any Linux distro): Mixer → insert → Autovocoder → right-click → pick a preset.

Install the LV2 plugin (Linux or Mac)

One-shot installer — builds and drops the bundle into ~/.lv2/:

./scripts/install-lv2.sh

Requires Rust (rustup install stable). After install, Ardour / Carla / any LV2 host will see Autovocoder after a plugin rescan.

Standalone CLI

Build

# render-only (no audio deps)
cargo build --release -p autovocoder-standalone

# with live mic → speakers support
cargo build --release -p autovocoder-standalone --features live

On Linux, --features live needs libasound2-dev for ALSA.

Offline render

./target/release/autovocoder render \
    --input in.wav --output out.wav \
    --mode fixed --fixed-note 48     # Soundwave, C3

All modes: mono (track the singer's pitch), major-triad, minor-triad, fixed. Scale snapping: --scale major --scale-root 0 etc.

Full flag list: ./target/release/autovocoder render --help.

Live (mic → speakers)

./target/release/autovocoder live --mode fixed --fixed-note 48

Use headphones — live output into the same mic creates feedback loops fast.

Robot voice in Teams/Zoom/Discord (Mac)

One-time setup:

  1. brew install blackhole-2ch — virtual audio device. Reboot after, or: sudo killall coreaudiod.
  2. In Audio MIDI Setup, create a Multi-Output Device with both BlackHole and your headphones checked — lets you monitor yourself.
  3. In Teams / Zoom / Discord, set Microphone → BlackHole 2ch.

Per-call:

./scripts/robot-voice.sh intergalactic
# or: ./scripts/robot-voice.sh soundwave-c2
# or: ./scripts/robot-voice.sh --list   # see all presets

Ctrl-C to restore your normal voice.

Presets

The LV2 plugin and the robot-voice.sh script share a curated preset set:

Preset Flavor
soundwave-c2 Deep Decepticon. Fixed C2, fully wet.
soundwave-c3 Neutral Soundwave register. Fixed C3.
soundwave-g2 Slightly higher Soundwave — more intelligible.
intergalactic Beastie Boys refrain vibe — fixed A2, bright buzzy carrier.
chromatic-robot Tracks pitch chromatically with a snappy glide.
heavy-glide Same as chromatic-robot but with long portamento (dub-style).
in-key-c-major Autotune-to-C-major. Wrong notes become right notes.
in-key-a-minor Autotune-to-A-minor. Melodic, natural.
dark-choir Minor triad per detected note. Eerie pad effect.
bright-angels Major triad per detected note. Auto-Tune-on-steroids heaven.
subtle-support 30% wet — layer under a real vocal for harmonic reinforcement.

The LV2 plugin also bundles a set of effect-showcase presets that exercise the chorus / tremolo modules (LV2-only — the standalone CLI doesn't expose those parameters yet):

Preset Flavor
soundwave-stutter Soundwave C2 + 8 Hz square chop. Mechanical staccato villain.
liquid-carrier Mono pitch tracking + deep chorus on the carrier. Watery timbre.
wormhole Fixed dim7 with both choruses deep + slow. Disorienting wash.
helicopter 14 Hz hard-square tremolo over chromatic mono. Rotor blades.
trance-gate-c Major-scale auto-tune + 6 Hz EDM gate + subtle output chorus.
synthwave-pad Sus2 fixed chord + lush slow output chorus. '80s pad.
megatron Low dom7 + slow square chop + carrier chorus. Heavier than Soundwave.
robotic-telegraph Fixed A2 + 10 Hz square chop. Speech as Morse code.
tron-cycle Low power chord + deep carrier chorus + slow sine tremolo.
vintage-choir-wash Major triad per note + subtle slow chorus. Mellotron-ish.
glitch-bot Augmented chord + 3.5 Hz hard chop + animated chorus. Rhythmic weird.
cyberbird Mono + fast carrier chorus + subtle sine tremolo. Inhuman creature.

Architecture

Cargo workspace, one DSP core + three frontends:

crates/
├── autovocoder-dsp/          # host-agnostic DSP: osc, filter, pitch (YIN),
│                             # scale, 16-band vocoder, top-level processor
├── autovocoder-lv2/          # LV2 plugin wrapper (hand-rolled C FFI)
│   └── lv2/*.ttl             # plugin manifest + presets
├── autovocoder-standalone/   # CLI: render + live (cpal) subcommands
└── autovocoder-wasm/         # wasm-bindgen bindings for browser use

Signal chain in one glance:

voice ──► YIN pitch detect ──► scale quantize ──► portamento ──► saw carrier(s)
                                                                         │
voice ──► analysis filterbank ──► envelope followers ──► × carrier bands ─┴─► out

Development

just check        # fmt + clippy + tests
just test         # run tests only
just render ...   # run the CLI render subcommand
just lv2-bundle   # build the LV2 bundle under target/lv2/
just lv2-install  # build + copy to ~/.lv2/
just wasm         # build the WASM package (needs wasm-pack)

Or without just, any cargo command works — e.g. cargo test --workspace --exclude autovocoder-wasm.

Deploying to constrained Linux hosts (Cloud Run, small VMs)

The default release profile builds a portable x86-64 binary — safe but leaves SIMD on the table. For a small (~2 vCPU) Linux box, build with the AVX2/FMA baseline:

just release-cloud   # RUSTFLAGS="-C target-cpu=x86-64-v3" cargo build --release

Then pick the cheapest pitch detector your material tolerates — the plugin exposes three:

  • YIN (FFT) — default, recommended. Same accuracy as classic YIN, ~30× cheaper for our window size.
  • YIN (classic) — pure time-domain, no FFT. Use only if FFT init cost matters (very rare).
  • FFT (HPS) — cheapest per-estimate. Best on sustained, harmonic voices; less robust on breathy / noisy material.

License

MIT OR Apache-2.0 — pick whichever you prefer.

About

A vocoder written in Rust that uses the input pitch to generate the carrier signal

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages