mirror of
https://github.com/kennethreitz/interpretations.git
synced 2026-06-05 06:46:15 +00:00
a9b356f5cc
Silk Road: mellotron_flute in finale. The Dialogue: drift pad, mellotron ending. Acid Reign: wavefold in breakdown. Chakra: drift at crown. Raga Midnight: mellotron_strings over 808 drop. The Temple: granular_pad texture. Sleight of Hand: mellotron_choir. Gravity: drift tambura. Ghost Protocol: NES pulled back. An Exception: psycho bass 0.3. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
412 lines
15 KiB
Python
412 lines
15 KiB
Python
"""
|
|
SLEIGHT OF HAND — you never see the next move coming.
|
|
Every section is a surprise. Each one beautiful.
|
|
Together, they shouldn't work. They do.
|
|
D minor, 100 BPM.
|
|
"""
|
|
|
|
from pytheory import Key, Duration, Score, Tone, play_score
|
|
from pytheory.rhythm import DrumSound
|
|
|
|
key = Key("D", "minor")
|
|
s = key.scale # D E F G A Bb C
|
|
|
|
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=100)
|
|
|
|
K = DrumSound.KICK
|
|
S = DrumSound.SNARE
|
|
CH = DrumSound.CLOSED_HAT
|
|
OH = DrumSound.OPEN_HAT
|
|
|
|
prog = key.progression("i", "VII", "VI", "v")
|
|
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
# STRUCTURE (72 bars, ~4:19):
|
|
# Bars 1-8: Music box — innocent, delicate, a lullaby
|
|
# Bars 9-16: Didgeridoo drone — the room changes completely
|
|
# Bars 17-24: Piano jazz chords — wait, where are we?
|
|
# Bars 25-32: 808 + trap hats slam in — now it's hip hop
|
|
# Bars 33-40: Everything drops to solo theremin — aching, alone
|
|
# Bars 41-48: Choir swells from nowhere — cathedral out of thin air
|
|
# Bars 49-56: Acid 303 rips through the choir — what??
|
|
# Bars 57-64: Music box returns — but now the 808 is underneath
|
|
# Bars 65-72: Everything at once — the trick revealed
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
|
|
# ── MUSIC BOX — innocent opening, you think you know this track ──
|
|
box = score.part("music_box", instrument="music_box", volume=0.35,
|
|
reverb=0.5, reverb_type="taj_mahal",
|
|
delay=0.2, delay_time=0.3, delay_feedback=0.3,
|
|
pan=-0.2, humanize=0.08)
|
|
|
|
# Bars 1-8: simple melody — like a child's toy
|
|
box_melody = [
|
|
(D.add(12), Duration.QUARTER, 72), (F.add(12), Duration.QUARTER, 68),
|
|
(A.add(12), Duration.HALF, 75),
|
|
(G.add(12), Duration.QUARTER, 70), (F.add(12), Duration.EIGHTH, 65),
|
|
(E.add(12), Duration.EIGHTH, 62), (D.add(12), Duration.HALF, 68),
|
|
(A, Duration.QUARTER, 65), (D.add(12), Duration.QUARTER, 70),
|
|
(F.add(12), Duration.HALF, 72),
|
|
(E.add(12), Duration.QUARTER, 68), (D.add(12), Duration.QUARTER, 65),
|
|
(C.add(12), Duration.QUARTER, 62), (D.add(12), Duration.QUARTER, 70),
|
|
(None, Duration.QUARTER, 0), (A.add(12), Duration.QUARTER, 72),
|
|
(G.add(12), Duration.QUARTER, 68), (F.add(12), Duration.QUARTER, 65),
|
|
(D.add(12), Duration.WHOLE, 72),
|
|
(None, Duration.WHOLE, 0),
|
|
]
|
|
for note, dur, vel in box_melody:
|
|
if note is None:
|
|
box.rest(dur)
|
|
else:
|
|
box.add(note, dur, velocity=vel)
|
|
|
|
# Bars 9-56: silent
|
|
for _ in range(48):
|
|
box.rest(Duration.WHOLE)
|
|
|
|
# Bars 57-64: RETURNS — same melody, but everything's different now
|
|
box.set(volume=0.3)
|
|
for note, dur, vel in box_melody:
|
|
if note is None:
|
|
box.rest(dur)
|
|
else:
|
|
box.add(note, dur, velocity=max(30, vel - 8))
|
|
|
|
# Bars 65-72: continues into the finale, fading
|
|
for note, dur, vel in box_melody[:10]:
|
|
if note is None:
|
|
box.rest(dur)
|
|
else:
|
|
box.add(note, dur, velocity=max(25, vel - 20))
|
|
for _ in range(4):
|
|
box.rest(Duration.WHOLE)
|
|
|
|
# ── DIDGERIDOO — the room changes, bar 9 ─────────────────────
|
|
didge = score.part("didge", instrument="didgeridoo", volume=0.12,
|
|
reverb=0.35, reverb_type="cathedral",
|
|
chorus=0.2, chorus_rate=0.05, chorus_depth=0.01,
|
|
lowpass=350, pan=0.1)
|
|
|
|
for _ in range(8):
|
|
didge.rest(Duration.WHOLE)
|
|
|
|
# Bars 9-16: primal drone — where did the music box go?
|
|
for _ in range(8):
|
|
didge.add(D.add(-24), Duration.WHOLE, velocity=62)
|
|
|
|
# Bars 17-24: fades under the piano
|
|
for vel in [52, 42, 32, 22, 15, 10, 5, 0]:
|
|
if vel > 0:
|
|
didge.add(D.add(-24), Duration.WHOLE, velocity=vel)
|
|
else:
|
|
didge.rest(Duration.WHOLE)
|
|
|
|
# Silent rest of track
|
|
for _ in range(48):
|
|
didge.rest(Duration.WHOLE)
|
|
|
|
# ── SINGING BOWL — transitions, the thread ───────────────────
|
|
bowl = score.part("bowl", instrument="singing_bowl", volume=0.3,
|
|
reverb=0.8, reverb_type="taj_mahal",
|
|
delay=0.15, delay_time=0.6, delay_feedback=0.2,
|
|
pan=0.25)
|
|
|
|
# Strike at every section change
|
|
section_bars = {1: 60, 9: 65, 17: 58, 25: 70, 33: 62, 41: 68,
|
|
49: 55, 57: 65, 65: 72}
|
|
for bar in range(1, 73):
|
|
if bar in section_bars:
|
|
bowl.add(D.add(-24), Duration.WHOLE, velocity=section_bars[bar])
|
|
else:
|
|
bowl.rest(Duration.WHOLE)
|
|
|
|
# ── PIANO — jazz chords out of nowhere, bar 17 ───────────────
|
|
piano = score.part("piano", instrument="piano", volume=0.4,
|
|
reverb=0.45, reverb_type="taj_mahal",
|
|
delay=0.1, delay_time=0.3, delay_feedback=0.15,
|
|
pan=-0.15, humanize=0.1)
|
|
|
|
for _ in range(16):
|
|
piano.rest(Duration.WHOLE)
|
|
|
|
# Bars 17-24: jazzy — extended chords, unexpected voicings
|
|
jazz_prog = key.progression("i", "iv", "VII", "III")
|
|
for _ in range(2):
|
|
for chord in jazz_prog:
|
|
piano.add(chord, Duration.EIGHTH, velocity=72)
|
|
piano.rest(Duration.QUARTER)
|
|
piano.rest(Duration.EIGHTH)
|
|
piano.add(chord, Duration.EIGHTH, velocity=58)
|
|
piano.rest(Duration.QUARTER)
|
|
piano.rest(Duration.EIGHTH)
|
|
|
|
# Bars 25-32: stays through the beat drop — anchoring the chaos
|
|
for _ in range(2):
|
|
for chord in jazz_prog:
|
|
piano.add(chord, Duration.EIGHTH, velocity=68)
|
|
piano.rest(Duration.DOTTED_QUARTER)
|
|
piano.rest(Duration.HALF)
|
|
|
|
# Bars 33-40: silent — theremin owns this
|
|
for _ in range(8):
|
|
piano.rest(Duration.WHOLE)
|
|
|
|
# Bars 41-48: returns under choir — gentle arps
|
|
for _ in range(2):
|
|
for chord in prog:
|
|
piano.add(chord, Duration.QUARTER, velocity=52)
|
|
piano.rest(Duration.DOTTED_HALF)
|
|
|
|
# Bars 49-56: silent — 303 owns this
|
|
for _ in range(8):
|
|
piano.rest(Duration.WHOLE)
|
|
|
|
# Bars 57-72: underneath the music box return
|
|
for _ in range(4):
|
|
for chord in prog:
|
|
piano.add(chord, Duration.EIGHTH, velocity=55)
|
|
piano.rest(Duration.DOTTED_QUARTER)
|
|
piano.rest(Duration.HALF)
|
|
|
|
# ── 808 — slams in at bar 25 ─────────────────────────────────
|
|
sub = score.part("808", synth="sine", envelope="pad", volume=0.6,
|
|
lowpass=200, distortion=0.2, distortion_drive=3.0,
|
|
sub_osc=0.5, saturation=0.4, sidechain=0.3)
|
|
|
|
roots = [D.add(-24), C.add(-24), Bb.add(-24), A.add(-24)]
|
|
|
|
for _ in range(24):
|
|
sub.rest(Duration.WHOLE)
|
|
|
|
# Bars 25-32: drops in — the shock
|
|
for _ in range(2):
|
|
for root in roots:
|
|
sub.add(root, Duration.WHOLE, velocity=40)
|
|
|
|
# Bars 33-40: stays through theremin — the weight underneath
|
|
for _ in range(8):
|
|
sub.add(D.add(-24), Duration.WHOLE, velocity=30)
|
|
|
|
# Bars 41-48: fades under choir
|
|
for vel in [28, 25, 22, 18, 15, 12, 8, 0]:
|
|
if vel > 0:
|
|
sub.add(D.add(-24), Duration.WHOLE, velocity=vel)
|
|
else:
|
|
sub.rest(Duration.WHOLE)
|
|
|
|
# Bars 49-56: back with the 303
|
|
for _ in range(2):
|
|
for root in roots:
|
|
sub.add(root, Duration.WHOLE, velocity=38)
|
|
|
|
# Bars 57-72: underneath the music box — the big reveal
|
|
for _ in range(4):
|
|
for root in roots:
|
|
sub.add(root, Duration.WHOLE, velocity=35)
|
|
|
|
# ── TRAP HATS — with the 808, bar 25 ─────────────────────────
|
|
hats = score.part("hats", volume=0.25, pan=0.2, humanize=0.05)
|
|
|
|
for _ in range(24):
|
|
hats.rest(Duration.WHOLE)
|
|
|
|
# Bars 25-32: trap hats — 16ths with rolls
|
|
for bar in range(8):
|
|
if bar % 4 == 3:
|
|
for i in range(32):
|
|
hats.hit(CH, 0.125, velocity=min(85, 40 + i * 2))
|
|
else:
|
|
for beat in range(4):
|
|
hats.hit(CH, Duration.SIXTEENTH, velocity=70)
|
|
hats.hit(CH, Duration.SIXTEENTH, velocity=42)
|
|
hats.hit(CH, Duration.SIXTEENTH, velocity=55)
|
|
hats.hit(CH, Duration.SIXTEENTH, velocity=38)
|
|
|
|
# Bars 33-56: silent
|
|
for _ in range(24):
|
|
hats.rest(Duration.WHOLE)
|
|
|
|
# Bars 57-64: back with the music box — gentler
|
|
for _ in range(8):
|
|
for beat in range(4):
|
|
hats.hit(CH, Duration.EIGHTH, velocity=58)
|
|
hats.hit(CH, Duration.EIGHTH, velocity=35)
|
|
|
|
# Bars 65-72: full trap hats for the finale
|
|
for bar in range(8):
|
|
if bar % 4 == 3:
|
|
for i in range(32):
|
|
hats.hit(CH, 0.125, velocity=min(90, 42 + i * 2))
|
|
else:
|
|
for beat in range(4):
|
|
hats.hit(CH, Duration.SIXTEENTH, velocity=72)
|
|
hats.hit(CH, Duration.SIXTEENTH, velocity=45)
|
|
hats.hit(CH, Duration.SIXTEENTH, velocity=58)
|
|
hats.hit(CH, Duration.SIXTEENTH, velocity=40)
|
|
|
|
# ── KICK + SNARE — boom bap, bars 25-32 and 57-72 ────────────
|
|
kick = score.part("kick", volume=0.7, humanize=0.04,
|
|
distortion=0.08, distortion_drive=1.5)
|
|
|
|
snare = score.part("snare", volume=0.5, humanize=0.04,
|
|
reverb=0.2, reverb_decay=0.8,
|
|
delay=0.06, delay_time=0.3, delay_feedback=0.1,
|
|
pan=0.05)
|
|
|
|
for _ in range(24):
|
|
kick.rest(Duration.WHOLE)
|
|
snare.rest(Duration.WHOLE)
|
|
|
|
# Bars 25-32: the drop
|
|
for _ in range(8):
|
|
kick.hit(K, Duration.QUARTER, velocity=110)
|
|
kick.rest(Duration.EIGHTH)
|
|
kick.hit(K, Duration.EIGHTH, velocity=92)
|
|
kick.hit(K, Duration.QUARTER, velocity=105)
|
|
kick.rest(Duration.QUARTER)
|
|
|
|
snare.rest(Duration.QUARTER)
|
|
snare.hit(S, Duration.QUARTER, velocity=102)
|
|
snare.rest(Duration.QUARTER)
|
|
snare.hit(S, Duration.QUARTER, velocity=105)
|
|
|
|
# Bars 33-56: silent
|
|
for _ in range(24):
|
|
kick.rest(Duration.WHOLE)
|
|
snare.rest(Duration.WHOLE)
|
|
|
|
# Bars 57-72: back for the reveal + finale
|
|
for _ in range(16):
|
|
kick.hit(K, Duration.QUARTER, velocity=108)
|
|
kick.rest(Duration.EIGHTH)
|
|
kick.hit(K, Duration.EIGHTH, velocity=90)
|
|
kick.hit(K, Duration.QUARTER, velocity=102)
|
|
kick.rest(Duration.QUARTER)
|
|
|
|
snare.rest(Duration.QUARTER)
|
|
snare.hit(S, Duration.QUARTER, velocity=100)
|
|
snare.rest(Duration.QUARTER)
|
|
snare.hit(S, Duration.QUARTER, velocity=102)
|
|
|
|
# ── THEREMIN — solo, bar 33, the emotional gut punch ──────────
|
|
theremin = score.part("theremin", instrument="theremin", volume=0.35,
|
|
reverb=0.4, reverb_type="taj_mahal",
|
|
delay=0.12, delay_time=0.3, delay_feedback=0.15,
|
|
pan=-0.1, humanize=0.06)
|
|
|
|
for _ in range(32):
|
|
theremin.rest(Duration.WHOLE)
|
|
|
|
# Bars 33-40: alone with just the 808 — aching
|
|
theremin.add(A, Duration.WHOLE, velocity=72, bend=0.5)
|
|
theremin.add(F, Duration.WHOLE, velocity=68, bend=-0.25)
|
|
theremin.rest(Duration.WHOLE)
|
|
theremin.add(D.add(12), Duration.HALF, velocity=78, bend=1.0)
|
|
theremin.add(C.add(12), Duration.HALF, velocity=72, bend=-0.5)
|
|
theremin.add(Bb, Duration.WHOLE, velocity=70, bend=0.25)
|
|
theremin.rest(Duration.WHOLE)
|
|
theremin.add(A, Duration.HALF, velocity=65, bend=-0.15)
|
|
theremin.add(D, Duration.HALF, velocity=60)
|
|
theremin.rest(Duration.WHOLE)
|
|
|
|
# Bars 41-72: silent
|
|
for _ in range(32):
|
|
theremin.rest(Duration.WHOLE)
|
|
|
|
# ── CHOIR — swells from nowhere, bar 41 ──────────────────────
|
|
choir = score.part("choir", instrument="mellotron_choir", volume=0.15,
|
|
reverb=0.8, reverb_type="cathedral",
|
|
chorus=0.3, chorus_rate=0.08, chorus_depth=0.012,
|
|
pan=0.2)
|
|
|
|
for _ in range(40):
|
|
choir.rest(Duration.WHOLE)
|
|
|
|
# Bars 41-48: cathedral appears — where did this come from?
|
|
for vel in [25, 32, 38, 42, 45, 48, 50, 52]:
|
|
choir.add(prog[vel % 4], Duration.WHOLE, velocity=vel)
|
|
|
|
# Bars 49-56: continues under the 303
|
|
for _ in range(2):
|
|
for chord in prog:
|
|
choir.add(chord, Duration.WHOLE, velocity=45)
|
|
|
|
# Bars 57-64: fading
|
|
for vel in [42, 38, 32, 28, 22, 18, 12, 0]:
|
|
if vel > 0:
|
|
choir.add(prog[0], Duration.WHOLE, velocity=vel)
|
|
else:
|
|
choir.rest(Duration.WHOLE)
|
|
|
|
# Bars 65-72: silent
|
|
for _ in range(8):
|
|
choir.rest(Duration.WHOLE)
|
|
|
|
# ── ACID 303 — rips through the choir, bar 49 ────────────────
|
|
acid = score.part("303", synth="saw", volume=0.4,
|
|
lowpass=2000, lowpass_q=10.0,
|
|
distortion=0.3, distortion_drive=3.5,
|
|
saturation=0.7, legato=True, glide=0.05,
|
|
reverb=0.2, reverb_type="spring",
|
|
delay=0.2, delay_time=0.3, delay_feedback=0.3,
|
|
pan=-0.25)
|
|
acid.lfo("lowpass", rate=0.02, min=600, max=8000, bars=8, shape="saw")
|
|
|
|
for _ in range(48):
|
|
acid.rest(Duration.WHOLE)
|
|
|
|
# Bars 49-56: acid line — screaming through the choir
|
|
acid_pattern = [
|
|
(D, Duration.SIXTEENTH, 105), (None, Duration.SIXTEENTH, 0),
|
|
(D, Duration.SIXTEENTH, 98), (F, Duration.SIXTEENTH, 92),
|
|
(D, Duration.SIXTEENTH, 108), (None, Duration.SIXTEENTH, 0),
|
|
(C, Duration.EIGHTH, 88),
|
|
(D, Duration.SIXTEENTH, 110), (A.add(-12), Duration.SIXTEENTH, 95),
|
|
(D, Duration.SIXTEENTH, 102), (None, Duration.SIXTEENTH, 0),
|
|
(Bb.add(-12), Duration.EIGHTH, 92),
|
|
(D, Duration.EIGHTH, 108),
|
|
]
|
|
for _ in range(8):
|
|
for note, dur, vel in acid_pattern:
|
|
if note is None:
|
|
acid.rest(dur)
|
|
else:
|
|
acid.add(note, dur, velocity=vel)
|
|
|
|
# Bars 57-72: silent — it was just a visit
|
|
for _ in range(16):
|
|
acid.rest(Duration.WHOLE)
|
|
|
|
# ── STRINGS — only in the finale, the grand reveal ───────────
|
|
strings = score.part("strings", instrument="string_ensemble", volume=0.12,
|
|
reverb=0.55, reverb_type="cathedral",
|
|
chorus=0.2, chorus_rate=0.15, chorus_depth=0.006,
|
|
pan=-0.2)
|
|
|
|
for _ in range(64):
|
|
strings.rest(Duration.WHOLE)
|
|
|
|
# Bars 65-72: everything together — strings tie the bow
|
|
for vel in [30, 38, 45, 50, 52, 48, 40, 28]:
|
|
strings.add(prog[vel % 4], Duration.WHOLE, velocity=vel)
|
|
|
|
# ═════════════════════════════════════════════════════════════════
|
|
import sys
|
|
|
|
print(f"Key: {key}")
|
|
print(f"BPM: 100")
|
|
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 SLEIGHT OF HAND (live engine)...")
|
|
from pytheory_live.live import LiveEngine
|
|
engine = LiveEngine(buffer_size=1024)
|
|
engine.play_score(score)
|
|
else:
|
|
print("Playing SLEIGHT OF HAND...")
|
|
play_score(score)
|