use labels instead of stacks

This commit is contained in:
Felix Roos 2024-06-04 00:05:51 +02:00
parent c05bbf3422
commit 771eb31d3f
10 changed files with 103 additions and 130 deletions

View file

@ -1163,10 +1163,8 @@ export const { octave } = registerControl('octave');
* @name orbit * @name orbit
* @param {number | Pattern} number * @param {number | Pattern} number
* @example * @example
* stack( * $: s("hh*6").delay(.5).delaytime(.25).orbit(1)
* s("hh*6").delay(.5).delaytime(.25).orbit(1), * $: s("~ sd ~ sd").delay(.5).delaytime(.125).orbit(2)
* s("~ sd ~ sd").delay(.5).delaytime(.125).orbit(2)
* )
*/ */
export const { orbit } = registerControl('orbit'); 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 // TODO: what is this? not found in tidal doc Answer: gain is limited to maximum of 2. This allows you to go over that

View file

@ -90,11 +90,13 @@ src(s0).kaleid(H("<4 5 6>"))
.modulateScale(osc(2,-0.25,1)) .modulateScale(osc(2,-0.25,1))
.out() .out()
// //
stack(
s("bd*4,[hh:0:<.5 1>]*8,~ rim").bank("RolandTR909").speed(.9), $: s("bd*4,[hh:0:<.5 1>]*8,~ rim").bank("RolandTR909").speed(.9)
note("[<g1!3 <bb1 <f1 d1>>>]*3").s("sawtooth")
.room(.75).sometimes(add(note(12))).clip(.3) $: note("[<g1!3 <bb1 <f1 d1>>>]\*3").s("sawtooth")
.lpa(.05).lpenv(-4).lpf(2000).lpq(8).ftype('24db')
).fft(4) .room(.75).sometimes(add(note(12))).clip(.3)
.scope({pos:0,smear:.95})`} .lpa(.05).lpenv(-4).lpf(2000).lpq(8).ftype('24db')
all(x=>x.fft(4).scope({pos:0,smear:.95}))`}
/> />

View file

