Scenes¶
krach can save and restore complete session states -- nodes, patterns, tempo, and all control values. Use scenes to build song sections, switch between arrangements, and persist your work to disk.
In-memory snapshots¶
Save the current state to memory with a name:
Restore it later:
In-memory snapshots are fast but lost when you exit the REPL.
Workflow: A/B between sections¶
# Build a verse
kr.play("kick", kr.hit() * 4)
kr.play("bass", kr.seq("A2", "D3", None, "E2").over(2))
kr.save("verse")
# Build a chorus
kr.play("kick", kr.hit() * 8)
kr.play("bass", kr.seq("A3", "C3", "E3", "G3"))
kr.save("chorus")
# Switch between them
kr.recall("verse")
kr.recall("chorus")
File persistence¶
Export the full session to a Python file:
Reload it in a later session:
Load from a subdirectory:
Smooth transitions¶
Use kr.transition(bars=N) to make all gain and control changes inside the
block fade smoothly over N bars instead of snapping instantly:
Every set(), gain(), and handle[param] = value inside the block becomes
a fade() over the specified number of bars. This is useful for smooth scene
changes:
# Build two scenes, transition between them
kr.save("verse")
# Modify into chorus
bass["gain"] = 0.5
kr.play("kick", kr.hit() * 8)
kr.save("chorus")
# Smooth recall
kr.recall("verse")
with kr.transition(bars=4):
kr.recall("chorus") # all changes fade over 4 bars
No nesting
kr.transition() blocks cannot be nested. A RuntimeError is raised if
you attempt to open a transition inside another transition.
What gets captured¶
A scene snapshot (both in-memory and file export) captures:
- Source nodes -- all active source nodes with their DSP type and gain
- Effect nodes -- all effect nodes and their configuration
- Routes -- all signal routings and levels
- Patterns -- all active pattern assignments
- Tempo -- current BPM
- Master gain --
kr.masterlevel - Controls -- current values of all node controls
Music as Python modules¶
Exported files are plain Python. You can edit them, share them, and version them with git. A typical exported file sets up nodes, routing, and patterns -- everything needed to reproduce the session.
Write reusable setup scripts by hand:
# my_kit.py -- reusable drum kit setup
def kick() -> krs.Signal:
gate = krs.control("gate", 0.0, 0.0, 1.0)
env = krs.adsr(0.001, 0.25, 0.0, 0.05, gate)
return krs.sine_osc(55.0 + env * 200.0) * env * 0.9
def hat() -> krs.Signal:
gate = krs.control("gate", 0.0, 0.0, 1.0)
env = krs.adsr(0.001, 0.04, 0.0, 0.02, gate)
return krs.highpass(krs.white_noise(), 8000.0) * env * 0.5
with kr.batch():
kr.node("drums/kick", kick, gain=0.8)
kr.node("drums/hat", hat, gain=0.5)
Then load it from the REPL:
kr.load("my_kit.py")
kr.play("drums/kick", kr.hit() * 4)
kr.play("drums/hat", (kr.rest() + kr.hit()) * 4)
Workflow: compose, export, iterate¶
- Compose -- build your session interactively in the REPL
- Export --
kr.export("session.py")saves everything - Iterate -- edit the file, reload with
kr.load(), repeat
# Session 1: build the initial arrangement
kr.tempo = 128
kr.node("kick", kick, gain=0.8)
kr.node("bass", acid_bass, gain=0.3)
kr.play("kick", kr.hit() * 4)
kr.play("bass", kr.seq("A2", "D3", None, "E2").over(2))
kr.export("track_v1.py")
# Session 2: pick up where you left off
kr.load("track_v1.py")
kr.node("lead", lead_fn, gain=0.25)
kr.play("lead", kr.seq("A4", "C5", "E5", "D5").over(2))
kr.export("track_v2.py")