mirror of
https://github.com/kennethreitz/interpretations.git
synced 2026-06-05 23:00:19 +00:00
Add The Observatory (track 12), Voltage tweaks, The Dialogue/Temple updates
The Observatory: G minor, 112 BPM — chapel through shortwave, by ChatGPT. Voltage: spring/taj_mahal reverb, delay, kick maxed. Remove Digital Raga and 3AM (for rework). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ Each track is a `.py` file. Run it to hear it.
|
||||
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.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ ALBUM_ORDER = [
|
||||
"the_temple.py",
|
||||
"the_dialogue.py",
|
||||
"voltage.py",
|
||||
"the_observatory.py",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,383 @@
|
||||
"""
|
||||
THE OBSERVATORY — chapel harmonies broadcast through shortwave static.
|
||||
An organ learns to levitate. By the time the kick arrives,
|
||||
the room is already in orbit.
|
||||
|
||||
G minor, 112 BPM. Radio hiss, bell, organ, choir, arp,
|
||||
sub bass, and a patient house pulse.
|
||||
"""
|
||||
|
||||
from pytheory import Key, Duration, Score, play_score
|
||||
from pytheory.rhythm import DrumSound
|
||||
|
||||
key = Key("G", "minor")
|
||||
s = key.scale # G A Bb C D Eb F
|
||||
|
||||
G = s[0]
|
||||
A = s[1]
|
||||
Bb = s[2]
|
||||
C = s[3]
|
||||
D = s[4]
|
||||
Eb = s[5]
|
||||
F = s[6]
|
||||
|
||||
score = Score("4/4", bpm=112)
|
||||
|
||||
K = DrumSound.KICK
|
||||
CL = DrumSound.CLAP
|
||||
CH = DrumSound.CLOSED_HAT
|
||||
OH = DrumSound.OPEN_HAT
|
||||
|
||||
prog = key.progression("i", "VI", "III", "VII") # Gm - Eb - Bb - F
|
||||
roots = [G.add(-24), Eb.add(-24), Bb.add(-24), F.add(-24)]
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# STRUCTURE (96 bars, ~5.1 minutes at 112 BPM):
|
||||
# Bars 1-8: Shortwave hiss + bell. Empty room, open sky.
|
||||
# Bars 9-16: Organ enters — first human architecture.
|
||||
# Bars 17-32: Arp appears, still no drums. The orbit begins.
|
||||
# Bars 33-48: Kick/sub/clap enter — lift.
|
||||
# Bars 49-64: Choir + signal melody — the windows open.
|
||||
# Bars 65-80: Peak — full transmission, bright and weightless.
|
||||
# Bars 81-88: Drums thin out. Organ and choir suspend.
|
||||
# Bars 89-96: Static, bell, and one last heartbeat.
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
# ── RADIO HISS — the sky itself ───────────────────────────────────
|
||||
radio = score.part("radio", synth="noise", envelope="pad", volume=0.04,
|
||||
reverb=0.85, reverb_type="taj_mahal",
|
||||
lowpass=900)
|
||||
radio.lfo("lowpass", rate=0.012, min=300, max=1800, bars=96, shape="sine")
|
||||
radio.lfo("volume", rate=0.02, min=0.02, max=0.06, bars=96, shape="triangle")
|
||||
|
||||
for _ in range(96):
|
||||
radio.add(G, Duration.WHOLE, velocity=25)
|
||||
|
||||
# ── BOWL — section markers, like light reflecting off metal ──────
|
||||
bowl = score.part("bowl", instrument="singing_bowl", volume=0.42,
|
||||
reverb=1.0, reverb_type="taj_mahal",
|
||||
delay=0.25, delay_time=0.875, delay_feedback=0.35)
|
||||
|
||||
marker_bars = {1: 78, 9: 72, 17: 68, 33: 75, 49: 72, 65: 76, 81: 60, 89: 54}
|
||||
for bar in range(1, 97):
|
||||
if bar in marker_bars:
|
||||
note = G.add(-24) if bar < 65 else D.add(-12)
|
||||
bowl.add(note, Duration.WHOLE, velocity=marker_bars[bar])
|
||||
else:
|
||||
bowl.rest(Duration.WHOLE)
|
||||
|
||||
# ── ORGAN — square-wave chapel, warm but slightly unreal ──────────
|
||||
organ = score.part("organ", synth="square", envelope="organ", volume=0.14,
|
||||
reverb=0.78, reverb_type="taj_mahal",
|
||||
chorus=0.25, chorus_rate=0.18, chorus_depth=0.01,
|
||||
lowpass=1800)
|
||||
|
||||
low_prog = [c.transpose(-12) for c in prog]
|
||||
mid_prog = prog
|
||||
high_prog = [c.transpose(12) for c in prog]
|
||||
|
||||
# Bars 1-8: silence
|
||||
for _ in range(8):
|
||||
organ.rest(Duration.WHOLE)
|
||||
|
||||
# Bars 9-16: first statement, low and slow
|
||||
for _ in range(2):
|
||||
for chord in low_prog:
|
||||
organ.add(chord, Duration.WHOLE, velocity=52)
|
||||
|
||||
# Bars 17-32: stronger, still no pulse beneath it
|
||||
for _ in range(4):
|
||||
for chord in low_prog:
|
||||
organ.add(chord, Duration.WHOLE, velocity=60)
|
||||
|
||||
# Bars 33-64: fully present
|
||||
for _ in range(8):
|
||||
for chord in mid_prog:
|
||||
organ.add(chord, Duration.WHOLE, velocity=72)
|
||||
|
||||
# Bars 65-80: brighter voicings at the peak
|
||||
for _ in range(4):
|
||||
for chord in high_prog:
|
||||
organ.add(chord, Duration.WHOLE, velocity=66)
|
||||
|
||||
# Bars 81-88: suspended, looking down at the earth
|
||||
for _ in range(2):
|
||||
for chord in [mid_prog[0], mid_prog[1], mid_prog[0], mid_prog[3]]:
|
||||
organ.add(chord, Duration.WHOLE, velocity=54)
|
||||
|
||||
# Bars 89-96: fading architecture
|
||||
for chord, vel in zip(low_prog * 2, [50, 44, 40, 36, 30, 24, 16, 8]):
|
||||
organ.add(chord, Duration.WHOLE, velocity=vel)
|
||||
|
||||
# ── CHOIR — the air inside the room starts singing ────────────────
|
||||
choir = score.part("choir", instrument="choir", volume=0.11,
|
||||
reverb=0.95, reverb_type="taj_mahal",
|
||||
chorus=0.35, chorus_rate=0.08, chorus_depth=0.012)
|
||||
|
||||
# Bars 1-32: silence
|
||||
for _ in range(32):
|
||||
choir.rest(Duration.WHOLE)
|
||||
|
||||
# Bars 33-48: arrives behind the drums, soft
|
||||
for _ in range(4):
|
||||
for chord in prog:
|
||||
choir.add(chord, Duration.WHOLE, velocity=38)
|
||||
|
||||
# Bars 49-80: fully open
|
||||
for _ in range(8):
|
||||
for chord in prog:
|
||||
choir.add(chord, Duration.WHOLE, velocity=48)
|
||||
|
||||
# Bars 81-88: held breath
|
||||
for _ in range(2):
|
||||
for chord in [prog[0], prog[1], prog[0], prog[3]]:
|
||||
choir.add(chord, Duration.WHOLE, velocity=36)
|
||||
|
||||
# Bars 89-96: gone
|
||||
for _ in range(8):
|
||||
choir.rest(Duration.WHOLE)
|
||||
|
||||
# ── HALO PAD — the light around the chord, not the chord itself ──
|
||||
halo = score.part("halo", synth="supersaw", envelope="pad", volume=0.08,
|
||||
reverb=0.65, reverb_type="taj_mahal",
|
||||
chorus=0.45, chorus_rate=0.2, chorus_depth=0.008,
|
||||
lowpass=1200)
|
||||
halo.lfo("lowpass", rate=0.01, min=500, max=2800, bars=96, shape="triangle")
|
||||
|
||||
# Bars 1-48: silence
|
||||
for _ in range(48):
|
||||
halo.rest(Duration.WHOLE)
|
||||
|
||||
# Bars 49-80: glow at the peak
|
||||
for _ in range(8):
|
||||
for chord in prog:
|
||||
halo.add(chord, Duration.WHOLE, velocity=42)
|
||||
|
||||
# Bars 81-96: silence
|
||||
for _ in range(16):
|
||||
halo.rest(Duration.WHOLE)
|
||||
|
||||
# ── ARP — the signal lock, patient and inevitable ────────────────
|
||||
arp = score.part("arp", synth="saw", envelope="pluck", volume=0.35,
|
||||
reverb=0.3, delay=0.35, delay_time=0.234,
|
||||
delay_feedback=0.42, lowpass=1300, detune=5,
|
||||
humanize=0.03)
|
||||
arp.lfo("lowpass", rate=0.009, min=900, max=5200, bars=96, shape="saw")
|
||||
|
||||
P1 = [
|
||||
G.add(12), None, D.add(12), None,
|
||||
Bb, None, F.add(12), None,
|
||||
G.add(12), None, D.add(12), None,
|
||||
C.add(12), Bb, F, D,
|
||||
]
|
||||
|
||||
P2 = [
|
||||
G.add(12), D.add(12), F.add(12), D.add(12),
|
||||
Eb.add(12), D.add(12), Bb, D.add(12),
|
||||
G.add(12), D.add(12), F.add(12), D.add(12),
|
||||
C.add(12), Bb, F, D,
|
||||
]
|
||||
|
||||
|
||||
def arp_bar(notes, vel):
|
||||
for note in notes:
|
||||
if note is None:
|
||||
arp.rest(Duration.SIXTEENTH)
|
||||
else:
|
||||
arp.add(note, Duration.SIXTEENTH, velocity=vel)
|
||||
|
||||
|
||||
# Bars 1-16: silence
|
||||
for _ in range(16):
|
||||
arp.rest(Duration.WHOLE)
|
||||
|
||||
# Bars 17-32: emerges quietly
|
||||
for _ in range(8):
|
||||
arp_bar(P1, 50)
|
||||
arp_bar(P2, 54)
|
||||
|
||||
# Bars 33-48: steady and confident
|
||||
for _ in range(8):
|
||||
arp_bar(P1, 64)
|
||||
arp_bar(P2, 68)
|
||||
|
||||
# Bars 49-64: brighter
|
||||
for _ in range(8):
|
||||
arp_bar(P1, 76)
|
||||
arp_bar(P2, 80)
|
||||
|
||||
# Bars 65-80: peak — no more hesitation
|
||||
for _ in range(8):
|
||||
arp_bar(P2, 88)
|
||||
arp_bar(P1, 92)
|
||||
|
||||
# Bars 81-88: thinning out
|
||||
for _ in range(4):
|
||||
arp_bar(P1, 62)
|
||||
arp_bar(P2, 58)
|
||||
|
||||
# Bars 89-96: silence
|
||||
for _ in range(8):
|
||||
arp.rest(Duration.WHOLE)
|
||||
|
||||
# ── SUB — the floor finally arrives beneath the chapel ───────────
|
||||
sub = score.part("sub", synth="sine", envelope="pad", volume=0.28,
|
||||
lowpass=120, distortion=0.12, distortion_drive=2.5,
|
||||
sub_osc=0.4, sidechain=0.25)
|
||||
|
||||
# Bars 1-32: silence
|
||||
for _ in range(32):
|
||||
sub.rest(Duration.WHOLE)
|
||||
|
||||
# Bars 33-80: root motion, simple and physical
|
||||
for _ in range(12):
|
||||
for root in roots:
|
||||
sub.add(root, Duration.HALF, velocity=92)
|
||||
sub.rest(Duration.HALF)
|
||||
|
||||
# Bars 81-88: just the home note, held
|
||||
for _ in range(8):
|
||||
sub.add(G.add(-24), Duration.HALF, velocity=72)
|
||||
sub.rest(Duration.HALF)
|
||||
|
||||
# Bars 89-96: fading heartbeat
|
||||
for vel in [66, 58, 50, 42, 34, 26, 16, 0]:
|
||||
if vel > 0:
|
||||
sub.add(G.add(-24), Duration.HALF, velocity=vel)
|
||||
sub.rest(Duration.HALF)
|
||||
else:
|
||||
sub.rest(Duration.WHOLE)
|
||||
|
||||
# ── KICK — the patient release ────────────────────────────────────
|
||||
kick = score.part("kick", volume=0.55, humanize=0.03)
|
||||
|
||||
# Bars 1-32: none
|
||||
for _ in range(32):
|
||||
kick.rest(Duration.WHOLE)
|
||||
|
||||
# Bars 33-80: four on the floor
|
||||
for _ in range(48):
|
||||
for _beat in range(4):
|
||||
kick.hit(K, Duration.QUARTER, velocity=114)
|
||||
|
||||
# Bars 81-88: still there, but more human now
|
||||
for _ in range(8):
|
||||
kick.hit(K, Duration.QUARTER, velocity=95)
|
||||
kick.rest(Duration.QUARTER)
|
||||
kick.hit(K, Duration.QUARTER, velocity=88)
|
||||
kick.rest(Duration.QUARTER)
|
||||
|
||||
# Bars 89-96: last pulses
|
||||
for vel in [88, 82, 76, 68, 58, 46, 32, 18]:
|
||||
kick.hit(K, Duration.QUARTER, velocity=vel)
|
||||
kick.rest(Duration.DOTTED_HALF)
|
||||
|
||||
# ── CLAP — 2 and 4, but never aggressive ─────────────────────────
|
||||
clap = score.part("clap", volume=0.28, reverb=0.18, humanize=0.04)
|
||||
|
||||
# Bars 1-32: silence
|
||||
for _ in range(32):
|
||||
clap.rest(Duration.WHOLE)
|
||||
|
||||
# Bars 33-80: standard house backbeat
|
||||
for _ in range(48):
|
||||
clap.rest(Duration.QUARTER)
|
||||
clap.hit(CL, Duration.QUARTER, velocity=96)
|
||||
clap.rest(Duration.QUARTER)
|
||||
clap.hit(CL, Duration.QUARTER, velocity=98)
|
||||
|
||||
# Bars 81-96: silence
|
||||
for _ in range(16):
|
||||
clap.rest(Duration.WHOLE)
|
||||
|
||||
# ── HATS — offbeat shimmer ────────────────────────────────────────
|
||||
hats = score.part("hats", volume=0.22, humanize=0.04)
|
||||
|
||||
# Bars 1-32: silence
|
||||
for _ in range(32):
|
||||
hats.rest(Duration.WHOLE)
|
||||
|
||||
# Bars 33-80: offbeat 8ths, occasional open hat on the turn
|
||||
for bar in range(48):
|
||||
for beat in range(4):
|
||||
hats.rest(Duration.EIGHTH)
|
||||
sound = OH if beat == 3 and bar % 4 == 3 else CH
|
||||
vel = 74 if sound == CH else 68
|
||||
hats.hit(sound, Duration.EIGHTH, velocity=vel)
|
||||
|
||||
# Bars 81-88: thinner
|
||||
for _ in range(8):
|
||||
for _beat in range(4):
|
||||
hats.rest(Duration.EIGHTH)
|
||||
hats.hit(CH, Duration.EIGHTH, velocity=52)
|
||||
|
||||
# Bars 89-96: silence
|
||||
for _ in range(8):
|
||||
hats.rest(Duration.WHOLE)
|
||||
|
||||
# ── SIGNAL — the melody finally resolves the transmission ────────
|
||||
signal = score.part("signal", instrument="theremin", volume=0.16,
|
||||
reverb=0.82, reverb_type="taj_mahal",
|
||||
delay=0.28, delay_time=0.375, delay_feedback=0.32,
|
||||
humanize=0.05)
|
||||
|
||||
# Bars 1-48: silence
|
||||
for _ in range(48):
|
||||
signal.rest(Duration.WHOLE)
|
||||
|
||||
phrase_a = [
|
||||
(D.add(12), Duration.HALF, 70, 0.2),
|
||||
(F.add(12), Duration.QUARTER, 74, 0.0),
|
||||
(G.add(12), Duration.QUARTER, 78, 0.35),
|
||||
(Bb.add(12), Duration.HALF, 80, -0.2),
|
||||
(A.add(12), Duration.QUARTER, 68, 0.0),
|
||||
(G.add(12), Duration.QUARTER, 72, 0.0),
|
||||
(F.add(12), Duration.HALF, 70, 0.15),
|
||||
(Eb.add(12), Duration.QUARTER, 68, 0.0),
|
||||
(D.add(12), Duration.QUARTER, 66, -0.1),
|
||||
(G.add(12), Duration.WHOLE, 78, 0.0),
|
||||
]
|
||||
|
||||
phrase_b = [
|
||||
(G.add(12), Duration.QUARTER, 78, 0.0),
|
||||
(Bb.add(12), Duration.QUARTER, 82, 0.15),
|
||||
(D.add(24), Duration.HALF, 86, -0.2),
|
||||
(F.add(24), Duration.HALF, 84, 0.0),
|
||||
(Eb.add(24), Duration.QUARTER, 78, 0.0),
|
||||
(D.add(24), Duration.QUARTER, 76, 0.0),
|
||||
(Bb.add(12), Duration.HALF, 72, -0.15),
|
||||
(A.add(12), Duration.QUARTER, 68, 0.0),
|
||||
(G.add(12), Duration.QUARTER, 66, 0.0),
|
||||
(F.add(12), Duration.WHOLE, 74, 0.0),
|
||||
]
|
||||
|
||||
# Bars 49-64: first message
|
||||
for _ in range(4):
|
||||
for note, dur, vel, bend in phrase_a:
|
||||
signal.add(note, dur, velocity=vel, bend=bend)
|
||||
|
||||
# Bars 65-80: stronger reply
|
||||
for _ in range(4):
|
||||
for note, dur, vel, bend in phrase_b:
|
||||
signal.add(note, dur, velocity=vel, bend=bend)
|
||||
|
||||
# Bars 81-96: silence
|
||||
for _ in range(16):
|
||||
signal.rest(Duration.WHOLE)
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
import sys
|
||||
|
||||
print(f"Key: {key}")
|
||||
print(f"BPM: 112")
|
||||
print(f"Parts: {list(score.parts.keys())}")
|
||||
print(f"Duration: {score.duration_ms / 1000:.1f}s | {score.measures} measures")
|
||||
|
||||
if "--live" in sys.argv:
|
||||
print("Playing THE OBSERVATORY (live engine)...")
|
||||
from pytheory_live.live import LiveEngine
|
||||
engine = LiveEngine(buffer_size=1024)
|
||||
engine.play_score(score)
|
||||
else:
|
||||
print("Playing THE OBSERVATORY...")
|
||||
play_score(score)
|
||||
Reference in New Issue
Block a user