dasAudio/strudel: one-shot patterns (once / playFor + strudel_one_shot)#3241
Merged
Conversation
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>
Contributor
There was a problem hiding this comment.
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 plusstrudel_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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
playFor(pat, n)/once(pat)(strudel_pattern): gate a pattern to its firstncycles (onsets in[0, n)), then silence forever. A purePatterncombinator — composes with the rest of the algebra.strudel_one_shot(pat, gain, quant_cycles, len_cycles)(strudel_player): firepatas a self-retiring track. It plays forlen_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_cyclessnaps 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
playFor(pat, n)ncycles, then silenceonce(pat)playFor(pat, 1)strudel_one_shot(pat, gain, quant_cycles, len_cycles)strudel_active_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.strudel_player) andplayFor/oncein thestrudel_patterncombinators.tutorials/daStrudel/daStrudel_19_one_shots.das+ RST), wired into the toctree. Both Sphinx builders pass-W.🤖 Generated with Claude Code