From d856e567c17c04cad083850955d838e3e328e404 Mon Sep 17 00:00:00 2001 From: alex Date: Sat, 14 Jun 2025 15:22:27 +0100 Subject: [PATCH 1/3] link back to tech manual in wiki --- packages/README.md | 2 +- technical.manual.md | 193 -------------------------------------------- 2 files changed, 1 insertion(+), 194 deletions(-) delete mode 100644 technical.manual.md diff --git a/packages/README.md b/packages/README.md index a5b93d321..98938d6c3 100644 --- a/packages/README.md +++ b/packages/README.md @@ -2,4 +2,4 @@ Each folder represents one of the @strudel/* packages [published to npm](https://www.npmjs.com/org/strudel). -To understand how those pieces connect, refer to the [Technical Manual](https://codeberg.org/uzu/strudel/src/branch/main/technical-manual.md) or the individual READMEs. +To understand how those pieces connect, refer to the [Technical Manual](https://codeberg.org/uzu/strudel/wiki/Technical-Manual) or the individual READMEs. diff --git a/technical.manual.md b/technical.manual.md deleted file mode 100644 index 6068b48fe..000000000 --- a/technical.manual.md +++ /dev/null @@ -1,193 +0,0 @@ -This document introduces you to Strudel in a technical sense. If you just want to *use* Strudel, have a look at the [Tutorial](https://strudel.tidalcycles.org/tutorial/). - -## Strudel Packages - -There are different packages for different purposes. They.. - -- split up the code into smaller chunks -- can be selectively used to implement some sort of time based system - -Please refer to the individual README files in the [packages folder](https://codeberg.org/uzu/strudel/src/branch/main/packages) - -## REPL - -The [REPL](https://strudel.tidalcycles.org/) is the place where all packages come together to form a live coding system. It can also be seen as a reference implementation for users of the library. - -More info in the [REPL README](https://codeberg.org/uzu/strudel/src/branch/main/packages/repl/README.md) - -# High Level Overview - - - -## 1. End User Code - -The End User Code is written in JavaScript with added syntax sugar. The [eval package](https://codeberg.org/uzu/strudel/src/branch/main/packages/eval#strudelcycleseval) evaluates the user code -after a transpilation step, which resolves the syntax sugar. If you don't want the syntax sugar, you can omit the eval package and call the native javascript `eval` instead. - -### 🍭 Syntax Sugar - -JavaScript Transpilation = converting valid JavaScript to valid JavaScript: - -```js -"c3 [e3 g3]".fast(2) -``` - -becomes - -```js -mini('c3 [e3 g3]') - .withMiniLocation([1, 0, 0], [1, 11, 11]) // source location - .fast(2); -``` - -- double quoted strings and backtick strings are turned into `mini` calls (single quoted strings are left as is) -- The source location is added by chaining `withMiniLocation`, which enables the real time highlighting later -- (psuedo) variable names that look like notes (like `c4`, `bb2` or `fs3`) are turned into strings -- support for top level await -- operator overloading could be implemented in the future - -This is how it works: - - - -- The user code is parsed with a [shift parser](https://github.com/shapesecurity/shift-parser-js), generating an AST -- The AST is transformed to resolve the syntax sugar -- The AST is used to generate code again (shift-codegen) - -Shift will most likely be replaced with acorn in the future, see https://codeberg.org/uzu/strudel/issues/174 - -### Mini Notation - -Another important part of the user code is the mini notation, which allows to express rhythms in a short manner. - -- the mini notation is [implemented as a PEG grammar](https://codeberg.org/uzu/strudel/src/branch/main/packages/mini/krill.pegjs), living in the [mini package](https://codeberg.org/uzu/strudel/src/branch/main/packages/mini) -- it is based on [krill](https://github.com/Mdashdotdashn/krill) by Mdashdotdashn -- the peg grammar is used to generate a parser with [peggyjs](https://peggyjs.org/) -- the generated parser takes a mini notation string and outputs an AST -- the AST can then be used to construct a pattern using the regular Strudel API - -Here's an example AST: - -```json -{ - "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 } } - } - ] - }, - } - ] -} -``` - -which translates to `seq(c3, seq(e3, g3))` - -## 2. Querying & Scheduling - -When the user code has been evaluated, we hopefully get a Pattern instance, which we can use to query events from. -These events can then be used to trigger side effects in the real world. On that note, Events are mostly called Hap(s) in the codebase, because JS already has a built in `Event` class. - -### Querying - -> Querying = Asking a Pattern for Events within a certain time span - -```js -seq('c3', ['e3', 'g3']) // <--- Pattern - .queryArc(0, 2) // query events within 0 and 2 cycles - .map((hap) => hap.showWhole()); // make readable -``` - -yields - -```js -[ - '0/1 -> 1/2: c3', // cycle 0 - '1/2 -> 3/4: e3', - '3/4 -> 1/1: g3', - '1/1 -> 3/2: c3', // cycle 1 - '3/2 -> 7/4: e3', - '7/4 -> 2/1: g3', -]; -``` - -### 🗓️ Scheduling - -The scheduler will query events repeatedly, creating a possibly endless loop of time slices. -Here is a simplified example of how it works - -```js -let step = 0.5; // query interval in seconds -let tick = 0; // how many intervals have passed -let pattern = seq('c3', ['e3', 'g3']); // pattern from user -setInterval(() => { - const events = pattern.queryArc(tick * step, ++tick * step); - events.forEach((event) => { - console.log(event.showWhole()); - const o = getAudioContext().createOscillator(); - o.frequency.value = getFreq(event.value); - o.start(event.whole.begin); - o.stop(event.whole.begin + event.duration); - o.connect(getAudioContext().destination); - }); -}, step * 1000); // query each "step" seconds -``` - -## 3. Sound Output - -The third and last step is to use the scheduled events to make sound. -Patterns are wrapped with param functions to compose different properties of the sound. - -```js -note("[c2(3,8) [ bb1]]") // sets frequency - .s("") // sound source - .gain(.5) // turn down volume - .cutoff(sine.range(200,1000).slow(4)) // modulated cutoff - .slow(2) - .out().logValues()`, - ]} -/> -``` - -Here is an example Hap value with different properties: - -```js -{ note: 'a4', s: 'sawtooth', gain: 0.5, cutoff: 267 } -``` - - -
- -- Patterns represent just values in time! -- Suitable for any time based output (music, visuals, movement, .. ?) - -### Supported Outputs - -At the time of writing this doc, the following outputs are supported: - -- Web Audio API `.out()` see [/webaudio](https://codeberg.org/uzu/strudel/src/branch/main/packages/webaudio) -- MIDI `.midi()` see [/midi](https://codeberg.org/uzu/strudel/src/branch/main/packages/midi) -- OSC `.osc()` see [/osc](https://codeberg.org/uzu/strudel/src/branch/main/packages/osc) -- Serial `.serial()` see [/serial](https://codeberg.org/uzu/strudel/src/branch/main/packages/serial) -- Tone.js `.tone()` (deprecated?) [/tone](https://codeberg.org/uzu/strudel/src/branch/main/packages/tone) -- WebDirt `.webdirt()` (deprecated?) [/webdirt](https://codeberg.org/uzu/strudel/src/branch/main/packages/webdirt) -- Speech `.speak()` (experimental) part of [/core](https://codeberg.org/uzu/strudel/src/branch/main/packages/core) - -These could change, so make sure to check the [packages folder](https://codeberg.org/uzu/strudel/src/branch/main/packages). From 9738c90b82dbae40e2bf5ad2e477d464d644ccdc Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sat, 14 Jun 2025 16:23:03 +0200 Subject: [PATCH 2/3] even more degithubbing --- packages/core/test/pattern.test.mjs | 2 +- packages/repl/README.md | 2 +- paper/demo-preprocessed.md | 2 +- paper/demo.md | 2 +- paper/iclc2023.html | 6 +- paper/iclc2023.md | 2 +- .../src/components/Footer/AvatarList.astro | 169 ------------------ website/src/components/Header/Search.tsx | 2 +- .../RightSidebar/RightSidebar.astro | 1 - .../src/repl/components/panel/WelcomeTab.jsx | 2 +- 10 files changed, 10 insertions(+), 180 deletions(-) delete mode 100644 website/src/components/Footer/AvatarList.astro diff --git a/packages/core/test/pattern.test.mjs b/packages/core/test/pattern.test.mjs index 696f13fef..45a1e2a98 100644 --- a/packages/core/test/pattern.test.mjs +++ b/packages/core/test/pattern.test.mjs @@ -884,7 +884,7 @@ describe('Pattern', () => { ); }); it('Doesnt drop haps in the 9th cycle', () => { - // fixed with https://github.com/tidalcycles/strudel/commit/72eeaf446e3d5e186d63cc0d2276f0723cde017a + // fixed with https://codeberg.org/uzu/strudel/commit/72eeaf446e3d5e186d63cc0d2276f0723cde017a expect(sequence(1, 2, 3).ply(2).early(8).firstCycle().length).toBe(6); }); }); diff --git a/packages/repl/README.md b/packages/repl/README.md index 3db4cc3f7..5b43b5e79 100644 --- a/packages/repl/README.md +++ b/packages/repl/README.md @@ -17,7 +17,7 @@ You can also pin the version like this: ``` This has the advantage that your code will always work, regardless of potential breaking changes in the strudel codebase. -See [releases](https://github.com/tidalcycles/strudel/releases) for the latest versions. +See [releases](https://codeberg.org/uzu/strudel/releases) for the latest versions. ## Use Web Component diff --git a/paper/demo-preprocessed.md b/paper/demo-preprocessed.md index e22823d90..2f0871e7c 100644 --- a/paper/demo-preprocessed.md +++ b/paper/demo-preprocessed.md @@ -201,7 +201,7 @@ interfaces. The Strudel REPL is available at , including an interactive tutorial. The repository is at -, all the code is open source +, all the code is open source under the GPL-3.0 License. # Acknowledgments diff --git a/paper/demo.md b/paper/demo.md index 23fe27754..841fb6064 100644 --- a/paper/demo.md +++ b/paper/demo.md @@ -128,7 +128,7 @@ For the future, it is planned to integrate alternative sound engines such as Gli # Links The Strudel REPL is available at , including an interactive tutorial. -The repository is at , all the code is open source under the GPL-3.0 License. +The repository is at , all the code is open source under the GPL-3.0 License. # Acknowledgments diff --git a/paper/iclc2023.html b/paper/iclc2023.html index a83e075a2..3771f560b 100644 --- a/paper/iclc2023.html +++ b/paper/iclc2023.html @@ -374,7 +374,7 @@ by the output.
REPL control flow
@@ -720,8 +720,8 @@ class="header-section-number">11 Links href="https://strudel.cc" class="uri">https://strudel.cc, including an interactive tutorial. The repository is at https://github.com/tidalcycles/strudel, all the code is +href="https://codeberg.org/uzu/strudel" +class="uri">https://codeberg.org/uzu/strudel, all the code is open source under the AGPL-3.0 License.

12 Acknowledgments

diff --git a/paper/iclc2023.md b/paper/iclc2023.md index 3afb27828..fdc9f0ca4 100644 --- a/paper/iclc2023.md +++ b/paper/iclc2023.md @@ -451,7 +451,7 @@ While Haskell's type system makes it a great language for the ongoing developmen # Links The Strudel REPL is available at , including an interactive tutorial. -The repository is at , all the code is open source under the AGPL-3.0 License. +The repository is at , all the code is open source under the AGPL-3.0 License. # Acknowledgments diff --git a/website/src/components/Footer/AvatarList.astro b/website/src/components/Footer/AvatarList.astro deleted file mode 100644 index 86bbcc875..000000000 --- a/website/src/components/Footer/AvatarList.astro +++ /dev/null @@ -1,169 +0,0 @@ ---- -// fetch all commits for just this page's path -type Props = { - path: string; -}; -const { path } = Astro.props as Props; -const resolvedPath = `website/src/pages${path}.mdx`; -const url = `https://api.github.com/repos/tidalcycles/strudel/commits?path=${resolvedPath}`; -const commitsURL = `https://github.com/tidalcycles/strudel/commits/main/${resolvedPath}`; - -type Commit = { - author: { - id: string; - login: string; - }; -}; - -async function getCommits(url: string) { - try { - const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN ?? 'hello'; - if (!token) { - throw new Error('Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.'); - } - - const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`; - - const res = await fetch(url, { - method: 'GET', - headers: { - Authorization: auth, - 'User-Agent': 'astro-docs/1.0', - }, - }); - - const data = await res.json(); - - if (!res.ok) { - throw new Error( - `Request to fetch commits failed. Reason: ${res.statusText} - Message: ${data.message}`, - ); - } - - return data as Commit[]; - } catch (e) { - console.warn(`[error] /src/components/AvatarList.astro - ${(e as any)?.message ?? e}`); - return [] as Commit[]; - } -} - -function removeDups(arr: Commit[]) { - const map = new Map(); - for (let item of arr) { - const author = item.author; - // Deduplicate based on author.id - //map.set(author.id, { login: author.login, id: author.id }); - author && map.set(author.id, { login: author.login, id: author.id }); - } - - return [...map.values()]; -} - -const data = await getCommits(url); -const unique = removeDups(data); -const recentContributors = unique.slice(0, 3); // only show avatars for the 3 most recent contributors -const additionalContributors = unique.length - recentContributors.length; // list the rest of them as # of extra contributors ---- - - -
-
    - { - recentContributors.map((item) => ( -
  • - - {`Contributor - -
  • - )) - } -
- { - additionalContributors > 0 && ( - - {`and ${additionalContributors} additional contributor${ - additionalContributors > 1 ? 's' : '' - }.`} - - ) - } - {unique.length === 0 && Contributors} -
- - diff --git a/website/src/components/Header/Search.tsx b/website/src/components/Header/Search.tsx index c982d80b6..f200dc79f 100644 --- a/website/src/components/Header/Search.tsx +++ b/website/src/components/Header/Search.tsx @@ -82,7 +82,7 @@ export default function Search() { appId={ALGOLIA.appId} apiKey={ALGOLIA.apiKey} getMissingResultsUrl={({ query }) => { - return `https://github.com/tidalcycles/strudel/issues/new?title=Missing doc for ${query}`; + return `https://codeberg.org/uzu/strudel/issues/new?title=Missing%20doc%20for${encodeURIComponent(query)}`; }} transformItems={(items) => { return items.map((item) => { diff --git a/website/src/components/RightSidebar/RightSidebar.astro b/website/src/components/RightSidebar/RightSidebar.astro index cd501b1a2..28c713022 100644 --- a/website/src/components/RightSidebar/RightSidebar.astro +++ b/website/src/components/RightSidebar/RightSidebar.astro @@ -18,5 +18,4 @@ currentPage = currentPage.endsWith('/') ? currentPage.slice(0, -1) : currentPage diff --git a/website/src/repl/components/panel/WelcomeTab.jsx b/website/src/repl/components/panel/WelcomeTab.jsx index b3b167c74..cd5fe030a 100644 --- a/website/src/repl/components/panel/WelcomeTab.jsx +++ b/website/src/repl/components/panel/WelcomeTab.jsx @@ -42,7 +42,7 @@ export function WelcomeTab({ context }) { GNU Affero General Public License . You can find the source code at{' '} - + github . You can also find licensing info{' '} From ee7d7830992ee521dac2d511158c0a0f3c133ed0 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sat, 14 Jun 2025 16:27:54 +0200 Subject: [PATCH 3/3] fix homepage link --- website/src/pages/learn/getting-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/pages/learn/getting-started.mdx b/website/src/pages/learn/getting-started.mdx index 2d056d3b4..b3348ccda 100644 --- a/website/src/pages/learn/getting-started.mdx +++ b/website/src/pages/learn/getting-started.mdx @@ -14,7 +14,7 @@ These pages will introduce you to [Strudel](https://strudel.cc/), a web-based [l # What is Strudel? -[Strudel](https://strudel.cc/) is a version of [Tidal Cycles](https://tidalcycles.org) written in [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript), initiated by [Alex McLean](https://slab.org) and [Felix Roos](https://github.com/felixroos) in 2022. +[Strudel](https://strudel.cc/) is a version of [Tidal Cycles](https://tidalcycles.org) written in [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript), initiated by [Alex McLean](https://slab.org) and [Felix Roos](https://froos.cc/) in 2022. Tidal Cycles, also known as Tidal, is a language for [algorithmic pattern](https://algorithmicpattern.org), and though it is most commonly used for [making music](https://tidalcycles.org/docs/showcase), it can be used for any kind of pattern making activity, including [weaving](https://www.youtube.com/watch?v=TfEmEsusXjU). Tidal was first implemented as a library written in the [Haskell](https://www.haskell.org/) functional programming language, and by itself it does not make any sound.