If you think, Trackers are not complicated enough #Strudel

This thing here called Strudel is coding/producing in one box.

This is so weird.

6 Likes

This is actually quite fascinating. I’ve dealt with both Supercollider and TidalCycles years ago, but this is the first time I see a Javascript port.

It’s not complicated as it looks, though. One of TidalCycles’ goal is to be a more accessible livecode environment in comparison to traditional SC. I do notice some syntax differences in this port, though.

Despite the example you provided being complex (and super cool), the basic patterns are super easy to do:

s("bd hh")

Hit Control+Enter to play the code block.

This example will fetch samples bd and hh and play them in sequence ad infinitum (in og TidalCycles there’s a built-in sample library for defaults like bd, hh, sd etc).

You can also stack patterns so they play at the same time:

stack (
s("bd bd bd bd"),
s("~ sd ~ sd")
)

In this example you have a classic “four on the floor”. The tilde (~) means silence. So the snare hits on 2nd and 4th beats of the cycle.

Let’s stack some hi-hats and this time change their speed/pitch and also panning:

stack (
s("bd bd bd bd"),
s("~ sd ~ sd"),
s("hh*8").speed("2 1 3 1").pan("0 1")
)

Notice we’re playing the hihats 8 times, changing the speed every step (looping every 4th) and also panning left and right (0 and 1).

Anyways, I highly recommend trying other stuff. It’s super fun and satisfying to use.

5 Likes

Currently digging Strudel (to send data and midi to Renoise).

This is amazing.

I’m left with some questions:

I’ve spent few weeks coding pattrns scripts (which also use some elements from Tidal (e.g. the mini notation)).

For my area of interest (mostly generative things) there are overlaps between Strudel and renoise pattrns scripts.
Pattrns scripts are interesting because of the tight integration with Renoise: automatable/modulable parameters with Instrument macros (!!!), access to built-in Renoise objects.

But Strudel has also strong points: it’s very fluid to work with, and the visual feedbacks and UI element (the punchcard is so useful) are stellar.

Sound-wise, I still prefer the Renoise platform (I’m not that interested in the sound-side of Strudel), but for generative things Strudel is really powerful.

In an ideal world, it would be awesome if Renoise pattrns could be more Strudel-like (without the audio and timing engine, on which Renoise is already stellar).

Are you on Linux? I tried this today on Ubuntu, but I’m getting a high latency, i.e. what I see selected in strudel is quite off to the audio. Must be a Strudel issue, cause triggering midi though this site is instant. → (Web MIDI test page)

I simply used:

$: note("c c f e").midiport("<0>").midi() 

I’m on OSX.
Had some troubles with sync-clock timing (made Renoise “MIDI-clock slave”). Had to push the “smoothing” param in Renoise to at least 96 to avoid too much BPM fluctuations.

I even separated the notes messages from the clock messages into separate MIDI output busses, to mitigate the issue, but it didn’t helped that much (but I kept this principle.).

I also noticed that Strudel is pretty resource-intensive, esp. when using audio. I guess you can’t do miracles with an browser-based engine, relying on bleeding-edge implemented standards (WebAudio and Web Midi).

Here the patch I used (link sharing is not working as expected, see code below).

Please note that I used Midi pipe (OSX freeware to create and manage midi busses), so you may have to change the two `midi_notes_bus` and `midi_clock_bus` values depending on your setup/routing. On Linux, I guess you’ll have to fiddle with JACK config.

Strudel patch used (I let all the WIP/debug/tries commented lines):


setcpm(88/4)
const midi_notes_bus = 'MidiPipe Entrée 1'
const midi_clock_bus = 'MidiPipe Entrée 2'

$:stack(
midicmd("clock*96").midi(midi_clock_bus)
)

$melody: 
note("c2 e3 g4 <b4 b4*2>")
//irand(slider(1,1,24,1))
.struct("x <x*2 x> x x*4")
//.chord("<Cm DM7 Gm#5 Am^7>").mode("above:c3").voicing()
  //.sound("gm_epiano1")
  .scale("<C:major@2 F:mixolydian>/2")
  .when("<0 1>/4", x=>x.scramble(8))
  //.lpf(slider(1000,4000,1))
  //.room(1.5)
  //.delay("<0 .25 .5 1>")
  .midi(midi_notes_bus, {midichannel:1})
  .color('yellow')._punchcard({labels:true, height:150})
//chords.struct("- x - x").voicing()
$melody2:
chord("<Cm@2 F-^7 E-add9>")
  .struct("x ~").slow(2).voicing()
  .scale("<C:major@2 F:mixolydian>/2")
  //.euclid(3,7).slow(2).voicing()
  .midi(midi_notes_bus, {midichannel:2})
  //.s('gm_synth_strings_2').gain(0.3)
  //.attack("<.3 .4 .5>")
  //.release(2.3)
  //.lpf(slider(1049,0,4000,1))
  //.hpf(slider(0,0,4000,1))
  //.orbit(3).room(2.5)
.color('#c0ffee')  
._punchcard({labels:true, height:200})
1 Like

I think I tried everything, didn’t get it in sync. thanks anyway!

You can use Supercollider with Superdirt or (better) Strudeldirt to generate audio. You can also use custom synthdefs with this. And you can still use the Strudel REPL running in the browser to write code. The OSC signal is then routed to supercollider via a server. It’s explained here how to set it up:

You can also expose SynthDef paramters to Strudel with

const modf = createParam('modf')

and use it in Strudel

const modf = createParam('modf')

$: n("1 2 12 8 5 3" ).fast(1).scale("A4:minor").adsr("0:3:1:1").
   sound("myfm").room(0).gain(0.3).modf(choose("10", "50",  "100", "0.1"))
(
SynthDef(\myfm, { arg out , amp = 0.1, freq, modf = 100;

	var snd;
	


	snd = SinOsc.ar(Vibrato.kr(freq,modf, 0.02));

	Out.ar(out, snd!2);
}).add;
)