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.
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
Counterpoint is a graph of consequences. Contrapunk renders that graph in real time.
Every block, the solver picks the best legal next note for each voice.
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.
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.
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.
Cartesian-product placements across Soprano / Alto / Tenor / Bass registers. Rejects parallel 5ths and 8ves, prevents voice crossings, scores spacing, common tones, contrary motion.
Timing jitter, velocity variation, swing on offbeats, duration extension. BeatClock tracks tempo and time signature. Per-note records match Note-Off to Note-On.
A full CLAP plugin host via clack-host. Route harmony straight into your favorite instrument inside Contrapunk — no DAW required. macOS, Windows, Linux.
Same Rust core compiled to WebAssembly at app.contrapunk.com. No install, no signup, no email. WebMIDI out for DAWs and hardware.
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.
Open-source, no magic. Every stage is a file you can read.
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, …)?;
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
)?; 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)?;
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)?;
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);
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
})?; Click a mode, hear what its rule produces on the same melody.
Click any fret. Hear the harmony your guitar would trigger.
Contrapunk's solver carries weights and hard rules from four historical styles. Toggle them live.
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 |
Contrapunk hosts CLAP plugins via a safe clack-host wrapper. Route the harmony straight into an instrument — no DAW required.
The Jazz mode voicings are better than I am. I mean that as a compliment to the code.
I make my species-counterpoint students check their homework against Palestrina mode. Beats my red pen.
Random-below-no-2nds into a Rhodes plugin hosted in-app. Instant ECM record.
Looked under the hood expecting hacks. Found a voice-leading solver with comments. Read the whole thing on a flight.
We run two guitars into two instances, quantize to different modes. Feels like a third band member.
Parallel-fifths rejection on by default is a value statement. Ship more value statements.
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.
Browser at app.contrapunk.com. macOS DMG from GitHub Releases. Build from source with cargo tauri dev.