From 0bb89d1a9f26b6bcecae3bf4694731bc47965437 Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Wed, 19 Nov 2025 20:09:14 +0100 Subject: [PATCH 01/30] New page FAQ in "More" --- website/src/config.ts | 1 + website/src/pages/learn/faq.mdx | 403 ++++++++++++++++++++++++++++++++ 2 files changed, 404 insertions(+) create mode 100644 website/src/pages/learn/faq.mdx diff --git a/website/src/config.ts b/website/src/config.ts index f335b272e..eb39d2958 100644 --- a/website/src/config.ts +++ b/website/src/config.ts @@ -76,6 +76,7 @@ export const SIDEBAR: Sidebar = { { text: 'MIDI & OSC', link: 'learn/input-output' }, ], More: [ + { text: 'FAQ', link: 'learn/faq' }, { text: 'Recipes', link: 'recipes/recipes' }, { text: 'Mini-Notation', link: 'learn/mini-notation' }, { text: 'Visual Feedback', link: 'learn/visual-feedback' }, diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx new file mode 100644 index 000000000..30f2986bd --- /dev/null +++ b/website/src/pages/learn/faq.mdx @@ -0,0 +1,403 @@ +--- +title: Frequently Asked Questions +layout: ../../layouts/MainLayout.astro +--- + +import { MiniRepl } from '../../docs/MiniRepl'; +import { JsDoc } from '../../docs/JsDoc'; + +# Frequently Asked Questions + +This page contains frequently asked questions. Usually, the topic is explained in more detail in a section which is linked in the answer. This page's aim is to give an overview over topics which are important to the users of strudel. + +## Is Strudel/Tidal free? + +Yes - there is no charge, this is a collective open source project, and the music you make with it is your own. + +However there are some caveats - the source code must stay free, i.e. you cannot distribute strudel or tidal as part of projects with incompatible licenses - see the [license]() for details. The contributed examples and tracks are also separately licensed, and must not e.g. be used to train AI models without permission. + +## How to record or export audio? + +There are multiple ways to record the audio -- and video -- output of Strudel: + - capture the raw stereo signal coming out of your web browser. + - use the alternative SuperDirt audio engine. Read [this page](/learn/input-output/#oscsuperdirtstrudeldirt) to know more about it. + - capture the audio/video stream using a capture tool such as [OBS](). + - don't record anything and code it again in front of your friends. + +You will need an external audio editor/DAW such as Reaper/Audacity/Ardour, etc. Strudel itself does not have functionality for exporting stems / individual tracks to an audio or midi file. Strudel is not a digital audio workstation and does not operate following the same principles shared by most traditional audio softwares. + +## Can I use strudel with my IDE? + +Yes you can. There are experimental modes, made by community members, for several IDEs such as: + - VS Code: [Strudel VS](): an experimental mode for Microsoft VSCode. A revived version of [TidalStrudel](), which is defunct. + - nvim: [strudel.nvim](https://github.com/gruvw/strudel.nvim) + +## How can I record samples? + +You can use your own samples with Strudel. There are multiple ways to load your sample collection. Some methods are good for quick experimentation, some others are good to share your audio collection with other musicians: + + - Import folders [from the interface](/learn/samples/#from-disk-via-import-sounds-folder) + - Host your sound library e.g. on github and [load them from an URL](/learn/samples/#loading-custom-samples) + +## Can I use Strudel with AI/LLM tools? + +You are free to do what you like with Strudel, within the terms of the free/open source AGPLv3 license. However as a community we are interested in exploring human creativity. AI is *way* over-hyped right now, including by people with very shady motives. Many in the community are very wary of people training models on their tunes that they've poured their love into. So please keep discussion and questions around AI and LLMs to channels dedicated to the topic and be fully respectful of other people's work. + +Furthermore, tools like ChatGPT generally give wrong answers. Please don't ask the community to fix those answers for you, as generally they will be timewasting nonsense. + +Human questions only! + +## How to run offline? + +Strudel works offline just fine! There are multiple techniques to run it yourself, see [this explanation](learn/pwa/#using-strudel-offline). + +## How to change tempo? How do I translate BPM to cpm? + +If you have your tempo in beats per minute and use 4 beats per cycle (e.g. if your track is in 4/4ths) then you can do `setcpm(BPM/4)` where BPM is your beats per minute. + +If you have a different number of beats per bar or are using more or less beats per cycle (e.g. If you want to put only half a bar or two bars into one cycle), adjust accordingly. + +## Where can I see all the functions? + +If you pop open the sidetab of strudel.cc (small white < on the right hand side), there is a tab "reference" which lists all the functions of strudel. + +## Where can I see all the samples and synths? + +If you pop open the sidetab of strudel.cc (small white < on the right hand side), there is a tab "sounds" which lists all the drum machines, samples and synths currently loaded. + +## How do I use this exactly like a DAW? + +Short answer: you don't. + +Long answer: you can use Strudel to work along your creative work in a DAW. There are many ways to do so. + +If you want to emulate the functionality of a DAW in a live coding language, you'll have to identify the operations executed by the DAW (sequencing, repeating, applying filters and envelopes) and write code that is equivalent to these operations. You might then find that the typical DAW workflow is not really adapted to live coding (because, despite both being ways of making music on the computer, they are two very different tools) and adapt your way of proceeding to the medium of code. This might mean leaving more place to serendipity and writing code that you don't predict the output of. + +## Why doesn't everyone just use a DAW? + +There is no easy answer to this question. Here are some thoughts: + - Live coding tools such as Strudel are excellent for improvising music and visuals using a computer. DAWs are valuable and robust companions for other activities such as producing, mastering and mixing audio, among other usages. Using a tool does not exclude from using any another tool, just build a toolbox. + - Live coding has been practiced for quite some time as a performative activity. Artists like to show their screens while playing in front of an audience. It is an essential part of what they do, of the way they share their activity with everybody. + - Code is a human language, it is made for other humans to read it. You can read the code and enjoy the music too. It has meaning, value, and there might even be something poetic/important about it! + - Strudel is free and open source, you can inspect the code, reshape it, contribute to it if you can/want. It is not opaque and this matters for many people. There is no black box, no obscure abstractions, no business model or hidden features. We need open tools in the arts! + - Live coders don't shy away from using DAWs. They use them all of the time, especially when it makes their life easier for... live coding! + - Code is an artistic material like any other. There is something valuable in the process of making music through code. More generally speaking, it is nice to tackle creative problems through the use of a programming language: creative thinking, building up your own solutions, DIY approach to music-making, unexpected outcome of algorithms, funny human errors, etc. + - There are pianos and trumpets in your DAW: why do people continue playing the piano or the trumpet? Think of live coding tools as instruments that you activate through the act of programming. + +## Is it more efficient to use Strudel than a DAW? + +Strudel was not build to be a DAW, yet it can still be used to make covers, arrange tracks, or prepare patterns for jamming. When playing concerts or jamming, some livecoders prepare their code, some perform from scratch. + +It might be interesting for you to check out for yourself how strudel can be used to express yourself creatively. Also you are free to combine a language like Strudel with a DAW. + +## How can I interface Strudel with my favorite music software? What can I do with it? + +Strudel can send [MIDI and OSC](/learn/input-output/), which are protocols for communicating musical information. + +Another music software (or hardware!) can then listen to these messages and process them according to its capabilities. + +A simple example would be to send livecoded audio to Ableton on different tracks and then use it to mix them. + +You could also send the MIDI of a sequenced pattern to Musescore and then have it transcribe your livecoded work as a musical score. + +You could also send MIDI to your hardware synths because you think they sound better than the software synths built-in Strudel. + +## How do I use this in my closed source webgame? + +You don't. You would need to re-license your game to AGPLv3 to fulfill the license Strudel is distributed under. + +## Where can I download loads of patterns to train my LLM? + +You cannot, as there is no such place. For details regarding our stance towards AI/LLM, see [above](/learn/faq/#can-i-use-strudel-with-aillm-tools) + +## How to play different patterns simultaneously? + +Using the $ operator, several patterns can be played at once: + + +See also [stack](intro/#combining-patterns) + +## Is it possible to mute a pattern? + +With an additional underscore, a pattern can be muted. + + + +See also [hush](/learn/conditional-modifiers/#hush) + +## How can I arrange in Strudel using `mask`? + +With mini-notation, using the `<>` and `!` operators, you can try something like +``` +.mask("<0!24 1!40>") +``` +It mutes a pattern for 24 cycles and plays it for 40. You would gain 64 cycles total, a multiple of 2/4/8 commonly used in western music. + +If each cycle is a bar, as a starting point, you could write a mask like that for any pattern: +``` +.mask("<0!16 0!16 0!16 0!16 0!16 0!10>") +``` +It mutes it throughout. + +For arranging, you could add the same mask to each part and replace some zeroes with ones in your different masks to make parts play. + +If you use `.mask()` on different patterns mess up your counting, then patterns do not align anymore. +On the other hand, doing that on purpose is one of the things that could be considered a strength of tidalcycles and Strudel. +You can make things quite lively and more organic with a little (controlled) interference, according to your own taste. +And you are free to arrange in cycles like 3, 6 or 9 too. + +To modify everything at once, you could try all and when, for example: + +``` +all(x=>x.when("<0!7 1>", x=>x.lpf(saw.range(200, 2000)))) +``` + +This would lowpass filter sweep everything every 8 cycles. + +## How can I arrange in Strudel using `arrange` or `pick`? + +Take [Pachelbel's Canon in D](https://en.wikipedia.org/wiki/Pachelbel%27s_Canon#Analysis) as an example which has 4 voices (one cello and 3 violins) which have repeating patterns, as seen in the link above. + +The following snipped defines the patterns as constants which can then be used for the different voices. `arrange` takes multiple arguments, which are each a number of cycles and a pattern which is played for the number of cycles, wrapped in `[]` If the pattern is shorter than the number, it is repeated. +") + .color("grey").sound("gm_tremolo_strings:3") + const violin_p1 = note( + "<[f#5 e5 d5 c#5] [b4 a4 b4 c#5]>") + .color("blue") + const violin_p2 = note( + "<[d5 c#5 b4 a4] [ g4 f#4 g4 f#4]>") + .color("green") + const violin_p3 = note( + "<[d4 f#4 a4 g4 f#4 d4 f#4 e4] [d4 b3 d4 a4 g4 b4 a4 g4]>") + .color("purple") + const violin_p4 = note( + "<[f#4 d4 e4 c#5 d5 f#5 a5 a4] [b4 g4 a4 f#4 d4 d5 [d5@3 c#5]@2]>") + .color("red") + + + cello$: arrange( + [2, silence], + [18,cello]) + violin1$: arrange( + [4,silence], + [2,violin_p1], [2,violin_p2], + [2,violin_p3], [2,violin_p4], + [2,violin_p1], [2,violin_p2], + [2,violin_p3], [2,violin_p4] + ).sound("gm_tremolo_strings:0") + violin2$: arrange( + [6,silence], [2,violin_p1], + [2,violin_p2], [2,violin_p3], + [2,violin_p4], [2,violin_p1], + [2,violin_p2], [2,violin_p3] + ).sound("gm_tremolo_strings:1") + violin3$: arrange( + [8,silence], + [2,violin_p1], [2,violin_p2], + [2,violin_p3], [2,violin_p4], + [2,violin_p1], [2,violin_p2] + ).sound("gm_tremolo_strings:2") + + all(x => x.release(.2)) +`} /> + +Alternatively, you can also put the different patterns for the violins into one single array (`const violins = [violin_p1, violin_p2, violin_p3, violin_p4]`) and use a pattern as an index to `pick` the nth element of that array. This replaces the voices defined above. Here you use `0@2` to specifiy that the first item (i.e. with index `0`) is played for `2` cycles. + +`pick` has better highlighting than `arrange`: + +") + .color("grey").sound("gm_tremolo_strings:3") + const violin_p1 = note( + "<[f#5 e5 d5 c#5] [b4 a4 b4 c#5]>") + .color("blue") + const violin_p2 = note( + "<[d5 c#5 b4 a4] [ g4 f#4 g4 f#4]>") + .color("green") + const violin_p3 = note( + "<[d4 f#4 a4 g4 f#4 d4 f#4 e4] [d4 b3 d4 a4 g4 b4 a4 g4]>") + .color("purple") + const violin_p4 = note( + "<[f#4 d4 e4 c#5 d5 f#5 a5 a4] [b4 g4 a4 f#4 d4 d5 [d5@3 c#5]@2]>") + .color("red") + +const violins = [violin_p1, violin_p2, violin_p3, violin_p4] + +cello$: "<~@2 0@18>".pick([cello]) +violin1$: "<~@4 0@2 1@2 2@2 3@2 0@2 1@2 2@2 3@2>".pick(violins) +.sound("gm_tremolo_strings:0") +violin2$: "<~@6 0@2 1@2 2@2 3@2 0@2 1@2 2@2>".pick(violins) +.sound("gm_tremolo_strings:1") +violin3$: "<~@8 0@2 1@2 2@2 3@2 0@2 1@2 >".pick(violins) +.sound("gm_tremolo_strings:2") +all(x => x.release(.2)) +`} /> + +The `pick` method also works with jsons which have named elements, which makes it easier to read, see the [here](/learn/conditional-modifiers/#pick). `pickRestart` restarts the pattern upon picking it which can make a difference if the duration of the pick indexes doesn't line up with the patterns which are picked - which is not the case here. + +Try adding `.punchcard()` after the `release(.2)` for a visualization. + +## I saw Switch Angel using functions which I cannot find in the reference (e.g. `trancegate`). How do I make it work? + +Methods like `trancegate()`, `rlpf()` and `acidenv()` are currently not pattern methods which come natively with strudel. + +It's part of a script for strudel which was written by Switch Angel and published [here](https://github.com/switchangel/strudel-scripts/blob/main/allscripts.js) + +Note that this script defines functions and registers methods which `trancegate()` will depend on so just pasting the `trancegate()` method from that script alone will not suffice, but you will also need the `fill` method. + +If you copy the full script into your strudel, be mindful of lines which try to load local samples - these should be deleted or prefixed with `//` as a comment. + +If you paste these functions into your strudel session, hit "Update" and delete the source of the functions, the functions will still be availabe until you do a browser refresh. + +## Is there difference between `n` and `note`? + +They are not aliases of each other, in contrast to `s` and `sound`. + +The method `note` is used to reference a certain note (either as its name, such as `c` or `b2` or the midi number `69`, for example `note("c3 e3 g3")`). + +On the other hand, `n` is a way to reference the nth index of something. This something can be a scale (eg `n("0 2 4").scale("C:major")`) , but it can also be a particular note in a chord (see https://strudel.cc/recipes/recipes/#arpeggios for an example) . + +The method `n` can also be used for something completely unrelated to notes like the nth sample from a sample map `s("hh*8").bank("RolandTR909").n("0 1 2 3")`. Note that `pick` does *not* use `n`. + +".pickRestart([ + n("0 1 2 0"), + n("2 3 4 ~"), + n("[4 5] [4 3] 2 0"), + n("0 -3 0 ~") + ]).scale("C:major").s("piano")`} /> + + +## Is there a cheat sheet for all symbols? + +Yes! + +``` +' marks start and end of strings, is different from " +" marks start and end of single line patterns in mini notation, is different from ' +` marks start and end of patterns with line breaks in mini notation, is different from ' +[] used for patterns, each item in it has the same length +<> used for patterns, alternates each item each cycle +{} historically used for polyrhythmic patterns. {a b c}%4 is the same as *4. +@3 elongates the item by a factor of 3 (other numbers work too) +@ after an item: elongates the item once (multiple @ work too c @ @ is the same as c@3) +_ after an item: also elongates an item once (multiple _ work too c _ _ is the same as c@3) +. this divides equal parts of a pattern and is called a foot. Can be used instead of [] like this: "1 6 7 8 . 2 . 3 . 4" is the same as "[1 6 7 8] 2 3 4" +- silence +~ also silence +x not silence (for the use in struct, same as 1) +s increase a note of a scale by one semitone, i.e. sharp +b decrease a note of a scale by one semitone, i.e. flat +# used in mondo notation +# also used for names of chords, like F# +*3 play the sample or pattern at thrice the speed, fast(3) +!3 play the sample or pattern three times +/2 play the sample or pattern at half speed, slow(2) +? play the pattern sometimes +| once per cycle, choose randomly a pattern of those separated by i.e. chooseCycles() +, play all items separated by it at the same time, i.e. stack() +: is used to separate multiple parameters, such as adsr(".1:.1:.5:.2") +$: at the start of a line, defines a member of the stack. is the only stack name that should occur multiple names +_ before a stack name: mutes the stack, i.e. hush(), for example _$: s("bd") +``` + +## Are there more FAQ items? + +These pages have been taken from [this pad](https://doc.patternclub.org/_CgofWouTciXXHexUP9AVg?both). Some of the items there have not been brushed up and brought here. + +These include the following items: 9, 11, 12 and 19 + +# Coding Syntax (old Content from code) + +Let's take a step back and understand how the syntax in Strudel works. + +Take a look at this simple example: + + + +- We have a word `note` which is followed by some brackets `()` with some words/letters/numbers inside, surrounded by quotes `"c a f e"` +- Then we have a dot `.` followed by another similar piece of code `s("piano")`. +- We can also see these texts are _highlighted_ using colours: word `note` is purple, the brackets `()` are grey, and the content inside the `""` are green. (The colors could be different if you've changed the default theme) + +What happens if we try to 'break' this pattern in different ways? + + + + + + + +Ok, none of these seem to work... + + + +This one does work, but now we only hear the first note... + +So what is going on here? + +# Functions, arguments and chaining + +So far, we've seen the following syntax: + +``` +xxx("foo").yyy("bar") +``` + +Generally, `xxx` and `yyy` are called [_functions_](), while `foo` and `bar` are called function [_arguments_ or _parameters_](). +So far, we've used the functions to declare which aspect of the sound we want to control, and their arguments for the actual data. +The `yyy` function is called a [_chained_ function](https://en.wikipedia.org/wiki/Method_chaining), because it is preceded with a dot (`.`). + +Generally, the idea with chaining is that code such as `a("this").b("that").c("other")` allows `a`, `b` and `c` functions to happen in a specified order, without needing to write them as three separate lines of code. +You can think of this as being similar to chaining audio effects together using guitar pedals or digital audio effects. + +Strudel makes heavy use of chained functions. Here is a more sophisticated example: + + + +## Write your own chained function + +You can write your own chained function using `register`. Here's the above chain but registered as a reusable, chained function. + + pat + .s("sawtooth") + .cutoff(500) + //.delay(0.5) + .room(0.5) + ) +note("a3 c#4 e4 a4").effectChain()`} +/> + +Try adding `.rev()` after `effectChain()` to hear further effects added. + +# Comments + +The `//` in the example above is a line comment, resulting in the `delay` function being ignored. +It is a handy way to quickly turn code on and off. +Try uncommenting this line by deleting `//` and refreshing the pattern. +You can also use the keyboard shortcut `cmd-/` to toggle comments on and off. + +You might noticed that some comments in the REPL samples include some words starting with a "@", like `@by` or `@license`. +Those are just a convention to define some information about the music. We will talk about it in the [Music metadata](/learn/metadata) section. + +# Strings + +Ok, so what about the content inside the quotes (e.g. `"c a f e"`)? +In JavaScript, as in most programming languages, this content is referred to as being a [_string_](). +A string is simply a sequence of individual characters. +In TidalCycles, double quoted strings are used to write _patterns_ using the mini-notation, and you may hear the phrase _pattern string_ from time to time. +If you want to create a regular string and not a pattern, you can use single quotes, e.g. `'C minor'` will not be parsed as Mini Notation. + +The good news is, that this covers most of the JavaScript syntax needed for Strudel! + +
From 371e6c7d6d4f1fdd780c6a07302049ae069c1a08 Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Wed, 19 Nov 2025 20:17:19 +0100 Subject: [PATCH 02/30] tidy up FAQ --- website/src/pages/learn/faq.mdx | 93 --------------------------------- 1 file changed, 93 deletions(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index 30f2986bd..dbce4c701 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -308,96 +308,3 @@ _ before a stack name: mutes the stack, i.e. hush(), for example _$: s("bd") These pages have been taken from [this pad](https://doc.patternclub.org/_CgofWouTciXXHexUP9AVg?both). Some of the items there have not been brushed up and brought here. These include the following items: 9, 11, 12 and 19 - -# Coding Syntax (old Content from code) - -Let's take a step back and understand how the syntax in Strudel works. - -Take a look at this simple example: - - - -- We have a word `note` which is followed by some brackets `()` with some words/letters/numbers inside, surrounded by quotes `"c a f e"` -- Then we have a dot `.` followed by another similar piece of code `s("piano")`. -- We can also see these texts are _highlighted_ using colours: word `note` is purple, the brackets `()` are grey, and the content inside the `""` are green. (The colors could be different if you've changed the default theme) - -What happens if we try to 'break' this pattern in different ways? - - - - - - - -Ok, none of these seem to work... - - - -This one does work, but now we only hear the first note... - -So what is going on here? - -# Functions, arguments and chaining - -So far, we've seen the following syntax: - -``` -xxx("foo").yyy("bar") -``` - -Generally, `xxx` and `yyy` are called [_functions_](), while `foo` and `bar` are called function [_arguments_ or _parameters_](). -So far, we've used the functions to declare which aspect of the sound we want to control, and their arguments for the actual data. -The `yyy` function is called a [_chained_ function](https://en.wikipedia.org/wiki/Method_chaining), because it is preceded with a dot (`.`). - -Generally, the idea with chaining is that code such as `a("this").b("that").c("other")` allows `a`, `b` and `c` functions to happen in a specified order, without needing to write them as three separate lines of code. -You can think of this as being similar to chaining audio effects together using guitar pedals or digital audio effects. - -Strudel makes heavy use of chained functions. Here is a more sophisticated example: - - - -## Write your own chained function - -You can write your own chained function using `register`. Here's the above chain but registered as a reusable, chained function. - - pat - .s("sawtooth") - .cutoff(500) - //.delay(0.5) - .room(0.5) - ) -note("a3 c#4 e4 a4").effectChain()`} -/> - -Try adding `.rev()` after `effectChain()` to hear further effects added. - -# Comments - -The `//` in the example above is a line comment, resulting in the `delay` function being ignored. -It is a handy way to quickly turn code on and off. -Try uncommenting this line by deleting `//` and refreshing the pattern. -You can also use the keyboard shortcut `cmd-/` to toggle comments on and off. - -You might noticed that some comments in the REPL samples include some words starting with a "@", like `@by` or `@license`. -Those are just a convention to define some information about the music. We will talk about it in the [Music metadata](/learn/metadata) section. - -# Strings - -Ok, so what about the content inside the quotes (e.g. `"c a f e"`)? -In JavaScript, as in most programming languages, this content is referred to as being a [_string_](). -A string is simply a sequence of individual characters. -In TidalCycles, double quoted strings are used to write _patterns_ using the mini-notation, and you may hear the phrase _pattern string_ from time to time. -If you want to create a regular string and not a pattern, you can use single quotes, e.g. `'C minor'` will not be parsed as Mini Notation. - -The good news is, that this covers most of the JavaScript syntax needed for Strudel! - -
From 69c5df67f5cb01ca372afc3d42f3cd23f2985d62 Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Wed, 19 Nov 2025 21:40:48 +0100 Subject: [PATCH 03/30] FAQ is now prettier --- website/src/pages/learn/faq.mdx | 134 +++++++++++++++++++------------- 1 file changed, 78 insertions(+), 56 deletions(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index dbce4c701..923bb5f66 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -12,16 +12,20 @@ This page contains frequently asked questions. Usually, the topic is explained i ## Is Strudel/Tidal free? -Yes - there is no charge, this is a collective open source project, and the music you make with it is your own. +Yes - there is no charge, this is a collective open source project, and the music you make with it is your own. -However there are some caveats - the source code must stay free, i.e. you cannot distribute strudel or tidal as part of projects with incompatible licenses - see the [license]() for details. The contributed examples and tracks are also separately licensed, and must not e.g. be used to train AI models without permission. +However there are some caveats - the source code must stay free, i.e. you cannot distribute strudel or tidal as part of projects with incompatible licenses - see the [license](https://www.gnu.org/licenses/agpl-3.0.en.html) for details. The contributed examples and tracks are also separately licensed, and must not e.g. be used to train AI models without permission. ## How to record or export audio? There are multiple ways to record the audio -- and video -- output of Strudel: + - capture the raw stereo signal coming out of your web browser. + - use the alternative SuperDirt audio engine. Read [this page](/learn/input-output/#oscsuperdirtstrudeldirt) to know more about it. + - capture the audio/video stream using a capture tool such as [OBS](). + - don't record anything and code it again in front of your friends. You will need an external audio editor/DAW such as Reaper/Audacity/Ardour, etc. Strudel itself does not have functionality for exporting stems / individual tracks to an audio or midi file. Strudel is not a digital audio workstation and does not operate following the same principles shared by most traditional audio softwares. @@ -29,9 +33,10 @@ You will need an external audio editor/DAW such as Reaper/Audacity/Ardour, etc. ## Can I use strudel with my IDE? Yes you can. There are experimental modes, made by community members, for several IDEs such as: - - VS Code: [Strudel VS](): an experimental mode for Microsoft VSCode. A revived version of [TidalStrudel](), which is defunct. - - nvim: [strudel.nvim](https://github.com/gruvw/strudel.nvim) - + +- VS Code: [Strudel VS](https://marketplace.visualstudio.com/items?itemName=cmillsdev.strudelvs): an experimental mode for Microsoft VSCode. A revived version of [TidalStrudel](https://marketplace.visualstudio.com/items?itemName=roipoussiere.tidal-strudel), which is defunct. +- nvim: [strudel.nvim](https://github.com/gruvw/strudel.nvim) + ## How can I record samples? You can use your own samples with Strudel. There are multiple ways to load your sample collection. Some methods are good for quick experimentation, some others are good to share your audio collection with other musicians: @@ -41,10 +46,10 @@ You can use your own samples with Strudel. There are multiple ways to load your ## Can I use Strudel with AI/LLM tools? -You are free to do what you like with Strudel, within the terms of the free/open source AGPLv3 license. However as a community we are interested in exploring human creativity. AI is *way* over-hyped right now, including by people with very shady motives. Many in the community are very wary of people training models on their tunes that they've poured their love into. So please keep discussion and questions around AI and LLMs to channels dedicated to the topic and be fully respectful of other people's work. +You are free to do what you like with Strudel, within the terms of the free/open source AGPLv3 license. However as a community we are interested in exploring human creativity. AI is _way_ over-hyped right now, including by people with very shady motives. Many in the community are very wary of people training models on their tunes that they've poured their love into. So please keep discussion and questions around AI and LLMs to channels dedicated to the topic and be fully respectful of other people's work. Furthermore, tools like ChatGPT generally give wrong answers. Please don't ask the community to fix those answers for you, as generally they will be timewasting nonsense. - + Human questions only! ## How to run offline? @@ -53,7 +58,7 @@ Strudel works offline just fine! There are multiple techniques to run it yoursel ## How to change tempo? How do I translate BPM to cpm? -If you have your tempo in beats per minute and use 4 beats per cycle (e.g. if your track is in 4/4ths) then you can do `setcpm(BPM/4)` where BPM is your beats per minute. +If you have your tempo in beats per minute and use 4 beats per cycle (e.g. if your track is in 4/4ths) then you can do `setcpm(BPM/4)` where BPM is your beats per minute. If you have a different number of beats per bar or are using more or less beats per cycle (e.g. If you want to put only half a bar or two bars into one cycle), adjust accordingly. @@ -68,21 +73,24 @@ If you pop open the sidetab of strudel.cc (small white < on the right hand side) ## How do I use this exactly like a DAW? Short answer: you don't. - + Long answer: you can use Strudel to work along your creative work in a DAW. There are many ways to do so. - + If you want to emulate the functionality of a DAW in a live coding language, you'll have to identify the operations executed by the DAW (sequencing, repeating, applying filters and envelopes) and write code that is equivalent to these operations. You might then find that the typical DAW workflow is not really adapted to live coding (because, despite both being ways of making music on the computer, they are two very different tools) and adapt your way of proceeding to the medium of code. This might mean leaving more place to serendipity and writing code that you don't predict the output of. ## Why doesn't everyone just use a DAW? -There is no easy answer to this question. Here are some thoughts: - - Live coding tools such as Strudel are excellent for improvising music and visuals using a computer. DAWs are valuable and robust companions for other activities such as producing, mastering and mixing audio, among other usages. Using a tool does not exclude from using any another tool, just build a toolbox. - - Live coding has been practiced for quite some time as a performative activity. Artists like to show their screens while playing in front of an audience. It is an essential part of what they do, of the way they share their activity with everybody. - - Code is a human language, it is made for other humans to read it. You can read the code and enjoy the music too. It has meaning, value, and there might even be something poetic/important about it! - - Strudel is free and open source, you can inspect the code, reshape it, contribute to it if you can/want. It is not opaque and this matters for many people. There is no black box, no obscure abstractions, no business model or hidden features. We need open tools in the arts! - - Live coders don't shy away from using DAWs. They use them all of the time, especially when it makes their life easier for... live coding! - - Code is an artistic material like any other. There is something valuable in the process of making music through code. More generally speaking, it is nice to tackle creative problems through the use of a programming language: creative thinking, building up your own solutions, DIY approach to music-making, unexpected outcome of algorithms, funny human errors, etc. - - There are pianos and trumpets in your DAW: why do people continue playing the piano or the trumpet? Think of live coding tools as instruments that you activate through the act of programming. +There is no easy answer to this question. Here are some thoughts: + +- Live coding tools such as Strudel are excellent for improvising music and visuals using a computer. DAWs are valuable and robust companions for other activities such as producing, mastering and mixing audio, among other usages. Using a tool does not exclude from using any another tool, just build a toolbox. + +- Live coding has been practiced for quite some time as a performative activity. Artists like to show their screens while playing in front of an audience. It is an essential part of what they do, of the way they share their activity with everybody. + +- Code is a human language, it is made for other humans to read it. You can read the code and enjoy the music too. It has meaning, value, and there might even be something poetic/important about it! - Strudel is free and open source, you can inspect the code, reshape it, contribute to it if you can/want. It is not opaque and this matters for many people. There is no black box, no obscure abstractions, no business model or hidden features. We need open tools in the arts! - Live coders don't shy away from using DAWs. They use them all of the time, especially when it makes their life easier for... live coding! + +- Code is an artistic material like any other. There is something valuable in the process of making music through code. More generally speaking, it is nice to tackle creative problems through the use of a programming language: creative thinking, building up your own solutions, DIY approach to music-making, unexpected outcome of algorithms, funny human errors, etc. + +- There are pianos and trumpets in your DAW: why do people continue playing the piano or the trumpet? Think of live coding tools as instruments that you activate through the act of programming. ## Is it more efficient to use Strudel than a DAW? @@ -96,11 +104,11 @@ Strudel can send [MIDI and OSC](/learn/input-output/), which are protocols for c Another music software (or hardware!) can then listen to these messages and process them according to its capabilities. -A simple example would be to send livecoded audio to Ableton on different tracks and then use it to mix them. +A simple example would be to send livecoded audio to Ableton on different tracks and then use it to mix them. You could also send the MIDI of a sequenced pattern to Musescore and then have it transcribe your livecoded work as a musical score. -You could also send MIDI to your hardware synths because you think they sound better than the software synths built-in Strudel. +You could also send MIDI to your hardware synths because you think they sound better than the software synths built-in Strudel. ## How do I use this in my closed source webgame? @@ -113,8 +121,12 @@ You cannot, as there is no such place. For details regarding our stance towards ## How to play different patterns simultaneously? Using the $ operator, several patterns can be played at once: - + + See also [stack](intro/#combining-patterns) @@ -122,29 +134,36 @@ See also [stack](intro/#combining-patterns) With an additional underscore, a pattern can be muted. - + See also [hush](/learn/conditional-modifiers/#hush) ## How can I arrange in Strudel using `mask`? -With mini-notation, using the `<>` and `!` operators, you can try something like +With mini-notation, using the `<>` and `!` operators, you can try something like + ``` .mask("<0!24 1!40>") ``` + It mutes a pattern for 24 cycles and plays it for 40. You would gain 64 cycles total, a multiple of 2/4/8 commonly used in western music. If each cycle is a bar, as a starting point, you could write a mask like that for any pattern: + ``` -.mask("<0!16 0!16 0!16 0!16 0!16 0!10>") +.mask("<0!16 0!16 0!16 0!16 0!16 0!10>") ``` + It mutes it throughout. For arranging, you could add the same mask to each part and replace some zeroes with ones in your different masks to make parts play. If you use `.mask()` on different patterns mess up your counting, then patterns do not align anymore. -On the other hand, doing that on purpose is one of the things that could be considered a strength of tidalcycles and Strudel. +On the other hand, doing that on purpose is one of the things that could be considered a strength of tidalcycles and Strudel. You can make things quite lively and more organic with a little (controlled) interference, according to your own taste. And you are free to arrange in cycles like 3, 6 or 9 too. @@ -159,8 +178,9 @@ This would lowpass filter sweep everything every 8 cycles. ## How can I arrange in Strudel using `arrange` or `pick`? Take [Pachelbel's Canon in D](https://en.wikipedia.org/wiki/Pachelbel%27s_Canon#Analysis) as an example which has 4 voices (one cello and 3 violins) which have repeating patterns, as seen in the link above. - + The following snipped defines the patterns as constants which can then be used for the different voices. `arrange` takes multiple arguments, which are each a number of cycles and a pattern which is played for the number of cycles, wrapped in `[]` If the pattern is shorter than the number, it is repeated. + ") .color("grey").sound("gm_tremolo_strings:3") @@ -177,34 +197,34 @@ The following snipped defines the patterns as constants which can then be used f "<[f#4 d4 e4 c#5 d5 f#5 a5 a4] [b4 g4 a4 f#4 d4 d5 [d5@3 c#5]@2]>") .color("red") - - cello$: arrange( +cello$: arrange( [2, silence], [18,cello]) violin1$: arrange( - [4,silence], - [2,violin_p1], [2,violin_p2], - [2,violin_p3], [2,violin_p4], - [2,violin_p1], [2,violin_p2], - [2,violin_p3], [2,violin_p4] - ).sound("gm_tremolo_strings:0") - violin2$: arrange( +[4,silence], +[2,violin_p1], [2,violin_p2], +[2,violin_p3], [2,violin_p4], +[2,violin_p1], [2,violin_p2], +[2,violin_p3], [2,violin_p4] +).sound("gm_tremolo_strings:0") +violin2$: arrange( [6,silence], [2,violin_p1], [2,violin_p2], [2,violin_p3], [2,violin_p4], [2,violin_p1], [2,violin_p2], [2,violin_p3] ).sound("gm_tremolo_strings:1") violin3$: arrange( - [8,silence], - [2,violin_p1], [2,violin_p2], - [2,violin_p3], [2,violin_p4], - [2,violin_p1], [2,violin_p2] - ).sound("gm_tremolo_strings:2") +[8,silence], +[2,violin_p1], [2,violin_p2], +[2,violin_p3], [2,violin_p4], +[2,violin_p1], [2,violin_p2] +).sound("gm_tremolo_strings:2") all(x => x.release(.2)) + `} /> -Alternatively, you can also put the different patterns for the violins into one single array (`const violins = [violin_p1, violin_p2, violin_p3, violin_p4]`) and use a pattern as an index to `pick` the nth element of that array. This replaces the voices defined above. Here you use `0@2` to specifiy that the first item (i.e. with index `0`) is played for `2` cycles. +Alternatively, you can also put the different patterns for the violins into one single array (`const violins = [violin_p1, violin_p2, violin_p3, violin_p4]`) and use a pattern as an index to `pick` the nth element of that array. This replaces the voices defined above. Here you use `0@2` to specifiy that the first item (i.e. with index `0`) is played for `2` cycles. `pick` has better highlighting than `arrange`: @@ -231,18 +251,18 @@ violin1$: "<~@4 0@2 1@2 2@2 3@2 0@2 1@2 2@2 3@2>".pick(violins) .sound("gm_tremolo_strings:0") violin2$: "<~@6 0@2 1@2 2@2 3@2 0@2 1@2 2@2>".pick(violins) .sound("gm_tremolo_strings:1") -violin3$: "<~@8 0@2 1@2 2@2 3@2 0@2 1@2 >".pick(violins) +violin3$: "<~@8 0@2 1@2 2@2 3@2 0@2 1@2 >".pick(violins) .sound("gm_tremolo_strings:2") all(x => x.release(.2)) -`} /> - +`} /> + The `pick` method also works with jsons which have named elements, which makes it easier to read, see the [here](/learn/conditional-modifiers/#pick). `pickRestart` restarts the pattern upon picking it which can make a difference if the duration of the pick indexes doesn't line up with the patterns which are picked - which is not the case here. Try adding `.punchcard()` after the `release(.2)` for a visualization. ## I saw Switch Angel using functions which I cannot find in the reference (e.g. `trancegate`). How do I make it work? -Methods like `trancegate()`, `rlpf()` and `acidenv()` are currently not pattern methods which come natively with strudel. +Methods like `trancegate()`, `rlpf()` and `acidenv()` are currently not pattern methods which come natively with strudel. It's part of a script for strudel which was written by Switch Angel and published [here](https://github.com/switchangel/strudel-scripts/blob/main/allscripts.js) @@ -255,20 +275,22 @@ If you paste these functions into your strudel session, hit "Update" and delete ## Is there difference between `n` and `note`? They are not aliases of each other, in contrast to `s` and `sound`. - -The method `note` is used to reference a certain note (either as its name, such as `c` or `b2` or the midi number `69`, for example `note("c3 e3 g3")`). - -On the other hand, `n` is a way to reference the nth index of something. This something can be a scale (eg `n("0 2 4").scale("C:major")`) , but it can also be a particular note in a chord (see https://strudel.cc/recipes/recipes/#arpeggios for an example) . -The method `n` can also be used for something completely unrelated to notes like the nth sample from a sample map `s("hh*8").bank("RolandTR909").n("0 1 2 3")`. Note that `pick` does *not* use `n`. +The method `note` is used to reference a certain note (either as its name, such as `c` or `b2` or the midi number `69`, for example `note("c3 e3 g3")`). -".pickRestart([ +On the other hand, `n` is a way to reference the nth index of something. This something can be a scale (eg `n("0 2 4").scale("C:major")`) , but it can also be a particular note in a chord (see https://strudel.cc/recipes/recipes/#arpeggios for an example) . + +The method `n` can also be used for something completely unrelated to notes like the nth sample from a sample map `s("hh*8").bank("RolandTR909").n("0 1 2 3")`. Note that `pick` does _not_ use `n`. + +".pickRestart([ n("0 1 2 0"), n("2 3 4 ~"), n("[4 5] [4 3] 2 0"), n("0 -3 0 ~") - ]).scale("C:major").s("piano")`} /> - + ]).scale("C:major").s("piano")`} +/>{' '} ## Is there a cheat sheet for all symbols? @@ -305,6 +327,6 @@ _ before a stack name: mutes the stack, i.e. hush(), for example _$: s("bd") ## Are there more FAQ items? -These pages have been taken from [this pad](https://doc.patternclub.org/_CgofWouTciXXHexUP9AVg?both). Some of the items there have not been brushed up and brought here. +These pages have been taken from [this pad](https://doc.patternclub.org/_CgofWouTciXXHexUP9AVg?both). Some of the items there have not been brushed up and brought here. These include the following items: 9, 11, 12 and 19 From 4504d1afd0f893f696600493c23dff122c06c6ca Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Wed, 19 Nov 2025 22:14:23 +0100 Subject: [PATCH 04/30] remove trailing spaces in FAQ --- website/src/pages/learn/faq.mdx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index 923bb5f66..2e4cb5c4b 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -42,6 +42,7 @@ Yes you can. There are experimental modes, made by community members, for severa You can use your own samples with Strudel. There are multiple ways to load your sample collection. Some methods are good for quick experimentation, some others are good to share your audio collection with other musicians: - Import folders [from the interface](/learn/samples/#from-disk-via-import-sounds-folder) + - - Host your sound library e.g. on github and [load them from an URL](/learn/samples/#loading-custom-samples) ## Can I use Strudel with AI/LLM tools? @@ -80,15 +81,15 @@ If you want to emulate the functionality of a DAW in a live coding language, you ## Why doesn't everyone just use a DAW? -There is no easy answer to this question. Here are some thoughts: +There is no easy answer to this question. Here are some thoughts: -- Live coding tools such as Strudel are excellent for improvising music and visuals using a computer. DAWs are valuable and robust companions for other activities such as producing, mastering and mixing audio, among other usages. Using a tool does not exclude from using any another tool, just build a toolbox. +- Live coding tools such as Strudel are excellent for improvising music and visuals using a computer. DAWs are valuable and robust companions for other activities such as producing, mastering and mixing audio, among other usages. Using a tool does not exclude from using any another tool, just build a toolbox. -- Live coding has been practiced for quite some time as a performative activity. Artists like to show their screens while playing in front of an audience. It is an essential part of what they do, of the way they share their activity with everybody. +- Live coding has been practiced for quite some time as a performative activity. Artists like to show their screens while playing in front of an audience. It is an essential part of what they do, of the way they share their activity with everybody. -- Code is a human language, it is made for other humans to read it. You can read the code and enjoy the music too. It has meaning, value, and there might even be something poetic/important about it! - Strudel is free and open source, you can inspect the code, reshape it, contribute to it if you can/want. It is not opaque and this matters for many people. There is no black box, no obscure abstractions, no business model or hidden features. We need open tools in the arts! - Live coders don't shy away from using DAWs. They use them all of the time, especially when it makes their life easier for... live coding! +- Code is a human language, it is made for other humans to read it. You can read the code and enjoy the music too. It has meaning, value, and there might even be something poetic/important about it! - Strudel is free and open source, you can inspect the code, reshape it, contribute to it if you can/want. It is not opaque and this matters for many people. There is no black box, no obscure abstractions, no business model or hidden features. We need open tools in the arts! - Live coders don't shy away from using DAWs. They use them all of the time, especially when it makes their life easier for... live coding! -- Code is an artistic material like any other. There is something valuable in the process of making music through code. More generally speaking, it is nice to tackle creative problems through the use of a programming language: creative thinking, building up your own solutions, DIY approach to music-making, unexpected outcome of algorithms, funny human errors, etc. +- Code is an artistic material like any other. There is something valuable in the process of making music through code. More generally speaking, it is nice to tackle creative problems through the use of a programming language: creative thinking, building up your own solutions, DIY approach to music-making, unexpected outcome of algorithms, funny human errors, etc. - There are pianos and trumpets in your DAW: why do people continue playing the piano or the trumpet? Think of live coding tools as instruments that you activate through the act of programming. From 4ec68fcd1de98ba0cd1d0fb22de84ecddfb15d1a Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Thu, 20 Nov 2025 00:07:44 +0100 Subject: [PATCH 05/30] a little prettier --- website/src/pages/learn/faq.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index 2e4cb5c4b..b16eb8cdd 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -42,7 +42,7 @@ Yes you can. There are experimental modes, made by community members, for severa You can use your own samples with Strudel. There are multiple ways to load your sample collection. Some methods are good for quick experimentation, some others are good to share your audio collection with other musicians: - Import folders [from the interface](/learn/samples/#from-disk-via-import-sounds-folder) - - + - - Host your sound library e.g. on github and [load them from an URL](/learn/samples/#loading-custom-samples) ## Can I use Strudel with AI/LLM tools? From 39bff8900f695b80e4c5a666a62a33a186e58ff0 Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Mon, 1 Dec 2025 18:22:26 +0100 Subject: [PATCH 06/30] website/src/pages/learn/faq.mdx aktualisiert updated the section on switch angel's prebake. Now refers to the readme for instructions. --- website/src/pages/learn/faq.mdx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index b16eb8cdd..c22391330 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -265,13 +265,9 @@ Try adding `.punchcard()` after the `release(.2)` for a visualization. Methods like `trancegate()`, `rlpf()` and `acidenv()` are currently not pattern methods which come natively with strudel. -It's part of a script for strudel which was written by Switch Angel and published [here](https://github.com/switchangel/strudel-scripts/blob/main/allscripts.js) +They are part of a script/prebake for strudel which was written by Switch Angel and published [here](https://github.com/switchangel/strudel-scripts) -Note that this script defines functions and registers methods which `trancegate()` will depend on so just pasting the `trancegate()` method from that script alone will not suffice, but you will also need the `fill` method. - -If you copy the full script into your strudel, be mindful of lines which try to load local samples - these should be deleted or prefixed with `//` as a comment. - -If you paste these functions into your strudel session, hit "Update" and delete the source of the functions, the functions will still be availabe until you do a browser refresh. +You can find the instructions how to use that script in the readme.md there. ## Is there difference between `n` and `note`? From 177c3a4a2ef848e7f532a0fcf374fb63cff9c209 Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Sat, 6 Dec 2025 16:36:25 +0100 Subject: [PATCH 07/30] some items from review --- website/src/pages/learn/faq.mdx | 44 +++++++++++++++++---------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index c22391330..cef6fbf50 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -263,8 +263,6 @@ Try adding `.punchcard()` after the `release(.2)` for a visualization. ## I saw Switch Angel using functions which I cannot find in the reference (e.g. `trancegate`). How do I make it work? -Methods like `trancegate()`, `rlpf()` and `acidenv()` are currently not pattern methods which come natively with strudel. - They are part of a script/prebake for strudel which was written by Switch Angel and published [here](https://github.com/switchangel/strudel-scripts) You can find the instructions how to use that script in the readme.md there. @@ -277,17 +275,20 @@ The method `note` is used to reference a certain note (either as its name, such On the other hand, `n` is a way to reference the nth index of something. This something can be a scale (eg `n("0 2 4").scale("C:major")`) , but it can also be a particular note in a chord (see https://strudel.cc/recipes/recipes/#arpeggios for an example) . -The method `n` can also be used for something completely unrelated to notes like the nth sample from a sample map `s("hh*8").bank("RolandTR909").n("0 1 2 3")`. Note that `pick` does _not_ use `n`. +The method `n` can also be used for something completely unrelated to notes, in particular the nth sample from a sample map `s("hh*8").bank("RolandTR909").n("0 1 2 3")`. ".pickRestart([ - n("0 1 2 0"), - n("2 3 4 ~"), - n("[4 5] [4 3] 2 0"), - n("0 -3 0 ~") - ]).scale("C:major").s("piano")`} -/>{' '} + tune={` + n("<[0 1 2 3@3 -@2] [3 2 1 0@3 -@2] >").scale("A:minor:pentatonic").s("gm_acoustic_guitar_steel").n("<0 1 2 3>/2")`} +/> + + + + + +Note that `n` is not the only way that functions use indices, some take numbered patterns instead. + ## Is there a cheat sheet for all symbols? @@ -297,29 +298,30 @@ Yes! ' marks start and end of strings, is different from " " marks start and end of single line patterns in mini notation, is different from ' ` marks start and end of patterns with line breaks in mini notation, is different from ' -[] used for patterns, each item in it has the same length -<> used for patterns, alternates each item each cycle +[] used for patterns in mini notation, each item in it has the same length +<> used for patterns, alternates between items each cycle {} historically used for polyrhythmic patterns. {a b c}%4 is the same as
*4. -@3 elongates the item by a factor of 3 (other numbers work too) +@3 elongates the item by a factor of 3 (other numbers work too, even non-integer, but for numbers between 0 and 1 you need a leading zero like this: @0.5) @ after an item: elongates the item once (multiple @ work too c @ @ is the same as c@3) -_ after an item: also elongates an item once (multiple _ work too c _ _ is the same as c@3) +_ after an item: also elongates an item once (multiple _ work too c _ _ is the same as c@3), see below for a different usage. . this divides equal parts of a pattern and is called a foot. Can be used instead of [] like this: "1 6 7 8 . 2 . 3 . 4" is the same as "[1 6 7 8] 2 3 4" - silence ~ also silence -x not silence (for the use in struct, same as 1) -s increase a note of a scale by one semitone, i.e. sharp -b decrease a note of a scale by one semitone, i.e. flat -# used in mondo notation -# also used for names of chords, like F# +x not silence (for the use in struct, any non-silence symbol works there) +b decrease by one semitone, i.e. flat, works for steps of scales, note names (but not midi numbers) and chord names +s increase by one semitone, i.e. sharp, works for steps of scales, note names (but not midi numbers) but not chord names +# increase by one semitone, i.e. sharp works for steps of scales, note names (but not midi numbers) and chord names +# also used in mondo notation + *3 play the sample or pattern at thrice the speed, fast(3) !3 play the sample or pattern three times /2 play the sample or pattern at half speed, slow(2) ? play the pattern sometimes | once per cycle, choose randomly a pattern of those separated by i.e. chooseCycles() , play all items separated by it at the same time, i.e. stack() -: is used to separate multiple parameters, such as adsr(".1:.1:.5:.2") +: is used to separate multiple parameters, such as adsr(".1:.1:.5:.2"), this is is an operator which creates a list of these objects. $: at the start of a line, defines a member of the stack. is the only stack name that should occur multiple names -_ before a stack name: mutes the stack, i.e. hush(), for example _$: s("bd") +_ before a stack name: mutes the stack, i.e. hush(), for example _$: s("bd"), see above for a different usage. ``` ## Are there more FAQ items? From bd282f439ab3b30f613e6f60eee33c098d37600e Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Sat, 6 Dec 2025 16:37:39 +0100 Subject: [PATCH 08/30] everyone wants that trancegate --- website/src/pages/learn/faq.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index cef6fbf50..d4c38d414 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -263,6 +263,8 @@ Try adding `.punchcard()` after the `release(.2)` for a visualization. ## I saw Switch Angel using functions which I cannot find in the reference (e.g. `trancegate`). How do I make it work? +Methods like `trancegate()`, `rlpf()` and `acidenv()` are currently not pattern methods which come natively with strudel. + They are part of a script/prebake for strudel which was written by Switch Angel and published [here](https://github.com/switchangel/strudel-scripts) You can find the instructions how to use that script in the readme.md there. From ab03ece2b7ea61e9de4761e73f318e62812168c4 Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Sat, 6 Dec 2025 16:48:40 +0100 Subject: [PATCH 09/30] prettier --- packages/osc/server.js | 0 website/src/pages/learn/faq.mdx | 12 +++--------- 2 files changed, 3 insertions(+), 9 deletions(-) mode change 100755 => 100644 packages/osc/server.js diff --git a/packages/osc/server.js b/packages/osc/server.js old mode 100755 new mode 100644 diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index d4c38d414..36a8bbef1 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -267,7 +267,7 @@ Methods like `trancegate()`, `rlpf()` and `acidenv()` are currently not pattern They are part of a script/prebake for strudel which was written by Switch Angel and published [here](https://github.com/switchangel/strudel-scripts) -You can find the instructions how to use that script in the readme.md there. +You can find the instructions how to use that script in the readme.md there. ## Is there difference between `n` and `note`? @@ -277,21 +277,16 @@ The method `note` is used to reference a certain note (either as its name, such On the other hand, `n` is a way to reference the nth index of something. This something can be a scale (eg `n("0 2 4").scale("C:major")`) , but it can also be a particular note in a chord (see https://strudel.cc/recipes/recipes/#arpeggios for an example) . -The method `n` can also be used for something completely unrelated to notes, in particular the nth sample from a sample map `s("hh*8").bank("RolandTR909").n("0 1 2 3")`. +The method `n` can also be used for something completely unrelated to notes, in particular the nth sample from a sample map `s("hh*8").bank("RolandTR909").n("0 1 2 3")`. ").scale("A:minor:pentatonic").s("gm_acoustic_guitar_steel").n("<0 1 2 3>/2")`} /> - - - - Note that `n` is not the only way that functions use indices, some take numbered patterns instead. - ## Is there a cheat sheet for all symbols? Yes! @@ -314,14 +309,13 @@ b decrease by one semitone, i.e. flat, works for steps of scales, note names ( s increase by one semitone, i.e. sharp, works for steps of scales, note names (but not midi numbers) but not chord names # increase by one semitone, i.e. sharp works for steps of scales, note names (but not midi numbers) and chord names # also used in mondo notation - *3 play the sample or pattern at thrice the speed, fast(3) !3 play the sample or pattern three times /2 play the sample or pattern at half speed, slow(2) ? play the pattern sometimes | once per cycle, choose randomly a pattern of those separated by i.e. chooseCycles() , play all items separated by it at the same time, i.e. stack() -: is used to separate multiple parameters, such as adsr(".1:.1:.5:.2"), this is is an operator which creates a list of these objects. +: is used to separate multiple parameters, such as adsr(".1:.1:.5:.2"), this is is an operator which creates a list of these objects. $: at the start of a line, defines a member of the stack. is the only stack name that should occur multiple names _ before a stack name: mutes the stack, i.e. hush(), for example _$: s("bd"), see above for a different usage. ``` From 6402ad5d37f70583ba967e8364e1610620a95e01 Mon Sep 17 00:00:00 2001 From: scrappy_fiddler Date: Sat, 6 Dec 2025 16:55:57 +0100 Subject: [PATCH 10/30] better linebreak in example --- website/src/pages/learn/faq.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index 36a8bbef1..b91b48cca 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -282,7 +282,9 @@ The method `n` can also be used for something completely unrelated to notes, in ").scale("A:minor:pentatonic").s("gm_acoustic_guitar_steel").n("<0 1 2 3>/2")`} + n("<[0 1 2 3@3 -@2] [3 2 1 0@3 -@2] >") + .scale("A:minor:pentatonic") + .s("gm_acoustic_guitar_steel").n("<0 1 2 3>/2")`} /> Note that `n` is not the only way that functions use indices, some take numbered patterns instead. From c8b2e1ac9e529333f72cb4ac8e87fe80cdf82a6e Mon Sep 17 00:00:00 2001 From: 1d10t <1d10t@noreply.codeberg.org> Date: Fri, 12 Dec 2025 21:22:21 +0100 Subject: [PATCH 11/30] feat(superdough/audiocontext): make AudioContext injection optional - Modify `setDefaultAudioContext()` to accept an optional `existingAudioCtx` parameter. - If provided, it will use the existing context; otherwise, it creates a new one. - This allows for better integration with external audio systems that manage their own AudioContext. --- packages/superdough/audioContext.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/superdough/audioContext.mjs b/packages/superdough/audioContext.mjs index 71e01d57d..9bae75bd9 100644 --- a/packages/superdough/audioContext.mjs +++ b/packages/superdough/audioContext.mjs @@ -1,7 +1,7 @@ let audioContext; -export const setDefaultAudioContext = () => { - audioContext = new AudioContext(); +export const setDefaultAudioContext = (existingAudioCtx) => { + audioContext = existingAudioCtx ?? new AudioContext(); return audioContext; }; From 4e14718e93b7d9a5ebe7fb1892109745577b8bc7 Mon Sep 17 00:00:00 2001 From: 1d10t <1d10t@noreply.codeberg.org> Date: Fri, 12 Dec 2025 21:56:31 +0100 Subject: [PATCH 12/30] feat(webaudio): enable AudioContext sharing for webaudioRepl - Add support for optional `existingAudioCtx` parameter in `webaudioRepl()` function - When provided, sets it as the default AudioContext via `setDefaultAudioContext()` - Allows integration with external systems that manage their own Web Audio API context - Maintains backward compatibility with existing usage patterns --- packages/webaudio/webaudio.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs index 383e87f87..8fc9b860f 100644 --- a/packages/webaudio/webaudio.mjs +++ b/packages/webaudio/webaudio.mjs @@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th */ import * as strudel from '@strudel/core'; -import { superdough, getAudioContext, setLogger, doughTrigger, registerWorklet } from 'superdough'; +import { superdough, setDefaultAudioContext, getAudioContext, setLogger, doughTrigger, registerWorklet } from 'superdough'; import './supradough.mjs'; import { workletUrl } from 'supradough'; @@ -27,6 +27,9 @@ export const webaudioOutput = (hap, _deadline, hapDuration, cps, t) => { }; export function webaudioRepl(options = {}) { + if (options.existingAudioCtx) { + setDefaultAudioContext(options.existingAudioCtx); + } options = { getTime: () => getAudioContext().currentTime, defaultOutput: webaudioOutput, From adf9596d070eb33ee8c52726cbd10fef7dea0141 Mon Sep 17 00:00:00 2001 From: Sergey S Yaglov Date: Sat, 13 Dec 2025 00:28:13 +0300 Subject: [PATCH 13/30] codestyle(webaudio) --- packages/webaudio/webaudio.mjs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs index 8fc9b860f..399e68ab1 100644 --- a/packages/webaudio/webaudio.mjs +++ b/packages/webaudio/webaudio.mjs @@ -5,7 +5,14 @@ This program is free software: you can redistribute it and/or modify it under th */ import * as strudel from '@strudel/core'; -import { superdough, setDefaultAudioContext, getAudioContext, setLogger, doughTrigger, registerWorklet } from 'superdough'; +import { + superdough, + setDefaultAudioContext, + getAudioContext, + setLogger, + doughTrigger, + registerWorklet, +} from 'superdough'; import './supradough.mjs'; import { workletUrl } from 'supradough'; From 181ebee374058b6bf7fcf686f39e7ab3ef23d733 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 19 Dec 2025 01:25:58 +0100 Subject: [PATCH 14/30] fix: repl package init audio properly --- examples/buildless/web-component-no-iframe.html | 3 ++- packages/repl/repl-component.mjs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/buildless/web-component-no-iframe.html b/examples/buildless/web-component-no-iframe.html index 8afa85cb5..ae4fb700d 100644 --- a/examples/buildless/web-component-no-iframe.html +++ b/examples/buildless/web-component-no-iframe.html @@ -1,4 +1,5 @@ - + + - + diff --git a/website/src/components/HeadCommonNext.astro b/website/src/components/HeadCommonNext.astro index 9f323a7a3..1f878bac0 100644 --- a/website/src/components/HeadCommonNext.astro +++ b/website/src/components/HeadCommonNext.astro @@ -24,7 +24,7 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL - + From b4e00538f86c7d50a276bcfe6698ca4d38ab9fa0 Mon Sep 17 00:00:00 2001 From: floy Date: Sat, 10 Jan 2026 15:30:07 +0100 Subject: [PATCH 19/30] Don't show 'No sounds loaded' text if search is active --- website/src/repl/components/panel/SoundsTab.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/repl/components/panel/SoundsTab.jsx b/website/src/repl/components/panel/SoundsTab.jsx index 52fbf928c..0e46b1382 100644 --- a/website/src/repl/components/panel/SoundsTab.jsx +++ b/website/src/repl/components/panel/SoundsTab.jsx @@ -210,7 +210,7 @@ export function SoundsTab() { ) : ( '' )} - {!soundEntries.length && soundsFilter !== 'importSounds' ? 'No sounds loaded' : ''} + {!soundEntries.length && soundsFilter !== 'importSounds' && search == '' ? 'No sounds loaded' : ''} ); From fd0209dbc067b4c683f946738dedc9da3f752942 Mon Sep 17 00:00:00 2001 From: floy Date: Sat, 10 Jan 2026 15:39:02 +0100 Subject: [PATCH 20/30] Show explicit help text when search doesn't match --- website/src/repl/components/panel/SoundsTab.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/website/src/repl/components/panel/SoundsTab.jsx b/website/src/repl/components/panel/SoundsTab.jsx index 0e46b1382..2060c64a9 100644 --- a/website/src/repl/components/panel/SoundsTab.jsx +++ b/website/src/repl/components/panel/SoundsTab.jsx @@ -210,7 +210,10 @@ export function SoundsTab() { ) : ( '' )} - {!soundEntries.length && soundsFilter !== 'importSounds' && search == '' ? 'No sounds loaded' : ''} + {!soundEntries.length && soundsFilter !== 'importSounds' ? + search == '' ? 'No sounds loaded' : 'No sounds found' + : '' + } ); From 0174e086399ae0411e7f6da31cc3fd2bf8df0840 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 11 Jan 2026 10:50:44 +0100 Subject: [PATCH 21/30] fix: add trem to top level --- packages/core/controls.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 8fef91294..f15b3d4cd 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -877,7 +877,7 @@ export const { coarse } = registerControl('coarse'); * note("d d d# d".fast(4)).s("supersaw").tremolo("<3 2 100> ").tremoloskew("<.5>") * */ -export const { tremolo } = registerControl(['tremolo', 'tremolodepth', 'tremoloskew', 'tremolophase'], 'trem'); +export const { tremolo, trem } = registerControl(['tremolo', 'tremolodepth', 'tremoloskew', 'tremolophase'], 'trem'); /** * Modulate the amplitude of a sound with a continuous waveform From c74707e804f926ffc3910a3e80aa8bda8e86d5a4 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 11 Jan 2026 10:58:13 +0100 Subject: [PATCH 22/30] fix: export start cycle min 0 --- website/src/repl/components/panel/ExportTab.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/repl/components/panel/ExportTab.jsx b/website/src/repl/components/panel/ExportTab.jsx index 9671ff1a3..cbb132e44 100644 --- a/website/src/repl/components/panel/ExportTab.jsx +++ b/website/src/repl/components/panel/ExportTab.jsx @@ -66,7 +66,7 @@ export default function ExportTab(Props) {
{ let v = parseInt(e.target.value); From 8f3dc8daea3759330f4a7bd930a42d5653d500a1 Mon Sep 17 00:00:00 2001 From: yaxu Date: Sun, 11 Jan 2026 11:34:55 +0100 Subject: [PATCH 23/30] Update website/src/pages/learn/faq.mdx --- website/src/pages/learn/faq.mdx | 35 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index b91b48cca..7fbc0d572 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -8,27 +8,26 @@ import { JsDoc } from '../../docs/JsDoc'; # Frequently Asked Questions -This page contains frequently asked questions. Usually, the topic is explained in more detail in a section which is linked in the answer. This page's aim is to give an overview over topics which are important to the users of strudel. +This page contains frequently asked questions, with answers. Usually, the topic is explained in more detail in a section which is linked in the answer. ## Is Strudel/Tidal free? -Yes - there is no charge, this is a collective open source project, and the music you make with it is your own. +Yes - there is no charge, this is a collective open source project, and the music you make with it is your own. However if you can, please make a one-off or regular donation to our [opencollective fund](https://opencollective.com/tidalcycles), that supports the software and cultural development of Strudel and other Uzu languages. -However there are some caveats - the source code must stay free, i.e. you cannot distribute strudel or tidal as part of projects with incompatible licenses - see the [license](https://www.gnu.org/licenses/agpl-3.0.en.html) for details. The contributed examples and tracks are also separately licensed, and must not e.g. be used to train AI models without permission. +While there is no charge there are some caveats, e.g.: + +* the source code must stay free, i.e. you cannot distribute strudel or tidal as part of projects with incompatible licenses - see the [license](https://www.gnu.org/licenses/agpl-3.0.en.html) for details. +* the contributed examples and tracks are also separately licensed, and must not e.g. be used to train AI models without permission. ## How to record or export audio? -There are multiple ways to record the audio -- and video -- output of Strudel: +Strudel is not a digital audio workstation and does not operate following the same principles shared by most traditional audio softwares. However, there are multiple ways to record the audio -- and video -- output of Strudel: - - capture the raw stereo signal coming out of your web browser. - - - use the alternative SuperDirt audio engine. Read [this page](/learn/input-output/#oscsuperdirtstrudeldirt) to know more about it. - - - capture the audio/video stream using a capture tool such as [OBS](). - - - don't record anything and code it again in front of your friends. - -You will need an external audio editor/DAW such as Reaper/Audacity/Ardour, etc. Strudel itself does not have functionality for exporting stems / individual tracks to an audio or midi file. Strudel is not a digital audio workstation and does not operate following the same principles shared by most traditional audio softwares. +* Use the 'export' tab to render and download as an audio file. +* capture the raw stereo signal coming out of your web browser. You will need an external audio editor/DAW such as Reaper/Audacity/Ardour, etc. +* use the alternative SuperDirt audio engine. Read [this page](/learn/input-output/#oscsuperdirtstrudeldirt) to know more about it. +* capture the audio/video stream using a capture tool such as [OBS](), which is designed for live streaming, but also works very well for recording. +* don't record anything and code it again in front of your friends. ## Can I use strudel with my IDE? @@ -37,13 +36,13 @@ Yes you can. There are experimental modes, made by community members, for severa - VS Code: [Strudel VS](https://marketplace.visualstudio.com/items?itemName=cmillsdev.strudelvs): an experimental mode for Microsoft VSCode. A revived version of [TidalStrudel](https://marketplace.visualstudio.com/items?itemName=roipoussiere.tidal-strudel), which is defunct. - nvim: [strudel.nvim](https://github.com/gruvw/strudel.nvim) -## How can I record samples? +## How can I use my own samples? -You can use your own samples with Strudel. There are multiple ways to load your sample collection. Some methods are good for quick experimentation, some others are good to share your audio collection with other musicians: +There are multiple ways to load your sample collection. Some methods are good for quick experimentation, some others are good to share your audio collection with other musicians: - - Import folders [from the interface](/learn/samples/#from-disk-via-import-sounds-folder) - - - - Host your sound library e.g. on github and [load them from an URL](/learn/samples/#loading-custom-samples) +- Import folders [from the interface](/learn/samples/#from-disk-via-import-sounds-folder). These are stored locally in your web browser, and not uploaded. +- Serve a folder of samples locally using the [strudel 'sampler' commandline tool](https://strudel.cc/learn/samples/#from-disk-via-strudelsampler). This can be most reliable method, but requires [nodejs](https://nodejs.org) to be installed. +- Host your sound library online on the web and [load them from an URL](/learn/samples/#loading-custom-samples) ## Can I use Strudel with AI/LLM tools? From 25dbfe4c7d38330892a2e8000eb75f8569b7dcfa Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 11 Jan 2026 11:43:04 +0100 Subject: [PATCH 24/30] fix: remove faulty default readme --- website/README.md | 184 +--------------------------------------------- 1 file changed, 1 insertion(+), 183 deletions(-) diff --git a/website/README.md b/website/README.md index 115d6d556..84bf732e1 100644 --- a/website/README.md +++ b/website/README.md @@ -3,186 +3,4 @@ This is the website for Strudel, deployed at [strudel.cc](https://strudel.cc). It includes the REPL live coding editor and the documentation site. -## Run locally - -```bash -# from project root -npm run setup -npm run repl -``` - -## Build - -```bash -cd website -npm run build # <- builds repl + tutorial to ../docs -npm run preview # <- test static build -``` - -## Generate PWA icons - -```sh -cd website/public -npx pwa-asset-generator icon.png icons -``` - -# Standard Readme of Astro Starter Kit: Docs Site - -```bash -npm create astro@latest -- --template docs -``` - -[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/docs) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/docs) - -![docs](https://user-images.githubusercontent.com/4677417/186189283-0831b9ab-d6b9-485d-8955-3057e532ab31.png) - - -## Features - -- ✅ **Full Markdown support** -- ✅ **Responsive mobile-friendly design** -- ✅ **Sidebar navigation** -- ✅ **Search (powered by Algolia)** -- ✅ **Multi-language i18n** -- ✅ **Automatic table of contents** -- ✅ **Automatic list of contributors** -- ✅ (and, best of all) **dark mode** - -## Commands Cheatsheet - -All commands are run from the root of the project, from a terminal: - -| Command | Action | -| :--------------------- | :----------------------------------------------- | -| `npm install` | Installs dependencies | -| `npm run dev` | Starts local dev server at `localhost:4321` | -| `npm run build` | Build your production site to `./dist/` | -| `npm run preview` | Preview your build locally, before deploying | -| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | -| `npm run astro --help` | Get help using the Astro CLI | - -To deploy your site to production, check out our [Deploy an Astro Website](https://docs.astro.build/guides/deploy) guide. - -## New to Astro? - -Welcome! Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). - -## Customize This Theme - -edit: removed, as css styles have been replaced with tailwind styles - -### Site metadata - -`src/config.ts` contains several data objects that describe metadata about your site like title, description, default language, and Open Graph details. You can customize these to match your project. - -## Page metadata - -Astro uses frontmatter in Markdown pages to choose layouts and pass properties to those layouts. If you are using the default layout, you can customize the page in many different ways to optimize SEO and other things. For example, you can use the `title` and `description` properties to set the document title, meta title, meta description, and Open Graph description. - -```markdown ---- -title: Example title -description: Really cool docs example that uses Astro -layout: ../../layouts/MainLayout.astro ---- - -# Page content... -``` - -For more SEO related properties, look at `src/components/HeadSEO.astro` - -### Sidebar navigation - -The sidebar navigation is controlled by the `SIDEBAR` variable in your `src/config.ts` file. You can customize the sidebar by modifying this object. A default, starter navigation has already been created for you. - -```ts -export const SIDEBAR = { - en: [ - { text: "Section Header", header: true }, - { text: "Introduction", link: "en/introduction" }, - { text: "Page 2", link: "en/page-2" }, - { text: "Page 3", link: "en/page-3" }, - - { text: "Another Section", header: true }, - { text: "Page 4", link: "en/page-4" }, - ], -}; -``` - -Note the top-level `en` key: This is needed for multi-language support. You can change it to whatever language you'd like, or add new languages as you go. More details on this below. - -### Multiple Languages support - -The Astro docs template supports multiple languages out of the box. The default theme only shows `en` documentation, but you can enable multi-language support features by adding a second language to your project. - -To add a new language to your project, you'll want to extend the current `src/pages/[lang]/...` layout: - -```diff - 📂 src/pages - ┣ 📂 en - ┃ ┣ 📜 page-1.md - ┃ ┣ 📜 page-2.md - ┃ ┣ 📜 page-3.astro -+ ┣ 📂 es -+ ┃ ┣ 📜 page-1.md -+ ┃ ┣ 📜 page-2.md -+ ┃ ┣ 📜 page-3.astro -``` - -You'll also need to add the new language name to the `KNOWN_LANGUAGES` map in your `src/config.ts` file. This will enable your new language switcher in the site header. - -```diff -// src/config.ts -export const KNOWN_LANGUAGES = { - English: 'en', -+ Spanish: 'es', -}; -``` - -Last step: you'll need to add a new entry to your sidebar, to create the table of contents for that language. While duplicating every page might not sound ideal to everyone, this extra control allows you to create entirely custom content for every language. - -> Make sure the sidebar `link` value points to the correct language! - -```diff -// src/config.ts -export const SIDEBAR = { - en: [ - { text: 'Section Header', header: true, }, - { text: 'Introduction', link: 'en/introduction' }, - // ... - ], -+ es: [ -+ { text: 'Encabezado de sección', header: true, }, -+ { text: 'Introducción', link: 'es/introduction' }, -+ // ... -+ ], -}; - -// ... -``` - -If you plan to use Spanish as the default language, you just need to modify the redirect path in `src/pages/index.astro`: - -```diff - -``` - -You can also remove the above script and write a landing page in Spanish instead. - -### What if I don't plan to support multiple languages? - -That's totally fine! Not all projects need (or can support) multiple languages. You can continue to use this theme without ever adding a second language. - -If that single language is not English, you can just replace `en` in directory layouts and configurations with the preferred language. - -### Search (Powered by Algolia) - -[Algolia](https://www.algolia.com/) offers a free service to qualified open source projects called [DocSearch](https://docsearch.algolia.com/). If you are accepted to the DocSearch program, provide your API Key & index name in `src/config.ts` and a search box will automatically appear in your site header. - -Note that Aglolia and Astro are not affiliated. We have no say over acceptance to the DocSearch program. - -If you'd prefer to remove Algolia's search and replace it with your own, check out the `src/components/Header.astro` component to see where the component is added. +more setup info, see [project setup](../CONTRIBUTING.md#project-setup) \ No newline at end of file From f3e6f868577a0f3e3ed50c97c9022a5972ac17e3 Mon Sep 17 00:00:00 2001 From: yaxu Date: Sun, 11 Jan 2026 11:55:40 +0100 Subject: [PATCH 25/30] Update website/src/pages/learn/faq.mdx Trimmed all the DAW talk a little! --- website/src/pages/learn/faq.mdx | 61 +++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index 7fbc0d572..f8ebcb0fb 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -46,21 +46,34 @@ There are multiple ways to load your sample collection. Some methods are good fo ## Can I use Strudel with AI/LLM tools? -You are free to do what you like with Strudel, within the terms of the free/open source AGPLv3 license. However as a community we are interested in exploring human creativity. AI is _way_ over-hyped right now, including by people with very shady motives. Many in the community are very wary of people training models on their tunes that they've poured their love into. So please keep discussion and questions around AI and LLMs to channels dedicated to the topic and be fully respectful of other people's work. +You are free to do what you like with Strudel, within the terms of the free/open source AGPLv3 license. +However as a community we are interested in exploring human creativity. AI is _way_ over-hyped right now, +including by people with very shady motives. Many in the community are very wary of people training models +on their tunes that they've poured their love into. So please keep discussion and questions around AI and +LLMs to channels dedicated to the topic and be fully respectful of other people's work. -Furthermore, tools like ChatGPT generally give wrong answers. Please don't ask the community to fix those answers for you, as generally they will be timewasting nonsense. +Furthermore, tools like ChatGPT generally give wrong answers. Please don't ask the community to fix those +answers for you, as generally they will be timewasting nonsense. -Human questions only! +Human questions are always welcome! + +## Where can I download loads of patterns to train my LLM? + +You cannot, as there is no such place. For details regarding our stance towards AI/LLM, see [above](/learn/faq/#can-i-use-strudel-with-aillm-tools) ## How to run offline? -Strudel works offline just fine! There are multiple techniques to run it yourself, see [this explanation](learn/pwa/#using-strudel-offline). +Strudel works offline just fine! There are multiple techniques for this, see [this explanation](learn/pwa/#using-strudel-offline). ## How to change tempo? How do I translate BPM to cpm? -If you have your tempo in beats per minute and use 4 beats per cycle (e.g. if your track is in 4/4ths) then you can do `setcpm(BPM/4)` where BPM is your beats per minute. +Strudel works in cycles, rather than beats, but if you assume a certain number of beats per cycle, you can convert between them. -If you have a different number of beats per bar or are using more or less beats per cycle (e.g. If you want to put only half a bar or two bars into one cycle), adjust accordingly. +For example, if you have your tempo in beats per minute and use 4 beats per cycle (e.g. if your track is in 4/4ths) then you can do `setcpm(BPM/4)` +where BPM is your beats per minute. + +If you have a different number of beats per bar or are using more or less beats per cycle (e.g. If you want to put only half a bar or +two bars into one cycle), adjust accordingly. ## Where can I see all the functions? @@ -72,11 +85,17 @@ If you pop open the sidetab of strudel.cc (small white < on the right hand side) ## How do I use this exactly like a DAW? -Short answer: you don't. +Strudel has different design aims for a DAW, and so treating it like one will likely be frustrating. DAWs are geared towards +sequencing notes over time in predictable ways, whereas Strudel and similar Uzu languages are geared towards combining and +transforming patterns in ways that can be hard to predict. -Long answer: you can use Strudel to work along your creative work in a DAW. There are many ways to do so. +If you want to emulate the functionality of a DAW in Strudel, you'll have to identify the operations +executed by the DAW (sequencing, repeating, applying filters and envelopes) and write code that is equivalent to these +operations. For example in Strudel, the 'arrange' and 'pick' methods are useful for sequencing patterns over time (see question on these later in this document). -If you want to emulate the functionality of a DAW in a live coding language, you'll have to identify the operations executed by the DAW (sequencing, repeating, applying filters and envelopes) and write code that is equivalent to these operations. You might then find that the typical DAW workflow is not really adapted to live coding (because, despite both being ways of making music on the computer, they are two very different tools) and adapt your way of proceeding to the medium of code. This might mean leaving more place to serendipity and writing code that you don't predict the output of. +You might still find that the typical DAW workflow is not really adapted to live coding because, despite +both being ways of making music on the computer, they are two very different tools. You could then adapt your way of proceeding +to the medium of code, which might mean leaving more place to serendipity and writing code that you don't predict the output of. ## Why doesn't everyone just use a DAW? @@ -84,39 +103,29 @@ There is no easy answer to this question. Here are some thoughts: - Live coding tools such as Strudel are excellent for improvising music and visuals using a computer. DAWs are valuable and robust companions for other activities such as producing, mastering and mixing audio, among other usages. Using a tool does not exclude from using any another tool, just build a toolbox. -- Live coding has been practiced for quite some time as a performative activity. Artists like to show their screens while playing in front of an audience. It is an essential part of what they do, of the way they share their activity with everybody. +- Live coding has developed over decades as a distinct creative practice. For example, live coding artists like to show their screens while playing in front of an audience. It is an essential part of what they do, of the way they share their activity with everybody. -- Code is a human language, it is made for other humans to read it. You can read the code and enjoy the music too. It has meaning, value, and there might even be something poetic/important about it! - Strudel is free and open source, you can inspect the code, reshape it, contribute to it if you can/want. It is not opaque and this matters for many people. There is no black box, no obscure abstractions, no business model or hidden features. We need open tools in the arts! - Live coders don't shy away from using DAWs. They use them all of the time, especially when it makes their life easier for... live coding! +- Code is a human language, it is made for other humans to read it. You can read the code and enjoy the music too. It has meaning, value, and there might even be something poetic/important about it! - Strudel is free and open source, you can inspect the code, reshape it, contribute to it if you can/want. It is not opaque and this matters for many people. There is no black box, no obscure abstractions, no business model, no user tracking or hidden features. We need open tools in the arts! - Live coders don't all shy away from using DAWs. Many use them all of the time, especially when it makes their life easier for... live coding! - Code is an artistic material like any other. There is something valuable in the process of making music through code. More generally speaking, it is nice to tackle creative problems through the use of a programming language: creative thinking, building up your own solutions, DIY approach to music-making, unexpected outcome of algorithms, funny human errors, etc. - There are pianos and trumpets in your DAW: why do people continue playing the piano or the trumpet? Think of live coding tools as instruments that you activate through the act of programming. -## Is it more efficient to use Strudel than a DAW? - -Strudel was not build to be a DAW, yet it can still be used to make covers, arrange tracks, or prepare patterns for jamming. When playing concerts or jamming, some livecoders prepare their code, some perform from scratch. - -It might be interesting for you to check out for yourself how strudel can be used to express yourself creatively. Also you are free to combine a language like Strudel with a DAW. - ## How can I interface Strudel with my favorite music software? What can I do with it? Strudel can send [MIDI and OSC](/learn/input-output/), which are protocols for communicating musical information. -Another music software (or hardware!) can then listen to these messages and process them according to its capabilities. +Other music software (or hardware!) can then listen to these messages and process them according to its capabilities. -A simple example would be to send livecoded audio to Ableton on different tracks and then use it to mix them. +A simple example would be to send livecoded audio to a DAW like Ardour on different tracks and then use it to mix them. You could also send the MIDI of a sequenced pattern to Musescore and then have it transcribe your livecoded work as a musical score. -You could also send MIDI to your hardware synths because you think they sound better than the software synths built-in Strudel. +You could also send MIDI to your hardware synths, if you like their sound. -## How do I use this in my closed source webgame? +## How do I use this in my closed source webgame or other software? -You don't. You would need to re-license your game to AGPLv3 to fulfill the license Strudel is distributed under. - -## Where can I download loads of patterns to train my LLM? - -You cannot, as there is no such place. For details regarding our stance towards AI/LLM, see [above](/learn/faq/#can-i-use-strudel-with-aillm-tools) +You don't. You need to license your game to a free/open source license fulfill the [AGPLv3 license](https://codeberg.org/uzu/strudel/src/branch/main/LICENSE) Strudel is distributed under. ## How to play different patterns simultaneously? From 85fd567fb2e2ac40e1aac886af103dc83744201c Mon Sep 17 00:00:00 2001 From: yaxu Date: Sun, 11 Jan 2026 12:21:05 +0100 Subject: [PATCH 26/30] Format and remove link to open document --- website/src/pages/learn/faq.mdx | 46 ++++++++++++++------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index f8ebcb0fb..e43839dc3 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -16,18 +16,18 @@ Yes - there is no charge, this is a collective open source project, and the musi While there is no charge there are some caveats, e.g.: -* the source code must stay free, i.e. you cannot distribute strudel or tidal as part of projects with incompatible licenses - see the [license](https://www.gnu.org/licenses/agpl-3.0.en.html) for details. -* the contributed examples and tracks are also separately licensed, and must not e.g. be used to train AI models without permission. +- the source code must stay free, i.e. you cannot distribute strudel or tidal as part of projects with incompatible licenses - see the [license](https://www.gnu.org/licenses/agpl-3.0.en.html) for details. +- the contributed examples and tracks are also separately licensed, and must not e.g. be used to train AI models without permission. ## How to record or export audio? Strudel is not a digital audio workstation and does not operate following the same principles shared by most traditional audio softwares. However, there are multiple ways to record the audio -- and video -- output of Strudel: -* Use the 'export' tab to render and download as an audio file. -* capture the raw stereo signal coming out of your web browser. You will need an external audio editor/DAW such as Reaper/Audacity/Ardour, etc. -* use the alternative SuperDirt audio engine. Read [this page](/learn/input-output/#oscsuperdirtstrudeldirt) to know more about it. -* capture the audio/video stream using a capture tool such as [OBS](), which is designed for live streaming, but also works very well for recording. -* don't record anything and code it again in front of your friends. +- Use the 'export' tab to render and download as an audio file. +- capture the raw stereo signal coming out of your web browser. You will need an external audio editor/DAW such as Reaper/Audacity/Ardour, etc. +- use the alternative SuperDirt audio engine. Read [this page](/learn/input-output/#oscsuperdirtstrudeldirt) to know more about it. +- capture the audio/video stream using a capture tool such as [OBS](https://obsproject.com/fr), which is designed for live streaming, but also works very well for recording. +- don't record anything and code it again in front of your friends. ## Can I use strudel with my IDE? @@ -40,19 +40,19 @@ Yes you can. There are experimental modes, made by community members, for severa There are multiple ways to load your sample collection. Some methods are good for quick experimentation, some others are good to share your audio collection with other musicians: -- Import folders [from the interface](/learn/samples/#from-disk-via-import-sounds-folder). These are stored locally in your web browser, and not uploaded. +- Import folders [from the interface](/learn/samples/#from-disk-via-import-sounds-folder). These are stored locally in your web browser, and not uploaded. - Serve a folder of samples locally using the [strudel 'sampler' commandline tool](https://strudel.cc/learn/samples/#from-disk-via-strudelsampler). This can be most reliable method, but requires [nodejs](https://nodejs.org) to be installed. - Host your sound library online on the web and [load them from an URL](/learn/samples/#loading-custom-samples) ## Can I use Strudel with AI/LLM tools? -You are free to do what you like with Strudel, within the terms of the free/open source AGPLv3 license. -However as a community we are interested in exploring human creativity. AI is _way_ over-hyped right now, -including by people with very shady motives. Many in the community are very wary of people training models -on their tunes that they've poured their love into. So please keep discussion and questions around AI and +You are free to do what you like with Strudel, within the terms of the free/open source AGPLv3 license. +However as a community we are interested in exploring human creativity. AI is _way_ over-hyped right now, +including by people with very shady motives. Many in the community are very wary of people training models +on their tunes that they've poured their love into. So please keep discussion and questions around AI and LLMs to channels dedicated to the topic and be fully respectful of other people's work. -Furthermore, tools like ChatGPT generally give wrong answers. Please don't ask the community to fix those +Furthermore, tools like ChatGPT generally give wrong answers. Please don't ask the community to fix those answers for you, as generally they will be timewasting nonsense. Human questions are always welcome! @@ -69,7 +69,7 @@ Strudel works offline just fine! There are multiple techniques for this, see [th Strudel works in cycles, rather than beats, but if you assume a certain number of beats per cycle, you can convert between them. -For example, if you have your tempo in beats per minute and use 4 beats per cycle (e.g. if your track is in 4/4ths) then you can do `setcpm(BPM/4)` +For example, if you have your tempo in beats per minute and use 4 beats per cycle (e.g. if your track is in 4/4ths) then you can do `setcpm(BPM/4)` where BPM is your beats per minute. If you have a different number of beats per bar or are using more or less beats per cycle (e.g. If you want to put only half a bar or @@ -85,16 +85,16 @@ If you pop open the sidetab of strudel.cc (small white < on the right hand side) ## How do I use this exactly like a DAW? -Strudel has different design aims for a DAW, and so treating it like one will likely be frustrating. DAWs are geared towards -sequencing notes over time in predictable ways, whereas Strudel and similar Uzu languages are geared towards combining and +Strudel has different design aims for a DAW, and so treating it like one will likely be frustrating. DAWs are geared towards +sequencing notes over time in predictable ways, whereas Strudel and similar Uzu languages are geared towards combining and transforming patterns in ways that can be hard to predict. -If you want to emulate the functionality of a DAW in Strudel, you'll have to identify the operations -executed by the DAW (sequencing, repeating, applying filters and envelopes) and write code that is equivalent to these +If you want to emulate the functionality of a DAW in Strudel, you'll have to identify the operations +executed by the DAW (sequencing, repeating, applying filters and envelopes) and write code that is equivalent to these operations. For example in Strudel, the 'arrange' and 'pick' methods are useful for sequencing patterns over time (see question on these later in this document). -You might still find that the typical DAW workflow is not really adapted to live coding because, despite -both being ways of making music on the computer, they are two very different tools. You could then adapt your way of proceeding +You might still find that the typical DAW workflow is not really adapted to live coding because, despite +both being ways of making music on the computer, they are two very different tools. You could then adapt your way of proceeding to the medium of code, which might mean leaving more place to serendipity and writing code that you don't predict the output of. ## Why doesn't everyone just use a DAW? @@ -329,9 +329,3 @@ s increase by one semitone, i.e. sharp, works for steps of scales, note names $: at the start of a line, defines a member of the stack. is the only stack name that should occur multiple names _ before a stack name: mutes the stack, i.e. hush(), for example _$: s("bd"), see above for a different usage. ``` - -## Are there more FAQ items? - -These pages have been taken from [this pad](https://doc.patternclub.org/_CgofWouTciXXHexUP9AVg?both). Some of the items there have not been brushed up and brought here. - -These include the following items: 9, 11, 12 and 19 From a659c89385b84e08c001c47669fb98253ffb55f9 Mon Sep 17 00:00:00 2001 From: floy Date: Sun, 11 Jan 2026 13:25:44 +0100 Subject: [PATCH 27/30] fix code formatting --- website/src/repl/components/panel/SoundsTab.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/website/src/repl/components/panel/SoundsTab.jsx b/website/src/repl/components/panel/SoundsTab.jsx index 2060c64a9..5a7df5ba9 100644 --- a/website/src/repl/components/panel/SoundsTab.jsx +++ b/website/src/repl/components/panel/SoundsTab.jsx @@ -210,10 +210,11 @@ export function SoundsTab() { ) : ( '' )} - {!soundEntries.length && soundsFilter !== 'importSounds' ? - search == '' ? 'No sounds loaded' : 'No sounds found' - : '' - } + {!soundEntries.length && soundsFilter !== 'importSounds' + ? search == '' + ? 'No sounds loaded' + : 'No sounds found' + : ''}
); From 8d2bca59c4373a74d6f05ecb9432b5384135109c Mon Sep 17 00:00:00 2001 From: JesCoding Date: Wed, 24 Dec 2025 11:39:28 +0100 Subject: [PATCH 28/30] Fix sounds example to work in the REPL `freq` only takes one argument, so switch this to mini-notation so this can be used in the REPL as indicated in the paragraph below. Make it so this can be played by the user. Fix syntax-type typo. --- website/src/pages/technical-manual/sounds.mdx | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/website/src/pages/technical-manual/sounds.mdx b/website/src/pages/technical-manual/sounds.mdx index 11078713f..73ae05796 100644 --- a/website/src/pages/technical-manual/sounds.mdx +++ b/website/src/pages/technical-manual/sounds.mdx @@ -13,7 +13,7 @@ Let's take a closer look about how sounds are implemented in the webaudio output All sounds are registered in the sound map, using the the `registerSound` function: -```ts +```js function registerSound( name: string, // The name of the sound that should be given to `s`, e.g. `mysaw` // The function called by the scheduler to trigger the sound: @@ -35,34 +35,36 @@ When `registerSound` is called, it registers `{ onTrigger, data }` under the giv This might be a bit abstract, so here is a minimal example: -```js -registerSound( - 'mysaw', - (time, value, onended) => { - let { freq } = value; // destructure control params - const ctx = getAudioContext(); - // create oscillator - const o = new OscillatorNode(ctx, { type: 'sawtooth', frequency: Number(freq) }); - o.start(time); - // add gain node to level down osc - const g = new GainNode(ctx, { gain: 0.3 }); - // connect osc to gain - const node = o.connect(g); - // this function can be called from outside to stop the sound - const stop = (time) => o.stop(time); - // ended will be fired when stop has been fired - o.addEventListener('ended', () => { - o.disconnect(); - g.disconnect(); - onended(); - }); - return { node, stop }; - }, - { type: 'synth' }, -); -// use the sound -freq(220, 440, 330).s('mysaw'); -``` + { + let { freq } = value; // destructure control params + const ctx = getAudioContext(); + // create oscillator + const o = new OscillatorNode(ctx, { type: 'sawtooth', frequency: Number(freq) }); + o.start(time); + // add gain node to level down osc + const g = new GainNode(ctx, { gain: 0.3 }); + // connect osc to gain + const node = o.connect(g); + // this function can be called from outside to stop the sound + const stop = (time) => o.stop(time); + // ended will be fired when stop has been fired + o.addEventListener('ended', () => { + o.disconnect(); + g.disconnect(); + onended(); + }); + return { node, stop }; + }, + { type: 'synth' }, + ); + // use the sound + freq("220 440 330").s('mysaw');`} +/> You can actually use this code in the [REPL](https://strudel.cc/) and it'll work. After evaluating the code, you should see `mysaw` in listed in the sounds tab. From 31cacc3c29a18e59761cda66e912c8ee8e00d8a3 Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 11 Jan 2026 16:23:17 +0000 Subject: [PATCH 29/30] add warm to faq --- website/src/pages/learn/faq.mdx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/website/src/pages/learn/faq.mdx b/website/src/pages/learn/faq.mdx index e43839dc3..fc3bcdb2d 100644 --- a/website/src/pages/learn/faq.mdx +++ b/website/src/pages/learn/faq.mdx @@ -19,6 +19,14 @@ While there is no charge there are some caveats, e.g.: - the source code must stay free, i.e. you cannot distribute strudel or tidal as part of projects with incompatible licenses - see the [license](https://www.gnu.org/licenses/agpl-3.0.en.html) for details. - the contributed examples and tracks are also separately licensed, and must not e.g. be used to train AI models without permission. +## How do I try out the latest features? + +The main, stable strudel website is [strudel.cc](https://strudel.cc/). There is also [warm.strudel.cc](https://warm.strudel.cc), known as "warm strudel", which has the latest development features. You might find warm strudel has bug fixes and features that the main website doesn't, but it will often be less stable and probably not suitable for important performances. + +Alternatively, you can run strudel locally to try out the latest features. You can find development-oriented [instructions for that here](https://codeberg.org/uzu/strudel/src/branch/main/CONTRIBUTING.md#project-setup). + +You can see the [latest changes here](https://codeberg.org/uzu/strudel/pulls?q=&type=all&sort=recentupdate&state=closed&labels=&milestone=0&project=0&assignee=0&poster=0), as 'pull requests'. + ## How to record or export audio? Strudel is not a digital audio workstation and does not operate following the same principles shared by most traditional audio softwares. However, there are multiple ways to record the audio -- and video -- output of Strudel: From 753dc48b69ef800d21efe4541a6126b30e9f292e Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 11 Jan 2026 19:12:45 +0100 Subject: [PATCH 30/30] update changelog --- CHANGELOG.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a13e379d9..19a502f33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,62 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly sorted... +## january 2026 + +- 2026-01-11T19:00:25+01:00 Fix sounds example to work in the REPL by JesCoding in: [#1851](https://codeberg.org/uzu/strudel/pulls/1851) +- 2026-01-11T13:52:02+01:00 Improve hint text when sound search has no results by floy in: [#1883](https://codeberg.org/uzu/strudel/pulls/1883) +- 2026-01-11T12:45:07+01:00 fix: remove faulty default readme by froos in: [#1889](https://codeberg.org/uzu/strudel/pulls/1889) +- 2026-01-11T12:15:34+01:00 fix/self-hosted-config by alienmind in: [#1880](https://codeberg.org/uzu/strudel/pulls/1880) +- 2026-01-11T12:07:48+01:00 Feat: Support External AudioContext Injection by 1d10t in: [#1833](https://codeberg.org/uzu/strudel/pulls/1833) +- 2026-01-11T11:37:37+01:00 fix: add trem to top level by froos in: [#1887](https://codeberg.org/uzu/strudel/pulls/1887) +- 2026-01-11T11:37:18+01:00 fix: export start cycle min 0 by froos in: [#1888](https://codeberg.org/uzu/strudel/pulls/1888) +- 2026-01-11T11:05:44+01:00 fix: repl package init audio properly by froos in: [#1836](https://codeberg.org/uzu/strudel/pulls/1836) +- 2026-01-11T06:51:24+01:00 Fix: show reload dialog when uploading prebake script by daslyfe in: [#1886](https://codeberg.org/uzu/strudel/pulls/1886) +- 2026-01-11T06:01:42+01:00 fixes Serial onTrigger() params #1633 by gueejla in: [#1885](https://codeberg.org/uzu/strudel/pulls/1885) +- 2026-01-10T20:52:40+01:00 Allow top level distortions for the purpose of FX by glossing in: [#1884](https://codeberg.org/uzu/strudel/pulls/1884) +- 2026-01-10T23:12:48+01:00 Perf: Targeted node pools by glossing in: [#1810](https://codeberg.org/uzu/strudel/pulls/1810) +- 2026-01-09T03:43:37+01:00 Bake in scaling by `freq` for FM with a gain node by glossing in: [#1878](https://codeberg.org/uzu/strudel/pulls/1878) +- 2026-01-09T02:53:38+01:00 Bug fix: Properly handle subcontrols by glossing in: [#1877](https://codeberg.org/uzu/strudel/pulls/1877) +- 2026-01-07T20:06:18+01:00 Feat: Add ability to turn mini parsing off with mini-off decorator by glossing in: [#1786](https://codeberg.org/uzu/strudel/pulls/1786) +- 2026-01-07T19:22:24+01:00 Bug Fix: Update loopStart/End to not be offset by glossing in: [#1826](https://codeberg.org/uzu/strudel/pulls/1826) +- 2026-01-06T06:35:49+01:00 Update modulator docstrings and allow ids to be patterns by glossing in: [#1874](https://codeberg.org/uzu/strudel/pulls/1874) +- 2026-01-04T17:14:11+01:00 Fix doc link in @strudel/osc README.md by forrcaho in: [#1872](https://codeberg.org/uzu/strudel/pulls/1872) +- 2026-01-04T02:01:07+01:00 Make stretch modulatable by glossing in: [#1870](https://codeberg.org/uzu/strudel/pulls/1870) +- 2026-01-02T18:44:53+01:00 Make pan modulatable by glossing in: [#1865](https://codeberg.org/uzu/strudel/pulls/1865) +- 2026-01-01T21:42:23+01:00 Fix transpilation example to have same mini-notation by JesCoding in: [#1850](https://codeberg.org/uzu/strudel/pulls/1850) +- 2026-01-01T21:39:05+01:00 fix: missing punctuation by eddyflux in: [#1860](https://codeberg.org/uzu/strudel/pulls/1860) +- 2026-01-01T20:20:34+01:00 Fix formatting of docstring by glossing in: [#1864](https://codeberg.org/uzu/strudel/pulls/1864) +- 2026-01-01T19:52:15+01:00 Feat: FX Chains by glossing in: [#1861](https://codeberg.org/uzu/strudel/pulls/1861) + +## december 2025 + +- 2025-12-29T21:59:11+01:00 Bugfix: Fix modulator clamping when min/max not specified by glossing in: [#1859](https://codeberg.org/uzu/strudel/pulls/1859) +- 2025-12-29T16:07:18+01:00 Fix AudioContext change detection. Use AudioNode.context by jeromew in: [#1858](https://codeberg.org/uzu/strudel/pulls/1858) +- 2025-12-28T14:20:03+01:00 dough repl fixes by froos in: [#1855](https://codeberg.org/uzu/strudel/pulls/1855) +- 2025-12-19T08:11:50+01:00 fix: visual block selection mode for vim bindings by Dsm0 in: [#1839](https://codeberg.org/uzu/strudel/pulls/1839) +- 2025-12-28T22:58:38+01:00 Say that @license should use SPDX identifier by Wuzzy in: [#1817](https://codeberg.org/uzu/strudel/pulls/1817) +- 2025-12-28T22:56:07+01:00 Expose Vim object in order to create custom keybindings by JohnBjrk in: [#1816](https://codeberg.org/uzu/strudel/pulls/1816) +- 2025-12-20T22:27:52+01:00 Document "-" in mini-notation by Wuzzy in: [#1818](https://codeberg.org/uzu/strudel/pulls/1818) +- 2025-12-20T22:20:27+01:00 simplify envValAtTime and remove asymmetric behavior (fix #1653) by pulu in: [#1815](https://codeberg.org/uzu/strudel/pulls/1815) +- 2025-12-14T15:09:12+01:00 delta -> per / perx / cyclesPer refinements by yaxu in: [#1832](https://codeberg.org/uzu/strudel/pulls/1832) +- 2025-12-14T19:33:37+01:00 Fix: wrong warning in build environments by jeromew in: [#1835](https://codeberg.org/uzu/strudel/pulls/1835) +- 2025-12-12T10:28:27+01:00 Add delta signal for representing the duration of events in patterns that are combined with it by yaxu in: [#1831](https://codeberg.org/uzu/strudel/pulls/1831) +- 2025-12-11T16:37:58+01:00 Updates relating to LLM, github, etc by yaxu in: [#1830](https://codeberg.org/uzu/strudel/pulls/1830) +- 2025-12-10T15:32:44+01:00 fix .as so it doesn't set undefined values by yaxu in: [#1827](https://codeberg.org/uzu/strudel/pulls/1827) +- 2025-12-08T19:27:31+01:00 [perf] propagate `onceEnded` and `releaseAudioNode` by jeromew in: [#1809](https://codeberg.org/uzu/strudel/pulls/1809) +- 2025-12-07T19:15:43+01:00 Add vel as a synonym for velocity & update a few docstrings by glossing in: [#1781](https://codeberg.org/uzu/strudel/pulls/1781) +- 2025-12-07T18:53:04+01:00 [perf] fix phaser leak of unused biquads by jeromew in: [#1800](https://codeberg.org/uzu/strudel/pulls/1800) +- 2025-12-07T18:42:50+01:00 Bug fix: Remove failing tests due to shabda removal by glossing in: [#1820](https://codeberg.org/uzu/strudel/pulls/1820) +- 2025-12-03T17:35:05+01:00 [perf] release unused AudioBufferSourceNode + releaseAudioNode by jeromew in: [#1805](https://codeberg.org/uzu/strudel/pulls/1805) +- **2025-12-01 strudel.cc deployed** + ## november 2025 +- 2025-11-29T01:00:42+01:00 added export to getSuperdoughAudioController() so that its possible to route superdough audio through other webaudio applications. by ndr0n in: [#1796](https://codeberg.org/uzu/strudel/pulls/1796) +- 2025-11-28T23:26:20+01:00 add revv() for reversing whole patterns by yaxu in: [#1791](https://codeberg.org/uzu/strudel/pulls/1791) +- 2025-11-28T20:19:16+01:00 [perf] Disconnect lfos for phaser and filters by glossing in: [#1787](https://codeberg.org/uzu/strudel/pulls/1787) +- 2025-11-27T23:08:52+01:00 fix: return silence when no pattern is returned by froos in: [#1795](https://codeberg.org/uzu/strudel/pulls/1795) +- 2025-11-27T22:38:05+01:00 add CHANGELOG.md + basic script to generate by froos in: [#1794](https://codeberg.org/uzu/strudel/pulls/1794) - 2025-11-27T22:03:53+01:00 [perf] in `noise`, let noiseMix do the disconnect when it exists by jeromew in: [#1783](https://codeberg.org/uzu/strudel/pulls/1783) - 2025-11-27T22:01:01+01:00 Bug Fix: Retries for sounds tab by glossing in: [#1754](https://codeberg.org/uzu/strudel/pulls/1754) - 2025-11-27T20:36:46+01:00 [hydra] return the hydra object when await initHydra(..) is called by jeromew in: [#1784](https://codeberg.org/uzu/strudel/pulls/1784) @@ -52,6 +106,7 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly - 2025-10-28T22:51:16+01:00 Repurpose vim shortcuts for usability by dtricks in: [#1624](https://codeberg.org/uzu/strudel/pulls/1624) - 2025-10-28T22:35:21+01:00 Add support for euclidian in mondo with `bd&3:8` by TristanCacqueray in: [#1630](https://codeberg.org/uzu/strudel/pulls/1630) - 2025-10-27T10:42:07+01:00 Use bunny cdn for all samples and json files by yaxu in: [#1701](https://codeberg.org/uzu/strudel/pulls/1701) +- **2025-10-27 @strudel/core@1.2.5** - 2025-10-26T22:52:54+01:00 degithub - switch some samples to bunnycdn by yaxu in: [#1697](https://codeberg.org/uzu/strudel/pulls/1697) - 2025-10-26T17:09:22+01:00 Fix ZZFX example by moumar in: [#1685](https://codeberg.org/uzu/strudel/pulls/1685) - 2025-10-23T15:56:04+02:00 Make osc port and host configurable. Changes dependencies. by yaxu in: [#1682](https://codeberg.org/uzu/strudel/pulls/1682)