Merge pull request #1126 from tidalcycles/labeled-statements-doc

Labeled statements doc
This commit is contained in:
Felix Roos 2024-06-04 00:26:48 +02:00 committed by GitHub
commit c403a92542
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 99 additions and 142 deletions

View file

@ -191,6 +191,7 @@ evalScope(
}, },
); );
// TBD: use transpiler to support labeled statements
export const queryCode = async (code, cycles = 1) => { export const queryCode = async (code, cycles = 1) => {
const { pattern } = await evaluate(code); const { pattern } = await evaluate(code);
const haps = pattern.sortHapsByPart().queryArc(0, cycles); const haps = pattern.sortHapsByPart().queryArc(0, cycles);

View file

@ -81,7 +81,7 @@ export function MiniRepl({
}, },
onToggle: (playing) => { onToggle: (playing) => {
if (!playing) { if (!playing) {
clearHydra(); // clearHydra(); // TBD: doesn't work with multiple MiniRepl's on a page
} }
}, },
beforeStart: () => audioReady, beforeStart: () => audioReady,

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

@ -314,11 +314,11 @@ Let's recap what we've learned in this chapter:
New functions: New functions:
| Name | Description | Example | | Name | Description | Example |
| ----- | ----------------------------------- | --------------------------------------------------------------------------------- | | ----- | ----------------------------- | --------------------------------------------------------------------------------- |
| 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"))`} /> | | $: | play patterns in parallel | <MiniRepl client:visible tune={'$: s("bd sd")\n$: note("c eb g")'} /> |
## Examples ## Examples
@ -356,25 +356,35 @@ New functions:
<Box> <Box>
It's called `stack` 😙 You can use `$:` 😙
</Box> </Box>
## Playing multiple patterns
If you want to play multiple patterns at the same time, make sure to write `$:` before each:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`stack( tune={`$: 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("gm_synth_bass_1").lpf(800)
.sound("gm_synth_bass_1").lpf(800),
n(\`< $: n(\`<
[~ 0] 2 [0 2] [~ 2] [~ 0] 2 [0 2] [~ 2]
[~ 0] 1 [0 1] [~ 1] [~ 0] 1 [0 1] [~ 1]
[~ 0] 3 [0 3] [~ 3] [~ 0] 3 [0 3] [~ 3]
[~ 0] 2 [0 2] [~ 2] [~ 0] 2 [0 2] [~ 2]
>*4\`).scale("C4:minor") >*4\`).scale("C4:minor")
.sound("gm_synth_strings_1"), .sound("gm_synth_strings_1")
sound("bd*4, [~ <sd cp>]*2, [~ hh]*4")
.bank("RolandTR909") $: 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,15 @@ 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**
@ -165,7 +157,7 @@ off is also useful for modifying other sounds, and can even be nested:
client:visible client:visible
tune={`s("bd sd [rim bd] sd,[~ hh]*4").bank("CasioRZ1") tune={`s("bd sd [rim bd] sd,[~ hh]*4").bank("CasioRZ1")
.off(2/16, x=>x.speed(1.5).gain(.25) .off(2/16, x=>x.speed(1.5).gain(.25)
.off(3/16, y=>y.vowel("<a e i o>*8")))`} .off(3/16, y=>y.vowel("<a e i o>*8")))`}
/> />
| name | description | example | | name | description | example |

View file

@ -39,7 +39,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"))`} /> | | $: | play patterns in parallel | <MiniRepl client:visible tune={'$: s("bd sd")\n$: note("c eb g")'} /> |
## Audio Effects ## Audio Effects