Ghost Protocol: Portishead intro → Strobe build, NES emotional peak

Rewritten from scratch with Strobe philosophy:
- Portishead dark Rhodes + trip-hop beat (bars 1-32)
- Hypnotic saw arp emerges, grows imperceptibly (bars 17+)
- No kick until bar 49 — the patient build IS the point
- NES square wave melody at the emotional peak (bars 65-96)
- Pluck stabs for the peak energy
- 128 bars (~6 min), filter sweeps across entire track
- Everything dissolves back to silence

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 05:08:19 -04:00
parent 58c7497ab5
commit fe8efa72be
+293 -318
View File
@@ -1,387 +1,362 @@
"""
GHOST PROTOCOL — progressive house in the style of deadmau5.
Dark and driving opening → long build → euphoric release.
Minimal, hypnotic, relentless.
GHOST PROTOCOL — Portishead intro → deadmau5 Strobe-style build.
Dark, patient, hypnotic. One pluck arp that IS the track.
The kick doesn't arrive until you've forgotten you're waiting for it.
"""
from pytheory import Key, Duration, Score, Tone, play_score
from pytheory.rhythm import DrumSound
# ── Key: F minor (dark) → Ab major (euphoric, relative major) ──
key_dark = Key("F", "minor")
key_bright = Key("Ab", "major")
key = Key("F", "minor")
s = key.scale
sd = key_dark.scale
sb = key_bright.scale
# F minor: F G Ab Bb C Db Eb
F = sd[0]; G = sd[1]; Ab = sd[2]; Bb = sd[3]
C = sd[4]; Db = sd[5]; Eb = sd[6]
F = s[0]; G = s[1]; Ab = s[2]; Bb = s[3]
C = s[4]; Db = s[5]; Eb = s[6]
score = Score("4/4", bpm=128)
# ═══════════════════════════════════════════════════════════════════
# STRUCTURE (96 bars, ~4.5 min at 128 BPM):
# Bars 1-8: Intro — kick + filtered pad, dark
# Bars 9-24: Build 1 — bass enters, saw lead, filter opens
# Bars 25-32: Breakdown — kick drops, pad swells, tension
# Bars 33-48: Drop 1 — everything hits, dark and driving
# Bars 49-56: Breakdown 2 — melodic, hopeful, the turn
# Bars 57-72: Drop 2 — euphoric, major key, full energy
# Bars 73-80: Outro — filtering down, kick rides out
# Bars 81-96: Fade — minimal, echoes
# ═══════════════════════════════════════════════════════════════════
K = DrumSound.KICK
S = DrumSound.SNARE
CL = DrumSound.CLAP
CH = DrumSound.CLOSED_HAT
OH = DrumSound.OPEN_HAT
# ── KICK — four on the floor, the heartbeat ────────────────────
kick = score.part("kick", volume=0.5, humanize=0.03)
prog = key.progression("i", "VI", "VII", "i")
# Bars 1-24: kick from the start
for _ in range(24):
for beat in range(4):
kick.hit(K, Duration.QUARTER, velocity=115)
# ═══════════════════════════════════════════════════════════════════
# STRUCTURE (128 bars, ~6 min at 128 BPM):
# Bars 1-16: Portishead — dark, downtempo feel, scratchy
# Bars 17-32: The arp emerges from the darkness
# Bars 33-48: Pad swells, arp grows, still no kick
# Bars 49-64: Kick arrives — release, the Strobe moment
# Bars 65-80: Full energy, filter wide open
# Bars 81-96: Peak — everything singing
# Bars 97-112: Filtering down, layers drop
# Bars 113-128: Just the arp and pad, dissolving
# ═══════════════════════════════════════════════════════════════════
# Bars 25-32: breakdown — kick drops out
# ── RHODES — Portishead dark chords, sparse, tremolo ────────────
rhodes = score.part("rhodes", instrument="electric_piano", volume=0.3,
reverb=0.5, reverb_type="taj_mahal",
tremolo_depth=0.2, tremolo_rate=2.5,
humanize=0.1)
# Bars 1-16: dark sparse chords — Portishead vibe
for _ in range(4):
for chord in prog:
rhodes.add(chord, Duration.HALF, velocity=70)
rhodes.rest(Duration.HALF)
# Bars 17-32: thinner, making room for the arp
for _ in range(4):
for chord in prog:
rhodes.add(chord, Duration.QUARTER, velocity=55)
rhodes.rest(Duration.DOTTED_HALF)
# Bars 33-48: fading out
for _ in range(2):
for chord in prog:
rhodes.add(chord, Duration.QUARTER, velocity=40)
rhodes.rest(Duration.DOTTED_HALF)
for _ in range(8):
kick.rest(Duration.WHOLE)
rhodes.rest(Duration.WHOLE)
# Bars 33-72: kick returns for both drops
for _ in range(40):
for beat in range(4):
kick.hit(K, Duration.QUARTER, velocity=118)
# Bars 49-128: gone
for _ in range(80):
rhodes.rest(Duration.WHOLE)
# Bars 73-96: outro, fading via velocity
for bar in range(24):
vel = max(30, 115 - bar * 4)
for beat in range(4):
kick.hit(K, Duration.QUARTER, velocity=vel)
# ── TRIP-HOP BEAT — Portishead style, bars 5-32 ────────────────
trip = score.part("trip_hop", volume=0.3, humanize=0.08,
reverb=0.15, reverb_decay=0.6)
# ── CLAP — on 2 and 4 ──────────────────────────────────────────
clap = score.part("clap", volume=0.35, reverb=0.2, reverb_decay=0.5,
humanize=0.04)
# Bars 1-4: silence — let rhodes breathe
for _ in range(4):
trip.rest(Duration.WHOLE)
# Bars 1-8: no clap yet
# Bars 5-16: slow, lazy breakbeat — Portishead pocket
S = DrumSound.SNARE
for _ in range(12):
trip.hit(K, Duration.QUARTER, velocity=90)
trip.rest(Duration.EIGHTH)
trip.hit(CH, Duration.EIGHTH, velocity=50)
trip.hit(S, Duration.QUARTER, velocity=85)
trip.hit(CH, Duration.EIGHTH, velocity=48)
trip.hit(K, Duration.EIGHTH, velocity=75)
# Bars 17-24: beat thins out
for _ in range(8):
clap.rest(Duration.WHOLE)
trip.hit(K, Duration.QUARTER, velocity=70)
trip.rest(Duration.QUARTER)
trip.hit(S, Duration.QUARTER, velocity=60)
trip.rest(Duration.QUARTER)
# Bars 9-24: clap enters
for _ in range(16):
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=95)
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=98)
# Bars 25-32: breakdown — clap out
for _ in range(8):
clap.rest(Duration.WHOLE)
# Bars 33-72: clap through both drops
for _ in range(40):
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=100)
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=102)
# Bars 73-96: fading
for bar in range(24):
vel = max(30, 100 - bar * 3)
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=vel)
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=vel)
# ── HATS — offbeat 8ths, deadmau5 style ────────────────────────
hats = score.part("hats", volume=0.3, humanize=0.04)
# Bars 1-8: no hats
for _ in range(8):
hats.rest(Duration.WHOLE)
# Bars 9-24: offbeat closed hats
for _ in range(16):
for beat in range(4):
hats.rest(Duration.EIGHTH)
hats.hit(CH, Duration.EIGHTH, velocity=72)
# Bars 25-32: breakdown — open hat rolls building
# Bars 25-32: just ghost hits, disappearing
for bar in range(8):
for beat in range(4):
hats.rest(Duration.EIGHTH)
vel = min(95, 50 + bar * 5 + beat)
hats.hit(OH if bar > 5 else CH, Duration.EIGHTH, velocity=vel)
vel = max(20, 60 - bar * 5)
trip.hit(K, Duration.QUARTER, velocity=vel)
trip.rest(Duration.DOTTED_HALF)
# Bars 33-72: hats through drops — offbeat 8ths
for _ in range(40):
for beat in range(4):
hats.rest(Duration.EIGHTH)
hats.hit(CH, Duration.EIGHTH, velocity=75)
# Bars 33-128: gone
for _ in range(96):
trip.rest(Duration.WHOLE)
# Bars 73-96: fading
for bar in range(24):
vel = max(25, 75 - bar * 2)
for beat in range(4):
hats.rest(Duration.EIGHTH)
hats.hit(CH, Duration.EIGHTH, velocity=vel)
# ── THE ARP — the soul of the track, enters quietly bar 17 ─────
arp = score.part("arp", synth="saw", envelope="pluck", volume=0.2,
reverb=0.3, delay=0.4, delay_time=0.234,
delay_feedback=0.45, lowpass=1200, detune=6,
humanize=0.04)
# Slow filter open over the entire track
arp.lfo("lowpass", rate=0.008, min=800, max=6000, bars=128, shape="saw")
# ── BASS — sidechained sub, minimal ────────────────────────────
bass = score.part("bass", synth="saw", envelope="pluck", volume=0.4,
lowpass=300, distortion=0.15, distortion_drive=2.5,
# Bars 1-16: silence
for _ in range(16):
arp.rest(Duration.WHOLE)
# The pattern — hypnotic, never changes, just grows
arp_pattern = [
F, None, C.add(12), None,
Eb, None, C.add(12), Ab,
F, None, C.add(12), None,
Ab, None, Eb, C.add(12),
]
# Bars 17-32: arp emerges, barely audible
for _ in range(4):
for note in arp_pattern:
if note is None:
arp.rest(Duration.SIXTEENTH)
else:
arp.add(note, Duration.SIXTEENTH, velocity=50)
# Bars 33-48: arp grows
for _ in range(4):
for note in arp_pattern:
if note is None:
arp.rest(Duration.SIXTEENTH)
else:
arp.add(note, Duration.SIXTEENTH, velocity=65)
# Bars 49-64: kick arrives, arp confident
for _ in range(4):
for note in arp_pattern:
if note is None:
arp.rest(Duration.SIXTEENTH)
else:
arp.add(note, Duration.SIXTEENTH, velocity=80)
# Bars 65-96: full energy, arp singing
for _ in range(8):
for note in arp_pattern:
if note is None:
arp.rest(Duration.SIXTEENTH)
else:
arp.add(note, Duration.SIXTEENTH, velocity=90)
# Bars 97-112: filtering down
for _ in range(4):
for note in arp_pattern:
if note is None:
arp.rest(Duration.SIXTEENTH)
else:
arp.add(note, Duration.SIXTEENTH, velocity=70)
# Bars 113-128: dissolving
for rep in range(4):
vel = max(25, 60 - rep * 10)
for note in arp_pattern:
if note is None:
arp.rest(Duration.SIXTEENTH)
else:
arp.add(note, Duration.SIXTEENTH, velocity=vel)
# ── PAD — supersaw atmosphere, builds imperceptibly ─────────────
pad = score.part("pad", synth="supersaw", envelope="pad", volume=0.15,
reverb=0.6, chorus=0.4, chorus_rate=0.2,
chorus_depth=0.01, lowpass=600)
pad.lfo("lowpass", rate=0.008, min=400, max=5000, bars=128, shape="triangle")
# Bars 1-16: dark, barely there
for _ in range(4):
for chord in prog:
pad.add(chord, Duration.WHOLE, velocity=40)
# Bars 17-48: slowly swelling
for _ in range(8):
for chord in prog:
pad.add(chord, Duration.WHOLE, velocity=55)
# Bars 49-96: full, warm
for _ in range(12):
for chord in prog:
pad.add(chord, Duration.WHOLE, velocity=70)
# Bars 97-128: fading
for rep in range(8):
vel = max(20, 65 - rep * 6)
for chord in prog:
pad.add(chord, Duration.WHOLE, velocity=vel)
# ── BASS — enters with the kick, bar 49 ────────────────────────
bass = score.part("bass", synth="saw", envelope="pluck", volume=0.35,
lowpass=250, distortion=0.15, distortion_drive=2.5,
sub_osc=0.5)
# Bars 1-8: no bass
for _ in range(8):
# Bars 1-48: silence
for _ in range(48):
bass.rest(Duration.WHOLE)
# Bars 9-32: dark bass line — F minor
bass_dark = [
# Bars 49-96: the groove
bass_line = [
(F.add(-24), Duration.EIGHTH), (None, Duration.EIGHTH),
(F.add(-24), Duration.EIGHTH), (None, Duration.EIGHTH),
(F.add(-24), Duration.EIGHTH), (None, Duration.QUARTER),
(Ab.add(-24), Duration.EIGHTH),
]
for _ in range(6):
for note, dur in bass_dark:
for _ in range(12):
for note, dur in bass_line:
if note is None:
bass.rest(dur)
else:
bass.add(note, dur, velocity=100)
# Bars 33-48: drop 1 bass — heavier, same pattern
for _ in range(4):
for note, dur in bass_dark:
# Bars 97-128: fading
for rep in range(8):
vel = max(20, 90 - rep * 10)
for note, dur in bass_line:
if note is None:
bass.rest(dur)
else:
bass.add(note, dur, velocity=110)
bass.add(note, dur, velocity=vel)
# Bars 49-56: breakdown 2 — bass sustains
for _ in range(4):
bass.add(F.add(-24), Duration.WHOLE, velocity=85)
for _ in range(4):
bass.add(Ab.add(-24), Duration.WHOLE, velocity=85)
# ── KICK — the Strobe moment, enters bar 49 ────────────────────
kick = score.part("kick", volume=0.5, humanize=0.03)
# Bars 57-72: drop 2 — euphoric bass, Ab major
bass_bright = [
(Ab.add(-24), Duration.EIGHTH), (None, Duration.EIGHTH),
(Ab.add(-24), Duration.EIGHTH), (None, Duration.EIGHTH),
(Ab.add(-24), Duration.EIGHTH), (None, Duration.QUARTER),
(Eb.add(-24), Duration.EIGHTH),
# Bars 1-48: no kick — this IS the point
for _ in range(48):
kick.rest(Duration.WHOLE)
# Bars 49-96: four on the floor — the release
for _ in range(48):
for beat in range(4):
kick.hit(K, Duration.QUARTER, velocity=115)
# Bars 97-112: kick continues, stable
for _ in range(16):
for beat in range(4):
kick.hit(K, Duration.QUARTER, velocity=108)
# Bars 113-128: kick fades last — the final heartbeat
for bar in range(16):
vel = max(25, 105 - bar * 5)
for beat in range(4):
kick.hit(K, Duration.QUARTER, velocity=vel)
# ── CLAP — with the kick ───────────────────────────────────────
clap = score.part("clap", volume=0.3, reverb=0.15, humanize=0.04)
# Bars 1-48: silence
for _ in range(48):
clap.rest(Duration.WHOLE)
# Bars 49-96: 2 and 4
for _ in range(48):
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=95)
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=98)
# Bars 97-128: fading
for bar in range(32):
vel = max(20, 95 - bar * 2)
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=vel)
clap.rest(Duration.QUARTER)
clap.hit(CL, Duration.QUARTER, velocity=vel)
# ── HATS — offbeat, with the kick ──────────────────────────────
hats = score.part("hats", volume=0.25, humanize=0.04)
# Bars 1-48: silence
for _ in range(48):
hats.rest(Duration.WHOLE)
# Bars 49-96: offbeat 8ths
for _ in range(48):
for beat in range(4):
hats.rest(Duration.EIGHTH)
hats.hit(CH, Duration.EIGHTH, velocity=70)
# Bars 97-128: fading
for bar in range(32):
vel = max(20, 70 - bar * 2)
for beat in range(4):
hats.rest(Duration.EIGHTH)
hats.hit(CH, Duration.EIGHTH, velocity=vel)
# ── NES MELODY — emotional square wave, the heart of the peak ───
nes = score.part("nes", synth="square", envelope="organ", volume=0.2,
reverb=0.4, reverb_type="taj_mahal",
delay=0.3, delay_time=0.234, delay_feedback=0.4,
lowpass=4000, humanize=0.05)
# Bars 1-64: silence
for _ in range(64):
nes.rest(Duration.WHOLE)
# Bars 65-80: the emotional peak — simple, singing melody
nes_melody = [
(F.add(12), Duration.HALF, 85),
(Eb.add(12), Duration.QUARTER, 80),
(C.add(12), Duration.QUARTER, 78),
(Db.add(12), Duration.HALF, 82),
(C.add(12), Duration.HALF, 80),
(Ab, Duration.HALF, 78),
(Bb, Duration.QUARTER, 75),
(C.add(12), Duration.QUARTER, 80),
(F.add(12), Duration.WHOLE, 88),
]
for _ in range(4):
for note, dur in bass_bright:
if note is None:
bass.rest(dur)
else:
bass.add(note, dur, velocity=108)
for note, dur, vel in nes_melody:
nes.add(note, dur, velocity=vel)
# Bars 73-96: outro bass fading
for _ in range(6):
for note, dur in bass_dark:
if note is None:
bass.rest(dur)
else:
bass.add(note, dur, velocity=max(30, 90 - _ * 10))
# ── PAD — filtered supersaw, the atmosphere ─────────────────────
pad = score.part("pad", synth="supersaw", envelope="pad", volume=0.25,
reverb=0.5, chorus=0.4, chorus_rate=0.3, chorus_depth=0.008,
lowpass=800)
pad.lfo("lowpass", rate=0.02, min=400, max=4000, bars=96, shape="triangle")
# Dark pads — i VI VII throughout, slow chord changes
dark_prog = key_dark.progression("i", "VI", "VII", "i")
bright_prog = key_bright.progression("I", "V", "vi", "IV")
# Bars 1-32: dark pads
# Bars 81-96: melody fades
for rep in range(2):
vel_off = rep * 15
for note, dur, vel in nes_melody:
nes.add(note, dur, velocity=max(25, vel - vel_off))
for _ in range(8):
for chord in dark_prog:
pad.add(chord, Duration.WHOLE)
nes.rest(Duration.WHOLE)
# Bars 33-48: drop 1 — same chords, filter open
for _ in range(4):
for chord in dark_prog:
pad.add(chord, Duration.WHOLE)
# Bars 49-56: breakdown 2 — transition chords
for chord in dark_prog:
pad.add(chord, Duration.WHOLE)
for chord in bright_prog:
pad.add(chord, Duration.WHOLE)
# Bars 57-72: drop 2 — euphoric! major key pads
for _ in range(4):
for chord in bright_prog:
pad.add(chord, Duration.WHOLE)
# Bars 73-96: outro — back to minor, filtering down
for _ in range(6):
for chord in dark_prog:
pad.add(chord, Duration.WHOLE)
# ── LEAD — saw pluck, the hook ──────────────────────────────────
lead = score.part("lead", synth="saw", envelope="pluck", volume=0.3,
reverb=0.3, delay=0.35, delay_time=0.234,
delay_feedback=0.4, lowpass=3000, humanize=0.05)
# Bars 1-8: silence
for _ in range(8):
lead.rest(Duration.WHOLE)
# Bars 9-24: dark minimal lead — hypnotic 16th note pattern
lead_dark = [
F.add(12), None, C.add(12), None,
Eb.add(12), None, C.add(12), Bb,
F.add(12), None, C.add(12), None,
Ab.add(12), None, Eb.add(12), C.add(12),
]
for _ in range(4):
for note in lead_dark:
if note is None:
lead.rest(Duration.SIXTEENTH)
else:
lead.add(note, Duration.SIXTEENTH, velocity=85)
# Bars 25-32: breakdown — lead gets melodic
lead_melody = [
(F.add(12), Duration.HALF, 90),
(Eb.add(12), Duration.QUARTER, 85),
(Db.add(12), Duration.QUARTER, 80),
(C.add(12), Duration.HALF, 88),
(Bb, Duration.QUARTER, 82),
(Ab, Duration.QUARTER, 78),
(Bb, Duration.HALF, 85),
(C.add(12), Duration.QUARTER, 88),
(Db.add(12), Duration.QUARTER, 82),
(C.add(12), Duration.WHOLE, 90),
]
for note, dur, vel in lead_melody:
lead.add(note, dur, velocity=vel)
for _ in range(4):
lead.rest(Duration.WHOLE)
# Bars 33-48: drop 1 — lead returns, more intense
for _ in range(4):
for note in lead_dark:
if note is None:
lead.rest(Duration.SIXTEENTH)
else:
lead.add(note, Duration.SIXTEENTH, velocity=95)
# Bars 49-56: breakdown 2 — emotional melody, the turn
lead_turn = [
(Ab.add(12), Duration.HALF, 95),
(Bb.add(12), Duration.QUARTER, 90),
(C.add(24), Duration.QUARTER, 100),
(Bb.add(12), Duration.HALF, 92),
(Ab.add(12), Duration.QUARTER, 88),
(Eb.add(12), Duration.QUARTER, 85),
(Ab.add(12), Duration.HALF, 95),
(C.add(24), Duration.HALF, 105),
(Bb.add(12), Duration.WHOLE, 100),
(Ab.add(12), Duration.WHOLE, 95),
]
for note, dur, vel in lead_turn:
lead.add(note, dur, velocity=vel)
for _ in range(2):
lead.rest(Duration.WHOLE)
# Bars 57-72: drop 2 — euphoric lead! Ab major arps
lead_euphoric = [
Ab.add(12), None, C.add(24), None,
Eb.add(24), None, C.add(24), Ab.add(12),
Ab.add(12), None, Bb.add(12), None,
C.add(24), None, Eb.add(24), C.add(24),
]
for _ in range(4):
for note in lead_euphoric:
if note is None:
lead.rest(Duration.SIXTEENTH)
else:
lead.add(note, Duration.SIXTEENTH, velocity=100)
# Bars 73-96: outro — lead dissolves
for _ in range(2):
for note in lead_dark:
if note is None:
lead.rest(Duration.SIXTEENTH)
else:
lead.add(note, Duration.SIXTEENTH, velocity=65)
for _ in range(20):
lead.rest(Duration.WHOLE)
# ── PLUCK — deadmau5 signature stab chord ──────────────────────
pluck = score.part("pluck", synth="saw", envelope="pluck", volume=0.2,
reverb=0.25, delay=0.2, delay_time=0.234,
delay_feedback=0.35, lowpass=2500, detune=8,
humanize=0.04)
# Bars 1-32: silence
# Bars 97-128: silence
for _ in range(32):
nes.rest(Duration.WHOLE)
# ── PLUCK STABS — offbeat chords, bars 65-96 ───────────────────
pluck = score.part("pluck", synth="saw", envelope="pluck", volume=0.18,
reverb=0.2, delay=0.2, delay_time=0.234,
delay_feedback=0.3, lowpass=2500, detune=8)
# Bars 1-64: silence
for _ in range(64):
pluck.rest(Duration.WHOLE)
# Bars 33-48: drop 1 — offbeat chord stabs
for _ in range(4):
for chord in dark_prog:
pluck.rest(Duration.EIGHTH)
pluck.add(chord, Duration.EIGHTH, velocity=90)
pluck.rest(Duration.QUARTER)
# Bars 65-96: the peak — offbeat stabs
for _ in range(8):
for chord in prog:
pluck.rest(Duration.EIGHTH)
pluck.add(chord, Duration.EIGHTH, velocity=85)
pluck.rest(Duration.QUARTER)
# Bars 49-56: breakdown — silence
for _ in range(8):
pluck.rest(Duration.WHOLE)
# Bars 57-72: drop 2 — euphoric stabs
for _ in range(4):
for chord in bright_prog:
pluck.rest(Duration.EIGHTH)
pluck.add(chord, Duration.EIGHTH, velocity=95)
pluck.rest(Duration.QUARTER)
pluck.rest(Duration.EIGHTH)
pluck.add(chord, Duration.EIGHTH, velocity=90)
pluck.add(chord, Duration.EIGHTH, velocity=80)
pluck.rest(Duration.QUARTER)
# Bars 73-96: silence
for _ in range(24):
# Bars 97-128: silence
for _ in range(32):
pluck.rest(Duration.WHOLE)
# ── RISER — noise sweep for breakdowns ──────────────────────────
riser = score.part("riser", synth="noise", envelope="pad", volume=0.15,
lowpass=200)
riser.lfo("lowpass", rate=0.125, min=200, max=8000, bars=8, shape="saw")
# Bars 1-24: silence
for _ in range(24):
riser.rest(Duration.WHOLE)
# Bars 25-32: first riser
for _ in range(8):
riser.add(C, Duration.WHOLE, velocity=80)
# Bars 33-48: silence
for _ in range(16):
riser.rest(Duration.WHOLE)
# Bars 49-56: second riser (bigger)
riser.lfo("lowpass", rate=0.125, min=200, max=10000, bars=8, shape="saw")
for _ in range(8):
riser.add(C, Duration.WHOLE, velocity=90)
# Bars 57-96: silence
for _ in range(40):
riser.rest(Duration.WHOLE)
# ═════════════════════════════════════════════════════════════════
import sys
print(f"Key: {key_dark}{key_bright}")
print(f"Key: {key}")
print(f"BPM: 128")
print(f"Parts: {list(score.parts.keys())}")
print(f"Duration: {score.duration_ms / 1000:.1f}s | {score.measures} measures")