let harmony = Engine.new(Palestrina);
fn detect_pitch(buf) -> Note
const MAX_VOICES: usize = 4;
voice_leading.reject_parallels()
struct GuitarInput { onset }
engine.harmonize(note, scale)
fn detect_pitch(
  buf: &[f32]
) -> Option<Note>
let voices =
  counterpoint::
    generate(line, mode);
if interval == Fifth
  && motion == Parallel
  { reject() }
#[inline(always)]
fn onset(
  frame: &Frame
) -> bool
block_size: 128
sample_rate: 48_000
latency_ms: 7.2
// Palestrina
// counterpoint
// rules.rs
CONTRAPUNK WEEKEND JAM·WK 01·Koji Kondo· STARTS IN 2DAYS→ /jam
THE TONNETZ · INTERVAL LATTICE · SINCE 1739

EVERY NOTE
HAS A CONSEQUENCE

Counterpoint is a graph of consequences. Contrapunk renders that graph in real time.

<10ms PLUCK→MIDI 7 MODES 57 SCALES MIT FOREVER
◆ ◇ ◆ ◇ ◆ LIVE · TRY IT NOW
LIVE · CLICK A KEY

PLAY ONE NOTE. HEAR COUNTERPOINT.

◆ ◇ ◆ ◇ ◆ OUTPUT · LIVE TAKE
DEMO REEL

WATCH THE HARMONY WRITE ITSELF

Every block, the solver picks the best legal next note for each voice.

demo · contrapunk.mp4 · live take
LIVE GUITAR TAKE · PALESTRINA MODE · SUB-10MS PLUCK→NOTE · NO EDITING
◆ ◇ ◆ ◇ ◆ WHAT IT DOES
ONE RUST CORE · DESKTOP + BROWSER

THE WHOLE THING

01 · HARMONY

SEVEN HARMONY MODES

PassThrough. Diatonic Thirds. Diatonic Fourths. Random Below. Random Below (No 2nds). Contrary Motion. Strict Counterpoint. Each is a file in src/harmony/modes.rs — two are stateful, five are pure.

02 · SCALES

FIFTY-SEVEN SCALES

Ten families: diatonic, harmonic minor, melodic minor, harmonic major, double harmonic, pentatonic, blues/bebop, symmetric, world, Barry Harris. Modal interchange with a tunable borrowing range.

03 · GUITAR

GUITAR → MIDI

McLeod + single-cycle pitch detection on 128-sample buffers (~2.7ms). Onset detection, pitch voting, auto-calibration, string/fret ID. Sub-10ms pluck-to-note on M-series Macs.

04 · VOICE

FOUR-VOICE LEADING SOLVER

Cartesian-product placements across Soprano / Alto / Tenor / Bass registers. Rejects parallel 5ths and 8ves, prevents voice crossings, scores spacing, common tones, contrary motion.

05 · HUMANIZE

HUMANIZER

Timing jitter, velocity variation, swing on offbeats, duration extension. BeatClock tracks tempo and time signature. Per-note records match Note-Off to Note-On.

06 · HOST

HOSTS CLAP PLUGINS

A full CLAP plugin host via clack-host. Route harmony straight into your favorite instrument inside Contrapunk — no DAW required. macOS, Windows, Linux.

07 · BROWSER

RUNS IN YOUR BROWSER

Same Rust core compiled to WebAssembly at app.contrapunk.com. No install, no signup, no email. WebMIDI out for DAWs and hardware.

08 · OPEN

MIT LICENSED FOREVER

Counterpoint rules are centuries of shared human knowledge. The code that applies them is MIT — fork it, ship it, use it in research, sell it.

~2.7MS
PITCH DETECTION
128
SAMPLE BUFFER
7
HARMONY MODES
57
SCALES
4
VOICE LEADING STYLES
MIT
LICENSE
◆ ◇ ◆ ◇ ◆ ENGINE INTERNALS
HOW IT WORKS

SIX STAGES · ONE AUDIO THREAD

Open-source, no magic. Every stage is a file you can read.

01 AUDIO IN

CPAL captures guitar audio at 48kHz in 128-sample blocks, ring-buffered to the DSP thread. MIDI input from any controller also lands here.

let stream = cpal::default_host()
  .default_input_device()?
  .build_input_stream(&cfg, …)?;
02 PITCH

McLeod autocorrelation + single-cycle refinement. Onset via spectral flux. Pitch voting smooths jitter. Sub-3ms per buffer.

let note = pitch_detection::
  mcleod_pitch(
    &buf, 48_000.0
  )?;
03 HARMONY

HarmonyEngine resolves the note against the current Scale and HarmonyMode. Stateful modes (Contrary, Strict CP) advance their internal history.

let line = engine
  .harmonize_note_on(note)?;
04 VOICING

VoiceLeadingProcessor places each harmony pitch-class into Soprano / Alto / Tenor / Bass, cartesian-products the combinations, scores them, picks the best.

let chord = solver
  .revoice_chord(line, prev)?;
05 HUMANIZE

