From fe8efa72bea763c368bd8bc8f027db619b294d44 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 30 Mar 2026 05:08:19 -0400 Subject: [PATCH] =?UTF-8?q?Ghost=20Protocol:=20Portishead=20intro=20?= =?UTF-8?q?=E2=86=92=20Strobe=20build,=20NES=20emotional=20peak?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- tracks/ghost_protocol.py | 611 +++++++++++++++++++-------------------- 1 file changed, 293 insertions(+), 318 deletions(-) diff --git a/tracks/ghost_protocol.py b/tracks/ghost_protocol.py index f5228c4..278b56a 100644 --- a/tracks/ghost_protocol.py +++ b/tracks/ghost_protocol.py @@ -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")