Skip to content

nanassound/conductr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Conductr

AI-directed generative MIDI — play anything, Opus arranges the band.

Conductr is a browser-based instrument that generates four tracks of real-time MIDI output (drums, bass, melody, harmony), driven by your playing and shaped by a Claude Opus 4.6 AI musical director. Say "make it funky" and the arrangement changes. Play softly and the band pulls back. No audio synthesis — connect to any DAW or synth via Web MIDI.

How It Works

Conductr operates on three timescales simultaneously:

Layer Timescale What it does
C Engine (WASM) ~15 ms per step Deterministic note generation — Euclidean drums, walking bass, constrained-walk melody, diatonic harmony
Performance Analyzer Every ~4 seconds Extracts features from your playing — density, velocity trend, pitch range, silence ratio
Opus 4.6 Director Every ~8 seconds Reads the performance summary and outputs arrangement decisions — density, complexity, scale, feel

The critical design insight: the engine never waits for Opus. Opus shapes the next phrase, not the current note. API latency is musically invisible — the band keeps playing while the director thinks.

Key Features

  • AI musical director — Opus 4.6 acts as an arranger, not a composer. It receives performance summaries and makes high-level decisions (energy, feel, scale, which tracks to feature)
  • Voice commands — say "build to a climax" or "strip it down to drums" via Web Speech API
  • Text commands — type "switch to minor" or "jazz feel" for instant arrangement changes
  • 3D city visualization — procedurally generated cityscape reacts to the music in real time (Three.js + bloom post-processing)
  • MIDI clock sync — slave to your DAW's transport (internal, auto-detect, or external clock modes)
  • Fallback director — rule-based energy mapping when the API is unavailable — the instrument always works
  • Deterministic C engine — same seed = same pattern. Lock a groove you like. ~3.6 KB total memory, zero heap allocation
  • Physical MIDI input — connect a controller via Web MIDI and play into the system

Architecture

  You ──┐
        │  notes / velocity / timing
        ▼
┌─────────────────────┐        ┌──────────────────────────┐
│ Performance Analyzer │───────▶│  Opus 4.6 Musical        │
│ (JS, every ~4 sec)  │ perf   │  Director (async API)    │
│                      │ data   │                          │
│ density, velocity,   │        │  "Building energy —      │
│ pitch range, silence │        │   adding syncopation     │
│                      │        │   and drive"             │
└─────────────────────┘        └────────────┬─────────────┘
                                            │ params + intent
                                            ▼
                               ┌──────────────────────────┐
                               │  Param Interpolator (JS)  │
                               │  smooth transition over   │
                               │  N bars                   │
                               └────────────┬─────────────┘
                                            │
                                            ▼
                               ┌──────────────────────────┐
                               │  libgenseq (C → WASM)    │
                               │  ~15 ms per step         │
                               │  3.6 KB, deterministic   │
                               └────────────┬─────────────┘
                                            │ MIDI events
                                            ▼
                               ┌──────────────────────────┐
                               │  Web MIDI API Output     │
                               │  Ch 10: Drums            │
                               │  Ch 1:  Bass             │
                               │  Ch 2:  Melody           │
                               │  Ch 3:  Harmony          │
                               └────────────┬─────────────┘
                                            │
                                            ▼
                                    DAW / Synth / Hardware

The AI Director

Opus 4.6 is an arranger, not a note-by-note composer. Every ~8 seconds (or immediately on voice/text command), it receives a performance summary and the current engine state, then outputs:

{
  "musical_intent": "Building energy — adding syncopation and drive",
  "params": {
    "drum_density": 95, "bass_movement": 80,
    "melody_complexity": 70, "swing": 45,
    "scale": "dorian", "track_mute": [false, false, false, false]
  },
  "transition": "gradual_2bars",
  "suggestion": "Try holding a sustained chord — I'll open up the melody"
}

The director maintains a conversation history (last 10 exchanges) so it tracks the musical arc of your performance. It knows what it did 30 seconds ago and builds on it — creating contrast, development, and surprise.

