Skip to content

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:

kr.save("verse")

Restore it later:

kr.recall("verse")

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:

kr.export("verse.py")

Reload it in a later session:

kr.load("verse.py")

Load from a subdirectory:

kr.load("songs/verse.py")

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:

with kr.transition(bars=8):
    bass["gain"] = 0.8
    verb["room"] = 0.9
    kr.tempo = 140

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.master level
  • 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

  1. Compose -- build your session interactively in the REPL
  2. Export -- kr.export("session.py") saves everything
  3. 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")