mirror of
https://codeberg.org/uzu/strudel
synced 2026-10-16 12:53:20 -04:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 61b6e96a4a | |||
| c33c845562 | |||
| 1df7e03668 | |||
| 276979f48a | |||
| 7e719c35f2 | |||
| a2c5af1673 | |||
| 2619144353 | |||
| e8a9974518 | |||
| a458dcf9fd | |||
| 8dbf5ce74c | |||
| 7f02baf93b | |||
| 2cf3ffa507 | |||
| 3583091e43 | |||
| 0ecf60f751 | |||
| 73c57f0f9d | |||
| cc8c9f1c26 | |||
| bcec4695a0 | |||
| e782debc15 | |||
| 459768af2a | |||
| 173a1654c8 | |||
| dedd687a1f | |||
| 6abb9f85a8 | |||
| 4f3ba01afc | |||
| f440d7869c | |||
| 13d404613c | |||
| f54a1f07d2 | |||
| 44e371c99d | |||
| c8d0342ecb | |||
| 096e53690f | |||
| d385ceba39 | |||
| e3e3cdfcfc |
@@ -42,7 +42,6 @@ export default [
|
|||||||
'**/hydra.mjs',
|
'**/hydra.mjs',
|
||||||
'**/jsdoc-synonyms.js',
|
'**/jsdoc-synonyms.js',
|
||||||
'packages/hs2js/src/hs2js.mjs',
|
'packages/hs2js/src/hs2js.mjs',
|
||||||
'packages/supradough/dough-export.mjs',
|
|
||||||
'**/samples',
|
'**/samples',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
+52
-66
@@ -446,7 +446,7 @@ export const { accelerate } = registerControl('accelerate');
|
|||||||
* Sets the velocity from 0 to 1. Is multiplied together with gain.
|
* Sets the velocity from 0 to 1. Is multiplied together with gain.
|
||||||
*
|
*
|
||||||
* @name velocity
|
* @name velocity
|
||||||
* @tags amplitude, superdough, supradough
|
* @tags amplitude, superdough
|
||||||
* @synonyms vel
|
* @synonyms vel
|
||||||
* @example
|
* @example
|
||||||
* s("hh*8")
|
* s("hh*8")
|
||||||
@@ -458,7 +458,7 @@ export const { velocity, vel } = registerControl('velocity', 'vel');
|
|||||||
* Controls the gain by an exponential amount.
|
* Controls the gain by an exponential amount.
|
||||||
*
|
*
|
||||||
* @name gain
|
* @name gain
|
||||||
* @tags amplitude, superdough, supradough
|
* @tags amplitude, superdough
|
||||||
* @param {number | Pattern} amount gain.
|
* @param {number | Pattern} amount gain.
|
||||||
* @example
|
* @example
|
||||||
* s("hh*8").gain(".4!2 1 .4!2 1 .4 1").fast(2)
|
* 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.
|
* Gain applied after all effects have been processed.
|
||||||
*
|
*
|
||||||
* @name postgain
|
* @name postgain
|
||||||
* @tags amplitude, superdough, supradough
|
* @tags amplitude, superdough
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd [~ bd] sd,hh*8")
|
* s("bd sd [~ bd] sd,hh*8")
|
||||||
* .compressor("-20:20:10:.002:.02").postgain(1.5)
|
* .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`)
|
* any of the 8 individual FMs (e.g. `fmh2`)
|
||||||
*
|
*
|
||||||
* @name fmh
|
* @name fmh
|
||||||
* @tags fm, superdough, supradough
|
* @tags fm, superdough
|
||||||
* @param {number | Pattern} harmonicity
|
* @param {number | Pattern} harmonicity
|
||||||
* @example
|
* @example
|
||||||
* note("c e g b g e")
|
* note("c e g b g e")
|
||||||
@@ -520,7 +520,7 @@ export const { fmh, fmh1, fmh2, fmh3, fmh4, fmh5, fmh6, fmh7, fmh8 } = registerM
|
|||||||
* `fm3`
|
* `fm3`
|
||||||
*
|
*
|
||||||
* @name fm
|
* @name fm
|
||||||
* @tags fm, superdough, supradough
|
* @tags fm, superdough
|
||||||
* @param {number | Pattern} brightness modulation index
|
* @param {number | Pattern} brightness modulation index
|
||||||
* @synonyms fmi
|
* @synonyms fmi
|
||||||
* @example
|
* @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`)
|
* any of the 8 individual FMs (e.g. `fmenv4`)
|
||||||
*
|
*
|
||||||
* @name fmenv
|
* @name fmenv
|
||||||
* @tags fm, envelope, superdough, supradough
|
* @tags fm, envelope, superdough
|
||||||
* @param {number | Pattern} type lin | exp
|
* @param {number | Pattern} type lin | exp
|
||||||
* @synonyms fme
|
* @synonyms fme
|
||||||
* @example
|
* @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`)
|
* any of the 8 individual FMs (e.g. `fmatt5`)
|
||||||
*
|
*
|
||||||
* @name fmattack
|
* @name fmattack
|
||||||
* @tags fm, envelope, superdough, supradough
|
* @tags fm, envelope, superdough
|
||||||
* @synonyms fmatt
|
* @synonyms fmatt
|
||||||
* @param {number | Pattern} time attack time
|
* @param {number | Pattern} time attack time
|
||||||
* @synonyms fmatt
|
* @synonyms fmatt
|
||||||
@@ -608,7 +608,7 @@ export const {
|
|||||||
* any of the 8 individual FMs (e.g. `fmwave6`)
|
* any of the 8 individual FMs (e.g. `fmwave6`)
|
||||||
*
|
*
|
||||||
* @name fmwave
|
* @name fmwave
|
||||||
* @tags fm, superdough, supradough
|
* @tags fm, superdough
|
||||||
* @param {number | Pattern} wave waveform
|
* @param {number | Pattern} wave waveform
|
||||||
* @example
|
* @example
|
||||||
* n("0 1 2 3".fast(4)).scale("d:minor").s("sine").fmwave("<sine square sawtooth crackle>").fm(4).fmh(2.01)
|
* 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`)
|
* any of the 8 individual FMs (e.g. `fmdec6`)
|
||||||
*
|
*
|
||||||
* @name fmdecay
|
* @name fmdecay
|
||||||
* @tags fm, envelope, superdough, supradough
|
* @tags fm, envelope, superdough
|
||||||
* @synonyms fmdec
|
* @synonyms fmdec
|
||||||
* @param {number | Pattern} time decay time
|
* @param {number | Pattern} time decay time
|
||||||
* @synonyms fmdec
|
* @synonyms fmdec
|
||||||
@@ -668,7 +668,7 @@ export const {
|
|||||||
* any of the 8 individual FMs (e.g. `fmsus7`)
|
* any of the 8 individual FMs (e.g. `fmsus7`)
|
||||||
*
|
*
|
||||||
* @name fmsustain
|
* @name fmsustain
|
||||||
* @tags fm, envelope, superdough, supradough
|
* @tags fm, envelope, superdough
|
||||||
* @synonyms fmsus
|
* @synonyms fmsus
|
||||||
* @param {number | Pattern} level sustain level
|
* @param {number | Pattern} level sustain level
|
||||||
* @synonyms fmsus
|
* @synonyms fmsus
|
||||||
@@ -708,7 +708,7 @@ export const {
|
|||||||
* any of the 8 individual FMs (e.g. `fmrel8`)
|
* any of the 8 individual FMs (e.g. `fmrel8`)
|
||||||
*
|
*
|
||||||
* @name fmrelease
|
* @name fmrelease
|
||||||
* @tags fm, envelope, superdough, supradough
|
* @tags fm, envelope, superdough
|
||||||
* @synonyms fmrel
|
* @synonyms fmrel
|
||||||
* @param {number | Pattern} time release time
|
* @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.
|
* Amplitude envelope attack time: Specifies how long it takes for the sound to reach its peak value, relative to the onset.
|
||||||
*
|
*
|
||||||
* @name attack
|
* @name attack
|
||||||
* @tags amplitude, envelope, superdough, supradough
|
* @tags amplitude, envelope, superdough
|
||||||
* @param {number | Pattern} attack time in seconds.
|
* @param {number | Pattern} attack time in seconds.
|
||||||
* @synonyms att
|
* @synonyms att
|
||||||
* @example
|
* @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.
|
* Note that the decay is only audible if the sustain value is lower than 1.
|
||||||
*
|
*
|
||||||
* @name decay
|
* @name decay
|
||||||
* @tags amplitude, envelope, superdough, supradough
|
* @tags amplitude, envelope, superdough
|
||||||
* @param {number | Pattern} time decay time in seconds
|
* @param {number | Pattern} time decay time in seconds
|
||||||
* @synonyms dec
|
* @synonyms dec
|
||||||
* @example
|
* @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.
|
* Amplitude envelope sustain level: The level which is reached after attack / decay, being sustained until the offset.
|
||||||
*
|
*
|
||||||
* @name sustain
|
* @name sustain
|
||||||
* @tags amplitude, envelope, superdough, supradough
|
* @tags amplitude, envelope, superdough
|
||||||
* @param {number | Pattern} gain sustain level between 0 and 1
|
* @param {number | Pattern} gain sustain level between 0 and 1
|
||||||
* @synonyms sus
|
* @synonyms sus
|
||||||
* @example
|
* @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.
|
* Amplitude envelope release time: The time it takes after the offset to go from sustain level to zero.
|
||||||
*
|
*
|
||||||
* @name release
|
* @name release
|
||||||
* @tags amplitude, envelope, superdough, supradough
|
* @tags amplitude, envelope, superdough
|
||||||
* @param {number | Pattern} time release time in seconds
|
* @param {number | Pattern} time release time in seconds
|
||||||
* @synonyms rel
|
* @synonyms rel
|
||||||
* @example
|
* @example
|
||||||
@@ -831,7 +831,7 @@ export const { hold } = registerControl('hold');
|
|||||||
* can also optionally supply the 'bpq' parameter separated by ':'.
|
* can also optionally supply the 'bpq' parameter separated by ':'.
|
||||||
*
|
*
|
||||||
* @name bpf
|
* @name bpf
|
||||||
* @tags filter, superdough, supradough
|
* @tags filter, superdough
|
||||||
* @param {number | Pattern} frequency center frequency
|
* @param {number | Pattern} frequency center frequency
|
||||||
* @synonyms bandf, bp
|
* @synonyms bandf, bp
|
||||||
* @example
|
* @example
|
||||||
@@ -844,7 +844,7 @@ export const { bandf, bpf, bp } = registerControl(['bandf', 'bandq', 'bpenv'], '
|
|||||||
* Sets the **b**and-**p**ass **q**-factor (resonance).
|
* Sets the **b**and-**p**ass **q**-factor (resonance).
|
||||||
*
|
*
|
||||||
* @name bpq
|
* @name bpq
|
||||||
* @tags filter, superdough, supradough
|
* @tags filter, superdough
|
||||||
* @param {number | Pattern} q q factor
|
* @param {number | Pattern} q q factor
|
||||||
* @synonyms bandq
|
* @synonyms bandq
|
||||||
* @example
|
* @example
|
||||||
@@ -923,7 +923,7 @@ export const { loopEnd, loope } = registerControl('loopEnd', 'loope');
|
|||||||
* Bit crusher effect.
|
* Bit crusher effect.
|
||||||
*
|
*
|
||||||
* @name crush
|
* @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).
|
* @param {number | Pattern} depth between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).
|
||||||
* @example
|
* @example
|
||||||
* s("<bd sd>,hh*3").fast(2).crush("<16 8 7 6 5 4 3 2>")
|
* 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
|
* Fake-resampling for lowering the sample rate. Caution: This effect seems to only work in chromium based browsers
|
||||||
*
|
*
|
||||||
* @name coarse
|
* @name coarse
|
||||||
* @tags superdough, supradough
|
* @tags superdough
|
||||||
* @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on.
|
* @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on.
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd [~ bd] sd,hh*8").coarse("<1 4 8 16 32>")
|
* 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 ':'.
|
* When using mininotation, you can also optionally add the 'lpq' parameter, separated by ':'.
|
||||||
*
|
*
|
||||||
* @name lpf
|
* @name lpf
|
||||||
* @tags filter, superdough, supradough
|
* @tags filter, superdough
|
||||||
* @param {number | Pattern} frequency audible between 0 and 20000
|
* @param {number | Pattern} frequency audible between 0 and 20000
|
||||||
* @synonyms cutoff, ctf, lp
|
* @synonyms cutoff, ctf, lp
|
||||||
* @example
|
* @example
|
||||||
@@ -1308,7 +1308,7 @@ export const { cutoff, ctf, lpf, lp } = registerControl(['cutoff', 'resonance',
|
|||||||
/**
|
/**
|
||||||
* Sets the lowpass filter envelope modulation depth.
|
* Sets the lowpass filter envelope modulation depth.
|
||||||
* @name lpenv
|
* @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_
|
* @param {number | Pattern} modulation depth of the lowpass filter envelope between 0 and _n_
|
||||||
* @synonyms lpe
|
* @synonyms lpe
|
||||||
* @example
|
* @example
|
||||||
@@ -1322,7 +1322,7 @@ export const { lpenv, lpe } = registerControl('lpenv', 'lpe');
|
|||||||
/**
|
/**
|
||||||
* Sets the highpass filter envelope modulation depth.
|
* Sets the highpass filter envelope modulation depth.
|
||||||
* @name hpenv
|
* @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_
|
* @param {number | Pattern} modulation depth of the highpass filter envelope between 0 and _n_
|
||||||
* @synonyms hpe
|
* @synonyms hpe
|
||||||
* @example
|
* @example
|
||||||
@@ -1336,7 +1336,7 @@ export const { hpenv, hpe } = registerControl('hpenv', 'hpe');
|
|||||||
/**
|
/**
|
||||||
* Sets the bandpass filter envelope modulation depth.
|
* Sets the bandpass filter envelope modulation depth.
|
||||||
* @name bpenv
|
* @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_
|
* @param {number | Pattern} modulation depth of the bandpass filter envelope between 0 and _n_
|
||||||
* @synonyms bpe
|
* @synonyms bpe
|
||||||
* @example
|
* @example
|
||||||
@@ -1350,7 +1350,7 @@ export const { bpenv, bpe } = registerControl('bpenv', 'bpe');
|
|||||||
/**
|
/**
|
||||||
* Sets the attack duration for the lowpass filter envelope.
|
* Sets the attack duration for the lowpass filter envelope.
|
||||||
* @name lpattack
|
* @name lpattack
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} attack time of the filter envelope
|
* @param {number | Pattern} attack time of the filter envelope
|
||||||
* @synonyms lpa
|
* @synonyms lpa
|
||||||
* @example
|
* @example
|
||||||
@@ -1364,7 +1364,7 @@ export const { lpattack, lpa } = registerControl('lpattack', 'lpa');
|
|||||||
/**
|
/**
|
||||||
* Sets the attack duration for the highpass filter envelope.
|
* Sets the attack duration for the highpass filter envelope.
|
||||||
* @name hpattack
|
* @name hpattack
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} attack time of the highpass filter envelope
|
* @param {number | Pattern} attack time of the highpass filter envelope
|
||||||
* @synonyms hpa
|
* @synonyms hpa
|
||||||
* @example
|
* @example
|
||||||
@@ -1378,7 +1378,7 @@ export const { hpattack, hpa } = registerControl('hpattack', 'hpa');
|
|||||||
/**
|
/**
|
||||||
* Sets the attack duration for the bandpass filter envelope.
|
* Sets the attack duration for the bandpass filter envelope.
|
||||||
* @name bpattack
|
* @name bpattack
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} attack time of the bandpass filter envelope
|
* @param {number | Pattern} attack time of the bandpass filter envelope
|
||||||
* @synonyms bpa
|
* @synonyms bpa
|
||||||
* @example
|
* @example
|
||||||
@@ -1392,7 +1392,7 @@ export const { bpattack, bpa } = registerControl('bpattack', 'bpa');
|
|||||||
/**
|
/**
|
||||||
* Sets the decay duration for the lowpass filter envelope.
|
* Sets the decay duration for the lowpass filter envelope.
|
||||||
* @name lpdecay
|
* @name lpdecay
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} decay time of the filter envelope
|
* @param {number | Pattern} decay time of the filter envelope
|
||||||
* @synonyms lpd
|
* @synonyms lpd
|
||||||
* @example
|
* @example
|
||||||
@@ -1406,7 +1406,7 @@ export const { lpdecay, lpd } = registerControl('lpdecay', 'lpd');
|
|||||||
/**
|
/**
|
||||||
* Sets the decay duration for the highpass filter envelope.
|
* Sets the decay duration for the highpass filter envelope.
|
||||||
* @name hpdecay
|
* @name hpdecay
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} decay time of the highpass filter envelope
|
* @param {number | Pattern} decay time of the highpass filter envelope
|
||||||
* @synonyms hpd
|
* @synonyms hpd
|
||||||
* @example
|
* @example
|
||||||
@@ -1421,7 +1421,7 @@ export const { hpdecay, hpd } = registerControl('hpdecay', 'hpd');
|
|||||||
/**
|
/**
|
||||||
* Sets the decay duration for the bandpass filter envelope.
|
* Sets the decay duration for the bandpass filter envelope.
|
||||||
* @name bpdecay
|
* @name bpdecay
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} decay time of the bandpass filter envelope
|
* @param {number | Pattern} decay time of the bandpass filter envelope
|
||||||
* @synonyms bpd
|
* @synonyms bpd
|
||||||
* @example
|
* @example
|
||||||
@@ -1436,7 +1436,7 @@ export const { bpdecay, bpd } = registerControl('bpdecay', 'bpd');
|
|||||||
/**
|
/**
|
||||||
* Sets the sustain amplitude for the lowpass filter envelope.
|
* Sets the sustain amplitude for the lowpass filter envelope.
|
||||||
* @name lpsustain
|
* @name lpsustain
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} sustain amplitude of the lowpass filter envelope
|
* @param {number | Pattern} sustain amplitude of the lowpass filter envelope
|
||||||
* @synonyms lps
|
* @synonyms lps
|
||||||
* @example
|
* @example
|
||||||
@@ -1451,7 +1451,7 @@ export const { lpsustain, lps } = registerControl('lpsustain', 'lps');
|
|||||||
/**
|
/**
|
||||||
* Sets the sustain amplitude for the highpass filter envelope.
|
* Sets the sustain amplitude for the highpass filter envelope.
|
||||||
* @name hpsustain
|
* @name hpsustain
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} sustain amplitude of the highpass filter envelope
|
* @param {number | Pattern} sustain amplitude of the highpass filter envelope
|
||||||
* @synonyms hps
|
* @synonyms hps
|
||||||
* @example
|
* @example
|
||||||
@@ -1466,7 +1466,7 @@ export const { hpsustain, hps } = registerControl('hpsustain', 'hps');
|
|||||||
/**
|
/**
|
||||||
* Sets the sustain amplitude for the bandpass filter envelope.
|
* Sets the sustain amplitude for the bandpass filter envelope.
|
||||||
* @name bpsustain
|
* @name bpsustain
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} sustain amplitude of the bandpass filter envelope
|
* @param {number | Pattern} sustain amplitude of the bandpass filter envelope
|
||||||
* @synonyms bps
|
* @synonyms bps
|
||||||
* @example
|
* @example
|
||||||
@@ -1481,7 +1481,7 @@ export const { bpsustain, bps } = registerControl('bpsustain', 'bps');
|
|||||||
/**
|
/**
|
||||||
* Sets the release time for the lowpass filter envelope.
|
* Sets the release time for the lowpass filter envelope.
|
||||||
* @name lprelease
|
* @name lprelease
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} release time of the filter envelope
|
* @param {number | Pattern} release time of the filter envelope
|
||||||
* @synonyms lpr
|
* @synonyms lpr
|
||||||
* @example
|
* @example
|
||||||
@@ -1497,7 +1497,7 @@ export const { lprelease, lpr } = registerControl('lprelease', 'lpr');
|
|||||||
/**
|
/**
|
||||||
* Sets the release time for the highpass filter envelope.
|
* Sets the release time for the highpass filter envelope.
|
||||||
* @name hprelease
|
* @name hprelease
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} release time of the highpass filter envelope
|
* @param {number | Pattern} release time of the highpass filter envelope
|
||||||
* @synonyms hpr
|
* @synonyms hpr
|
||||||
* @example
|
* @example
|
||||||
@@ -1513,7 +1513,7 @@ export const { hprelease, hpr } = registerControl('hprelease', 'hpr');
|
|||||||
/**
|
/**
|
||||||
* Sets the release time for the bandpass filter envelope.
|
* Sets the release time for the bandpass filter envelope.
|
||||||
* @name bprelease
|
* @name bprelease
|
||||||
* @tags filter, envelope, superdough, supradough
|
* @tags filter, envelope, superdough
|
||||||
* @param {number | Pattern} release time of the bandpass filter envelope
|
* @param {number | Pattern} release time of the bandpass filter envelope
|
||||||
* @synonyms bpr
|
* @synonyms bpr
|
||||||
* @example
|
* @example
|
||||||
@@ -1558,7 +1558,7 @@ export const { fanchor } = registerControl('fanchor');
|
|||||||
* When using mininotation, you can also optionally add the 'hpq' parameter, separated by ':'.
|
* When using mininotation, you can also optionally add the 'hpq' parameter, separated by ':'.
|
||||||
*
|
*
|
||||||
* @name hpf
|
* @name hpf
|
||||||
* @tags filter, superdough, supradough
|
* @tags filter, superdough
|
||||||
* @param {number | Pattern} frequency audible between 0 and 20000
|
* @param {number | Pattern} frequency audible between 0 and 20000
|
||||||
* @synonyms hp, hcutoff
|
* @synonyms hp, hcutoff
|
||||||
* @example
|
* @example
|
||||||
@@ -1781,7 +1781,7 @@ export const { hpskew } = registerControl('hpskew');
|
|||||||
* Applies a vibrato to the frequency of the oscillator.
|
* Applies a vibrato to the frequency of the oscillator.
|
||||||
*
|
*
|
||||||
* @name vib
|
* @name vib
|
||||||
* @tags pitch, lfo, superdough, supradough
|
* @tags pitch, lfo, superdough
|
||||||
* @synonyms vibrato, v
|
* @synonyms vibrato, v
|
||||||
* @param {number | Pattern} frequency of the vibrato in hertz
|
* @param {number | Pattern} frequency of the vibrato in hertz
|
||||||
* @example
|
* @example
|
||||||
@@ -1799,7 +1799,7 @@ export const { vib, vibrato, v } = registerControl(['vib', 'vibmod'], 'vibrato',
|
|||||||
* Adds pink noise to the mix
|
* Adds pink noise to the mix
|
||||||
*
|
*
|
||||||
* @name noise
|
* @name noise
|
||||||
* @tags generators, superdough, supradough
|
* @tags generators, superdough
|
||||||
* @param {number | Pattern} wet wet amount
|
* @param {number | Pattern} wet wet amount
|
||||||
* @example
|
* @example
|
||||||
* sound("<white pink brown>/2")
|
* 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
|
* Sets the vibrato depth in semitones. Only has an effect if `vibrato` | `vib` | `v` is is also set
|
||||||
*
|
*
|
||||||
* @name vibmod
|
* @name vibmod
|
||||||
* @tags pitch, lfo, superdough, supradough
|
* @tags pitch, lfo, superdough
|
||||||
* @synonyms vmod
|
* @synonyms vmod
|
||||||
* @param {number | Pattern} depth of vibrato (in semitones)
|
* @param {number | Pattern} depth of vibrato (in semitones)
|
||||||
* @example
|
* @example
|
||||||
@@ -1828,7 +1828,7 @@ export const { hcutoff, hpf, hp } = registerControl(['hcutoff', 'hresonance', 'h
|
|||||||
* Controls the **h**igh-**p**ass **q**-value.
|
* Controls the **h**igh-**p**ass **q**-value.
|
||||||
*
|
*
|
||||||
* @name hpq
|
* @name hpq
|
||||||
* @tags filter, superdough, supradough
|
* @tags filter, superdough
|
||||||
* @param {number | Pattern} q resonance factor between 0 and 50
|
* @param {number | Pattern} q resonance factor between 0 and 50
|
||||||
* @synonyms hresonance
|
* @synonyms hresonance
|
||||||
* @example
|
* @example
|
||||||
@@ -1840,7 +1840,7 @@ export const { hresonance, hpq } = registerControl('hresonance', 'hpq');
|
|||||||
* Controls the **l**ow-**p**ass **q**-value.
|
* Controls the **l**ow-**p**ass **q**-value.
|
||||||
*
|
*
|
||||||
* @name lpq
|
* @name lpq
|
||||||
* @tags filter, superdough, supradough
|
* @tags filter, superdough
|
||||||
* @param {number | Pattern} q resonance factor between 0 and 50
|
* @param {number | Pattern} q resonance factor between 0 and 50
|
||||||
* @synonyms resonance
|
* @synonyms resonance
|
||||||
* @example
|
* @example
|
||||||
@@ -1870,7 +1870,7 @@ export const { djf } = registerControl('djf');
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @name delay
|
* @name delay
|
||||||
* @tags orbit, superdough, supradough
|
* @tags orbit, superdough
|
||||||
* @param {number | Pattern} level between 0 and 1
|
* @param {number | Pattern} level between 0 and 1
|
||||||
* @example
|
* @example
|
||||||
* s("bd bd").delay("<0 .25 .5 1>")
|
* 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
|
* Caution: Values >= 1 will result in a signal that gets louder and louder! Don't do it
|
||||||
*
|
*
|
||||||
* @name delayfeedback
|
* @name delayfeedback
|
||||||
* @tags orbit, superdough, supradough
|
* @tags orbit, superdough
|
||||||
* @param {number | Pattern} feedback between 0 and 1
|
* @param {number | Pattern} feedback between 0 and 1
|
||||||
* @synonyms delayfb, dfb
|
* @synonyms delayfb, dfb
|
||||||
* @example
|
* @example
|
||||||
@@ -1893,24 +1893,11 @@ export const { delay } = registerControl(['delay', 'delaytime', 'delayfeedback']
|
|||||||
*/
|
*/
|
||||||
export const { delayfeedback, delayfb, dfb } = registerControl('delayfeedback', 'delayfb', 'dfb');
|
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.
|
* Sets the time of the delay effect in seconds.
|
||||||
*
|
*
|
||||||
* @name delaytime
|
* @name delaytime
|
||||||
* @tags orbit, superdough, supradough
|
* @tags orbit, superdough
|
||||||
* @param {number | Pattern} delay in seconds
|
* @param {number | Pattern} delay in seconds
|
||||||
* @synonyms delayt, dt
|
* @synonyms delayt, dt
|
||||||
* @example
|
* @example
|
||||||
@@ -1918,7 +1905,6 @@ export const { delayspeed } = registerControl('delayspeed');
|
|||||||
* .s("sawtooth")
|
* .s("sawtooth")
|
||||||
* .delay(.8)
|
* .delay(.8)
|
||||||
* .delaytime(1/2)
|
* .delaytime(1/2)
|
||||||
* .delayspeed("<2 .5 -1 -2>")
|
|
||||||
*/
|
*/
|
||||||
export const { delaytime, delayt, dt } = registerControl('delaytime', 'delayt', 'dt');
|
export const { delaytime, delayt, dt } = registerControl('delaytime', 'delayt', 'dt');
|
||||||
|
|
||||||
@@ -2026,7 +2012,7 @@ export const { freq } = registerControl('freq');
|
|||||||
* Attack time of pitch envelope.
|
* Attack time of pitch envelope.
|
||||||
*
|
*
|
||||||
* @name pattack
|
* @name pattack
|
||||||
* @tags pitch, envelope, superdough, supradough
|
* @tags pitch, envelope, superdough
|
||||||
* @synonyms patt
|
* @synonyms patt
|
||||||
* @param {number | Pattern} time time in seconds
|
* @param {number | Pattern} time time in seconds
|
||||||
* @example
|
* @example
|
||||||
@@ -2038,7 +2024,7 @@ export const { pattack, patt } = registerControl('pattack', 'patt');
|
|||||||
* Decay time of pitch envelope.
|
* Decay time of pitch envelope.
|
||||||
*
|
*
|
||||||
* @name pdecay
|
* @name pdecay
|
||||||
* @tags pitch, envelope, superdough, supradough
|
* @tags pitch, envelope, superdough
|
||||||
* @synonyms pdec
|
* @synonyms pdec
|
||||||
* @param {number | Pattern} time time in seconds
|
* @param {number | Pattern} time time in seconds
|
||||||
* @example
|
* @example
|
||||||
@@ -2052,7 +2038,7 @@ export const { psustain, psus } = registerControl('psustain', 'psus');
|
|||||||
* Release time of pitch envelope
|
* Release time of pitch envelope
|
||||||
*
|
*
|
||||||
* @name prelease
|
* @name prelease
|
||||||
* @tags pitch, envelope, superdough, supradough
|
* @tags pitch, envelope, superdough
|
||||||
* @synonyms prel
|
* @synonyms prel
|
||||||
* @param {number | Pattern} time time in seconds
|
* @param {number | Pattern} time time in seconds
|
||||||
* @example
|
* @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.
|
* If you don't set other pitch envelope controls, `pattack:.2` will be the default.
|
||||||
*
|
*
|
||||||
* @name penv
|
* @name penv
|
||||||
* @tags pitch, envelope, superdough, supradough
|
* @tags pitch, envelope, superdough
|
||||||
* @param {number | Pattern} semitones change in semitones
|
* @param {number | Pattern} semitones change in semitones
|
||||||
* @example
|
* @example
|
||||||
* note("c")
|
* note("c")
|
||||||
@@ -2248,7 +2234,7 @@ export const { overshape } = registerControl('overshape');
|
|||||||
* Sets position in stereo.
|
* Sets position in stereo.
|
||||||
*
|
*
|
||||||
* @name pan
|
* @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)
|
* @param {number | Pattern} pan between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel)
|
||||||
* @example
|
* @example
|
||||||
* s("[bd hh]*2").pan("<.5 1 .5 0>")
|
* 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 ;)
|
* 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
|
* @name distort
|
||||||
* @tags distortion, superdough, supradough
|
* @tags distortion, superdough
|
||||||
* @synonyms dist
|
* @synonyms dist
|
||||||
* @param {number | Pattern} distortion amount of distortion to apply
|
* @param {number | Pattern} distortion amount of distortion to apply
|
||||||
* @param {number | Pattern} volume linear postgain of the distortion
|
* @param {number | Pattern} volume linear postgain of the distortion
|
||||||
@@ -2526,7 +2512,7 @@ export const { distort, dist } = registerControl(['distort', 'distortvol', 'dist
|
|||||||
*
|
*
|
||||||
* @name distortvol
|
* @name distortvol
|
||||||
* @synonyms distortion, distvol
|
* @synonyms distortion, distvol
|
||||||
* @tags superdough, supradough
|
* @tags superdough
|
||||||
* @param {number | Pattern} volume linear postgain of the distortion
|
* @param {number | Pattern} volume linear postgain of the distortion
|
||||||
* @example
|
* @example
|
||||||
* s("bd*4").bank("tr909").distort(2).distortvol(0.8)
|
* 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.
|
* Type of waveshaping distortion to apply.
|
||||||
*
|
*
|
||||||
* @name distorttype
|
* @name distorttype
|
||||||
* @tags distortion, superdough, supradough
|
* @tags distortion, superdough
|
||||||
* @synonyms disttype
|
* @synonyms disttype
|
||||||
* @param {number | string | Pattern} type type of distortion to apply
|
* @param {number | string | Pattern} type type of distortion to apply
|
||||||
* @example
|
* @example
|
||||||
|
|||||||
+88
-23
@@ -28,31 +28,34 @@ export class Cyclist {
|
|||||||
this.started = false;
|
this.started = false;
|
||||||
this.beforeStart = beforeStart;
|
this.beforeStart = beforeStart;
|
||||||
this.cps = 0.5;
|
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.lastTick = 0; // absolute time when last tick (clock callback) happened
|
||||||
this.lastBegin = 0; // query begin of last tick
|
this.lastBegin = 0; // query begin of last tick
|
||||||
this.lastEnd = 0; // query end of last tick
|
this.lastEnd = 0; // query end of last tick
|
||||||
this.getTime = getTime; // get absolute time
|
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.onToggle = onToggle;
|
||||||
this.latency = latency; // fixed trigger time offset
|
this.latency = latency; // fixed trigger time offset
|
||||||
this.clock = createClock(
|
this.clock = createClock(
|
||||||
getTime,
|
getTime,
|
||||||
// called slightly before each cycle
|
// called slightly before each cycle
|
||||||
(phase, duration, _, t) => {
|
(phase, duration, _, t) => {
|
||||||
if (this.num_ticks_since_cps_change === 0) {
|
if (this.num_ticks_since_checkpoint === 0) {
|
||||||
this.num_cycles_at_cps_change = this.lastEnd;
|
this.checkpoint = {
|
||||||
this.seconds_at_cps_change = phase;
|
cycles: this.lastEnd,
|
||||||
|
seconds: phase,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
this.num_ticks_since_cps_change++;
|
this.num_ticks_since_checkpoint++;
|
||||||
const seconds_since_cps_change = this.num_ticks_since_cps_change * duration;
|
|
||||||
const num_cycles_since_cps_change = seconds_since_cps_change * this.cps;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const begin = this.lastEnd;
|
var begin = this.lastEnd;
|
||||||
this.lastBegin = begin;
|
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.lastEnd = end;
|
||||||
this.lastTick = phase;
|
this.lastTick = phase;
|
||||||
|
|
||||||
@@ -62,20 +65,79 @@ export class Cyclist {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// query the pattern for events
|
const tickEndTime = phase + duration;
|
||||||
const haps = this.pattern.queryArc(begin, end, { _cps: this.cps, cyclist: 'cyclist' });
|
|
||||||
|
|
||||||
haps.forEach((hap) => {
|
var cpsChanged = false;
|
||||||
if (hap.hasOnset()) {
|
do {
|
||||||
const targetTime =
|
cpsChanged = false;
|
||||||
(hap.whole.begin - this.num_cycles_at_cps_change) / this.cps + this.seconds_at_cps_change + latency;
|
|
||||||
onSchedule?.(hap, targetTime, this.cps);
|
// 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) {
|
if (hap.value.cps !== undefined && this.cps != hap.value.cps) {
|
||||||
|
cpsChanged = true;
|
||||||
this.cps = hap.value.cps;
|
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) {
|
} catch (e) {
|
||||||
errorLogger(e);
|
errorLogger(e);
|
||||||
onError?.(e);
|
onError?.(e);
|
||||||
@@ -101,8 +163,11 @@ export class Cyclist {
|
|||||||
}
|
}
|
||||||
async start() {
|
async start() {
|
||||||
await this.beforeStart?.();
|
await this.beforeStart?.();
|
||||||
this.num_ticks_since_cps_change = 0;
|
this.checkpoint = {
|
||||||
this.num_cycles_at_cps_change = 0;
|
cycles: 0,
|
||||||
|
seconds: 0,
|
||||||
|
};
|
||||||
|
this.num_ticks_since_checkpoint = 0;
|
||||||
if (!this.pattern) {
|
if (!this.pattern) {
|
||||||
throw new Error('Scheduler: no pattern set! call .setPattern first.');
|
throw new Error('Scheduler: no pattern set! call .setPattern first.');
|
||||||
}
|
}
|
||||||
@@ -132,7 +197,7 @@ export class Cyclist {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.cps = cps;
|
this.cps = cps;
|
||||||
this.num_ticks_since_cps_change = 0;
|
this.num_ticks_since_checkpoint = 0;
|
||||||
}
|
}
|
||||||
log(begin, end, haps) {
|
log(begin, end, haps) {
|
||||||
const onsets = haps.filter((h) => h.hasOnset());
|
const onsets = haps.filter((h) => h.hasOnset());
|
||||||
|
|||||||
@@ -420,7 +420,7 @@ export const binaryNL = (n, nBits = 16) => {
|
|||||||
* .partials(randL(8))
|
* .partials(randL(8))
|
||||||
*/
|
*/
|
||||||
export const randL = (n) => {
|
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) => {
|
export const randrun = (n) => {
|
||||||
|
|||||||
@@ -29,10 +29,10 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://codeberg.org/uzu/strudel/",
|
"homepage": "https://codeberg.org/uzu/strudel/",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"web-tree-sitter": "^0.24.7"
|
"web-tree-sitter": "^0.24.7",
|
||||||
|
"tree-sitter-haskell": "^0.23.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tree-sitter-haskell": "^0.23.1",
|
|
||||||
"vite": "^6.0.11"
|
"vite": "^6.0.11"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import Parser from 'web-tree-sitter';
|
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) {
|
export function setBase(path) {
|
||||||
base = path;
|
base = path;
|
||||||
}
|
}
|
||||||
@@ -10,11 +12,15 @@ let isReady = false,
|
|||||||
async function _loadParser() {
|
async function _loadParser() {
|
||||||
await Parser.init({
|
await Parser.init({
|
||||||
locateFile(scriptName, scriptDirectory) {
|
locateFile(scriptName, scriptDirectory) {
|
||||||
return `${base}${scriptName}`;
|
if (base) {
|
||||||
|
return `${base}${scriptName}`;
|
||||||
|
}
|
||||||
|
return treeSitterWasm;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
parser = new Parser();
|
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);
|
parser.setLanguage(Lang);
|
||||||
isReady = true;
|
isReady = true;
|
||||||
return parser;
|
return parser;
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
pattern.wav
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# supradough
|
|
||||||
|
|
||||||
platform agnostic synth and sampler intended for live coding. a reimplementation of superdough.
|
|
||||||
@@ -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));
|
|
||||||
});
|
|
||||||
@@ -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
@@ -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;
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Experimental Tidal Code interpreter",
|
"description": "Experimental Tidal Code interpreter",
|
||||||
|
"main": "tidal.mjs",
|
||||||
"module": "tidal.mjs",
|
"module": "tidal.mjs",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -94,9 +94,6 @@ export function getWidgetID(widgetConfig) {
|
|||||||
|
|
||||||
function widgetWithLocation(node, widgetConfig) {
|
function widgetWithLocation(node, widgetConfig) {
|
||||||
const id = getWidgetID(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
|
// add loc as identifier to first argument
|
||||||
// the sliderWithID function is assumed to be sliderWithID(id, value, min?, max?)
|
// the sliderWithID function is assumed to be sliderWithID(id, value, min?, max?)
|
||||||
node.arguments.unshift({
|
node.arguments.unshift({
|
||||||
|
|||||||
@@ -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 './webaudio.mjs';
|
||||||
export * from './scope.mjs';
|
export * from './scope.mjs';
|
||||||
export * from './spectrum.mjs';
|
export * from './spectrum.mjs';
|
||||||
export * from './supradough.mjs';
|
|
||||||
export * from 'superdough';
|
export * from 'superdough';
|
||||||
|
|||||||
@@ -35,8 +35,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel/core": "workspace:*",
|
"@strudel/core": "workspace:*",
|
||||||
"@strudel/draw": "workspace:*",
|
"@strudel/draw": "workspace:*",
|
||||||
"superdough": "workspace:*",
|
"superdough": "workspace:*"
|
||||||
"supradough": "workspace:*"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^6.0.11"
|
"vite": "^6.0.11"
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -17,10 +17,7 @@ import {
|
|||||||
resetGlobalEffects,
|
resetGlobalEffects,
|
||||||
errorLogger,
|
errorLogger,
|
||||||
} from 'superdough';
|
} from 'superdough';
|
||||||
import './supradough.mjs';
|
|
||||||
import { workletUrl } from 'supradough';
|
|
||||||
import { SuperdoughAudioController } from 'superdough/superdoughoutput.mjs';
|
import { SuperdoughAudioController } from 'superdough/superdoughoutput.mjs';
|
||||||
registerWorklet(workletUrl);
|
|
||||||
|
|
||||||
const { Pattern, logger, repl } = strudel;
|
const { Pattern, logger, repl } = strudel;
|
||||||
|
|
||||||
|
|||||||
Generated
+3
-23
@@ -359,13 +359,13 @@ importers:
|
|||||||
|
|
||||||
packages/hs2js:
|
packages/hs2js:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
tree-sitter-haskell:
|
||||||
|
specifier: ^0.23.1
|
||||||
|
version: 0.23.1(tree-sitter@0.21.1)
|
||||||
web-tree-sitter:
|
web-tree-sitter:
|
||||||
specifier: ^0.24.7
|
specifier: ^0.24.7
|
||||||
version: 0.24.7
|
version: 0.24.7
|
||||||
devDependencies:
|
devDependencies:
|
||||||
tree-sitter-haskell:
|
|
||||||
specifier: ^0.23.1
|
|
||||||
version: 0.23.1(tree-sitter@0.21.1)
|
|
||||||
vite:
|
vite:
|
||||||
specifier: ^6.0.11
|
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)
|
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:*
|
specifier: workspace:*
|
||||||
version: link:../vite-plugin-bundle-audioworklet
|
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:
|
packages/tidal:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@strudel/core':
|
'@strudel/core':
|
||||||
@@ -729,9 +717,6 @@ importers:
|
|||||||
superdough:
|
superdough:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../superdough
|
version: link:../superdough
|
||||||
supradough:
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../supradough
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^6.0.11
|
specifier: ^6.0.11
|
||||||
@@ -7782,9 +7767,6 @@ packages:
|
|||||||
walk-up-path@3.0.1:
|
walk-up-path@3.0.1:
|
||||||
resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==}
|
resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==}
|
||||||
|
|
||||||
wav-encoder@1.3.0:
|
|
||||||
resolution: {integrity: sha512-FXJdEu2qDOI+wbVYZpu21CS1vPEg5NaxNskBr4SaULpOJMrLE6xkH8dECa7PiS+ZoeyvP7GllWUAxPN3AvFSEw==}
|
|
||||||
|
|
||||||
wav@1.0.2:
|
wav@1.0.2:
|
||||||
resolution: {integrity: sha512-viHtz3cDd/Tcr/HbNqzQCofKdF6kWUymH9LGDdskfWFoIy/HJ+RTihgjEcHfnsy1PO4e9B+y4HwgTwMrByquhg==}
|
resolution: {integrity: sha512-viHtz3cDd/Tcr/HbNqzQCofKdF6kWUymH9LGDdskfWFoIy/HJ+RTihgjEcHfnsy1PO4e9B+y4HwgTwMrByquhg==}
|
||||||
|
|
||||||
@@ -16365,8 +16347,6 @@ snapshots:
|
|||||||
|
|
||||||
walk-up-path@3.0.1: {}
|
walk-up-path@3.0.1: {}
|
||||||
|
|
||||||
wav-encoder@1.3.0: {}
|
|
||||||
|
|
||||||
wav@1.0.2:
|
wav@1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer-alloc: 1.2.0
|
buffer-alloc: 1.2.0
|
||||||
|
|||||||
@@ -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`] = `
|
exports[`runs examples > example "delaysync" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd delay:0.25 delaysync:0.125 ]",
|
"[ 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`] = `
|
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 ]",
|
"[ 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 delayspeed:2 ]",
|
"[ 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 delayspeed:2 ]",
|
"[ 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 delayspeed:2 ]",
|
"[ 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 delayspeed:2 ]",
|
"[ 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 delayspeed:2 ]",
|
"[ 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 delayspeed:2 ]",
|
"[ 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 delayspeed:2 ]",
|
"[ 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 delayspeed: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 delayspeed: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 delayspeed: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 delayspeed: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 delayspeed: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 delayspeed: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 delayspeed: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 delayspeed: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 delayspeed:-1 ]",
|
"[ 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 delayspeed:-1 ]",
|
"[ 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 delayspeed:-1 ]",
|
"[ 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 delayspeed:-1 ]",
|
"[ 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 delayspeed:-1 ]",
|
"[ 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 delayspeed:-1 ]",
|
"[ 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 delayspeed:-1 ]",
|
"[ 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 delayspeed:-1 ]",
|
"[ 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 delayspeed:-2 ]",
|
"[ 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 delayspeed:-2 ]",
|
"[ 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 delayspeed:-2 ]",
|
"[ 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 delayspeed:-2 ]",
|
"[ 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 delayspeed:-2 ]",
|
"[ 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 delayspeed:-2 ]",
|
"[ 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 delayspeed:-2 ]",
|
"[ 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 delayspeed:-2 ]",
|
"[ 31/8 → 4/1 | note:a s:sawtooth delay:0.8 delaytime:0.5 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ export default defineConfig({
|
|||||||
/^https:\/\/freesound\.org\/.*/i,
|
/^https:\/\/freesound\.org\/.*/i,
|
||||||
/^https:\/\/cdn\.freesound\.org\/.*/i,
|
/^https:\/\/cdn\.freesound\.org\/.*/i,
|
||||||
/^https:\/\/shabda\.ndre\.gr\/.*/i,
|
/^https:\/\/shabda\.ndre\.gr\/.*/i,
|
||||||
|
/^https:\/\/felixroos\.github\.io\/webaudiofontdata\/.*/i,
|
||||||
].some((regex) => regex.test(url)),
|
].some((regex) => regex.test(url)),
|
||||||
handler: 'CacheFirst',
|
handler: 'CacheFirst',
|
||||||
options: {
|
options: {
|
||||||
|
|||||||
@@ -5,9 +5,8 @@ import { Textbox } from '@src/repl/components/panel/SettingsTab';
|
|||||||
import { settingsMap, useSettings } from '@src/settings.mjs';
|
import { settingsMap, useSettings } from '@src/settings.mjs';
|
||||||
|
|
||||||
const isValid = ({ name, description, tags = [] }) => {
|
const isValid = ({ name, description, tags = [] }) => {
|
||||||
const isSupradoughOnly = tags.includes('supradough') && !tags.includes('superdough');
|
|
||||||
const isSuperdirtOnly = tags.includes('superdirt') && !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 = (() => {
|
const availableFunctions = (() => {
|
||||||
@@ -38,7 +37,7 @@ const availableFunctions = (() => {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
const tagCounts = {};
|
const tagCounts = {};
|
||||||
const ignoredTags = ['supradough', 'superdirt'];
|
const ignoredTags = ['superdirt'];
|
||||||
// const tagOptions = { all: `all (${availableFunctions.length})` };
|
// const tagOptions = { all: `all (${availableFunctions.length})` };
|
||||||
const tagOptions = { all: `all` };
|
const tagOptions = { all: `all` };
|
||||||
for (const doc of availableFunctions) {
|
for (const doc of availableFunctions) {
|
||||||
|
|||||||
Reference in New Issue
Block a user