From c05bbf34220b3ae2c1417237a72933d86259cf59 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 3 Jun 2024 23:53:08 +0200 Subject: [PATCH 1/4] don't clear hydra in minirepl for now --- website/src/docs/MiniRepl.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/docs/MiniRepl.jsx b/website/src/docs/MiniRepl.jsx index 56548471..0884786e 100644 --- a/website/src/docs/MiniRepl.jsx +++ b/website/src/docs/MiniRepl.jsx @@ -81,7 +81,7 @@ export function MiniRepl({ }, onToggle: (playing) => { if (!playing) { - clearHydra(); + // clearHydra(); // TBD: doesn't work with multiple MiniRepl's on a page } }, beforeStart: () => audioReady, From 771eb31d3f4829ed5457d4f1ac4ab326c2816054 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 4 Jun 2024 00:05:51 +0200 Subject: [PATCH 2/4] use labels instead of stacks --- packages/core/controls.mjs | 6 +- website/src/pages/learn/hydra.mdx | 16 ++-- website/src/pages/learn/input-output.mdx | 12 +-- website/src/pages/learn/samples.mdx | 16 ++-- website/src/pages/learn/strudel-vs-tidal.mdx | 27 ++----- website/src/pages/learn/tonal.mdx | 14 ---- website/src/pages/workshop/first-effects.mdx | 79 ++++++++----------- website/src/pages/workshop/first-notes.mdx | 26 ++++++ .../src/pages/workshop/pattern-effects.mdx | 36 ++++----- website/src/pages/workshop/recap.mdx | 1 + 10 files changed, 103 insertions(+), 130 deletions(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 94f46f44..5aa4b46b 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -1163,10 +1163,8 @@ export const { octave } = registerControl('octave'); * @name orbit * @param {number | Pattern} number * @example - * stack( - * s("hh*6").delay(.5).delaytime(.25).orbit(1), - * s("~ sd ~ sd").delay(.5).delaytime(.125).orbit(2) - * ) + * $: s("hh*6").delay(.5).delaytime(.25).orbit(1) + * $: s("~ sd ~ sd").delay(.5).delaytime(.125).orbit(2) */ export const { orbit } = registerControl('orbit'); // TODO: what is this? not found in tidal doc Answer: gain is limited to maximum of 2. This allows you to go over that diff --git a/website/src/pages/learn/hydra.mdx b/website/src/pages/learn/hydra.mdx index d7a692dd..2bf5fab4 100644 --- a/website/src/pages/learn/hydra.mdx +++ b/website/src/pages/learn/hydra.mdx @@ -90,11 +90,13 @@ src(s0).kaleid(H("<4 5 6>")) .modulateScale(osc(2,-0.25,1)) .out() // -stack( - s("bd*4,[hh:0:<.5 1>]*8,~ rim").bank("RolandTR909").speed(.9), - note("[>>]*3").s("sawtooth") - .room(.75).sometimes(add(note(12))).clip(.3) - .lpa(.05).lpenv(-4).lpf(2000).lpq(8).ftype('24db') -).fft(4) - .scope({pos:0,smear:.95})`} + +$: s("bd*4,[hh:0:<.5 1>]*8,~ rim").bank("RolandTR909").speed(.9) + +$: note("[>>]\*3").s("sawtooth") + +.room(.75).sometimes(add(note(12))).clip(.3) +.lpa(.05).lpenv(-4).lpf(2000).lpq(8).ftype('24db') + +all(x=>x.fft(4).scope({pos:0,smear:.95}))`} /> diff --git a/website/src/pages/learn/input-output.mdx b/website/src/pages/learn/input-output.mdx index de44b4f9..0151e6eb 100644 --- a/website/src/pages/learn/input-output.mdx +++ b/website/src/pages/learn/input-output.mdx @@ -20,11 +20,7 @@ Strudel also supports midi via [webmidi](https://npmjs.com/package/webmidi). Either connect a midi device or use the IAC Driver (Mac) or Midi Through Port (Linux) for internal midi messages. If no outputName is given, it uses the first midi output it finds. -".voicings('lefthand'), "").note() - .midi()`} -/> +").voicing().midi()`} /> In the console, you will see a log of the available MIDI devices as soon as you run the code, e.g. `Midi connected! Using "Midi Through Port-0".` @@ -45,10 +41,8 @@ But you can also control cc messages separately like this: # SuperDirt API diff --git a/website/src/pages/learn/samples.mdx b/website/src/pages/learn/samples.mdx index c2c166b3..44259617 100644 --- a/website/src/pages/learn/samples.mdx +++ b/website/src/pages/learn/samples.mdx @@ -268,11 +268,10 @@ With it, you can enter any sample name(s) to query from [freesound.org](https:// You can also generate artificial voice samples with any text, in multiple languages. @@ -282,10 +281,9 @@ Note that the language code and the gender parameters are optional and default t client:idle tune={`samples('shabda/speech:the_drum,forever') samples('shabda/speech/fr-FR/m:magnifique') -stack( - s("the_drum*2").chop(16).speed(rand.range(0.85,1.1)), - s("forever magnifique").slow(4).late(0.125) -)`} + +$: s("the_drum*2").chop(16).speed(rand.range(0.85,1.1)) +$: s("forever magnifique").slow(4).late(0.125)`} /> # Sampler Effects diff --git a/website/src/pages/learn/strudel-vs-tidal.mdx b/website/src/pages/learn/strudel-vs-tidal.mdx index 0c7213c7..40ea188f 100644 --- a/website/src/pages/learn/strudel-vs-tidal.mdx +++ b/website/src/pages/learn/strudel-vs-tidal.mdx @@ -112,29 +112,14 @@ Also, samples are always loaded from a URL rather than from the disk, although [ ## Evaluation The Strudel REPL does not support [block based evaluation](https://github.com/tidalcycles/strudel/issues/34) yet. -You can use the following "workaround" to create multiple patterns that can be turned on and off: +You can use labeled statements and `_` to mute: -``` -let a = note("c a f e") + ## Tempo diff --git a/website/src/pages/learn/tonal.mdx b/website/src/pages/learn/tonal.mdx index a5a02508..202b8481 100644 --- a/website/src/pages/learn/tonal.mdx +++ b/website/src/pages/learn/tonal.mdx @@ -55,20 +55,6 @@ Transposes notes inside the scale by the number of steps: .note()`} /> -### voicings(range?) - -Turns chord symbols into voicings, using the smoothest voice leading possible: - -".voicings('lefthand'), - "" -).note()`} -/> - -Note: This function might be removed, as `voicing` (without s) is a newer implementation. - ### rootNotes(octave = 2) Turns chord symbols into root notes of chords in given octave. diff --git a/website/src/pages/workshop/first-effects.mdx b/website/src/pages/workshop/first-effects.mdx index 220a7cbc..99e72a13 100644 --- a/website/src/pages/workshop/first-effects.mdx +++ b/website/src/pages/workshop/first-effects.mdx @@ -60,11 +60,10 @@ We will learn how to automate with waves later... @@ -76,31 +75,21 @@ Rhythm is all about dynamics! -**stacks within stacks** - Let's combine all of the above into a little tune: ") -.sound("sawtooth").lpf("200 1000 200 1000"), -note("<[c3,g3,e4] [bb2,f3,d4] [a2,f3,c4] [bb2,g3,eb4]>") -.sound("sawtooth").vowel("") -)`} + tune={`$: sound("hh*8").gain("[.25 1]*4") + +$: sound("bd*4,[~ sd:1]*2") + +$: note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>") +.sound("sawtooth").lpf("200 1000 200 1000") + +$: note("<[c3,g3,e4] [bb2,f3,d4] [a2,f3,c4] [bb2,g3,eb4]>") +.sound("sawtooth").vowel("")`} /> - - -Try to identify the individual parts of the stacks, pay attention to where the commas are. -The 3 parts (drums, bassline, chords) are exactly as earlier, just stacked together, separated by comma. - - - **shape the sound with an adsr envelope** ~]]*2") -.sound("gm_electric_guitar_muted"), -sound("bd rim").bank("RolandTR707") -).delay(".5")`} + tune={`$: note("[~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]]*2") + .sound("gm_electric_guitar_muted").delay(.5) + +$: sound("bd rim").bank("RolandTR707").delay(".5")`} /> @@ -199,31 +187,32 @@ Add a delay too! ~]]*2") -.sound("gm_electric_guitar_muted").delay(.5), -sound("bd rim").bank("RolandTR707").delay(.5), -n("<4 [3@3 4] [<2 0> ~@16] ~>") + tune={`$: note("[~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]]*2") +.sound("gm_electric_guitar_muted").delay(.5) + +$: sound("bd rim").bank("RolandTR707").delay(.5) + +$: n("<4 [3@3 4] [<2 0> ~@16] ~>") .scale("D4:minor").sound("gm_accordion:2") -.room(2).gain(.5) -)`} +.room(2).gain(.5)`} /> Let's add a bass to make this complete: ~]]*2") -.sound("gm_electric_guitar_muted").delay(.5), -sound("bd rim").bank("RolandTR707").delay(.5), -n("<4 [3@3 4] [<2 0> ~@16] ~>") + tune={`$: note("[~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]]*2") +.sound("gm_electric_guitar_muted").delay(.5) + +$: sound("bd rim").bank("RolandTR707").delay(.5) + +$: n("<4 [3@3 4] [<2 0> ~@16] ~>") .scale("D4:minor").sound("gm_accordion:2") -.room(2).gain(.4), -n("[0 [~ 0] 4 [3 2] [0 ~] [0 ~] <0 2> ~]/2") +.room(2).gain(.4) + +$: n("[0 [~ 0] 4 [3 2] [0 ~] [0 ~] <0 2> ~]/2") .scale("D2:minor") -.sound("sawtooth,triangle").lpf(800) -)`} +.sound("sawtooth,triangle").lpf(800)`} /> diff --git a/website/src/pages/workshop/first-notes.mdx b/website/src/pages/workshop/first-notes.mdx index 71a21764..f0ea5569 100644 --- a/website/src/pages/workshop/first-notes.mdx +++ b/website/src/pages/workshop/first-notes.mdx @@ -319,6 +319,7 @@ New functions: | note | set pitch as number or letter | | | scale | interpret `n` as scale degree | | | stack | play patterns in parallel (read on) | | +| $: | play patterns in parallel | | ## Examples @@ -377,4 +378,29 @@ It's called `stack` 😙 )`} /> +Since Strudel 1.1.0, there is another, simpler way to write multiple patterns in parallel. Just write `$:` before every part: + +") + .sound("gm_synth_bass_1").lpf(800) + +$: n(\`< + [~ 0] 2 [0 2] [~ 2] + [~ 0] 1 [0 1] [~ 1] + [~ 0] 3 [0 3] [~ 3] + [~ 0] 2 [0 2] [~ 2] + >*4\`).scale("C4:minor") + .sound("gm_synth_strings_1") + +$: sound("bd*4, [~ ]*2, [~ hh]*4") +.bank("RolandTR909")`} +/> + + + +Try changing `$` to `_$` to mute a part! + + + This is starting to sound like actual music! We have sounds, we have notes, now the last piece of the puzzle is missing: [effects](/workshop/first-effects) diff --git a/website/src/pages/workshop/pattern-effects.mdx b/website/src/pages/workshop/pattern-effects.mdx index 06ebd6b0..119a6123 100644 --- a/website/src/pages/workshop/pattern-effects.mdx +++ b/website/src/pages/workshop/pattern-effects.mdx @@ -25,20 +25,16 @@ This is the same as: Let's visualize what happens here: @@ -56,11 +52,9 @@ This is like doing @@ -110,17 +104,17 @@ We can add as often as we like: [~ <4 1>]".add("<0 [0,2,4]>")) + tune={`$: n("0 [2 4] <3 5> [~ <4 1>]".add("<0 [0,2,4]>")) .scale("C5:minor") .sound("gm_xylophone") - .room(.4).delay(.125), - note("c2 [eb3,g3]".add("<0 <1 -1>>")) + .room(.4).delay(.125) + +$: note("c2 [eb3,g3]".add("<0 <1 -1>>")) .adsr("[.1 0]:.2:[1 0]") .sound("gm_acoustic_bass") - .room(.5), - n("0 1 [2 3] 2").sound("jazz").jux(rev) -)`} + .room(.5) + +$: n("0 1 [2 3] 2").sound("jazz").jux(rev)`} /> **ply** @@ -165,7 +159,7 @@ off is also useful for modifying other sounds, and can even be nested: client:visible tune={`s("bd sd [rim bd] sd,[~ hh]*4").bank("CasioRZ1") .off(2/16, x=>x.speed(1.5).gain(.25) - .off(3/16, y=>y.vowel("*8")))`} + .off(3/16, y=>y.vowel("*8")))`} /> | name | description | example | diff --git a/website/src/pages/workshop/recap.mdx b/website/src/pages/workshop/recap.mdx index fda7a171..a800de53 100644 --- a/website/src/pages/workshop/recap.mdx +++ b/website/src/pages/workshop/recap.mdx @@ -40,6 +40,7 @@ This page is just a listing of all functions covered in the workshop! | note | set pitch as number or letter | | | n + scale | set note in scale | | | stack | play patterns in parallel | | +| $: | play patterns in parallel | | ## Audio Effects From 666c695c63a00d4b0f4a1c7bc683a7b451f645ae Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 4 Jun 2024 00:10:46 +0200 Subject: [PATCH 3/4] don't use labeled statements in example for now --- packages/core/controls.mjs | 6 ++++-- test/runtime.mjs | 1 + website/src/pages/workshop/pattern-effects.mdx | 2 -- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 5aa4b46b..94f46f44 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -1163,8 +1163,10 @@ export const { octave } = registerControl('octave'); * @name orbit * @param {number | Pattern} number * @example - * $: s("hh*6").delay(.5).delaytime(.25).orbit(1) - * $: s("~ sd ~ sd").delay(.5).delaytime(.125).orbit(2) + * stack( + * s("hh*6").delay(.5).delaytime(.25).orbit(1), + * s("~ sd ~ sd").delay(.5).delaytime(.125).orbit(2) + * ) */ export const { orbit } = registerControl('orbit'); // TODO: what is this? not found in tidal doc Answer: gain is limited to maximum of 2. This allows you to go over that diff --git a/test/runtime.mjs b/test/runtime.mjs index ca92b196..19b71627 100644 --- a/test/runtime.mjs +++ b/test/runtime.mjs @@ -191,6 +191,7 @@ evalScope( }, ); +// TBD: use transpiler to support labeled statements export const queryCode = async (code, cycles = 1) => { const { pattern } = await evaluate(code); const haps = pattern.sortHapsByPart().queryArc(0, cycles); diff --git a/website/src/pages/workshop/pattern-effects.mdx b/website/src/pages/workshop/pattern-effects.mdx index 119a6123..c9cb7b46 100644 --- a/website/src/pages/workshop/pattern-effects.mdx +++ b/website/src/pages/workshop/pattern-effects.mdx @@ -108,12 +108,10 @@ We can add as often as we like: .scale("C5:minor") .sound("gm_xylophone") .room(.4).delay(.125) - $: note("c2 [eb3,g3]".add("<0 <1 -1>>")) .adsr("[.1 0]:.2:[1 0]") .sound("gm_acoustic_bass") .room(.5) - $: n("0 1 [2 3] 2").sound("jazz").jux(rev)`} /> From 269d6dde31873fe536431df26a4e5411b0b034b1 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 4 Jun 2024 00:22:49 +0200 Subject: [PATCH 4/4] remove stack from workshop --- website/src/pages/workshop/first-notes.mdx | 32 ++++++---------------- website/src/pages/workshop/recap.mdx | 1 - 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/website/src/pages/workshop/first-notes.mdx b/website/src/pages/workshop/first-notes.mdx index f0ea5569..f3d74ddc 100644 --- a/website/src/pages/workshop/first-notes.mdx +++ b/website/src/pages/workshop/first-notes.mdx @@ -314,12 +314,11 @@ Let's recap what we've learned in this chapter: New functions: -| Name | Description | Example | -| ----- | ----------------------------------- | --------------------------------------------------------------------------------- | -| note | set pitch as number or letter | | -| scale | interpret `n` as scale degree | | -| stack | play patterns in parallel (read on) | | -| $: | play patterns in parallel | | +| Name | Description | Example | +| ----- | ----------------------------- | --------------------------------------------------------------------------------- | +| note | set pitch as number or letter | | +| scale | interpret `n` as scale degree | | +| $: | play patterns in parallel | | ## Examples @@ -357,28 +356,13 @@ New functions: -It's called `stack` 😙 +You can use `$:` 😙 -") - .sound("gm_synth_bass_1").lpf(800), - n(\`< - [~ 0] 2 [0 2] [~ 2] - [~ 0] 1 [0 1] [~ 1] - [~ 0] 3 [0 3] [~ 3] - [~ 0] 2 [0 2] [~ 2] - >*4\`).scale("C4:minor") - .sound("gm_synth_strings_1"), - sound("bd*4, [~ ]*2, [~ hh]*4") - .bank("RolandTR909") -)`} -/> +## Playing multiple patterns -Since Strudel 1.1.0, there is another, simpler way to write multiple patterns in parallel. Just write `$:` before every part: +If you want to play multiple patterns at the same time, make sure to write `$:` before each: | | n + scale | set note in scale | | -| stack | play patterns in parallel | | | $: | play patterns in parallel | | ## Audio Effects