Jitter, velocity, swing, duration. A per-note record ties Note-Off to its Note-On so releases stay coherent.

let humanized = humanizer
  .humanize_note_on(note, vel);
06 MIDI OUT

Virtual MIDI (CoreMIDI / WinMM / ALSA) to your DAW, or straight into a CLAP plugin hosted inside Contrapunk via clack-host.

midi_out.send(NoteOn {
  ch, note, vel
})?;
◆ ◇ ◆ ◇ ◆ SEVEN HARMONY MODES
PICK A RULE

ONE ENGINE · SEVEN HARMONY MODES

Click a mode, hear what its rule produces on the same melody.

PARALLEL 3RDS · HarmonyMode::DIATONICTHIRDS

DIATONIC THIRDS

+2 scale degrees above melody
Stays in key (snaps via harmonize_smart)
Handles out-of-key via modal interchange
Stateless
LIVE · CLICK A FRET
E2A2D3G3B3E4357912
◆ ◇ ◆ ◇ ◆ PLAY IT
FRETBOARD · INTERACTIVE

FROM STRINGS TO STAFF

Click any fret. Hear the harmony your guitar would trigger.

E2A2D3G3B3E4357912
Chord
◆ ◇ ◆ ◇ ◆ VOICE LEADING
FOUR STYLE PRESETS

THE SAME VOICES · DIFFERENT CENTURIES

Contrapunk's solver carries weights and hard rules from four historical styles. Toggle them live.

STYLE_RULES::PALESTRINA

PALESTRINA

16th-century strict species

Hard reject parallel 5ths
Hard reject parallel 8ves
Max leap (semitones)5 (P4)
Stepwise bonus+60
Common-tone bonus+45
Leap penalty / semitone−15
Voice-cross penalty−150
Spread preference−4 (tight)
Contrary motion bonus+40
LIVE · CLICK A FRET
E2A2D3G3B3E4357912
◆ ◇ ◆ ◇ ◆ PLUGIN HOST
CLAP · HOSTED IN-APP

BRING YOUR OWN SYNTH

Contrapunk hosts CLAP plugins via a safe clack-host wrapper. Route the harmony straight into an instrument — no DAW required.

CLAP PLUGIN HOST · clack-host
SLOT 01 · INSTRUMENT
VITAL.clap
wavetable · 2 in · 2 out
HARMONY
→ MIDI →
PLUGIN
→ AUDIO →
OUT
CLAP ABI · SAFE WRAPPER · GUI, LOG, AUDIO-PORTS, NOTE-PORTSROUTING HARMONY → INSTRUMENT
◆ ◇ ◆ ◇ ◆ HOW TO RUN IT
FREE · MIT · NO ACCOUNT

THREE WAYS IN

DESKTOP
FREE
TAURI V2 · NATIVE · OFFLINE
  • ✓ Full engine · 7 harmony modes · 57 scales
  • ✓ Hosts CLAP plugins inside the app
  • ✓ macOS DMG, Windows, Linux
  • ✓ Your audio never leaves your machine
BROWSER
NO INSTALL
APP.CONTRAPUNK.COM · WASM
  • ✓ Same Rust core, compiled to WebAssembly
  • ✓ WebMIDI out to DAWs and hardware
  • ✓ Open a tab, grant mic, play
OPEN IN BROWSER →
SOURCE
MIT
BUILD FROM SOURCE WITH CARGO TAURI
  • ✓ Fork it, ship a DAW plugin
  • ✓ Use the rules engine in research
  • ✓ No CLA, no copyleft, just credit
  • ✓ Rust + Tauri + WASM on one repo
CLONE THE REPO →
◆ ◇ ◆ ◇ ◆ VOICES
FROM THE COMMUNITY

WHAT MUSICIANS SAY

"

The Jazz mode voicings are better than I am. I mean that as a compliment to the code.

KE
@kenji_osaka
JAZZ GUITARIST
"

I make my species-counterpoint students check their homework against Palestrina mode. Beats my red pen.

LE
@lena.strings
COMPOSITION PROF
"

Random-below-no-2nds into a Rhodes plugin hosted in-app. Instant ECM record.

DR
@drifter_7
AMBIENT PRODUCER
"

Looked under the hood expecting hacks. Found a voice-leading solver with comments. Read the whole thing on a flight.

BO
@boris.k
DSP ENGINEER
"

We run two guitars into two instances, quantize to different modes. Feels like a third band member.

SU
@sunday_kids
POST-ROCK BAND
"

Parallel-fifths rejection on by default is a value statement. Ship more value statements.

MA
@mara.note
MUSIC THEORIST
◆ ◇ ◆ ◇ ◆ FUN FACT
1970s INDONESIAN PROG ROCK

There was a 1970s Indonesian progressive rock band also called Contrapunk that released an album called "Putri Mohon Diri". They blended traditional Indonesian instruments, intense guitar work, and classical influences. Listen on YouTube.

GET CONTRAPUNK

THREE WAYS IN.
ALL FREE.

Browser at app.contrapunk.com. macOS DMG from GitHub Releases. Build from source with cargo tauri dev.