The Escalating Hypno Curse of the Unmarked Girl Part 4
By starpause on January 25, 2026 10:55 pm
This week my goal was to figure out Strudel sample loading and it worked. I spent a ton of time messing with phasing and getting the hpf to happen only every 8 cycles which was a mess. I was able to get the saw sweep to last multiple cycles but not get it to do it only every 8 cycles so I settled with just a 1 cycle sweep. Another gotcha was that being event driven, the hpf value was being calculated at the start of sample playback but not sweeping as the sample played, so I had to slice the sample for playback and each slice got it's own hpf value.
https://strudel.cc/#CnNldGNwbSgxNjAvNCkKc2FtcGxlcygnZ2l0aHViOnN0YXJwYXVzZS90ZS1lcC1wYWtzLTQtc3RydWRlbC9tYWluL2VwLTQwLXJpZGRpbS1zb3VuZHMnKQoKLy8gV2F0Y2hlcnMKJDogbm90ZSgiQSBCIEMgRCIpLnNsb3coNCkucygic2luZSIpLmdhaW4oMCkubHBmKDQwMCkKJDogbm90ZSgiMSAyIDMgNCA1IDYgNyA4IDkgMTAgMTEgMTIgMTMgMTQgMTUgMTYiKS5zbG93KDgpLnMoInNhdyIpLmdhaW4oMCkubHBmKDIwMCkKCi8vIERlZmluZSB0aGUgc3dlZXAgdG8gYmUgZXhhY3RseSA4IGN5Y2xlcyBsb25nCmNvbnN0IGhwZlN3ZWVwID0gY2F0KAogIDAsIDAsIDAsIDAsIDAsIDAsIDAsIC8vIEN5Y2xlcyAxIHRocm91Z2ggNwogIHNhdy5yYW5nZSg1MCwgY2hvb3NlKDYwMCwgMzAwMCwgNTAwMCwgNzAwMCwgOTAwMCwgMTIwMDApKSAvLyBDeWNsZSA4Cikuc2xvdygxKTsKCiQ6IHMoImJkIC0gLSBiZCAtIC0gYmQgLSBiZCAtIC0gYmQgLSAtIGJkIC0iKQogIC5uKGNob29zZUN5Y2xlcyguLi5BcnJheS5mcm9tKHtsZW5ndGg6IDU1fSwgKF8sIGkpID0%2BIGkpKS5zbG93KDgpKSAKICAuZ2FpbigiMC44IikKICAuaHBmKGhwZlN3ZWVwKQoKJDogcygiLSAtIC0gLSAtIC0gLSAtIGNwIC0gLSAtIC0gLSAtIC0iKQogIC5uKGNob29zZUN5Y2xlcyguLi5BcnJheS5mcm9tKHtsZW5ndGg6IDZ9LCAoXywgaSkgPT4gaSkpLnNsb3coOCkpIAogIC5nYWluKCIwLjgiKQogIC5ocGYoaHBmU3dlZXApCgokOiBzKCJza2FuayAtIC0gLSAtIC0gLSAtIC0gLSAtIC0gLSAtIC0gLSIpCiAgLm4oY2hvb3NlQ3ljbGVzKC4uLkFycmF5LmZyb20oe2xlbmd0aDogMjl9LCAoXywgaSkgPT4gaSkpLnNsb3coOCkpIAogIC5nYWluKCIwLjciKQogIC5ocGYoaHBmU3dlZXApCgovLyBTVEFCTEUgU0tJVFRFUlkgSEktSEFUUwokOiBzKCJoaCoxNiIpIAogIC5uKGlyYW5kKDMzKSkgLy8gQ3ljbGUgdGhyb3VnaCB0aGUgMzMgaGF0cyByYW5kb21seQogIC5nYWluKCI8MC4yLzMgMC40LzMgMC4zLzMgMC41LzMgMC4xLzMgMC40LzMgMC4yLzMgMC42LzM%2BIikgLy8gTWFudWFsbHkgZGVmaW5lZCBqaXR0ZXJ5IHZlbG9jaXRpZXMKICAuaHBmKGhwZlN3ZWVwKQoKJDogcygiZngiKQogIC5uKGNob29zZUN5Y2xlcyguLi5BcnJheS5mcm9tKHtsZW5ndGg6IDU1fSwgKF8sIGkpID0%2BIGkpKS5zbG93KDgpKQogIC5zbGljZSgxNiwgIjAgMSAyIDMgNCA1IDYgNyA4IDkgMTAgMTEgMTIgMTMgMTQgMTUiKQogIC8vIFVzaW5nIC5zdHJ1Y3QgdG8gZm9yY2UgdGhlIDE2IHRyaWdnZXJzIHRvIGxvb2sgYXQgdGhlIEhQRiB2YWx1ZQogIC5zdHJ1Y3QoIjE2KjgiKSAKICAuZ2FpbigiPDAgMCAwIDAgMCAwIDAgMC41PiIpIAogIC5sZWdhdG8oMC45KQogIC5hdHRhY2soMC4wMSkKICAucmVsZWFzZSgwLjAyKQogIC5ocGYoaHBmU3dlZXAp
setcpm(160/4)
samples('github:starpause/te-ep-paks-4-strudel/main/ep-40-riddim-sounds')
// Watchers
$: note("A B C D").slow(4).s("sine").gain(0).lpf(400)
$: note("1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16").slow(8).s("saw").gain(0).lpf(200)
// Define the sweep to be exactly 8 cycles long
const hpfSweep = cat(
0, 0, 0, 0, 0, 0, 0, // Cycles 1 through 7
saw.range(50, choose(600, 3000, 5000, 7000, 9000, 12000)) // Cycle 8
).slow(1);
$: s("bd - - bd - - bd - bd - - bd - - bd -")
.n(chooseCycles(...Array.from({length: 55}, (_, i) => i)).slow(8))
.gain("0.8")
.hpf(hpfSweep)
$: s("- - - - - - - - cp - - - - - - -")
.n(chooseCycles(...Array.from({length: 6}, (_, i) => i)).slow(8))
.gain("0.8")
.hpf(hpfSweep)
$: s("skank - - - - - - - - - - - - - - -")
.n(chooseCycles(...Array.from({length: 29}, (_, i) => i)).slow(8))
.gain("0.7")
.hpf(hpfSweep)
// STABLE SKITTERY HI-HATS
$: s("hh*16")
.n(irand(33)) // Cycle through the 33 hats randomly
.gain("<0.2/3 0.4/3 0.3/3 0.5/3 0.1/3 0.4/3 0.2/3 0.6/3>") // Manually defined jittery velocities
.hpf(hpfSweep)
$: s("fx")
.n(chooseCycles(...Array.from({length: 55}, (_, i) => i)).slow(8))
.slice(16, "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15")
// Using .struct to force the 16 triggers to look at the HPF value
.struct("16*8")
.gain("<0 0 0 0 0 0 0 0.5>")
.legato(0.9)
.attack(0.01)
.release(0.02)
.hpf(hpfSweep)Audio works licensed by author under:
CC0 Creative Commons Zero (Public Domain)
