Files
kennethreitz 9d27bb0f91 The Interruption: reese volume 0.28→0.2
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 14:17:44 -04:00

498 lines
20 KiB
Python

"""
THE INTERRUPTION — a string quartet gets ambushed by drum & bass.
Classical beauty. Then at bar 33 the breakbeat hits and the strings
just... keep playing. Like a concert in a warehouse.
"""
from pytheory import Key, Duration, Score, Tone, play_score
from pytheory.rhythm import DrumSound
key = Key("D", "minor")
s = key.scale
prog = key.progression("i", "VI", "iv", "V")
prog2 = key.progression("i", "VII", "III", "iv")
D = s[0]; E = s[1]; F = s[2]; G = s[3]
A = s[4]; Bb = s[5]; C = s[6]
score = Score("4/4", bpm=85)
# ═══════════════════════════════════════════════════════════════════
# STRUCTURE (80 bars):
# Bars 1-32: String quartet — pure classical, no hint of what's coming
# Bar 33: THE INTERRUPTION — DnB breakbeat slams in at 170 BPM feel
# Bars 33-64: Strings + DnB coexisting, sub bass, the collision
# Bars 65-80: Strings win — beat dissolves, quartet plays out
# ═══════════════════════════════════════════════════════════════════
# ── HARPSICHORD — baroque opening, sets the scene ───────────────
harpsi = score.part("harpsichord", instrument="harpsichord", volume=0.3,
reverb=0.55, reverb_type="cathedral",
delay=0.15, delay_time=0.35, delay_feedback=0.2,
pan=0.1, humanize=0.08)
# Bars 1-16: arpeggiated chords — elegant, formal
for _ in range(4):
for chord in prog:
harpsi.add(chord, Duration.QUARTER, velocity=72)
harpsi.rest(Duration.QUARTER)
harpsi.add(chord, Duration.QUARTER, velocity=65)
harpsi.rest(Duration.QUARTER)
# Bars 17-32: thinner, violins take over
for _ in range(2):
for chord in prog:
harpsi.add(chord, Duration.HALF, velocity=55)
harpsi.rest(Duration.HALF)
for _ in range(8):
harpsi.rest(Duration.WHOLE)
# Bars 33-64: gone — obliterated by the beat
for _ in range(32):
harpsi.rest(Duration.WHOLE)
# Bars 65-80: returns for the ending — full circle
for _ in range(2):
for chord in prog:
harpsi.add(chord, Duration.QUARTER, velocity=60)
harpsi.rest(Duration.QUARTER)
harpsi.add(chord, Duration.QUARTER, velocity=52)
harpsi.rest(Duration.QUARTER)
for _ in range(8):
harpsi.rest(Duration.WHOLE)
# ── FLUTE — soaring above the quartet, baroque ornamental ───────
flute = score.part("flute", instrument="flute", volume=0.22,
reverb=0.5, reverb_type="cathedral",
delay=0.12, delay_time=0.35, delay_feedback=0.15,
pan=0.3, humanize=0.1)
# Bars 1-4: silent — let the harpsichord set the scene
for _ in range(4):
flute.rest(Duration.WHOLE)
# Bars 5-16: ornamental melody — floats above the strings
flute_a = [
(D.add(12), Duration.QUARTER, 78), (E.add(12), Duration.EIGHTH, 72),
(F.add(12), Duration.EIGHTH, 75), (A.add(12), Duration.HALF, 80),
(G.add(12), Duration.QUARTER, 75), (F.add(12), Duration.EIGHTH, 70),
(E.add(12), Duration.EIGHTH, 68), (D.add(12), Duration.HALF, 72),
(F.add(12), Duration.QUARTER, 78), (G.add(12), Duration.QUARTER, 75),
(A.add(12), Duration.HALF, 82),
(Bb.add(12), Duration.QUARTER, 78), (A.add(12), Duration.EIGHTH, 72),
(G.add(12), Duration.EIGHTH, 70), (F.add(12), Duration.HALF, 75),
]
flute_b = [
(A.add(12), Duration.HALF, 80), (Bb.add(12), Duration.QUARTER, 75),
(A.add(12), Duration.QUARTER, 72),
(G.add(12), Duration.QUARTER, 70), (F.add(12), Duration.EIGHTH, 65),
(E.add(12), Duration.EIGHTH, 62), (D.add(12), Duration.HALF, 68),
(None, Duration.QUARTER, 0), (F.add(12), Duration.EIGHTH, 72),
(G.add(12), Duration.EIGHTH, 75), (A.add(12), Duration.HALF, 80),
(D.add(12), Duration.WHOLE, 75),
]
for _ in range(2):
for note, dur, vel in flute_a:
flute.add(note, dur, velocity=vel)
for note, dur, vel in flute_b:
if note is None:
flute.rest(dur)
else:
flute.add(note, dur, velocity=vel)
# Bars 17-32: more active — 16th note runs between phrases
flute_c = [
(D.add(12), Duration.EIGHTH, 82), (E.add(12), Duration.SIXTEENTH, 75),
(F.add(12), Duration.SIXTEENTH, 78), (G.add(12), Duration.QUARTER, 80),
(A.add(12), Duration.HALF, 85),
(G.add(12), Duration.EIGHTH, 78), (F.add(12), Duration.SIXTEENTH, 72),
(E.add(12), Duration.SIXTEENTH, 70), (D.add(12), Duration.QUARTER, 75),
(F.add(12), Duration.HALF, 78),
(A.add(12), Duration.QUARTER, 85), (Bb.add(12), Duration.EIGHTH, 80),
(A.add(12), Duration.EIGHTH, 78), (G.add(12), Duration.HALF, 75),
(D.add(12), Duration.WHOLE, 72),
]
for _ in range(4):
for note, dur, vel in flute_c:
flute.add(note, dur, velocity=vel)
# Bars 33-64: keeps playing through the interruption — unshaken
flute.set(volume=0.4)
for _ in range(4):
for note, dur, vel in flute_a:
flute.add(note, dur, velocity=min(127, vel + 8))
for note, dur, vel in flute_b:
if note is None:
flute.rest(dur)
else:
flute.add(note, dur, velocity=min(127, vel + 8))
# Bars 65-80: returns to gentle — the quartet wins
flute.set(volume=0.3)
for _ in range(2):
for note, dur, vel in flute_a:
flute.add(note, dur, velocity=max(40, vel - 10))
for note, dur, vel in flute_b:
if note is None:
flute.rest(dur)
else:
flute.add(note, dur, velocity=max(40, vel - 12))
# ── HARP — arpeggiated chords, delicate, angelic ────────────────
harp = score.part("harp", instrument="harp", volume=0.28,
reverb=0.25, reverb_decay=1.0,
delay=0.1, delay_time=0.353, delay_feedback=0.15,
pan=-0.25, humanize=0.1)
# Bars 1-8: silent — let harpsichord establish
for _ in range(8):
harp.rest(Duration.WHOLE)
# Bars 9-32: arpeggiated chords — cascading 16ths
harp_arps = {
"i": [D.add(-12), A.add(-12), D, F, A, F, D, A.add(-12)],
"VI": [Bb.add(-24), F.add(-12), Bb.add(-12), D, F, D, Bb.add(-12), F.add(-12)],
"iv": [G.add(-12), Bb.add(-12), D, G, Bb, G, D, Bb.add(-12)],
"V": [A.add(-24), E.add(-12), A.add(-12), C, E, C, A.add(-12), E.add(-12)],
}
chord_order = ["i", "VI", "iv", "V"]
for _ in range(6):
for name in chord_order:
for note in harp_arps[name]:
harp.add(note, Duration.EIGHTH, velocity=62)
# Bars 33-48: keeps going through the interruption, quieter
harp.set(volume=0.18)
for _ in range(4):
for name in chord_order:
for note in harp_arps[name]:
harp.add(note, Duration.EIGHTH, velocity=55)
# Bars 49-64: silent — overwhelmed
for _ in range(16):
harp.rest(Duration.WHOLE)
# Bars 65-80: returns for the ending
harp.set(volume=0.22)
for _ in range(4):
for name in chord_order:
for note in harp_arps[name]:
harp.add(note, Duration.EIGHTH, velocity=58)
# ── VIOLIN 1 — melody, the lead voice ──────────────────────────
violin1 = score.part("violin_1", instrument="violin", volume=0.4,
reverb=0.5, reverb_type="cathedral",
chorus=0.18, chorus_rate=0.3, chorus_depth=0.006,
delay=0.1, delay_time=0.25, delay_feedback=0.15,
pan=-0.35, humanize=0.1)
# Bars 1-16: opening melody — lyrical, romantic
melody_a = [
(A, Duration.HALF, 80), (Bb, Duration.QUARTER, 72),
(A, Duration.QUARTER, 75),
(G, Duration.HALF, 78), (F, Duration.QUARTER, 70),
(E, Duration.QUARTER, 68),
(F, Duration.DOTTED_HALF, 82), (E, Duration.QUARTER, 72),
(D, Duration.WHOLE, 78),
]
melody_b = [
(D.add(12), Duration.HALF, 85), (C.add(12), Duration.QUARTER, 78),
(Bb, Duration.QUARTER, 75),
(A, Duration.HALF, 80), (G, Duration.QUARTER, 72),
(F, Duration.QUARTER, 70),
(G, Duration.HALF, 78), (A, Duration.QUARTER, 75),
(Bb, Duration.QUARTER, 72),
(A, Duration.WHOLE, 82),
]
for _ in range(2):
for note, dur, vel in melody_a:
violin1.add(note, dur, velocity=vel)
for note, dur, vel in melody_b:
violin1.add(note, dur, velocity=vel)
# Bars 17-32: development — higher, more intense
melody_c = [
(D.add(12), Duration.QUARTER, 88), (E.add(12), Duration.QUARTER, 82),
(F.add(12), Duration.HALF, 90),
(E.add(12), Duration.QUARTER, 82), (D.add(12), Duration.QUARTER, 78),
(C.add(12), Duration.QUARTER, 80), (Bb, Duration.QUARTER, 75),
(A, Duration.HALF, 85), (G, Duration.QUARTER, 78),
(A, Duration.QUARTER, 80),
(D.add(12), Duration.WHOLE, 88),
]
for _ in range(2):
for note, dur, vel in melody_c:
violin1.add(note, dur, velocity=vel)
for note, dur, vel in melody_a:
violin1.add(note, dur, velocity=vel)
# Bars 33-64: THE INTERRUPTION — strings keep playing, unshaken
for _ in range(4):
for note, dur, vel in melody_b:
violin1.add(note, dur, velocity=min(127, vel + 10))
for note, dur, vel in melody_c:
violin1.add(note, dur, velocity=min(127, vel + 10))
# Bars 65-80: strings take over again, softer
for _ in range(2):
for note, dur, vel in melody_a:
violin1.add(note, dur, velocity=max(40, vel - 10))
for note, dur, vel in melody_b:
violin1.add(note, dur, velocity=max(40, vel - 15))
# ── VIOLIN 2 — harmony, follows violin 1 a third below ─────────
violin2 = score.part("violin_2", instrument="violin", volume=0.32,
reverb=0.5, reverb_type="cathedral",
chorus=0.18, chorus_rate=0.25, chorus_depth=0.006,
delay=0.1, delay_time=0.28, delay_feedback=0.12,
pan=0.4, humanize=0.1)
# Bars 1-16: harmony part
harm_a = [
(F, Duration.HALF, 72), (G, Duration.QUARTER, 65),
(F, Duration.QUARTER, 68),
(E, Duration.HALF, 70), (D, Duration.QUARTER, 62),
(C, Duration.QUARTER, 60),
(D, Duration.DOTTED_HALF, 75), (C, Duration.QUARTER, 65),
(D, Duration.WHOLE, 70),
]
harm_b = [
(Bb, Duration.HALF, 78), (A, Duration.QUARTER, 70),
(G, Duration.QUARTER, 68),
(F, Duration.HALF, 72), (E, Duration.QUARTER, 65),
(D, Duration.QUARTER, 62),
(E, Duration.HALF, 70), (F, Duration.QUARTER, 68),
(G, Duration.QUARTER, 65),
(F, Duration.WHOLE, 75),
]
for _ in range(2):
for note, dur, vel in harm_a:
violin2.add(note, dur, velocity=vel)
for note, dur, vel in harm_b:
violin2.add(note, dur, velocity=vel)
# Bars 17-32
for _ in range(4):
for note, dur, vel in harm_b:
violin2.add(note, dur, velocity=vel)
# Bars 33-64
for _ in range(4):
for note, dur, vel in harm_a:
violin2.add(note, dur, velocity=min(127, vel + 8))
for note, dur, vel in harm_b:
violin2.add(note, dur, velocity=min(127, vel + 8))
# Bars 65-80
for _ in range(2):
for note, dur, vel in harm_a:
violin2.add(note, dur, velocity=max(35, vel - 12))
for note, dur, vel in harm_b:
violin2.add(note, dur, velocity=max(35, vel - 15))
# ── VIOLA — inner voice, warm ──────────────────────────────────
viola = score.part("viola", instrument="viola", volume=0.3,
reverb=0.5, reverb_type="cathedral",
chorus=0.15, chorus_rate=0.2, chorus_depth=0.006,
pan=-0.15, humanize=0.1)
# Whole note chords throughout — the glue
for _ in range(10):
for chord in prog:
viola.add(chord, Duration.WHOLE, velocity=65)
for _ in range(10):
for chord in prog2:
viola.add(chord, Duration.WHOLE, velocity=60)
# ── CELLO — bass voice, foundation ─────────────────────────────
cello = score.part("cello", instrument="cello", volume=0.35,
reverb=0.45, reverb_type="cathedral",
chorus=0.1, chorus_rate=0.15, chorus_depth=0.004,
pan=0.15, humanize=0.1)
# Walking bass in half notes
cello_line = [
(D.add(-12), Duration.HALF, 75), (A.add(-24), Duration.HALF, 70),
(Bb.add(-24), Duration.HALF, 72), (F.add(-12), Duration.HALF, 68),
(G.add(-12), Duration.HALF, 70), (D.add(-12), Duration.HALF, 72),
(A.add(-12), Duration.HALF, 75), (E.add(-12), Duration.HALF, 70),
]
for _ in range(20):
for note, dur, vel in cello_line:
cello.add(note, dur, velocity=vel)
# ═══════════════════════════════════════════════════════════════════
# BAR 33: THE INTERRUPTION
# DnB breakbeat at double time (feels like 170 even though clock is 85)
# ═══════════════════════════════════════════════════════════════════
K = DrumSound.KICK
S = DrumSound.SNARE
CH = DrumSound.CLOSED_HAT
OH = DrumSound.OPEN_HAT
# ── BREAKBEAT — enters bar 33, no warning ──────────────────────
beat = score.part("breakbeat", volume=0.9, humanize=0.06,
reverb=0.25, reverb_decay=1.0,
delay=0.15, delay_time=0.353, delay_feedback=0.2,
pan=-0.1)
# Bars 1-32: silence — the audience suspects nothing
for _ in range(32):
beat.rest(Duration.WHOLE)
# Bars 33-64: DnB breakbeat — 16th notes at 85 BPM = 8th notes at 170
# Classic amen-style break
for bar in range(32):
if bar % 8 == 7:
# Fill — snare into 32nd note hat cascade
beat.hit(S, Duration.SIXTEENTH, velocity=108)
beat.hit(S, Duration.SIXTEENTH, velocity=105)
beat.hit(K, Duration.SIXTEENTH, velocity=110)
beat.hit(S, Duration.SIXTEENTH, velocity=100)
# 32nd note hat roll
for i in range(8):
vel = min(127, 55 + i * 8)
beat.hit(CH, 0.125, velocity=vel)
# Back to snare hits
beat.hit(S, Duration.SIXTEENTH, velocity=112)
beat.hit(K, Duration.SIXTEENTH, velocity=115)
beat.hit(S, Duration.SIXTEENTH, velocity=118)
beat.hit(S, Duration.SIXTEENTH, velocity=120)
elif bar % 4 == 3:
# Mini fill — 32nd hat flurry on beat 4
beat.hit(K, Duration.SIXTEENTH, velocity=110)
beat.hit(CH, Duration.SIXTEENTH, velocity=50)
beat.hit(CH, Duration.SIXTEENTH, velocity=45)
beat.hit(CH, Duration.SIXTEENTH, velocity=48)
beat.hit(S, Duration.SIXTEENTH, velocity=105)
beat.hit(CH, Duration.SIXTEENTH, velocity=50)
beat.hit(CH, Duration.SIXTEENTH, velocity=42)
beat.hit(K, Duration.SIXTEENTH, velocity=95)
beat.hit(CH, Duration.SIXTEENTH, velocity=48)
beat.hit(K, Duration.SIXTEENTH, velocity=100)
beat.hit(S, Duration.SIXTEENTH, velocity=108)
beat.hit(CH, Duration.SIXTEENTH, velocity=45)
# 32nd note hat burst
for i in range(8):
beat.hit(CH, 0.125, velocity=min(90, 50 + i * 5))
else:
# K---S--K-KS----
beat.hit(K, Duration.SIXTEENTH, velocity=110)
beat.hit(CH, Duration.SIXTEENTH, velocity=50)
beat.hit(CH, Duration.SIXTEENTH, velocity=45)
beat.hit(CH, Duration.SIXTEENTH, velocity=48)
beat.hit(S, Duration.SIXTEENTH, velocity=105)
beat.hit(CH, Duration.SIXTEENTH, velocity=50)
beat.hit(CH, Duration.SIXTEENTH, velocity=42)
beat.hit(K, Duration.SIXTEENTH, velocity=95)
beat.hit(CH, Duration.SIXTEENTH, velocity=48)
beat.hit(K, Duration.SIXTEENTH, velocity=100)
beat.hit(S, Duration.SIXTEENTH, velocity=108)
beat.hit(CH, Duration.SIXTEENTH, velocity=45)
beat.hit(CH, Duration.SIXTEENTH, velocity=48)
beat.hit(CH, Duration.SIXTEENTH, velocity=42)
beat.hit(CH, Duration.SIXTEENTH, velocity=50)
beat.hit(CH, Duration.SIXTEENTH, velocity=45)
# Bars 65-72: beat thins out — strings winning
for bar in range(8):
vel = max(25, 100 - bar * 9)
beat.hit(K, Duration.SIXTEENTH, velocity=vel)
beat.rest(Duration.SIXTEENTH)
beat.rest(Duration.SIXTEENTH)
beat.rest(Duration.SIXTEENTH)
beat.hit(S, Duration.SIXTEENTH, velocity=max(20, vel - 5))
beat.rest(Duration.SIXTEENTH)
beat.rest(Duration.SIXTEENTH)
beat.hit(K, Duration.SIXTEENTH, velocity=max(20, vel - 10))
beat.rest(Duration.SIXTEENTH)
beat.hit(K, Duration.SIXTEENTH, velocity=max(20, vel - 8))
beat.hit(S, Duration.SIXTEENTH, velocity=max(20, vel - 5))
beat.rest(Duration.SIXTEENTH)
beat.rest(Duration.SIXTEENTH)
beat.rest(Duration.SIXTEENTH)
beat.rest(Duration.SIXTEENTH)
beat.rest(Duration.SIXTEENTH)
# Bars 73-80: gone
for _ in range(8):
beat.rest(Duration.WHOLE)
# ── 808 KICK — four on the floor, the slap ─────────────────────
kick808 = score.part("kick808", volume=1.0, humanize=0.03,
distortion=0.1, distortion_drive=1.5)
for _ in range(32):
kick808.rest(Duration.WHOLE)
# Bars 33-64: FOUR ON THE FLOOR — hits like a truck
for _ in range(32):
for beat_num in range(4):
kick808.hit(K, Duration.QUARTER, velocity=125)
# Bars 65-72: fading
for bar in range(8):
vel = max(30, 120 - bar * 12)
for beat_num in range(4):
kick808.hit(K, Duration.QUARTER, velocity=vel)
# Bars 73-80: gone
for _ in range(8):
kick808.rest(Duration.WHOLE)
# ── SUB BASS — DnB sub, enters with the beat ───────────────────
sub = score.part("sub", synth="sine", envelope="pad", volume=0.9,
lowpass=150, distortion=0.25, distortion_drive=3.5,
sub_osc=0.7, sidechain=0.6)
for _ in range(32):
sub.rest(Duration.WHOLE)
# Bars 33-64: following the root
sub_roots = [D.add(-24), Bb.add(-24), G.add(-24), A.add(-24)]
for _ in range(8):
for root in sub_roots:
sub.add(root, Duration.WHOLE, velocity=95)
# Bars 65-80: fading
for vel in [85, 78, 70, 62, 55, 48, 40, 35, 30, 25, 22, 20, 18, 15, 12, 8]:
sub.add(D.add(-24), Duration.WHOLE, velocity=vel)
# ── REESE BASS — detuned saw, DnB signature ────────────────────
reese = score.part("reese", synth="drift", envelope="pad", volume=0.2,
lowpass=400, detune=15, spread=0.3,
distortion=0.2, sidechain=0.55,
reverb=0.2, reverb_decay=1.5,
delay=0.1, delay_time=0.706, delay_feedback=0.2,
pan=0.15)
for _ in range(32):
reese.rest(Duration.WHOLE)
# Bars 33-64: dark, menacing
for _ in range(8):
for root in sub_roots:
reese.add(root.add(12), Duration.WHOLE, velocity=75)
# Bars 65-80: fading
for vel in [65, 58, 52, 46, 40, 35, 30, 26, 22, 18, 16, 14, 12, 10, 8, 5]:
reese.add(D.add(-12), Duration.WHOLE, velocity=vel)
# ═════════════════════════════════════════════════════════════════
import sys
print(f"Key: {key}")
print(f"BPM: 85 (DnB section feels like 170)")
print(f"Parts: {list(score.parts.keys())}")
print(f"Duration: {score.duration_ms / 1000:.1f}s | {score.measures} measures")
if "--live" in sys.argv:
print("Playing THE INTERRUPTION (live engine)...")
from pytheory_live.live import LiveEngine
engine = LiveEngine(buffer_size=1024)
engine.play_score(score)
else:
print("Playing THE INTERRUPTION...")
play_score(score)