This is cool because a lot of the current tools are a bit old and I feel a bit like they suffer from NIH (not invented here) syndrome, where what is actually needed is for things to just be in javascript.
This wasn’t possible as much when the last gen of tools came out (sonic pi etc) but I think the time is right.
The next iteration that would be cool is a true two-way interface between the visualizations and the code. Right now the slider is a really awesome element, for example. I think Bret Victor would be proud.
Strudel is a JavaScript port of TidalCycles (Haskell). While TC uses SuperCollider for the synthesis, Strudel uses superdough which seems to be a custom implementation. I'm currently learning SuperCollider sclang and waiting for a version upgrade to have a reason to submit it here - usually some of the discussion is quite insightful. Anyway sclang is the PHP of music - just uglier and less consistent. But it's also powerful and and quite fun.
I don't know what half this stuff does but it was still so much fun and this is probably one of my favorite projects ever. What made it most fun for me is that the reference docs are in the page so it's really easy to pick something at random and just see what it does.
There are plenty of instruments in there. I did a quick and dirty encoding of the first bar of “City of Star” with the piano when I first discovered it.
note("G2@2 A#2 D@2 G@2 ~ G F@2 D@1.5")
.sound("piano")
Oh and there is flok[1] which combines the strudel repl with visuals from hydra. Also there are sclang and other algorave environments available. Everything is synced (with crdts i guess) so it’s live collaborative. Which is nice to remotely jam with friends
This being text based makes it really easy to have AI generate the music. Now waiting for Strudel agent that will transcribe music into strudel notation.
Strudel did something many other approaches to live coding have failed to do imho. No hosting needed. Just open the web based REPL and go. Great entry to live coding, but you quickly run into limitations.
Here is a piece inspired by Dawn of Midi and my attempt at taking a piano synth and trying to make it sound like a lof of different things.
Uncaught (in promise) ReferenceError: AudioContext is not defined
ln https://strudel.cc/_astro/spectrum.Bf7jMx6O.js:1
W https://strudel.cc/_astro/spectrum.Bf7jMx6O.js:1
un https://strudel.cc/_astro/spectrum.Bf7jMx6O.js:1
c https://strudel.cc/_astro/spectrum.Bf7jMx6O.js:1
What would I need to change in my security settings for this?
27 comments
[ 3.2 ms ] story [ 48.6 ms ] threadhttps://www.youtube.com/watch?v=HkgV_-nJOuE
https://www.youtube.com/watch?v=HkgV_-nJOuE
This wasn’t possible as much when the last gen of tools came out (sonic pi etc) but I think the time is right.
The next iteration that would be cool is a true two-way interface between the visualizations and the code. Right now the slider is a really awesome element, for example. I think Bret Victor would be proud.
$: arrange( [4, "<sh09_bd>(4,8)"], [4, "<sh09_bd>(4,8)"], [1, "<sh09_bd mfb512_sd>(6,6)"] ).s().fast(2).layer(x=>x.add("0,2")).gain(".4!2 .5").phaser(2).phasercenter("<4000 800 4000 4000>")
$: s("gm_tinkle_bell").distort("<1 2 1 2:.5>").crush("<8 8 8 6 6 8 8>").chop(4)
$: arrange( [2, "<c4 e4 g4>(3,8)"], [1, "<f4 a4 c5>(3,8)"], [1, "<c4 e4 g4>(3,8)"] ).note().chop(4).fast(4).distort("<3:.5>").phaser(4).phasercenter("<800>").fm(4).fmdecay("<.05 .05 .1 .2>").fmsustain(.4)._scope()
I don't know what half this stuff does but it was still so much fun and this is probably one of my favorite projects ever. What made it most fun for me is that the reference docs are in the page so it's really easy to pick something at random and just see what it does.
note("G2@2 A#2 D@2 G@2 ~ G F@2 D@1.5") .sound("piano")
[1] https://flok.cc
All examples I've heard from Strudel so far are pretty boring (constant beat/chord machine music).
Are there examples in other styles?
Tide Cycles doesn't work on Fedora, so I might use this instead. Anyway to get it running as a node js script so I use it locally?
For some music ed stuff I work on, I actually have s7 Scheme in WASM controlling csound in WASM, both were surprisingly easy to get going!
My only criticism is it makes music feel like CSS. In some ways it helps with theory, yes, but the DX is more like Tailwind.
i remember seing a .appimage hosted on github in the releases, but they moved to a new host now
oh and if you don't know what inspired the name of the software ; a strudel is really yummy: https://en.wikipedia.org/wiki/Strudel
It will explain the process DJDave uses to create music under strudel
It's already really easy for AI to generate music without using text as an intermediate format.
Here is a piece inspired by Dawn of Midi and my attempt at taking a piano synth and trying to make it sound like a lof of different things.
Copy, paste, modify.
const bpm = 138; setcps(bpm/60/4);
// Pattern 1: lower melodic pulse
const bass_pulse = note("<d2 f2 a2 g2>") .s("piano") .slow(4) .gain(rand.range(0.45, 0.65)) .attack(0.005) .decay(0.8) .sustain(1.2) .release(1.2) .lpf(800) .room(0.3) .delay(0.15) .delaytime(0.375) .delayfeedback(0.25) .pan(0.5);
// Pattern 1.5 (?): layered base
const bass_pulse_2 = note("<d2 f2 a2 g2>") .s("piano") .slow(4) .gain(rand.range(0.45, 0.65)) .add(note(12)) .attack(0.005) .decay(0.8) .sustain(1.2) .release(1.2) .lpf(800) .room(0.3) .delay(0.15) .delaytime(0.375) .delayfeedback(0.25) .pan(0.5);
// Pattern 2: Mid-range polyrhythm
const mid_pattern = note("<a3 c4 d4 f4 a3>") .s("piano") .struct("x(5,8)") .gain(rand.range(0.25, 0.45)) .attack(0.008) .decay(0.4) .sustain(0.05) .release(0.6) .lpf(perlin.range(1200, 2200).slow(8)) .room(0.5) .pan(rand.range(0.3, 0.7));
// Pattern 3: repetitive pulse
const high_pulse = note("d5 [~ d5] d5 ~") .s("piano") .fast(2) .gain(rand.range(0.18, 0.35)) .attack(0.01) .decay(0.3) .sustain(0) .release(0.4) .lpf(2800) .room(0.6) .delay(0.25) .delaytime(0.1875) .delayfeedback(0.3) .pan(0.7);
// Pattern 4: Sparse accent notes (3 over 4 polyrhythm)
const accents = note("a4 ~ f4") .s("piano") .slow(2) .gain(rand.range(0.35, 0.55)) .attack(0.5) .decay(0.6) .sustain(0.9) .release(0.9) .lpf(1800) .room(0.45) .pan(0.2) .sometimes(x => x.delay(0.3).delayfeedback(0.4));
// Pattern 5: Extended mid-range polyrhythm (13 over 16 - cello thingie)
const mid_long = note("<a3 c4 d4 f4 a3 c4 e4 d4 f4 g3 a3 c4 d4>") .s("piano") .struct("x(13,16)") .gain(rand.range(0.32, 0.48)) .attack(0.06) .decay(0.9) .sustain(0.25) .release(1.1) .lpf(perlin.range(800, 1400).slow(12)) .lpq(4) .room(0.55) .delay(0.18) .delaytime(0.25) .delayfeedback(0.3) .pan(rand.range(0.35, 0.65));
const high_long = note("<d5 a4 f5 d5 c5 a4 g4>") .s("piano") .struct("x(7,8)") .gain(rand.range(0.28, 0.42)) .attack(0.05) .decay(0.8) .sustain(0.3) .release(1.0) .lpf(sine.range(1000, 1600).slow(8)) .lpq(3.5) .room(0.6) .delay(0.22) .delaytime(0.1875) .delayfeedback(0.35) .pan(0.7);
stack( bass_pulse, bass_pulse_2, mid_long, high_long, mid_pattern, high_pulse, accents );
https://strudel.cc/?mTeJt_ICoPrw
https://www.youtube.com/watch?v=QrMk5HTVwJQ
quick question, where do strudel load those sounds? snd/bass/build_0.mp3 (line 11) ? are those built in samples?