Silk Road: dry-to-wet koto, tabla grows with caravan, remove Culture Clash

Koto starts bone dry, reverb fades in like mist over 16 bars.
Tabla volume/velocity increases as each civilization joins.
Culture Clash removed for rework.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-01 22:21:08 -04:00
parent ac36b3ace2
commit 1123e773e4
4 changed files with 94 additions and 724 deletions
+10 -11
View File
@@ -18,17 +18,16 @@ Each track is a `.py` file. Run it to hear it.
## Tracks
1. **Raga Midnight** — D Phrygian (Bhairavi), shruti just intonation, 90 BPM. Tabla, sitar, tambura, dhol. Hand-written tabla solo with tihai cadence.
2. **Culture Clash** — D minor, 95 BPM. Didgeridoo drone, Rhodes, tabla with fills, sitar arps, NES Mario theme, Hotline Bling on steel drum, theremin solo, marching snare military finale with DCI cadence. 808 sub bass throughout.
3. **Chakra** — Root to crown frequency activation journey. Shruti tuning at A=432 Hz. Ukulele opening, singing bowls, harmonium, tambura, sitar, theremin. Metric modulation tempo changes (60 → 90 → 108 → 135 BPM) ascending through seven chakras.
4. **Ghost Protocol**F minor, 128 BPM. Portishead-style dark Rhodes intro with trip-hop beat, morphing into a Strobe-inspired hypnotic build. Saw arp emerges, kick doesn't arrive until bar 49. NES square wave melody at the emotional peak.
5. **Acid Reign**A minor, 140 BPM. Dual 303 acid bass lines (saw + square) with resonant filter sweeps (Q up to 20). Cajon in cathedral reverb, Rhodes pad, 808 sub. Five hand-written groove patterns.
6. **Silk Road**D minor, 95 BPM. A caravan picking up musicians along the ancient trade route. Koto solo (China) → sitar + tabla (India) → mandolin + doumbek (Persia) → guitar + cajon (Mediterranean) → all together. Nobody leaves, everyone adds their voice.
7. **Deep Time**B minor, 40 BPM, just intonation. Ambient drone. Tingsha, rainstick, finger cymbals, singing bowls, didgeridoo, sine drones, harmonium, theremin, choir, cello. 7.5 minutes of deep listening.
8. **The Interruption** — D minor, 85 BPM. A baroque harpsichord and string quartet playing beautifully. Then at bar 33, a drum & bass breakbeat slams in with sub bass and reese. The strings keep playing like nothing happened. The beat dissolves, the quartet wins.
9. **The Temple**A Phrygian (Bhairavi), 65 BPM, shruti just intonation, A=432 Hz. Devotional layers inside a vast stone chamber. Singing bowls, tambura drone, harmonium, sitar, bansuri, tabla. The reverb is the instrument. Everything enters slowly, sings together, then dissolves back into silence.
10. **The Dialogue** — E Phrygian (Bhairavi), 75 BPM, shruti just intonation, A=432 Hz. Sitar (human) and theremin (machine) start alone, find each other through call-and-response, and become something neither could be on their own. House beat enters when they find the groove.
11. **Voltage**F minor, 138 BPM. Raw oscillators, nothing else. Sine sub, saw lead, pulse counter-rhythm. Rhythm is pitch. Saw arp solo, pulse arp solo, 32nd note chaos at the peak. Aggressive, monophonic, electric.
12. **The Observatory** — G minor, 112 BPM. Chapel harmonies broadcast through shortwave static. Radio hiss, singing bowl, square-wave organ, choir, saw arp, supersaw halo pad, theremin signal melody. Patient house pulse arrives at bar 33.
2. **Chakra** — Root to crown frequency activation journey. Shruti tuning at A=432 Hz. Ukulele opening, singing bowls, harmonium, tambura, sitar, theremin. Metric modulation tempo changes (60 → 90 → 108 → 135 BPM) ascending through seven chakras.
3. **Ghost Protocol** — F minor, 128 BPM. Portishead-style dark Rhodes intro with trip-hop beat, morphing into a Strobe-inspired hypnotic build. Saw arp emerges, kick doesn't arrive until bar 49. NES square wave melody at the emotional peak.
4. **Acid Reign**A minor, 140 BPM. Dual 303 acid bass lines (saw + square) with resonant filter sweeps (Q up to 20). Cajon in cathedral reverb, Rhodes pad, 808 sub. Five hand-written groove patterns.
5. **Silk Road**D minor, 95 BPM. A caravan picking up musicians along the ancient trade route. Koto solo (China) → sitar + tabla (India) → mandolin + doumbek (Persia) → guitar + cajon (Mediterranean) → all together. Nobody leaves, everyone adds their voice.
6. **Deep Time**B minor, 40 BPM, just intonation. Ambient drone. Tingsha, rainstick, finger cymbals, singing bowls, didgeridoo, sine drones, harmonium, theremin, choir, cello. 7.5 minutes of deep listening.
7. **The Interruption**D minor, 85 BPM. A baroque harpsichord and string quartet playing beautifully. Then at bar 33, a drum & bass breakbeat slams in with sub bass and reese. The strings keep playing like nothing happened. The beat dissolves, the quartet wins.
8. **The Temple** — A Phrygian (Bhairavi), 65 BPM, shruti just intonation, A=432 Hz. Devotional layers inside a vast stone chamber. Singing bowls, tambura drone, harmonium, sitar, bansuri, tabla. The reverb is the instrument. Everything enters slowly, sings together, then dissolves back into silence.
9. **The Dialogue**E Phrygian (Bhairavi), 75 BPM, shruti just intonation, A=432 Hz. Sitar (human) and theremin (machine) start alone, find each other through call-and-response, and become something neither could be on their own. House beat enters when they find the groove.
10. **Voltage** — F minor, 138 BPM. Raw oscillators, nothing else. Sine sub, saw lead, pulse counter-rhythm. Rhythm is pitch. Saw arp solo, pulse arp solo, 32nd note chaos at the peak. Aggressive, monophonic, electric.
11. **The Observatory**G minor, 112 BPM. Chapel harmonies broadcast through shortwave static. Radio hiss, singing bowl, square-wave organ, choir, saw arp, supersaw halo pad, theremin signal melody. Patient house pulse arrives at bar 33.
## Usage
-1
View File
@@ -40,7 +40,6 @@ TRACKS_DIR = Path(__file__).parent / "tracks"
# Album order — defines the canonical tracklist
ALBUM_ORDER = [
"raga_midnight.py",
"culture_clash.py",
"chakra.py",
"ghost_protocol.py",
"acid_reign.py",
-704
View File
@@ -1,704 +0,0 @@
"""
CULTURE CLASH — didgeridoo chord → rhodes → tabla/sitar pop progression →
NES Mario meets Drake → marching snare military finale over 808 fadeout.
A fever dream of musical tourism. ~4 minutes.
"""
from pytheory import Key, Duration, Score, Tone, play_score
from pytheory.rhythm import DrumSound
# ── Key: C major ────────────────────────────────────────────────
key = Key("D", "minor")
s = key.scale
prog = key.progression("i", "VII", "VI", "iv") # Dm - C - Bb - Gm
C = Tone.from_string("C4")
D = s[0]; E = s[1]; F = s[2]; G = s[3]
A = s[4]; Bb = s[5]; Cs = s[6] # C#/Db for leading tone
score = Score("4/4", bpm=95)
# Tabla bols
NA = DrumSound.TABLA_NA
TIT = DrumSound.TABLA_TIT
GE = DrumSound.TABLA_GE
tDHA = DrumSound.TABLA_DHA
KE = DrumSound.TABLA_KE
GEB = DrumSound.TABLA_GE_BEND
MR = DrumSound.MARCH_SNARE
# ═══════════════════════════════════════════════════════════════════
# STRUCTURE (64 bars, ~4 minutes at 95 BPM):
# Bars 1-8: Didgeridoo chord + Rhodes
# Bars 9-24: Tabla + sitar arp (I-V-vi-IV), 808 enters
# Bars 25-40: NES Mario × Drake mashup, tabla continues
# Bars 41-56: Marching snare builds, 808 drives
# Bars 57-64: Military snare crescendo, everything fades, final hit
# ═══════════════════════════════════════════════════════════════════
# # ── INTRO — Nokia ringtone (commented out)
# intro = score.part("intro", synth="pulse", envelope="staccato", volume=0.35,
# lowpass=4000)
# intro.add(E.add(12), Duration.EIGHTH, velocity=95)
# intro.add(D.add(12), Duration.EIGHTH, velocity=90)
# intro.add(Tone.from_string("F#4"), Duration.QUARTER, velocity=88)
# intro.add(Tone.from_string("G#4"), Duration.QUARTER, velocity=85)
# intro.add(Tone.from_string("C#5"), Duration.EIGHTH, velocity=90)
# intro.add(Tone.from_string("B4"), Duration.EIGHTH, velocity=85)
# intro.add(D, Duration.QUARTER, velocity=82)
# intro.add(E, Duration.QUARTER, velocity=80)
# intro.rest(Duration.WHOLE)
# for _ in range(62):
# intro.rest(Duration.WHOLE)
# ── DRUMS — four on the floor, snare on 2 & 4, trap hats ───────
drums = score.part("kit", volume=0.65, humanize=0.06)
# Bars 1-8: rests
for _ in range(8):
drums.rest(Duration.WHOLE)
# Bars 9-56: kick + snare + trap hats
K = DrumSound.KICK
S = DrumSound.SNARE
CH = DrumSound.CLOSED_HAT
OH = DrumSound.OPEN_HAT
for bar in range(48):
if bar % 8 == 7:
# FILL BAR — snare rolls + kick accents
drums.hit(S, Duration.SIXTEENTH, velocity=100)
drums.hit(S, Duration.SIXTEENTH, velocity=65)
drums.hit(S, Duration.SIXTEENTH, velocity=70)
drums.hit(K, Duration.SIXTEENTH, velocity=105)
drums.hit(S, Duration.SIXTEENTH, velocity=105)
drums.hit(S, Duration.SIXTEENTH, velocity=68)
drums.hit(S, Duration.SIXTEENTH, velocity=72)
drums.hit(K, Duration.SIXTEENTH, velocity=108)
drums.hit(S, Duration.SIXTEENTH, velocity=110)
drums.hit(S, Duration.SIXTEENTH, velocity=70)
drums.hit(K, Duration.SIXTEENTH, velocity=112)
drums.hit(S, Duration.SIXTEENTH, velocity=75)
drums.hit(K, Duration.SIXTEENTH, velocity=115)
drums.hit(S, Duration.SIXTEENTH, velocity=118, articulation="accent")
drums.hit(OH, Duration.SIXTEENTH, velocity=90)
drums.hit(K, Duration.SIXTEENTH, velocity=120, articulation="accent")
else:
# Normal bar
# Beat 1: kick + hat
drums.hit(K, Duration.SIXTEENTH, velocity=110)
drums.hit(CH, Duration.SIXTEENTH, velocity=55)
drums.hit(CH, Duration.SIXTEENTH, velocity=45)
drums.hit(CH, Duration.SIXTEENTH, velocity=50)
# Beat 2: snare + hat
drums.hit(S, Duration.SIXTEENTH, velocity=105)
drums.hit(CH, Duration.SIXTEENTH, velocity=55)
drums.hit(CH, Duration.SIXTEENTH, velocity=42)
drums.hit(CH, Duration.SIXTEENTH, velocity=48)
# Beat 3: kick + hat (open hat on the &)
drums.hit(K, Duration.SIXTEENTH, velocity=108)
drums.hit(CH, Duration.SIXTEENTH, velocity=55)
drums.hit(OH, Duration.SIXTEENTH, velocity=60)
drums.hit(CH, Duration.SIXTEENTH, velocity=45)
# Beat 4: snare + hat rolls
drums.hit(S, Duration.SIXTEENTH, velocity=108)
drums.hit(CH, Duration.SIXTEENTH, velocity=52)
drums.hit(CH, Duration.SIXTEENTH, velocity=48)
drums.hit(CH, Duration.SIXTEENTH, velocity=55)
# Bars 57-64: fading via velocity
for bar in range(8):
v = max(10, 100 - bar * 12)
drums.hit(K, Duration.QUARTER, velocity=v)
drums.hit(S, Duration.QUARTER, velocity=max(10, v - 10))
drums.hit(K, Duration.QUARTER, velocity=max(10, v - 5))
drums.hit(S, Duration.QUARTER, velocity=max(10, v - 15))
# ── DIDGERIDOO CHORD — two drones a fifth apart ────────────────
didge_lo = score.part("didge_lo", instrument="didgeridoo", volume=0.45,
lowpass=250)
didge_hi = score.part("didge_hi", instrument="didgeridoo", volume=0.35,
lowpass=300, pan=0.2)
# Bars 1-8: drone chord (D2 + A2)
for _ in range(8):
didge_lo.add(D.add(-24), Duration.WHOLE, velocity=75)
didge_hi.add(A.add(-24), Duration.WHOLE, velocity=65)
# Bars 9-12: fading
for vel in [60, 50, 35, 20]:
didge_lo.add(D.add(-24), Duration.WHOLE, velocity=vel)
didge_hi.add(A.add(-24), Duration.WHOLE, velocity=vel)
# Bars 13-56: silent
for _ in range(44):
didge_lo.rest(Duration.WHOLE)
didge_hi.rest(Duration.WHOLE)
# Bars 57-64: DIDGE RETURNS — massive, under the snare crescendo
for vel in [60, 75, 90, 100, 110, 115, 120, 127]:
didge_lo.add(D.add(-24), Duration.WHOLE, velocity=vel)
didge_hi.add(A.add(-24), Duration.WHOLE, velocity=vel)
# ── RHODES — from bar 1, the harmonic anchor ───────────────────
rhodes = score.part("rhodes", instrument="electric_piano", volume=0.35,
reverb=0.6, reverb_type="taj_mahal",
chorus=0.3, chorus_rate=0.4, chorus_depth=0.005,
tremolo_depth=0.12, tremolo_rate=3.5, humanize=0.08)
# Bars 1-8
for _ in range(2):
for chord in prog:
rhodes.add(chord, Duration.WHOLE)
# Bars 9-24: full chords under tabla/sitar
for _ in range(4):
for chord in prog:
rhodes.add(chord, Duration.WHOLE)
# Bars 25-40: choppy stabs under Mario/Drake
for _ in range(4):
for chord in prog:
rhodes.add(chord, Duration.QUARTER)
rhodes.rest(Duration.QUARTER)
rhodes.add(chord, Duration.QUARTER)
rhodes.rest(Duration.QUARTER)
# Bars 41-56: half notes, thinning — making room for theremin
for _ in range(4):
for chord in prog:
rhodes.add(chord, Duration.HALF)
rhodes.rest(Duration.HALF)
# ── THEREMIN SOLO — wailing over the chaos (bars 41-52) ─────────
theremin = score.part("theremin", instrument="theremin", volume=0.6,
reverb=0.5, reverb_type="taj_mahal",
delay=0.3, delay_time=0.316, delay_feedback=0.35,
pan=0.25, humanize=0.06)
# Bars 1-40: silent
for _ in range(40):
theremin.rest(Duration.WHOLE)
# Bars 41-42: entrance — slow, eerie, one long note bending up
theremin.add(A, Duration.WHOLE, velocity=90, bend=1.5)
theremin.add(D.add(12), Duration.HALF, velocity=95)
theremin.add(F.add(12), Duration.HALF, velocity=100, bend=-0.5)
# Bars 43-44: the solo takes off — expressive, vocal-like
theremin.add(A.add(12), Duration.QUARTER, velocity=110, bend=0.5)
theremin.add(G.add(12), Duration.EIGHTH, velocity=95)
theremin.add(F.add(12), Duration.EIGHTH, velocity=90)
theremin.add(D.add(12), Duration.HALF, velocity=100, bend=-0.25)
theremin.add(F.add(12), Duration.QUARTER, velocity=105, bend=1.0)
theremin.add(A.add(12), Duration.QUARTER, velocity=112)
theremin.add(D.add(24), Duration.QUARTER, velocity=115, bend=-0.5)
theremin.add(A.add(12), Duration.QUARTER, velocity=100)
# Bars 45-46: climax — reaching for the top, crying
theremin.add(D.add(24), Duration.HALF, velocity=120, bend=2.0)
theremin.add(A.add(12), Duration.QUARTER, velocity=105, bend=0.5)
theremin.add(F.add(12), Duration.QUARTER, velocity=100)
theremin.add(G.add(12), Duration.QUARTER, velocity=110, bend=1.0)
theremin.add(A.add(12), Duration.QUARTER, velocity=115, bend=1.5)
theremin.add(D.add(24), Duration.HALF, velocity=125, bend=-1.0)
# Bars 47-48: fast vibrato-like passages
theremin.add(D.add(24), Duration.EIGHTH, velocity=115, bend=-0.25)
theremin.add(Cs.add(12), Duration.EIGHTH, velocity=100)
theremin.add(D.add(24), Duration.EIGHTH, velocity=118, bend=0.25)
theremin.add(Cs.add(12), Duration.EIGHTH, velocity=100)
theremin.add(A.add(12), Duration.QUARTER, velocity=110, bend=0.5)
theremin.add(F.add(12), Duration.QUARTER, velocity=105, bend=-0.5)
theremin.add(D.add(12), Duration.QUARTER, velocity=100, bend=1.0)
theremin.add(A, Duration.QUARTER, velocity=95)
theremin.add(D.add(12), Duration.HALF, velocity=108, bend=-0.25)
# Bars 49-50: descending, fading — handing off to the mario solo
theremin.add(A, Duration.QUARTER, velocity=90, bend=0.5)
theremin.add(G, Duration.QUARTER, velocity=80)
theremin.add(F, Duration.QUARTER, velocity=75, bend=-0.5)
theremin.add(D, Duration.QUARTER, velocity=70)
theremin.add(A.add(-12), Duration.WHOLE, velocity=60, bend=-1.0)
# Bars 51-52: last gasp
theremin.add(D, Duration.WHOLE, velocity=45, bend=0.5)
theremin.add(D, Duration.WHOLE, velocity=25)
# Bars 53-64: silent
for _ in range(12):
theremin.rest(Duration.WHOLE)
# Bars 57-64: silent
for _ in range(8):
rhodes.rest(Duration.WHOLE)
# ── TABLA — enters bar 9 ───────────────────────────────────────
tabla = score.part("tabla", volume=0.35,
reverb=0.3, reverb_decay=1.2, humanize=0.08)
# Bars 1-8: rests
for _ in range(8):
tabla.rest(Duration.WHOLE)
# Bars 9-40: keherwa groove with fills every 4 bars
for bar in range(32):
if bar % 4 == 3:
tabla.hit(tDHA, Duration.EIGHTH, velocity=100, articulation="accent")
tabla.hit(GEB, Duration.EIGHTH, velocity=115)
tabla.hit(NA, Duration.EIGHTH, velocity=80)
tabla.hit(GEB, Duration.EIGHTH, velocity=110)
tabla.hit(tDHA, Duration.EIGHTH, velocity=95, articulation="accent")
tabla.hit(NA, Duration.SIXTEENTH, velocity=70)
tabla.hit(KE, Duration.SIXTEENTH, velocity=60)
tabla.hit(GEB, Duration.QUARTER, velocity=120)
else:
tabla.hit(tDHA, Duration.EIGHTH, velocity=95, articulation="accent")
tabla.hit(GE, Duration.EIGHTH, velocity=65)
tabla.hit(NA, Duration.EIGHTH, velocity=75)
tabla.hit(TIT, Duration.EIGHTH, velocity=50)
tabla.hit(NA, Duration.EIGHTH, velocity=70)
tabla.hit(TIT, Duration.EIGHTH, velocity=45)
tabla.hit(tDHA, Duration.EIGHTH, velocity=88, articulation="accent")
tabla.hit(NA, Duration.EIGHTH, velocity=68)
# Bars 41-48: fading via velocity
for bar in range(8):
tabla.hit(tDHA, Duration.EIGHTH, velocity=70)
tabla.hit(GE, Duration.EIGHTH, velocity=45)
tabla.hit(NA, Duration.EIGHTH, velocity=55)
tabla.hit(TIT, Duration.EIGHTH, velocity=35)
tabla.hit(NA, Duration.EIGHTH, velocity=50)
tabla.hit(TIT, Duration.EIGHTH, velocity=32)
tabla.hit(tDHA, Duration.EIGHTH, velocity=65)
tabla.hit(NA, Duration.EIGHTH, velocity=48)
# Bars 49-64: silent
for _ in range(16):
tabla.rest(Duration.WHOLE)
# ── SITAR — I V vi IV arpeggiated (bars 9-32) ──────────────────
sitar = score.part("sitar", instrument="sitar", volume=0.8,
reverb=0.3, reverb_decay=1.5,
delay=0.35, delay_time=0.316, delay_feedback=0.4,
pan=-0.2, humanize=0.1)
# ── SITAR LOW — octave down double, thickens it up ─────────────
sitar_lo = score.part("sitar_lo", instrument="sitar", volume=0.5,
reverb=0.25, reverb_decay=1.2,
delay=0.2, delay_time=0.316, delay_feedback=0.3,
pan=0.15, humanize=0.1, lowpass=2000)
# Bars 1-8: rests
for _ in range(8):
sitar.rest(Duration.WHOLE)
sitar_lo.rest(Duration.WHOLE)
# Bars 9-24: arpeggiated pop progression
# i(Dm) - VII(C) - VI(Bb) - iv(Gm) arpeggiated
arp_chords = [
[D, F, A, D.add(12), A, F, D, A.add(-12)],
[C, E, G, C.add(12), G, E, C, G.add(-12)],
[Bb.add(-12), D, F, Bb, F, D, Bb.add(-12), F.add(-12)],
[G.add(-12), Bb.add(-12), D, G, D, Bb.add(-12), G.add(-12), D.add(-12)],
]
for _ in range(4):
for arp in arp_chords:
for note in arp:
sitar.add(note, Duration.EIGHTH, velocity=85)
sitar_lo.add(note.add(-12), Duration.EIGHTH, velocity=70)
# Bars 25-32: fading via velocity
for _ in range(2):
for arp in arp_chords:
for note in arp:
sitar.add(note, Duration.EIGHTH, velocity=55)
sitar_lo.add(note.add(-12), Duration.EIGHTH, velocity=40)
# Bars 33-64: silent
for _ in range(32):
sitar.rest(Duration.WHOLE)
sitar_lo.rest(Duration.WHOLE)
# ── NES MARIO — pulse wave (bars 25-56) ────────────────────────
mario = score.part("mario", synth="square", volume=0.2,
reverb=0.4, reverb_decay=1.5, lowpass=5000,
humanize=0.05)
# Bars 1-24: rests
for _ in range(24):
mario.rest(Duration.WHOLE)
# Bars 25-28: World 1-1 theme
mario_melody = [
(E.add(12), Duration.EIGHTH), (E.add(12), Duration.EIGHTH),
(None, Duration.EIGHTH), (E.add(12), Duration.EIGHTH),
(None, Duration.EIGHTH), (C.add(12), Duration.EIGHTH),
(E.add(12), Duration.QUARTER),
(G.add(12), Duration.QUARTER), (None, Duration.QUARTER),
(G, Duration.QUARTER), (None, Duration.QUARTER),
(C.add(12), Duration.QUARTER), (None, Duration.EIGHTH),
(G, Duration.EIGHTH), (None, Duration.QUARTER),
(E, Duration.QUARTER),
(None, Duration.EIGHTH), (A, Duration.QUARTER),
(Bb, Duration.QUARTER), (Tone.from_string("Bb4"), Duration.EIGHTH),
(A, Duration.QUARTER),
]
for note, dur in mario_melody:
if note is None:
mario.rest(dur)
else:
mario.add(note, dur, velocity=100)
# Bars 29-32: repeat
for note, dur in mario_melody:
if note is None:
mario.rest(dur)
else:
mario.add(note, dur, velocity=105)
# Bars 33-40: Mario keeps going — repeat the theme
for _ in range(2):
for note, dur in mario_melody:
if note is None:
mario.rest(dur)
else:
mario.add(note, dur, velocity=90)
# Bars 41-48: Mario keeps looping underneath drake
for _ in range(2):
for note, dur in mario_melody:
if note is None:
mario.rest(dur)
else:
mario.add(note, dur, velocity=75)
# Bars 49-52: one last Mario statement fading
for note, dur in mario_melody:
if note is None:
mario.rest(dur)
else:
mario.add(note, dur, velocity=70)
# ══ Bars 53-60: MARIO SOLO — emotional 8-bit shredding ═══════════
# The NES cries out. Fast arps climbing through D minor, getting
# faster and higher. Like watching Mario run out of time.
mario.set(volume=0.55)
# Bars 53-54: 16th note arps — establishing the run
solo_arps_16 = [
# Dm arp up and down
D, F, A, D.add(12), A, F, D, A.add(-12),
F, A, D.add(12), F.add(12), D.add(12), A, F, D,
# C arp
C, E, G, C.add(12), G, E, C, G.add(-12),
E, G, C.add(12), E.add(12), C.add(12), G, E, C,
]
for note in solo_arps_16:
mario.add(note, Duration.SIXTEENTH, velocity=105)
# Bars 55-56: 32nd notes — faster, climbing higher
solo_arps_32 = [
# Dm climbing
D, F, A, D.add(12), F.add(12), A.add(12),
D.add(24), A.add(12), F.add(12), D.add(12), A, F,
# Bb arp
Bb.add(-12), D, F, Bb, D.add(12), F.add(12),
Bb.add(12), F.add(12), D.add(12), Bb, F, D,
# Gm arp
G.add(-12), Bb.add(-12), D, G, Bb, D.add(12),
G.add(12), D.add(12), Bb, G, D, Bb.add(-12),
# Back to Dm — reaching for the top
D, A, D.add(12), A.add(12), D.add(24), A.add(24),
D.add(24), A.add(12), D.add(12), A, D, A.add(-12),
]
for note in solo_arps_32:
mario.add(note, 0.125, velocity=110)
# Bars 57-58: the emotional peak — sustained high notes with fast trills
# Hold a high D while trilling between neighbors
mario.add(D.add(24), Duration.QUARTER, velocity=120)
mario.add(Cs.add(12), 0.125, velocity=100)
mario.add(D.add(24), 0.125, velocity=115)
mario.add(Cs.add(12), 0.125, velocity=100)
mario.add(D.add(24), 0.125, velocity=118)
mario.add(E.add(12), Duration.QUARTER, velocity=110)
mario.add(F.add(12), Duration.QUARTER, velocity=115)
# Descending cry
mario.add(D.add(24), Duration.EIGHTH, velocity=120)
mario.add(A.add(12), Duration.EIGHTH, velocity=105)
mario.add(F.add(12), Duration.EIGHTH, velocity=100)
mario.add(D.add(12), Duration.EIGHTH, velocity=95)
mario.add(A, Duration.EIGHTH, velocity=90)
mario.add(F, Duration.EIGHTH, velocity=85)
mario.add(D, Duration.QUARTER, velocity=110)
# Bars 59-60: final blaze — 32nd note scale runs up and down
# Full D minor scale run ascending then descending, twice
scale_up = [D, E, F, G, A, Bb, Cs, D.add(12),
E.add(12), F.add(12), G.add(12), A.add(12),
Bb.add(12), Cs.add(12), D.add(24), Cs.add(12)]
scale_down = [Bb.add(12), A.add(12), G.add(12), F.add(12),
E.add(12), D.add(12), Cs, Bb,
A, G, F, E, D, E, F, A]
for note in scale_up:
mario.add(note, 0.125, velocity=115)
for note in scale_down:
mario.add(note, 0.125, velocity=108)
# Bars 61-64: mario fades into the snare crescendo
mario.add(D.add(12), Duration.WHOLE, velocity=90) # one last held note
for _ in range(3):
mario.rest(Duration.WHOLE)
# ── NOKIA — Gran Vals ringtone on pulse wave (bars 49-56) ───────
nokia = score.part("nokia", synth="pulse", envelope="staccato", volume=0.3,
reverb=0.4, reverb_type="taj_mahal", lowpass=4000,
humanize=0.04)
# Bars 1-48: rests
for _ in range(48):
nokia.rest(Duration.WHOLE)
# Bars 49-52: the iconic Nokia tune (Gran Vals by Francisco Tárrega)
# E5 D5 F#4 G#4 | C#5 B4 D4 E4 | B4 A4 C#4 E4 | A4
nokia_melody = [
(E.add(12), Duration.EIGHTH), (D.add(12), Duration.EIGHTH),
(Tone.from_string("F#4"), Duration.QUARTER), (Tone.from_string("G#4"), Duration.QUARTER),
(Tone.from_string("C#5"), Duration.EIGHTH), (Tone.from_string("B4"), Duration.EIGHTH),
(D, Duration.QUARTER), (E, Duration.QUARTER),
(Tone.from_string("B4"), Duration.EIGHTH), (A, Duration.EIGHTH),
(Tone.from_string("C#4"), Duration.QUARTER), (E, Duration.QUARTER),
(A, Duration.HALF), (None, Duration.HALF),
]
for _ in range(2):
for note, dur in nokia_melody:
if note is None:
nokia.rest(dur)
else:
nokia.add(note, dur, velocity=95)
# Bars 53-56: nokia fading under the mario solo
for note, dur in nokia_melody:
if note is None:
nokia.rest(dur)
else:
nokia.add(note, dur, velocity=60)
nokia.rest(Duration.WHOLE)
# Bars 57-64: silent
for _ in range(8):
nokia.rest(Duration.WHOLE)
# ── DRAKE — steel drum Hotline Bling melody (bars 33-52) ────────
bling = score.part("bling", instrument="steel_drum", volume=0.7,
reverb=0.4, reverb_type="taj_mahal",
delay=0.3, delay_time=0.316, delay_feedback=0.35,
humanize=0.06)
# Bars 1-32: rests
for _ in range(32):
bling.rest(Duration.WHOLE)
# Bars 33-40: that Hotline Bling melody — hypnotic, descending
drake_melody = [
(D.add(12), Duration.QUARTER), (C.add(12), Duration.QUARTER),
(A, Duration.QUARTER), (G, Duration.QUARTER),
(A, Duration.QUARTER), (None, Duration.QUARTER),
(G, Duration.QUARTER), (E, Duration.QUARTER),
(D.add(12), Duration.QUARTER), (C.add(12), Duration.EIGHTH),
(A, Duration.EIGHTH), (G, Duration.HALF),
(A, Duration.HALF), (G, Duration.QUARTER),
(E, Duration.QUARTER),
]
for _ in range(2):
for note, dur in drake_melody:
if note is None:
bling.rest(dur)
else:
bling.add(note, dur, velocity=100)
# Bars 41-48: keep going, Mario layered underneath
for _ in range(2):
for note, dur in drake_melody:
if note is None:
bling.rest(dur)
else:
bling.add(note, dur, velocity=95)
# Bars 49-52: fading
for note, dur in drake_melody:
if note is None:
bling.rest(dur)
else:
bling.add(note, dur, velocity=65)
# Bars 53-64: silent
for _ in range(12):
bling.rest(Duration.WHOLE)
# ── 808 BASS — enters bar 9, throughout ────────────────────────
bass = score.part("bass_808", synth="sine", envelope="pad", volume=0.3,
distortion=0.2, distortion_drive=3.0,
lowpass=140, lowpass_q=1.8, sub_osc=0.4,
humanize=0.06)
# Bars 1-8: rests
for _ in range(8):
bass.rest(Duration.WHOLE)
# Bars 9-56: 808 following roots
bass_roots = [D.add(-24), C.add(-24), Bb.add(-24), G.add(-24)]
for _ in range(12):
for root in bass_roots:
bass.add(root, Duration.HALF, velocity=100)
bass.rest(Duration.QUARTER)
bass.add(root, Duration.QUARTER, velocity=85)
# Bars 57-64: fading via velocity
for vel in [70, 60, 50, 40, 30, 20, 10, 5]:
bass.add(D.add(-24), Duration.WHOLE, velocity=vel)
# ── MARCHING SNARE — military finale (bars 49-64) ──────────────
march = score.part("march", volume=1.0,
reverb=0.2, reverb_decay=0.8, humanize=0.03,
ensemble=16)
# Bars 1-48: rests
for _ in range(48):
march.rest(Duration.WHOLE)
# ── LEVEL 1 — Bars 49-50: single hits, lots of space. A warning. ──
march.hit(MR, Duration.HALF, velocity=115, articulation="marcato")
march.rest(Duration.HALF)
march.rest(Duration.HALF)
march.hit(MR, Duration.HALF, velocity=118, articulation="marcato")
# ── LEVEL 2 — Bars 51-52: quarter notes. Marching begins. ────────
for _ in range(2):
march.hit(MR, Duration.QUARTER, velocity=110, articulation="accent")
march.hit(MR, Duration.QUARTER, velocity=55)
march.hit(MR, Duration.QUARTER, velocity=112, articulation="accent")
march.hit(MR, Duration.QUARTER, velocity=55)
# ── LEVEL 3 — Bars 53-54: 8ths with ghost notes. Getting serious. ─
for _ in range(2):
march.hit(MR, Duration.EIGHTH, velocity=115, articulation="accent")
march.hit(MR, Duration.EIGHTH, velocity=48)
march.hit(MR, Duration.EIGHTH, velocity=55)
march.hit(MR, Duration.EIGHTH, velocity=112, articulation="accent")
march.hit(MR, Duration.EIGHTH, velocity=50)
march.hit(MR, Duration.EIGHTH, velocity=48)
march.hit(MR, Duration.EIGHTH, velocity=118, articulation="marcato")
march.hit(MR, Duration.EIGHTH, velocity=50)
# ── LEVEL 4 — Bars 55-56: 16ths. Full paradiddle. ────────────────
for _ in range(2):
# RLRR LRLL RLRR LRLL
march.hit(MR, Duration.SIXTEENTH, velocity=125, articulation="marcato")
march.hit(MR, Duration.SIXTEENTH, velocity=50)
march.hit(MR, Duration.SIXTEENTH, velocity=55)
march.hit(MR, Duration.SIXTEENTH, velocity=52)
march.hit(MR, Duration.SIXTEENTH, velocity=122, articulation="accent")
march.hit(MR, Duration.SIXTEENTH, velocity=50)
march.hit(MR, Duration.SIXTEENTH, velocity=52)
march.hit(MR, Duration.SIXTEENTH, velocity=48)
march.hit(MR, Duration.SIXTEENTH, velocity=127, articulation="marcato")
march.hit(MR, Duration.SIXTEENTH, velocity=52)
march.hit(MR, Duration.SIXTEENTH, velocity=55)
march.hit(MR, Duration.SIXTEENTH, velocity=50)
march.hit(MR, Duration.SIXTEENTH, velocity=125, articulation="accent")
march.hit(MR, Duration.SIXTEENTH, velocity=50)
march.hit(MR, Duration.SIXTEENTH, velocity=52)
march.hit(MR, Duration.SIXTEENTH, velocity=48)
# ── LEVEL 5 — Bars 57-58: 16ths, louder, accents on every beat ───
for _ in range(2):
for beat in range(4):
march.hit(MR, Duration.SIXTEENTH, velocity=127, articulation="marcato")
march.hit(MR, Duration.SIXTEENTH, velocity=58)
march.hit(MR, Duration.SIXTEENTH, velocity=62)
march.hit(MR, Duration.SIXTEENTH, velocity=55)
# ── LEVEL 6 — Bars 59-60: 32nds creep in. Here it comes. ─────────
for _ in range(2):
# Half bar 16ths, half bar 32nds
for beat in range(2):
march.hit(MR, Duration.SIXTEENTH, velocity=125, articulation="accent")
march.hit(MR, Duration.SIXTEENTH, velocity=55)
march.hit(MR, Duration.SIXTEENTH, velocity=58)
march.hit(MR, Duration.SIXTEENTH, velocity=52)
for beat in range(2):
march.hit(MR, 0.125, velocity=125, articulation="accent")
march.hit(MR, 0.125, velocity=52)
march.hit(MR, 0.125, velocity=55)
march.hit(MR, 0.125, velocity=48)
march.hit(MR, 0.125, velocity=122, articulation="accent")
march.hit(MR, 0.125, velocity=50)
march.hit(MR, 0.125, velocity=55)
march.hit(MR, 0.125, velocity=48)
# ── LEVEL 7 — Bars 61-62: full 32nd note rolls ───────────────────
for bar in range(2):
for beat in range(4):
base = 80 + bar * 15 + beat * 3
march.hit(MR, 0.125, velocity=min(127, base + 30), articulation="accent")
march.hit(MR, 0.125, velocity=min(127, base))
march.hit(MR, 0.125, velocity=min(127, base + 10))
march.hit(MR, 0.125, velocity=min(127, base))
march.hit(MR, 0.125, velocity=min(127, base + 25), articulation="accent")
march.hit(MR, 0.125, velocity=min(127, base + 5))
march.hit(MR, 0.125, velocity=min(127, base + 15))
march.hit(MR, 0.125, velocity=min(127, base))
# Bar 63: 32nd note crescendo — wall of snare
for i in range(32):
vel = min(127, 70 + i * 2)
art = "accent" if i % 4 == 0 else "marcato" if i % 8 == 0 else ""
march.hit(MR, 0.125, velocity=vel, articulation=art)
# Bar 64: CADENCE — DCI-style ending
# Flam drags into triplets into unison hits
# Flam drag: grace-MAIN grace-MAIN (tight doubles)
march.hit(MR, 0.125, velocity=55) # grace
march.hit(MR, Duration.SIXTEENTH, velocity=127, articulation="marcato") # MAIN
march.hit(MR, 0.125, velocity=55) # grace
march.hit(MR, Duration.SIXTEENTH, velocity=125, articulation="marcato") # MAIN
# 16th note triplets — six per beat, blazing
for _ in range(4):
march.hit(MR, 1/6, velocity=127, articulation="marcato")
march.hit(MR, 1/6, velocity=52)
march.hit(MR, 1/6, velocity=55)
march.hit(MR, 1/6, velocity=125, articulation="accent")
march.hit(MR, 1/6, velocity=50)
march.hit(MR, 1/6, velocity=55)
# Rimshot quarter notes — CRACK . CRACK . CRACK . CRACK
march.hit(MR, Duration.QUARTER, velocity=127, articulation="marcato")
march.hit(MR, Duration.QUARTER, velocity=127, articulation="marcato")
march.hit(MR, Duration.QUARTER, velocity=127, articulation="marcato")
# THE FINAL RIMSHOT — everything stops
march.hit(MR, Duration.QUARTER, velocity=127, articulation="fermata")
# ── PAD — atmospheric glue throughout ───────────────────────────
pad = score.part("pad", synth="supersaw", envelope="pad", volume=0.12,
reverb=0.6, reverb_type="taj_mahal",
chorus=0.3, chorus_rate=0.2, chorus_depth=0.008,
lowpass=1400)
pad.lfo("lowpass", rate=0.03, min=600, max=2000, bars=64, shape="triangle")
for _ in range(16):
for chord in prog:
pad.add(chord, Duration.WHOLE)
# ═════════════════════════════════════════════════════════════════
import sys
print(f"Key: {key}")
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 CULTURE CLASH (live engine)...")
from pytheory_live.live import LiveEngine
engine = LiveEngine(buffer_size=1024)
engine.play_score(score)
else:
print("Playing CULTURE CLASH...")
play_score(score)
+84 -8
View File
@@ -46,11 +46,11 @@ def play_phrases(part, phrases, reps=1, vel_offset=0):
# ── KOTO — China, pentatonic, sparse ───────────────────────────
# D minor pentatonic: D F G A C (removes E and Bb)
koto = score.part("koto", instrument="koto", volume=0.4,
reverb=0.55, reverb_type="taj_mahal",
delay=0.3, delay_time=0.316, delay_feedback=0.4,
reverb=0.0,
delay=0.0,
pan=-0.45, humanize=0.1)
# Bars 1-16: solo koto — contemplative, lots of space
# Bars 1-16: solo koto — starts dry, reverb fades in like mist
koto_phrases = [
# Phrase 1: simple, announcing
[(D.add(12), Duration.HALF, 80), (None, Duration.QUARTER, 0),
@@ -73,11 +73,19 @@ koto_phrases = [
(A, Duration.QUARTER, 75)],
[(D, Duration.WHOLE, 80)],
]
play_phrases(koto, koto_phrases, reps=2)
# First pass: dry, intimate, close
play_phrases(koto, koto_phrases, reps=1)
# Second pass: reverb creeping in
koto.set(reverb=0.15, reverb_type="taj_mahal", delay=0.1, delay_time=0.316, delay_feedback=0.15)
play_phrases(koto, koto_phrases, reps=1)
# Bars 17-80: koto continues, same phrases, quieter as others join
# Bars 17-80: koto continues, reverb grows as the caravan fills
koto.set(reverb=0.3, delay=0.2, delay_feedback=0.25)
play_phrases(koto, koto_phrases, reps=2, vel_offset=-15)
play_phrases(koto, koto_phrases, reps=6, vel_offset=-25)
koto.set(reverb=0.45, delay=0.3, delay_feedback=0.35)
play_phrases(koto, koto_phrases, reps=2, vel_offset=-20)
koto.set(reverb=0.55, delay=0.3, delay_feedback=0.4)
play_phrases(koto, koto_phrases, reps=4, vel_offset=-25)
# ── SITAR — India, enters bar 17 ───────────────────────────────
sitar = score.part("sitar", instrument="sitar", volume=0.5,
@@ -118,8 +126,10 @@ tabla = score.part("tabla", volume=0.3, reverb=0.3, reverb_type="cathedral",
for _ in range(16):
tabla.rest(Duration.WHOLE)
# Bars 17-80: keherwa groove throughout
for bar in range(64):
# Bars 17-80: keherwa groove — gets louder as the caravan grows
# Bars 17-32: India section — gentle
tabla.set(volume=0.2)
for bar in range(16):
if bar % 8 == 7:
tabla.hit(tDHA, Duration.EIGHTH, velocity=95, articulation="accent")
tabla.hit(GEB, Duration.EIGHTH, velocity=108)
@@ -139,6 +149,72 @@ for bar in range(64):
tabla.hit(tDHA, Duration.EIGHTH, velocity=80, articulation="accent")
tabla.hit(NA, Duration.EIGHTH, velocity=58)
# Bars 33-48: Persia joins — fuller
tabla.set(volume=0.3)
for bar in range(16):
if bar % 8 == 7:
tabla.hit(tDHA, Duration.EIGHTH, velocity=100, articulation="accent")
tabla.hit(GEB, Duration.EIGHTH, velocity=112)
tabla.hit(NA, Duration.EIGHTH, velocity=78)
tabla.hit(GEB, Duration.EIGHTH, velocity=110)
tabla.hit(tDHA, Duration.EIGHTH, velocity=95, articulation="accent")
tabla.hit(NA, Duration.SIXTEENTH, velocity=68)
tabla.hit(TIT, Duration.SIXTEENTH, velocity=55)
tabla.hit(GEB, Duration.QUARTER, velocity=118)
else:
tabla.hit(tDHA, Duration.EIGHTH, velocity=90, articulation="accent")
tabla.hit(GE, Duration.EIGHTH, velocity=60)
tabla.hit(NA, Duration.EIGHTH, velocity=70)
tabla.hit(TIT, Duration.EIGHTH, velocity=48)
tabla.hit(NA, Duration.EIGHTH, velocity=65)
tabla.hit(TIT, Duration.EIGHTH, velocity=42)
tabla.hit(tDHA, Duration.EIGHTH, velocity=85, articulation="accent")
tabla.hit(NA, Duration.EIGHTH, velocity=62)
# Bars 49-64: Mediterranean joins — confident
tabla.set(volume=0.38)
for bar in range(16):
if bar % 8 == 7:
tabla.hit(tDHA, Duration.EIGHTH, velocity=105, articulation="accent")
tabla.hit(GEB, Duration.EIGHTH, velocity=115)
tabla.hit(NA, Duration.EIGHTH, velocity=82)
tabla.hit(GEB, Duration.EIGHTH, velocity=112)
tabla.hit(tDHA, Duration.EIGHTH, velocity=100, articulation="accent")
tabla.hit(NA, Duration.SIXTEENTH, velocity=72)
tabla.hit(TIT, Duration.SIXTEENTH, velocity=58)
tabla.hit(GEB, Duration.QUARTER, velocity=120)
else:
tabla.hit(tDHA, Duration.EIGHTH, velocity=95, articulation="accent")
tabla.hit(GE, Duration.EIGHTH, velocity=65)
tabla.hit(NA, Duration.EIGHTH, velocity=75)
tabla.hit(TIT, Duration.EIGHTH, velocity=52)
tabla.hit(NA, Duration.EIGHTH, velocity=70)
tabla.hit(TIT, Duration.EIGHTH, velocity=45)
tabla.hit(tDHA, Duration.EIGHTH, velocity=90, articulation="accent")
tabla.hit(NA, Duration.EIGHTH, velocity=68)
# Bars 65-80: all together — full power
tabla.set(volume=0.45)
for bar in range(16):
if bar % 8 == 7:
tabla.hit(tDHA, Duration.EIGHTH, velocity=110, articulation="accent")
tabla.hit(GEB, Duration.EIGHTH, velocity=118)
tabla.hit(NA, Duration.EIGHTH, velocity=85)
tabla.hit(GEB, Duration.EIGHTH, velocity=115)
tabla.hit(tDHA, Duration.EIGHTH, velocity=105, articulation="accent")
tabla.hit(NA, Duration.SIXTEENTH, velocity=75)
tabla.hit(TIT, Duration.SIXTEENTH, velocity=62)
tabla.hit(GEB, Duration.QUARTER, velocity=122)
else:
tabla.hit(tDHA, Duration.EIGHTH, velocity=100, articulation="accent")
tabla.hit(GE, Duration.EIGHTH, velocity=70)
tabla.hit(NA, Duration.EIGHTH, velocity=80)
tabla.hit(TIT, Duration.EIGHTH, velocity=55)
tabla.hit(NA, Duration.EIGHTH, velocity=75)
tabla.hit(TIT, Duration.EIGHTH, velocity=48)
tabla.hit(tDHA, Duration.EIGHTH, velocity=95, articulation="accent")
tabla.hit(NA, Duration.EIGHTH, velocity=72)
# ── MANDOLIN (oud) — Persia, enters bar 33 ─────────────────────
oud = score.part("oud", instrument="mandolin", volume=0.4,
reverb=0.45, reverb_type="cathedral",