TYPESCRIPT-FIRST FRAMEWORK

MUSIC
COMPOSITION
AS CODE

A powerful framework for algorithmic and generative music. Build compositions using functional patterns, explore music theory, and create music impossible on physical instruments.

Why Contour?

Built for developers who explore music through code

Functional Composition

Build music using composable, immutable patterns inspired by TidalCycles. Transform patterns with fast(), slow(), retrograde(), and more.

🎼

Mini-Notation

Express complex rhythms and melodies with concise syntax. Support for repetition, rests, subdivisions, and Euclidean rhythms.

🔥

Live Coding

Perfect for performances with instant hot-reload and graceful audio transitions. Edit patterns in real-time without clicks or pops.

🔒

Type Safety

Branded types prevent unit mixing (Hz vs BPM) at compile time. Catch musical mistakes before runtime with TypeScript.

🎛️

Debug Tools

Interactive debug panel with transport inspector, pattern analyzer, and performance monitor for real-time insights.

🔌

Plugin Architecture

Extensible renderer system for audio playback, WAV export, MIDI files, and custom visualizations.

See It In Action

Write music with the expressiveness of code

Simple Melody
// Create a pattern with mini-notation
const melody = pattern()
  .fromNotation('C4 E4 G4 C5')
  .build();

// Transform it functionally
const transformed = melody
  .transpose(5)      // Up 5 semitones
  .retrograde()     // Reverse
  .fast(2);          // Double speed

// Play it
await play(transformed);
Euclidean Rhythms
// Generate algorithmic rhythms
const kick = Pattern
  .euclidean(16, 4)     // 4 hits in 16 steps
  .transpose(36);           // MIDI C2

const snare = Pattern
  .euclidean(16, 5, 3)   // Rotated
  .transpose(38);

// Combine patterns
const drums = kick.stack(snare);
Pattern Algebra
// Conditional transformations
const evolving = pattern()
  .fromNotation('C4 E4 G4')
  .every(4, p => p.rev())
  .every(8, p => p.transpose(7))
  .build();

// Stack patterns vertically
const harmony = melody
  .stack(melody.transpose(4))
  .stack(melody.transpose(7));
Export to Files
import { MidiRenderer } from '@contour/plugins/midi';

// Render to MIDI file
const renderer = new MidiRenderer();
await renderer.initialize({});

const result = await renderer
  .render(composition);

fs.writeFileSync('song.mid', result.data);

Built With

Modern tools for the best developer experience

TypeScript
Full Type Safety
Tone.js
Web Audio Engine
Vite
Instant HMR
Vitest
Testing Framework

Live Playground

Interactive pattern grid with real-time audio