@ -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. 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. If no outputName is given, it uses the first midi output it finds.
<MiniRepl <MiniRepl client:idle tune={`chord("<C^7 A7 Dm7 G7>").voicing().midi()`} />
client:idle
tune={`stack("<C^7 A7 Dm7 G7>".voicings('lefthand'), "<C3 A2 D3 G2>").note()
.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".` 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:
<MiniRepl <MiniRepl
client:idle client:idle
tune={`stack( tune={`$: note("c a f e").midi()
note("c a f e"), $: ccv(sine.segment(16).slow(4)).ccn(74).midi()`}
ccv(sine.segment(16).slow(4)).ccn(74)
).midi()`}
/> />
# SuperDirt API # SuperDirt API

View file

@ -268,11 +268,10 @@ With it, you can enter any sample name(s) to query from [freesound.org](https://
<MiniRepl <MiniRepl
client:idle client:idle
tune={`samples('shabda:bass:4,hihat:4,rimshot:2') tune={`samples('shabda:bass:4,hihat:4,rimshot:2')
stack(
n("0 1 2 3 0 1 2 3").s('bass'), $: n("0 1 2 3 0 1 2 3").s('bass')
n("0 1*2 2 3*2").s('hihat'), $: n("0 1*2 2 3*2").s('hihat').clip(1)
n("~ 0 ~ 1 ~ 0 0 1").s('rimshot') $: n("~ 0 ~ 1 ~ 0 0 1").s('rimshot')`}
).clip(1)`}
/> />
You can also generate artificial voice samples with any text, in multiple languages. 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 client:idle
tune={`samples('shabda/speech:the_drum,forever') tune={`samples('shabda/speech:the_drum,forever')
samples('shabda/speech/fr-FR/m:magnifique') samples('shabda/speech/fr-FR/m:magnifique')
stack(
s("the_drum*2").chop(16).speed(rand.range(0.85,1.1)), $: s("the_drum*2").chop(16).speed(rand.range(0.85,1.1))
s("forever magnifique").slow(4).late(0.125) $: s("forever magnifique").slow(4).late(0.125)`}
)`}
/> />
# Sampler Effects # Sampler Effects

View file

@ -112,29 +112,14 @@ Also, samples are always loaded from a URL rather than from the disk, although [
## Evaluation ## Evaluation
The Strudel REPL does not support [block based evaluation](https://github.com/tidalcycles/strudel/issues/34) yet. 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:
``` <MiniRepl
let a = note("c a f e") client:visible
tune={`$: n("[0 .. 8]*8/9").scale("C:minor:pentatonic")
let b = s("bd sd") \_$: s("bd\*4").bank('RolandTR909')`}
/>
stack(
a,
// b
)
```
Alternatively, you could write everything as one `stack` and use `.hush()` to silence a pattern:
```
stack(
note("c a f e"),
s("bd sd").hush()
)
```
Note that strudel will always use the last statement in your code as the pattern for querying
## Tempo ## Tempo

View file

@ -55,20 +55,6 @@ Transposes notes inside the scale by the number of steps:
.note()`} .note()`}
/> />
### voicings(range?)
Turns chord symbols into voicings, using the smoothest voice leading possible:
<MiniRepl
client:only="react"
tune={`stack(
"<C^7 A7 Dm7 G7>".voicings('lefthand'),
"<C3 A2 D3 G2>"
).note()`}
/>
Note: This function might be removed, as `voicing` (without s) is a newer implementation.
### rootNotes(octave = 2) ### rootNotes(octave = 2)
Turns chord symbols into root notes of chords in given octave. Turns chord symbols into root notes of chords in given octave.

View file

@ -60,11 +60,10 @@ We will learn how to automate with waves later...
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: sound("hh*16").gain("[.25 1]*4")
sound("hh*16").gain("[.25 1]*4"),
sound("bd*4,[~ sd:1]*2") $: sound("bd*4,[~ sd:1]*2")`}
) `} punchcard
punchcard
/> />
<Box> <Box>
@ -76,31 +75,21 @@ Rhythm is all about dynamics!
</Box> </Box>
**stacks within stacks**
Let's combine all of the above into a little tune: Let's combine all of the above into a little tune:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: sound("hh*8").gain("[.25 1]*4")
stack(
sound("hh*8").gain("[.25 1]*4"), $: sound("bd*4,[~ sd:1]*2")
sound("bd*4,[~ sd:1]*2")
), $: note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>")
note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>") .sound("sawtooth").lpf("200 1000 200 1000")
.sound("sawtooth").lpf("200 1000 200 1000"),
note("<[c3,g3,e4] [bb2,f3,d4] [a2,f3,c4] [bb2,g3,eb4]>") $: note("<[c3,g3,e4] [bb2,f3,d4] [a2,f3,c4] [bb2,g3,eb4]>")
.sound("sawtooth").vowel("<a e i o>") .sound("sawtooth").vowel("<a e i o>")`}
)`}
/> />
<Box>
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.
</Box>
**shape the sound with an adsr envelope** **shape the sound with an adsr envelope**
<MiniRepl <MiniRepl
@ -151,11 +140,10 @@ Can you guess what they do?
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: note("[~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]]*2")
note("[~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]]*2") .sound("gm_electric_guitar_muted").delay(.5)
.sound("gm_electric_guitar_muted"),
sound("bd rim").bank("RolandTR707") $: sound("bd rim").bank("RolandTR707").delay(".5")`}
).delay(".5")`}
/> />
<Box> <Box>
@ -199,31 +187,32 @@ Add a delay too!
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: note("[~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]]*2")
note("[~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]]*2") .sound("gm_electric_guitar_muted").delay(.5)
.sound("gm_electric_guitar_muted").delay(.5),
sound("bd rim").bank("RolandTR707").delay(.5), $: sound("bd rim").bank("RolandTR707").delay(.5)
n("<4 [3@3 4] [<2 0> ~@16] ~>")
$: n("<4 [3@3 4] [<2 0> ~@16] ~>")
.scale("D4:minor").sound("gm_accordion:2") .scale("D4:minor").sound("gm_accordion:2")
.room(2).gain(.5) .room(2).gain(.5)`}
)`}
/> />
Let's add a bass to make this complete: Let's add a bass to make this complete:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: note("[~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]]*2")
note("[~ [<[d3,a3,f4]!2 [d3,bb3,g4]!2> ~]]*2") .sound("gm_electric_guitar_muted").delay(.5)
.sound("gm_electric_guitar_muted").delay(.5),
sound("bd rim").bank("RolandTR707").delay(.5), $: sound("bd rim").bank("RolandTR707").delay(.5)
n("<4 [3@3 4] [<2 0> ~@16] ~>")
$: n("<4 [3@3 4] [<2 0> ~@16] ~>")
.scale("D4:minor").sound("gm_accordion:2") .scale("D4:minor").sound("gm_accordion:2")
.room(2).gain(.4), .room(2).gain(.4)
n("[0 [~ 0] 4 [3 2] [0 ~] [0 ~] <0 2> ~]/2")
$: n("[0 [~ 0] 4 [3 2] [0 ~] [0 ~] <0 2> ~]/2")
.scale("D2:minor") .scale("D2:minor")
.sound("sawtooth,triangle").lpf(800) .sound("sawtooth,triangle").lpf(800)`}
)`}
/> />
<Box> <Box>

View file

@ -319,6 +319,7 @@ New functions:
| note | set pitch as number or letter | <MiniRepl client:visible tune={`note("b g e c").sound("piano")`} /> | | note | set pitch as number or letter | <MiniRepl client:visible tune={`note("b g e c").sound("piano")`} /> |
| scale | interpret `n` as scale degree | <MiniRepl client:visible tune={`n("6 4 2 0").scale("C:minor").sound("piano")`} /> | | scale | interpret `n` as scale degree | <MiniRepl client:visible tune={`n("6 4 2 0").scale("C:minor").sound("piano")`} /> |
| stack | play patterns in parallel (read on) | <MiniRepl client:visible tune={`stack(s("bd sd"),note("c eb g"))`} /> | | stack | play patterns in parallel (read on) | <MiniRepl client:visible tune={`stack(s("bd sd"),note("c eb g"))`} /> |
| $: | play patterns in parallel | <MiniRepl client:visible tune={'$: s("bd sd")\n$: note("c eb g")'} /> |
## Examples ## 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:
<MiniRepl
client:visible
tune={`$: note("<[c2 c3]*4 [bb1 bb2]*4 [f2 f3]*4 [eb2 eb3]*4>")
.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, [~ <sd cp>]*2, [~ hh]*4")
.bank("RolandTR909")`}
/>
<Box>
Try changing `$` to `_$` to mute a part!
</Box>
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) 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)

View file

@ -25,20 +25,16 @@ This is the same as:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: n("0 1 [4 3] 2 0 2 [~ 3] 4").sound("jazz").pan(0)
n("0 1 [4 3] 2 0 2 [~ 3] 4").sound("jazz").pan(0), $: n("0 1 [4 3] 2 0 2 [~ 3] 4").sound("jazz").pan(1).rev()`}
n("0 1 [4 3] 2 0 2 [~ 3] 4").sound("jazz").pan(1).rev()
)`}
/> />
Let's visualize what happens here: Let's visualize what happens here:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: n("0 1 [4 3] 2 0 2 [~ 3] 4").sound("jazz").pan(0).color("cyan")
n("0 1 [4 3] 2 0 2 [~ 3] 4").sound("jazz").pan(0).color("cyan"), $: n("0 1 [4 3] 2 0 2 [~ 3] 4").sound("jazz").pan(1).color("magenta").rev()`}
n("0 1 [4 3] 2 0 2 [~ 3] 4").sound("jazz").pan(1).color("magenta").rev()
)`}
punchcard punchcard
/> />
@ -56,11 +52,9 @@ This is like doing
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: note("c2, eb3 g3 [bb3 c4]").s("piano").slow(0.5).color('cyan')
note("c2, eb3 g3 [bb3 c4]").s("piano").slow(0.5).color('cyan'), $: note("c2, eb3 g3 [bb3 c4]").s("piano").slow(1).color('magenta')
note("c2, eb3 g3 [bb3 c4]").s("piano").slow(1).color('magenta'), $: note("c2, eb3 g3 [bb3 c4]").s("piano").slow(1.5).color('yellow')`}
note("c2, eb3 g3 [bb3 c4]").s("piano").slow(1.5).color('yellow')
)`}
punchcard punchcard
/> />
@ -110,17 +104,17 @@ We can add as often as we like:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: n("0 [2 4] <3 5> [~ <4 1>]".add("<0 [0,2,4]>"))
n("0 [2 4] <3 5> [~ <4 1>]".add("<0 [0,2,4]>"))
.scale("C5:minor") .scale("C5:minor")
.sound("gm_xylophone") .sound("gm_xylophone")
.room(.4).delay(.125), .room(.4).delay(.125)
note("c2 [eb3,g3]".add("<0 <1 -1>>"))
$: note("c2 [eb3,g3]".add("<0 <1 -1>>"))
.adsr("[.1 0]:.2:[1 0]") .adsr("[.1 0]:.2:[1 0]")
.sound("gm_acoustic_bass") .sound("gm_acoustic_bass")
.room(.5), .room(.5)
n("0 1 [2 3] 2").sound("jazz").jux(rev)
)`} $: n("0 1 [2 3] 2").sound("jazz").jux(rev)`}
/> />
**ply** **ply**

View file

@ -40,6 +40,7 @@ This page is just a listing of all functions covered in the workshop!
| note | set pitch as number or letter | <MiniRepl client:visible tune={`note("b g e c").sound("piano")`} /> | | note | set pitch as number or letter | <MiniRepl client:visible tune={`note("b g e c").sound("piano")`} /> |
| n + scale | set note in scale | <MiniRepl client:visible tune={`n("6 4 2 0").scale("C:minor").sound("piano")`} /> | | n + scale | set note in scale | <MiniRepl client:visible tune={`n("6 4 2 0").scale("C:minor").sound("piano")`} /> |
| stack | play patterns in parallel | <MiniRepl client:visible tune={`stack(s("bd sd"),note("c eb g"))`} /> | | stack | play patterns in parallel | <MiniRepl client:visible tune={`stack(s("bd sd"),note("c eb g"))`} /> |
| $: | play patterns in parallel | <MiniRepl client:visible tune={'$: s("bd sd")\n$: note("c eb g")'} /> |
## Audio Effects ## Audio Effects