npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jmove/generator

v1.2.7

Published

Jazz backing track generator — walking bass, piano comping, drum patterns, and style presets for practice sessions

Readme

@jmove/generator

Jazz backing track generator — walking bass lines, piano comping, drum patterns, and full jam sessions from chord progressions.

Zero dependencies. TypeScript. ESM + CJS.

CI npm License: MIT

Demo

Try the live app at jmove.it.com — the Practice Player uses this package to generate all backing tracks in real time.

Stories

Deep technical articles about how JMove and the generator work:

Features

  • Per-Instrument Complexity — 3 general sliders (drumComplexity, pianoComplexity, bassComplexity) drive 13 granular sub-controls via piecewise linear mapping. Drums: tomFrequency, fillIntensity, rideWash, ghostDensity, cymbalColor. Piano: voicingDensity, rhythmicActivity, registerRange, anticipation. Bass: chromaticApproach, registerWidth, syncopation, beatVariety. Manual overrides take precedence over derived values
  • Musicality Engine — phrase-level intelligence: dynamic drops, air gaps, harmonic anticipation, passing chords, conversation dynamics, motif memory. Four parameters (creativity, conversation, airGaps, harmonicFreedom) control how musical and surprising the output sounds
  • Ensemble CoordinationgenerateEnsemble() produces drums, bass, and piano as a coordinated band. Kick patterns shape bass timing, bass register guides piano voicings, drum density modulates comping activity
  • Seedable & Reproducible — deterministic PRNG (xoshiro128**) with per-instrument streams. Save a seed, replay the exact same take
  • Jam Session Generator — random chord progressions across 17 jazz forms (blues, rhythm changes, AABA, modal, Coltrane matrix, and more)
  • Walking Bass — rule-based walking lines with dissonance filtering, chromatic approaches, pattern variety, 19 styles (swing, bossa, Latin tumbao, neo-soul, math rock, IDM), proper odd-meter groupings (11/8, 7/8, 5/4)
  • Piano Comping — Bill Evans rootless voicings (Type A/B), quartal, shell, cluster — all quality-aware (diatonic intervals per chord type), voice-led with rhythmic templates per style
  • Drum Patterns — 19 styles with humanization, ghost notes, groove templates based on GrooVAE research. Holdsworth preset features Chad Wackerman-inspired drumming: cross-stick interjections, ghost cascades, linear fills, 11/8-specific patterns with asymmetric grouping accents
  • 23 Style Presets — Classic Swing to IDM, with per-instrument style overrides and tuned musicality parameters
  • Auto-Detect — analyze a score to recommend the best preset
  • Full Song Form — multi-section arrangements with dynamic shaping
  • Phrase-Aware Generation — 2/4/8-bar phrase boundaries with section-driven dynamics (intro sparse, shout dense)
  • Streaming IteratorgenerateEnsembleMeasures() yields measure-by-measure for incremental generation
  • Groove Templates — structured micro-timing offsets per instrument, not random jitter

Install

npm install @jmove/generator

Requires Node.js 20+.

Quick Start

Ensemble (recommended)

import { generateJamSession, generateEnsemble, scoreChordsToEvents } from '@jmove/generator';

// Generate a 12-bar blues in Bb
const session = generateJamSession({
  key: 'Bb',
  form: 'blues12',
  style: 'swing',
  tempo: 140,
  timeSignature: [4, 4],
});

// Generate coordinated ensemble (drums → bass → piano)
const chords = scoreChordsToEvents(session.score.measures);
const result = generateEnsemble({
  chordEvents: chords,
  style: 'swing',
  tempo: 140,
  measures: 12,
  seed: 42,  // deterministic — omit for random
});

console.log(result.drums.length, 'drum hits');
console.log(result.bass.length, 'bass notes');
console.log(result.piano.length, 'piano chords');
console.log('Replay with seed:', result.seed);

Individual Generators

import {
  generateWalkingBass,
  generatePianoComping,
  generateDrumPattern,
  scoreChordsToEvents,
} from '@jmove/generator';

// Generate individual instrument parts (standalone, no coordination)
const bass = generateWalkingBass(chords, { style: 'swing', tempo: 140 });
const piano = generatePianoComping(chords, { style: 'swing', tempo: 140 });
const drums = generateDrumPattern({ style: 'swing', tempo: 140, measures: 12 });

API Reference

Jam Session

generateJamSession(config: JamConfig): JamResult

Generate a complete chord progression with score.

interface JamConfig {
  key: JamKey;                    // 'C' | 'Db' | 'D' | ... | 'B'
  form: JamForm;                  // 'blues12' | 'rhythm32' | 'aaba32' | ...
  style: PracticeStyle;           // 'swing' | 'bossa' | 'funk' | ...
  tempo: number;                  // BPM (must be > 0)
  timeSignature: [number, number]; // e.g. [4, 4], [3, 4], [7, 8]
  measures?: number;              // override measure count (for 'free' form)
}

