mirror of
https://github.com/kennethreitz/interpretations.git
synced 2026-06-05 23:00:19 +00:00
Acid Reign: complete rewrite — dual 303s, 5 groove patterns, 808 sub
Two 303 voices (saw + square octave-down) with sweeping resonance. Five hand-written 16th note patterns building from sparse to relentless. Filter Q sweeps from 3→12 for screaming resonance. 808 sub bass on the root. Sidechain on everything. 140 BPM, A minor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+146
-115
@@ -1,139 +1,172 @@
|
||||
"""
|
||||
ACID REIGN — 303 acid bass. Groovy, squelchy, raw.
|
||||
ACID REIGN — two 303s fighting each other through a wall of resonance.
|
||||
"""
|
||||
|
||||
from pytheory import Key, Duration, Score, Tone, play_score
|
||||
from pytheory.rhythm import DrumSound
|
||||
|
||||
key = Key("A", "minor")
|
||||
s = key.scale
|
||||
|
||||
# Notes in the bass range (octave 2-3)
|
||||
# Bass range notes
|
||||
A = Tone.from_string("A2")
|
||||
B = Tone.from_string("B2")
|
||||
Bb = Tone.from_string("Bb2")
|
||||
C = Tone.from_string("C3")
|
||||
D = Tone.from_string("D3")
|
||||
E = Tone.from_string("E3")
|
||||
F = Tone.from_string("F3")
|
||||
G = Tone.from_string("G3")
|
||||
Ab = Tone.from_string("Ab2") # chromatic approach
|
||||
Bb = Tone.from_string("Bb2")
|
||||
G = Tone.from_string("G2")
|
||||
A1 = Tone.from_string("A1") # sub octave
|
||||
|
||||
score = Score("4/4", bpm=135)
|
||||
score = Score("4/4", bpm=140)
|
||||
|
||||
K = DrumSound.KICK
|
||||
CL = DrumSound.CLAP
|
||||
CH = DrumSound.CLOSED_HAT
|
||||
OH = DrumSound.OPEN_HAT
|
||||
|
||||
# ── 303 — the groove, hand-written, legato slides ──────────────
|
||||
acid = score.part("303", synth="saw", volume=0.7,
|
||||
lowpass=800, lowpass_q=4.0,
|
||||
distortion=0.3, distortion_drive=4.0,
|
||||
# ── 303 MAIN — the lead voice ──────────────────────────────────
|
||||
acid = score.part("303", synth="saw", volume=0.6,
|
||||
lowpass=600, lowpass_q=6.0,
|
||||
distortion=0.35, distortion_drive=4.0,
|
||||
saturation=0.6, legato=True, glide=0.05,
|
||||
sub_osc=0.4, sidechain=0.3)
|
||||
acid.lfo("lowpass", rate=0.02, min=500, max=6000, bars=64, shape="triangle")
|
||||
# Filter sweeps UP across the track — the whole point of acid
|
||||
acid.lfo("lowpass", rate=0.01, min=300, max=10000, bars=64, shape="saw")
|
||||
# Resonance also sweeps
|
||||
acid.lfo("lowpass_q", rate=0.02, min=3.0, max=12.0, bars=32, shape="triangle")
|
||||
|
||||
# Four groove patterns — the rests make the groove
|
||||
# Pattern A: pumping root — DUM-rest-dum-DUM rest-dum-dum-DUM
|
||||
pA = [(A, 110), (None, 0), (A, 80), (E, 100),
|
||||
(None, 0), (A, 85), (G, 75), (A, 105)]
|
||||
# ── 303 SUB — dirty double, octave down, more distortion ───────
|
||||
acid2 = score.part("303_sub", synth="square", volume=0.35,
|
||||
lowpass=400, lowpass_q=3.0,
|
||||
distortion=0.5, distortion_drive=6.0,
|
||||
saturation=0.7, legato=True, glide=0.08,
|
||||
pan=0.15)
|
||||
acid2.lfo("lowpass", rate=0.015, min=200, max=4000, bars=64, shape="triangle")
|
||||
|
||||
# Pattern B: climbing — slides up chromatically
|
||||
pB = [(A, 105), (Bb, 80), (C, 95), (None, 0),
|
||||
(C, 85), (D, 90), (E, 100), (None, 0)]
|
||||
# 16th note patterns — the groove comes from accent + rest placement
|
||||
# _ = rest, lowercase = soft, UPPERCASE = hard accent
|
||||
#
|
||||
# Real acid: every note that ISN'T a rest or accent matters just as much
|
||||
# The pattern creates tension by where it DOESN'T play
|
||||
|
||||
# Pattern C: menacing — big gaps, low hits
|
||||
pC = [(A, 110), (None, 0), (None, 0), (E, 95),
|
||||
(None, 0), (A, 100), (Ab, 85), (A, 108)]
|
||||
def acid_bar(part, notes, sub_part=None, sub_offset=-12):
|
||||
"""Write one bar of 16th notes. None = rest."""
|
||||
for note, vel in notes:
|
||||
if note is None:
|
||||
part.rest(Duration.SIXTEENTH)
|
||||
if sub_part:
|
||||
sub_part.rest(Duration.SIXTEENTH)
|
||||
else:
|
||||
part.add(note, Duration.SIXTEENTH, velocity=vel)
|
||||
if sub_part:
|
||||
sub_part.add(note.add(sub_offset), Duration.SIXTEENTH,
|
||||
velocity=max(30, vel - 20))
|
||||
|
||||
# Pattern D: funky — syncopated, all over the place
|
||||
pD = [(None, 0), (A, 100), (C, 90), (None, 0),
|
||||
(E, 105), (D, 85), (None, 0), (A, 110)]
|
||||
# ── THE PATTERNS ────────────────────────────────────────────────
|
||||
# Each is 16 steps (one bar of 16ths at 140 BPM)
|
||||
|
||||
# Bars 1-8: 303 alone — patterns A and B
|
||||
for _ in range(2):
|
||||
for pat in [pA, pB]:
|
||||
for _ in range(2):
|
||||
for note, vel in pat:
|
||||
if note is None:
|
||||
acid.rest(Duration.EIGHTH)
|
||||
else:
|
||||
acid.add(note, Duration.EIGHTH, velocity=vel)
|
||||
# P1: the hook — simple, driving, root-heavy
|
||||
P1 = [(A, 110), (None, 0), (A, 75), (None, 0),
|
||||
(A, 105), (E, 80), (None, 0), (A, 110),
|
||||
(None, 0), (None, 0), (A, 85), (E, 90),
|
||||
(A, 108), (None, 0), (G, 78), (A, 112)]
|
||||
|
||||
# Bars 9-24: cycling all patterns
|
||||
for _ in range(2):
|
||||
for pat in [pA, pB, pC, pD]:
|
||||
for _ in range(2):
|
||||
for note, vel in pat:
|
||||
if note is None:
|
||||
acid.rest(Duration.EIGHTH)
|
||||
else:
|
||||
acid.add(note, Duration.EIGHTH, velocity=vel)
|
||||
# P2: the answer — climbing, chromatic tension
|
||||
P2 = [(A, 105), (Bb, 82), (C, 90), (C, 75),
|
||||
(D, 95), (None, 0), (C, 80), (A, 100),
|
||||
(None, 0), (Bb, 78), (A, 105), (None, 0),
|
||||
(G, 85), (A, 110), (None, 0), (None, 0)]
|
||||
|
||||
# Bars 25-32: just A and C patterns, harder
|
||||
for _ in range(2):
|
||||
for pat in [pA, pC]:
|
||||
for _ in range(2):
|
||||
for note, vel in pat:
|
||||
if note is None:
|
||||
acid.rest(Duration.EIGHTH)
|
||||
else:
|
||||
acid.add(note, Duration.EIGHTH, velocity=min(127, vel + 10))
|
||||
# P3: the freak — wide intervals, unexpected
|
||||
P3 = [(E, 110), (None, 0), (A, 90), (None, 0),
|
||||
(None, 0), (E, 105), (F, 82), (E, 100),
|
||||
(A, 112), (None, 0), (None, 0), (None, 0),
|
||||
(D, 95), (C, 85), (A, 108), (E, 90)]
|
||||
|
||||
# Bars 33-40: breakdown — sustained notes, filter wide open
|
||||
for _ in range(2):
|
||||
acid.add(A, Duration.WHOLE, velocity=90)
|
||||
acid.add(E, Duration.WHOLE, velocity=85)
|
||||
acid.add(C, Duration.WHOLE, velocity=88)
|
||||
acid.add(A, Duration.WHOLE, velocity=92)
|
||||
# P4: the build — relentless, fewer rests
|
||||
P4 = [(A, 108), (E, 85), (A, 100), (C, 90),
|
||||
(A, 105), (None, 0), (E, 88), (A, 110),
|
||||
(G, 82), (A, 108), (C, 92), (E, 95),
|
||||
(A, 112), (G, 80), (A, 105), (None, 0)]
|
||||
|
||||
# Bars 41-56: peak — all patterns cycling, max energy
|
||||
for _ in range(2):
|
||||
for pat in [pA, pB, pC, pD]:
|
||||
for _ in range(2):
|
||||
for note, vel in pat:
|
||||
if note is None:
|
||||
acid.rest(Duration.EIGHTH)
|
||||
else:
|
||||
acid.add(note, Duration.EIGHTH, velocity=min(127, vel + 12))
|
||||
# P5: the drop — ALL notes, maximum intensity
|
||||
P5 = [(A, 115), (Bb, 90), (A, 108), (E, 95),
|
||||
(A, 112), (C, 88), (D, 92), (A, 110),
|
||||
(E, 98), (F, 85), (E, 105), (A, 115),
|
||||
(G, 90), (A, 112), (Bb, 88), (A, 118)]
|
||||
|
||||
# Bars 57-64: patterns A only, filtering down
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
# ARRANGEMENT — builds intensity through pattern selection
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
# Bars 1-8: 303 alone — P1 and P2 alternating, sparse
|
||||
for _ in range(4):
|
||||
for _ in range(2):
|
||||
for note, vel in pA:
|
||||
if note is None:
|
||||
acid.rest(Duration.EIGHTH)
|
||||
else:
|
||||
acid.add(note, Duration.EIGHTH, velocity=max(40, vel - 15))
|
||||
acid_bar(acid, P1, acid2)
|
||||
acid_bar(acid, P2, acid2)
|
||||
|
||||
# ── KICK — four on the floor, enters bar 9, sidechained ────────
|
||||
# Bars 9-16: kick enters, still P1/P2
|
||||
for _ in range(4):
|
||||
acid_bar(acid, P1, acid2)
|
||||
acid_bar(acid, P2, acid2)
|
||||
|
||||
# Bars 17-24: P3 enters — gets weird
|
||||
for _ in range(2):
|
||||
acid_bar(acid, P1, acid2)
|
||||
acid_bar(acid, P3, acid2)
|
||||
acid_bar(acid, P2, acid2)
|
||||
acid_bar(acid, P3, acid2)
|
||||
|
||||
# Bars 25-32: P4 takes over — relentless build
|
||||
for _ in range(4):
|
||||
acid_bar(acid, P4, acid2)
|
||||
acid_bar(acid, P4, acid2)
|
||||
|
||||
# Bars 33-40: BREAKDOWN — sustained notes, filter screaming
|
||||
for _ in range(2):
|
||||
acid.add(A, Duration.WHOLE, velocity=95)
|
||||
acid2.add(A1, Duration.WHOLE, velocity=80)
|
||||
acid.add(E, Duration.WHOLE, velocity=90)
|
||||
acid2.add(Tone.from_string("E1"), Duration.WHOLE, velocity=75)
|
||||
acid.add(C, Duration.WHOLE, velocity=88)
|
||||
acid2.add(Tone.from_string("C2"), Duration.WHOLE, velocity=78)
|
||||
acid.add(A, Duration.WHOLE, velocity=95)
|
||||
acid2.add(A1, Duration.WHOLE, velocity=82)
|
||||
|
||||
# Bars 41-56: THE DROP — P5 (maximum intensity) cycling with P1
|
||||
for _ in range(4):
|
||||
acid_bar(acid, P5, acid2)
|
||||
acid_bar(acid, P1, acid2)
|
||||
acid_bar(acid, P5, acid2)
|
||||
acid_bar(acid, P3, acid2)
|
||||
|
||||
# Bars 57-64: outro — back to P1 alone, filtering down
|
||||
for _ in range(4):
|
||||
acid_bar(acid, P1, acid2)
|
||||
acid_bar(acid, P1, acid2)
|
||||
|
||||
# ── KICK — enters bar 9 ────────────────────────────────────────
|
||||
kick = score.part("kick", volume=0.5, humanize=0.03)
|
||||
|
||||
for _ in range(8):
|
||||
kick.rest(Duration.WHOLE)
|
||||
|
||||
for _ in range(48):
|
||||
for beat in range(4):
|
||||
kick.hit(K, Duration.QUARTER, velocity=118)
|
||||
|
||||
for bar in range(8):
|
||||
vel = max(30, 112 - bar * 10)
|
||||
vel = max(30, 115 - bar * 10)
|
||||
for beat in range(4):
|
||||
kick.hit(K, Duration.QUARTER, velocity=vel)
|
||||
|
||||
# ── CLAP — 2 and 4, enters bar 9 ──────────────────────────────
|
||||
# ── CLAP — 2 and 4 ─────────────────────────────────────────────
|
||||
clap = score.part("clap", volume=0.3, reverb=0.15, humanize=0.04)
|
||||
|
||||
for _ in range(8):
|
||||
clap.rest(Duration.WHOLE)
|
||||
|
||||
for _ in range(48):
|
||||
clap.rest(Duration.QUARTER)
|
||||
clap.hit(CL, Duration.QUARTER, velocity=100)
|
||||
clap.rest(Duration.QUARTER)
|
||||
clap.hit(CL, Duration.QUARTER, velocity=102)
|
||||
|
||||
for bar in range(8):
|
||||
vel = max(25, 95 - bar * 9)
|
||||
clap.rest(Duration.QUARTER)
|
||||
@@ -141,47 +174,45 @@ for bar in range(8):
|
||||
clap.rest(Duration.QUARTER)
|
||||
clap.hit(CL, Duration.QUARTER, velocity=vel)
|
||||
|
||||
# ── HATS — 16ths with open hat accents, enters bar 17 ──────────
|
||||
hats = score.part("hats", volume=0.25, humanize=0.04, sidechain=0.15)
|
||||
|
||||
for _ in range(16):
|
||||
hats.rest(Duration.WHOLE)
|
||||
|
||||
for _ in range(40):
|
||||
for beat in range(4):
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=75)
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=42)
|
||||
hats.hit(OH if beat % 2 == 1 else CH, Duration.SIXTEENTH, velocity=60)
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=40)
|
||||
|
||||
for bar in range(8):
|
||||
vel = max(20, 68 - bar * 6)
|
||||
for beat in range(4):
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=vel)
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=max(15, vel - 28))
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=max(15, vel - 15))
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=max(15, vel - 30))
|
||||
|
||||
# ── PAD — dark atmosphere, sidechained ──────────────────────────
|
||||
pad = score.part("pad", synth="supersaw", envelope="pad", volume=0.15,
|
||||
reverb=0.5, chorus=0.3, chorus_rate=0.2,
|
||||
chorus_depth=0.008, lowpass=1200,
|
||||
sidechain=0.4)
|
||||
|
||||
prog = key.progression("i", "VII", "VI", "v")
|
||||
# ── HATS — 16ths, enters bar 9 ─────────────────────────────────
|
||||
hats = score.part("hats", volume=0.22, humanize=0.04, sidechain=0.15)
|
||||
|
||||
for _ in range(8):
|
||||
pad.rest(Duration.WHOLE)
|
||||
hats.rest(Duration.WHOLE)
|
||||
for _ in range(48):
|
||||
for beat in range(4):
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=72)
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=40)
|
||||
hats.hit(OH if beat % 2 == 1 else CH, Duration.SIXTEENTH, velocity=58)
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=38)
|
||||
for bar in range(8):
|
||||
vel = max(18, 65 - bar * 6)
|
||||
for beat in range(4):
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=vel)
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=max(12, vel - 28))
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=max(12, vel - 15))
|
||||
hats.hit(CH, Duration.SIXTEENTH, velocity=max(12, vel - 30))
|
||||
|
||||
for _ in range(14):
|
||||
for chord in prog:
|
||||
pad.add(chord, Duration.WHOLE, velocity=60)
|
||||
# ── 808 SUB — deep sine, follows the root ───────────────────────
|
||||
sub = score.part("808", synth="sine", envelope="pad", volume=0.35,
|
||||
lowpass=100, distortion=0.15, distortion_drive=2.0,
|
||||
sidechain=0.4)
|
||||
|
||||
for _ in range(8):
|
||||
sub.rest(Duration.WHOLE)
|
||||
for _ in range(48):
|
||||
sub.add(A1, Duration.HALF, velocity=95)
|
||||
sub.rest(Duration.HALF)
|
||||
for bar in range(8):
|
||||
vel = max(20, 85 - bar * 10)
|
||||
sub.add(A1, Duration.HALF, velocity=vel)
|
||||
sub.rest(Duration.HALF)
|
||||
|
||||
# ═════════════════════════════════════════════════════════════════
|
||||
import sys
|
||||
|
||||
print(f"Key: {key}")
|
||||
print(f"BPM: 135")
|
||||
print(f"BPM: 140")
|
||||
print(f"Parts: {list(score.parts.keys())}")
|
||||
print(f"Duration: {score.duration_ms / 1000:.1f}s | {score.measures} measures")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user