Created
January 27, 2026 20:53
-
-
Save twobob/ddc3b495d897d399152087ed515984d8 to your computer and use it in GitHub Desktop.
strudel file for a rando xylo player with beats
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
| setcpm(60/4) | |
| addVoicings('cookie', { | |
| 7: ['3M 7m 9M 12P 15P', '7m 10M 13M 16M 19P', '3M 6M 9M 13M 15P', '7m 9M 13M 16M 20P'], | |
| '^7': ['3M 6M 9M 12P 14M', '7M 10M 13M 16M 19P', '3M 7M 10M 14M 17M', '6M 10M 14M 17M 21M'], | |
| m7: ['8P 11P 14m 17m 19P', '5P 8P 11P 14m 17m', '3m 7m 10m 14m 17m', '5P 10m 14m 17m 19P'], | |
| m7b5: ['3m 5d 8P 11P 14m', '5d 8P 11P 14m 17m', '3m 5d 10m 14m 17m', '8P 12d 15P 17m 21m'], | |
| o7: ['3m 6M 9M 11A 15P', '3m 5d 8P 11A 14d', '6M 9M 12d 15P 18d'], | |
| '7alt': ['3M 7m 10m 13m 15P', '3M 6m 10m 13m 16m', '7m 10m 13m 16m 18A'], | |
| '7#11': ['7m 10m 13m 15P 17m', '3M 7m 11A 14M 17m', '7m 11A 14M 17m 19P'], | |
| }, ['C3', 'C6']) | |
| // --- progression ------------------------------------------------------------ | |
| const chords = | |
| "<C^7 Am7 Dm7 G7 C^7 Em7 Am7 Dm7 F^7 G7 C^7 A7 Dm7 G7 Em7 Am7 Dm7 G7 C^7 E7 Am7 D7 G7 C^7 F^7 Bm7b5 E7 Am7 Dm7 G7 C^7 F^7>" | |
| .voicings('cookie') | |
| // chord “events” | |
| const chordStruct = chords | |
| const chordNotes = chords.note().struct(chordStruct) | |
| // --- chord dynamics (per chord event) -------------------------------------- | |
| const hardC = rand.pow(2).segment(1) | |
| const velC = hardC.range(0.12, 1.0) | |
| const sampC = irand(8).segment(1) | |
| // --- chord sound ------------------------------------------------------------ | |
| const chordPad = stack( | |
| chordNotes.s("xylophone_hard_ff").n(sampC).gain(velC).mask(hardC.gte(0.86)), | |
| chordNotes.s("xylophone_hard_pp").n(sampC).gain(velC).mask(hardC.gte(0.70).and(hardC.lt(0.86))), | |
| chordNotes.s("xylophone_medium_ff").n(sampC).gain(velC).mask(hardC.gte(0.50).and(hardC.lt(0.70))), | |
| chordNotes.s("xylophone_medium_pp").n(sampC).gain(velC).mask(hardC.gte(0.30).and(hardC.lt(0.50))), | |
| chordNotes.s("xylophone_soft_ff").n(sampC).gain(velC).mask(hardC.lt(0.30)), | |
| ) | |
| .pan(rand.range(-0.6, 0.6)) | |
| .fm("<0.5 1 2 8 32>".withValue(v => v * 0.5).log()) | |
| .room(0.85) | |
| .size(3.95) | |
| .delay(0.82) | |
| .delaysync("<1 2 3 5>".div(8)) | |
| .delayfeedback("<.55 .5 .75 1>") | |
| // --- arp (real: iterates chord notes) -------------------------------------- | |
| const arpNotes = | |
| chords | |
| .note() | |
| .iter(1) | |
| .struct(chords) // resets on chord change | |
| .fast(8) // 8th-note ostinato | |
| const hardA = rand.pow(2).segment(1/8) | |
| const velA = hardA.range(0.02, 0.30) | |
| const sampA = irand(8).segment(1/8) | |
| const arp = stack( | |
| //arpNotes.s("xylophone_hard_pp").n(sampA).gain(velA).mask(hardA.gte(0.75)), | |
| arpNotes.s("xylophone_medium_pp").n(sampA).gain(velA).mask(hardA.gte(0.40).and(hardA.lt(0.75))), | |
| arpNotes.s("xylophone_soft_ff").n(sampA).gain(velA).mask(hardA.lt(0.40)), | |
| ) | |
| .pan(rand.range(-0.25, 0.25)) | |
| .room(0.85) | |
| .size(.9) | |
| .delay(0.82) | |
| .delaysync("<.5 1 2 4>".div(16)) | |
| .delayfeedback("<.45 .35 .25>") | |
| // --- Logic Helpers --------------------------------------------------------- | |
| const swing = (p) => p.late(0.05).off(1/6, x => x.gain(0.4)) // Simple swing feel | |
| const ghost = (p) => p.gain(rand.range(0.1, 0.3)).delay(rand.range(0, 0.02)) | |
| // --- Patterns -------------------------------------------------------------- | |
| // 1. Bass Drum: Sparse, "feathered" jazz style with occasional syncopation | |
| const kick = s("bd:4") | |
| .struct("t(3,8) <t f>!3") | |
| .gain(0.6) | |
| .lpf(400) // Keep it "thumpy" and felt rather than heard | |
| // 2. Snare: Main backbeat on 2 and 4, mixed with randomized ghost notes | |
| const snare = stack( | |
| s("sd:2").struct("f t f t").gain(0.8), // Backbeat | |
| s("sd:5").struct("~ t? ~ <t? f>").gain(rand.range(0.2, 0.5)).delay(0.01) // Ghosting | |
| ) | |
| // 3. Hats/Ride: The core of the jazz feel | |
| // Uses a weighted choice between standard 8ths and swing triplets | |
| const hats = s("<hh*4 [hh hh?]*2 [hh*3]/1.5 hh*2>") | |
| .n(irand(4)) // Vary the sample slightly per hit | |
| .gain(velocity("<0.8 0.5 0.7 0.4>").range(0.4, 0.9)) | |
| .pan(rand.range(0.2, 0.4)) | |
| // 4. Percussion / Rim: Occasional "woody" accents | |
| //const accents = s("rim:2?") | |
| // .struct("~ ~ ~ t(5,16)") | |
| // .gain(rand.range(0.3, 0.6)) | |
| // --- Integration ----------------------------------------------------------- | |
| const beat = stack( | |
| kick, | |
| snare, | |
| hats//, | |
| // accents | |
| ) | |
| .jux(rev) // Subtle binaural variation | |
| .delay(0.02).room(0.2).size(0.2) // Tight room acoustics | |
| // --- mix: THIS MUST BE A BODY EXPRESSION ----------------------------------- | |
| const mix = stack(beat, chordPad, arp) | |
| // audio output (last expression) | |
| mix | |
| // optional visual (separate expression) | |
| mix._scope() |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://strudel.cc/#c2V0Y3BtKDQwLzQpCgovLyAtLS0gTUlYIFNMSURFUlMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIExpbmVhciBnYWluIChub3QgZEIpCmNvbnN0IE1BU1RFUiA9IHNsaWRlcigwLjU1LCAwLjAsIDEuMiwgMC44NSkKY29uc3QgRFJVTVMgID0gc2xpZGVyKDAuNDUsICAwLjAsIDEuMiwgMC43NSkKY29uc3QgQ0hPUkRTID0gc2xpZGVyKDAuNywgMC4wLCAxLjIsIDAuOTApCmNvbnN0IEFSUCAgICA9IHNsaWRlcigwLjQ1LCAgICAwLjAsIDEuMiwgMC41NSkKCmFkZFZvaWNpbmdzKCdjb29raWUnLCB7CiAgNzogICAgICBbJzNNIDdtIDlNIDEyUCAxNVAnLCAnN20gMTBNIDEzTSAxNk0gMTlQJywgJzNNIDZNIDlNIDEzTSAxNVAnLCAnN20gOU0gMTNNIDE2TSAyMFAnXSwKICAnXjcnOiAgIFsnM00gNk0gOU0gMTJQIDE0TScsICc3TSAxME0gMTNNIDE2TSAxOVAnLCAnM00gN00gMTBNIDE0TSAxN00nLCAnNk0gMTBNIDE0TSAxN00gMjFNJ10sCiAgbTc6ICAgICBbJzhQIDExUCAxNG0gMTdtIDE5UCcsICc1UCA4UCAxMVAgMTRtIDE3bScsICczbSA3bSAxMG0gMTRtIDE3bScsICc1UCAxMG0gMTRtIDE3bSAxOVAnXSwKICBtN2I1OiAgIFsnM20gNWQgOFAgMTFQIDE0bScsICc1ZCA4UCAxMVAgMTRtIDE3bScsICczbSA1ZCAxMG0gMTRtIDE3bScsICc4UCAxMmQgMTVQIDE3bSAyMW0nXSwKICBvNzogICAgIFsnM20gNk0gOU0gMTFBIDE1UCcsICczbSA1ZCA4UCAxMUEgMTRkJywgJzZNIDlNIDEyZCAxNVAgMThkJ10sCiAgJzdhbHQnOiBbJzNNIDdtIDEwbSAxM20gMTVQJywgJzNNIDZtIDEwbSAxM20gMTZtJywgJzdtIDEwbSAxM20gMTZtIDE4QSddLAogICc3IzExJzogWyc3bSAxMG0gMTNtIDE1UCAxN20nLCAnM00gN20gMTFBIDE0TSAxN20nLCAnN20gMTFBIDE0TSAxN20gMTlQJ10sCn0sIFsnQzMnLCAnQzYnXSkKCi8vIC0tLSBwcm9ncmVzc2lvbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KY29uc3QgY2hvcmRzID0KICAiPENeNyBBbTcgRG03IEc3IENeNyBFbTcgQW03IERtNyBGXjcgRzcgQ143IEE3IERtNyBHNyBFbTcgQW03IERtNyBHNyBDXjcgRTcgQW03IEQ3IEc3IENeNyBGXjcgQm03YjUgRTcgQW03IERtNyBHNyBDXjcgRl43PiIKICAgIC52b2ljaW5ncygnY29va2llJykKCi8vIGNob3JkIOKAnGV2ZW50c%2BKAnQpjb25zdCBjaG9yZFN0cnVjdCA9IGNob3Jkcwpjb25zdCBjaG9yZE5vdGVzICA9IGNob3Jkcy5ub3RlKCkuc3RydWN0KGNob3JkU3RydWN0KQoKLy8gLS0tIGNob3JkIGR5bmFtaWNzIChwZXIgY2hvcmQgZXZlbnQpIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmNvbnN0IGhhcmRDID0gcmFuZC5wb3coMikuc2VnbWVudCgxKQpjb25zdCB2ZWxDICA9IGhhcmRDLnJhbmdlKDAuMTIsIDEuMCkKY29uc3Qgc2FtcEMgPSBpcmFuZCg4KS5zZWdtZW50KDEpCgovLyAtLS0gY2hvcmQgc291bmQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmNvbnN0IGNob3JkUGFkID0gc3RhY2soCiAgY2hvcmROb3Rlcy5zKCJ4eWxvcGhvbmVfaGFyZF9mZiIpLm4oc2FtcEMpLmdhaW4odmVsQykubWFzayhoYXJkQy5ndGUoMC44NikpLAogIGNob3JkTm90ZXMucygieHlsb3Bob25lX2hhcmRfcHAiKS5uKHNhbXBDKS5nYWluKHZlbEMpLm1hc2soaGFyZEMuZ3RlKDAuNzApLmFuZChoYXJkQy5sdCgwLjg2KSkpLAogIGNob3JkTm90ZXMucygieHlsb3Bob25lX21lZGl1bV9mZiIpLm4oc2FtcEMpLmdhaW4odmVsQykubWFzayhoYXJkQy5ndGUoMC41MCkuYW5kKGhhcmRDLmx0KDAuNzApKSksCiAgY2hvcmROb3Rlcy5zKCJ4eWxvcGhvbmVfbWVkaXVtX3BwIikubihzYW1wQykuZ2Fpbih2ZWxDKS5tYXNrKGhhcmRDLmd0ZSgwLjMwKS5hbmQoaGFyZEMubHQoMC41MCkpKSwKICBjaG9yZE5vdGVzLnMoInh5bG9waG9uZV9zb2Z0X2ZmIikubihzYW1wQykuZ2Fpbih2ZWxDKS5tYXNrKGhhcmRDLmx0KDAuMzApKSwKKQogIC5nYWluKENIT1JEUykKICAucGFuKHJhbmQucmFuZ2UoLTAuNiwgMC42KSkKICAuZm0oIjwxMjggMSAyMDQ4IDggNjQ%2BIi53aXRoVmFsdWUodiA9PiB2ICogMC41KS5sb2coKSkKICAucm9vbSgwLjg1KQogIC5zaXplKDMuOTUpCiAgLmRlbGF5KDAuODIpCiAgLmRlbGF5c3luYygiPDEgMiAzIDU%2BIi5kaXYoOCkpCiAgLmRlbGF5ZmVlZGJhY2soIjwuNTUgLjUgLjc1IDE%2BIikKCi8vIC0tLSBhcnAgKHJlYWw6IGl0ZXJhdGVzIGNob3JkIG5vdGVzKSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpjb25zdCBhcnBOb3RlcyA9CiAgY2hvcmRzCiAgICAubm90ZSgpCiAgICAuaXRlcigxKQogICAgLnN0cnVjdChjaG9yZHMpICAgICAvLyByZXNldHMgb24gY2hvcmQgY2hhbmdlCiAgICAuZmFzdCg4KSAgICAgICAgICAgIC8vIDh0aC1ub3RlIG9zdGluYXRvCgpjb25zdCBoYXJkQSA9IHJhbmQucG93KDIpLnNlZ21lbnQoMS84KQpjb25zdCB2ZWxBICA9IGhhcmRBLnJhbmdlKDAuMDIsIDAuMzApCmNvbnN0IHNhbXBBID0gaXJhbmQoOCkuc2VnbWVudCgxLzgpCgpjb25zdCBhcnAgPSBzdGFjaygKICBhcnBOb3Rlcy5zKCJ4eWxvcGhvbmVfbWVkaXVtX3BwIikubihzYW1wQSkuZ2Fpbih2ZWxBKS5tYXNrKGhhcmRBLmd0ZSgwLjQwKS5hbmQoaGFyZEEubHQoMC43NSkpKSwKICBhcnBOb3Rlcy5zKCJ4eWxvcGhvbmVfc29mdF9mZiIpLm4oc2FtcEEpLmdhaW4odmVsQSkubWFzayhoYXJkQS5sdCgwLjQwKSksCikKICAuZ2FpbihBUlApCiAgLnBhbihyYW5kLnJhbmdlKC0wLjI1LCAwLjI1KSkKICAucm9vbSgwLjg1KQogIC5zaXplKC45KQogIC5kZWxheSgwLjgyKQogIC5kZWxheXN5bmMoIjwuNSAxIDIgND4iLmRpdigxNikpCiAgLmRlbGF5ZmVlZGJhY2soIjwuNDUgLjM1IC4yNT4iKQoKLy8gLS0tIExvZ2ljIEhlbHBlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpjb25zdCBzd2luZyA9IChwKSA9PiBwLmxhdGUoMC4wNSkub2ZmKDEvNiwgeCA9PiB4LmdhaW4oMC40KSkKY29uc3QgZ2hvc3QgPSAocCkgPT4gcC5nYWluKHJhbmQucmFuZ2UoMC4xLCAwLjMpKS5kZWxheShyYW5kLnJhbmdlKDAsIDAuMDIpKQoKLy8gLS0tIFBhdHRlcm5zIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgovLyAxLiBCYXNzIERydW0KY29uc3Qga2ljayA9IHMoImJkOjQiKQogIC5zdHJ1Y3QoInQoMyw4KSA8dCBmPiEzIikKICAuZ2FpbigwLjYpCiAgLmxwZig0MDApCgovLyAyLiBTbmFyZQpjb25zdCBzbmFyZSA9IHN0YWNrKAogIHMoInNkOjIiKS5zdHJ1Y3QoImYgdCBmIHQiKS5nYWluKDAuOCksCiAgcygic2Q6NSIpLnN0cnVjdCgifiB0PyB%2BIDx0PyBmPiIpLmdhaW4ocmFuZC5yYW5nZSgwLjIsIDAuNSkpLmRlbGF5KDAuMDEpCikKCi8vIDMuIEhhdHMvUmlkZQpjb25zdCBoYXRzID0gcygiPGhoKjQgW2hoIGhoP10qMiBbaGgqM10vMS41IGhoKjI%2BIikKICAubihpcmFuZCg0KSkKICAuZ2Fpbih2ZWxvY2l0eSgiPDAuOCAwLjUgMC43IDAuND4iKS5yYW5nZSgwLjQsIDAuOSkpCiAgLnBhbihyYW5kLnJhbmdlKDAuMiwgMC40KSkKCi8vIC0tLSBJbnRlZ3JhdGlvbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpjb25zdCBiZWF0ID0gc3RhY2soCiAga2ljaywKICBzbmFyZSwKICBoYXRzCikKICAuZ2FpbihEUlVNUykKICAuanV4KHJldikKICAuZGVsYXkoMC4wMikKICAucm9vbSgwLjIpCiAgLnNpemUoMC4yKQoKLy8gLS0tIG1peCAoYm9keSBleHByZXNzaW9uIGF0IGVuZCkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmNvbnN0IG1peCA9IHN0YWNrKGJlYXQsIGNob3JkUGFkLCBhcnApLmdhaW4oTUFTVEVSKQoKLy8gYXVkaW8gb3V0cHV0IChsYXN0IGV4cHJlc3Npb24pCm1peAoKLy8gb3B0aW9uYWwgdmlzdWFsIChzZXBhcmF0ZSBleHByZXNzaW9uKQptaXguX3Njb3BlKCkK