interface JamResult {
  score: QuantizedScore;          // full score with measures and chords
  config: JamConfig;
  progressionLabel: string;       // e.g. "Bb7 | Eb7 | Bb7 | ..."
  sections?: SongSection[];       // for 'fullSong' form
}

transposeProgression(chords, semitones): string[][]

Transpose a chord progression by semitones.

getFormsForStyle(style): JamForm[]

Get available forms for a style (e.g. waltz styles get waltz-compatible forms).

enrichQuality(quality): string

Normalize chord quality strings (e.g. '-''m', '^7''maj7').

Walking Bass

generateWalkingBass(chords: ChordEvent[], options?: WalkingBassOptions): BassNote[]

Generate a walking bass line from chord events.

interface BassNote {
  pitch: number;     // MIDI pitch (28-55, E1-G3)
  time: number;      // seconds
  duration: number;  // seconds
  velocity: number;  // 0-127
}

interface WalkingBassOptions {
  style?: string;    // affects pattern: swing=quarter walk, bossa=root-5th, latin=tumbao
  tempo?: number;    // affects swing ratio and dynamics
  swingAmount?: number;
  density?: number;
  humanize?: boolean;
}

scoreChordsToEvents(measures): ChordEvent[]

Extract chord events with timing from score measures.

Piano Comping

generatePianoComping(chords: ChordEvent[], options?: PianoCompingOptions): CompNote[]

Generate piano voicings with rhythmic comping patterns.

interface CompNote {
  pitches: number[];  // MIDI pitches (chord voicing)
  time: number;
  duration: number;
  velocity: number;
}

interface PianoCompingOptions {
  style?: string;
  tempo?: number;
  humanize?: boolean;
  swingAmount?: number;
  density?: number;
  strum?: boolean;    // arpeggiate voicings
  strumMs?: number;   // strum speed in ms
}

Drum Patterns

generateDrumPattern(options: DrumPatternOptions): DrumHit[]

Generate a drum pattern for the specified style and duration.

interface DrumHit {
  pitch: number;     // GM drum map pitch
  time: number;      // seconds
  duration: number;
  velocity: number;
}

interface DrumPatternOptions {
  style?: string;
  tempo?: number;
  measures?: number;
  timeSignature?: [number, number];
  humanize?: boolean;
  startTime?: number;
  swingAmount?: number;
  density?: number;
}

GM_DRUMS

General MIDI drum map constants:

GM_DRUMS.KICK          // 36
GM_DRUMS.SNARE         // 38
GM_DRUMS.HI_HAT_CLOSED // 42
GM_DRUMS.HI_HAT_OPEN  // 46
GM_DRUMS.RIDE          // 51
GM_DRUMS.CRASH         // 49
GM_DRUMS.SPLASH        // 55
GM_DRUMS.CHINA         // 52
GM_DRUMS.TOM_HIGH      // 50
GM_DRUMS.TOM_MID       // 47
GM_DRUMS.TOM_LOW       // 45
GM_DRUMS.TOM_FLOOR     // 43
// ... and more

Ensemble

generateEnsemble(options: EnsembleOptions): EnsembleResult

Generate a coordinated ensemble with built-in alignment and phrase awareness.

interface EnsembleOptions {
  chordEvents: ChordEvent[];
  style: PracticeStyle;
  tempo: number;
  measures: number;
  timeSignature?: [number, number];
  sections?: SongSection[];        // section-driven dynamics
  density?: number;                // 0-100
  swingAmount?: number;            // 0-100
  strumMs?: number;                // 0-30
  seed?: number;                   // omit = random, provide = deterministic
  instrumentStyles?: InstrumentStyles;
  creativity?: number;             // 0-100: surprise frequency
  conversation?: number;           // 0-100: inter-instrument responsiveness
  airGaps?: number;                // 0-100: intentional silence
  harmonicFreedom?: number;        // 0-100: reharmonization intensity
  drumGranular?: DrumGranular;     // per-control drum overrides
  pianoGranular?: PianoGranular;   // per-control piano overrides
  bassGranular?: BassGranular;     // per-control bass overrides
}

interface EnsembleResult {
  drums: DrumHit[];
  bass: BassNote[];
  piano: CompNote[];
  seed: number;                    // always returned for replay
  context: BandContext;            // coordination state (kick times, bass register, etc.)
}

generateEnsembleMeasures(options: EnsembleOptions): Generator<MeasureSlice>

Streaming version — yields one measure at a time for incremental generation.

for (const slice of generateEnsembleMeasures(options)) {
  schedule(slice.drums, slice.bass, slice.piano);
}

createPRNG(seed: number): RandomFn

Create a seedable random function (xoshiro128**). Pass to any generator via the random option for deterministic output.

import { createPRNG, generateDrumPattern } from '@jmove/generator';

const rng = createPRNG(42);
const drums = generateDrumPattern({ style: 'swing', measures: 4, random: rng });
// Same seed → same drums every time

Complexity Mapping

resolveDrumGranular(complexity?, overrides?): DrumGranular

resolvePianoGranular(complexity?, overrides?): PianoGranular

resolveBassGranular(complexity?, overrides?): BassGranular

Map a general complexity slider (0-100, default 50) to per-control values. Manual overrides take precedence.

import { resolveDrumGranular } from '@jmove/generator';

// Complexity 70 → busier drums, override tom frequency to max
const drum = resolveDrumGranular(70, { tomFrequency: 85 });
// drum.tomFrequency = 85 (overridden)
// drum.fillIntensity = 66 (derived from complexity 70)
// drum.rideWash = 66, drum.ghostDensity = 58, drum.cymbalColor = 48

// Pass to generateEnsemble
const result = generateEnsemble({
  chordEvents, style: 'swing', tempo: 140, measures: 12,
  drumGranular: drum,
});
interface DrumGranular {
  tomFrequency: number;      // 0-100: tom probability in comping + micro-variation
  fillIntensity: number;     // 0-100: fill frequency and size
  rideWash: number;          // 0-100: ride cymbal density (sparse → dense)
  ghostDensity: number;      // 0-100: ghost note frequency
  cymbalColor: number;       // 0-100: splash/china substitution on section boundaries
}

interface PianoGranular {
  voicingDensity: number;    // 0-100: shell (2-note) → full (4-note) voicings
  rhythmicActivity: number;  // 0-100: sparse → dense comping patterns
  registerRange: number;     // 0-100: register drift magnitude (narrow → wide)
  anticipation: number;      // 0-100: harmonic anticipation probability
}

interface BassGranular {
  chromaticApproach: number; // 0-100: diatonic → chromatic approach tones
  registerWidth: number;     // 0-100: narrow → full 2-octave range
  syncopation: number;       // 0-100: 8th-note enclosure fill probability
  beatVariety: number;       // 0-100: predictable → adventurous beat 2 choices
}

Style Presets

STYLE_PRESETS: StylePreset[]

23 built-in presets:

| Category | Presets | |----------|---------| | Traditional | Classic Swing, Hard Bop Drive, West Coast Cool, Soft Ballad | | Modern | Fusion Groove, ECM Space, Miles Modal, Contemporary Jazz | | Latin | Bossa Nova, Latin Fire | | Groove | Funk Pocket, Jazz Waltz, Blues Shuffle, Neo-Soul Pocket | | Experimental | Holdsworth Fusion, Alfa Mist, Pat Metheny, Math Rock, IDM | | Hybrid | Fusion/ECM, Modal Funk, Fusion/Neo-Soul |

interface StylePreset {
  id: string;
  name: string;
  description: string;
  style: PracticeStyle;
  instrumentStyles?: {     // per-instrument overrides
    bass?: PracticeStyle;
    piano?: PracticeStyle;
    drums?: PracticeStyle;
  };
  parameters: {
    swingAmount: number;   // 0-100
    density: number;       // 0-100
    strumMs?: number;      // 0-30: piano chord strum spread in ms
    creativity?: number;   // 0-100: surprise frequency
    conversation?: number; // 0-100: inter-instrument responsiveness
    airGaps?: number;      // 0-100: intentional silence
    harmonicFreedom?: number; // 0-100: reharmonization intensity
  };
  tempoRange: [number, number];
}

STYLE_LABELS: Record<PracticeStyle, string>

Display names for all 19 practice styles.

STYLE_CATEGORIES: Record<string, PracticeStyle[]>

Styles grouped by category (Traditional, Modern, Latin, Groove, Experimental).

autoDetectPreset(score: QuantizedScore): StylePreset

Analyze a score and return the best-matching preset based on tempo, time signature, chord content, and style hints.

Groove & Swing Utilities

getGrooveTemplate(style): GrooveTemplate

Get micro-timing template for a style. Templates define per-instrument bias and jitter values based on GrooVAE research.

applyGroove(time, element, template): number

Apply groove displacement to a note time.

tempoSwingMultiplier(tempo): number

Tempo-dependent swing scaling. Slow tempos swing harder; fast tempos straighten out.

instrumentSwingFactor(role): number

Per-instrument swing scaling. Ride swings hardest, bass walks straighter, piano between.

humanizeTime(time, amount?): number

Add timing jitter to a note.

humanizeVelocity(velocity, amount?): number

Add velocity variation to a note.

Style Mapping

irealStyleToPracticeStyle(irealStyle): PracticeStyle

Convert iReal Pro style strings (e.g. "Medium Swing", "Bossa Nova") to generator styles.

Constants

ALL_KEYS              // ['C', 'Db', 'D', ..., 'B']
FORM_LABELS           // { blues12: '12-Bar Blues', ... }
FORM_MEASURE_COUNTS   // { blues12: 12, rhythm32: 32, ... }
TIME_SIGNATURE_GROUPS // grouped time signatures
ALL_TIME_SIGNATURES   // all supported time signatures

Styles

19 styles with distinct algorithms for bass, piano, and drums:

| Style | Swing | Bass | Piano | Drums | |-------|-------|------|-------|-------| | swing | Triplet swing | Quarter-note walk | Rootless voicings, syncopated | Ride + hi-hat 2&4 | | bossa | Straight 8ths | Root-5th pattern | Montuno rhythm | Cross-stick + syncopated kick | | latin | Straight 8ths | Tumbao pattern | Montuno variations | Cascara + clave | | ballad | Light swing | Half-note roots | Whole/half-note voicings | Brushes feel | | funk | Straight 16ths | Syncopated octaves | Staccato stabs | 16th hi-hat + ghost notes | | fusion | Light swing | Chromaticism | Extended voicings | Linear patterns | | ecm | Minimal | Sparse, open | Wide intervals | Brushes, space | | hardBop | Heavy swing | Strong walk | Punchy voicings | Driving ride | | coolJazz | Light swing | Melodic walk | Light touch | Brushes | | modal | Medium swing | Pedal points | Quartal voicings | Sparse | | jazzWaltz | Waltz swing | 3/4 walk | Waltz comp | 3/4 ride pattern | | shuffleBlues | Triplet shuffle | Shuffle bass | Blues comping | Shuffle groove | | neoSoul | Broken feel | Erykah-style | Glasper voicings | J Dilla pocket | | contemporaryJazz | Moderate | Nordic clarity | Avishai Cohen trio | Brushes/sticks mix | | holdsworth | Straight | Melodic minor | Wide voicings | Wackerman: bell ride, cross-stick, ghost cascades, 11/8-aware | | alfaMist | Broken beat | Lo-fi chromatic | Rhodes, chromatic | Broken beat | | metheny | Light swing | Jaco melodic | Lydian shimmer | Bob Moses brushes | | mathRock | Straight | Angular | Staccato | Odd groupings | | idm | Generative | Glitch patterns | Algorithmic | Generative |

Forms

17 chord progression forms:

| Form | Measures | Description | |------|----------|-------------| | blues12 | 12 | 12-bar blues | | minorBlues12 | 12 | Minor blues | | rhythm32 | 32 | Rhythm changes (I Got Rhythm) | | aaba32 | 32 | AABA standard form | | abac32 | 32 | ABAC form | | modal16 | 16 | Modal vamp | | turnaround8 | 8 | Short turnaround | | songForm24 | 24 | Song form | | rondo20 | 20 | Rondo form | | clave16 | 16 | Clave-based montuno | | secondLine16 | 16 | New Orleans second line | | coltraneMatrix16 | 16 | Coltrane changes matrix | | throughComposed12 | 12 | Through-composed | | pentatonic8 | 8 | Pentatonic vamp | | quartal16 | 16 | Quartal harmony | | fullSong | varies | Multi-section arrangement | | free | custom | Free form (set measures in config) |

Community Presets

Contribute new style presets! See CONTRIBUTING.md.

# Copy the template
cp preset-template.ts presets/your-preset.ts

# Edit and validate
npx tsx scripts/validate-preset.ts presets/your-preset.ts

# Submit a PR

Presets are validated against preset-schema.json and smoke-tested with the generator.

Development

# Install
npm install

# Run tests (1196 tests)
npm test

# Watch mode
npm run test:watch

# Lint + type check
npm run lint
npm run typecheck

# Build (ESM + CJS + .d.ts)
npm run build

# Validate community presets
npm run validate-preset -- --all

Architecture

src/
  index.ts              Barrel exports (public API)
  types.ts              All public type definitions
  ensemble.ts           Ensemble coordination layer (generateEnsemble)
  prng.ts               Seedable PRNG (xoshiro128**)
  jamGenerator.ts       Chord progression generation (17 forms)
  walkingBass.ts        Walking bass line generation
  pianoComping.ts       Piano voicing + comping patterns
  drumPatterns.ts       Drum pattern generation (19 styles)
  complexityMapping.ts  Per-instrument complexity → granular controls
  stylePresets.ts       Built-in style presets
  autoDetectPreset.ts   Score analysis + preset recommendation
  grooveTemplates.ts    Micro-timing templates (GrooVAE-based)
  swingUtils.ts         Tempo/instrument swing calculations
  styleMapping.ts       iReal Pro style string mapping

License

MIT