Compare commits

...

32 Commits

Author SHA1 Message Date
alex a2811ba35b draft of humane dev policy 2026-10-18 21:10:36 +01:00
Alex McLean 61b6e96a4a Merge pull request 'Fix haps with no onset crashing cyclist, fix no latency' (#2154) from tzwaan/fix-cyclist-cps-2 into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2154
2026-10-16 11:31:09 +02:00
Tijmen Zwaan c33c845562 Use fractional values in cyclist 2026-10-16 11:16:29 +02:00
Tijmen Zwaan 1df7e03668 Fix haps with no onset crashing cyclist, fix no latency 2026-10-16 10:37:22 +02:00
Tijmen Zwaan 276979f48a Fix after rebase 2026-10-16 10:37:22 +02:00
Tijmen Zwaan 7e719c35f2 Fix the lastEnd not being correct when cps slowed down 2026-10-16 10:37:22 +02:00
Tijmen Zwaan a2c5af1673 Fix cps haps sort order being reversed 2026-10-16 10:37:22 +02:00
Tijmen Zwaan 2619144353 Slightly more correct sorting of haps for cps changes 2026-10-16 10:37:22 +02:00
Tijmen Zwaan e8a9974518 Fix Cyclist skipping haps during triggered increases in cps 2026-10-16 10:37:22 +02:00
Alex McLean a458dcf9fd Merge pull request 'revert 3583091e43 "Fix Cyclist skipping haps during triggered increases in cps"' (#2153) from yaxu-patch-1 into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2153
2026-10-16 09:30:19 +02:00
yaxu 8dbf5ce74c revert 3583091e43
revert Merge pull request 'Fix Cyclist skipping haps during triggered increases in cps' (#2103) from tzwaan/fix-cyclist-cps into main

Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2103
2026-10-16 09:25:24 +02:00
Alex McLean 7f02baf93b Merge pull request 'Add open and close signals, useful for making linear envelopes' (#2148) from openclose into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2148
2026-10-16 00:52:42 +02:00
Alex McLean 2cf3ffa507 Merge pull request 'Allow randL to be seeded' (#2152) from tyow/localstrudel:randl-seed-fix into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2152
2026-10-15 23:53:21 +02:00
Alex McLean 3583091e43 Merge pull request 'Fix Cyclist skipping haps during triggered increases in cps' (#2103) from tzwaan/fix-cyclist-cps into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2103
2026-10-15 23:49:48 +02:00
tyow 0ecf60f751 fix #2143 2026-10-15 17:34:22 -04:00
froos 73c57f0f9d Merge pull request 'fix(website): add webaudiofontdata URL to PWA runtime caching' (#2080) from gregocham/strudel:fix/cache-soundfonts-2068 into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2080
2026-10-15 21:56:12 +02:00
Felix Roos cc8c9f1c26 Merge remote-tracking branch 'origin/main' into fix/cache-soundfonts-2068 2026-10-15 21:53:06 +02:00
Felix Roos bcec4695a0 codeformat 2026-10-15 21:52:57 +02:00
froos e782debc15 Merge pull request 'Bug fix: Remove left-over widget id line from block-based evals' (#2150) from glossing/pianoroll-bug into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2150
2026-10-15 21:41:44 +02:00
Aria 459768af2a Bug fix: Remove left-over widget id line from block-based evals 2026-10-15 14:01:28 -05:00
froos 173a1654c8 Merge pull request 'fix hs2js + tidal package' (#2149) from fix-tidal-package into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2149
2026-10-15 17:32:01 +02:00
Felix Roos dedd687a1f Merge remote-tracking branch 'origin/main' into fix-tidal-package 2026-10-15 16:12:59 +02:00
froos 6abb9f85a8 Merge pull request 'remove supradough' (#2147) from remove-supradough into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/2147
2026-10-15 15:07:11 +02:00
Felix Roos 4f3ba01afc fix snapshots 2026-10-15 15:01:10 +02:00
Felix Roos f440d7869c remove supradough 2026-10-15 14:57:59 +02:00
Tijmen Zwaan 13d404613c Fix after rebase 2026-10-14 21:21:26 +02:00
Tijmen Zwaan f54a1f07d2 Fix the lastEnd not being correct when cps slowed down 2026-10-14 21:21:26 +02:00
Tijmen Zwaan 44e371c99d Fix cps haps sort order being reversed 2026-10-14 21:21:26 +02:00
Tijmen Zwaan c8d0342ecb Slightly more correct sorting of haps for cps changes 2026-10-14 21:21:26 +02:00
Tijmen Zwaan 096e53690f Fix Cyclist skipping haps during triggered increases in cps 2026-10-14 21:21:25 +02:00
Felix Roos d385ceba39 fix tidal package wasm url for vite build 2026-10-12 18:28:41 +02:00
karolinaskg e3e3cdfcfc fix(website): add webaudiofontdata URL to PWA runtime caching 2026-06-30 23:39:43 +03:00
25 changed files with 233 additions and 1675 deletions
+41
View File
@@ -0,0 +1,41 @@
# Code of Conduct
## The Short Version
We are dedicated to providing a harassment-free experience for everyone, regardless of gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, ethnicity, religion (or lack thereof), technology choices, and so on. This applies both in person or via online media.
## The Less Short Version
Harassment includes offensive verbal comments related to gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, ethnicity, religion, technology choices, deliberate intimidation, stalking, following, disruption of performances, inappropriate physical contact, and unwelcome sexual attention.
If you are being harassed, notice that someone else is being harassed, or have any other concerns, please contact an admin immediately.
If you report an incident of harassment you can expect to be listened to and taken seriously. The admin will take action they deem appropriate in response depending on the scale and severity of the incident. For example:
1. Discuss the perpetrator’s behaviour with them and ask them to stop. Explain what they have done and why it is unacceptable. Remind the perpetrator of the code of conduct. Monitor the perpetrator’s behaviour and if it improves then they will continue to be welcome.
2. Temporarily exclude the perpetrator from the forum for a cool-off period. Explain what they have done and why it is unacceptable and remind them of the code of conduct. Monitor the person’s behaviour and if it improves then they will continue to be welcome.
3. Remove the perpetrator from the forum. Explain what they have done and why it is unacceptable and remind them of the code of conduct.
# Post-AI humane policy for live coding development
Please follow the following policy on AI/LLM use.
## Community
All community members should be treated with respect and kindness. We welcome contributors to the community who are ready to follow this policy as well as the above code of conduct.
## Principles
* We wish to protect the humanity of our communities and projects, to support the motivation and mental health of all of its contributors and users.
* To this end, contributors and other users of our projects should not have to engage with LLM-generated code and text as part of their community work.
* We recognise that LLM-based scraping and generation of (A)GPL code shared by ourselves and others is of questionable legality. For example under many juristictions, LLM-generated work does not have a copyright holder and can therefore not be licensed under the (A)GPL.
* A contributor's personal use of LLMs and related technology is their own business, whether for research, analysis, bug discovery or other assistive technology, so long as the output is not included in any contributions to our projects.
## In practice
* Contributions including LLM-generated content will be declined.
* LLM-generated text (e.g. commit messages, issue comments, forum posts etc) generated by LLMs will be flagged, and ultimately deleted.
* We encourage asking each other questions and working through problems to promote collective knowledge and creative ideas (never telling each other to "just google it").
* We strongly discourage others from forking/importing our projects into corporate AI platforms, including Microsoft Github.
* All contributions must be submitted by a human who understands the changes, is happy to answer questions about them, and where possible, help maintain the code in the future.
* Where stipulated, discussion (including criticism) of LLM technology and use should be kept to designated channels.
-1
View File
@@ -42,7 +42,6 @@ export default [
'**/hydra.mjs',
'**/jsdoc-synonyms.js',
'packages/hs2js/src/hs2js.mjs',
'packages/supradough/dough-export.mjs',
'**/samples',
],
},
+52 -66
View File
@@ -446,7 +446,7 @@ export const { accelerate } = registerControl('accelerate');
* Sets the velocity from 0 to 1. Is multiplied together with gain.
*
* @name velocity
* @tags amplitude, superdough, supradough
* @tags amplitude, superdough
* @synonyms vel
* @example
* s("hh*8")
@@ -458,7 +458,7 @@ export const { velocity, vel } = registerControl('velocity', 'vel');
* Controls the gain by an exponential amount.
*
* @name gain
* @tags amplitude, superdough, supradough
* @tags amplitude, superdough
* @param {number | Pattern} amount gain.
* @example
* s("hh*8").gain(".4!2 1 .4!2 1 .4 1").fast(2)
@@ -469,7 +469,7 @@ export const { gain } = registerControl('gain');
* Gain applied after all effects have been processed.
*
* @name postgain
* @tags amplitude, superdough, supradough
* @tags amplitude, superdough
* @example
* s("bd sd [~ bd] sd,hh*8")
* .compressor("-20:20:10:.002:.02").postgain(1.5)
@@ -499,7 +499,7 @@ export const { amp } = registerControl('amp');
* any of the 8 individual FMs (e.g. `fmh2`)
*
* @name fmh
* @tags fm, superdough, supradough
* @tags fm, superdough
* @param {number | Pattern} harmonicity
* @example
* note("c e g b g e")
@@ -520,7 +520,7 @@ export const { fmh, fmh1, fmh2, fmh3, fmh4, fmh5, fmh6, fmh7, fmh8 } = registerM
* `fm3`
*
* @name fm
* @tags fm, superdough, supradough
* @tags fm, superdough
* @param {number | Pattern} brightness modulation index
* @synonyms fmi
* @example
@@ -544,7 +544,7 @@ export const { fmi, fmi1, fmi2, fmi3, fmi4, fmi5, fmi6, fmi7, fmi8, fm, fm1, fm2
* any of the 8 individual FMs (e.g. `fmenv4`)
*
* @name fmenv
* @tags fm, envelope, superdough, supradough
* @tags fm, envelope, superdough
* @param {number | Pattern} type lin | exp
* @synonyms fme
* @example
@@ -569,7 +569,7 @@ export const { fmenv, fmenv1, fmenv2, fmenv3, fmenv4, fmenv5, fmenv6, fmenv7, fm
* any of the 8 individual FMs (e.g. `fmatt5`)
*
* @name fmattack
* @tags fm, envelope, superdough, supradough
* @tags fm, envelope, superdough
* @synonyms fmatt
* @param {number | Pattern} time attack time
* @synonyms fmatt
@@ -608,7 +608,7 @@ export const {
* any of the 8 individual FMs (e.g. `fmwave6`)
*
* @name fmwave
* @tags fm, superdough, supradough
* @tags fm, superdough
* @param {number | Pattern} wave waveform
* @example
* n("0 1 2 3".fast(4)).scale("d:minor").s("sine").fmwave("<sine square sawtooth crackle>").fm(4).fmh(2.01)
@@ -628,7 +628,7 @@ export const { fmwave, fmwave1, fmwave2, fmwave3, fmwave4, fmwave5, fmwave6, fmw
* any of the 8 individual FMs (e.g. `fmdec6`)
*
* @name fmdecay
* @tags fm, envelope, superdough, supradough
* @tags fm, envelope, superdough
* @synonyms fmdec
* @param {number | Pattern} time decay time
* @synonyms fmdec
@@ -668,7 +668,7 @@ export const {
* any of the 8 individual FMs (e.g. `fmsus7`)
*
* @name fmsustain
* @tags fm, envelope, superdough, supradough
* @tags fm, envelope, superdough
* @synonyms fmsus
* @param {number | Pattern} level sustain level
* @synonyms fmsus
@@ -708,7 +708,7 @@ export const {
* any of the 8 individual FMs (e.g. `fmrel8`)
*
* @name fmrelease
* @tags fm, envelope, superdough, supradough
* @tags fm, envelope, superdough
* @synonyms fmrel
* @param {number | Pattern} time release time
*
@@ -778,7 +778,7 @@ export const { fft } = registerControl('fft');
* Amplitude envelope attack time: Specifies how long it takes for the sound to reach its peak value, relative to the onset.
*
* @name attack
* @tags amplitude, envelope, superdough, supradough
* @tags amplitude, envelope, superdough
* @param {number | Pattern} attack time in seconds.
* @synonyms att
* @example
@@ -792,7 +792,7 @@ export const { attack, att } = registerControl('attack', 'att');
* Note that the decay is only audible if the sustain value is lower than 1.
*
* @name decay
* @tags amplitude, envelope, superdough, supradough
* @tags amplitude, envelope, superdough
* @param {number | Pattern} time decay time in seconds
* @synonyms dec
* @example
@@ -804,7 +804,7 @@ export const { decay, dec } = registerControl('decay', 'dec');
* Amplitude envelope sustain level: The level which is reached after attack / decay, being sustained until the offset.
*
* @name sustain
* @tags amplitude, envelope, superdough, supradough
* @tags amplitude, envelope, superdough
* @param {number | Pattern} gain sustain level between 0 and 1
* @synonyms sus
* @example
@@ -816,7 +816,7 @@ export const { sustain, sus } = registerControl('sustain', 'sus');
* Amplitude envelope release time: The time it takes after the offset to go from sustain level to zero.
*
* @name release
* @tags amplitude, envelope, superdough, supradough
* @tags amplitude, envelope, superdough
* @param {number | Pattern} time release time in seconds
* @synonyms rel
* @example
@@ -831,7 +831,7 @@ export const { hold } = registerControl('hold');
* can also optionally supply the 'bpq' parameter separated by ':'.
*
* @name bpf
* @tags filter, superdough, supradough
* @tags filter, superdough
* @param {number | Pattern} frequency center frequency
* @synonyms bandf, bp
* @example
@@ -844,7 +844,7 @@ export const { bandf, bpf, bp } = registerControl(['bandf', 'bandq', 'bpenv'], '
* Sets the **b**and-**p**ass **q**-factor (resonance).
*
* @name bpq
* @tags filter, superdough, supradough
* @tags filter, superdough
* @param {number | Pattern} q q factor
* @synonyms bandq
* @example
@@ -923,7 +923,7 @@ export const { loopEnd, loope } = registerControl('loopEnd', 'loope');
* Bit crusher effect.
*
* @name crush
* @tags superdough, supradough
* @tags superdough
* @param {number | Pattern} depth between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).
* @example
* s("<bd sd>,hh*3").fast(2).crush("<16 8 7 6 5 4 3 2>")
@@ -935,7 +935,7 @@ export const { crush } = registerControl('crush');
* Fake-resampling for lowering the sample rate. Caution: This effect seems to only work in chromium based browsers
*
* @name coarse
* @tags superdough, supradough
* @tags superdough
* @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on.
* @example
* s("bd sd [~ bd] sd,hh*8").coarse("<1 4 8 16 32>")
@@ -1294,7 +1294,7 @@ export const { cut } = registerControl('cut');
* When using mininotation, you can also optionally add the 'lpq' parameter, separated by ':'.
*
* @name lpf
* @tags filter, superdough, supradough
* @tags filter, superdough
* @param {number | Pattern} frequency audible between 0 and 20000
* @synonyms cutoff, ctf, lp
* @example
@@ -1308,7 +1308,7 @@ export const { cutoff, ctf, lpf, lp } = registerControl(['cutoff', 'resonance',
/**
* Sets the lowpass filter envelope modulation depth.
* @name lpenv
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} modulation depth of the lowpass filter envelope between 0 and _n_
* @synonyms lpe
* @example
@@ -1322,7 +1322,7 @@ export const { lpenv, lpe } = registerControl('lpenv', 'lpe');
/**
* Sets the highpass filter envelope modulation depth.
* @name hpenv
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} modulation depth of the highpass filter envelope between 0 and _n_
* @synonyms hpe
* @example
@@ -1336,7 +1336,7 @@ export const { hpenv, hpe } = registerControl('hpenv', 'hpe');
/**
* Sets the bandpass filter envelope modulation depth.
* @name bpenv
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} modulation depth of the bandpass filter envelope between 0 and _n_
* @synonyms bpe
* @example
@@ -1350,7 +1350,7 @@ export const { bpenv, bpe } = registerControl('bpenv', 'bpe');
/**
* Sets the attack duration for the lowpass filter envelope.
* @name lpattack
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} attack time of the filter envelope
* @synonyms lpa
* @example
@@ -1364,7 +1364,7 @@ export const { lpattack, lpa } = registerControl('lpattack', 'lpa');
/**
* Sets the attack duration for the highpass filter envelope.
* @name hpattack
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} attack time of the highpass filter envelope
* @synonyms hpa
* @example
@@ -1378,7 +1378,7 @@ export const { hpattack, hpa } = registerControl('hpattack', 'hpa');
/**
* Sets the attack duration for the bandpass filter envelope.
* @name bpattack
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} attack time of the bandpass filter envelope
* @synonyms bpa
* @example
@@ -1392,7 +1392,7 @@ export const { bpattack, bpa } = registerControl('bpattack', 'bpa');
/**
* Sets the decay duration for the lowpass filter envelope.
* @name lpdecay
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} decay time of the filter envelope
* @synonyms lpd
* @example
@@ -1406,7 +1406,7 @@ export const { lpdecay, lpd } = registerControl('lpdecay', 'lpd');
/**
* Sets the decay duration for the highpass filter envelope.
* @name hpdecay
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} decay time of the highpass filter envelope
* @synonyms hpd
* @example
@@ -1421,7 +1421,7 @@ export const { hpdecay, hpd } = registerControl('hpdecay', 'hpd');
/**
* Sets the decay duration for the bandpass filter envelope.
* @name bpdecay
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} decay time of the bandpass filter envelope
* @synonyms bpd
* @example
@@ -1436,7 +1436,7 @@ export const { bpdecay, bpd } = registerControl('bpdecay', 'bpd');
/**
* Sets the sustain amplitude for the lowpass filter envelope.
* @name lpsustain
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} sustain amplitude of the lowpass filter envelope
* @synonyms lps
* @example
@@ -1451,7 +1451,7 @@ export const { lpsustain, lps } = registerControl('lpsustain', 'lps');
/**
* Sets the sustain amplitude for the highpass filter envelope.
* @name hpsustain
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} sustain amplitude of the highpass filter envelope
* @synonyms hps
* @example
@@ -1466,7 +1466,7 @@ export const { hpsustain, hps } = registerControl('hpsustain', 'hps');
/**
* Sets the sustain amplitude for the bandpass filter envelope.
* @name bpsustain
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} sustain amplitude of the bandpass filter envelope
* @synonyms bps
* @example
@@ -1481,7 +1481,7 @@ export const { bpsustain, bps } = registerControl('bpsustain', 'bps');
/**
* Sets the release time for the lowpass filter envelope.
* @name lprelease
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} release time of the filter envelope
* @synonyms lpr
* @example
@@ -1497,7 +1497,7 @@ export const { lprelease, lpr } = registerControl('lprelease', 'lpr');
/**
* Sets the release time for the highpass filter envelope.
* @name hprelease
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} release time of the highpass filter envelope
* @synonyms hpr
* @example
@@ -1513,7 +1513,7 @@ export const { hprelease, hpr } = registerControl('hprelease', 'hpr');
/**
* Sets the release time for the bandpass filter envelope.
* @name bprelease
* @tags filter, envelope, superdough, supradough
* @tags filter, envelope, superdough
* @param {number | Pattern} release time of the bandpass filter envelope
* @synonyms bpr
* @example
@@ -1558,7 +1558,7 @@ export const { fanchor } = registerControl('fanchor');
* When using mininotation, you can also optionally add the 'hpq' parameter, separated by ':'.
*
* @name hpf
* @tags filter, superdough, supradough
* @tags filter, superdough
* @param {number | Pattern} frequency audible between 0 and 20000
* @synonyms hp, hcutoff
* @example
@@ -1781,7 +1781,7 @@ export const { hpskew } = registerControl('hpskew');
* Applies a vibrato to the frequency of the oscillator.
*
* @name vib
* @tags pitch, lfo, superdough, supradough
* @tags pitch, lfo, superdough
* @synonyms vibrato, v
* @param {number | Pattern} frequency of the vibrato in hertz
* @example
@@ -1799,7 +1799,7 @@ export const { vib, vibrato, v } = registerControl(['vib', 'vibmod'], 'vibrato',
* Adds pink noise to the mix
*
* @name noise
* @tags generators, superdough, supradough
* @tags generators, superdough
* @param {number | Pattern} wet wet amount
* @example
* sound("<white pink brown>/2")
@@ -1809,7 +1809,7 @@ export const { noise } = registerControl('noise');
* Sets the vibrato depth in semitones. Only has an effect if `vibrato` | `vib` | `v` is is also set
*
* @name vibmod
* @tags pitch, lfo, superdough, supradough
* @tags pitch, lfo, superdough
* @synonyms vmod
* @param {number | Pattern} depth of vibrato (in semitones)
* @example
@@ -1828,7 +1828,7 @@ export const { hcutoff, hpf, hp } = registerControl(['hcutoff', 'hresonance', 'h
* Controls the **h**igh-**p**ass **q**-value.
*
* @name hpq
* @tags filter, superdough, supradough
* @tags filter, superdough
* @param {number | Pattern} q resonance factor between 0 and 50
* @synonyms hresonance
* @example
@@ -1840,7 +1840,7 @@ export const { hresonance, hpq } = registerControl('hresonance', 'hpq');
* Controls the **l**ow-**p**ass **q**-value.
*
* @name lpq
* @tags filter, superdough, supradough
* @tags filter, superdough
* @param {number | Pattern} q resonance factor between 0 and 50
* @synonyms resonance
* @example
@@ -1870,7 +1870,7 @@ export const { djf } = registerControl('djf');
*
*
* @name delay
* @tags orbit, superdough, supradough
* @tags orbit, superdough
* @param {number | Pattern} level between 0 and 1
* @example
* s("bd bd").delay("<0 .25 .5 1>")
@@ -1884,7 +1884,7 @@ export const { delay } = registerControl(['delay', 'delaytime', 'delayfeedback']
* Caution: Values >= 1 will result in a signal that gets louder and louder! Don't do it
*
* @name delayfeedback
* @tags orbit, superdough, supradough
* @tags orbit, superdough
* @param {number | Pattern} feedback between 0 and 1
* @synonyms delayfb, dfb
* @example
@@ -1893,24 +1893,11 @@ export const { delay } = registerControl(['delay', 'delaytime', 'delayfeedback']
*/
export const { delayfeedback, delayfb, dfb } = registerControl('delayfeedback', 'delayfb', 'dfb');
/**
* Sets the time of the delay effect.
*
* @name delayspeed
* @tags supradough
* @param {number | Pattern} delayspeed controls the pitch of the delay feedback
* @synonyms delayt, dt
* @example
* note("d d a# a".fast(2)).s("sawtooth").delay(.8).delaytime(1/2).delayspeed("<2 .5 -1 -2>")
*
*/
export const { delayspeed } = registerControl('delayspeed');
/**
* Sets the time of the delay effect in seconds.
*
* @name delaytime
* @tags orbit, superdough, supradough
* @tags orbit, superdough
* @param {number | Pattern} delay in seconds
* @synonyms delayt, dt
* @example
@@ -1918,7 +1905,6 @@ export const { delayspeed } = registerControl('delayspeed');
* .s("sawtooth")
* .delay(.8)
* .delaytime(1/2)
* .delayspeed("<2 .5 -1 -2>")
*/
export const { delaytime, delayt, dt } = registerControl('delaytime', 'delayt', 'dt');
@@ -2026,7 +2012,7 @@ export const { freq } = registerControl('freq');
* Attack time of pitch envelope.
*
* @name pattack
* @tags pitch, envelope, superdough, supradough
* @tags pitch, envelope, superdough
* @synonyms patt
* @param {number | Pattern} time time in seconds
* @example
@@ -2038,7 +2024,7 @@ export const { pattack, patt } = registerControl('pattack', 'patt');
* Decay time of pitch envelope.
*
* @name pdecay
* @tags pitch, envelope, superdough, supradough
* @tags pitch, envelope, superdough
* @synonyms pdec
* @param {number | Pattern} time time in seconds
* @example
@@ -2052,7 +2038,7 @@ export const { psustain, psus } = registerControl('psustain', 'psus');
* Release time of pitch envelope
*
* @name prelease
* @tags pitch, envelope, superdough, supradough
* @tags pitch, envelope, superdough
* @synonyms prel
* @param {number | Pattern} time time in seconds
* @example
@@ -2067,7 +2053,7 @@ export const { prelease, prel } = registerControl('prelease', 'prel');
* If you don't set other pitch envelope controls, `pattack:.2` will be the default.
*
* @name penv
* @tags pitch, envelope, superdough, supradough
* @tags pitch, envelope, superdough
* @param {number | Pattern} semitones change in semitones
* @example
* note("c")
@@ -2248,7 +2234,7 @@ export const { overshape } = registerControl('overshape');
* Sets position in stereo.
*
* @name pan
* @tags superdough, supradough
* @tags superdough
* @param {number | Pattern} pan between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel)
* @example
* s("[bd hh]*2").pan("<.5 1 .5 0>")
@@ -2506,7 +2492,7 @@ export const { shape } = registerControl(['shape', 'shapevol']);
* Most useful values are usually between 0 and 10 (depending on source gain). If you are feeling adventurous, you can turn it up to 11 and beyond ;)
*
* @name distort
* @tags distortion, superdough, supradough
* @tags distortion, superdough
* @synonyms dist
* @param {number | Pattern} distortion amount of distortion to apply
* @param {number | Pattern} volume linear postgain of the distortion
@@ -2526,7 +2512,7 @@ export const { distort, dist } = registerControl(['distort', 'distortvol', 'dist
*
* @name distortvol
* @synonyms distortion, distvol
* @tags superdough, supradough
* @tags superdough
* @param {number | Pattern} volume linear postgain of the distortion
* @example
* s("bd*4").bank("tr909").distort(2).distortvol(0.8)
@@ -2537,7 +2523,7 @@ export const { distortvol } = registerControl('distortvol', 'distvol');
* Type of waveshaping distortion to apply.
*
* @name distorttype
* @tags distortion, superdough, supradough
* @tags distortion, superdough
* @synonyms disttype
* @param {number | string | Pattern} type type of distortion to apply
* @example
+88 -23
View File
@@ -28,31 +28,34 @@ export class Cyclist {
this.started = false;
this.beforeStart = beforeStart;
this.cps = 0.5;
this.num_ticks_since_cps_change = 0;
this.checkpoint = {
// new checkpoints are created when there's a change in cps
cycles: 0, // number of cycles when cps was changed
seconds: 0, // clock phase when cps was changed
};
this.num_ticks_since_checkpoint = 0;
this.lastTick = 0; // absolute time when last tick (clock callback) happened
this.lastBegin = 0; // query begin of last tick
this.lastEnd = 0; // query end of last tick
this.getTime = getTime; // get absolute time
this.num_cycles_at_cps_change = 0;
this.seconds_at_cps_change; // clock phase when cps was changed
this.onToggle = onToggle;
this.latency = latency; // fixed trigger time offset
this.clock = createClock(
getTime,
// called slightly before each cycle
(phase, duration, _, t) => {
if (this.num_ticks_since_cps_change === 0) {
this.num_cycles_at_cps_change = this.lastEnd;
this.seconds_at_cps_change = phase;
if (this.num_ticks_since_checkpoint === 0) {
this.checkpoint = {
cycles: this.lastEnd,
seconds: phase,
};
}
this.num_ticks_since_cps_change++;
const seconds_since_cps_change = this.num_ticks_since_cps_change * duration;
const num_cycles_since_cps_change = seconds_since_cps_change * this.cps;
this.num_ticks_since_checkpoint++;
try {
const begin = this.lastEnd;
var begin = this.lastEnd;
this.lastBegin = begin;
const end = this.num_cycles_at_cps_change + num_cycles_since_cps_change;
var end = this.checkpoint.cycles + this.num_ticks_since_checkpoint * duration * this.cps;
this.lastEnd = end;
this.lastTick = phase;
@@ -62,20 +65,79 @@ export class Cyclist {
return;
}
// query the pattern for events
const haps = this.pattern.queryArc(begin, end, { _cps: this.cps, cyclist: 'cyclist' });
const tickEndTime = phase + duration;
haps.forEach((hap) => {
if (hap.hasOnset()) {
const targetTime =
(hap.whole.begin - this.num_cycles_at_cps_change) / this.cps + this.seconds_at_cps_change + latency;
onSchedule?.(hap, targetTime, this.cps);
var cpsChanged = false;
do {
cpsChanged = false;
// query the pattern for events
const haps = this.pattern
.queryArc(begin, end, { _cps: this.cps, cyclist: 'cyclist' })
.filter((hap) => hap.hasOnset())
// Sort the haps based on their onset, so cps changes within the
// tick duration happen in the correct order.
.sort((a, b) => {
const aBegin = a.whole.begin;
const bBegin = b.whole.begin;
// If haps happen at the same time, trigger the haps that cause
// cps changes first, so the durations of the simultaneous haps
// are adjusted accordingly.
if (aBegin.eq(bBegin)) {
if (a.value.cps !== undefined) {
return b.value.cps !== undefined ? 0 : -1;
}
if (b.value.cps !== undefined) {
return 1;
}
return 0;
}
return aBegin.sub(bBegin);
});
haps.forEach((hap) => {
const targetTime = (hap.whole.begin - this.checkpoint.cycles) / this.cps + this.checkpoint.seconds;
if (tickEndTime < targetTime) {
// If the targetTime exceeds the tickEndTime, this means
// the cps has slowed down, and the latter haps from the query
// no longer fall within the window of the current tick.
// They'll be scheduled during the next tick.
return;
}
onSchedule?.(hap, targetTime + this.latency, hap.value.cps ?? this.cps);
if (hap.value.cps !== undefined && this.cps != hap.value.cps) {
cpsChanged = true;
this.cps = hap.value.cps;
this.num_ticks_since_cps_change = 0;
this.num_ticks_since_checkpoint = 0;
this.checkpoint = {
cycles: hap.whole.begin,
seconds: targetTime,
};
}
});
// If there are any haps in the query that trigger changes to the
// cps that result in the pattern speeding up, the current cycle end
// may not capture all the haps that need to be scheduled.
// If this is the case, we repeat the query + scheduling with a
// newly calculated end time.
// This process can repeat multiple times until no additional
// changes to the cps are triggered.
// In practice, this doesn't happen more than once during a tick.
if (cpsChanged) {
begin = end;
const remainingSecondsSinceCheckpoint = tickEndTime - this.checkpoint.seconds;
const remainingCycles = remainingSecondsSinceCheckpoint * this.cps;
end = this.checkpoint.cycles + remainingCycles;
this.lastEnd = end;
if (end < begin) {
// If the new end is before the old end this means the track
// slowed down, so we don't need to schedule additional haps.
// Otherwise, schedule the remaining events.
break;
}
}
});
} while (cpsChanged);
} catch (e) {
errorLogger(e);
onError?.(e);
@@ -101,8 +163,11 @@ export class Cyclist {
}
async start() {
await this.beforeStart?.();
this.num_ticks_since_cps_change = 0;
this.num_cycles_at_cps_change = 0;
this.checkpoint = {
cycles: 0,
seconds: 0,
};
this.num_ticks_since_checkpoint = 0;
if (!this.pattern) {
throw new Error('Scheduler: no pattern set! call .setPattern first.');
}
@@ -132,7 +197,7 @@ export class Cyclist {
return;
}
this.cps = cps;
this.num_ticks_since_cps_change = 0;
this.num_ticks_since_checkpoint = 0;
}
log(begin, end, haps) {
const onsets = haps.filter((h) => h.hasOnset());
+1 -1
View File
@@ -420,7 +420,7 @@ export const binaryNL = (n, nBits = 16) => {
* .partials(randL(8))
*/
export const randL = (n) => {
return signal((t) => (nVal) => getRandsAtTime(t, nVal).map(Math.abs)).appLeft(reify(n));
return signal((t, controls) => (nVal) => getRandsAtTime(t, nVal, controls.randSeed).map(Math.abs)).appLeft(reify(n));
};
export const randrun = (n) => {
+2 -2
View File
@@ -29,10 +29,10 @@
},
"homepage": "https://codeberg.org/uzu/strudel/",
"dependencies": {
"web-tree-sitter": "^0.24.7"
"web-tree-sitter": "^0.24.7",
"tree-sitter-haskell": "^0.23.1"
},
"devDependencies": {
"tree-sitter-haskell": "^0.23.1",
"vite": "^6.0.11"
},
"engines": {
+9 -3
View File
@@ -1,6 +1,8 @@
import Parser from 'web-tree-sitter';
import treeSitterWasm from 'web-tree-sitter/tree-sitter.wasm?url';
import grammarWasm from 'tree-sitter-haskell/tree-sitter-haskell.wasm?url';
let base = '/';
let base;
export function setBase(path) {
base = path;
}
@@ -10,11 +12,15 @@ let isReady = false,
async function _loadParser() {
await Parser.init({
locateFile(scriptName, scriptDirectory) {
return `${base}${scriptName}`;
if (base) {
return `${base}${scriptName}`;
}
return treeSitterWasm;
},
});
parser = new Parser();
const Lang = await Parser.Language.load(`${base}tree-sitter-haskell.wasm`);
let grammarUrl = base ? `${base}tree-sitter-haskell.wasm` : grammarWasm;
const Lang = await Parser.Language.load(grammarUrl);
parser.setLanguage(Lang);
isReady = true;
return parser;
-1
View File
@@ -1 +0,0 @@
pattern.wav
-3
View File
@@ -1,3 +0,0 @@
# supradough
platform agnostic synth and sampler intended for live coding. a reimplementation of superdough.
-123
View File
@@ -1,123 +0,0 @@
// this is a poc of how a pattern can be rendered as a wav file using node
// run via: node dough-export.mjs
import fs from 'node:fs';
import WavEncoder from 'wav-encoder';
import { evalScope } from '@strudel/core';
import { miniAllStrings } from '@strudel/mini';
import { Dough } from './dough.mjs';
await evalScope(
import('@strudel/core'),
import('@strudel/mini'),
import('@strudel/tonal'),
// import('@strudel/tonal'),
);
miniAllStrings(); // allows using single quotes for mini notation / skip transpilation
let sampleRate = 48000,
cps = 0.4;
/* await doughsamples('github:eddyflux/crate');
await doughsamples('github:eddyflux/wax'); */
let pat = note('c,eb,g,<bb c4 d4 eb4>')
.s('sine')
.press()
.add(note(24))
.fmi(3)
.fmh(5.01)
.dec(0.4)
.delay('.6:<.12 .22>:.8')
.jux(press)
.rarely(add(note('12')))
.lpf(400)
.lpq(0.2)
.lpd(0.4)
.lpenv(3)
.fmdecay(0.4)
.fmenv(1)
.postgain(0.6)
.stack(s('<pink white>*8').dec(0.07).rarely(ply('2')).delay(0.5).hpf(sine.range(200, 2000).slow(4)).hpq(0.2))
.stack(
s('[- white@3]*2')
.dec(0.4)
.hpf('<2000!3 <4000 8000>>*4')
.hpq(0.6)
.ply('<1 2>*4')
.postgain(0.5)
.delay(0.5)
.jux(rev)
.lpf(5000),
)
.stack(
note('<c2 - [- f1] ->*2')
.s('square')
.lpf(sine.range(100, 300).slow(4))
.lpe(1)
.segment(8)
.lpd(0.3)
.lpq(0.2)
.dec(0.2)
.speed('<1 2>')
.ply('<1 2>')
.postgain(1),
)
.stack(
chord('<Cm Cm7 Cm9 Cm11 Fm Fm7 Fm9 Fm11>')
.voicing()
.s('<sine>')
.clip(1)
.rel(0.4)
.vib('4:.2')
.gain(0.7)
.hpf(1200)
.fm(0.5)
.att(1)
.lpa(0.5)
.lpf(200)
.lpenv(4)
.chorus(0.8),
)
.slow(1 / cps);
let cycles = 30;
let seconds = cycles + 1; // 1s release tail
const haps = pat.queryArc(0, cycles);
const dough = new Dough(sampleRate);
console.log('spawn voices...');
haps.forEach((hap) => {
hap.value._begin = Number(hap.whole.begin);
hap.value._duration = hap.duration /* / cps */;
dough.scheduleSpawn(hap.value);
});
console.log(`render ${seconds}s long buffer, each dot is 1 second:`);
const buffers = [new Float32Array(seconds * sampleRate), new Float32Array(seconds * sampleRate)];
let t = performance.now();
while (dough.t <= buffers[0].length) {
dough.update();
buffers[0][dough.t] = dough.out[0];
buffers[1][dough.t] = dough.out[1];
if (dough.t % sampleRate === 0) {
process.stdout.write('.');
}
}
const took = (performance.now() - t) / 1000;
const load = (took / seconds) * 100;
const speed = (seconds / took).toFixed(2);
console.log('');
console.log(`done!
rendered ${seconds}s in ${took.toFixed(2)}s
speed: ${speed}x
load: ${load.toFixed(2)}%`);
const patternAudio = {
sampleRate,
channelData: buffers,
};
WavEncoder.encode(patternAudio).then((buffer) => {
fs.writeFileSync('pattern.wav', new Float32Array(buffer));
});
-39
View File
@@ -1,39 +0,0 @@
import { Dough } from './dough.mjs';
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
class DoughProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.dough = new Dough(sampleRate, currentTime);
this.port.onmessage = (event) => {
if (event.data.spawn) {
this.dough.scheduleSpawn(event.data.spawn);
} else if (event.data.sample) {
this.dough.loadSample(event.data.sample, event.data.channels, event.data.sampleRate);
} else if (event.data.samples) {
event.data.samples.forEach(([name, channels, sampleRate]) => {
this.dough.loadSample(name, channels, sampleRate);
});
} else {
console.log('unrecognized event type', event.data);
}
};
}
process(inputs, outputs, params) {
if (this.disconnected) {
return false;
}
const output = outputs[0];
for (let i = 0; i < output[0].length; i++) {
this.dough.update();
for (let c = 0; c < output.length; c++) {
//prevent speaker blowout via clipping if threshold exceeds
output[c][i] = clamp(this.dough.out[c], -1, 1);
}
}
return true; // keep the audio processing going
}
}
registerProcessor('dough-processor', DoughProcessor);
File diff suppressed because it is too large Load Diff
-5
View File
@@ -1,5 +0,0 @@
// import _workletUrl from './dough-worklet.mjs?url'; // only for dev (breaks for production build)
import _workletUrl from './dough-worklet.mjs?audioworklet'; // only for prod (breaks in development?!)
export * from './dough.mjs';
export const workletUrl = _workletUrl;
-39
View File
@@ -1,39 +0,0 @@
{
"name": "supradough",
"version": "1.2.4",
"description": "platform agnostic synth and sampler intended for live coding. a reimplementation of superdough.",
"main": "index.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
"prepublishOnly": "npm run build"
},
"repository": {
"type": "git",
"url": "git+https://codeberg.org/uzu/strudel.git"
},
"keywords": [
"tidalcycles",
"strudel",
"pattern",
"livecoding",
"algorave"
],
"author": "Felix Roos <flix91@gmail.com>",
"license": "AGPL-3.0-or-later",
"bugs": {
"url": "https://codeberg.org/uzu/strudel/issues"
},
"homepage": "https://codeberg.org/uzu/strudel#readme",
"devDependencies": {
"vite": "^6.0.11",
"vite-plugin-bundle-audioworklet": "workspace:*",
"wav-encoder": "^1.3.0"
},
"engines": {
"node": ">=18.0.0"
}
}
-16
View File
@@ -1,16 +0,0 @@
import { defineConfig } from 'vite';
import { resolve } from 'path';
import bundleAudioWorkletPlugin from 'vite-plugin-bundle-audioworklet';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [bundleAudioWorkletPlugin()],
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
},
target: 'esnext',
},
});
+1
View File
@@ -3,6 +3,7 @@
"version": "0.2.0",
"private": true,
"description": "Experimental Tidal Code interpreter",
"main": "tidal.mjs",
"module": "tidal.mjs",
"repository": {
"type": "git",
-3
View File
@@ -94,9 +94,6 @@ export function getWidgetID(widgetConfig) {
function widgetWithLocation(node, widgetConfig) {
const id = getWidgetID(widgetConfig);
// Store the unique ID back into the config so it's available for widget management
// This is critical for block-based evaluation to match existing widgets with new ones
widgetConfig.id = id;
// add loc as identifier to first argument
// the sliderWithID function is assumed to be sliderWithID(id, value, min?, max?)
node.arguments.unshift({
-1
View File
@@ -7,5 +7,4 @@ This program is free software: you can redistribute it and/or modify it under th
export * from './webaudio.mjs';
export * from './scope.mjs';
export * from './spectrum.mjs';
export * from './supradough.mjs';
export * from 'superdough';
+1 -2
View File
@@ -35,8 +35,7 @@
"dependencies": {
"@strudel/core": "workspace:*",
"@strudel/draw": "workspace:*",
"superdough": "workspace:*",
"supradough": "workspace:*"
"superdough": "workspace:*"
},
"devDependencies": {
"vite": "^6.0.11"
-130
View File
@@ -1,130 +0,0 @@
import { Pattern } from '@strudel/core';
import { connectToDestination, getAudioContext, getWorklet } from 'superdough';
let doughWorklet;
function initDoughWorklet() {
const ac = getAudioContext();
doughWorklet = getWorklet(
ac,
'dough-processor',
{},
{
outputChannelCount: [2],
},
);
connectToDestination(doughWorklet); // channels?
}
const soundMap = new Map();
const loadedSounds = new Map();
Pattern.prototype.supradough = function () {
return this.onSchedule((hap, begin, cps) => {
hap.value._begin = begin;
hap.value._duration = hap.duration / cps;
!doughWorklet && initDoughWorklet();
const s = (hap.value.bank ? hap.value.bank + '_' : '') + hap.value.s;
const n = hap.value.n ?? 0;
const soundKey = `${s}:${n}`;
if (soundMap.has(s)) {
hap.value.s = soundKey; // dough.mjs is unaware of bank and n (only maps keys to buffers)
}
if (soundMap.has(s) && !loadedSounds.has(soundKey)) {
const urls = soundMap.get(s);
const url = urls[n % urls.length];
console.log(`load ${soundKey} from ${url}`);
const loadSample = fetchSample(url);
loadedSounds.set(soundKey, loadSample);
loadSample.then(({ channels, sampleRate }) =>
doughWorklet.port.postMessage({
sample: soundKey,
channels,
sampleRate,
}),
);
}
doughWorklet.port.postMessage({ spawn: hap.value });
}, 1);
};
function githubPath(base, subpath = '') {
if (!base.startsWith('github:')) {
throw new Error('expected "github:" at the start of pseudoUrl');
}
let [_, path] = base.split('github:');
path = path.endsWith('/') ? path.slice(0, -1) : path;
if (path.split('/').length === 2) {
// assume main as default branch if none set
path += '/main';
}
return `https://raw.githubusercontent.com/${path}/${subpath}`;
}
export async function _fetchSampleMap(url) {
if (url.startsWith('github:')) {
url = githubPath(url, 'strudel.json');
}
if (url.startsWith('local:')) {
url = `http://localhost:5432`;
}
if (url.startsWith('shabda:')) {
let [_, path] = url.split('shabda:');
url = `https://shabda.ndre.gr/${path}.json?strudel=1`;
}
if (url.startsWith('shabda/speech')) {
let [_, path] = url.split('shabda/speech');
path = path.startsWith('/') ? path.substring(1) : path;
let [params, words] = path.split(':');
let gender = 'f';
let language = 'en-GB';
if (params) {
[language, gender] = params.split('/');
}
url = `https://shabda.ndre.gr/speech/${words}.json?gender=${gender}&language=${language}&strudel=1'`;
}
if (typeof fetch !== 'function') {
// not a browser
return;
}
const base = url.split('/').slice(0, -1).join('/');
if (typeof fetch === 'undefined') {
// skip fetch when in node / testing
return;
}
const json = await fetch(url)
.then((res) => res.json())
.catch((error) => {
console.error(error);
throw new Error(`error loading "${url}"`);
});
return [json, json._base || base];
}
// for some reason, only piano and flute work.. is it because mp3??
async function fetchSample(url) {
const buffer = await fetch(url)
.then((res) => res.arrayBuffer())
.then((buf) => getAudioContext().decodeAudioData(buf));
let channels = [];
for (let i = 0; i < buffer.numberOfChannels; i++) {
channels.push(buffer.getChannelData(i));
}
return { channels, sampleRate: buffer.sampleRate };
}
export async function supradoughsamples(sampleMap, baseUrl) {
if (typeof sampleMap === 'string') {
const [json, base] = await _fetchSampleMap(sampleMap);
// console.log('json', json, 'base', base);
return supradoughsamples(json, base);
}
Object.entries(sampleMap).map(async ([key, urls]) => {
if (key !== '_base') {
urls = urls.map((url) => baseUrl + url);
// console.log('set', key, urls);
soundMap.set(key, urls);
}
});
}
-3
View File
@@ -17,10 +17,7 @@ import {
resetGlobalEffects,
errorLogger,
} from 'superdough';
import './supradough.mjs';
import { workletUrl } from 'supradough';
import { SuperdoughAudioController } from 'superdough/superdoughoutput.mjs';
registerWorklet(workletUrl);
const { Pattern, logger, repl } = strudel;
+3 -23
View File
@@ -359,13 +359,13 @@ importers:
packages/hs2js:
dependencies:
tree-sitter-haskell:
specifier: ^0.23.1
version: 0.23.1(tree-sitter@0.21.1)
web-tree-sitter:
specifier: ^0.24.7
version: 0.24.7
devDependencies:
tree-sitter-haskell:
specifier: ^0.23.1
version: 0.23.1(tree-sitter@0.21.1)
vite:
specifier: ^6.0.11
version: 6.0.11(@types/node@22.10.10)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0)
@@ -606,18 +606,6 @@ importers:
specifier: workspace:*
version: link:../vite-plugin-bundle-audioworklet
packages/supradough:
devDependencies:
vite:
specifier: ^6.0.11
version: 6.0.11(@types/node@22.10.10)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0)
vite-plugin-bundle-audioworklet:
specifier: workspace:*
version: link:../vite-plugin-bundle-audioworklet
wav-encoder:
specifier: ^1.3.0
version: 1.3.0
packages/tidal:
dependencies:
'@strudel/core':
@@ -729,9 +717,6 @@ importers:
superdough:
specifier: workspace:*
version: link:../superdough
supradough:
specifier: workspace:*
version: link:../supradough
devDependencies:
vite:
specifier: ^6.0.11
@@ -7782,9 +7767,6 @@ packages:
walk-up-path@3.0.1:
resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==}
wav-encoder@1.3.0:
resolution: {integrity: sha512-FXJdEu2qDOI+wbVYZpu21CS1vPEg5NaxNskBr4SaULpOJMrLE6xkH8dECa7PiS+ZoeyvP7GllWUAxPN3AvFSEw==}
wav@1.0.2:
resolution: {integrity: sha512-viHtz3cDd/Tcr/HbNqzQCofKdF6kWUymH9LGDdskfWFoIy/HJ+RTihgjEcHfnsy1PO4e9B+y4HwgTwMrByquhg==}
@@ -16365,8 +16347,6 @@ snapshots:
walk-up-path@3.0.1: {}
wav-encoder@1.3.0: {}
wav@1.0.2:
dependencies:
buffer-alloc: 1.2.0
+32 -69
View File
@@ -3175,43 +3175,6 @@ exports[`runs examples > example "delayfeedback" example index 0 1`] = `
]
`;
exports[`runs examples > example "delayspeed" example index 0 1`] = `
[
"[ 0/1 → 1/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 1/8 → 1/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 1/4 → 3/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 3/8 → 1/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 1/2 → 5/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 5/8 → 3/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 3/4 → 7/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 7/8 → 1/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 1/1 → 9/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 9/8 → 5/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 5/4 → 11/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 11/8 → 3/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 3/2 → 13/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 13/8 → 7/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 7/4 → 15/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 15/8 → 2/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 2/1 → 17/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 17/8 → 9/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 9/4 → 19/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 19/8 → 5/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 5/2 → 21/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 21/8 → 11/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 11/4 → 23/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 23/8 → 3/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 3/1 → 25/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 25/8 → 13/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 13/4 → 27/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 27/8 → 7/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 7/2 → 29/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 29/8 → 15/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 15/4 → 31/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 31/8 → 4/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
]
`;
exports[`runs examples > example "delaysync" example index 0 1`] = `
[
"[ 0/1 → 1/2 | s:bd delay:0.25 delaysync:0.125 ]",
@@ -3227,38 +3190,38 @@ exports[`runs examples > example "delaysync" example index 0 1`] = `
exports[`runs examples > example "delaytime" example index 0 1`] = `
[
"[ 0/1 → 1/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 1/8 → 1/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 1/4 → 3/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 3/8 → 1/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 1/2 → 5/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 5/8 → 3/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 3/4 → 7/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 7/8 → 1/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:2 ]",
"[ 1/1 → 9/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 9/8 → 5/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 5/4 → 11/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 11/8 → 3/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 3/2 → 13/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 13/8 → 7/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 7/4 → 15/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 15/8 → 2/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:0.5 ]",
"[ 2/1 → 17/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 17/8 → 9/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 9/4 → 19/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 19/8 → 5/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 5/2 → 21/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 21/8 → 11/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 11/4 → 23/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 23/8 → 3/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-1 ]",
"[ 3/1 → 25/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 25/8 → 13/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 13/4 → 27/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 27/8 → 7/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 7/2 → 29/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 29/8 → 15/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 15/4 → 31/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 31/8 → 4/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 delayspeed:-2 ]",
"[ 0/1 → 1/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 1/8 → 1/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 1/4 → 3/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 3/8 → 1/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 1/2 → 5/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 5/8 → 3/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 3/4 → 7/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 7/8 → 1/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 1/1 → 9/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 9/8 → 5/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 5/4 → 11/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 11/8 → 3/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 3/2 → 13/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 13/8 → 7/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 7/4 → 15/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 15/8 → 2/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 2/1 → 17/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 17/8 → 9/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 9/4 → 19/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 19/8 → 5/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 5/2 → 21/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 21/8 → 11/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 11/4 → 23/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 23/8 → 3/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 3/1 → 25/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 25/8 → 13/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 13/4 → 27/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 27/8 → 7/2 | note:a s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 7/2 → 29/8 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 29/8 → 15/4 | note:d s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 15/4 → 31/8 | note:a# s:sawtooth delay:0.8 delaytime:0.5 ]",
"[ 31/8 → 4/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 ]",
]
`;
+1
View File
@@ -80,6 +80,7 @@ export default defineConfig({
/^https:\/\/freesound\.org\/.*/i,
/^https:\/\/cdn\.freesound\.org\/.*/i,
/^https:\/\/shabda\.ndre\.gr\/.*/i,
/^https:\/\/felixroos\.github\.io\/webaudiofontdata\/.*/i,
].some((regex) => regex.test(url)),
handler: 'CacheFirst',
options: {
@@ -5,9 +5,8 @@ import { Textbox } from '@src/repl/components/panel/SettingsTab';
import { settingsMap, useSettings } from '@src/settings.mjs';
const isValid = ({ name, description, tags = [] }) => {
const isSupradoughOnly = tags.includes('supradough') && !tags.includes('superdough');
const isSuperdirtOnly = tags.includes('superdirt') && !tags.includes('superdough');
return name && !name.startsWith('_') && !!description && !isSupradoughOnly && !isSuperdirtOnly;
return name && !name.startsWith('_') && !!description && !isSuperdirtOnly;
};
const availableFunctions = (() => {
@@ -38,7 +37,7 @@ const availableFunctions = (() => {
})();
const tagCounts = {};
const ignoredTags = ['supradough', 'superdirt'];
const ignoredTags = ['superdirt'];
// const tagOptions = { all: `all (${availableFunctions.length})` };
const tagOptions = { all: `all` };
for (const doc of availableFunctions) {