diff --git a/packages/tone/pianoroll.mjs b/packages/tone/pianoroll.mjs index 9233b0407..a74effa91 100644 --- a/packages/tone/pianoroll.mjs +++ b/packages/tone/pianoroll.mjs @@ -90,6 +90,7 @@ Pattern.prototype.pianoroll = function ({ barThickness - 2, // height ]; } + coords = coords.map((c) => Math.round(c)); isActive ? ctx.strokeRect(...coords) : ctx.fillRect(...coords); }); const playheadPosition = scale(-from / timeExtent, ...timeRange); diff --git a/talk/deck.mdx b/talk/deck.mdx index 64e79b701..08a065c7f 100644 --- a/talk/deck.mdx +++ b/talk/deck.mdx @@ -10,12 +10,24 @@ import ImgTile from './ImgTile';

Algorithmic Patterns for the Web

+ + "The Analytical Engine weaves algebraic patterns, just as the Jacquard loom weaves flowers and leaves." - Ada + Lovelace + - "The Analytical Engine weaves algebraic patterns, just as the Jacquard loom weaves flowers and leaves." + “[The Analytical Engine] might act upon other things besides number, were objects found whose + mutual fundamental relations could be expressed by those of the abstract science of operations{' '} + [...] + + , and which should be also susceptible of adaptations to the action of the operating notation and mechanism of the + engine.{' '} +
- “Supposing, for instance, that the fundamental relations of pitched sounds in the science of harmony and of musical - composition were susceptible of such expression and adaptations, the [Analytical] Engine might compose elaborate and - scientific pieces of music of any degree of complexity or extent." - Ada Lovelace + Supposing, for instance, that the fundamental relations of pitched sounds in the science of harmony and of musical composition + were susceptible of such expression and adaptations, the [Analytical] Engine might compose elaborate and scientific pieces + of music of any degree of complexity or extent." +
+ -- Ada Lovelace, (1815 - 1852)
@@ -29,10 +41,11 @@ import ImgTile from './ImgTile'; - How to represent and control music with code? - How to leverage unique features of computing? - How to break loose from old conventions? +- Answer: Live Coding? - + +## Parsing Expression Grammars + +
+ +1. write [peg](https://github.com/tidalcycles/strudel/blob/main/packages/mini/krill.pegjs), generate [parser](https://github.com/tidalcycles/strudel/blob/main/packages/mini/krill-parser.js) with [parser generator](https://peggyjs.org/) +2. pass string (e.g. `c3 [e3 g3]`) to generated parser +3. obtain Abstract Syntax Tree (AST) +4. [transform](https://github.com/tidalcycles/strudel/blob/main/packages/mini/mini.mjs#L76) AST into Pattern + +
+ + + +[OhmJS Editor](https://ohmjs.org/editor/) + +
+ +## AST of `c3 [e3 g3]` + +
+ +```js +{ + "type_": "pattern", + "arguments_": { "alignment": "h" }, + "source_": [ + { + "type_": "element", "source_": "c3", + "location_": { "start": { "offset": 1, "line": 1, "column": 2 }, "end": { "offset": 4, "line": 1, "column": 5 } } + }, + { + "type_": "element", + "location_": { "start": { "offset": 4, "line": 1, "column": 5 }, "end": { "offset": 11, "line": 1, "column": 12 } } + "source_": { + "type_": "pattern", "arguments_": { "alignment": "h" }, + "source_": [ + { + "type_": "element", "source_": "e3", + "location_": { "start": { "offset": 5, "line": 1, "column": 6 }, "end": { "offset": 8, "line": 1, "column": 9 } } + }, + { + "type_": "element", "source_": "g3", + "location_": { "start": { "offset": 8, "line": 1, "column": 9 }, "end": { "offset": 10, "line": 1, "column": 11 } } + } + ] + }, + } + ] +} +``` + +
+ += `seq(c3, seq(e3, g3))` + +
+ ## Pattern Factories seq, cat, stack @@ -352,7 +430,7 @@ seq, cat, stack ## Time Control -fast / slow, early / late, rev +fast / slow, early / late, rev, palindrome ".early(.16)).late(.16) - .tone((await piano()).toDestination()) - .pianoroll()`, + `stack( + "c3 e3".color('steelblue'), + "".early(.16) +).late(.16) + .tone((await piano()).toDestination()) + .pianoroll()`, `"c3 e3 g3 bb3".rev() .tone((await piano()).toDestination()) .pianoroll()`, @@ -373,6 +454,35 @@ fast / slow, early / late, rev +## JavaScript Transpilation + +
+ +- [converting](https://github.com/tidalcycles/strudel/blob/main/packages/eval/shapeshifter.mjs#L40) valid JavaScript to valid JavaScript + + + +
+
+ +Before (User Code) +After (Ready to Eval) + +
{`"c3 e3"
+  .fast(2)`}
+ +
{`mini('c3 e3')
+  .withMiniLocation([1,0,0],[1,7,7])
+  .fast(2)`}
+ +
+ +
+ +[Blog Post](https://loophole-letters.vercel.app/shift-ast), [AST Explorer](https://astexplorer.net/) + +
+ ## Arithmetic & Patternified Params add, sub, mul, div @@ -381,7 +491,7 @@ add, sub, mul, div code={[ `"30,42 45 49 54".add(0) .tone((await piano()).toDestination()) - .pianoroll({autorange:0,minMidi:30,maxMidi:56})`, + .pianoroll({autorange:0,minMidi:28,maxMidi:56})`, `"30,42 45 49 54".add("<0 1 2 1>/2") .tone((await piano()).toDestination()) .pianoroll({fold:1,cycles:8})`, @@ -440,6 +550,14 @@ sine / saw / tri / square / rand / perlin, range, segment .range(42,54).slow(4).segment(8) .pianoroll({ minMidi:42, maxMidi: 54, autorange:0, cycles:8,fold:0,inactive:'orange'})`, + `s("hh*8").speed(sine.range(.5,2).slow(4)) + .webdirt()`, + `sine.range(42,50).color('#00ff0050') + .superimpose(x=>x.fast(3/2).color('#ff00ff50')) + .fast(1) + .segment(64) + .pianoroll({fold:0,vertical:0,cycles:2}) +// strudel disable-highlighting`, ]} /> @@ -461,7 +579,7 @@ sine / saw / tri / square / rand / perlin, range, segment ]} /> - + -## Continuous Signals +## Chord Voicings + +chord dictionaries + smooth voice leading (blog post) x.fast(3/2).color('#ff00ff50')) - .fast(1) - .segment(64) - .pianoroll({fold:0,vertical:0,cycles:2}) -// strudel disable-highlighting`, - ]} -/> - - - - - -## Chords and Scales - -] E2") + .slow(4) + .tone((await piano()).toDestination()) + .pianoroll({cycles:8,fold:1,inactive:'orange'})`, + `// froos - giant steps, stride version stack( // melody seq( @@ -582,7 +688,60 @@ stack( "[B2 F#2] [F2 Bb2] [Eb2 Bb2] [C#2 F#2]" ) .struct("x ~".fast(4*8)) -).slow(25)`]}/> +).slow(25) + .tone((await piano()).toDestination()) + .pianoroll({cycles:8,fold:1,inactive:'orange'})`]}/> + + +## Strudel Packages + +`npm i @strudel.cycles/*`, where \* is one of: + +
+ +- core: tidal pattern engine +- mini: mini notation parser + core binding +- eval: user code evaluator. syntax sugar + highlighting +- tone: bindings for Tone.js instruments and effects +- osc: bindings to communicate via OSC +- midi: webmidi bindings +- serial: webserial bindings +- tonal: tonal functions +- xen: microtonal / xenharmonic functions +- ... there are [more](https://github.com/tidalcycles/strudel/tree/main/packages) + +
+ +
+ +## Workflow + +
+ +- Everything is in one [monorepo](https://github.com/tidalcycles/strudel) +- Development via npm workspaces +- Packages are published with lerna +- REPL is Deployed to github pages +- Features are added with Pull Requests +- Automated tests run for every PR +- Snapshot tests + +
+ +
+ +## Tech Stack + +
+ +- REPL: Codemirror 6 + react + tailwind +- Everything is built with vite +- In source documentation with jsdoc +- Tutorial written with MDX +- jsdoc is inserted into MDX with nunjucks + +
+
diff --git a/talk/public/pegflow.png b/talk/public/pegflow.png new file mode 100644 index 000000000..615d48180 Binary files /dev/null and b/talk/public/pegflow.png differ diff --git a/talk/public/shiftflow.png b/talk/public/shiftflow.png new file mode 100644 index 000000000..8d91658dc Binary files /dev/null and b/talk/public/shiftflow.png differ