Merge branch 'tidalcycles:main' into repl_sync_fixes
This commit is contained in:
commit
af740c3abb
39 changed files with 3266 additions and 2872 deletions
|
|
@ -102,9 +102,10 @@ export const SIDEBAR: Sidebar = {
|
|||
{ text: 'Strudel vs Tidal', link: 'learn/strudel-vs-tidal' },
|
||||
],
|
||||
Development: [
|
||||
{ text: 'Strudel in your Project', link: 'technical-manual/project-start' },
|
||||
{ text: 'Packages', link: 'technical-manual/packages' },
|
||||
{ text: 'REPL', link: 'technical-manual/repl' },
|
||||
{ text: 'Sounds', link: 'technical-manual/sounds' },
|
||||
{ text: 'Packages', link: 'technical-manual/packages' },
|
||||
{ text: 'Docs', link: 'technical-manual/docs' },
|
||||
{ text: 'Testing', link: 'technical-manual/testing' },
|
||||
// { text: 'Internals', link: 'technical-manual/internals' },
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { getPunchcardPainter } from '@strudel/draw';
|
|||
import { transpiler } from '@strudel/transpiler';
|
||||
import { getAudioContext, webaudioOutput, initAudioOnFirstClick } from '@strudel/webaudio';
|
||||
import { StrudelMirror } from '@strudel/codemirror';
|
||||
// import { prebake } from '@strudel/repl';
|
||||
import { prebake } from '../repl/prebake.mjs';
|
||||
import { loadModules } from '../repl/util.mjs';
|
||||
import Claviature from '@components/Claviature';
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ This makes way for other ways to align the pattern, and several are already defi
|
|||
- `mix` - structures from both patterns are combined, so that the new events are not fragments but are created at intersections of events from both sides.
|
||||
- `squeeze` - cycles from the pattern on the right are squeezed into events on the left. So that e.g. `"0 1 2".add.squeeze("10 20")` is equivalent to `"[10 20] [11 21] [12 22]"`.
|
||||
- `squeezeout` - as with `squeeze`, but cycles from the left are squeezed into events on the right. So, `"0 1 2".add.squeezeout("10 20")` is equivalent to `[10 11 12] [20 21 22]`.
|
||||
- `trig` is similar to `squeezeout` in that cycles from the right are aligned with events on the left. However those cycles are not 'squeezed', rather they are truncated to fit the event. So `"0 1 2 3 4 5 6 7".add.trig("10 [20 30]")` would be equivalent to `10 11 12 13 20 21 30 31`. In effect, events on the right 'trigger' cycles on the left.
|
||||
- `trigzero` is similar to `trig`, but the pattern is 'triggered' from its very first cycle, rather than from the current cycle. `trig` and `trigzero` therefore only give different results where the leftmost pattern differs from one cycle to the next.
|
||||
- `reset` is similar to `squeezeout` in that cycles from the right are aligned with events on the left. However those cycles are not 'squeezed', rather they are truncated to fit the event. So `"0 1 2 3 4 5 6 7".add.trig("10 [20 30]")` would be equivalent to `10 11 12 13 20 21 30 31`. In effect, events on the right 'trigger' cycles on the left.
|
||||
- `restart` is similar to `reset`, but the pattern is 'restarted' from its very first cycle, rather than from the current cycle. `reset` and `restart` therefore only give different results where the leftmost pattern differs from one cycle to the next.
|
||||
|
||||
We will save going deeper into the background, design and practicalities of these alignment functions for future publications. However in the next section, we take them as a case study for looking at the different design affordances offered by Haskell to Tidal, and JavaScript to Strudel.
|
||||
|
||||
|
|
|
|||
|
|
@ -60,13 +60,13 @@ These functions are more low level, probably not needed by the live coder.
|
|||
|
||||
<JsDoc client:idle name="Pattern#innerJoin" h={0} />
|
||||
|
||||
## trigJoin
|
||||
## resetJoin
|
||||
|
||||
<JsDoc client:idle name="Pattern#trigJoin" h={0} />
|
||||
<JsDoc client:idle name="Pattern#resetJoin" h={0} />
|
||||
|
||||
## trigzeroJoin
|
||||
## restartJoin
|
||||
|
||||
<JsDoc client:idle name="Pattern#trigzeroJoin" h={0} />
|
||||
<JsDoc client:idle name="Pattern#restartJoin" h={0} />
|
||||
|
||||
## squeezeJoin
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,15 @@ The purpose of the multiple packages is to
|
|||
[See the latest published packages on npm](https://www.npmjs.com/search?q=%40strudel).
|
||||
Here is an overview of all the packages:
|
||||
|
||||
### Umbrella Packages
|
||||
|
||||
These packages give you a batteries-included point of getting started, and most likely the thing you'd want to use in your project:
|
||||
|
||||
- [repl](https://github.com/tidalcycles/strudel/tree/main/packages/repl): The Strudel REPL as a web component.
|
||||
- [web](https://github.com/tidalcycles/strudel/tree/main/packages/web): Strudel library for the browser, without UI.
|
||||
|
||||
To find out more about these two, read [Using Strudel in Your Project](/technical-manual/project-start)
|
||||
|
||||
### Essential Packages
|
||||
|
||||
These package are the most essential. You might want to use all of those if you're using strudel in your project:
|
||||
|
|
|
|||
129
website/src/pages/technical-manual/project-start.mdx
Normal file
129
website/src/pages/technical-manual/project-start.mdx
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
---
|
||||
title: Using Strudel in your Project
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
# Using Strudel in your Project
|
||||
|
||||
This Guide shows you the different ways to get started with using Strudel in your own project.
|
||||
|
||||
## Embedding the Strudel REPL
|
||||
|
||||
There are 3 quick ways to embed strudel in your website:
|
||||
|
||||
1. Embed the strudel website as an iframe directly
|
||||
2. Embed the strudel website as an iframe using `@strudel/embed`
|
||||
3. Embed the REPL directly using `@strudel/repl`
|
||||
|
||||
### Inside an iframe
|
||||
|
||||
Using an iframe is the most easy way to embed a studel tune.
|
||||
You can embed any pattern of your choice via an iframe and the URL of the pattern of your choice:
|
||||
|
||||
```html
|
||||
<iframe src="https://strudel.cc/?xwWRfuCE8TAR" width="600" height="300"></iframe>
|
||||
```
|
||||
|
||||
The URL can be obtained by pressing `share` in the REPL.
|
||||
Note that these share links depend on a database, which is not guaranteed to live forever.
|
||||
To make sure your code is not lost, you can also use the long url:
|
||||
|
||||
```html
|
||||
<iframe
|
||||
src="https://strudel.cc/#c2V0Y3BzKDEpCm4oIjwwIDEgMiAzIDQ%2BKjgiKS5zY2FsZSgnRzQgbWlub3InKQoucygiZ21fbGVhZF82X3ZvaWNlIikKLmNsaXAoc2luZS5yYW5nZSguMiwuOCkuc2xvdyg4KSkKLmp1eChyZXYpCi5yb29tKDIpCi5zb21ldGltZXMoYWRkKG5vdGUoIjEyIikpKQoubHBmKHBlcmxpbi5yYW5nZSgyMDAsMjAwMDApLnNsb3coNCkp"
|
||||
width="600"
|
||||
height="300"
|
||||
></iframe>
|
||||
```
|
||||
|
||||
That long URL can just be copy pasted from the URL bar when you're on the strudel website. It always reflects the latest evaluation of your code.
|
||||
|
||||
### @strudel/embed
|
||||
|
||||
To simplify the process of emebdding via an iframe, you can use the package `@strudel/embed`:
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/@strudel/embed@latest"></script>
|
||||
<strudel-repl>
|
||||
<!--
|
||||
setcps(1)
|
||||
n("<0 1 2 3 4>*8").scale('G4 minor')
|
||||
.s("gm_lead_6_voice")
|
||||
.clip(sine.range(.2,.8).slow(8))
|
||||
.jux(rev)
|
||||
.room(2)
|
||||
.sometimes(add(note("12")))
|
||||
.lpf(perlin.range(200,20000).slow(4))
|
||||
-->
|
||||
</strudel-repl>
|
||||
```
|
||||
|
||||
This will load the strudel website in an iframe, using the code provided within the HTML comments `<!-- -->`.
|
||||
The HTML comments are needed to make sure the browser won't interpret it as HTML.
|
||||
|
||||
For alternative ways to load this package, see the [@strudel/embed README](https://github.com/tidalcycles/strudel/tree/main/packages/embed#strudelembed).
|
||||
|
||||
### @strudel/repl
|
||||
|
||||
Loading strudel directly in your site, without an iframe, looks similar to the iframe variant:
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/@strudel/repl@latest"></script>
|
||||
<strudel-editor>
|
||||
<!--
|
||||
setcps(1)
|
||||
n("<0 1 2 3 4>*8").scale('G4 minor')
|
||||
.s("gm_lead_6_voice")
|
||||
.clip(sine.range(.2,.8).slow(8))
|
||||
.jux(rev)
|
||||
.room(2)
|
||||
.sometimes(add(note("12")))
|
||||
.lpf(perlin.range(200,20000).slow(4))
|
||||
-->
|
||||
</strudel-editor>
|
||||
```
|
||||
|
||||
Here, we're loading `@strudel/repl` instead of `@strudel/embed`, and the component is called `strudel-editor` instead of `strudel-repl`.
|
||||
Yes the naming is a bit confusing..
|
||||
|
||||
The upside of using the repl without an iframe is that you can pin the strudel version you're using:
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/@strudel/repl@1.0.2"></script>
|
||||
<strudel-editor>
|
||||
<!--
|
||||
...
|
||||
-->
|
||||
</strudel-editor>
|
||||
```
|
||||
|
||||
This will guarantee your pattern wont break due to changes to the strudel project in the future.
|
||||
|
||||
For more info on this package, see the [@strudel/repl README](https://github.com/tidalcycles/strudel/tree/main/packages/repl#strudelrepl).
|
||||
|
||||
## With your own UI
|
||||
|
||||
The above approach assumes you want to use the builtin [codemirror](https://codemirror.net/) editor.
|
||||
If you'd rather use your own UI, you can use the `@strudel/web` package:
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<script src="https://unpkg.com/@strudel/web@1.0.3"></script>
|
||||
<button id="play">play</button>
|
||||
<button id="stop">stop</button>
|
||||
<script>
|
||||
initStrudel();
|
||||
document.getElementById('play').addEventListener('click', () => note('<c a f e>(3,8)').jux(rev).play());
|
||||
document.getElementById('stop').addEventListener('click', () => hush());
|
||||
</script>
|
||||
```
|
||||
|
||||
For more info on this package, see the [@strudel/web README](https://github.com/tidalcycles/strudel/tree/main/packages/web#strudelweb).
|
||||
|
||||
## Via npm
|
||||
|
||||
[All the packages and many more are available on npm under the @strudel namespace](https://www.npmjs.com/search?q=%40strudel).
|
||||
There are actually many more packages you can use to have fine grained control over what you use and what not.
|
||||
To use these packages, you have to use a bundler that supports es modules, like [vite](https://vitejs.dev/).
|
||||
|
||||
To find out more about the purpose of each package, see [Packages](/technical-manual/packages)
|
||||
|
|
@ -106,8 +106,7 @@ stack(
|
|||
[B3@2 D4] [A3@2 [G3 A3]] [B3@2 D4] [A3]
|
||||
[B3@2 D4] [A4@2 G4] D5@2
|
||||
[D5@2 [C5 B4]] [[C5 B4] G4@2] [C5@2 [B4 A4]] [[B4 A4] E4@2]
|
||||
[D5@2 [C5 B4]] [[C5 B4] G4 C5] [G5] [~ ~ B3]\`
|
||||
.color('#9C7C38'),
|
||||
[D5@2 [C5 B4]] [[C5 B4] G4 C5] [G5] [~ ~ B3]\`,
|
||||
// bass
|
||||
\`[[C2 G2] E3@2] [[C2 G2] F#3@2] [[C2 G2] E3@2] [[C2 G2] F#3@2]
|
||||
[[B1 D3] G3@2] [[Bb1 Db3] G3@2] [[A1 C3] G3@2] [[D2 C3] F#3@2]
|
||||
|
|
@ -115,7 +114,6 @@ stack(
|
|||
[[B1 D3] G3@2] [[Bb1 Db3] G3@2] [[A1 C3] G3@2] [[D2 C3] F#3@2]
|
||||
[[F2 C3] E3@2] [[E2 B2] D3@2] [[D2 A2] C3@2] [[C2 G2] B2@2]
|
||||
[[F2 C3] E3@2] [[E2 B2] D3@2] [[Eb2 Bb2] Db3@2] [[D2 A2] C3 [F3,G2]]\`
|
||||
.color('#4C4646')
|
||||
).transpose(12).slow(48)
|
||||
.superimpose(x=>x.add(0.06)) // add slightly detuned voice
|
||||
.note()
|
||||
|
|
@ -447,58 +445,6 @@ note(
|
|||
.room(.5)
|
||||
.lpa(.125).lpenv(-2).v("8:.125").fanchor(.25)`;
|
||||
|
||||
export const hyperpop = `// "Hyperpop"
|
||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// @by Felix Roos
|
||||
|
||||
const lfo = cosine.slow(15);
|
||||
const lfo2 = sine.slow(16);
|
||||
const filter1 = x=>x.cutoff(lfo2.range(300,3000));
|
||||
const filter2 = x=>x.hcutoff(lfo.range(1000,6000)).cutoff(4000)
|
||||
const scales = cat('D3 major', 'G3 major').slow(8)
|
||||
|
||||
samples({
|
||||
bd: '344/344757_1676145-lq.mp3',
|
||||
sn: '387/387186_7255534-lq.mp3',
|
||||
hh: '561/561241_12517458-lq.mp3',
|
||||
hh2:'44/44944_236326-lq.mp3',
|
||||
hh3: '44/44944_236326-lq.mp3',
|
||||
}, 'https://cdn.freesound.org/previews/')
|
||||
|
||||
stack(
|
||||
"-7 0 -7 7".struct("x(5,8,1)").fast(2).sub(7)
|
||||
.scale(scales)
|
||||
.note()
|
||||
.s("sawtooth,square")
|
||||
.gain(.3).attack(0.01).decay(0.1).sustain(.5)
|
||||
.apply(filter1)
|
||||
.lpa(.1).lpenv(2).ftype('24db')
|
||||
,
|
||||
n("~@3 [<2 3>,<4 5>]")
|
||||
.echo(4,1/16,.7)
|
||||
.scale(scales)
|
||||
.s('square').gain(.7)
|
||||
.attack(0.01).decay(0.1).sustain(0)
|
||||
.apply(filter1),
|
||||
"6 4 2".add(14)
|
||||
.superimpose(sub("5"))
|
||||
.fast(1).euclidLegato(3,8)
|
||||
.mask("<1 0@7>")
|
||||
.fast(2).n()
|
||||
.echo(32, 1/8, .8)
|
||||
.scale(scales)
|
||||
.s("sawtooth")
|
||||
.mul(gain(sine.range(.1,.4).slow(8)))
|
||||
.attack(.001).decay(.2).sustain(0)
|
||||
.apply(filter2)
|
||||
).stack(
|
||||
stack(
|
||||
"bd <~@7 [~ bd]>".fast(2),
|
||||
"~ sn",
|
||||
"[~ hh3]*2"
|
||||
).s().fast(2).gain(.7)
|
||||
).slow(2)`;
|
||||
|
||||
export const festivalOfFingers3 = `// "Festival of fingers 3"
|
||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// @by Felix Roos
|
||||
|
|
@ -615,7 +561,7 @@ setcps(1)
|
|||
"<8(3,8) <7 7*2> [4 5@3] 8>".sub(1) // sub 1 -> 1-indexed
|
||||
.layer(
|
||||
x=>x,
|
||||
x=>x.add(7).color('steelblue')
|
||||
x=>x.add(7)
|
||||
.off(1/8,x=>x.add("2,4").off(1/8,x=>x.add(5).echo(4,.125,.5)))
|
||||
.slow(2),
|
||||
).n().scale('A1 minor')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue