Files
pytheory/examples/songs.py
T
kennethreitz a5c9a46eb2 Add ensemble= to strings, cellos, choir, pads in songs.py
String ensembles: 6-10 players. Cellos: 3 players.
Choir: 6 voices. Cathedral siren pad: 4 voices.
Makes everything sound fuller and more alive.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 10:39:51 -04:00

3066 lines
126 KiB
Python

"""Play songs with PyTheory — drums, chords, bass, leads, and effects.
Requires PortAudio: brew install portaudio (macOS)
Each song showcases the full Score API:
- 58 drum pattern presets with genre-matched fills
- 10 synth waveforms (sine, saw, triangle, square, pulse, FM, noise, supersaw, PWM slow/fast)
- 8 ADSR envelope presets
- Per-part effects: reverb, delay, lowpass filter with resonance
- Named parts with independent voices mixed together
Usage:
python examples/song.py
"""
import sounddevice as sd
from pytheory import Chord, Key, Pattern, Duration, Score, Tone, TonedScale, SYSTEMS
from pytheory.rhythm import DrumSound, _Hit
from pytheory.play import render_score, SAMPLE_RATE
def play_song(score, label=""):
"""Render and play. Ctrl-C to skip."""
if label:
print(f" {label}")
print(f" {score}")
print()
try:
buf = render_score(score)
sd.play(buf, SAMPLE_RATE)
sd.wait()
except KeyboardInterrupt:
sd.stop()
print(" (skipped)")
# ── Songs ──────────────────────────────────────────────────────────────────
def bossa_nova_girl():
"""Bossa nova in A minor — Ipanema vibes with reverb-washed chords."""
print(" Bossa Nova in A minor")
print(" bossa nova drums | FM rhodes + reverb | triangle lead + delay")
print(" sine bass + LP 600Hz")
score = Score("4/4", bpm=140)
score.drums("bossa nova", repeats=4)
rhodes = score.part("rhodes", instrument="electric_piano",
volume=0.3, pan=-0.3,
reverb=0.4, reverb_decay=1.8, reverb_type="plate")
lead = score.part("lead", instrument="flute",
volume=0.45, pan=0.3,
delay=0.25, delay_time=0.32, delay_feedback=0.35,
reverb=0.2, reverb_type="plate",
humanize=0.2)
bass = score.part("bass", instrument="upright_bass",
volume=0.45, pan=0.0, lowpass=600,
humanize=0.2, reverb=0.2)
for sym in ["Am", "Am", "Dm", "Dm", "E7", "E7", "Am", "Am"]:
rhodes.add(Chord.from_symbol(sym), Duration.WHOLE)
for n, d, v in [
("E5",.67,85),("D5",.33,75),("C5",.67,80),("B4",.33,70),("A4",1,85),("C5",.67,78),("E5",.33,82),
("D5",.67,78),("C5",.33,72),("A4",1,80),(None,1,0),
("F5",.67,88),("E5",.33,78),("D5",.67,82),("C5",.33,72),("D5",1,80),("F5",.67,85),("A5",.33,90),
("G5",.67,82),("F5",.33,75),("D5",1,78),(None,1,0),
("G#5",.67,92),("F5",.33,78),("E5",.67,85),("D5",.33,75),("E5",1,82),(None,.5,0),("B4",.5,72),
("D5",.67,78),("E5",.33,82),("G#4",1,75),(None,1,0),
("A4",1,80),("C5",.67,78),("E5",.33,85),("A5",1.5,95),(None,.5,0),
("G5",.67,82),("E5",.33,78),("C5",.67,75),("A4",.33,70),("A4",2,85),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["A2","E2","A2","C3","D2","A2","D2","F2",
"E2","B2","E2","G#2","A2","E2","A2","C3",
"A2","E2","A2","C3","D2","A2","D2","F2",
"E2","B2","E2","G#2","A2","E2","A2","A2"]:
bass.add(n, Duration.QUARTER)
play_song(score)
def bebop_in_bb():
"""Bebop in Bb — horn lead over rhythm changes with walking bass."""
print(" Bebop in Bb major")
print(" bebop drums + fill | saw lead + LP 4kHz | FM rhodes + reverb")
score = Score("4/4", bpm=160)
score.drums("bebop", repeats=8, fill="jazz", fill_every=8)
rhodes = score.part("rhodes", instrument="electric_piano",
volume=0.25, pan=-0.3,
reverb=0.35, reverb_decay=1.2, reverb_type="plate")
lead = score.part("lead", instrument="trumpet",
volume=0.4, pan=0.25,
lowpass=4000, lowpass_q=1.1,
delay=0.15, delay_time=0.19, delay_feedback=0.25,
reverb=0.15, reverb_type="plate",
humanize=0.2)
bass = score.part("bass", instrument="upright_bass",
volume=0.4, pan=0.0, lowpass=500,
humanize=0.2, reverb=0.2)
for sym in ["Bb", "Gm", "Cm", "F7"] * 2:
rhodes.add(Chord.from_symbol(sym), Duration.WHOLE)
for n, d, v in [
("Bb4",.67,82),("D5",.33,75),("F5",.67,88),("D5",.33,78),
("Bb4",.67,80),("C5",.33,72),("D5",.67,82),("F5",.33,85),
("G5",.67,90),("F5",.33,78),("D5",.67,82),("Bb4",.33,72),
("A4",.67,78),("Bb4",.33,72),("D5",.67,85),("G4",.33,70),
("C5",.67,82),("Eb5",.33,78),("G5",.67,92),("Eb5",.33,80),
("C5",.67,78),("D5",.33,75),("Eb5",.67,82),("F5",.33,85),
("A5",.67,95),("G5",.33,82),("F5",.67,85),("Eb5",.33,78),
("D5",.67,80),("C5",.33,72),("A4",.5,75),(None,.5,0),
("Bb4",1,85),("D5",.67,80),("F5",.33,88),
("G5",.67,90),("F5",.33,82),("D5",.67,78),("Bb4",.33,72),
("Bb5",.67,95),("A5",.33,85),("G5",.67,88),("F5",.33,80),
("Eb5",.67,82),("D5",.33,75),("Bb4",.67,78),("G4",.33,70),
("C5",.5,78),(None,.5,0),("Eb5",.67,82),("G5",.33,88),
("F5",.67,85),("Eb5",.33,78),("D5",.67,82),("C5",.33,75),
("A4",.67,78),("C5",.33,80),("Eb5",.67,85),("F5",.33,88),
("G5",.67,92),("A5",.33,88),("Bb5",1,95),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["Bb2","D3","F3","A3","G3","F3","D3","Bb2",
"C3","Eb3","G3","Bb3","F3","A3","C4","Eb3",
"Bb2","D3","F3","A3","G3","F3","D3","Bb2",
"C3","Eb3","G3","Bb3","F3","C3","F2","F3"]:
bass.add(n, Duration.QUARTER)
play_song(score)
def salsa_descarga():
"""Salsa descarga in D minor — clave-driven with timbale lead."""
print(" Salsa Descarga in D minor")
print(" salsa drums + fill | saw lead + delay | pulse bass + LP 500Hz")
score = Score("4/4", bpm=180)
score.drums("salsa", repeats=8, fill="salsa", fill_every=4)
pads = score.part("pads", synth="pwm_slow", envelope="pad",
volume=0.2, pan=-0.35,
reverb=0.3, reverb_type="plate", lowpass=2000,
detune=10, humanize=0.2)
lead = score.part("lead", instrument="trumpet",
volume=0.4, pan=0.3,
delay=0.2, delay_time=0.167, delay_feedback=0.3,
reverb=0.15, reverb_type="plate",
humanize=0.2)
bass = score.part("bass", instrument="synth_bass",
volume=0.45, pan=0.0, lowpass=500, lowpass_q=1.3,
humanize=0.2, reverb=0.2)
for sym in ["Em7b5", "A7", "Dm7", "Bbmaj7"] * 2:
pads.add(Chord.from_symbol(sym), Duration.WHOLE)
for n, d, v in [
("E5",.67,85),("G5",.33,78),("Bb5",.67,92),("A5",.33,82),
("G5",.67,85),("F5",.33,78),("E5",.67,82),("D5",.33,75),
("C#5",.67,80),("D5",.33,75),("E5",.67,85),("G5",.33,80),
("F5",.67,82),("E5",.33,78),("C#5",.5,75),(None,.5,0),
("D5",.5,78),(None,.17,0),("F5",.67,85),("A5",.33,90),
("G5",.67,88),("F5",.33,80),("E5",.67,82),("D5",.33,75),
("Bb4",1,78),("D5",.67,82),("F5",.33,88),("A5",1,95),(None,1,0),
("E5",.5,80),("F5",.5,82),("G5",.67,88),("A5",.33,85),
("Bb5",.67,95),("A5",.33,85),("G5",.67,88),("E5",.33,78),
("C#5",.67,80),("E5",.33,82),("A5",.67,92),("G5",.33,85),
("F5",.67,82),("E5",.33,78),("C#5",.67,75),("A4",.33,70),
("D5",1,82),("F5",.67,85),("A5",.33,92),("G5",.67,88),("F5",.33,80),("D5",1,78),(None,1,0),
("Bb4",.67,75),("D5",.33,80),("F5",.67,88),("Bb5",.33,95),("A5",1.5,90),(None,.5,0),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["E2","E3","A2","A3","D2","D3","Bb2","Bb3"] * 4:
bass.add(n, Duration.QUARTER)
play_song(score)
def afrobeat_groove():
"""Afrobeat in E minor — Fela-inspired hypnotic groove."""
print(" Afrobeat in E minor")
print(" afrobeat drums + fill | saw lead + LP 3kHz | supersaw pads + reverb")
score = Score("4/4", bpm=115)
score.drums("afrobeat", repeats=8, fill="afrobeat", fill_every=8)
pads = score.part("pads", instrument="synth_pad",
volume=0.2, pan=-0.3,
reverb=0.4, reverb_decay=2.0, reverb_type="cathedral",
lowpass=3000)
lead = score.part("lead", instrument="trumpet",
volume=0.4, pan=0.3,
lowpass=3000, lowpass_q=1.0,
delay=0.2, delay_time=0.26, delay_feedback=0.3,
reverb=0.15, reverb_type="plate",
humanize=0.2)
bass = score.part("bass", instrument="bass_guitar",
volume=0.5, pan=0.0, lowpass=500,
humanize=0.2, reverb=0.2)
for sym in ["Em", "Am", "D", "C"] * 2:
pads.add(Chord.from_symbol(sym), Duration.WHOLE)
riff = [("E5",.5,82),("G5",.5,78),("A5",.5,88),("G5",.5,80),
("E5",.5,78),("D5",.5,72),("E5",1,85),
("E5",.5,80),("G5",.5,78),("A5",.5,88),("B5",.5,92),
("A5",.5,85),("G5",.5,78),("E5",1,82),
(None,.5,0),("A5",.5,85),("G5",.5,80),("E5",.5,75),
("D5",1,78),("E5",.5,80),("G5",.5,82),
("A5",.5,88),("B5",.5,92),("A5",.5,85),("G5",.5,80),
("E5",1.5,82),(None,.5,0)]
for n, d, v in riff * 2:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["E2","E2","G2","A2","A2","G2","E2","D2",
"D2","D2","F#2","A2","C3","C3","B2","G2"] * 2:
bass.add(n, Duration.QUARTER)
play_song(score)
def reggae_one_drop():
"""Reggae one-drop in G major — roots vibes with dub effects."""
print(" Reggae One-Drop in G major")
print(" reggae drums + fill | triangle lead + delay + reverb")
print(" square chords + reverb | sine bass + LP 400Hz")
score = Score("4/4", bpm=80)
score.drums("reggae", repeats=8, fill="reggae", fill_every=8)
chords = score.part("chords", synth="square", envelope="staccato",
volume=0.2, pan=-0.4,
reverb=0.5, reverb_decay=2.0, reverb_type="cathedral",
lowpass=2000, detune=8,
humanize=0.2)
lead = score.part("lead", instrument="flute",
volume=0.4, pan=0.3,
delay=0.35, delay_time=0.5625, delay_feedback=0.45,
reverb=0.3, reverb_type="cathedral",
humanize=0.2)
bass = score.part("bass", instrument="bass_guitar",
volume=0.55, pan=0.0, lowpass=400, lowpass_q=1.3,
humanize=0.2, reverb=0.2)
for sym in ["G", "C", "D", "C"] * 2:
chords.add(Chord.from_symbol(sym), Duration.WHOLE)
for n, d, v in [
("G5",1.5,85),(None,.5,0),("B5",1,90),("A5",1,82),
("G5",2,80),("E5",1,75),("D5",1,72),
("C5",1.5,78),(None,.5,0),("E5",1,80),("G5",1,85),
("A5",1.5,88),(None,.5,0),("G5",2,82),
("D5",1.5,78),(None,.5,0),("E5",1,80),("G5",1,85),
("A5",2,90),("B5",1,92),("A5",1,85),
("G5",1.5,82),(None,.5,0),("E5",1,78),("D5",1,72),
("G4",3,75),(None,1,0),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["G2","G2","B2","D3","C3","C3","E3","G3",
"D3","D3","F#3","A3","C3","C3","E3","G3",
"G2","G2","B2","D3","C3","C3","E3","G3",
"D3","D3","F#3","A3","C3","G2","C3","D3"]:
bass.add(n, Duration.QUARTER)
play_song(score)
def funk_workout():
"""Funk in E minor — syncopated 16ths with filtered everything."""
print(" Funk Workout in E minor")
print(" funk drums + fill | saw lead + LP 3.5kHz Q=1.5 | pulse bass")
score = Score("4/4", bpm=100)
score.drums("funk", repeats=8, fill="funk", fill_every=4)
chords = score.part("chords", synth="square", envelope="staccato",
volume=0.25, pan=-0.4,
lowpass=2500, reverb=0.15, reverb_type="plate",
sidechain=0.4, humanize=0.2)
lead = score.part("lead", instrument="synth_lead",
volume=0.4, pan=0.35,
lowpass=3500, lowpass_q=1.5,
delay=0.15, delay_time=0.15, delay_feedback=0.25,
reverb=0.1, reverb_type="plate",
humanize=0.2)
bass = score.part("bass", instrument="synth_bass",
volume=0.5, pan=0.0, lowpass=600, lowpass_q=1.2,
humanize=0.2, reverb=0.15)
for sym in ["Em", "Am", "D", "B7"] * 2:
chords.add(Chord.from_symbol(sym), Duration.WHOLE)
for n, d, v in [
("E5",.25,90),("E5",.25,78),(None,.25,0),("G5",.25,85),
(None,.25,0),("A5",.25,88),("G5",.25,82),("E5",.25,78),
("D5",.5,80),("E5",.5,85),(None,.5,0),("B4",.5,72),
("E5",.25,88),("E5",.25,78),(None,.25,0),("G5",.25,85),
(None,.25,0),("A5",.25,90),("B5",.25,92),("A5",.25,85),
("G5",.5,82),("E5",.5,78),(None,1,0),
("A4",.25,80),("C5",.25,82),("E5",.25,88),("A5",.25,92),
("G5",.5,85),("E5",.5,78),(None,.5,0),("C5",.5,75),
("A4",.5,78),("C5",.5,80),("D5",.5,82),("E5",.5,85),
("E5",1,82),(None,1,0),
("D5",.25,82),("F#5",.25,85),("A5",.25,90),("D5",.25,78),
("F#5",.5,85),("D5",.5,78),("A4",.5,75),("D5",.5,80),
("D#5",.5,82),("F#5",.5,88),("B4",.5,78),("D#5",.5,82),
("F#5",1,85),(None,1,0),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["E2","E2","G2","E2","A2","A2","C3","A2",
"D2","D2","F#2","D2","B1","B1","D#2","F#2"] * 2:
bass.add(n, Duration.QUARTER)
play_song(score)
def blues_shuffle():
"""12/8 blues in A — slow shuffle with wailing lead."""
print(" 12/8 Blues Shuffle in A")
print(" 12/8 blues drums | saxophone lead + reverb + delay | upright bass + LP 500Hz")
score = Score("12/8", bpm=70)
score.drums("12/8 blues", repeats=6)
chords = score.part("chords", instrument="electric_piano",
volume=0.3, pan=-0.3,
reverb=0.3, reverb_decay=1.5, reverb_type="plate")
lead = score.part("lead", instrument="saxophone",
volume=0.45, pan=0.25,
reverb=0.3, reverb_decay=1.2, reverb_type="plate",
delay=0.2, delay_time=0.43, delay_feedback=0.3,
lowpass=3500,
humanize=0.2)
bass = score.part("bass", instrument="upright_bass",
volume=0.5, pan=0.0, lowpass=500,
humanize=0.2, reverb=0.2)
for sym in ["A", "A", "D", "D", "E7", "A"]:
chords.add(Chord.from_symbol(sym), Duration.DOTTED_HALF)
chords.add(Chord.from_symbol(sym), Duration.DOTTED_HALF)
for n, d, v in [
("A4",1,80),("C5",.67,85),("A4",.33,75),("E4",1,78),
(None,.5,0),("A4",.5,80),("C5",.67,85),("D5",.33,82),
("E5",1.5,92),("D5",.5,80),("C5",.5,78),("A4",.5,75),
("E4",1.5,72),(None,.5,0),("A4",1,80),
("D5",1,85),("F5",.67,90),("D5",.33,78),("A4",1,80),
(None,1,0),("D5",.67,82),("F5",.33,88),("A5",1,95),
("G5",.67,88),("F5",.33,80),("D5",1,78),(None,1,0),
("E5",.67,85),("G#4",.33,72),("B4",.67,80),("E5",.33,85),
("D5",1,82),("A4",1,78),(None,1,0),
("A4",.67,78),("C5",.33,82),("E5",.67,90),("A5",.33,95),
("A5",2,92),(None,1,0),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["A1","A1","E2","A2","A1","A1","E2","A2","A1","A1","E2","A2",
"D2","D2","A2","D2","D2","D2","A2","D2",
"E2","E2","B2","E2","A1","A1","E2","A2",
"E2","E2","B2","E2","A1","A1","E2","A2"]:
bass.add(n, Duration.QUARTER)
play_song(score)
def samba_de_janeiro():
"""Samba in G major — carnival energy with shimmering pads."""
print(" Samba in G major")
print(" samba drums + fill | triangle lead + delay | supersaw pads + reverb")
score = Score("4/4", bpm=170)
score.drums("samba", repeats=8, fill="samba", fill_every=8)
pads = score.part("pads", instrument="synth_pad",
volume=0.2, pan=-0.3,
reverb=0.45, reverb_decay=2.0, reverb_type="plate",
lowpass=4000)
lead = score.part("lead", instrument="flute",
volume=0.45, pan=0.3,
delay=0.2, delay_time=0.176, delay_feedback=0.3,
reverb=0.15, reverb_type="plate",
humanize=0.2)
bass = score.part("bass", instrument="bass_guitar",
volume=0.45, pan=0.0, lowpass=500,
humanize=0.2, reverb=0.2)
for sym in ["G", "Em", "Am", "D7"] * 2:
pads.add(Chord.from_symbol(sym), Duration.WHOLE)
for n, d, v in [
("B5",.33,88),("A5",.33,82),("G5",.34,78),("F#5",.5,82),("E5",.5,75),
("D5",.5,72),("G5",.5,80),("B5",.5,88),("A5",.5,82),
("G5",.67,85),("E5",.33,78),("D5",.67,75),("B4",.33,70),("G4",1,72),(None,1,0),
("E5",.5,80),("G5",.5,85),("B5",.5,90),("A5",.5,82),
("G5",.67,85),("F#5",.33,80),("E5",.67,78),("D5",.33,72),("E5",1,80),(None,1,0),
("A5",.5,85),("C6",.5,92),("B5",.5,88),("A5",.5,82),
("G5",.67,85),("E5",.33,78),("C5",.67,75),("A4",.33,70),("A4",1,72),(None,1,0),
("D5",.5,78),("F#5",.5,85),("A5",.5,90),("C5",.5,75),
("B4",.67,78),("A4",.33,72),("G4",.67,70),("F#4",.33,68),("G4",2,75),(None,2,0),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["G2","B2","D3","G2","E2","G2","B2","E2",
"A2","C3","E3","A2","D2","F#2","A2","D3"] * 2:
bass.add(n, Duration.QUARTER)
play_song(score)
def jazz_waltz():
"""Jazz waltz in F major — 3/4 with brushes and space."""
print(" Jazz Waltz in F major")
print(" waltz drums | triangle lead + reverb + delay | FM rhodes")
score = Score("3/4", bpm=150)
score.drums("waltz", repeats=16)
rhodes = score.part("rhodes", instrument="electric_piano",
volume=0.3, pan=-0.3,
reverb=0.4, reverb_decay=2.0, reverb_type="cathedral")
lead = score.part("lead", instrument="flute",
volume=0.4, pan=0.25,
reverb=0.3, reverb_decay=1.5, reverb_type="plate",
delay=0.2, delay_time=0.4, delay_feedback=0.3,
humanize=0.2)
bass = score.part("bass", instrument="upright_bass",
volume=0.4, pan=0.0, lowpass=500,
humanize=0.2, reverb=0.2)
for _ in range(2):
for sym in ["Fmaj7", "Gm", "C7", "Fmaj7"]:
for _ in range(4):
rhodes.add(Chord.from_symbol(sym), Duration.DOTTED_HALF)
for n, d, v in [
("A5",1.5,85),("G5",.5,78),("F5",1,80),("E5",1,75),("C5",1,72),("F5",1,80),
("A5",2,88),(None,1,0),("G5",2,82),(None,1,0),
("Bb5",1,90),("A5",.5,82),("G5",.5,78),("F5",1,80),("D5",1,75),("G5",1,82),
("Bb5",2,90),(None,1,0),("A5",1.5,85),("G5",.5,78),("F5",1,80),
("E5",1,78),("G5",1,82),("Bb5",1,88),("A5",1.5,85),("G5",.5,78),("E5",1,75),
("C5",2,72),(None,1,0),("E5",1,78),("G5",1,82),("C5",1,72),
("F5",2,82),("A5",1,88),("C6",2,92),(None,1,0),
("A5",1,85),("F5",1,80),("C5",1,72),("F5",3,82),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["F2","A2","C3","G2","Bb2","D3","C2","E2","G2","F2","A2","C3"] * 4:
bass.add(n, Duration.QUARTER)
play_song(score)
def house_anthem():
"""House in C minor — four-on-the-floor with acid lead."""
print(" House Anthem in C minor")
print(" house drums + fill | saw acid lead + LP 2kHz Q=2 + delay")
print(" supersaw pads + reverb | sine bass")
score = Score("4/4", bpm=124)
score.drums("house", repeats=8, fill="house", fill_every=8)
pads = score.part("pads", instrument="synth_pad",
volume=0.25, pan=-0.3,
reverb=0.5, reverb_decay=2.5, reverb_type="cathedral",
lowpass=5000,
sidechain=0.6)
lead = score.part("lead", instrument="synth_lead",
volume=0.35, pan=0.3,
lowpass=2000, lowpass_q=2.0,
delay=0.2, delay_time=0.242, delay_feedback=0.35,
reverb=0.15, reverb_type="plate")
bass = score.part("bass", instrument="808_bass",
volume=0.55, pan=0.0,
sidechain=0.5,
reverb=0.1)
for sym in ["Cm", "Ab", "Bb", "Cm"] * 2:
pads.add(Chord.from_symbol(sym), Duration.WHOLE)
for n, d in [
("C5",.25),("Eb5",.25),("G5",.25),("C5",.25),
("Eb5",.25),("G5",.25),("C5",.25),("Eb5",.25),
("G5",.25),("Eb5",.25),("C5",.25),("G4",.25),
("C5",.5),(None,.5),("Eb5",.5),("G5",.5),
("Ab4",.25),("C5",.25),("Eb5",.25),("Ab4",.25),
("C5",.25),("Eb5",.25),("Ab4",.25),("C5",.25),
("Eb5",.25),("C5",.25),("Ab4",.25),("Eb4",.25),
("Ab4",.5),(None,.5),("C5",.5),("Eb5",.5),
("Bb4",.25),("D5",.25),("F5",.25),("Bb4",.25),
("D5",.25),("F5",.25),("Bb4",.25),("D5",.25),
("F5",.5),("D5",.5),("Bb4",.5),("F5",.5),
("C5",.25),("Eb5",.25),("G5",.25),("C6",.25),
("G5",.25),("Eb5",.25),("C5",.25),(None,.25),
("C5",1.5),(None,.5),
("G5",.25),("G5",.25),("Eb5",.25),("C5",.25),
("G5",.25),("G5",.25),("Eb5",.25),("C5",.25),
("Eb5",.5),("C5",.5),("G4",.5),("C5",.5),
("Eb5",1),(None,1),
("Ab4",.5),("C5",.5),("Eb5",.5),("Ab5",.5),
("G5",.5),("Eb5",.5),("C5",1),
("Bb4",.5),("D5",.5),("F5",.5),("Bb5",.5),
("F5",.5),("D5",.5),("Bb4",1),
("C5",.5),("Eb5",.5),("G5",.5),("C6",.5),("C6",2),
]:
lead.rest(d) if n is None else lead.add(n, d)
for n in ["C2","C2","C2","C2","Ab1","Ab1","Ab1","Ab1",
"Bb1","Bb1","Bb1","Bb1","C2","C2","C2","C2"] * 2:
bass.add(n, Duration.QUARTER)
play_song(score)
def dub_kingston():
"""Dub in A minor — deep, sparse, drenched in effects."""
print(" Kingston After Dark")
print(" dub drums | triangle melodica + delay + reverb")
print(" square skank + reverb + LP 1.5kHz | sine bass + LP 400Hz")
print(" PWM siren + reverb + LP 1.2kHz")
score = Score("4/4", bpm=72)
score.drums("dub", repeats=8)
chords = score.part("chords", synth="square", envelope="staccato",
volume=0.2, pan=-0.4,
reverb=0.6, reverb_decay=2.5, reverb_type="cathedral",
lowpass=1500, lowpass_q=0.9, detune=8,
humanize=0.2)
lead = score.part("lead", instrument="flute",
volume=0.4, pan=0.3,
delay=0.45, delay_time=0.625, delay_feedback=0.5,
reverb=0.35, reverb_decay=2.0, reverb_type="cathedral",
humanize=0.2)
bass = score.part("bass", instrument="bass_guitar",
volume=0.6, pan=0.0, lowpass=400, lowpass_q=1.5,
humanize=0.2)
siren = score.part("siren", synth="pwm_slow", envelope="pad",
volume=0.15, pan=0.5, ensemble=4,
reverb=0.7, reverb_decay=3.0, reverb_type="cathedral",
lowpass=1200, detune=10)
for sym in ["Am", "Am", "Dm", "Dm", "Am", "Am", "Em", "Am"]:
chords.add(Chord.from_symbol(sym), Duration.WHOLE)
for n, d, v in [
("A4", 2, 78), (None, 2, 0), ("C5", 1.5, 82), (None, 2.5, 0),
("D5", 1, 85), ("C5", 1, 78), ("A4", 2, 75), (None, 4, 0),
("E5", 2, 88), (None, 2, 0), ("D5", 1.5, 82), ("C5", 1.5, 78), (None, 3, 0),
("A4", 1, 75), ("G4", 1, 70), ("A4", 3, 78), (None, 3, 0),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["A1","A1","A1","A1","D1","D1","D1","D1",
"A1","A1","A1","A1","E1","E1","A1","A1"]:
bass.add(n, Duration.HALF)
for n, d in [
(None, 8), ("A5", 4), (None, 4),
(None, 4), ("E5", 3), (None, 5),
("D5", 4), (None, 4),
]:
siren.rest(d) if n is None else siren.add(n, d)
play_song(score)
def techno_minimal():
"""Minimal techno in F minor — hypnotic and relentless."""
print(" Minimal Techno in F minor")
print(" techno drums | PWM fast lead + LP 1.5kHz Q=3 + delay")
print(" supersaw pad + reverb | sine sub bass")
score = Score("4/4", bpm=130)
score.drums("techno", repeats=8, fill="house", fill_every=8)
pad = score.part("pad", instrument="synth_pad",
volume=0.2, pan=-0.3,
reverb=0.5, reverb_decay=3.0, reverb_type="cathedral",
lowpass=3000,
sidechain=0.6)
lead = score.part("lead", synth="pwm_fast", envelope="staccato",
volume=0.35, pan=0.3,
lowpass=1500, lowpass_q=3.0,
delay=0.3, delay_time=0.231, delay_feedback=0.4,
reverb=0.1, reverb_type="plate",
humanize=0.2)
bass = score.part("bass", instrument="808_bass",
volume=0.55, pan=0.0,
sidechain=0.5,
reverb=0.1)
for sym in ["Fm", "Db", "Eb", "Fm"] * 2:
pad.add(Chord.from_symbol(sym), Duration.WHOLE)
# Minimal arpeggiated sequence — hypnotic repetition
seq = [("F4",.25),("Ab4",.25),("C5",.25),("F4",.25),
("Ab4",.25),("C5",.25),("Eb5",.25),("C5",.25)]
for n, d in seq * 8:
lead.add(n, d)
for n in ["F1","F1","F1","F1","Db1","Db1","Db1","Db1",
"Eb1","Eb1","Eb1","Eb1","F1","F1","F1","F1"] * 2:
bass.add(n, Duration.QUARTER)
play_song(score)
def gospel_shuffle():
"""Gospel in C major — joyful shuffle with FM organ."""
print(" Gospel Shuffle in C major")
print(" gospel drums + fill | FM organ + reverb | triangle lead + delay")
score = Score("4/4", bpm=108)
score.drums("gospel", repeats=8, fill="buildup", fill_every=8)
organ = score.part("organ", instrument="organ",
volume=0.3, pan=-0.3,
reverb=0.45, reverb_decay=2.0, reverb_type="cathedral")
lead = score.part("lead", instrument="flute",
volume=0.4, pan=0.3,
delay=0.2, delay_time=0.278, delay_feedback=0.3,
reverb=0.2, reverb_type="plate",
humanize=0.2)
bass = score.part("bass", instrument="upright_bass",
volume=0.45, pan=0.0, lowpass=500,
humanize=0.2, reverb=0.2)
for sym in ["C", "Am", "F", "G"] * 2:
organ.add(Chord.from_symbol(sym), Duration.WHOLE)
for n, d, v in [
("E5",.67,82),("G5",.33,78),("C6",1,92),("B5",.67,85),("A5",.33,80),
("G5",1,82),(None,1,0),
("A5",.67,85),("C6",.33,88),("E5",1,80),("D5",.67,78),("C5",.33,72),
("A4",1,75),(None,1,0),
("F5",.67,82),("A5",.33,85),("C6",1,92),("B5",.67,88),("A5",.33,82),
("G5",.67,80),("E5",.33,75),("C5",1,72),(None,1,0),
("D5",.67,78),("E5",.33,80),("G5",.67,85),("B5",.33,88),
("C6",2,92),(None,2,0),
# Second half: more intense
("C6",.67,95),("B5",.33,88),("A5",.67,90),("G5",.33,82),
("E5",1,85),("C5",.67,78),("E5",.33,82),
("A5",1,90),("G5",.67,85),("E5",.33,78),("C5",1,75),(None,1,0),
("F5",1,85),("A5",.67,90),("C6",.33,95),("E6",2,100),
("D6",.67,92),("C6",.33,88),("B5",.67,90),("G5",.33,82),
("C6",3,95),(None,1,0),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
for n in ["C2","E2","G2","C3","A1","C2","E2","A2",
"F2","A2","C3","F2","G2","B2","D3","G2"] * 2:
bass.add(n, Duration.QUARTER)
play_song(score)
def dub_delay_madness():
"""Dub with separate delay snare track — King Tubby style."""
print(" Dub Delay Madness in E minor")
print(" dub drums + separate snare w/ massive delay + reverb")
print(" square skank + reverb | sine sub bass | PWM siren")
score = Score("4/4", bpm=68)
score.drums("dub", repeats=8)
# Separate snare hits — fed through massive delay and reverb
# This is how Tubby did it: mute the snare from the main mix,
# then send it to a separate channel drowning in effects
from pytheory.rhythm import _Hit, DrumSound
for bar in range(8):
offset = bar * 4.0
# Snare on beat 3 of every bar
score._drum_hits.append(_Hit(DrumSound.SNARE, offset + 2.0, 110))
# Occasional rimshot ghost that the delay catches
if bar % 2 == 1:
score._drum_hits.append(_Hit(DrumSound.RIMSHOT, offset + 3.5, 60))
chords = score.part("skank", synth="square", envelope="staccato",
volume=0.15, pan=-0.4,
reverb=0.7, reverb_decay=3.0, reverb_type="cathedral",
lowpass=1200, detune=8, humanize=0.2)
bass = score.part("bass", instrument="bass_guitar",
volume=0.6, pan=0.0, lowpass=350, lowpass_q=1.5,
humanize=0.2)
siren = score.part("siren", synth="pwm_slow", envelope="pad",
volume=0.12, pan=0.5,
reverb=0.8, reverb_decay=4.0, reverb_type="cathedral",
delay=0.4, delay_time=0.88, delay_feedback=0.6,
lowpass=900, detune=10)
# Melodica stabs — sparse, lots of delay
melodica = score.part("melodica", instrument="flute",
volume=0.35, pan=0.3,
delay=0.6, delay_time=0.66, delay_feedback=0.55,
reverb=0.5, reverb_decay=2.5, reverb_type="cathedral",
humanize=0.2)
for sym in ["Em", "Em", "Am", "Am", "Em", "Em", "Bm", "Em"]:
chords.add(Chord.from_symbol(sym), Duration.WHOLE)
for n in ["E1","E1","E1","E1","A1","A1","A1","A1",
"E1","E1","E1","E1","B1","B1","E1","E1"]:
bass.add(n, Duration.HALF)
# Melodica: very sparse — let the delay do the work
for n, d, v in [
("E5", 1.5, 78), (None, 6.5, 0),
("G5", 1, 82), ("A5", 1, 85), (None, 6, 0),
(None, 4, 0), ("B5", 2, 88), (None, 6, 0),
("E5", 1, 75), (None, 3, 0), ("D5", 1.5, 72), (None, 2.5, 0),
]:
melodica.rest(d) if n is None else melodica.add(n, d, velocity=v)
# Siren: long notes that disappear into the void
for n, d in [
(None, 12), ("B5", 6), (None, 6),
("E5", 4), (None, 4),
]:
siren.rest(d) if n is None else siren.add(n, d)
play_song(score)
def drum_and_bass():
"""Drum and bass in A minor — 174 bpm liquid rollers."""
print(" Liquid DnB in A minor")
print(" drum and bass drums + fill | supersaw pads + reverb")
print(" triangle lead + delay | sine sub bass + LP 300Hz")
score = Score("4/4", bpm=174)
score.drums("drum and bass", repeats=8, fill="buildup", fill_every=8)
pads = score.part("pads", instrument="synth_pad",
volume=0.25, pan=-0.3,
reverb=0.5, reverb_decay=2.5, reverb_type="plate",
lowpass=4000)
lead = score.part("lead", instrument="flute",
volume=0.4, pan=0.3,
delay=0.3, delay_time=0.172, delay_feedback=0.4,
reverb=0.25, reverb_type="plate",
humanize=0.2)
bass = score.part("bass", instrument="808_bass",
volume=0.55, pan=0.0,
reverb=0.1)
for sym in ["Am", "F", "C", "G"] * 2:
pads.add(Chord.from_symbol(sym), Duration.WHOLE)
# Liquid melody — flowing, emotional
for n, d, v in [
("A5", 1, 85), ("G5", .5, 78), ("E5", .5, 72), ("C5", 1, 75), (None, 1, 0),
("D5", .5, 72), ("E5", .5, 78), ("G5", 1, 82), ("A5", 1.5, 88), (None, .5, 0),
("C6", 1, 92), ("B5", .5, 85), ("A5", .5, 80), ("G5", 1, 82), ("E5", 1, 75),
("F5", .5, 78), ("G5", .5, 82), ("A5", 1.5, 88), (None, .5, 0), ("G5", 1, 80),
("A5", 1, 85), ("G5", .5, 78), ("E5", .5, 72), ("C5", 1, 75), (None, 1, 0),
("E5", .5, 78), ("G5", .5, 82), ("B5", 1, 90), ("A5", 2, 85),
("G5", 1, 80), ("E5", .5, 75), ("D5", .5, 70), ("C5", 1.5, 72), (None, .5, 0),
("E5", .5, 78), ("G5", .5, 82), ("A5", 2, 88), (None, 1, 0),
]:
lead.rest(d) if n is None else lead.add(n, d, velocity=v)
# Sub bass — half note roots, deep
for n in ["A1","A1","F1","F1","C1","C1","G1","G1"] * 2:
bass.add(n, Duration.HALF)
play_song(score)
def drake_vibes():
"""Drake-style moody hip hop — 808s, pads, and melancholy."""
print(" Late Night Texts (Drake-style)")
print(" trap drums | FM bells + reverb + delay | supersaw pads + LP")
print(" sine 808 bass + distortion | PWM slow lead")
score = Score("4/4", bpm=68)
score.drums("trap", repeats=8, fill="trap", fill_every=8)
pads = score.part("pads", instrument="synth_pad",
volume=0.2, pan=-0.25,
reverb=0.5, reverb_decay=3.0, reverb_type="cathedral",
lowpass=2500,
sidechain=0.4)
bells = score.part("bells", instrument="vibraphone",
volume=0.3, pan=0.4,
reverb=0.4, reverb_decay=2.0, reverb_type="plate",
delay=0.25, delay_time=0.44, delay_feedback=0.35,
humanize=0.2)
lead = score.part("lead", synth="pwm_slow", envelope="strings",
volume=0.35, pan=-0.2,
reverb=0.3, reverb_type="cathedral", lowpass=2000,
delay=0.2, delay_time=0.88, delay_feedback=0.3,
humanize=0.2)
bass = score.part("bass", instrument="808_bass",
volume=0.6, pan=0.0,
distortion=0.4, distortion_drive=2.0,
sidechain=0.3)
for sym in ["Ebm", "B", "Gb", "Db"] * 2:
pads.add(Chord.from_symbol(sym), Duration.WHOLE)
# FM bells — sparse, melancholy arpeggios
for n, d in [
("Eb5", .5), ("Gb5", .5), ("Bb5", 1), (None, 2),
("Db5", .5), ("F5", .5), ("Ab5", 1), (None, 2),
("Gb5", .5), ("Bb5", .5), ("Db6", 1), (None, 2),
("F5", .5), ("Ab5", .5), ("Db6", 1.5), (None, 1.5),
("Eb5", .5), ("Gb5", .5), ("Bb5", 1), (None, 2),
("B4", .5), ("Eb5", .5), ("Gb5", 1), (None, 2),
("Gb5", 1), ("F5", .5), ("Eb5", .5), ("Db5", 2),
(None, 4),
]:
bells.rest(d) if n is None else bells.add(n, d)
# PWM lead — long held notes, moody
for n, d in [
(None, 4), ("Bb5", 3), (None, 1),
(None, 2), ("Ab5", 2), ("Gb5", 2), (None, 2),
("Db6", 4), (None, 4),
("Bb5", 2), ("Ab5", 2), (None, 4),
]:
lead.rest(d) if n is None else lead.add(n, d)
# 808 bass — sustained with distortion warmth
for n in ["Eb1","Eb1","Eb1","Eb1","B0","B0","B0","B0",
"Gb1","Gb1","Gb1","Gb1","Db1","Db1","Db1","Db1"] * 2:
bass.add(n, Duration.QUARTER)
play_song(score)
# ── Main ───────────────────────────────────────────────────────────────────
def neon_grid():
"""Cyberpunk electronic — stereo acid, wide pads, ping-pong bells."""
print(" Neon Grid in F minor")
print(" techno drums | dual acid L/R + LFO | supersaw pad spread=1.0")
print(" FM stabs | ping-pong bells | sine sub + sidechain")
score = Score("4/4", bpm=132)
score.drums("techno", repeats=8, fill="house", fill_every=8)
from pytheory.rhythm import _Hit, DrumSound
for bar in range(8):
for beat in range(4):
score._drum_hits.append(_Hit(DrumSound.KICK, bar * 4.0 + beat, 120))
score._drum_pattern_beats = max(score._drum_pattern_beats, 32.0)
sky = score.part(
"sky", instrument="synth_pad",
volume=0.18, pan=0.0,
detune=30, spread=1.0,
reverb=0.6, reverb_decay=3.5,
chorus=0.3, sidechain=0.5,
)
acid_l = score.part(
"acid_l", instrument="acid_bass",
volume=0.35, pan=-0.7,
legato=True, glide=0.025,
distortion=0.9, distortion_drive=12.0,
lowpass=800, lowpass_q=6.0,
delay=0.2, delay_time=0.227, delay_feedback=0.35,
)
acid_l.lfo("lowpass", rate=0.5, min=400, max=3000, bars=8, shape="sine")
acid_r = score.part(
"acid_r", instrument="acid_bass",
volume=0.3, pan=0.7,
legato=True, glide=0.02,
distortion=0.85, distortion_drive=10.0,
lowpass=1000, lowpass_q=5.0,
delay=0.25, delay_time=0.341, delay_feedback=0.4,
)
acid_r.lfo("lowpass", rate=0.33, min=500, max=2500, bars=8, shape="triangle")
sub = score.part(
"sub", instrument="808_bass",
volume=0.55, pan=0.0,
lowpass=160, sidechain=0.85, sidechain_release=0.08,
)
stab = score.part(
"stab", synth="fm", envelope="staccato",
volume=0.2, pan=-0.4,
reverb=0.4, reverb_decay=1.5,
detune=15, spread=0.7,
)
bell_l = score.part(
"bell_l", instrument="vibraphone",
volume=0.1, pan=-1.0,
reverb=0.7, reverb_decay=3.0,
)
bell_r = score.part(
"bell_r", instrument="vibraphone",
volume=0.1, pan=1.0,
reverb=0.7, reverb_decay=3.0,
delay=0.2, delay_time=0.8, delay_feedback=0.4,
)
chords = ["Fm", "Dbm", "Abm", "Ebm"]
for sym in chords * 2:
sky.add(Chord.from_symbol(sym), Duration.WHOLE)
for sym in chords:
acid_l.arpeggio(Chord.from_symbol(sym, octave=2), bars=2,
pattern="up", octaves=2, division=Duration.SIXTEENTH)
for sym in chords:
acid_r.arpeggio(Chord.from_symbol(sym, octave=2), bars=2,
pattern="down", octaves=2, division=Duration.SIXTEENTH)
for n in ["F1"] * 8 + ["Db1"] * 8 + ["Ab1"] * 8 + ["Eb1"] * 8:
sub.add(n, Duration.QUARTER)
for sym in chords * 2:
stab.rest(1)
stab.add(Chord.from_symbol(sym), 0.5)
stab.rest(0.5)
stab.add(Chord.from_symbol(sym), 0.5)
stab.rest(1.5)
for n, v, d in [
("F6", 50, 2), (None, 0, 6), ("Ab6", 45, 2), (None, 0, 6),
("Eb7", 55, 3), (None, 0, 13),
]:
bell_l.rest(d) if n is None else bell_l.add(n, d, velocity=v)
for n, v, d in [
(None, 0, 4), ("Db7", 45, 2), (None, 0, 6),
("F7", 50, 2), (None, 0, 6),
(None, 0, 4), ("Ab6", 40, 4), (None, 0, 8),
]:
bell_r.rest(d) if n is None else bell_r.add(n, d, velocity=v)
play_song(score)
def glass_and_silk():
"""Pure sine and triangle — smooth shapes in a stereo cathedral."""
print(" Glass and Silk in Ab major")
print(" sine + triangle only | waltz 72bpm | cathedral + Taj Mahal reverb")
score = Score("3/4", bpm=72, swing=0.2)
score.drums("waltz", repeats=16)
sub = score.part("sub", synth="sine", envelope="pad",
volume=0.3, pan=0.0, lowpass=120)
voice = score.part("voice", synth="triangle", envelope="strings",
volume=0.45, pan=0.2, legato=True, glide=0.07,
reverb=0.5, reverb_type="cathedral",
delay=0.2, delay_time=0.56, delay_feedback=0.4,
humanize=0.3)
pad = score.part("pad", synth="sine", envelope="pad",
volume=0.2, pan=0.0, detune=10, spread=0.6,
reverb=0.6, reverb_type="taj_mahal",
chorus=0.2, chorus_rate=0.3)
counter = score.part("counter", synth="triangle", envelope="strings",
volume=0.2, pan=-0.5,
reverb=0.4, reverb_type="plate",
delay=0.15, delay_time=0.83, delay_feedback=0.35,
humanize=0.25)
chords = [Chord.from_symbol(s) for s in ["Ab", "Fm", "Db", "Eb"]]
for c in chords * 2:
for _ in range(3):
pad.add(c, Duration.DOTTED_HALF)
for n in (["Ab2"] * 9 + ["F2"] * 9 + ["Db2"] * 9 + ["Eb2"] * 9) * 2:
sub.add(n, Duration.QUARTER)
for n, v, d in [
("Ab4", 60, 3), ("C5", 70, 1.5), ("Eb5", 75, 1.5),
("Ab5", 85, 4.5), (None, 0, 1.5),
("F5", 75, 1.5), ("Ab5", 80, 1.5), ("C6", 90, 3),
("Bb5", 80, 1.5), ("Ab5", 70, 1.5), (None, 0, 3),
("Db5", 70, 1.5), ("Eb5", 80, 1.5), ("Ab5", 95, 3),
("Bb5", 100, 3), ("C6", 105, 4.5), (None, 0, 1.5),
("Bb5", 85, 1.5), ("Ab5", 75, 1.5), ("Eb5", 70, 3),
("C5", 60, 3), ("Ab4", 55, 6), (None, 0, 3),
("Eb5", 65, 3), ("Ab5", 80, 3), ("C6", 90, 4.5), (None, 0, 1.5),
("Bb5", 85, 1.5), ("Ab5", 75, 1.5), ("F5", 70, 3),
("Eb5", 65, 1.5), ("Db5", 60, 1.5), (None, 0, 3),
("Eb5", 70, 1.5), ("F5", 80, 1.5), ("Ab5", 90, 3),
("Bb5", 95, 3), ("Ab5", 85, 3),
("Eb5", 70, 3), ("Ab4", 55, 9),
]:
voice.rest(d) if n is None else voice.add(n, d, velocity=v)
for _ in range(24):
counter.rest(Duration.QUARTER)
for n, v, d in [
(None, 0, 3), ("C6", 55, 3), ("Eb6", 60, 4.5), (None, 0, 1.5),
("Db6", 50, 3), ("C6", 45, 3), (None, 0, 6),
("Eb6", 55, 4.5), ("Db6", 50, 1.5), ("C6", 45, 3),
("Ab5", 40, 6), (None, 0, 3),
("Bb5", 50, 3), ("C6", 55, 4.5), (None, 0, 1.5),
("Ab5", 45, 9),
]:
counter.rest(d) if n is None else counter.add(n, d, velocity=v)
play_song(score)
def dance_party():
"""Dance party — bouncy, joyful, impossible not to move."""
print(" Dance Party at the Reitz House")
print(" disco 128bpm | FM sparkle | square chiptune arps | supersaw pump")
from pytheory.rhythm import _Hit, DrumSound
score = Score("4/4", bpm=128)
score.drums("disco", repeats=8, fill="buildup", fill_every=8)
for bar in range(8):
for beat in range(4):
score._drum_hits.append(_Hit(DrumSound.KICK, bar * 4.0 + beat, 120))
score._drum_pattern_beats = max(score._drum_pattern_beats, 32.0)
bass = score.part("bass", instrument="synth_bass",
volume=0.45, lowpass=500, lowpass_q=1.3,
sidechain=0.75, sidechain_release=0.12,
reverb=0.15)
sparkle = score.part("sparkle", instrument="vibraphone",
volume=0.3, pan=0.4, reverb=0.3, reverb_decay=1.5,
delay=0.2, delay_time=0.234, delay_feedback=0.3,
humanize=0.2)
chords_part = score.part("chords", instrument="synth_pad",
volume=0.2,
reverb=0.4, reverb_type="plate", sidechain=0.7)
fun = score.part("fun", synth="square", envelope="staccato",
volume=0.2, pan=-0.5, delay=0.15, delay_time=0.117,
delay_feedback=0.25, reverb=0.2)
for sym in ["C", "Am", "F", "G"] * 2:
chords_part.add(Chord.from_symbol(sym), Duration.WHOLE)
for n in ["C2", "C2", "C3", "C2", "A1", "A1", "A2", "A1",
"F1", "F1", "F2", "F1", "G1", "G1", "G2", "G1"] * 2:
bass.add(n, Duration.QUARTER)
for n, v, d in [
("E5", 100, 0.5), ("G5", 110, 0.5), ("C6", 120, 1), (None, 0, 0.5),
("B5", 100, 0.5), ("G5", 90, 0.5), ("E5", 100, 0.5),
("C5", 90, 0.5), ("E5", 100, 0.5), ("G5", 110, 1), (None, 0, 0.5),
("A5", 100, 0.5),
("C6", 120, 0.5), ("A5", 100, 0.5), ("F5", 90, 0.5), ("A5", 100, 0.5),
("C6", 110, 1), (None, 0, 1),
("B5", 100, 0.5), ("D6", 120, 0.5), ("B5", 100, 0.5), ("G5", 90, 0.5),
("D5", 80, 0.5), ("G5", 100, 1), (None, 0, 0.5),
("E5", 100, 0.5), ("G5", 110, 0.5), ("C6", 120, 1),
("E6", 125, 1), (None, 0, 0.5),
("D6", 110, 0.5), ("C6", 100, 0.5), ("B5", 90, 0.5),
("A5", 100, 0.5), ("G5", 110, 0.5), ("E5", 90, 1), (None, 0, 0.5),
("F5", 100, 0.5), ("A5", 110, 0.5), ("C6", 120, 1), (None, 0, 0.5),
("B5", 100, 0.5), ("G5", 110, 0.5), ("D6", 120, 0.5),
("C6", 110, 1), ("G5", 90, 0.5), ("C6", 120, 1), (None, 0, 0.5),
]:
sparkle.rest(d) if n is None else sparkle.add(n, d, velocity=v)
for sym in ["C", "Am", "F", "G", "C", "Am", "F", "G"]:
pat = "up" if sym in ("C", "F") else "updown"
fun.arpeggio(sym, bars=1, pattern=pat, octaves=2, division=Duration.EIGHTH)
play_song(score)
def temple_bell():
"""Japanese-inspired — sparse koto, Taj Mahal reverb, silence as instrument."""
print(" Temple Bell")
print(" E hirajoshi | 65 bpm | triangle koto + Taj Mahal reverb")
score = Score("4/4", bpm=65)
score.drums("bolero", repeats=8)
koto = score.part("koto", instrument="koto",
volume=0.45, pan=0.2,
reverb=0.5, reverb_type="taj_mahal")
drone = score.part("drone", synth="sine", envelope="pad",
volume=0.15, reverb=0.6, reverb_type="taj_mahal",
chorus=0.15, chorus_rate=0.2)
bell = score.part("bell", instrument="vibraphone",
volume=0.1, pan=-0.6,
reverb=0.8, reverb_type="taj_mahal")
for _ in range(8):
drone.add("E2", Duration.WHOLE)
for n, v, d in [
("E4", 70, 2), (None, 0, 2), ("A4", 60, 1.5), (None, 0, 2.5),
("B4", 75, 2), ("A4", 60, 1), ("E4", 55, 1), (None, 0, 4),
("C5", 80, 3), (None, 0, 1), ("B4", 65, 1.5), ("A4", 55, 1.5),
("E4", 50, 3), (None, 0, 5),
("F4", 60, 1), ("A4", 70, 1.5), ("B4", 80, 2.5), (None, 0, 3),
("E5", 85, 4), (None, 0, 4),
("C5", 65, 1.5), ("B4", 55, 1.5), ("A4", 50, 2),
("E4", 45, 5), (None, 0, 3),
]:
koto.rest(d) if n is None else koto.add(n, d, velocity=v)
for n, v, d in [
(None, 0, 8), ("E6", 30, 4), (None, 0, 8),
("B6", 25, 3), (None, 0, 9),
("A6", 30, 4), (None, 0, 12),
]:
bell.rest(d) if n is None else bell.add(n, d, velocity=v)
play_song(score)
def cinematic_showcase():
"""Cinematic orchestral showcase — tubular bells, strings, organ, harp, acid bass."""
score = Score("4/4", bpm=100)
# Tubular bells — dramatic intro
bells = score.part("bells", instrument="tubular_bells",
reverb=0.5, reverb_type="cathedral")
bells.add("A3", Duration.WHOLE)
for _ in range(7):
bells.rest(Duration.WHOLE)
# String ensemble — lush wide pad
strings = score.part("strings", instrument="string_ensemble", ensemble=8,
reverb=0.4, reverb_type="hall")
strings.rest(Duration.WHOLE)
for sym in ["Am", "F", "C", "G", "Dm", "Am", "E"]:
strings.add(Chord.from_symbol(sym), Duration.WHOLE)
# Cello — deep foundation
cello = score.part("cello", instrument="cello", ensemble=3,
reverb=0.3, reverb_type="hall")
cello.rest(Duration.WHOLE)
for n in ["A2", "F2", "C3", "G2", "D3", "A2", "E2"]:
cello.add(n, Duration.WHOLE)
# Violin — legato melody enters bar 3
violin = score.part("violin", instrument="violin",
reverb=0.25, reverb_type="hall", legato=True)
violin.rest(Duration.WHOLE)
violin.rest(Duration.WHOLE)
for note, dur in [
("E5", Duration.HALF), ("C5", Duration.HALF),
("D5", Duration.QUARTER), ("E5", Duration.QUARTER), ("G5", Duration.HALF),
("A5", Duration.HALF), ("G5", Duration.QUARTER), ("E5", Duration.QUARTER),
("F5", Duration.WHOLE),
("E5", Duration.HALF), ("D5", Duration.HALF),
("C5", Duration.HALF), ("B4", Duration.HALF),
("A4", Duration.WHOLE),
]:
violin.add(note, dur)
# Organ — enters halfway, cathedral weight
organ = score.part("organ", instrument="organ",
reverb=0.3, reverb_type="cathedral")
for _ in range(4):
organ.rest(Duration.WHOLE)
for sym in ["Dm", "Am", "E", "Am"]:
organ.add(Chord.from_symbol(sym), Duration.WHOLE)
# Harp — arpeggiated flourishes bars 3-4
harp = score.part("harp", instrument="harp")
harp.rest(Duration.WHOLE)
harp.rest(Duration.WHOLE)
for n in ["A3", "C4", "E4", "A4", "C5", "E5", "A5", "E5",
"G3", "B3", "D4", "G4", "B4", "D5", "G5", "D5"]:
harp.add(n, Duration.EIGHTH)
for _ in range(4):
harp.rest(Duration.WHOLE)
# Vibraphone — shimmer in last bars with delay
vib = score.part("vib", instrument="vibraphone",
delay=0.25, delay_time=0.375, delay_feedback=0.35)
for _ in range(5):
vib.rest(Duration.WHOLE)
for note, dur in [
("E5", Duration.QUARTER), ("D5", Duration.QUARTER),
("C5", Duration.QUARTER), ("A4", Duration.QUARTER),
("B4", Duration.HALF), ("E5", Duration.HALF),
("A5", Duration.WHOLE),
]:
vib.add(note, dur)
# Acid bass — gritty texture bars 4-5
acid = score.part("acid", instrument="acid_bass")
for _ in range(3):
acid.rest(Duration.WHOLE)
for n in ["C2", "C2", "E2", "G2", "G2", "G2", "A2", "E2",
"D2", "D2", "F2", "A2", "A2", "A2", "E2", "E2"]:
acid.add(n, Duration.EIGHTH)
for _ in range(2):
acid.rest(Duration.WHOLE)
# Half time drums
score.drums("half time", repeats=8)
play_song(score, "Cinematic Showcase — A minor")
def greensleeves():
"""Greensleeves — Renaissance lute, meantone tuning, A=415 Hz."""
score = Score("3/4", bpm=120, temperament="meantone", reference_pitch=415.0)
lute = score.part("lute", instrument="acoustic_guitar",
reverb=0.3, reverb_type="taj_mahal")
melody = [
("A4", 1.0, 80),
("C5", 2.0, 85), ("D5", 1.0, 80),
("E5", 3.0, 90),
("F5", 1.0, 75), ("E5", 2.0, 85),
("D5", 1.0, 80),
("B4", 3.0, 85),
("G4", 1.0, 70), ("B4", 2.0, 80),
("C5", 1.0, 75),
("A4", 3.0, 85),
("A4", 1.0, 70), ("A4", 2.0, 75),
("G#4", 1.0, 70),
("A4", 2.0, 80), ("B4", 1.0, 75),
("G4", 3.0, 85),
("E4", 1.0, 70),
("A4", 3.0, 90),
]
for note, dur, vel in melody:
lute.add(note, dur, velocity=vel)
play_song(score, "Greensleeves — Renaissance Lute (Meantone, A=415)")
def tabla_solo_yaman():
"""Tabla solo with tanpura drone, sitar, and Raga Yaman — 22-shruti tuning."""
shruti = SYSTEMS["shruti"]
score = Score("4/4", bpm=160, system=shruti)
h = _Hit
NA = DrumSound.TABLA_NA
TI = DrumSound.TABLA_TIN
GE = DrumSound.TABLA_GE
DH = DrumSound.TABLA_DHA
TT = DrumSound.TABLA_TIT
KE = DrumSound.TABLA_KE
GB = DrumSound.TABLA_GE_BEND
# Tanpura drone — Sa + Pa
tanpura_sa = score.part("tanpura_sa", synth="strings_synth", envelope="pad",
detune=3, lowpass=1000, volume=0.18,
reverb=0.5, reverb_type="taj_mahal")
tanpura_pa = score.part("tanpura_pa", synth="strings_synth", envelope="pad",
detune=3, lowpass=1400, volume=0.14,
reverb=0.5, reverb_type="taj_mahal")
sa3 = Tone("Sa", octave=3, system=shruti)
pa3 = Tone("Pa", octave=3, system=shruti)
for _ in range(16):
tanpura_sa.add(sa3, Duration.WHOLE)
tanpura_pa.add(pa3, Duration.WHOLE)
# Quiet sitar — Raga Yaman (Kalyan thaat)
sitar = score.part("sitar", instrument="sitar", volume=0.12,
reverb=0.4, reverb_type="taj_mahal")
ts = TonedScale(system=shruti, tonic=Tone("Sa", octave=4, system=shruti))
y = list(ts["kalyan"].tones)
S, R, G, M, P, D, N, S2 = y
sitar.rest(Duration.WHOLE)
sitar.rest(Duration.WHOLE)
for tone, dur, vel in [
(S, 3.0, 55), (R, 1.0, 50), (G, 3.0, 58), (R, 1.0, 48),
(S, 4.0, 55), (G, 1.0, 50), (M, 1.0, 52), (P, 3.0, 58),
(M, 1.0, 48), (G, 1.0, 50), (R, 1.0, 48), (S, 4.0, 55),
(P, 2.0, 52), (D, 1.0, 55), (N, 2.0, 58), (S2, 3.0, 60),
(N, 1.0, 52), (D, 1.0, 50), (P, 1.0, 52), (G, 1.0, 48),
(R, 1.0, 48), (S, 4.0, 55),
]:
sitar.add(tone, dur, velocity=vel)
# 4 bars drone intro (silence for drums)
silence = Pattern(name="silence", time_signature="4/4", beats=16.0, hits=[])
score.add_pattern(silence, repeats=1)
# Gentle opening
p1 = Pattern(name="gentle", time_signature="4/4", beats=8.0, hits=[
h(DH, 0.0, 80), h(NA, 2.0, 60),
h(DH, 4.0, 85), h(NA, 5.0, 55), h(NA, 6.0, 60), h(DH, 7.0, 80),
])
# Building with ghost notes
p2 = Pattern(name="build", time_signature="4/4", beats=16.0, hits=[
h(DH, 0.0, 95), h(TT, 0.5, 35), h(NA, 1.0, 70), h(TT, 1.5, 30),
h(NA, 2.0, 65), h(DH, 3.0, 90),
h(DH, 4.0, 100), h(TT, 4.25, 35), h(TT, 4.5, 40), h(NA, 5.0, 75),
h(TT, 5.5, 35), h(NA, 6.0, 70), h(TT, 6.5, 30), h(DH, 7.0, 95),
h(DH, 8.0, 95), h(TI, 9.0, 70), h(TI, 10.0, 72), h(NA, 11.0, 80),
h(TT, 11.25, 40), h(TT, 11.5, 42), h(KE, 11.75, 45),
h(TT, 12.0, 50), h(TT, 12.25, 55), h(KE, 12.5, 58), h(NA, 12.75, 70),
h(DH, 13.0, 100), h(TT, 13.25, 40), h(TT, 13.5, 45), h(KE, 13.75, 50),
h(NA, 14.0, 75), h(KE, 14.25, 50), h(DH, 14.5, 85), h(NA, 14.75, 70),
h(DH, 15.0, 110), h(GB, 15.5, 100),
])
# Full intensity
p3 = Pattern(name="fire", time_signature="4/4", beats=16.0, hits=[
h(TT, 0.0, 50), h(TT, 0.125, 35), h(TT, 0.25, 45), h(KE, 0.5, 55),
h(NA, 0.75, 85),
h(DH, 1.0, 115), h(TT, 1.25, 38), h(DH, 1.5, 70), h(NA, 1.75, 60),
h(TT, 2.0, 50), h(TT, 2.125, 35), h(TT, 2.25, 48), h(KE, 2.5, 55),
h(NA, 2.75, 88),
h(DH, 3.0, 115), h(GB, 3.5, 105), h(NA, 3.75, 72),
h(NA, 4.0, 115), h(NA, 4.25, 60), h(TT, 4.5, 40), h(NA, 4.75, 105),
h(GE, 5.0, 105), h(GE, 5.25, 55), h(GB, 5.5, 95), h(GE, 5.75, 50),
h(NA, 6.0, 115), h(TT, 6.125, 30), h(TT, 6.25, 38), h(NA, 6.5, 100),
h(TT, 6.625, 32), h(TT, 6.75, 42),
h(GB, 7.0, 115), h(KE, 7.25, 52), h(GE, 7.5, 72), h(KE, 7.75, 48),
# Tihai
h(DH, 8.0, 115), h(NA, 8.25, 78), h(TT, 8.5, 52), h(KE, 8.75, 58),
h(DH, 9.0, 105),
h(DH, 9.5, 110), h(NA, 9.75, 78), h(TT, 10.0, 52), h(KE, 10.25, 58),
h(DH, 10.5, 105),
h(DH, 11.0, 120), h(NA, 11.25, 82), h(TT, 11.5, 58), h(KE, 11.75, 62),
h(DH, 12.0, 120),
# Silence... then finish
h(GB, 14.5, 120),
h(DH, 15.5, 127), h(DH, 15.75, 127),
])
score.add_pattern(p1, repeats=1)
score.add_pattern(p2, repeats=1)
score.add_pattern(p3, repeats=1)
score.set_drum_effects(reverb=0.4, reverb_type="taj_mahal")
play_song(score, "Tabla Solo — Raga Yaman (22-Shruti, Taj Mahal)")
def journey():
"""Journey — piano → orchestra → world → sitar EDM.
One reverb space (Taj Mahal), tanpura drone throughout. Piano opens
alone, cello joins, harp/oboe/flute take over with djembe, sitar
arrives over tabla, builds to an EDM section with house drums.
"""
REV = "taj_mahal"
score = Score("4/4", bpm=72)
# ── Drone — runs the entire piece ──
tanpura = score.part("tanpura", synth="strings_synth", envelope="pad",
detune=3, lowpass=1000, volume=0.12,
reverb=0.6, reverb_type=REV)
for _ in range(40):
tanpura.add("A2", Duration.WHOLE)
# ── Bars 1-8: Piano alone, then cello ──
piano = score.part("piano", instrument="piano", volume=0.35,
reverb=0.6, reverb_type=REV)
for notes in [
["A2","E3","A3","C4","E4","C4","A3","E3"],
["F2","C3","F3","A3","C4","A3","F3","C3"],
["G2","D3","G3","B3","D4","B3","G3","D3"],
["E2","B2","E3","G#3","B3","G#3","E3","B2"],
["A2","E3","A3","C4","E4","C4","A3","E3"],
["D2","A2","D3","F3","A3","F3","D3","A2"],
["E2","B2","E3","G#3","B3","G#3","E3","B2"],
["A2","E3","A3","C4","E4","A4","E4","C4"],
]:
for n in notes:
piano.add(n, Duration.EIGHTH, velocity=68)
cello = score.part("cello", instrument="cello", volume=0.2,
reverb=0.55, reverb_type=REV)
cello.rest(Duration.WHOLE)
for note, dur, vel in [
("A3", 4.0, 55), ("C4", 4.0, 58),
("B3", 2.0, 52), ("A3", 2.0, 50), ("G3", 4.0, 55),
("F3", 4.0, 52), ("E3", 4.0, 55), ("A3", 4.0, 58),
]:
cello.add(note, dur, velocity=vel)
# ── Bars 9-16: Harp + oboe + flute + djembe ──
harp = score.part("harp", instrument="harp", volume=0.28,
reverb=0.6, reverb_type=REV)
oboe = score.part("oboe", instrument="oboe", volume=0.22,
reverb=0.55, reverb_type=REV)
flute = score.part("flute", instrument="flute", volume=0.18,
reverb=0.55, reverb_type=REV)
for _ in range(8):
harp.rest(Duration.WHOLE)
for notes in [
["A3","C4","E4","A4","C5","E5","A5","E5"],
["D3","F3","A3","D4","F4","A4","D5","A4"],
["E3","G3","B3","E4","G4","B4","E5","B4"],
["A3","C4","E4","A4","E5","C5","A4","E4"],
["F3","A3","C4","F4","A4","C5","F5","C5"],
["E3","G#3","B3","E4","G#4","B4","E5","B4"],
]:
for n in notes:
harp.add(n, Duration.EIGHTH, velocity=58)
for _ in range(9):
oboe.rest(Duration.WHOLE)
for note, dur, vel in [
("E5", 1.5, 62), ("D5", 0.5, 55), ("C5", 1.0, 58),
("A4", 1.0, 62), ("G4", 1.0, 55), ("A4", 1.5, 58),
("B4", 0.5, 52), ("C5", 2.0, 62), ("A4", 4.0, 58),
]:
oboe.add(note, dur, velocity=vel)
for _ in range(10):
flute.rest(Duration.WHOLE)
for note, dur, vel in [
("A5", 2.0, 50), ("G5", 1.0, 45), ("E5", 1.0, 48),
("D5", 2.0, 50), ("C5", 1.0, 45), ("A4", 1.0, 48),
("G4", 2.0, 50), ("A4", 2.0, 52),
]:
flute.add(note, dur, velocity=vel)
# ── Bars 15-20: Sitar + tabla ──
sitar = score.part("sitar", instrument="sitar", volume=0.2,
reverb=0.6, reverb_type=REV)
for _ in range(14):
sitar.rest(Duration.WHOLE)
for note, dur, vel in [
("A4", 1.0, 70), ("Bb4", 0.5, 60), ("A4", 0.5, 65),
("C5", 1.5, 75), ("Bb4", 0.5, 60),
("D5", 1.0, 70), ("E5", 1.5, 78),
("F5", 0.5, 62), ("E5", 1.0, 70),
("D5", 0.5, 62), ("C5", 0.5, 65), ("Bb4", 0.5, 58),
("A4", 2.0, 75),
("Bb4", 0.25, 55), ("C5", 0.25, 58), ("D5", 0.25, 62),
("E5", 0.25, 68),
("F5", 0.25, 65), ("G5", 0.25, 70), ("A5", 0.5, 80),
("G5", 0.25, 62), ("F5", 0.25, 58), ("E5", 0.5, 62),
("C5", 0.5, 58), ("Bb4", 0.5, 55), ("A4", 2.0, 75),
]:
sitar.add(note, dur, velocity=vel)
# ── EDM section — sitar over house beat ──
# Solo sections: 8+8+8+12 = 36 beats = 9 bars
# Total bars before EDM: 8 piano + 6 harp + 6 djembe + 4 tabla + 9 solo = 33
edm_start = 33
pad = score.part("pad", instrument="synth_pad", volume=0.18,
reverb=0.6, reverb_type=REV,
sidechain=0.6, sidechain_release=0.15)
for _ in range(edm_start):
pad.rest(Duration.WHOLE)
for sym in ["Am", "F", "G", "Em"] * 2:
pad.add(Chord.from_symbol(sym), Duration.WHOLE)
sub = score.part("sub", instrument="808_bass", volume=0.4)
for _ in range(edm_start):
sub.rest(Duration.WHOLE)
for n in ["A1","A1","F1","F1","G1","G1","E1","E1"] * 2:
sub.add(n, Duration.HALF)
sitar2 = score.part("sitar2", instrument="sitar", volume=0.4,
reverb=0.3, reverb_type=REV)
for _ in range(edm_start + 2):
sitar2.rest(Duration.WHOLE)
for note, dur, vel in [
("A4", 0.25, 75), ("C5", 0.25, 78), ("E5", 0.5, 85),
("D5", 0.25, 72), ("C5", 0.25, 70), ("A4", 0.5, 75),
("G4", 0.25, 68), ("A4", 0.25, 72), ("C5", 0.5, 78),
("A4", 0.5, 72),
("E5", 0.5, 82), ("D5", 0.25, 72), ("C5", 0.25, 70),
("A4", 0.5, 75), ("G4", 0.5, 68), ("A4", 1.0, 78),
] * 2:
sitar2.add(note, dur, velocity=vel)
# Drums: djembe bars 9-14, tabla bars 15-20, house bars 21-28
DJB = DrumSound.DJEMBE_BASS
DJT = DrumSound.DJEMBE_TONE
DJS = DrumSound.DJEMBE_SLAP
NA = DrumSound.TABLA_NA
DH = DrumSound.TABLA_DHA
TT = DrumSound.TABLA_TIT
GB = DrumSound.TABLA_GE_BEND
silence = Pattern(name="s", time_signature="4/4", beats=32.0, hits=[])
score.add_pattern(silence, repeats=1)
p_dj = Pattern(name="dj", time_signature="4/4", beats=8.0, hits=[
_Hit(DJB, 0.0, 48), _Hit(DJT, 1.0, 40), _Hit(DJT, 1.5, 35),
_Hit(DJS, 2.0, 45), _Hit(DJT, 3.0, 40),
_Hit(DJB, 4.0, 52), _Hit(DJT, 5.0, 42), _Hit(DJT, 5.5, 38),
_Hit(DJS, 6.0, 48), _Hit(DJT, 6.5, 35), _Hit(DJS, 7.0, 45),
])
score.add_pattern(p_dj, repeats=3)
p_tab = Pattern(name="tab", time_signature="4/4", beats=8.0, hits=[
_Hit(DH, 0.0, 80), _Hit(TT, 0.5, 30), _Hit(NA, 1.0, 65),
_Hit(NA, 2.0, 60), _Hit(DH, 3.0, 80),
_Hit(DH, 4.0, 85), _Hit(TT, 4.25, 32), _Hit(TT, 4.5, 35),
_Hit(NA, 5.0, 68), _Hit(TT, 5.5, 30), _Hit(NA, 6.0, 65),
_Hit(DH, 7.0, 85),
])
score.add_pattern(p_tab, repeats=2)
# Tabla solo — everything drops out, just tabla and drone
KE = DrumSound.TABLA_KE
TI = DrumSound.TABLA_TIN
GE = DrumSound.TABLA_GE
T3 = 1.0 / 12.0 # 32nd triplet
T9 = 1.0 / 9.0 # ninth note
# Part 1: whisper — space, breath, single hits
p_solo1 = Pattern(name="solo1", time_signature="4/4", beats=8.0, hits=[
_Hit(DH, 0.0, 78),
_Hit(NA, 2.0, 55),
_Hit(DH, 4.0, 82),
_Hit(TT, 5.0, 30), _Hit(NA, 5.5, 52), _Hit(TT, 6.0, 28),
_Hit(DH, 7.0, 78),
])
score.add_pattern(p_solo1, repeats=1)
# Part 2: ghosts emerge — 16th note ghost fills between accents
p_solo2 = Pattern(name="solo2", time_signature="4/4", beats=8.0, hits=[
_Hit(DH, 0.0, 92), _Hit(TT, 0.25, 32), _Hit(TT, 0.5, 35),
_Hit(NA, 1.0, 68), _Hit(TT, 1.25, 30), _Hit(TT, 1.5, 28),
_Hit(NA, 2.0, 62), _Hit(TT, 2.5, 32), _Hit(DH, 3.0, 88),
_Hit(TT, 3.25, 35), _Hit(TT, 3.5, 38),
_Hit(DH, 4.0, 95), _Hit(TT, 4.25, 38), _Hit(TT, 4.5, 42),
_Hit(NA, 5.0, 72), _Hit(TT, 5.25, 32), _Hit(TT, 5.5, 35),
_Hit(KE, 5.75, 40),
_Hit(NA, 6.0, 68), _Hit(TT, 6.25, 35), _Hit(KE, 6.5, 38),
_Hit(DH, 7.0, 95), _Hit(GB, 7.5, 88),
])
score.add_pattern(p_solo2, repeats=1)
# Part 3: call and response — dayan vs bayan, dynamics wide open
p_solo3 = Pattern(name="solo3", time_signature="4/4", beats=8.0, hits=[
# Dayan speaks
_Hit(NA, 0.0, 110), _Hit(NA, 0.25, 55), _Hit(TT, 0.5, 38),
_Hit(NA, 0.75, 100),
# Bayan answers
_Hit(GE, 1.0, 100), _Hit(GE, 1.25, 50), _Hit(GB, 1.5, 90),
_Hit(GE, 1.75, 45),
# Dayan louder
_Hit(NA, 2.0, 115), _Hit(TT, 2.125, 30), _Hit(TT, 2.25, 35),
_Hit(NA, 2.5, 105), _Hit(TT, 2.625, 32), _Hit(TT, 2.75, 38),
# Bayan louder
_Hit(GB, 3.0, 112), _Hit(KE, 3.25, 50), _Hit(GE, 3.5, 68),
_Hit(KE, 3.75, 45),
# Together — explosion
_Hit(DH, 4.0, 120), _Hit(TT, 4.25, 45), _Hit(TT, 4.5, 48),
_Hit(DH, 5.0, 115), _Hit(TT, 5.25, 42), _Hit(NA, 5.5, 72),
# 9-tuplet — the weird one, breaks the grid
*[_Hit(TT if i % 2 == 0 else KE, 6.0 + i * T9, 38 + i * 5)
for i in range(9)],
_Hit(DH, 7.0, 118),
])
score.add_pattern(p_solo3, repeats=1)
# Part 4: blazing — 32nd triplets, cascades, tihai finale
p_solo4 = Pattern(name="solo4", time_signature="4/4", beats=12.0, hits=[
# 32nd triplet opening flourish
*[_Hit(TT, 0.0 + i * T3, 40 + i * 2) for i in range(12)],
_Hit(DH, 1.0, 120), _Hit(GB, 1.5, 108),
# Rapid alternating hands
_Hit(NA, 2.0, 110), _Hit(KE, 2.125, 45), _Hit(NA, 2.25, 105),
_Hit(KE, 2.375, 48), _Hit(NA, 2.5, 108), _Hit(KE, 2.625, 50),
_Hit(NA, 2.75, 112),
_Hit(DH, 3.0, 118),
# Another 32nd triplet burst — longer, crescendo
*[_Hit(TT, 3.5 + i * T3, 32 + i * 4) for i in range(18)],
_Hit(DH, 5.0, 122), _Hit(DH, 5.25, 118), _Hit(GB, 5.5, 115),
# 9 against 4 polyrhythm moment
_Hit(GE, 6.0, 88), _Hit(GE, 7.0, 85),
*[_Hit(NA if i % 3 == 0 else TT, 6.0 + i * (2.0 / 9.0), 42 + (i % 3) * 15)
for i in range(9)],
# Grand tihai — 3x pattern, each louder
_Hit(DH, 8.0, 108), _Hit(NA, 8.25, 72), _Hit(TT, 8.5, 48),
_Hit(KE, 8.75, 52), _Hit(DH, 9.0, 100),
_Hit(DH, 9.25, 112), _Hit(NA, 9.5, 78), _Hit(TT, 9.75, 52),
_Hit(KE, 10.0, 58), _Hit(DH, 10.25, 108),
_Hit(DH, 10.5, 120), _Hit(NA, 10.75, 85), _Hit(TT, 11.0, 58),
_Hit(KE, 11.25, 62), _Hit(DH, 11.5, 127),
# Silence.....
# SLAM
_Hit(GB, 11.875, 127),
])
score.add_pattern(p_solo4, repeats=1)
score.drums("house", repeats=8)
score.set_drum_effects(reverb=0.3, reverb_type=REV)
play_song(score, "Journey — Piano → World → Sitar EDM (Taj Mahal)")
def epic_bhairav():
"""Epic Bhairav — orchestral + choir + tabla with extended solo finale."""
shruti = SYSTEMS["shruti"]
score = Score("4/4", bpm=90, system=shruti)
REV = "taj_mahal"
T3 = 1.0 / 12.0
T9 = 1.0 / 9.0
ts = TonedScale(system=shruti, tonic=Tone("Sa", octave=4, system=shruti))
bh = list(ts["bhairav"].tones)
S, kR, G, M, P, kD, N, S2 = bh
NA = DrumSound.TABLA_NA
DH = DrumSound.TABLA_DHA
TT = DrumSound.TABLA_TIT
KE = DrumSound.TABLA_KE
GB = DrumSound.TABLA_GE_BEND
GE = DrumSound.TABLA_GE
DJB = DrumSound.DJEMBE_BASS
DJT = DrumSound.DJEMBE_TONE
DJS = DrumSound.DJEMBE_SLAP
# Tanpura
tanpura = score.part("tanpura", synth="strings_synth", envelope="pad",
detune=3, lowpass=900, volume=0.14, reverb=0.4, reverb_type=REV)
tanpura_pa = score.part("tanpura_pa", synth="strings_synth", envelope="pad",
detune=3, lowpass=1200, volume=0.1, reverb=0.4, reverb_type=REV)
sa = Tone("Sa", octave=3, system=shruti)
pa = Tone("Pa", octave=3, system=shruti)
for _ in range(34):
tanpura.add(sa, Duration.WHOLE)
tanpura_pa.add(pa, Duration.WHOLE)
# Timpani
timp = score.part("timp", instrument="timpani")
timp.roll(Tone("Sa", octave=2, system=shruti), Duration.WHOLE,
velocity_start=20, velocity_end=90, speed=0.125)
timp.add(Tone("Sa", octave=2, system=shruti), Duration.HALF, velocity=105)
timp.rest(Duration.HALF)
for _ in range(8):
timp.rest(Duration.WHOLE)
timp.roll(Tone("Sa", octave=2, system=shruti), Duration.WHOLE,
velocity_start=25, velocity_end=115, speed=0.125)
timp.add(Tone("Sa", octave=2, system=shruti), Duration.HALF, velocity=120)
timp.add(Tone("Pa", octave=2, system=shruti), Duration.HALF, velocity=115)
# Choir — bar 3
choir = score.part("choir", synth="vocal_synth", envelope="pad", ensemble=6,
detune=8, spread=0.4, reverb=0.4, reverb_type=REV, volume=0.2)
for _ in range(2):
choir.rest(Duration.WHOLE)
for tone, dur, lyric, vel in [
(S, 4.0, "ah", 60), (M, 4.0, "oh", 62), (P, 4.0, "ah", 68),
(S, 4.0, "ee", 65), (kD, 4.0, "oh", 70), (P, 4.0, "ah", 72),
]:
choir.add(tone, dur, velocity=vel, lyric=lyric)
# Bansuri — bar 5
bansuri = score.part("bansuri", instrument="flute", volume=0.22,
reverb=0.4, reverb_type=REV)
for _ in range(4):
bansuri.rest(Duration.WHOLE)
for tone, dur, vel in [
(P, 2.0, 58), (kD, 1.0, 50), (P, 1.0, 55),
(M, 2.0, 55), (G, 1.0, 50), (kR, 1.0, 48), (S, 4.0, 58),
]:
bansuri.add(tone, dur, velocity=vel)
# Cello — bar 3
cello = score.part("cello", instrument="cello", volume=0.22, reverb=0.4, reverb_type=REV, ensemble=3)
for _ in range(2):
cello.rest(Duration.WHOLE)
for name, dur, vel in [
("Sa", 4.0, 55), ("Ma", 4.0, 52), ("Pa", 4.0, 58),
("Sa", 4.0, 55), ("komal Dha", 4.0, 58), ("Pa", 4.0, 55),
]:
cello.add(Tone(name, octave=2, system=shruti), dur, velocity=vel)
# Sitar — bar 9
sitar = score.part("sitar", instrument="sitar", volume=0.25, reverb=0.4, reverb_type=REV)
for _ in range(8):
sitar.rest(Duration.WHOLE)
for tone, dur, vel in [
(S, 1.0, 72), (kR, 0.5, 62), (S, 0.5, 68), (G, 2.0, 78),
(M, 1.0, 72), (P, 2.0, 82), (kD, 0.5, 65), (P, 1.0, 75),
(M, 0.5, 65), (G, 0.5, 68), (kR, 0.5, 60), (S, 2.0, 78),
(kR, 0.25, 62), (G, 0.25, 65), (M, 0.25, 70), (P, 0.25, 75),
(kD, 0.25, 70), (N, 0.25, 78), (S2, 0.5, 88),
(N, 0.25, 68), (kD, 0.25, 62), (P, 0.5, 68),
(M, 0.5, 62), (G, 0.5, 65), (kR, 0.5, 58), (S, 2.0, 80),
]:
sitar.add(tone, dur, velocity=vel)
# Strings — bar 13
strings = score.part("strings", instrument="string_ensemble", volume=0.18,
reverb=0.4, reverb_type=REV, ensemble=10)
for _ in range(12):
strings.rest(Duration.WHOLE)
for name, dur, vel in [("Sa", 4.0, 58), ("Ma", 4.0, 62), ("Pa", 4.0, 68), ("Sa", 4.0, 72)]:
strings.add(Tone(name, octave=3, system=shruti), dur, velocity=vel)
# Harp — bar 14
harp = score.part("harp", instrument="harp", volume=0.15, reverb=0.4, reverb_type=REV)
for _ in range(13):
harp.rest(Duration.WHOLE)
for name in ["Sa", "komal Ga", "Pa", "Sa", "Pa", "komal Ga", "Sa", "Sa"]:
oct = 4 if name == "Sa" and harp.total_beats > 55 else 3
harp.add(Tone(name, octave=oct, system=shruti), Duration.EIGHTH, velocity=50)
# Drums
silence = Pattern(name="s", time_signature="4/4", beats=16.0, hits=[])
score.add_pattern(silence, repeats=1)
p_dj = Pattern(name="dj", time_signature="4/4", beats=8.0, hits=[
_Hit(DJB, 0.0, 45), _Hit(DJT, 1.0, 38), _Hit(DJT, 1.5, 32),
_Hit(DJS, 2.0, 42), _Hit(DJT, 3.0, 38),
_Hit(DJB, 4.0, 50), _Hit(DJT, 5.0, 42), _Hit(DJT, 5.5, 35),
_Hit(DJS, 6.0, 48), _Hit(DJT, 6.5, 32), _Hit(DJS, 7.0, 45),
])
score.add_pattern(p_dj, repeats=2)
p_tab = Pattern(name="tab", time_signature="4/4", beats=8.0, hits=[
_Hit(DH, 0.0, 82), _Hit(TT, 0.5, 30), _Hit(NA, 1.0, 65),
_Hit(NA, 2.0, 60), _Hit(DH, 3.0, 82),
_Hit(DH, 4.0, 88), _Hit(TT, 4.25, 32), _Hit(TT, 4.5, 35),
_Hit(NA, 5.0, 68), _Hit(TT, 5.5, 30), _Hit(NA, 6.0, 65),
_Hit(DH, 7.0, 88),
])
score.add_pattern(p_tab, repeats=3)
# Extended tabla finale — whisper → ghosts → call/response → blazing
p_f1 = Pattern(name="f1", time_signature="4/4", beats=8.0, hits=[
_Hit(DH, 0.0, 78), _Hit(NA, 2.0, 55),
_Hit(DH, 4.0, 82), _Hit(TT, 5.0, 30), _Hit(NA, 5.5, 52),
_Hit(DH, 7.0, 78),
])
score.add_pattern(p_f1, repeats=1)
p_f2 = Pattern(name="f2", time_signature="4/4", beats=8.0, hits=[
_Hit(DH, 0.0, 95), _Hit(TT, 0.25, 35), _Hit(TT, 0.5, 38),
_Hit(NA, 1.0, 70), _Hit(TT, 1.25, 30), _Hit(NA, 2.0, 65),
_Hit(TT, 2.5, 35), _Hit(DH, 3.0, 90),
_Hit(DH, 4.0, 98), _Hit(TT, 4.25, 38), _Hit(TT, 4.5, 42),
_Hit(NA, 5.0, 75), _Hit(KE, 5.5, 40), _Hit(NA, 6.0, 70),
_Hit(KE, 6.5, 42), _Hit(DH, 7.0, 100), _Hit(GB, 7.5, 92),
])
score.add_pattern(p_f2, repeats=1)
p_f3 = Pattern(name="f3", time_signature="4/4", beats=8.0, hits=[
_Hit(NA, 0.0, 112), _Hit(NA, 0.25, 58), _Hit(TT, 0.5, 40), _Hit(NA, 0.75, 105),
_Hit(GE, 1.0, 105), _Hit(GE, 1.25, 52), _Hit(GB, 1.5, 95), _Hit(GE, 1.75, 48),
_Hit(NA, 2.0, 115), _Hit(TT, 2.125, 32), _Hit(TT, 2.25, 38),
_Hit(NA, 2.5, 108), _Hit(TT, 2.625, 35), _Hit(TT, 2.75, 42),
_Hit(GB, 3.0, 115), _Hit(KE, 3.25, 52), _Hit(GE, 3.5, 70),
_Hit(DH, 4.0, 118),
*[_Hit(TT if i % 2 == 0 else KE, 5.0 + i * T9, 40 + i * 5) for i in range(9)],
_Hit(DH, 7.0, 120),
])
score.add_pattern(p_f3, repeats=1)
# Part 3.5: polyrhythm — space and conversation, not density
T5 = 4.0 / 5.0
p_poly = Pattern(name="poly", time_signature="4/4", beats=16.0, hits=[
# Bar 1: single Dha, let reverb ring. Bayan answers.
_Hit(DH, 0.0, 95),
_Hit(GB, 3.0, 88),
# Bar 2: one 5-group phrase, then breathe
_Hit(NA, 4.0, 75), _Hit(TT, 4.0 + T5, 42),
_Hit(NA, 4.0 + 2*T5, 70), _Hit(TT, 4.0 + 3*T5, 40),
_Hit(DH, 4.0 + 4*T5, 88),
# Bar 3: bayan, pause, one floating 9-group
_Hit(GB, 8.0, 100),
_Hit(NA, 9.0, 62),
*[_Hit(TT if i % 2 == 0 else KE, 10.0 + i * T9, 35 + i * 4)
for i in range(9)],
_Hit(DH, 11.0, 105),
# Bar 4: simple question-answer into sam
_Hit(DH, 12.0, 100), _Hit(NA, 12.5, 62),
_Hit(GE, 13.0, 88),
_Hit(NA, 14.0, 72), _Hit(TT, 14.25, 40), _Hit(NA, 14.5, 70),
_Hit(DH, 15.0, 112), _Hit(GB, 15.5, 105),
])
score.add_pattern(p_poly, repeats=1)
p_f4 = Pattern(name="f4", time_signature="4/4", beats=12.0, hits=[
*[_Hit(TT, 0.0 + i * T3, 38 + i * 2) for i in range(12)],
_Hit(DH, 1.0, 118), _Hit(GB, 1.5, 110),
_Hit(NA, 2.0, 112), _Hit(KE, 2.125, 48), _Hit(NA, 2.25, 108),
_Hit(KE, 2.375, 50), _Hit(NA, 2.5, 110), _Hit(KE, 2.625, 52), _Hit(NA, 2.75, 115),
_Hit(DH, 3.0, 120),
*[_Hit(TT, 3.5 + i * T3, 30 + i * 4) for i in range(18)],
_Hit(DH, 5.0, 122), _Hit(DH, 5.25, 118), _Hit(GB, 5.5, 115),
_Hit(GE, 6.0, 90), _Hit(GE, 7.0, 88),
*[_Hit(NA if i % 3 == 0 else TT, 6.0 + i * (2.0/9.0), 42 + (i%3)*15) for i in range(9)],
_Hit(DH, 8.0, 110), _Hit(NA, 8.25, 75), _Hit(TT, 8.5, 50),
_Hit(KE, 8.75, 55), _Hit(DH, 9.0, 105),
_Hit(DH, 9.25, 115), _Hit(NA, 9.5, 80), _Hit(TT, 9.75, 55),
_Hit(KE, 10.0, 60), _Hit(DH, 10.25, 110),
_Hit(DH, 10.5, 122), _Hit(NA, 10.75, 85), _Hit(TT, 11.0, 60),
_Hit(KE, 11.25, 65), _Hit(DH, 11.5, 127),
_Hit(GB, 11.875, 127),
])
score.add_pattern(p_f4, repeats=1)
score.set_drum_effects(reverb=0.4, reverb_type=REV)
play_song(score, "Epic Bhairav — Orchestra + Choir + Tabla (22-Shruti JI)")
def acoustic_ensemble():
"""Acoustic Ensemble — guitar, ukulele, mandolin, cajón."""
import random
from pytheory import Fretboard
random.seed(7)
score = Score("4/4", bpm=115)
fb_g = Fretboard.guitar()
guitar = score.part("guitar", instrument="acoustic_guitar", fretboard=fb_g,
reverb=0.3, reverb_type="plate", humanize=0.2, pan=-0.3)
fb_u = Fretboard.ukulele()
uke = score.part("uke", instrument="ukulele", fretboard=fb_u,
reverb=0.25, reverb_type="plate", humanize=0.25, pan=0.3)
fb_m = Fretboard.mandolin()
mando = score.part("mando", instrument="mandolin", fretboard=fb_m,
reverb=0.25, reverb_type="plate", humanize=0.2, pan=0.15)
for sym in ["C", "G", "Am", "F"] * 3:
vd = random.randint(75, 95)
vu = random.randint(58, 78)
guitar.strum(sym, Duration.QUARTER, direction="down", velocity=vd)
guitar.strum(sym, Duration.EIGHTH, direction="up", velocity=vu)
guitar.strum(sym, Duration.EIGHTH, direction="down", velocity=vd - 8)
guitar.strum(sym, Duration.QUARTER, direction="up", velocity=vu)
guitar.strum(sym, Duration.QUARTER, direction="down", velocity=vd)
vd2 = random.randint(65, 88)
vu2 = random.randint(50, 72)
uke.rest(Duration.EIGHTH)
uke.strum(sym, Duration.EIGHTH, direction="up", velocity=vu2)
uke.strum(sym, Duration.QUARTER, direction="down", velocity=vd2)
uke.strum(sym, Duration.EIGHTH, direction="up", velocity=vu2)
uke.strum(sym, Duration.EIGHTH, direction="down", velocity=vd2 - 5)
uke.strum(sym, Duration.QUARTER, direction="up", velocity=vu2)
mando.strum(sym, Duration.EIGHTH, direction="down",
velocity=random.randint(65, 82))
mando.strum(sym, Duration.EIGHTH, direction="up",
velocity=random.randint(55, 72))
mando.strum(sym, Duration.EIGHTH, direction="down",
velocity=random.randint(65, 82))
mando.rest(Duration.EIGHTH)
mando.strum(sym, Duration.EIGHTH, direction="up",
velocity=random.randint(55, 72))
mando.strum(sym, Duration.EIGHTH, direction="down",
velocity=random.randint(68, 85))
mando.strum(sym, Duration.QUARTER, direction="down",
velocity=random.randint(70, 85))
score.drums("cajon", repeats=6)
score.set_drum_effects(reverb=0.15)
play_song(score, "Acoustic Ensemble — Guitar, Uke, Mandolin, Cajón")
def ascent():
"""Ascent — from the deep to the sky, theremin solo, tabla solo."""
import random
from pytheory import Fretboard
random.seed(13)
score = Score("4/4", bpm=80)
REV = "cathedral"
T3 = 1.0 / 12.0
T9 = 1.0 / 9.0
NA = DrumSound.TABLA_NA; DH_ = DrumSound.TABLA_DHA
TT_ = DrumSound.TABLA_TIT; KE_ = DrumSound.TABLA_KE
GB_ = DrumSound.TABLA_GE_BEND; GE_ = DrumSound.TABLA_GE
DJB_ = DrumSound.DJEMBE_BASS; DJT_ = DrumSound.DJEMBE_TONE
DJS_ = DrumSound.DJEMBE_SLAP
CB_ = DrumSound.CAJON_BASS; CSL_ = DrumSound.CAJON_SLAP
CT_ = DrumSound.CAJON_TAP
# Didgeridoo drone
didg = score.part("didg", instrument="didgeridoo", volume=0.15)
for _ in range(32):
didg.add("E1", 4.0, velocity=52)
# 1: THE DEEP (1-4)
grain = score.part("grain", synth="granular_synth", envelope="pad",
lowpass=800, reverb=0.55, reverb_type="cave", volume=0.12)
for note in ["E2", "B2", "E2", "G2"]:
grain.add(note, 4.0, velocity=40)
# 2: LIGHT (3-6)
kal = score.part("kalimba", instrument="kalimba", volume=0.2,
delay=0.2, delay_time=0.375, delay_feedback=0.4,
reverb=0.45, reverb_type=REV)
kal.rest(8.0)
for note, vel in [("B4",58),("E5",62),("G5",65),("B5",68),
("G5",62),("E5",58),("B4",55),("E4",52)]:
kal.add(note, Duration.QUARTER, velocity=vel)
kal.rest(4.0)
for note, vel in [("E5",60),("G5",65),("B5",70),("E6",72),
("B5",65),("G5",60),("E5",58),("B4",55)]:
kal.add(note, Duration.QUARTER, velocity=vel)
# 3: SURFACING (5-8)
cello = score.part("cello", instrument="cello", volume=0.22,
reverb=0.4, reverb_type=REV, ensemble=3)
cello.rest(16.0)
for note, dur, vel in [("E2",4.0,52),("G2",4.0,55),("B2",4.0,58),("E3",4.0,62)]:
cello.add(note, dur, velocity=vel)
# 4: AIR (7-10) — piano + quiet uke
piano = score.part("piano", instrument="piano", volume=0.28,
reverb=0.35, reverb_type=REV)
piano.rest(24.0)
for notes in [
["E3","B3","E4","G4","B4","G4","E4","B3"],
["C3","G3","C4","E4","G4","E4","C4","G3"],
["A2","E3","A3","C4","E4","C4","A3","E3"],
["B2","F#3","B3","D4","F#4","D4","B3","F#3"],
]:
for n in notes:
piano.add(n, Duration.EIGHTH, velocity=random.randint(58, 70))
fb = Fretboard.ukulele()
uke = score.part("uke", instrument="ukulele", fretboard=fb,
reverb=0.4, reverb_type=REV, humanize=0.2,
pan=-0.2, volume=0.15)
uke.rest(28.0)
for sym in ["Em", "C", "Am", "B"]:
vd = random.randint(60, 75)
vu = random.randint(45, 62)
uke.strum(sym, Duration.QUARTER, direction="down", velocity=vd)
uke.strum(sym, Duration.EIGHTH, direction="up", velocity=vu)
uke.strum(sym, Duration.EIGHTH, direction="down", velocity=vd - 8)
uke.strum(sym, Duration.QUARTER, direction="up", velocity=vu)
uke.strum(sym, Duration.QUARTER, direction="down", velocity=vd)
# 5: THEREMIN SOLO (11-16)
steel = score.part("steel", instrument="pedal_steel", volume=0.16,
reverb=0.4, reverb_type=REV, pan=0.2)
steel.rest(36.0)
for note, dur, vel in [("B4",3.0,58),("A4",1.0,50),("G4",2.0,55),("E4",2.0,52)]:
steel.add(note, dur, velocity=vel)
theremin = score.part("theremin", instrument="theremin", volume=0.3,
reverb=0.45, reverb_type=REV,
delay=0.15, delay_time=0.375, delay_feedback=0.3)
theremin.rest(40.0)
for note, dur, vel in [
("E4",2.0,62),("G4",1.0,58),("B4",1.0,62),
("A4",2.0,65),("G4",1.0,58),("E4",1.0,55),("D4",3.0,60),("E4",1.0,58),
("G4",1.0,62),("B4",1.5,68),("D5",0.5,65),
("E5",2.0,72),("D5",1.0,65),("B4",1.0,62),
("G4",1.0,60),("A4",1.0,62),("B4",2.0,68),
("E5",1.5,75),("G5",1.5,80),("B5",2.0,85),
("A5",1.0,78),("G5",1.0,72),("E5",2.0,75),
("D5",1.0,68),("B4",1.0,62),("E4",4.0,70),
]:
theremin.add(note, dur, velocity=vel)
strings = score.part("strings", instrument="string_ensemble", volume=0.15,
reverb=0.45, reverb_type=REV, ensemble=8)
strings.rest(40.0)
for sym, vel in [("Em",52),("C",55),("Am",58),("B",55),("Em",60),("C",62)]:
strings.add(Chord.from_symbol(sym), 4.0, velocity=vel)
# 6: THE PEAK (17-18)
flute = score.part("flute", instrument="flute", volume=0.2, reverb=0.4, reverb_type=REV)
flute.rest(64.0)
for note, dur, vel in [
("B5",2.0,55),("A5",1.0,50),("G5",1.0,52),
("E5",2.0,55),("D5",1.0,50),("E5",1.0,52),
]:
flute.add(note, dur, velocity=vel)
harp = score.part("harp", instrument="harp", volume=0.16, reverb=0.4, reverb_type=REV)
harp.rest(68.0)
for n in ["B5","G5","E5","B4","G4","E4","B3","E3"]:
harp.add(n, Duration.QUARTER, velocity=random.randint(48, 58))
timp = score.part("timp", instrument="timpani")
timp.rest(64.0)
timp.roll("E2", 4.0, velocity_start=20, velocity_end=95, speed=0.125)
timp.add("E2", 4.0, velocity=105)
# Drums: silence → cajón → djembe → tabla solo
score.add_pattern(Pattern(name="s", time_signature="4/4", beats=16.0, hits=[]),
repeats=1)
p_caj = Pattern(name="caj", time_signature="4/4", beats=4.0, hits=[
_Hit(CB_, 0.0, 58), _Hit(CT_, 0.5, 22), _Hit(CSL_, 1.0, 50),
_Hit(CT_, 1.5, 20), _Hit(CB_, 2.0, 55), _Hit(CT_, 2.5, 22),
_Hit(CSL_, 3.0, 52),
])
score.add_pattern(p_caj, repeats=4)
p_dj = Pattern(name="dj", time_signature="4/4", beats=4.0, hits=[
_Hit(DJB_, 0.0, 42), _Hit(DJT_, 1.0, 35), _Hit(DJT_, 1.5, 30),
_Hit(DJS_, 2.0, 38), _Hit(DJT_, 3.0, 35),
])
score.add_pattern(p_dj, repeats=10)
# 7: TABLA SOLO (bars 19-26)
score.add_pattern(Pattern(name="ts1", time_signature="4/4", beats=8.0, hits=[
_Hit(DH_, 0.0, 72), _Hit(NA, 2.5, 48),
_Hit(DH_, 4.0, 75), _Hit(TT_, 5.5, 25), _Hit(NA, 6.0, 45),
_Hit(DH_, 7.5, 72),
]), repeats=1)
score.add_pattern(Pattern(name="ts2", time_signature="4/4", beats=8.0, hits=[
_Hit(DH_, 0.0, 85), _Hit(TT_, 0.25, 30), _Hit(TT_, 0.5, 32),
_Hit(NA, 1.0, 62), _Hit(TT_, 1.25, 25), _Hit(NA, 2.0, 58),
_Hit(TT_, 2.5, 28), _Hit(DH_, 3.0, 82),
_Hit(DH_, 4.0, 90), _Hit(TT_, 4.25, 32), _Hit(TT_, 4.5, 35),
_Hit(NA, 5.0, 68), _Hit(KE_, 5.5, 35), _Hit(NA, 6.0, 62),
_Hit(KE_, 6.5, 38), _Hit(DH_, 7.0, 92), _Hit(GB_, 7.5, 85),
]), repeats=1)
score.add_pattern(Pattern(name="ts3", time_signature="4/4", beats=8.0, hits=[
_Hit(NA, 0.0, 108), _Hit(NA, 0.25, 52), _Hit(TT_, 0.5, 35),
_Hit(NA, 0.75, 100),
_Hit(GE_, 1.0, 98), _Hit(GE_, 1.25, 48), _Hit(GB_, 1.5, 90),
_Hit(GE_, 1.75, 42),
_Hit(NA, 2.0, 110), _Hit(TT_, 2.125, 28), _Hit(TT_, 2.25, 32),
_Hit(NA, 2.5, 102), _Hit(TT_, 2.625, 30), _Hit(TT_, 2.75, 35),
_Hit(GB_, 3.0, 110), _Hit(KE_, 3.25, 45), _Hit(GE_, 3.5, 65),
_Hit(DH_, 4.0, 112),
*[_Hit(TT_ if i % 2 == 0 else KE_, 5.0 + i * T9, 35 + i * 5)
for i in range(9)],
_Hit(DH_, 7.0, 115),
]), repeats=1)
score.add_pattern(Pattern(name="ts4", time_signature="4/4", beats=8.0, hits=[
*[_Hit(TT_, i * T3, 32 + i * 2) for i in range(12)],
_Hit(DH_, 1.0, 115), _Hit(GB_, 1.5, 105),
_Hit(NA, 2.0, 108), _Hit(KE_, 2.125, 42), _Hit(NA, 2.25, 102),
_Hit(KE_, 2.375, 45), _Hit(NA, 2.5, 105), _Hit(KE_, 2.625, 48),
_Hit(NA, 2.75, 110), _Hit(DH_, 3.0, 118),
*[_Hit(TT_, 3.5 + i * T3, 30 + i * 4) for i in range(12)],
_Hit(DH_, 4.5, 120), _Hit(DH_, 4.75, 115), _Hit(GB_, 5.0, 112),
_Hit(GE_, 5.5, 85), _Hit(GE_, 6.5, 82),
*[_Hit(NA if i % 3 == 0 else TT_, 5.5 + i * (2.0 / 9.0),
40 + (i % 3) * 12) for i in range(9)],
_Hit(DH_, 7.5, 127), _Hit(GB_, 7.875, 127),
]), repeats=1)
score.set_drum_effects(reverb=0.3, reverb_type=REV)
play_song(score, "Ascent — Deep → Sky → Theremin Solo → Tabla Solo")
def descent():
"""Descent — generative, different every time. From sky to deep."""
import random
import time
from pytheory import Fretboard, TonedScale
# No seed — truly random every play
random.seed(int(time.time() * 1000) % 2**31)
# Random key — always minor, always dark
roots = ["A", "B", "C", "D", "E", "F", "G"]
root = random.choice(roots)
mode = random.choice(["minor", "harmonic minor"])
key = Key(root, mode)
scale_tones = [t.name for t in key.scale.tones[:-1]]
bpm = random.randint(65, 85)
score = Score("4/4", bpm=bpm)
REV = random.choice(["cathedral", "taj_mahal", "cave"])
T3 = 1.0 / 12.0
NA = DrumSound.TABLA_NA; DH_ = DrumSound.TABLA_DHA
TT_ = DrumSound.TABLA_TIT; KE_ = DrumSound.TABLA_KE
GB_ = DrumSound.TABLA_GE_BEND; GE_ = DrumSound.TABLA_GE
print(f" {root} {mode} | {bpm} bpm | {REV}")
# ── Pad drone — random synth, the whole piece ──
pad_synth = random.choice(["strings_synth", "granular_synth", "vocal_synth"])
pad = score.part("pad", synth=pad_synth, envelope="pad",
detune=random.randint(6, 14), spread=0.4,
reverb=0.5, reverb_type=REV, volume=0.15,
analog=random.uniform(0.1, 0.4))
prog = key.progression("i", "iv", "V", "i")
for _ in range(6):
for chord in prog:
pad.add(chord, Duration.WHOLE, velocity=random.randint(48, 62))
# ── 1: HIGH — theremin or flute, random melody from scale ──
lead_synth = random.choice(["theremin", "flute", "pedal_steel"])
lead = score.part("lead", instrument=lead_synth, volume=0.25,
reverb=0.4, reverb_type=REV,
delay=0.2, delay_time=random.uniform(0.2, 0.5),
delay_feedback=random.uniform(0.2, 0.4))
lead.rest(4.0)
# Generate melody by WALKING the scale — stepwise with occasional leaps
# Real melodies move to neighboring notes, not random jumps
scale_idx = len(scale_tones) - 1 # start high
octave = 5
for _ in range(random.randint(10, 16)):
note = scale_tones[scale_idx]
dur = random.choice([1.5, 2.0, 3.0, 4.0])
vel = random.randint(58, 70)
lead.add(f"{note}{octave}", dur, velocity=vel)
# Mostly step down (descent!), sometimes hold, rare leap
r = random.random()
if r < 0.5: # step down
scale_idx -= 1
elif r < 0.65: # step up (tension)
scale_idx += 1
elif r < 0.8: # leap down
scale_idx -= random.randint(2, 3)
# else hold same note
# Wrap octaves
if scale_idx < 0:
scale_idx += len(scale_tones)
octave -= 1
elif scale_idx >= len(scale_tones):
scale_idx -= len(scale_tones)
octave += 1
octave = max(3, min(5, octave))
# ── 2: Kalimba or steel drum — random arpeggios ──
sparkle_inst = random.choice(["kalimba", "steel_drum", "vibraphone", "harp"])
sparkle = score.part("sparkle", instrument=sparkle_inst, volume=0.18,
delay=0.2, delay_time=random.uniform(0.15, 0.4),
delay_feedback=random.uniform(0.3, 0.5),
reverb=0.4, reverb_type=REV)
sparkle.rest(8.0)
# Arpeggios — walk chord tones in patterns, not random
for chord in prog * 3:
chord_tones = [t.name for t in chord.tones]
pattern_type = random.choice(["up", "down", "updown"])
oct = random.choice([4, 5])
if pattern_type == "up":
seq = chord_tones + [chord_tones[0]]
elif pattern_type == "down":
seq = list(reversed(chord_tones)) + [chord_tones[-1]]
else:
seq = chord_tones + list(reversed(chord_tones[1:-1]))
# Pad to 8 notes
while len(seq) < 8:
seq = seq + seq
seq = seq[:8]
for i, n in enumerate(seq):
o = oct + (1 if i >= 4 and pattern_type == "up" else 0)
sparkle.add(f"{n}{o}", Duration.EIGHTH,
velocity=random.randint(48, 58))
# ── 3: Piano — random broken chords ──
piano = score.part("piano", instrument="piano", volume=0.22,
reverb=0.35, reverb_type=REV)
piano.rest(random.uniform(8.0, 16.0))
for chord in prog * 2:
chord_tones = [t.name for t in chord.tones]
oct = random.choice([3, 4])
# Walk up the chord then back down
up = [f"{n}{oct}" for n in chord_tones]
up.append(f"{chord_tones[0]}{oct+1}")
down = [f"{n}{oct}" for n in reversed(chord_tones[:-1])]
arp = (up + down)[:8]
for n in arp:
piano.add(n, Duration.EIGHTH,
velocity=random.randint(58, 65))
# ── 4: Cello — descending long notes ──
cello = score.part("cello", instrument="cello", volume=0.2,
reverb=0.4, reverb_type=REV)
cello.rest(16.0)
oct = 3
for _ in range(8):
note = random.choice(scale_tones)
cello.add(f"{note}{oct}", 4.0, velocity=random.randint(48, 62))
if random.random() < 0.4 and oct > 2:
oct -= 1
# ── 5: Bass — deep, sparse ──
bass_inst = random.choice(["upright_bass", "didgeridoo"])
bass = score.part("bass", instrument=bass_inst, volume=0.18)
bass.rest(random.uniform(4.0, 12.0))
for chord in prog * 4:
r = chord.root
if r:
oct = 2 if bass_inst == "upright_bass" else 1
bass.add(f"{r.name}{oct}", 4.0,
velocity=random.randint(50, 65))
# ── Drums: random combination ──
drum_start = random.randint(2, 5) * 4 # 8-20 beats silence
score.add_pattern(Pattern(name="s", time_signature="4/4",
beats=float(drum_start), hits=[]),
repeats=1)
# Pick random world drum combo
drum_choice = random.choice(["cajon folk", "djembe", "keherwa", "dadra"])
score.drums(drum_choice, repeats=random.randint(6, 12))
# Tabla solo at the end — always
score.add_pattern(Pattern(name="ts1", time_signature="4/4", beats=8.0, hits=[
_Hit(DH_, 0.0, 72), _Hit(NA, 2.5, 48),
_Hit(DH_, 4.0, 75), _Hit(TT_, 5.5, 25), _Hit(NA, 6.0, 45),
_Hit(DH_, 7.5, 72),
]), repeats=1)
# Generate random tabla solo — different every time
solo_hits = []
beat = 0.0
while beat < 16.0:
stroke = random.choice([DH_, NA, TT_, KE_, GB_, GE_])
vel = random.randint(35, 120)
# Ghost notes are quiet, accents are loud
if stroke == TT_:
vel = random.randint(25, 50)
elif stroke in (DH_, GB_):
vel = random.randint(70, 120)
solo_hits.append(_Hit(stroke, beat, vel))
# Random spacing — mix of tight and open
beat += random.choice([0.125, 0.25, 0.25, 0.5, 0.5, 1.0])
score.add_pattern(Pattern(name="ts_rand", time_signature="4/4",
beats=16.0, hits=solo_hits), repeats=1)
score.set_drum_effects(reverb=0.3, reverb_type=REV)
play_song(score, f"Descent — {root} {mode} (generative, {REV})")
def pop_rock():
"""Pop Rock — the I-V-vi-IV progression that launched a thousand hits."""
import random
from pytheory import Fretboard
random.seed(42)
score = Score("4/4", bpm=120)
fb = Fretboard.guitar()
guitar = score.part("guitar", instrument="acoustic_guitar", fretboard=fb,
reverb=0.2, reverb_type="plate", humanize=0.15, pan=-0.2)
bass = score.part("bass", instrument="bass_guitar", volume=0.35, humanize=0.1)
lead = score.part("lead", instrument="electric_guitar",
cabinet=1.0, cabinet_brightness=0.6,
reverb=0.2, reverb_type="plate", pan=0.2)
strings = score.part("strings", instrument="string_ensemble", volume=0.12,
reverb=0.35, reverb_type="hall", ensemble=6)
prog = ["G", "D", "Em", "C"]
# Intro — picked
for sym in prog:
chord_obj = Chord.from_symbol(sym)
tones = [t.name for t in chord_obj.tones]
for t in tones:
guitar.add(f"{t}3", Duration.QUARTER,
velocity=random.randint(62, 72))
# Verse — strum
for _ in range(2):
for sym in prog:
vd = random.randint(72, 88)
vu = random.randint(55, 70)
guitar.strum(sym, Duration.QUARTER, direction="down", velocity=vd)
guitar.strum(sym, Duration.EIGHTH, direction="up", velocity=vu)
guitar.strum(sym, Duration.EIGHTH, direction="down", velocity=vd - 8)
guitar.strum(sym, Duration.QUARTER, direction="up", velocity=vu)
guitar.strum(sym, Duration.QUARTER, direction="down", velocity=vd)
bass_notes = ["G2", "G2", "D2", "D2", "E2", "E2", "C2", "C2"]
for _ in range(3):
for n in bass_notes:
bass.add(n, Duration.HALF, velocity=random.randint(68, 78))
# Melody
for _ in range(4):
lead.rest(Duration.WHOLE)
for note, dur, vel in [
("B4",0.5,78),("B4",0.5,75),("B4",0.5,78),("B4",0.5,72),
("A4",0.5,75),("A4",0.5,72),("B4",1.0,80),
("B4",0.5,78),("B4",0.5,75),("B4",0.5,78),("D5",0.5,82),
("G4",0.75,72),("G4",0.25,68),("A4",1.0,78),
("B4",0.5,78),("B4",0.5,75),("B4",0.5,78),("B4",0.5,72),
("A4",0.5,75),("A4",0.5,72),("B4",0.5,78),("A4",0.5,72),
("G4",2.0,80),
]:
lead.add(note, dur, velocity=vel)
for _ in range(4):
strings.rest(Duration.WHOLE)
for sym in prog * 2:
strings.add(Chord.from_symbol(sym), Duration.WHOLE,
velocity=random.randint(55, 68))
score.drums("rock", repeats=6)
play_song(score, "Pop Rock — G D Em C (I-V-vi-IV)")
def sitar_drone():
"""Sitar Drone — Raga Bhairav with hold() polyphony, 22-shruti JI."""
shruti = SYSTEMS["shruti"]
score = Score("4/4", bpm=72, system=shruti)
ts = TonedScale(system=shruti, tonic=Tone("Sa", octave=4, system=shruti))
bh = list(ts["bhairav"].tones)
S, kR, G, M, P, kD, N, S2 = bh
sitar = score.part("sitar", instrument="sitar", volume=0.3,
reverb=0.4, reverb_type="taj_mahal")
# Sa drone held — rings under the whole melody
sitar.hold(Tone("Sa", octave=3, system=shruti), 32.0, velocity=60)
sitar.rest(Duration.WHOLE)
for tone, dur, vel in [
(S, 2.0, 72), (kR, 0.5, 62), (S, 0.5, 68),
(G, 2.0, 78), (kR, 0.5, 60), (G, 0.5, 70),
(M, 1.5, 75), (P, 2.5, 82),
(kD, 0.5, 65), (P, 1.0, 75), (M, 0.5, 65),
(G, 0.5, 68), (kR, 0.5, 60), (S, 2.0, 78),
(kR, 0.25, 62), (G, 0.25, 65), (M, 0.25, 70), (P, 0.25, 75),
(kD, 0.25, 70), (N, 0.25, 78), (S2, 0.5, 85),
(N, 0.25, 68), (kD, 0.25, 62), (P, 0.5, 68),
(M, 0.5, 62), (G, 0.5, 65), (kR, 0.5, 58),
(S, 4.0, 80),
]:
sitar.add(tone, dur, velocity=vel)
tanpura = score.part("tanpura", synth="strings_synth", envelope="pad",
detune=3, lowpass=900, volume=0.12,
reverb=0.5, reverb_type="taj_mahal")
tanpura_pa = score.part("tanpura_pa", synth="strings_synth", envelope="pad",
detune=3, lowpass=1200, volume=0.1,
reverb=0.5, reverb_type="taj_mahal")
for _ in range(8):
tanpura.add(Tone("Sa", octave=3, system=shruti), Duration.WHOLE)
tanpura_pa.add(Tone("Pa", octave=3, system=shruti), Duration.WHOLE)
NA = DrumSound.TABLA_NA
DH_ = DrumSound.TABLA_DHA
TT_ = DrumSound.TABLA_TIT
silence = Pattern(name="s", time_signature="4/4", beats=8.0, hits=[])
score.add_pattern(silence, repeats=1)
p = Pattern(name="t", time_signature="4/4", beats=4.0, hits=[
_Hit(DH_, 0.0, 68), _Hit(TT_, 0.5, 25), _Hit(NA, 1.0, 55),
_Hit(NA, 2.0, 52), _Hit(DH_, 3.0, 68),
])
score.add_pattern(p, repeats=6)
score.set_drum_effects(reverb=0.25, reverb_type="taj_mahal")
play_song(score, "Sitar Drone — Raga Bhairav (22-Shruti JI, hold() polyphony)")
def acid_tabla():
"""Acid Tabla — 303 filter automation meets Indian percussion."""
score = Score("4/4", bpm=132)
# ── House drums ──
score.drums("house", repeats=20, fill="house", fill_every=8)
score.set_drum_effects(volume=0.45)
# ── 303 acid bass ──
acid = score.part("acid", synth="saw", volume=0.75,
legato=True, glide=0.035,
distortion=0.35, distortion_drive=4.5,
saturation=0.15, humanize=0.05)
# Intro (4 bars): filter closed, high resonance
acid.set(lowpass=600, lowpass_q=12.0)
for _ in range(4):
for n in ["C3","C3","C2","C3","Eb3","C2","G2","C3"]:
acid.add(n, Duration.EIGHTH)
# Build (4 bars): filter opens
acid.ramp(over=Duration.WHOLE * 4, curve="ease_in", lowpass=4500)
for _ in range(4):
for n in ["C2","G2","C3","Eb3","C2","Bb2","G2","C3"]:
acid.add(n, Duration.EIGHTH)
# Peak (4 bars): wide open, wilder pattern
acid.set(lowpass=7000, lowpass_q=7.0)
for _ in range(2):
for n in ["C2","C3","Eb3","G3","C2","Bb2","G2","Eb3"]:
acid.add(n, Duration.EIGHTH)
for _ in range(2):
for n in ["C2","Eb3","C3","G3","Bb2","C3","G2","C2"]:
acid.add(n, Duration.EIGHTH)
# Tabla section (4 bars): filter pulls back
acid.set(lowpass=3000, lowpass_q=5.0)
for _ in range(4):
for n in ["C2","G2","C3","C2","Eb2","G2","Bb2","C2"]:
acid.add(n, Duration.EIGHTH)
# Outro (4 bars): filter closes
acid.ramp(over=Duration.WHOLE * 4, curve="ease_out", lowpass=400, lowpass_q=15.0)
for _ in range(4):
for n in ["C3","G2","C2","C3","C2","G2","Eb2","C2"]:
acid.add(n, Duration.EIGHTH)
# ── Tabla: enters bar 9, rides through to the end ──
tabla = score.part("tabla", synth="sine", volume=0.55, reverb=0.15)
# 8 bars rest
for _ in range(64):
tabla.rest(Duration.EIGHTH)
# Bars 9-12: keherwa groove
for _ in range(4):
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=100, articulation="accent")
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=55)
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=50)
tabla.hit(DrumSound.TABLA_NA, Duration.EIGHTH, velocity=88)
tabla.hit(DrumSound.TABLA_TIN, Duration.EIGHTH, velocity=82)
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=52)
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=95, articulation="accent")
tabla.hit(DrumSound.TABLA_GE, Duration.EIGHTH, velocity=78)
# Bars 13-14: busier with 16ths
for _ in range(2):
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=105, articulation="marcato")
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=48)
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=52)
tabla.hit(DrumSound.TABLA_NA, Duration.EIGHTH, velocity=90)
tabla.hit(DrumSound.TABLA_TIN, Duration.EIGHTH, velocity=85)
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=48)
tabla.hit(DrumSound.TABLA_NA, Duration.SIXTEENTH, velocity=58)
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=100, articulation="accent")
tabla.hit(DrumSound.TABLA_GE_BEND, Duration.EIGHTH, velocity=88)
# Bars 15-16: tihai crescendo ending
for vel in [85, 90, 95]:
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=vel, articulation="accent")
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=int(vel * 0.6))
tabla.hit(DrumSound.TABLA_NA, Duration.SIXTEENTH, velocity=int(vel * 0.75))
for vel in [100, 105, 110]:
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=vel, articulation="marcato")
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=int(vel * 0.55))
tabla.hit(DrumSound.TABLA_NA, Duration.SIXTEENTH, velocity=int(vel * 0.7))
tabla.hit(DrumSound.TABLA_DHA, Duration.QUARTER, velocity=127, articulation="fermata")
tabla.hit(DrumSound.TABLA_GE_BEND, Duration.QUARTER, velocity=110)
tabla.rest(Duration.HALF)
# Bars 17-20: tabla continues through outro, lighter
for _ in range(4):
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=85, articulation="accent")
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=45)
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=42)
tabla.hit(DrumSound.TABLA_NA, Duration.EIGHTH, velocity=75)
tabla.hit(DrumSound.TABLA_TIN, Duration.EIGHTH, velocity=70)
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=42)
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=80)
tabla.hit(DrumSound.TABLA_GE, Duration.EIGHTH, velocity=65)
# ── Pad: enters at peak, fades during outro ──
pad = score.part("pad", synth="supersaw", envelope="pad", volume=0.0,
reverb=0.4, chorus=0.2, detune=10, lowpass=2500)
for _ in range(32):
pad.rest(Duration.QUARTER)
pad.ramp(over=Duration.WHOLE * 2, volume=0.18)
for sym in ["Cm", "Ab", "Eb", "Bb"] * 3:
pad.add(Chord.from_symbol(sym), Duration.WHOLE)
pad.ramp(over=Duration.WHOLE * 2, curve="ease_out", volume=0.0)
for sym in ["Cm", "Cm"]:
pad.add(Chord.from_symbol(sym), Duration.WHOLE)
play_song(score, "Acid Tabla — 303 filter automation + tabla (ramp, articulations, Part.hit)")
def snare_cadence():
"""Snare Cadence — full drumline with ensemble, flams, diddles, cheese."""
score = Score("4/4", bpm=120)
S = DrumSound.MARCH_SNARE
R = DrumSound.MARCH_RIMSHOT
C = DrumSound.MARCH_CLICK
Q1 = DrumSound.QUAD_1
Q2 = DrumSound.QUAD_2
Q3 = DrumSound.QUAD_3
Q4 = DrumSound.QUAD_4
QS = DrumSound.QUAD_SPOCK
B1 = DrumSound.BASS_1
B2 = DrumSound.BASS_2
B3 = DrumSound.BASS_3
B4 = DrumSound.BASS_4
B5 = DrumSound.BASS_5
# Snare line — 8 players
p = score.part("snares", synth="sine", volume=0.9, reverb=0.2, ensemble=8)
# Quad line — 4 players
q = score.part("quads", synth="sine", volume=0.5, reverb=0.2, ensemble=4)
# Bass line — 5 players
b = score.part("basses", synth="sine", volume=0.55, reverb=0.2, ensemble=5)
_trip = 1.0 / 3
# Helper: bass split run (down or up)
def bass_down(dur=Duration.SIXTEENTH):
b.hit(B1, dur, velocity=95)
b.hit(B2, dur, velocity=90)
b.hit(B3, dur, velocity=85)
b.hit(B4, dur, velocity=90)
def bass_up(dur=Duration.SIXTEENTH):
b.hit(B4, dur, velocity=90)
b.hit(B3, dur, velocity=85)
b.hit(B2, dur, velocity=90)
b.hit(B1, dur, velocity=95)
def bass_hit(dur=Duration.QUARTER):
b.hit(B3, dur, velocity=100)
def quad_sweep_down():
q.hit(Q1, Duration.SIXTEENTH, velocity=95)
q.hit(Q2, Duration.SIXTEENTH, velocity=88)
q.hit(Q3, Duration.SIXTEENTH, velocity=82)
q.hit(Q4, Duration.SIXTEENTH, velocity=78)
def quad_sweep_up():
q.hit(Q4, Duration.SIXTEENTH, velocity=78)
q.hit(Q3, Duration.SIXTEENTH, velocity=82)
q.hit(Q2, Duration.SIXTEENTH, velocity=88)
q.hit(Q1, Duration.SIXTEENTH, velocity=95)
# ── Click count-off ──
for _ in range(4):
p.hit(C, Duration.QUARTER, velocity=95)
q.rest(Duration.QUARTER)
b.rest(Duration.QUARTER)
# ── Section 1: 16th groove — snares only (4 bars) ──
for _ in range(16):
q.rest(Duration.QUARTER)
b.rest(Duration.QUARTER)
for _ in range(2):
p.hit(R, Duration.SIXTEENTH, velocity=118)
p.hit(S, Duration.SIXTEENTH, velocity=32)
p.hit(S, Duration.SIXTEENTH, velocity=35)
p.hit(S, Duration.SIXTEENTH, velocity=30)
p.hit(R, Duration.SIXTEENTH, velocity=115)
p.hit(S, Duration.SIXTEENTH, velocity=30)
p.hit(S, Duration.SIXTEENTH, velocity=28)
p.hit(S, Duration.SIXTEENTH, velocity=32)
p.hit(R, Duration.SIXTEENTH, velocity=118)
p.hit(S, Duration.SIXTEENTH, velocity=35)
p.hit(S, Duration.SIXTEENTH, velocity=30)
p.hit(S, Duration.SIXTEENTH, velocity=32)
p.hit(R, Duration.SIXTEENTH, velocity=120)
p.hit(S, Duration.SIXTEENTH, velocity=30)
p.hit(S, Duration.SIXTEENTH, velocity=28)
p.hit(S, Duration.SIXTEENTH, velocity=32)
# Triplets mixed in
for _ in range(2):
p.hit(R, _trip, velocity=118)
p.hit(S, _trip, velocity=32)
p.hit(S, _trip, velocity=30)
p.hit(R, _trip, velocity=115)
p.hit(S, _trip, velocity=28)
p.hit(S, _trip, velocity=32)
p.hit(R, Duration.SIXTEENTH, velocity=118)
p.hit(S, Duration.SIXTEENTH, velocity=30)
p.hit(S, Duration.SIXTEENTH, velocity=32)
p.hit(S, Duration.SIXTEENTH, velocity=28)
p.hit(R, _trip, velocity=118)
p.hit(S, _trip, velocity=30)
p.hit(S, _trip, velocity=35)
# ── Section 2: Quads + bass enter (4 bars) ──
for _ in range(2):
p.flam(S, Duration.QUARTER, velocity=118)
p.hit(S, Duration.SIXTEENTH, velocity=30)
p.hit(S, Duration.SIXTEENTH, velocity=32)
p.hit(R, _trip, velocity=118)
p.hit(S, _trip, velocity=28)
p.hit(S, _trip, velocity=30)
p.flam(S, Duration.QUARTER, velocity=118)
quad_sweep_down()
q.hit(QS, Duration.QUARTER, velocity=100)
quad_sweep_up()
q.hit(QS, Duration.QUARTER, velocity=100)
bass_hit()
b.hit(B5, Duration.QUARTER, velocity=95)
bass_hit()
b.hit(B1, Duration.QUARTER, velocity=95)
for _ in range(2):
p.hit(S, _trip, velocity=35)
p.flam(S, _trip * 2, velocity=118)
p.hit(S, Duration.SIXTEENTH, velocity=30)
p.hit(S, Duration.SIXTEENTH, velocity=32)
p.flam(S, Duration.QUARTER, velocity=118)
p.hit(S, _trip, velocity=28)
p.hit(R, _trip, velocity=122)
p.hit(S, _trip, velocity=35)
quad_sweep_down()
quad_sweep_up()
q.hit(Q1, Duration.EIGHTH, velocity=95)
q.hit(Q4, Duration.EIGHTH, velocity=85)
q.hit(QS, Duration.QUARTER, velocity=100)
bass_down()
bass_up()
b.hit(B3, Duration.HALF, velocity=100)
# ── Section 3: Flams + diddles + full line (4 bars) ──
for _ in range(2):
p.flam(S, Duration.QUARTER, velocity=120)
p.diddle(S, Duration.EIGHTH, velocity=45)
p.hit(S, _trip, velocity=30)
p.hit(S, _trip, velocity=32)
p.hit(S, _trip, velocity=28)
p.hit(R, Duration.EIGHTH, velocity=122)
p.diddle(S, Duration.EIGHTH, velocity=42)
q.hit(Q1, Duration.QUARTER, velocity=95)
q.hit(Q3, Duration.EIGHTH, velocity=55)
q.hit(Q2, _trip, velocity=55)
q.hit(Q3, _trip, velocity=55)
q.hit(Q4, _trip, velocity=55)
q.hit(QS, Duration.EIGHTH, velocity=100)
q.hit(Q1, Duration.EIGHTH, velocity=55)
bass_hit()
b.hit(B1, Duration.EIGHTH, velocity=90)
b.hit(B5, Duration.EIGHTH, velocity=95)
bass_hit()
b.hit(B5, Duration.EIGHTH, velocity=90)
b.hit(B1, Duration.EIGHTH, velocity=95)
for _ in range(2):
p.diddle(S, Duration.EIGHTH, velocity=45)
p.hit(R, _trip, velocity=120)
p.hit(S, _trip, velocity=30)
p.hit(S, _trip, velocity=32)
p.diddle(S, Duration.EIGHTH, velocity=48)
p.hit(R, _trip, velocity=118)
p.hit(S, _trip, velocity=28)
p.hit(S, _trip, velocity=30)
p.flam(S, Duration.EIGHTH, velocity=122)
p.hit(S, Duration.EIGHTH, velocity=35)
quad_sweep_down()
quad_sweep_up()
quad_sweep_down()
quad_sweep_up()
bass_down()
bass_up()
bass_down()
bass_up()
# ── Section 4: Cheese + 32nds (4 bars) ──
for _ in range(2):
p.cheese(S, Duration.QUARTER, velocity=120)
p.hit(S, 0.0625, velocity=30)
p.hit(S, 0.0625, velocity=32)
p.hit(S, 0.0625, velocity=35)
p.hit(S, 0.0625, velocity=30)
p.cheese(S, Duration.QUARTER, velocity=118)
p.diddle(S, Duration.EIGHTH, velocity=48)
p.hit(R, Duration.EIGHTH, velocity=125)
q.hit(QS, Duration.QUARTER, velocity=105)
q.hit(Q1, Duration.SIXTEENTH, velocity=55)
q.hit(Q2, Duration.SIXTEENTH, velocity=55)
q.hit(Q3, Duration.SIXTEENTH, velocity=55)
q.hit(Q4, Duration.SIXTEENTH, velocity=55)
q.hit(QS, Duration.QUARTER, velocity=105)
q.hit(Q4, Duration.EIGHTH, velocity=55)
q.hit(Q1, Duration.EIGHTH, velocity=90)
bass_hit()
b.hit(B1, Duration.EIGHTH, velocity=90)
b.hit(B3, Duration.EIGHTH, velocity=85)
b.hit(B5, Duration.EIGHTH, velocity=95)
b.hit(B3, Duration.EIGHTH, velocity=85)
bass_hit()
b.rest(Duration.QUARTER)
# All cheese
p.cheese(S, Duration.QUARTER, velocity=122)
p.cheese(S, Duration.QUARTER, velocity=120)
p.cheese(S, Duration.QUARTER, velocity=125)
p.cheese(S, Duration.QUARTER, velocity=122)
q.hit(QS, Duration.QUARTER, velocity=105)
q.hit(QS, Duration.QUARTER, velocity=105)
q.hit(QS, Duration.QUARTER, velocity=108)
q.hit(QS, Duration.QUARTER, velocity=105)
b.hit(B5, Duration.QUARTER, velocity=100)
b.hit(B3, Duration.QUARTER, velocity=100)
b.hit(B1, Duration.QUARTER, velocity=100)
b.hit(B3, Duration.QUARTER, velocity=100)
p.flam(S, Duration.EIGHTH, velocity=120)
p.diddle(S, Duration.EIGHTH, velocity=50)
p.flam(S, Duration.EIGHTH, velocity=122)
p.diddle(S, Duration.EIGHTH, velocity=52)
p.flam(S, Duration.EIGHTH, velocity=125)
p.diddle(S, Duration.EIGHTH, velocity=55)
p.hit(R, Duration.EIGHTH, velocity=127)
p.hit(S, Duration.EIGHTH, velocity=38)
quad_sweep_down()
quad_sweep_up()
quad_sweep_down()
quad_sweep_up()
bass_down()
bass_up()
bass_down()
bass_up()
# ── Section 5: 16ths + triplet 16ths + 32nds (4 bars) ──
_trip16 = 1.0 / 6
for _ in range(2):
for beat in range(4):
p.hit(R, _trip, velocity=118)
p.hit(S, _trip, velocity=35)
p.hit(S, _trip, velocity=32)
quad_sweep_down()
quad_sweep_up()
quad_sweep_down()
quad_sweep_up()
bass_hit()
b.hit(B5, Duration.QUARTER, velocity=95)
bass_hit()
b.hit(B1, Duration.QUARTER, velocity=95)
# 32nd run crescendo
for i in range(32):
p.hit(S, 0.0625, velocity=min(22 + i * 3, 92))
p.hit(R, Duration.EIGHTH, velocity=125)
p.hit(R, Duration.EIGHTH, velocity=127)
for _ in range(4):
q.hit(Q1, 0.0625, velocity=55)
q.hit(Q2, 0.0625, velocity=55)
q.hit(Q3, 0.0625, velocity=55)
q.hit(Q4, 0.0625, velocity=55)
q.hit(QS, Duration.QUARTER, velocity=108)
bass_down()
bass_up()
bass_down()
b.hit(B5, Duration.QUARTER, velocity=100)
b.hit(B1, Duration.QUARTER, velocity=100)
# Triplet 16ths — all sections
for _ in range(2):
for beat in range(4):
p.hit(R, _trip16, velocity=115)
p.hit(S, _trip16, velocity=30)
p.hit(S, _trip16, velocity=32)
p.hit(R, _trip16, velocity=112)
p.hit(S, _trip16, velocity=28)
p.hit(S, _trip16, velocity=30)
for beat in range(4):
q.hit(Q1, _trip16, velocity=90)
q.hit(Q2, _trip16, velocity=55)
q.hit(Q3, _trip16, velocity=55)
q.hit(Q4, _trip16, velocity=55)
q.hit(Q3, _trip16, velocity=55)
q.hit(Q2, _trip16, velocity=55)
bass_down()
bass_up()
bass_down()
bass_up()
# ── Section 6: Buzz roll climax (2 bars) ──
for i in range(64):
p.hit(S, 0.0625, velocity=min(20 + i * 1.5, 100))
p.hit(R, Duration.EIGHTH, velocity=127)
p.hit(R, Duration.EIGHTH, velocity=127)
for i in range(32):
q.hit([Q1, Q2, Q3, Q4][i % 4], 0.0625, velocity=min(40 + i * 2, 95))
q.hit(QS, Duration.QUARTER, velocity=110)
for i in range(16):
b.hit([B1, B2, B3, B4, B5, B4, B3, B2,
B1, B2, B3, B4, B5, B4, B3, B2][i], Duration.SIXTEENTH, velocity=90)
b.hit(B3, Duration.HALF, velocity=100)
b.hit(B3, Duration.HALF, velocity=100)
# ── Ending: big unison hits ──
p.hit(R, Duration.EIGHTH, velocity=127)
q.hit(QS, Duration.EIGHTH, velocity=110)
b.hit(B3, Duration.EIGHTH, velocity=100)
p.rest(Duration.QUARTER + Duration.EIGHTH)
q.rest(Duration.QUARTER + Duration.EIGHTH)
b.rest(Duration.QUARTER + Duration.EIGHTH)
p.hit(R, Duration.EIGHTH, velocity=127)
q.hit(QS, Duration.EIGHTH, velocity=110)
b.hit(B3, Duration.EIGHTH, velocity=100)
p.rest(Duration.QUARTER + Duration.EIGHTH)
q.rest(Duration.QUARTER + Duration.EIGHTH)
b.rest(Duration.QUARTER + Duration.EIGHTH)
# Flam into final CRACK — all sections
p.flam(S, Duration.EIGHTH, velocity=127)
q.hit(QS, Duration.EIGHTH, velocity=110)
b.hit(B3, Duration.EIGHTH, velocity=100)
p.rest(Duration.QUARTER + Duration.EIGHTH)
q.rest(Duration.QUARTER + Duration.EIGHTH)
b.rest(Duration.QUARTER + Duration.EIGHTH)
p.hit(R, Duration.QUARTER, velocity=127)
q.hit(QS, Duration.QUARTER, velocity=110)
b.hit(B3, Duration.QUARTER, velocity=100)
p.rest(Duration.HALF)
q.rest(Duration.HALF)
b.rest(Duration.HALF)
play_song(score, "Snare Cadence — full drumline (8 snares, 4 quads, 5 basses)")
def ensemble_showcase():
"""Ensemble Showcase — acid bass, tabla solo, strings, snare line."""
score = Score("4/4", bpm=128)
# ── Drums: house kit ──
score.drums("house", repeats=24, fill="house", fill_every=8)
score.set_drum_effects(volume=0.4, reverb=0.1)
# ── 303 Acid Bass: detuned, spread, LFO filter, ensemble=3 ──
acid = score.part("acid", synth="saw", volume=0.55, ensemble=3,
lowpass=400, lowpass_q=10.0, distortion=0.35,
distortion_drive=4.0, legato=True, glide=0.03,
detune=12, spread=0.4, sub_osc=0.15,
sidechain=0.5, sidechain_release=0.08)
acid.lfo("lowpass", rate=0.5, min=400, max=5000, bars=16, shape="sine")
for _ in range(8):
for n in ["C2", "C3", "C2", "Eb2", "C2", "G2", "Bb2", "C2"]:
acid.add(n, Duration.EIGHTH, velocity=90)
acid.ramp(over=Duration.WHOLE * 8, curve="ease_in", lowpass=6000)
for _ in range(8):
for n in ["C2", "Eb3", "C3", "G2", "Bb2", "C3", "G2", "C2"]:
acid.add(n, Duration.EIGHTH, velocity=95)
acid.ramp(over=Duration.WHOLE * 8, curve="ease_out", lowpass=500)
for _ in range(8):
for n in ["C2", "C3", "C2", "Eb2", "C2", "G2", "Bb2", "C2"]:
acid.add(n, Duration.EIGHTH, velocity=88)
# ── Strings: 16-player ensemble pad ──
strings = score.part("strings", instrument="string_ensemble", volume=0.0,
reverb=0.4, ensemble=16, detune=8, spread=0.5)
for _ in range(32):
strings.rest(Duration.QUARTER)
strings.ramp(over=Duration.WHOLE * 4, curve="ease_in", volume=0.18)
for ch in ["Cm", "Ab", "Eb", "Bb"] * 4:
strings.add(Chord.from_symbol(ch), Duration.WHOLE, velocity=55)
strings.ramp(over=Duration.WHOLE * 4, curve="ease_out", volume=0.0)
for ch in ["Cm", "Ab", "Eb", "Bb"]:
strings.add(Chord.from_symbol(ch), Duration.WHOLE, velocity=45)
for _ in range(16):
strings.rest(Duration.QUARTER)
# ── Tabla: ensemble=3, enters bar 9 ──
tabla = score.part("tabla", synth="sine", volume=0.0, reverb=0.15, ensemble=3)
for _ in range(32):
tabla.rest(Duration.QUARTER)
tabla.ramp(over=Duration.WHOLE * 2, volume=0.45)
# Keherwa groove — 8 bars
for _ in range(8):
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=95, articulation="accent")
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=50)
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=48)
tabla.hit(DrumSound.TABLA_NA, Duration.EIGHTH, velocity=82)
tabla.hit(DrumSound.TABLA_TIN, Duration.EIGHTH, velocity=78)
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=48)
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=88, articulation="accent")
tabla.hit(DrumSound.TABLA_GE, Duration.EIGHTH, velocity=72)
# Tabla solo — getting busier
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=100, articulation="marcato")
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=45)
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=48)
tabla.hit(DrumSound.TABLA_NA, Duration.EIGHTH, velocity=85)
tabla.hit(DrumSound.TABLA_TIN, Duration.EIGHTH, velocity=80)
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=45)
tabla.hit(DrumSound.TABLA_NA, Duration.SIXTEENTH, velocity=55)
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=95, articulation="accent")
tabla.hit(DrumSound.TABLA_GE_BEND, Duration.EIGHTH, velocity=82)
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=105, articulation="marcato")
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=48)
tabla.hit(DrumSound.TABLA_NA, Duration.SIXTEENTH, velocity=55)
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=45)
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=48)
tabla.hit(DrumSound.TABLA_NA, Duration.EIGHTH, velocity=88)
tabla.hit(DrumSound.TABLA_DHA, Duration.SIXTEENTH, velocity=100)
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=50)
tabla.hit(DrumSound.TABLA_GE_BEND, Duration.EIGHTH, velocity=85)
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=108, articulation="accent")
# Tihai crescendo
for vel in [85, 90, 95, 100, 105, 110]:
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=vel, articulation="accent")
tabla.hit(DrumSound.TABLA_TIT, Duration.SIXTEENTH, velocity=int(vel * 0.55))
tabla.hit(DrumSound.TABLA_NA, Duration.SIXTEENTH, velocity=int(vel * 0.7))
tabla.hit(DrumSound.TABLA_DHA, Duration.QUARTER, velocity=125, articulation="fermata")
tabla.hit(DrumSound.TABLA_GE_BEND, Duration.QUARTER, velocity=110)
# Groove out
for _ in range(4):
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=88, articulation="accent")
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=45)
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=42)
tabla.hit(DrumSound.TABLA_NA, Duration.EIGHTH, velocity=75)
tabla.hit(DrumSound.TABLA_TIN, Duration.EIGHTH, velocity=70)
tabla.hit(DrumSound.TABLA_TIT, Duration.EIGHTH, velocity=42)
tabla.hit(DrumSound.TABLA_DHA, Duration.EIGHTH, velocity=80)
tabla.hit(DrumSound.TABLA_GE, Duration.EIGHTH, velocity=65)
# ── Snare line: 8-player ensemble, enters bar 17 ──
S = DrumSound.MARCH_SNARE
R = DrumSound.MARCH_RIMSHOT
snares = score.part("snares", synth="sine", volume=0.0, reverb=0.15, ensemble=8)
for _ in range(64):
snares.rest(Duration.QUARTER)
snares.ramp(over=Duration.WHOLE * 2, volume=0.7)
for _ in range(4):
snares.hit(R, Duration.SIXTEENTH, velocity=118)
snares.hit(S, Duration.SIXTEENTH, velocity=30)
snares.hit(S, Duration.SIXTEENTH, velocity=32)
snares.hit(S, Duration.SIXTEENTH, velocity=28)
snares.hit(R, Duration.SIXTEENTH, velocity=115)
snares.hit(S, Duration.SIXTEENTH, velocity=30)
snares.hit(S, Duration.SIXTEENTH, velocity=28)
snares.hit(S, Duration.SIXTEENTH, velocity=32)
snares.hit(R, Duration.SIXTEENTH, velocity=118)
snares.hit(S, Duration.SIXTEENTH, velocity=35)
snares.hit(S, Duration.SIXTEENTH, velocity=28)
snares.hit(S, Duration.SIXTEENTH, velocity=30)
snares.hit(R, Duration.SIXTEENTH, velocity=120)
snares.hit(S, Duration.SIXTEENTH, velocity=30)
snares.hit(S, Duration.SIXTEENTH, velocity=28)
snares.hit(S, Duration.SIXTEENTH, velocity=32)
# Buzz roll finale
for i in range(64):
snares.hit(S, 0.0625, velocity=min(20 + i * 1.5, 100))
snares.hit(R, Duration.EIGHTH, velocity=127)
snares.hit(R, Duration.EIGHTH, velocity=127)
snares.ramp(over=Duration.WHOLE * 2, curve="ease_out", volume=0.0)
for _ in range(2):
snares.hit(R, Duration.SIXTEENTH, velocity=110)
snares.hit(S, Duration.SIXTEENTH, velocity=30)
snares.hit(S, Duration.SIXTEENTH, velocity=28)
snares.hit(S, Duration.SIXTEENTH, velocity=32)
snares.hit(R, Duration.SIXTEENTH, velocity=108)
snares.hit(S, Duration.SIXTEENTH, velocity=30)
snares.hit(S, Duration.SIXTEENTH, velocity=28)
snares.hit(S, Duration.SIXTEENTH, velocity=32)
snares.hit(R, Duration.SIXTEENTH, velocity=105)
snares.hit(S, Duration.SIXTEENTH, velocity=30)
snares.hit(S, Duration.SIXTEENTH, velocity=28)
snares.hit(S, Duration.SIXTEENTH, velocity=32)
snares.hit(R, Duration.SIXTEENTH, velocity=100)
snares.hit(S, Duration.SIXTEENTH, velocity=30)
snares.hit(S, Duration.SIXTEENTH, velocity=28)
snares.hit(S, Duration.SIXTEENTH, velocity=32)
# ── Lead synth: 6-player ensemble, enters bar 5 ──
lead = score.part("lead", synth="saw", envelope="pluck", volume=0.0,
lowpass=3500, detune=6, chorus=0.1, reverb=0.2,
delay=0.15, delay_time=0.33, delay_feedback=0.25,
ensemble=6)
for _ in range(16):
lead.rest(Duration.QUARTER)
lead.ramp(over=Duration.WHOLE * 2, volume=0.3)
for _ in range(2):
lead.add("Eb5", Duration.QUARTER, velocity=88)
lead.add("G5", Duration.QUARTER, velocity=92)
lead.add("Bb5", Duration.HALF, velocity=95, articulation="accent")
lead.add("Ab5", Duration.QUARTER, velocity=88)
lead.add("G5", Duration.QUARTER, velocity=85)
lead.add("Eb5", Duration.QUARTER, velocity=82)
lead.add("D5", Duration.QUARTER, velocity=80)
lead.swell(["Eb5", "G5", "Bb5", "C6", "Bb5", "G5", "Eb5", "D5"],
Duration.QUARTER, low_vel=75, peak_vel=105)
lead.decrescendo(["Eb5", "D5", "C5", "Bb4"], Duration.HALF,
start_vel=90, end_vel=60)
for _ in range(16):
lead.rest(Duration.QUARTER)
lead.ramp(over=Duration.WHOLE * 2, volume=0.35)
lead.crescendo(["C5", "Eb5", "G5", "Bb5", "C6", "Eb6", "C6", "Bb5"],
Duration.QUARTER, start_vel=80, end_vel=110)
lead.add("G5", Duration.HALF, velocity=105, bend=1, bend_type="smooth")
lead.add("Eb5", Duration.HALF, velocity=95)
lead.decrescendo(["C5", "Bb4", "G4", "Eb4"], Duration.WHOLE,
start_vel=85, end_vel=40)
play_song(score, "Ensemble Showcase — acid bass, tabla solo, 16-player strings, 8-player snare line")
SONGS = {
"1": ("Bossa Nova in A minor", bossa_nova_girl),
"2": ("Bebop in Bb major", bebop_in_bb),
"3": ("Salsa Descarga in D minor", salsa_descarga),
"4": ("Afrobeat in E minor", afrobeat_groove),
"5": ("Reggae One-Drop in G major", reggae_one_drop),
"6": ("Funk Workout in E minor", funk_workout),
"7": ("12/8 Blues Shuffle in A", blues_shuffle),
"8": ("Samba in G major", samba_de_janeiro),
"9": ("Jazz Waltz in F major", jazz_waltz),
"10": ("House Anthem in C minor", house_anthem),
"11": ("Kingston After Dark (Dub)", dub_kingston),
"12": ("Minimal Techno in F minor", techno_minimal),
"13": ("Gospel Shuffle in C major", gospel_shuffle),
"14": ("Dub Delay Madness in E minor", dub_delay_madness),
"15": ("Liquid DnB in A minor", drum_and_bass),
"16": ("Late Night Texts (Drake-style)", drake_vibes),
"17": ("Neon Grid (Stereo Acid)", neon_grid),
"18": ("Glass and Silk (Sine+Triangle)", glass_and_silk),
"19": ("Dance Party at the Reitz House", dance_party),
"20": ("Temple Bell (Japanese)", temple_bell),
"21": ("Cinematic Showcase (Orchestral)", cinematic_showcase),
"22": ("Greensleeves (Renaissance Lute)", greensleeves),
"23": ("Tabla Solo (Raga Yaman)", tabla_solo_yaman),
"24": ("Journey (Western → World → Indian)", journey),
"25": ("Epic Bhairav (Orchestral + Tabla)", epic_bhairav),
"26": ("Acoustic Ensemble (Guitar+Uke+Mando+Cajón)", acoustic_ensemble),
"27": ("Ascent (Deep → Sky → Tabla Solo)", ascent),
"28": ("Descent (Generative — different every time)", descent),
"29": ("Pop Rock (I-V-vi-IV)", pop_rock),
"30": ("Sitar Drone (Bhairav, hold() polyphony)", sitar_drone),
"31": ("Acid Tabla (303 + tabla, ramp, articulations)", acid_tabla),
"32": ("Snare Cadence (marching snare, flams, diddles)", snare_cadence),
"33": ("Ensemble Showcase (acid+tabla+strings+snare line)", ensemble_showcase),
}
if __name__ == "__main__":
try:
print()
print(" PyTheory Song Player")
print(" " + "=" * 40)
print()
for key, (name, _) in SONGS.items():
print(f" {key:>2}. {name}")
print()
choice = input(" Pick a song (1-33, or 'all'): ").strip()
print()
if choice == "all":
for _, (_, fn) in SONGS.items():
fn()
print()
elif choice in SONGS:
SONGS[choice][1]()
else:
print(" Playing all songs...")
for _, (_, fn) in SONGS.items():
fn()
print()
except KeyboardInterrupt:
sd.stop()
print("\n\n Bye!")