From c62428ca27b34f62598db1506dd42af36f23f80f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Va=CC=81clav=20Volhejn?=
Date: Sun, 12 Oct 2025 16:07:11 +0200
Subject: [PATCH 030/476] Document remaining functions
---
packages/codemirror/codemirror.mjs | 1 +
packages/codemirror/slider.mjs | 1 +
packages/core/controls.mjs | 7 +-
packages/core/drawLine.mjs | 1 +
packages/core/euclid.mjs | 5 +
packages/core/pattern.mjs | 159 ++++++++++++++-------------
packages/core/pick.mjs | 13 +++
packages/core/repl.mjs | 5 +
packages/core/signal.mjs | 1 +
packages/csound/index.mjs | 2 +
packages/draw/pianoroll.mjs | 2 +
packages/draw/pitchwheel.mjs | 1 +
packages/draw/spiral.mjs | 1 +
packages/midi/midi.mjs | 4 +
packages/osc/osc.mjs | 1 +
packages/superdough/ola-processor.js | 29 +++--
packages/superdough/reverbGen.mjs | 5 +-
packages/superdough/sampler.mjs | 1 +
packages/superdough/superdough.mjs | 3 +
packages/superdough/wavetable.mjs | 1 +
packages/superdough/worklets.mjs | 20 +++-
packages/tonal/tonal.mjs | 3 +
packages/tonal/voicings.mjs | 4 +
packages/webaudio/scope.mjs | 2 +
packages/webaudio/spectrum.mjs | 1 +
25 files changed, 179 insertions(+), 94 deletions(-)
diff --git a/packages/codemirror/codemirror.mjs b/packages/codemirror/codemirror.mjs
index 4dc23996f..193b93e3e 100644
--- a/packages/codemirror/codemirror.mjs
+++ b/packages/codemirror/codemirror.mjs
@@ -379,6 +379,7 @@ function s4() {
/**
* Overrides the css of highlighted events. Make sure to use single quotes!
* @name markcss
+ * @tag visualization
* @example
* note("c a f e")
* .markcss('text-decoration:underline')
diff --git a/packages/codemirror/slider.mjs b/packages/codemirror/slider.mjs
index 72f951254..cc224a6cc 100644
--- a/packages/codemirror/slider.mjs
+++ b/packages/codemirror/slider.mjs
@@ -117,6 +117,7 @@ export const sliderPlugin = ViewPlugin.fromClass(
* Displays a slider widget to allow the user manipulate a value
*
* @name slider
+ * @tags external_io, visualization
* @param {number} value Initial value
* @param {number} min Minimum value - optional, defaults to 0
* @param {number} max Maximum value - optional, defaults to 1
diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs
index 44b358e67..4e60fc487 100644
--- a/packages/core/controls.mjs
+++ b/packages/core/controls.mjs
@@ -949,6 +949,7 @@ export const { duckattack } = registerControl('duckattack', 'duckatt');
*
* @name byteBeatExpression
* @synonyms bbexpr
+ * @tags effects
*
* @param {number | Pattern} byteBeatExpression bitwise expression for creating bytebeat
* @example
@@ -962,6 +963,7 @@ export const { byteBeatExpression, bbexpr } = registerControl('byteBeatExpressio
*
* @name byteBeatStartTime
* @synonyms bbst
+ * @tags effects
*
* @param {number | Pattern} byteBeatStartTime in samples (t)
* @example
@@ -1518,7 +1520,7 @@ export const { delayspeed } = registerControl('delayspeed');
* Sets the time of the delay effect.
*
* @name delayspeed
- * @tags effects, foo
+ * @tags effects
* @param {number | Pattern} delayspeed controls the pitch of the delay feedback
* @synonyms delayt, dt
* @example
@@ -1544,7 +1546,7 @@ export const { delaysync } = registerControl('delaysync');
* Specifies whether delaytime is calculated relative to cps.
*
* @name lock
- * @tags effects, foo
+ * @tags effects
* @param {number | Pattern} enable When set to 1, delaytime is a direct multiple of a cycle.
* @superdirtOnly
* @example
@@ -1812,6 +1814,7 @@ export const { octave } = registerControl('octave');
* An `orbit` is a global parameter context for patterns. Patterns with the same orbit will share the same global effects.
*
* @name orbit
+ * @tags effects
* @param {number | Pattern} number
* @example
* stack(
diff --git a/packages/core/drawLine.mjs b/packages/core/drawLine.mjs
index 7509c0f6f..212d06279 100644
--- a/packages/core/drawLine.mjs
+++ b/packages/core/drawLine.mjs
@@ -15,6 +15,7 @@ import Fraction, { gcd } from './fraction.mjs';
* - "-" hold previous value
* - "." silence
*
+ * @tags visualization
* @param {Pattern} pattern the pattern to use
* @param {number} chars max number of characters (approximately)
* @returns string
diff --git a/packages/core/euclid.mjs b/packages/core/euclid.mjs
index 44ab07f11..e8252a984 100644
--- a/packages/core/euclid.mjs
+++ b/packages/core/euclid.mjs
@@ -61,6 +61,7 @@ export const bjork = function (ons, steps) {
*
* @memberof Pattern
* @name euclid
+ * @tags temporal
* @param {number} pulses the number of onsets/beats
* @param {number} steps the number of steps to fill
* @returns Pattern
@@ -73,6 +74,7 @@ export const bjork = function (ons, steps) {
* Like `euclid`, but has an additional parameter for 'rotating' the resulting sequence.
* @memberof Pattern
* @name euclidRot
+ * @tags temporal
* @param {number} pulses the number of onsets/beats
* @param {number} steps the number of steps to fill
* @param {number} rotation offset in steps
@@ -156,6 +158,7 @@ export const { euclidrot, euclidRot } = register(['euclidrot', 'euclidRot'], fun
* so there will be no gaps.
* @name euclidLegato
* @memberof Pattern
+ * @tags temporal
* @param {number} pulses the number of onsets/beats
* @param {number} steps the number of steps to fill
* @param rotation offset in steps
@@ -187,6 +190,7 @@ export const euclidLegato = register(['euclidLegato'], function (pulses, steps,
* the resulting sequence
* @name euclidLegatoRot
* @memberof Pattern
+ * @tags temporal
* @param {number} pulses the number of onsets/beats
* @param {number} steps the number of steps to fill
* @param {number} rotation offset in steps
@@ -208,6 +212,7 @@ export const euclidLegatoRot = register(['euclidLegatoRot'], function (pulses, s
* @name euclidish
* @synonyms eish
* @memberof Pattern
+ * @tags temporal
* @param {number} pulses the number of onsets
* @param {number} steps the number of steps to fill
* @param {number} groove exists between the extremes of 0 (straight euclidian) and 1 (straight pulse)
diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs
index 39d6555f5..2d6459a89 100644
--- a/packages/core/pattern.mjs
+++ b/packages/core/pattern.mjs
@@ -889,7 +889,7 @@ export class Pattern {
/**
* Writes the content of the current event to the console (visible in the side menu).
- * @tags visualizers
+ * @tags visualization
* @name log
* @memberof Pattern
* @example
@@ -904,7 +904,7 @@ export class Pattern {
/**
* A simplified version of `log` which writes all "values" (various configurable parameters)
* within the event to the console (visible in the side menu).
- * @tags visualizers
+ * @tags visualization
* @name logValues
* @memberof Pattern
* @example
@@ -938,7 +938,7 @@ export class Pattern {
* source pattern to be looped, and for an (optional) given function to be
* applied. False values result in the corresponding part of the source pattern
* to be played unchanged.
- * @tags structure
+ * @tags temporal
* @name into
* @memberof Pattern
* @example
@@ -1066,6 +1066,7 @@ function _composeOp(a, b, func) {
* Assumes a pattern of numbers. Adds the given number to each item in the pattern.
* @name add
* @memberof Pattern
+ * @tags math
* @example
* // Here, the triad 0, 2, 4 is shifted by different amounts
* n("0 2 4".add("<0 3 4 0>")).scale("C:major")
@@ -1076,7 +1077,6 @@ function _composeOp(a, b, func) {
* note("c3 e3 g3".add("<0 5 7 0>"))
* // Behind the scenes, the notes are converted to midi numbers:
* // note("48 52 55".add("<0 5 7 0>"))
- * @tags math
*/
add: [numeralArgs((a, b) => a + b)], // support string concatenation
/**
@@ -1084,6 +1084,7 @@ function _composeOp(a, b, func) {
* Like add, but the given numbers are subtracted.
* @name sub
* @memberof Pattern
+ * @tags math
* @example
* n("0 2 4".sub("<0 1 2 3>")).scale("C4:minor")
* // See add for more information.
@@ -1094,6 +1095,7 @@ function _composeOp(a, b, func) {
* Multiplies each number by the given factor.
* @name mul
* @memberof Pattern
+ * @tags math
* @example
* "<1 1.5 [1.66, <2 2.33>]>*4".mul(150).freq()
*/
@@ -1103,6 +1105,7 @@ function _composeOp(a, b, func) {
* Divides each number by the given factor.
* @name div
* @memberof Pattern
+ * @tags math
*/
div: [numeralArgs((a, b) => a / b)],
mod: [numeralArgs(_mod)],
@@ -1189,7 +1192,7 @@ function _composeOp(a, b, func) {
/**
* Applies the given structure to the pattern:
*
- * @tags structure
+ * @tags temporal
* @example
* note("c,eb,g")
* .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~")
@@ -1204,7 +1207,7 @@ function _composeOp(a, b, func) {
/**
* Returns silence when mask is 0 or "~"
*
- * @tags structure
+ * @tags temporal
* @example
* note("c [eb,g] d [eb,g]").mask("<1 [0 1]>")
*/
@@ -1217,7 +1220,7 @@ function _composeOp(a, b, func) {
/**
* Resets the pattern to the start of the cycle for each onset of the reset pattern.
*
- * @tags structure
+ * @tags temporal
* @example
* s("[ sd]*2, hh*8").reset("")
*/
@@ -1231,7 +1234,7 @@ function _composeOp(a, b, func) {
* Restarts the pattern for each onset of the restart pattern.
* While reset will only reset the current cycle, restart will start from cycle 0.
*
- * @tags structure
+ * @tags temporal
* @example
* s("[ sd]*2, hh*8").restart("")
*/
@@ -1352,7 +1355,7 @@ export function sequenceP(pats) {
/**
* The given items are played at the same time at the same length.
*
- * @tags structure
+ * @tags temporal
* @return {Pattern}
* @synonyms polyrhythm, pr
* @example
@@ -1566,14 +1569,9 @@ export function fastcat(...pats) {
return result;
}
-/** See `fastcat` */
-export function sequence(...pats) {
- return fastcat(...pats);
-}
-
/** Like **cat**, but the items are crammed into one cycle.
* @tags combiners
- * @synonyms sequence, fastcat
+ * @synonyms seq, fastcat
* @example
* seq("e5", "b4", ["d5", "c5"]).note()
* // "e5 b4 [d5 c5]".note()
@@ -1584,6 +1582,9 @@ export function sequence(...pats) {
* note("c4(5,8)")
* )
*/
+export function sequence(...pats) {
+ return fastcat(...pats);
+}
export function seq(...pats) {
return fastcat(...pats);
@@ -1877,7 +1878,7 @@ export const ratio = register('ratio', (pat) =>
// Structural and temporal transformations
/** Compress each cycle into the given timespan, leaving a gap
- * @tags structure
+ * @tags temporal
* @example
* cat(
* s("bd sd").compress(.25,.75),
@@ -1899,7 +1900,7 @@ export const { compressSpan, compressspan } = register(['compressSpan', 'compres
/**
* speeds up a pattern like fast, but rather than it playing multiple times as fast would it instead leaves a gap in the remaining space of the cycle. For example, the following will play the sound pattern "bd sn" only once but compressed into the first half of the cycle, i.e. twice as fast.
- * @tags structure
+ * @tags temporal
* @name fastGap
* @synonyms fastgap
* @example
@@ -1937,7 +1938,7 @@ export const { fastGap, fastgap } = register(['fastGap', 'fastgap'], function (f
/**
* Similar to `compress`, but doesn't leave gaps, and the 'focus' can be bigger than a cycle
- * @tags structure
+ * @tags temporal
* @example
* s("bd hh sd hh").focus(1/4, 3/4)
*/
@@ -1955,7 +1956,7 @@ export const { focusSpan, focusspan } = register(['focusSpan', 'focusspan'], fun
});
/** The ply function repeats each event the given number of times.
- * @tags structure
+ * @tags temporal
* @example
* s("bd ~ sd cp").ply("<1 2 3>")
*/
@@ -1970,7 +1971,7 @@ export const ply = register('ply', function (factor, pat) {
/**
* Speed up a pattern by the given factor. Used by "*" in mini notation.
*
- * @tags structure
+ * @tags temporal
* @name fast
* @synonyms density
* @memberof Pattern
@@ -1995,7 +1996,7 @@ export const { fast, density } = register(
/**
* Both speeds up the pattern (like 'fast') and the sample playback (like 'speed').
- * @tags structure
+ * @tags temporal
* @example
* s("bd sd:2").hurry("<1 2 4 3>").slow(1.5)
*/
@@ -2006,7 +2007,7 @@ export const hurry = register('hurry', function (r, pat) {
/**
* Slow down a pattern over the given number of cycles. Like the "/" operator in mini notation.
*
- * @tags structure
+ * @tags temporal
* @name slow
* @synonyms sparsity
* @memberof Pattern
@@ -2024,7 +2025,7 @@ export const { slow, sparsity } = register(['slow', 'sparsity'], function (facto
/**
* Carries out an operation 'inside' a cycle.
- * @tags structure
+ * @tags temporal
* @example
* "0 1 2 3 4 3 2 1".inside(4, rev).scale('C major').note()
* // "0 1 2 3 4 3 2 1".slow(4).rev().fast(4).scale('C major').note()
@@ -2035,7 +2036,7 @@ export const inside = register('inside', function (factor, f, pat) {
/**
* Carries out an operation 'outside' a cycle.
- * @tags structure
+ * @tags temporal
* @example
* "<[0 1] 2 [3 4] 5>".outside(4, rev).scale('C major').note()
* // "<[0 1] 2 [3 4] 5>".fast(4).rev().slow(4).scale('C major').note()
@@ -2046,7 +2047,7 @@ export const outside = register('outside', function (factor, f, pat) {
/**
* Applies the given function every n cycles, starting from the last cycle.
- * @tags structure
+ * @tags temporal
* @name lastOf
* @memberof Pattern
* @param {number} n how many cycles
@@ -2063,7 +2064,7 @@ export const lastOf = register('lastOf', function (n, func, pat) {
/**
* Applies the given function every n cycles, starting from the first cycle.
- * @tags structure
+ * @tags temporal
* @name firstOf
* @memberof Pattern
* @param {number} n how many cycles
@@ -2075,7 +2076,7 @@ export const lastOf = register('lastOf', function (n, func, pat) {
/**
* An alias for `firstOf`
- * @tags structure
+ * @tags temporal
* @name every
* @memberof Pattern
* @param {number} n how many cycles
@@ -2092,7 +2093,7 @@ export const { firstOf, every } = register(['firstOf', 'every'], function (n, fu
/**
* Like layer, but with a single function:
- * @tags structure
+ * @tags temporal
* @name apply
* @example
* "".scale('C minor').apply(scaleTranspose("0,2,4")).note()
@@ -2104,7 +2105,7 @@ export const apply = register('apply', function (func, pat) {
/**
* Plays the pattern at the given cycles per minute.
- * @tags structure
+ * @tags temporal
* @deprecated
* @example
* s(",hh*2").cpm(90) // = 90 bpm
@@ -2117,7 +2118,7 @@ export const cpm = register('cpm', function (cpm, pat) {
/**
* Nudge a pattern to start earlier in time. Equivalent of Tidal's <~ operator
*
- * @tags structure
+ * @tags temporal
* @name early
* @memberof Pattern
* @param {number | Pattern} cycles number of cycles to nudge left
@@ -2138,7 +2139,7 @@ export const early = register(
/**
* Nudge a pattern to start later in time. Equivalent of Tidal's ~> operator
*
- * @tags structure
+ * @tags temporal
* @name late
* @memberof Pattern
* @param {number | Pattern} cycles number of cycles to nudge right
@@ -2159,7 +2160,7 @@ export const late = register(
/**
* Plays a portion of a pattern, specified by the beginning and end of a time span. The new resulting pattern is played over the time period of the original pattern:
*
- * @tags structure
+ * @tags temporal
* @example
* s("bd*2 hh*3 [sd bd]*2 perc").zoom(0.25, 0.75)
* // s("hh*3 [sd bd]*2") // equivalent
@@ -2186,7 +2187,7 @@ export const { zoomArc, zoomarc } = register(['zoomArc', 'zoomarc'], function (a
/**
* Splits a pattern into the given number of slices, and plays them according to a pattern of slice numbers.
* Similar to `slice`, but slices up patterns rather than sound samples.
- * @tags structure
+ * @tags temporal
* @param {number} number of slices
* @param {number} slices to play
* @example
@@ -2214,7 +2215,7 @@ export const bite = register(
/**
* Selects the given fraction of the pattern and repeats that part to fill the remainder of the cycle.
- * @tags structure
+ * @tags temporal
* @param {number} fraction fraction to select
* @example
* s("lt ht mt cp, [hh oh]*2").linger("<1 .5 .25 .125>")
@@ -2235,7 +2236,7 @@ export const linger = register(
/**
* Samples the pattern at a rate of n events per cycle. Useful for turning a continuous pattern into a discrete one.
- * @tags structure
+ * @tags temporal
* @name segment
* @synonyms seg
* @param {number} segments number of segments per cycle
@@ -2248,7 +2249,7 @@ export const { segment, seg } = register(['segment', 'seg'], function (rate, pat
/**
* The function `swingBy x n` breaks each cycle into `n` slices, and then delays events in the second half of each slice by the amount `x`, which is relative to the size of the (half) slice. So if `x` is 0 it does nothing, `0.5` delays for half the note duration, and 1 will wrap around to doing nothing again. The end result is a shuffle or swing-like rhythm
- * @tags structure
+ * @tags temporal
* @param {number} subdivision
* @param {number} offset
* @example
@@ -2258,7 +2259,7 @@ export const swingBy = register('swingBy', (swing, n, pat) => pat.inside(n, late
/**
* Shorthand for swingBy with 1/3:
- * @tags structure
+ * @tags temporal
* @param {number} subdivision
* @example
* s("hh*8").swing(4)
@@ -2268,7 +2269,7 @@ export const swing = register('swing', (n, pat) => pat.swingBy(1 / 3, n));
/**
* Swaps 1s and 0s in a binary pattern.
- * @tags structure
+ * @tags temporal
* @name invert
* @synonyms inv
* @example
@@ -2286,7 +2287,7 @@ export const { invert, inv } = register(
/**
* Applies the given function whenever the given pattern is in a true state.
- * @tags structure
+ * @tags temporal
* @name when
* @memberof Pattern
* @param {Pattern} binary_pat
@@ -2301,7 +2302,7 @@ export const when = register('when', function (on, func, pat) {
/**
* Superimposes the function result on top of the original pattern, delayed by the given time.
- * @tags structure
+ * @tags temporal
* @name off
* @memberof Pattern
* @param {Pattern | number} time offset time
@@ -2318,7 +2319,7 @@ export const off = register('off', function (time_pat, func, pat) {
* Returns a new pattern where every other cycle is played once, twice as
* fast, and offset in time by one quarter of a cycle. Creates a kind of
* breakbeat feel.
- * @tags structure
+ * @tags temporal
* @returns Pattern
*/
export const brak = register('brak', function (pat) {
@@ -2328,7 +2329,7 @@ export const brak = register('brak', function (pat) {
/**
* Reverse all haps in a pattern
*
- * @tags structure
+ * @tags temporal
* @name rev
* @memberof Pattern
* @returns Pattern
@@ -2362,7 +2363,7 @@ export const rev = register(
/** Like press, but allows you to specify the amount by which each
* event is shifted. pressBy(0.5) is the same as press, while
* pressBy(1/3) shifts each event by a third of its timespan.
- * @tags structure
+ * @tags temporal
* @example
* stack(s("hh*4"),
* s("bd mt sd ht").pressBy("<0 0.5 0.25>")
@@ -2374,7 +2375,7 @@ export const pressBy = register('pressBy', function (r, pat) {
/**
* Syncopates a rhythm, by shifting each event halfway into its timespan.
- * @tags structure
+ * @tags temporal
* @example
* stack(s("hh*4"),
* s("bd mt sd ht").every(4, press)
@@ -2386,7 +2387,7 @@ export const press = register('press', function (pat) {
/**
* Silences a pattern.
- * @tags structure
+ * @tags temporal
* @example
* stack(
* s("bd").hush(),
@@ -2399,7 +2400,7 @@ Pattern.prototype.hush = function () {
/**
* Applies `rev` to a pattern every other cycle, so that the pattern alternates between forwards and backwards.
- * @tags structure
+ * @tags temporal
* @example
* note("c d e g").palindrome()
*/
@@ -2414,7 +2415,7 @@ export const palindrome = register(
/**
* Jux with adjustable stereo width. 0 = mono, 1 = full stereo.
- * @tags structure
+ * @tags temporal
* @name juxBy
* @synonyms juxby
* @example
@@ -2436,7 +2437,7 @@ export const { juxBy, juxby } = register(['juxBy', 'juxby'], function (by, func,
/**
* The jux function creates strange stereo effects, by applying a function to a pattern, but only in the right-hand channel.
- * @tags structure
+ * @tags temporal
* @example
* s("bd lt [~ ht] mt cp ~ bd hh").jux(rev)
* @example
@@ -2450,7 +2451,7 @@ export const jux = register('jux', function (func, pat) {
/**
* Superimpose and offset multiple times, applying the given function each time.
- * @tags structure
+ * @tags temporal
* @name echoWith
* @synonyms echowith, stutWith, stutwith
* @param {number} times how many times to repeat
@@ -2470,7 +2471,7 @@ export const { echoWith, echowith, stutWith, stutwith } = register(
/**
* Superimpose and offset multiple times, gradually decreasing the velocity
- * @tags structure
+ * @tags temporal
* @name echo
* @memberof Pattern
* @returns Pattern
@@ -2486,7 +2487,7 @@ export const echo = register('echo', function (times, time, feedback, pat) {
/**
* Deprecated. Like echo, but the last 2 parameters are flipped.
- * @tags structure
+ * @tags temporal
* @name stut
* @param {number} times how many times to repeat
* @param {number} feedback velocity multiplicator for each iteration
@@ -2508,7 +2509,7 @@ export const applyN = register('applyN', function (n, func, p) {
/**
* The plyWith function repeats each event the given number of times, applying the given function to each event.\n
- * @tags structure
+ * @tags temporal
* @name plyWith
* @synonyms plywith
* @param {number} factor how many times to repeat
@@ -2531,7 +2532,7 @@ export const plyWith = register(['plyWith', 'plywith'], function (factor, func,
/**
* The plyForEach function repeats each event the given number of times, applying the given function to each event.
* This version of ply uses the iteration index as an argument to the function, similar to echoWith.
- * @tags structure
+ * @tags temporal
* @name plyForEach
* @synonyms plyforeach
* @param {number} factor how many times to repeat
@@ -2553,7 +2554,7 @@ export const plyForEach = register(['plyForEach', 'plyforeach'], function (facto
/**
* Divides a pattern into a given number of subdivisions, plays the subdivisions in order, but increments the starting subdivision each cycle. The pattern wraps to the first subdivision after the last subdivision is played.
- * @tags structure
+ * @tags temporal
* @name iter
* @memberof Pattern
* @returns Pattern
@@ -2581,7 +2582,7 @@ export const iter = register(
/**
* Like `iter`, but plays the subdivisions in reverse order. Known as iter' in tidalcycles
- * @tags structure
+ * @tags temporal
* @name iterBack
* @synonyms iterback
* @memberof Pattern
@@ -2600,7 +2601,7 @@ export const { iterBack, iterback } = register(
/**
* Repeats each cycle the given number of times.
- * @tags structure
+ * @tags temporal
* @name repeatCycles
* @memberof Pattern
* @returns Pattern
@@ -2624,7 +2625,7 @@ export const { repeatCycles } = register(
/**
* Divides a pattern into a given number of parts, then cycles through those parts in turn, applying the given function to each part in turn (one part per cycle).
- * @tags structure
+ * @tags temporal
* @name chunk
* @synonyms slowChunk, slowchunk
* @memberof Pattern
@@ -2656,7 +2657,7 @@ export const { chunk, slowchunk, slowChunk } = register(
/**
* Like `chunk`, but cycles through the parts in reverse order. Known as chunk' in tidalcycles
- * @tags structure
+ * @tags temporal
* @name chunkBack
* @synonyms chunkback
* @memberof Pattern
@@ -2677,7 +2678,7 @@ export const { chunkBack, chunkback } = register(
/**
* Like `chunk`, but the cycles of the source pattern aren't repeated
* for each set of chunks.
- * @tags structure
+ * @tags temporal
* @name fastChunk
* @synonyms fastchunk
* @memberof Pattern
@@ -2698,7 +2699,7 @@ export const { fastchunk, fastChunk } = register(
/**
* Like `chunk`, but the function is applied to a looped subcycle of the source pattern.
- * @tags structure
+ * @tags temporal
* @name chunkInto
* @synonyms chunkinto
* @memberof Pattern
@@ -2712,7 +2713,7 @@ export const { chunkinto, chunkInto } = register(['chunkinto', 'chunkInto'], fun
/**
* Like `chunkInto`, but moves backwards through the chunks.
- * @tags structure
+ * @tags temporal
* @name chunkBackInto
* @synonyms chunkbackinto
* @memberof Pattern
@@ -2743,7 +2744,7 @@ export const bypass = register(
/**
* Loops the pattern inside an `offset` for `cycles`.
* If you think of the entire span of time in cycles as a ribbon, you can cut a single piece and loop it.
- * @tags structure
+ * @tags temporal
* @name ribbon
* @synonyms rib
* @param {number} offset start point of loop in cycles
@@ -2772,7 +2773,7 @@ export const hsl = register('hsl', (h, s, l, pat) => {
/**
* Tags each Hap with an identifier. Good for filtering. The function populates Hap.context.tags (Array).
* @name tag
- * @tags structure
+ * @tags temporal
* @noAutocomplete
* @param {string} tag anything unique
*/
@@ -2783,7 +2784,7 @@ Pattern.prototype.tag = function (tag) {
/**
* Filters haps using the given function
* @name filter
- * @tags structure
+ * @tags temporal
* @param {Function} test function to test Hap
* @example
* s("hh!7 oh").filter(hap => hap.value.s==='hh')
@@ -2793,7 +2794,7 @@ export const filter = register('filter', (test, pat) => pat.withHaps((haps) => h
/**
* Filters haps by their begin time
* @name filterWhen
- * @tags structure
+ * @tags temporal
* @noAutocomplete
* @param {Function} test function to test Hap.whole.begin
*/
@@ -2802,7 +2803,7 @@ export const filterWhen = register('filterWhen', (test, pat) => pat.filter((h) =
/**
* Use within to apply a function to only a part of a pattern.
* @name within
- * @tags structure
+ * @tags temporal
* @param {number} start start within cycle (0 - 1)
* @param {number} end end within cycle (0 - 1). Must be > start
* @param {Function} func function to be applied to the sub-pattern
@@ -2877,7 +2878,7 @@ export function _match(span, hap_p) {
* *Experimental*
*
* Speeds a pattern up or down, to fit to the given number of steps per cycle.
- * @tags structure
+ * @tags temporal
* @example
* sound("bd sd cp").pace(4)
* // The same as sound("{bd sd cp}%4") or sound("*4")
@@ -2919,7 +2920,7 @@ export function _polymeterListSteps(steps, ...args) {
* *Experimental*
*
* Aligns the steps of the patterns, creating polymeters. The patterns are repeated until they all fit the cycle. For example, in the below the first pattern is repeated twice, and the second is repeated three times, to fit the lowest common multiple of six steps.
- * @tags structure
+ * @tags temporal
* @synonyms pm
* @example
* // The same as note("{c eb g, c2 g2}%6")
@@ -3037,7 +3038,7 @@ export function stepalt(...groups) {
*
* Takes the given number of steps from a pattern (dropping the rest).
* A positive number will take steps from the start of a pattern, and a negative number from the end.
- * @tags structure
+ * @tags temporal
* @return {Pattern}
* @example
* "bd cp ht mt".take("2").sound()
@@ -3082,7 +3083,7 @@ export const take = stepRegister('take', function (i, pat) {
*
* Drops the given number of steps from a pattern.
* A positive number will drop steps from the start of a pattern, and a negative number from the end.
- * @tags structure
+ * @tags temporal
* @return {Pattern}
* @example
* "tha dhi thom nam".drop("1").sound().bank("mridangam")
@@ -3111,7 +3112,7 @@ export const drop = stepRegister('drop', function (i, pat) {
* `extend` is similar to `fast` in that it increases its density, but it also increases the step count
* accordingly. So `stepcat("a b".extend(2), "c d")` would be the same as `"a b a b c d"`, whereas
* `stepcat("a b".fast(2), "c d")` would be the same as `"[a b] [a b] c d"`.
- * @tags structure
+ * @tags temporal
* @example
* stepcat(
* sound("bd bd - cp").extend(2),
@@ -3126,7 +3127,7 @@ export const extend = stepRegister('extend', function (factor, pat) {
* *Experimental*
*
* Expands the step size of the pattern by the given factor.
- * @tags structure
+ * @tags temporal
* @example
* sound("tha dhi thom nam").bank("mridangam").expand("3 2 1 1 2 3").pace(8)
*/
@@ -3138,7 +3139,7 @@ export const expand = stepRegister('expand', function (factor, pat) {
* *Experimental*
*
* Contracts the step size of the pattern by the given factor. See also `expand`.
- * @tags structure
+ * @tags temporal
* @example
* sound("tha dhi thom nam").bank("mridangam").contract("3 2 1 1 2 3").pace(8)
*/
@@ -3193,7 +3194,7 @@ export const shrinklist = (amount, pat) => pat.shrinklist(amount);
* Progressively shrinks the pattern by 'n' steps until there's nothing left, or if a second value is given (using mininotation list syntax with `:`),
* that number of times.
* A positive number will progressively drop steps from the start of a pattern, and a negative number from the end.
- * @tags structure
+ * @tags temporal
* @return {Pattern}
* @example
* "tha dhi thom nam".shrink("1").sound()
@@ -3233,7 +3234,7 @@ export const shrink = register(
* Progressively grows the pattern by 'n' steps until the full pattern is played, or if a second value is given (using mininotation list syntax with `:`),
* that number of times.
* A positive number will progressively grow steps from the start of a pattern, and a negative number from the end.
- * @tags structure
+ * @tags temporal
* @return {Pattern}
* @example
* "tha dhi thom nam".grow("1").sound()
@@ -3552,7 +3553,9 @@ export const { loopAtCps, loopatcps } = register(['loopAtCps', 'loopatcps'], fun
return _loopAt(factor, pat, cps);
});
-/** exposes a custom value at query time. basically allows mutating state without evaluation */
+/** exposes a custom value at query time. basically allows mutating state without evaluation
+ * @tags internals
+ */
export const ref = (accessor) =>
pure(1)
.withValue(() => reify(accessor()))
@@ -3589,7 +3592,7 @@ Pattern.prototype.xfade = function (pos, b) {
* creates a structure pattern from divisions of a cycle
* especially useful for creating rhythms
* @name beat
- * @tags structure
+ * @tags temporal
* @example
* s("bd").beat("0,7,10", 16)
* @example
@@ -3666,7 +3669,7 @@ export const _morph = (from, to, by) => {
* sine.slow(8) // slowly morph between the rhythms
* )
* )
- * @tags structure
+ * @tags temporal
*/
export const morph = (frompat, topat, bypat) => {
frompat = reify(frompat);
diff --git a/packages/core/pick.mjs b/packages/core/pick.mjs
index 206fa619b..cce691905 100644
--- a/packages/core/pick.mjs
+++ b/packages/core/pick.mjs
@@ -28,6 +28,7 @@ const _pick = function (lookup, pat, modulo = true) {
/** * Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
* Similar to `inhabit`, but maintains the structure of the original patterns.
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -57,6 +58,7 @@ const __pick = register('pick', function (lookup, pat) {
* it wraps around, rather than sticking at the maximum value.
* For example, if you pick the fifth pattern of a list of three, you'll get the
* second one.
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -67,6 +69,7 @@ export const pickmod = register('pickmod', function (lookup, pat) {
});
/** * pickF lets you use a pattern of numbers to pick which function to apply to another pattern.
+ * @tags combiners, functional
* @param {Pattern} pat
* @param {Pattern} lookup a pattern of indices
* @param {function[]} funcs the array of functions from which to pull
@@ -83,6 +86,7 @@ export const pickF = register('pickF', function (lookup, funcs, pat) {
/** * The same as `pickF`, but if you pick a number greater than the size of the functions list,
* it wraps around, rather than sticking at the maximum value.
+ * @tags combiners
* @param {Pattern} pat
* @param {Pattern} lookup a pattern of indices
* @param {function[]} funcs the array of functions from which to pull
@@ -93,6 +97,7 @@ export const pickmodF = register('pickmodF', function (lookup, funcs, pat) {
});
/** * Similar to `pick`, but it applies an outerJoin instead of an innerJoin.
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -103,6 +108,7 @@ export const pickOut = register('pickOut', function (lookup, pat) {
/** * The same as `pickOut`, but if you pick a number greater than the size of the list,
* it wraps around, rather than sticking at the maximum value.
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -112,6 +118,7 @@ export const pickmodOut = register('pickmodOut', function (lookup, pat) {
});
/** * Similar to `pick`, but the choosen pattern is restarted when its index is triggered.
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -122,6 +129,7 @@ export const pickRestart = register('pickRestart', function (lookup, pat) {
/** * The same as `pickRestart`, but if you pick a number greater than the size of the list,
* it wraps around, rather than sticking at the maximum value.
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -138,6 +146,7 @@ export const pickmodRestart = register('pickmodRestart', function (lookup, pat)
});
/** * Similar to `pick`, but the choosen pattern is reset when its index is triggered.
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -148,6 +157,7 @@ export const pickReset = register('pickReset', function (lookup, pat) {
/** * The same as `pickReset`, but if you pick a number greater than the size of the list,
* it wraps around, rather than sticking at the maximum value.
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -159,6 +169,7 @@ export const pickmodReset = register('pickmodReset', function (lookup, pat) {
/** Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
* Similar to `pick`, but cycles are squeezed into the target ('inhabited') pattern.
* @name inhabit
+ * @tags combiners
* @synonyms pickSqueeze
* @param {Pattern} pat
* @param {*} xs
@@ -180,6 +191,7 @@ export const { inhabit, pickSqueeze } = register(['inhabit', 'pickSqueeze'], fun
* second one.
* @name inhabitmod
* @synonyms pickmodSqueeze
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -192,6 +204,7 @@ export const { inhabitmod, pickmodSqueeze } = register(['inhabitmod', 'pickmodSq
/**
* Pick from the list of values (or patterns of values) via the index using the given
* pattern of integers. The selected pattern will be compressed to fit the duration of the selecting event
+ * @tags combiners
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
diff --git a/packages/core/repl.mjs b/packages/core/repl.mjs
index 53562f216..b8bab3d4b 100644
--- a/packages/core/repl.mjs
+++ b/packages/core/repl.mjs
@@ -102,6 +102,7 @@ export function repl({
* Changes the global tempo to the given cycles per minute
*
* @name setcpm
+ * @tags temporal
* @alias setCpm
* @param {number} cpm cycles per minute
* @example
@@ -127,6 +128,8 @@ export function repl({
* $: sound("hh*8")
* all(x => x.pianoroll())
* ```
+ *
+ * @tags combiners
*/
let allTransforms = [];
const all = function (transform) {
@@ -134,11 +137,13 @@ export function repl({
return silence;
};
/** Applies a function to each of the running patterns separately. This is intended for future use with upcoming 'stepwise' features. See `all` for a version that applies the function to all the patterns stacked together into a single pattern.
+ *
* ```
* $: sound("bd - cp sd")
* $: sound("hh*8")
* each(fast("<2 3>"))
* ```
+ * @tags combiners
*/
const each = function (transform) {
eachTransform = transform;
diff --git a/packages/core/signal.mjs b/packages/core/signal.mjs
index 03dd641a5..2c3a63324 100644
--- a/packages/core/signal.mjs
+++ b/packages/core/signal.mjs
@@ -337,6 +337,7 @@ export const scramble = register('scramble', (n, pat) => {
export const rand = signal(timeToRand);
/**
* A continuous pattern of random numbers, between -1 and 1
+ * @tags generators
*/
export const rand2 = rand.toBipolar();
diff --git a/packages/csound/index.mjs b/packages/csound/index.mjs
index e44765227..e459f3873 100644
--- a/packages/csound/index.mjs
+++ b/packages/csound/index.mjs
@@ -135,6 +135,8 @@ export async function loadOrc(url) {
* p4 -- MIDI key number (as a real number, not an integer but in [0, 127].
* p5 -- MIDI velocity (as a real number, not an integer but in [0, 127].
* p6 -- Strudel controls, as a string.
+ *
+ * @tags external_io
*/
export const csoundm = register('csoundm', (instrument, pat) => {
let p1 = instrument;
diff --git a/packages/draw/pianoroll.mjs b/packages/draw/pianoroll.mjs
index 1cf218fa0..6fb1dfc76 100644
--- a/packages/draw/pianoroll.mjs
+++ b/packages/draw/pianoroll.mjs
@@ -42,6 +42,7 @@ const getValue = (e) => {
*
* @name pianoroll
* @synonyms punchcard
+ * @tags visualization
* @param {Object} options Object containing all the optional following parameters as key value pairs:
* @param {integer} cycles number of cycles to be displayed at the same time - defaults to 4
* @param {number} playhead location of the active notes on the time axis - 0 to 1, defaults to 0.5
@@ -299,6 +300,7 @@ Pattern.prototype.punchcard = function (options) {
* Supports all the same options as pianoroll.
*
* @name wordfall
+ * @tags visualization
*/
Pattern.prototype.wordfall = function (options) {
return this.punchcard({ vertical: 1, labels: 1, stroke: 0, fillActive: 1, active: 'white', ...options });
diff --git a/packages/draw/pitchwheel.mjs b/packages/draw/pitchwheel.mjs
index ba76df079..f9dacc53f 100644
--- a/packages/draw/pitchwheel.mjs
+++ b/packages/draw/pitchwheel.mjs
@@ -116,6 +116,7 @@ export function pitchwheel({
/**
* Renders a pitch circle to visualize frequencies within one octave
* @name pitchwheel
+ * @tags visualization
* @param {number} hapcircles
* @param {number} circle
* @param {number} edo
diff --git a/packages/draw/spiral.mjs b/packages/draw/spiral.mjs
index cebf3d374..c18c66c59 100644
--- a/packages/draw/spiral.mjs
+++ b/packages/draw/spiral.mjs
@@ -129,6 +129,7 @@ function drawSpiral(options) {
* Displays a spiral visual.
*
* @name spiral
+ * @tags visualization
* @param {Object} options Object containing all the optional following parameters as key value pairs:
* @param {number} stretch controls the rotations per cycle ratio, where 1 = 1 cycle / 360 degrees
* @param {number} size the diameter of the spiral
diff --git a/packages/midi/midi.mjs b/packages/midi/midi.mjs
index ae983d200..bff36c870 100644
--- a/packages/midi/midi.mjs
+++ b/packages/midi/midi.mjs
@@ -123,6 +123,7 @@ function githubPath(base, subpath = '') {
/**
* configures the default midimap, which is used when no "midimap" port is set
+ * @tags external_io
* @example
* defaultmidimap({ lpf: 74 })
* $: note("c a f e").midi();
@@ -136,6 +137,7 @@ let loadCache = {};
/**
* Adds midimaps to the registry. Inside each midimap, control names (e.g. lpf) are mapped to cc numbers.
+ * @tags external_io
* @example
* midimaps({ mymap: { lpf: 74 } })
* $: note("c a f e")
@@ -278,6 +280,7 @@ function sendNote(note, velocity, duration, device, midichan, timeOffsetString)
/**
* MIDI output: Opens a MIDI output port.
+ * @tags external_io
* @param {string | number} midiport MIDI device name or index defaulting to 0
* @param {object} options Additional MIDI configuration options
* @example
@@ -465,6 +468,7 @@ const refs = {};
/**
* MIDI input: Opens a MIDI input port to receive MIDI control change messages.
+ * @tags external_io
* @param {string | number} input MIDI device name or index defaulting to 0
* @returns {Function}
* @example
diff --git a/packages/osc/osc.mjs b/packages/osc/osc.mjs
index fe0691522..1358ad2db 100644
--- a/packages/osc/osc.mjs
+++ b/packages/osc/osc.mjs
@@ -78,6 +78,7 @@ export async function oscTrigger(hap, currentTime, cps = 1, targetTime) {
* For more info, read [MIDI & OSC in the docs](https://strudel.cc/learn/input-output/)
*
* @name osc
+ * @tags external_io
* @memberof Pattern
* @returns Pattern
*/
diff --git a/packages/superdough/ola-processor.js b/packages/superdough/ola-processor.js
index 38d45a25d..0000d1bbb 100644
--- a/packages/superdough/ola-processor.js
+++ b/packages/superdough/ola-processor.js
@@ -35,7 +35,9 @@ class OLAProcessor extends AudioWorkletProcessor {
}
/** Handles dynamic reallocation of input/output channels buffer
- (channel numbers may lety during lifecycle) **/
+ * (channel numbers may vary during lifecycle)
+ * @tags internals
+ **/
reallocateChannelsIfNeeded(inputs, outputs) {
for (let i = 0; i < this.nbInputs; i++) {
let nbChannels = inputs[i].length;
@@ -88,7 +90,10 @@ class OLAProcessor extends AudioWorkletProcessor {
}
}
- /** Read next web audio block to input buffers **/
+ /**
+ * Read next web audio block to input buffers
+ * @tags internals
+ **/
readInputs(inputs) {
// when playback is paused, we may stop receiving new samples
if (inputs[0].length && inputs[0][0].length == 0) {
@@ -108,7 +113,9 @@ class OLAProcessor extends AudioWorkletProcessor {
}
}
- /** Write next web audio block from output buffers **/
+ /** Write next web audio block from output buffers
+ * @tags internals
+ **/
writeOutputs(outputs) {
for (let i = 0; i < this.nbInputs; i++) {
for (let j = 0; j < this.inputBuffers[i].length; j++) {
@@ -118,7 +125,9 @@ class OLAProcessor extends AudioWorkletProcessor {
}
}
- /** Shift left content of input buffers to receive new web audio block **/
+ /** Shift left content of input buffers to receive new web audio block
+ * @tags internals
+ **/
shiftInputBuffers() {
for (let i = 0; i < this.nbInputs; i++) {
for (let j = 0; j < this.inputBuffers[i].length; j++) {
@@ -127,7 +136,9 @@ class OLAProcessor extends AudioWorkletProcessor {
}
}
- /** Shift left content of output buffers to receive new web audio block **/
+ /** Shift left content of output buffers to receive new web audio block
+ * @tags internals
+ **/
shiftOutputBuffers() {
for (let i = 0; i < this.nbOutputs; i++) {
for (let j = 0; j < this.outputBuffers[i].length; j++) {
@@ -137,7 +148,9 @@ class OLAProcessor extends AudioWorkletProcessor {
}
}
- /** Copy contents of input buffers to buffer actually sent to process **/
+ /** Copy contents of input buffers to buffer actually sent to process
+ * @tags internals
+ **/
prepareInputBuffersToSend() {
for (let i = 0; i < this.nbInputs; i++) {
for (let j = 0; j < this.inputBuffers[i].length; j++) {
@@ -146,7 +159,9 @@ class OLAProcessor extends AudioWorkletProcessor {
}
}
- /** Add contents of output buffers just processed to output buffers **/
+ /** Add contents of output buffers just processed to output buffers
+ * @tags internals
+ **/
handleOutputBuffersToRetrieve() {
for (let i = 0; i < this.nbOutputs; i++) {
for (let j = 0; j < this.outputBuffers[i].length; j++) {
diff --git a/packages/superdough/reverbGen.mjs b/packages/superdough/reverbGen.mjs
index 42da7c6d5..c52188b08 100644
--- a/packages/superdough/reverbGen.mjs
+++ b/packages/superdough/reverbGen.mjs
@@ -16,6 +16,7 @@ var reverbGen = {};
/** Generates a reverb impulse response.
+ @tags internals
@param {!Object} params TODO: Document the properties.
@param {!function(!AudioBuffer)} callback Function to call when
the impulse response has been generated. The impulse response
@@ -48,7 +49,7 @@ reverbGen.generateReverb = function (params, callback) {
/** Creates a canvas element showing a graph of the given data.
-
+ @tags internals
@param {!Float32Array} data An array of numbers, or a Float32Array.
@param {number} width Width in pixels of the canvas.
@param {number} height Height in pixels of the canvas.
@@ -80,7 +81,7 @@ reverbGen.generateGraph = function (data, width, height, min, max) {
@param {number} lpFreqEndAt
@param {!function(!AudioBuffer)} callback May be called
immediately within the current execution context, or later.
- @tags effects
+ @tags internals
*/
var applyGradualLowpass = function (input, lpFreqStart, lpFreqEnd, lpFreqEndAt, callback) {
if (lpFreqStart == 0) {
diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs
index b195ba79c..69a949ad1 100644
--- a/packages/superdough/sampler.mjs
+++ b/packages/superdough/sampler.mjs
@@ -221,6 +221,7 @@ export async function fetchSampleMap(url) {
/**
* Loads a collection of samples to use with `s`
+ * @tags samples
* @example
* samples('github:tidalcycles/dirt-samples');
* s("[bd ~]*2, [~ hh]*2, ~ sd")
diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs
index 52ed9bff8..873fdfa5d 100644
--- a/packages/superdough/superdough.mjs
+++ b/packages/superdough/superdough.mjs
@@ -91,6 +91,8 @@ async function aliasBankPath(path) {
* Optionally accepts a single argument string of a path to a JSON file containing bank aliases.
* @param {string} bank - The bank to alias
* @param {string} alias - The alias to use for the bank
+ *
+ * @tags samples
*/
export async function aliasBank(...args) {
switch (args.length) {
@@ -109,6 +111,7 @@ export async function aliasBank(...args) {
/**
* Register an alias for a sound.
+ * @tags samples
* @param {string} original - The original sound name
* @param {string} alias - The alias to use for the sound
*/
diff --git a/packages/superdough/wavetable.mjs b/packages/superdough/wavetable.mjs
index 44367f786..cfc669c83 100644
--- a/packages/superdough/wavetable.mjs
+++ b/packages/superdough/wavetable.mjs
@@ -180,6 +180,7 @@ export function registerWaveTable(key, tables, params) {
* Loads a collection of wavetables to use with `s`
*
* @name tables
+ * @tags effects
*/
export const tables = async (url, frameLen, json, options = {}) => {
if (json !== undefined) return _processTables(json, url, frameLen);
diff --git a/packages/superdough/worklets.mjs b/packages/superdough/worklets.mjs
index ccfaf5107..3e8276225 100644
--- a/packages/superdough/worklets.mjs
+++ b/packages/superdough/worklets.mjs
@@ -635,14 +635,18 @@ class PhaseVocoderProcessor extends OLAProcessor {
this.timeCursor += this.hopSize;
}
- /** Apply Hann window in-place */
+ /** Apply Hann window in-place
+ * @tags internals
+ */
applyHannWindow(input) {
for (var i = 0; i < this.blockSize; i++) {
input[i] = input[i] * this.hannWindow[i] * 1.62;
}
}
- /** Compute squared magnitudes for peak finding **/
+ /** Compute squared magnitudes for peak finding
+ * @tags internals
+ **/
computeMagnitudes() {
var i = 0,
j = 0;
@@ -656,7 +660,9 @@ class PhaseVocoderProcessor extends OLAProcessor {
}
}
- /** Find peaks in spectrum magnitudes **/
+ /** Find peaks in spectrum magnitudes
+ * @tags internals
+ **/
findPeaks() {
this.nbPeaks = 0;
var i = 2;
@@ -680,7 +686,9 @@ class PhaseVocoderProcessor extends OLAProcessor {
}
}
- /** Shift peaks and regions of influence by pitchFactor into new specturm */
+ /** Shift peaks and regions of influence by pitchFactor into new specturm
+ * @tags internals
+ */
shiftPeaks(pitchFactor) {
// zero-fill new spectrum
this.freqComplexBufferShifted.fill(0);
@@ -843,7 +851,9 @@ class PulseOscillatorProcessor extends AudioWorkletProcessor {
registerProcessor('pulse-oscillator', PulseOscillatorProcessor);
-/** BYTE BEATS */
+/** BYTE BEATS
+ * @tags internals
+ */
const chyx = {
/*bit*/ bitC: function (x, y, z) {
return x & y ? z : 0;
diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs
index ae75ab690..613ba51e0 100644
--- a/packages/tonal/tonal.mjs
+++ b/packages/tonal/tonal.mjs
@@ -92,6 +92,7 @@ function scaleOffset(scale, offset, note) {
* - 5P = perfect fifth
* - 5d = diminished fifth
*
+ * @tags music_theory
* @param {string | number} amount Either number of semitones or interval string.
* @returns Pattern
* @memberof Pattern
@@ -146,6 +147,7 @@ export const { transpose, trans } = register(['transpose', 'trans'], function tr
*
* @memberof Pattern
* @name scaleTranspose
+ * @tags music_theory
* @param {offset} offset number of steps inside the scale
* @returns Pattern
* @synonyms scaleTrans, strans
@@ -235,6 +237,7 @@ function _getNearestScaleNote(scaleName, note, preferHigher = true) {
* The root note defaults to octave 3, if no octave number is given.
*
* @name scale
+ * @tags music_theory
* @param {string} scale Name of scale
* @returns Pattern
* @example
diff --git a/packages/tonal/voicings.mjs b/packages/tonal/voicings.mjs
index d81911e01..6dce6ca8b 100644
--- a/packages/tonal/voicings.mjs
+++ b/packages/tonal/voicings.mjs
@@ -90,6 +90,7 @@ export const setVoicingRange = (name, range) => addVoicings(name, voicingRegistr
* Adds a new custom voicing dictionary.
*
* @name addVoicings
+ * @tags music_theory
* @memberof Pattern
* @param {string} name identifier for the voicing dictionary
* @param {Object} dictionary maps chord symbol to possible voicings
@@ -133,6 +134,7 @@ const getVoicing = (chord, dictionaryName, lastVoicing) => {
* Uses [chord-voicings package](https://github.com/felixroos/chord-voicings#chord-voicings).
*
* @name voicings
+ * @tags music_theory
* @memberof Pattern
* @param {string} dictionary which voicing dictionary to use.
* @returns Pattern
@@ -157,6 +159,7 @@ export const voicings = register('voicings', function (dictionary, pat) {
* Maps the chords of the incoming pattern to root notes in the given octave.
*
* @name rootNotes
+ * @tags music_theory
* @memberof Pattern
* @param {octave} octave octave to use
* @returns Pattern
@@ -189,6 +192,7 @@ export const rootNotes = register('rootNotes', function (octave, pat) {
* If you pass a pattern of strings to voicing, they will be interpreted as chords.
*
* @name voicing
+ * @tags music_theory
* @returns Pattern
* @example
* n("0 1 2 3").chord("").voicing()
diff --git a/packages/webaudio/scope.mjs b/packages/webaudio/scope.mjs
index e423b20fc..866e0a435 100644
--- a/packages/webaudio/scope.mjs
+++ b/packages/webaudio/scope.mjs
@@ -98,6 +98,7 @@ function clearScreen(smear = 0, smearRGB = `0,0,0`, ctx = getDrawContext()) {
/**
* Renders an oscilloscope for the frequency domain of the audio signal.
* @name fscope
+ * @tags visualization
* @param {string} color line color as hex or color name. defaults to white.
* @param {number} scale scales the y-axis. Defaults to 0.25
* @param {number} pos y-position relative to screen height. 0 = top, 1 = bottom of screen
@@ -122,6 +123,7 @@ Pattern.prototype.fscope = function (config = {}) {
* Renders an oscilloscope for the time domain of the audio signal.
* @name scope
* @synonyms tscope
+ * @tags visualization
* @param {object} config optional config with options:
* @param {boolean} align if 1, the scope will be aligned to the first zero crossing. defaults to 1
* @param {string} color line color as hex or color name. defaults to white.
diff --git a/packages/webaudio/spectrum.mjs b/packages/webaudio/spectrum.mjs
index 2ddd214fa..c67e321b5 100644
--- a/packages/webaudio/spectrum.mjs
+++ b/packages/webaudio/spectrum.mjs
@@ -5,6 +5,7 @@ import { analysers, getAnalyzerData } from 'superdough';
/**
* Renders a spectrum analyzer for the incoming audio signal.
* @name spectrum
+ * @tags visualization
* @param {object} config optional config with options:
* @param {integer} thickness line thickness in px (default 3)
* @param {integer} speed scroll speed (default 1)
From ee1a894f3ba2dc468fbf6510afc50c3a7387e2c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Va=CC=81clav=20Volhejn?=
Date: Sun, 12 Oct 2025 16:28:05 +0200
Subject: [PATCH 031/476] Show tags in reference, more compact functions list
---
.../src/repl/components/panel/Reference.jsx | 42 ++++++++++++-------
1 file changed, 27 insertions(+), 15 deletions(-)
diff --git a/website/src/repl/components/panel/Reference.jsx b/website/src/repl/components/panel/Reference.jsx
index 3faa5c6f1..d1157ba26 100644
--- a/website/src/repl/components/panel/Reference.jsx
+++ b/website/src/repl/components/panel/Reference.jsx
@@ -11,6 +11,7 @@ const availableFunctions = (() => {
for (const doc of jsdocJson.docs) {
if (!isValid(doc)) continue;
if (seen.has(doc.name)) continue;
+ doc.tags = doc.tags?.filter((t) => t && typeof t === 'string') || [];
functions.push(doc);
const synonyms = doc.synonyms || [];
seen.add(doc.name);
@@ -113,7 +114,7 @@ export function Reference() {
return (
-
+
@@ -134,19 +135,21 @@ export function Reference() {
))}
@@ -161,8 +164,17 @@ export function Reference() {
that you can already make music with a small set of functions!
{visibleFunctions.map((entry, i) => (
-
-
Synonyms: {entry.synonyms_text}
From a4212589e5e0a2d3d6e9a31bf196f30e557b24e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Va=CC=81clav=20Volhejn?=
Date: Sun, 12 Oct 2025 16:33:07 +0200
Subject: [PATCH 032/476] Recategorize
---
packages/core/controls.mjs | 36 ++++++++++++++--------------
packages/core/pattern.mjs | 20 ++++++++--------
packages/core/signal.mjs | 48 +++++++++++++++++++-------------------
3 files changed, 52 insertions(+), 52 deletions(-)
diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs
index 4e60fc487..db689e1a2 100644
--- a/packages/core/controls.mjs
+++ b/packages/core/controls.mjs
@@ -1621,7 +1621,7 @@ export const { fadeInTime } = registerControl('fadeInTime');
* Set frequency of sound.
*
* @name freq
- * @tags transforms
+ * @tags temporal
* @param {number | Pattern} frequency in Hz. the audible range is between 20 and 20000 Hz
* @example
* freq("220 110 440 110").s("superzow").osc()
@@ -2205,7 +2205,7 @@ export const { cps } = registerControl('cps');
* Multiplies the duration with the given number. Also cuts samples off at the end if they exceed the duration.
*
* @name clip
- * @tags transforms
+ * @tags temporal
* @synonyms legato
* @param {number | Pattern} factor >= 0
* @example
@@ -2218,7 +2218,7 @@ export const { clip, legato } = registerControl('clip', 'legato');
* Sets the duration of the event in cycles. Similar to clip / legato, it also cuts samples off at the end if they exceed the duration.
*
* @name duration
- * @tags transforms
+ * @tags temporal
* @synonyms dur
* @param {number | Pattern} seconds >= 0
* @example
@@ -2297,7 +2297,7 @@ export const ar = register('ar', (t, pat) => {
* MIDI channel: Sets the MIDI channel for the event.
*
* @name midichan
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} channel MIDI channel number (0-15)
* @example
* note("c4").midichan(1).midi()
@@ -2310,7 +2310,7 @@ export const { midimap } = registerControl('midimap');
* MIDI port: Sets the MIDI port for the event.
*
* @name midiport
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} port MIDI port
* @example
* note("c a f e").midiport("<0 1 2 3>").midi()
@@ -2321,7 +2321,7 @@ export const { midiport } = registerControl('midiport');
* MIDI command: Sends a MIDI command message.
*
* @name midicmd
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} command MIDI command
* @example
* midicmd("clock*48,/2").midi()
@@ -2332,7 +2332,7 @@ export const { midicmd } = registerControl('midicmd');
* MIDI control: Sends a MIDI control change message.
*
* @name control
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} MIDI control number (0-127)
* @param {number | Pattern} MIDI controller value (0-127)
*/
@@ -2348,7 +2348,7 @@ export const control = register('control', (args, pat) => {
* MIDI control number: Sends a MIDI control change message.
*
* @name ccn
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} MIDI control number (0-127)
*/
export const { ccn } = registerControl('ccn');
@@ -2356,7 +2356,7 @@ export const { ccn } = registerControl('ccn');
* MIDI control value: Sends a MIDI control change message.
*
* @name ccv
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} MIDI control value (0-127)
*/
export const { ccv } = registerControl('ccv');
@@ -2366,7 +2366,7 @@ export const { ctlNum } = registerControl('ctlNum');
/**
* MIDI NRPN non-registered parameter number: Sends a MIDI NRPN non-registered parameter number message.
* @name nrpnn
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} nrpnn MIDI NRPN non-registered parameter number (0-127)
* @example
* note("c4").nrpnn("1:8").nrpv("123").midichan(1).midi()
@@ -2375,7 +2375,7 @@ export const { nrpnn } = registerControl('nrpnn');
/**
* MIDI NRPN non-registered parameter value: Sends a MIDI NRPN non-registered parameter value message.
* @name nrpv
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} nrpv MIDI NRPN non-registered parameter value (0-127)
* @example
* note("c4").nrpnn("1:8").nrpv("123").midichan(1).midi()
@@ -2386,7 +2386,7 @@ export const { nrpv } = registerControl('nrpv');
* MIDI program number: Sends a MIDI program change message.
*
* @name progNum
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} program MIDI program number (0-127)
* @example
* note("c4").progNum(10).midichan(1).midi()
@@ -2396,7 +2396,7 @@ export const { progNum } = registerControl('progNum');
/**
* MIDI sysex: Sends a MIDI sysex message.
* @name sysex
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} id Sysex ID
* @param {number | Pattern} data Sysex data
* @example
@@ -2412,7 +2412,7 @@ export const sysex = register('sysex', (args, pat) => {
/**
* MIDI sysex ID: Sends a MIDI sysex identifier message.
* @name sysexid
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} id Sysex ID
* @example
* note("c4").sysexid("0x77").sysexdata("0x01:0x02:0x03:0x04").midichan(1).midi()
@@ -2421,7 +2421,7 @@ export const { sysexid } = registerControl('sysexid');
/**
* MIDI sysex data: Sends a MIDI sysex message.
* @name sysexdata
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} data Sysex data
* @example
* note("c4").sysexid("0x77").sysexdata("0x01:0x02:0x03:0x04").midichan(1).midi()
@@ -2431,7 +2431,7 @@ export const { sysexdata } = registerControl('sysexdata');
/**
* MIDI pitch bend: Sends a MIDI pitch bend message.
* @name midibend
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} midibend MIDI pitch bend (-1 - 1)
* @example
* note("c4").midibend(sine.slow(4).range(-0.4,0.4)).midi()
@@ -2440,7 +2440,7 @@ export const { midibend } = registerControl('midibend');
/**
* MIDI key after touch: Sends a MIDI key after touch message.
* @name miditouch
- * @tags examples
+ * @tags external_io
* @param {number | Pattern} miditouch MIDI key after touch (0-1)
* @example
* note("c4").miditouch(sine.slow(4).range(0,1)).midi()
@@ -2461,7 +2461,7 @@ export const getControlName = (alias) => {
* Sets properties in a batch.
*
* @name as
- * @tags transforms
+ * @tags temporal
* @param {String | Array} mapping the control names that are set
* @example
* "c:.5 a:1 f:.25 e:.8".as("note:clip")
diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs
index 2d6459a89..4a0dbe58f 100644
--- a/packages/core/pattern.mjs
+++ b/packages/core/pattern.mjs
@@ -978,7 +978,7 @@ Pattern.prototype.collect = function () {
/**
* Selects indices in in stacked notes.
- * @tags transforms
+ * @tags temporal
* @example
* note("<[c,eb,g]!2 [c,f,ab] [d,f,ab]>")
* .arpWith(haps => haps[2])
@@ -993,7 +993,7 @@ export const arpWith = register('arpWith', (func, pat) => {
/**
* Selects indices in in stacked notes.
- * @tags transforms
+ * @tags temporal
* @example
* note("<[c,eb,g]!2 [c,f,ab] [d,f,ab]>")
* .arp("0 [0,2] 1 [0,2]")
@@ -1342,7 +1342,7 @@ export function reify(thing) {
/**
* Takes a list of patterns, and returns a pattern of lists.
*
- * @tags transforms
+ * @tags temporal
*/
export function sequenceP(pats) {
let result = pure([]);
@@ -3354,7 +3354,7 @@ Pattern.prototype.steps = Pattern.prototype.pace;
* Cuts each sample into the given number of parts, allowing you to explore a technique known as 'granular synthesis'.
* It turns a pattern of samples into a pattern of parts of samples.
* @name chop
- * @tags transforms
+ * @tags temporal
* @memberof Pattern
* @returns Pattern
* @example
@@ -3385,7 +3385,7 @@ export const chop = register('chop', function (n, pat) {
/**
* Cuts each sample into the given number of parts, triggering progressive portions of each sample at each loop.
* @name striate
- * @tags transforms
+ * @tags temporal
* @memberof Pattern
* @returns Pattern
* @example
@@ -3404,7 +3404,7 @@ export const striate = register('striate', function (n, pat) {
/**
* Makes the sample fit the given number of cycles by changing the speed.
* @name loopAt
- * @tags transforms
+ * @tags temporal
* @memberof Pattern
* @returns Pattern
* @example
@@ -3423,7 +3423,7 @@ const _loopAt = function (factor, pat, cps = 0.5) {
* Chops samples into the given number of slices, triggering those slices with a given pattern of slice numbers.
* Instead of a number, it also accepts a list of numbers from 0 to 1 to slice at specific points.
* @name slice
- * @tags transforms
+ * @tags temporal
* @memberof Pattern
* @returns Pattern
* @example
@@ -3477,7 +3477,7 @@ Pattern.prototype.onTriggerTime = function (func) {
/**
* Works the same as slice, but changes the playback speed of each slice to match the duration of its step.
* @name splice
- * @tags transforms
+ * @tags temporal
* @example
* samples('github:tidalcycles/dirt-samples')
* s("breaks165")
@@ -3515,7 +3515,7 @@ export const { loopAt, loopat } = register(['loopAt', 'loopat'], function (facto
* Makes the sample fit its event duration. Good for rhythmical loops like drum breaks.
* Similar to `loopAt`.
* @name fit
- * @tags transforms
+ * @tags temporal
* @example
* samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' })
* s("rhodes/2").fit()
@@ -3541,7 +3541,7 @@ export const fit = register('fit', (pat) =>
* given by a global clock and this function will be
* deprecated/removed.
* @name loopAtCps
- * @tags transforms
+ * @tags temporal
* @memberof Pattern
* @returns Pattern
* @example
diff --git a/packages/core/signal.mjs b/packages/core/signal.mjs
index 2c3a63324..ce17fdeae 100644
--- a/packages/core/signal.mjs
+++ b/packages/core/signal.mjs
@@ -300,7 +300,7 @@ const _rearrangeWith = (ipat, n, pat) => {
* Slices a pattern into the given number of parts, then plays those parts in random order.
* Each part will be played exactly once per cycle.
* @name shuffle
- * @tags transforms
+ * @tags temporal
* @example
* note("c d e f").sound("piano").shuffle(4)
* @example
@@ -314,7 +314,7 @@ export const shuffle = register('shuffle', (n, pat) => {
* Slices a pattern into the given number of parts, then plays those parts at random. Similar to `shuffle`,
* but parts might be played more than once, or not at all, per cycle.
* @name scramble
- * @tags transforms
+ * @tags temporal
* @example
* note("c d e f").sound("piano").scramble(4)
* @example
@@ -393,7 +393,7 @@ export const __chooseWith = (pat, xs) => {
/**
* Choose from the list of values (or patterns of values) using the given
* pattern of numbers, which should be in the range of 0..1
- * @tags transforms
+ * @tags temporal
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -407,7 +407,7 @@ export const chooseWith = (pat, xs) => {
/**
* As with {chooseWith}, but the structure comes from the chosen values, rather
* than the pattern you're using to choose with.
- * @tags transforms
+ * @tags temporal
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
@@ -418,7 +418,7 @@ export const chooseInWith = (pat, xs) => {
/**
* Chooses randomly from the given list of elements.
- * @tags transforms
+ * @tags temporal
* @param {...any} xs values / patterns to choose from.
* @returns {Pattern} - a continuous pattern.
* @example
@@ -434,7 +434,7 @@ export const chooseOut = choose;
* Chooses from the given list of values (or patterns of values), according
* to the pattern that the method is called on. The pattern should be in
* the range 0 .. 1.
- * @tags transforms
+ * @tags temporal
* @param {...any} xs
* @returns {Pattern}
*/
@@ -445,7 +445,7 @@ Pattern.prototype.choose = function (...xs) {
/**
* As with choose, but the pattern that this method is called on should be
* in the range -1 .. 1
- * @tags transforms
+ * @tags temporal
* @param {...any} xs
* @returns {Pattern}
*/
@@ -455,7 +455,7 @@ Pattern.prototype.choose2 = function (...xs) {
/**
* Picks one of the elements at random each cycle.
- * @tags transforms
+ * @tags temporal
* @synonyms randcat
* @returns {Pattern}
* @example
@@ -498,7 +498,7 @@ const wchooseWith = (...args) => _wchooseWith(...args).outerJoin();
/**
* Chooses randomly from the given list of elements by giving a probability to each element
- * @tags transforms
+ * @tags temporal
* @param {...any} pairs arrays of value and weight
* @returns {Pattern} - a continuous pattern.
* @example
@@ -508,7 +508,7 @@ export const wchoose = (...pairs) => wchooseWith(rand, ...pairs);
/**
* Picks one of the elements at random each cycle by giving a probability to each element
- * @tags transforms
+ * @tags temporal
* @synonyms wrandcat
* @returns {Pattern}
* @example
@@ -590,7 +590,7 @@ export const degradeByWith = register(
* 0 = 0% chance of removal
* 1 = 100% chance of removal
*
- * @tags transforms
+ * @tags temporal
* @name degradeBy
* @memberof Pattern
* @param {number} amount - a number between 0 and 1
@@ -616,7 +616,7 @@ export const degradeBy = register(
*
* Randomly removes 50% of events from the pattern. Shorthand for `.degradeBy(0.5)`
*
- * @tags transforms
+ * @tags temporal
* @name degrade
* @memberof Pattern
* @returns Pattern
@@ -633,7 +633,7 @@ export const degrade = register('degrade', (pat) => pat._degradeBy(0.5), true, t
* 1 = 0% chance of removal
* Events that would be removed by degradeBy are let through by undegradeBy and vice versa (see second example).
*
- * @tags transforms
+ * @tags temporal
* @name undegradeBy
* @memberof Pattern
* @param {number} amount - a number between 0 and 1
@@ -662,7 +662,7 @@ export const undegradeBy = register(
* Inverse of `degrade`: Randomly removes 50% of events from the pattern. Shorthand for `.undegradeBy(0.5)`
* Events that would be removed by degrade are let through by undegrade and vice versa (see second example).
*
- * @tags transforms
+ * @tags temporal
* @name undegrade
* @memberof Pattern
* @returns Pattern
@@ -681,7 +681,7 @@ export const undegrade = register('undegrade', (pat) => pat._undegradeBy(0.5), t
* Randomly applies the given function by the given probability.
* Similar to `someCyclesBy`
*
- * @tags transforms
+ * @tags temporal
* @name sometimesBy
* @memberof Pattern
* @param {number | Pattern} probability - a number between 0 and 1
@@ -701,7 +701,7 @@ export const sometimesBy = register('sometimesBy', function (patx, func, pat) {
*
* Applies the given function with a 50% chance
*
- * @tags transforms
+ * @tags temporal
* @name sometimes
* @memberof Pattern
* @param {function} function - the transformation to apply
@@ -723,7 +723,7 @@ export const sometimes = register('sometimes', function (func, pat) {
* @param {number | Pattern} probability - a number between 0 and 1
* @param {function} function - the transformation to apply
* @returns Pattern
- * @tags transforms
+ * @tags temporal
* @example
* s("bd,hh*8").someCyclesBy(.3, x=>x.speed("0.5"))
*/
@@ -746,7 +746,7 @@ export const someCyclesBy = register('someCyclesBy', function (patx, func, pat)
* @name someCycles
* @memberof Pattern
* @returns Pattern
- * @tags transforms
+ * @tags temporal
* @example
* s("bd,hh*8").someCycles(x=>x.speed("0.5"))
*/
@@ -761,7 +761,7 @@ export const someCycles = register('someCycles', function (func, pat) {
* @name often
* @memberof Pattern
* @returns Pattern
- * @tags transforms
+ * @tags temporal
* @example
* s("hh*8").often(x=>x.speed("0.5"))
*/
@@ -776,7 +776,7 @@ export const often = register('often', function (func, pat) {
* @name rarely
* @memberof Pattern
* @returns Pattern
- * @tags transforms
+ * @tags temporal
* @example
* s("hh*8").rarely(x=>x.speed("0.5"))
*/
@@ -788,7 +788,7 @@ export const rarely = register('rarely', function (func, pat) {
*
* Shorthand for `.sometimesBy(0.1, fn)`
*
- * @tags transforms
+ * @tags temporal
* @name almostNever
* @memberof Pattern
* @returns Pattern
@@ -803,7 +803,7 @@ export const almostNever = register('almostNever', function (func, pat) {
*
* Shorthand for `.sometimesBy(0.9, fn)`
*
- * @tags transforms
+ * @tags temporal
* @name almostAlways
* @memberof Pattern
* @returns Pattern
@@ -818,7 +818,7 @@ export const almostAlways = register('almostAlways', function (func, pat) {
*
* Shorthand for `.sometimesBy(0, fn)` (never calls fn)
*
- * @tags transforms
+ * @tags temporal
* @name never
* @memberof Pattern
* @returns Pattern
@@ -833,7 +833,7 @@ export const never = register('never', function (_, pat) {
*
* Shorthand for `.sometimesBy(1, fn)` (always calls fn)
*
- * @tags transforms
+ * @tags temporal
* @name always
* @memberof Pattern
* @returns Pattern
From 1be9f40574aa213d3ef501024e5a0e18cb04fef9 Mon Sep 17 00:00:00 2001
From: alex
Date: Sat, 18 Oct 2025 10:42:35 +0100
Subject: [PATCH 033/476] timeline feature
---
packages/core/impure.mjs | 60 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 packages/core/impure.mjs
diff --git a/packages/core/impure.mjs b/packages/core/impure.mjs
new file mode 100644
index 000000000..66fc1dd5f
--- /dev/null
+++ b/packages/core/impure.mjs
@@ -0,0 +1,60 @@
+/*
+stateful.mjs - File of shame for stateful, impure and otherwise illegal pattern methods
+Copyright (C) 2025 Strudel contributors - see
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .
+*/
+
+import { register, reify } from './pattern.mjs';
+
+let timelines = {};
+
+export const reset_timelines = function () {
+ timelines = {};
+};
+
+export const timeline = register(
+ 'timeline',
+ function (tpat, pat) {
+ tpat = reify(tpat);
+ const f = function (state) {
+ let scheduler = !!state.controls._cps;
+
+ const timehaps = tpat.query(state);
+ const result = [];
+ for (const timehap of timehaps) {
+ const tlid = timehap.value;
+ const ignore = false;
+ let offset;
+ if (tlid in timelines) {
+ offset = timelines[tlid];
+ } else {
+ const timearc = timehap.wholeOrPart();
+ if (!scheduler || state.span.begin.lt(timearc.midpoint())) {
+ offset = timearc.begin;
+ } else {
+ // Sync to end of timearc if we first see it over halfway into its
+ // timespan. Allows 'cuing up' next timeline when live coding.
+ offset = timearc.end;
+ }
+ }
+ if (scheduler) {
+ // update state
+ timelines[tlid] = offset;
+ const negative = 0 - tlid;
+ if (negative in timelines) {
+ delete timelines[negative];
+ }
+ }
+
+ const pathaps = pat
+ .late(offset)
+ .query(state.setSpan(timehap.part))
+ .map((h) => h.setContext(h.combineContext(timehap)));
+ result.push(...pathaps);
+ }
+ return result;
+ };
+ return new Pattern(f, pat._steps);
+ },
+ false,
+);
From b2ce4591d9bd4260511bb08a06f791f515452456 Mon Sep 17 00:00:00 2001
From: alex
Date: Sat, 18 Oct 2025 10:42:55 +0100
Subject: [PATCH 034/476] sort exports and add impure.mjs
---
packages/core/index.mjs | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/packages/core/index.mjs b/packages/core/index.mjs
index e4daf445a..9260e3671 100644
--- a/packages/core/index.mjs
+++ b/packages/core/index.mjs
@@ -1,6 +1,6 @@
/*
index.mjs -
-Copyright (C) 2022 Strudel contributors - see
+Copyright (C) 2025 Strudel contributors - see
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .
*/
@@ -11,20 +11,21 @@ import createClock from './zyklus.mjs';
import { logger } from './logger.mjs';
export { Fraction, controls, createClock };
export * from './controls.mjs';
-export * from './hap.mjs';
-export * from './pattern.mjs';
-export * from './signal.mjs';
-export * from './pick.mjs';
-export * from './state.mjs';
-export * from './timespan.mjs';
-export * from './util.mjs';
-export * from './speak.mjs';
-export * from './evaluate.mjs';
-export * from './repl.mjs';
export * from './cyclist.mjs';
+export * from './evaluate.mjs';
+export * from './hap.mjs';
+export * from './impure.mjs';
export * from './logger.mjs';
+export * from './pattern.mjs';
+export * from './pick.mjs';
+export * from './repl.mjs';
+export * from './signal.mjs';
+export * from './speak.mjs';
+export * from './state.mjs';
export * from './time.mjs';
+export * from './timespan.mjs';
export * from './ui.mjs';
+export * from './util.mjs';
export { default as drawLine } from './drawLine.mjs';
// below won't work with runtime.mjs (json import fails)
/* import * as p from './package.json';
From 92a82ce4bdf951ae80a34c0e609aa3515951fa6f Mon Sep 17 00:00:00 2001
From: alex
Date: Sat, 18 Oct 2025 10:49:15 +0100
Subject: [PATCH 035/476] delint
---
packages/core/impure.mjs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/core/impure.mjs b/packages/core/impure.mjs
index 66fc1dd5f..e16cfbe45 100644
--- a/packages/core/impure.mjs
+++ b/packages/core/impure.mjs
@@ -4,7 +4,7 @@ Copyright (C) 2025 Strudel contributors - see .
*/
-import { register, reify } from './pattern.mjs';
+import { register, reify, Pattern } from './pattern.mjs';
let timelines = {};
From 3373fa39a6be2d2d3765dcbd52b63c30e4f3b10a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Va=CC=81clav=20Volhejn?=
Date: Sat, 18 Oct 2025 12:14:39 +0200
Subject: [PATCH 036/476] Fix the documentation of `stretch`
---
packages/core/controls.mjs | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs
index 7e3c2a8e2..130608447 100644
--- a/packages/core/controls.mjs
+++ b/packages/core/controls.mjs
@@ -1935,12 +1935,16 @@ export const { compressorRelease } = registerControl('compressorRelease');
export const { speed } = registerControl('speed');
/**
- * Changes the speed of sample playback, i.e. a cheap way of changing pitch.
+ * Changes the pitch of the sample without changing its speed.
+ * The frequencies are multiplied by (factor + 1) for positive numbers
+ * and by max(factor / 4 + 1, 0) for negative numbers.
+ * So tuning up by octaves can be done with 1, 3, 7, ...
+ * and tuning down by octaves with -2, -3, -3.5...
*
* @name stretch
- * @param {number | Pattern} factor -inf to inf, negative numbers play the sample backwards.
+ * @param {number | Pattern} factor between `-4` and `inf`. Positive increases pitch, 0 does nothing, negative decreases the pitch.
* @example
- * s("gm_flute").stretch("1 2 .5")
+ * s("gm_flute").stretch("<3 2 1 0 -2>")
*
*/
export const { stretch } = registerControl('stretch');
From 7d948fd1a76cb92d0da8a29a8710a977fa010083 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Va=CC=81clav=20Volhejn?=
Date: Sat, 18 Oct 2025 12:25:15 +0200
Subject: [PATCH 037/476] Fix example snapshot
---
packages/core/controls.mjs | 2 +-
test/__snapshots__/examples.test.mjs.snap | 16 ++++------------
2 files changed, 5 insertions(+), 13 deletions(-)
diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs
index 130608447..03de38666 100644
--- a/packages/core/controls.mjs
+++ b/packages/core/controls.mjs
@@ -1944,7 +1944,7 @@ export const { speed } = registerControl('speed');
* @name stretch
* @param {number | Pattern} factor between `-4` and `inf`. Positive increases pitch, 0 does nothing, negative decreases the pitch.
* @example
- * s("gm_flute").stretch("<3 2 1 0 -2>")
+ * s("gm_flute").stretch("<2 1 0 -2>")
*
*/
export const { stretch } = registerControl('stretch');
diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap
index 73278947d..a23806c1c 100644
--- a/test/__snapshots__/examples.test.mjs.snap
+++ b/test/__snapshots__/examples.test.mjs.snap
@@ -10439,18 +10439,10 @@ exports[`runs examples > example "stepcat" example index 1 1`] = `
exports[`runs examples > example "stretch" example index 0 1`] = `
[
- "[ (0/1 → 1/3) ⇝ 1/1 | s:gm_flute stretch:1 ]",
- "[ 0/1 ⇜ (1/3 → 2/3) ⇝ 1/1 | s:gm_flute stretch:2 ]",
- "[ 0/1 ⇜ (2/3 → 1/1) | s:gm_flute stretch:0.5 ]",
- "[ (1/1 → 4/3) ⇝ 2/1 | s:gm_flute stretch:1 ]",
- "[ 1/1 ⇜ (4/3 → 5/3) ⇝ 2/1 | s:gm_flute stretch:2 ]",
- "[ 1/1 ⇜ (5/3 → 2/1) | s:gm_flute stretch:0.5 ]",
- "[ (2/1 → 7/3) ⇝ 3/1 | s:gm_flute stretch:1 ]",
- "[ 2/1 ⇜ (7/3 → 8/3) ⇝ 3/1 | s:gm_flute stretch:2 ]",
- "[ 2/1 ⇜ (8/3 → 3/1) | s:gm_flute stretch:0.5 ]",
- "[ (3/1 → 10/3) ⇝ 4/1 | s:gm_flute stretch:1 ]",
- "[ 3/1 ⇜ (10/3 → 11/3) ⇝ 4/1 | s:gm_flute stretch:2 ]",
- "[ 3/1 ⇜ (11/3 → 4/1) | s:gm_flute stretch:0.5 ]",
+ "[ 0/1 → 1/1 | s:gm_flute stretch:3 ]",
+ "[ 1/1 → 2/1 | s:gm_flute stretch:2 ]",
+ "[ 2/1 → 3/1 | s:gm_flute stretch:1 ]",
+ "[ 3/1 → 4/1 | s:gm_flute stretch:-2 ]",
]
`;
From 54fd877be1272031972f9b0df183874c11f3e32f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Va=CC=81clav=20Volhejn?=
Date: Sat, 18 Oct 2025 13:19:18 +0200
Subject: [PATCH 038/476] Update snapshot
---
test/__snapshots__/examples.test.mjs.snap | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap
index a23806c1c..9eebfed35 100644
--- a/test/__snapshots__/examples.test.mjs.snap
+++ b/test/__snapshots__/examples.test.mjs.snap
@@ -10439,9 +10439,9 @@ exports[`runs examples > example "stepcat" example index 1 1`] = `
exports[`runs examples > example "stretch" example index 0 1`] = `
[
- "[ 0/1 → 1/1 | s:gm_flute stretch:3 ]",
- "[ 1/1 → 2/1 | s:gm_flute stretch:2 ]",
- "[ 2/1 → 3/1 | s:gm_flute stretch:1 ]",
+ "[ 0/1 → 1/1 | s:gm_flute stretch:2 ]",
+ "[ 1/1 → 2/1 | s:gm_flute stretch:1 ]",
+ "[ 2/1 → 3/1 | s:gm_flute stretch:0 ]",
"[ 3/1 → 4/1 | s:gm_flute stretch:-2 ]",
]
`;
From 4c49cd9297326cf4991f1dca879bef3ed657be51 Mon Sep 17 00:00:00 2001
From: Aria
Date: Sat, 18 Oct 2025 11:24:56 -0500
Subject: [PATCH 039/476] More examples
---
packages/core/controls.mjs | 30 ++++++++++++++++++
test/__snapshots__/examples.test.mjs.snap | 37 +++++++++++++++++++++++
2 files changed, 67 insertions(+)
diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs
index 55a07cc27..281bf76b7 100644
--- a/packages/core/controls.mjs
+++ b/packages/core/controls.mjs
@@ -456,6 +456,9 @@ export const { attack, att } = registerControl('attack', 'att');
* Whole numbers and simple ratios sound more natural,
* while decimal numbers and complex ratios sound metallic.
*
+ * A number may be added afterwards to control the harmonicity of
+ * any of the 8 individual FMs (e.g. `fmh2`)
+ *
* @name fmh
* @param {number | Pattern} harmonicity
* @example
@@ -470,6 +473,11 @@ export const { fmh, fmh1, fmh2, fmh3, fmh4, fmh5, fmh6, fmh7, fmh8 } = registerM
* Sets the Frequency Modulation of the synth.
* Controls the modulation index, which defines the brightness of the sound.
*
+ * A number may be added afterwards to control the modulation index of
+ * any of the 8 individual FMs (e.g. `fm3`). Also, FMs may be routed into
+ * each other with matrix commands like `fm13`, which would send `fm1` back into
+ * `fm3`
+ *
* @name fmi
* @param {number | Pattern} brightness modulation index
* @synonyms fm
@@ -477,6 +485,10 @@ export const { fmh, fmh1, fmh2, fmh3, fmh4, fmh5, fmh6, fmh7, fmh8 } = registerM
* note("c e g b g e")
* .fm("<0 1 2 8 32>")
* ._scope()
+ * @example
+ * s("sine").note("F1").seg(8)
+ * .fm(4).fm2(rand.mul(4)).fm3(saw.mul(8).slow(8))
+ * .fmh(1.06).fmh2(10).fmh3(0.1)
*
*/
export const { fmi, fmi1, fmi2, fmi3, fmi4, fmi5, fmi6, fmi7, fmi8, fm, fm1, fm2, fm3, fm4, fm5, fm6, fm7, fm8 } =
@@ -485,6 +497,9 @@ export const { fmi, fmi1, fmi2, fmi3, fmi4, fmi5, fmi6, fmi7, fmi8, fm, fm1, fm2
/**
* Ramp type of fm envelope. Exp might be a bit broken..
*
+ * A number may be added afterwards to control the envelope of
+ * any of the 8 individual FMs (e.g. `fmenv4`)
+ *
* @name fmenv
* @param {number | Pattern} type lin | exp
* @example
@@ -503,6 +518,9 @@ export const { fmenv, fmenv1, fmenv2, fmenv3, fmenv4, fmenv5, fmenv6, fmenv7, fm
/**
* Attack time for the FM envelope: time it takes to reach maximum modulation
*
+ * A number may be added afterwards to control the attack of the envelope of
+ * any of the 8 individual FMs (e.g. `fmatt5`)
+ *
* @name fmattack
* @synonyms fmatt
* @param {number | Pattern} time attack time
@@ -537,6 +555,9 @@ export const {
/**
* Waveform of the fm modulator
*
+ * A number may be added afterwards to control the waveform
+ * any of the 8 individual FMs (e.g. `fmwave6`)
+ *
* @name fmwave
* @param {number | Pattern} wave waveform
* @example
@@ -553,6 +574,9 @@ export const { fmwave, fmwave1, fmwave2, fmwave3, fmwave4, fmwave5, fmwave6, fmw
/**
* Decay time for the FM envelope: seconds until the sustain level is reached after the attack phase.
*
+ * A number may be added afterwards to control the decay of the envelope of
+ * any of the 8 individual FMs (e.g. `fmdec6`)
+ *
* @name fmdecay
* @synonyms fmdec
* @param {number | Pattern} time decay time
@@ -587,6 +611,9 @@ export const {
/**
* Sustain level for the FM envelope: how much modulation is applied after the decay phase
*
+ * A number may be added afterwards to control the sustain of the envelope of
+ * any of the 8 individual FMs (e.g. `fmsus7`)
+ *
* @name fmsustain
* @synonyms fmsus
* @param {number | Pattern} level sustain level
@@ -621,6 +648,9 @@ export const {
/**
* Release time for the FM envelope: how much modulation is applied after the note is released
*
+ * A number may be added afterwards to control the release of the envelope of
+ * any of the 8 individual FMs (e.g. `fmrel8`)
+ *
* @name fmrelease
* @synonyms fmrel
* @param {number | Pattern} time release time
diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap
index 590c47e4e..04360a4dd 100644
--- a/test/__snapshots__/examples.test.mjs.snap
+++ b/test/__snapshots__/examples.test.mjs.snap
@@ -4101,6 +4101,43 @@ exports[`runs examples > example "fmi" example index 0 1`] = `
]
`;
+exports[`runs examples > example "fmi" example index 1 1`] = `
+[
+ "[ 0/1 → 1/8 | s:sine note:F1 fmi:4 fmi2:0 fmi3:0 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 1/8 → 1/4 | s:sine note:F1 fmi:4 fmi2:2.7408622801303864 fmi3:0.125 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 1/4 → 3/8 | s:sine note:F1 fmi:4 fmi2:1.479038767516613 fmi3:0.25 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 3/8 → 1/2 | s:sine note:F1 fmi:4 fmi2:1.605570062994957 fmi3:0.375 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 1/2 → 5/8 | s:sine note:F1 fmi:4 fmi2:1.041922464966774 fmi3:0.5 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 5/8 → 3/4 | s:sine note:F1 fmi:4 fmi2:0.5425434708595276 fmi3:0.625 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 3/4 → 7/8 | s:sine note:F1 fmi:4 fmi2:0.7833059206604958 fmi3:0.75 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 7/8 → 1/1 | s:sine note:F1 fmi:4 fmi2:1.590524323284626 fmi3:0.875 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 1/1 → 9/8 | s:sine note:F1 fmi:4 fmi2:2.078168660402298 fmi3:1 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 9/8 → 5/4 | s:sine note:F1 fmi:4 fmi2:2.689958058297634 fmi3:1.125 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 5/4 → 11/8 | s:sine note:F1 fmi:4 fmi2:2.914912812411785 fmi3:1.25 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 11/8 → 3/2 | s:sine note:F1 fmi:4 fmi2:0.7312150076031685 fmi3:1.375 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 3/2 → 13/8 | s:sine note:F1 fmi:4 fmi2:2.4336322993040085 fmi3:1.5 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 13/8 → 7/4 | s:sine note:F1 fmi:4 fmi2:1.987018845975399 fmi3:1.625 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 7/4 → 15/8 | s:sine note:F1 fmi:4 fmi2:0.8189515843987465 fmi3:1.75 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 15/8 → 2/1 | s:sine note:F1 fmi:4 fmi2:2.3782287165522575 fmi3:1.875 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 2/1 → 17/8 | s:sine note:F1 fmi:4 fmi2:3.838108479976654 fmi3:2 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 17/8 → 9/4 | s:sine note:F1 fmi:4 fmi2:3.613561175763607 fmi3:2.125 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 9/4 → 19/8 | s:sine note:F1 fmi:4 fmi2:1.3819300457835197 fmi3:2.25 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 19/8 → 5/2 | s:sine note:F1 fmi:4 fmi2:3.346026562154293 fmi3:2.375 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 5/2 → 21/8 | s:sine note:F1 fmi:4 fmi2:1.8344642966985703 fmi3:2.5 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 21/8 → 11/4 | s:sine note:F1 fmi:4 fmi2:0.6407739371061325 fmi3:2.625 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 11/4 → 23/8 | s:sine note:F1 fmi:4 fmi2:2.5329310819506645 fmi3:2.75 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 23/8 → 3/1 | s:sine note:F1 fmi:4 fmi2:0.06501668691635132 fmi3:2.875 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 3/1 → 25/8 | s:sine note:F1 fmi:4 fmi2:0.8691564425826073 fmi3:3 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 25/8 → 13/4 | s:sine note:F1 fmi:4 fmi2:1.3729755133390427 fmi3:3.125 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 13/4 → 27/8 | s:sine note:F1 fmi:4 fmi2:3.9694602862000465 fmi3:3.25 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 27/8 → 7/2 | s:sine note:F1 fmi:4 fmi2:1.6347672045230865 fmi3:3.375 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 7/2 → 29/8 | s:sine note:F1 fmi:4 fmi2:1.639795258641243 fmi3:3.5 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 29/8 → 15/4 | s:sine note:F1 fmi:4 fmi2:3.7565943151712418 fmi3:3.625 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 15/4 → 31/8 | s:sine note:F1 fmi:4 fmi2:3.2486692890524864 fmi3:3.75 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+ "[ 31/8 → 4/1 | s:sine note:F1 fmi:4 fmi2:2.9446661546826363 fmi3:3.875 fmh:1.06 fmh2:10 fmh3:0.1 ]",
+]
+`;
+
exports[`runs examples > example "fmsustain" example index 0 1`] = `
[
"[ 0/1 → 1/6 | note:c fmi:4 fmdecay:0.1 fmsustain:1 ]",
From 0fbde61b2dd4bb2f2c3bdf2b451d05bfa73264e4 Mon Sep 17 00:00:00 2001
From: Nikita
Date: Sun, 19 Oct 2025 14:35:23 +0300
Subject: [PATCH 040/476] WIP non-realtime exporting
---
packages/codemirror/codemirror.mjs | 10 +-
packages/core/cyclist.mjs | 13 ++
packages/core/repl.mjs | 31 ++--
packages/superdough/audioContext.mjs | 5 +
packages/superdough/feedbackdelay.mjs | 2 +-
packages/superdough/reverb.mjs | 4 +-
packages/superdough/superdough.mjs | 12 +-
packages/superdough/vowel.mjs | 2 +-
packages/webaudio/webaudio.mjs | 151 +++++++++++++++++-
website/src/repl/components/Header.jsx | 12 +-
.../src/repl/components/panel/SettingsTab.jsx | 2 +-
website/src/repl/useReplContext.jsx | 4 +
12 files changed, 217 insertions(+), 31 deletions(-)
diff --git a/packages/codemirror/codemirror.mjs b/packages/codemirror/codemirror.mjs
index 4dc23996f..645a8a190 100644
--- a/packages/codemirror/codemirror.mjs
+++ b/packages/codemirror/codemirror.mjs
@@ -42,9 +42,9 @@ const extensions = {
isMultiCursorEnabled: (on) =>
on
? [
- EditorState.allowMultipleSelections.of(true),
- EditorView.clickAddsSelectionRange.of((ev) => ev.metaKey || ev.ctrlKey),
- ]
+ EditorState.allowMultipleSelections.of(true),
+ EditorView.clickAddsSelectionRange.of((ev) => ev.metaKey || ev.ctrlKey),
+ ]
: [],
};
const compartments = Object.fromEntries(Object.keys(extensions).map((key) => [key, new Compartment()]));
@@ -268,6 +268,10 @@ export class StrudelMirror {
this.flash();
await this.repl.evaluate(this.code);
}
+ async exportAudio(begin, end) {
+ // await this.repl.evaluate(this.code, false)
+ this.repl.exportAudio(begin, end);
+ }
async stop() {
this.repl.scheduler.stop();
}
diff --git a/packages/core/cyclist.mjs b/packages/core/cyclist.mjs
index 59e410c53..b7ab7dde4 100644
--- a/packages/core/cyclist.mjs
+++ b/packages/core/cyclist.mjs
@@ -6,6 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th
import createClock from './zyklus.mjs';
import { errorLogger, logger } from './logger.mjs';
+import { loadBuffer, renderPatternAudio, setAudioContext, superdough } from '@strudel/webaudio';
export class Cyclist {
constructor({
@@ -98,6 +99,7 @@ export class Cyclist {
this.started = v;
this.onToggle?.(v);
}
+
async start() {
await this.beforeStart?.();
this.num_ticks_since_cps_change = 0;
@@ -109,6 +111,17 @@ export class Cyclist {
this.clock.start();
this.setStarted(true);
}
+
+ async exportAudio(begin, end) {
+ if (!this.pattern) {
+ throw new Error('Scheduler: no pattern set! call .setPattern first.');
+ }
+ logger('[cyclist] exporting');
+ // this.clock.start();
+ // this.setStarted(true);
+ await renderPatternAudio(this.pattern, this.cps, begin, end)
+ }
+
pause() {
logger('[cyclist] pause');
this.clock.pause();
diff --git a/packages/core/repl.mjs b/packages/core/repl.mjs
index 171697eb9..d0cb1e19f 100644
--- a/packages/core/repl.mjs
+++ b/packages/core/repl.mjs
@@ -91,6 +91,7 @@ export function repl({
const stop = () => scheduler.stop();
const start = () => scheduler.start();
+ const exportAudio = (begin, end) => scheduler.exportAudio(begin, end);
const pause = () => scheduler.pause();
const toggle = () => scheduler.toggle();
const setCps = (cps) => {
@@ -257,23 +258,23 @@ export function repl({
}
};
const setCode = (code) => updateState({ code });
- return { scheduler, evaluate, start, stop, pause, setCps, setPattern, setCode, toggle, state };
+ return { scheduler, evaluate, start, exportAudio, stop, pause, setCps, setPattern, setCode, toggle, state };
}
export const getTrigger =
({ getTime, defaultOutput }) =>
- async (hap, deadline, duration, cps, t) => {
- // ^ this signature is different from hap.context.onTrigger, as set by Pattern.onTrigger(onTrigger)
- // TODO: get rid of deadline after https://codeberg.org/uzu/strudel/pulls/1004
- try {
- if (!hap.context.onTrigger || !hap.context.dominantTrigger) {
- await defaultOutput(hap, deadline, duration, cps, t);
+ async (hap, deadline, duration, cps, t) => {
+ // ^ this signature is different from hap.context.onTrigger, as set by Pattern.onTrigger(onTrigger)
+ // TODO: get rid of deadline after https://codeberg.org/uzu/strudel/pulls/1004
+ try {
+ if (!hap.context.onTrigger || !hap.context.dominantTrigger) {
+ await defaultOutput(hap, deadline, duration, cps, t);
+ }
+ if (hap.context.onTrigger) {
+ // call signature of output / onTrigger is different...
+ await hap.context.onTrigger(hap, getTime(), cps, t);
+ }
+ } catch (err) {
+ errorLogger(err, 'getTrigger');
}
- if (hap.context.onTrigger) {
- // call signature of output / onTrigger is different...
- await hap.context.onTrigger(hap, getTime(), cps, t);
- }
- } catch (err) {
- errorLogger(err, 'getTrigger');
- }
- };
+ };
diff --git a/packages/superdough/audioContext.mjs b/packages/superdough/audioContext.mjs
index 71e01d57d..30fbd9fd0 100644
--- a/packages/superdough/audioContext.mjs
+++ b/packages/superdough/audioContext.mjs
@@ -5,6 +5,11 @@ export const setDefaultAudioContext = () => {
return audioContext;
};
+export const setAudioContext = (context) => {
+ audioContext = context
+ return audioContext;
+};
+
export const getAudioContext = () => {
if (!audioContext) {
return setDefaultAudioContext();
diff --git a/packages/superdough/feedbackdelay.mjs b/packages/superdough/feedbackdelay.mjs
index c182d6558..b8269bc02 100644
--- a/packages/superdough/feedbackdelay.mjs
+++ b/packages/superdough/feedbackdelay.mjs
@@ -25,7 +25,7 @@ if (typeof DelayNode !== 'undefined') {
}
}
- AudioContext.prototype.createFeedbackDelay = function (wet, time, feedback) {
+ BaseAudioContext.prototype.createFeedbackDelay = function (wet, time, feedback) {
return new FeedbackDelayNode(this, wet, time, feedback);
};
}
diff --git a/packages/superdough/reverb.mjs b/packages/superdough/reverb.mjs
index 2960b597c..c8b6eb3e5 100644
--- a/packages/superdough/reverb.mjs
+++ b/packages/superdough/reverb.mjs
@@ -2,7 +2,7 @@ import reverbGen from './reverbGen.mjs';
import { clamp } from './util.mjs';
if (typeof AudioContext !== 'undefined') {
- AudioContext.prototype.adjustLength = function (duration, buffer, speed = 1, offsetAmount = 0) {
+ BaseAudioContext.prototype.adjustLength = function (duration, buffer, speed = 1, offsetAmount = 0) {
const sampleOffset = Math.floor(clamp(offsetAmount, 0, 1) * buffer.length);
const newLength = buffer.sampleRate * duration;
const newBuffer = this.createBuffer(buffer.numberOfChannels, buffer.length, buffer.sampleRate);
@@ -23,7 +23,7 @@ if (typeof AudioContext !== 'undefined') {
return newBuffer;
};
- AudioContext.prototype.createReverb = function (duration, fade, lp, dim, ir, irspeed, irbegin) {
+ BaseAudioContext.prototype.createReverb = function (duration, fade, lp, dim, ir, irspeed, irbegin) {
const convolver = this.createConvolver();
convolver.generate = (d = 2, fade = 0.1, lp = 15000, dim = 1000, ir, irspeed, irbegin) => {
convolver.duration = d;
diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs
index a37504b1d..80205a298 100644
--- a/packages/superdough/superdough.mjs
+++ b/packages/superdough/superdough.mjs
@@ -13,7 +13,7 @@ import { createFilter, gainNode, getCompressor, getDistortion, getLfo, getWorkle
import { map } from 'nanostores';
import { logger } from './logger.mjs';
import { loadBuffer } from './sampler.mjs';
-import { getAudioContext } from './audioContext.mjs';
+import { getAudioContext, setAudioContext } from './audioContext.mjs';
import { SuperdoughAudioController } from './superdoughoutput.mjs';
export const DEFAULT_MAX_POLYPHONY = 128;
@@ -367,6 +367,7 @@ function mapChannelNumbers(channels) {
}
export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) => {
+ controller = null;
// new: t is always expected to be the absolute target onset time
const ac = getAudioContext();
const audioController = getSuperdoughAudioController();
@@ -387,14 +388,13 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
// duration is passed as value too..
value.duration = hapDuration;
// calculate absolute time
-
- if (t < ac.currentTime) {
+ if (t < ac.currentTime && !(ac instanceof OfflineAudioContext)) {
console.warn(
`[superdough]: cannot schedule sounds in the past (target: ${t.toFixed(2)}, now: ${ac.currentTime.toFixed(2)})`,
);
return;
- }
- // destructure
+ } // FIXME: fix
+ // destructure
let {
tremolo,
tremolosync,
@@ -736,4 +736,4 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
export const superdoughTrigger = (t, hap, ct, cps) => {
superdough(hap, t - ct, hap.duration / cps, cps);
-};
+};
\ No newline at end of file
diff --git a/packages/superdough/vowel.mjs b/packages/superdough/vowel.mjs
index 3f30aef1e..025677fc1 100644
--- a/packages/superdough/vowel.mjs
+++ b/packages/superdough/vowel.mjs
@@ -63,7 +63,7 @@ if (typeof GainNode !== 'undefined') {
}
}
- AudioContext.prototype.createVowelFilter = function (letter) {
+ BaseAudioContext.prototype.createVowelFilter = function (letter) {
return new VowelNode(this, letter);
};
}
diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs
index 383e87f87..46bef88d6 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, getAudioContext, setLogger, doughTrigger, registerWorklet, setAudioContext, getSampleBufferSource, loadBuffer, getSampleInfo, getSound } from 'superdough';
import './supradough.mjs';
import { workletUrl } from 'supradough';
@@ -26,6 +26,60 @@ export const webaudioOutput = (hap, _deadline, hapDuration, cps, t) => {
return superdough(hap2value(hap), t, hapDuration, cps, hap.whole?.begin.valueOf());
};
+export async function renderPatternAudio(pattern, cps, begin, end) {
+ let audioContext = new OfflineAudioContext(2, (end - begin) / cps * 48000, 48000);
+ setAudioContext(audioContext)
+ logger('[webaudio] start rendering');
+ console.log(audioContext)
+
+ let haps = pattern.queryArc(begin, end, { _cps: cps })
+ Promise.all(haps.map(async h => {
+ let s;
+ if (h.value.s) {
+ if (h.value.bank) {
+ s = `${h.value.bank}_${h.value.s}`;
+ }
+ else {
+ s = h.value.s
+ }
+ }
+ let bank = getSound(s).data.samples
+ if (bank) {
+ let { url: sampleUrl, label } = getSampleInfo(h.value, bank);
+ await loadBuffer(sampleUrl, audioContext, label)
+ }
+ }))
+ haps.forEach(async (hap) => {
+ if (hap.hasOnset()) {
+ hap.ensureObjectValue();
+ await superdough(hap.value, hap.whole.begin.valueOf() / cps, hap.duration, cps, hap.whole?.begin.valueOf());
+ }
+ })
+
+ let context = getAudioContext()
+ context.startRendering().then((renderedBuffer) => {
+ // console.log(renderedBuffer)
+ const wavBuffer = audioBufferToWav(renderedBuffer);
+ const blob = new Blob([wavBuffer], { type: 'audio/wav' });
+ let downloadName = ''
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ // remove leading dash if they want an empty download name
+ if (downloadName == '') {
+ downloadName = `${new Date().toISOString()}.wav`;
+ } else {
+ downloadName = downloadName + `-${new Date().toISOString()}.wav`;
+ }
+ a.download = `${downloadName}`;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(url);
+ setAudioContext(null)
+ });
+}
+
export function webaudioRepl(options = {}) {
options = {
getTime: () => getAudioContext().currentTime,
@@ -38,3 +92,98 @@ export function webaudioRepl(options = {}) {
Pattern.prototype.dough = function () {
return this.onTrigger(doughTrigger, 1);
};
+
+
+function audioBufferToWav(buffer, opt) {
+ opt = opt || {}
+
+ var numChannels = buffer.numberOfChannels
+ var sampleRate = buffer.sampleRate
+ var format = opt.float32 ? 3 : 1
+ var bitDepth = format === 3 ? 32 : 16
+
+ var result
+ if (numChannels === 2) {
+ result = interleave(buffer.getChannelData(0), buffer.getChannelData(1))
+ } else {
+ result = buffer.getChannelData(0)
+ }
+
+ return encodeWAV(result, format, sampleRate, numChannels, bitDepth)
+}
+
+function encodeWAV(samples, format, sampleRate, numChannels, bitDepth) {
+ var bytesPerSample = bitDepth / 8
+ var blockAlign = numChannels * bytesPerSample
+
+ var buffer = new ArrayBuffer(44 + samples.length * bytesPerSample)
+ var view = new DataView(buffer)
+
+ /* RIFF identifier */
+ writeString(view, 0, 'RIFF')
+ /* RIFF chunk length */
+ view.setUint32(4, 36 + samples.length * bytesPerSample, true)
+ /* RIFF type */
+ writeString(view, 8, 'WAVE')
+ /* format chunk identifier */
+ writeString(view, 12, 'fmt ')
+ /* format chunk length */
+ view.setUint32(16, 16, true)
+ /* sample format (raw) */
+ view.setUint16(20, format, true)
+ /* channel count */
+ view.setUint16(22, numChannels, true)
+ /* sample rate */
+ view.setUint32(24, sampleRate, true)
+ /* byte rate (sample rate * block align) */
+ view.setUint32(28, sampleRate * blockAlign, true)
+ /* block align (channel count * bytes per sample) */
+ view.setUint16(32, blockAlign, true)
+ /* bits per sample */
+ view.setUint16(34, bitDepth, true)
+ /* data chunk identifier */
+ writeString(view, 36, 'data')
+ /* data chunk length */
+ view.setUint32(40, samples.length * bytesPerSample, true)
+ if (format === 1) { // Raw PCM
+ floatTo16BitPCM(view, 44, samples)
+ } else {
+ writeFloat32(view, 44, samples)
+ }
+
+ return buffer
+}
+
+function interleave(inputL, inputR) {
+ var length = inputL.length + inputR.length
+ var result = new Float32Array(length)
+
+ var index = 0
+ var inputIndex = 0
+
+ while (index < length) {
+ result[index++] = inputL[inputIndex]
+ result[index++] = inputR[inputIndex]
+ inputIndex++
+ }
+ return result
+}
+
+function writeFloat32(output, offset, input) {
+ for (var i = 0; i < input.length; i++, offset += 4) {
+ output.setFloat32(offset, input[i], true)
+ }
+}
+
+function floatTo16BitPCM(output, offset, input) {
+ for (var i = 0; i < input.length; i++, offset += 2) {
+ var s = Math.max(-1, Math.min(1, input[i]))
+ output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true)
+ }
+}
+
+function writeString(view, offset, string) {
+ for (var i = 0; i < string.length; i++) {
+ view.setUint8(offset + i, string.charCodeAt(i))
+ }
+}
\ No newline at end of file
diff --git a/website/src/repl/components/Header.jsx b/website/src/repl/components/Header.jsx
index ca4e1ecf9..656aa7861 100644
--- a/website/src/repl/components/Header.jsx
+++ b/website/src/repl/components/Header.jsx
@@ -8,7 +8,7 @@ const { BASE_URL } = import.meta.env;
const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL;
export function Header({ context, embedded = false }) {
- const { started, pending, isDirty, activeCode, handleTogglePlay, handleEvaluate, handleShuffle, handleShare } =
+ const { started, pending, isDirty, activeCode, handleTogglePlay, handleEvaluate, handleShuffle, handleShare, handleExport } =
context;
const isEmbedded = typeof window !== 'undefined' && (embedded || window.location !== window.parent.location);
const { isZen, isButtonRowHidden, isCSSAnimationDisabled, fontFamily } = useSettings();
@@ -93,6 +93,16 @@ export function Header({ context, embedded = false }) {
>
{!isEmbedded && update}
+
{/* !isEmbedded && (
From 9ffd0e496fcb71fcbc46add25eef7e40f56d4fb6 Mon Sep 17 00:00:00 2001
From: Felix Roos
Date: Sun, 11 Jan 2026 12:33:03 +0100
Subject: [PATCH 285/476] fix: all doc
---
packages/core/repl.mjs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/packages/core/repl.mjs b/packages/core/repl.mjs
index 047989f7f..9fe8eef81 100644
--- a/packages/core/repl.mjs
+++ b/packages/core/repl.mjs
@@ -120,7 +120,9 @@ export function repl({
// TODO - not documented as jsdoc examples as the test framework doesn't simulate enough context for `each` and `all`..
- /** Applies a function to all the running patterns. Note that the patterns are groups together into a single `stack` before the function is applied. This is probably what you want, but see `each` for
+ let allTransforms = [];
+ /**
+ * Applies a function to all the running patterns. Note that the patterns are groups together into a single `stack` before the function is applied. This is probably what you want, but see `each` for
* a version that applies the function to each pattern separately.
* ```
* $: sound("bd - cp sd")
@@ -135,7 +137,6 @@ export function repl({
*
* @tags combiners
*/
- let allTransforms = [];
const all = function (transform) {
allTransforms.push(transform);
return silence;
From a659c89385b84e08c001c47669fb98253ffb55f9 Mon Sep 17 00:00:00 2001
From: floy
Date: Sun, 11 Jan 2026 13:25:44 +0100
Subject: [PATCH 286/476] 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 287/476] 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 288/476] 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 289/476] 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)
From 12cc1e9b5ea22017bacfce974e2c5aad0ca7eaa6 Mon Sep 17 00:00:00 2001
From: Aria
Date: Sun, 11 Jan 2026 14:51:47 -0600
Subject: [PATCH 290/476] Add immediate triggering; move time to schedulerState
---
packages/core/index.mjs | 2 +-
packages/core/repl.mjs | 4 +-
.../core/{time.mjs => schedulerState.mjs} | 22 ++++++-
packages/midi/midi.mjs | 59 +++++++++++++++++--
4 files changed, 79 insertions(+), 8 deletions(-)
rename packages/core/{time.mjs => schedulerState.mjs} (70%)
diff --git a/packages/core/index.mjs b/packages/core/index.mjs
index 9260e3671..542a54243 100644
--- a/packages/core/index.mjs
+++ b/packages/core/index.mjs
@@ -22,7 +22,7 @@ export * from './repl.mjs';
export * from './signal.mjs';
export * from './speak.mjs';
export * from './state.mjs';
-export * from './time.mjs';
+export * from './schedulerState.mjs';
export * from './timespan.mjs';
export * from './ui.mjs';
export * from './util.mjs';
diff --git a/packages/core/repl.mjs b/packages/core/repl.mjs
index 71f68b809..e39b57de3 100644
--- a/packages/core/repl.mjs
+++ b/packages/core/repl.mjs
@@ -2,7 +2,7 @@ import { NeoCyclist } from './neocyclist.mjs';
import { Cyclist } from './cyclist.mjs';
import { evaluate as _evaluate } from './evaluate.mjs';
import { errorLogger, logger } from './logger.mjs';
-import { setCpsFunc, setTime } from './time.mjs';
+import { setCpsFunc, setPattern as exposeSchedulerPattern, setTime, setTriggerFunc } from './schedulerState.mjs';
import { evalScope } from './evaluate.mjs';
import { register, Pattern, isPattern, silence, stack } from './pattern.mjs';
import { reset_state } from './impure.mjs';
@@ -65,6 +65,7 @@ export function repl({
// NeoCyclist uses a shared worker to communicate between instances, which is not supported on mobile chrome
const scheduler =
sync && typeof SharedWorker != 'undefined' ? new NeoCyclist(schedulerOptions) : new Cyclist(schedulerOptions);
+ setTriggerFunc(schedulerOptions.onTrigger);
setCpsFunc(() => scheduler.cps);
let pPatterns = {};
let anonymousIndex = 0;
@@ -90,6 +91,7 @@ export function repl({
const setPattern = async (pattern, autostart = true) => {
pattern = editPattern?.(pattern) || pattern;
await scheduler.setPattern(pattern, autostart);
+ exposeSchedulerPattern(pattern);
return pattern;
};
setTime(() => scheduler.now()); // TODO: refactor?
diff --git a/packages/core/time.mjs b/packages/core/schedulerState.mjs
similarity index 70%
rename from packages/core/time.mjs
rename to packages/core/schedulerState.mjs
index 2d4caecf5..97a4f56dc 100644
--- a/packages/core/time.mjs
+++ b/packages/core/schedulerState.mjs
@@ -1,11 +1,13 @@
/*
-time.mjs - Core time module. Used to expose parameters from the Scheduler like `time` and `cps`
-Copyright (C) 2026 Strudel contributors - see
+schedulerState.mjs - Module to pipe out various parameters from the scheduler for global consumption
+Copyright (C) 2026 Strudel contributors - see
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .
*/
let time;
let cpsFunc;
+let pattern;
+let triggerFunc;
export function getTime() {
if (!time) {
throw new Error('no time set! use setTime to define a time source');
@@ -24,3 +26,19 @@ export function setCpsFunc(func) {
export function getCps() {
return cpsFunc?.();
}
+
+export function setPattern(pat) {
+ pattern = pat;
+}
+
+export function getPattern() {
+ return pattern;
+}
+
+export function setTriggerFunc(func) {
+ triggerFunc = func;
+}
+
+export function getTriggerFunc() {
+ return triggerFunc;
+}
diff --git a/packages/midi/midi.mjs b/packages/midi/midi.mjs
index 6233bf60d..ad6b799dc 100644
--- a/packages/midi/midi.mjs
+++ b/packages/midi/midi.mjs
@@ -5,9 +5,22 @@ This program is free software: you can redistribute it and/or modify it under th
*/
import * as _WebMidi from 'webmidi';
-import { Hap, Pattern, TimeSpan, getCps, getTime, isPattern, logger, ref, reify } from '@strudel/core';
+import {
+ Hap,
+ Pattern,
+ TimeSpan,
+ getCps,
+ getPattern,
+ getTime,
+ getTriggerFunc,
+ isPattern,
+ logger,
+ ref,
+ reify,
+} from '@strudel/core';
import { noteToMidi, getControlName } from '@strudel/core';
import { Note } from 'webmidi';
+import { getAudioContext } from '@strudel/webaudio';
import { scheduleAtTime } from '../superdough/helpers.mjs';
// if you use WebMidi from outside of this package, make sure to import that instance:
@@ -575,6 +588,33 @@ export async function midin(input) {
*/
const kHaps = {};
const kListeners = {};
+
+function triggerKbNow(input, cps, now, latencyCycles) {
+ const pattern = getPattern();
+ const trigger = getTriggerFunc();
+ if (!pattern || !trigger) {
+ return false;
+ }
+ const t = now + latencyCycles;
+ const eps = 1e-6;
+ const haps = pattern.queryArc(t - eps, t + eps, { _cps: cps });
+ // Only keep haps coming from `midikeys`
+ const kbHaps = haps.filter((hap) => hap.value?.midikey?.startsWith(`${input}_`));
+ const ctxNow = getAudioContext().currentTime;
+ if (!kbHaps.length) {
+ return false;
+ }
+ kbHaps.forEach((hap) => {
+ if (!hap.hasOnset()) {
+ return;
+ }
+ const t = ctxNow + (hap.whole.begin - now) / cps;
+ const duration = hap.duration / cps;
+ trigger(hap, t - ctxNow, duration, cps, t);
+ });
+
+ return true;
+}
export async function midikeys(input) {
const device = await _initialize(input);
if (!kHaps[input]) {
@@ -584,11 +624,14 @@ export async function midikeys(input) {
kListeners[input] = (e) => {
const { dataBytes, message } = e;
const [note, velocity] = dataBytes;
- const noteoff = message.command === 8;
+ const noteon = message.command === 9;
+ const noteoff = message.command === 8 || (noteon && velocity === 0);
const key = `${input}_${note}`;
const cps = getCps() ?? 0.5;
- const latencySeconds = 0.06; // slight delay so it's not too late for cyclist to catch
- const t = getTime() + latencySeconds * cps;
+ const triggerAvailable = !!(getPattern() && getTriggerFunc());
+ const latencySeconds = triggerAvailable ? 0.01 : 0.06; // avoid missing notes due to cyclist / trigger latency
+ const now = getTime();
+ const t = now + latencySeconds * cps;
const span = new TimeSpan(t, t);
let value = { midikey: key };
if (noteoff) {
@@ -609,6 +652,14 @@ export async function midikeys(input) {
value = { ...value, note: Math.round(note), velocity: velocity / 127 };
}
kHaps[input].push(new Hap(span, span, value, {}));
+ if (!noteoff && triggerAvailable) {
+ // If we have access to a trigger function, we call it to immediately
+ // dispatch to the audio engine, rather than waiting for cyclist to catch these haps
+ const triggered = triggerKbNow(input, cps, now, latencySeconds * cps);
+ if (triggered) {
+ kHaps[input] = [];
+ }
+ }
};
device.addListener('midimessage', kListeners[input]);
const kb = (noteLength = 0.5) => {
From 5355a0c563bea7b0e98dbfbfbff65c7a60f00b01 Mon Sep 17 00:00:00 2001
From: Aria
Date: Sun, 11 Jan 2026 23:34:52 -0600
Subject: [PATCH 291/476] Ignore non-note messages
---
packages/midi/midi.mjs | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/packages/midi/midi.mjs b/packages/midi/midi.mjs
index ad6b799dc..50a58b059 100644
--- a/packages/midi/midi.mjs
+++ b/packages/midi/midi.mjs
@@ -589,7 +589,7 @@ export async function midin(input) {
const kHaps = {};
const kListeners = {};
-function triggerKbNow(input, cps, now, latencyCycles) {
+function _triggerKeyboard(input, cps, now, latencyCycles) {
const pattern = getPattern();
const trigger = getTriggerFunc();
if (!pattern || !trigger) {
@@ -623,9 +623,14 @@ export async function midikeys(input) {
kListeners[input] && device.removeListener('midimessage', kListeners[input]);
kListeners[input] = (e) => {
const { dataBytes, message } = e;
- const [note, velocity] = dataBytes;
const noteon = message.command === 9;
- const noteoff = message.command === 8 || (noteon && velocity === 0);
+ let noteoff = message.command === 8;
+ if (!noteon && !noteoff) {
+ // Ignore non-note messages (e.g. CC, pitchbend, modwheel, etc.)
+ return;
+ }
+ const [note, velocity] = dataBytes;
+ noteoff ||= noteon && velocity === 0; // handle devices which may use velocity = 0 to signal noteoff
const key = `${input}_${note}`;
const cps = getCps() ?? 0.5;
const triggerAvailable = !!(getPattern() && getTriggerFunc());
@@ -655,7 +660,7 @@ export async function midikeys(input) {
if (!noteoff && triggerAvailable) {
// If we have access to a trigger function, we call it to immediately
// dispatch to the audio engine, rather than waiting for cyclist to catch these haps
- const triggered = triggerKbNow(input, cps, now, latencySeconds * cps);
+ const triggered = _triggerKeyboard(input, cps, now, latencySeconds * cps);
if (triggered) {
kHaps[input] = [];
}
From c2720a573821562b816a11d75311613cf57541f9 Mon Sep 17 00:00:00 2001
From: "Jade (Rose) Rowland"
Date: Mon, 12 Jan 2026 11:26:18 -0800
Subject: [PATCH 292/476] working
---
packages/core/pattern.mjs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs
index 58c83a6f8..4cf30c787 100644
--- a/packages/core/pattern.mjs
+++ b/packages/core/pattern.mjs
@@ -26,6 +26,7 @@ import {
} from './util.mjs';
import drawLine from './drawLine.mjs';
import { errorLogger, logger } from './logger.mjs';
+import { strudelScope } from './evaluate.mjs';
let stringParser;
@@ -1683,7 +1684,9 @@ export function register(name, func, patternify = true, preserveSteps = false, j
// toplevel functions get curried as well as patternified
// because pfunc uses spread args, we need to state the arity explicitly!
- return curry(pfunc, null, arity);
+ const curried = curry(pfunc, null, arity);
+ strudelScope[name] = pfunc;
+ return curried;
}
// Like register, but defaults to stepJoin
From 35bfd8b3ff53111425fd35eb0486979ba5265a3b Mon Sep 17 00:00:00 2001
From: "Jade (Rose) Rowland"
Date: Mon, 12 Jan 2026 11:28:54 -0800
Subject: [PATCH 293/476] curried
---
packages/core/pattern.mjs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs
index 4cf30c787..25a2bb0b9 100644
--- a/packages/core/pattern.mjs
+++ b/packages/core/pattern.mjs
@@ -1685,7 +1685,7 @@ export function register(name, func, patternify = true, preserveSteps = false, j
// toplevel functions get curried as well as patternified
// because pfunc uses spread args, we need to state the arity explicitly!
const curried = curry(pfunc, null, arity);
- strudelScope[name] = pfunc;
+ strudelScope[name] = curried;
return curried;
}
From 7c5f53f9ae8b85507300164be00852eccf6d0bf6 Mon Sep 17 00:00:00 2001
From: Aria
Date: Mon, 12 Jan 2026 13:51:21 -0600
Subject: [PATCH 294/476] Add ack message for worklet death; remove max pool
size
---
packages/superdough/nodePools.mjs | 7 ++-----
packages/superdough/synth.mjs | 5 ++++-
packages/superdough/wavetable.mjs | 5 ++++-
packages/superdough/worklets.mjs | 26 ++++++++++++++++++++++++--
4 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/packages/superdough/nodePools.mjs b/packages/superdough/nodePools.mjs
index 205352247..000099dc6 100644
--- a/packages/superdough/nodePools.mjs
+++ b/packages/superdough/nodePools.mjs
@@ -8,7 +8,6 @@ This program is free software: you can redistribute it and/or modify it under th
const nodePools = new Map();
const POOL_KEY = Symbol('nodePoolKey');
const IS_WORKLET_DEAD = Symbol('nodePoolIsWorkletDead');
-const MAX_POOL_SIZE = 64;
export const isPoolable = (node) => !!node[POOL_KEY];
@@ -47,10 +46,8 @@ export const releaseNodeToPool = (node) => {
const now = node.context?.currentTime ?? 0;
getParams(node).forEach((param) => param.cancelScheduledValues(now));
const pool = nodePools.get(key) ?? [];
- if (pool.length < MAX_POOL_SIZE) {
- pool.push(new WeakRef(node));
- nodePools.set(key, pool);
- }
+ pool.push(new WeakRef(node));
+ nodePools.set(key, pool);
};
export const markWorkletAsDead = (worklet) => (worklet[IS_WORKLET_DEAD] = true);
diff --git a/packages/superdough/synth.mjs b/packages/superdough/synth.mjs
index f4bdd749f..ec1724da0 100644
--- a/packages/superdough/synth.mjs
+++ b/packages/superdough/synth.mjs
@@ -186,7 +186,10 @@ export function registerSynthSounds() {
});
o.port.postMessage({ type: 'initialize' });
o.port.onmessage = (e) => {
- if (e.data.type === 'died') markWorkletAsDead(o);
+ if (e.data.type === 'died') {
+ markWorkletAsDead(o);
+ o.port.postMessage({ type: 'diedACK' });
+ }
o.port.onmessage = null;
};
const gainAdjustment = 1 / Math.sqrt(voices);
diff --git a/packages/superdough/wavetable.mjs b/packages/superdough/wavetable.mjs
index adf8b0c44..a228bc1d7 100644
--- a/packages/superdough/wavetable.mjs
+++ b/packages/superdough/wavetable.mjs
@@ -252,7 +252,10 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) {
});
source.port.postMessage({ type: 'initialize', payload });
source.port.onmessage = (e) => {
- if (e.data.type === 'died') markWorkletAsDead(source);
+ if (e.data.type === 'died') {
+ markWorkletAsDead(source);
+ source.port.postMessage({ type: 'diedACK' });
+ }
source.port.onmessage = null;
};
if (ac.currentTime > t) {
diff --git a/packages/superdough/worklets.mjs b/packages/superdough/worklets.mjs
index 52c13e836..61c620878 100644
--- a/packages/superdough/worklets.mjs
+++ b/packages/superdough/worklets.mjs
@@ -464,11 +464,19 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.isAlive = true; // used internally to prevent multiple death messages
+ // diedACK is used for the main thread to acknowledge that the worklet has died
+ // This is so that we don't risk simultaneously killing the worklet (`return false`)
+ // and pooling the worklet (main thread) before the async `died` message hits
+ // the main thread
+ this.diedACK = false;
this.port.onmessage = (e) => {
const { type, payload } = e.data || {};
if (type === 'initialize') {
this.initialize(payload);
}
+ if (type === 'diedACK') {
+ this.diedACK = true;
+ }
};
this.initialize();
}
@@ -529,7 +537,10 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
this.port.postMessage({ type: 'died' });
this.isAlive = false;
}
- return false;
+ if (this.diedACK || currentTime >= params.end[1] + 1) {
+ return false;
+ }
+ return true;
}
if (currentTime >= params.end[0] || currentTime <= params.begin[0]) {
// Inside of grace period or not yet started
@@ -1165,11 +1176,19 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
constructor(options) {
super(options);
this.isAlive = true; // used internally to prevent multiple death messages
+ // diedACK is used for the main thread to acknowledge that the worklet has died
+ // This is so that we don't risk simultaneously killing the worklet (`return false`)
+ // and pooling the worklet (main thread) before the async `died` message hits
+ // the main thread
+ this.diedACK = false;
this.port.onmessage = (e) => {
const { type, payload } = e.data || {};
if (type === 'initialize') {
this.initialize(payload);
}
+ if (type === 'diedACK') {
+ this.diedACK = true;
+ }
};
this.initialize();
}
@@ -1338,7 +1357,10 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
this.port.postMessage({ type: 'died' });
this.isAlive = false;
}
- return false;
+ if (this.diedACK || currentTime >= parameters.end[1] + 1) {
+ return false;
+ }
+ return true;
}
if (currentTime >= parameters.end[0] || currentTime <= parameters.begin[0]) {
// Inside of grace period or not yet started
From 1f1f3288a6fe0d9f1803f1ceb00cd12bb746ba05 Mon Sep 17 00:00:00 2001
From: Aria
Date: Mon, 12 Jan 2026 17:58:20 -0600
Subject: [PATCH 295/476] Switch to tracking grace period in node pool; add
negative begin and ends
---
packages/superdough/nodePools.mjs | 32 +++++++++----
packages/superdough/synth.mjs | 9 +---
packages/superdough/wavetable.mjs | 9 +---
packages/superdough/worklets.mjs | 78 +++++++++++--------------------
4 files changed, 53 insertions(+), 75 deletions(-)
diff --git a/packages/superdough/nodePools.mjs b/packages/superdough/nodePools.mjs
index 000099dc6..90b4c0ae7 100644
--- a/packages/superdough/nodePools.mjs
+++ b/packages/superdough/nodePools.mjs
@@ -7,10 +7,13 @@ This program is free software: you can redistribute it and/or modify it under th
const nodePools = new Map();
const POOL_KEY = Symbol('nodePoolKey');
-const IS_WORKLET_DEAD = Symbol('nodePoolIsWorkletDead');
export const isPoolable = (node) => !!node[POOL_KEY];
+const getNodeTime = (node) => {
+ return node.context?.currentTime ?? 0;
+};
+
const getParams = (node) => {
const params = new Set();
node.parameters?.forEach((param) => params.add(param));
@@ -37,32 +40,43 @@ export const releaseNodeToPool = (node) => {
// not reusable
return;
}
- if (node[IS_WORKLET_DEAD]) {
- // Worklet already terminated, don't pool it
- return;
- }
const key = node[POOL_KEY];
if (key == null) return;
- const now = node.context?.currentTime ?? 0;
+ const now = getNodeTime(node);
getParams(node).forEach((param) => param.cancelScheduledValues(now));
const pool = nodePools.get(key) ?? [];
pool.push(new WeakRef(node));
nodePools.set(key, pool);
};
-export const markWorkletAsDead = (worklet) => (worklet[IS_WORKLET_DEAD] = true);
+// Audio worklets are given a grace period to survive (`return true`) after
+// being released. This concludes at time `end + 0.5`. We test here whether we are
+// within some safe distance of that (`end + 0.45`) and if so, permit the node to be
+// released. This helps to prevent race conditions between node termination and node
+// re-use
+const isNodeAlive = (node) => {
+ // Skip check if node is not a worklet
+ if (!(node instanceof AudioWorkletNode)) return true;
+ const now = getNodeTime(node);
+ const end = node?.parameters?.get('end').value ?? 0;
+ return now < end + 0.45;
+};
// Attempt to get node from the pool. If this fails, fall back
// to building it with the factory
export const getNodeFromPool = (key, factory) => {
const pool = nodePools.get(key) ?? [];
let node;
+ let found = false;
while (pool.length) {
const ref = pool.pop();
node = ref?.deref();
- if (node != null && !node[IS_WORKLET_DEAD]) break;
+ if (node != null && isNodeAlive(node)) {
+ found = true;
+ break;
+ }
}
- if (node == null || node[IS_WORKLET_DEAD]) {
+ if (!found) {
node = factory();
}
node[POOL_KEY] = key;
diff --git a/packages/superdough/synth.mjs b/packages/superdough/synth.mjs
index ec1724da0..9561ab363 100644
--- a/packages/superdough/synth.mjs
+++ b/packages/superdough/synth.mjs
@@ -18,7 +18,7 @@ import {
} from './helpers.mjs';
import { logger } from './logger.mjs';
import { getNoiseMix, getNoiseOscillator } from './noise.mjs';
-import { getNodeFromPool, markWorkletAsDead, releaseNodeToPool } from './nodePools.mjs';
+import { getNodeFromPool, releaseNodeToPool } from './nodePools.mjs';
const waveforms = ['triangle', 'square', 'sawtooth', 'sine', 'user', 'one'];
const waveformAliases = [
@@ -185,13 +185,6 @@ export function registerSynthSounds() {
param.setValueAtTime(target, now);
});
o.port.postMessage({ type: 'initialize' });
- o.port.onmessage = (e) => {
- if (e.data.type === 'died') {
- markWorkletAsDead(o);
- o.port.postMessage({ type: 'diedACK' });
- }
- o.port.onmessage = null;
- };
const gainAdjustment = 1 / Math.sqrt(voices);
getPitchEnvelope(o.parameters.get('detune'), value, begin, holdend);
const vibratoHandle = getVibratoOscillator(o.parameters.get('detune'), value, begin);
diff --git a/packages/superdough/wavetable.mjs b/packages/superdough/wavetable.mjs
index a228bc1d7..1de42f643 100644
--- a/packages/superdough/wavetable.mjs
+++ b/packages/superdough/wavetable.mjs
@@ -11,7 +11,7 @@ import {
webAudioTimeout,
releaseAudioNode,
} from './helpers.mjs';
-import { getNodeFromPool, markWorkletAsDead, releaseNodeToPool } from './nodePools.mjs';
+import { getNodeFromPool, releaseNodeToPool } from './nodePools.mjs';
import { logger } from './logger.mjs';
export const Warpmode = Object.freeze({
@@ -251,13 +251,6 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) {
param.setValueAtTime(target, now);
});
source.port.postMessage({ type: 'initialize', payload });
- source.port.onmessage = (e) => {
- if (e.data.type === 'died') {
- markWorkletAsDead(source);
- source.port.postMessage({ type: 'diedACK' });
- }
- source.port.onmessage = null;
- };
if (ac.currentTime > t) {
logger(`[wavetable] still loading sound "${s}:${n}"`, 'highlight');
return;
diff --git a/packages/superdough/worklets.mjs b/packages/superdough/worklets.mjs
index 61c620878..6689278e3 100644
--- a/packages/superdough/worklets.mjs
+++ b/packages/superdough/worklets.mjs
@@ -463,20 +463,11 @@ registerProcessor('distort-processor', DistortProcessor);
class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
constructor() {
super();
- this.isAlive = true; // used internally to prevent multiple death messages
- // diedACK is used for the main thread to acknowledge that the worklet has died
- // This is so that we don't risk simultaneously killing the worklet (`return false`)
- // and pooling the worklet (main thread) before the async `died` message hits
- // the main thread
- this.diedACK = false;
this.port.onmessage = (e) => {
const { type, payload } = e.data || {};
if (type === 'initialize') {
this.initialize(payload);
}
- if (type === 'diedACK') {
- this.diedACK = true;
- }
};
this.initialize();
}
@@ -487,16 +478,16 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
return [
{
name: 'begin',
- defaultValue: 0,
+ defaultValue: -1,
max: Number.POSITIVE_INFINITY,
- min: 0,
+ min: -1,
},
{
name: 'end',
- defaultValue: 0,
+ defaultValue: -1,
max: Number.POSITIVE_INFINITY,
- min: 0,
+ min: -1,
},
{
@@ -531,19 +522,17 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
];
}
process(_input, outputs, params) {
- if (currentTime >= params.end[0] + 0.5) {
- // Outside of grace period - should terminate
- if (this.isAlive) {
- this.port.postMessage({ type: 'died' });
- this.isAlive = false;
- }
- if (this.diedACK || currentTime >= params.end[1] + 1) {
- return false;
- }
- return true;
- }
- if (currentTime >= params.end[0] || currentTime <= params.begin[0]) {
- // Inside of grace period or not yet started
+ const begin = params.begin[0];
+ const end = params.end[0];
+ const beginDefined = begin >= 0;
+ const endDefined = end >= 0;
+ // We give a 0.5s grace period (for node pooling) before termination
+ const shouldTerminate = endDefined && currentTime >= end + 0.5;
+ const ended = endDefined && currentTime >= end;
+ const notStarted = currentTime <= begin;
+ if (shouldTerminate) {
+ return false;
+ } else if (ended || notStarted || !beginDefined) {
return true;
}
const output = outputs[0];
@@ -1159,8 +1148,8 @@ const tablesCache = {};
class WavetableOscillatorProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [
- { name: 'begin', defaultValue: 0, min: 0, max: Number.POSITIVE_INFINITY },
- { name: 'end', defaultValue: 0, min: 0, max: Number.POSITIVE_INFINITY },
+ { name: 'begin', defaultValue: -1, min: -1, max: Number.POSITIVE_INFINITY },
+ { name: 'end', defaultValue: -1, min: -1, max: Number.POSITIVE_INFINITY },
{ name: 'frequency', defaultValue: 440, min: Number.EPSILON },
{ name: 'detune', defaultValue: 0 },
{ name: 'freqspread', defaultValue: 0.18, min: 0 },
@@ -1175,20 +1164,11 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
constructor(options) {
super(options);
- this.isAlive = true; // used internally to prevent multiple death messages
- // diedACK is used for the main thread to acknowledge that the worklet has died
- // This is so that we don't risk simultaneously killing the worklet (`return false`)
- // and pooling the worklet (main thread) before the async `died` message hits
- // the main thread
- this.diedACK = false;
this.port.onmessage = (e) => {
const { type, payload } = e.data || {};
if (type === 'initialize') {
this.initialize(payload);
}
- if (type === 'diedACK') {
- this.diedACK = true;
- }
};
this.initialize();
}
@@ -1351,19 +1331,17 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
}
process(_inputs, outputs, parameters) {
- if (currentTime >= parameters.end[0] + 0.5) {
- // Outside of grace period - should terminate
- if (this.isAlive) {
- this.port.postMessage({ type: 'died' });
- this.isAlive = false;
- }
- if (this.diedACK || currentTime >= parameters.end[1] + 1) {
- return false;
- }
- return true;
- }
- if (currentTime >= parameters.end[0] || currentTime <= parameters.begin[0]) {
- // Inside of grace period or not yet started
+ const begin = parameters.begin[0];
+ const end = parameters.end[0];
+ const beginDefined = begin >= 0;
+ const endDefined = end >= 0;
+ // We give a 0.5s grace period (for node pooling) before termination
+ const shouldTerminate = endDefined && currentTime >= end + 0.5;
+ const ended = endDefined && currentTime >= end;
+ const notStarted = currentTime <= begin;
+ if (shouldTerminate) {
+ return false;
+ } else if (ended || notStarted || !beginDefined) {
return true;
}
const outL = outputs[0][0];
From 8b1fb12388aa523224f8e7a93e5bca0e3368fbd0 Mon Sep 17 00:00:00 2001
From: Felix Roos
Date: Tue, 13 Jan 2026 03:32:19 +0100
Subject: [PATCH 296/476] fix: class -> className
---
website/src/repl/components/panel/PatternsTab.jsx | 2 +-
website/src/repl/components/panel/Reference.jsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx
index 56f0b4cb8..04f6452e5 100644
--- a/website/src/repl/components/panel/PatternsTab.jsx
+++ b/website/src/repl/components/panel/PatternsTab.jsx
@@ -126,7 +126,7 @@ export function PatternsTab({ context }) {
return (
From e82bb6c4100e58b4a9f99e617745a74d1fb74b1c Mon Sep 17 00:00:00 2001
From: Felix Roos
Date: Tue, 13 Jan 2026 03:38:09 +0100
Subject: [PATCH 297/476] fix: use pattern.id as title fallback
---
website/src/repl/components/panel/PatternsTab.jsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx
index 04f6452e5..75c019438 100644
--- a/website/src/repl/components/panel/PatternsTab.jsx
+++ b/website/src/repl/components/panel/PatternsTab.jsx
@@ -29,7 +29,7 @@ export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) {
if (!isNaN(date)) {
title = date.toLocaleDateString();
} else {
- title = 'unnamed';
+ title = pattern.id || 'unnamed';
}
}
From e5ab6b3c93b35973e46607c45bb071b323177bbf Mon Sep 17 00:00:00 2001
From: Felix Roos
Date: Tue, 13 Jan 2026 03:47:33 +0100
Subject: [PATCH 298/476] fix: short circuit
---
website/src/repl/components/panel/PatternsTab.jsx | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/website/src/repl/components/panel/PatternsTab.jsx b/website/src/repl/components/panel/PatternsTab.jsx
index 75c019438..c72ebaa30 100644
--- a/website/src/repl/components/panel/PatternsTab.jsx
+++ b/website/src/repl/components/panel/PatternsTab.jsx
@@ -89,12 +89,11 @@ export function PatternsTab({ context }) {
const viewingPatternID = viewingPatternData?.id;
const visiblePatterns = useMemo(() => {
+ if (!search) {
+ return userPatterns;
+ }
return Object.fromEntries(
Object.entries(userPatterns).filter(([_key, pattern]) => {
- if (!search) {
- return true;
- }
-
const meta = getMetadata(pattern.code);
// Search for specific meta keys
From 055f009357f0b8b7438e9b7b06945c04c65167cd Mon Sep 17 00:00:00 2001
From: space-shell
Date: Tue, 13 Jan 2026 19:47:12 +0100
Subject: [PATCH 299/476] feat: Refactor Vim/Helix keybindings with shared
helper functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Factor out the repl-eval and repl-stop event dispatching code into
replEval() and replStop() helper functions that are shared between
Vim and Helix keybindings.
This refactoring:
- Reduces code duplication between Vim :w/:q and Helix :w/:q commands
- Makes the keybinding handlers more maintainable
- Properly implements Helix commands using the commands.of() API
- Ensures consistent behavior across both keybinding modes
The Helix keybindings now properly integrate with the REPL using the
same event dispatch mechanism as Vim, dispatching custom repl-evaluate
and repl-stop events with fallbacks to keyboard events.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude
---
packages/codemirror/keybindings.mjs | 163 ++++++++++++++++++----------
1 file changed, 106 insertions(+), 57 deletions(-)
diff --git a/packages/codemirror/keybindings.mjs b/packages/codemirror/keybindings.mjs
index bc13f3234..3e6606306 100644
--- a/packages/codemirror/keybindings.mjs
+++ b/packages/codemirror/keybindings.mjs
@@ -6,7 +6,7 @@ import { emacs } from '@replit/codemirror-emacs';
import { vim, Vim } from '@replit/codemirror-vim';
// import { vim } from './vim_test.mjs';
import { vscodeKeymap } from '@replit/codemirror-vscode-keymap';
-import { helix } from 'codemirror-helix';
+import { helix, commands } from 'codemirror-helix';
import { logger } from '@strudel/core';
const vscodePlugin = ViewPlugin.fromClass(
@@ -21,6 +21,70 @@ const vscodePlugin = ViewPlugin.fromClass(
);
const vscodeExtension = (options) => [vscodePlugin].concat(options ?? []);
+function replEval(view) {
+ try {
+ // Dispatch a dedicated evaluate event first
+ let handled = false;
+ try {
+ const ev = new CustomEvent('repl-evaluate', { detail: { source: 'vim', view }, cancelable: true });
+ handled = document.dispatchEvent(ev) === false; // false means preventDefault was called
+ } catch (e) {
+ console.error('Error dispatching repl-evaluate event', e);
+ }
+ if (handled) {
+ return;
+ }
+ // Try Ctrl+Enter first if not handled by custom event
+ const ctrlEnter = new KeyboardEvent('keydown', {
+ key: 'Enter',
+ code: 'Enter',
+ ctrlKey: true,
+ bubbles: true,
+ cancelable: true,
+ });
+ view?.dom?.dispatchEvent?.(ctrlEnter);
+ // If not handled (no handler called preventDefault), try Alt+Enter as
+ // fallback
+ if (!ctrlEnter.defaultPrevented) {
+ const altEnter = new KeyboardEvent('keydown', {
+ key: 'Enter',
+ code: 'Enter',
+ altKey: true,
+ bubbles: true,
+ cancelable: true,
+ });
+ view?.dom?.dispatchEvent?.(altEnter);
+ }
+ } catch (e) {
+ console.error('Error dispatching repl evaluation event', e);
+ }
+}
+
+function replStop(view) {
+ try {
+ // First try dispatching our custom stop event, then fallback to Alt+.
+ let handled = false;
+ try {
+ const ev = new CustomEvent('repl-stop', { detail: { source: 'vim', view }, cancelable: true });
+ handled = document.dispatchEvent(ev) === false;
+ } catch (e) {
+ console.error('Error dispatching repl-stop event', e);
+ }
+ if (!handled) {
+ const altDot = new KeyboardEvent('keydown', {
+ key: '.',
+ code: 'Period',
+ altKey: true,
+ bubbles: true,
+ cancelable: true,
+ });
+ view?.dom?.dispatchEvent?.(altDot);
+ }
+ } catch (e) {
+ console.error('Error dispatching repl stop event', e);
+ }
+}
+
// Map Vim :w to trigger the same action as evaluation. We dispatch a custom
// event 'repl-evaluate' that the editor listens for, and also simulate
// Ctrl+Enter/Alt+Enter as a fallback. We log to the Strudel logger so it
@@ -48,29 +112,8 @@ try {
// :q to pause/stop
Vim.defineEx('quit', 'q', (cm) => {
- try {
- const view = cm?.view || cm;
- // First try dispatching our custom stop event, then fallback to Alt+.
- let handled = false;
- try {
- const ev = new CustomEvent('repl-stop', { detail: { source: 'vim', view }, cancelable: true });
- handled = document.dispatchEvent(ev) === false;
- } catch (e) {
- console.error('Error dispatching repl-stop event', e);
- }
- if (!handled) {
- const altDot = new KeyboardEvent('keydown', {
- key: '.',
- code: 'Period',
- altKey: true,
- bubbles: true,
- cancelable: true,
- });
- view?.dom?.dispatchEvent?.(altDot);
- }
- } catch (e) {
- console.error('Error dispatching :q stop event', e);
- }
+ const view = cm?.view || cm;
+ replStop(view);
});
// :w to evaluate
@@ -84,38 +127,7 @@ try {
} catch (e) {
console.error('Error logging Vim :w evaluation', e);
}
- // Dispatch a dedicated evaluate event first
- let handled = false;
- try {
- const ev = new CustomEvent('repl-evaluate', { detail: { source: 'vim', view }, cancelable: true });
- handled = document.dispatchEvent(ev) === false; // false means preventDefault was called
- } catch (e) {
- console.error('Error dispatching repl-evaluate event', e);
- }
- if (handled) {
- return;
- }
- // Try Ctrl+Enter first if not handled by custom event
- const ctrlEnter = new KeyboardEvent('keydown', {
- key: 'Enter',
- code: 'Enter',
- ctrlKey: true,
- bubbles: true,
- cancelable: true,
- });
- view?.dom?.dispatchEvent?.(ctrlEnter);
- // If not handled (no handler called preventDefault), try Alt+Enter as
- // fallback
- if (!ctrlEnter.defaultPrevented) {
- const altEnter = new KeyboardEvent('keydown', {
- key: 'Enter',
- code: 'Enter',
- altKey: true,
- bubbles: true,
- cancelable: true,
- });
- view?.dom?.dispatchEvent?.(altEnter);
- }
+ replEval(view);
} catch (e) {
console.error('Error dispatching :w evaluation event', e);
}
@@ -125,12 +137,49 @@ try {
console.error('Vim ex command setup failed (defineEx missing or Vim unavailable)', e);
}
+// Map Helix :w to trigger the same action as evaluation. We dispatch a custom
+// event 'repl-evaluate' that the editor listens for, and also simulate
+// Ctrl+Enter/Alt+Enter as a fallback. We log to the Strudel logger so it
+// appears in the Console panel.
+const helixCommands = commands.of([
+ {
+ // :w to evaluate
+ name: 'write',
+ aliases: ['w'],
+ help: 'Repl-eval',
+ handler(view, args) {
+ try {
+ view?.focus?.(); // Let the app know this came from Helix :w
+ logger('[helix] :w — evaluating code');
+ replEval(view);
+ } catch (e) {
+ console.error('Error dispatching helix :w evaluation event', e);
+ }
+ },
+ },
+ {
+ // :q to pause/stop
+ name: 'quit',
+ aliases: ['q'],
+ help: 'Repl-stop',
+ handler(view, args) {
+ try {
+ view?.focus?.(); // Let the app know this came from Helix :q
+ logger('[helix] :q — stopping repl');
+ replStop(view);
+ } catch (e) {
+ console.error('Error dispatching helix :q stop event', e);
+ }
+ },
+ },
+]);
+
const keymaps = {
vim,
emacs,
- helix,
codemirror: () => keymap.of(defaultKeymap),
vscode: vscodeExtension,
+ helix: () => [helix(), helixCommands],
};
export function keybindings(name) {
From 80875cca956024e017281108fcd2fee673e6f1f3 Mon Sep 17 00:00:00 2001
From: Aria
Date: Wed, 14 Jan 2026 11:44:48 -0600
Subject: [PATCH 300/476] Expose scheduler state and don't enqueue/trigger midi
keys when repl stopped
---
packages/core/repl.mjs | 9 ++++++++-
packages/core/schedulerState.mjs | 9 +++++++++
packages/midi/midi.mjs | 8 ++++++--
3 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/packages/core/repl.mjs b/packages/core/repl.mjs
index e39b57de3..a056cac53 100644
--- a/packages/core/repl.mjs
+++ b/packages/core/repl.mjs
@@ -2,7 +2,13 @@ import { NeoCyclist } from './neocyclist.mjs';
import { Cyclist } from './cyclist.mjs';
import { evaluate as _evaluate } from './evaluate.mjs';
import { errorLogger, logger } from './logger.mjs';
-import { setCpsFunc, setPattern as exposeSchedulerPattern, setTime, setTriggerFunc } from './schedulerState.mjs';
+import {
+ setCpsFunc,
+ setIsStarted,
+ setPattern as exposeSchedulerPattern,
+ setTime,
+ setTriggerFunc,
+} from './schedulerState.mjs';
import { evalScope } from './evaluate.mjs';
import { register, Pattern, isPattern, silence, stack } from './pattern.mjs';
import { reset_state } from './impure.mjs';
@@ -52,6 +58,7 @@ export function repl({
getTime,
onToggle: (started) => {
updateState({ started });
+ setIsStarted(started);
onToggle?.(started);
if (!started) {
reset_state();
diff --git a/packages/core/schedulerState.mjs b/packages/core/schedulerState.mjs
index 97a4f56dc..14b4c9054 100644
--- a/packages/core/schedulerState.mjs
+++ b/packages/core/schedulerState.mjs
@@ -8,6 +8,7 @@ let time;
let cpsFunc;
let pattern;
let triggerFunc;
+let isStarted;
export function getTime() {
if (!time) {
throw new Error('no time set! use setTime to define a time source');
@@ -42,3 +43,11 @@ export function setTriggerFunc(func) {
export function getTriggerFunc() {
return triggerFunc;
}
+
+export function setIsStarted(val) {
+ isStarted = !!val;
+}
+
+export function getIsStarted() {
+ return isStarted;
+}
diff --git a/packages/midi/midi.mjs b/packages/midi/midi.mjs
index 50a58b059..d0a1ce18d 100644
--- a/packages/midi/midi.mjs
+++ b/packages/midi/midi.mjs
@@ -10,6 +10,7 @@ import {
Pattern,
TimeSpan,
getCps,
+ getIsStarted,
getPattern,
getTime,
getTriggerFunc,
@@ -625,8 +626,11 @@ export async function midikeys(input) {
const { dataBytes, message } = e;
const noteon = message.command === 9;
let noteoff = message.command === 8;
- if (!noteon && !noteoff) {
- // Ignore non-note messages (e.g. CC, pitchbend, modwheel, etc.)
+ // Don't enqueue or trigger midi notes if scheduler is not started
+ const notStarted = !getIsStarted();
+ // Ignore non-note messages (e.g. CC, pitchbend, modwheel, etc.)
+ const notANote = !noteon && !noteoff;
+ if (notStarted || notANote) {
return;
}
const [note, velocity] = dataBytes;
From ffcab7bf6c774b452b99709f035f9f2b7116599c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20Bj=C3=B6rk?=
Date: Wed, 14 Jan 2026 22:25:27 +0100
Subject: [PATCH 301/476] Added docs for pattern search
---
website/src/pages/learn/metadata.mdx | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/website/src/pages/learn/metadata.mdx b/website/src/pages/learn/metadata.mdx
index c94257925..35a1ad05c 100644
--- a/website/src/pages/learn/metadata.mdx
+++ b/website/src/pages/learn/metadata.mdx
@@ -53,6 +53,7 @@ Available tags are:
- `@url`: web page(s) related to the music (git repository, Soundcloud link, etc.)
- `@genre`: music genre(s) (pop, jazz, etc.)
- `@album`: music album name
+- `@tag`: custom tag
Note to tool authors: _Never_ trust that a song has filled those fields with syntactically correct values; make sure your software is robust enough it doesn't break if it encounters bad values
@@ -92,3 +93,18 @@ If a tag doesn't accept a list, it can take multi-line values:
the sofa in the living room.
*/
```
+
+# Searching meta-data in the online repl
+
+Meta-data can be used in the search field of the patterns tab in the online repl.
+
+For example to search for all patterns by a specific author use the search term
+```
+by: Ada L
+```
+or search for patterns with a specific genre like
+```
+genre: unicorns
+```
+
+Hint: If no meta-data property is provided in the search all patterns with a `@title`, `@by` or `@tag` matching the search term will be shown.
From 71dfbeea8828590a7cf061f5d9aa8648c35b96c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20Bj=C3=B6rk?=
Date: Wed, 14 Jan 2026 22:35:10 +0100
Subject: [PATCH 302/476] Fix markdown format
---
website/src/pages/learn/metadata.mdx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/website/src/pages/learn/metadata.mdx b/website/src/pages/learn/metadata.mdx
index 35a1ad05c..07a1357c1 100644
--- a/website/src/pages/learn/metadata.mdx
+++ b/website/src/pages/learn/metadata.mdx
@@ -99,10 +99,13 @@ If a tag doesn't accept a list, it can take multi-line values:
Meta-data can be used in the search field of the patterns tab in the online repl.
For example to search for all patterns by a specific author use the search term
+
```
by: Ada L
-```
+```
+
or search for patterns with a specific genre like
+
```
genre: unicorns
```
From 85e79d993263f84b1aa63f4efa9eb71b9cb93d42 Mon Sep 17 00:00:00 2001
From: Aria
Date: Wed, 14 Jan 2026 16:53:11 -0600
Subject: [PATCH 303/476] Set pooled values immediately instead of scheduling
---
packages/superdough/helpers.mjs | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs
index 0ca085e3e..bb402ea78 100644
--- a/packages/superdough/helpers.mjs
+++ b/packages/superdough/helpers.mjs
@@ -154,9 +154,8 @@ export function getCompressor(ac, threshold, ratio, knee, attack, release) {
attack: attack ?? 0.005,
release: release ?? 0.05,
};
- const now = ac.currentTime;
Object.entries(options).forEach(([key, value]) => {
- node[key].setValueAtTime(value, now);
+ node[key].value = value;;
});
return node;
}
@@ -242,9 +241,8 @@ export function createFilter(context, start, end, params, cps, cycle) {
const factory = () => context.createBiquadFilter();
filter = getNodeFromPool('filter', factory);
filter.type = type;
- const now = context.currentTime;
Object.entries({ Q: q, frequency }).forEach(([key, value]) => {
- filter[key].setValueAtTime(value, now);
+ filter[key].value = value;
});
frequencyParam = filter.frequency;
}
From 21e6d81d349f475527d26509749385d70c5d0374 Mon Sep 17 00:00:00 2001
From: Aria
Date: Wed, 14 Jan 2026 16:58:45 -0600
Subject: [PATCH 304/476] Also set values immediately for supersaw and
wavetable
---
packages/superdough/helpers.mjs | 2 +-
packages/superdough/synth.mjs | 3 +--
packages/superdough/wavetable.mjs | 3 +--
3 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs
index bb402ea78..584b19673 100644
--- a/packages/superdough/helpers.mjs
+++ b/packages/superdough/helpers.mjs
@@ -155,7 +155,7 @@ export function getCompressor(ac, threshold, ratio, knee, attack, release) {
release: release ?? 0.05,
};
Object.entries(options).forEach(([key, value]) => {
- node[key].value = value;;
+ node[key].value = value;
});
return node;
}
diff --git a/packages/superdough/synth.mjs b/packages/superdough/synth.mjs
index 9561ab363..38ad643de 100644
--- a/packages/superdough/synth.mjs
+++ b/packages/superdough/synth.mjs
@@ -178,11 +178,10 @@ export function registerSynthSounds() {
};
const factory = () => new AudioWorkletNode(ac, 'supersaw-oscillator', { outputChannelCount: [2] });
const o = getNodeFromPool('supersaw', factory);
- const now = ac.currentTime;
Object.entries(params).forEach(([key, value]) => {
const param = o.parameters.get(key);
const target = value !== undefined ? value : param.defaultValue;
- param.setValueAtTime(target, now);
+ param.value = target;
});
o.port.postMessage({ type: 'initialize' });
const gainAdjustment = 1 / Math.sqrt(voices);
diff --git a/packages/superdough/wavetable.mjs b/packages/superdough/wavetable.mjs
index 1de42f643..6ef1f0ebb 100644
--- a/packages/superdough/wavetable.mjs
+++ b/packages/superdough/wavetable.mjs
@@ -244,11 +244,10 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) {
};
const factory = () => new AudioWorkletNode(ac, 'wavetable-oscillator-processor', { outputChannelCount: [2] });
const source = getNodeFromPool('wavetable', factory);
- const now = ac.currentTime;
Object.entries(params).forEach(([key, value]) => {
const param = source.parameters.get(key);
const target = value !== undefined ? value : param.defaultValue;
- param.setValueAtTime(target, now);
+ param.value = target;
});
source.port.postMessage({ type: 'initialize', payload });
if (ac.currentTime > t) {
From 44ad05fb203368f6cc1fa17144b7b527bdf0c453 Mon Sep 17 00:00:00 2001
From: Nick Matantsev
Date: Wed, 14 Jan 2026 23:37:26 -0500
Subject: [PATCH 305/476] Whitespace fixes
---
packages/midi/input.mjs | 360 ++++++++++++++++++++--------------------
packages/midi/util.mjs | 88 +++++-----
2 files changed, 224 insertions(+), 224 deletions(-)
diff --git a/packages/midi/input.mjs b/packages/midi/input.mjs
index 8e4889427..498e6fe21 100644
--- a/packages/midi/input.mjs
+++ b/packages/midi/input.mjs
@@ -1,180 +1,180 @@
-/*
-input.mjs - MIDI input wrapper
-Copyright (C) 2022 Strudel contributors - see
-This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .
-*/
-
-import { WebMidi } from 'webmidi';
-import { logger, ref } from '@strudel/core';
-import { getDevice } from './util.mjs';
-
-export class MidiInput {
- /**
- *
- * @param {string | number} input MIDI device name or index defaulting to 0
- */
- constructor(input) {
- this.input = input;
- this.stateKey = typeof input === 'string' ? input : undefined; // Saved state is not tracked for numeric index inputs
-
- this._refs = {};
- this._refsByChan = {};
-
- this._loadAllStates();
-
- this.initialDevice = this._startDeviceListener();
- }
-
- createCC(cc, chan) {
- const lookupMap = chan === undefined ? this._refs : this._refsByChan[chan];
- if (!(cc in lookupMap)) {
- const initialState = this._loadState(chan);
- lookupMap[cc] = initialState[cc] || 0;
- }
-
- return ref(() => lookupMap[cc]);
- }
-
- _startDeviceListener() {
- const initialDevice = getDevice(this.input, WebMidi.inputs);
-
- // Background connection loop
- (async () => {
- const midiListener = this._onMidiMessage.bind(this);
- let device = initialDevice;
-
- while (true) {
- if (!device) {
- device = await this._waitForDevice();
- }
-
- // Wait a bit for device to be ready to receive last state
- await new Promise((resolve) => setTimeout(resolve, 2000));
-
- try {
- // Still continue if sending did not work
- this._sendAllStates(device);
- } catch (err) {
- console.error('midiin: failed to send last state on connect:', device.name, err);
- }
-
- // Listen for incoming MIDI messages and for disconnection
- device.addListener('midimessage', midiListener);
-
- await this._waitForDeviceDisconnect(device);
-
- device.removeListener('midimessage', midiListener);
- device = null; // Clear var to trigger wait for connection
- }
- })();
-
- return initialDevice;
- }
-
- _waitForDevice() {
- return new Promise((resolve) => {
- const connListener = () => {
- const device = getDevice(this.input, WebMidi.inputs);
- if (device) {
- logger(`[midi] device reconnected: ${device.name}`);
-
- WebMidi.removeListener('connected', connListener);
- resolve(device);
- }
- };
-
- WebMidi.addListener('connected', connListener);
- });
- }
-
- _waitForDeviceDisconnect(device) {
- return new Promise((resolve) => {
- const disconnListener = (e) => {
- if (e.port.name === device.name) {
- logger(`[midi] device disconnected: ${device.name}`);
-
- WebMidi.removeListener('disconnected', disconnListener);
- resolve();
- }
- };
-
- WebMidi.addListener('disconnected', disconnListener);
- });
- }
-
- _onMidiMessage(e) {
- const ccNum = e.dataBytes[0];
- const v = e.dataBytes[1];
- const chan = e.message.channel;
- const scaled = v / 127;
-
- this._refs[ccNum] = scaled;
- this._refsByChan[ccNum] ??= {};
- this._refsByChan[ccNum][chan] = scaled;
-
- this._saveState(undefined, ccNum, scaled);
- this._saveState(chan, ccNum, scaled);
- }
-
- _loadAllStates() {
- Object.assign(this._refs, this._loadState(undefined));
-
- for (let chan = 1; chan <= 16; chan++) {
- this._refsByChan[chan] ??= {};
- Object.assign(this._refsByChan[chan], this._loadState(chan));
- }
- }
-
- _loadState(chan) {
- if (!this.stateKey) {
- return {};
- }
-
- const initialDataRaw = localStorage.getItem(
- `strudel-midin-${this.stateKey}-chan${chan !== undefined ? chan : 'all'}`,
- );
- if (!initialDataRaw) {
- return {};
- }
-
- try {
- return JSON.parse(initialDataRaw);
- } catch (err) {
- console.warn(
- `Failed to parse MIDI state from localStorage for input "${this.stateKey}" and channel "${chan}"`,
- initialDataRaw,
- err,
- );
- return {};
- }
- }
-
- _saveState(chan, cc, value) {
- if (!this.stateKey) {
- return;
- }
-
- const state = this._loadState(chan);
- state[cc] = value;
- localStorage.setItem(
- `strudel-midin-${this.stateKey}-chan${chan !== undefined ? chan : 'all'}`,
- JSON.stringify(state),
- );
- }
-
- _sendAllStates(device) {
- const output = WebMidi.outputs.find((o) => o.name === device.name);
- if (!output) {
- return;
- }
-
- for (const [chan, refs] of Object.entries(this._refsByChan)) {
- const channel = Number(chan);
- for (const [cc, value] of Object.entries(refs)) {
- const ccn = Number(cc);
- const scaled = Math.round(value * 127);
- output.sendControlChange(ccn, scaled, channel);
- }
- }
- }
-}
+/*
+input.mjs - MIDI input wrapper
+Copyright (C) 2022 Strudel contributors - see
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .
+*/
+
+import { WebMidi } from 'webmidi';
+import { logger, ref } from '@strudel/core';
+import { getDevice } from './util.mjs';
+
+export class MidiInput {
+ /**
+ *
+ * @param {string | number} input MIDI device name or index defaulting to 0
+ */
+ constructor(input) {
+ this.input = input;
+ this.stateKey = typeof input === 'string' ? input : undefined; // Saved state is not tracked for numeric index inputs
+
+ this._refs = {};
+ this._refsByChan = {};
+
+ this._loadAllStates();
+
+ this.initialDevice = this._startDeviceListener();
+ }
+
+ createCC(cc, chan) {
+ const lookupMap = chan === undefined ? this._refs : this._refsByChan[chan];
+ if (!(cc in lookupMap)) {
+ const initialState = this._loadState(chan);
+ lookupMap[cc] = initialState[cc] || 0;
+ }
+
+ return ref(() => lookupMap[cc]);
+ }
+
+ _startDeviceListener() {
+ const initialDevice = getDevice(this.input, WebMidi.inputs);
+
+ // Background connection loop
+ (async () => {
+ const midiListener = this._onMidiMessage.bind(this);
+ let device = initialDevice;
+
+ while (true) {
+ if (!device) {
+ device = await this._waitForDevice();
+ }
+
+ // Wait a bit for device to be ready to receive last state
+ await new Promise((resolve) => setTimeout(resolve, 2000));
+
+ try {
+ // Still continue if sending did not work
+ this._sendAllStates(device);
+ } catch (err) {
+ console.error('midiin: failed to send last state on connect:', device.name, err);
+ }
+
+ // Listen for incoming MIDI messages and for disconnection
+ device.addListener('midimessage', midiListener);
+
+ await this._waitForDeviceDisconnect(device);
+
+ device.removeListener('midimessage', midiListener);
+ device = null; // Clear var to trigger wait for connection
+ }
+ })();
+
+ return initialDevice;
+ }
+
+ _waitForDevice() {
+ return new Promise((resolve) => {
+ const connListener = () => {
+ const device = getDevice(this.input, WebMidi.inputs);
+ if (device) {
+ logger(`[midi] device reconnected: ${device.name}`);
+
+ WebMidi.removeListener('connected', connListener);
+ resolve(device);
+ }
+ };
+
+ WebMidi.addListener('connected', connListener);
+ });
+ }
+
+ _waitForDeviceDisconnect(device) {
+ return new Promise((resolve) => {
+ const disconnListener = (e) => {
+ if (e.port.name === device.name) {
+ logger(`[midi] device disconnected: ${device.name}`);
+
+ WebMidi.removeListener('disconnected', disconnListener);
+ resolve();
+ }
+ };
+
+ WebMidi.addListener('disconnected', disconnListener);
+ });
+ }
+
+ _onMidiMessage(e) {
+ const ccNum = e.dataBytes[0];
+ const v = e.dataBytes[1];
+ const chan = e.message.channel;
+ const scaled = v / 127;
+
+ this._refs[ccNum] = scaled;
+ this._refsByChan[ccNum] ??= {};
+ this._refsByChan[ccNum][chan] = scaled;
+
+ this._saveState(undefined, ccNum, scaled);
+ this._saveState(chan, ccNum, scaled);
+ }
+
+ _loadAllStates() {
+ Object.assign(this._refs, this._loadState(undefined));
+
+ for (let chan = 1; chan <= 16; chan++) {
+ this._refsByChan[chan] ??= {};
+ Object.assign(this._refsByChan[chan], this._loadState(chan));
+ }
+ }
+
+ _loadState(chan) {
+ if (!this.stateKey) {
+ return {};
+ }
+
+ const initialDataRaw = localStorage.getItem(
+ `strudel-midin-${this.stateKey}-chan${chan !== undefined ? chan : 'all'}`,
+ );
+ if (!initialDataRaw) {
+ return {};
+ }
+
+ try {
+ return JSON.parse(initialDataRaw);
+ } catch (err) {
+ console.warn(
+ `Failed to parse MIDI state from localStorage for input "${this.stateKey}" and channel "${chan}"`,
+ initialDataRaw,
+ err,
+ );
+ return {};
+ }
+ }
+
+ _saveState(chan, cc, value) {
+ if (!this.stateKey) {
+ return;
+ }
+
+ const state = this._loadState(chan);
+ state[cc] = value;
+ localStorage.setItem(
+ `strudel-midin-${this.stateKey}-chan${chan !== undefined ? chan : 'all'}`,
+ JSON.stringify(state),
+ );
+ }
+
+ _sendAllStates(device) {
+ const output = WebMidi.outputs.find((o) => o.name === device.name);
+ if (!output) {
+ return;
+ }
+
+ for (const [chan, refs] of Object.entries(this._refsByChan)) {
+ const channel = Number(chan);
+ for (const [cc, value] of Object.entries(refs)) {
+ const ccn = Number(cc);
+ const scaled = Math.round(value * 127);
+ output.sendControlChange(ccn, scaled, channel);
+ }
+ }
+ }
+}
diff --git a/packages/midi/util.mjs b/packages/midi/util.mjs
index 99158e68a..f02f1f64e 100644
--- a/packages/midi/util.mjs
+++ b/packages/midi/util.mjs
@@ -1,44 +1,44 @@
-/*
-util.mjs - MIDI utility functions
-Copyright (C) 2022 Strudel contributors - see
-This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .
-*/
-
-import { Input, Output } from 'webmidi';
-
-/**
- * Get a string listing device names for error messages.
- * @param {Input[] | Output[]} devices
- * @returns {string}
- */
-export function getMidiDeviceNamesString(devices) {
- return devices.map((o) => `'${o.name}'`).join(' | ');
-}
-
-/**
- * Look up a device by index or name. Otherwise return a default device, or fail if none are connected.
- *
- * @param {string | number} indexOrName
- * @param {Input[] | Output[]} devices
- * @returns {Input | Output | undefined}
- */
-export function getDevice(indexOrName, devices) {
- if (typeof indexOrName === 'number') {
- return devices[indexOrName];
- }
- const byName = (name) => devices.find((output) => output.name.includes(name));
- if (typeof indexOrName === 'string') {
- return byName(indexOrName);
- }
- // attempt to default to first IAC device if none is specified
- const IACOutput = byName('IAC');
- const device = IACOutput ?? devices[0];
- if (!device) {
- if (!devices.length) {
- throw new Error(`🔌 No MIDI devices found. Connect a device or enable IAC Driver.`);
- }
- throw new Error(`🔌 Default MIDI device not found. Use one of ${getMidiDeviceNamesString(devices)}`);
- }
-
- return device;
-}
+/*
+util.mjs - MIDI utility functions
+Copyright (C) 2022 Strudel contributors - see
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .
+*/
+
+import { Input, Output } from 'webmidi';
+
+/**
+ * Get a string listing device names for error messages.
+ * @param {Input[] | Output[]} devices
+ * @returns {string}
+ */
+export function getMidiDeviceNamesString(devices) {
+ return devices.map((o) => `'${o.name}'`).join(' | ');
+}
+
+/**
+ * Look up a device by index or name. Otherwise return a default device, or fail if none are connected.
+ *
+ * @param {string | number} indexOrName
+ * @param {Input[] | Output[]} devices
+ * @returns {Input | Output | undefined}
+ */
+export function getDevice(indexOrName, devices) {
+ if (typeof indexOrName === 'number') {
+ return devices[indexOrName];
+ }
+ const byName = (name) => devices.find((output) => output.name.includes(name));
+ if (typeof indexOrName === 'string') {
+ return byName(indexOrName);
+ }
+ // attempt to default to first IAC device if none is specified
+ const IACOutput = byName('IAC');
+ const device = IACOutput ?? devices[0];
+ if (!device) {
+ if (!devices.length) {
+ throw new Error(`🔌 No MIDI devices found. Connect a device or enable IAC Driver.`);
+ }
+ throw new Error(`🔌 Default MIDI device not found. Use one of ${getMidiDeviceNamesString(devices)}`);
+ }
+
+ return device;
+}
From bc9e97b9ac2473095d6b807297f530269b512ae8 Mon Sep 17 00:00:00 2001
From: Nick Matantsev
Date: Thu, 15 Jan 2026 00:13:49 -0500
Subject: [PATCH 306/476] Add comments
---
packages/midi/input.mjs | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/packages/midi/input.mjs b/packages/midi/input.mjs
index 498e6fe21..b9f07581a 100644
--- a/packages/midi/input.mjs
+++ b/packages/midi/input.mjs
@@ -8,6 +8,11 @@ import { WebMidi } from 'webmidi';
import { logger, ref } from '@strudel/core';
import { getDevice } from './util.mjs';
+/**
+ * MIDI input device wrapper that manages connection and reconnection, tracks
+ * persisted CC states, etc. These instances are long-lived and are maintained as singletons
+ * (keyed globally by input string/number).
+ */
export class MidiInput {
/**
*
@@ -25,6 +30,11 @@ export class MidiInput {
this.initialDevice = this._startDeviceListener();
}
+ /**
+ * Implementation for the cc() factory function tied to this specific input.
+ * @param {number} cc MIDI CC number
+ * @param {number | undefined} chan MIDI channel (1-16) or undefined for all channels
+ */
createCC(cc, chan) {
const lookupMap = chan === undefined ? this._refs : this._refsByChan[chan];
if (!(cc in lookupMap)) {
@@ -71,6 +81,7 @@ export class MidiInput {
return initialDevice;
}
+ // Returns a promise that resolves when the specified device is connected
_waitForDevice() {
return new Promise((resolve) => {
const connListener = () => {
@@ -87,6 +98,7 @@ export class MidiInput {
});
}
+ // Returns a promise that resolves when the specified device is disconnected
_waitForDeviceDisconnect(device) {
return new Promise((resolve) => {
const disconnListener = (e) => {
@@ -162,6 +174,7 @@ export class MidiInput {
);
}
+ // Send CC values back to device to restore encoders and motorized sliders
_sendAllStates(device) {
const output = WebMidi.outputs.find((o) => o.name === device.name);
if (!output) {
From 60e5682829848dcc65a3073c9e0fb0eb46a08183 Mon Sep 17 00:00:00 2001
From: jeromew
Date: Thu, 15 Jan 2026 15:42:34 +0000
Subject: [PATCH 307/476] Update kabelsalat dependency
---
packages/core/package.json | 2 +-
packages/superdough/package.json | 2 +-
pnpm-lock.yaml | 36 ++++++++++++++++----------------
3 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/packages/core/package.json b/packages/core/package.json
index 64253b081..abb54e9ce 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -31,7 +31,7 @@
},
"homepage": "https://strudel.cc",
"dependencies": {
- "@kabelsalat/web": "^0.4.0",
+ "@kabelsalat/web": "^0.4.1",
"fraction.js": "^5.2.1"
},
"gitHead": "0e26d4e741500f5bae35b023608f062a794905c2",
diff --git a/packages/superdough/package.json b/packages/superdough/package.json
index 2125b8d98..78db8338e 100644
--- a/packages/superdough/package.json
+++ b/packages/superdough/package.json
@@ -36,7 +36,7 @@
"vite-plugin-bundle-audioworklet": "workspace:*"
},
"dependencies": {
- "@kabelsalat/lib": "^0.4.0",
+ "@kabelsalat/lib": "^0.4.1",
"nanostores": "^0.11.3"
},
"engines": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2684ce3bb..53437f8f5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -41,7 +41,7 @@ importers:
version: 2.2.7
'@vitest/coverage-v8':
specifier: 3.0.4
- version: 3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.10.10)(@vitest/ui@3.0.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0))
+ version: 3.0.4(vitest@3.0.4)
'@vitest/ui':
specifier: ^3.0.4
version: 3.0.4(vitest@3.0.4)
@@ -235,8 +235,8 @@ importers:
packages/core:
dependencies:
'@kabelsalat/web':
- specifier: ^0.4.0
- version: 0.4.0
+ specifier: ^0.4.1
+ version: 0.4.1
fraction.js:
specifier: ^5.2.1
version: 5.2.1
@@ -522,8 +522,8 @@ importers:
packages/superdough:
dependencies:
'@kabelsalat/lib':
- specifier: ^0.4.0
- version: 0.4.0
+ specifier: ^0.4.1
+ version: 0.4.1
nanostores:
specifier: ^0.11.3
version: 0.11.3
@@ -1975,14 +1975,14 @@ packages:
resolution: {integrity: sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==}
engines: {node: '>=v12.0.0'}
- '@kabelsalat/core@0.3.1':
- resolution: {integrity: sha512-y2wHZyKnwbhJdGuwXvkaIb5vqbNTW6rMDnBslHGxQHTFX5xYyxJLOcuF2/EOB698t09kOVhmmpLXKbyokf3pOA==}
+ '@kabelsalat/core@0.4.0':
+ resolution: {integrity: sha512-5zV8nh8HffW8aexObXs5pE0xgL0jb1cHc3o8UN6AvK0mBt87fjZvW65E4rMslHyq+OuCscoBJW7B3MbYfWrwMQ==}
- '@kabelsalat/lib@0.4.0':
- resolution: {integrity: sha512-UoOUhYOFShDjYCTne1edevCHHxSC07FsxG9tQ5GGOOzNoKMUpGVY8Ecq9X1GVyseQFvQBgz3aqAC6K8FPZp4ZQ==}
+ '@kabelsalat/lib@0.4.1':
+ resolution: {integrity: sha512-gBCjrZKD9huTKNJuBC6BXM4PMQSg8otL8A/vp8j98P9v6yWTX1TuyaqdLg/1PrIAMV4hlWoav9ZD3YMFlrvouw==}
- '@kabelsalat/web@0.4.0':
- resolution: {integrity: sha512-uvcOJjpKf8PG6KrgY0QEpoV4IAbIPDXh73bPtFSdDcXApbkSyEEyeNE8IoqIlqfcjIX926IOCAx9nM6FsFp6DA==}
+ '@kabelsalat/web@0.4.1':
+ resolution: {integrity: sha512-ASkFhePJLx3GjadYOueI7sHKXBbRPk/a1pfslFeQNI9gU7yZq/KrnkmOmLrgrtixAsy7gyi1vWqkmRRvH3Ki6w==}
'@lerna/create@8.1.9':
resolution: {integrity: sha512-DPnl5lPX4v49eVxEbJnAizrpMdMTBz1qykZrAbBul9rfgk531v8oAt+Pm6O/rpAleRombNM7FJb5rYGzBJatOQ==}
@@ -9276,16 +9276,16 @@ snapshots:
dependencies:
lodash: 4.17.21
- '@kabelsalat/core@0.3.1': {}
+ '@kabelsalat/core@0.4.0': {}
- '@kabelsalat/lib@0.4.0':
+ '@kabelsalat/lib@0.4.1':
dependencies:
- '@kabelsalat/core': 0.3.1
+ '@kabelsalat/core': 0.4.0
- '@kabelsalat/web@0.4.0':
+ '@kabelsalat/web@0.4.1':
dependencies:
- '@kabelsalat/core': 0.3.1
- '@kabelsalat/lib': 0.4.0
+ '@kabelsalat/core': 0.4.0
+ '@kabelsalat/lib': 0.4.1
'@lerna/create@8.1.9(encoding@0.1.13)(typescript@5.7.3)':
dependencies:
@@ -10580,7 +10580,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@vitest/coverage-v8@3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.10.10)(@vitest/ui@3.0.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0))':
+ '@vitest/coverage-v8@3.0.4(vitest@3.0.4)':
dependencies:
'@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 1.0.2
From 2e7ec9ea272b368e4c9b4fe98990d0e662c0f57a Mon Sep 17 00:00:00 2001
From: Dsm0
Date: Thu, 15 Jan 2026 19:27:54 -0800
Subject: [PATCH 308/476] variable declarations with active patterns now have
highlighting
---
packages/core/repl.mjs | 56 +++++++++++++++++++++++++++++++++---------
1 file changed, 44 insertions(+), 12 deletions(-)
diff --git a/packages/core/repl.mjs b/packages/core/repl.mjs
index e3efdd3e5..09c76d607 100644
--- a/packages/core/repl.mjs
+++ b/packages/core/repl.mjs
@@ -126,7 +126,23 @@ export function repl({
);
}
- // Helper function to handle single label code block storage
+ // helper
+ function cleanupConflictingRanges(codeBlocks, currentKey, newRange) {
+ for (const [existingKey, existingBlock] of Object.entries(codeBlocks)) {
+ if (existingKey === currentKey) continue;
+ if (!existingBlock.range) continue;
+
+ const [existingStart, existingEnd] = existingBlock.range;
+ const [newStart, newEnd] = newRange;
+
+ // If ranges overlap (not just touch), remove the stale block
+ if (!(newEnd <= existingStart || newStart >= existingEnd)) {
+ delete codeBlocks[existingKey];
+ }
+ }
+ }
+
+ // helper
function handleSingleLabelBlock(label, code, options, meta) {
// Detect if this block contains a non-inline widget
// The activeVisualizer is now provided by the transpiler for all labels
@@ -147,18 +163,30 @@ export function repl({
activeVisualizer: activeVisualizer, // Store the widget type if present, null otherwise
};
- // Clean up any blocks with conflicting ranges
- for (const [existingKey, existingBlock] of Object.entries(codeBlocks)) {
- if (existingKey !== label.name && existingBlock.range && options.range) {
- const [existingStart, existingEnd] = existingBlock.range;
- const [newStart, newEnd] = options.range;
+ // Clean up any blocks with conflicting ranges (including declaration blocks)
+ cleanupConflictingRanges(codeBlocks, label.name, options.range);
+ }
- // If ranges overlap (not just touch), remove the stale block
- if (!(newEnd <= existingStart || newStart >= existingEnd)) {
- delete codeBlocks[existingKey];
- }
- }
- }
+ // helper
+ // These blocks return silence but may contain mini notation strings that need highlighting
+ function handleDeclarationBlock(code, options, meta) {
+ const range = options.range || [];
+ if (range.length < 2) return;
+
+ const blockKey = `_decl:${range[0]}:${range[1]}`;
+
+ codeBlocks[blockKey] = {
+ code: code,
+ range: range,
+ labels: [],
+ miniLocations: meta?.miniLocations || [],
+ widgets: meta?.widgets || [],
+ sliders: meta?.sliders || [],
+ activeVisualizer: null,
+ };
+
+ // Clean up any overlapping declaration blocks
+ cleanupConflictingRanges(codeBlocks, blockKey, range);
}
const hush = function () {
@@ -443,6 +471,10 @@ export function repl({
throw new Error(
'anonymous labels disabled for block based evaluation (see https://strudel.cc/blog/#label-notation)',
);
+ } else {
+ // Declaration block (variable/function that returns silence)
+ // Store it so its miniLocations are preserved for highlighting patterns stored in variables
+ handleDeclarationBlock(code, options, meta);
}
meta.miniLocations = collectFromBlocks('miniLocations');
From ae9638c3534635e48d9671ef018a297f8ffcd11c Mon Sep 17 00:00:00 2001
From: Felix Roos
Date: Fri, 16 Jan 2026 09:58:14 +0100
Subject: [PATCH 309/476] update changelog + fix script to not miss entries
---
CHANGELOG.md | 961 ++++++++++++++++++++++++++++++++++++++++++++++++++-
warm.js | 40 ++-
2 files changed, 977 insertions(+), 24 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 19a502f33..3daf4e6cf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,8 +4,20 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
## january 2026
+
+- 2026-01-15T16:59:14+01:00 mondo fix: add registered functions to scope automatically by daslyfe in: [#1896](https://codeberg.org/uzu/strudel/pulls/1896)
+- 2026-01-15T16:58:14+01:00 Added docs for pattern search by JohnBjrk in: [#1905](https://codeberg.org/uzu/strudel/pulls/1905)
+- 2026-01-15T16:57:19+01:00 Update kabelsalat dependency by jeromew in: [#1911](https://codeberg.org/uzu/strudel/pulls/1911)
+- 2026-01-15T00:24:39+01:00 Bug Fix: Set pooled values immediately instead of scheduling by glossing in: [#1907](https://codeberg.org/uzu/strudel/pulls/1907)
+- 2026-01-14T20:29:16+01:00 Feat: Kabelsalat integration by glossing in: [#1876](https://codeberg.org/uzu/strudel/pulls/1876)
+- 2026-01-14T19:07:49+01:00 Feat: MIDI Keyboard 🎹🐈 by glossing in: [#1828](https://codeberg.org/uzu/strudel/pulls/1828)
+- 2026-01-14T18:14:52+01:00 Bug Fix: Fix race condition between worklet termination and port messages by glossing in: [#1897](https://codeberg.org/uzu/strudel/pulls/1897)
+- 2026-01-13T04:06:52+01:00 Add search/filter in patterns tab by JohnBjrk in: [#1842](https://codeberg.org/uzu/strudel/pulls/1842)
+- 2026-01-13T00:18:10+01:00 Add shortcut for navigating through labels! by daslyfe in: [#1807](https://codeberg.org/uzu/strudel/pulls/1807)
+- 2026-01-12T00:17:37+01:00 add warm.strudel.cc to faq by yaxu in: [#1891](https://codeberg.org/uzu/strudel/pulls/1891)
- 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-11T13:19:46+01:00 New page FAQ in "More" by scrappy_fiddler in: [#1753](https://codeberg.org/uzu/strudel/pulls/1753)
- 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)
@@ -14,8 +26,8 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
- 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-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-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)
@@ -32,23 +44,32 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
## 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-29T20:54:11+01:00 Feature: LFOs and Envelopes by glossing in: [#1507](https://codeberg.org/uzu/strudel/pulls/1507)
- 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-28T14:20:03+01:00 dough repl fixes by froos in: [#1855](https://codeberg.org/uzu/strudel/pulls/1855)
+- 2025-12-28T13:40:29+01:00 add basic dough repl by froos in: [#1749](https://codeberg.org/uzu/strudel/pulls/1749)
- 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-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-19T01:03:53+01:00 [perf] Add audiograph `await debugAudiograph()` feature by jeromew in: [#1763](https://codeberg.org/uzu/strudel/pulls/1763)
+- 2025-12-19T00:45:41+01:00 Feature: non-realtime exporting by Ghost in: [#1674](https://codeberg.org/uzu/strudel/pulls/1674)
+- 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-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-14T01:07:36+01:00 Improved randomness by glossing in: [#1505](https://codeberg.org/uzu/strudel/pulls/1505)
- 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-11T18:00:49+01:00 Feature: stateful timeline function for jumping between timelines by yaxu in: [#1669](https://codeberg.org/uzu/strudel/pulls/1669)
- 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-07T21:51:40+01:00 Feat: Add channel support to midi in by glossing in: [#1775](https://codeberg.org/uzu/strudel/pulls/1775)
+- 2025-12-07T21:23:43+01:00 Feat: Transient shaper by glossing in: [#1777](https://codeberg.org/uzu/strudel/pulls/1777)
- 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-03T18:27:28+01:00 Feature: Eight FMs by glossing in: [#1628](https://codeberg.org/uzu/strudel/pulls/1628)
+- 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
@@ -57,6 +78,7 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
- 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:47:03+01:00 fix(tool/dbpatch): add missing package name by peterpf in: [#1765](https://codeberg.org/uzu/strudel/pulls/1765)
- 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)
@@ -73,6 +95,7 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
- 2025-11-23T09:47:24+01:00 Fix interoperability issue between `all` and `await initHydra()` by jeromew in: [#1663](https://codeberg.org/uzu/strudel/pulls/1663)
- 2025-11-23T04:23:06+01:00 Bug fix: Swap l/r gains with temp variable by glossing in: [#1768](https://codeberg.org/uzu/strudel/pulls/1768)
- 2025-11-23T00:52:28+01:00 FIX: prevent LFO filter modulation from popping from negative values by daslyfe in: [#1767](https://codeberg.org/uzu/strudel/pulls/1767)
+- 2025-11-23T00:03:32+01:00 prefix "S" for solo by froos in: [#1481](https://codeberg.org/uzu/strudel/pulls/1481)
- 2025-11-21T01:56:11+01:00 Bug Fix: Use frac due to negative frequencies from FM by glossing in: [#1759](https://codeberg.org/uzu/strudel/pulls/1759)
- 2025-11-20T19:48:16+01:00 [perf] fix `connect-leak` added by #1742 when noise() is not used by jeromew in: [#1757](https://codeberg.org/uzu/strudel/pulls/1757)
- 2025-11-20T14:51:00+01:00 [perf] fix `connect-leak` in `delay` effect by jeromew in: [#1755](https://codeberg.org/uzu/strudel/pulls/1755)
@@ -80,6 +103,7 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
- 2025-11-18T23:52:45+01:00 wchooseCycles has now notes in an example by scrappy_fiddler in: [#1748](https://codeberg.org/uzu/strudel/pulls/1748)
- 2025-11-17T05:31:54+01:00 Feature: Partials by glossing in: [#1659](https://codeberg.org/uzu/strudel/pulls/1659)
- 2025-11-16T22:06:14+01:00 README: update superdough documentation by TristanMlct in: [#1741](https://codeberg.org/uzu/strudel/pulls/1741)
+- 2025-11-16T22:00:43+01:00 Feature: Envelope worklet by glossing in: [#1524](https://codeberg.org/uzu/strudel/pulls/1524)
- 2025-11-16T21:08:54+01:00 Worklet optimizations by glossing in: [#1730](https://codeberg.org/uzu/strudel/pulls/1730)
- 2025-11-15T14:59:30+01:00 [perf] disconnect Offline AudioNode connections in generateReverb by jeromew in: [#1740](https://codeberg.org/uzu/strudel/pulls/1740)
- 2025-11-15T14:57:47+01:00 [perf] disconnect `send` effect AudioNode when `room` is used by jeromew in: [#1736](https://codeberg.org/uzu/strudel/pulls/1736)
@@ -88,15 +112,15 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
- 2025-11-12T21:06:13+01:00 Fix web README sample code by Kissaki in: [#1725](https://codeberg.org/uzu/strudel/pulls/1725)
- 2025-11-12T20:59:39+01:00 Fix typo: 'studel' -> 'strudel' by drhayes in: [#1726](https://codeberg.org/uzu/strudel/pulls/1726)
- 2025-11-12T15:23:41+01:00 fix for node 24 support in tests - #1718 by ausav in: [#1719](https://codeberg.org/uzu/strudel/pulls/1719)
-- 2025-11-11T09:00:49+01:00 soundAlias example fix by PepsiiMan in: [#1720](https://codeberg.org/uzu/strudel/pulls/1720)
+- 2025-11-11T09:00:49+01:00 soundAlias example fix by PepsiiMan in: [#1720](https://codeberg.org/uzu/strudel/pulls/1720)
- 2025-11-10T08:18:36+01:00 fix: Make Supradough package build by munshkr in: [#1711](https://codeberg.org/uzu/strudel/pulls/1711)
- 2025-11-10T08:18:00+01:00 added docs for spaces in scale names by ondras in: [#1715](https://codeberg.org/uzu/strudel/pulls/1715)
-- 2025-11-10T02:44:01+01:00 Feature: LFOs for Filters by glossing in: [#1636](https://codeberg.org/uzu/strudel/pulls/1636)
+- 2025-11-10T02:44:01+01:00 Feature: LFOs for Filters by glossing in: [#1636](https://codeberg.org/uzu/strudel/pulls/1636)
- 2025-11-05T17:07:00+01:00 improvement: sync midi messages to audio context clock by daslyfe in: [#1708](https://codeberg.org/uzu/strudel/pulls/1708)
- 2025-11-04T19:36:14+01:00 Add stick button mappings to gamepad implementation and improve docs by kaosuryoko in: [#1696](https://codeberg.org/uzu/strudel/pulls/1696)
- 2025-11-04T19:29:35+01:00 Refactor sound stopping and triggering logic in SoundsTab component by IJOL in: [#1688](https://codeberg.org/uzu/strudel/pulls/1688)
- 2025-11-04T19:13:21+01:00 Add setting to toggle pattern auto-start on pattern change by moumar in: [#1690](https://codeberg.org/uzu/strudel/pulls/1690)
-- 2025-11-04T18:58:50+01:00 Voicings JSDoc by sharkeys_lunchbox in: [#1686](https://codeberg.org/uzu/strudel/pulls/1686)
+- 2025-11-04T18:58:50+01:00 Voicings JSDoc by sharkeys_lunchbox in: [#1686](https://codeberg.org/uzu/strudel/pulls/1686)
- 2025-11-01T07:50:40+01:00 FIX: Loading local samples uses too much memory by daslyfe in: [#1706](https://codeberg.org/uzu/strudel/pulls/1706)
@@ -104,7 +128,7 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
- 2025-10-28T22:58:24+01:00 Bug Fix: Handle scale-for-notes when n also supplied by glossing in: [#1625](https://codeberg.org/uzu/strudel/pulls/1625)
- 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-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)
@@ -114,30 +138,943 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
- 2025-10-22T22:15:19+02:00 Fix sampler.mjs githubPath by jeromew in: [#1684](https://codeberg.org/uzu/strudel/pulls/1684)
- 2025-10-22T16:20:50+02:00 Fix onPaint for widgets by yaxu in: [#1658](https://codeberg.org/uzu/strudel/pulls/1658)
- 2025-10-22T15:19:12+02:00 Fix a bug introduced by #4e17cfbdd6 by milliganf in: [#1679](https://codeberg.org/uzu/strudel/pulls/1679)
+- 2025-10-20T22:37:15+02:00 feature/autocomplete-sound-names by drdozer in: [#1564](https://codeberg.org/uzu/strudel/pulls/1564)
+- 2025-10-20T21:58:12+02:00 add replicate + use it for ! in mondo by JoStro in: [#1436](https://codeberg.org/uzu/strudel/pulls/1436)
- 2025-10-18T04:29:20+02:00 Bug Fix: Wavetable: phase wrapping at 1 and detune by glossing in: [#1620](https://codeberg.org/uzu/strudel/pulls/1620)
- 2025-10-16T20:26:28+02:00 github samples: default to "samples" if repository is not specified by prezmop in: [#1644](https://codeberg.org/uzu/strudel/pulls/1644)
- 2025-10-16T17:33:39+02:00 Docs: add example of custom chained function by dariusk in: [#1642](https://codeberg.org/uzu/strudel/pulls/1642)
- 2025-10-14T12:39:48+02:00 textbox by yaxu in: [#1650](https://codeberg.org/uzu/strudel/pulls/1650)
+- 2025-10-13T07:26:51+02:00 Feature: Distortion Modes by glossing in: [#1561](https://codeberg.org/uzu/strudel/pulls/1561)
- 2025-10-13T07:05:57+02:00 Feature: Wavetable FM by glossing in: [#1623](https://codeberg.org/uzu/strudel/pulls/1623)
-- 2025-10-12T20:43:42+02:00 fix: repair REPL sample sources and URL concat (#1640) by erikfox in: [#1646](https://codeberg.org/uzu/strudel/pulls/1646)
+- 2025-10-12T20:43:42+02:00 fix: repair REPL sample sources and URL concat (#1640) by erikfox in: [#1646](https://codeberg.org/uzu/strudel/pulls/1646)
- 2025-10-10T11:25:02+02:00 Add control-metadata by yaxu in: [#1634](https://codeberg.org/uzu/strudel/pulls/1634)
- 2025-10-07T22:59:39+02:00 Fix MQTT: change the trigger handler to match new hap by jurrchen in: [#1629](https://codeberg.org/uzu/strudel/pulls/1629)
- 2025-10-05T21:42:19+02:00 Fix case sensitivity for synonym search by vvolhejn in: [#1618](https://codeberg.org/uzu/strudel/pulls/1618)
- 2025-10-01T08:56:35+02:00 Optimize wavetable synth by glossing in: [#1613](https://codeberg.org/uzu/strudel/pulls/1613)
- 2025-10-01T02:02:33+02:00 fix: pattern switching by daslyfe in: [#1616](https://codeberg.org/uzu/strudel/pulls/1616)
-## September 2025
+## september 2025
- 2025-09-29T02:10:54+02:00 fix wavetable JSON by daslyfe in: [#1611](https://codeberg.org/uzu/strudel/pulls/1611)
- 2025-09-28T21:28:16+02:00 rename wavetable controls to match existing naming conventions by daslyfe in: [#1610](https://codeberg.org/uzu/strudel/pulls/1610)
- 2025-09-27T23:28:13+02:00 Feature: Wavetable synth improvements by glossing in: [#1607](https://codeberg.org/uzu/strudel/pulls/1607)
- 2025-09-27T21:43:10+02:00 wavetable improvements by daslyfe in: [#1608](https://codeberg.org/uzu/strudel/pulls/1608)
- 2025-09-26T08:48:46+02:00 create orbit based DJ filter by daslyfe in: [#1603](https://codeberg.org/uzu/strudel/pulls/1603)
+- 2025-09-26T08:15:49+02:00 Feature: Wavetable synth by glossing in: [#1525](https://codeberg.org/uzu/strudel/pulls/1525)
- 2025-09-23T13:28:20+02:00 fix: time signal by daslyfe in: [#1583](https://codeberg.org/uzu/strudel/pulls/1583)
- 2025-09-21T16:16:06+02:00 mondo: fix all + setcpm + setcps by froos in: [#1600](https://codeberg.org/uzu/strudel/pulls/1600)
- 2025-09-19T21:59:43+02:00 fix: osc error message by froos in: [#1597](https://codeberg.org/uzu/strudel/pulls/1597)
- 2025-09-18T21:09:56+02:00 osc: --debug flag to see incoming messages by froos in: [#1595](https://codeberg.org/uzu/strudel/pulls/1595)
- 2025-09-17T14:12:10+02:00 simplify osc usage by froos in: [#1588](https://codeberg.org/uzu/strudel/pulls/1588)
- 2025-09-16T16:59:58+02:00 dev: logger errors to console in dev mode by daslyfe in: [#1585](https://codeberg.org/uzu/strudel/pulls/1585)
+- 2025-09-16T03:19:37+02:00 Bug Fix / Feature: Updates to `duck` to avoid clicks and allow configuration over release/attack by glossing in: [#1514](https://codeberg.org/uzu/strudel/pulls/1514)
+- 2025-09-15T23:36:31+02:00 Feat: Enhance `scale` function to quantize notes to a named scale by glossing in: [#1492](https://codeberg.org/uzu/strudel/pulls/1492)
- 2025-09-15T22:52:14+02:00 add tic80 font by froos in: [#1579](https://codeberg.org/uzu/strudel/pulls/1579)
-- 2025-09-15T00:00:19+02:00 supradough: fix delay + add some jsdoc types by froos in: [#1578](https://codeberg.org/uzu/strudel/pulls/1578)
\ No newline at end of file
+- 2025-09-15T00:00:19+02:00 supradough: fix delay + add some jsdoc types by froos in: [#1578](https://codeberg.org/uzu/strudel/pulls/1578)
+- 2025-09-14T12:42:58+02:00 added plyWith/plyWithClassic functions by Dsm0 in: [#1571](https://codeberg.org/uzu/strudel/pulls/1571)
+- 2025-09-14T10:39:12+02:00 feat: sound alias by Options in: [#1494](https://codeberg.org/uzu/strudel/pulls/1494)
+- 2025-09-14T01:20:15+02:00 Bug Fix: Allow penv values to be falsy by glossing in: [#1559](https://codeberg.org/uzu/strudel/pulls/1559)
+- 2025-09-14T01:10:48+02:00 Update website/src/pages/workshop/first-sounds.mdx by fesmith in: [#1566](https://codeberg.org/uzu/strudel/pulls/1566)
+- 2025-09-14T01:07:47+02:00 fix: autocomplete-styles + html rendering by froos in: [#1570](https://codeberg.org/uzu/strudel/pulls/1570)
+- 2025-09-14T00:49:17+02:00 Feature: Synonyms in autocomplete and reference by glossing in: [#1535](https://codeberg.org/uzu/strudel/pulls/1535)
+- 2025-09-13T20:01:48+02:00 Docs: add xen package examples by dudymas in: [#1446](https://codeberg.org/uzu/strudel/pulls/1446)
+- 2025-09-13T19:51:10+02:00 Update website/src/pages/learn/code.mdx by anecondev in: [#1391](https://codeberg.org/uzu/strudel/pulls/1391)
+- 2025-09-11T22:52:30+02:00 supradough poc by froos in: [#1362](https://codeberg.org/uzu/strudel/pulls/1362)
+- 2025-09-11T17:29:35+02:00 fix: exclude mondough dependencies by froos in: [#1563](https://codeberg.org/uzu/strudel/pulls/1563)
+- 2025-09-11T00:27:21+02:00 add basicSetup for keybindings by Dsm0 in: [#1462](https://codeberg.org/uzu/strudel/pulls/1462)
+- 2025-09-10T17:25:26+02:00 feat: add delete user samples button for convenience by daslyfe in: [#1556](https://codeberg.org/uzu/strudel/pulls/1556)
+- 2025-09-08T08:54:01+02:00 Fix formatting of REPL footnote by ddbeck in: [#1547](https://codeberg.org/uzu/strudel/pulls/1547)
+- 2025-09-08T05:38:08+02:00 fix: OSC by daslyfe in: [#1557](https://codeberg.org/uzu/strudel/pulls/1557)
+- 2025-09-07T22:47:13+02:00 Add examples for ? and | operators to documentation by james-collapse in: [#1532](https://codeberg.org/uzu/strudel/pulls/1532)
+- 2025-09-07T21:48:19+02:00 Signal flow documentation by glossing in: [#1504](https://codeberg.org/uzu/strudel/pulls/1504)
+- 2025-09-07T21:27:29+02:00 Allow flattening of dirs with sample server by glossing in: [#1529](https://codeberg.org/uzu/strudel/pulls/1529)
+- 2025-09-07T21:05:24+02:00 fix: prevent orbit clicking by defining max number of channels in an orbit by daslyfe in: [#1552](https://codeberg.org/uzu/strudel/pulls/1552)
+- 2025-09-02T08:42:42+02:00 Padding for tooltips, preserving linebreaks in descriptions, not closing autocompletes on click by glossing in: [#1521](https://codeberg.org/uzu/strudel/pulls/1521)
+- 2025-09-01T17:50:11+02:00 Update "restore defaults" to not delete patterns by glossing in: [#1519](https://codeberg.org/uzu/strudel/pulls/1519)
+
+## august 2025
+
+- 2025-08-31T19:10:04+02:00 feat: add the ability to control the speed and start time of the reverb IR by daslyfe in: [#1501](https://codeberg.org/uzu/strudel/pulls/1501)
+- 2025-08-25T02:31:22+02:00 Bug Fix: Duck on Mobile / Safari by glossing in: [#1503](https://codeberg.org/uzu/strudel/pulls/1503)
+- 2025-08-23T18:39:53+02:00 fix benchmarks by yaxu in: [#1517](https://codeberg.org/uzu/strudel/pulls/1517)
+- 2025-08-21T20:57:31+02:00 add --json flag to @strudel/sampler to generate a strudel.json by froos in: [#1513](https://codeberg.org/uzu/strudel/pulls/1513)
+- 2025-08-21T10:04:28+02:00 remove hs2js postinstall by froos in: [#1510](https://codeberg.org/uzu/strudel/pulls/1510)
+- 2025-08-20T15:15:34+02:00 doc: scrub, duckorbit, duckattack, duckdepth + fix: arp, arpWidth, hush by fyynn in: [#1502](https://codeberg.org/uzu/strudel/pulls/1502)
+- 2025-08-20T12:31:37+02:00 fix: repl autocomplete not rendering correctly by robase in: [#1480](https://codeberg.org/uzu/strudel/pulls/1480)
+- 2025-08-20T12:10:02+02:00 BUG FIX: make 'midin' initialization work with multiple controllers by cbabraham in: [#1469](https://codeberg.org/uzu/strudel/pulls/1469)
+- 2025-08-17T23:18:46+02:00 euclidish by yaxu in: [#1482](https://codeberg.org/uzu/strudel/pulls/1482)
+- 2025-08-17T06:37:23+02:00 feat: Create a duck (sidechain) orbit effect by daslyfe in: [#1470](https://codeberg.org/uzu/strudel/pulls/1470)
+- 2025-08-17T04:40:15+02:00 Bug Fix: Restore `log` functionality after onTrigger arg removal by glossing in: [#1491](https://codeberg.org/uzu/strudel/pulls/1491)
+- 2025-08-17T04:33:39+02:00 Bug Fix: Handle zero appearing first in FM's ADSR by glossing in: [#1496](https://codeberg.org/uzu/strudel/pulls/1496)
+- 2025-08-17T04:27:19+02:00 Bug Fix: FM (and vibrato) for Supersaws by glossing in: [#1495](https://codeberg.org/uzu/strudel/pulls/1495)
+- 2025-08-04T07:51:31+02:00 Fix incorrect stack Mini Notation by samyk in: [#1484](https://codeberg.org/uzu/strudel/pulls/1484)
+- 2025-08-03T18:57:45+02:00 fix: regression caused by incorrectly exported alias for transpose and scaleTranspose by daslyfe in: [#1489](https://codeberg.org/uzu/strudel/pulls/1489)
+- 2025-08-03T18:34:13+02:00 Add `strans` and `scaleTrans` as synonyms of `scaleTranspose` by TodePond in: [#1488](https://codeberg.org/uzu/strudel/pulls/1488)
+- 2025-08-02T18:18:28+02:00 Add `trans` alias for `transpose` by TodePond in: [#1487](https://codeberg.org/uzu/strudel/pulls/1487)
+- 2025-08-02T03:27:26+02:00 feat: Create Accurate 909 bass drum synthesizer by daslyfe in: [#1478](https://codeberg.org/uzu/strudel/pulls/1478)
+- 2025-08-02T03:23:49+02:00 feat: Add fmwave control and ability to fm with noise by daslyfe in: [#1472](https://codeberg.org/uzu/strudel/pulls/1472)
+
+## july 2025
+
+- 2025-07-30T00:22:41+02:00 hotfix: uzu kit JSON should be in the repo to avoid offline loading errors by daslyfe in: [#1485](https://codeberg.org/uzu/strudel/pulls/1485)
+- 2025-07-24T05:28:23+02:00 feat: make uzu-drumkit the default drumkit by daslyfe in: [#1422](https://codeberg.org/uzu/strudel/pulls/1422)
+- 2025-07-21T07:16:19+02:00 FIX: PWM modulation by daslyfe in: [#1467](https://codeberg.org/uzu/strudel/pulls/1467)
+- 2025-07-19T17:16:22+02:00 Tremolo modulation by Ghost in: [#1095](https://codeberg.org/uzu/strudel/pulls/1095)
+- 2025-07-15T09:39:33+02:00 fix: can now use def in mondough by froos in: [#1461](https://codeberg.org/uzu/strudel/pulls/1461)
+- 2025-07-11T11:10:24+02:00 fixed keybinding presedence issue by Dsm0 in: [#1456](https://codeberg.org/uzu/strudel/pulls/1456)
+- 2025-07-11T11:09:05+02:00 added multicursor support on ctrl/cmd + click by Dsm0 in: [#1457](https://codeberg.org/uzu/strudel/pulls/1457)
+- 2025-07-09T09:39:46+02:00 added tab-indent setting by Dsm0 in: [#1454](https://codeberg.org/uzu/strudel/pulls/1454)
+- 2025-07-08T15:48:41+02:00 ontrigger-refactoring by froos in: [#1442](https://codeberg.org/uzu/strudel/pulls/1442)
+- 2025-07-07T23:14:24+02:00 fix: remove first gm_synth_bass_1, as it doesn't work in safari by froos in: [#1452](https://codeberg.org/uzu/strudel/pulls/1452)
+- 2025-07-07T00:06:16+02:00 fix: minor doc changes by Aurel300 in: [#1435](https://codeberg.org/uzu/strudel/pulls/1435)
+- 2025-07-05T12:53:45+02:00 Fix randrun and deps including shuffle. Fixes #1441 by yaxu in: [#1447](https://codeberg.org/uzu/strudel/pulls/1447)
+- 2025-07-05T12:15:52+02:00 add setDefault + resetDefaults to superdough by froos in: [#1433](https://codeberg.org/uzu/strudel/pulls/1433)
+- 2025-07-04T22:36:19+02:00 disable fm for supersaw by froos in: [#1443](https://codeberg.org/uzu/strudel/pulls/1443)
+
+## june 2025
+
+- 2025-06-30T13:28:10+02:00 corrected minor spelling mistake (#1425) by tj-mueller in: [#1434](https://codeberg.org/uzu/strudel/pulls/1434)
+- 2025-06-30T05:26:11+02:00 Add browser cache explanation in samples.mdx by Ghost in: [#1369](https://codeberg.org/uzu/strudel/pulls/1369)
+- 2025-06-30T05:18:42+02:00 add-release-notes by froos in: [#1432](https://codeberg.org/uzu/strudel/pulls/1432)
+- 2025-06-28T20:30:49+02:00 feat: delaytime in cycles by Ghost in: [#1341](https://codeberg.org/uzu/strudel/pulls/1341)
+- 2025-06-28T13:44:49+02:00 Case insensitive search in the reference tab by kdiab in: [#1420](https://codeberg.org/uzu/strudel/pulls/1420)
+- 2025-06-28T00:04:13+02:00 add unjoin, into and chunkinto by yaxu in: [#1418](https://codeberg.org/uzu/strudel/pulls/1418)
+- 2025-06-26T15:29:46+02:00 mondo notation by froos in: [#1311](https://codeberg.org/uzu/strudel/pulls/1311)
+- 2025-06-24T06:14:15+02:00 allow calling `all` multiple times by froos in: [#1417](https://codeberg.org/uzu/strudel/pulls/1417)
+- 2025-06-24T05:53:22+02:00 tonal: allow scales without tonic (default to C) by Ghost in: [#1092](https://codeberg.org/uzu/strudel/pulls/1092)
+- 2025-06-20T20:00:12+02:00 website intro: fix whitespace and code hosting name by trofi in: [#1400](https://codeberg.org/uzu/strudel/pulls/1400)
+- 2025-06-19T10:15:07+02:00 fix stepcat #1396 by yaxu in: [#1398](https://codeberg.org/uzu/strudel/pulls/1398)
+- 2025-06-19T09:52:38+02:00 deprecate cpm + refactor docs to use setcpm by froos in: [#1397](https://codeberg.org/uzu/strudel/pulls/1397)
+- 2025-06-19T02:49:09+02:00 feat: 3 new codemirror themes by daslyfe in: [#1394](https://codeberg.org/uzu/strudel/pulls/1394)
+- 2025-06-14T16:23:00+02:00 link back to tech manual in wiki by yaxu in: [#1382](https://codeberg.org/uzu/strudel/pulls/1382)
+- 2025-06-14T14:55:37+02:00 degithub-links by froos in: [#1380](https://codeberg.org/uzu/strudel/pulls/1380)
+- 2025-06-13T15:24:42+02:00 fix euclidLegatoRot by bwagner in: [#1378](https://codeberg.org/uzu/strudel/pulls/1378)
+- 2025-06-13T10:07:51+02:00 remove-ms by yaxu in: [#1377](https://codeberg.org/uzu/strudel/pulls/1377)
+- 2025-06-12T10:25:48+02:00 Share fat URL by Ghost in: [#1375](https://codeberg.org/uzu/strudel/pulls/1375)
+- 2025-06-05T20:39:16+02:00 feat: onTriggerTime for interfacing with random APIs and doing illegal things on event time by Ghost in: [#1364](https://codeberg.org/uzu/strudel/pulls/1364)
+- 2025-06-05T01:08:18+02:00 feat: berlin noise by Ghost in: [#1363](https://codeberg.org/uzu/strudel/pulls/1363)
+
+## may 2025
+
+- 2025-05-29T14:36:43+02:00 Fix bytebeat sample offset by Ghost in: [#1359](https://codeberg.org/uzu/strudel/pulls/1359)
+- 2025-05-29T12:14:18+02:00 preserve stepcount in chunks by yaxu in: [#1358](https://codeberg.org/uzu/strudel/pulls/1358)
+- 2025-05-29T02:34:30+02:00 Byte Beat improvements -> 2 by Ghost in: [#1357](https://codeberg.org/uzu/strudel/pulls/1357)
+- 2025-05-28T16:40:32+02:00 Bytebeat improvements by Ghost in: [#1356](https://codeberg.org/uzu/strudel/pulls/1356)
+- 2025-05-27T17:42:39+02:00 feat: Byte Beats! by Ghost in: [#1354](https://codeberg.org/uzu/strudel/pulls/1354)
+- 2025-05-18T21:43:05+02:00 fix: typo on docs causing problems with autocompletion. by Ghost in: [#1350](https://codeberg.org/uzu/strudel/pulls/1350)
+- 2025-05-15T01:12:07+02:00 feat: Create pulsewidth (pw) and pulsewidth lfo parameters by Ghost in: [#1343](https://codeberg.org/uzu/strudel/pulls/1343)
+- 2025-05-14T18:25:17+02:00 feat: Multi Channel Orbits by Ghost in: [#1344](https://codeberg.org/uzu/strudel/pulls/1344)
+- 2025-05-13T17:45:29+02:00 Fix typo by Ghost in: [#1346](https://codeberg.org/uzu/strudel/pulls/1346)
+- 2025-05-02T00:01:27+02:00 Fix web + repl package builds by froos in: [#1339](https://codeberg.org/uzu/strudel/pulls/1339)
+- 2025-05-01T23:50:57+02:00 fix: superdough worklets bundling by froos in: [#1338](https://codeberg.org/uzu/strudel/pulls/1338)
+
+## april 2025
+
+- 2025-04-27T22:25:54+02:00 FIX: sound import order by Ghost in: [#1333](https://codeberg.org/uzu/strudel/pulls/1333)
+- 2025-04-27T18:39:49+02:00 update docs to reflect import sounds tab change by hpunq in: [#1332](https://codeberg.org/uzu/strudel/pulls/1332)
+- 2025-04-27T18:38:26+02:00 feat: Improve gain curve by Ghost in: [#1318](https://codeberg.org/uzu/strudel/pulls/1318)
+- 2025-04-27T07:54:49+02:00 Add Icon to import sample button by Ghost in: [#1331](https://codeberg.org/uzu/strudel/pulls/1331)
+- 2025-04-27T07:53:41+02:00 Add new "import-sounds" tab with explanation on folder import by hpunq in: [#1329](https://codeberg.org/uzu/strudel/pulls/1329)
+- 2025-04-22T00:04:38+02:00 feat: new themes + theme improvements by Ghost in: [#1326](https://codeberg.org/uzu/strudel/pulls/1326)
+- 2025-04-20T18:24:15+02:00 feat: Create scrub function for scrubbing an audio file by Ghost in: [#1321](https://codeberg.org/uzu/strudel/pulls/1321)
+- 2025-04-18T07:17:39+02:00 fix: disable astro toolbar by default by Ghost in: [#1324](https://codeberg.org/uzu/strudel/pulls/1324)
+- 2025-04-18T07:17:38+02:00 fix: udels header by Ghost in: [#1325](https://codeberg.org/uzu/strudel/pulls/1325)
+- 2025-04-11T09:18:58+02:00 Send delta in OSC message in seconds, to match tidal/superdirt by yaxu in: [#1323](https://codeberg.org/uzu/strudel/pulls/1323)
+- 2025-04-08T06:08:57+02:00 FIX: Multichannel Audio by Ghost in: [#1322](https://codeberg.org/uzu/strudel/pulls/1322)
+- 2025-04-08T04:18:03+02:00 feat: add max polyphony feature for superdough by Ghost in: [#1317](https://codeberg.org/uzu/strudel/pulls/1317)
+- 2025-04-05T21:12:05+02:00 enhancement: make error messages easier to read by Ghost in: [#1315](https://codeberg.org/uzu/strudel/pulls/1315)
+- 2025-04-04T06:26:57+02:00 fix: replace empty spaces in registered sound keys by Ghost in: [#1319](https://codeberg.org/uzu/strudel/pulls/1319)
+
+## march 2025
+
+- 2025-03-26T17:01:05+01:00 small feat: Add alias for segment and ribbon by Ghost in: [#1314](https://codeberg.org/uzu/strudel/pulls/1314)
+- 2025-03-26T14:54:18+01:00 Fix typo pattnr by Ghost in: [#1316](https://codeberg.org/uzu/strudel/pulls/1316)
+- 2025-03-23T20:05:31+01:00 bugfix: Allow single param to be used in the as function by Ghost in: [#1312](https://codeberg.org/uzu/strudel/pulls/1312)
+- 2025-03-20T23:35:18+01:00 Add MIDI Program Change, SysEx, NRPN, PitchBend and AfterTouch Output by nkymut in: [#1244](https://codeberg.org/uzu/strudel/pulls/1244)
+- 2025-03-19T17:32:30+01:00 make soundfont base url configurable by Ghost in: [#1040](https://codeberg.org/uzu/strudel/pulls/1040)
+- 2025-03-18T20:07:08+01:00 Add num samples from 0 up to 20 by yaxu in: [#1310](https://codeberg.org/uzu/strudel/pulls/1310)
+- 2025-03-17T10:38:54+01:00 add num samples (edited numbers) by yaxu in: [#1309](https://codeberg.org/uzu/strudel/pulls/1309)
+- 2025-03-08T22:17:47+01:00 @strudel/sampler improvements by froos in: [#1288](https://codeberg.org/uzu/strudel/pulls/1288)
+- 2025-03-08T21:56:50+01:00 Add Gamepad module by nkymut in: [#1223](https://codeberg.org/uzu/strudel/pulls/1223)
+- 2025-03-04T19:17:37+01:00 change behaviour of polymeter, and remove polymeterSteps by yaxu in: [#1302](https://codeberg.org/uzu/strudel/pulls/1302)
+- 2025-03-04T03:36:57+01:00 feat: Create Pulse Oscillator with variable PWM by Ghost in: [#1304](https://codeberg.org/uzu/strudel/pulls/1304)
+- 2025-03-02T17:08:31+01:00 feat: Theme improvements by Ghost in: [#1295](https://codeberg.org/uzu/strudel/pulls/1295)
+- 2025-03-02T11:58:46+01:00 bugfix zoom stepcount by yaxu in: [#1301](https://codeberg.org/uzu/strudel/pulls/1301)
+
+## february 2025
+
+- 2025-02-28T16:01:20+01:00 Fix test error #1297 by nkymut in: [#1298](https://codeberg.org/uzu/strudel/pulls/1298)
+- 2025-02-28T02:53:42+01:00 Hotfix: prevent undefined pattern code from crashing strudel on load by Ghost in: [#1297](https://codeberg.org/uzu/strudel/pulls/1297)
+- 2025-02-27T08:24:58+01:00 Fix misplaced ending sentence by Ghost in: [#1296](https://codeberg.org/uzu/strudel/pulls/1296)
+- 2025-02-23T10:54:13+01:00 Signpost licenses for source code and samples a bit more, ref #1277 by yaxu in: [#1289](https://codeberg.org/uzu/strudel/pulls/1289)
+- 2025-02-23T10:52:27+01:00 Allow wchooseCycles probabilities to be patterned by yaxu in: [#1292](https://codeberg.org/uzu/strudel/pulls/1292)
+- 2025-02-22T02:18:59+01:00 Create Pattern Page Pagination by Ghost in: [#1287](https://codeberg.org/uzu/strudel/pulls/1287)
+- 2025-02-21T22:38:10+01:00 showcase tweaks by yaxu in: [#1291](https://codeberg.org/uzu/strudel/pulls/1291)
+- 2025-02-11T16:34:24+01:00 Fixes inverted triangle wave by renaming it to `itri`, making non-inverted `tri` by yaxu in: [#1283](https://codeberg.org/uzu/strudel/pulls/1283)
+- 2025-02-11T10:02:34+01:00 Fix `squeezejoin` and functions using it, including `bite` by yaxu in: [#1286](https://codeberg.org/uzu/strudel/pulls/1286)
+- 2025-02-09T16:18:28+01:00 Rename repeat back to extend by yaxu in: [#1285](https://codeberg.org/uzu/strudel/pulls/1285)
+- 2025-02-07T18:11:52+01:00 mqtt bugfix - connection check by yaxu in: [#1282](https://codeberg.org/uzu/strudel/pulls/1282)
+- 2025-02-07T17:38:29+01:00 Bugfix: update mqtt connections dictionary by yaxu in: [#1281](https://codeberg.org/uzu/strudel/pulls/1281)
+- 2025-02-07T11:39:54+01:00 make mqtt topic patternable by yaxu in: [#1280](https://codeberg.org/uzu/strudel/pulls/1280)
+- 2025-02-07T11:07:32+01:00 midimaps by froos in: [#1274](https://codeberg.org/uzu/strudel/pulls/1274)
+- 2025-02-06T15:59:03+01:00 MQTT - support adding hap duration and cps metadata to JSON messages by yaxu in: [#1279](https://codeberg.org/uzu/strudel/pulls/1279)
+- 2025-02-05T16:10:54+01:00 [breaking change] Sample signals from query onset, rather than midpoint by yaxu in: [#1278](https://codeberg.org/uzu/strudel/pulls/1278)
+- 2025-02-03T00:55:36+01:00 Stepwise documentation tweaks, with mridangam samples by yaxu in: [#1275](https://codeberg.org/uzu/strudel/pulls/1275)
+- 2025-02-02T21:26:44+01:00 Polish, rename, and document stepwise functions by yaxu in: [#1262](https://codeberg.org/uzu/strudel/pulls/1262)
+- 2025-02-01T22:57:00+01:00 Fix sf2 timing by froos in: [#1272](https://codeberg.org/uzu/strudel/pulls/1272)
+- 2025-02-01T22:32:59+01:00 Add bank aliasing and case insensitivity by TodePond in: [#1245](https://codeberg.org/uzu/strudel/pulls/1245)
+
+## january 2025
+
+- 2025-01-31T09:39:54+01:00 Add Device Motion module by nkymut in: [#1217](https://codeberg.org/uzu/strudel/pulls/1217)
+- 2025-01-29T15:40:01+01:00 add "as" function + getControlName by froos in: [#1247](https://codeberg.org/uzu/strudel/pulls/1247)
+- 2025-01-29T15:30:04+01:00 Theme glowup by froos in: [#1268](https://codeberg.org/uzu/strudel/pulls/1268)
+- 2025-01-29T15:22:18+01:00 patchday by froos in: [#1264](https://codeberg.org/uzu/strudel/pulls/1264)
+- 2025-01-28T00:00:03+01:00 Revert "Fix sometimes" by yaxu in: [#1267](https://codeberg.org/uzu/strudel/pulls/1267)
+- 2025-01-24T15:32:48+01:00 add reference package by froos in: [#1252](https://codeberg.org/uzu/strudel/pulls/1252)
+- 2025-01-24T15:16:55+01:00 support `all(pianoroll)` and `all(pianoroll({labels: true}))` by yaxu in: [#1234](https://codeberg.org/uzu/strudel/pulls/1234)
+- 2025-01-24T12:13:49+01:00 MQTT - if password isn't provided, prompt for one by yaxu in: [#1249](https://codeberg.org/uzu/strudel/pulls/1249)
+- 2025-01-21T06:24:03+01:00 fix docs for beat function by Ghost in: [#1248](https://codeberg.org/uzu/strudel/pulls/1248)
+- 2025-01-18T23:27:51+01:00 understand voicings page by froos in: [#1230](https://codeberg.org/uzu/strudel/pulls/1230)
+- 2025-01-17T19:27:00+01:00 Add binary and binaryN by Ghost in: [#1226](https://codeberg.org/uzu/strudel/pulls/1226)
+- 2025-01-16T12:18:33+01:00 Fix sometimes by yaxu in: [#1243](https://codeberg.org/uzu/strudel/pulls/1243)
+- 2025-01-16T05:55:46+01:00 "beat" function for "step sequencer" style rhythm notation by Ghost in: [#1237](https://codeberg.org/uzu/strudel/pulls/1237)
+- 2025-01-14T14:39:15+01:00 Add stepBind, and some toplevel aliases for binds and withValue by yaxu in: [#1241](https://codeberg.org/uzu/strudel/pulls/1241)
+- 2025-01-14T06:11:10+01:00 Add onKey function for custom key commands for patterns by Ghost in: [#1235](https://codeberg.org/uzu/strudel/pulls/1235)
+- 2025-01-12T11:32:24+01:00 Update documentation for param value modification by Ghost in: [#1238](https://codeberg.org/uzu/strudel/pulls/1238)
+
+## december 2024
+
+- 2024-12-29T13:16:08+01:00 Documentation for all/each, and bugfix for each by yaxu in: [#1233](https://codeberg.org/uzu/strudel/pulls/1233)
+- 2024-12-29T11:29:52+01:00 Make `all()` post-stack again, and add `each()` for pre-stack by yaxu in: [#1229](https://codeberg.org/uzu/strudel/pulls/1229)
+- 2024-12-27T22:16:54+01:00 suggested changes to voicings.mdx by Ghost in: [#1231](https://codeberg.org/uzu/strudel/pulls/1231)
+- 2024-12-23T11:53:11+01:00 add basic spectrum function by froos in: [#1213](https://codeberg.org/uzu/strudel/pulls/1213)
+- 2024-12-22T21:04:45+01:00 Fix regression for d1, p1, p(n) by yaxu in: [#1227](https://codeberg.org/uzu/strudel/pulls/1227)
+
+## november 2024
+
+- 2024-11-30T10:09:36+01:00 Make cps patternable by eefano in: [#1001](https://codeberg.org/uzu/strudel/pulls/1001)
+- 2024-11-30T10:07:56+01:00 MQTT support by yaxu in: [#1224](https://codeberg.org/uzu/strudel/pulls/1224)
+- 2024-11-30T09:46:14+01:00 Apply `all` function to individual patterns rather than final stack by yaxu in: [#1209](https://codeberg.org/uzu/strudel/pulls/1209)
+- 2024-11-20T16:32:51+01:00 REPL: solo and sync configuration by Ghost in: [#1214](https://codeberg.org/uzu/strudel/pulls/1214)
+
+## october 2024
+
+- 2024-10-30T21:29:43+01:00 Add s_zip for 'cat'-ing patterns together step-by-step, bugfix `steps` by yaxu in: [#1208](https://codeberg.org/uzu/strudel/pulls/1208)
+- 2024-10-30T21:28:32+01:00 Preserve tactus for 'degrade' and friends, and tidy up 'pick' and friends by yaxu in: [#1205](https://codeberg.org/uzu/strudel/pulls/1205)
+- 2024-10-30T17:11:53+01:00 chore: Edit run locally instructions in README.md by Ghost in: [#1206](https://codeberg.org/uzu/strudel/pulls/1206)
+- 2024-10-23T23:08:14+02:00 colorize console + tweak header by froos in: [#1203](https://codeberg.org/uzu/strudel/pulls/1203)
+- 2024-10-22T22:55:00+02:00 markcss by froos in: [#1202](https://codeberg.org/uzu/strudel/pulls/1202)
+- 2024-10-21T22:56:37+02:00 add 2 new ui settings by froos in: [#1200](https://codeberg.org/uzu/strudel/pulls/1200)
+- 2024-10-21T20:22:52+02:00 Make panel hover behavior optional by Ghost in: [#1199](https://codeberg.org/uzu/strudel/pulls/1199)
+- 2024-10-19T04:28:36+02:00 Menu Panel Improvements! by Ghost in: [#1193](https://codeberg.org/uzu/strudel/pulls/1193)
+- 2024-10-19T01:10:06+02:00 update lockfile + minor versions by froos in: [#1198](https://codeberg.org/uzu/strudel/pulls/1198)
+
+## september 2024
+
+- 2024-09-27T00:17:00+02:00 remove redundant example for cat, update snapshot by Ghost in: [#1189](https://codeberg.org/uzu/strudel/pulls/1189)
+- 2024-09-25T13:18:19+02:00 Adding search bar (soundtab.jsx) by Ghost in: [#1185](https://codeberg.org/uzu/strudel/pulls/1185)
+- 2024-09-23T17:18:34+02:00 Screenreader improvements by yaxu in: [#1158](https://codeberg.org/uzu/strudel/pulls/1158)
+- 2024-09-20T22:26:41+02:00 Fix serial timing by yaxu in: [#1188](https://codeberg.org/uzu/strudel/pulls/1188)
+- 2024-09-20T00:26:30+02:00 Add bite function by yaxu in: [#1187](https://codeberg.org/uzu/strudel/pulls/1187)
+- 2024-09-14T13:30:53+02:00 better spacing in zen mode by froos in: [#1147](https://codeberg.org/uzu/strudel/pulls/1147)
+- 2024-09-14T10:50:24+02:00 add filter + filterWhen + within by froos in: [#1039](https://codeberg.org/uzu/strudel/pulls/1039)
+- 2024-09-14T10:49:21+02:00 refactor sampler by froos in: [#1101](https://codeberg.org/uzu/strudel/pulls/1101)
+- 2024-09-14T10:43:17+02:00 handle midin device not found error by froos in: [#1146](https://codeberg.org/uzu/strudel/pulls/1146)
+- 2024-09-13T21:59:23+02:00 Add a search bar to the REPL Reference tab by Ghost in: [#1165](https://codeberg.org/uzu/strudel/pulls/1165)
+- 2024-09-13T21:58:47+02:00 Correct spelling mistakes by Ghost in: [#1183](https://codeberg.org/uzu/strudel/pulls/1183)
+- 2024-09-07T23:41:29+02:00 Add seqPLoop from Tidal by yaxu in: [#1182](https://codeberg.org/uzu/strudel/pulls/1182)
+- 2024-09-05T05:52:50+02:00 make phaser control match superdirt by Ghost in: [#1180](https://codeberg.org/uzu/strudel/pulls/1180)
+- 2024-09-05T05:33:41+02:00 Revert "Make phaser control consistent with superdirt" by Ghost in: [#1179](https://codeberg.org/uzu/strudel/pulls/1179)
+- 2024-09-05T05:29:12+02:00 Make phaser control consistent with superdirt by Ghost in: [#1178](https://codeberg.org/uzu/strudel/pulls/1178)
+- 2024-09-03T04:37:15+02:00 fix sample speed when using splice and fit with superdirt by Ghost in: [#1172](https://codeberg.org/uzu/strudel/pulls/1172)
+- 2024-09-01T16:02:24+02:00 Create audio target selector for OSC/Superdirt by Ghost in: [#1160](https://codeberg.org/uzu/strudel/pulls/1160)
+- 2024-09-01T15:03:47+02:00 Fixes fit so it works after a chop or slice by yaxu in: [#1171](https://codeberg.org/uzu/strudel/pulls/1171)
+
+## august 2024
+
+- 2024-08-30T14:24:08+02:00 polyJoin by yaxu in: [#1168](https://codeberg.org/uzu/strudel/pulls/1168)
+- 2024-08-23T17:05:10+02:00 Add scramble and shuffle by yaxu in: [#1167](https://codeberg.org/uzu/strudel/pulls/1167)
+- 2024-08-18T18:22:20+02:00 Improve + simplify neocyclist timing by Ghost in: [#1164](https://codeberg.org/uzu/strudel/pulls/1164)
+- 2024-08-15T05:18:33+02:00 containerize/seperate out boolean checks for repl types/Repl logic into bespoke components. by Ghost in: [#1163](https://codeberg.org/uzu/strudel/pulls/1163)
+- 2024-08-12T18:57:21+02:00 [CORS HOTFIX] by Ghost in: [#1162](https://codeberg.org/uzu/strudel/pulls/1162)
+- 2024-08-09T05:11:28+02:00 Fix OSC clock jitter by Ghost in: [#1157](https://codeberg.org/uzu/strudel/pulls/1157)
+
+## july 2024
+
+- 2024-07-27T11:02:38+02:00 Fix loopAt tactus by yaxu in: [#1145](https://codeberg.org/uzu/strudel/pulls/1145)
+- 2024-07-26T04:37:34+02:00 "stretch" function (phase vocoder) by Ghost in: [#1130](https://codeberg.org/uzu/strudel/pulls/1130)
+- 2024-07-26T04:37:17+02:00 Udels (MultiFrame Strudel) Revisited by Ghost in: [#1132](https://codeberg.org/uzu/strudel/pulls/1132)
+- 2024-07-24T11:40:28+02:00 Fix tactus marking in mininotation by yaxu in: [#1144](https://codeberg.org/uzu/strudel/pulls/1144)
+
+## june 2024
+
+- 2024-06-25T18:13:28+02:00 export comment commands by froos in: [#1136](https://codeberg.org/uzu/strudel/pulls/1136)
+- 2024-06-24T18:19:22+02:00 Chop chop by yaxu in: [#1078](https://codeberg.org/uzu/strudel/pulls/1078)
+- 2024-06-18T23:58:08+02:00 Fix bug in Fraction.lcm by yaxu in: [#1133](https://codeberg.org/uzu/strudel/pulls/1133)
+- 2024-06-18T05:32:12+02:00 Fix clock worker dependency path in module builds by Ghost in: [#1129](https://codeberg.org/uzu/strudel/pulls/1129)
+- 2024-06-04T00:26:48+02:00 Labeled statements doc by froos in: [#1126](https://codeberg.org/uzu/strudel/pulls/1126)
+- 2024-06-03T22:40:21+02:00 doc: visual functions + refactor onPaint by froos in: [#1125](https://codeberg.org/uzu/strudel/pulls/1125)
+- 2024-06-02T18:36:29+02:00 Fix indexDB failing with large amount of files by Ghost in: [#1124](https://codeberg.org/uzu/strudel/pulls/1124)
+
+## may 2024
+
+- 2024-05-31T12:17:34+02:00 Migrate tutorial fanchor by froos in: [#1122](https://codeberg.org/uzu/strudel/pulls/1122)
+- 2024-05-31T10:46:47+02:00 [BUG FIX] Audio worklets sometimes dont load by Ghost in: [#1121](https://codeberg.org/uzu/strudel/pulls/1121)
+- 2024-05-31T10:25:24+02:00 change fanchor to 0 by Ghost in: [#1107](https://codeberg.org/uzu/strudel/pulls/1107)
+- 2024-05-30T14:39:30+02:00 fix: use full repl in web package by froos in: [#1119](https://codeberg.org/uzu/strudel/pulls/1119)
+- 2024-05-30T09:36:32+02:00 can now access strudelMirror from repl by froos in: [#1117](https://codeberg.org/uzu/strudel/pulls/1117)
+- 2024-05-29T13:06:34+02:00 Add the mousex and mousey signal by Ghost in: [#1112](https://codeberg.org/uzu/strudel/pulls/1112)
+- 2024-05-29T13:02:00+02:00 Fixes drawPianoroll import in codemirror example by Ghost in: [#1116](https://codeberg.org/uzu/strudel/pulls/1116)
+- 2024-05-28T22:43:46+02:00 clarify `off` in pattern-effects.mdx by Ghost in: [#1074](https://codeberg.org/uzu/strudel/pulls/1074)
+- 2024-05-26T17:33:07+02:00 rollback phaser by Ghost in: [#1113](https://codeberg.org/uzu/strudel/pulls/1113)
+- 2024-05-26T17:33:06+02:00 Fix audio worklets by Ghost in: [#1114](https://codeberg.org/uzu/strudel/pulls/1114)
+- 2024-05-26T16:53:56+02:00 Calculate phaser modulation phase based on time by Ghost in: [#1110](https://codeberg.org/uzu/strudel/pulls/1110)
+- 2024-05-23T15:06:01+02:00 Add analog-style ladder filter by Ghost in: [#1103](https://codeberg.org/uzu/strudel/pulls/1103)
+- 2024-05-22T12:53:20+02:00 fix sampler on windows by Ghost in: [#1109](https://codeberg.org/uzu/strudel/pulls/1109)
+- 2024-05-20T23:26:20+02:00 web package fixes by froos in: [#1044](https://codeberg.org/uzu/strudel/pulls/1044)
+- 2024-05-20T22:41:28+02:00 Fix sampler windows by froos in: [#1108](https://codeberg.org/uzu/strudel/pulls/1108)
+- 2024-05-19T12:07:26+02:00 hs2js package / tidal parser by froos in: [#870](https://codeberg.org/uzu/strudel/pulls/870)
+- 2024-05-18T10:49:08+02:00 fix little dub tune example by Ghost in: [#1104](https://codeberg.org/uzu/strudel/pulls/1104)
+- 2024-05-17T14:43:58+02:00 Samples tab improvements by Ghost in: [#1102](https://codeberg.org/uzu/strudel/pulls/1102)
+- 2024-05-13T10:10:34+02:00 osc: couple of fixes by Ghost in: [#1093](https://codeberg.org/uzu/strudel/pulls/1093)
+- 2024-05-13T06:31:20+02:00 Use sessionStorage for viewingPatternData and activePattern by Ghost in: [#1091](https://codeberg.org/uzu/strudel/pulls/1091)
+- 2024-05-12T18:23:09+02:00 repl: set document.title from @title by Ghost in: [#1090](https://codeberg.org/uzu/strudel/pulls/1090)
+- 2024-05-07T14:29:22+02:00 fix: missing events due to premature worklet cleanup by froos in: [#1089](https://codeberg.org/uzu/strudel/pulls/1089)
+- 2024-05-03T11:52:57+02:00 Benchmarks by yaxu in: [#1079](https://codeberg.org/uzu/strudel/pulls/1079)
+- 2024-05-03T08:46:52+02:00 fix: csound + dough timing by froos in: [#1086](https://codeberg.org/uzu/strudel/pulls/1086)
+- 2024-05-03T00:37:32+02:00 Improve performance of ! (replicate) by yaxu in: [#1084](https://codeberg.org/uzu/strudel/pulls/1084)
+- 2024-05-02T23:40:22+02:00 fix: url parsing with extra params by froos in: [#1083](https://codeberg.org/uzu/strudel/pulls/1083)
+
+## april 2024
+
+- 2024-04-29T12:36:11+02:00 Tactus calculation toggle and breaking change to tactus calculation in fast/slow/hurry by yaxu in: [#1081](https://codeberg.org/uzu/strudel/pulls/1081)
+- 2024-04-28T20:56:21+02:00 fix docs on alignment.mdx by Ghost in: [#1076](https://codeberg.org/uzu/strudel/pulls/1076)
+- 2024-04-28T20:49:18+02:00 add signals to recap in first-effects.mdx by Ghost in: [#1073](https://codeberg.org/uzu/strudel/pulls/1073)
+- 2024-04-28T20:44:57+02:00 fix translation issue in first-effects.mdx by Ghost in: [#1072](https://codeberg.org/uzu/strudel/pulls/1072)
+- 2024-04-28T20:44:29+02:00 fix failing format test by Ghost in: [#1077](https://codeberg.org/uzu/strudel/pulls/1077)
+- 2024-04-27T22:50:17+02:00 add nesting to `off` example variation in pattern-effects.mdx by Ghost in: [#1075](https://codeberg.org/uzu/strudel/pulls/1075)
+- 2024-04-27T22:48:58+02:00 add `<...>` to first-sounds.mdx recap by Ghost in: [#1070](https://codeberg.org/uzu/strudel/pulls/1070)
+- 2024-04-27T22:48:07+02:00 fix first sounds typo by Ghost in: [#1069](https://codeberg.org/uzu/strudel/pulls/1069)
+- 2024-04-27T22:47:44+02:00 fix cr typo on first-sounds.mdx by Ghost in: [#1068](https://codeberg.org/uzu/strudel/pulls/1068)
+- 2024-04-26T15:12:30+02:00 More tactus tidying by yaxu in: [#1071](https://codeberg.org/uzu/strudel/pulls/1071)
+- 2024-04-23T23:37:21+02:00 Fix stepjoin by yaxu in: [#1067](https://codeberg.org/uzu/strudel/pulls/1067)
+- 2024-04-23T23:32:00+02:00 clarify license by yaxu in: [#1064](https://codeberg.org/uzu/strudel/pulls/1064)
+- 2024-04-23T15:14:30+02:00 Tactus tweaks - fixes for maintaining tactus and highlight locations by yaxu in: [#1065](https://codeberg.org/uzu/strudel/pulls/1065)
+- 2024-04-21T23:57:57+02:00 fix OSC timing for recent scheduler updates by Ghost in: [#1062](https://codeberg.org/uzu/strudel/pulls/1062)
+- 2024-04-21T22:17:07+02:00 Stepwise functions from Tidal by yaxu in: [#1060](https://codeberg.org/uzu/strudel/pulls/1060)
+- 2024-04-21T11:03:55+02:00 Fix wchooseCycles not picking the whole pattern by Ghost in: [#1061](https://codeberg.org/uzu/strudel/pulls/1061)
+- 2024-04-19T00:05:52+02:00 add swing + swingBy by froos in: [#1038](https://codeberg.org/uzu/strudel/pulls/1038)
+- 2024-04-19T00:05:08+02:00 anonymous patterns + muting by froos in: [#1059](https://codeberg.org/uzu/strudel/pulls/1059)
+- 2024-04-12T12:34:27+02:00 improve tutorial + custom samples doc by froos in: [#1053](https://codeberg.org/uzu/strudel/pulls/1053)
+- 2024-04-12T12:31:49+02:00 fix: do not reset cc input values on each eval by froos in: [#1054](https://codeberg.org/uzu/strudel/pulls/1054)
+- 2024-04-08T17:25:27+02:00 transpose: support all combinations of numbers and strings for notes and intervals by froos in: [#1048](https://codeberg.org/uzu/strudel/pulls/1048)
+- 2024-04-08T10:46:18+02:00 Wax, wane, taper and taperlist by yaxu in: [#1042](https://codeberg.org/uzu/strudel/pulls/1042)
+- 2024-04-06T23:44:57+02:00 Midi Time hotfix for scheduler updates by Ghost in: [#1047](https://codeberg.org/uzu/strudel/pulls/1047)
+- 2024-04-05T12:48:03+02:00 pitchwheel visual by froos in: [#1041](https://codeberg.org/uzu/strudel/pulls/1041)
+- 2024-04-05T12:47:19+02:00 fix cyclist fizzling out by froos in: [#1046](https://codeberg.org/uzu/strudel/pulls/1046)
+
+## march 2024
+
+- 2024-03-30T16:05:59+01:00 remove dangerous arithmetic feature by froos in: [#1030](https://codeberg.org/uzu/strudel/pulls/1030)
+- 2024-03-30T16:05:27+01:00 Fix sampler paths by froos in: [#1034](https://codeberg.org/uzu/strudel/pulls/1034)
+- 2024-03-30T14:43:08+01:00 local sample server cli by froos in: [#1033](https://codeberg.org/uzu/strudel/pulls/1033)
+- 2024-03-29T17:14:28+01:00 add font file types to offline cache by froos in: [#1032](https://codeberg.org/uzu/strudel/pulls/1032)
+- 2024-03-29T17:10:16+01:00 add closeBrackets setting by froos in: [#1031](https://codeberg.org/uzu/strudel/pulls/1031)
+- 2024-03-29T14:55:06+01:00 Tactus tidy by yaxu in: [#1027](https://codeberg.org/uzu/strudel/pulls/1027)
+- 2024-03-28T17:06:44+01:00 add setting for sync flag by froos in: [#1025](https://codeberg.org/uzu/strudel/pulls/1025)
+- 2024-03-28T11:37:57+01:00 better theme integration for visuals + various fixes by froos in: [#1024](https://codeberg.org/uzu/strudel/pulls/1024)
+- 2024-03-28T11:33:25+01:00 More fonts by froos in: [#1023](https://codeberg.org/uzu/strudel/pulls/1023)
+- 2024-03-27T13:06:05+01:00 Feature: tactus marking by yaxu in: [#1021](https://codeberg.org/uzu/strudel/pulls/1021)
+- 2024-03-25T06:02:02+01:00 hotfix for 1017 by Ghost in: [#1020](https://codeberg.org/uzu/strudel/pulls/1020)
+- 2024-03-24T15:06:33+01:00 Document signals by Ghost in: [#1015](https://codeberg.org/uzu/strudel/pulls/1015)
+- 2024-03-24T10:16:11+01:00 Repl sync fixes by Ghost in: [#1014](https://codeberg.org/uzu/strudel/pulls/1014)
+- 2024-03-23T20:21:51+01:00 eliminate chromium clock jitter by froos in: [#1004](https://codeberg.org/uzu/strudel/pulls/1004)
+- 2024-03-23T15:51:07+01:00 update undocumented script by froos in: [#1013](https://codeberg.org/uzu/strudel/pulls/1013)
+- 2024-03-23T15:26:52+01:00 fix: await injectPatternMethods by froos in: [#1012](https://codeberg.org/uzu/strudel/pulls/1012)
+- 2024-03-23T15:18:12+01:00 rename trig -> reset, trigzero -> restart by froos in: [#1010](https://codeberg.org/uzu/strudel/pulls/1010)
+- 2024-03-23T12:30:03+01:00 Inline punchcard + spiral by froos in: [#1008](https://codeberg.org/uzu/strudel/pulls/1008)
+- 2024-03-23T12:27:22+01:00 Color in hap value by froos in: [#1007](https://codeberg.org/uzu/strudel/pulls/1007)
+- 2024-03-22T23:53:51+01:00 using strudel in your project guide + cleanup examples by froos in: [#1006](https://codeberg.org/uzu/strudel/pulls/1006)
+- 2024-03-22T23:41:50+01:00 accidentals in scale degrees by eefano in: [#1000](https://codeberg.org/uzu/strudel/pulls/1000)
+- 2024-03-21T22:53:55+01:00 supersaw oscillator by Ghost in: [#978](https://codeberg.org/uzu/strudel/pulls/978)
+- 2024-03-21T13:00:04+01:00 remove canvas, externalize samples, delete junk by froos in: [#1003](https://codeberg.org/uzu/strudel/pulls/1003)
+- 2024-03-18T11:37:55+01:00 Fix pure mini highlight by yaxu in: [#994](https://codeberg.org/uzu/strudel/pulls/994)
+- 2024-03-18T07:12:14+01:00 inline viz / widgets package by froos in: [#989](https://codeberg.org/uzu/strudel/pulls/989)
+- 2024-03-17T04:07:00+01:00 Labeled statements by froos in: [#991](https://codeberg.org/uzu/strudel/pulls/991)
+- 2024-03-16T18:24:38+01:00 Beat-oriented functionality by yaxu in: [#976](https://codeberg.org/uzu/strudel/pulls/976)
+- 2024-03-15T01:47:35+01:00 REPL sync between windows by Ghost in: [#900](https://codeberg.org/uzu/strudel/pulls/900)
+- 2024-03-14T00:20:07+01:00 Update synths.mdx by Ghost in: [#984](https://codeberg.org/uzu/strudel/pulls/984)
+- 2024-03-13T00:36:22+01:00 fix: share now shares what's visible instead of active by froos in: [#985](https://codeberg.org/uzu/strudel/pulls/985)
+- 2024-03-10T01:18:57+01:00 use ireal as default voicing dict by froos in: [#967](https://codeberg.org/uzu/strudel/pulls/967)
+- 2024-03-10T00:50:23+01:00 little fix for withVal by eefano in: [#980](https://codeberg.org/uzu/strudel/pulls/980)
+- 2024-03-10T00:46:51+01:00 Velocity in value by froos in: [#974](https://codeberg.org/uzu/strudel/pulls/974)
+- 2024-03-10T00:42:50+01:00 fix: clear hydra on reset by froos in: [#983](https://codeberg.org/uzu/strudel/pulls/983)
+- 2024-03-10T00:38:43+01:00 move canvas related helpers from core to new draw package by froos in: [#971](https://codeberg.org/uzu/strudel/pulls/971)
+- 2024-03-08T05:38:07+01:00 replace shape with distort in learn doc by Ghost in: [#982](https://codeberg.org/uzu/strudel/pulls/982)
+- 2024-03-06T12:14:49+01:00 alias - for ~ by yaxu in: [#981](https://codeberg.org/uzu/strudel/pulls/981)
+- 2024-03-04T16:04:23+01:00 Worklet Improvents / fixes by Ghost in: [#963](https://codeberg.org/uzu/strudel/pulls/963)
+- 2024-03-01T17:30:19+01:00 Nested controls by froos in: [#973](https://codeberg.org/uzu/strudel/pulls/973)
+
+## february 2024
+
+- 2024-02-29T15:33:12+01:00 feat: can now invert euclid pulses with negative numbers by froos in: [#959](https://codeberg.org/uzu/strudel/pulls/959)
+- 2024-02-29T15:31:23+01:00 pickOut(), pickRestart(), pickReset() by eefano in: [#950](https://codeberg.org/uzu/strudel/pulls/950)
+- 2024-02-29T15:12:45+01:00 remove legacy legato + duration implementations by froos in: [#965](https://codeberg.org/uzu/strudel/pulls/965)
+- 2024-02-29T08:47:53+01:00 fix for transpose(): preserve hap value object structure by eefano in: [#966](https://codeberg.org/uzu/strudel/pulls/966)
+- 2024-02-29T08:32:00+01:00 add debounce to logger by froos in: [#968](https://codeberg.org/uzu/strudel/pulls/968)
+- 2024-02-28T18:43:52+01:00 controls refactoring: simplify exports by froos in: [#962](https://codeberg.org/uzu/strudel/pulls/962)
+- 2024-02-25T19:17:00+01:00 fix: reset global fx on pattern change by froos in: [#960](https://codeberg.org/uzu/strudel/pulls/960)
+- 2024-02-25T14:15:30+01:00 fix midi issue on firefox and added quote error by Ghost in: [#936](https://codeberg.org/uzu/strudel/pulls/936)
+- 2024-02-25T13:19:47+01:00 'Enable Bracket Matching' option in Codemirror by eefano in: [#956](https://codeberg.org/uzu/strudel/pulls/956)
+- 2024-02-23T14:37:46+01:00 fix script importable packages (web + repl) by froos in: [#957](https://codeberg.org/uzu/strudel/pulls/957)
+- 2024-02-21T16:17:37+01:00 account for cps in midi time duration by Ghost in: [#954](https://codeberg.org/uzu/strudel/pulls/954)
+- 2024-02-21T10:27:12+01:00 Auto await samples by froos in: [#955](https://codeberg.org/uzu/strudel/pulls/955)
+- 2024-02-08T13:16:15+01:00 remove cjs builds by froos in: [#945](https://codeberg.org/uzu/strudel/pulls/945)
+- 2024-02-04T23:15:37+01:00 Minor documentation error: Update first-sounds.mdx by Ghost in: [#941](https://codeberg.org/uzu/strudel/pulls/941)
+
+
+## january 2024
+
+- 2024-01-24T16:48:57+01:00 fix: pianoroll sorting by froos in: [#938](https://codeberg.org/uzu/strudel/pulls/938)
+- 2024-01-23T00:04:03+01:00 V1 release notes by froos in: [#935](https://codeberg.org/uzu/strudel/pulls/935)
+- 2024-01-22T20:20:53+01:00 2 years blog post by froos in: [#929](https://codeberg.org/uzu/strudel/pulls/929)
+- 2024-01-22T20:02:34+01:00 make 0.5hz cps the default by yaxu in: [#931](https://codeberg.org/uzu/strudel/pulls/931)
+- 2024-01-22T00:52:01+01:00 Fix pattern tab not showing patterns without created date by Ghost in: [#934](https://codeberg.org/uzu/strudel/pulls/934)
+- 2024-01-21T20:46:28+01:00 Add useful pattern selection behavior for performing. by Ghost in: [#897](https://codeberg.org/uzu/strudel/pulls/897)
+- 2024-01-21T01:30:28+01:00 Refactor cps functions by froos in: [#933](https://codeberg.org/uzu/strudel/pulls/933)
+- 2024-01-20T23:47:31+01:00 Make splice cps-aware by yaxu in: [#932](https://codeberg.org/uzu/strudel/pulls/932)
+- 2024-01-19T18:50:57+01:00 community bakery by froos in: [#923](https://codeberg.org/uzu/strudel/pulls/923)
+- 2024-01-19T18:49:54+01:00 add pickF and pickmodF by Ghost in: [#924](https://codeberg.org/uzu/strudel/pulls/924)
+- 2024-01-19T15:10:48+01:00 Mini-notation additions towards tidal compatibility by yaxu in: [#926](https://codeberg.org/uzu/strudel/pulls/926)
+- 2024-01-18T23:34:11+01:00 Blog improvements by froos in: [#919](https://codeberg.org/uzu/strudel/pulls/919)
+- 2024-01-18T18:08:29+01:00 pick, pickmod, inhabit, inhabitmod by yaxu in: [#921](https://codeberg.org/uzu/strudel/pulls/921)
+- 2024-01-18T18:04:27+01:00 Revert "`pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function" by yaxu in: [#920](https://codeberg.org/uzu/strudel/pulls/920)
+- 2024-01-18T17:45:39+01:00 `pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function by yaxu in: [#918](https://codeberg.org/uzu/strudel/pulls/918)
+- 2024-01-18T10:30:08+01:00 rename @strudel.cycles/* packages to @strudel/* by froos in: [#917](https://codeberg.org/uzu/strudel/pulls/917)
+- 2024-01-18T06:54:33+01:00 pitch envelopes by froos in: [#913](https://codeberg.org/uzu/strudel/pulls/913)
+- 2024-01-18T05:09:38+01:00 Fix: swatch/[name].png.js static path by Ghost in: [#916](https://codeberg.org/uzu/strudel/pulls/916)
+- 2024-01-16T08:22:28+01:00 Add more vowel qualities for the vowels function by Ghost in: [#907](https://codeberg.org/uzu/strudel/pulls/907)
+- 2024-01-14T23:56:36+01:00 adds a blog by froos in: [#911](https://codeberg.org/uzu/strudel/pulls/911)
+- 2024-01-14T23:52:41+01:00 Remove hideHeader for better mobile UI and consistency by Ghost in: [#894](https://codeberg.org/uzu/strudel/pulls/894)
+- 2024-01-14T22:43:06+01:00 Further Envelope improvements by Ghost in: [#868](https://codeberg.org/uzu/strudel/pulls/868)
+- 2024-01-14T00:48:04+01:00 public sharing by froos in: [#910](https://codeberg.org/uzu/strudel/pulls/910)
+- 2024-01-12T18:31:41+01:00 fix some build warnings by froos in: [#902](https://codeberg.org/uzu/strudel/pulls/902)
+- 2024-01-12T18:01:55+01:00 prevent vite from complaining about additional exports in jsx files by Ghost in: [#891](https://codeberg.org/uzu/strudel/pulls/891)
+- 2024-01-12T17:05:47+01:00 Update Vite version so hot reload works properly with newest pnpm version by Ghost in: [#892](https://codeberg.org/uzu/strudel/pulls/892)
+- 2024-01-12T15:09:41+01:00 support , in < > by froos in: [#886](https://codeberg.org/uzu/strudel/pulls/886)
+- 2024-01-10T13:55:39+01:00 fix: autocomplete / tooltip code example bug by froos in: [#898](https://codeberg.org/uzu/strudel/pulls/898)
+- 2024-01-06T15:23:55+01:00 fix: invisible selection on vim + emacs mode by froos in: [#889](https://codeberg.org/uzu/strudel/pulls/889)
+- 2024-01-05T22:29:20+01:00 scales can now be anchored by froos in: [#888](https://codeberg.org/uzu/strudel/pulls/888)
+- 2024-01-04T11:21:42+01:00 add root mode for voicings by froos in: [#887](https://codeberg.org/uzu/strudel/pulls/887)
+- 2024-01-01T18:32:17+01:00 Showcase by froos in: [#885](https://codeberg.org/uzu/strudel/pulls/885)
+- 2024-01-01T14:22:11+01:00 bugfix: suspend and close exisiting audio context when changing interface by Ghost in: [#882](https://codeberg.org/uzu/strudel/pulls/882)
+- 2024-01-01T14:21:52+01:00 add mastodon link by froos in: [#884](https://codeberg.org/uzu/strudel/pulls/884)
+
+## december 2023
+
+- 2023-12-31T17:02:57+01:00 fix: make sure n is never undefined before nanFallback by froos in: [#881](https://codeberg.org/uzu/strudel/pulls/881)
+- 2023-12-31T16:47:22+01:00 Error tolerance by froos in: [#880](https://codeberg.org/uzu/strudel/pulls/880)
+- 2023-12-31T10:06:24+01:00 bugfix: sound select indexes out of bounds by Ghost in: [#871](https://codeberg.org/uzu/strudel/pulls/871)
+- 2023-12-31T10:03:01+01:00 Audio device selection by Ghost in: [#854](https://codeberg.org/uzu/strudel/pulls/854)
+- 2023-12-31T00:59:49+01:00 Dependency update by froos in: [#879](https://codeberg.org/uzu/strudel/pulls/879)
+- 2023-12-29T16:53:41+01:00 move all examples to separate examples folder by froos in: [#878](https://codeberg.org/uzu/strudel/pulls/878)
+- 2023-12-29T15:29:17+01:00 final vanillification by froos in: [#876](https://codeberg.org/uzu/strudel/pulls/876)
+- 2023-12-27T18:38:09+01:00 Bug Fix #119: Clock drift by Ghost in: [#874](https://codeberg.org/uzu/strudel/pulls/874)
+- 2023-12-27T13:17:03+01:00 main repl vanillification by froos in: [#873](https://codeberg.org/uzu/strudel/pulls/873)
+- 2023-12-25T17:47:25+01:00 more work on vanilla repl: repl web component + package + MicroRepl by froos in: [#866](https://codeberg.org/uzu/strudel/pulls/866)
+- 2023-12-15T00:11:35+01:00 Vanilla repl 3 by froos in: [#865](https://codeberg.org/uzu/strudel/pulls/865)
+- 2023-12-14T21:28:49+01:00 Vanilla repl 2 by froos in: [#863](https://codeberg.org/uzu/strudel/pulls/863)
+- 2023-12-12T21:49:23+01:00 fix: finally repair envelopes by froos in: [#861](https://codeberg.org/uzu/strudel/pulls/861)
+- 2023-12-12T21:20:00+01:00 add missing trailing slashes by froos in: [#860](https://codeberg.org/uzu/strudel/pulls/860)
+- 2023-12-12T19:08:31+01:00 Sound Import from local file system by Ghost in: [#839](https://codeberg.org/uzu/strudel/pulls/839)
+- 2023-12-11T22:48:35+01:00 Pattern organization by froos in: [#858](https://codeberg.org/uzu/strudel/pulls/858)
+- 2023-12-09T17:25:11+01:00 Export patterns + ui tweaks by froos in: [#855](https://codeberg.org/uzu/strudel/pulls/855)
+- 2023-12-08T09:41:10+01:00 patterns tab: import patterns + style by froos in: [#852](https://codeberg.org/uzu/strudel/pulls/852)
+- 2023-12-07T20:42:00+01:00 Patterns tab + Refactor Panel by froos in: [#769](https://codeberg.org/uzu/strudel/pulls/769)
+- 2023-12-07T10:25:16+01:00 CHANGES: pnpm 8.1.3 to 8.11.0 by Ghost in: [#850](https://codeberg.org/uzu/strudel/pulls/850)
+- 2023-12-07T09:35:14+01:00 Fix edge case with rehype-urls and trailing slashes in image file paths by Ghost in: [#849](https://codeberg.org/uzu/strudel/pulls/849)
+- 2023-12-06T23:02:31+01:00 Fix examples page, piano() and a few workshop imgs by Ghost in: [#848](https://codeberg.org/uzu/strudel/pulls/848)
+- 2023-12-06T22:30:59+01:00 fix: swatch png src by froos in: [#846](https://codeberg.org/uzu/strudel/pulls/846)
+- 2023-12-06T22:19:30+01:00 fix: missing hash for links starting with / by froos in: [#845](https://codeberg.org/uzu/strudel/pulls/845)
+- 2023-12-06T22:05:05+01:00 improve slashing + base href behavior by froos in: [#842](https://codeberg.org/uzu/strudel/pulls/842)
+- 2023-12-06T21:26:49+01:00 Add in fixes from my fork to slashocalypse branch by Ghost in: [#843](https://codeberg.org/uzu/strudel/pulls/843)
+- 2023-12-05T18:43:58+01:00 Prevent 404 on Algolia crawls by Ghost in: [#838](https://codeberg.org/uzu/strudel/pulls/838)
+- 2023-12-05T18:26:47+01:00 Multichannel audio by Ghost in: [#820](https://codeberg.org/uzu/strudel/pulls/820)
+- 2023-12-05T12:19:58+01:00 ADDS: JetBrains IDE files and directories to .gitignore by Ghost in: [#840](https://codeberg.org/uzu/strudel/pulls/840)
+- 2023-12-05T12:19:27+01:00 CHANGES: github action pnpm version from 7 to 8.3.1 by Ghost in: [#835](https://codeberg.org/uzu/strudel/pulls/835)
+- 2023-12-05T12:19:17+01:00 CHANGES: pin pnpm to version 8.3.1 by Ghost in: [#834](https://codeberg.org/uzu/strudel/pulls/834)
+- 2023-12-05T12:19:06+01:00 CHANGES: github action checkout v2 -> v4 by Ghost in: [#837](https://codeberg.org/uzu/strudel/pulls/837)
+- 2023-12-05T11:15:14+01:00 FIXES: palindrome abc -> abccba by Ghost in: [#831](https://codeberg.org/uzu/strudel/pulls/831)
+- 2023-12-02T09:43:50+01:00 Fix a typo by Ghost in: [#830](https://codeberg.org/uzu/strudel/pulls/830)
+
+## november 2023
+
+- 2023-11-30T10:42:41+01:00 Add and style algolia search by Ghost in: [#827](https://codeberg.org/uzu/strudel/pulls/827)
+- 2023-11-25T15:50:44+01:00 Hydra fixes and improvements by Ghost in: [#818](https://codeberg.org/uzu/strudel/pulls/818)
+- 2023-11-24T10:07:17+01:00 add options param to initHydra by Ghost in: [#808](https://codeberg.org/uzu/strudel/pulls/808)
+- 2023-11-24T09:57:02+01:00 Improve documentation for synonym functions by Ghost in: [#800](https://codeberg.org/uzu/strudel/pulls/800)
+- 2023-11-24T09:00:54+01:00 New noise type: "crackle" by Ghost in: [#806](https://codeberg.org/uzu/strudel/pulls/806)
+- 2023-11-18T21:18:16+01:00 Color hsl by froos in: [#815](https://codeberg.org/uzu/strudel/pulls/815)
+- 2023-11-17T23:18:23+01:00 fix: multiple repls by froos in: [#813](https://codeberg.org/uzu/strudel/pulls/813)
+- 2023-11-17T20:52:25+01:00 upstream changes by yaxu in: [#809](https://codeberg.org/uzu/strudel/pulls/809)
+- 2023-11-17T16:04:10+01:00 Add doc for euclidLegatoRot, wordfall and slider by Ghost in: [#801](https://codeberg.org/uzu/strudel/pulls/801)
+- 2023-11-17T14:42:58+01:00 add option to disable active line highlighting in Code Settings by Ghost in: [#804](https://codeberg.org/uzu/strudel/pulls/804)
+- 2023-11-17T14:37:52+01:00 tidal style d1 ... d9 functions + more by froos in: [#805](https://codeberg.org/uzu/strudel/pulls/805)
+- 2023-11-15T20:12:23+01:00 remove unwanted cm6 outline for strudelTheme by Ghost in: [#802](https://codeberg.org/uzu/strudel/pulls/802)
+- 2023-11-13T23:30:15+01:00 Create phaser effect by Ghost in: [#798](https://codeberg.org/uzu/strudel/pulls/798)
+- 2023-11-10T12:17:35+01:00 support multiple named serial connections, change default baudrate by yaxu in: [#551](https://codeberg.org/uzu/strudel/pulls/551)
+- 2023-11-09T09:27:57+01:00 Fix for #1. Enables named instruments for csoundm. by gogins in: [#662](https://codeberg.org/uzu/strudel/pulls/662)
+- 2023-11-09T09:26:45+01:00 Adding vibrato to Superdough sampler by Ghost in: [#706](https://codeberg.org/uzu/strudel/pulls/706)
+- 2023-11-09T08:46:03+01:00 Document pianoroll by Ghost in: [#784](https://codeberg.org/uzu/strudel/pulls/784)
+- 2023-11-09T08:45:29+01:00 Update first-effects.mdx by Ghost in: [#795](https://codeberg.org/uzu/strudel/pulls/795)
+- 2023-11-09T08:44:43+01:00 Update pattern-effects.mdx by Ghost in: [#796](https://codeberg.org/uzu/strudel/pulls/796)
+- 2023-11-09T08:43:50+01:00 Update recap.mdx by Ghost in: [#797](https://codeberg.org/uzu/strudel/pulls/797)
+- 2023-11-07T11:53:49+01:00 Update first-sounds.mdx by Ghost in: [#794](https://codeberg.org/uzu/strudel/pulls/794)
+- 2023-11-06T23:17:32+01:00 don't use anchor links for reference by froos in: [#791](https://codeberg.org/uzu/strudel/pulls/791)
+- 2023-11-06T22:40:44+01:00 samples loading shortcuts: by froos in: [#788](https://codeberg.org/uzu/strudel/pulls/788)
+- 2023-11-05T22:47:48+01:00 Fix scope pos + document by froos in: [#786](https://codeberg.org/uzu/strudel/pulls/786)
+- 2023-11-05T22:10:25+01:00 Implement optional hover tooltip with function documentation by Ghost in: [#783](https://codeberg.org/uzu/strudel/pulls/783)
+- 2023-11-05T16:46:06+01:00 Add function params in reference tab by Ghost in: [#785](https://codeberg.org/uzu/strudel/pulls/785)
+- 2023-11-05T12:42:00+01:00 fix: style issues by froos in: [#781](https://codeberg.org/uzu/strudel/pulls/781)
+- 2023-11-05T12:21:28+01:00 add xfade by froos in: [#780](https://codeberg.org/uzu/strudel/pulls/780)
+- 2023-11-02T09:30:26+01:00 Update to Astro 3 by froos in: [#775](https://codeberg.org/uzu/strudel/pulls/775)
+- 2023-11-02T08:57:14+01:00 add vscode bindings by Ghost in: [#773](https://codeberg.org/uzu/strudel/pulls/773)
+- 2023-11-02T08:31:30+01:00 fix: share copy to clipboard + alert by froos in: [#774](https://codeberg.org/uzu/strudel/pulls/774)
+- 2023-11-01T22:22:34+01:00 Fix chunk, add fastChunk and repeatCycles by yaxu in: [#712](https://codeberg.org/uzu/strudel/pulls/712)
+- 2023-11-01T22:12:49+01:00 Document adsr function by Ghost in: [#767](https://codeberg.org/uzu/strudel/pulls/767)
+- 2023-11-01T22:11:49+01:00 Add pick and squeeze functions by Ghost in: [#771](https://codeberg.org/uzu/strudel/pulls/771)
+- 2023-11-01T22:04:00+01:00 Update vite pwa by froos in: [#772](https://codeberg.org/uzu/strudel/pulls/772)
+
+## october 2023
+
+- 2023-10-28T23:55:07+02:00 replace strudel.tidalcycles.org with strudel.cc by froos in: [#768](https://codeberg.org/uzu/strudel/pulls/768)
+- 2023-10-28T12:52:37+02:00 Document striate function by Ghost in: [#766](https://codeberg.org/uzu/strudel/pulls/766)
+- 2023-10-27T23:06:20+02:00 fix zen mode logo overlap by froos in: [#760](https://codeberg.org/uzu/strudel/pulls/760)
+- 2023-10-27T23:01:18+02:00 fix: scale offset by froos in: [#764](https://codeberg.org/uzu/strudel/pulls/764)
+- 2023-10-27T21:59:35+02:00 Fix addivite synthesis phases by froos in: [#762](https://codeberg.org/uzu/strudel/pulls/762)
+- 2023-10-26T16:28:16+02:00 Hydra integration by froos in: [#759](https://codeberg.org/uzu/strudel/pulls/759)
+- 2023-10-26T14:14:27+02:00 add play function by froos in: [#758](https://codeberg.org/uzu/strudel/pulls/758)
+- 2023-10-26T13:11:00+02:00 Add shabda shortcut by Ghost in: [#740](https://codeberg.org/uzu/strudel/pulls/740)
+- 2023-10-26T13:07:23+02:00 mini notation: international alphabets support by Ghost in: [#751](https://codeberg.org/uzu/strudel/pulls/751)
+- 2023-10-22T23:00:52+02:00 hopefully fix trainling slashes bug by froos in: [#753](https://codeberg.org/uzu/strudel/pulls/753)
+- 2023-10-21T23:38:50+02:00 Fix krill build command in README by Ghost in: [#748](https://codeberg.org/uzu/strudel/pulls/748)
+- 2023-10-21T00:20:50+02:00 completely revert config mess by froos in: [#745](https://codeberg.org/uzu/strudel/pulls/745)
+- 2023-10-20T22:41:39+02:00 fix: try different trailing slash behavior by froos in: [#744](https://codeberg.org/uzu/strudel/pulls/744)
+- 2023-10-20T22:34:03+02:00 fix: trailing slash confusion by froos in: [#743](https://codeberg.org/uzu/strudel/pulls/743)
+- 2023-10-20T12:07:04+02:00 [Bug Fix] chooseWith: prevent pattern from stopping audio when selection is >= 1 or < 0 by Ghost in: [#741](https://codeberg.org/uzu/strudel/pulls/741)
+- 2023-10-20T11:34:26+02:00 Recipes by froos in: [#742](https://codeberg.org/uzu/strudel/pulls/742)
+- 2023-10-13T12:57:24+02:00 vite-vanilla-repl readme fix by froos in: [#737](https://codeberg.org/uzu/strudel/pulls/737)
+- 2023-10-10T00:17:59+02:00 Add support for using samples as impulse response buffers for the reverb by Ghost in: [#717](https://codeberg.org/uzu/strudel/pulls/717)
+- 2023-10-09T21:43:42+02:00 fix: reverb sampleRate by froos in: [#732](https://codeberg.org/uzu/strudel/pulls/732)
+- 2023-10-09T21:34:33+02:00 fix: reverb roomsize not required by froos in: [#731](https://codeberg.org/uzu/strudel/pulls/731)
+- 2023-10-08T13:54:52+02:00 Compressor by froos in: [#729](https://codeberg.org/uzu/strudel/pulls/729)
+- 2023-10-08T13:25:57+02:00 fix: hashes in urls by froos in: [#728](https://codeberg.org/uzu/strudel/pulls/728)
+- 2023-10-07T15:48:06+02:00 consume n with scale by froos in: [#727](https://codeberg.org/uzu/strudel/pulls/727)
+- 2023-10-07T00:27:21+02:00 fix: reverb regenerate loophole by froos in: [#726](https://codeberg.org/uzu/strudel/pulls/726)
+- 2023-10-05T00:04:17+02:00 Better convolution reverb by generating impulse responses by Ghost in: [#718](https://codeberg.org/uzu/strudel/pulls/718)
+- 2023-10-04T10:31:53+02:00 Slider afterthoughts by froos in: [#723](https://codeberg.org/uzu/strudel/pulls/723)
+- 2023-10-03T16:39:06+02:00 Add 'white', 'pink' and 'brown' oscillators + refactor synth by Ghost in: [#713](https://codeberg.org/uzu/strudel/pulls/713)
+- 2023-10-01T14:20:50+02:00 support mininotation '..' range operator, fixes #715 by yaxu in: [#716](https://codeberg.org/uzu/strudel/pulls/716)
+- 2023-10-01T14:15:09+02:00 widgets by froos in: [#714](https://codeberg.org/uzu/strudel/pulls/714)
+
+## september 2023
+
+- 2023-09-28T11:03:09+02:00 Midi in by froos in: [#699](https://codeberg.org/uzu/strudel/pulls/699)
+- 2023-09-27T22:53:49+02:00 add midi clock support by froos in: [#710](https://codeberg.org/uzu/strudel/pulls/710)
+- 2023-09-25T23:36:10+02:00 Update bournemouth.mdx by Ghost in: [#708](https://codeberg.org/uzu/strudel/pulls/708)
+- 2023-09-25T23:06:30+02:00 add dough function for raw dsp by froos in: [#707](https://codeberg.org/uzu/strudel/pulls/707)
+- 2023-09-17T15:53:27+02:00 Update tauri.yml workflow file by Ghost in: [#705](https://codeberg.org/uzu/strudel/pulls/705)
+- 2023-09-17T11:05:06+02:00 Adding vibrato to base oscillators by Ghost in: [#693](https://codeberg.org/uzu/strudel/pulls/693)
+- 2023-09-17T08:27:36+02:00 Adding loop points and thus wavetable synthesis by Ghost in: [#698](https://codeberg.org/uzu/strudel/pulls/698)
+- 2023-09-16T02:03:49+02:00 Adding filter envelopes and filter order selection by Ghost in: [#692](https://codeberg.org/uzu/strudel/pulls/692)
+- 2023-09-09T11:19:58+02:00 Add logging from tauri by Ghost in: [#697](https://codeberg.org/uzu/strudel/pulls/697)
+- 2023-09-05T00:33:54+02:00 Direct OSC Support in Tauri by Ghost in: [#694](https://codeberg.org/uzu/strudel/pulls/694)
+- 2023-09-03T22:19:22+02:00 fix MIDI CC messages by Ghost in: [#690](https://codeberg.org/uzu/strudel/pulls/690)
+- 2023-09-03T10:22:15+02:00 add sleep timer + improve message iterating by Ghost in: [#688](https://codeberg.org/uzu/strudel/pulls/688)
+
+## august 2023
+
+- 2023-08-31T13:00:31+02:00 ZZFX Synth support by Ghost in: [#684](https://codeberg.org/uzu/strudel/pulls/684)
+- 2023-08-31T12:36:37+02:00 Wave Selection and Global Envelope on the FM Synth Modulator by Ghost in: [#683](https://codeberg.org/uzu/strudel/pulls/683)
+- 2023-08-31T05:52:17+02:00 Create Midi Integration for Tauri Desktop app by Ghost in: [#685](https://codeberg.org/uzu/strudel/pulls/685)
+- 2023-08-31T05:32:16+02:00 teletext theme + fonts by froos in: [#681](https://codeberg.org/uzu/strudel/pulls/681)
+- 2023-08-31T05:20:55+02:00 control osc partial count with n by froos in: [#674](https://codeberg.org/uzu/strudel/pulls/674)
+- 2023-08-27T22:18:06+02:00 add emoji support by froos in: [#680](https://codeberg.org/uzu/strudel/pulls/680)
+- 2023-08-27T16:12:32+02:00 Pianoroll improvements by froos in: [#679](https://codeberg.org/uzu/strudel/pulls/679)
+- 2023-08-26T21:22:17+02:00 Scope by froos in: [#677](https://codeberg.org/uzu/strudel/pulls/677)
+- 2023-08-23T21:50:50+02:00 Midi time fixes by Ghost in: [#668](https://codeberg.org/uzu/strudel/pulls/668)
+- 2023-08-20T23:19:08+02:00 basic fm by froos in: [#669](https://codeberg.org/uzu/strudel/pulls/669)
+- 2023-08-18T23:56:20+02:00 togglable panel position by froos in: [#667](https://codeberg.org/uzu/strudel/pulls/667)
+- 2023-08-18T15:59:20+02:00 fix osc bundle timestamp glitches caused by drifting clock by Ghost in: [#666](https://codeberg.org/uzu/strudel/pulls/666)
+- 2023-08-17T11:36:07+02:00 superdough: encapsulates web audio output by froos in: [#664](https://codeberg.org/uzu/strudel/pulls/664)
+- 2023-08-11T00:06:21+02:00 fix: always run previous trigger by froos in: [#660](https://codeberg.org/uzu/strudel/pulls/660)
+- 2023-08-10T23:54:58+02:00 fix: welcome message for latestCode by froos in: [#659](https://codeberg.org/uzu/strudel/pulls/659)
+- 2023-08-07T07:45:26+02:00 [Bug Fix] Midi: Don't treat note 0 as false by Ghost in: [#657](https://codeberg.org/uzu/strudel/pulls/657)
+
+## july 2023
+
+- 2023-07-29T09:06:18+02:00 [Bug Fix] Account for numeral notation when converting to midi by Ghost in: [#656](https://codeberg.org/uzu/strudel/pulls/656)
+- 2023-07-23T22:18:49+02:00 ireal voicings by froos in: [#653](https://codeberg.org/uzu/strudel/pulls/653)
+- 2023-07-22T09:30:21+02:00 Understand pitch by froos in: [#652](https://codeberg.org/uzu/strudel/pulls/652)
+- 2023-07-17T23:42:59+02:00 update vitest by froos in: [#651](https://codeberg.org/uzu/strudel/pulls/651)
+- 2023-07-17T23:34:33+02:00 stateless voicings + tonleiter lib by froos in: [#647](https://codeberg.org/uzu/strudel/pulls/647)
+- 2023-07-17T17:57:17+02:00 FIXES: TODO in rotateChroma by Ghost in: [#650](https://codeberg.org/uzu/strudel/pulls/650)
+- 2023-07-10T19:07:45+02:00 slice: list mode by froos in: [#645](https://codeberg.org/uzu/strudel/pulls/645)
+- 2023-07-04T23:50:30+02:00 Delete old packages by froos in: [#639](https://codeberg.org/uzu/strudel/pulls/639)
+- 2023-07-04T23:38:42+02:00 Adaptive Highlighting by froos in: [#634](https://codeberg.org/uzu/strudel/pulls/634)
+- 2023-07-04T21:55:57+02:00 More work on highlight IDs by Ghost in: [#636](https://codeberg.org/uzu/strudel/pulls/636)
+- 2023-07-04T18:44:48+02:00 snapshot tests: sort haps by part by froos in: [#637](https://codeberg.org/uzu/strudel/pulls/637)
+
+## juny 2023
+
+- 2023-06-30T22:47:40+02:00 fix: update canvas size on window resize by froos in: [#631](https://codeberg.org/uzu/strudel/pulls/631)
+- 2023-06-30T22:45:41+02:00 fix: out of range error by froos in: [#630](https://codeberg.org/uzu/strudel/pulls/630)
+- 2023-06-30T08:14:40+02:00 fix: midi clock drift by froos in: [#627](https://codeberg.org/uzu/strudel/pulls/627)
+- 2023-06-29T22:02:28+02:00 desktop: play samples from disk by froos in: [#621](https://codeberg.org/uzu/strudel/pulls/621)
+- 2023-06-29T21:59:43+02:00 cps dependent functions by froos in: [#620](https://codeberg.org/uzu/strudel/pulls/620)
+- 2023-06-26T22:45:04+02:00 Fix typo on packages.mdx by Ghost in: [#520](https://codeberg.org/uzu/strudel/pulls/520)
+- 2023-06-26T22:35:02+02:00 patterning ui settings by froos in: [#606](https://codeberg.org/uzu/strudel/pulls/606)
+- 2023-06-26T22:32:46+02:00 add spiral viz by froos in: [#614](https://codeberg.org/uzu/strudel/pulls/614)
+- 2023-06-26T22:17:46+02:00 tauri desktop app by Ghost in: [#613](https://codeberg.org/uzu/strudel/pulls/613)
+- 2023-06-23T09:59:43+02:00 fix: doc links by froos in: [#612](https://codeberg.org/uzu/strudel/pulls/612)
+- 2023-06-23T09:55:18+02:00 clip now works like legato in tidal by froos in: [#598](https://codeberg.org/uzu/strudel/pulls/598)
+- 2023-06-18T10:36:19+02:00 fix: flatten scale lists by froos in: [#605](https://codeberg.org/uzu/strudel/pulls/605)
+- 2023-06-18T10:36:17+02:00 tonal fixes by froos in: [#607](https://codeberg.org/uzu/strudel/pulls/607)
+- 2023-06-15T12:51:40+02:00 editor: enable line wrapping by Ghost in: [#581](https://codeberg.org/uzu/strudel/pulls/581)
+- 2023-06-15T10:22:46+02:00 add ratio function by froos in: [#602](https://codeberg.org/uzu/strudel/pulls/602)
+- 2023-06-12T23:24:29+02:00 enable auto-completion by Ghost in: [#588](https://codeberg.org/uzu/strudel/pulls/588)
+- 2023-06-11T22:04:17+02:00 improve cursor by froos in: [#597](https://codeberg.org/uzu/strudel/pulls/597)
+- 2023-06-11T20:00:45+02:00 Solmization added by Ghost in: [#570](https://codeberg.org/uzu/strudel/pulls/570)
+- 2023-06-11T19:45:00+02:00 fix: division by zero by froos in: [#591](https://codeberg.org/uzu/strudel/pulls/591)
+- 2023-06-11T19:44:43+02:00 fix: allow f for flat notes like tidal by froos in: [#593](https://codeberg.org/uzu/strudel/pulls/593)
+- 2023-06-11T19:44:41+02:00 Fix option dot by froos in: [#596](https://codeberg.org/uzu/strudel/pulls/596)
+- 2023-06-09T21:02:12+02:00 New Workshop by froos in: [#587](https://codeberg.org/uzu/strudel/pulls/587)
+- 2023-06-09T17:31:58+02:00 Music metadata by Ghost in: [#580](https://codeberg.org/uzu/strudel/pulls/580)
+- 2023-06-08T09:33:34+02:00 learn/tonal: fix typo in "scaleTran[s]pose" by Ghost in: [#585](https://codeberg.org/uzu/strudel/pulls/585)
+- 2023-06-07T20:19:11+02:00 repl: add option to display line numbers by Ghost in: [#582](https://codeberg.org/uzu/strudel/pulls/582)
+- 2023-06-05T21:35:49+02:00 Vanilla JS Refactoring by froos in: [#563](https://codeberg.org/uzu/strudel/pulls/563)
+
+## may 2023
+
+- 2023-05-05T08:34:37+02:00 Patchday by froos in: [#559](https://codeberg.org/uzu/strudel/pulls/559)
+- 2023-05-02T21:48:33+02:00 add basic triads and guidetone voicings by froos in: [#557](https://codeberg.org/uzu/strudel/pulls/557)
+
+## april 2023
+
+- 2023-04-28T12:46:56+02:00 fix: make soundfonts import dynamic by froos in: [#556](https://codeberg.org/uzu/strudel/pulls/556)
+- 2023-04-22T15:43:22+02:00 fix: colorable highlighting by froos in: [#553](https://codeberg.org/uzu/strudel/pulls/553)
+- 2023-04-06T00:11:02+02:00 fix: load soundfonts in prebake by froos in: [#550](https://codeberg.org/uzu/strudel/pulls/550)
+
+## march 2023
+
+- 2023-03-29T22:23:07+02:00 fix: reset time on stop by froos in: [#548](https://codeberg.org/uzu/strudel/pulls/548)
+- 2023-03-29T22:16:38+02:00 fix: allow whitespace at the end of a mini pattern by froos in: [#547](https://codeberg.org/uzu/strudel/pulls/547)
+- 2023-03-24T22:10:56+01:00 add firacode font by froos in: [#544](https://codeberg.org/uzu/strudel/pulls/544)
+- 2023-03-24T12:54:20+01:00 feat: add loader bar to animate loading state by froos in: [#542](https://codeberg.org/uzu/strudel/pulls/542)
+- 2023-03-23T22:39:27+01:00 do not reset cps before eval #517 by froos in: [#539](https://codeberg.org/uzu/strudel/pulls/539)
+- 2023-03-23T22:27:31+01:00 improve initial loading + wait before eval by froos in: [#538](https://codeberg.org/uzu/strudel/pulls/538)
+- 2023-03-23T21:40:20+01:00 fix period key for dvorak + remove duplicated code by froos in: [#537](https://codeberg.org/uzu/strudel/pulls/537)
+- 2023-03-23T11:44:56+01:00 Update lerna by froos in: [#535](https://codeberg.org/uzu/strudel/pulls/535)
+- 2023-03-23T10:21:55+01:00 feat: add freq support to gm soundfonts by froos in: [#534](https://codeberg.org/uzu/strudel/pulls/534)
+- 2023-03-23T10:18:58+01:00 Maintain random seed state in parser, not globally by Ghost in: [#531](https://codeberg.org/uzu/strudel/pulls/531)
+- 2023-03-21T22:35:18+01:00 FIXES: alias pm for polymeter by Ghost in: [#527](https://codeberg.org/uzu/strudel/pulls/527)
+- 2023-03-21T22:29:07+01:00 fix(footer): fix link to tidalcycles by julienbouquillon in: [#529](https://codeberg.org/uzu/strudel/pulls/529)
+- 2023-03-18T20:25:21+01:00 Update intro.mdx by Ghost in: [#525](https://codeberg.org/uzu/strudel/pulls/525)
+- 2023-03-18T20:24:38+01:00 Update samples.mdx by Ghost in: [#524](https://codeberg.org/uzu/strudel/pulls/524)
+- 2023-03-17T09:03:11+01:00 fix: envelopes in chrome by froos in: [#521](https://codeberg.org/uzu/strudel/pulls/521)
+- 2023-03-16T16:13:30+01:00 registerSound API + improved sounds tab + regroup soundfonts by froos in: [#516](https://codeberg.org/uzu/strudel/pulls/516)
+- 2023-03-14T21:54:53+01:00 add 2 illegible fonts by froos in: [#518](https://codeberg.org/uzu/strudel/pulls/518)
+- 2023-03-06T22:55:00+01:00 Update README.md by Ghost in: [#474](https://codeberg.org/uzu/strudel/pulls/474)
+- 2023-03-05T14:52:30+01:00 add arrange function by froos in: [#508](https://codeberg.org/uzu/strudel/pulls/508)
+- 2023-03-05T14:29:08+01:00 update react to 18 by froos in: [#514](https://codeberg.org/uzu/strudel/pulls/514)
+- 2023-03-04T19:06:18+01:00 Support list syntax in mininotation by yaxu in: [#512](https://codeberg.org/uzu/strudel/pulls/512)
+- 2023-03-03T12:40:23+01:00 can now use : as a replacement for space in scales by froos in: [#502](https://codeberg.org/uzu/strudel/pulls/502)
+- 2023-03-02T15:44:41+01:00 Reinstate slice and splice by yaxu in: [#500](https://codeberg.org/uzu/strudel/pulls/500)
+- 2023-03-02T14:49:30+01:00 fix: nano-repl highlighting by froos in: [#501](https://codeberg.org/uzu/strudel/pulls/501)
+- 2023-03-02T14:17:13+01:00 Add control aliases by yaxu in: [#497](https://codeberg.org/uzu/strudel/pulls/497)
+- 2023-03-01T09:27:27+01:00 implement cps in scheduler by froos in: [#493](https://codeberg.org/uzu/strudel/pulls/493)
+
+## february 2023
+
+- 2023-02-28T23:06:29+01:00 react style fixes by froos in: [#491](https://codeberg.org/uzu/strudel/pulls/491)
+- 2023-02-28T22:57:20+01:00 refactor react package by froos in: [#490](https://codeberg.org/uzu/strudel/pulls/490)
+- 2023-02-27T23:47:34+01:00 add algolia creds + optimize sidebar for crawling by froos in: [#488](https://codeberg.org/uzu/strudel/pulls/488)
+- 2023-02-27T19:28:10+01:00 fix app height by froos in: [#485](https://codeberg.org/uzu/strudel/pulls/485)
+- 2023-02-27T16:04:21+01:00 Revert "Another attempt at composable functions - WIP (#390)" by froos in: [#484](https://codeberg.org/uzu/strudel/pulls/484)
+- 2023-02-27T15:45:20+01:00 Update mini-notation.mdx by yaxu in: [#365](https://codeberg.org/uzu/strudel/pulls/365)
+- 2023-02-27T12:52:09+01:00 docs: packages + offline by froos in: [#482](https://codeberg.org/uzu/strudel/pulls/482)
+- 2023-02-25T14:26:49+01:00 Fix array args by froos in: [#480](https://codeberg.org/uzu/strudel/pulls/480)
+- 2023-02-25T12:33:22+01:00 midi cc support by froos in: [#478](https://codeberg.org/uzu/strudel/pulls/478)
+- 2023-02-23T00:11:05+01:00 fix: hash links by froos in: [#473](https://codeberg.org/uzu/strudel/pulls/473)
+- 2023-02-22T22:54:39+01:00 settings tab with vim / emacs modes + additional themes and fonts by froos in: [#467](https://codeberg.org/uzu/strudel/pulls/467)
+- 2023-02-22T22:53:22+01:00 Update input-output.mdx by Ghost in: [#471](https://codeberg.org/uzu/strudel/pulls/471)
+- 2023-02-22T22:52:50+01:00 FIXES: freqs instead of pitches by Ghost in: [#464](https://codeberg.org/uzu/strudel/pulls/464)
+- 2023-02-22T20:01:00+01:00 fix: osc should not return a promise by froos in: [#472](https://codeberg.org/uzu/strudel/pulls/472)
+- 2023-02-22T12:51:31+01:00 slice and splice by yaxu in: [#466](https://codeberg.org/uzu/strudel/pulls/466)
+- 2023-02-18T01:00:19+01:00 weave and weaveWith by yaxu in: [#465](https://codeberg.org/uzu/strudel/pulls/465)
+- 2023-02-17T00:15:21+01:00 Composable functions by yaxu in: [#390](https://codeberg.org/uzu/strudel/pulls/390)
+- 2023-02-16T20:38:45+01:00 FIXES: Warning about jsxBracketSameLine deprecation by Ghost in: [#461](https://codeberg.org/uzu/strudel/pulls/461)
+- 2023-02-14T22:11:02+01:00 Update synths.mdx by Ghost in: [#438](https://codeberg.org/uzu/strudel/pulls/438)
+- 2023-02-14T19:54:42+01:00 Update mini-notation.mdx by Ghost in: [#437](https://codeberg.org/uzu/strudel/pulls/437)
+- 2023-02-14T19:54:25+01:00 Update code.mdx by Ghost in: [#436](https://codeberg.org/uzu/strudel/pulls/436)
+- 2023-02-13T00:43:29+01:00 Fix anchors by froos in: [#433](https://codeberg.org/uzu/strudel/pulls/433)
+- 2023-02-11T21:02:11+01:00 autocomplete preparations by froos in: [#427](https://codeberg.org/uzu/strudel/pulls/427)
+- 2023-02-10T23:14:48+01:00 Themes by froos in: [#431](https://codeberg.org/uzu/strudel/pulls/431)
+- 2023-02-09T19:22:56+01:00 minirepl: add keyboard shortcuts by froos in: [#429](https://codeberg.org/uzu/strudel/pulls/429)
+- 2023-02-09T08:56:42+01:00 add cdn.freesound to cache list by froos in: [#425](https://codeberg.org/uzu/strudel/pulls/425)
+- 2023-02-08T20:36:00+01:00 add more offline caching by froos in: [#421](https://codeberg.org/uzu/strudel/pulls/421)
+- 2023-02-07T22:08:01+01:00 add caching strategy for missing file types + cache all samples loaded from github by froos in: [#419](https://codeberg.org/uzu/strudel/pulls/419)
+- 2023-02-06T23:29:57+01:00 PWA with offline support by froos in: [#417](https://codeberg.org/uzu/strudel/pulls/417)
+- 2023-02-05T17:27:32+01:00 improve samples doc by froos in: [#411](https://codeberg.org/uzu/strudel/pulls/411)
+- 2023-02-05T17:27:10+01:00 google gtfo by froos in: [#413](https://codeberg.org/uzu/strudel/pulls/413)
+- 2023-02-05T16:27:59+01:00 improve effects doc by froos in: [#409](https://codeberg.org/uzu/strudel/pulls/409)
+- 2023-02-05T14:56:03+01:00 Update effects.mdx by Ghost in: [#410](https://codeberg.org/uzu/strudel/pulls/410)
+- 2023-02-03T19:54:47+01:00 add shabda doc by froos in: [#407](https://codeberg.org/uzu/strudel/pulls/407)
+- 2023-02-02T21:45:56+01:00 fix: share url on subpath by froos in: [#405](https://codeberg.org/uzu/strudel/pulls/405)
+- 2023-02-02T21:35:45+01:00 update csound + fix sound output by froos in: [#404](https://codeberg.org/uzu/strudel/pulls/404)
+- 2023-02-02T19:53:36+01:00 pin @csound/browser to 6.18.3 + bump by froos in: [#403](https://codeberg.org/uzu/strudel/pulls/403)
+- 2023-02-01T22:47:27+01:00 release webaudio by froos in: [#400](https://codeberg.org/uzu/strudel/pulls/400)
+- 2023-02-01T22:45:16+01:00 can now await initAudio + initAudioOnFirstClick by froos in: [#399](https://codeberg.org/uzu/strudel/pulls/399)
+- 2023-02-01T22:32:18+01:00 fix: minirepl styles by froos in: [#398](https://codeberg.org/uzu/strudel/pulls/398)
+- 2023-02-01T22:17:19+01:00 proper builds + use pnpm workspaces by froos in: [#396](https://codeberg.org/uzu/strudel/pulls/396)
+- 2023-02-01T16:49:55+01:00 add pattern methods hurry, press and pressBy by yaxu in: [#397](https://codeberg.org/uzu/strudel/pulls/397)
+
+## january 2023
+
+- 2023-01-27T14:40:40+01:00 Add tidal-drum-patterns to examples by Ghost in: [#379](https://codeberg.org/uzu/strudel/pulls/379)
+- 2023-01-27T14:39:56+01:00 add ribbon + test + docs by froos in: [#388](https://codeberg.org/uzu/strudel/pulls/388)
+- 2023-01-27T12:10:37+01:00 Notes are not essential :) by yaxu in: [#393](https://codeberg.org/uzu/strudel/pulls/393)
+- 2023-01-21T17:18:13+01:00 document csound by froos in: [#391](https://codeberg.org/uzu/strudel/pulls/391)
+- 2023-01-19T12:04:51+01:00 Rename a to angle by froos in: [#387](https://codeberg.org/uzu/strudel/pulls/387)
+- 2023-01-19T11:49:39+01:00 add run + test + docs by froos in: [#386](https://codeberg.org/uzu/strudel/pulls/386)
+- 2023-01-19T11:32:56+01:00 docs: use note instead of n to mitigate confusion by froos in: [#385](https://codeberg.org/uzu/strudel/pulls/385)
+- 2023-01-18T17:10:09+01:00 update my-patterns instructions by froos in: [#384](https://codeberg.org/uzu/strudel/pulls/384)
+- 2023-01-15T23:19:43+01:00 Draw fixes by froos in: [#377](https://codeberg.org/uzu/strudel/pulls/377)
+- 2023-01-14T11:07:08+01:00 improve new draw logic by froos in: [#372](https://codeberg.org/uzu/strudel/pulls/372)
+- 2023-01-12T14:40:59+01:00 document more functions + change arp join by froos in: [#369](https://codeberg.org/uzu/strudel/pulls/369)
+- 2023-01-10T00:03:47+01:00 add https to url by Ghost in: [#364](https://codeberg.org/uzu/strudel/pulls/364)
+- 2023-01-09T23:37:34+01:00 doc structuring by froos in: [#360](https://codeberg.org/uzu/strudel/pulls/360)
+- 2023-01-09T23:23:28+01:00 Support for multiple mininotation operators by yaxu in: [#350](https://codeberg.org/uzu/strudel/pulls/350)
+- 2023-01-09T00:40:15+01:00 Fix .out(), renaming webaudio's out() to webaudio() by yaxu in: [#361](https://codeberg.org/uzu/strudel/pulls/361)
+- 2023-01-06T22:02:31+01:00 docs: tidal comparison + add global fx + add missing sampler fx by froos in: [#356](https://codeberg.org/uzu/strudel/pulls/356)
+- 2023-01-06T12:31:32+01:00 Fix Bjorklund by yaxu in: [#343](https://codeberg.org/uzu/strudel/pulls/343)
+- 2023-01-04T20:29:35+01:00 Fix prebake base path by froos in: [#345](https://codeberg.org/uzu/strudel/pulls/345)
+- 2023-01-04T19:55:49+01:00 fixes #346 by froos in: [#347](https://codeberg.org/uzu/strudel/pulls/347)
+- 2023-01-02T21:28:07+01:00 Patternify euclid, fast, slow and polymeter step parameters in mininotation by yaxu in: [#341](https://codeberg.org/uzu/strudel/pulls/341)
+- 2023-01-02T00:30:16+01:00 more animate functions + mini repl fix by froos in: [#340](https://codeberg.org/uzu/strudel/pulls/340)
+- 2023-01-01T12:34:11+01:00 move /my-patterns to /swatch by yaxu in: [#338](https://codeberg.org/uzu/strudel/pulls/338)
+- 2023-01-01T12:22:55+01:00 animation options by froos in: [#337](https://codeberg.org/uzu/strudel/pulls/337)
+
+## december 2022
+
+- 2022-12-31T22:42:49+01:00 Tidy parser, implement polymeters by yaxu in: [#336](https://codeberg.org/uzu/strudel/pulls/336)
+- 2022-12-31T16:51:53+01:00 animate mvp by froos in: [#335](https://codeberg.org/uzu/strudel/pulls/335)
+- 2022-12-30T20:16:10+01:00 testing + docs docs by froos in: [#334](https://codeberg.org/uzu/strudel/pulls/334)
+- 2022-12-29T21:11:16+01:00 Embed mode improvements by froos in: [#333](https://codeberg.org/uzu/strudel/pulls/333)
+- 2022-12-29T14:06:20+01:00 fix: can now multiply floats in mini notation by froos in: [#332](https://codeberg.org/uzu/strudel/pulls/332)
+- 2022-12-29T13:50:07+01:00 improve displaying 's' in pianoroll by froos in: [#331](https://codeberg.org/uzu/strudel/pulls/331)
+- 2022-12-28T17:35:35+01:00 my-patterns: fix paths + update readme by froos in: [#330](https://codeberg.org/uzu/strudel/pulls/330)
+- 2022-12-28T17:11:40+01:00 my-patterns build + deploy by froos in: [#329](https://codeberg.org/uzu/strudel/pulls/329)
+- 2022-12-28T15:43:31+01:00 add my-patterns by froos in: [#328](https://codeberg.org/uzu/strudel/pulls/328)
+- 2022-12-28T14:47:14+01:00 add examples route by froos in: [#327](https://codeberg.org/uzu/strudel/pulls/327)
+- 2022-12-28T14:44:31+01:00 fix: workaround Object.assign globalThis by froos in: [#326](https://codeberg.org/uzu/strudel/pulls/326)
+- 2022-12-26T23:29:47+01:00 mini repl improvements by froos in: [#324](https://codeberg.org/uzu/strudel/pulls/324)
+- 2022-12-26T23:00:34+01:00 support notes without octave by froos in: [#323](https://codeberg.org/uzu/strudel/pulls/323)
+- 2022-12-26T12:37:36+01:00 tutorial updates by Ghost in: [#320](https://codeberg.org/uzu/strudel/pulls/320)
+- 2022-12-23T18:26:30+01:00 Reference tab sort by froos in: [#318](https://codeberg.org/uzu/strudel/pulls/318)
+- 2022-12-23T00:49:56+01:00 Astro build by froos in: [#315](https://codeberg.org/uzu/strudel/pulls/315)
+- 2022-12-19T21:02:37+01:00 object support for .scale by froos in: [#307](https://codeberg.org/uzu/strudel/pulls/307)
+- 2022-12-19T21:02:22+01:00 Jsdoc component by froos in: [#312](https://codeberg.org/uzu/strudel/pulls/312)
+- 2022-12-19T20:31:46+01:00 fix: copy share link to clipboard was broken for some browers by froos in: [#311](https://codeberg.org/uzu/strudel/pulls/311)
+- 2022-12-19T12:11:24+01:00 ICLC2023 paper WIP by yaxu in: [#306](https://codeberg.org/uzu/strudel/pulls/306)
+- 2022-12-15T21:23:22+01:00 support freq in pianoroll by froos in: [#308](https://codeberg.org/uzu/strudel/pulls/308)
+- 2022-12-13T22:07:27+01:00 Updated csoundm to use the register facility . by gogins in: [#303](https://codeberg.org/uzu/strudel/pulls/303)
+- 2022-12-13T21:57:03+01:00 add lint + prettier check before test by froos in: [#305](https://codeberg.org/uzu/strudel/pulls/305)
+- 2022-12-13T21:21:44+01:00 add freq support to sampler by froos in: [#301](https://codeberg.org/uzu/strudel/pulls/301)
+- 2022-12-12T00:48:41+01:00 fix whitespace trimming by froos in: [#300](https://codeberg.org/uzu/strudel/pulls/300)
+- 2022-12-12T00:21:53+01:00 .defragmentHaps() for merging touching haps that share a whole and value by yaxu in: [#299](https://codeberg.org/uzu/strudel/pulls/299)
+- 2022-12-11T23:17:49+01:00 remove whitespace from highlighted region by froos in: [#298](https://codeberg.org/uzu/strudel/pulls/298)
+- 2022-12-11T22:03:26+01:00 update vitest by froos in: [#297](https://codeberg.org/uzu/strudel/pulls/297)
+- 2022-12-11T21:44:16+01:00 can now add bare numbers to numeral object props by froos in: [#287](https://codeberg.org/uzu/strudel/pulls/287)
+- 2022-12-11T21:27:58+01:00 Move stuff to new register function by froos in: [#295](https://codeberg.org/uzu/strudel/pulls/295)
+- 2022-12-11T20:07:12+01:00 add prettier task by froos in: [#296](https://codeberg.org/uzu/strudel/pulls/296)
+- 2022-12-10T15:39:04+01:00 Reorganise pattern.mjs with a 'toplevel first' regime by yaxu in: [#286](https://codeberg.org/uzu/strudel/pulls/286)
+- 2022-12-10T11:56:16+01:00 Fancy hap show, include part in snapshots by yaxu in: [#291](https://codeberg.org/uzu/strudel/pulls/291)
+- 2022-12-07T20:07:55+01:00 Switch 'operators' from .whatHow to .what.how by yaxu in: [#285](https://codeberg.org/uzu/strudel/pulls/285)
+- 2022-12-04T12:51:01+01:00 implement collect + arp function by froos in: [#281](https://codeberg.org/uzu/strudel/pulls/281)
+- 2022-12-02T13:38:27+01:00 do not recompile orc by froos in: [#278](https://codeberg.org/uzu/strudel/pulls/278)
+- 2022-12-02T12:49:26+01:00 add basic csound output by froos in: [#275](https://codeberg.org/uzu/strudel/pulls/275)
+- 2022-12-02T12:18:41+01:00 add licenses / credits to all tunes + remove some by froos in: [#277](https://codeberg.org/uzu/strudel/pulls/277)
+- 2022-12-02T11:45:02+01:00 Support sending CRC16 bytes with serial messages by yaxu in: [#276](https://codeberg.org/uzu/strudel/pulls/276)
+
+## november 2022
+
+- 2022-11-29T23:41:39+01:00 release version bumps by froos in: [#273](https://codeberg.org/uzu/strudel/pulls/273)
+- 2022-11-29T23:34:50+01:00 add eslint by froos in: [#271](https://codeberg.org/uzu/strudel/pulls/271)
+- 2022-11-29T23:34:26+01:00 tonal update with fixed memory leak by froos in: [#272](https://codeberg.org/uzu/strudel/pulls/272)
+- 2022-11-22T09:51:26+01:00 Tidying up core by yaxu in: [#256](https://codeberg.org/uzu/strudel/pulls/256)
+- 2022-11-21T22:15:48+01:00 fix performance bottleneck by froos in: [#266](https://codeberg.org/uzu/strudel/pulls/266)
+- 2022-11-17T11:08:38+01:00 fix tutorial bugs by froos in: [#263](https://codeberg.org/uzu/strudel/pulls/263)
+- 2022-11-16T13:15:28+01:00 Binaries by froos in: [#254](https://codeberg.org/uzu/strudel/pulls/254)
+- 2022-11-13T20:20:32+01:00 Repl refactoring by froos in: [#255](https://codeberg.org/uzu/strudel/pulls/255)
+- 2022-11-08T23:35:11+01:00 Webaudio build by froos in: [#250](https://codeberg.org/uzu/strudel/pulls/250)
+- 2022-11-08T22:43:32+01:00 new transpiler based on acorn by froos in: [#249](https://codeberg.org/uzu/strudel/pulls/249)
+- 2022-11-06T19:03:19+01:00 General purpose scheduler by froos in: [#248](https://codeberg.org/uzu/strudel/pulls/248)
+- 2022-11-06T11:05:23+01:00 snapshot tests on shared snippets by froos in: [#243](https://codeberg.org/uzu/strudel/pulls/243)
+- 2022-11-06T11:03:42+01:00 Some tunes by froos in: [#247](https://codeberg.org/uzu/strudel/pulls/247)
+- 2022-11-06T00:37:11+01:00 patchday by froos in: [#246](https://codeberg.org/uzu/strudel/pulls/246)
+- 2022-11-04T20:28:23+01:00 Readme + TLC by froos in: [#244](https://codeberg.org/uzu/strudel/pulls/244)
+- 2022-11-03T15:16:04+01:00 in source example tests by froos in: [#242](https://codeberg.org/uzu/strudel/pulls/242)
+- 2022-11-02T23:16:43+01:00 feat: support github: links by froos in: [#240](https://codeberg.org/uzu/strudel/pulls/240)
+- 2022-11-02T21:26:44+01:00 Load samples from url by froos in: [#239](https://codeberg.org/uzu/strudel/pulls/239)
+- 2022-11-02T11:42:32+01:00 Object arithmetic by froos in: [#238](https://codeberg.org/uzu/strudel/pulls/238)
+- 2022-11-01T00:36:14+01:00 Tidal drum machines by froos in: [#237](https://codeberg.org/uzu/strudel/pulls/237)
+- 2022-10-31T21:39:23+01:00 fx on stereo speakers by froos in: [#236](https://codeberg.org/uzu/strudel/pulls/236)
+
+## october 2022
+
+- 2022-10-30T19:10:33+01:00 add vcsl sample library by froos in: [#235](https://codeberg.org/uzu/strudel/pulls/235)
+- 2022-10-30T00:23:10+02:00 Fix zero length queries WIP by yaxu in: [#234](https://codeberg.org/uzu/strudel/pulls/234)
+- 2022-10-29T17:54:05+02:00 Out by default by froos in: [#232](https://codeberg.org/uzu/strudel/pulls/232)
+- 2022-10-26T23:53:49+02:00 Patternify range by yaxu in: [#231](https://codeberg.org/uzu/strudel/pulls/231)
+- 2022-10-26T21:42:12+02:00 Just another docs branch by froos in: [#228](https://codeberg.org/uzu/strudel/pulls/228)
+- 2022-10-26T21:41:12+02:00 Refactor tunes away from tone by froos in: [#230](https://codeberg.org/uzu/strudel/pulls/230)
+- 2022-10-20T09:26:28+02:00 Core util tests by Ghost in: [#226](https://codeberg.org/uzu/strudel/pulls/226)
+- 2022-10-06T22:35:45+02:00 fix fastgap for events that go across cycle boundaries by yaxu in: [#225](https://codeberg.org/uzu/strudel/pulls/225)
+
+## september 2022
+
+- 2022-09-25T21:15:36+02:00 Reverb by froos in: [#224](https://codeberg.org/uzu/strudel/pulls/224)
+- 2022-09-25T00:27:26+02:00 focus tweak for squeezeJoin - another go at fixing #216 by yaxu in: [#221](https://codeberg.org/uzu/strudel/pulls/221)
+- 2022-09-24T23:17:21+02:00 support negative speeds by froos in: [#222](https://codeberg.org/uzu/strudel/pulls/222)
+- 2022-09-24T21:55:15+02:00 Feedback Delay by froos in: [#213](https://codeberg.org/uzu/strudel/pulls/213)
+- 2022-09-23T12:06:17+02:00 Fix squeeze join by yaxu in: [#220](https://codeberg.org/uzu/strudel/pulls/220)
+- 2022-09-22T21:23:11+02:00 encapsulate webaudio output by froos in: [#219](https://codeberg.org/uzu/strudel/pulls/219)
+- 2022-09-22T19:18:18+02:00 samples now have envelopes by froos in: [#218](https://codeberg.org/uzu/strudel/pulls/218)
+- 2022-09-22T00:03:30+02:00 sampler features + fixes by froos in: [#217](https://codeberg.org/uzu/strudel/pulls/217)
+- 2022-09-19T23:32:55+02:00 Just another docs PR by froos in: [#215](https://codeberg.org/uzu/strudel/pulls/215)
+- 2022-09-17T23:47:43+02:00 Even more docs by froos in: [#212](https://codeberg.org/uzu/strudel/pulls/212)
+- 2022-09-17T15:36:53+02:00 Webaudio guide by froos in: [#207](https://codeberg.org/uzu/strudel/pulls/207)
+- 2022-09-16T00:21:29+02:00 Coarse crush shape by froos in: [#205](https://codeberg.org/uzu/strudel/pulls/205)
+- 2022-09-15T21:04:28+02:00 add vowel to .out by froos in: [#201](https://codeberg.org/uzu/strudel/pulls/201)
+- 2022-09-15T16:55:52+02:00 add rollup-plugin-visualizer to build by froos in: [#200](https://codeberg.org/uzu/strudel/pulls/200)
+- 2022-09-14T23:46:39+02:00 document random functions by froos in: [#199](https://codeberg.org/uzu/strudel/pulls/199)
+- 2022-09-09T22:04:40+02:00 Fix numbers in sampler by froos in: [#196](https://codeberg.org/uzu/strudel/pulls/196)
+
+## august 2022
+
+- 2022-08-14T17:40:41+02:00 change "stride"/"offset" of successive degradeBy/chooseIn by Ghost in: [#185](https://codeberg.org/uzu/strudel/pulls/185)
+- 2022-08-14T16:04:14+02:00 Soundfont file support by froos in: [#183](https://codeberg.org/uzu/strudel/pulls/183)
+- 2022-08-14T15:55:50+02:00 fix regression: old way of setting frequencies was broken by froos in: [#190](https://codeberg.org/uzu/strudel/pulls/190)
+- 2022-08-14T15:45:53+02:00 wait for prebake to finish before evaluating by froos in: [#189](https://codeberg.org/uzu/strudel/pulls/189)
+- 2022-08-14T11:31:00+02:00 Fix codemirror bug by froos in: [#186](https://codeberg.org/uzu/strudel/pulls/186)
+- 2022-08-13T16:29:53+02:00 scheduler improvements by froos in: [#181](https://codeberg.org/uzu/strudel/pulls/181)
+- 2022-08-12T23:10:36+02:00 replace mocha with vitest by froos in: [#175](https://codeberg.org/uzu/strudel/pulls/175)
+- 2022-08-07T00:59:07+02:00 incorporate elements of randomness to the mini notation by Ghost in: [#165](https://codeberg.org/uzu/strudel/pulls/165)
+- 2022-08-06T23:32:16+02:00 fix some annoying bugs by froos in: [#177](https://codeberg.org/uzu/strudel/pulls/177)
+- 2022-08-06T00:27:17+02:00 Replace react-codemirror6 with @uiw/react-codemirror by froos in: [#173](https://codeberg.org/uzu/strudel/pulls/173)
+- 2022-08-04T22:19:46+02:00 add more shapeshifter flags by froos in: [#99](https://codeberg.org/uzu/strudel/pulls/99)
+- 2022-08-04T22:06:38+02:00 Amend shapeshifter to allow use of dynamic import by Ghost in: [#171](https://codeberg.org/uzu/strudel/pulls/171)
+- 2022-08-02T23:43:07+02:00 Talk fixes by froos in: [#164](https://codeberg.org/uzu/strudel/pulls/164)
+- 2022-08-02T23:04:34+02:00 Pianoroll fixes by froos in: [#163](https://codeberg.org/uzu/strudel/pulls/163)
+- 2022-08-02T22:57:43+02:00 fix: jsdoc comments by froos in: [#169](https://codeberg.org/uzu/strudel/pulls/169)
+
+## july 2022
+
+- 2022-07-30T23:51:11+02:00 add chooseInWith/chooseCycles by yaxu in: [#166](https://codeberg.org/uzu/strudel/pulls/166)
+- 2022-07-28T19:26:42+02:00 update to tutorial documentation by Ghost in: [#162](https://codeberg.org/uzu/strudel/pulls/162)
+- 2022-07-12T18:58:47+02:00 add webdirt drum samples to prebake for general availability by Ghost in: [#150](https://codeberg.org/uzu/strudel/pulls/150)
+- 2022-07-12T08:34:17+02:00 Final update to demo.pdf by yaxu in: [#151](https://codeberg.org/uzu/strudel/pulls/151)
+
+## june 2022
+
+- 2022-06-28T21:54:35+02:00 Sampler optimizations and more by froos in: [#148](https://codeberg.org/uzu/strudel/pulls/148)
+- 2022-06-26T12:58:53+02:00 can now generate short link for sharing by froos in: [#146](https://codeberg.org/uzu/strudel/pulls/146)
+- 2022-06-24T22:16:04+02:00 flash effect on ctrl enter by froos in: [#144](https://codeberg.org/uzu/strudel/pulls/144)
+- 2022-06-22T20:18:17+02:00 Pianoroll Object Support by froos in: [#142](https://codeberg.org/uzu/strudel/pulls/142)
+- 2022-06-21T22:57:28+02:00 Serial twiddles by yaxu in: [#141](https://codeberg.org/uzu/strudel/pulls/141)
+- 2022-06-21T22:20:05+02:00 Soundfont Support by froos in: [#139](https://codeberg.org/uzu/strudel/pulls/139)
+- 2022-06-21T14:11:50+02:00 Fix createParam() by yaxu in: [#140](https://codeberg.org/uzu/strudel/pulls/140)
+- 2022-06-18T23:24:42+02:00 Webaudio rewrite by froos in: [#138](https://codeberg.org/uzu/strudel/pulls/138)
+- 2022-06-16T21:58:38+02:00 add onTrigger helper by froos in: [#136](https://codeberg.org/uzu/strudel/pulls/136)
+- 2022-06-16T20:48:23+02:00 Scheduler improvements by froos in: [#134](https://codeberg.org/uzu/strudel/pulls/134)
+- 2022-06-16T20:48:07+02:00 remove cycle + delta from onTrigger by froos in: [#135](https://codeberg.org/uzu/strudel/pulls/135)
+- 2022-06-13T21:28:27+02:00 add createParam + createParams by froos in: [#110](https://codeberg.org/uzu/strudel/pulls/110)
+- 2022-06-13T21:27:09+02:00 Pianoroll enhancements by froos in: [#131](https://codeberg.org/uzu/strudel/pulls/131)
+- 2022-06-05T13:06:03+02:00 Fix link to contributing to tutorial docs by Ghost in: [#129](https://codeberg.org/uzu/strudel/pulls/129)
+- 2022-06-02T00:20:45+02:00 Webdirt by froos in: [#121](https://codeberg.org/uzu/strudel/pulls/121)
+- 2022-06-01T23:56:04+02:00 fix: #122 ctrl enter would add newline by froos in: [#124](https://codeberg.org/uzu/strudel/pulls/124)
+- 2022-06-01T18:21:56+02:00 fix: #108 by froos in: [#123](https://codeberg.org/uzu/strudel/pulls/123)
+
+## may 2022
+
+- 2022-05-29T09:54:59+02:00 In source doc by froos in: [#117](https://codeberg.org/uzu/strudel/pulls/117)
+- 2022-05-20T11:49:10+02:00 react package + vite build by froos in: [#116](https://codeberg.org/uzu/strudel/pulls/116)
+- 2022-05-15T22:29:26+02:00 Osc timing improvements by yaxu in: [#113](https://codeberg.org/uzu/strudel/pulls/113)
+- 2022-05-15T22:28:24+02:00 loopAt by yaxu in: [#114](https://codeberg.org/uzu/strudel/pulls/114)
+- 2022-05-09T20:09:47+02:00 `.brak()`, `.inside()` and `.outside()` by yaxu in: [#112](https://codeberg.org/uzu/strudel/pulls/112)
+- 2022-05-06T15:18:41+02:00 In source doc by yaxu in: [#105](https://codeberg.org/uzu/strudel/pulls/105)
+- 2022-05-04T22:59:31+02:00 Embed style by froos in: [#109](https://codeberg.org/uzu/strudel/pulls/109)
+- 2022-05-03T01:40:22+02:00 Reset, Restart and other composers by froos in: [#88](https://codeberg.org/uzu/strudel/pulls/88)
+- 2022-05-02T22:47:21+02:00 /embed package: web component for repl by froos in: [#106](https://codeberg.org/uzu/strudel/pulls/106)
+- 2022-05-02T22:05:34+02:00 Tune tests by froos in: [#104](https://codeberg.org/uzu/strudel/pulls/104)
+- 2022-05-01T14:33:11+02:00 Codemirror 6 by froos in: [#97](https://codeberg.org/uzu/strudel/pulls/97)
+
+## april 2022
+
+- 2022-04-28T23:45:53+02:00 Work on Codemirror 6 highlighting by Ghost in: [#102](https://codeberg.org/uzu/strudel/pulls/102)
+- 2022-04-28T15:46:06+02:00 Change to Affero GPL by yaxu in: [#101](https://codeberg.org/uzu/strudel/pulls/101)
+- 2022-04-26T00:13:07+02:00 Paper by froos in: [#98](https://codeberg.org/uzu/strudel/pulls/98)
+- 2022-04-25T22:10:21+02:00 Fiddles with cat/stack by yaxu in: [#90](https://codeberg.org/uzu/strudel/pulls/90)
+- 2022-04-22T13:08:11+02:00 Add pattern composers, implements #82 by yaxu in: [#83](https://codeberg.org/uzu/strudel/pulls/83)
+- 2022-04-21T20:57:45+02:00 Tidy up a couple of old files by Ghost in: [#84](https://codeberg.org/uzu/strudel/pulls/84)
+- 2022-04-21T15:21:29+02:00 add `striate()` by yaxu in: [#76](https://codeberg.org/uzu/strudel/pulls/76)
+- 2022-04-20T20:17:27+02:00 Webaudio in REPL by froos in: [#77](https://codeberg.org/uzu/strudel/pulls/77)
+- 2022-04-19T15:31:34+02:00 Basic webserial support by yaxu in: [#80](https://codeberg.org/uzu/strudel/pulls/80)
+- 2022-04-17T19:29:49+02:00 Try to fix appLeft / appRight by yaxu in: [#75](https://codeberg.org/uzu/strudel/pulls/75)
+- 2022-04-16T13:26:57+02:00 More random functions by yaxu in: [#74](https://codeberg.org/uzu/strudel/pulls/74)
+- 2022-04-16T11:13:26+02:00 Port `perlin` noise, `rangex`, and `palindrome` by yaxu in: [#73](https://codeberg.org/uzu/strudel/pulls/73)
+- 2022-04-16T10:26:07+02:00 webaudio package by froos in: [#26](https://codeberg.org/uzu/strudel/pulls/26)
+- 2022-04-15T20:18:06+02:00 More randomness, fix `rand`, and add `brand`, `irand` and `choose` by yaxu in: [#70](https://codeberg.org/uzu/strudel/pulls/70)
+- 2022-04-15T11:29:51+02:00 First effort at rand() by yaxu in: [#69](https://codeberg.org/uzu/strudel/pulls/69)
+- 2022-04-14T17:41:18+02:00 use new fixed version of osc-js package by froos in: [#68](https://codeberg.org/uzu/strudel/pulls/68)
+- 2022-04-14T00:09:18+02:00 Speech output by froos in: [#67](https://codeberg.org/uzu/strudel/pulls/67)
+- 2022-04-13T23:55:33+02:00 Separate out strudel.mjs, make index.mjs aggregate module by yaxu in: [#62](https://codeberg.org/uzu/strudel/pulls/62)
+- 2022-04-13T17:26:45+02:00 More functions by yaxu in: [#61](https://codeberg.org/uzu/strudel/pulls/61)
+- 2022-04-13T10:04:29+02:00 More functions by yaxu in: [#56](https://codeberg.org/uzu/strudel/pulls/56)
+- 2022-04-12T17:04:04+02:00 OSC and SuperDirt support by yaxu in: [#27](https://codeberg.org/uzu/strudel/pulls/27)
+- 2022-04-12T13:24:14+02:00 Implement `chop()` by yaxu in: [#50](https://codeberg.org/uzu/strudel/pulls/50)
+- 2022-04-12T12:37:32+02:00 First run at squeezeBind, ref #32 by yaxu in: [#48](https://codeberg.org/uzu/strudel/pulls/48)
+- 2022-04-12T00:03:37+02:00 Fix polymeter by yaxu in: [#44](https://codeberg.org/uzu/strudel/pulls/44)
+- 2022-04-11T22:39:44+02:00 Compose by froos in: [#40](https://codeberg.org/uzu/strudel/pulls/40)
+- 2022-04-11T21:49:35+02:00 Update tutorial.mdx by Ghost in: [#38](https://codeberg.org/uzu/strudel/pulls/38)
+- 2022-04-11T08:43:44+02:00 Update tutorial.mdx by Ghost in: [#37](https://codeberg.org/uzu/strudel/pulls/37)
+
+## march 2022
+
+- 2022-03-28T17:27:22+02:00 Add chunk, chunkBack and iterBack by yaxu in: [#25](https://codeberg.org/uzu/strudel/pulls/25)
+- 2022-03-28T11:48:22+02:00 packaging by froos in: [#24](https://codeberg.org/uzu/strudel/pulls/24)
+- 2022-03-22T12:06:48+01:00 Update package.json by Ghost in: [#23](https://codeberg.org/uzu/strudel/pulls/23)
+- 2022-03-06T20:35:20+01:00 added _asNumber + interprete numbers as midi by froos in: [#21](https://codeberg.org/uzu/strudel/pulls/21)
+
+## february 2022
+
+- 2022-02-28T00:32:29+01:00 Fix resolveState by yaxu in: [#22](https://codeberg.org/uzu/strudel/pulls/22)
+- 2022-02-27T20:52:52+01:00 Stateful queries and events (WIP) by yaxu in: [#14](https://codeberg.org/uzu/strudel/pulls/14)
+- 2022-02-27T18:04:07+01:00 fix: 💄 Enhance visualisation of the Tutorial on mobile by Ghost in: [#19](https://codeberg.org/uzu/strudel/pulls/19)
+- 2022-02-26T21:16:34+01:00 test: 📦 Add missing dependency and a CI check, to prevent oversights ;p by Ghost in: [#17](https://codeberg.org/uzu/strudel/pulls/17)
+- 2022-02-26T13:29:19+01:00 higher latencyHint by froos in: [#16](https://codeberg.org/uzu/strudel/pulls/16)
+- 2022-02-23T22:15:11+01:00 add apply and layer, and missing div/mul methods by yaxu in: [#15](https://codeberg.org/uzu/strudel/pulls/15)
+- 2022-02-21T01:02:07+01:00 Add continuous signals (sine, cosine, saw, etc) by yaxu in: [#13](https://codeberg.org/uzu/strudel/pulls/13)
+- 2022-02-19T21:30:04+01:00 Added mask() and struct() by yaxu in: [#11](https://codeberg.org/uzu/strudel/pulls/11)
+- 2022-02-19T16:07:07+01:00 Failing test for `when` WIP by yaxu in: [#10](https://codeberg.org/uzu/strudel/pulls/10)
+- 2022-02-10T17:21:31+01:00 Bugfix every, and create more top level functions by yaxu in: [#9](https://codeberg.org/uzu/strudel/pulls/9)
+- 2022-02-10T00:51:21+01:00 timeCat by yaxu in: [#8](https://codeberg.org/uzu/strudel/pulls/8)
+- 2022-02-07T23:07:58+01:00 fixed editor crash by froos in: [#7](https://codeberg.org/uzu/strudel/pulls/7)
+- 2022-02-07T19:08:40+01:00 krill parser + improved repl by froos in: [#6](https://codeberg.org/uzu/strudel/pulls/6)
+- 2022-02-06T00:59:16+01:00 Patternify all the things by yaxu in: [#5](https://codeberg.org/uzu/strudel/pulls/5)
+- 2022-02-05T23:31:37+01:00 update readme for local dev by Ghost in: [#4](https://codeberg.org/uzu/strudel/pulls/4)
+- 2022-02-05T22:36:06+01:00 Fix path by yaxu in: [#3](https://codeberg.org/uzu/strudel/pulls/3)
+- 2022-02-05T21:52:51+01:00 repl + reify functions by froos in: [#2](https://codeberg.org/uzu/strudel/pulls/2)
+[9:37:36] strudel %
\ No newline at end of file
diff --git a/warm.js b/warm.js
index 0d148dee9..846d59a99 100644
--- a/warm.js
+++ b/warm.js
@@ -1,14 +1,30 @@
-fetch('https://codeberg.org/api/v1/repos/uzu/strudel/pulls?state=closed&page=1')
- .then((res) => res.json())
- .then((pulls) => {
- const r = pulls
- .filter((pull) => pull.merged)
- .sort((a, b) => new Date(b.closed_at) - new Date(a.closed_at))
- .map((pull) => `${pull.closed_at} ${pull.title} by ${pull.user.login || '?'} in: [#${pull.number}](${pull.url}) `)
- .join('\n');
- console.log(r);
- });
+// this script loads all merged PRs within the given page range
+// it can be used to update the CHANGELOG.md file in a semi-automated way
+// the problem: codeberg doesn't support loading merged PRs, so we have to filter them in memory
+// luckily, we can sort after "recentupdate", which means we can do incremental changelog generation
+// todo: support setting a "last_updated" date, so the script would automatically check how far it has to go
-/*
+async function main() {
+ let pageStart = 1;
+ let pageEnd = 1;
+ let prs = [];
+ for (let p = pageStart; p <= pageEnd; p++) {
+ console.log(`load page ${p}/${pageEnd}`);
+ const res = await fetch(
+ `https://codeberg.org/api/v1/repos/uzu/strudel/pulls?state=closed&sort=recentupdate&page=${p}`,
+ );
+ const pulls = await res.json();
+ const merged = pulls.filter((pull) => pull.merged);
+ prs = prs.concat(merged);
+ }
+ const output = prs
+ .sort((a, b) => new Date(b.closed_at) - new Date(a.closed_at))
+ .map(
+ (pull) => `- ${pull.closed_at} ${pull.title} by @${pull.user.login || '?'} in: [#${pull.number}](${pull.url}) `,
+ )
+ .join('\n');
+ console.log('-------------');
+ console.log(output);
+}
- */
+main();
From 3d13955c41cf9fa4e6ffafa1262d0d53b95c17a5 Mon Sep 17 00:00:00 2001
From: Felix Roos
Date: Fri, 16 Jan 2026 10:08:41 +0100
Subject: [PATCH 310/476] fix: prefix usernames with @
---
CHANGELOG.md | 1854 +++++++++++++++++++++++++-------------------------
1 file changed, 927 insertions(+), 927 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3daf4e6cf..587343e43 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,1076 +5,1076 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
## january 2026
-- 2026-01-15T16:59:14+01:00 mondo fix: add registered functions to scope automatically by daslyfe in: [#1896](https://codeberg.org/uzu/strudel/pulls/1896)
-- 2026-01-15T16:58:14+01:00 Added docs for pattern search by JohnBjrk in: [#1905](https://codeberg.org/uzu/strudel/pulls/1905)
-- 2026-01-15T16:57:19+01:00 Update kabelsalat dependency by jeromew in: [#1911](https://codeberg.org/uzu/strudel/pulls/1911)
-- 2026-01-15T00:24:39+01:00 Bug Fix: Set pooled values immediately instead of scheduling by glossing in: [#1907](https://codeberg.org/uzu/strudel/pulls/1907)
-- 2026-01-14T20:29:16+01:00 Feat: Kabelsalat integration by glossing in: [#1876](https://codeberg.org/uzu/strudel/pulls/1876)
-- 2026-01-14T19:07:49+01:00 Feat: MIDI Keyboard 🎹🐈 by glossing in: [#1828](https://codeberg.org/uzu/strudel/pulls/1828)
-- 2026-01-14T18:14:52+01:00 Bug Fix: Fix race condition between worklet termination and port messages by glossing in: [#1897](https://codeberg.org/uzu/strudel/pulls/1897)
-- 2026-01-13T04:06:52+01:00 Add search/filter in patterns tab by JohnBjrk in: [#1842](https://codeberg.org/uzu/strudel/pulls/1842)
-- 2026-01-13T00:18:10+01:00 Add shortcut for navigating through labels! by daslyfe in: [#1807](https://codeberg.org/uzu/strudel/pulls/1807)
-- 2026-01-12T00:17:37+01:00 add warm.strudel.cc to faq by yaxu in: [#1891](https://codeberg.org/uzu/strudel/pulls/1891)
-- 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-11T13:19:46+01:00 New page FAQ in "More" by scrappy_fiddler in: [#1753](https://codeberg.org/uzu/strudel/pulls/1753)
-- 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-10T23:12:48+01:00 Perf: Targeted node pools by glossing in: [#1810](https://codeberg.org/uzu/strudel/pulls/1810)
-- 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-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)
+- 2026-01-15T16:59:14+01:00 mondo fix: add registered functions to scope automatically by @daslyfe in: [#1896](https://codeberg.org/uzu/strudel/pulls/1896)
+- 2026-01-15T16:58:14+01:00 Added docs for pattern search by @JohnBjrk in: [#1905](https://codeberg.org/uzu/strudel/pulls/1905)
+- 2026-01-15T16:57:19+01:00 Update kabelsalat dependency by @jeromew in: [#1911](https://codeberg.org/uzu/strudel/pulls/1911)
+- 2026-01-15T00:24:39+01:00 Bug Fix: Set pooled values immediately instead of scheduling by @glossing in: [#1907](https://codeberg.org/uzu/strudel/pulls/1907)
+- 2026-01-14T20:29:16+01:00 Feat: Kabelsalat integration by @glossing in: [#1876](https://codeberg.org/uzu/strudel/pulls/1876)
+- 2026-01-14T19:07:49+01:00 Feat: MIDI Keyboard 🎹🐈 by @glossing in: [#1828](https://codeberg.org/uzu/strudel/pulls/1828)
+- 2026-01-14T18:14:52+01:00 Bug Fix: Fix race condition between worklet termination and port messages by @glossing in: [#1897](https://codeberg.org/uzu/strudel/pulls/1897)
+- 2026-01-13T04:06:52+01:00 Add search/filter in patterns tab by @JohnBjrk in: [#1842](https://codeberg.org/uzu/strudel/pulls/1842)
+- 2026-01-13T00:18:10+01:00 Add shortcut for navigating through labels! by @daslyfe in: [#1807](https://codeberg.org/uzu/strudel/pulls/1807)
+- 2026-01-12T00:17:37+01:00 add warm.strudel.cc to faq by @yaxu in: [#1891](https://codeberg.org/uzu/strudel/pulls/1891)
+- 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-11T13:19:46+01:00 New page FAQ in "More" by @scrappy_fiddler in: [#1753](https://codeberg.org/uzu/strudel/pulls/1753)
+- 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-10T23:12:48+01:00 Perf: Targeted node pools by @glossing in: [#1810](https://codeberg.org/uzu/strudel/pulls/1810)
+- 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-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-29T20:54:11+01:00 Feature: LFOs and Envelopes by glossing in: [#1507](https://codeberg.org/uzu/strudel/pulls/1507)
-- 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-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-28T14:20:03+01:00 dough repl fixes by froos in: [#1855](https://codeberg.org/uzu/strudel/pulls/1855)
-- 2025-12-28T13:40:29+01:00 add basic dough repl by froos in: [#1749](https://codeberg.org/uzu/strudel/pulls/1749)
-- 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-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-19T01:03:53+01:00 [perf] Add audiograph `await debugAudiograph()` feature by jeromew in: [#1763](https://codeberg.org/uzu/strudel/pulls/1763)
-- 2025-12-19T00:45:41+01:00 Feature: non-realtime exporting by Ghost in: [#1674](https://codeberg.org/uzu/strudel/pulls/1674)
-- 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-14T15:09:12+01:00 delta -> per / perx / cyclesPer refinements by yaxu in: [#1832](https://codeberg.org/uzu/strudel/pulls/1832)
-- 2025-12-14T01:07:36+01:00 Improved randomness by glossing in: [#1505](https://codeberg.org/uzu/strudel/pulls/1505)
-- 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-11T18:00:49+01:00 Feature: stateful timeline function for jumping between timelines by yaxu in: [#1669](https://codeberg.org/uzu/strudel/pulls/1669)
-- 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-07T21:51:40+01:00 Feat: Add channel support to midi in by glossing in: [#1775](https://codeberg.org/uzu/strudel/pulls/1775)
-- 2025-12-07T21:23:43+01:00 Feat: Transient shaper by glossing in: [#1777](https://codeberg.org/uzu/strudel/pulls/1777)
-- 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-03T18:27:28+01:00 Feature: Eight FMs by glossing in: [#1628](https://codeberg.org/uzu/strudel/pulls/1628)
-- 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-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-29T20:54:11+01:00 Feature: LFOs and Envelopes by @glossing in: [#1507](https://codeberg.org/uzu/strudel/pulls/1507)
+- 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-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-28T14:20:03+01:00 dough repl fixes by @froos in: [#1855](https://codeberg.org/uzu/strudel/pulls/1855)
+- 2025-12-28T13:40:29+01:00 add basic dough repl by @froos in: [#1749](https://codeberg.org/uzu/strudel/pulls/1749)
+- 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-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-19T01:03:53+01:00 [perf] Add audiograph `await debugAudiograph()` feature by @jeromew in: [#1763](https://codeberg.org/uzu/strudel/pulls/1763)
+- 2025-12-19T00:45:41+01:00 Feature: non-realtime exporting by @Ghost in: [#1674](https://codeberg.org/uzu/strudel/pulls/1674)
+- 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-14T15:09:12+01:00 delta -> per / perx / cyclesPer refinements by @yaxu in: [#1832](https://codeberg.org/uzu/strudel/pulls/1832)
+- 2025-12-14T01:07:36+01:00 Improved randomness by @glossing in: [#1505](https://codeberg.org/uzu/strudel/pulls/1505)
+- 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-11T18:00:49+01:00 Feature: stateful timeline function for jumping between timelines by @yaxu in: [#1669](https://codeberg.org/uzu/strudel/pulls/1669)
+- 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-07T21:51:40+01:00 Feat: Add channel support to midi in by @glossing in: [#1775](https://codeberg.org/uzu/strudel/pulls/1775)
+- 2025-12-07T21:23:43+01:00 Feat: Transient shaper by @glossing in: [#1777](https://codeberg.org/uzu/strudel/pulls/1777)
+- 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-03T18:27:28+01:00 Feature: Eight FMs by @glossing in: [#1628](https://codeberg.org/uzu/strudel/pulls/1628)
+- 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:47:03+01:00 fix(tool/dbpatch): add missing package name by peterpf in: [#1765](https://codeberg.org/uzu/strudel/pulls/1765)
-- 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)
-- 2025-11-27T20:36:14+01:00 Use errorLogger for query and tonal errors by glossing in: [#1782](https://codeberg.org/uzu/strudel/pulls/1782)
-- 2025-11-27T20:27:10+01:00 [perf] level 5 `connect-leak` on `vowel` by jeromew in: [#1779](https://codeberg.org/uzu/strudel/pulls/1779)
-- 2025-11-26T08:23:38+01:00 feat: add prebake script import button for loading .strudel files by daslyfe in: [#1774](https://codeberg.org/uzu/strudel/pulls/1774)
-- 2025-11-26T07:39:28+01:00 Fix Sampler port trampling by Dayglo in: [#1717](https://codeberg.org/uzu/strudel/pulls/1717)
-- 2025-11-25T20:59:09+01:00 Feat: Hook up octave and fix example by glossing in: [#1773](https://codeberg.org/uzu/strudel/pulls/1773)
-- 2025-11-25T20:48:09+01:00 [perf] fix `connect-leak` in `tremolo` param by jeromew in: [#1780](https://codeberg.org/uzu/strudel/pulls/1780)
-- 2025-11-24T17:51:20+01:00 filter modulation improvements! by daslyfe in: [#1769](https://codeberg.org/uzu/strudel/pulls/1769)
-- 2025-11-24T01:20:53+01:00 Add o as a synonym for orbit by daslyfe in: [#1766](https://codeberg.org/uzu/strudel/pulls/1766)
-- 2025-11-23T22:23:26+01:00 [perf] fix `connect-leak` in `fm` modulation by jeromew in: [#1758](https://codeberg.org/uzu/strudel/pulls/1758)
-- 2025-11-23T09:47:24+01:00 Fix interoperability issue between `all` and `await initHydra()` by jeromew in: [#1663](https://codeberg.org/uzu/strudel/pulls/1663)
-- 2025-11-23T04:23:06+01:00 Bug fix: Swap l/r gains with temp variable by glossing in: [#1768](https://codeberg.org/uzu/strudel/pulls/1768)
-- 2025-11-23T00:52:28+01:00 FIX: prevent LFO filter modulation from popping from negative values by daslyfe in: [#1767](https://codeberg.org/uzu/strudel/pulls/1767)
-- 2025-11-23T00:03:32+01:00 prefix "S" for solo by froos in: [#1481](https://codeberg.org/uzu/strudel/pulls/1481)
-- 2025-11-21T01:56:11+01:00 Bug Fix: Use frac due to negative frequencies from FM by glossing in: [#1759](https://codeberg.org/uzu/strudel/pulls/1759)
-- 2025-11-20T19:48:16+01:00 [perf] fix `connect-leak` added by #1742 when noise() is not used by jeromew in: [#1757](https://codeberg.org/uzu/strudel/pulls/1757)
-- 2025-11-20T14:51:00+01:00 [perf] fix `connect-leak` in `delay` effect by jeromew in: [#1755](https://codeberg.org/uzu/strudel/pulls/1755)
-- 2025-11-20T14:49:41+01:00 [perf] fix `connect leak` when .noise() is in the mix by jeromew in: [#1742](https://codeberg.org/uzu/strudel/pulls/1742)
-- 2025-11-18T23:52:45+01:00 wchooseCycles has now notes in an example by scrappy_fiddler in: [#1748](https://codeberg.org/uzu/strudel/pulls/1748)
-- 2025-11-17T05:31:54+01:00 Feature: Partials by glossing in: [#1659](https://codeberg.org/uzu/strudel/pulls/1659)
-- 2025-11-16T22:06:14+01:00 README: update superdough documentation by TristanMlct in: [#1741](https://codeberg.org/uzu/strudel/pulls/1741)
-- 2025-11-16T22:00:43+01:00 Feature: Envelope worklet by glossing in: [#1524](https://codeberg.org/uzu/strudel/pulls/1524)
-- 2025-11-16T21:08:54+01:00 Worklet optimizations by glossing in: [#1730](https://codeberg.org/uzu/strudel/pulls/1730)
-- 2025-11-15T14:59:30+01:00 [perf] disconnect Offline AudioNode connections in generateReverb by jeromew in: [#1740](https://codeberg.org/uzu/strudel/pulls/1740)
-- 2025-11-15T14:57:47+01:00 [perf] disconnect `send` effect AudioNode when `room` is used by jeromew in: [#1736](https://codeberg.org/uzu/strudel/pulls/1736)
-- 2025-11-12T21:22:34+01:00 [supradough] fix: unstable filter by froos in: [#1593](https://codeberg.org/uzu/strudel/pulls/1593)
-- 2025-11-12T21:12:07+01:00 Fix link syntax in `project-start` by Kissaki in: [#1724](https://codeberg.org/uzu/strudel/pulls/1724)
-- 2025-11-12T21:06:13+01:00 Fix web README sample code by Kissaki in: [#1725](https://codeberg.org/uzu/strudel/pulls/1725)
-- 2025-11-12T20:59:39+01:00 Fix typo: 'studel' -> 'strudel' by drhayes in: [#1726](https://codeberg.org/uzu/strudel/pulls/1726)
-- 2025-11-12T15:23:41+01:00 fix for node 24 support in tests - #1718 by ausav in: [#1719](https://codeberg.org/uzu/strudel/pulls/1719)
-- 2025-11-11T09:00:49+01:00 soundAlias example fix by PepsiiMan in: [#1720](https://codeberg.org/uzu/strudel/pulls/1720)
-- 2025-11-10T08:18:36+01:00 fix: Make Supradough package build by munshkr in: [#1711](https://codeberg.org/uzu/strudel/pulls/1711)
-- 2025-11-10T08:18:00+01:00 added docs for spaces in scale names by ondras in: [#1715](https://codeberg.org/uzu/strudel/pulls/1715)
-- 2025-11-10T02:44:01+01:00 Feature: LFOs for Filters by glossing in: [#1636](https://codeberg.org/uzu/strudel/pulls/1636)
-- 2025-11-05T17:07:00+01:00 improvement: sync midi messages to audio context clock by daslyfe in: [#1708](https://codeberg.org/uzu/strudel/pulls/1708)
-- 2025-11-04T19:36:14+01:00 Add stick button mappings to gamepad implementation and improve docs by kaosuryoko in: [#1696](https://codeberg.org/uzu/strudel/pulls/1696)
-- 2025-11-04T19:29:35+01:00 Refactor sound stopping and triggering logic in SoundsTab component by IJOL in: [#1688](https://codeberg.org/uzu/strudel/pulls/1688)
-- 2025-11-04T19:13:21+01:00 Add setting to toggle pattern auto-start on pattern change by moumar in: [#1690](https://codeberg.org/uzu/strudel/pulls/1690)
-- 2025-11-04T18:58:50+01:00 Voicings JSDoc by sharkeys_lunchbox in: [#1686](https://codeberg.org/uzu/strudel/pulls/1686)
-- 2025-11-01T07:50:40+01:00 FIX: Loading local samples uses too much memory by daslyfe in: [#1706](https://codeberg.org/uzu/strudel/pulls/1706)
+- 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:47:03+01:00 fix(tool/dbpatch): add missing package name by @peterpf in: [#1765](https://codeberg.org/uzu/strudel/pulls/1765)
+- 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)
+- 2025-11-27T20:36:14+01:00 Use errorLogger for query and tonal errors by @glossing in: [#1782](https://codeberg.org/uzu/strudel/pulls/1782)
+- 2025-11-27T20:27:10+01:00 [perf] level 5 `connect-leak` on `vowel` by @jeromew in: [#1779](https://codeberg.org/uzu/strudel/pulls/1779)
+- 2025-11-26T08:23:38+01:00 feat: add prebake script import button for loading .strudel files by @daslyfe in: [#1774](https://codeberg.org/uzu/strudel/pulls/1774)
+- 2025-11-26T07:39:28+01:00 Fix Sampler port trampling by @Dayglo in: [#1717](https://codeberg.org/uzu/strudel/pulls/1717)
+- 2025-11-25T20:59:09+01:00 Feat: Hook up octave and fix example by @glossing in: [#1773](https://codeberg.org/uzu/strudel/pulls/1773)
+- 2025-11-25T20:48:09+01:00 [perf] fix `connect-leak` in `tremolo` param by @jeromew in: [#1780](https://codeberg.org/uzu/strudel/pulls/1780)
+- 2025-11-24T17:51:20+01:00 filter modulation improvements! by @daslyfe in: [#1769](https://codeberg.org/uzu/strudel/pulls/1769)
+- 2025-11-24T01:20:53+01:00 Add o as a synonym for orbit by @daslyfe in: [#1766](https://codeberg.org/uzu/strudel/pulls/1766)
+- 2025-11-23T22:23:26+01:00 [perf] fix `connect-leak` in `fm` modulation by @jeromew in: [#1758](https://codeberg.org/uzu/strudel/pulls/1758)
+- 2025-11-23T09:47:24+01:00 Fix interoperability issue between `all` and `await initHydra()` by @jeromew in: [#1663](https://codeberg.org/uzu/strudel/pulls/1663)
+- 2025-11-23T04:23:06+01:00 Bug fix: Swap l/r gains with temp variable by @glossing in: [#1768](https://codeberg.org/uzu/strudel/pulls/1768)
+- 2025-11-23T00:52:28+01:00 FIX: prevent LFO filter modulation from popping from negative values by @daslyfe in: [#1767](https://codeberg.org/uzu/strudel/pulls/1767)
+- 2025-11-23T00:03:32+01:00 prefix "S" for solo by @froos in: [#1481](https://codeberg.org/uzu/strudel/pulls/1481)
+- 2025-11-21T01:56:11+01:00 Bug Fix: Use frac due to negative frequencies from FM by @glossing in: [#1759](https://codeberg.org/uzu/strudel/pulls/1759)
+- 2025-11-20T19:48:16+01:00 [perf] fix `connect-leak` added by #1742 when noise() is not used by @jeromew in: [#1757](https://codeberg.org/uzu/strudel/pulls/1757)
+- 2025-11-20T14:51:00+01:00 [perf] fix `connect-leak` in `delay` effect by @jeromew in: [#1755](https://codeberg.org/uzu/strudel/pulls/1755)
+- 2025-11-20T14:49:41+01:00 [perf] fix `connect leak` when .noise() is in the mix by @jeromew in: [#1742](https://codeberg.org/uzu/strudel/pulls/1742)
+- 2025-11-18T23:52:45+01:00 wchooseCycles has now notes in an example by @scrappy_fiddler in: [#1748](https://codeberg.org/uzu/strudel/pulls/1748)
+- 2025-11-17T05:31:54+01:00 Feature: Partials by @glossing in: [#1659](https://codeberg.org/uzu/strudel/pulls/1659)
+- 2025-11-16T22:06:14+01:00 README: update superdough documentation by @TristanMlct in: [#1741](https://codeberg.org/uzu/strudel/pulls/1741)
+- 2025-11-16T22:00:43+01:00 Feature: Envelope worklet by @glossing in: [#1524](https://codeberg.org/uzu/strudel/pulls/1524)
+- 2025-11-16T21:08:54+01:00 Worklet optimizations by @glossing in: [#1730](https://codeberg.org/uzu/strudel/pulls/1730)
+- 2025-11-15T14:59:30+01:00 [perf] disconnect Offline AudioNode connections in generateReverb by @jeromew in: [#1740](https://codeberg.org/uzu/strudel/pulls/1740)
+- 2025-11-15T14:57:47+01:00 [perf] disconnect `send` effect AudioNode when `room` is used by @jeromew in: [#1736](https://codeberg.org/uzu/strudel/pulls/1736)
+- 2025-11-12T21:22:34+01:00 [supradough] fix: unstable filter by @froos in: [#1593](https://codeberg.org/uzu/strudel/pulls/1593)
+- 2025-11-12T21:12:07+01:00 Fix link syntax in `project-start` by @Kissaki in: [#1724](https://codeberg.org/uzu/strudel/pulls/1724)
+- 2025-11-12T21:06:13+01:00 Fix web README sample code by @Kissaki in: [#1725](https://codeberg.org/uzu/strudel/pulls/1725)
+- 2025-11-12T20:59:39+01:00 Fix typo: 'studel' -> 'strudel' by @drhayes in: [#1726](https://codeberg.org/uzu/strudel/pulls/1726)
+- 2025-11-12T15:23:41+01:00 fix for node 24 support in tests - #1718 by @ausav in: [#1719](https://codeberg.org/uzu/strudel/pulls/1719)
+- 2025-11-11T09:00:49+01:00 soundAlias example fix by @PepsiiMan in: [#1720](https://codeberg.org/uzu/strudel/pulls/1720)
+- 2025-11-10T08:18:36+01:00 fix: Make Supradough package build by @munshkr in: [#1711](https://codeberg.org/uzu/strudel/pulls/1711)
+- 2025-11-10T08:18:00+01:00 added docs for spaces in scale names by @ondras in: [#1715](https://codeberg.org/uzu/strudel/pulls/1715)
+- 2025-11-10T02:44:01+01:00 Feature: LFOs for Filters by @glossing in: [#1636](https://codeberg.org/uzu/strudel/pulls/1636)
+- 2025-11-05T17:07:00+01:00 improvement: sync midi messages to audio context clock by @daslyfe in: [#1708](https://codeberg.org/uzu/strudel/pulls/1708)
+- 2025-11-04T19:36:14+01:00 Add stick button mappings to gamepad implementation and improve docs by @kaosuryoko in: [#1696](https://codeberg.org/uzu/strudel/pulls/1696)
+- 2025-11-04T19:29:35+01:00 Refactor sound stopping and triggering logic in SoundsTab component by @IJOL in: [#1688](https://codeberg.org/uzu/strudel/pulls/1688)
+- 2025-11-04T19:13:21+01:00 Add setting to toggle pattern auto-start on pattern change by @moumar in: [#1690](https://codeberg.org/uzu/strudel/pulls/1690)
+- 2025-11-04T18:58:50+01:00 Voicings JSDoc by @sharkeys_lunchbox in: [#1686](https://codeberg.org/uzu/strudel/pulls/1686)
+- 2025-11-01T07:50:40+01:00 FIX: Loading local samples uses too much memory by @daslyfe in: [#1706](https://codeberg.org/uzu/strudel/pulls/1706)
## october 2025
-- 2025-10-28T22:58:24+01:00 Bug Fix: Handle scale-for-notes when n also supplied by glossing in: [#1625](https://codeberg.org/uzu/strudel/pulls/1625)
-- 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-28T22:58:24+01:00 Bug Fix: Handle scale-for-notes when n also supplied by @glossing in: [#1625](https://codeberg.org/uzu/strudel/pulls/1625)
+- 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)
-- 2025-10-23T03:47:31+02:00 Adds back shape to superdough by glossing in: [#1672](https://codeberg.org/uzu/strudel/pulls/1672)
-- 2025-10-22T22:15:19+02:00 Fix sampler.mjs githubPath by jeromew in: [#1684](https://codeberg.org/uzu/strudel/pulls/1684)
-- 2025-10-22T16:20:50+02:00 Fix onPaint for widgets by yaxu in: [#1658](https://codeberg.org/uzu/strudel/pulls/1658)
-- 2025-10-22T15:19:12+02:00 Fix a bug introduced by #4e17cfbdd6 by milliganf in: [#1679](https://codeberg.org/uzu/strudel/pulls/1679)
-- 2025-10-20T22:37:15+02:00 feature/autocomplete-sound-names by drdozer in: [#1564](https://codeberg.org/uzu/strudel/pulls/1564)
-- 2025-10-20T21:58:12+02:00 add replicate + use it for ! in mondo by JoStro in: [#1436](https://codeberg.org/uzu/strudel/pulls/1436)
-- 2025-10-18T04:29:20+02:00 Bug Fix: Wavetable: phase wrapping at 1 and detune by glossing in: [#1620](https://codeberg.org/uzu/strudel/pulls/1620)
-- 2025-10-16T20:26:28+02:00 github samples: default to "samples" if repository is not specified by prezmop in: [#1644](https://codeberg.org/uzu/strudel/pulls/1644)
-- 2025-10-16T17:33:39+02:00 Docs: add example of custom chained function by dariusk in: [#1642](https://codeberg.org/uzu/strudel/pulls/1642)
-- 2025-10-14T12:39:48+02:00 textbox by yaxu in: [#1650](https://codeberg.org/uzu/strudel/pulls/1650)
-- 2025-10-13T07:26:51+02:00 Feature: Distortion Modes by glossing in: [#1561](https://codeberg.org/uzu/strudel/pulls/1561)
-- 2025-10-13T07:05:57+02:00 Feature: Wavetable FM by glossing in: [#1623](https://codeberg.org/uzu/strudel/pulls/1623)
-- 2025-10-12T20:43:42+02:00 fix: repair REPL sample sources and URL concat (#1640) by erikfox in: [#1646](https://codeberg.org/uzu/strudel/pulls/1646)
-- 2025-10-10T11:25:02+02:00 Add control-metadata by yaxu in: [#1634](https://codeberg.org/uzu/strudel/pulls/1634)
-- 2025-10-07T22:59:39+02:00 Fix MQTT: change the trigger handler to match new hap by jurrchen in: [#1629](https://codeberg.org/uzu/strudel/pulls/1629)
-- 2025-10-05T21:42:19+02:00 Fix case sensitivity for synonym search by vvolhejn in: [#1618](https://codeberg.org/uzu/strudel/pulls/1618)
-- 2025-10-01T08:56:35+02:00 Optimize wavetable synth by glossing in: [#1613](https://codeberg.org/uzu/strudel/pulls/1613)
-- 2025-10-01T02:02:33+02:00 fix: pattern switching by daslyfe in: [#1616](https://codeberg.org/uzu/strudel/pulls/1616)
+- 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)
+- 2025-10-23T03:47:31+02:00 Adds back shape to superdough by @glossing in: [#1672](https://codeberg.org/uzu/strudel/pulls/1672)
+- 2025-10-22T22:15:19+02:00 Fix sampler.mjs githubPath by @jeromew in: [#1684](https://codeberg.org/uzu/strudel/pulls/1684)
+- 2025-10-22T16:20:50+02:00 Fix onPaint for widgets by @yaxu in: [#1658](https://codeberg.org/uzu/strudel/pulls/1658)
+- 2025-10-22T15:19:12+02:00 Fix a bug introduced by #4e17cfbdd6 by @milliganf in: [#1679](https://codeberg.org/uzu/strudel/pulls/1679)
+- 2025-10-20T22:37:15+02:00 feature/autocomplete-sound-names by @drdozer in: [#1564](https://codeberg.org/uzu/strudel/pulls/1564)
+- 2025-10-20T21:58:12+02:00 add replicate + use it for ! in mondo by @JoStro in: [#1436](https://codeberg.org/uzu/strudel/pulls/1436)
+- 2025-10-18T04:29:20+02:00 Bug Fix: Wavetable: phase wrapping at 1 and detune by @glossing in: [#1620](https://codeberg.org/uzu/strudel/pulls/1620)
+- 2025-10-16T20:26:28+02:00 github samples: default to "samples" if repository is not specified by @prezmop in: [#1644](https://codeberg.org/uzu/strudel/pulls/1644)
+- 2025-10-16T17:33:39+02:00 Docs: add example of custom chained function by @dariusk in: [#1642](https://codeberg.org/uzu/strudel/pulls/1642)
+- 2025-10-14T12:39:48+02:00 textbox by @yaxu in: [#1650](https://codeberg.org/uzu/strudel/pulls/1650)
+- 2025-10-13T07:26:51+02:00 Feature: Distortion Modes by @glossing in: [#1561](https://codeberg.org/uzu/strudel/pulls/1561)
+- 2025-10-13T07:05:57+02:00 Feature: Wavetable FM by @glossing in: [#1623](https://codeberg.org/uzu/strudel/pulls/1623)
+- 2025-10-12T20:43:42+02:00 fix: repair REPL sample sources and URL concat (#1640) by @erikfox in: [#1646](https://codeberg.org/uzu/strudel/pulls/1646)
+- 2025-10-10T11:25:02+02:00 Add control-metadata by @yaxu in: [#1634](https://codeberg.org/uzu/strudel/pulls/1634)
+- 2025-10-07T22:59:39+02:00 Fix MQTT: change the trigger handler to match new hap by @jurrchen in: [#1629](https://codeberg.org/uzu/strudel/pulls/1629)
+- 2025-10-05T21:42:19+02:00 Fix case sensitivity for synonym search by @vvolhejn in: [#1618](https://codeberg.org/uzu/strudel/pulls/1618)
+- 2025-10-01T08:56:35+02:00 Optimize wavetable synth by @glossing in: [#1613](https://codeberg.org/uzu/strudel/pulls/1613)
+- 2025-10-01T02:02:33+02:00 fix: pattern switching by @daslyfe in: [#1616](https://codeberg.org/uzu/strudel/pulls/1616)
## september 2025
-- 2025-09-29T02:10:54+02:00 fix wavetable JSON by daslyfe in: [#1611](https://codeberg.org/uzu/strudel/pulls/1611)
-- 2025-09-28T21:28:16+02:00 rename wavetable controls to match existing naming conventions by daslyfe in: [#1610](https://codeberg.org/uzu/strudel/pulls/1610)
-- 2025-09-27T23:28:13+02:00 Feature: Wavetable synth improvements by glossing in: [#1607](https://codeberg.org/uzu/strudel/pulls/1607)
-- 2025-09-27T21:43:10+02:00 wavetable improvements by daslyfe in: [#1608](https://codeberg.org/uzu/strudel/pulls/1608)
-- 2025-09-26T08:48:46+02:00 create orbit based DJ filter by daslyfe in: [#1603](https://codeberg.org/uzu/strudel/pulls/1603)
-- 2025-09-26T08:15:49+02:00 Feature: Wavetable synth by glossing in: [#1525](https://codeberg.org/uzu/strudel/pulls/1525)
-- 2025-09-23T13:28:20+02:00 fix: time signal by daslyfe in: [#1583](https://codeberg.org/uzu/strudel/pulls/1583)
-- 2025-09-21T16:16:06+02:00 mondo: fix all + setcpm + setcps by froos in: [#1600](https://codeberg.org/uzu/strudel/pulls/1600)
-- 2025-09-19T21:59:43+02:00 fix: osc error message by froos in: [#1597](https://codeberg.org/uzu/strudel/pulls/1597)
-- 2025-09-18T21:09:56+02:00 osc: --debug flag to see incoming messages by froos in: [#1595](https://codeberg.org/uzu/strudel/pulls/1595)
-- 2025-09-17T14:12:10+02:00 simplify osc usage by froos in: [#1588](https://codeberg.org/uzu/strudel/pulls/1588)
-- 2025-09-16T16:59:58+02:00 dev: logger errors to console in dev mode by daslyfe in: [#1585](https://codeberg.org/uzu/strudel/pulls/1585)
-- 2025-09-16T03:19:37+02:00 Bug Fix / Feature: Updates to `duck` to avoid clicks and allow configuration over release/attack by glossing in: [#1514](https://codeberg.org/uzu/strudel/pulls/1514)
-- 2025-09-15T23:36:31+02:00 Feat: Enhance `scale` function to quantize notes to a named scale by glossing in: [#1492](https://codeberg.org/uzu/strudel/pulls/1492)
-- 2025-09-15T22:52:14+02:00 add tic80 font by froos in: [#1579](https://codeberg.org/uzu/strudel/pulls/1579)
-- 2025-09-15T00:00:19+02:00 supradough: fix delay + add some jsdoc types by froos in: [#1578](https://codeberg.org/uzu/strudel/pulls/1578)
-- 2025-09-14T12:42:58+02:00 added plyWith/plyWithClassic functions by Dsm0 in: [#1571](https://codeberg.org/uzu/strudel/pulls/1571)
-- 2025-09-14T10:39:12+02:00 feat: sound alias by Options in: [#1494](https://codeberg.org/uzu/strudel/pulls/1494)
-- 2025-09-14T01:20:15+02:00 Bug Fix: Allow penv values to be falsy by glossing in: [#1559](https://codeberg.org/uzu/strudel/pulls/1559)
-- 2025-09-14T01:10:48+02:00 Update website/src/pages/workshop/first-sounds.mdx by fesmith in: [#1566](https://codeberg.org/uzu/strudel/pulls/1566)
-- 2025-09-14T01:07:47+02:00 fix: autocomplete-styles + html rendering by froos in: [#1570](https://codeberg.org/uzu/strudel/pulls/1570)
-- 2025-09-14T00:49:17+02:00 Feature: Synonyms in autocomplete and reference by glossing in: [#1535](https://codeberg.org/uzu/strudel/pulls/1535)
-- 2025-09-13T20:01:48+02:00 Docs: add xen package examples by dudymas in: [#1446](https://codeberg.org/uzu/strudel/pulls/1446)
-- 2025-09-13T19:51:10+02:00 Update website/src/pages/learn/code.mdx by anecondev in: [#1391](https://codeberg.org/uzu/strudel/pulls/1391)
-- 2025-09-11T22:52:30+02:00 supradough poc by froos in: [#1362](https://codeberg.org/uzu/strudel/pulls/1362)
-- 2025-09-11T17:29:35+02:00 fix: exclude mondough dependencies by froos in: [#1563](https://codeberg.org/uzu/strudel/pulls/1563)
-- 2025-09-11T00:27:21+02:00 add basicSetup for keybindings by Dsm0 in: [#1462](https://codeberg.org/uzu/strudel/pulls/1462)
-- 2025-09-10T17:25:26+02:00 feat: add delete user samples button for convenience by daslyfe in: [#1556](https://codeberg.org/uzu/strudel/pulls/1556)
-- 2025-09-08T08:54:01+02:00 Fix formatting of REPL footnote by ddbeck in: [#1547](https://codeberg.org/uzu/strudel/pulls/1547)
-- 2025-09-08T05:38:08+02:00 fix: OSC by daslyfe in: [#1557](https://codeberg.org/uzu/strudel/pulls/1557)
-- 2025-09-07T22:47:13+02:00 Add examples for ? and | operators to documentation by james-collapse in: [#1532](https://codeberg.org/uzu/strudel/pulls/1532)
-- 2025-09-07T21:48:19+02:00 Signal flow documentation by glossing in: [#1504](https://codeberg.org/uzu/strudel/pulls/1504)
-- 2025-09-07T21:27:29+02:00 Allow flattening of dirs with sample server by glossing in: [#1529](https://codeberg.org/uzu/strudel/pulls/1529)
-- 2025-09-07T21:05:24+02:00 fix: prevent orbit clicking by defining max number of channels in an orbit by daslyfe in: [#1552](https://codeberg.org/uzu/strudel/pulls/1552)
-- 2025-09-02T08:42:42+02:00 Padding for tooltips, preserving linebreaks in descriptions, not closing autocompletes on click by glossing in: [#1521](https://codeberg.org/uzu/strudel/pulls/1521)
-- 2025-09-01T17:50:11+02:00 Update "restore defaults" to not delete patterns by glossing in: [#1519](https://codeberg.org/uzu/strudel/pulls/1519)
+- 2025-09-29T02:10:54+02:00 fix wavetable JSON by @daslyfe in: [#1611](https://codeberg.org/uzu/strudel/pulls/1611)
+- 2025-09-28T21:28:16+02:00 rename wavetable controls to match existing naming conventions by @daslyfe in: [#1610](https://codeberg.org/uzu/strudel/pulls/1610)
+- 2025-09-27T23:28:13+02:00 Feature: Wavetable synth improvements by @glossing in: [#1607](https://codeberg.org/uzu/strudel/pulls/1607)
+- 2025-09-27T21:43:10+02:00 wavetable improvements by @daslyfe in: [#1608](https://codeberg.org/uzu/strudel/pulls/1608)
+- 2025-09-26T08:48:46+02:00 create orbit based DJ filter by @daslyfe in: [#1603](https://codeberg.org/uzu/strudel/pulls/1603)
+- 2025-09-26T08:15:49+02:00 Feature: Wavetable synth by @glossing in: [#1525](https://codeberg.org/uzu/strudel/pulls/1525)
+- 2025-09-23T13:28:20+02:00 fix: time signal by @daslyfe in: [#1583](https://codeberg.org/uzu/strudel/pulls/1583)
+- 2025-09-21T16:16:06+02:00 mondo: fix all + setcpm + setcps by @froos in: [#1600](https://codeberg.org/uzu/strudel/pulls/1600)
+- 2025-09-19T21:59:43+02:00 fix: osc error message by @froos in: [#1597](https://codeberg.org/uzu/strudel/pulls/1597)
+- 2025-09-18T21:09:56+02:00 osc: --debug flag to see incoming messages by @froos in: [#1595](https://codeberg.org/uzu/strudel/pulls/1595)
+- 2025-09-17T14:12:10+02:00 simplify osc usage by @froos in: [#1588](https://codeberg.org/uzu/strudel/pulls/1588)
+- 2025-09-16T16:59:58+02:00 dev: logger errors to console in dev mode by @daslyfe in: [#1585](https://codeberg.org/uzu/strudel/pulls/1585)
+- 2025-09-16T03:19:37+02:00 Bug Fix / Feature: Updates to `duck` to avoid clicks and allow configuration over release/attack by @glossing in: [#1514](https://codeberg.org/uzu/strudel/pulls/1514)
+- 2025-09-15T23:36:31+02:00 Feat: Enhance `scale` function to quantize notes to a named scale by @glossing in: [#1492](https://codeberg.org/uzu/strudel/pulls/1492)
+- 2025-09-15T22:52:14+02:00 add tic80 font by @froos in: [#1579](https://codeberg.org/uzu/strudel/pulls/1579)
+- 2025-09-15T00:00:19+02:00 supradough: fix delay + add some jsdoc types by @froos in: [#1578](https://codeberg.org/uzu/strudel/pulls/1578)
+- 2025-09-14T12:42:58+02:00 added plyWith/plyWithClassic functions by @Dsm0 in: [#1571](https://codeberg.org/uzu/strudel/pulls/1571)
+- 2025-09-14T10:39:12+02:00 feat: sound alias by @Options in: [#1494](https://codeberg.org/uzu/strudel/pulls/1494)
+- 2025-09-14T01:20:15+02:00 Bug Fix: Allow penv values to be falsy by @glossing in: [#1559](https://codeberg.org/uzu/strudel/pulls/1559)
+- 2025-09-14T01:10:48+02:00 Update website/src/pages/workshop/first-sounds.mdx by @fesmith in: [#1566](https://codeberg.org/uzu/strudel/pulls/1566)
+- 2025-09-14T01:07:47+02:00 fix: autocomplete-styles + html rendering by @froos in: [#1570](https://codeberg.org/uzu/strudel/pulls/1570)
+- 2025-09-14T00:49:17+02:00 Feature: Synonyms in autocomplete and reference by @glossing in: [#1535](https://codeberg.org/uzu/strudel/pulls/1535)
+- 2025-09-13T20:01:48+02:00 Docs: add xen package examples by @dudymas in: [#1446](https://codeberg.org/uzu/strudel/pulls/1446)
+- 2025-09-13T19:51:10+02:00 Update website/src/pages/learn/code.mdx by @anecondev in: [#1391](https://codeberg.org/uzu/strudel/pulls/1391)
+- 2025-09-11T22:52:30+02:00 supradough poc by @froos in: [#1362](https://codeberg.org/uzu/strudel/pulls/1362)
+- 2025-09-11T17:29:35+02:00 fix: exclude mondough dependencies by @froos in: [#1563](https://codeberg.org/uzu/strudel/pulls/1563)
+- 2025-09-11T00:27:21+02:00 add basicSetup for keybindings by @Dsm0 in: [#1462](https://codeberg.org/uzu/strudel/pulls/1462)
+- 2025-09-10T17:25:26+02:00 feat: add delete user samples button for convenience by @daslyfe in: [#1556](https://codeberg.org/uzu/strudel/pulls/1556)
+- 2025-09-08T08:54:01+02:00 Fix formatting of REPL footnote by @ddbeck in: [#1547](https://codeberg.org/uzu/strudel/pulls/1547)
+- 2025-09-08T05:38:08+02:00 fix: OSC by @daslyfe in: [#1557](https://codeberg.org/uzu/strudel/pulls/1557)
+- 2025-09-07T22:47:13+02:00 Add examples for ? and | operators to documentation by james-@collapse in: [#1532](https://codeberg.org/uzu/strudel/pulls/1532)
+- 2025-09-07T21:48:19+02:00 Signal flow documentation by @glossing in: [#1504](https://codeberg.org/uzu/strudel/pulls/1504)
+- 2025-09-07T21:27:29+02:00 Allow flattening of dirs with sample server by @glossing in: [#1529](https://codeberg.org/uzu/strudel/pulls/1529)
+- 2025-09-07T21:05:24+02:00 fix: prevent orbit clicking by defining max number of channels in an orbit by @daslyfe in: [#1552](https://codeberg.org/uzu/strudel/pulls/1552)
+- 2025-09-02T08:42:42+02:00 Padding for tooltips, preserving linebreaks in descriptions, not closing autocompletes on click by @glossing in: [#1521](https://codeberg.org/uzu/strudel/pulls/1521)
+- 2025-09-01T17:50:11+02:00 Update "restore defaults" to not delete patterns by @glossing in: [#1519](https://codeberg.org/uzu/strudel/pulls/1519)
## august 2025
-- 2025-08-31T19:10:04+02:00 feat: add the ability to control the speed and start time of the reverb IR by daslyfe in: [#1501](https://codeberg.org/uzu/strudel/pulls/1501)
-- 2025-08-25T02:31:22+02:00 Bug Fix: Duck on Mobile / Safari by glossing in: [#1503](https://codeberg.org/uzu/strudel/pulls/1503)
-- 2025-08-23T18:39:53+02:00 fix benchmarks by yaxu in: [#1517](https://codeberg.org/uzu/strudel/pulls/1517)
-- 2025-08-21T20:57:31+02:00 add --json flag to @strudel/sampler to generate a strudel.json by froos in: [#1513](https://codeberg.org/uzu/strudel/pulls/1513)
-- 2025-08-21T10:04:28+02:00 remove hs2js postinstall by froos in: [#1510](https://codeberg.org/uzu/strudel/pulls/1510)
-- 2025-08-20T15:15:34+02:00 doc: scrub, duckorbit, duckattack, duckdepth + fix: arp, arpWidth, hush by fyynn in: [#1502](https://codeberg.org/uzu/strudel/pulls/1502)
-- 2025-08-20T12:31:37+02:00 fix: repl autocomplete not rendering correctly by robase in: [#1480](https://codeberg.org/uzu/strudel/pulls/1480)
-- 2025-08-20T12:10:02+02:00 BUG FIX: make 'midin' initialization work with multiple controllers by cbabraham in: [#1469](https://codeberg.org/uzu/strudel/pulls/1469)
-- 2025-08-17T23:18:46+02:00 euclidish by yaxu in: [#1482](https://codeberg.org/uzu/strudel/pulls/1482)
-- 2025-08-17T06:37:23+02:00 feat: Create a duck (sidechain) orbit effect by daslyfe in: [#1470](https://codeberg.org/uzu/strudel/pulls/1470)
-- 2025-08-17T04:40:15+02:00 Bug Fix: Restore `log` functionality after onTrigger arg removal by glossing in: [#1491](https://codeberg.org/uzu/strudel/pulls/1491)
-- 2025-08-17T04:33:39+02:00 Bug Fix: Handle zero appearing first in FM's ADSR by glossing in: [#1496](https://codeberg.org/uzu/strudel/pulls/1496)
-- 2025-08-17T04:27:19+02:00 Bug Fix: FM (and vibrato) for Supersaws by glossing in: [#1495](https://codeberg.org/uzu/strudel/pulls/1495)
-- 2025-08-04T07:51:31+02:00 Fix incorrect stack Mini Notation by samyk in: [#1484](https://codeberg.org/uzu/strudel/pulls/1484)
-- 2025-08-03T18:57:45+02:00 fix: regression caused by incorrectly exported alias for transpose and scaleTranspose by daslyfe in: [#1489](https://codeberg.org/uzu/strudel/pulls/1489)
-- 2025-08-03T18:34:13+02:00 Add `strans` and `scaleTrans` as synonyms of `scaleTranspose` by TodePond in: [#1488](https://codeberg.org/uzu/strudel/pulls/1488)
-- 2025-08-02T18:18:28+02:00 Add `trans` alias for `transpose` by TodePond in: [#1487](https://codeberg.org/uzu/strudel/pulls/1487)
-- 2025-08-02T03:27:26+02:00 feat: Create Accurate 909 bass drum synthesizer by daslyfe in: [#1478](https://codeberg.org/uzu/strudel/pulls/1478)
-- 2025-08-02T03:23:49+02:00 feat: Add fmwave control and ability to fm with noise by daslyfe in: [#1472](https://codeberg.org/uzu/strudel/pulls/1472)
+- 2025-08-31T19:10:04+02:00 feat: add the ability to control the speed and start time of the reverb IR by @daslyfe in: [#1501](https://codeberg.org/uzu/strudel/pulls/1501)
+- 2025-08-25T02:31:22+02:00 Bug Fix: Duck on Mobile / Safari by @glossing in: [#1503](https://codeberg.org/uzu/strudel/pulls/1503)
+- 2025-08-23T18:39:53+02:00 fix benchmarks by @yaxu in: [#1517](https://codeberg.org/uzu/strudel/pulls/1517)
+- 2025-08-21T20:57:31+02:00 add --json flag to @strudel/sampler to generate a strudel.json by @froos in: [#1513](https://codeberg.org/uzu/strudel/pulls/1513)
+- 2025-08-21T10:04:28+02:00 remove hs2js postinstall by @froos in: [#1510](https://codeberg.org/uzu/strudel/pulls/1510)
+- 2025-08-20T15:15:34+02:00 doc: scrub, duckorbit, duckattack, duckdepth + fix: arp, arpWidth, hush by @fyynn in: [#1502](https://codeberg.org/uzu/strudel/pulls/1502)
+- 2025-08-20T12:31:37+02:00 fix: repl autocomplete not rendering correctly by @robase in: [#1480](https://codeberg.org/uzu/strudel/pulls/1480)
+- 2025-08-20T12:10:02+02:00 BUG FIX: make 'midin' initialization work with multiple controllers by @cbabraham in: [#1469](https://codeberg.org/uzu/strudel/pulls/1469)
+- 2025-08-17T23:18:46+02:00 euclidish by @yaxu in: [#1482](https://codeberg.org/uzu/strudel/pulls/1482)
+- 2025-08-17T06:37:23+02:00 feat: Create a duck (sidechain) orbit effect by @daslyfe in: [#1470](https://codeberg.org/uzu/strudel/pulls/1470)
+- 2025-08-17T04:40:15+02:00 Bug Fix: Restore `log` functionality after onTrigger arg removal by @glossing in: [#1491](https://codeberg.org/uzu/strudel/pulls/1491)
+- 2025-08-17T04:33:39+02:00 Bug Fix: Handle zero appearing first in FM's ADSR by @glossing in: [#1496](https://codeberg.org/uzu/strudel/pulls/1496)
+- 2025-08-17T04:27:19+02:00 Bug Fix: FM (and vibrato) for Supersaws by @glossing in: [#1495](https://codeberg.org/uzu/strudel/pulls/1495)
+- 2025-08-04T07:51:31+02:00 Fix incorrect stack Mini Notation by @samyk in: [#1484](https://codeberg.org/uzu/strudel/pulls/1484)
+- 2025-08-03T18:57:45+02:00 fix: regression caused by incorrectly exported alias for transpose and scaleTranspose by @daslyfe in: [#1489](https://codeberg.org/uzu/strudel/pulls/1489)
+- 2025-08-03T18:34:13+02:00 Add `strans` and `scaleTrans` as synonyms of `scaleTranspose` by @TodePond in: [#1488](https://codeberg.org/uzu/strudel/pulls/1488)
+- 2025-08-02T18:18:28+02:00 Add `trans` alias for `transpose` by @TodePond in: [#1487](https://codeberg.org/uzu/strudel/pulls/1487)
+- 2025-08-02T03:27:26+02:00 feat: Create Accurate 909 bass drum synthesizer by @daslyfe in: [#1478](https://codeberg.org/uzu/strudel/pulls/1478)
+- 2025-08-02T03:23:49+02:00 feat: Add fmwave control and ability to fm with noise by @daslyfe in: [#1472](https://codeberg.org/uzu/strudel/pulls/1472)
## july 2025
-- 2025-07-30T00:22:41+02:00 hotfix: uzu kit JSON should be in the repo to avoid offline loading errors by daslyfe in: [#1485](https://codeberg.org/uzu/strudel/pulls/1485)
-- 2025-07-24T05:28:23+02:00 feat: make uzu-drumkit the default drumkit by daslyfe in: [#1422](https://codeberg.org/uzu/strudel/pulls/1422)
-- 2025-07-21T07:16:19+02:00 FIX: PWM modulation by daslyfe in: [#1467](https://codeberg.org/uzu/strudel/pulls/1467)
-- 2025-07-19T17:16:22+02:00 Tremolo modulation by Ghost in: [#1095](https://codeberg.org/uzu/strudel/pulls/1095)
-- 2025-07-15T09:39:33+02:00 fix: can now use def in mondough by froos in: [#1461](https://codeberg.org/uzu/strudel/pulls/1461)
-- 2025-07-11T11:10:24+02:00 fixed keybinding presedence issue by Dsm0 in: [#1456](https://codeberg.org/uzu/strudel/pulls/1456)
-- 2025-07-11T11:09:05+02:00 added multicursor support on ctrl/cmd + click by Dsm0 in: [#1457](https://codeberg.org/uzu/strudel/pulls/1457)
-- 2025-07-09T09:39:46+02:00 added tab-indent setting by Dsm0 in: [#1454](https://codeberg.org/uzu/strudel/pulls/1454)
-- 2025-07-08T15:48:41+02:00 ontrigger-refactoring by froos in: [#1442](https://codeberg.org/uzu/strudel/pulls/1442)
-- 2025-07-07T23:14:24+02:00 fix: remove first gm_synth_bass_1, as it doesn't work in safari by froos in: [#1452](https://codeberg.org/uzu/strudel/pulls/1452)
-- 2025-07-07T00:06:16+02:00 fix: minor doc changes by Aurel300 in: [#1435](https://codeberg.org/uzu/strudel/pulls/1435)
-- 2025-07-05T12:53:45+02:00 Fix randrun and deps including shuffle. Fixes #1441 by yaxu in: [#1447](https://codeberg.org/uzu/strudel/pulls/1447)
-- 2025-07-05T12:15:52+02:00 add setDefault + resetDefaults to superdough by froos in: [#1433](https://codeberg.org/uzu/strudel/pulls/1433)
-- 2025-07-04T22:36:19+02:00 disable fm for supersaw by froos in: [#1443](https://codeberg.org/uzu/strudel/pulls/1443)
+- 2025-07-30T00:22:41+02:00 hotfix: uzu kit JSON should be in the repo to avoid offline loading errors by @daslyfe in: [#1485](https://codeberg.org/uzu/strudel/pulls/1485)
+- 2025-07-24T05:28:23+02:00 feat: make uzu-drumkit the default drumkit by @daslyfe in: [#1422](https://codeberg.org/uzu/strudel/pulls/1422)
+- 2025-07-21T07:16:19+02:00 FIX: PWM modulation by @daslyfe in: [#1467](https://codeberg.org/uzu/strudel/pulls/1467)
+- 2025-07-19T17:16:22+02:00 Tremolo modulation by @Ghost in: [#1095](https://codeberg.org/uzu/strudel/pulls/1095)
+- 2025-07-15T09:39:33+02:00 fix: can now use def in mondough by @froos in: [#1461](https://codeberg.org/uzu/strudel/pulls/1461)
+- 2025-07-11T11:10:24+02:00 fixed keybinding presedence issue by @Dsm0 in: [#1456](https://codeberg.org/uzu/strudel/pulls/1456)
+- 2025-07-11T11:09:05+02:00 added multicursor support on ctrl/cmd + click by @Dsm0 in: [#1457](https://codeberg.org/uzu/strudel/pulls/1457)
+- 2025-07-09T09:39:46+02:00 added tab-indent setting by @Dsm0 in: [#1454](https://codeberg.org/uzu/strudel/pulls/1454)
+- 2025-07-08T15:48:41+02:00 ontrigger-refactoring by @froos in: [#1442](https://codeberg.org/uzu/strudel/pulls/1442)
+- 2025-07-07T23:14:24+02:00 fix: remove first gm_synth_bass_1, as it doesn't work in safari by @froos in: [#1452](https://codeberg.org/uzu/strudel/pulls/1452)
+- 2025-07-07T00:06:16+02:00 fix: minor doc changes by @Aurel300 in: [#1435](https://codeberg.org/uzu/strudel/pulls/1435)
+- 2025-07-05T12:53:45+02:00 Fix randrun and deps including shuffle. Fixes #1441 by @yaxu in: [#1447](https://codeberg.org/uzu/strudel/pulls/1447)
+- 2025-07-05T12:15:52+02:00 add setDefault + resetDefaults to superdough by @froos in: [#1433](https://codeberg.org/uzu/strudel/pulls/1433)
+- 2025-07-04T22:36:19+02:00 disable fm for supersaw by @froos in: [#1443](https://codeberg.org/uzu/strudel/pulls/1443)
## june 2025
-- 2025-06-30T13:28:10+02:00 corrected minor spelling mistake (#1425) by tj-mueller in: [#1434](https://codeberg.org/uzu/strudel/pulls/1434)
-- 2025-06-30T05:26:11+02:00 Add browser cache explanation in samples.mdx by Ghost in: [#1369](https://codeberg.org/uzu/strudel/pulls/1369)
-- 2025-06-30T05:18:42+02:00 add-release-notes by froos in: [#1432](https://codeberg.org/uzu/strudel/pulls/1432)
-- 2025-06-28T20:30:49+02:00 feat: delaytime in cycles by Ghost in: [#1341](https://codeberg.org/uzu/strudel/pulls/1341)
-- 2025-06-28T13:44:49+02:00 Case insensitive search in the reference tab by kdiab in: [#1420](https://codeberg.org/uzu/strudel/pulls/1420)
-- 2025-06-28T00:04:13+02:00 add unjoin, into and chunkinto by yaxu in: [#1418](https://codeberg.org/uzu/strudel/pulls/1418)
-- 2025-06-26T15:29:46+02:00 mondo notation by froos in: [#1311](https://codeberg.org/uzu/strudel/pulls/1311)
-- 2025-06-24T06:14:15+02:00 allow calling `all` multiple times by froos in: [#1417](https://codeberg.org/uzu/strudel/pulls/1417)
-- 2025-06-24T05:53:22+02:00 tonal: allow scales without tonic (default to C) by Ghost in: [#1092](https://codeberg.org/uzu/strudel/pulls/1092)
-- 2025-06-20T20:00:12+02:00 website intro: fix whitespace and code hosting name by trofi in: [#1400](https://codeberg.org/uzu/strudel/pulls/1400)
-- 2025-06-19T10:15:07+02:00 fix stepcat #1396 by yaxu in: [#1398](https://codeberg.org/uzu/strudel/pulls/1398)
-- 2025-06-19T09:52:38+02:00 deprecate cpm + refactor docs to use setcpm by froos in: [#1397](https://codeberg.org/uzu/strudel/pulls/1397)
-- 2025-06-19T02:49:09+02:00 feat: 3 new codemirror themes by daslyfe in: [#1394](https://codeberg.org/uzu/strudel/pulls/1394)
-- 2025-06-14T16:23:00+02:00 link back to tech manual in wiki by yaxu in: [#1382](https://codeberg.org/uzu/strudel/pulls/1382)
-- 2025-06-14T14:55:37+02:00 degithub-links by froos in: [#1380](https://codeberg.org/uzu/strudel/pulls/1380)
-- 2025-06-13T15:24:42+02:00 fix euclidLegatoRot by bwagner in: [#1378](https://codeberg.org/uzu/strudel/pulls/1378)
-- 2025-06-13T10:07:51+02:00 remove-ms by yaxu in: [#1377](https://codeberg.org/uzu/strudel/pulls/1377)
-- 2025-06-12T10:25:48+02:00 Share fat URL by Ghost in: [#1375](https://codeberg.org/uzu/strudel/pulls/1375)
-- 2025-06-05T20:39:16+02:00 feat: onTriggerTime for interfacing with random APIs and doing illegal things on event time by Ghost in: [#1364](https://codeberg.org/uzu/strudel/pulls/1364)
-- 2025-06-05T01:08:18+02:00 feat: berlin noise by Ghost in: [#1363](https://codeberg.org/uzu/strudel/pulls/1363)
+- 2025-06-30T13:28:10+02:00 corrected minor spelling mistake (#1425) by tj-@mueller in: [#1434](https://codeberg.org/uzu/strudel/pulls/1434)
+- 2025-06-30T05:26:11+02:00 Add browser cache explanation in samples.mdx by @Ghost in: [#1369](https://codeberg.org/uzu/strudel/pulls/1369)
+- 2025-06-30T05:18:42+02:00 add-release-notes by @froos in: [#1432](https://codeberg.org/uzu/strudel/pulls/1432)
+- 2025-06-28T20:30:49+02:00 feat: delaytime in cycles by @Ghost in: [#1341](https://codeberg.org/uzu/strudel/pulls/1341)
+- 2025-06-28T13:44:49+02:00 Case insensitive search in the reference tab by @kdiab in: [#1420](https://codeberg.org/uzu/strudel/pulls/1420)
+- 2025-06-28T00:04:13+02:00 add unjoin, into and chunkinto by @yaxu in: [#1418](https://codeberg.org/uzu/strudel/pulls/1418)
+- 2025-06-26T15:29:46+02:00 mondo notation by @froos in: [#1311](https://codeberg.org/uzu/strudel/pulls/1311)
+- 2025-06-24T06:14:15+02:00 allow calling `all` multiple times by @froos in: [#1417](https://codeberg.org/uzu/strudel/pulls/1417)
+- 2025-06-24T05:53:22+02:00 tonal: allow scales without tonic (default to C) by @Ghost in: [#1092](https://codeberg.org/uzu/strudel/pulls/1092)
+- 2025-06-20T20:00:12+02:00 website intro: fix whitespace and code hosting name by @trofi in: [#1400](https://codeberg.org/uzu/strudel/pulls/1400)
+- 2025-06-19T10:15:07+02:00 fix stepcat #1396 by @yaxu in: [#1398](https://codeberg.org/uzu/strudel/pulls/1398)
+- 2025-06-19T09:52:38+02:00 deprecate cpm + refactor docs to use setcpm by @froos in: [#1397](https://codeberg.org/uzu/strudel/pulls/1397)
+- 2025-06-19T02:49:09+02:00 feat: 3 new codemirror themes by @daslyfe in: [#1394](https://codeberg.org/uzu/strudel/pulls/1394)
+- 2025-06-14T16:23:00+02:00 link back to tech manual in wiki by @yaxu in: [#1382](https://codeberg.org/uzu/strudel/pulls/1382)
+- 2025-06-14T14:55:37+02:00 degithub-links by @froos in: [#1380](https://codeberg.org/uzu/strudel/pulls/1380)
+- 2025-06-13T15:24:42+02:00 fix euclidLegatoRot by @bwagner in: [#1378](https://codeberg.org/uzu/strudel/pulls/1378)
+- 2025-06-13T10:07:51+02:00 remove-ms by @yaxu in: [#1377](https://codeberg.org/uzu/strudel/pulls/1377)
+- 2025-06-12T10:25:48+02:00 Share fat URL by @Ghost in: [#1375](https://codeberg.org/uzu/strudel/pulls/1375)
+- 2025-06-05T20:39:16+02:00 feat: onTriggerTime for interfacing with random APIs and doing illegal things on event time by @Ghost in: [#1364](https://codeberg.org/uzu/strudel/pulls/1364)
+- 2025-06-05T01:08:18+02:00 feat: berlin noise by @Ghost in: [#1363](https://codeberg.org/uzu/strudel/pulls/1363)
## may 2025
-- 2025-05-29T14:36:43+02:00 Fix bytebeat sample offset by Ghost in: [#1359](https://codeberg.org/uzu/strudel/pulls/1359)
-- 2025-05-29T12:14:18+02:00 preserve stepcount in chunks by yaxu in: [#1358](https://codeberg.org/uzu/strudel/pulls/1358)
-- 2025-05-29T02:34:30+02:00 Byte Beat improvements -> 2 by Ghost in: [#1357](https://codeberg.org/uzu/strudel/pulls/1357)
-- 2025-05-28T16:40:32+02:00 Bytebeat improvements by Ghost in: [#1356](https://codeberg.org/uzu/strudel/pulls/1356)
-- 2025-05-27T17:42:39+02:00 feat: Byte Beats! by Ghost in: [#1354](https://codeberg.org/uzu/strudel/pulls/1354)
-- 2025-05-18T21:43:05+02:00 fix: typo on docs causing problems with autocompletion. by Ghost in: [#1350](https://codeberg.org/uzu/strudel/pulls/1350)
-- 2025-05-15T01:12:07+02:00 feat: Create pulsewidth (pw) and pulsewidth lfo parameters by Ghost in: [#1343](https://codeberg.org/uzu/strudel/pulls/1343)
-- 2025-05-14T18:25:17+02:00 feat: Multi Channel Orbits by Ghost in: [#1344](https://codeberg.org/uzu/strudel/pulls/1344)
-- 2025-05-13T17:45:29+02:00 Fix typo by Ghost in: [#1346](https://codeberg.org/uzu/strudel/pulls/1346)
-- 2025-05-02T00:01:27+02:00 Fix web + repl package builds by froos in: [#1339](https://codeberg.org/uzu/strudel/pulls/1339)
-- 2025-05-01T23:50:57+02:00 fix: superdough worklets bundling by froos in: [#1338](https://codeberg.org/uzu/strudel/pulls/1338)
+- 2025-05-29T14:36:43+02:00 Fix bytebeat sample offset by @Ghost in: [#1359](https://codeberg.org/uzu/strudel/pulls/1359)
+- 2025-05-29T12:14:18+02:00 preserve stepcount in chunks by @yaxu in: [#1358](https://codeberg.org/uzu/strudel/pulls/1358)
+- 2025-05-29T02:34:30+02:00 Byte Beat improvements -> 2 by @Ghost in: [#1357](https://codeberg.org/uzu/strudel/pulls/1357)
+- 2025-05-28T16:40:32+02:00 Bytebeat improvements by @Ghost in: [#1356](https://codeberg.org/uzu/strudel/pulls/1356)
+- 2025-05-27T17:42:39+02:00 feat: Byte Beats! by @Ghost in: [#1354](https://codeberg.org/uzu/strudel/pulls/1354)
+- 2025-05-18T21:43:05+02:00 fix: typo on docs causing problems with autocompletion. by @Ghost in: [#1350](https://codeberg.org/uzu/strudel/pulls/1350)
+- 2025-05-15T01:12:07+02:00 feat: Create pulsewidth (pw) and pulsewidth lfo parameters by @Ghost in: [#1343](https://codeberg.org/uzu/strudel/pulls/1343)
+- 2025-05-14T18:25:17+02:00 feat: Multi Channel Orbits by @Ghost in: [#1344](https://codeberg.org/uzu/strudel/pulls/1344)
+- 2025-05-13T17:45:29+02:00 Fix typo by @Ghost in: [#1346](https://codeberg.org/uzu/strudel/pulls/1346)
+- 2025-05-02T00:01:27+02:00 Fix web + repl package builds by @froos in: [#1339](https://codeberg.org/uzu/strudel/pulls/1339)
+- 2025-05-01T23:50:57+02:00 fix: superdough worklets bundling by @froos in: [#1338](https://codeberg.org/uzu/strudel/pulls/1338)
## april 2025
-- 2025-04-27T22:25:54+02:00 FIX: sound import order by Ghost in: [#1333](https://codeberg.org/uzu/strudel/pulls/1333)
-- 2025-04-27T18:39:49+02:00 update docs to reflect import sounds tab change by hpunq in: [#1332](https://codeberg.org/uzu/strudel/pulls/1332)
-- 2025-04-27T18:38:26+02:00 feat: Improve gain curve by Ghost in: [#1318](https://codeberg.org/uzu/strudel/pulls/1318)
-- 2025-04-27T07:54:49+02:00 Add Icon to import sample button by Ghost in: [#1331](https://codeberg.org/uzu/strudel/pulls/1331)
-- 2025-04-27T07:53:41+02:00 Add new "import-sounds" tab with explanation on folder import by hpunq in: [#1329](https://codeberg.org/uzu/strudel/pulls/1329)
-- 2025-04-22T00:04:38+02:00 feat: new themes + theme improvements by Ghost in: [#1326](https://codeberg.org/uzu/strudel/pulls/1326)
-- 2025-04-20T18:24:15+02:00 feat: Create scrub function for scrubbing an audio file by Ghost in: [#1321](https://codeberg.org/uzu/strudel/pulls/1321)
-- 2025-04-18T07:17:39+02:00 fix: disable astro toolbar by default by Ghost in: [#1324](https://codeberg.org/uzu/strudel/pulls/1324)
-- 2025-04-18T07:17:38+02:00 fix: udels header by Ghost in: [#1325](https://codeberg.org/uzu/strudel/pulls/1325)
-- 2025-04-11T09:18:58+02:00 Send delta in OSC message in seconds, to match tidal/superdirt by yaxu in: [#1323](https://codeberg.org/uzu/strudel/pulls/1323)
-- 2025-04-08T06:08:57+02:00 FIX: Multichannel Audio by Ghost in: [#1322](https://codeberg.org/uzu/strudel/pulls/1322)
-- 2025-04-08T04:18:03+02:00 feat: add max polyphony feature for superdough by Ghost in: [#1317](https://codeberg.org/uzu/strudel/pulls/1317)
-- 2025-04-05T21:12:05+02:00 enhancement: make error messages easier to read by Ghost in: [#1315](https://codeberg.org/uzu/strudel/pulls/1315)
-- 2025-04-04T06:26:57+02:00 fix: replace empty spaces in registered sound keys by Ghost in: [#1319](https://codeberg.org/uzu/strudel/pulls/1319)
+- 2025-04-27T22:25:54+02:00 FIX: sound import order by @Ghost in: [#1333](https://codeberg.org/uzu/strudel/pulls/1333)
+- 2025-04-27T18:39:49+02:00 update docs to reflect import sounds tab change by @hpunq in: [#1332](https://codeberg.org/uzu/strudel/pulls/1332)
+- 2025-04-27T18:38:26+02:00 feat: Improve gain curve by @Ghost in: [#1318](https://codeberg.org/uzu/strudel/pulls/1318)
+- 2025-04-27T07:54:49+02:00 Add Icon to import sample button by @Ghost in: [#1331](https://codeberg.org/uzu/strudel/pulls/1331)
+- 2025-04-27T07:53:41+02:00 Add new "import-sounds" tab with explanation on folder import by @hpunq in: [#1329](https://codeberg.org/uzu/strudel/pulls/1329)
+- 2025-04-22T00:04:38+02:00 feat: new themes + theme improvements by @Ghost in: [#1326](https://codeberg.org/uzu/strudel/pulls/1326)
+- 2025-04-20T18:24:15+02:00 feat: Create scrub function for scrubbing an audio file by @Ghost in: [#1321](https://codeberg.org/uzu/strudel/pulls/1321)
+- 2025-04-18T07:17:39+02:00 fix: disable astro toolbar by default by @Ghost in: [#1324](https://codeberg.org/uzu/strudel/pulls/1324)
+- 2025-04-18T07:17:38+02:00 fix: udels header by @Ghost in: [#1325](https://codeberg.org/uzu/strudel/pulls/1325)
+- 2025-04-11T09:18:58+02:00 Send delta in OSC message in seconds, to match tidal/superdirt by @yaxu in: [#1323](https://codeberg.org/uzu/strudel/pulls/1323)
+- 2025-04-08T06:08:57+02:00 FIX: Multichannel Audio by @Ghost in: [#1322](https://codeberg.org/uzu/strudel/pulls/1322)
+- 2025-04-08T04:18:03+02:00 feat: add max polyphony feature for superdough by @Ghost in: [#1317](https://codeberg.org/uzu/strudel/pulls/1317)
+- 2025-04-05T21:12:05+02:00 enhancement: make error messages easier to read by @Ghost in: [#1315](https://codeberg.org/uzu/strudel/pulls/1315)
+- 2025-04-04T06:26:57+02:00 fix: replace empty spaces in registered sound keys by @Ghost in: [#1319](https://codeberg.org/uzu/strudel/pulls/1319)
## march 2025
-- 2025-03-26T17:01:05+01:00 small feat: Add alias for segment and ribbon by Ghost in: [#1314](https://codeberg.org/uzu/strudel/pulls/1314)
-- 2025-03-26T14:54:18+01:00 Fix typo pattnr by Ghost in: [#1316](https://codeberg.org/uzu/strudel/pulls/1316)
-- 2025-03-23T20:05:31+01:00 bugfix: Allow single param to be used in the as function by Ghost in: [#1312](https://codeberg.org/uzu/strudel/pulls/1312)
-- 2025-03-20T23:35:18+01:00 Add MIDI Program Change, SysEx, NRPN, PitchBend and AfterTouch Output by nkymut in: [#1244](https://codeberg.org/uzu/strudel/pulls/1244)
-- 2025-03-19T17:32:30+01:00 make soundfont base url configurable by Ghost in: [#1040](https://codeberg.org/uzu/strudel/pulls/1040)
-- 2025-03-18T20:07:08+01:00 Add num samples from 0 up to 20 by yaxu in: [#1310](https://codeberg.org/uzu/strudel/pulls/1310)
-- 2025-03-17T10:38:54+01:00 add num samples (edited numbers) by yaxu in: [#1309](https://codeberg.org/uzu/strudel/pulls/1309)
-- 2025-03-08T22:17:47+01:00 @strudel/sampler improvements by froos in: [#1288](https://codeberg.org/uzu/strudel/pulls/1288)
-- 2025-03-08T21:56:50+01:00 Add Gamepad module by nkymut in: [#1223](https://codeberg.org/uzu/strudel/pulls/1223)
-- 2025-03-04T19:17:37+01:00 change behaviour of polymeter, and remove polymeterSteps by yaxu in: [#1302](https://codeberg.org/uzu/strudel/pulls/1302)
-- 2025-03-04T03:36:57+01:00 feat: Create Pulse Oscillator with variable PWM by Ghost in: [#1304](https://codeberg.org/uzu/strudel/pulls/1304)
-- 2025-03-02T17:08:31+01:00 feat: Theme improvements by Ghost in: [#1295](https://codeberg.org/uzu/strudel/pulls/1295)
-- 2025-03-02T11:58:46+01:00 bugfix zoom stepcount by yaxu in: [#1301](https://codeberg.org/uzu/strudel/pulls/1301)
+- 2025-03-26T17:01:05+01:00 small feat: Add alias for segment and ribbon by @Ghost in: [#1314](https://codeberg.org/uzu/strudel/pulls/1314)
+- 2025-03-26T14:54:18+01:00 Fix typo pattnr by @Ghost in: [#1316](https://codeberg.org/uzu/strudel/pulls/1316)
+- 2025-03-23T20:05:31+01:00 bugfix: Allow single param to be used in the as function by @Ghost in: [#1312](https://codeberg.org/uzu/strudel/pulls/1312)
+- 2025-03-20T23:35:18+01:00 Add MIDI Program Change, SysEx, NRPN, PitchBend and AfterTouch Output by @nkymut in: [#1244](https://codeberg.org/uzu/strudel/pulls/1244)
+- 2025-03-19T17:32:30+01:00 make soundfont base url configurable by @Ghost in: [#1040](https://codeberg.org/uzu/strudel/pulls/1040)
+- 2025-03-18T20:07:08+01:00 Add num samples from 0 up to 20 by @yaxu in: [#1310](https://codeberg.org/uzu/strudel/pulls/1310)
+- 2025-03-17T10:38:54+01:00 add num samples (edited numbers) by @yaxu in: [#1309](https://codeberg.org/uzu/strudel/pulls/1309)
+- 2025-03-08T22:17:47+01:00 @strudel/sampler improvements by @froos in: [#1288](https://codeberg.org/uzu/strudel/pulls/1288)
+- 2025-03-08T21:56:50+01:00 Add Gamepad module by @nkymut in: [#1223](https://codeberg.org/uzu/strudel/pulls/1223)
+- 2025-03-04T19:17:37+01:00 change behaviour of polymeter, and remove polymeterSteps by @yaxu in: [#1302](https://codeberg.org/uzu/strudel/pulls/1302)
+- 2025-03-04T03:36:57+01:00 feat: Create Pulse Oscillator with variable PWM by @Ghost in: [#1304](https://codeberg.org/uzu/strudel/pulls/1304)
+- 2025-03-02T17:08:31+01:00 feat: Theme improvements by @Ghost in: [#1295](https://codeberg.org/uzu/strudel/pulls/1295)
+- 2025-03-02T11:58:46+01:00 bugfix zoom stepcount by @yaxu in: [#1301](https://codeberg.org/uzu/strudel/pulls/1301)
## february 2025
-- 2025-02-28T16:01:20+01:00 Fix test error #1297 by nkymut in: [#1298](https://codeberg.org/uzu/strudel/pulls/1298)
-- 2025-02-28T02:53:42+01:00 Hotfix: prevent undefined pattern code from crashing strudel on load by Ghost in: [#1297](https://codeberg.org/uzu/strudel/pulls/1297)
-- 2025-02-27T08:24:58+01:00 Fix misplaced ending sentence by Ghost in: [#1296](https://codeberg.org/uzu/strudel/pulls/1296)
-- 2025-02-23T10:54:13+01:00 Signpost licenses for source code and samples a bit more, ref #1277 by yaxu in: [#1289](https://codeberg.org/uzu/strudel/pulls/1289)
-- 2025-02-23T10:52:27+01:00 Allow wchooseCycles probabilities to be patterned by yaxu in: [#1292](https://codeberg.org/uzu/strudel/pulls/1292)
-- 2025-02-22T02:18:59+01:00 Create Pattern Page Pagination by Ghost in: [#1287](https://codeberg.org/uzu/strudel/pulls/1287)
-- 2025-02-21T22:38:10+01:00 showcase tweaks by yaxu in: [#1291](https://codeberg.org/uzu/strudel/pulls/1291)
-- 2025-02-11T16:34:24+01:00 Fixes inverted triangle wave by renaming it to `itri`, making non-inverted `tri` by yaxu in: [#1283](https://codeberg.org/uzu/strudel/pulls/1283)
-- 2025-02-11T10:02:34+01:00 Fix `squeezejoin` and functions using it, including `bite` by yaxu in: [#1286](https://codeberg.org/uzu/strudel/pulls/1286)
-- 2025-02-09T16:18:28+01:00 Rename repeat back to extend by yaxu in: [#1285](https://codeberg.org/uzu/strudel/pulls/1285)
-- 2025-02-07T18:11:52+01:00 mqtt bugfix - connection check by yaxu in: [#1282](https://codeberg.org/uzu/strudel/pulls/1282)
-- 2025-02-07T17:38:29+01:00 Bugfix: update mqtt connections dictionary by yaxu in: [#1281](https://codeberg.org/uzu/strudel/pulls/1281)
-- 2025-02-07T11:39:54+01:00 make mqtt topic patternable by yaxu in: [#1280](https://codeberg.org/uzu/strudel/pulls/1280)
-- 2025-02-07T11:07:32+01:00 midimaps by froos in: [#1274](https://codeberg.org/uzu/strudel/pulls/1274)
-- 2025-02-06T15:59:03+01:00 MQTT - support adding hap duration and cps metadata to JSON messages by yaxu in: [#1279](https://codeberg.org/uzu/strudel/pulls/1279)
-- 2025-02-05T16:10:54+01:00 [breaking change] Sample signals from query onset, rather than midpoint by yaxu in: [#1278](https://codeberg.org/uzu/strudel/pulls/1278)
-- 2025-02-03T00:55:36+01:00 Stepwise documentation tweaks, with mridangam samples by yaxu in: [#1275](https://codeberg.org/uzu/strudel/pulls/1275)
-- 2025-02-02T21:26:44+01:00 Polish, rename, and document stepwise functions by yaxu in: [#1262](https://codeberg.org/uzu/strudel/pulls/1262)
-- 2025-02-01T22:57:00+01:00 Fix sf2 timing by froos in: [#1272](https://codeberg.org/uzu/strudel/pulls/1272)
-- 2025-02-01T22:32:59+01:00 Add bank aliasing and case insensitivity by TodePond in: [#1245](https://codeberg.org/uzu/strudel/pulls/1245)
+- 2025-02-28T16:01:20+01:00 Fix test error #1297 by @nkymut in: [#1298](https://codeberg.org/uzu/strudel/pulls/1298)
+- 2025-02-28T02:53:42+01:00 Hotfix: prevent undefined pattern code from crashing strudel on load by @Ghost in: [#1297](https://codeberg.org/uzu/strudel/pulls/1297)
+- 2025-02-27T08:24:58+01:00 Fix misplaced ending sentence by @Ghost in: [#1296](https://codeberg.org/uzu/strudel/pulls/1296)
+- 2025-02-23T10:54:13+01:00 Signpost licenses for source code and samples a bit more, ref #1277 by @yaxu in: [#1289](https://codeberg.org/uzu/strudel/pulls/1289)
+- 2025-02-23T10:52:27+01:00 Allow wchooseCycles probabilities to be patterned by @yaxu in: [#1292](https://codeberg.org/uzu/strudel/pulls/1292)
+- 2025-02-22T02:18:59+01:00 Create Pattern Page Pagination by @Ghost in: [#1287](https://codeberg.org/uzu/strudel/pulls/1287)
+- 2025-02-21T22:38:10+01:00 showcase tweaks by @yaxu in: [#1291](https://codeberg.org/uzu/strudel/pulls/1291)
+- 2025-02-11T16:34:24+01:00 Fixes inverted triangle wave by renaming it to `itri`, making non-inverted `tri` by @yaxu in: [#1283](https://codeberg.org/uzu/strudel/pulls/1283)
+- 2025-02-11T10:02:34+01:00 Fix `squeezejoin` and functions using it, including `bite` by @yaxu in: [#1286](https://codeberg.org/uzu/strudel/pulls/1286)
+- 2025-02-09T16:18:28+01:00 Rename repeat back to extend by @yaxu in: [#1285](https://codeberg.org/uzu/strudel/pulls/1285)
+- 2025-02-07T18:11:52+01:00 mqtt bugfix - connection check by @yaxu in: [#1282](https://codeberg.org/uzu/strudel/pulls/1282)
+- 2025-02-07T17:38:29+01:00 Bugfix: update mqtt connections dictionary by @yaxu in: [#1281](https://codeberg.org/uzu/strudel/pulls/1281)
+- 2025-02-07T11:39:54+01:00 make mqtt topic patternable by @yaxu in: [#1280](https://codeberg.org/uzu/strudel/pulls/1280)
+- 2025-02-07T11:07:32+01:00 midimaps by @froos in: [#1274](https://codeberg.org/uzu/strudel/pulls/1274)
+- 2025-02-06T15:59:03+01:00 MQTT - support adding hap duration and cps metadata to JSON messages by @yaxu in: [#1279](https://codeberg.org/uzu/strudel/pulls/1279)
+- 2025-02-05T16:10:54+01:00 [breaking change] Sample signals from query onset, rather than midpoint by @yaxu in: [#1278](https://codeberg.org/uzu/strudel/pulls/1278)
+- 2025-02-03T00:55:36+01:00 Stepwise documentation tweaks, with mridangam samples by @yaxu in: [#1275](https://codeberg.org/uzu/strudel/pulls/1275)
+- 2025-02-02T21:26:44+01:00 Polish, rename, and document stepwise functions by @yaxu in: [#1262](https://codeberg.org/uzu/strudel/pulls/1262)
+- 2025-02-01T22:57:00+01:00 Fix sf2 timing by @froos in: [#1272](https://codeberg.org/uzu/strudel/pulls/1272)
+- 2025-02-01T22:32:59+01:00 Add bank aliasing and case insensitivity by @TodePond in: [#1245](https://codeberg.org/uzu/strudel/pulls/1245)
## january 2025
-- 2025-01-31T09:39:54+01:00 Add Device Motion module by nkymut in: [#1217](https://codeberg.org/uzu/strudel/pulls/1217)
-- 2025-01-29T15:40:01+01:00 add "as" function + getControlName by froos in: [#1247](https://codeberg.org/uzu/strudel/pulls/1247)
-- 2025-01-29T15:30:04+01:00 Theme glowup by froos in: [#1268](https://codeberg.org/uzu/strudel/pulls/1268)
-- 2025-01-29T15:22:18+01:00 patchday by froos in: [#1264](https://codeberg.org/uzu/strudel/pulls/1264)
-- 2025-01-28T00:00:03+01:00 Revert "Fix sometimes" by yaxu in: [#1267](https://codeberg.org/uzu/strudel/pulls/1267)
-- 2025-01-24T15:32:48+01:00 add reference package by froos in: [#1252](https://codeberg.org/uzu/strudel/pulls/1252)
-- 2025-01-24T15:16:55+01:00 support `all(pianoroll)` and `all(pianoroll({labels: true}))` by yaxu in: [#1234](https://codeberg.org/uzu/strudel/pulls/1234)
-- 2025-01-24T12:13:49+01:00 MQTT - if password isn't provided, prompt for one by yaxu in: [#1249](https://codeberg.org/uzu/strudel/pulls/1249)
-- 2025-01-21T06:24:03+01:00 fix docs for beat function by Ghost in: [#1248](https://codeberg.org/uzu/strudel/pulls/1248)
-- 2025-01-18T23:27:51+01:00 understand voicings page by froos in: [#1230](https://codeberg.org/uzu/strudel/pulls/1230)
-- 2025-01-17T19:27:00+01:00 Add binary and binaryN by Ghost in: [#1226](https://codeberg.org/uzu/strudel/pulls/1226)
-- 2025-01-16T12:18:33+01:00 Fix sometimes by yaxu in: [#1243](https://codeberg.org/uzu/strudel/pulls/1243)
-- 2025-01-16T05:55:46+01:00 "beat" function for "step sequencer" style rhythm notation by Ghost in: [#1237](https://codeberg.org/uzu/strudel/pulls/1237)
-- 2025-01-14T14:39:15+01:00 Add stepBind, and some toplevel aliases for binds and withValue by yaxu in: [#1241](https://codeberg.org/uzu/strudel/pulls/1241)
-- 2025-01-14T06:11:10+01:00 Add onKey function for custom key commands for patterns by Ghost in: [#1235](https://codeberg.org/uzu/strudel/pulls/1235)
-- 2025-01-12T11:32:24+01:00 Update documentation for param value modification by Ghost in: [#1238](https://codeberg.org/uzu/strudel/pulls/1238)
+- 2025-01-31T09:39:54+01:00 Add Device Motion module by @nkymut in: [#1217](https://codeberg.org/uzu/strudel/pulls/1217)
+- 2025-01-29T15:40:01+01:00 add "as" function + getControlName by @froos in: [#1247](https://codeberg.org/uzu/strudel/pulls/1247)
+- 2025-01-29T15:30:04+01:00 Theme glowup by @froos in: [#1268](https://codeberg.org/uzu/strudel/pulls/1268)
+- 2025-01-29T15:22:18+01:00 patchday by @froos in: [#1264](https://codeberg.org/uzu/strudel/pulls/1264)
+- 2025-01-28T00:00:03+01:00 Revert "Fix sometimes" by @yaxu in: [#1267](https://codeberg.org/uzu/strudel/pulls/1267)
+- 2025-01-24T15:32:48+01:00 add reference package by @froos in: [#1252](https://codeberg.org/uzu/strudel/pulls/1252)
+- 2025-01-24T15:16:55+01:00 support `all(pianoroll)` and `all(pianoroll({labels: true}))` by @yaxu in: [#1234](https://codeberg.org/uzu/strudel/pulls/1234)
+- 2025-01-24T12:13:49+01:00 MQTT - if password isn't provided, prompt for one by @yaxu in: [#1249](https://codeberg.org/uzu/strudel/pulls/1249)
+- 2025-01-21T06:24:03+01:00 fix docs for beat function by @Ghost in: [#1248](https://codeberg.org/uzu/strudel/pulls/1248)
+- 2025-01-18T23:27:51+01:00 understand voicings page by @froos in: [#1230](https://codeberg.org/uzu/strudel/pulls/1230)
+- 2025-01-17T19:27:00+01:00 Add binary and binaryN by @Ghost in: [#1226](https://codeberg.org/uzu/strudel/pulls/1226)
+- 2025-01-16T12:18:33+01:00 Fix sometimes by @yaxu in: [#1243](https://codeberg.org/uzu/strudel/pulls/1243)
+- 2025-01-16T05:55:46+01:00 "beat" function for "step sequencer" style rhythm notation by @Ghost in: [#1237](https://codeberg.org/uzu/strudel/pulls/1237)
+- 2025-01-14T14:39:15+01:00 Add stepBind, and some toplevel aliases for binds and withValue by @yaxu in: [#1241](https://codeberg.org/uzu/strudel/pulls/1241)
+- 2025-01-14T06:11:10+01:00 Add onKey function for custom key commands for patterns by @Ghost in: [#1235](https://codeberg.org/uzu/strudel/pulls/1235)
+- 2025-01-12T11:32:24+01:00 Update documentation for param value modification by @Ghost in: [#1238](https://codeberg.org/uzu/strudel/pulls/1238)
## december 2024
-- 2024-12-29T13:16:08+01:00 Documentation for all/each, and bugfix for each by yaxu in: [#1233](https://codeberg.org/uzu/strudel/pulls/1233)
-- 2024-12-29T11:29:52+01:00 Make `all()` post-stack again, and add `each()` for pre-stack by yaxu in: [#1229](https://codeberg.org/uzu/strudel/pulls/1229)
-- 2024-12-27T22:16:54+01:00 suggested changes to voicings.mdx by Ghost in: [#1231](https://codeberg.org/uzu/strudel/pulls/1231)
-- 2024-12-23T11:53:11+01:00 add basic spectrum function by froos in: [#1213](https://codeberg.org/uzu/strudel/pulls/1213)
-- 2024-12-22T21:04:45+01:00 Fix regression for d1, p1, p(n) by yaxu in: [#1227](https://codeberg.org/uzu/strudel/pulls/1227)
+- 2024-12-29T13:16:08+01:00 Documentation for all/each, and bugfix for each by @yaxu in: [#1233](https://codeberg.org/uzu/strudel/pulls/1233)
+- 2024-12-29T11:29:52+01:00 Make `all()` post-stack again, and add `each()` for pre-stack by @yaxu in: [#1229](https://codeberg.org/uzu/strudel/pulls/1229)
+- 2024-12-27T22:16:54+01:00 suggested changes to voicings.mdx by @Ghost in: [#1231](https://codeberg.org/uzu/strudel/pulls/1231)
+- 2024-12-23T11:53:11+01:00 add basic spectrum function by @froos in: [#1213](https://codeberg.org/uzu/strudel/pulls/1213)
+- 2024-12-22T21:04:45+01:00 Fix regression for d1, p1, p(n) by @yaxu in: [#1227](https://codeberg.org/uzu/strudel/pulls/1227)
## november 2024
-- 2024-11-30T10:09:36+01:00 Make cps patternable by eefano in: [#1001](https://codeberg.org/uzu/strudel/pulls/1001)
-- 2024-11-30T10:07:56+01:00 MQTT support by yaxu in: [#1224](https://codeberg.org/uzu/strudel/pulls/1224)
-- 2024-11-30T09:46:14+01:00 Apply `all` function to individual patterns rather than final stack by yaxu in: [#1209](https://codeberg.org/uzu/strudel/pulls/1209)
-- 2024-11-20T16:32:51+01:00 REPL: solo and sync configuration by Ghost in: [#1214](https://codeberg.org/uzu/strudel/pulls/1214)
+- 2024-11-30T10:09:36+01:00 Make cps patternable by @eefano in: [#1001](https://codeberg.org/uzu/strudel/pulls/1001)
+- 2024-11-30T10:07:56+01:00 MQTT support by @yaxu in: [#1224](https://codeberg.org/uzu/strudel/pulls/1224)
+- 2024-11-30T09:46:14+01:00 Apply `all` function to individual patterns rather than final stack by @yaxu in: [#1209](https://codeberg.org/uzu/strudel/pulls/1209)
+- 2024-11-20T16:32:51+01:00 REPL: solo and sync configuration by @Ghost in: [#1214](https://codeberg.org/uzu/strudel/pulls/1214)
## october 2024
-- 2024-10-30T21:29:43+01:00 Add s_zip for 'cat'-ing patterns together step-by-step, bugfix `steps` by yaxu in: [#1208](https://codeberg.org/uzu/strudel/pulls/1208)
-- 2024-10-30T21:28:32+01:00 Preserve tactus for 'degrade' and friends, and tidy up 'pick' and friends by yaxu in: [#1205](https://codeberg.org/uzu/strudel/pulls/1205)
-- 2024-10-30T17:11:53+01:00 chore: Edit run locally instructions in README.md by Ghost in: [#1206](https://codeberg.org/uzu/strudel/pulls/1206)
-- 2024-10-23T23:08:14+02:00 colorize console + tweak header by froos in: [#1203](https://codeberg.org/uzu/strudel/pulls/1203)
-- 2024-10-22T22:55:00+02:00 markcss by froos in: [#1202](https://codeberg.org/uzu/strudel/pulls/1202)
-- 2024-10-21T22:56:37+02:00 add 2 new ui settings by froos in: [#1200](https://codeberg.org/uzu/strudel/pulls/1200)
-- 2024-10-21T20:22:52+02:00 Make panel hover behavior optional by Ghost in: [#1199](https://codeberg.org/uzu/strudel/pulls/1199)
-- 2024-10-19T04:28:36+02:00 Menu Panel Improvements! by Ghost in: [#1193](https://codeberg.org/uzu/strudel/pulls/1193)
-- 2024-10-19T01:10:06+02:00 update lockfile + minor versions by froos in: [#1198](https://codeberg.org/uzu/strudel/pulls/1198)
+- 2024-10-30T21:29:43+01:00 Add s_zip for 'cat'-ing patterns together step-by-step, bugfix `steps` by @yaxu in: [#1208](https://codeberg.org/uzu/strudel/pulls/1208)
+- 2024-10-30T21:28:32+01:00 Preserve tactus for 'degrade' and friends, and tidy up 'pick' and friends by @yaxu in: [#1205](https://codeberg.org/uzu/strudel/pulls/1205)
+- 2024-10-30T17:11:53+01:00 chore: Edit run locally instructions in README.md by @Ghost in: [#1206](https://codeberg.org/uzu/strudel/pulls/1206)
+- 2024-10-23T23:08:14+02:00 colorize console + tweak header by @froos in: [#1203](https://codeberg.org/uzu/strudel/pulls/1203)
+- 2024-10-22T22:55:00+02:00 markcss by @froos in: [#1202](https://codeberg.org/uzu/strudel/pulls/1202)
+- 2024-10-21T22:56:37+02:00 add 2 new ui settings by @froos in: [#1200](https://codeberg.org/uzu/strudel/pulls/1200)
+- 2024-10-21T20:22:52+02:00 Make panel hover behavior optional by @Ghost in: [#1199](https://codeberg.org/uzu/strudel/pulls/1199)
+- 2024-10-19T04:28:36+02:00 Menu Panel Improvements! by @Ghost in: [#1193](https://codeberg.org/uzu/strudel/pulls/1193)
+- 2024-10-19T01:10:06+02:00 update lockfile + minor versions by @froos in: [#1198](https://codeberg.org/uzu/strudel/pulls/1198)
## september 2024
-- 2024-09-27T00:17:00+02:00 remove redundant example for cat, update snapshot by Ghost in: [#1189](https://codeberg.org/uzu/strudel/pulls/1189)
-- 2024-09-25T13:18:19+02:00 Adding search bar (soundtab.jsx) by Ghost in: [#1185](https://codeberg.org/uzu/strudel/pulls/1185)
-- 2024-09-23T17:18:34+02:00 Screenreader improvements by yaxu in: [#1158](https://codeberg.org/uzu/strudel/pulls/1158)
-- 2024-09-20T22:26:41+02:00 Fix serial timing by yaxu in: [#1188](https://codeberg.org/uzu/strudel/pulls/1188)
-- 2024-09-20T00:26:30+02:00 Add bite function by yaxu in: [#1187](https://codeberg.org/uzu/strudel/pulls/1187)
-- 2024-09-14T13:30:53+02:00 better spacing in zen mode by froos in: [#1147](https://codeberg.org/uzu/strudel/pulls/1147)
-- 2024-09-14T10:50:24+02:00 add filter + filterWhen + within by froos in: [#1039](https://codeberg.org/uzu/strudel/pulls/1039)
-- 2024-09-14T10:49:21+02:00 refactor sampler by froos in: [#1101](https://codeberg.org/uzu/strudel/pulls/1101)
-- 2024-09-14T10:43:17+02:00 handle midin device not found error by froos in: [#1146](https://codeberg.org/uzu/strudel/pulls/1146)
-- 2024-09-13T21:59:23+02:00 Add a search bar to the REPL Reference tab by Ghost in: [#1165](https://codeberg.org/uzu/strudel/pulls/1165)
-- 2024-09-13T21:58:47+02:00 Correct spelling mistakes by Ghost in: [#1183](https://codeberg.org/uzu/strudel/pulls/1183)
-- 2024-09-07T23:41:29+02:00 Add seqPLoop from Tidal by yaxu in: [#1182](https://codeberg.org/uzu/strudel/pulls/1182)
-- 2024-09-05T05:52:50+02:00 make phaser control match superdirt by Ghost in: [#1180](https://codeberg.org/uzu/strudel/pulls/1180)
-- 2024-09-05T05:33:41+02:00 Revert "Make phaser control consistent with superdirt" by Ghost in: [#1179](https://codeberg.org/uzu/strudel/pulls/1179)
-- 2024-09-05T05:29:12+02:00 Make phaser control consistent with superdirt by Ghost in: [#1178](https://codeberg.org/uzu/strudel/pulls/1178)
-- 2024-09-03T04:37:15+02:00 fix sample speed when using splice and fit with superdirt by Ghost in: [#1172](https://codeberg.org/uzu/strudel/pulls/1172)
-- 2024-09-01T16:02:24+02:00 Create audio target selector for OSC/Superdirt by Ghost in: [#1160](https://codeberg.org/uzu/strudel/pulls/1160)
-- 2024-09-01T15:03:47+02:00 Fixes fit so it works after a chop or slice by yaxu in: [#1171](https://codeberg.org/uzu/strudel/pulls/1171)
+- 2024-09-27T00:17:00+02:00 remove redundant example for cat, update snapshot by @Ghost in: [#1189](https://codeberg.org/uzu/strudel/pulls/1189)
+- 2024-09-25T13:18:19+02:00 Adding search bar (soundtab.jsx) by @Ghost in: [#1185](https://codeberg.org/uzu/strudel/pulls/1185)
+- 2024-09-23T17:18:34+02:00 Screenreader improvements by @yaxu in: [#1158](https://codeberg.org/uzu/strudel/pulls/1158)
+- 2024-09-20T22:26:41+02:00 Fix serial timing by @yaxu in: [#1188](https://codeberg.org/uzu/strudel/pulls/1188)
+- 2024-09-20T00:26:30+02:00 Add bite function by @yaxu in: [#1187](https://codeberg.org/uzu/strudel/pulls/1187)
+- 2024-09-14T13:30:53+02:00 better spacing in zen mode by @froos in: [#1147](https://codeberg.org/uzu/strudel/pulls/1147)
+- 2024-09-14T10:50:24+02:00 add filter + filterWhen + within by @froos in: [#1039](https://codeberg.org/uzu/strudel/pulls/1039)
+- 2024-09-14T10:49:21+02:00 refactor sampler by @froos in: [#1101](https://codeberg.org/uzu/strudel/pulls/1101)
+- 2024-09-14T10:43:17+02:00 handle midin device not found error by @froos in: [#1146](https://codeberg.org/uzu/strudel/pulls/1146)
+- 2024-09-13T21:59:23+02:00 Add a search bar to the REPL Reference tab by @Ghost in: [#1165](https://codeberg.org/uzu/strudel/pulls/1165)
+- 2024-09-13T21:58:47+02:00 Correct spelling mistakes by @Ghost in: [#1183](https://codeberg.org/uzu/strudel/pulls/1183)
+- 2024-09-07T23:41:29+02:00 Add seqPLoop from Tidal by @yaxu in: [#1182](https://codeberg.org/uzu/strudel/pulls/1182)
+- 2024-09-05T05:52:50+02:00 make phaser control match superdirt by @Ghost in: [#1180](https://codeberg.org/uzu/strudel/pulls/1180)
+- 2024-09-05T05:33:41+02:00 Revert "Make phaser control consistent with superdirt" by @Ghost in: [#1179](https://codeberg.org/uzu/strudel/pulls/1179)
+- 2024-09-05T05:29:12+02:00 Make phaser control consistent with superdirt by @Ghost in: [#1178](https://codeberg.org/uzu/strudel/pulls/1178)
+- 2024-09-03T04:37:15+02:00 fix sample speed when using splice and fit with superdirt by @Ghost in: [#1172](https://codeberg.org/uzu/strudel/pulls/1172)
+- 2024-09-01T16:02:24+02:00 Create audio target selector for OSC/Superdirt by @Ghost in: [#1160](https://codeberg.org/uzu/strudel/pulls/1160)
+- 2024-09-01T15:03:47+02:00 Fixes fit so it works after a chop or slice by @yaxu in: [#1171](https://codeberg.org/uzu/strudel/pulls/1171)
## august 2024
-- 2024-08-30T14:24:08+02:00 polyJoin by yaxu in: [#1168](https://codeberg.org/uzu/strudel/pulls/1168)
-- 2024-08-23T17:05:10+02:00 Add scramble and shuffle by yaxu in: [#1167](https://codeberg.org/uzu/strudel/pulls/1167)
-- 2024-08-18T18:22:20+02:00 Improve + simplify neocyclist timing by Ghost in: [#1164](https://codeberg.org/uzu/strudel/pulls/1164)
-- 2024-08-15T05:18:33+02:00 containerize/seperate out boolean checks for repl types/Repl logic into bespoke components. by Ghost in: [#1163](https://codeberg.org/uzu/strudel/pulls/1163)
-- 2024-08-12T18:57:21+02:00 [CORS HOTFIX] by Ghost in: [#1162](https://codeberg.org/uzu/strudel/pulls/1162)
-- 2024-08-09T05:11:28+02:00 Fix OSC clock jitter by Ghost in: [#1157](https://codeberg.org/uzu/strudel/pulls/1157)
+- 2024-08-30T14:24:08+02:00 polyJoin by @yaxu in: [#1168](https://codeberg.org/uzu/strudel/pulls/1168)
+- 2024-08-23T17:05:10+02:00 Add scramble and shuffle by @yaxu in: [#1167](https://codeberg.org/uzu/strudel/pulls/1167)
+- 2024-08-18T18:22:20+02:00 Improve + simplify neocyclist timing by @Ghost in: [#1164](https://codeberg.org/uzu/strudel/pulls/1164)
+- 2024-08-15T05:18:33+02:00 containerize/seperate out boolean checks for repl types/Repl logic into bespoke components. by @Ghost in: [#1163](https://codeberg.org/uzu/strudel/pulls/1163)
+- 2024-08-12T18:57:21+02:00 [CORS HOTFIX] by @Ghost in: [#1162](https://codeberg.org/uzu/strudel/pulls/1162)
+- 2024-08-09T05:11:28+02:00 Fix OSC clock jitter by @Ghost in: [#1157](https://codeberg.org/uzu/strudel/pulls/1157)
## july 2024
-- 2024-07-27T11:02:38+02:00 Fix loopAt tactus by yaxu in: [#1145](https://codeberg.org/uzu/strudel/pulls/1145)
-- 2024-07-26T04:37:34+02:00 "stretch" function (phase vocoder) by Ghost in: [#1130](https://codeberg.org/uzu/strudel/pulls/1130)
-- 2024-07-26T04:37:17+02:00 Udels (MultiFrame Strudel) Revisited by Ghost in: [#1132](https://codeberg.org/uzu/strudel/pulls/1132)
-- 2024-07-24T11:40:28+02:00 Fix tactus marking in mininotation by yaxu in: [#1144](https://codeberg.org/uzu/strudel/pulls/1144)
+- 2024-07-27T11:02:38+02:00 Fix loopAt tactus by @yaxu in: [#1145](https://codeberg.org/uzu/strudel/pulls/1145)
+- 2024-07-26T04:37:34+02:00 "stretch" function (phase vocoder) by @Ghost in: [#1130](https://codeberg.org/uzu/strudel/pulls/1130)
+- 2024-07-26T04:37:17+02:00 Udels (MultiFrame Strudel) Revisited by @Ghost in: [#1132](https://codeberg.org/uzu/strudel/pulls/1132)
+- 2024-07-24T11:40:28+02:00 Fix tactus marking in mininotation by @yaxu in: [#1144](https://codeberg.org/uzu/strudel/pulls/1144)
## june 2024
-- 2024-06-25T18:13:28+02:00 export comment commands by froos in: [#1136](https://codeberg.org/uzu/strudel/pulls/1136)
-- 2024-06-24T18:19:22+02:00 Chop chop by yaxu in: [#1078](https://codeberg.org/uzu/strudel/pulls/1078)
-- 2024-06-18T23:58:08+02:00 Fix bug in Fraction.lcm by yaxu in: [#1133](https://codeberg.org/uzu/strudel/pulls/1133)
-- 2024-06-18T05:32:12+02:00 Fix clock worker dependency path in module builds by Ghost in: [#1129](https://codeberg.org/uzu/strudel/pulls/1129)
-- 2024-06-04T00:26:48+02:00 Labeled statements doc by froos in: [#1126](https://codeberg.org/uzu/strudel/pulls/1126)
-- 2024-06-03T22:40:21+02:00 doc: visual functions + refactor onPaint by froos in: [#1125](https://codeberg.org/uzu/strudel/pulls/1125)
-- 2024-06-02T18:36:29+02:00 Fix indexDB failing with large amount of files by Ghost in: [#1124](https://codeberg.org/uzu/strudel/pulls/1124)
+- 2024-06-25T18:13:28+02:00 export comment commands by @froos in: [#1136](https://codeberg.org/uzu/strudel/pulls/1136)
+- 2024-06-24T18:19:22+02:00 Chop chop by @yaxu in: [#1078](https://codeberg.org/uzu/strudel/pulls/1078)
+- 2024-06-18T23:58:08+02:00 Fix bug in Fraction.lcm by @yaxu in: [#1133](https://codeberg.org/uzu/strudel/pulls/1133)
+- 2024-06-18T05:32:12+02:00 Fix clock worker dependency path in module builds by @Ghost in: [#1129](https://codeberg.org/uzu/strudel/pulls/1129)
+- 2024-06-04T00:26:48+02:00 Labeled statements doc by @froos in: [#1126](https://codeberg.org/uzu/strudel/pulls/1126)
+- 2024-06-03T22:40:21+02:00 doc: visual functions + refactor onPaint by @froos in: [#1125](https://codeberg.org/uzu/strudel/pulls/1125)
+- 2024-06-02T18:36:29+02:00 Fix indexDB failing with large amount of files by @Ghost in: [#1124](https://codeberg.org/uzu/strudel/pulls/1124)
## may 2024
-- 2024-05-31T12:17:34+02:00 Migrate tutorial fanchor by froos in: [#1122](https://codeberg.org/uzu/strudel/pulls/1122)
-- 2024-05-31T10:46:47+02:00 [BUG FIX] Audio worklets sometimes dont load by Ghost in: [#1121](https://codeberg.org/uzu/strudel/pulls/1121)
-- 2024-05-31T10:25:24+02:00 change fanchor to 0 by Ghost in: [#1107](https://codeberg.org/uzu/strudel/pulls/1107)
-- 2024-05-30T14:39:30+02:00 fix: use full repl in web package by froos in: [#1119](https://codeberg.org/uzu/strudel/pulls/1119)
-- 2024-05-30T09:36:32+02:00 can now access strudelMirror from repl by froos in: [#1117](https://codeberg.org/uzu/strudel/pulls/1117)
-- 2024-05-29T13:06:34+02:00 Add the mousex and mousey signal by Ghost in: [#1112](https://codeberg.org/uzu/strudel/pulls/1112)
-- 2024-05-29T13:02:00+02:00 Fixes drawPianoroll import in codemirror example by Ghost in: [#1116](https://codeberg.org/uzu/strudel/pulls/1116)
-- 2024-05-28T22:43:46+02:00 clarify `off` in pattern-effects.mdx by Ghost in: [#1074](https://codeberg.org/uzu/strudel/pulls/1074)
-- 2024-05-26T17:33:07+02:00 rollback phaser by Ghost in: [#1113](https://codeberg.org/uzu/strudel/pulls/1113)
-- 2024-05-26T17:33:06+02:00 Fix audio worklets by Ghost in: [#1114](https://codeberg.org/uzu/strudel/pulls/1114)
-- 2024-05-26T16:53:56+02:00 Calculate phaser modulation phase based on time by Ghost in: [#1110](https://codeberg.org/uzu/strudel/pulls/1110)
-- 2024-05-23T15:06:01+02:00 Add analog-style ladder filter by Ghost in: [#1103](https://codeberg.org/uzu/strudel/pulls/1103)
-- 2024-05-22T12:53:20+02:00 fix sampler on windows by Ghost in: [#1109](https://codeberg.org/uzu/strudel/pulls/1109)
-- 2024-05-20T23:26:20+02:00 web package fixes by froos in: [#1044](https://codeberg.org/uzu/strudel/pulls/1044)
-- 2024-05-20T22:41:28+02:00 Fix sampler windows by froos in: [#1108](https://codeberg.org/uzu/strudel/pulls/1108)
-- 2024-05-19T12:07:26+02:00 hs2js package / tidal parser by froos in: [#870](https://codeberg.org/uzu/strudel/pulls/870)
-- 2024-05-18T10:49:08+02:00 fix little dub tune example by Ghost in: [#1104](https://codeberg.org/uzu/strudel/pulls/1104)
-- 2024-05-17T14:43:58+02:00 Samples tab improvements by Ghost in: [#1102](https://codeberg.org/uzu/strudel/pulls/1102)
-- 2024-05-13T10:10:34+02:00 osc: couple of fixes by Ghost in: [#1093](https://codeberg.org/uzu/strudel/pulls/1093)
-- 2024-05-13T06:31:20+02:00 Use sessionStorage for viewingPatternData and activePattern by Ghost in: [#1091](https://codeberg.org/uzu/strudel/pulls/1091)
-- 2024-05-12T18:23:09+02:00 repl: set document.title from @title by Ghost in: [#1090](https://codeberg.org/uzu/strudel/pulls/1090)
-- 2024-05-07T14:29:22+02:00 fix: missing events due to premature worklet cleanup by froos in: [#1089](https://codeberg.org/uzu/strudel/pulls/1089)
-- 2024-05-03T11:52:57+02:00 Benchmarks by yaxu in: [#1079](https://codeberg.org/uzu/strudel/pulls/1079)
-- 2024-05-03T08:46:52+02:00 fix: csound + dough timing by froos in: [#1086](https://codeberg.org/uzu/strudel/pulls/1086)
-- 2024-05-03T00:37:32+02:00 Improve performance of ! (replicate) by yaxu in: [#1084](https://codeberg.org/uzu/strudel/pulls/1084)
-- 2024-05-02T23:40:22+02:00 fix: url parsing with extra params by froos in: [#1083](https://codeberg.org/uzu/strudel/pulls/1083)
+- 2024-05-31T12:17:34+02:00 Migrate tutorial fanchor by @froos in: [#1122](https://codeberg.org/uzu/strudel/pulls/1122)
+- 2024-05-31T10:46:47+02:00 [BUG FIX] Audio worklets sometimes dont load by @Ghost in: [#1121](https://codeberg.org/uzu/strudel/pulls/1121)
+- 2024-05-31T10:25:24+02:00 change fanchor to 0 by @Ghost in: [#1107](https://codeberg.org/uzu/strudel/pulls/1107)
+- 2024-05-30T14:39:30+02:00 fix: use full repl in web package by @froos in: [#1119](https://codeberg.org/uzu/strudel/pulls/1119)
+- 2024-05-30T09:36:32+02:00 can now access strudelMirror from repl by @froos in: [#1117](https://codeberg.org/uzu/strudel/pulls/1117)
+- 2024-05-29T13:06:34+02:00 Add the mousex and mousey signal by @Ghost in: [#1112](https://codeberg.org/uzu/strudel/pulls/1112)
+- 2024-05-29T13:02:00+02:00 Fixes drawPianoroll import in codemirror example by @Ghost in: [#1116](https://codeberg.org/uzu/strudel/pulls/1116)
+- 2024-05-28T22:43:46+02:00 clarify `off` in pattern-effects.mdx by @Ghost in: [#1074](https://codeberg.org/uzu/strudel/pulls/1074)
+- 2024-05-26T17:33:07+02:00 rollback phaser by @Ghost in: [#1113](https://codeberg.org/uzu/strudel/pulls/1113)
+- 2024-05-26T17:33:06+02:00 Fix audio worklets by @Ghost in: [#1114](https://codeberg.org/uzu/strudel/pulls/1114)
+- 2024-05-26T16:53:56+02:00 Calculate phaser modulation phase based on time by @Ghost in: [#1110](https://codeberg.org/uzu/strudel/pulls/1110)
+- 2024-05-23T15:06:01+02:00 Add analog-style ladder filter by @Ghost in: [#1103](https://codeberg.org/uzu/strudel/pulls/1103)
+- 2024-05-22T12:53:20+02:00 fix sampler on windows by @Ghost in: [#1109](https://codeberg.org/uzu/strudel/pulls/1109)
+- 2024-05-20T23:26:20+02:00 web package fixes by @froos in: [#1044](https://codeberg.org/uzu/strudel/pulls/1044)
+- 2024-05-20T22:41:28+02:00 Fix sampler windows by @froos in: [#1108](https://codeberg.org/uzu/strudel/pulls/1108)
+- 2024-05-19T12:07:26+02:00 hs2js package / tidal parser by @froos in: [#870](https://codeberg.org/uzu/strudel/pulls/870)
+- 2024-05-18T10:49:08+02:00 fix little dub tune example by @Ghost in: [#1104](https://codeberg.org/uzu/strudel/pulls/1104)
+- 2024-05-17T14:43:58+02:00 Samples tab improvements by @Ghost in: [#1102](https://codeberg.org/uzu/strudel/pulls/1102)
+- 2024-05-13T10:10:34+02:00 osc: couple of fixes by @Ghost in: [#1093](https://codeberg.org/uzu/strudel/pulls/1093)
+- 2024-05-13T06:31:20+02:00 Use sessionStorage for viewingPatternData and activePattern by @Ghost in: [#1091](https://codeberg.org/uzu/strudel/pulls/1091)
+- 2024-05-12T18:23:09+02:00 repl: set document.title from @title by @Ghost in: [#1090](https://codeberg.org/uzu/strudel/pulls/1090)
+- 2024-05-07T14:29:22+02:00 fix: missing events due to premature worklet cleanup by @froos in: [#1089](https://codeberg.org/uzu/strudel/pulls/1089)
+- 2024-05-03T11:52:57+02:00 Benchmarks by @yaxu in: [#1079](https://codeberg.org/uzu/strudel/pulls/1079)
+- 2024-05-03T08:46:52+02:00 fix: csound + dough timing by @froos in: [#1086](https://codeberg.org/uzu/strudel/pulls/1086)
+- 2024-05-03T00:37:32+02:00 Improve performance of ! (replicate) by @yaxu in: [#1084](https://codeberg.org/uzu/strudel/pulls/1084)
+- 2024-05-02T23:40:22+02:00 fix: url parsing with extra params by @froos in: [#1083](https://codeberg.org/uzu/strudel/pulls/1083)
## april 2024
-- 2024-04-29T12:36:11+02:00 Tactus calculation toggle and breaking change to tactus calculation in fast/slow/hurry by yaxu in: [#1081](https://codeberg.org/uzu/strudel/pulls/1081)
-- 2024-04-28T20:56:21+02:00 fix docs on alignment.mdx by Ghost in: [#1076](https://codeberg.org/uzu/strudel/pulls/1076)
-- 2024-04-28T20:49:18+02:00 add signals to recap in first-effects.mdx by Ghost in: [#1073](https://codeberg.org/uzu/strudel/pulls/1073)
-- 2024-04-28T20:44:57+02:00 fix translation issue in first-effects.mdx by Ghost in: [#1072](https://codeberg.org/uzu/strudel/pulls/1072)
-- 2024-04-28T20:44:29+02:00 fix failing format test by Ghost in: [#1077](https://codeberg.org/uzu/strudel/pulls/1077)
-- 2024-04-27T22:50:17+02:00 add nesting to `off` example variation in pattern-effects.mdx by Ghost in: [#1075](https://codeberg.org/uzu/strudel/pulls/1075)
-- 2024-04-27T22:48:58+02:00 add `<...>` to first-sounds.mdx recap by Ghost in: [#1070](https://codeberg.org/uzu/strudel/pulls/1070)
-- 2024-04-27T22:48:07+02:00 fix first sounds typo by Ghost in: [#1069](https://codeberg.org/uzu/strudel/pulls/1069)
-- 2024-04-27T22:47:44+02:00 fix cr typo on first-sounds.mdx by Ghost in: [#1068](https://codeberg.org/uzu/strudel/pulls/1068)
-- 2024-04-26T15:12:30+02:00 More tactus tidying by yaxu in: [#1071](https://codeberg.org/uzu/strudel/pulls/1071)
-- 2024-04-23T23:37:21+02:00 Fix stepjoin by yaxu in: [#1067](https://codeberg.org/uzu/strudel/pulls/1067)
-- 2024-04-23T23:32:00+02:00 clarify license by yaxu in: [#1064](https://codeberg.org/uzu/strudel/pulls/1064)
-- 2024-04-23T15:14:30+02:00 Tactus tweaks - fixes for maintaining tactus and highlight locations by yaxu in: [#1065](https://codeberg.org/uzu/strudel/pulls/1065)
-- 2024-04-21T23:57:57+02:00 fix OSC timing for recent scheduler updates by Ghost in: [#1062](https://codeberg.org/uzu/strudel/pulls/1062)
-- 2024-04-21T22:17:07+02:00 Stepwise functions from Tidal by yaxu in: [#1060](https://codeberg.org/uzu/strudel/pulls/1060)
-- 2024-04-21T11:03:55+02:00 Fix wchooseCycles not picking the whole pattern by Ghost in: [#1061](https://codeberg.org/uzu/strudel/pulls/1061)
-- 2024-04-19T00:05:52+02:00 add swing + swingBy by froos in: [#1038](https://codeberg.org/uzu/strudel/pulls/1038)
-- 2024-04-19T00:05:08+02:00 anonymous patterns + muting by froos in: [#1059](https://codeberg.org/uzu/strudel/pulls/1059)
-- 2024-04-12T12:34:27+02:00 improve tutorial + custom samples doc by froos in: [#1053](https://codeberg.org/uzu/strudel/pulls/1053)
-- 2024-04-12T12:31:49+02:00 fix: do not reset cc input values on each eval by froos in: [#1054](https://codeberg.org/uzu/strudel/pulls/1054)
-- 2024-04-08T17:25:27+02:00 transpose: support all combinations of numbers and strings for notes and intervals by froos in: [#1048](https://codeberg.org/uzu/strudel/pulls/1048)
-- 2024-04-08T10:46:18+02:00 Wax, wane, taper and taperlist by yaxu in: [#1042](https://codeberg.org/uzu/strudel/pulls/1042)
-- 2024-04-06T23:44:57+02:00 Midi Time hotfix for scheduler updates by Ghost in: [#1047](https://codeberg.org/uzu/strudel/pulls/1047)
-- 2024-04-05T12:48:03+02:00 pitchwheel visual by froos in: [#1041](https://codeberg.org/uzu/strudel/pulls/1041)
-- 2024-04-05T12:47:19+02:00 fix cyclist fizzling out by froos in: [#1046](https://codeberg.org/uzu/strudel/pulls/1046)
+- 2024-04-29T12:36:11+02:00 Tactus calculation toggle and breaking change to tactus calculation in fast/slow/hurry by @yaxu in: [#1081](https://codeberg.org/uzu/strudel/pulls/1081)
+- 2024-04-28T20:56:21+02:00 fix docs on alignment.mdx by @Ghost in: [#1076](https://codeberg.org/uzu/strudel/pulls/1076)
+- 2024-04-28T20:49:18+02:00 add signals to recap in first-effects.mdx by @Ghost in: [#1073](https://codeberg.org/uzu/strudel/pulls/1073)
+- 2024-04-28T20:44:57+02:00 fix translation issue in first-effects.mdx by @Ghost in: [#1072](https://codeberg.org/uzu/strudel/pulls/1072)
+- 2024-04-28T20:44:29+02:00 fix failing format test by @Ghost in: [#1077](https://codeberg.org/uzu/strudel/pulls/1077)
+- 2024-04-27T22:50:17+02:00 add nesting to `off` example variation in pattern-effects.mdx by @Ghost in: [#1075](https://codeberg.org/uzu/strudel/pulls/1075)
+- 2024-04-27T22:48:58+02:00 add `<...>` to first-sounds.mdx recap by @Ghost in: [#1070](https://codeberg.org/uzu/strudel/pulls/1070)
+- 2024-04-27T22:48:07+02:00 fix first sounds typo by @Ghost in: [#1069](https://codeberg.org/uzu/strudel/pulls/1069)
+- 2024-04-27T22:47:44+02:00 fix cr typo on first-sounds.mdx by @Ghost in: [#1068](https://codeberg.org/uzu/strudel/pulls/1068)
+- 2024-04-26T15:12:30+02:00 More tactus tidying by @yaxu in: [#1071](https://codeberg.org/uzu/strudel/pulls/1071)
+- 2024-04-23T23:37:21+02:00 Fix stepjoin by @yaxu in: [#1067](https://codeberg.org/uzu/strudel/pulls/1067)
+- 2024-04-23T23:32:00+02:00 clarify license by @yaxu in: [#1064](https://codeberg.org/uzu/strudel/pulls/1064)
+- 2024-04-23T15:14:30+02:00 Tactus tweaks - fixes for maintaining tactus and highlight locations by @yaxu in: [#1065](https://codeberg.org/uzu/strudel/pulls/1065)
+- 2024-04-21T23:57:57+02:00 fix OSC timing for recent scheduler updates by @Ghost in: [#1062](https://codeberg.org/uzu/strudel/pulls/1062)
+- 2024-04-21T22:17:07+02:00 Stepwise functions from Tidal by @yaxu in: [#1060](https://codeberg.org/uzu/strudel/pulls/1060)
+- 2024-04-21T11:03:55+02:00 Fix wchooseCycles not picking the whole pattern by @Ghost in: [#1061](https://codeberg.org/uzu/strudel/pulls/1061)
+- 2024-04-19T00:05:52+02:00 add swing + swingBy by @froos in: [#1038](https://codeberg.org/uzu/strudel/pulls/1038)
+- 2024-04-19T00:05:08+02:00 anonymous patterns + muting by @froos in: [#1059](https://codeberg.org/uzu/strudel/pulls/1059)
+- 2024-04-12T12:34:27+02:00 improve tutorial + custom samples doc by @froos in: [#1053](https://codeberg.org/uzu/strudel/pulls/1053)
+- 2024-04-12T12:31:49+02:00 fix: do not reset cc input values on each eval by @froos in: [#1054](https://codeberg.org/uzu/strudel/pulls/1054)
+- 2024-04-08T17:25:27+02:00 transpose: support all combinations of numbers and strings for notes and intervals by @froos in: [#1048](https://codeberg.org/uzu/strudel/pulls/1048)
+- 2024-04-08T10:46:18+02:00 Wax, wane, taper and taperlist by @yaxu in: [#1042](https://codeberg.org/uzu/strudel/pulls/1042)
+- 2024-04-06T23:44:57+02:00 Midi Time hotfix for scheduler updates by @Ghost in: [#1047](https://codeberg.org/uzu/strudel/pulls/1047)
+- 2024-04-05T12:48:03+02:00 pitchwheel visual by @froos in: [#1041](https://codeberg.org/uzu/strudel/pulls/1041)
+- 2024-04-05T12:47:19+02:00 fix cyclist fizzling out by @froos in: [#1046](https://codeberg.org/uzu/strudel/pulls/1046)
## march 2024
-- 2024-03-30T16:05:59+01:00 remove dangerous arithmetic feature by froos in: [#1030](https://codeberg.org/uzu/strudel/pulls/1030)
-- 2024-03-30T16:05:27+01:00 Fix sampler paths by froos in: [#1034](https://codeberg.org/uzu/strudel/pulls/1034)
-- 2024-03-30T14:43:08+01:00 local sample server cli by froos in: [#1033](https://codeberg.org/uzu/strudel/pulls/1033)
-- 2024-03-29T17:14:28+01:00 add font file types to offline cache by froos in: [#1032](https://codeberg.org/uzu/strudel/pulls/1032)
-- 2024-03-29T17:10:16+01:00 add closeBrackets setting by froos in: [#1031](https://codeberg.org/uzu/strudel/pulls/1031)
-- 2024-03-29T14:55:06+01:00 Tactus tidy by yaxu in: [#1027](https://codeberg.org/uzu/strudel/pulls/1027)
-- 2024-03-28T17:06:44+01:00 add setting for sync flag by froos in: [#1025](https://codeberg.org/uzu/strudel/pulls/1025)
-- 2024-03-28T11:37:57+01:00 better theme integration for visuals + various fixes by froos in: [#1024](https://codeberg.org/uzu/strudel/pulls/1024)
-- 2024-03-28T11:33:25+01:00 More fonts by froos in: [#1023](https://codeberg.org/uzu/strudel/pulls/1023)
-- 2024-03-27T13:06:05+01:00 Feature: tactus marking by yaxu in: [#1021](https://codeberg.org/uzu/strudel/pulls/1021)
-- 2024-03-25T06:02:02+01:00 hotfix for 1017 by Ghost in: [#1020](https://codeberg.org/uzu/strudel/pulls/1020)
-- 2024-03-24T15:06:33+01:00 Document signals by Ghost in: [#1015](https://codeberg.org/uzu/strudel/pulls/1015)
-- 2024-03-24T10:16:11+01:00 Repl sync fixes by Ghost in: [#1014](https://codeberg.org/uzu/strudel/pulls/1014)
-- 2024-03-23T20:21:51+01:00 eliminate chromium clock jitter by froos in: [#1004](https://codeberg.org/uzu/strudel/pulls/1004)
-- 2024-03-23T15:51:07+01:00 update undocumented script by froos in: [#1013](https://codeberg.org/uzu/strudel/pulls/1013)
-- 2024-03-23T15:26:52+01:00 fix: await injectPatternMethods by froos in: [#1012](https://codeberg.org/uzu/strudel/pulls/1012)
-- 2024-03-23T15:18:12+01:00 rename trig -> reset, trigzero -> restart by froos in: [#1010](https://codeberg.org/uzu/strudel/pulls/1010)
-- 2024-03-23T12:30:03+01:00 Inline punchcard + spiral by froos in: [#1008](https://codeberg.org/uzu/strudel/pulls/1008)
-- 2024-03-23T12:27:22+01:00 Color in hap value by froos in: [#1007](https://codeberg.org/uzu/strudel/pulls/1007)
-- 2024-03-22T23:53:51+01:00 using strudel in your project guide + cleanup examples by froos in: [#1006](https://codeberg.org/uzu/strudel/pulls/1006)
-- 2024-03-22T23:41:50+01:00 accidentals in scale degrees by eefano in: [#1000](https://codeberg.org/uzu/strudel/pulls/1000)
-- 2024-03-21T22:53:55+01:00 supersaw oscillator by Ghost in: [#978](https://codeberg.org/uzu/strudel/pulls/978)
-- 2024-03-21T13:00:04+01:00 remove canvas, externalize samples, delete junk by froos in: [#1003](https://codeberg.org/uzu/strudel/pulls/1003)
-- 2024-03-18T11:37:55+01:00 Fix pure mini highlight by yaxu in: [#994](https://codeberg.org/uzu/strudel/pulls/994)
-- 2024-03-18T07:12:14+01:00 inline viz / widgets package by froos in: [#989](https://codeberg.org/uzu/strudel/pulls/989)
-- 2024-03-17T04:07:00+01:00 Labeled statements by froos in: [#991](https://codeberg.org/uzu/strudel/pulls/991)
-- 2024-03-16T18:24:38+01:00 Beat-oriented functionality by yaxu in: [#976](https://codeberg.org/uzu/strudel/pulls/976)
-- 2024-03-15T01:47:35+01:00 REPL sync between windows by Ghost in: [#900](https://codeberg.org/uzu/strudel/pulls/900)
-- 2024-03-14T00:20:07+01:00 Update synths.mdx by Ghost in: [#984](https://codeberg.org/uzu/strudel/pulls/984)
-- 2024-03-13T00:36:22+01:00 fix: share now shares what's visible instead of active by froos in: [#985](https://codeberg.org/uzu/strudel/pulls/985)
-- 2024-03-10T01:18:57+01:00 use ireal as default voicing dict by froos in: [#967](https://codeberg.org/uzu/strudel/pulls/967)
-- 2024-03-10T00:50:23+01:00 little fix for withVal by eefano in: [#980](https://codeberg.org/uzu/strudel/pulls/980)
-- 2024-03-10T00:46:51+01:00 Velocity in value by froos in: [#974](https://codeberg.org/uzu/strudel/pulls/974)
-- 2024-03-10T00:42:50+01:00 fix: clear hydra on reset by froos in: [#983](https://codeberg.org/uzu/strudel/pulls/983)
-- 2024-03-10T00:38:43+01:00 move canvas related helpers from core to new draw package by froos in: [#971](https://codeberg.org/uzu/strudel/pulls/971)
-- 2024-03-08T05:38:07+01:00 replace shape with distort in learn doc by Ghost in: [#982](https://codeberg.org/uzu/strudel/pulls/982)
-- 2024-03-06T12:14:49+01:00 alias - for ~ by yaxu in: [#981](https://codeberg.org/uzu/strudel/pulls/981)
-- 2024-03-04T16:04:23+01:00 Worklet Improvents / fixes by Ghost in: [#963](https://codeberg.org/uzu/strudel/pulls/963)
-- 2024-03-01T17:30:19+01:00 Nested controls by froos in: [#973](https://codeberg.org/uzu/strudel/pulls/973)
+- 2024-03-30T16:05:59+01:00 remove dangerous arithmetic feature by @froos in: [#1030](https://codeberg.org/uzu/strudel/pulls/1030)
+- 2024-03-30T16:05:27+01:00 Fix sampler paths by @froos in: [#1034](https://codeberg.org/uzu/strudel/pulls/1034)
+- 2024-03-30T14:43:08+01:00 local sample server cli by @froos in: [#1033](https://codeberg.org/uzu/strudel/pulls/1033)
+- 2024-03-29T17:14:28+01:00 add font file types to offline cache by @froos in: [#1032](https://codeberg.org/uzu/strudel/pulls/1032)
+- 2024-03-29T17:10:16+01:00 add closeBrackets setting by @froos in: [#1031](https://codeberg.org/uzu/strudel/pulls/1031)
+- 2024-03-29T14:55:06+01:00 Tactus tidy by @yaxu in: [#1027](https://codeberg.org/uzu/strudel/pulls/1027)
+- 2024-03-28T17:06:44+01:00 add setting for sync flag by @froos in: [#1025](https://codeberg.org/uzu/strudel/pulls/1025)
+- 2024-03-28T11:37:57+01:00 better theme integration for visuals + various fixes by @froos in: [#1024](https://codeberg.org/uzu/strudel/pulls/1024)
+- 2024-03-28T11:33:25+01:00 More fonts by @froos in: [#1023](https://codeberg.org/uzu/strudel/pulls/1023)
+- 2024-03-27T13:06:05+01:00 Feature: tactus marking by @yaxu in: [#1021](https://codeberg.org/uzu/strudel/pulls/1021)
+- 2024-03-25T06:02:02+01:00 hotfix for 1017 by @Ghost in: [#1020](https://codeberg.org/uzu/strudel/pulls/1020)
+- 2024-03-24T15:06:33+01:00 Document signals by @Ghost in: [#1015](https://codeberg.org/uzu/strudel/pulls/1015)
+- 2024-03-24T10:16:11+01:00 Repl sync fixes by @Ghost in: [#1014](https://codeberg.org/uzu/strudel/pulls/1014)
+- 2024-03-23T20:21:51+01:00 eliminate chromium clock jitter by @froos in: [#1004](https://codeberg.org/uzu/strudel/pulls/1004)
+- 2024-03-23T15:51:07+01:00 update undocumented script by @froos in: [#1013](https://codeberg.org/uzu/strudel/pulls/1013)
+- 2024-03-23T15:26:52+01:00 fix: await injectPatternMethods by @froos in: [#1012](https://codeberg.org/uzu/strudel/pulls/1012)
+- 2024-03-23T15:18:12+01:00 rename trig -> reset, trigzero -> restart by @froos in: [#1010](https://codeberg.org/uzu/strudel/pulls/1010)
+- 2024-03-23T12:30:03+01:00 Inline punchcard + spiral by @froos in: [#1008](https://codeberg.org/uzu/strudel/pulls/1008)
+- 2024-03-23T12:27:22+01:00 Color in hap value by @froos in: [#1007](https://codeberg.org/uzu/strudel/pulls/1007)
+- 2024-03-22T23:53:51+01:00 using strudel in your project guide + cleanup examples by @froos in: [#1006](https://codeberg.org/uzu/strudel/pulls/1006)
+- 2024-03-22T23:41:50+01:00 accidentals in scale degrees by @eefano in: [#1000](https://codeberg.org/uzu/strudel/pulls/1000)
+- 2024-03-21T22:53:55+01:00 supersaw oscillator by @Ghost in: [#978](https://codeberg.org/uzu/strudel/pulls/978)
+- 2024-03-21T13:00:04+01:00 remove canvas, externalize samples, delete junk by @froos in: [#1003](https://codeberg.org/uzu/strudel/pulls/1003)
+- 2024-03-18T11:37:55+01:00 Fix pure mini highlight by @yaxu in: [#994](https://codeberg.org/uzu/strudel/pulls/994)
+- 2024-03-18T07:12:14+01:00 inline viz / widgets package by @froos in: [#989](https://codeberg.org/uzu/strudel/pulls/989)
+- 2024-03-17T04:07:00+01:00 Labeled statements by @froos in: [#991](https://codeberg.org/uzu/strudel/pulls/991)
+- 2024-03-16T18:24:38+01:00 Beat-oriented functionality by @yaxu in: [#976](https://codeberg.org/uzu/strudel/pulls/976)
+- 2024-03-15T01:47:35+01:00 REPL sync between windows by @Ghost in: [#900](https://codeberg.org/uzu/strudel/pulls/900)
+- 2024-03-14T00:20:07+01:00 Update synths.mdx by @Ghost in: [#984](https://codeberg.org/uzu/strudel/pulls/984)
+- 2024-03-13T00:36:22+01:00 fix: share now shares what's visible instead of active by @froos in: [#985](https://codeberg.org/uzu/strudel/pulls/985)
+- 2024-03-10T01:18:57+01:00 use ireal as default voicing dict by @froos in: [#967](https://codeberg.org/uzu/strudel/pulls/967)
+- 2024-03-10T00:50:23+01:00 little fix for withVal by @eefano in: [#980](https://codeberg.org/uzu/strudel/pulls/980)
+- 2024-03-10T00:46:51+01:00 Velocity in value by @froos in: [#974](https://codeberg.org/uzu/strudel/pulls/974)
+- 2024-03-10T00:42:50+01:00 fix: clear hydra on reset by @froos in: [#983](https://codeberg.org/uzu/strudel/pulls/983)
+- 2024-03-10T00:38:43+01:00 move canvas related helpers from core to new draw package by @froos in: [#971](https://codeberg.org/uzu/strudel/pulls/971)
+- 2024-03-08T05:38:07+01:00 replace shape with distort in learn doc by @Ghost in: [#982](https://codeberg.org/uzu/strudel/pulls/982)
+- 2024-03-06T12:14:49+01:00 alias - for ~ by @yaxu in: [#981](https://codeberg.org/uzu/strudel/pulls/981)
+- 2024-03-04T16:04:23+01:00 Worklet Improvents / fixes by @Ghost in: [#963](https://codeberg.org/uzu/strudel/pulls/963)
+- 2024-03-01T17:30:19+01:00 Nested controls by @froos in: [#973](https://codeberg.org/uzu/strudel/pulls/973)
## february 2024
-- 2024-02-29T15:33:12+01:00 feat: can now invert euclid pulses with negative numbers by froos in: [#959](https://codeberg.org/uzu/strudel/pulls/959)
-- 2024-02-29T15:31:23+01:00 pickOut(), pickRestart(), pickReset() by eefano in: [#950](https://codeberg.org/uzu/strudel/pulls/950)
-- 2024-02-29T15:12:45+01:00 remove legacy legato + duration implementations by froos in: [#965](https://codeberg.org/uzu/strudel/pulls/965)
-- 2024-02-29T08:47:53+01:00 fix for transpose(): preserve hap value object structure by eefano in: [#966](https://codeberg.org/uzu/strudel/pulls/966)
-- 2024-02-29T08:32:00+01:00 add debounce to logger by froos in: [#968](https://codeberg.org/uzu/strudel/pulls/968)
-- 2024-02-28T18:43:52+01:00 controls refactoring: simplify exports by froos in: [#962](https://codeberg.org/uzu/strudel/pulls/962)
-- 2024-02-25T19:17:00+01:00 fix: reset global fx on pattern change by froos in: [#960](https://codeberg.org/uzu/strudel/pulls/960)
-- 2024-02-25T14:15:30+01:00 fix midi issue on firefox and added quote error by Ghost in: [#936](https://codeberg.org/uzu/strudel/pulls/936)
-- 2024-02-25T13:19:47+01:00 'Enable Bracket Matching' option in Codemirror by eefano in: [#956](https://codeberg.org/uzu/strudel/pulls/956)
-- 2024-02-23T14:37:46+01:00 fix script importable packages (web + repl) by froos in: [#957](https://codeberg.org/uzu/strudel/pulls/957)
-- 2024-02-21T16:17:37+01:00 account for cps in midi time duration by Ghost in: [#954](https://codeberg.org/uzu/strudel/pulls/954)
-- 2024-02-21T10:27:12+01:00 Auto await samples by froos in: [#955](https://codeberg.org/uzu/strudel/pulls/955)
-- 2024-02-08T13:16:15+01:00 remove cjs builds by froos in: [#945](https://codeberg.org/uzu/strudel/pulls/945)
-- 2024-02-04T23:15:37+01:00 Minor documentation error: Update first-sounds.mdx by Ghost in: [#941](https://codeberg.org/uzu/strudel/pulls/941)
+- 2024-02-29T15:33:12+01:00 feat: can now invert euclid pulses with negative numbers by @froos in: [#959](https://codeberg.org/uzu/strudel/pulls/959)
+- 2024-02-29T15:31:23+01:00 pickOut(), pickRestart(), pickReset() by @eefano in: [#950](https://codeberg.org/uzu/strudel/pulls/950)
+- 2024-02-29T15:12:45+01:00 remove legacy legato + duration implementations by @froos in: [#965](https://codeberg.org/uzu/strudel/pulls/965)
+- 2024-02-29T08:47:53+01:00 fix for transpose(): preserve hap value object structure by @eefano in: [#966](https://codeberg.org/uzu/strudel/pulls/966)
+- 2024-02-29T08:32:00+01:00 add debounce to logger by @froos in: [#968](https://codeberg.org/uzu/strudel/pulls/968)
+- 2024-02-28T18:43:52+01:00 controls refactoring: simplify exports by @froos in: [#962](https://codeberg.org/uzu/strudel/pulls/962)
+- 2024-02-25T19:17:00+01:00 fix: reset global fx on pattern change by @froos in: [#960](https://codeberg.org/uzu/strudel/pulls/960)
+- 2024-02-25T14:15:30+01:00 fix midi issue on firefox and added quote error by @Ghost in: [#936](https://codeberg.org/uzu/strudel/pulls/936)
+- 2024-02-25T13:19:47+01:00 'Enable Bracket Matching' option in Codemirror by @eefano in: [#956](https://codeberg.org/uzu/strudel/pulls/956)
+- 2024-02-23T14:37:46+01:00 fix script importable packages (web + repl) by @froos in: [#957](https://codeberg.org/uzu/strudel/pulls/957)
+- 2024-02-21T16:17:37+01:00 account for cps in midi time duration by @Ghost in: [#954](https://codeberg.org/uzu/strudel/pulls/954)
+- 2024-02-21T10:27:12+01:00 Auto await samples by @froos in: [#955](https://codeberg.org/uzu/strudel/pulls/955)
+- 2024-02-08T13:16:15+01:00 remove cjs builds by @froos in: [#945](https://codeberg.org/uzu/strudel/pulls/945)
+- 2024-02-04T23:15:37+01:00 Minor documentation error: Update first-sounds.mdx by @Ghost in: [#941](https://codeberg.org/uzu/strudel/pulls/941)
## january 2024
-- 2024-01-24T16:48:57+01:00 fix: pianoroll sorting by froos in: [#938](https://codeberg.org/uzu/strudel/pulls/938)
-- 2024-01-23T00:04:03+01:00 V1 release notes by froos in: [#935](https://codeberg.org/uzu/strudel/pulls/935)
-- 2024-01-22T20:20:53+01:00 2 years blog post by froos in: [#929](https://codeberg.org/uzu/strudel/pulls/929)
-- 2024-01-22T20:02:34+01:00 make 0.5hz cps the default by yaxu in: [#931](https://codeberg.org/uzu/strudel/pulls/931)
-- 2024-01-22T00:52:01+01:00 Fix pattern tab not showing patterns without created date by Ghost in: [#934](https://codeberg.org/uzu/strudel/pulls/934)
-- 2024-01-21T20:46:28+01:00 Add useful pattern selection behavior for performing. by Ghost in: [#897](https://codeberg.org/uzu/strudel/pulls/897)
-- 2024-01-21T01:30:28+01:00 Refactor cps functions by froos in: [#933](https://codeberg.org/uzu/strudel/pulls/933)
-- 2024-01-20T23:47:31+01:00 Make splice cps-aware by yaxu in: [#932](https://codeberg.org/uzu/strudel/pulls/932)
-- 2024-01-19T18:50:57+01:00 community bakery by froos in: [#923](https://codeberg.org/uzu/strudel/pulls/923)
-- 2024-01-19T18:49:54+01:00 add pickF and pickmodF by Ghost in: [#924](https://codeberg.org/uzu/strudel/pulls/924)
-- 2024-01-19T15:10:48+01:00 Mini-notation additions towards tidal compatibility by yaxu in: [#926](https://codeberg.org/uzu/strudel/pulls/926)
-- 2024-01-18T23:34:11+01:00 Blog improvements by froos in: [#919](https://codeberg.org/uzu/strudel/pulls/919)
-- 2024-01-18T18:08:29+01:00 pick, pickmod, inhabit, inhabitmod by yaxu in: [#921](https://codeberg.org/uzu/strudel/pulls/921)
-- 2024-01-18T18:04:27+01:00 Revert "`pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function" by yaxu in: [#920](https://codeberg.org/uzu/strudel/pulls/920)
-- 2024-01-18T17:45:39+01:00 `pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function by yaxu in: [#918](https://codeberg.org/uzu/strudel/pulls/918)
-- 2024-01-18T10:30:08+01:00 rename @strudel.cycles/* packages to @strudel/* by froos in: [#917](https://codeberg.org/uzu/strudel/pulls/917)
-- 2024-01-18T06:54:33+01:00 pitch envelopes by froos in: [#913](https://codeberg.org/uzu/strudel/pulls/913)
-- 2024-01-18T05:09:38+01:00 Fix: swatch/[name].png.js static path by Ghost in: [#916](https://codeberg.org/uzu/strudel/pulls/916)
-- 2024-01-16T08:22:28+01:00 Add more vowel qualities for the vowels function by Ghost in: [#907](https://codeberg.org/uzu/strudel/pulls/907)
-- 2024-01-14T23:56:36+01:00 adds a blog by froos in: [#911](https://codeberg.org/uzu/strudel/pulls/911)
-- 2024-01-14T23:52:41+01:00 Remove hideHeader for better mobile UI and consistency by Ghost in: [#894](https://codeberg.org/uzu/strudel/pulls/894)
-- 2024-01-14T22:43:06+01:00 Further Envelope improvements by Ghost in: [#868](https://codeberg.org/uzu/strudel/pulls/868)
-- 2024-01-14T00:48:04+01:00 public sharing by froos in: [#910](https://codeberg.org/uzu/strudel/pulls/910)
-- 2024-01-12T18:31:41+01:00 fix some build warnings by froos in: [#902](https://codeberg.org/uzu/strudel/pulls/902)
-- 2024-01-12T18:01:55+01:00 prevent vite from complaining about additional exports in jsx files by Ghost in: [#891](https://codeberg.org/uzu/strudel/pulls/891)
-- 2024-01-12T17:05:47+01:00 Update Vite version so hot reload works properly with newest pnpm version by Ghost in: [#892](https://codeberg.org/uzu/strudel/pulls/892)
-- 2024-01-12T15:09:41+01:00 support , in < > by froos in: [#886](https://codeberg.org/uzu/strudel/pulls/886)
-- 2024-01-10T13:55:39+01:00 fix: autocomplete / tooltip code example bug by froos in: [#898](https://codeberg.org/uzu/strudel/pulls/898)
-- 2024-01-06T15:23:55+01:00 fix: invisible selection on vim + emacs mode by froos in: [#889](https://codeberg.org/uzu/strudel/pulls/889)
-- 2024-01-05T22:29:20+01:00 scales can now be anchored by froos in: [#888](https://codeberg.org/uzu/strudel/pulls/888)
-- 2024-01-04T11:21:42+01:00 add root mode for voicings by froos in: [#887](https://codeberg.org/uzu/strudel/pulls/887)
-- 2024-01-01T18:32:17+01:00 Showcase by froos in: [#885](https://codeberg.org/uzu/strudel/pulls/885)
-- 2024-01-01T14:22:11+01:00 bugfix: suspend and close exisiting audio context when changing interface by Ghost in: [#882](https://codeberg.org/uzu/strudel/pulls/882)
-- 2024-01-01T14:21:52+01:00 add mastodon link by froos in: [#884](https://codeberg.org/uzu/strudel/pulls/884)
+- 2024-01-24T16:48:57+01:00 fix: pianoroll sorting by @froos in: [#938](https://codeberg.org/uzu/strudel/pulls/938)
+- 2024-01-23T00:04:03+01:00 V1 release notes by @froos in: [#935](https://codeberg.org/uzu/strudel/pulls/935)
+- 2024-01-22T20:20:53+01:00 2 years blog post by @froos in: [#929](https://codeberg.org/uzu/strudel/pulls/929)
+- 2024-01-22T20:02:34+01:00 make 0.5hz cps the default by @yaxu in: [#931](https://codeberg.org/uzu/strudel/pulls/931)
+- 2024-01-22T00:52:01+01:00 Fix pattern tab not showing patterns without created date by @Ghost in: [#934](https://codeberg.org/uzu/strudel/pulls/934)
+- 2024-01-21T20:46:28+01:00 Add useful pattern selection behavior for performing. by @Ghost in: [#897](https://codeberg.org/uzu/strudel/pulls/897)
+- 2024-01-21T01:30:28+01:00 Refactor cps functions by @froos in: [#933](https://codeberg.org/uzu/strudel/pulls/933)
+- 2024-01-20T23:47:31+01:00 Make splice cps-aware by @yaxu in: [#932](https://codeberg.org/uzu/strudel/pulls/932)
+- 2024-01-19T18:50:57+01:00 community bakery by @froos in: [#923](https://codeberg.org/uzu/strudel/pulls/923)
+- 2024-01-19T18:49:54+01:00 add pickF and pickmodF by @Ghost in: [#924](https://codeberg.org/uzu/strudel/pulls/924)
+- 2024-01-19T15:10:48+01:00 Mini-notation additions towards tidal compatibility by @yaxu in: [#926](https://codeberg.org/uzu/strudel/pulls/926)
+- 2024-01-18T23:34:11+01:00 Blog improvements by @froos in: [#919](https://codeberg.org/uzu/strudel/pulls/919)
+- 2024-01-18T18:08:29+01:00 pick, pickmod, inhabit, inhabitmod by @yaxu in: [#921](https://codeberg.org/uzu/strudel/pulls/921)
+- 2024-01-18T18:04:27+01:00 Revert "`pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function" by @yaxu in: [#920](https://codeberg.org/uzu/strudel/pulls/920)
+- 2024-01-18T17:45:39+01:00 `pick` now accepts lookup tables, with alternate cycle squeezing behaviour as new `inhabit` function by @yaxu in: [#918](https://codeberg.org/uzu/strudel/pulls/918)
+- 2024-01-18T10:30:08+01:00 rename @strudel.cycles/* packages to @strudel/* by @froos in: [#917](https://codeberg.org/uzu/strudel/pulls/917)
+- 2024-01-18T06:54:33+01:00 pitch envelopes by @froos in: [#913](https://codeberg.org/uzu/strudel/pulls/913)
+- 2024-01-18T05:09:38+01:00 Fix: swatch/[name].png.js static path by @Ghost in: [#916](https://codeberg.org/uzu/strudel/pulls/916)
+- 2024-01-16T08:22:28+01:00 Add more vowel qualities for the vowels function by @Ghost in: [#907](https://codeberg.org/uzu/strudel/pulls/907)
+- 2024-01-14T23:56:36+01:00 adds a blog by @froos in: [#911](https://codeberg.org/uzu/strudel/pulls/911)
+- 2024-01-14T23:52:41+01:00 Remove hideHeader for better mobile UI and consistency by @Ghost in: [#894](https://codeberg.org/uzu/strudel/pulls/894)
+- 2024-01-14T22:43:06+01:00 Further Envelope improvements by @Ghost in: [#868](https://codeberg.org/uzu/strudel/pulls/868)
+- 2024-01-14T00:48:04+01:00 public sharing by @froos in: [#910](https://codeberg.org/uzu/strudel/pulls/910)
+- 2024-01-12T18:31:41+01:00 fix some build warnings by @froos in: [#902](https://codeberg.org/uzu/strudel/pulls/902)
+- 2024-01-12T18:01:55+01:00 prevent vite from complaining about additional exports in jsx files by @Ghost in: [#891](https://codeberg.org/uzu/strudel/pulls/891)
+- 2024-01-12T17:05:47+01:00 Update Vite version so hot reload works properly with newest pnpm version by @Ghost in: [#892](https://codeberg.org/uzu/strudel/pulls/892)
+- 2024-01-12T15:09:41+01:00 support , in < > by @froos in: [#886](https://codeberg.org/uzu/strudel/pulls/886)
+- 2024-01-10T13:55:39+01:00 fix: autocomplete / tooltip code example bug by @froos in: [#898](https://codeberg.org/uzu/strudel/pulls/898)
+- 2024-01-06T15:23:55+01:00 fix: invisible selection on vim + emacs mode by @froos in: [#889](https://codeberg.org/uzu/strudel/pulls/889)
+- 2024-01-05T22:29:20+01:00 scales can now be anchored by @froos in: [#888](https://codeberg.org/uzu/strudel/pulls/888)
+- 2024-01-04T11:21:42+01:00 add root mode for voicings by @froos in: [#887](https://codeberg.org/uzu/strudel/pulls/887)
+- 2024-01-01T18:32:17+01:00 Showcase by @froos in: [#885](https://codeberg.org/uzu/strudel/pulls/885)
+- 2024-01-01T14:22:11+01:00 bugfix: suspend and close exisiting audio context when changing interface by @Ghost in: [#882](https://codeberg.org/uzu/strudel/pulls/882)
+- 2024-01-01T14:21:52+01:00 add mastodon link by @froos in: [#884](https://codeberg.org/uzu/strudel/pulls/884)
## december 2023
-- 2023-12-31T17:02:57+01:00 fix: make sure n is never undefined before nanFallback by froos in: [#881](https://codeberg.org/uzu/strudel/pulls/881)
-- 2023-12-31T16:47:22+01:00 Error tolerance by froos in: [#880](https://codeberg.org/uzu/strudel/pulls/880)
-- 2023-12-31T10:06:24+01:00 bugfix: sound select indexes out of bounds by Ghost in: [#871](https://codeberg.org/uzu/strudel/pulls/871)
-- 2023-12-31T10:03:01+01:00 Audio device selection by Ghost in: [#854](https://codeberg.org/uzu/strudel/pulls/854)
-- 2023-12-31T00:59:49+01:00 Dependency update by froos in: [#879](https://codeberg.org/uzu/strudel/pulls/879)
-- 2023-12-29T16:53:41+01:00 move all examples to separate examples folder by froos in: [#878](https://codeberg.org/uzu/strudel/pulls/878)
-- 2023-12-29T15:29:17+01:00 final vanillification by froos in: [#876](https://codeberg.org/uzu/strudel/pulls/876)
-- 2023-12-27T18:38:09+01:00 Bug Fix #119: Clock drift by Ghost in: [#874](https://codeberg.org/uzu/strudel/pulls/874)
-- 2023-12-27T13:17:03+01:00 main repl vanillification by froos in: [#873](https://codeberg.org/uzu/strudel/pulls/873)
-- 2023-12-25T17:47:25+01:00 more work on vanilla repl: repl web component + package + MicroRepl by froos in: [#866](https://codeberg.org/uzu/strudel/pulls/866)
-- 2023-12-15T00:11:35+01:00 Vanilla repl 3 by froos in: [#865](https://codeberg.org/uzu/strudel/pulls/865)
-- 2023-12-14T21:28:49+01:00 Vanilla repl 2 by froos in: [#863](https://codeberg.org/uzu/strudel/pulls/863)
-- 2023-12-12T21:49:23+01:00 fix: finally repair envelopes by froos in: [#861](https://codeberg.org/uzu/strudel/pulls/861)
-- 2023-12-12T21:20:00+01:00 add missing trailing slashes by froos in: [#860](https://codeberg.org/uzu/strudel/pulls/860)
-- 2023-12-12T19:08:31+01:00 Sound Import from local file system by Ghost in: [#839](https://codeberg.org/uzu/strudel/pulls/839)
-- 2023-12-11T22:48:35+01:00 Pattern organization by froos in: [#858](https://codeberg.org/uzu/strudel/pulls/858)
-- 2023-12-09T17:25:11+01:00 Export patterns + ui tweaks by froos in: [#855](https://codeberg.org/uzu/strudel/pulls/855)
-- 2023-12-08T09:41:10+01:00 patterns tab: import patterns + style by froos in: [#852](https://codeberg.org/uzu/strudel/pulls/852)
-- 2023-12-07T20:42:00+01:00 Patterns tab + Refactor Panel by froos in: [#769](https://codeberg.org/uzu/strudel/pulls/769)
-- 2023-12-07T10:25:16+01:00 CHANGES: pnpm 8.1.3 to 8.11.0 by Ghost in: [#850](https://codeberg.org/uzu/strudel/pulls/850)
-- 2023-12-07T09:35:14+01:00 Fix edge case with rehype-urls and trailing slashes in image file paths by Ghost in: [#849](https://codeberg.org/uzu/strudel/pulls/849)
-- 2023-12-06T23:02:31+01:00 Fix examples page, piano() and a few workshop imgs by Ghost in: [#848](https://codeberg.org/uzu/strudel/pulls/848)
-- 2023-12-06T22:30:59+01:00 fix: swatch png src by froos in: [#846](https://codeberg.org/uzu/strudel/pulls/846)
-- 2023-12-06T22:19:30+01:00 fix: missing hash for links starting with / by froos in: [#845](https://codeberg.org/uzu/strudel/pulls/845)
-- 2023-12-06T22:05:05+01:00 improve slashing + base href behavior by froos in: [#842](https://codeberg.org/uzu/strudel/pulls/842)
-- 2023-12-06T21:26:49+01:00 Add in fixes from my fork to slashocalypse branch by Ghost in: [#843](https://codeberg.org/uzu/strudel/pulls/843)
-- 2023-12-05T18:43:58+01:00 Prevent 404 on Algolia crawls by Ghost in: [#838](https://codeberg.org/uzu/strudel/pulls/838)
-- 2023-12-05T18:26:47+01:00 Multichannel audio by Ghost in: [#820](https://codeberg.org/uzu/strudel/pulls/820)
-- 2023-12-05T12:19:58+01:00 ADDS: JetBrains IDE files and directories to .gitignore by Ghost in: [#840](https://codeberg.org/uzu/strudel/pulls/840)
-- 2023-12-05T12:19:27+01:00 CHANGES: github action pnpm version from 7 to 8.3.1 by Ghost in: [#835](https://codeberg.org/uzu/strudel/pulls/835)
-- 2023-12-05T12:19:17+01:00 CHANGES: pin pnpm to version 8.3.1 by Ghost in: [#834](https://codeberg.org/uzu/strudel/pulls/834)
-- 2023-12-05T12:19:06+01:00 CHANGES: github action checkout v2 -> v4 by Ghost in: [#837](https://codeberg.org/uzu/strudel/pulls/837)
-- 2023-12-05T11:15:14+01:00 FIXES: palindrome abc -> abccba by Ghost in: [#831](https://codeberg.org/uzu/strudel/pulls/831)
-- 2023-12-02T09:43:50+01:00 Fix a typo by Ghost in: [#830](https://codeberg.org/uzu/strudel/pulls/830)
+- 2023-12-31T17:02:57+01:00 fix: make sure n is never undefined before nanFallback by @froos in: [#881](https://codeberg.org/uzu/strudel/pulls/881)
+- 2023-12-31T16:47:22+01:00 Error tolerance by @froos in: [#880](https://codeberg.org/uzu/strudel/pulls/880)
+- 2023-12-31T10:06:24+01:00 bugfix: sound select indexes out of bounds by @Ghost in: [#871](https://codeberg.org/uzu/strudel/pulls/871)
+- 2023-12-31T10:03:01+01:00 Audio device selection by @Ghost in: [#854](https://codeberg.org/uzu/strudel/pulls/854)
+- 2023-12-31T00:59:49+01:00 Dependency update by @froos in: [#879](https://codeberg.org/uzu/strudel/pulls/879)
+- 2023-12-29T16:53:41+01:00 move all examples to separate examples folder by @froos in: [#878](https://codeberg.org/uzu/strudel/pulls/878)
+- 2023-12-29T15:29:17+01:00 final vanillification by @froos in: [#876](https://codeberg.org/uzu/strudel/pulls/876)
+- 2023-12-27T18:38:09+01:00 Bug Fix #119: Clock drift by @Ghost in: [#874](https://codeberg.org/uzu/strudel/pulls/874)
+- 2023-12-27T13:17:03+01:00 main repl vanillification by @froos in: [#873](https://codeberg.org/uzu/strudel/pulls/873)
+- 2023-12-25T17:47:25+01:00 more work on vanilla repl: repl web component + package + MicroRepl by @froos in: [#866](https://codeberg.org/uzu/strudel/pulls/866)
+- 2023-12-15T00:11:35+01:00 Vanilla repl 3 by @froos in: [#865](https://codeberg.org/uzu/strudel/pulls/865)
+- 2023-12-14T21:28:49+01:00 Vanilla repl 2 by @froos in: [#863](https://codeberg.org/uzu/strudel/pulls/863)
+- 2023-12-12T21:49:23+01:00 fix: finally repair envelopes by @froos in: [#861](https://codeberg.org/uzu/strudel/pulls/861)
+- 2023-12-12T21:20:00+01:00 add missing trailing slashes by @froos in: [#860](https://codeberg.org/uzu/strudel/pulls/860)
+- 2023-12-12T19:08:31+01:00 Sound Import from local file system by @Ghost in: [#839](https://codeberg.org/uzu/strudel/pulls/839)
+- 2023-12-11T22:48:35+01:00 Pattern organization by @froos in: [#858](https://codeberg.org/uzu/strudel/pulls/858)
+- 2023-12-09T17:25:11+01:00 Export patterns + ui tweaks by @froos in: [#855](https://codeberg.org/uzu/strudel/pulls/855)
+- 2023-12-08T09:41:10+01:00 patterns tab: import patterns + style by @froos in: [#852](https://codeberg.org/uzu/strudel/pulls/852)
+- 2023-12-07T20:42:00+01:00 Patterns tab + Refactor Panel by @froos in: [#769](https://codeberg.org/uzu/strudel/pulls/769)
+- 2023-12-07T10:25:16+01:00 CHANGES: pnpm 8.1.3 to 8.11.0 by @Ghost in: [#850](https://codeberg.org/uzu/strudel/pulls/850)
+- 2023-12-07T09:35:14+01:00 Fix edge case with rehype-urls and trailing slashes in image file paths by @Ghost in: [#849](https://codeberg.org/uzu/strudel/pulls/849)
+- 2023-12-06T23:02:31+01:00 Fix examples page, piano() and a few workshop imgs by @Ghost in: [#848](https://codeberg.org/uzu/strudel/pulls/848)
+- 2023-12-06T22:30:59+01:00 fix: swatch png src by @froos in: [#846](https://codeberg.org/uzu/strudel/pulls/846)
+- 2023-12-06T22:19:30+01:00 fix: missing hash for links starting with / by @froos in: [#845](https://codeberg.org/uzu/strudel/pulls/845)
+- 2023-12-06T22:05:05+01:00 improve slashing + base href behavior by @froos in: [#842](https://codeberg.org/uzu/strudel/pulls/842)
+- 2023-12-06T21:26:49+01:00 Add in fixes from my fork to slashocalypse branch by @Ghost in: [#843](https://codeberg.org/uzu/strudel/pulls/843)
+- 2023-12-05T18:43:58+01:00 Prevent 404 on Algolia crawls by @Ghost in: [#838](https://codeberg.org/uzu/strudel/pulls/838)
+- 2023-12-05T18:26:47+01:00 Multichannel audio by @Ghost in: [#820](https://codeberg.org/uzu/strudel/pulls/820)
+- 2023-12-05T12:19:58+01:00 ADDS: JetBrains IDE files and directories to .gitignore by @Ghost in: [#840](https://codeberg.org/uzu/strudel/pulls/840)
+- 2023-12-05T12:19:27+01:00 CHANGES: github action pnpm version from 7 to 8.3.1 by @Ghost in: [#835](https://codeberg.org/uzu/strudel/pulls/835)
+- 2023-12-05T12:19:17+01:00 CHANGES: pin pnpm to version 8.3.1 by @Ghost in: [#834](https://codeberg.org/uzu/strudel/pulls/834)
+- 2023-12-05T12:19:06+01:00 CHANGES: github action checkout v2 -> v4 by @Ghost in: [#837](https://codeberg.org/uzu/strudel/pulls/837)
+- 2023-12-05T11:15:14+01:00 FIXES: palindrome abc -> abccba by @Ghost in: [#831](https://codeberg.org/uzu/strudel/pulls/831)
+- 2023-12-02T09:43:50+01:00 Fix a typo by @Ghost in: [#830](https://codeberg.org/uzu/strudel/pulls/830)
## november 2023
-- 2023-11-30T10:42:41+01:00 Add and style algolia search by Ghost in: [#827](https://codeberg.org/uzu/strudel/pulls/827)
-- 2023-11-25T15:50:44+01:00 Hydra fixes and improvements by Ghost in: [#818](https://codeberg.org/uzu/strudel/pulls/818)
-- 2023-11-24T10:07:17+01:00 add options param to initHydra by Ghost in: [#808](https://codeberg.org/uzu/strudel/pulls/808)
-- 2023-11-24T09:57:02+01:00 Improve documentation for synonym functions by Ghost in: [#800](https://codeberg.org/uzu/strudel/pulls/800)
-- 2023-11-24T09:00:54+01:00 New noise type: "crackle" by Ghost in: [#806](https://codeberg.org/uzu/strudel/pulls/806)
-- 2023-11-18T21:18:16+01:00 Color hsl by froos in: [#815](https://codeberg.org/uzu/strudel/pulls/815)
-- 2023-11-17T23:18:23+01:00 fix: multiple repls by froos in: [#813](https://codeberg.org/uzu/strudel/pulls/813)
-- 2023-11-17T20:52:25+01:00 upstream changes by yaxu in: [#809](https://codeberg.org/uzu/strudel/pulls/809)
-- 2023-11-17T16:04:10+01:00 Add doc for euclidLegatoRot, wordfall and slider by Ghost in: [#801](https://codeberg.org/uzu/strudel/pulls/801)
-- 2023-11-17T14:42:58+01:00 add option to disable active line highlighting in Code Settings by Ghost in: [#804](https://codeberg.org/uzu/strudel/pulls/804)
-- 2023-11-17T14:37:52+01:00 tidal style d1 ... d9 functions + more by froos in: [#805](https://codeberg.org/uzu/strudel/pulls/805)
-- 2023-11-15T20:12:23+01:00 remove unwanted cm6 outline for strudelTheme by Ghost in: [#802](https://codeberg.org/uzu/strudel/pulls/802)
-- 2023-11-13T23:30:15+01:00 Create phaser effect by Ghost in: [#798](https://codeberg.org/uzu/strudel/pulls/798)
-- 2023-11-10T12:17:35+01:00 support multiple named serial connections, change default baudrate by yaxu in: [#551](https://codeberg.org/uzu/strudel/pulls/551)
-- 2023-11-09T09:27:57+01:00 Fix for #1. Enables named instruments for csoundm. by gogins in: [#662](https://codeberg.org/uzu/strudel/pulls/662)
-- 2023-11-09T09:26:45+01:00 Adding vibrato to Superdough sampler by Ghost in: [#706](https://codeberg.org/uzu/strudel/pulls/706)
-- 2023-11-09T08:46:03+01:00 Document pianoroll by Ghost in: [#784](https://codeberg.org/uzu/strudel/pulls/784)
-- 2023-11-09T08:45:29+01:00 Update first-effects.mdx by Ghost in: [#795](https://codeberg.org/uzu/strudel/pulls/795)
-- 2023-11-09T08:44:43+01:00 Update pattern-effects.mdx by Ghost in: [#796](https://codeberg.org/uzu/strudel/pulls/796)
-- 2023-11-09T08:43:50+01:00 Update recap.mdx by Ghost in: [#797](https://codeberg.org/uzu/strudel/pulls/797)
-- 2023-11-07T11:53:49+01:00 Update first-sounds.mdx by Ghost in: [#794](https://codeberg.org/uzu/strudel/pulls/794)
-- 2023-11-06T23:17:32+01:00 don't use anchor links for reference by froos in: [#791](https://codeberg.org/uzu/strudel/pulls/791)
-- 2023-11-06T22:40:44+01:00 samples loading shortcuts: by froos in: [#788](https://codeberg.org/uzu/strudel/pulls/788)
-- 2023-11-05T22:47:48+01:00 Fix scope pos + document by froos in: [#786](https://codeberg.org/uzu/strudel/pulls/786)
-- 2023-11-05T22:10:25+01:00 Implement optional hover tooltip with function documentation by Ghost in: [#783](https://codeberg.org/uzu/strudel/pulls/783)
-- 2023-11-05T16:46:06+01:00 Add function params in reference tab by Ghost in: [#785](https://codeberg.org/uzu/strudel/pulls/785)
-- 2023-11-05T12:42:00+01:00 fix: style issues by froos in: [#781](https://codeberg.org/uzu/strudel/pulls/781)
-- 2023-11-05T12:21:28+01:00 add xfade by froos in: [#780](https://codeberg.org/uzu/strudel/pulls/780)
-- 2023-11-02T09:30:26+01:00 Update to Astro 3 by froos in: [#775](https://codeberg.org/uzu/strudel/pulls/775)
-- 2023-11-02T08:57:14+01:00 add vscode bindings by Ghost in: [#773](https://codeberg.org/uzu/strudel/pulls/773)
-- 2023-11-02T08:31:30+01:00 fix: share copy to clipboard + alert by froos in: [#774](https://codeberg.org/uzu/strudel/pulls/774)
-- 2023-11-01T22:22:34+01:00 Fix chunk, add fastChunk and repeatCycles by yaxu in: [#712](https://codeberg.org/uzu/strudel/pulls/712)
-- 2023-11-01T22:12:49+01:00 Document adsr function by Ghost in: [#767](https://codeberg.org/uzu/strudel/pulls/767)
-- 2023-11-01T22:11:49+01:00 Add pick and squeeze functions by Ghost in: [#771](https://codeberg.org/uzu/strudel/pulls/771)
-- 2023-11-01T22:04:00+01:00 Update vite pwa by froos in: [#772](https://codeberg.org/uzu/strudel/pulls/772)
+- 2023-11-30T10:42:41+01:00 Add and style algolia search by @Ghost in: [#827](https://codeberg.org/uzu/strudel/pulls/827)
+- 2023-11-25T15:50:44+01:00 Hydra fixes and improvements by @Ghost in: [#818](https://codeberg.org/uzu/strudel/pulls/818)
+- 2023-11-24T10:07:17+01:00 add options param to initHydra by @Ghost in: [#808](https://codeberg.org/uzu/strudel/pulls/808)
+- 2023-11-24T09:57:02+01:00 Improve documentation for synonym functions by @Ghost in: [#800](https://codeberg.org/uzu/strudel/pulls/800)
+- 2023-11-24T09:00:54+01:00 New noise type: "crackle" by @Ghost in: [#806](https://codeberg.org/uzu/strudel/pulls/806)
+- 2023-11-18T21:18:16+01:00 Color hsl by @froos in: [#815](https://codeberg.org/uzu/strudel/pulls/815)
+- 2023-11-17T23:18:23+01:00 fix: multiple repls by @froos in: [#813](https://codeberg.org/uzu/strudel/pulls/813)
+- 2023-11-17T20:52:25+01:00 upstream changes by @yaxu in: [#809](https://codeberg.org/uzu/strudel/pulls/809)
+- 2023-11-17T16:04:10+01:00 Add doc for euclidLegatoRot, wordfall and slider by @Ghost in: [#801](https://codeberg.org/uzu/strudel/pulls/801)
+- 2023-11-17T14:42:58+01:00 add option to disable active line highlighting in Code Settings by @Ghost in: [#804](https://codeberg.org/uzu/strudel/pulls/804)
+- 2023-11-17T14:37:52+01:00 tidal style d1 ... d9 functions + more by @froos in: [#805](https://codeberg.org/uzu/strudel/pulls/805)
+- 2023-11-15T20:12:23+01:00 remove unwanted cm6 outline for strudelTheme by @Ghost in: [#802](https://codeberg.org/uzu/strudel/pulls/802)
+- 2023-11-13T23:30:15+01:00 Create phaser effect by @Ghost in: [#798](https://codeberg.org/uzu/strudel/pulls/798)
+- 2023-11-10T12:17:35+01:00 support multiple named serial connections, change default baudrate by @yaxu in: [#551](https://codeberg.org/uzu/strudel/pulls/551)
+- 2023-11-09T09:27:57+01:00 Fix for #1. Enables named instruments for csoundm. by @gogins in: [#662](https://codeberg.org/uzu/strudel/pulls/662)
+- 2023-11-09T09:26:45+01:00 Adding vibrato to Superdough sampler by @Ghost in: [#706](https://codeberg.org/uzu/strudel/pulls/706)
+- 2023-11-09T08:46:03+01:00 Document pianoroll by @Ghost in: [#784](https://codeberg.org/uzu/strudel/pulls/784)
+- 2023-11-09T08:45:29+01:00 Update first-effects.mdx by @Ghost in: [#795](https://codeberg.org/uzu/strudel/pulls/795)
+- 2023-11-09T08:44:43+01:00 Update pattern-effects.mdx by @Ghost in: [#796](https://codeberg.org/uzu/strudel/pulls/796)
+- 2023-11-09T08:43:50+01:00 Update recap.mdx by @Ghost in: [#797](https://codeberg.org/uzu/strudel/pulls/797)
+- 2023-11-07T11:53:49+01:00 Update first-sounds.mdx by @Ghost in: [#794](https://codeberg.org/uzu/strudel/pulls/794)
+- 2023-11-06T23:17:32+01:00 don't use anchor links for reference by @froos in: [#791](https://codeberg.org/uzu/strudel/pulls/791)
+- 2023-11-06T22:40:44+01:00 samples loading shortcuts: by @froos in: [#788](https://codeberg.org/uzu/strudel/pulls/788)
+- 2023-11-05T22:47:48+01:00 Fix scope pos + document by @froos in: [#786](https://codeberg.org/uzu/strudel/pulls/786)
+- 2023-11-05T22:10:25+01:00 Implement optional hover tooltip with function documentation by @Ghost in: [#783](https://codeberg.org/uzu/strudel/pulls/783)
+- 2023-11-05T16:46:06+01:00 Add function params in reference tab by @Ghost in: [#785](https://codeberg.org/uzu/strudel/pulls/785)
+- 2023-11-05T12:42:00+01:00 fix: style issues by @froos in: [#781](https://codeberg.org/uzu/strudel/pulls/781)
+- 2023-11-05T12:21:28+01:00 add xfade by @froos in: [#780](https://codeberg.org/uzu/strudel/pulls/780)
+- 2023-11-02T09:30:26+01:00 Update to Astro 3 by @froos in: [#775](https://codeberg.org/uzu/strudel/pulls/775)
+- 2023-11-02T08:57:14+01:00 add vscode bindings by @Ghost in: [#773](https://codeberg.org/uzu/strudel/pulls/773)
+- 2023-11-02T08:31:30+01:00 fix: share copy to clipboard + alert by @froos in: [#774](https://codeberg.org/uzu/strudel/pulls/774)
+- 2023-11-01T22:22:34+01:00 Fix chunk, add fastChunk and repeatCycles by @yaxu in: [#712](https://codeberg.org/uzu/strudel/pulls/712)
+- 2023-11-01T22:12:49+01:00 Document adsr function by @Ghost in: [#767](https://codeberg.org/uzu/strudel/pulls/767)
+- 2023-11-01T22:11:49+01:00 Add pick and squeeze functions by @Ghost in: [#771](https://codeberg.org/uzu/strudel/pulls/771)
+- 2023-11-01T22:04:00+01:00 Update vite pwa by @froos in: [#772](https://codeberg.org/uzu/strudel/pulls/772)
## october 2023
-- 2023-10-28T23:55:07+02:00 replace strudel.tidalcycles.org with strudel.cc by froos in: [#768](https://codeberg.org/uzu/strudel/pulls/768)
-- 2023-10-28T12:52:37+02:00 Document striate function by Ghost in: [#766](https://codeberg.org/uzu/strudel/pulls/766)
-- 2023-10-27T23:06:20+02:00 fix zen mode logo overlap by froos in: [#760](https://codeberg.org/uzu/strudel/pulls/760)
-- 2023-10-27T23:01:18+02:00 fix: scale offset by froos in: [#764](https://codeberg.org/uzu/strudel/pulls/764)
-- 2023-10-27T21:59:35+02:00 Fix addivite synthesis phases by froos in: [#762](https://codeberg.org/uzu/strudel/pulls/762)
-- 2023-10-26T16:28:16+02:00 Hydra integration by froos in: [#759](https://codeberg.org/uzu/strudel/pulls/759)
-- 2023-10-26T14:14:27+02:00 add play function by froos in: [#758](https://codeberg.org/uzu/strudel/pulls/758)
-- 2023-10-26T13:11:00+02:00 Add shabda shortcut by Ghost in: [#740](https://codeberg.org/uzu/strudel/pulls/740)
-- 2023-10-26T13:07:23+02:00 mini notation: international alphabets support by Ghost in: [#751](https://codeberg.org/uzu/strudel/pulls/751)
-- 2023-10-22T23:00:52+02:00 hopefully fix trainling slashes bug by froos in: [#753](https://codeberg.org/uzu/strudel/pulls/753)
-- 2023-10-21T23:38:50+02:00 Fix krill build command in README by Ghost in: [#748](https://codeberg.org/uzu/strudel/pulls/748)
-- 2023-10-21T00:20:50+02:00 completely revert config mess by froos in: [#745](https://codeberg.org/uzu/strudel/pulls/745)
-- 2023-10-20T22:41:39+02:00 fix: try different trailing slash behavior by froos in: [#744](https://codeberg.org/uzu/strudel/pulls/744)
-- 2023-10-20T22:34:03+02:00 fix: trailing slash confusion by froos in: [#743](https://codeberg.org/uzu/strudel/pulls/743)
-- 2023-10-20T12:07:04+02:00 [Bug Fix] chooseWith: prevent pattern from stopping audio when selection is >= 1 or < 0 by Ghost in: [#741](https://codeberg.org/uzu/strudel/pulls/741)
-- 2023-10-20T11:34:26+02:00 Recipes by froos in: [#742](https://codeberg.org/uzu/strudel/pulls/742)
-- 2023-10-13T12:57:24+02:00 vite-vanilla-repl readme fix by froos in: [#737](https://codeberg.org/uzu/strudel/pulls/737)
-- 2023-10-10T00:17:59+02:00 Add support for using samples as impulse response buffers for the reverb by Ghost in: [#717](https://codeberg.org/uzu/strudel/pulls/717)
-- 2023-10-09T21:43:42+02:00 fix: reverb sampleRate by froos in: [#732](https://codeberg.org/uzu/strudel/pulls/732)
-- 2023-10-09T21:34:33+02:00 fix: reverb roomsize not required by froos in: [#731](https://codeberg.org/uzu/strudel/pulls/731)
-- 2023-10-08T13:54:52+02:00 Compressor by froos in: [#729](https://codeberg.org/uzu/strudel/pulls/729)
-- 2023-10-08T13:25:57+02:00 fix: hashes in urls by froos in: [#728](https://codeberg.org/uzu/strudel/pulls/728)
-- 2023-10-07T15:48:06+02:00 consume n with scale by froos in: [#727](https://codeberg.org/uzu/strudel/pulls/727)
-- 2023-10-07T00:27:21+02:00 fix: reverb regenerate loophole by froos in: [#726](https://codeberg.org/uzu/strudel/pulls/726)
-- 2023-10-05T00:04:17+02:00 Better convolution reverb by generating impulse responses by Ghost in: [#718](https://codeberg.org/uzu/strudel/pulls/718)
-- 2023-10-04T10:31:53+02:00 Slider afterthoughts by froos in: [#723](https://codeberg.org/uzu/strudel/pulls/723)
-- 2023-10-03T16:39:06+02:00 Add 'white', 'pink' and 'brown' oscillators + refactor synth by Ghost in: [#713](https://codeberg.org/uzu/strudel/pulls/713)
-- 2023-10-01T14:20:50+02:00 support mininotation '..' range operator, fixes #715 by yaxu in: [#716](https://codeberg.org/uzu/strudel/pulls/716)
-- 2023-10-01T14:15:09+02:00 widgets by froos in: [#714](https://codeberg.org/uzu/strudel/pulls/714)
+- 2023-10-28T23:55:07+02:00 replace strudel.tidalcycles.org with strudel.cc by @froos in: [#768](https://codeberg.org/uzu/strudel/pulls/768)
+- 2023-10-28T12:52:37+02:00 Document striate function by @Ghost in: [#766](https://codeberg.org/uzu/strudel/pulls/766)
+- 2023-10-27T23:06:20+02:00 fix zen mode logo overlap by @froos in: [#760](https://codeberg.org/uzu/strudel/pulls/760)
+- 2023-10-27T23:01:18+02:00 fix: scale offset by @froos in: [#764](https://codeberg.org/uzu/strudel/pulls/764)
+- 2023-10-27T21:59:35+02:00 Fix addivite synthesis phases by @froos in: [#762](https://codeberg.org/uzu/strudel/pulls/762)
+- 2023-10-26T16:28:16+02:00 Hydra integration by @froos in: [#759](https://codeberg.org/uzu/strudel/pulls/759)
+- 2023-10-26T14:14:27+02:00 add play function by @froos in: [#758](https://codeberg.org/uzu/strudel/pulls/758)
+- 2023-10-26T13:11:00+02:00 Add shabda shortcut by @Ghost in: [#740](https://codeberg.org/uzu/strudel/pulls/740)
+- 2023-10-26T13:07:23+02:00 mini notation: international alphabets support by @Ghost in: [#751](https://codeberg.org/uzu/strudel/pulls/751)
+- 2023-10-22T23:00:52+02:00 hopefully fix trainling slashes bug by @froos in: [#753](https://codeberg.org/uzu/strudel/pulls/753)
+- 2023-10-21T23:38:50+02:00 Fix krill build command in README by @Ghost in: [#748](https://codeberg.org/uzu/strudel/pulls/748)
+- 2023-10-21T00:20:50+02:00 completely revert config mess by @froos in: [#745](https://codeberg.org/uzu/strudel/pulls/745)
+- 2023-10-20T22:41:39+02:00 fix: try different trailing slash behavior by @froos in: [#744](https://codeberg.org/uzu/strudel/pulls/744)
+- 2023-10-20T22:34:03+02:00 fix: trailing slash confusion by @froos in: [#743](https://codeberg.org/uzu/strudel/pulls/743)
+- 2023-10-20T12:07:04+02:00 [Bug Fix] chooseWith: prevent pattern from stopping audio when selection is >= 1 or < 0 by @Ghost in: [#741](https://codeberg.org/uzu/strudel/pulls/741)
+- 2023-10-20T11:34:26+02:00 Recipes by @froos in: [#742](https://codeberg.org/uzu/strudel/pulls/742)
+- 2023-10-13T12:57:24+02:00 vite-vanilla-repl readme fix by @froos in: [#737](https://codeberg.org/uzu/strudel/pulls/737)
+- 2023-10-10T00:17:59+02:00 Add support for using samples as impulse response buffers for the reverb by @Ghost in: [#717](https://codeberg.org/uzu/strudel/pulls/717)
+- 2023-10-09T21:43:42+02:00 fix: reverb sampleRate by @froos in: [#732](https://codeberg.org/uzu/strudel/pulls/732)
+- 2023-10-09T21:34:33+02:00 fix: reverb roomsize not required by @froos in: [#731](https://codeberg.org/uzu/strudel/pulls/731)
+- 2023-10-08T13:54:52+02:00 Compressor by @froos in: [#729](https://codeberg.org/uzu/strudel/pulls/729)
+- 2023-10-08T13:25:57+02:00 fix: hashes in urls by @froos in: [#728](https://codeberg.org/uzu/strudel/pulls/728)
+- 2023-10-07T15:48:06+02:00 consume n with scale by @froos in: [#727](https://codeberg.org/uzu/strudel/pulls/727)
+- 2023-10-07T00:27:21+02:00 fix: reverb regenerate loophole by @froos in: [#726](https://codeberg.org/uzu/strudel/pulls/726)
+- 2023-10-05T00:04:17+02:00 Better convolution reverb by generating impulse responses by @Ghost in: [#718](https://codeberg.org/uzu/strudel/pulls/718)
+- 2023-10-04T10:31:53+02:00 Slider afterthoughts by @froos in: [#723](https://codeberg.org/uzu/strudel/pulls/723)
+- 2023-10-03T16:39:06+02:00 Add 'white', 'pink' and 'brown' oscillators + refactor synth by @Ghost in: [#713](https://codeberg.org/uzu/strudel/pulls/713)
+- 2023-10-01T14:20:50+02:00 support mininotation '..' range operator, fixes #715 by @yaxu in: [#716](https://codeberg.org/uzu/strudel/pulls/716)
+- 2023-10-01T14:15:09+02:00 widgets by @froos in: [#714](https://codeberg.org/uzu/strudel/pulls/714)
## september 2023
-- 2023-09-28T11:03:09+02:00 Midi in by froos in: [#699](https://codeberg.org/uzu/strudel/pulls/699)
-- 2023-09-27T22:53:49+02:00 add midi clock support by froos in: [#710](https://codeberg.org/uzu/strudel/pulls/710)
-- 2023-09-25T23:36:10+02:00 Update bournemouth.mdx by Ghost in: [#708](https://codeberg.org/uzu/strudel/pulls/708)
-- 2023-09-25T23:06:30+02:00 add dough function for raw dsp by froos in: [#707](https://codeberg.org/uzu/strudel/pulls/707)
-- 2023-09-17T15:53:27+02:00 Update tauri.yml workflow file by Ghost in: [#705](https://codeberg.org/uzu/strudel/pulls/705)
-- 2023-09-17T11:05:06+02:00 Adding vibrato to base oscillators by Ghost in: [#693](https://codeberg.org/uzu/strudel/pulls/693)
-- 2023-09-17T08:27:36+02:00 Adding loop points and thus wavetable synthesis by Ghost in: [#698](https://codeberg.org/uzu/strudel/pulls/698)
-- 2023-09-16T02:03:49+02:00 Adding filter envelopes and filter order selection by Ghost in: [#692](https://codeberg.org/uzu/strudel/pulls/692)
-- 2023-09-09T11:19:58+02:00 Add logging from tauri by Ghost in: [#697](https://codeberg.org/uzu/strudel/pulls/697)
-- 2023-09-05T00:33:54+02:00 Direct OSC Support in Tauri by Ghost in: [#694](https://codeberg.org/uzu/strudel/pulls/694)
-- 2023-09-03T22:19:22+02:00 fix MIDI CC messages by Ghost in: [#690](https://codeberg.org/uzu/strudel/pulls/690)
-- 2023-09-03T10:22:15+02:00 add sleep timer + improve message iterating by Ghost in: [#688](https://codeberg.org/uzu/strudel/pulls/688)
+- 2023-09-28T11:03:09+02:00 Midi in by @froos in: [#699](https://codeberg.org/uzu/strudel/pulls/699)
+- 2023-09-27T22:53:49+02:00 add midi clock support by @froos in: [#710](https://codeberg.org/uzu/strudel/pulls/710)
+- 2023-09-25T23:36:10+02:00 Update bournemouth.mdx by @Ghost in: [#708](https://codeberg.org/uzu/strudel/pulls/708)
+- 2023-09-25T23:06:30+02:00 add dough function for raw dsp by @froos in: [#707](https://codeberg.org/uzu/strudel/pulls/707)
+- 2023-09-17T15:53:27+02:00 Update tauri.yml workflow file by @Ghost in: [#705](https://codeberg.org/uzu/strudel/pulls/705)
+- 2023-09-17T11:05:06+02:00 Adding vibrato to base oscillators by @Ghost in: [#693](https://codeberg.org/uzu/strudel/pulls/693)
+- 2023-09-17T08:27:36+02:00 Adding loop points and thus wavetable synthesis by @Ghost in: [#698](https://codeberg.org/uzu/strudel/pulls/698)
+- 2023-09-16T02:03:49+02:00 Adding filter envelopes and filter order selection by @Ghost in: [#692](https://codeberg.org/uzu/strudel/pulls/692)
+- 2023-09-09T11:19:58+02:00 Add logging from tauri by @Ghost in: [#697](https://codeberg.org/uzu/strudel/pulls/697)
+- 2023-09-05T00:33:54+02:00 Direct OSC Support in Tauri by @Ghost in: [#694](https://codeberg.org/uzu/strudel/pulls/694)
+- 2023-09-03T22:19:22+02:00 fix MIDI CC messages by @Ghost in: [#690](https://codeberg.org/uzu/strudel/pulls/690)
+- 2023-09-03T10:22:15+02:00 add sleep timer + improve message iterating by @Ghost in: [#688](https://codeberg.org/uzu/strudel/pulls/688)
## august 2023
-- 2023-08-31T13:00:31+02:00 ZZFX Synth support by Ghost in: [#684](https://codeberg.org/uzu/strudel/pulls/684)
-- 2023-08-31T12:36:37+02:00 Wave Selection and Global Envelope on the FM Synth Modulator by Ghost in: [#683](https://codeberg.org/uzu/strudel/pulls/683)
-- 2023-08-31T05:52:17+02:00 Create Midi Integration for Tauri Desktop app by Ghost in: [#685](https://codeberg.org/uzu/strudel/pulls/685)
-- 2023-08-31T05:32:16+02:00 teletext theme + fonts by froos in: [#681](https://codeberg.org/uzu/strudel/pulls/681)
-- 2023-08-31T05:20:55+02:00 control osc partial count with n by froos in: [#674](https://codeberg.org/uzu/strudel/pulls/674)
-- 2023-08-27T22:18:06+02:00 add emoji support by froos in: [#680](https://codeberg.org/uzu/strudel/pulls/680)
-- 2023-08-27T16:12:32+02:00 Pianoroll improvements by froos in: [#679](https://codeberg.org/uzu/strudel/pulls/679)
-- 2023-08-26T21:22:17+02:00 Scope by froos in: [#677](https://codeberg.org/uzu/strudel/pulls/677)
-- 2023-08-23T21:50:50+02:00 Midi time fixes by Ghost in: [#668](https://codeberg.org/uzu/strudel/pulls/668)
-- 2023-08-20T23:19:08+02:00 basic fm by froos in: [#669](https://codeberg.org/uzu/strudel/pulls/669)
-- 2023-08-18T23:56:20+02:00 togglable panel position by froos in: [#667](https://codeberg.org/uzu/strudel/pulls/667)
-- 2023-08-18T15:59:20+02:00 fix osc bundle timestamp glitches caused by drifting clock by Ghost in: [#666](https://codeberg.org/uzu/strudel/pulls/666)
-- 2023-08-17T11:36:07+02:00 superdough: encapsulates web audio output by froos in: [#664](https://codeberg.org/uzu/strudel/pulls/664)
-- 2023-08-11T00:06:21+02:00 fix: always run previous trigger by froos in: [#660](https://codeberg.org/uzu/strudel/pulls/660)
-- 2023-08-10T23:54:58+02:00 fix: welcome message for latestCode by froos in: [#659](https://codeberg.org/uzu/strudel/pulls/659)
-- 2023-08-07T07:45:26+02:00 [Bug Fix] Midi: Don't treat note 0 as false by Ghost in: [#657](https://codeberg.org/uzu/strudel/pulls/657)
+- 2023-08-31T13:00:31+02:00 ZZFX Synth support by @Ghost in: [#684](https://codeberg.org/uzu/strudel/pulls/684)
+- 2023-08-31T12:36:37+02:00 Wave Selection and Global Envelope on the FM Synth Modulator by @Ghost in: [#683](https://codeberg.org/uzu/strudel/pulls/683)
+- 2023-08-31T05:52:17+02:00 Create Midi Integration for Tauri Desktop app by @Ghost in: [#685](https://codeberg.org/uzu/strudel/pulls/685)
+- 2023-08-31T05:32:16+02:00 teletext theme + fonts by @froos in: [#681](https://codeberg.org/uzu/strudel/pulls/681)
+- 2023-08-31T05:20:55+02:00 control osc partial count with n by @froos in: [#674](https://codeberg.org/uzu/strudel/pulls/674)
+- 2023-08-27T22:18:06+02:00 add emoji support by @froos in: [#680](https://codeberg.org/uzu/strudel/pulls/680)
+- 2023-08-27T16:12:32+02:00 Pianoroll improvements by @froos in: [#679](https://codeberg.org/uzu/strudel/pulls/679)
+- 2023-08-26T21:22:17+02:00 Scope by @froos in: [#677](https://codeberg.org/uzu/strudel/pulls/677)
+- 2023-08-23T21:50:50+02:00 Midi time fixes by @Ghost in: [#668](https://codeberg.org/uzu/strudel/pulls/668)
+- 2023-08-20T23:19:08+02:00 basic fm by @froos in: [#669](https://codeberg.org/uzu/strudel/pulls/669)
+- 2023-08-18T23:56:20+02:00 togglable panel position by @froos in: [#667](https://codeberg.org/uzu/strudel/pulls/667)
+- 2023-08-18T15:59:20+02:00 fix osc bundle timestamp glitches caused by drifting clock by @Ghost in: [#666](https://codeberg.org/uzu/strudel/pulls/666)
+- 2023-08-17T11:36:07+02:00 superdough: encapsulates web audio output by @froos in: [#664](https://codeberg.org/uzu/strudel/pulls/664)
+- 2023-08-11T00:06:21+02:00 fix: always run previous trigger by @froos in: [#660](https://codeberg.org/uzu/strudel/pulls/660)
+- 2023-08-10T23:54:58+02:00 fix: welcome message for latestCode by @froos in: [#659](https://codeberg.org/uzu/strudel/pulls/659)
+- 2023-08-07T07:45:26+02:00 [Bug Fix] Midi: Don't treat note 0 as false by @Ghost in: [#657](https://codeberg.org/uzu/strudel/pulls/657)
## july 2023
-- 2023-07-29T09:06:18+02:00 [Bug Fix] Account for numeral notation when converting to midi by Ghost in: [#656](https://codeberg.org/uzu/strudel/pulls/656)
-- 2023-07-23T22:18:49+02:00 ireal voicings by froos in: [#653](https://codeberg.org/uzu/strudel/pulls/653)
-- 2023-07-22T09:30:21+02:00 Understand pitch by froos in: [#652](https://codeberg.org/uzu/strudel/pulls/652)
-- 2023-07-17T23:42:59+02:00 update vitest by froos in: [#651](https://codeberg.org/uzu/strudel/pulls/651)
-- 2023-07-17T23:34:33+02:00 stateless voicings + tonleiter lib by froos in: [#647](https://codeberg.org/uzu/strudel/pulls/647)
-- 2023-07-17T17:57:17+02:00 FIXES: TODO in rotateChroma by Ghost in: [#650](https://codeberg.org/uzu/strudel/pulls/650)
-- 2023-07-10T19:07:45+02:00 slice: list mode by froos in: [#645](https://codeberg.org/uzu/strudel/pulls/645)
-- 2023-07-04T23:50:30+02:00 Delete old packages by froos in: [#639](https://codeberg.org/uzu/strudel/pulls/639)
-- 2023-07-04T23:38:42+02:00 Adaptive Highlighting by froos in: [#634](https://codeberg.org/uzu/strudel/pulls/634)
-- 2023-07-04T21:55:57+02:00 More work on highlight IDs by Ghost in: [#636](https://codeberg.org/uzu/strudel/pulls/636)
-- 2023-07-04T18:44:48+02:00 snapshot tests: sort haps by part by froos in: [#637](https://codeberg.org/uzu/strudel/pulls/637)
+- 2023-07-29T09:06:18+02:00 [Bug Fix] Account for numeral notation when converting to midi by @Ghost in: [#656](https://codeberg.org/uzu/strudel/pulls/656)
+- 2023-07-23T22:18:49+02:00 ireal voicings by @froos in: [#653](https://codeberg.org/uzu/strudel/pulls/653)
+- 2023-07-22T09:30:21+02:00 Understand pitch by @froos in: [#652](https://codeberg.org/uzu/strudel/pulls/652)
+- 2023-07-17T23:42:59+02:00 update vitest by @froos in: [#651](https://codeberg.org/uzu/strudel/pulls/651)
+- 2023-07-17T23:34:33+02:00 stateless voicings + tonleiter lib by @froos in: [#647](https://codeberg.org/uzu/strudel/pulls/647)
+- 2023-07-17T17:57:17+02:00 FIXES: TODO in rotateChroma by @Ghost in: [#650](https://codeberg.org/uzu/strudel/pulls/650)
+- 2023-07-10T19:07:45+02:00 slice: list mode by @froos in: [#645](https://codeberg.org/uzu/strudel/pulls/645)
+- 2023-07-04T23:50:30+02:00 Delete old packages by @froos in: [#639](https://codeberg.org/uzu/strudel/pulls/639)
+- 2023-07-04T23:38:42+02:00 Adaptive Highlighting by @froos in: [#634](https://codeberg.org/uzu/strudel/pulls/634)
+- 2023-07-04T21:55:57+02:00 More work on highlight IDs by @Ghost in: [#636](https://codeberg.org/uzu/strudel/pulls/636)
+- 2023-07-04T18:44:48+02:00 snapshot tests: sort haps by part by @froos in: [#637](https://codeberg.org/uzu/strudel/pulls/637)
## juny 2023
-- 2023-06-30T22:47:40+02:00 fix: update canvas size on window resize by froos in: [#631](https://codeberg.org/uzu/strudel/pulls/631)
-- 2023-06-30T22:45:41+02:00 fix: out of range error by froos in: [#630](https://codeberg.org/uzu/strudel/pulls/630)
-- 2023-06-30T08:14:40+02:00 fix: midi clock drift by froos in: [#627](https://codeberg.org/uzu/strudel/pulls/627)
-- 2023-06-29T22:02:28+02:00 desktop: play samples from disk by froos in: [#621](https://codeberg.org/uzu/strudel/pulls/621)
-- 2023-06-29T21:59:43+02:00 cps dependent functions by froos in: [#620](https://codeberg.org/uzu/strudel/pulls/620)
-- 2023-06-26T22:45:04+02:00 Fix typo on packages.mdx by Ghost in: [#520](https://codeberg.org/uzu/strudel/pulls/520)
-- 2023-06-26T22:35:02+02:00 patterning ui settings by froos in: [#606](https://codeberg.org/uzu/strudel/pulls/606)
-- 2023-06-26T22:32:46+02:00 add spiral viz by froos in: [#614](https://codeberg.org/uzu/strudel/pulls/614)
-- 2023-06-26T22:17:46+02:00 tauri desktop app by Ghost in: [#613](https://codeberg.org/uzu/strudel/pulls/613)
-- 2023-06-23T09:59:43+02:00 fix: doc links by froos in: [#612](https://codeberg.org/uzu/strudel/pulls/612)
-- 2023-06-23T09:55:18+02:00 clip now works like legato in tidal by froos in: [#598](https://codeberg.org/uzu/strudel/pulls/598)
-- 2023-06-18T10:36:19+02:00 fix: flatten scale lists by froos in: [#605](https://codeberg.org/uzu/strudel/pulls/605)
-- 2023-06-18T10:36:17+02:00 tonal fixes by froos in: [#607](https://codeberg.org/uzu/strudel/pulls/607)
-- 2023-06-15T12:51:40+02:00 editor: enable line wrapping by Ghost in: [#581](https://codeberg.org/uzu/strudel/pulls/581)
-- 2023-06-15T10:22:46+02:00 add ratio function by froos in: [#602](https://codeberg.org/uzu/strudel/pulls/602)
-- 2023-06-12T23:24:29+02:00 enable auto-completion by Ghost in: [#588](https://codeberg.org/uzu/strudel/pulls/588)
-- 2023-06-11T22:04:17+02:00 improve cursor by froos in: [#597](https://codeberg.org/uzu/strudel/pulls/597)
-- 2023-06-11T20:00:45+02:00 Solmization added by Ghost in: [#570](https://codeberg.org/uzu/strudel/pulls/570)
-- 2023-06-11T19:45:00+02:00 fix: division by zero by froos in: [#591](https://codeberg.org/uzu/strudel/pulls/591)
-- 2023-06-11T19:44:43+02:00 fix: allow f for flat notes like tidal by froos in: [#593](https://codeberg.org/uzu/strudel/pulls/593)
-- 2023-06-11T19:44:41+02:00 Fix option dot by froos in: [#596](https://codeberg.org/uzu/strudel/pulls/596)
-- 2023-06-09T21:02:12+02:00 New Workshop by froos in: [#587](https://codeberg.org/uzu/strudel/pulls/587)
-- 2023-06-09T17:31:58+02:00 Music metadata by Ghost in: [#580](https://codeberg.org/uzu/strudel/pulls/580)
-- 2023-06-08T09:33:34+02:00 learn/tonal: fix typo in "scaleTran[s]pose" by Ghost in: [#585](https://codeberg.org/uzu/strudel/pulls/585)
-- 2023-06-07T20:19:11+02:00 repl: add option to display line numbers by Ghost in: [#582](https://codeberg.org/uzu/strudel/pulls/582)
-- 2023-06-05T21:35:49+02:00 Vanilla JS Refactoring by froos in: [#563](https://codeberg.org/uzu/strudel/pulls/563)
+- 2023-06-30T22:47:40+02:00 fix: update canvas size on window resize by @froos in: [#631](https://codeberg.org/uzu/strudel/pulls/631)
+- 2023-06-30T22:45:41+02:00 fix: out of range error by @froos in: [#630](https://codeberg.org/uzu/strudel/pulls/630)
+- 2023-06-30T08:14:40+02:00 fix: midi clock drift by @froos in: [#627](https://codeberg.org/uzu/strudel/pulls/627)
+- 2023-06-29T22:02:28+02:00 desktop: play samples from disk by @froos in: [#621](https://codeberg.org/uzu/strudel/pulls/621)
+- 2023-06-29T21:59:43+02:00 cps dependent functions by @froos in: [#620](https://codeberg.org/uzu/strudel/pulls/620)
+- 2023-06-26T22:45:04+02:00 Fix typo on packages.mdx by @Ghost in: [#520](https://codeberg.org/uzu/strudel/pulls/520)
+- 2023-06-26T22:35:02+02:00 patterning ui settings by @froos in: [#606](https://codeberg.org/uzu/strudel/pulls/606)
+- 2023-06-26T22:32:46+02:00 add spiral viz by @froos in: [#614](https://codeberg.org/uzu/strudel/pulls/614)
+- 2023-06-26T22:17:46+02:00 tauri desktop app by @Ghost in: [#613](https://codeberg.org/uzu/strudel/pulls/613)
+- 2023-06-23T09:59:43+02:00 fix: doc links by @froos in: [#612](https://codeberg.org/uzu/strudel/pulls/612)
+- 2023-06-23T09:55:18+02:00 clip now works like legato in tidal by @froos in: [#598](https://codeberg.org/uzu/strudel/pulls/598)
+- 2023-06-18T10:36:19+02:00 fix: flatten scale lists by @froos in: [#605](https://codeberg.org/uzu/strudel/pulls/605)
+- 2023-06-18T10:36:17+02:00 tonal fixes by @froos in: [#607](https://codeberg.org/uzu/strudel/pulls/607)
+- 2023-06-15T12:51:40+02:00 editor: enable line wrapping by @Ghost in: [#581](https://codeberg.org/uzu/strudel/pulls/581)
+- 2023-06-15T10:22:46+02:00 add ratio function by @froos in: [#602](https://codeberg.org/uzu/strudel/pulls/602)
+- 2023-06-12T23:24:29+02:00 enable auto-completion by @Ghost in: [#588](https://codeberg.org/uzu/strudel/pulls/588)
+- 2023-06-11T22:04:17+02:00 improve cursor by @froos in: [#597](https://codeberg.org/uzu/strudel/pulls/597)
+- 2023-06-11T20:00:45+02:00 Solmization added by @Ghost in: [#570](https://codeberg.org/uzu/strudel/pulls/570)
+- 2023-06-11T19:45:00+02:00 fix: division by zero by @froos in: [#591](https://codeberg.org/uzu/strudel/pulls/591)
+- 2023-06-11T19:44:43+02:00 fix: allow f for flat notes like tidal by @froos in: [#593](https://codeberg.org/uzu/strudel/pulls/593)
+- 2023-06-11T19:44:41+02:00 Fix option dot by @froos in: [#596](https://codeberg.org/uzu/strudel/pulls/596)
+- 2023-06-09T21:02:12+02:00 New Workshop by @froos in: [#587](https://codeberg.org/uzu/strudel/pulls/587)
+- 2023-06-09T17:31:58+02:00 Music metadata by @Ghost in: [#580](https://codeberg.org/uzu/strudel/pulls/580)
+- 2023-06-08T09:33:34+02:00 learn/tonal: fix typo in "scaleTran[s]pose" by @Ghost in: [#585](https://codeberg.org/uzu/strudel/pulls/585)
+- 2023-06-07T20:19:11+02:00 repl: add option to display line numbers by @Ghost in: [#582](https://codeberg.org/uzu/strudel/pulls/582)
+- 2023-06-05T21:35:49+02:00 Vanilla JS Refactoring by @froos in: [#563](https://codeberg.org/uzu/strudel/pulls/563)
## may 2023
-- 2023-05-05T08:34:37+02:00 Patchday by froos in: [#559](https://codeberg.org/uzu/strudel/pulls/559)
-- 2023-05-02T21:48:33+02:00 add basic triads and guidetone voicings by froos in: [#557](https://codeberg.org/uzu/strudel/pulls/557)
+- 2023-05-05T08:34:37+02:00 Patchday by @froos in: [#559](https://codeberg.org/uzu/strudel/pulls/559)
+- 2023-05-02T21:48:33+02:00 add basic triads and guidetone voicings by @froos in: [#557](https://codeberg.org/uzu/strudel/pulls/557)
## april 2023
-- 2023-04-28T12:46:56+02:00 fix: make soundfonts import dynamic by froos in: [#556](https://codeberg.org/uzu/strudel/pulls/556)
-- 2023-04-22T15:43:22+02:00 fix: colorable highlighting by froos in: [#553](https://codeberg.org/uzu/strudel/pulls/553)
-- 2023-04-06T00:11:02+02:00 fix: load soundfonts in prebake by froos in: [#550](https://codeberg.org/uzu/strudel/pulls/550)
+- 2023-04-28T12:46:56+02:00 fix: make soundfonts import dynamic by @froos in: [#556](https://codeberg.org/uzu/strudel/pulls/556)
+- 2023-04-22T15:43:22+02:00 fix: colorable highlighting by @froos in: [#553](https://codeberg.org/uzu/strudel/pulls/553)
+- 2023-04-06T00:11:02+02:00 fix: load soundfonts in prebake by @froos in: [#550](https://codeberg.org/uzu/strudel/pulls/550)
## march 2023
-- 2023-03-29T22:23:07+02:00 fix: reset time on stop by froos in: [#548](https://codeberg.org/uzu/strudel/pulls/548)
-- 2023-03-29T22:16:38+02:00 fix: allow whitespace at the end of a mini pattern by froos in: [#547](https://codeberg.org/uzu/strudel/pulls/547)
-- 2023-03-24T22:10:56+01:00 add firacode font by froos in: [#544](https://codeberg.org/uzu/strudel/pulls/544)
-- 2023-03-24T12:54:20+01:00 feat: add loader bar to animate loading state by froos in: [#542](https://codeberg.org/uzu/strudel/pulls/542)
-- 2023-03-23T22:39:27+01:00 do not reset cps before eval #517 by froos in: [#539](https://codeberg.org/uzu/strudel/pulls/539)
-- 2023-03-23T22:27:31+01:00 improve initial loading + wait before eval by froos in: [#538](https://codeberg.org/uzu/strudel/pulls/538)
-- 2023-03-23T21:40:20+01:00 fix period key for dvorak + remove duplicated code by froos in: [#537](https://codeberg.org/uzu/strudel/pulls/537)
-- 2023-03-23T11:44:56+01:00 Update lerna by froos in: [#535](https://codeberg.org/uzu/strudel/pulls/535)
-- 2023-03-23T10:21:55+01:00 feat: add freq support to gm soundfonts by froos in: [#534](https://codeberg.org/uzu/strudel/pulls/534)
-- 2023-03-23T10:18:58+01:00 Maintain random seed state in parser, not globally by Ghost in: [#531](https://codeberg.org/uzu/strudel/pulls/531)
-- 2023-03-21T22:35:18+01:00 FIXES: alias pm for polymeter by Ghost in: [#527](https://codeberg.org/uzu/strudel/pulls/527)
-- 2023-03-21T22:29:07+01:00 fix(footer): fix link to tidalcycles by julienbouquillon in: [#529](https://codeberg.org/uzu/strudel/pulls/529)
-- 2023-03-18T20:25:21+01:00 Update intro.mdx by Ghost in: [#525](https://codeberg.org/uzu/strudel/pulls/525)
-- 2023-03-18T20:24:38+01:00 Update samples.mdx by Ghost in: [#524](https://codeberg.org/uzu/strudel/pulls/524)
-- 2023-03-17T09:03:11+01:00 fix: envelopes in chrome by froos in: [#521](https://codeberg.org/uzu/strudel/pulls/521)
-- 2023-03-16T16:13:30+01:00 registerSound API + improved sounds tab + regroup soundfonts by froos in: [#516](https://codeberg.org/uzu/strudel/pulls/516)
-- 2023-03-14T21:54:53+01:00 add 2 illegible fonts by froos in: [#518](https://codeberg.org/uzu/strudel/pulls/518)
-- 2023-03-06T22:55:00+01:00 Update README.md by Ghost in: [#474](https://codeberg.org/uzu/strudel/pulls/474)
-- 2023-03-05T14:52:30+01:00 add arrange function by froos in: [#508](https://codeberg.org/uzu/strudel/pulls/508)
-- 2023-03-05T14:29:08+01:00 update react to 18 by froos in: [#514](https://codeberg.org/uzu/strudel/pulls/514)
-- 2023-03-04T19:06:18+01:00 Support list syntax in mininotation by yaxu in: [#512](https://codeberg.org/uzu/strudel/pulls/512)
-- 2023-03-03T12:40:23+01:00 can now use : as a replacement for space in scales by froos in: [#502](https://codeberg.org/uzu/strudel/pulls/502)
-- 2023-03-02T15:44:41+01:00 Reinstate slice and splice by yaxu in: [#500](https://codeberg.org/uzu/strudel/pulls/500)
-- 2023-03-02T14:49:30+01:00 fix: nano-repl highlighting by froos in: [#501](https://codeberg.org/uzu/strudel/pulls/501)
-- 2023-03-02T14:17:13+01:00 Add control aliases by yaxu in: [#497](https://codeberg.org/uzu/strudel/pulls/497)
-- 2023-03-01T09:27:27+01:00 implement cps in scheduler by froos in: [#493](https://codeberg.org/uzu/strudel/pulls/493)
+- 2023-03-29T22:23:07+02:00 fix: reset time on stop by @froos in: [#548](https://codeberg.org/uzu/strudel/pulls/548)
+- 2023-03-29T22:16:38+02:00 fix: allow whitespace at the end of a mini pattern by @froos in: [#547](https://codeberg.org/uzu/strudel/pulls/547)
+- 2023-03-24T22:10:56+01:00 add firacode font by @froos in: [#544](https://codeberg.org/uzu/strudel/pulls/544)
+- 2023-03-24T12:54:20+01:00 feat: add loader bar to animate loading state by @froos in: [#542](https://codeberg.org/uzu/strudel/pulls/542)
+- 2023-03-23T22:39:27+01:00 do not reset cps before eval #517 by @froos in: [#539](https://codeberg.org/uzu/strudel/pulls/539)
+- 2023-03-23T22:27:31+01:00 improve initial loading + wait before eval by @froos in: [#538](https://codeberg.org/uzu/strudel/pulls/538)
+- 2023-03-23T21:40:20+01:00 fix period key for dvorak + remove duplicated code by @froos in: [#537](https://codeberg.org/uzu/strudel/pulls/537)
+- 2023-03-23T11:44:56+01:00 Update lerna by @froos in: [#535](https://codeberg.org/uzu/strudel/pulls/535)
+- 2023-03-23T10:21:55+01:00 feat: add freq support to gm soundfonts by @froos in: [#534](https://codeberg.org/uzu/strudel/pulls/534)
+- 2023-03-23T10:18:58+01:00 Maintain random seed state in parser, not globally by @Ghost in: [#531](https://codeberg.org/uzu/strudel/pulls/531)
+- 2023-03-21T22:35:18+01:00 FIXES: alias pm for polymeter by @Ghost in: [#527](https://codeberg.org/uzu/strudel/pulls/527)
+- 2023-03-21T22:29:07+01:00 fix(footer): fix link to tidalcycles by @julienbouquillon in: [#529](https://codeberg.org/uzu/strudel/pulls/529)
+- 2023-03-18T20:25:21+01:00 Update intro.mdx by @Ghost in: [#525](https://codeberg.org/uzu/strudel/pulls/525)
+- 2023-03-18T20:24:38+01:00 Update samples.mdx by @Ghost in: [#524](https://codeberg.org/uzu/strudel/pulls/524)
+- 2023-03-17T09:03:11+01:00 fix: envelopes in chrome by @froos in: [#521](https://codeberg.org/uzu/strudel/pulls/521)
+- 2023-03-16T16:13:30+01:00 registerSound API + improved sounds tab + regroup soundfonts by @froos in: [#516](https://codeberg.org/uzu/strudel/pulls/516)
+- 2023-03-14T21:54:53+01:00 add 2 illegible fonts by @froos in: [#518](https://codeberg.org/uzu/strudel/pulls/518)
+- 2023-03-06T22:55:00+01:00 Update README.md by @Ghost in: [#474](https://codeberg.org/uzu/strudel/pulls/474)
+- 2023-03-05T14:52:30+01:00 add arrange function by @froos in: [#508](https://codeberg.org/uzu/strudel/pulls/508)
+- 2023-03-05T14:29:08+01:00 update react to 18 by @froos in: [#514](https://codeberg.org/uzu/strudel/pulls/514)
+- 2023-03-04T19:06:18+01:00 Support list syntax in mininotation by @yaxu in: [#512](https://codeberg.org/uzu/strudel/pulls/512)
+- 2023-03-03T12:40:23+01:00 can now use : as a replacement for space in scales by @froos in: [#502](https://codeberg.org/uzu/strudel/pulls/502)
+- 2023-03-02T15:44:41+01:00 Reinstate slice and splice by @yaxu in: [#500](https://codeberg.org/uzu/strudel/pulls/500)
+- 2023-03-02T14:49:30+01:00 fix: nano-repl highlighting by @froos in: [#501](https://codeberg.org/uzu/strudel/pulls/501)
+- 2023-03-02T14:17:13+01:00 Add control aliases by @yaxu in: [#497](https://codeberg.org/uzu/strudel/pulls/497)
+- 2023-03-01T09:27:27+01:00 implement cps in scheduler by @froos in: [#493](https://codeberg.org/uzu/strudel/pulls/493)
## february 2023
-- 2023-02-28T23:06:29+01:00 react style fixes by froos in: [#491](https://codeberg.org/uzu/strudel/pulls/491)
-- 2023-02-28T22:57:20+01:00 refactor react package by froos in: [#490](https://codeberg.org/uzu/strudel/pulls/490)
-- 2023-02-27T23:47:34+01:00 add algolia creds + optimize sidebar for crawling by froos in: [#488](https://codeberg.org/uzu/strudel/pulls/488)
-- 2023-02-27T19:28:10+01:00 fix app height by froos in: [#485](https://codeberg.org/uzu/strudel/pulls/485)
-- 2023-02-27T16:04:21+01:00 Revert "Another attempt at composable functions - WIP (#390)" by froos in: [#484](https://codeberg.org/uzu/strudel/pulls/484)
-- 2023-02-27T15:45:20+01:00 Update mini-notation.mdx by yaxu in: [#365](https://codeberg.org/uzu/strudel/pulls/365)
-- 2023-02-27T12:52:09+01:00 docs: packages + offline by froos in: [#482](https://codeberg.org/uzu/strudel/pulls/482)
-- 2023-02-25T14:26:49+01:00 Fix array args by froos in: [#480](https://codeberg.org/uzu/strudel/pulls/480)
-- 2023-02-25T12:33:22+01:00 midi cc support by froos in: [#478](https://codeberg.org/uzu/strudel/pulls/478)
-- 2023-02-23T00:11:05+01:00 fix: hash links by froos in: [#473](https://codeberg.org/uzu/strudel/pulls/473)
-- 2023-02-22T22:54:39+01:00 settings tab with vim / emacs modes + additional themes and fonts by froos in: [#467](https://codeberg.org/uzu/strudel/pulls/467)
-- 2023-02-22T22:53:22+01:00 Update input-output.mdx by Ghost in: [#471](https://codeberg.org/uzu/strudel/pulls/471)
-- 2023-02-22T22:52:50+01:00 FIXES: freqs instead of pitches by Ghost in: [#464](https://codeberg.org/uzu/strudel/pulls/464)
-- 2023-02-22T20:01:00+01:00 fix: osc should not return a promise by froos in: [#472](https://codeberg.org/uzu/strudel/pulls/472)
-- 2023-02-22T12:51:31+01:00 slice and splice by yaxu in: [#466](https://codeberg.org/uzu/strudel/pulls/466)
-- 2023-02-18T01:00:19+01:00 weave and weaveWith by yaxu in: [#465](https://codeberg.org/uzu/strudel/pulls/465)
-- 2023-02-17T00:15:21+01:00 Composable functions by yaxu in: [#390](https://codeberg.org/uzu/strudel/pulls/390)
-- 2023-02-16T20:38:45+01:00 FIXES: Warning about jsxBracketSameLine deprecation by Ghost in: [#461](https://codeberg.org/uzu/strudel/pulls/461)
-- 2023-02-14T22:11:02+01:00 Update synths.mdx by Ghost in: [#438](https://codeberg.org/uzu/strudel/pulls/438)
-- 2023-02-14T19:54:42+01:00 Update mini-notation.mdx by Ghost in: [#437](https://codeberg.org/uzu/strudel/pulls/437)
-- 2023-02-14T19:54:25+01:00 Update code.mdx by Ghost in: [#436](https://codeberg.org/uzu/strudel/pulls/436)
-- 2023-02-13T00:43:29+01:00 Fix anchors by froos in: [#433](https://codeberg.org/uzu/strudel/pulls/433)
-- 2023-02-11T21:02:11+01:00 autocomplete preparations by froos in: [#427](https://codeberg.org/uzu/strudel/pulls/427)
-- 2023-02-10T23:14:48+01:00 Themes by froos in: [#431](https://codeberg.org/uzu/strudel/pulls/431)
-- 2023-02-09T19:22:56+01:00 minirepl: add keyboard shortcuts by froos in: [#429](https://codeberg.org/uzu/strudel/pulls/429)
-- 2023-02-09T08:56:42+01:00 add cdn.freesound to cache list by froos in: [#425](https://codeberg.org/uzu/strudel/pulls/425)
-- 2023-02-08T20:36:00+01:00 add more offline caching by froos in: [#421](https://codeberg.org/uzu/strudel/pulls/421)
-- 2023-02-07T22:08:01+01:00 add caching strategy for missing file types + cache all samples loaded from github by froos in: [#419](https://codeberg.org/uzu/strudel/pulls/419)
-- 2023-02-06T23:29:57+01:00 PWA with offline support by froos in: [#417](https://codeberg.org/uzu/strudel/pulls/417)
-- 2023-02-05T17:27:32+01:00 improve samples doc by froos in: [#411](https://codeberg.org/uzu/strudel/pulls/411)
-- 2023-02-05T17:27:10+01:00 google gtfo by froos in: [#413](https://codeberg.org/uzu/strudel/pulls/413)
-- 2023-02-05T16:27:59+01:00 improve effects doc by froos in: [#409](https://codeberg.org/uzu/strudel/pulls/409)
-- 2023-02-05T14:56:03+01:00 Update effects.mdx by Ghost in: [#410](https://codeberg.org/uzu/strudel/pulls/410)
-- 2023-02-03T19:54:47+01:00 add shabda doc by froos in: [#407](https://codeberg.org/uzu/strudel/pulls/407)
-- 2023-02-02T21:45:56+01:00 fix: share url on subpath by froos in: [#405](https://codeberg.org/uzu/strudel/pulls/405)
-- 2023-02-02T21:35:45+01:00 update csound + fix sound output by froos in: [#404](https://codeberg.org/uzu/strudel/pulls/404)
-- 2023-02-02T19:53:36+01:00 pin @csound/browser to 6.18.3 + bump by froos in: [#403](https://codeberg.org/uzu/strudel/pulls/403)
-- 2023-02-01T22:47:27+01:00 release webaudio by froos in: [#400](https://codeberg.org/uzu/strudel/pulls/400)
-- 2023-02-01T22:45:16+01:00 can now await initAudio + initAudioOnFirstClick by froos in: [#399](https://codeberg.org/uzu/strudel/pulls/399)
-- 2023-02-01T22:32:18+01:00 fix: minirepl styles by froos in: [#398](https://codeberg.org/uzu/strudel/pulls/398)
-- 2023-02-01T22:17:19+01:00 proper builds + use pnpm workspaces by froos in: [#396](https://codeberg.org/uzu/strudel/pulls/396)
-- 2023-02-01T16:49:55+01:00 add pattern methods hurry, press and pressBy by yaxu in: [#397](https://codeberg.org/uzu/strudel/pulls/397)
+- 2023-02-28T23:06:29+01:00 react style fixes by @froos in: [#491](https://codeberg.org/uzu/strudel/pulls/491)
+- 2023-02-28T22:57:20+01:00 refactor react package by @froos in: [#490](https://codeberg.org/uzu/strudel/pulls/490)
+- 2023-02-27T23:47:34+01:00 add algolia creds + optimize sidebar for crawling by @froos in: [#488](https://codeberg.org/uzu/strudel/pulls/488)
+- 2023-02-27T19:28:10+01:00 fix app height by @froos in: [#485](https://codeberg.org/uzu/strudel/pulls/485)
+- 2023-02-27T16:04:21+01:00 Revert "Another attempt at composable functions - WIP (#390)" by @froos in: [#484](https://codeberg.org/uzu/strudel/pulls/484)
+- 2023-02-27T15:45:20+01:00 Update mini-notation.mdx by @yaxu in: [#365](https://codeberg.org/uzu/strudel/pulls/365)
+- 2023-02-27T12:52:09+01:00 docs: packages + offline by @froos in: [#482](https://codeberg.org/uzu/strudel/pulls/482)
+- 2023-02-25T14:26:49+01:00 Fix array args by @froos in: [#480](https://codeberg.org/uzu/strudel/pulls/480)
+- 2023-02-25T12:33:22+01:00 midi cc support by @froos in: [#478](https://codeberg.org/uzu/strudel/pulls/478)
+- 2023-02-23T00:11:05+01:00 fix: hash links by @froos in: [#473](https://codeberg.org/uzu/strudel/pulls/473)
+- 2023-02-22T22:54:39+01:00 settings tab with vim / emacs modes + additional themes and fonts by @froos in: [#467](https://codeberg.org/uzu/strudel/pulls/467)
+- 2023-02-22T22:53:22+01:00 Update input-output.mdx by @Ghost in: [#471](https://codeberg.org/uzu/strudel/pulls/471)
+- 2023-02-22T22:52:50+01:00 FIXES: freqs instead of pitches by @Ghost in: [#464](https://codeberg.org/uzu/strudel/pulls/464)
+- 2023-02-22T20:01:00+01:00 fix: osc should not return a promise by @froos in: [#472](https://codeberg.org/uzu/strudel/pulls/472)
+- 2023-02-22T12:51:31+01:00 slice and splice by @yaxu in: [#466](https://codeberg.org/uzu/strudel/pulls/466)
+- 2023-02-18T01:00:19+01:00 weave and weaveWith by @yaxu in: [#465](https://codeberg.org/uzu/strudel/pulls/465)
+- 2023-02-17T00:15:21+01:00 Composable functions by @yaxu in: [#390](https://codeberg.org/uzu/strudel/pulls/390)
+- 2023-02-16T20:38:45+01:00 FIXES: Warning about jsxBracketSameLine deprecation by @Ghost in: [#461](https://codeberg.org/uzu/strudel/pulls/461)
+- 2023-02-14T22:11:02+01:00 Update synths.mdx by @Ghost in: [#438](https://codeberg.org/uzu/strudel/pulls/438)
+- 2023-02-14T19:54:42+01:00 Update mini-notation.mdx by @Ghost in: [#437](https://codeberg.org/uzu/strudel/pulls/437)
+- 2023-02-14T19:54:25+01:00 Update code.mdx by @Ghost in: [#436](https://codeberg.org/uzu/strudel/pulls/436)
+- 2023-02-13T00:43:29+01:00 Fix anchors by @froos in: [#433](https://codeberg.org/uzu/strudel/pulls/433)
+- 2023-02-11T21:02:11+01:00 autocomplete preparations by @froos in: [#427](https://codeberg.org/uzu/strudel/pulls/427)
+- 2023-02-10T23:14:48+01:00 Themes by @froos in: [#431](https://codeberg.org/uzu/strudel/pulls/431)
+- 2023-02-09T19:22:56+01:00 minirepl: add keyboard shortcuts by @froos in: [#429](https://codeberg.org/uzu/strudel/pulls/429)
+- 2023-02-09T08:56:42+01:00 add cdn.freesound to cache list by @froos in: [#425](https://codeberg.org/uzu/strudel/pulls/425)
+- 2023-02-08T20:36:00+01:00 add more offline caching by @froos in: [#421](https://codeberg.org/uzu/strudel/pulls/421)
+- 2023-02-07T22:08:01+01:00 add caching strategy for missing file types + cache all samples loaded from github by @froos in: [#419](https://codeberg.org/uzu/strudel/pulls/419)
+- 2023-02-06T23:29:57+01:00 PWA with offline support by @froos in: [#417](https://codeberg.org/uzu/strudel/pulls/417)
+- 2023-02-05T17:27:32+01:00 improve samples doc by @froos in: [#411](https://codeberg.org/uzu/strudel/pulls/411)
+- 2023-02-05T17:27:10+01:00 google gtfo by @froos in: [#413](https://codeberg.org/uzu/strudel/pulls/413)
+- 2023-02-05T16:27:59+01:00 improve effects doc by @froos in: [#409](https://codeberg.org/uzu/strudel/pulls/409)
+- 2023-02-05T14:56:03+01:00 Update effects.mdx by @Ghost in: [#410](https://codeberg.org/uzu/strudel/pulls/410)
+- 2023-02-03T19:54:47+01:00 add shabda doc by @froos in: [#407](https://codeberg.org/uzu/strudel/pulls/407)
+- 2023-02-02T21:45:56+01:00 fix: share url on subpath by @froos in: [#405](https://codeberg.org/uzu/strudel/pulls/405)
+- 2023-02-02T21:35:45+01:00 update csound + fix sound output by @froos in: [#404](https://codeberg.org/uzu/strudel/pulls/404)
+- 2023-02-02T19:53:36+01:00 pin @csound/browser to 6.18.3 + bump by @froos in: [#403](https://codeberg.org/uzu/strudel/pulls/403)
+- 2023-02-01T22:47:27+01:00 release webaudio by @froos in: [#400](https://codeberg.org/uzu/strudel/pulls/400)
+- 2023-02-01T22:45:16+01:00 can now await initAudio + initAudioOnFirstClick by @froos in: [#399](https://codeberg.org/uzu/strudel/pulls/399)
+- 2023-02-01T22:32:18+01:00 fix: minirepl styles by @froos in: [#398](https://codeberg.org/uzu/strudel/pulls/398)
+- 2023-02-01T22:17:19+01:00 proper builds + use pnpm workspaces by @froos in: [#396](https://codeberg.org/uzu/strudel/pulls/396)
+- 2023-02-01T16:49:55+01:00 add pattern methods hurry, press and pressBy by @yaxu in: [#397](https://codeberg.org/uzu/strudel/pulls/397)
## january 2023
-- 2023-01-27T14:40:40+01:00 Add tidal-drum-patterns to examples by Ghost in: [#379](https://codeberg.org/uzu/strudel/pulls/379)
-- 2023-01-27T14:39:56+01:00 add ribbon + test + docs by froos in: [#388](https://codeberg.org/uzu/strudel/pulls/388)
-- 2023-01-27T12:10:37+01:00 Notes are not essential :) by yaxu in: [#393](https://codeberg.org/uzu/strudel/pulls/393)
-- 2023-01-21T17:18:13+01:00 document csound by froos in: [#391](https://codeberg.org/uzu/strudel/pulls/391)
-- 2023-01-19T12:04:51+01:00 Rename a to angle by froos in: [#387](https://codeberg.org/uzu/strudel/pulls/387)
-- 2023-01-19T11:49:39+01:00 add run + test + docs by froos in: [#386](https://codeberg.org/uzu/strudel/pulls/386)
-- 2023-01-19T11:32:56+01:00 docs: use note instead of n to mitigate confusion by froos in: [#385](https://codeberg.org/uzu/strudel/pulls/385)
-- 2023-01-18T17:10:09+01:00 update my-patterns instructions by froos in: [#384](https://codeberg.org/uzu/strudel/pulls/384)
-- 2023-01-15T23:19:43+01:00 Draw fixes by froos in: [#377](https://codeberg.org/uzu/strudel/pulls/377)
-- 2023-01-14T11:07:08+01:00 improve new draw logic by froos in: [#372](https://codeberg.org/uzu/strudel/pulls/372)
-- 2023-01-12T14:40:59+01:00 document more functions + change arp join by froos in: [#369](https://codeberg.org/uzu/strudel/pulls/369)
-- 2023-01-10T00:03:47+01:00 add https to url by Ghost in: [#364](https://codeberg.org/uzu/strudel/pulls/364)
-- 2023-01-09T23:37:34+01:00 doc structuring by froos in: [#360](https://codeberg.org/uzu/strudel/pulls/360)
-- 2023-01-09T23:23:28+01:00 Support for multiple mininotation operators by yaxu in: [#350](https://codeberg.org/uzu/strudel/pulls/350)
-- 2023-01-09T00:40:15+01:00 Fix .out(), renaming webaudio's out() to webaudio() by yaxu in: [#361](https://codeberg.org/uzu/strudel/pulls/361)
-- 2023-01-06T22:02:31+01:00 docs: tidal comparison + add global fx + add missing sampler fx by froos in: [#356](https://codeberg.org/uzu/strudel/pulls/356)
-- 2023-01-06T12:31:32+01:00 Fix Bjorklund by yaxu in: [#343](https://codeberg.org/uzu/strudel/pulls/343)
-- 2023-01-04T20:29:35+01:00 Fix prebake base path by froos in: [#345](https://codeberg.org/uzu/strudel/pulls/345)
-- 2023-01-04T19:55:49+01:00 fixes #346 by froos in: [#347](https://codeberg.org/uzu/strudel/pulls/347)
-- 2023-01-02T21:28:07+01:00 Patternify euclid, fast, slow and polymeter step parameters in mininotation by yaxu in: [#341](https://codeberg.org/uzu/strudel/pulls/341)
-- 2023-01-02T00:30:16+01:00 more animate functions + mini repl fix by froos in: [#340](https://codeberg.org/uzu/strudel/pulls/340)
-- 2023-01-01T12:34:11+01:00 move /my-patterns to /swatch by yaxu in: [#338](https://codeberg.org/uzu/strudel/pulls/338)
-- 2023-01-01T12:22:55+01:00 animation options by froos in: [#337](https://codeberg.org/uzu/strudel/pulls/337)
+- 2023-01-27T14:40:40+01:00 Add tidal-drum-patterns to examples by @Ghost in: [#379](https://codeberg.org/uzu/strudel/pulls/379)
+- 2023-01-27T14:39:56+01:00 add ribbon + test + docs by @froos in: [#388](https://codeberg.org/uzu/strudel/pulls/388)
+- 2023-01-27T12:10:37+01:00 Notes are not essential :) by @yaxu in: [#393](https://codeberg.org/uzu/strudel/pulls/393)
+- 2023-01-21T17:18:13+01:00 document csound by @froos in: [#391](https://codeberg.org/uzu/strudel/pulls/391)
+- 2023-01-19T12:04:51+01:00 Rename a to angle by @froos in: [#387](https://codeberg.org/uzu/strudel/pulls/387)
+- 2023-01-19T11:49:39+01:00 add run + test + docs by @froos in: [#386](https://codeberg.org/uzu/strudel/pulls/386)
+- 2023-01-19T11:32:56+01:00 docs: use note instead of n to mitigate confusion by @froos in: [#385](https://codeberg.org/uzu/strudel/pulls/385)
+- 2023-01-18T17:10:09+01:00 update my-patterns instructions by @froos in: [#384](https://codeberg.org/uzu/strudel/pulls/384)
+- 2023-01-15T23:19:43+01:00 Draw fixes by @froos in: [#377](https://codeberg.org/uzu/strudel/pulls/377)
+- 2023-01-14T11:07:08+01:00 improve new draw logic by @froos in: [#372](https://codeberg.org/uzu/strudel/pulls/372)
+- 2023-01-12T14:40:59+01:00 document more functions + change arp join by @froos in: [#369](https://codeberg.org/uzu/strudel/pulls/369)
+- 2023-01-10T00:03:47+01:00 add https to url by @Ghost in: [#364](https://codeberg.org/uzu/strudel/pulls/364)
+- 2023-01-09T23:37:34+01:00 doc structuring by @froos in: [#360](https://codeberg.org/uzu/strudel/pulls/360)
+- 2023-01-09T23:23:28+01:00 Support for multiple mininotation operators by @yaxu in: [#350](https://codeberg.org/uzu/strudel/pulls/350)
+- 2023-01-09T00:40:15+01:00 Fix .out(), renaming webaudio's out() to webaudio() by @yaxu in: [#361](https://codeberg.org/uzu/strudel/pulls/361)
+- 2023-01-06T22:02:31+01:00 docs: tidal comparison + add global fx + add missing sampler fx by @froos in: [#356](https://codeberg.org/uzu/strudel/pulls/356)
+- 2023-01-06T12:31:32+01:00 Fix Bjorklund by @yaxu in: [#343](https://codeberg.org/uzu/strudel/pulls/343)
+- 2023-01-04T20:29:35+01:00 Fix prebake base path by @froos in: [#345](https://codeberg.org/uzu/strudel/pulls/345)
+- 2023-01-04T19:55:49+01:00 fixes #346 by @froos in: [#347](https://codeberg.org/uzu/strudel/pulls/347)
+- 2023-01-02T21:28:07+01:00 Patternify euclid, fast, slow and polymeter step parameters in mininotation by @yaxu in: [#341](https://codeberg.org/uzu/strudel/pulls/341)
+- 2023-01-02T00:30:16+01:00 more animate functions + mini repl fix by @froos in: [#340](https://codeberg.org/uzu/strudel/pulls/340)
+- 2023-01-01T12:34:11+01:00 move /my-patterns to /swatch by @yaxu in: [#338](https://codeberg.org/uzu/strudel/pulls/338)
+- 2023-01-01T12:22:55+01:00 animation options by @froos in: [#337](https://codeberg.org/uzu/strudel/pulls/337)
## december 2022
-- 2022-12-31T22:42:49+01:00 Tidy parser, implement polymeters by yaxu in: [#336](https://codeberg.org/uzu/strudel/pulls/336)
-- 2022-12-31T16:51:53+01:00 animate mvp by froos in: [#335](https://codeberg.org/uzu/strudel/pulls/335)
-- 2022-12-30T20:16:10+01:00 testing + docs docs by froos in: [#334](https://codeberg.org/uzu/strudel/pulls/334)
-- 2022-12-29T21:11:16+01:00 Embed mode improvements by froos in: [#333](https://codeberg.org/uzu/strudel/pulls/333)
-- 2022-12-29T14:06:20+01:00 fix: can now multiply floats in mini notation by froos in: [#332](https://codeberg.org/uzu/strudel/pulls/332)
-- 2022-12-29T13:50:07+01:00 improve displaying 's' in pianoroll by froos in: [#331](https://codeberg.org/uzu/strudel/pulls/331)
-- 2022-12-28T17:35:35+01:00 my-patterns: fix paths + update readme by froos in: [#330](https://codeberg.org/uzu/strudel/pulls/330)
-- 2022-12-28T17:11:40+01:00 my-patterns build + deploy by froos in: [#329](https://codeberg.org/uzu/strudel/pulls/329)
-- 2022-12-28T15:43:31+01:00 add my-patterns by froos in: [#328](https://codeberg.org/uzu/strudel/pulls/328)
-- 2022-12-28T14:47:14+01:00 add examples route by froos in: [#327](https://codeberg.org/uzu/strudel/pulls/327)
-- 2022-12-28T14:44:31+01:00 fix: workaround Object.assign globalThis by froos in: [#326](https://codeberg.org/uzu/strudel/pulls/326)
-- 2022-12-26T23:29:47+01:00 mini repl improvements by froos in: [#324](https://codeberg.org/uzu/strudel/pulls/324)
-- 2022-12-26T23:00:34+01:00 support notes without octave by froos in: [#323](https://codeberg.org/uzu/strudel/pulls/323)
-- 2022-12-26T12:37:36+01:00 tutorial updates by Ghost in: [#320](https://codeberg.org/uzu/strudel/pulls/320)
-- 2022-12-23T18:26:30+01:00 Reference tab sort by froos in: [#318](https://codeberg.org/uzu/strudel/pulls/318)
-- 2022-12-23T00:49:56+01:00 Astro build by froos in: [#315](https://codeberg.org/uzu/strudel/pulls/315)
-- 2022-12-19T21:02:37+01:00 object support for .scale by froos in: [#307](https://codeberg.org/uzu/strudel/pulls/307)
-- 2022-12-19T21:02:22+01:00 Jsdoc component by froos in: [#312](https://codeberg.org/uzu/strudel/pulls/312)
-- 2022-12-19T20:31:46+01:00 fix: copy share link to clipboard was broken for some browers by froos in: [#311](https://codeberg.org/uzu/strudel/pulls/311)
-- 2022-12-19T12:11:24+01:00 ICLC2023 paper WIP by yaxu in: [#306](https://codeberg.org/uzu/strudel/pulls/306)
-- 2022-12-15T21:23:22+01:00 support freq in pianoroll by froos in: [#308](https://codeberg.org/uzu/strudel/pulls/308)
-- 2022-12-13T22:07:27+01:00 Updated csoundm to use the register facility . by gogins in: [#303](https://codeberg.org/uzu/strudel/pulls/303)
-- 2022-12-13T21:57:03+01:00 add lint + prettier check before test by froos in: [#305](https://codeberg.org/uzu/strudel/pulls/305)
-- 2022-12-13T21:21:44+01:00 add freq support to sampler by froos in: [#301](https://codeberg.org/uzu/strudel/pulls/301)
-- 2022-12-12T00:48:41+01:00 fix whitespace trimming by froos in: [#300](https://codeberg.org/uzu/strudel/pulls/300)
-- 2022-12-12T00:21:53+01:00 .defragmentHaps() for merging touching haps that share a whole and value by yaxu in: [#299](https://codeberg.org/uzu/strudel/pulls/299)
-- 2022-12-11T23:17:49+01:00 remove whitespace from highlighted region by froos in: [#298](https://codeberg.org/uzu/strudel/pulls/298)
-- 2022-12-11T22:03:26+01:00 update vitest by froos in: [#297](https://codeberg.org/uzu/strudel/pulls/297)
-- 2022-12-11T21:44:16+01:00 can now add bare numbers to numeral object props by froos in: [#287](https://codeberg.org/uzu/strudel/pulls/287)
-- 2022-12-11T21:27:58+01:00 Move stuff to new register function by froos in: [#295](https://codeberg.org/uzu/strudel/pulls/295)
-- 2022-12-11T20:07:12+01:00 add prettier task by froos in: [#296](https://codeberg.org/uzu/strudel/pulls/296)
-- 2022-12-10T15:39:04+01:00 Reorganise pattern.mjs with a 'toplevel first' regime by yaxu in: [#286](https://codeberg.org/uzu/strudel/pulls/286)
-- 2022-12-10T11:56:16+01:00 Fancy hap show, include part in snapshots by yaxu in: [#291](https://codeberg.org/uzu/strudel/pulls/291)
-- 2022-12-07T20:07:55+01:00 Switch 'operators' from .whatHow to .what.how by yaxu in: [#285](https://codeberg.org/uzu/strudel/pulls/285)
-- 2022-12-04T12:51:01+01:00 implement collect + arp function by froos in: [#281](https://codeberg.org/uzu/strudel/pulls/281)
-- 2022-12-02T13:38:27+01:00 do not recompile orc by froos in: [#278](https://codeberg.org/uzu/strudel/pulls/278)
-- 2022-12-02T12:49:26+01:00 add basic csound output by froos in: [#275](https://codeberg.org/uzu/strudel/pulls/275)
-- 2022-12-02T12:18:41+01:00 add licenses / credits to all tunes + remove some by froos in: [#277](https://codeberg.org/uzu/strudel/pulls/277)
-- 2022-12-02T11:45:02+01:00 Support sending CRC16 bytes with serial messages by yaxu in: [#276](https://codeberg.org/uzu/strudel/pulls/276)
+- 2022-12-31T22:42:49+01:00 Tidy parser, implement polymeters by @yaxu in: [#336](https://codeberg.org/uzu/strudel/pulls/336)
+- 2022-12-31T16:51:53+01:00 animate mvp by @froos in: [#335](https://codeberg.org/uzu/strudel/pulls/335)
+- 2022-12-30T20:16:10+01:00 testing + docs docs by @froos in: [#334](https://codeberg.org/uzu/strudel/pulls/334)
+- 2022-12-29T21:11:16+01:00 Embed mode improvements by @froos in: [#333](https://codeberg.org/uzu/strudel/pulls/333)
+- 2022-12-29T14:06:20+01:00 fix: can now multiply floats in mini notation by @froos in: [#332](https://codeberg.org/uzu/strudel/pulls/332)
+- 2022-12-29T13:50:07+01:00 improve displaying 's' in pianoroll by @froos in: [#331](https://codeberg.org/uzu/strudel/pulls/331)
+- 2022-12-28T17:35:35+01:00 my-patterns: fix paths + update readme by @froos in: [#330](https://codeberg.org/uzu/strudel/pulls/330)
+- 2022-12-28T17:11:40+01:00 my-patterns build + deploy by @froos in: [#329](https://codeberg.org/uzu/strudel/pulls/329)
+- 2022-12-28T15:43:31+01:00 add my-patterns by @froos in: [#328](https://codeberg.org/uzu/strudel/pulls/328)
+- 2022-12-28T14:47:14+01:00 add examples route by @froos in: [#327](https://codeberg.org/uzu/strudel/pulls/327)
+- 2022-12-28T14:44:31+01:00 fix: workaround Object.assign globalThis by @froos in: [#326](https://codeberg.org/uzu/strudel/pulls/326)
+- 2022-12-26T23:29:47+01:00 mini repl improvements by @froos in: [#324](https://codeberg.org/uzu/strudel/pulls/324)
+- 2022-12-26T23:00:34+01:00 support notes without octave by @froos in: [#323](https://codeberg.org/uzu/strudel/pulls/323)
+- 2022-12-26T12:37:36+01:00 tutorial updates by @Ghost in: [#320](https://codeberg.org/uzu/strudel/pulls/320)
+- 2022-12-23T18:26:30+01:00 Reference tab sort by @froos in: [#318](https://codeberg.org/uzu/strudel/pulls/318)
+- 2022-12-23T00:49:56+01:00 Astro build by @froos in: [#315](https://codeberg.org/uzu/strudel/pulls/315)
+- 2022-12-19T21:02:37+01:00 object support for .scale by @froos in: [#307](https://codeberg.org/uzu/strudel/pulls/307)
+- 2022-12-19T21:02:22+01:00 Jsdoc component by @froos in: [#312](https://codeberg.org/uzu/strudel/pulls/312)
+- 2022-12-19T20:31:46+01:00 fix: copy share link to clipboard was broken for some browers by @froos in: [#311](https://codeberg.org/uzu/strudel/pulls/311)
+- 2022-12-19T12:11:24+01:00 ICLC2023 paper WIP by @yaxu in: [#306](https://codeberg.org/uzu/strudel/pulls/306)
+- 2022-12-15T21:23:22+01:00 support freq in pianoroll by @froos in: [#308](https://codeberg.org/uzu/strudel/pulls/308)
+- 2022-12-13T22:07:27+01:00 Updated csoundm to use the register facility . by @gogins in: [#303](https://codeberg.org/uzu/strudel/pulls/303)
+- 2022-12-13T21:57:03+01:00 add lint + prettier check before test by @froos in: [#305](https://codeberg.org/uzu/strudel/pulls/305)
+- 2022-12-13T21:21:44+01:00 add freq support to sampler by @froos in: [#301](https://codeberg.org/uzu/strudel/pulls/301)
+- 2022-12-12T00:48:41+01:00 fix whitespace trimming by @froos in: [#300](https://codeberg.org/uzu/strudel/pulls/300)
+- 2022-12-12T00:21:53+01:00 .defragmentHaps() for merging touching haps that share a whole and value by @yaxu in: [#299](https://codeberg.org/uzu/strudel/pulls/299)
+- 2022-12-11T23:17:49+01:00 remove whitespace from highlighted region by @froos in: [#298](https://codeberg.org/uzu/strudel/pulls/298)
+- 2022-12-11T22:03:26+01:00 update vitest by @froos in: [#297](https://codeberg.org/uzu/strudel/pulls/297)
+- 2022-12-11T21:44:16+01:00 can now add bare numbers to numeral object props by @froos in: [#287](https://codeberg.org/uzu/strudel/pulls/287)
+- 2022-12-11T21:27:58+01:00 Move stuff to new register function by @froos in: [#295](https://codeberg.org/uzu/strudel/pulls/295)
+- 2022-12-11T20:07:12+01:00 add prettier task by @froos in: [#296](https://codeberg.org/uzu/strudel/pulls/296)
+- 2022-12-10T15:39:04+01:00 Reorganise pattern.mjs with a 'toplevel first' regime by @yaxu in: [#286](https://codeberg.org/uzu/strudel/pulls/286)
+- 2022-12-10T11:56:16+01:00 Fancy hap show, include part in snapshots by @yaxu in: [#291](https://codeberg.org/uzu/strudel/pulls/291)
+- 2022-12-07T20:07:55+01:00 Switch 'operators' from .whatHow to .what.how by @yaxu in: [#285](https://codeberg.org/uzu/strudel/pulls/285)
+- 2022-12-04T12:51:01+01:00 implement collect + arp function by @froos in: [#281](https://codeberg.org/uzu/strudel/pulls/281)
+- 2022-12-02T13:38:27+01:00 do not recompile orc by @froos in: [#278](https://codeberg.org/uzu/strudel/pulls/278)
+- 2022-12-02T12:49:26+01:00 add basic csound output by @froos in: [#275](https://codeberg.org/uzu/strudel/pulls/275)
+- 2022-12-02T12:18:41+01:00 add licenses / credits to all tunes + remove some by @froos in: [#277](https://codeberg.org/uzu/strudel/pulls/277)
+- 2022-12-02T11:45:02+01:00 Support sending CRC16 bytes with serial messages by @yaxu in: [#276](https://codeberg.org/uzu/strudel/pulls/276)
## november 2022
-- 2022-11-29T23:41:39+01:00 release version bumps by froos in: [#273](https://codeberg.org/uzu/strudel/pulls/273)
-- 2022-11-29T23:34:50+01:00 add eslint by froos in: [#271](https://codeberg.org/uzu/strudel/pulls/271)
-- 2022-11-29T23:34:26+01:00 tonal update with fixed memory leak by froos in: [#272](https://codeberg.org/uzu/strudel/pulls/272)
-- 2022-11-22T09:51:26+01:00 Tidying up core by yaxu in: [#256](https://codeberg.org/uzu/strudel/pulls/256)
-- 2022-11-21T22:15:48+01:00 fix performance bottleneck by froos in: [#266](https://codeberg.org/uzu/strudel/pulls/266)
-- 2022-11-17T11:08:38+01:00 fix tutorial bugs by froos in: [#263](https://codeberg.org/uzu/strudel/pulls/263)
-- 2022-11-16T13:15:28+01:00 Binaries by froos in: [#254](https://codeberg.org/uzu/strudel/pulls/254)
-- 2022-11-13T20:20:32+01:00 Repl refactoring by froos in: [#255](https://codeberg.org/uzu/strudel/pulls/255)
-- 2022-11-08T23:35:11+01:00 Webaudio build by froos in: [#250](https://codeberg.org/uzu/strudel/pulls/250)
-- 2022-11-08T22:43:32+01:00 new transpiler based on acorn by froos in: [#249](https://codeberg.org/uzu/strudel/pulls/249)
-- 2022-11-06T19:03:19+01:00 General purpose scheduler by froos in: [#248](https://codeberg.org/uzu/strudel/pulls/248)
-- 2022-11-06T11:05:23+01:00 snapshot tests on shared snippets by froos in: [#243](https://codeberg.org/uzu/strudel/pulls/243)
-- 2022-11-06T11:03:42+01:00 Some tunes by froos in: [#247](https://codeberg.org/uzu/strudel/pulls/247)
-- 2022-11-06T00:37:11+01:00 patchday by froos in: [#246](https://codeberg.org/uzu/strudel/pulls/246)
-- 2022-11-04T20:28:23+01:00 Readme + TLC by froos in: [#244](https://codeberg.org/uzu/strudel/pulls/244)
-- 2022-11-03T15:16:04+01:00 in source example tests by froos in: [#242](https://codeberg.org/uzu/strudel/pulls/242)
-- 2022-11-02T23:16:43+01:00 feat: support github: links by froos in: [#240](https://codeberg.org/uzu/strudel/pulls/240)
-- 2022-11-02T21:26:44+01:00 Load samples from url by froos in: [#239](https://codeberg.org/uzu/strudel/pulls/239)
-- 2022-11-02T11:42:32+01:00 Object arithmetic by froos in: [#238](https://codeberg.org/uzu/strudel/pulls/238)
-- 2022-11-01T00:36:14+01:00 Tidal drum machines by froos in: [#237](https://codeberg.org/uzu/strudel/pulls/237)
-- 2022-10-31T21:39:23+01:00 fx on stereo speakers by froos in: [#236](https://codeberg.org/uzu/strudel/pulls/236)
+- 2022-11-29T23:41:39+01:00 release version bumps by @froos in: [#273](https://codeberg.org/uzu/strudel/pulls/273)
+- 2022-11-29T23:34:50+01:00 add eslint by @froos in: [#271](https://codeberg.org/uzu/strudel/pulls/271)
+- 2022-11-29T23:34:26+01:00 tonal update with fixed memory leak by @froos in: [#272](https://codeberg.org/uzu/strudel/pulls/272)
+- 2022-11-22T09:51:26+01:00 Tidying up core by @yaxu in: [#256](https://codeberg.org/uzu/strudel/pulls/256)
+- 2022-11-21T22:15:48+01:00 fix performance bottleneck by @froos in: [#266](https://codeberg.org/uzu/strudel/pulls/266)
+- 2022-11-17T11:08:38+01:00 fix tutorial bugs by @froos in: [#263](https://codeberg.org/uzu/strudel/pulls/263)
+- 2022-11-16T13:15:28+01:00 Binaries by @froos in: [#254](https://codeberg.org/uzu/strudel/pulls/254)
+- 2022-11-13T20:20:32+01:00 Repl refactoring by @froos in: [#255](https://codeberg.org/uzu/strudel/pulls/255)
+- 2022-11-08T23:35:11+01:00 Webaudio build by @froos in: [#250](https://codeberg.org/uzu/strudel/pulls/250)
+- 2022-11-08T22:43:32+01:00 new transpiler based on acorn by @froos in: [#249](https://codeberg.org/uzu/strudel/pulls/249)
+- 2022-11-06T19:03:19+01:00 General purpose scheduler by @froos in: [#248](https://codeberg.org/uzu/strudel/pulls/248)
+- 2022-11-06T11:05:23+01:00 snapshot tests on shared snippets by @froos in: [#243](https://codeberg.org/uzu/strudel/pulls/243)
+- 2022-11-06T11:03:42+01:00 Some tunes by @froos in: [#247](https://codeberg.org/uzu/strudel/pulls/247)
+- 2022-11-06T00:37:11+01:00 patchday by @froos in: [#246](https://codeberg.org/uzu/strudel/pulls/246)
+- 2022-11-04T20:28:23+01:00 Readme + TLC by @froos in: [#244](https://codeberg.org/uzu/strudel/pulls/244)
+- 2022-11-03T15:16:04+01:00 in source example tests by @froos in: [#242](https://codeberg.org/uzu/strudel/pulls/242)
+- 2022-11-02T23:16:43+01:00 feat: support github: links by @froos in: [#240](https://codeberg.org/uzu/strudel/pulls/240)
+- 2022-11-02T21:26:44+01:00 Load samples from url by @froos in: [#239](https://codeberg.org/uzu/strudel/pulls/239)
+- 2022-11-02T11:42:32+01:00 Object arithmetic by @froos in: [#238](https://codeberg.org/uzu/strudel/pulls/238)
+- 2022-11-01T00:36:14+01:00 Tidal drum machines by @froos in: [#237](https://codeberg.org/uzu/strudel/pulls/237)
+- 2022-10-31T21:39:23+01:00 fx on stereo speakers by @froos in: [#236](https://codeberg.org/uzu/strudel/pulls/236)
## october 2022
-- 2022-10-30T19:10:33+01:00 add vcsl sample library by froos in: [#235](https://codeberg.org/uzu/strudel/pulls/235)
-- 2022-10-30T00:23:10+02:00 Fix zero length queries WIP by yaxu in: [#234](https://codeberg.org/uzu/strudel/pulls/234)
-- 2022-10-29T17:54:05+02:00 Out by default by froos in: [#232](https://codeberg.org/uzu/strudel/pulls/232)
-- 2022-10-26T23:53:49+02:00 Patternify range by yaxu in: [#231](https://codeberg.org/uzu/strudel/pulls/231)
-- 2022-10-26T21:42:12+02:00 Just another docs branch by froos in: [#228](https://codeberg.org/uzu/strudel/pulls/228)
-- 2022-10-26T21:41:12+02:00 Refactor tunes away from tone by froos in: [#230](https://codeberg.org/uzu/strudel/pulls/230)
-- 2022-10-20T09:26:28+02:00 Core util tests by Ghost in: [#226](https://codeberg.org/uzu/strudel/pulls/226)
-- 2022-10-06T22:35:45+02:00 fix fastgap for events that go across cycle boundaries by yaxu in: [#225](https://codeberg.org/uzu/strudel/pulls/225)
+- 2022-10-30T19:10:33+01:00 add vcsl sample library by @froos in: [#235](https://codeberg.org/uzu/strudel/pulls/235)
+- 2022-10-30T00:23:10+02:00 Fix zero length queries WIP by @yaxu in: [#234](https://codeberg.org/uzu/strudel/pulls/234)
+- 2022-10-29T17:54:05+02:00 Out by default by @froos in: [#232](https://codeberg.org/uzu/strudel/pulls/232)
+- 2022-10-26T23:53:49+02:00 Patternify range by @yaxu in: [#231](https://codeberg.org/uzu/strudel/pulls/231)
+- 2022-10-26T21:42:12+02:00 Just another docs branch by @froos in: [#228](https://codeberg.org/uzu/strudel/pulls/228)
+- 2022-10-26T21:41:12+02:00 Refactor tunes away from tone by @froos in: [#230](https://codeberg.org/uzu/strudel/pulls/230)
+- 2022-10-20T09:26:28+02:00 Core util tests by @Ghost in: [#226](https://codeberg.org/uzu/strudel/pulls/226)
+- 2022-10-06T22:35:45+02:00 fix fastgap for events that go across cycle boundaries by @yaxu in: [#225](https://codeberg.org/uzu/strudel/pulls/225)
## september 2022
-- 2022-09-25T21:15:36+02:00 Reverb by froos in: [#224](https://codeberg.org/uzu/strudel/pulls/224)
-- 2022-09-25T00:27:26+02:00 focus tweak for squeezeJoin - another go at fixing #216 by yaxu in: [#221](https://codeberg.org/uzu/strudel/pulls/221)
-- 2022-09-24T23:17:21+02:00 support negative speeds by froos in: [#222](https://codeberg.org/uzu/strudel/pulls/222)
-- 2022-09-24T21:55:15+02:00 Feedback Delay by froos in: [#213](https://codeberg.org/uzu/strudel/pulls/213)
-- 2022-09-23T12:06:17+02:00 Fix squeeze join by yaxu in: [#220](https://codeberg.org/uzu/strudel/pulls/220)
-- 2022-09-22T21:23:11+02:00 encapsulate webaudio output by froos in: [#219](https://codeberg.org/uzu/strudel/pulls/219)
-- 2022-09-22T19:18:18+02:00 samples now have envelopes by froos in: [#218](https://codeberg.org/uzu/strudel/pulls/218)
-- 2022-09-22T00:03:30+02:00 sampler features + fixes by froos in: [#217](https://codeberg.org/uzu/strudel/pulls/217)
-- 2022-09-19T23:32:55+02:00 Just another docs PR by froos in: [#215](https://codeberg.org/uzu/strudel/pulls/215)
-- 2022-09-17T23:47:43+02:00 Even more docs by froos in: [#212](https://codeberg.org/uzu/strudel/pulls/212)
-- 2022-09-17T15:36:53+02:00 Webaudio guide by froos in: [#207](https://codeberg.org/uzu/strudel/pulls/207)
-- 2022-09-16T00:21:29+02:00 Coarse crush shape by froos in: [#205](https://codeberg.org/uzu/strudel/pulls/205)
-- 2022-09-15T21:04:28+02:00 add vowel to .out by froos in: [#201](https://codeberg.org/uzu/strudel/pulls/201)
-- 2022-09-15T16:55:52+02:00 add rollup-plugin-visualizer to build by froos in: [#200](https://codeberg.org/uzu/strudel/pulls/200)
-- 2022-09-14T23:46:39+02:00 document random functions by froos in: [#199](https://codeberg.org/uzu/strudel/pulls/199)
-- 2022-09-09T22:04:40+02:00 Fix numbers in sampler by froos in: [#196](https://codeberg.org/uzu/strudel/pulls/196)
+- 2022-09-25T21:15:36+02:00 Reverb by @froos in: [#224](https://codeberg.org/uzu/strudel/pulls/224)
+- 2022-09-25T00:27:26+02:00 focus tweak for squeezeJoin - another go at fixing #216 by @yaxu in: [#221](https://codeberg.org/uzu/strudel/pulls/221)
+- 2022-09-24T23:17:21+02:00 support negative speeds by @froos in: [#222](https://codeberg.org/uzu/strudel/pulls/222)
+- 2022-09-24T21:55:15+02:00 Feedback Delay by @froos in: [#213](https://codeberg.org/uzu/strudel/pulls/213)
+- 2022-09-23T12:06:17+02:00 Fix squeeze join by @yaxu in: [#220](https://codeberg.org/uzu/strudel/pulls/220)
+- 2022-09-22T21:23:11+02:00 encapsulate webaudio output by @froos in: [#219](https://codeberg.org/uzu/strudel/pulls/219)
+- 2022-09-22T19:18:18+02:00 samples now have envelopes by @froos in: [#218](https://codeberg.org/uzu/strudel/pulls/218)
+- 2022-09-22T00:03:30+02:00 sampler features + fixes by @froos in: [#217](https://codeberg.org/uzu/strudel/pulls/217)
+- 2022-09-19T23:32:55+02:00 Just another docs PR by @froos in: [#215](https://codeberg.org/uzu/strudel/pulls/215)
+- 2022-09-17T23:47:43+02:00 Even more docs by @froos in: [#212](https://codeberg.org/uzu/strudel/pulls/212)
+- 2022-09-17T15:36:53+02:00 Webaudio guide by @froos in: [#207](https://codeberg.org/uzu/strudel/pulls/207)
+- 2022-09-16T00:21:29+02:00 Coarse crush shape by @froos in: [#205](https://codeberg.org/uzu/strudel/pulls/205)
+- 2022-09-15T21:04:28+02:00 add vowel to .out by @froos in: [#201](https://codeberg.org/uzu/strudel/pulls/201)
+- 2022-09-15T16:55:52+02:00 add rollup-plugin-visualizer to build by @froos in: [#200](https://codeberg.org/uzu/strudel/pulls/200)
+- 2022-09-14T23:46:39+02:00 document random functions by @froos in: [#199](https://codeberg.org/uzu/strudel/pulls/199)
+- 2022-09-09T22:04:40+02:00 Fix numbers in sampler by @froos in: [#196](https://codeberg.org/uzu/strudel/pulls/196)
## august 2022
-- 2022-08-14T17:40:41+02:00 change "stride"/"offset" of successive degradeBy/chooseIn by Ghost in: [#185](https://codeberg.org/uzu/strudel/pulls/185)
-- 2022-08-14T16:04:14+02:00 Soundfont file support by froos in: [#183](https://codeberg.org/uzu/strudel/pulls/183)
-- 2022-08-14T15:55:50+02:00 fix regression: old way of setting frequencies was broken by froos in: [#190](https://codeberg.org/uzu/strudel/pulls/190)
-- 2022-08-14T15:45:53+02:00 wait for prebake to finish before evaluating by froos in: [#189](https://codeberg.org/uzu/strudel/pulls/189)
-- 2022-08-14T11:31:00+02:00 Fix codemirror bug by froos in: [#186](https://codeberg.org/uzu/strudel/pulls/186)
-- 2022-08-13T16:29:53+02:00 scheduler improvements by froos in: [#181](https://codeberg.org/uzu/strudel/pulls/181)
-- 2022-08-12T23:10:36+02:00 replace mocha with vitest by froos in: [#175](https://codeberg.org/uzu/strudel/pulls/175)
-- 2022-08-07T00:59:07+02:00 incorporate elements of randomness to the mini notation by Ghost in: [#165](https://codeberg.org/uzu/strudel/pulls/165)
-- 2022-08-06T23:32:16+02:00 fix some annoying bugs by froos in: [#177](https://codeberg.org/uzu/strudel/pulls/177)
-- 2022-08-06T00:27:17+02:00 Replace react-codemirror6 with @uiw/react-codemirror by froos in: [#173](https://codeberg.org/uzu/strudel/pulls/173)
-- 2022-08-04T22:19:46+02:00 add more shapeshifter flags by froos in: [#99](https://codeberg.org/uzu/strudel/pulls/99)
-- 2022-08-04T22:06:38+02:00 Amend shapeshifter to allow use of dynamic import by Ghost in: [#171](https://codeberg.org/uzu/strudel/pulls/171)
-- 2022-08-02T23:43:07+02:00 Talk fixes by froos in: [#164](https://codeberg.org/uzu/strudel/pulls/164)
-- 2022-08-02T23:04:34+02:00 Pianoroll fixes by froos in: [#163](https://codeberg.org/uzu/strudel/pulls/163)
-- 2022-08-02T22:57:43+02:00 fix: jsdoc comments by froos in: [#169](https://codeberg.org/uzu/strudel/pulls/169)
+- 2022-08-14T17:40:41+02:00 change "stride"/"offset" of successive degradeBy/chooseIn by @Ghost in: [#185](https://codeberg.org/uzu/strudel/pulls/185)
+- 2022-08-14T16:04:14+02:00 Soundfont file support by @froos in: [#183](https://codeberg.org/uzu/strudel/pulls/183)
+- 2022-08-14T15:55:50+02:00 fix regression: old way of setting frequencies was broken by @froos in: [#190](https://codeberg.org/uzu/strudel/pulls/190)
+- 2022-08-14T15:45:53+02:00 wait for prebake to finish before evaluating by @froos in: [#189](https://codeberg.org/uzu/strudel/pulls/189)
+- 2022-08-14T11:31:00+02:00 Fix codemirror bug by @froos in: [#186](https://codeberg.org/uzu/strudel/pulls/186)
+- 2022-08-13T16:29:53+02:00 scheduler improvements by @froos in: [#181](https://codeberg.org/uzu/strudel/pulls/181)
+- 2022-08-12T23:10:36+02:00 replace mocha with vitest by @froos in: [#175](https://codeberg.org/uzu/strudel/pulls/175)
+- 2022-08-07T00:59:07+02:00 incorporate elements of randomness to the mini notation by @Ghost in: [#165](https://codeberg.org/uzu/strudel/pulls/165)
+- 2022-08-06T23:32:16+02:00 fix some annoying bugs by @froos in: [#177](https://codeberg.org/uzu/strudel/pulls/177)
+- 2022-08-06T00:27:17+02:00 Replace react-codemirror6 with @uiw/react-codemirror by @froos in: [#173](https://codeberg.org/uzu/strudel/pulls/173)
+- 2022-08-04T22:19:46+02:00 add more shapeshifter flags by @froos in: [#99](https://codeberg.org/uzu/strudel/pulls/99)
+- 2022-08-04T22:06:38+02:00 Amend shapeshifter to allow use of dynamic import by @Ghost in: [#171](https://codeberg.org/uzu/strudel/pulls/171)
+- 2022-08-02T23:43:07+02:00 Talk fixes by @froos in: [#164](https://codeberg.org/uzu/strudel/pulls/164)
+- 2022-08-02T23:04:34+02:00 Pianoroll fixes by @froos in: [#163](https://codeberg.org/uzu/strudel/pulls/163)
+- 2022-08-02T22:57:43+02:00 fix: jsdoc comments by @froos in: [#169](https://codeberg.org/uzu/strudel/pulls/169)
## july 2022
-- 2022-07-30T23:51:11+02:00 add chooseInWith/chooseCycles by yaxu in: [#166](https://codeberg.org/uzu/strudel/pulls/166)
-- 2022-07-28T19:26:42+02:00 update to tutorial documentation by Ghost in: [#162](https://codeberg.org/uzu/strudel/pulls/162)
-- 2022-07-12T18:58:47+02:00 add webdirt drum samples to prebake for general availability by Ghost in: [#150](https://codeberg.org/uzu/strudel/pulls/150)
-- 2022-07-12T08:34:17+02:00 Final update to demo.pdf by yaxu in: [#151](https://codeberg.org/uzu/strudel/pulls/151)
+- 2022-07-30T23:51:11+02:00 add chooseInWith/chooseCycles by @yaxu in: [#166](https://codeberg.org/uzu/strudel/pulls/166)
+- 2022-07-28T19:26:42+02:00 update to tutorial documentation by @Ghost in: [#162](https://codeberg.org/uzu/strudel/pulls/162)
+- 2022-07-12T18:58:47+02:00 add webdirt drum samples to prebake for general availability by @Ghost in: [#150](https://codeberg.org/uzu/strudel/pulls/150)
+- 2022-07-12T08:34:17+02:00 Final update to demo.pdf by @yaxu in: [#151](https://codeberg.org/uzu/strudel/pulls/151)
## june 2022
-- 2022-06-28T21:54:35+02:00 Sampler optimizations and more by froos in: [#148](https://codeberg.org/uzu/strudel/pulls/148)
-- 2022-06-26T12:58:53+02:00 can now generate short link for sharing by froos in: [#146](https://codeberg.org/uzu/strudel/pulls/146)
-- 2022-06-24T22:16:04+02:00 flash effect on ctrl enter by froos in: [#144](https://codeberg.org/uzu/strudel/pulls/144)
-- 2022-06-22T20:18:17+02:00 Pianoroll Object Support by froos in: [#142](https://codeberg.org/uzu/strudel/pulls/142)
-- 2022-06-21T22:57:28+02:00 Serial twiddles by yaxu in: [#141](https://codeberg.org/uzu/strudel/pulls/141)
-- 2022-06-21T22:20:05+02:00 Soundfont Support by froos in: [#139](https://codeberg.org/uzu/strudel/pulls/139)
-- 2022-06-21T14:11:50+02:00 Fix createParam() by yaxu in: [#140](https://codeberg.org/uzu/strudel/pulls/140)
-- 2022-06-18T23:24:42+02:00 Webaudio rewrite by froos in: [#138](https://codeberg.org/uzu/strudel/pulls/138)
-- 2022-06-16T21:58:38+02:00 add onTrigger helper by froos in: [#136](https://codeberg.org/uzu/strudel/pulls/136)
-- 2022-06-16T20:48:23+02:00 Scheduler improvements by froos in: [#134](https://codeberg.org/uzu/strudel/pulls/134)
-- 2022-06-16T20:48:07+02:00 remove cycle + delta from onTrigger by froos in: [#135](https://codeberg.org/uzu/strudel/pulls/135)
-- 2022-06-13T21:28:27+02:00 add createParam + createParams by froos in: [#110](https://codeberg.org/uzu/strudel/pulls/110)
-- 2022-06-13T21:27:09+02:00 Pianoroll enhancements by froos in: [#131](https://codeberg.org/uzu/strudel/pulls/131)
-- 2022-06-05T13:06:03+02:00 Fix link to contributing to tutorial docs by Ghost in: [#129](https://codeberg.org/uzu/strudel/pulls/129)
-- 2022-06-02T00:20:45+02:00 Webdirt by froos in: [#121](https://codeberg.org/uzu/strudel/pulls/121)
-- 2022-06-01T23:56:04+02:00 fix: #122 ctrl enter would add newline by froos in: [#124](https://codeberg.org/uzu/strudel/pulls/124)
-- 2022-06-01T18:21:56+02:00 fix: #108 by froos in: [#123](https://codeberg.org/uzu/strudel/pulls/123)
+- 2022-06-28T21:54:35+02:00 Sampler optimizations and more by @froos in: [#148](https://codeberg.org/uzu/strudel/pulls/148)
+- 2022-06-26T12:58:53+02:00 can now generate short link for sharing by @froos in: [#146](https://codeberg.org/uzu/strudel/pulls/146)
+- 2022-06-24T22:16:04+02:00 flash effect on ctrl enter by @froos in: [#144](https://codeberg.org/uzu/strudel/pulls/144)
+- 2022-06-22T20:18:17+02:00 Pianoroll Object Support by @froos in: [#142](https://codeberg.org/uzu/strudel/pulls/142)
+- 2022-06-21T22:57:28+02:00 Serial twiddles by @yaxu in: [#141](https://codeberg.org/uzu/strudel/pulls/141)
+- 2022-06-21T22:20:05+02:00 Soundfont Support by @froos in: [#139](https://codeberg.org/uzu/strudel/pulls/139)
+- 2022-06-21T14:11:50+02:00 Fix createParam() by @yaxu in: [#140](https://codeberg.org/uzu/strudel/pulls/140)
+- 2022-06-18T23:24:42+02:00 Webaudio rewrite by @froos in: [#138](https://codeberg.org/uzu/strudel/pulls/138)
+- 2022-06-16T21:58:38+02:00 add onTrigger helper by @froos in: [#136](https://codeberg.org/uzu/strudel/pulls/136)
+- 2022-06-16T20:48:23+02:00 Scheduler improvements by @froos in: [#134](https://codeberg.org/uzu/strudel/pulls/134)
+- 2022-06-16T20:48:07+02:00 remove cycle + delta from onTrigger by @froos in: [#135](https://codeberg.org/uzu/strudel/pulls/135)
+- 2022-06-13T21:28:27+02:00 add createParam + createParams by @froos in: [#110](https://codeberg.org/uzu/strudel/pulls/110)
+- 2022-06-13T21:27:09+02:00 Pianoroll enhancements by @froos in: [#131](https://codeberg.org/uzu/strudel/pulls/131)
+- 2022-06-05T13:06:03+02:00 Fix link to contributing to tutorial docs by @Ghost in: [#129](https://codeberg.org/uzu/strudel/pulls/129)
+- 2022-06-02T00:20:45+02:00 Webdirt by @froos in: [#121](https://codeberg.org/uzu/strudel/pulls/121)
+- 2022-06-01T23:56:04+02:00 fix: #122 ctrl enter would add newline by @froos in: [#124](https://codeberg.org/uzu/strudel/pulls/124)
+- 2022-06-01T18:21:56+02:00 fix: #108 by @froos in: [#123](https://codeberg.org/uzu/strudel/pulls/123)
## may 2022
-- 2022-05-29T09:54:59+02:00 In source doc by froos in: [#117](https://codeberg.org/uzu/strudel/pulls/117)
-- 2022-05-20T11:49:10+02:00 react package + vite build by froos in: [#116](https://codeberg.org/uzu/strudel/pulls/116)
-- 2022-05-15T22:29:26+02:00 Osc timing improvements by yaxu in: [#113](https://codeberg.org/uzu/strudel/pulls/113)
-- 2022-05-15T22:28:24+02:00 loopAt by yaxu in: [#114](https://codeberg.org/uzu/strudel/pulls/114)
-- 2022-05-09T20:09:47+02:00 `.brak()`, `.inside()` and `.outside()` by yaxu in: [#112](https://codeberg.org/uzu/strudel/pulls/112)
-- 2022-05-06T15:18:41+02:00 In source doc by yaxu in: [#105](https://codeberg.org/uzu/strudel/pulls/105)
-- 2022-05-04T22:59:31+02:00 Embed style by froos in: [#109](https://codeberg.org/uzu/strudel/pulls/109)
-- 2022-05-03T01:40:22+02:00 Reset, Restart and other composers by froos in: [#88](https://codeberg.org/uzu/strudel/pulls/88)
-- 2022-05-02T22:47:21+02:00 /embed package: web component for repl by froos in: [#106](https://codeberg.org/uzu/strudel/pulls/106)
-- 2022-05-02T22:05:34+02:00 Tune tests by froos in: [#104](https://codeberg.org/uzu/strudel/pulls/104)
-- 2022-05-01T14:33:11+02:00 Codemirror 6 by froos in: [#97](https://codeberg.org/uzu/strudel/pulls/97)
+- 2022-05-29T09:54:59+02:00 In source doc by @froos in: [#117](https://codeberg.org/uzu/strudel/pulls/117)
+- 2022-05-20T11:49:10+02:00 react package + vite build by @froos in: [#116](https://codeberg.org/uzu/strudel/pulls/116)
+- 2022-05-15T22:29:26+02:00 Osc timing improvements by @yaxu in: [#113](https://codeberg.org/uzu/strudel/pulls/113)
+- 2022-05-15T22:28:24+02:00 loopAt by @yaxu in: [#114](https://codeberg.org/uzu/strudel/pulls/114)
+- 2022-05-09T20:09:47+02:00 `.brak()`, `.inside()` and `.outside()` by @yaxu in: [#112](https://codeberg.org/uzu/strudel/pulls/112)
+- 2022-05-06T15:18:41+02:00 In source doc by @yaxu in: [#105](https://codeberg.org/uzu/strudel/pulls/105)
+- 2022-05-04T22:59:31+02:00 Embed style by @froos in: [#109](https://codeberg.org/uzu/strudel/pulls/109)
+- 2022-05-03T01:40:22+02:00 Reset, Restart and other composers by @froos in: [#88](https://codeberg.org/uzu/strudel/pulls/88)
+- 2022-05-02T22:47:21+02:00 /embed package: web component for repl by @froos in: [#106](https://codeberg.org/uzu/strudel/pulls/106)
+- 2022-05-02T22:05:34+02:00 Tune tests by @froos in: [#104](https://codeberg.org/uzu/strudel/pulls/104)
+- 2022-05-01T14:33:11+02:00 Codemirror 6 by @froos in: [#97](https://codeberg.org/uzu/strudel/pulls/97)
## april 2022
-- 2022-04-28T23:45:53+02:00 Work on Codemirror 6 highlighting by Ghost in: [#102](https://codeberg.org/uzu/strudel/pulls/102)
-- 2022-04-28T15:46:06+02:00 Change to Affero GPL by yaxu in: [#101](https://codeberg.org/uzu/strudel/pulls/101)
-- 2022-04-26T00:13:07+02:00 Paper by froos in: [#98](https://codeberg.org/uzu/strudel/pulls/98)
-- 2022-04-25T22:10:21+02:00 Fiddles with cat/stack by yaxu in: [#90](https://codeberg.org/uzu/strudel/pulls/90)
-- 2022-04-22T13:08:11+02:00 Add pattern composers, implements #82 by yaxu in: [#83](https://codeberg.org/uzu/strudel/pulls/83)
-- 2022-04-21T20:57:45+02:00 Tidy up a couple of old files by Ghost in: [#84](https://codeberg.org/uzu/strudel/pulls/84)
-- 2022-04-21T15:21:29+02:00 add `striate()` by yaxu in: [#76](https://codeberg.org/uzu/strudel/pulls/76)
-- 2022-04-20T20:17:27+02:00 Webaudio in REPL by froos in: [#77](https://codeberg.org/uzu/strudel/pulls/77)
-- 2022-04-19T15:31:34+02:00 Basic webserial support by yaxu in: [#80](https://codeberg.org/uzu/strudel/pulls/80)
-- 2022-04-17T19:29:49+02:00 Try to fix appLeft / appRight by yaxu in: [#75](https://codeberg.org/uzu/strudel/pulls/75)
-- 2022-04-16T13:26:57+02:00 More random functions by yaxu in: [#74](https://codeberg.org/uzu/strudel/pulls/74)
-- 2022-04-16T11:13:26+02:00 Port `perlin` noise, `rangex`, and `palindrome` by yaxu in: [#73](https://codeberg.org/uzu/strudel/pulls/73)
-- 2022-04-16T10:26:07+02:00 webaudio package by froos in: [#26](https://codeberg.org/uzu/strudel/pulls/26)
-- 2022-04-15T20:18:06+02:00 More randomness, fix `rand`, and add `brand`, `irand` and `choose` by yaxu in: [#70](https://codeberg.org/uzu/strudel/pulls/70)
-- 2022-04-15T11:29:51+02:00 First effort at rand() by yaxu in: [#69](https://codeberg.org/uzu/strudel/pulls/69)
-- 2022-04-14T17:41:18+02:00 use new fixed version of osc-js package by froos in: [#68](https://codeberg.org/uzu/strudel/pulls/68)
-- 2022-04-14T00:09:18+02:00 Speech output by froos in: [#67](https://codeberg.org/uzu/strudel/pulls/67)
-- 2022-04-13T23:55:33+02:00 Separate out strudel.mjs, make index.mjs aggregate module by yaxu in: [#62](https://codeberg.org/uzu/strudel/pulls/62)
-- 2022-04-13T17:26:45+02:00 More functions by yaxu in: [#61](https://codeberg.org/uzu/strudel/pulls/61)
-- 2022-04-13T10:04:29+02:00 More functions by yaxu in: [#56](https://codeberg.org/uzu/strudel/pulls/56)
-- 2022-04-12T17:04:04+02:00 OSC and SuperDirt support by yaxu in: [#27](https://codeberg.org/uzu/strudel/pulls/27)
-- 2022-04-12T13:24:14+02:00 Implement `chop()` by yaxu in: [#50](https://codeberg.org/uzu/strudel/pulls/50)
-- 2022-04-12T12:37:32+02:00 First run at squeezeBind, ref #32 by yaxu in: [#48](https://codeberg.org/uzu/strudel/pulls/48)
-- 2022-04-12T00:03:37+02:00 Fix polymeter by yaxu in: [#44](https://codeberg.org/uzu/strudel/pulls/44)
-- 2022-04-11T22:39:44+02:00 Compose by froos in: [#40](https://codeberg.org/uzu/strudel/pulls/40)
-- 2022-04-11T21:49:35+02:00 Update tutorial.mdx by Ghost in: [#38](https://codeberg.org/uzu/strudel/pulls/38)
-- 2022-04-11T08:43:44+02:00 Update tutorial.mdx by Ghost in: [#37](https://codeberg.org/uzu/strudel/pulls/37)
+- 2022-04-28T23:45:53+02:00 Work on Codemirror 6 highlighting by @Ghost in: [#102](https://codeberg.org/uzu/strudel/pulls/102)
+- 2022-04-28T15:46:06+02:00 Change to Affero GPL by @yaxu in: [#101](https://codeberg.org/uzu/strudel/pulls/101)
+- 2022-04-26T00:13:07+02:00 Paper by @froos in: [#98](https://codeberg.org/uzu/strudel/pulls/98)
+- 2022-04-25T22:10:21+02:00 Fiddles with cat/stack by @yaxu in: [#90](https://codeberg.org/uzu/strudel/pulls/90)
+- 2022-04-22T13:08:11+02:00 Add pattern composers, implements #82 by @yaxu in: [#83](https://codeberg.org/uzu/strudel/pulls/83)
+- 2022-04-21T20:57:45+02:00 Tidy up a couple of old files by @Ghost in: [#84](https://codeberg.org/uzu/strudel/pulls/84)
+- 2022-04-21T15:21:29+02:00 add `striate()` by @yaxu in: [#76](https://codeberg.org/uzu/strudel/pulls/76)
+- 2022-04-20T20:17:27+02:00 Webaudio in REPL by @froos in: [#77](https://codeberg.org/uzu/strudel/pulls/77)
+- 2022-04-19T15:31:34+02:00 Basic webserial support by @yaxu in: [#80](https://codeberg.org/uzu/strudel/pulls/80)
+- 2022-04-17T19:29:49+02:00 Try to fix appLeft / appRight by @yaxu in: [#75](https://codeberg.org/uzu/strudel/pulls/75)
+- 2022-04-16T13:26:57+02:00 More random functions by @yaxu in: [#74](https://codeberg.org/uzu/strudel/pulls/74)
+- 2022-04-16T11:13:26+02:00 Port `perlin` noise, `rangex`, and `palindrome` by @yaxu in: [#73](https://codeberg.org/uzu/strudel/pulls/73)
+- 2022-04-16T10:26:07+02:00 webaudio package by @froos in: [#26](https://codeberg.org/uzu/strudel/pulls/26)
+- 2022-04-15T20:18:06+02:00 More randomness, fix `rand`, and add `brand`, `irand` and `choose` by @yaxu in: [#70](https://codeberg.org/uzu/strudel/pulls/70)
+- 2022-04-15T11:29:51+02:00 First effort at rand() by @yaxu in: [#69](https://codeberg.org/uzu/strudel/pulls/69)
+- 2022-04-14T17:41:18+02:00 use new fixed version of osc-js package by @froos in: [#68](https://codeberg.org/uzu/strudel/pulls/68)
+- 2022-04-14T00:09:18+02:00 Speech output by @froos in: [#67](https://codeberg.org/uzu/strudel/pulls/67)
+- 2022-04-13T23:55:33+02:00 Separate out strudel.mjs, make index.mjs aggregate module by @yaxu in: [#62](https://codeberg.org/uzu/strudel/pulls/62)
+- 2022-04-13T17:26:45+02:00 More functions by @yaxu in: [#61](https://codeberg.org/uzu/strudel/pulls/61)
+- 2022-04-13T10:04:29+02:00 More functions by @yaxu in: [#56](https://codeberg.org/uzu/strudel/pulls/56)
+- 2022-04-12T17:04:04+02:00 OSC and SuperDirt support by @yaxu in: [#27](https://codeberg.org/uzu/strudel/pulls/27)
+- 2022-04-12T13:24:14+02:00 Implement `chop()` by @yaxu in: [#50](https://codeberg.org/uzu/strudel/pulls/50)
+- 2022-04-12T12:37:32+02:00 First run at squeezeBind, ref #32 by @yaxu in: [#48](https://codeberg.org/uzu/strudel/pulls/48)
+- 2022-04-12T00:03:37+02:00 Fix polymeter by @yaxu in: [#44](https://codeberg.org/uzu/strudel/pulls/44)
+- 2022-04-11T22:39:44+02:00 Compose by @froos in: [#40](https://codeberg.org/uzu/strudel/pulls/40)
+- 2022-04-11T21:49:35+02:00 Update tutorial.mdx by @Ghost in: [#38](https://codeberg.org/uzu/strudel/pulls/38)
+- 2022-04-11T08:43:44+02:00 Update tutorial.mdx by @Ghost in: [#37](https://codeberg.org/uzu/strudel/pulls/37)
## march 2022
-- 2022-03-28T17:27:22+02:00 Add chunk, chunkBack and iterBack by yaxu in: [#25](https://codeberg.org/uzu/strudel/pulls/25)
-- 2022-03-28T11:48:22+02:00 packaging by froos in: [#24](https://codeberg.org/uzu/strudel/pulls/24)
-- 2022-03-22T12:06:48+01:00 Update package.json by Ghost in: [#23](https://codeberg.org/uzu/strudel/pulls/23)
-- 2022-03-06T20:35:20+01:00 added _asNumber + interprete numbers as midi by froos in: [#21](https://codeberg.org/uzu/strudel/pulls/21)
+- 2022-03-28T17:27:22+02:00 Add chunk, chunkBack and iterBack by @yaxu in: [#25](https://codeberg.org/uzu/strudel/pulls/25)
+- 2022-03-28T11:48:22+02:00 packaging by @froos in: [#24](https://codeberg.org/uzu/strudel/pulls/24)
+- 2022-03-22T12:06:48+01:00 Update package.json by @Ghost in: [#23](https://codeberg.org/uzu/strudel/pulls/23)
+- 2022-03-06T20:35:20+01:00 added _asNumber + interprete numbers as midi by @froos in: [#21](https://codeberg.org/uzu/strudel/pulls/21)
## february 2022
-- 2022-02-28T00:32:29+01:00 Fix resolveState by yaxu in: [#22](https://codeberg.org/uzu/strudel/pulls/22)
-- 2022-02-27T20:52:52+01:00 Stateful queries and events (WIP) by yaxu in: [#14](https://codeberg.org/uzu/strudel/pulls/14)
-- 2022-02-27T18:04:07+01:00 fix: 💄 Enhance visualisation of the Tutorial on mobile by Ghost in: [#19](https://codeberg.org/uzu/strudel/pulls/19)
-- 2022-02-26T21:16:34+01:00 test: 📦 Add missing dependency and a CI check, to prevent oversights ;p by Ghost in: [#17](https://codeberg.org/uzu/strudel/pulls/17)
-- 2022-02-26T13:29:19+01:00 higher latencyHint by froos in: [#16](https://codeberg.org/uzu/strudel/pulls/16)
-- 2022-02-23T22:15:11+01:00 add apply and layer, and missing div/mul methods by yaxu in: [#15](https://codeberg.org/uzu/strudel/pulls/15)
-- 2022-02-21T01:02:07+01:00 Add continuous signals (sine, cosine, saw, etc) by yaxu in: [#13](https://codeberg.org/uzu/strudel/pulls/13)
-- 2022-02-19T21:30:04+01:00 Added mask() and struct() by yaxu in: [#11](https://codeberg.org/uzu/strudel/pulls/11)
-- 2022-02-19T16:07:07+01:00 Failing test for `when` WIP by yaxu in: [#10](https://codeberg.org/uzu/strudel/pulls/10)
-- 2022-02-10T17:21:31+01:00 Bugfix every, and create more top level functions by yaxu in: [#9](https://codeberg.org/uzu/strudel/pulls/9)
-- 2022-02-10T00:51:21+01:00 timeCat by yaxu in: [#8](https://codeberg.org/uzu/strudel/pulls/8)
-- 2022-02-07T23:07:58+01:00 fixed editor crash by froos in: [#7](https://codeberg.org/uzu/strudel/pulls/7)
-- 2022-02-07T19:08:40+01:00 krill parser + improved repl by froos in: [#6](https://codeberg.org/uzu/strudel/pulls/6)
-- 2022-02-06T00:59:16+01:00 Patternify all the things by yaxu in: [#5](https://codeberg.org/uzu/strudel/pulls/5)
-- 2022-02-05T23:31:37+01:00 update readme for local dev by Ghost in: [#4](https://codeberg.org/uzu/strudel/pulls/4)
-- 2022-02-05T22:36:06+01:00 Fix path by yaxu in: [#3](https://codeberg.org/uzu/strudel/pulls/3)
-- 2022-02-05T21:52:51+01:00 repl + reify functions by froos in: [#2](https://codeberg.org/uzu/strudel/pulls/2)
+- 2022-02-28T00:32:29+01:00 Fix resolveState by @yaxu in: [#22](https://codeberg.org/uzu/strudel/pulls/22)
+- 2022-02-27T20:52:52+01:00 Stateful queries and events (WIP) by @yaxu in: [#14](https://codeberg.org/uzu/strudel/pulls/14)
+- 2022-02-27T18:04:07+01:00 fix: 💄 Enhance visualisation of the Tutorial on mobile by @Ghost in: [#19](https://codeberg.org/uzu/strudel/pulls/19)
+- 2022-02-26T21:16:34+01:00 test: 📦 Add missing dependency and a CI check, to prevent oversights ;p by @Ghost in: [#17](https://codeberg.org/uzu/strudel/pulls/17)
+- 2022-02-26T13:29:19+01:00 higher latencyHint by @froos in: [#16](https://codeberg.org/uzu/strudel/pulls/16)
+- 2022-02-23T22:15:11+01:00 add apply and layer, and missing div/mul methods by @yaxu in: [#15](https://codeberg.org/uzu/strudel/pulls/15)
+- 2022-02-21T01:02:07+01:00 Add continuous signals (sine, cosine, saw, etc) by @yaxu in: [#13](https://codeberg.org/uzu/strudel/pulls/13)
+- 2022-02-19T21:30:04+01:00 Added mask() and struct() by @yaxu in: [#11](https://codeberg.org/uzu/strudel/pulls/11)
+- 2022-02-19T16:07:07+01:00 Failing test for `when` WIP by @yaxu in: [#10](https://codeberg.org/uzu/strudel/pulls/10)
+- 2022-02-10T17:21:31+01:00 Bugfix every, and create more top level functions by @yaxu in: [#9](https://codeberg.org/uzu/strudel/pulls/9)
+- 2022-02-10T00:51:21+01:00 timeCat by @yaxu in: [#8](https://codeberg.org/uzu/strudel/pulls/8)
+- 2022-02-07T23:07:58+01:00 fixed editor crash by @froos in: [#7](https://codeberg.org/uzu/strudel/pulls/7)
+- 2022-02-07T19:08:40+01:00 krill parser + improved repl by @froos in: [#6](https://codeberg.org/uzu/strudel/pulls/6)
+- 2022-02-06T00:59:16+01:00 Patternify all the things by @yaxu in: [#5](https://codeberg.org/uzu/strudel/pulls/5)
+- 2022-02-05T23:31:37+01:00 update readme for local dev by @Ghost in: [#4](https://codeberg.org/uzu/strudel/pulls/4)
+- 2022-02-05T22:36:06+01:00 Fix path by @yaxu in: [#3](https://codeberg.org/uzu/strudel/pulls/3)
+- 2022-02-05T21:52:51+01:00 repl + reify functions by @froos in: [#2](https://codeberg.org/uzu/strudel/pulls/2)
[9:37:36] strudel %
\ No newline at end of file
From 2dc921e3756f6805d15d92ca28108c7b18921fda Mon Sep 17 00:00:00 2001
From: Felix Roos
Date: Fri, 16 Jan 2026 10:14:17 +0100
Subject: [PATCH 311/476] fix: add fun fact
---
CHANGELOG.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 587343e43..911463dec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1076,5 +1076,6 @@ NOTE: you can generate this with `node warm.js`. it might still not be perfectly
- 2022-02-06T00:59:16+01:00 Patternify all the things by @yaxu in: [#5](https://codeberg.org/uzu/strudel/pulls/5)
- 2022-02-05T23:31:37+01:00 update readme for local dev by @Ghost in: [#4](https://codeberg.org/uzu/strudel/pulls/4)
- 2022-02-05T22:36:06+01:00 Fix path by @yaxu in: [#3](https://codeberg.org/uzu/strudel/pulls/3)
-- 2022-02-05T21:52:51+01:00 repl + reify functions by @froos in: [#2](https://codeberg.org/uzu/strudel/pulls/2)
-[9:37:36] strudel %
\ No newline at end of file
+- 2022-02-05T21:52:51+01:00 repl + reify functions by @froos in: [#2](https://codeberg.org/uzu/strudel/pulls/2)
+
+... hello from the bottom of this file! you seem to be interested in the history of strudel, so it's worth noting that the first [commit](https://codeberg.org/uzu/strudel/commit/38b5a0d5cdf28685b2b5e18d460772b70246207b) to the repo was actually on Jan 22, 2022, 09:24 PM GMT+1 by @yaxu which could be seen as strudel's birthday 🎂
From f9d0e154e841997f4260b9ceb81faa58bff5fee2 Mon Sep 17 00:00:00 2001
From: robojumper
Date: Sat, 17 Jan 2026 17:47:48 +0100
Subject: [PATCH 312/476] fix: performance issues when reference is open
---
website/src/repl/components/panel/Reference.jsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/website/src/repl/components/panel/Reference.jsx b/website/src/repl/components/panel/Reference.jsx
index c03ac0cf9..4c48b6a35 100644
--- a/website/src/repl/components/panel/Reference.jsx
+++ b/website/src/repl/components/panel/Reference.jsx
@@ -1,4 +1,4 @@
-import { useMemo, useState } from 'react';
+import { memo, useMemo, useState } from 'react';
import jsdocJson from '../../../../../doc.json';
import { Textbox } from '../textbox/Textbox';
@@ -35,7 +35,7 @@ const getInnerText = (html) => {
return div.textContent || div.innerText || '';
};
-export function Reference() {
+export const Reference = memo(function Reference() {
const [search, setSearch] = useState('');
const visibleFunctions = useMemo(() => {
@@ -112,4 +112,4 @@ export function Reference() {