When the API is unavailable, a fallback rule-based director maps your playing energy directly to engine parameters: play louder → denser arrangement, stop playing → the band strips back.

Built With

Component Technology
Generative engine C (compiled to WASM via Emscripten)
Browser app Vanilla JavaScript, Vite
3D visualization Three.js + UnrealBloomPass post-processing
MIDI I/O Web MIDI API
Voice input Web Speech API
AI director Claude Opus 4.6 (Anthropic API)
Timing Web Worker clock (not setInterval)

No frameworks. No React. No build-time AI. The entire generative core is 1,134 lines of C. The web app is 3,656 lines of vanilla JS. Total codebase: ~4,800 LOC.

Quick Start

Prerequisites

  • C compiler (gcc or clang)
  • Emscripten (emcc on PATH)
  • Node.js 18+
  • A Chromium-based browser (Web MIDI + Web Speech APIs)
  • An Anthropic API key (optional — fallback director works without it)

Setup

# 1. Build the C engine to WASM
cd engine
make wasm            # outputs web/public/wasm/genseq.{js,wasm}

# 2. Install web dependencies
cd ../web
npm install

# 3. Configure API key (optional)
cp .env.example .env
# Edit .env and paste your Anthropic key

# 4. Start dev server
npm run dev          # opens http://localhost:5173

Open the page in Chrome, pick a MIDI output port, and hit Play.

MIDI Channel Map

Channel Track
Ch 10 Drums (GM standard)
Ch 1 Bass
Ch 2 Melody
Ch 3 Harmony
Ch 5 User input echo

Project Structure

conductr/
├── engine/                        Pure C library — 1,134 LOC
│   ├── include/genseq.h           Public API + all type definitions
│   ├── src/
│   │   ├── genseq.c              Tick loop, transport, pattern swap
│   │   ├── gen_drums.c           Euclidean rhythm generation
│   │   ├── gen_bass.c            Template + scale-constrained bass
│   │   ├── gen_melody.c          Constrained random-walk melody
│   │   ├── gen_harmony.c         Diatonic interval offset harmony
│   │   ├── music_utils.c         Scale/MIDI conversion, quantize
│   │   └── rng.c                 xorshift32 PRNG (11 lines)
│   ├── test/                      4 test files (euclidean, scale, generators, integration)
│   └── Makefile
├── web/                           Browser app — 3,656 LOC
│   ├── src/
│   │   ├── app.js                Entry point, wires everything together
│   │   ├── engine-bridge.js      JS ↔ WASM bridge (HEAPU8 memory reads)
│   │   ├── musical-director.js   Opus 4.6 API integration
│   │   ├── fallback-director.js  Rule-based director (no API needed)
│   │   ├── performance-analyzer.js  8-sec sliding window feature extraction
│   │   ├── param-interpolator.js Smooth parameter transitions
│   │   ├── midi-output.js        Web MIDI API output
│   │   ├── midi-input.js         Web MIDI API input
│   │   ├── midi-clock.js         External MIDI clock sync
│   │   ├── clock-worker.js       Web Worker tick clock
│   │   ├── input-pads.js         Virtual pads + keyboard input
│   │   ├── input-voice.js        Web Speech API voice commands
│   │   ├── ui.js                 DOM updates, pattern grid, controls
│   │   └── viz/                   3D city visualization (Three.js)
│   │       ├── city-viz.js       WebGL renderer + bloom post-processing
│   │       ├── city-scene.js     Procedural city generation
│   │       ├── highway-system.js Animated track paths
│   │       ├── pulse-pool.js     Custom shader particle system
│   │       ├── mood-camera.js    Dynamic camera presets
│   │       └── atmosphere.js     Fog + lighting mapped to music
│   ├── index.html
│   ├── package.json
│   └── vite.config.js
├── docs/overview.md               Full design document
└── LICENSE                        Apache 2.0

License

Apache 2.0

About

A generative sequencer that combine LLM and local rule based sequencer

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors