Sequencing (Score, Part, Pattern)

The composition layer: Score holds an arrangement, Part holds one instrument’s notes, Pattern holds drum patterns. See the Sequencing and Drums guides for tutorials.

Rhythm and duration primitives for PyTheory.

class pytheory.rhythm.Duration(*values)[source]

Bases: Enum

Note durations in beats (quarter note = 1 beat).

WHOLE = 4.0
HALF = 2.0
QUARTER = 1.0
EIGHTH = 0.5
SIXTEENTH = 0.25
DOTTED_HALF = 3.0
DOTTED_QUARTER = 1.5
TRIPLET_QUARTER = 0.6666666666666666
class pytheory.rhythm.TimeSignature(beats: int = 4, unit: int = 4)[source]

Bases: object

A musical time signature like 4/4 or 6/8.

classmethod from_string(s: str) TimeSignature[source]

Parse ‘4/4’, ‘3/4’, ‘6/8’ etc.

property beats_per_measure: float

Total beats in one measure (in quarter-note units).

class pytheory.rhythm.Note(tone: object, duration: Duration, velocity: int = 100, bend: float = 0.0, bend_type: str = 'smooth', lyric: str = '', articulation: str = '', _hold: bool = False)[source]

Bases: object

A pairing of a sound (Tone, Chord, or None for rest) with a duration.

The optional bend field specifies a pitch bend in semitones applied over the note’s duration. Positive = bend up, negative = down. For example, bend=2 bends the note up a whole step by the end.

tone: object
duration: Duration
velocity: int = 100
bend: float = 0.0
bend_type: str = 'smooth'
lyric: str = ''
articulation: str = ''
property beats: float
pytheory.rhythm.Rest(duration=Duration.QUARTER) Note[source]

Create a rest (silent note) with the given duration.

class pytheory.rhythm.DrumSound(*values)[source]

Bases: Enum

General MIDI percussion note numbers (channel 10).

These map to the GM drum map standard supported by virtually all MIDI devices and DAWs.

KICK = 36
SNARE = 38
RIMSHOT = 37
CLAP = 39
CLOSED_HAT = 42
OPEN_HAT = 46
PEDAL_HAT = 44
LOW_TOM = 45
MID_TOM = 47
HIGH_TOM = 50
CRASH = 49
RIDE = 51
RIDE_BELL = 53
COWBELL = 56
CLAVE = 75
SHAKER = 70
TAMBOURINE = 54
CONGA_HIGH = 63
CONGA_LOW = 64
BONGO_HIGH = 60
BONGO_LOW = 61
TIMBALE_HIGH = 65
TIMBALE_LOW = 66
AGOGO_HIGH = 67
AGOGO_LOW = 68
GUIRO = 73
MARACAS = 70
TABLA_NA = 86
TABLA_TIN = 87
TABLA_GE = 88
TABLA_DHA = 89
TABLA_TIT = 90
TABLA_KE = 91
DHOL_DAGGA = 92
DHOL_TILLI = 93
DHOL_BOTH = 94
DHOLAK_GE = 95
DHOLAK_NA = 96
DHOLAK_TIT = 97
MRIDANGAM_THAM = 98
MRIDANGAM_NAM = 99
MRIDANGAM_DIN = 100
MRIDANGAM_THA = 101
TABLA_GE_BEND = 108
DJEMBE_BASS = 102
DJEMBE_TONE = 103
DJEMBE_SLAP = 104
DOUMBEK_DUM = 112
DOUMBEK_TEK = 113
DOUMBEK_KA = 114
CAJON_BASS = 108
CAJON_SLAP = 109
CAJON_TAP = 110
CAJON_SLAP_SNARE = 111
METAL_KICK = 105
METAL_SNARE = 106
METAL_HAT = 107
MARCH_SNARE = 115
MARCH_RIMSHOT = 116
MARCH_CLICK = 118
QUAD_1 = 119
QUAD_2 = 120
QUAD_3 = 121
QUAD_4 = 122
QUAD_SPOCK = 123
BASS_1 = 124
BASS_2 = 125
BASS_3 = 126
BASS_4 = 127
BASS_5 = 80
RAINSTICK = 81
RAINSTICK_SLOW = 128
OCEAN_DRUM = 82
CABASA = 83
WIND_CHIMES = 84
FINGER_CYMBAL = 85
class pytheory.rhythm.Pattern(name: str, hits: list[_Hit], beats: float = 4.0, time_signature: str = '4/4')[source]

Bases: object

A drum pattern — a repeating rhythmic figure.

Patterns are defined as a list of hits within a fixed number of beats. They can be rendered to a Score for MIDI export, or combined with chord progressions.

Example:

>>> pattern = Pattern.preset("rock")
>>> print(pattern)
<Pattern 'rock' 4/4 4.0 beats 12 hits>
to_score(repeats: int = 4, bpm: int = 120) Score[source]

Render this pattern to a Score for MIDI export.

Parameters:
  • repeats – Number of times to repeat the pattern.

  • bpm – Tempo in beats per minute.

Returns:

A Score containing drum hits as MIDI percussion notes.

classmethod fill(name: str) Pattern[source]

Load a named 1-bar drum fill.

Available fills: rock, rock crash, jazz, jazz brush, salsa, samba, funk, metal, blast, buildup, breakdown.

Example:

>>> Pattern.fill("rock")
<Pattern 'rock fill' 4/4 4.0 beats ...>
classmethod list_fills() list[str][source]

Return a list of all available fill names.

classmethod preset(name: str) Pattern[source]

Load a named drum pattern preset.

Available presets:

  • rock — standard 4/4 rock beat (kick-snare-hat)

  • jazz — swing ride pattern with ghost notes

  • bebop — fast jazz ride with syncopated kick/snare

  • bossa nova — Brazilian 2-bar pattern with cross-stick

  • salsa — clave-driven Afro-Cuban pattern

  • funk — syncopated 16th-note groove

  • reggae — one-drop pattern (snare on 3)

  • waltz — 3/4 pattern (oom-pah-pah)

  • 12/8 blues — slow blues shuffle

  • samba — Brazilian carnival pattern

  • son clave 3-2 — the Afro-Cuban rhythmic key

  • son clave 2-3 — reversed clave

Example:

>>> Pattern.preset("salsa")
<Pattern 'salsa' 4/4 8.0 beats ...>
classmethod list_presets() list[str][source]

Return a list of all available preset names.

class pytheory.rhythm.Part(name: str, *, synth: str = 'sine', envelope: str = 'piano', volume: float = 0.5, reverb: float = 0.0, reverb_decay: float = 1.0, reverb_type: str = 'algorithmic', delay: float = 0.0, delay_time: float = 0.375, delay_feedback: float = 0.4, highpass: float = 0.0, highpass_q: float = 0.707, lowpass: float = 0.0, lowpass_q: float = 0.707, distortion: float = 0.0, distortion_drive: float = 3.0, legato: bool = False, glide: float = 0.0, chorus: float = 0.0, chorus_rate: float = 1.5, chorus_depth: float = 0.003, swing: float | None = None, humanize: float = 0.0, sidechain: float = 0.0, sidechain_release: float = 0.1, detune: float = 0.0, pan: float = 0.0, spread: float = 0.0, sub_osc: float = 0.0, noise_mix: float = 0.0, filter_attack: float = 0.01, filter_decay: float = 0.3, filter_sustain: float = 0.0, filter_amount: float = 0.0, vel_to_filter: float = 0.0, saturation: float = 0.0, tremolo_depth: float = 0.0, tremolo_rate: float = 5.0, phaser: float = 0.0, phaser_rate: float = 0.5, cabinet: float = 0.0, cabinet_brightness: float = 0.5, analog: float = 0.0, ensemble: int = 1, fm_ratio: float = 2.0, fm_index: float = 3.0, synth_kw: dict = None)[source]

Bases: object

A named voice within a Score, with its own synth, envelope, and effects.

Parts allow layering multiple instruments — lead, bass, pads, etc. — each with independent synth settings and effects, mixed together on playback.

Don’t instantiate directly — use Score.part() instead.

Example:

score = Score("4/4", bpm=140)
lead = score.part("lead", synth="saw", envelope="pluck",
                  reverb=0.3, delay=0.25)
lead.add("E5", Duration.QUARTER).add("D5", Duration.EIGHTH)
bass = score.part("bass", synth="triangle", envelope="pluck")
bass.add("A2", Duration.HALF)
notes: list[Note]
add(tone_or_string, duration=Duration.QUARTER, *, velocity: int = 100, bend: float = 0.0, bend_type: str = 'smooth', lyric: str = '', articulation: str = '') Part[source]

Add a note. Accepts Tone/Chord objects or note strings like "E5".

Duration can be a Duration enum or a raw float (beats). Velocity controls loudness (1-127, default 100). Bend specifies a pitch bend in semitones over the note duration (e.g. bend=2 bends up a whole step, bend=-1 bends down a half step). Used for guitar bends, sitar meends, slides. Articulation changes how the note is played: "staccato" (short, ~40% duration), "legato" (overlaps next note), "marcato" (heavy accent), "tenuto" (full duration, soft attack), "accent" (velocity bump), "fermata" (held ~50% longer).

Returns self for chaining.

hold(tone_or_string, duration=Duration.QUARTER, *, velocity: int = 100, bend: float = 0.0, bend_type: str = 'smooth', lyric: str = '', articulation: str = '') Part[source]

Add a note without advancing the beat position.

The note plays at the current position but the next note starts at the same time — enabling polyphonic overlap on a single part.

Use this for: piano sustain pedal (bass note rings while melody plays above), guitar strumming with individual string timing, held drone notes under a melody.

Example:

>>> piano = score.part("piano", instrument="piano")
>>> piano.hold("C3", Duration.WHOLE)   # bass rings for 4 beats
>>> piano.add("E4", Duration.HALF)     # starts at same time as C3
>>> piano.add("G4", Duration.HALF)     # starts at beat 2
hit(sound, duration=Duration.EIGHTH, *, velocity: int = 100, articulation: str = '') Part[source]

Add a drum hit to this part.

Places a drum sound into the note stream so it goes through the normal renderer — meaning articulations, humanize, and effects all work on individual hits.

Parameters:
  • sound – A DrumSound enum member (e.g. DrumSound.KICK) or its name as a string ("kick", "snare", "closed_hat" — case-insensitive).

  • duration – How long the hit occupies in the timeline (default 8th note).

  • velocity – Hit loudness 1-127.

  • articulation"accent", "staccato", "marcato", etc.

Example:

>>> drums = score.part("kit", synth="sine")
>>> drums.hit("kick", Duration.QUARTER, articulation="accent")
>>> drums.hit(DrumSound.CLOSED_HAT, Duration.EIGHTH)
flam(sound, duration=Duration.QUARTER, *, velocity: int = 110, gap: float = 0.015, grace_vel: float = 0.3, articulation: str = '') Part[source]

Add a flam — a grace note immediately before the main hit.

The grace note is nearly simultaneous with the main hit, thickening the attack. Tighter gap = more like one fat hit, wider gap = audible double.

Parameters:
  • sound – A DrumSound enum member.

  • duration – Total duration the flam occupies.

  • velocity – Main hit velocity.

  • gap – Beats between grace and main (default 0.008 ≈ 4ms at 120).

  • grace_vel – Grace note velocity as fraction of main (default 0.3).

  • articulation – Optional articulation for the main hit.

Example:

>>> p.flam(DrumSound.MARCH_SNARE, Duration.QUARTER, velocity=120)
diddle(sound, duration=Duration.EIGHTH, *, velocity: int = 70) Part[source]

Add a diddle — two equal strokes in the space of one note.

A double-stroke roll building block. Two hits split evenly across the duration.

Parameters:
  • sound – A DrumSound enum member.

  • duration – Total duration (default 8th note). Each stroke gets half.

  • velocity – Velocity for both strokes.

Example:

>>> p.diddle(DrumSound.MARCH_SNARE, Duration.EIGHTH, velocity=60)
cheese(sound, duration=Duration.QUARTER, *, velocity: int = 110, gap: float = 0.008, grace_vel: float = 0.3) Part[source]

Add a cheese — a flam followed by a diddle.

Common marching rudiment: grace-MAIN-tap-tap.

Parameters:
  • sound – A DrumSound enum member.

  • duration – Total duration.

  • velocity – Main hit velocity.

crescendo(notes, duration=Duration.QUARTER, *, start_vel: int = 40, end_vel: int = 110, articulation: str = '') Part[source]

Add notes with velocity ramping up (getting louder).

Parameters:
  • notes – List of note strings (e.g. ["C4", "D4", "E4"]).

  • duration – Duration for each note.

  • start_vel – Starting velocity (quiet).

  • end_vel – Ending velocity (loud).

  • articulation – Optional articulation for all notes.

Example:

>>> piano.crescendo(["C4","D4","E4","F4","G4"], Duration.QUARTER,
...                 start_vel=40, end_vel=110)
decrescendo(notes, duration=Duration.QUARTER, *, start_vel: int = 110, end_vel: int = 40, articulation: str = '') Part[source]

Add notes with velocity ramping down (getting quieter).

Parameters:
  • notes – List of note strings.

  • duration – Duration for each note.

  • start_vel – Starting velocity (loud).

  • end_vel – Ending velocity (quiet).

  • articulation – Optional articulation for all notes.

Example:

>>> piano.decrescendo(["G4","F4","E4","D4","C4"], Duration.QUARTER,
...                   start_vel=110, end_vel=40)
dynamics(notes, duration=Duration.QUARTER, *, velocities=None, articulation: str = '') Part[source]

Add notes with a velocity curve.

Parameters:
  • notes – List of note strings or Tone/Chord objects.

  • duration – Duration for each note (or list of durations).

  • velocities – Velocity curve — either a (start, end) tuple for a linear ramp, or a list of ints (one per note).

  • articulation – Optional articulation for all notes (or list).

Example:

>>> # Linear ramp
>>> piano.dynamics(["C4","E4","G4","C5"], Duration.QUARTER,
...                velocities=(50, 120))
>>> # Custom curve (swell and fade)
>>> piano.dynamics(["C4","D4","E4","F4","G4","F4","E4","D4"],
...                Duration.EIGHTH,
...                velocities=[50, 70, 90, 110, 110, 90, 70, 50])
swell(notes, duration=Duration.QUARTER, *, low_vel: int = 40, peak_vel: int = 110, articulation: str = '') Part[source]

Add notes that swell up then fade back down (< > shape).

The velocity ramps up to the midpoint then back down, creating the classic orchestral swell.

Parameters:
  • notes – List of note strings.

  • duration – Duration for each note.

  • low_vel – Velocity at start and end.

  • peak_vel – Velocity at the peak (midpoint).

  • articulation – Optional articulation.

Example:

>>> strings.swell(["C4","D4","E4","F4","G4","F4","E4","D4"],
...               Duration.QUARTER, low_vel=40, peak_vel=110)
set(**params) Part[source]

Change effect parameters at the current beat position.

Inserts an automation marker — from this point forward, the specified parameters take new values. Use this to open filters, add reverb, kick in distortion, or change volume mid-song.

Parameters:

**params – Any Part parameter — lowpass, lowpass_q, reverb, reverb_decay, delay, delay_time, delay_feedback, distortion, distortion_drive, volume, chorus, chorus_rate, chorus_depth.

Returns:

Self for chaining.

Example:

>>> lead = score.part("lead", synth="saw", lowpass=800)
>>> lead.add("C5", Duration.WHOLE)            # filtered
>>> lead.set(lowpass=3000, reverb=0.4)        # filter opens
>>> lead.add("E5", Duration.WHOLE)            # bright + reverb
>>> lead.set(distortion=0.6, lowpass=1500)    # grit
>>> lead.add("G5", Duration.WHOLE)
ramp(over: float = 4.0, resolution: float = 0.25, curve: str = 'linear', **params) Part[source]

Smoothly ramp parameters from their current values to new targets.

Generates interpolated automation points — like turning a knob gradually instead of jumping to a new position. Works for any parameter that .set() accepts.

Parameters:
  • over – Duration of the ramp in beats (default 4.0 = 1 bar). Use Duration.WHOLE * 4 for a 4-bar ramp, etc.

  • resolution – How often to insert points, in beats (default 0.25). Lower = smoother but more points.

  • curve – Interpolation shape — "linear" (default), "ease_in" (slow start, fast end), "ease_out" (fast start, slow end), "ease_in_out" (slow start and end).

  • **params – Target values for any parameter. The ramp starts from the parameter’s current value at this beat position.

Returns:

Self for chaining.

Example:

>>> lead = score.part("lead", synth="saw", lowpass=200)
>>> # Open the filter over 4 bars
>>> lead.ramp(over=Duration.WHOLE * 4, lowpass=8000)
>>> # Fade reverb in over 2 bars
>>> pad.ramp(over=Duration.WHOLE * 2, reverb=0.5)
>>> # Multiple params at once with easing
>>> lead.ramp(over=8.0, curve="ease_in", lowpass=6000, distortion=0.4)
lfo(param: str, *, rate: float = 0.5, min: float = 0.0, max: float = 1.0, bars: float = 4, shape: str = 'sine', resolution: float = 0.25) Part[source]

Automate a parameter with an LFO (low-frequency oscillator).

Generates automation points at regular intervals, sweeping a parameter smoothly between min and max values. This is how filter sweeps, tremolo, and auto-wah effects work.

Parameters:
  • param – Parameter name to modulate (e.g. "lowpass", "reverb", "distortion", "volume", "chorus", "delay").

  • rate – LFO speed in cycles per bar (default 0.5 = one sweep every 2 bars). 0.25 = very slow, 1 = once per bar, 4 = four times per bar.

  • min – Minimum parameter value.

  • max – Maximum parameter value.

  • bars – Number of bars to run the LFO over (default 4).

  • shape – Waveform shape — "sine" (smooth), "triangle" (linear), "saw" (ramp up), "square" (on/off).

  • resolution – How often to insert automation points, in beats (default 0.25 = every 16th note). Lower = smoother.

Returns:

Self for chaining.

Example:

>>> lead = score.part("lead", synth="saw", lowpass=400)
>>> # Slow filter sweep: 400→3000 Hz over 8 bars
>>> lead.lfo("lowpass", rate=0.125, min=400, max=3000, bars=8)
>>> lead.arpeggio("Cm", bars=8, pattern="up", octaves=2)
rest(duration=Duration.QUARTER) Part[source]

Add a rest. Returns self for chaining.

fade_in(bars: float = 4) Part[source]

Fade volume from 0 to current level over N bars.

fade_out(bars: float = 4) Part[source]

Fade volume from current level to 0 over N bars.

arpeggio(chord, *, bars: float = 1, pattern: str = 'up', division=Duration.SIXTEENTH, octaves: int = 1, velocity: int = 100) Part[source]

Arpeggiate a chord into a rhythmic pattern.

Takes a chord and sequences through its notes automatically, like a hardware arpeggiator on a synth. Combined with legato=True and glide, this produces classic acid and trance arpeggiated lines.

Parameters:
  • chord – A Chord object (or string like "Am").

  • bars – Number of bars to fill (default 1).

  • pattern – Arpeggio pattern: - "up" — low to high, repeat - "down" — high to low, repeat - "updown" — up then down (bounce) - "downup" — down then up - "random" — random note order

  • division – Note length for each step (default Duration.SIXTEENTH).

  • octaves – Number of octaves to span (default 1). With 2, the pattern repeats one octave higher before cycling.

Returns:

Self for chaining.

Example:

>>> lead = score.part("lead", synth="saw", legato=True, glide=0.03)
>>> lead.arpeggio(Chord.from_symbol("Am"), bars=2, pattern="updown")
strum(chord_name: str, duration=Duration.QUARTER, *, direction: str = 'down', velocity: int = 100, strum_time: float = 0.05) Part[source]

Strum a chord using the part’s fretboard fingering.

Looks up the chord on the fretboard, gets the fingering, and adds each string as a rapid sequence with tiny time offsets — like a real guitar strum. Muted strings are skipped.

Parameters:
  • chord_name – Chord name (e.g. "Am", "G", "D").

  • duration – Total duration of the strum (default QUARTER).

  • direction"down" (low→high, default) or "up" (high→low).

  • velocity – Base velocity (each string gets slight variation).

  • strum_time – Time in beats for the full strum sweep (default 0.03 = very fast). Larger values = slower, more audible strum. Try 0.1 for a lazy strum.

Returns:

Self for chaining.

Example:

>>> guitar = score.part("guitar", instrument="acoustic_guitar",
...                     fretboard=Fretboard.guitar())
>>> guitar.strum("Am", Duration.HALF)
>>> guitar.strum("G", Duration.HALF, direction="up")
roll(tone_or_string, duration=Duration.WHOLE, *, velocity_start: int = 40, velocity_end: int = 100, speed=Duration.SIXTEENTH) Part[source]

Play a roll — rapid repeated notes with velocity ramp.

Perfect for timpani rolls, snare rolls, tremolo on any instrument. The velocity ramps from velocity_start to velocity_end over the duration for crescendo/decrescendo.

Parameters:
  • tone_or_string – The note to repeat.

  • duration – Total duration of the roll.

  • velocity_start – Velocity of the first hit (default 40).

  • velocity_end – Velocity of the last hit (default 100).

  • speed – How fast to repeat (default SIXTEENTH notes).

Returns:

Self for chaining.

Example:

>>> timp = score.part("timp", instrument="timpani")
>>> timp.roll("C3", Duration.WHOLE, velocity_start=30, velocity_end=110)
property is_drums: bool

True if this part contains drum hits.

property total_beats: float
to_tab(*, tuning='guitar', frets=24, time_signature=None)[source]

Generate ASCII guitar/bass tablature from this part’s notes.

Parameters:
  • tuning"guitar" (6-string standard), "bass" (4-string), "drop_d" (guitar drop D), a Fretboard object, or a list of MIDI note numbers for custom tuning (low string first).

  • frets – Maximum fret number (default 24).

  • time_signature – A TimeSignature or None for 4/4.

Returns:

A multi-line ASCII tablature string.

class pytheory.rhythm.Section(name: str, score: Score)[source]

Bases: object

A named section of a Score (verse, chorus, bridge, etc.).

property beats: float
class pytheory.rhythm.Score(time_signature='4/4', bpm=120, swing: float = 0.0, drum_humanize: float = 0.15, system: str = 'western', temperament: str = 'equal', reference_pitch: float = 440.0)[source]

Bases: object

A multi-part arrangement with drums, chords, and instrument voices.

A Score combines:

  • Drum patterns via add_pattern()

  • Chord/tone notes via add() (backwards-compatible default part)

  • Named parts via part() — each with its own synth and envelope

Example:

score = Score("4/4", bpm=140)
score.add_pattern(Pattern.preset("bossa nova"), repeats=4)

chords = score.part("chords", synth="sine", envelope="pad")
lead   = score.part("lead",   synth="saw",  envelope="pluck")
bass   = score.part("bass",   synth="triangle", envelope="pluck")

for chord in key.progression("i", "iv", "V", "i"):
    chords.add(chord, Duration.WHOLE)

lead.add("E5", Duration.QUARTER).add("D5", Duration.EIGHTH)
bass.add("A2", Duration.HALF).add("D2", Duration.HALF)

play_score(score)
notes: list[Note]
parts: dict[str, Part]
property drum_effects: dict

drum effects are just the drums Part’s effect settings.

Type:

Proxy

set_drum_effects(**kwargs) Score[source]

Set effects on all drum parts.

When drums are split, applies to every drum Part (kick, snare, hats, etc.). When not split, applies to the single drums Part.

Example:

score.set_drum_effects(reverb=0.2, reverb_type="plate")
part(name: str, *, instrument: str = None, synth: str = None, envelope: str = None, volume: float = None, reverb: float = None, reverb_decay: float = None, reverb_type: str = None, delay: float = None, delay_time: float = None, delay_feedback: float = None, highpass: float = None, highpass_q: float = None, lowpass: float = None, lowpass_q: float = None, distortion: float = None, distortion_drive: float = None, legato: bool = None, glide: float = None, chorus: float = None, chorus_rate: float = None, chorus_depth: float = None, swing: float | None = None, humanize: float = None, sidechain: float = None, sidechain_release: float = None, detune: float = None, pan: float = None, spread: float = None, sub_osc: float = None, noise_mix: float = None, filter_attack: float = None, filter_decay: float = None, filter_sustain: float = None, filter_amount: float = None, vel_to_filter: float = None, saturation: float = None, tremolo_depth: float = None, tremolo_rate: float = None, phaser: float = None, phaser_rate: float = None, cabinet: float = None, cabinet_brightness: float = None, analog: float = None, ensemble: int = None, fm_ratio: float = None, fm_index: float = None, fretboard=None) Part[source]

Create a named part with its own synth voice and effects.

Parameters:
  • name – Part name (e.g. "lead", "bass", "pads").

  • instrument – Instrument preset name (e.g. "piano", "violin", "808_bass"). See INSTRUMENTS for the full list. When set, the preset’s synth, envelope, and effects are used as defaults; any explicit keyword argument still overrides the preset value.

  • synth – Waveform — "sine", "saw", "triangle", "square", "pulse", "fm", "noise", "supersaw", "pwm_slow", "pwm_fast".

  • envelope – ADSR preset name — "piano", "pluck", "pad", "organ", "bell", "strings", "staccato", or "none".

  • volume – Mix level from 0.0 to 1.0 (default 0.5).

  • reverb – Reverb wet/dry mix, 0.0–1.0 (default 0, off).

  • reverb_decay – Reverb tail length in seconds (default 1.0).

  • reverb_type – Reverb algorithm — "algorithmic" (Schroeder, default) or a convolution IR preset: "taj_mahal", "cathedral", "plate", "spring", "cave", "parking_garage", "canyon".

  • delay – Delay wet/dry mix, 0.0–1.0 (default 0, off).

  • delay_time – Delay time in seconds (default 0.375, dotted 8th).

  • delay_feedback – Delay feedback 0.0–1.0 (default 0.4).

  • lowpass – Lowpass filter cutoff in Hz (default 0, off). Try 800 for muffled bass, 2000 for warm lead, 5000 for subtle brightness rolloff.

  • lowpass_q – Filter resonance/Q factor (default 0.707, flat). Higher values add a resonant peak at the cutoff — 1.0 = slight peak, 2.0 = pronounced, 5.0+ = aggressive.

  • distortion – Distortion wet/dry mix, 0.0–1.0 (default 0, off).

  • distortion_drive – Gain before soft clipping (default 3.0). 0.5–2 = subtle warmth, 3–8 = overdrive, 10+ = fuzz.

  • legato – If True, notes share a continuous waveform instead of retriggering the envelope on each note (default False).

  • glide – Portamento time in seconds between consecutive pitches (default 0, instant). 0.03–0.05 = quick 303 slide, 0.1–0.2 = slow glide.

  • humanize – Random timing and velocity variation, 0.0–1.0 (default 0, off). Adds micro-imperfections that make programmed parts feel like a real player. 0.1 = subtle, 0.3 = natural, 0.5+ = loose/drunk.

  • sidechain – Sidechain compression amount, 0.0–1.0 (default 0, off). How much the drum hits duck this part’s volume. 0.8 = typical EDM pumping effect.

  • sidechain_release – How fast the volume comes back after ducking, in seconds (default 0.1).

Returns:

A Part object. Add notes with .add() and .rest().

Example:

lead = score.part("lead", synth="saw", envelope="pluck",
                  reverb=0.3, delay=0.25, lowpass=3000)

# Or use an instrument preset:
piano = score.part("keys", instrument="piano")
classmethod list_instruments() list[source]

Return a sorted list of available instrument preset names.

Example:

Score.list_instruments()
# ['808_bass', 'acid_bass', 'acoustic_guitar', ...]
add_pattern(pattern, repeats: int = 1) Score[source]

Add a drum pattern to this score.

Parameters:
  • pattern – A Pattern object.

  • repeats – Number of times to repeat.

Returns:

Self for chaining.

fill(name: str = 'rock') Score[source]

Insert a 1-bar drum fill at the current position.

Replaces what would be the next bar of drums with a genre-appropriate fill.

drums(preset: str, repeats: int = 4, fill: str = None, fill_every: int = None, split: bool = False) Score[source]

Add a drum pattern by preset name, with optional auto-fills.

Parameters:
  • preset – Pattern preset name (e.g. "bossa nova", "rock").

  • repeats – Number of times to repeat (default 4).

  • fill – Optional fill name.

  • fill_every – Replace every Nth bar with a fill.

  • split – If True, create separate Parts for kick, snare, hats, toms, cymbals, and percussion — each with independent effects. Access via score.parts["kick"], etc.

Returns:

Self for chaining.

Example:

>>> score.drums("rock", repeats=4, split=True)
>>> score.parts["snare"].reverb_mix = 0.3
>>> score.parts["hats"].lowpass = 6000
add(tone_or_chord, duration=Duration.QUARTER) Score[source]

Add a note to the default (unnamed) part.

For simple scores without named parts. Returns self for chaining.

rest(duration=Duration.QUARTER) Score[source]

Add a rest to the default part. Returns self for chaining.

set_tempo(bpm: int) Score[source]

Insert a tempo change at the current beat position.

The new tempo takes effect from the current total_beats position and remains until the next tempo change.

Parameters:

bpm – New tempo in beats per minute.

Returns:

Self for chaining.

section(name: str) Section[source]

Begin a named section. Everything added after this call until the next section() or end_section() belongs to this section.

Example:

score.section("verse")
chords.add(chord, Duration.WHOLE)
lead.add("C5", Duration.QUARTER)

score.section("chorus")
chords.add(chord, Duration.WHOLE)

score.repeat("verse")
score.repeat("chorus", times=2)
end_section() Score[source]

Close the current section explicitly.

Returns:

Self for chaining.

repeat(name: str, times: int = 1) Score[source]

Repeat a previously defined section.

Copies all notes, drum hits, and automation from the named section and appends them at the current position.

Parameters:
  • name – Name of a section defined with section().

  • times – Number of times to repeat (default 1).

Returns:

Self for chaining.

property total_beats: float
property measures: float

Number of measures (may be fractional if incomplete).

property duration_ms: float

Total duration in milliseconds.

to_abc(*, title='Untitled', key='C', html=False)[source]

Export the score as ABC notation.

Parameters:
  • title – Tune title for the T: field.

  • key – Key signature (e.g. "C", "Gm", "D") for the K: field.

  • html – If True, wrap the ABC string in a self-contained HTML page that renders sheet music via abcjs.

Returns:

An ABC notation string, or a full HTML document string when html is True.

to_lilypond(*, title='Untitled', key='C', mode='major')[source]

Export the score as a LilyPond source string.

Parameters:
  • title – Title for the \header block.

  • key – Key signature root (e.g. "C", "D", "Bb").

  • mode – LilyPond mode string ("major", "minor", etc.).

Returns:

A complete LilyPond source string.

to_musicxml(*, title='Untitled')[source]

Export the score as a MusicXML string.

Parameters:

title – Work title embedded in the <work-title> element.

Returns:

A MusicXML 4.0 partwise document as a pretty-printed XML string.

to_tab(part_name=None, **kwargs)[source]

Generate ASCII tablature for a part in this score.

Parameters:
  • part_name – Name of the part to tab. If None, tabs the first non-drum part that has notes.

  • **kwargs – Passed through to Part.to_tab() (e.g. tuning, frets, time_signature).

Returns:

An ASCII tablature string.

Raises:

ValueError – If no suitable part is found.

save_midi(path, velocity=100)[source]

Export to Standard MIDI File, measure-aware.

classmethod from_wav(path, *, bpm=None, quantize=None, split=False, part_name='melody', synth='piano_synth', fmin=50.0, fmax=1500.0) Score[source]

Transcribe an audio recording into a Score.

Hum a melody, whistle a hook, record a bass line — load the recording and get editable notes back. Pitch tracking is the YIN algorithm; transcription is monophonic per pass (voice, whistle, a single instrument line), not chords.

Reads WAV directly; .m4a voice memos, .mp3, and anything else convert automatically through afconvert (macOS) or ffmpeg.

Parameters:
  • path – Path to an audio file.

  • bpm – Tempo to interpret the timing against. Default None estimates it from the recording’s onset pattern (falling back to 120 for pulse-free rubato).

  • quantize – Optional grid in beats — 0.25 snaps starts and durations to sixteenths. Default keeps the timing as performed.

  • split – If True, separate harmonics from drums first and transcribe a "bass" part and a "melody" part. For full mixes — the bassline comes out well; the melody only as well as it dominates the mix.

  • part_name – Name of the created part (default “melody”).

  • synth – Playback synth for the transcription.

  • fmin/fmax – Pitch search range in Hz. Tighten for better results (e.g. fmin=60, fmax=350 for bass).

Returns:

A Score of detected notes, rests, and velocities, with score.bpm set to the estimated (or given) tempo.

Example:

>>> score = Score.from_wav("hum.m4a", quantize=0.25)
>>> print(score.to_abc(title="My Hum"))
>>> score.save_midi("hum.mid")
classmethod from_midi(path, synth='sine', envelope='pluck') Score[source]

Import a Standard MIDI File into a Score.

Reads notes, tempo, and time signature from any Type 0 or Type 1 MIDI file. Each MIDI channel becomes a named Part. Channel 10 (drums) becomes drum hits.

Parameters:
  • path – Path to a .mid file.

  • synth – Default synth for all parts (default “sine”).

  • envelope – Default envelope for all parts (default “pluck”).

Returns:

A Score with Parts populated from the MIDI data.

Example:

>>> score = Score.from_midi("song.mid")
>>> score.parts["ch1"].synth = "saw"
>>> score.parts["ch1"].reverb_mix = 0.3