Skip to content

dasAudio/strudel: one-shot patterns (once / playFor + strudel_one_shot)#3241

Merged
borisbat merged 2 commits into
masterfrom
bbatkin/strudel-one-shot
Jun 21, 2026
Merged

dasAudio/strudel: one-shot patterns (once / playFor + strudel_one_shot)#3241
borisbat merged 2 commits into
masterfrom
bbatkin/strudel-one-shot

Conversation

@borisbat

Copy link
Copy Markdown
Collaborator

What

Strudel patterns loop forever by construction — there is no "play this phrase once, then stop". This adds the missing primitive so a finite phrase can be fired on a host event (a win sting, a pickup chime, an impact) and then cleanly retire itself. It is a daStrudel extension over strudel.cc.

The two halves

  • stopplayFor(pat, n) / once(pat) (strudel_pattern): gate a pattern to its first n cycles (onsets in [0, n)), then silence forever. A pure Pattern combinator — composes with the rest of the algebra.
  • diestrudel_one_shot(pat, gain, quant_cycles, len_cycles) (strudel_player): fire pat as a self-retiring track. It plays for len_cycles, goes silent, and the track auto-removes from the mix once every voice has finished ringing — so the release tail is never clipped. Returns the track index. strudel_active_tracks() reports how many tracks are live ("is the sting still ringing?").

Quantize to the beat

quant_cycles snaps the start to the global beat grid (0 = immediate; 0.25 = the next quarter-cycle beat), so a sting triggered at an arbitrary instant still lands musically in time rather than on the exact frame of the event.

Why it matters

Each one-shot is an independent track built fresh per call, so the same mechanism scales to parametric SFX — vary the pattern per event (pitch by impact, instrument by surface) and fire a different sting each time, with no baked or shipped audio assets. It is the discrete-event complement to the continuous adaptive control (signal + orbit fades) already in the library.

API

Function
playFor(pat, n) gate to the first n cycles, then silence
once(pat) playFor(pat, 1)
strudel_one_shot(pat, gain, quant_cycles, len_cycles) fire a self-retiring one-shot track; returns its index
strudel_active_tracks() count of live (non-null) tracks

Tests

tests/strudel/test_one_shot.das (AOT-registered): the gate (stop), the render tail (decays, no re-trigger), auto-retire (die), and the beat-quantized onset — 8 assertions. Interp + AOT both green; the full strudel suite is 657/657 on both.

Docs

  • strudel_vs_strudel_cc.rst: a new "One-shot patterns (fire-and-forget stings)" section under Extensions.
  • Generated reference: a new "One-shots" group (strudel_player) and playFor / once in the strudel_pattern combinators.
  • New tutorial daStrudel-19 (tutorials/daStrudel/daStrudel_19_one_shots.das + RST), wired into the toctree. Both Sphinx builders pass -W.

🤖 Generated with Claude Code

borisbat and others added 2 commits June 21, 2026 03:16
Strudel patterns loop forever by construction — there's no "play once then stop".
Add the missing primitive so a finite phrase can be fired on an event (game stings,
parametric SFX), which strudel.cc has no equivalent for:

- strudel_pattern: playFor(pat, n) / once(pat) — gate a pattern to its first n
  cycles (onsets in [0, n)), then silence. A pure pattern transform.
- strudel_player: strudel_one_shot(pat, gain, quant_cycles, len_cycles) — fire a
  one-shot as a self-retiring track. quant_cycles snaps the start to the global
  beat grid (0 = immediate); the track auto-removes once every voice has finished
  ringing, so the release tail is never cut. Plus strudel_active_tracks().
- tests/strudel/test_one_shot: the gate (stop), render tail (no cut, no
  re-trigger), auto-retire (die), and beat-quantized onset — 8 assertions.

Docs (strudel_vs_strudel_cc, API, tutorial) to follow before PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- strudel_vs_strudel_cc: new "One-shot patterns (fire-and-forget stings)"
  extension section — the stop (playFor/once) / die (strudel_one_shot) split,
  beat quantization, and parametric SFX.
- das2rst: "One-shots" group (strudel_player) + playFor/once added to the
  strudel_pattern combinators group, so the generated reference documents the
  new API.
- tutorials/daStrudel_19_one_shots: new numbered tutorial (.das + .rst), wired
  into the tutorials toctree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 21, 2026 10:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds “one-shot” support to daStrudel so finite phrases can be triggered by host/game events, quantized to the beat grid, and then automatically retire after audio finishes.

Changes:

  • Added playFor(pat, n) / once(pat) pattern combinators to gate patterns to a finite number of cycles.
  • Added strudel_one_shot(...) self-retiring track primitive plus strudel_active_tracks() for lifecycle/introspection.
  • Added tests, docs, and a new tutorial covering one-shots and beat-quantized triggering.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tutorials/daStrudel/daStrudel_19_one_shots.das New tutorial demonstrating gating, one-shot firing, quantization, and parametric SFX patterns.
tests/strudel/test_one_shot.das New tests for once/playFor, render “stop + tail”, one-shot auto-retire, and quantized onset.
tests/aot/CMakeLists.txt Registers the new one-shot test for AOT test runs.
modules/dasAudio/strudel/strudel_player.das Implements strudel_one_shot, one-shot retirement logic, and strudel_active_tracks().
modules/dasAudio/strudel/strudel_pattern.das Implements playFor and once combinators.
doc/source/reference/tutorials/daStrudel_19_one_shots.rst Adds the STRUDEL-19 tutorial page.
doc/source/reference/tutorials.rst Adds STRUDEL-19 to the tutorials toctree.
doc/source/reference/strudel_vs_strudel_cc.rst Documents one-shots as a daStrudel extension over strudel.cc.
doc/reflections/das2rst.das Updates doc grouping to surface one-shot APIs in generated reference.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread modules/dasAudio/strudel/strudel_pattern.das
Comment thread modules/dasAudio/strudel/strudel_player.das
@borisbat borisbat merged commit ec2d158 into master Jun 21, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants