CtrlK
BlogDocsLog inGet started
Tessl Logo

ai-ecoverse/skills

Collection of agent skills for SLICC and Tessl-compatible runtimes — productivity, creative, document, and integration skills.

74

Quality

92%

Does it follow best practices?

Impact

No eval scenarios have been run

SecuritybySnyk

Risky

Do not use without reviewing

Overview
Quality
Evals
Security
Files

api-reference.mdskills/strudel-music/references/

Strudel API Reference

Comprehensive reference for the Strudel music library. Read the main SKILL.md first for the essentials.

Table of contents

  1. Initialization
  2. Pattern constructors
  3. Control parameters
  4. Mini-notation full reference
  5. Effects reference
  6. Time modifiers reference
  7. Pattern modifiers reference
  8. Scales and chords
  9. Sample banks
  10. Drum sound codes
  11. Samples manifest
  12. Continuous signals
  13. Multi-pattern playback

Initialization

initStrudel(options?)

One-call setup. Registers all Strudel functions as globals (note, sound, s, n, stack, cat, etc.), initializes audio on first click, registers built-in synths.

initStrudel();  // basic

initStrudel({
  prebake: () => samples('github:tidalcycles/dirt-samples'),
});  // with sample loading

Returns { evaluate } — the function to evaluate Strudel code strings.

evaluate(code, autoplay?)

Transpile and run a Strudel code string. Supports $: syntax, mini-notation, and all sugar.

hush()

Stop all playing patterns immediately.

setcps(n) / setcpm(n)

Set tempo. Default is 0.5 cps (cycles per second) = 120 BPM at 4 events per cycle.

Pattern constructors

FunctionDescription
sequence(a, b, ...) / seq(a, b)All items in one cycle
cat(a, b, ...) / slowcat(a, b)One item per cycle
fastcat(a, b)All in one cycle (alias for seq)
stack(a, b, ...)Play in parallel
polymeter(a, b)Different-length cycles
polyrhythm(a, b)Polyrhythmic combination
silenceEmpty pattern
pure(x)Constant value
run(n)Numbers 0 to n-1
binary(n)Binary pattern from integer
arrange([4, pat1], [2, pat2])Multi-cycle arrangement

Control parameters

These create patterns from values and attach a control name:

FunctionDescriptionExample
note(pat)Pitch (letter or MIDI)note("c3 e3 g3")
sound(pat) / s(pat)Sound namesound("bd sd")
n(pat)Sample/scale degree numbern("0 2 4")
freq(pat)Frequency in Hzfreq("440 660")
gain(pat)Volume 0-1gain("0.5 1")
pan(pat)Stereo 0-1pan("0 1")
speed(pat)Playback speedspeed("1 2 -1")
begin(pat)Sample start 0-1begin("0 0.5")
end(pat)Sample end 0-1end("0.5 1")
cut(pat)Cut groupcut(1)
bank(pat)Sample bankbank("RolandTR909")

Mini-notation full reference

SyntaxMeaningExample
spaceSequence"a b c" = 3 events per cycle
.Same as space (separator)"a.b.c"
[x y]Subdivide slot"a [b c] d"
<x y>Alternate per cycle"<a b c>"
x*nRepeat n times in slot"a*4"
x/nSpan n cycles"a/2"
x,yPolyphony"[a,b,c]"
~Silence/rest"a ~ b ~"
-Rest (alias)"a - b -"
_Extend previous"a _ b _"
x@nWeight/elongate"a@3 b"
x!nReplicate (no squish)"a!3 b" = 4 events
x?50% random mute"a*8?"
x?0.220% random mute"a*8?0.2"
x|yRandom choice"[a|b|c]"
x(p,s)Euclidean rhythm"a(3,8)"
x(p,s,o)Euclidean + offset"a(3,8,2)"
x:nSample number"bd:2"
{a b, x y z}Polymeter{a b c, x y}

Effects reference

Filters

MethodDescriptionRange
.lpf(freq) / .cutoff(freq)Low-pass filter20-20000 Hz
.hpf(freq)High-pass filter20-20000 Hz
.bpf(freq)Band-pass filter20-20000 Hz
.lpq(q) / .hpq(q) / .bpq(q)Filter resonance0-50
.vowel(v)Vowel filter"a e i o u"

Amplitude

MethodDescriptionRange
.gain(g)Volume0-1+
.shape(s)Waveshaping distortion0-1

Spatial

MethodDescriptionRange
.pan(p)Stereo position0 (L) to 1 (R)
.room(r)Reverb amount0-4+
.roomsize(s)Reverb room size0-2
.roomlp(f)Reverb low-passHz
.roomdim(d)Reverb dampening0-1

Delay

MethodDescription
.delay(d)Delay wet amount (0-1)
.delaytime(t)Delay time in cycles
.delayfeedback(f)Feedback amount
.delay("wet:time:feedback")Shorthand

Envelope (ADSR)

MethodDescription
.attack(t)Attack time (seconds)
.decay(t)Decay time
.sustain(l)Sustain level (0-1)
.release(t)Release time
.adsr("a:d:s:r")Shorthand
.clip(f) / .legato(f)Duration multiplier

Synthesis

MethodDescription
.fm(depth)FM synthesis modulation depth
.fmh(ratio)FM harmonicity ratio
.vib(freq)Vibrato frequency
.vibmod(depth)Vibrato depth

Playback

MethodDescription
.speed(s)Playback rate (negative = reverse)
.begin(b)Start position 0-1
.end(e)End position 0-1
.unit("c")Use cycles as duration unit
.cut(n)Cut group (same group cuts previous)

Time modifiers reference

MethodDescription
.slow(n)Stretch over n cycles
.fast(n)Compress into 1/n cycle
.early(n)Shift earlier by n cycles
.late(n)Shift later by n cycles
.rev()Reverse pattern
.euclid(p, s)Euclidean rhythm
.euclid(p, s, o)Euclidean with rotation
.ply(n)Repeat each event n times
.iter(n)Rotate subdivisions each cycle
.iter2(n)Reverse iter
.palindrome()Reverse alternate cycles
.segment(n)Sample signal n times per cycle
.swing(amount)Swing feel
.ribbon(offset, cycles)Loop portion

Pattern modifiers reference

MethodDescription
.jux(fn)Stereo split — apply fn to right
.juxBy(amount, fn)jux with variable width
.every(n, fn)Apply fn every n cycles
.sometimes(fn)Apply fn ~50% of events
.often(fn)Apply fn ~75%
.rarely(fn)Apply fn ~25%
.almostNever(fn)Apply fn ~10%
.almostAlways(fn)Apply fn ~90%
.someCycles(fn)Apply fn ~50% of cycles
.struct(pat)Apply rhythmic structure
.mask(pat)Silence where pat is silent
.off(time, fn)Offset copy with transformation
.add(pat)Add values
.sub(pat)Subtract values
.mul(pat)Multiply values
.div(pat)Divide values
.range(min, max)Scale 0-1 signal to range
.rangex(min, max)Exponential range
.degradeBy(amount)Random silence (0-1)
.degrade()degradeBy(0.5)
.superimpose(fn)Stack with transformed copy
.layer(fn1, fn2, ...)Stack with multiple transforms

Scales and chords

Using scales

n("0 1 2 3 4 5 6 7").scale("C:minor").s("piano")

Scale format: "Root:mode" or "Root:mode:variation".

Common scales

ScaleNotes
C:majorC D E F G A B
C:minorC D Eb F G Ab Bb
C:dorianC D Eb F G A Bb
C:mixolydianC D E F G A Bb
C:minor:pentatonicC Eb F G Bb
C:major:pentatonicC D E G A
C:bluesC Eb F Gb G Bb
C:chromaticall 12 semitones

Chords in mini-notation

note("<[c3,e3,g3] [f3,a3,c4] [g3,b3,d4]>")

Or with tonal functions:

note("<C3 F3 G3>").chord()  // auto-voice chords

Sample banks

Drum machines

Bank nameMachine
RolandTR808TR-808
RolandTR909TR-909
RolandTR707TR-707
RolandTR505TR-505
AkaiLinnAkai/Linn
RhythmAceRhythm Ace
ViscoSpaceDrumSpace Drum
RolandCompurhythm1000CR-1000
CasioRZ1Casio RZ-1

Loading external samples

// GitHub sample packs
samples('github:tidalcycles/dirt-samples')

// After loading, use hundreds of sample names:
// jazz, piano, bass, strings, etc.

GM Soundfonts

After loading soundfonts, use gm_ prefixed names:

sound("gm_acoustic_grand_piano")
sound("gm_electric_bass_finger")
sound("gm_synth_strings_1")
sound("gm_lead_6_voice")

Drum sound codes

Common dirt-sample drum names usable directly with sound("..."):

CodeDrumCodeDrum
bdBass drumohOpen hi-hat
sdSnarecpClap
hhHi-hatrimRimshot
ltLow tommtMid tom
htHigh tomrdRide
crCrash

808 variants: 808bd, 808sd, 808cy, 808hc, 808ht, 808lt, 808mt, 808oh — separate sample names, not banks.

Samples manifest

Manifest structure

samples() takes a JSON object mapping category names to arrays of WAV file paths, plus a _base URL prefix. When a pattern references a sound name like bd or 808bd, Strudel fetches the WAV from _base + path on demand.

{
  "_base": "https://raw.githubusercontent.com/tidalcycles/dirt-samples/master/",
  "bd": ["bd/BT0A0A7.wav", "bd/BT0A0D0.wav"],
  "808bd": ["808bd/BD0000.WAV", "808bd/BD0010.WAV"]
}

Included categories

The curated manifest at /shared/sprinkles/strudel-music/samples-manifest.json contains 44 categories / ~223 samples:

TypeCategories
Standard drumsbd, sd, hh, cp, oh, ho, hc, lt, mt, ht, cr, rm, rs, cb
808 drum machine808, 808bd, 808sd, 808cy, 808hc, 808ht, 808lt, 808mt, 808oh
909909
Drum kitsdrumtraks, electro1, gretsch, house, jazz, jungle, tech, feel, clubkick
Melodic/tonalarpy, bass, jvbass, casio, moog, juno, pad, pluck, sitar, stab, rave
Percussiontabla

Adding more samples

To expand the curated manifest, download the full dirt-samples manifest and add categories:

# Download the complete dirt-samples manifest
curl -sL "https://raw.githubusercontent.com/tidalcycles/dirt-samples/master/strudel.json" > /tmp/strudel-samples.json

# Then use node to merge new categories into the curated manifest:
node -e "
const full = JSON.parse(await fs.readFile('/tmp/strudel-samples.json'));
const curated = JSON.parse(await fs.readFile('/shared/sprinkles/strudel-music/samples-manifest.json'));

// Add new categories (up to 6 samples each)
var newCats = ['piano', 'flick', 'mouth', 'wind', 'birds', 'metal'];
for (var k of newCats) {
  if (full[k]) curated[k] = full[k].slice(0, 6);
}

await fs.writeFile('/shared/sprinkles/strudel-music/samples-manifest.json', JSON.stringify(curated));
console.log('Updated manifest');
"

The full dirt-samples repo has 218 categories / 2038 samples. The curated manifest keeps only the most useful subset to avoid unnecessary network requests.

Continuous signals

All signals oscillate from 0 to 1 over one cycle (bipolar variants from -1 to 1):

SignalDescription
sine / sine2Sine wave
cosine / cosine2Cosine
saw / saw2Sawtooth
tri / tri2Triangle
square / square2Square
randRandom per event
perlinSmooth noise
irand(n)Random integer 0 to n-1

Use patterns:

.lpf(sine.range(200, 4000).slow(8))   // filter sweep
.gain(saw.range(0.2, 1))              // volume ramp
.pan(sine.slow(4))                     // autopan
.speed(perlin.range(0.5, 2).slow(16)) // random speed drift

Multi-pattern playback

In evaluate() (REPL syntax)

evaluate(`
$: sound("bd*4, [~ sd]*2, hh*8")
$: note("c2 eb2 f2 g2").s("sawtooth").lpf(800)
$: n("0 2 4 <3 5>").scale("C:minor").s("triangle").room(0.3)
`)

Use _$: to mute a pattern.

With .play() (direct API)

Each .play() call creates an independent playback. Call hush() to stop all.

note("c3 e3 g3").s("triangle").play()
sound("bd*4, [~ sd]*2").play()

With stack()

stack(
  note("c2 eb2 f2 g2").s("sawtooth").lpf(800),
  sound("bd*4, [~ sd]*2, hh*8").bank("RolandTR909"),
  n("0 2 4 6").scale("C:minor").s("triangle").room(0.5)
).play()

More example patterns

Ambient generative:

note("c3 [eb3 g3] <bb3 ab3> f3")
  .s("sine")
  .room(4)
  .delay(0.6)
  .lpf(1200)
  .slow(2)
  .jux(x => x.add(note("7")).slow(1.5))

Euclidean polyrhythm:

stack(
  sound("808bd(3,8)"),
  sound("sd(5,8,2)").gain(0.6),
  sound("hh(7,16)").gain(0.4)
)

Multi-sample showcase (arpy, moog, jvbass, juno, pluck):

stack(
  note("e4 e4 f#4 g4").sound("arpy").room(0.3).gain(0.7),
  note("e3 ~ f#3 ~").sound("moog").lpf(1200).gain(0.3),
  note("d2 g2 a2 d2").sound("jvbass").gain(0.5).lpf(500),
  note("[d3,f#3,a3]").sound("juno").gain(0.15).room(2),
  note("[~ d5 ~ a4]").sound("pluck").gain(0.2).delay(0.3),
  sound("808bd(3,8)").gain(0.5),
  sound("[~ gretsch:2]*2").gain(0.4),
  sound("808hc*8").gain(0.25)
)

skills

strudel-music

tile.json