Merge branch 'main' into fix-stepcat

This commit is contained in:
Alex McLean 2025-06-19 10:08:08 +02:00
commit 09fdc45ff2
15 changed files with 209 additions and 116 deletions

View file

@ -1,6 +1,6 @@
name: Strudel tests name: Strudel tests
on: [push, pull_request] on: [push]
jobs: jobs:
build: build:
@ -11,13 +11,15 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: apt install ztd
run: apt update && apt install -y zstd
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v4
with: with:
version: 9.12.2 version: 9.12.2
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
# cache: 'pnpm' cache: 'pnpm'
- run: pnpm install - run: pnpm install
- run: pnpm run format-check - run: pnpm run format-check
- run: pnpm run lint - run: pnpm run lint

View file

@ -1981,6 +1981,7 @@ export const apply = register('apply', function (func, pat) {
/** /**
* Plays the pattern at the given cycles per minute. * Plays the pattern at the given cycles per minute.
* @deprecated
* @example * @example
* s("<bd sd>,hh*2").cpm(90) // = 90 bpm * s("<bd sd>,hh*2").cpm(90) // = 90 bpm
*/ */

View file

@ -85,6 +85,17 @@ export function repl({
const pause = () => scheduler.pause(); const pause = () => scheduler.pause();
const toggle = () => scheduler.toggle(); const toggle = () => scheduler.toggle();
const setCps = (cps) => scheduler.setCps(cps); const setCps = (cps) => scheduler.setCps(cps);
/**
* Changes the global tempo to the given cycles per minute
*
* @name setcpm
* @alias setCpm
* @param {number} cpm cycles per minute
* @example
* setcpm(140/4) // =140 bpm in 4/4
* $: s("bd*4,[- sd]*2").bank('tr707')
*/
const setCpm = (cpm) => scheduler.setCps(cpm / 60); const setCpm = (cpm) => scheduler.setCps(cpm / 60);
// TODO - not documented as jsdoc examples as the test framework doesn't simulate enough context for `each` and `all`.. // TODO - not documented as jsdoc examples as the test framework doesn't simulate enough context for `each` and `all`..

View file

@ -56,14 +56,15 @@ You can use button inputs to control different aspects of your music, such as ga
<MiniRepl <MiniRepl
client:idle client:idle
tune={`const gp = gamepad(0) tune={`const gp = gamepad(0)
// Use button values to control amplitude setcpm(120)
// Use button values to control amplitude
$: stack( $: stack(
s("[[hh hh] oh hh oh]/2").mask(gp.tglX).bank("RolandTR909"), // X btn for HH s("[[hh hh] oh hh oh]/2").mask(gp.tglX).bank("RolandTR909"), // X btn for HH
s("cr*1").mask(gp.Y).bank("RolandTR909"), // LB btn for CR s("cr*1").mask(gp.Y).bank("RolandTR909"), // LB btn for CR
s("bd").mask(gp.tglA).bank("RolandTR909"), // A btn for BD s("bd").mask(gp.tglA).bank("RolandTR909"), // A btn for BD
s("[ht - - mt - - lt - ]/2").mask(gp.tglB).bank("RolandTR909"), // B btn for Toms s("[ht - - mt - - lt - ]/2").mask(gp.tglB).bank("RolandTR909"), // B btn for Toms
s("sd*4").mask(gp.RB).bank("RolandTR909"), // RB btn for SD s("sd*4").mask(gp.RB).bank("RolandTR909"), // RB btn for SD
).cpm(120) )
`} `}
/> />
@ -74,14 +75,13 @@ Analog sticks can be used for continuous control, such as pitch shifting or pann
<MiniRepl <MiniRepl
client:idle client:idle
tune={`const gp = gamepad(0) tune={`const gp = gamepad(0)
// Use analog stick for continuous control setcpm(120)
// Use analog stick for continuous control
$: note("c4 d3 a3 e3").sound("sawtooth") $: note("c4 d3 a3 e3").sound("sawtooth")
.lpf(gp.x1.range(100,4000)) .lpf(gp.x1.range(100,4000))
.lpq(gp.y1.range(5,30)) .lpq(gp.y1.range(5,30))
.decay(gp.y2.range(0.1,2)) .decay(gp.y2.range(0.1,2))
.lpenv(gp.x2.range(-5,5)) .lpenv(gp.x2.range(-5,5))`}
.cpm(120)
`}
/> />
### Button Sequences ### Button Sequences
@ -89,6 +89,7 @@ $: note("c4 d3 a3 e3").sound("sawtooth")
You can define button sequences to trigger specific actions, like playing a sound when a sequence is detected. You can define button sequences to trigger specific actions, like playing a sound when a sequence is detected.
<MiniRepl client:idle tune={`const gp = gamepad(0) <MiniRepl client:idle tune={`const gp = gamepad(0)
setcpm(120)
// Define button sequences // Define button sequences
const HADOUKEN = [ const HADOUKEN = [
'd', // Down 'd', // Down
@ -99,7 +100,7 @@ const KONAMI = 'uuddlrlrba' //Konami Code ↑↑↓↓←→←→BA
// Check butto-n sequence (returns 1 while detected, 0 when not within last 1 second) // Check butto-n sequence (returns 1 while detected, 0 when not within last 1 second)
$: s("free_hadouken -").slow(2) $: s("free_hadouken -").slow(2)
.mask(gp.btnSequence(HADOUKEN)).room(1).cpm(120) .mask(gp.btnSequence(HADOUKEN)).room(1)
// hadouken.wav by Syna-Max // hadouken.wav by Syna-Max
//https://freesound.org/people/Syna-Max/sounds/67674/ //https://freesound.org/people/Syna-Max/sounds/67674/

View file

@ -8450,6 +8450,35 @@ exports[`runs examples > example "seqPLoop" example index 0 1`] = `
] ]
`; `;
exports[`runs examples > example "setcpm" example index 0 1`] = `
[
"[ 0/1 → 1/4 | s:bd bank:tr707 ]",
"[ 1/4 → 1/2 | s:bd bank:tr707 ]",
"[ 1/4 → 1/2 | s:sd bank:tr707 ]",
"[ 1/2 → 3/4 | s:bd bank:tr707 ]",
"[ 3/4 → 1/1 | s:bd bank:tr707 ]",
"[ 3/4 → 1/1 | s:sd bank:tr707 ]",
"[ 1/1 → 5/4 | s:bd bank:tr707 ]",
"[ 5/4 → 3/2 | s:bd bank:tr707 ]",
"[ 5/4 → 3/2 | s:sd bank:tr707 ]",
"[ 3/2 → 7/4 | s:bd bank:tr707 ]",
"[ 7/4 → 2/1 | s:bd bank:tr707 ]",
"[ 7/4 → 2/1 | s:sd bank:tr707 ]",
"[ 2/1 → 9/4 | s:bd bank:tr707 ]",
"[ 9/4 → 5/2 | s:bd bank:tr707 ]",
"[ 9/4 → 5/2 | s:sd bank:tr707 ]",
"[ 5/2 → 11/4 | s:bd bank:tr707 ]",
"[ 11/4 → 3/1 | s:bd bank:tr707 ]",
"[ 11/4 → 3/1 | s:sd bank:tr707 ]",
"[ 3/1 → 13/4 | s:bd bank:tr707 ]",
"[ 13/4 → 7/2 | s:bd bank:tr707 ]",
"[ 13/4 → 7/2 | s:sd bank:tr707 ]",
"[ 7/2 → 15/4 | s:bd bank:tr707 ]",
"[ 15/4 → 4/1 | s:bd bank:tr707 ]",
"[ 15/4 → 4/1 | s:sd bank:tr707 ]",
]
`;
exports[`runs examples > example "shape" example index 0 1`] = ` exports[`runs examples > example "shape" example index 0 1`] = `
[ [
"[ 0/1 → 1/8 | s:hh shape:0 ]", "[ 0/1 → 1/8 | s:hh shape:0 ]",

View file

@ -97,6 +97,7 @@ const toneHelpersMocked = {
'_pianoroll', '_pianoroll',
'_spectrum', '_spectrum',
'markcss', 'markcss',
'p',
].forEach((mock) => { ].forEach((mock) => {
strudel.Pattern.prototype[mock] = function () { strudel.Pattern.prototype[mock] = function () {
return this; return this;
@ -163,6 +164,7 @@ evalScope(
loadCsound, loadCsound,
loadcsound, loadcsound,
setcps: id, setcps: id,
setcpm: id,
Clock: {}, // whatever Clock: {}, // whatever
}, },
); );

View file

@ -168,9 +168,14 @@ Korrekt, der echte Vorteil dieser Schreibweise zeigt sich wenn du Elemente entfe
</Box> </Box>
**Tempo ändern mit `cpm`** **Tempo ändern mit `setcpm`**
<MiniRepl client:visible tune={`sound("<bd hh rim hh>*8").cpm(90/4)`} punchcard /> <MiniRepl
client:visible
tune={`setcpm(90/4)
sound("<bd hh rim hh>*8")`}
punchcard
/>
<Box> <Box>
@ -233,8 +238,9 @@ Bolero:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`sound("sd sd*3 sd sd*3 sd sd sd sd*3 sd sd*3 sd*3 sd*3") tune={`
.cpm(10)`} setcpm(10)
sound("sd sd*3 sd sd*3 sd sd sd sd*3 sd sd*3 sd*3 sd*3")`}
punchcard punchcard
/> />
@ -313,18 +319,23 @@ Das haben wir bisher gelernt:
Die mit Apostrophen umgebene Mini-Notation benutzt man normalerweise in einer sogenannten Funktion. Die mit Apostrophen umgebene Mini-Notation benutzt man normalerweise in einer sogenannten Funktion.
Die folgenden Funktionen haben wir bereits gesehen: Die folgenden Funktionen haben wir bereits gesehen:
| Name | Description | Example | | Name | Description | Example |
| ----- | -------------------------------------- | ----------------------------------------------------------------------- | | ------ | -------------------------------------- | ----------------------------------------------------------------------- |
| sound | Spielt den Sound mit dem Namen | <MiniRepl client:visible tune={`sound("bd sd")`} /> | | sound | Spielt den Sound mit dem Namen | <MiniRepl client:visible tune={`sound("bd sd")`} /> |
| bank | Wählt die Soundbank / Drum Machine | <MiniRepl client:visible tune={`sound("bd sd").bank("RolandTR909")`} /> | | bank | Wählt die Soundbank / Drum Machine | <MiniRepl client:visible tune={`sound("bd sd").bank("RolandTR909")`} /> |
| cpm | Tempo in **C**ycles **p**ro **M**inute | <MiniRepl client:visible tune={`sound("bd sd").cpm(90)`} /> | | setcpm | Tempo in **C**ycles **p**ro **M**inute | <MiniRepl client:visible tune={`setcpm(90); sound("bd sd")`} /> |
| n | Sample Nummer | <MiniRepl client:visible tune={`n("0 1 4 2").sound("jazz")`} /> | | n | Sample Nummer | <MiniRepl client:visible tune={`n("0 1 4 2").sound("jazz")`} /> |
## Beispiele ## Beispiele
**Einfacher Rock Beat** **Einfacher Rock Beat**
<MiniRepl client:visible tune={`sound("bd sd, hh*4").bank("RolandTR505").cpm(100/2)`} punchcard /> <MiniRepl
client:visible
tune={`setcpm(100/2)
sound("bd sd, hh*4").bank("RolandTR505")`}
punchcard
/>
**Klassischer House** **Klassischer House**
@ -339,7 +350,12 @@ Bestimmte Drum Patterns werden oft genreübergreifend wiederverwendet.
We Will Rock you We Will Rock you
<MiniRepl client:visible tune={`sound("bd*2 cp").bank("RolandTR707").cpm(81/2)`} punchcard /> <MiniRepl
client:visible
tune={`setcpm(81/2)
sound("bd*2 cp").bank("RolandTR707")`}
punchcard
/>
**Yellow Magic Orchestra - Firecracker** **Yellow Magic Orchestra - Firecracker**
@ -354,12 +370,13 @@ We Will Rock you
<MiniRepl <MiniRepl
client:visible client:visible
tune={`sound(\` tune={`setcpm(90/4)
sound(\`
[- - oh - ] [- - - - ] [- - - - ] [- - - - ], [- - oh - ] [- - - - ] [- - - - ] [- - - - ],
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ], [hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ], [- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd] [bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
\`).cpm(90/4)`} \`)`}
punchcard punchcard
/> />
@ -367,12 +384,13 @@ We Will Rock you
<MiniRepl <MiniRepl
client:visible client:visible
tune={`sound(\` tune={`setcpm(88/4)
sound(\`
[- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ], [- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ],
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ], [hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ],
[- - - - ] [cp - - - ] [- - - - ] [- cp - - ], [- - - - ] [cp - - - ] [- - - - ] [- cp - - ],
[bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ] [bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ]
\`).bank("RolandTR808").cpm(88/4)`} \`).bank("RolandTR808")`}
punchcard punchcard
/> />
@ -380,11 +398,11 @@ We Will Rock you
<MiniRepl <MiniRepl
client:visible client:visible
tune={`s(\`jazz*2, tune={`setcpm(100/2)
s(\`jazz*2,
insect [crow metal] - -, insect [crow metal] - -,
- space:4 - space:1, - space:4 - space:1,
- wind\`) - wind\`)`}
.cpm(100/2)`}
punchcard punchcard
/> />

View file

@ -56,13 +56,13 @@ Diese Seite ist eine Auflistung aller im Workshop vorgestellten Funktionen.
## Pattern-Effekte ## Pattern-Effekte
| Name | Beschreibung | Beispiel | | Name | Beschreibung | Beispiel |
| ---- | --------------------------------- | ----------------------------------------------------------------------------------- | | ------ | --------------------------------- | ----------------------------------------------------------------------------------- |
| cpm | Tempo in Cycles pro Minute | <MiniRepl client:visible tune={`sound("bd sd").cpm(90)`} /> | | setcpm | Tempo in Cycles pro Minute | <MiniRepl client:visible tune={`setcpm(90); sound("bd sd")`} /> |
| fast | schneller | <MiniRepl client:visible tune={`sound("bd sd").fast(2)`} /> | | fast | schneller | <MiniRepl client:visible tune={`sound("bd sd").fast(2)`} /> |
| slow | langsamer | <MiniRepl client:visible tune={`sound("bd sd").slow(2)`} /> | | slow | langsamer | <MiniRepl client:visible tune={`sound("bd sd").slow(2)`} /> |
| rev | rückwärts | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> | | rev | rückwärts | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
| jux | einen Stereo-Kanal modifizieren | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> | | jux | einen Stereo-Kanal modifizieren | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
| add | addiert Zahlen oder Noten | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> | | add | addiert Zahlen oder Noten | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
| ply | jedes Element schneller machen | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> | | ply | jedes Element schneller machen | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
| off | verzögert eine modifizierte Kopie | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> | | off | verzögert eine modifizierte Kopie | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |

View file

@ -247,15 +247,17 @@ We can also declare different samples for different regions of the keyboard:
<MiniRepl <MiniRepl
client:idle client:idle
tune={`samples({ tune={`setcpm(60)
samples({
'moog': { 'moog': {
'g2': 'moog/004_Mighty%20Moog%20G2.wav', 'g2': 'moog/004_Mighty%20Moog%20G2.wav',
'g3': 'moog/005_Mighty%20Moog%20G3.wav', 'g3': 'moog/005_Mighty%20Moog%20G3.wav',
'g4': 'moog/006_Mighty%20Moog%20G4.wav', 'g4': 'moog/006_Mighty%20Moog%20G4.wav',
}}, 'github:tidalcycles/dirt-samples'); }}, 'github:tidalcycles/dirt-samples')
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>") note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
.s('moog').clip(1) .s('moog').clip(1)
.gain(.5).cpm(60)`} .gain(.5)`}
/> />
The sampler will always pick the closest matching sample for the current note! The sampler will always pick the closest matching sample for the current note!

View file

@ -43,21 +43,33 @@ This is why the same CPS can produce different perceived tempos.
## Setting CPM ## Setting CPM
If you're familiar with BPM, you can use the `cpm` method to set the tempo in cycles per minute: If you're familiar with BPM, you can use the `setcpm` method to set the global tempo in cycles per minute:
<MiniRepl client:visible tune={`s("bd hh").cpm(110)`} /> <MiniRepl
client:visible
tune={`setcpm(110)
s("bd hh")`}
/>
If you want to add more beats per cycle, you might want to divide the cpm: If you want to add more beats per cycle, you might want to divide the cpm:
<MiniRepl client:visible tune={`s("bd sd bd rim, hh*8").cpm(110/4)`} /> <MiniRepl
client:visible
tune={`setcpm(110/4)
s("bd sd bd rim, hh*8")`}
/>
Or using 2 beats per cycle: Or using 2 beats per cycle:
<MiniRepl client:visible tune={`s("bd sd, hh*4").cpm(110/2)`} /> <MiniRepl
client:visible
tune={`setcpm(110/2)
s("bd sd, hh*4")`}
/>
<Box> <Box>
To set a specific bpm, use `.cpm(bpm/bpc)` To set a specific bpm, use `setcpm(bpm/bpc)`
- bpm: the target beats per minute - bpm: the target beats per minute
- bpc: the number of perceived beats per cycle - bpc: the number of perceived beats per cycle
@ -74,22 +86,31 @@ Many music programs use it as a default.
Strudel does not a have concept of bars or measures, there are only cycles. Strudel does not a have concept of bars or measures, there are only cycles.
How you use them is up to you. Above, we've had this example: How you use them is up to you. Above, we've had this example:
<MiniRepl client:visible tune={`s("bd sd bd rim, hh*8").cpm(110/4)`} /> <MiniRepl
client:visible
tune={`setcpm(110/4)
s("bd sd bd rim, hh*8")`}
/>
This could be interpreted as 4/4 time with a tempo of 110bpm. This could be interpreted as 4/4 time with a tempo of 110bpm.
We could write out multiple bars like this: We could write out multiple bars like this:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`s(\`< tune={`setcpm(110/4)
s(\`<
[bd sd bd rim, hh*8] [bd sd bd rim, hh*8]
[bd sd bd rim*2, hh*8] [bd sd bd rim*2, hh*8]
>\`).cpm(110/4)`} >\`)`}
/> />
Instead of writing out each bar separately, we could express this much shorter: Instead of writing out each bar separately, we could express this much shorter:
<MiniRepl client:visible tune={`s("bd <sd rim*<1 2>>,hh*4").cpm(110/2)`} /> <MiniRepl
client:visible
tune={`setcpm(110/2)
s("bd <sd rim*<1 2>>,hh*4")`}
/>
Here we can see that thinking in cycles rather than bars simplifies things a lot! Here we can see that thinking in cycles rather than bars simplifies things a lot!
These types of simplifications work because of the repetitive nature of rhythm. These types of simplifications work because of the repetitive nature of rhythm.
@ -109,10 +130,11 @@ We could also write multiple bars with different time signatures:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`s(\`< tune={`setcpm(110*2)
s(\`<
[bd hh rim]@3 [bd hh rim]@3
[bd hh rim sd]@4 [bd hh rim sd]@4
>\`).cpm(110*2)`} >\`)`}
/> />
Here we switch between 3/4 and 4/4, keeping the same tempo. Here we switch between 3/4 and 4/4, keeping the same tempo.
@ -121,10 +143,11 @@ If we don't specify the length, we get what's called a metric modulation:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`s(\`< tune={`setcpm(110/2)
s(\`<
[bd hh rim] [bd hh rim]
[bd hh rim sd] [bd hh rim sd]
>\`).cpm(110/2)`} >\`)`}
/> />
Now the 3 elements get the same time as the 4 elements, which is why the tempo changes. Now the 3 elements get the same time as the 4 elements, which is why the tempo changes.

View file

@ -216,8 +216,9 @@ Finding the right notes can be difficult.. Scales are here to help:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`n("0 2 4 <[6,8] [7,9]>") tune={`setcpm(60)
.scale("C:minor").sound("piano").cpm(60)`} n("0 2 4 <[6,8] [7,9]>")
.scale("C:minor").sound("piano")`}
punchcard punchcard
/> />
@ -242,9 +243,10 @@ Just like anything, we can automate the scale with a pattern:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`n("<0 -3>, 2 4 <[6,8] [7,9]>") tune={`setcpm(60)
n("<0 -3>, 2 4 <[6,8] [7,9]>")
.scale("<C:major D:mixolydian>/4") .scale("<C:major D:mixolydian>/4")
.sound("piano").cpm(60)`} .sound("piano")`}
punchcard punchcard
/> />
@ -275,9 +277,10 @@ Try changing that number!
<MiniRepl <MiniRepl
client:visible client:visible
tune={`n("<[4@2 4] [5@2 5] [6@2 6] [5@2 5]>*2") tune={`setcpm(60)
n("<[4@2 4] [5@2 5] [6@2 6] [5@2 5]>*2")
.scale("<C2:mixolydian F2:mixolydian>/4") .scale("<C2:mixolydian F2:mixolydian>/4")
.sound("gm_acoustic_bass").cpm(60)`} .sound("gm_acoustic_bass")`}
punchcard punchcard
/> />
@ -291,7 +294,12 @@ This is also sometimes called triplet swing. You'll often find it in blues and j
**Replicate** **Replicate**
<MiniRepl client:visible tune={`note("c!2 [eb,<g a bb a>]").sound("piano").cpm(60)`} punchcard /> <MiniRepl
client:visible
tune={`setcpm(60)
note("c!2 [eb,<g a bb a>]").sound("piano")`}
punchcard
/>
<Box> <Box>

View file

@ -166,9 +166,14 @@ Try also changing the number at the end to change the tempo!
</Box> </Box>
**changing the tempo with cpm** **changing the tempo with setcpm**
<MiniRepl client:visible tune={`sound("<bd hh rim hh>*8").cpm(90/4)`} punchcard /> <MiniRepl
client:visible
tune={`setcpm(90/4)
sound("<bd hh rim hh>*8")`}
punchcard
/>
<Box> <Box>
@ -283,12 +288,12 @@ This is what we've learned so far:
The Mini-Notation is usually used inside some function. These are the functions we've seen so far: The Mini-Notation is usually used inside some function. These are the functions we've seen so far:
| Name | Description | Example | | Name | Description | Example |
| ----- | ----------------------------------- | --------------------------------------------------------------------------------- | | ------ | ----------------------------------- | --------------------------------------------------------------------------------- |
| sound | plays the sound of the given name | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd")`} /> | | sound | plays the sound of the given name | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd")`} /> |
| bank | selects the sound bank | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").bank("RolandTR909")`} /> | | bank | selects the sound bank | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").bank("RolandTR909")`} /> |
| cpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`sound("bd sd [- bd] sd").cpm(45)`} /> | | setcpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`setcpm(45); sound("bd sd [- bd] sd")`} /> |
| n | select sample number | <MiniRepl client:visible tune={`n("0 1 4 2 0 6 3 2").sound("jazz")`} /> | | n | select sample number | <MiniRepl client:visible tune={`n("0 1 4 2 0 6 3 2").sound("jazz")`} /> |
## Examples ## Examples
@ -296,8 +301,8 @@ The Mini-Notation is usually used inside some function. These are the functions
<MiniRepl <MiniRepl
client:visible client:visible
tune={`sound("[bd sd]*2, hh*8").bank("RolandTR505") tune={`setcpm(100/4)
.cpm(100/4)`} sound("[bd sd]*2, hh*8").bank("RolandTR505")`}
punchcard punchcard
/> />
@ -314,14 +319,20 @@ Certain drum patterns are reused across genres.
We Will Rock you We Will Rock you
<MiniRepl client:visible tune={`sound("bd*2 cp").bank("RolandTR707").cpm(81/2)`} punchcard /> <MiniRepl
client:visible
tune={`setcpm(81/2)
sound("bd*2 cp").bank("RolandTR707")`}
punchcard
/>
**Yellow Magic Orchestra - Firecracker** **Yellow Magic Orchestra - Firecracker**
<MiniRepl <MiniRepl
client:visible client:visible
tune={`sound("bd sd, - - - hh - hh - -, - perc - perc:1*2") tune={`setcpm(120/2)
.bank("RolandCompurhythm1000").cpm(120/2)`} sound("bd sd, - - - hh - hh - -, - perc - perc:1*2")
.bank("RolandCompurhythm1000")`}
punchcard punchcard
/> />
@ -329,12 +340,14 @@ We Will Rock you
<MiniRepl <MiniRepl
client:visible client:visible
tune={`sound(\` tune={`
setcpm(90/4)
sound(\`
[- - oh - ] [- - - - ] [- - - - ] [- - - - ], [- - oh - ] [- - - - ] [- - - - ] [- - - - ],
[hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ], [hh hh - - ] [hh - hh - ] [hh - hh - ] [hh - hh - ],
[- - - - ] [cp - - - ] [- - - - ] [cp - - - ], [- - - - ] [cp - - - ] [- - - - ] [cp - - - ],
[bd - - - ] [- - - bd] [- - bd - ] [- - - bd] [bd - - - ] [- - - bd] [- - bd - ] [- - - bd]
\`).cpm(90/4)`} \`)`}
punchcard punchcard
/> />
@ -342,12 +355,13 @@ We Will Rock you
<MiniRepl <MiniRepl
client:visible client:visible
tune={`sound(\` tune={`setcpm(88/4)
sound(\`
[- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ], [- - - - ] [- - - - ] [- - - - ] [- - oh:1 - ],
[hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ], [hh hh hh hh] [hh hh hh hh] [hh hh hh hh] [hh hh - - ],
[- - - - ] [cp - - - ] [- - - - ] [~ cp - - ], [- - - - ] [cp - - - ] [- - - - ] [~ cp - - ],
[bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ] [bd bd - - ] [- - bd - ] [bd bd - bd ] [- - - - ]
\`).bank("RolandTR808").cpm(88/4)`} \`).bank("RolandTR808")`}
punchcard punchcard
/> />
@ -355,11 +369,11 @@ We Will Rock you
<MiniRepl <MiniRepl
client:visible client:visible
tune={`s(\`jazz*2, tune={`setcpm(100/2)
s(\`jazz*2,
insect [crow metal] - -, insect [crow metal] - -,
- space:4 - space:1, - space:4 - space:1,
- wind\`) - wind\`)`}
.cpm(100/2)`}
punchcard punchcard
/> />

View file

@ -68,9 +68,10 @@ Try commenting out one or more by adding `//` before a line
<MiniRepl <MiniRepl
client:visible client:visible
tune={`note("c2 [eb3,g3] ".add("<0 <1 -1>>")) tune={`setcpm(60)
note("c2 [eb3,g3] ".add("<0 <1 -1>>"))
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]") .color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
.sound("gm_acoustic_bass").room(.5).cpm(60)`} .sound("gm_acoustic_bass").room(.5)`}
punchcard punchcard
/> />
@ -84,9 +85,10 @@ We can add as often as we like:
<MiniRepl <MiniRepl
client:visible client:visible
tune={`note("c2 [eb3,g3]".add("<0 <1 -1>>").add("0,7")) tune={`setcpm(60)
note("c2 [eb3,g3]".add("<0 <1 -1>>").add("0,7"))
.color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]") .color("<cyan <magenta yellow>>").adsr("[.1 0]:.2:[1 0]")
.sound("gm_acoustic_bass").room(.5).cpm(60)`} .sound("gm_acoustic_bass").room(.5)`}
punchcard punchcard
/> />

View file

@ -56,13 +56,13 @@ This page is just a listing of all functions covered in the workshop!
## Pattern Effects ## Pattern Effects
| name | description | example | | name | description | example |
| ---- | ----------------------------------- | ----------------------------------------------------------------------------------- | | ------ | ----------------------------------- | ----------------------------------------------------------------------------------- |
| cpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").cpm(45)`} /> | | setcpm | sets the tempo in cycles per minute | <MiniRepl client:visible tune={`setcpm(45); sound("bd sd [~ bd] sd")`} /> |
| fast | speed up | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").fast(2)`} /> | | fast | speed up | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").fast(2)`} /> |
| slow | slow down | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").slow(2)`} /> | | slow | slow down | <MiniRepl client:visible tune={`sound("bd sd [~ bd] sd").slow(2)`} /> |
| rev | reverse | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> | | rev | reverse | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").rev()`} /> |
| jux | split left/right, modify right | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> | | jux | split left/right, modify right | <MiniRepl client:visible tune={`n("0 2 4 6").scale("C:minor").jux(rev)`} /> |
| add | add numbers / notes | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> | | add | add numbers / notes | <MiniRepl client:visible tune={`n("0 2 4 6".add("<0 1 2 1>")).scale("C:minor")`} /> |
| ply | speed up each event n times | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> | | ply | speed up each event n times | <MiniRepl client:visible tune={`s("bd sd").ply("<1 2 3>")`} /> |
| off | copy, shift time & modify | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> | | off | copy, shift time & modify | <MiniRepl client:visible tune={`s("bd sd, hh*4").off(1/8, x=>x.speed(2))`} /> |

View file

@ -313,26 +313,6 @@ stack(
) )
.fast(2/3) .fast(2/3)
.pianoroll()`; .pianoroll()`;
/*
export const bridgeIsOver = `// "Bridge is over"
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
// @by Felix Roos, bassline by BDP - The Bridge Is Over
samples({mad:'https://freesound.org/data/previews/22/22274_109943-lq.mp3'})
stack(
stack(
note("c3*2 [[c3@1.4 bb2] ab2] gb2*2 <[[gb2@1.4 ab2] bb2] gb2>")
.gain(.8).clip("[.5 1]*2"),
n("<0 1 2 3 4 3 2 1>")
.clip(.5)
.echoWith(8, 1/32, (x,i)=>x.add(n(i)).velocity(Math.pow(.7,i)))
.scale('c4 whole tone')
.echo(3, 1/8, .5)
).piano(),
s("mad").slow(2)
).cpm(78).slow(4)
.pianoroll()
`; */
export const goodTimes = `// "Good times" export const goodTimes = `// "Good times"
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/ // @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/