mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-26 13:08:28 +00:00
Merge branch 'tidalcycles:main' into main
This commit is contained in:
commit
ef7182cd76
@ -46,14 +46,15 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://strudel.tidalcycles.org",
|
"homepage": "https://strudel.tidalcycles.org",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dependency-tree": "^9.0.0",
|
|
||||||
"vitest": "^0.25.7",
|
|
||||||
"@strudel.cycles/core": "workspace:*",
|
"@strudel.cycles/core": "workspace:*",
|
||||||
"@strudel.cycles/mini": "workspace:*",
|
"@strudel.cycles/mini": "workspace:*",
|
||||||
"@strudel.cycles/tonal": "workspace:*",
|
"@strudel.cycles/tonal": "workspace:*",
|
||||||
"@strudel.cycles/transpiler": "workspace:*",
|
"@strudel.cycles/transpiler": "workspace:*",
|
||||||
"@strudel.cycles/webaudio": "workspace:*",
|
"@strudel.cycles/webaudio": "workspace:*",
|
||||||
"@strudel.cycles/xen": "workspace:*"
|
"@strudel.cycles/xen": "workspace:*",
|
||||||
|
"acorn": "^8.8.1",
|
||||||
|
"dependency-tree": "^9.0.0",
|
||||||
|
"vitest": "^0.25.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitest/ui": "^0.25.7",
|
"@vitest/ui": "^0.25.7",
|
||||||
|
|||||||
@ -4,20 +4,25 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
|
|||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Pattern, sequence, registerControl } from './pattern.mjs';
|
import { Pattern, sequence } from './pattern.mjs';
|
||||||
|
import { zipWith } from './util.mjs';
|
||||||
|
|
||||||
const controls = {};
|
const controls = {};
|
||||||
const generic_params = [
|
const generic_params = [
|
||||||
/**
|
/**
|
||||||
* Select a sound / sample by name.
|
* Select a sound / sample by name. When using mininotation, you can also optionally supply 'n' and 'gain' parameters
|
||||||
|
* separated by ':'.
|
||||||
*
|
*
|
||||||
* @name s
|
* @name s
|
||||||
* @param {string | Pattern} sound The sound / pattern of sounds to pick
|
* @param {string | Pattern} sound The sound / pattern of sounds to pick
|
||||||
|
* @synonyms sound
|
||||||
* @example
|
* @example
|
||||||
* s("bd hh")
|
* s("bd hh")
|
||||||
|
* @example
|
||||||
|
* s("bd:0 bd:1 bd:0:0.3 bd:1:1.4")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['s', 's', 'sound'],
|
[['s', 'n', 'gain'], 'sound'],
|
||||||
/**
|
/**
|
||||||
* Selects the given index from the sample map.
|
* Selects the given index from the sample map.
|
||||||
* Numbers too high will wrap around.
|
* Numbers too high will wrap around.
|
||||||
@ -29,7 +34,7 @@ const generic_params = [
|
|||||||
* s("bd sd,hh*3").n("<0 1>")
|
* s("bd sd,hh*3").n("<0 1>")
|
||||||
*/
|
*/
|
||||||
// also see https://github.com/tidalcycles/strudel/pull/63
|
// also see https://github.com/tidalcycles/strudel/pull/63
|
||||||
['f', 'n', 'The sample number to choose for a synth or sampleset'],
|
['n'],
|
||||||
/**
|
/**
|
||||||
* Plays the given note name or midi number. A note name consists of
|
* Plays the given note name or midi number. A note name consists of
|
||||||
*
|
*
|
||||||
@ -49,10 +54,8 @@ const generic_params = [
|
|||||||
* @example
|
* @example
|
||||||
* note("60 69 65 64")
|
* note("60 69 65 64")
|
||||||
*/
|
*/
|
||||||
['f', 'note', 'The note or pitch to play a sound or synth with'],
|
[['note', 'n']],
|
||||||
//['s', 'toArg', 'for internal sound routing'],
|
|
||||||
// ["f", "from", "for internal sound routing"),
|
|
||||||
//['f', 'to', 'for internal sound routing'],
|
|
||||||
/**
|
/**
|
||||||
* A pattern of numbers that speed up (or slow down) samples while they play. Currently only supported by osc / superdirt.
|
* A pattern of numbers that speed up (or slow down) samples while they play. Currently only supported by osc / superdirt.
|
||||||
*
|
*
|
||||||
@ -63,7 +66,7 @@ const generic_params = [
|
|||||||
* s("sax").accelerate("<0 1 2 4 8 16>").slow(2).osc()
|
* s("sax").accelerate("<0 1 2 4 8 16>").slow(2).osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'accelerate', 'a pattern of numbers that speed up (or slow down) samples while they play.'],
|
['accelerate'],
|
||||||
/**
|
/**
|
||||||
* Controls the gain by an exponential amount.
|
* Controls the gain by an exponential amount.
|
||||||
*
|
*
|
||||||
@ -73,11 +76,7 @@ const generic_params = [
|
|||||||
* s("hh*8").gain(".4!2 1 .4!2 1 .4 1")
|
* s("hh*8").gain(".4!2 1 .4!2 1 .4 1")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['gain'],
|
||||||
'f',
|
|
||||||
'gain',
|
|
||||||
'a pattern of numbers that specify volume. Values less than 1 make the sound quieter. Values greater than 1 make the sound louder. For the linear equivalent, see @amp@.',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* Like {@link gain}, but linear.
|
* Like {@link gain}, but linear.
|
||||||
*
|
*
|
||||||
@ -88,17 +87,18 @@ const generic_params = [
|
|||||||
* s("bd*8").amp(".1*2 .5 .1*2 .5 .1 .5").osc()
|
* s("bd*8").amp(".1*2 .5 .1*2 .5 .1 .5").osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'amp', 'like @gain@, but linear.'],
|
['amp'],
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* @param {number | Pattern} attack time in seconds.
|
* @param {number | Pattern} attack time in seconds.
|
||||||
|
* @synonyms att
|
||||||
* @example
|
* @example
|
||||||
* note("c3 e3").attack("<0 .1 .5>")
|
* note("c3 e3").attack("<0 .1 .5>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'attack'],
|
['attack', 'att'],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select the sound bank to use. To be used together with `s`. The bank name (+ "_") will be prepended to the value of `s`.
|
* Select the sound bank to use. To be used together with `s`. The bank name (+ "_") will be prepended to the value of `s`.
|
||||||
@ -109,7 +109,7 @@ const generic_params = [
|
|||||||
* s("bd sd").bank('RolandTR909') // = s("RolandTR909_bd RolandTR909_sd")
|
* s("bd sd").bank('RolandTR909') // = s("RolandTR909_bd RolandTR909_sd")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'bank', 'selects sound bank to use'],
|
['bank'],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amplitude envelope decay time: the time it takes after the attack time to reach the sustain level.
|
* Amplitude envelope decay time: the time it takes after the attack time to reach the sustain level.
|
||||||
@ -121,52 +121,46 @@ const generic_params = [
|
|||||||
* note("c3 e3").decay("<.1 .2 .3 .4>").sustain(0)
|
* note("c3 e3").decay("<.1 .2 .3 .4>").sustain(0)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'decay', ''],
|
['decay'],
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* @param {number | Pattern} gain sustain level between 0 and 1
|
* @param {number | Pattern} gain sustain level between 0 and 1
|
||||||
|
* @synonyms sus
|
||||||
* @example
|
* @example
|
||||||
* note("c3 e3").decay(.2).sustain("<0 .1 .4 .6 1>")
|
* note("c3 e3").decay(.2).sustain("<0 .1 .4 .6 1>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'sustain', ''],
|
['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
|
||||||
* @param {number | Pattern} time release time in seconds
|
* @param {number | Pattern} time release time in seconds
|
||||||
|
* @synonyms rel
|
||||||
* @example
|
* @example
|
||||||
* note("c3 e3 g3 c4").release("<0 .1 .4 .6 1>/2")
|
* note("c3 e3 g3 c4").release("<0 .1 .4 .6 1>/2")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['release', 'rel'],
|
||||||
'f',
|
['hold'],
|
||||||
'release',
|
|
||||||
'a pattern of numbers to specify the release time (in seconds) of an envelope applied to each sample.',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'f',
|
|
||||||
'hold',
|
|
||||||
'a pattern of numbers to specify the hold time (in seconds) of an envelope applied to each sample. Only takes effect if `attack` and `release` are also specified.',
|
|
||||||
],
|
|
||||||
// TODO: in tidal, it seems to be normalized
|
// TODO: in tidal, it seems to be normalized
|
||||||
/**
|
/**
|
||||||
* Sets the center frequency of the **b**and-**p**ass **f**ilter.
|
* Sets the center frequency of the **b**and-**p**ass **f**ilter. When using mininotation, you
|
||||||
|
* can also optionally supply the 'bpq' parameter separated by ':'.
|
||||||
*
|
*
|
||||||
* @name bpf
|
* @name bpf
|
||||||
* @param {number | Pattern} frequency center frequency
|
* @param {number | Pattern} frequency center frequency
|
||||||
* @synonyms bandf
|
* @synonyms bandf, bp
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd,hh*3").bpf("<1000 2000 4000 8000>")
|
* s("bd sd,hh*3").bpf("<1000 2000 4000 8000>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'bpf', ''],
|
[['bandf', 'bandq'], 'bpf', 'bp'],
|
||||||
['f', 'bandf', 'A pattern of numbers from 0 to 1. Sets the center frequency of the band-pass filter.'],
|
|
||||||
// TODO: in tidal, it seems to be normalized
|
// TODO: in tidal, it seems to be normalized
|
||||||
/**
|
/**
|
||||||
* Sets the **b**and-**p**ass **q**-factor (resonance)
|
* Sets the **b**and-**p**ass **q**-factor (resonance).
|
||||||
*
|
*
|
||||||
* @name bpq
|
* @name bpq
|
||||||
* @param {number | Pattern} q q factor
|
* @param {number | Pattern} q q factor
|
||||||
@ -175,8 +169,9 @@ const generic_params = [
|
|||||||
* s("bd sd").bpf(500).bpq("<0 1 2 3>")
|
* s("bd sd").bpf(500).bpq("<0 1 2 3>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'bpq', ''],
|
// currently an alias of 'bandq' https://github.com/tidalcycles/strudel/issues/496
|
||||||
['f', 'bandq', 'a pattern of anumbers from 0 to 1. Sets the q-factor of the band-pass filter.'],
|
// ['bpq'],
|
||||||
|
['bandq', 'bpq'],
|
||||||
/**
|
/**
|
||||||
* a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.
|
* a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.
|
||||||
*
|
*
|
||||||
@ -188,11 +183,7 @@ const generic_params = [
|
|||||||
* s("rave").begin("<0 .25 .5 .75>")
|
* s("rave").begin("<0 .25 .5 .75>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['begin'],
|
||||||
'f',
|
|
||||||
'begin',
|
|
||||||
'a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* The same as .begin, but cuts off the end off each sample.
|
* The same as .begin, but cuts off the end off each sample.
|
||||||
*
|
*
|
||||||
@ -203,11 +194,7 @@ const generic_params = [
|
|||||||
* s("bd*2,oh*4").end("<.1 .2 .5 1>")
|
* s("bd*2,oh*4").end("<.1 .2 .5 1>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['end'],
|
||||||
'f',
|
|
||||||
'end',
|
|
||||||
'the same as `begin`, but cuts the end off samples, shortening them; e.g. `0.75` to cut off the last quarter of each sample.',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* Loops the sample (from `begin` to `end`) the specified number of times.
|
* Loops the sample (from `begin` to `end`) the specified number of times.
|
||||||
* Note that the tempo of the loop is not synced with the cycle tempo.
|
* Note that the tempo of the loop is not synced with the cycle tempo.
|
||||||
@ -218,7 +205,7 @@ const generic_params = [
|
|||||||
* s("bd").loop("<1 2 3 4>").osc()
|
* s("bd").loop("<1 2 3 4>").osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'loop', 'loops the sample (from `begin` to `end`) the specified number of times.'],
|
['loop'],
|
||||||
// TODO: currently duplicated with "native" legato
|
// TODO: currently duplicated with "native" legato
|
||||||
// TODO: superdirt legato will do more: https://youtu.be/dQPmE1WaD1k?t=419
|
// TODO: superdirt legato will do more: https://youtu.be/dQPmE1WaD1k?t=419
|
||||||
/**
|
/**
|
||||||
@ -230,8 +217,8 @@ const generic_params = [
|
|||||||
* "c4 eb4 g4 bb4".legato("<0.125 .25 .5 .75 1 2 4>")
|
* "c4 eb4 g4 bb4".legato("<0.125 .25 .5 .75 1 2 4>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// ['f', 'legato', 'controls the amount of overlap between two adjacent sounds'],
|
// ['legato'],
|
||||||
// ['f', 'clhatdecay', ''],
|
// ['clhatdecay'],
|
||||||
/**
|
/**
|
||||||
* bit crusher effect.
|
* bit crusher effect.
|
||||||
*
|
*
|
||||||
@ -241,11 +228,7 @@ const generic_params = [
|
|||||||
* 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>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['crush'],
|
||||||
'f',
|
|
||||||
'crush',
|
|
||||||
'bit crushing, a pattern of numbers from 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*
|
*
|
||||||
@ -255,11 +238,7 @@ const generic_params = [
|
|||||||
* s("bd sd,hh*4").coarse("<1 4 8 16 32>")
|
* s("bd sd,hh*4").coarse("<1 4 8 16 32>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['coarse'],
|
||||||
'f',
|
|
||||||
'coarse',
|
|
||||||
'fake-resampling, a pattern of numbers for lowering the sample rate, i.e. 1 for original 2 for half, 3 for a third and so on.',
|
|
||||||
],
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* choose the channel the pattern is sent to in superdirt
|
* choose the channel the pattern is sent to in superdirt
|
||||||
@ -268,7 +247,7 @@ const generic_params = [
|
|||||||
* @param {number | Pattern} channel channel number
|
* @param {number | Pattern} channel channel number
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['i', 'channel', 'choose the channel the pattern is sent to in superdirt'],
|
['channel'],
|
||||||
/**
|
/**
|
||||||
* In the style of classic drum-machines, `cut` will stop a playing sample as soon as another samples with in same cutgroup is to be played. An example would be an open hi-hat followed by a closed one, essentially muting the open.
|
* In the style of classic drum-machines, `cut` will stop a playing sample as soon as another samples with in same cutgroup is to be played. An example would be an open hi-hat followed by a closed one, essentially muting the open.
|
||||||
*
|
*
|
||||||
@ -278,35 +257,39 @@ const generic_params = [
|
|||||||
* s("rd*4").cut(1)
|
* s("rd*4").cut(1)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['cut'],
|
||||||
'i',
|
|
||||||
'cut',
|
|
||||||
'In the style of classic drum-machines, `cut` will stop a playing sample as soon as another samples with in same cutgroup is to be played. An example would be an open hi-hat followed by a closed one, essentially muting the open.',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* Applies the cutoff frequency of the **l**ow-**p**ass **f**ilter.
|
* Applies the cutoff frequency of the **l**ow-**p**ass **f**ilter.
|
||||||
*
|
*
|
||||||
|
* When using mininotation, you can also optionally add the 'lpq' parameter, separated by ':'.
|
||||||
|
*
|
||||||
* @name lpf
|
* @name lpf
|
||||||
* @param {number | Pattern} frequency audible between 0 and 20000
|
* @param {number | Pattern} frequency audible between 0 and 20000
|
||||||
* @synonyms cutoff
|
* @synonyms cutoff, ctf, lp
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd,hh*3").lpf("<4000 2000 1000 500 200 100>")
|
* s("bd sd,hh*3").lpf("<4000 2000 1000 500 200 100>")
|
||||||
|
* @example
|
||||||
|
* s("bd*8").lpf("1000:0 1000:10 1000:20 1000:30")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'lpf'],
|
[['cutoff', 'resonance'], 'ctf', 'lpf', 'lp'],
|
||||||
['f', 'cutoff', 'a pattern of numbers from 0 to 1. Applies the cutoff frequency of the low-pass filter.'],
|
|
||||||
/**
|
/**
|
||||||
* Applies the cutoff frequency of the **h**igh-**p**ass **f**ilter.
|
* Applies the cutoff frequency of the **h**igh-**p**ass **f**ilter.
|
||||||
*
|
*
|
||||||
|
* When using mininotation, you can also optionally add the 'hpq' parameter, separated by ':'.
|
||||||
|
*
|
||||||
* @name hpf
|
* @name hpf
|
||||||
* @param {number | Pattern} frequency audible between 0 and 20000
|
* @param {number | Pattern} frequency audible between 0 and 20000
|
||||||
* @synonyms hcutoff
|
* @synonyms hp, hcutoff
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd,hh*4").hpf("<4000 2000 1000 500 200 100>")
|
* s("bd sd,hh*4").hpf("<4000 2000 1000 500 200 100>")
|
||||||
|
* @example
|
||||||
|
* s("bd sd,hh*4").hpf("<2000 2000:25>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'hpf', ''],
|
// currently an alias of 'hcutoff' https://github.com/tidalcycles/strudel/issues/496
|
||||||
['f', 'hcutoff', ''],
|
// ['hpf'],
|
||||||
|
[['hcutoff', 'hresonance'], 'hpf', 'hp'],
|
||||||
/**
|
/**
|
||||||
* Controls the **h**igh-**p**ass **q**-value.
|
* Controls the **h**igh-**p**ass **q**-value.
|
||||||
*
|
*
|
||||||
@ -317,8 +300,7 @@ const generic_params = [
|
|||||||
* s("bd sd,hh*4").hpf(2000).hpq("<0 10 20 30>")
|
* s("bd sd,hh*4").hpf(2000).hpq("<0 10 20 30>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'hresonance', ''],
|
['hresonance', 'hpq'],
|
||||||
['f', 'hpq', ''],
|
|
||||||
/**
|
/**
|
||||||
* Controls the **l**ow-**p**ass **q**-value.
|
* Controls the **l**ow-**p**ass **q**-value.
|
||||||
*
|
*
|
||||||
@ -329,8 +311,8 @@ const generic_params = [
|
|||||||
* s("bd sd,hh*4").lpf(2000).lpq("<0 10 20 30>")
|
* s("bd sd,hh*4").lpf(2000).lpq("<0 10 20 30>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'lpq'],
|
// currently an alias of 'resonance' https://github.com/tidalcycles/strudel/issues/496
|
||||||
['f', 'resonance', ''],
|
['resonance', 'lpq'],
|
||||||
/**
|
/**
|
||||||
* DJ filter, below 0.5 is low pass filter, above is high pass filter.
|
* DJ filter, below 0.5 is low pass filter, above is high pass filter.
|
||||||
*
|
*
|
||||||
@ -340,40 +322,48 @@ const generic_params = [
|
|||||||
* n("0 3 7 [10,24]").s('superzow').octave(3).djf("<.5 .25 .5 .75>").osc()
|
* n("0 3 7 [10,24]").s('superzow').octave(3).djf("<.5 .25 .5 .75>").osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'djf', 'DJ filter, below 0.5 is low pass filter, above is high pass filter.'],
|
['djf'],
|
||||||
// ['f', 'cutoffegint', ''],
|
// ['cutoffegint'],
|
||||||
// TODO: does not seem to work
|
// TODO: does not seem to work
|
||||||
/**
|
/**
|
||||||
* Sets the level of the delay signal.
|
* Sets the level of the delay signal.
|
||||||
*
|
*
|
||||||
|
* When using mininotation, you can also optionally add the 'delaytime' and 'delayfeedback' parameter,
|
||||||
|
* separated by ':'.
|
||||||
|
*
|
||||||
|
*
|
||||||
* @name delay
|
* @name delay
|
||||||
* @param {number | Pattern} level between 0 and 1
|
* @param {number | Pattern} level between 0 and 1
|
||||||
* @example
|
* @example
|
||||||
* s("bd").delay("<0 .25 .5 1>")
|
* s("bd").delay("<0 .25 .5 1>")
|
||||||
|
* @example
|
||||||
|
* s("bd bd").delay("0.65:0.25:0.9 0.65:0.125:0.7")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'delay', 'a pattern of numbers from 0 to 1. Sets the level of the delay signal.'],
|
[['delay', 'delaytime', 'delayfeedback']],
|
||||||
/**
|
/**
|
||||||
* Sets the level of the signal that is fed back into the delay.
|
* Sets the level of the signal that is fed back into the delay.
|
||||||
* 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
|
||||||
* @param {number | Pattern} feedback between 0 and 1
|
* @param {number | Pattern} feedback between 0 and 1
|
||||||
|
* @synonyms delayfb, dfb
|
||||||
* @example
|
* @example
|
||||||
* s("bd").delay(.25).delayfeedback("<.25 .5 .75 1>").slow(2)
|
* s("bd").delay(.25).delayfeedback("<.25 .5 .75 1>").slow(2)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'delayfeedback', 'a pattern of numbers from 0 to 1. Sets the amount of delay feedback.'],
|
['delayfeedback', 'delayfb', 'dfb'],
|
||||||
/**
|
/**
|
||||||
* Sets the time of the delay effect.
|
* Sets the time of the delay effect.
|
||||||
*
|
*
|
||||||
* @name delaytime
|
* @name delaytime
|
||||||
* @param {number | Pattern} seconds between 0 and Infinity
|
* @param {number | Pattern} seconds between 0 and Infinity
|
||||||
|
* @synonyms delayt, dt
|
||||||
* @example
|
* @example
|
||||||
* s("bd").delay(.25).delaytime("<.125 .25 .5 1>").slow(2)
|
* s("bd").delay(.25).delaytime("<.125 .25 .5 1>").slow(2)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'delaytime', 'a pattern of numbers from 0 to 1. Sets the length of the delay.'],
|
['delaytime', 'delayt', 'dt'],
|
||||||
/* // TODO: test
|
/* // TODO: test
|
||||||
* Specifies whether delaytime is calculated relative to cps.
|
* Specifies whether delaytime is calculated relative to cps.
|
||||||
*
|
*
|
||||||
@ -383,22 +373,19 @@ const generic_params = [
|
|||||||
* s("sd").delay().lock(1).osc()
|
* s("sd").delay().lock(1).osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['lock'],
|
||||||
'f',
|
|
||||||
'lock',
|
|
||||||
'A pattern of numbers. Specifies whether delaytime is calculated relative to cps. When set to 1, delaytime is a direct multiple of a cycle.',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* Set detune of oscillators. Works only with some synths, see <a target="_blank" href="https://tidalcycles.org/docs/patternlib/tutorials/synthesizers">tidal doc</a>
|
* Set detune of oscillators. Works only with some synths, see <a target="_blank" href="https://tidalcycles.org/docs/patternlib/tutorials/synthesizers">tidal doc</a>
|
||||||
*
|
*
|
||||||
* @name detune
|
* @name detune
|
||||||
* @param {number | Pattern} amount between 0 and 1
|
* @param {number | Pattern} amount between 0 and 1
|
||||||
|
* @synonyms det
|
||||||
* @superdirtOnly
|
* @superdirtOnly
|
||||||
* @example
|
* @example
|
||||||
* n("0 3 7").s('superzow').octave(3).detune("<0 .25 .5 1 2>").osc()
|
* n("0 3 7").s('superzow').octave(3).detune("<0 .25 .5 1 2>").osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'detune', ''],
|
['detune', 'det'],
|
||||||
/**
|
/**
|
||||||
* Set dryness of reverb. See {@link room} and {@link size} for more information about reverb.
|
* Set dryness of reverb. See {@link room} and {@link size} for more information about reverb.
|
||||||
*
|
*
|
||||||
@ -409,11 +396,7 @@ const generic_params = [
|
|||||||
* @superdirtOnly
|
* @superdirtOnly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['dry'],
|
||||||
'f',
|
|
||||||
'dry',
|
|
||||||
'when set to `1` will disable all reverb for this pattern. See `room` and `size` for more information about reverb.',
|
|
||||||
],
|
|
||||||
// TODO: does not seem to do anything
|
// TODO: does not seem to do anything
|
||||||
/*
|
/*
|
||||||
* Used when using {@link begin}/{@link end} or {@link chop}/{@link striate} and friends, to change the fade out time of the 'grain' envelope.
|
* Used when using {@link begin}/{@link end} or {@link chop}/{@link striate} and friends, to change the fade out time of the 'grain' envelope.
|
||||||
@ -424,17 +407,9 @@ const generic_params = [
|
|||||||
* s("oh*4").end(.1).fadeTime("<0 .2 .4 .8>").osc()
|
* s("oh*4").end(.1).fadeTime("<0 .2 .4 .8>").osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['fadeTime', 'fadeOutTime'],
|
||||||
'f',
|
|
||||||
'fadeTime',
|
|
||||||
"Used when using begin/end or chop/striate and friends, to change the fade out time of the 'grain' envelope.",
|
|
||||||
],
|
|
||||||
// TODO: see above
|
// TODO: see above
|
||||||
[
|
['fadeInTime'],
|
||||||
'f',
|
|
||||||
'fadeInTime',
|
|
||||||
'As with fadeTime, but controls the fade in time of the grain envelope. Not used if the grain begins at position 0 in the sample.',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* Set frequency of sound.
|
* Set frequency of sound.
|
||||||
*
|
*
|
||||||
@ -446,15 +421,15 @@ const generic_params = [
|
|||||||
* freq("110".mul.out(".5 1.5 .6 [2 3]")).s("superzow").osc()
|
* freq("110".mul.out(".5 1.5 .6 [2 3]")).s("superzow").osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'freq', ''],
|
['freq'],
|
||||||
// TODO: https://tidalcycles.org/docs/configuration/MIDIOSC/control-voltage/#gate
|
// TODO: https://tidalcycles.org/docs/configuration/MIDIOSC/control-voltage/#gate
|
||||||
['f', 'gate', ''],
|
['gate', 'gat'],
|
||||||
// ['f', 'hatgrain', ''],
|
// ['hatgrain'],
|
||||||
// ['f', 'lagogo', ''],
|
// ['lagogo'],
|
||||||
// ['f', 'lclap', ''],
|
// ['lclap'],
|
||||||
// ['f', 'lclaves', ''],
|
// ['lclaves'],
|
||||||
// ['f', 'lclhat', ''],
|
// ['lclhat'],
|
||||||
// ['f', 'lcrash', ''],
|
// ['lcrash'],
|
||||||
// TODO:
|
// TODO:
|
||||||
// https://tidalcycles.org/docs/reference/audio_effects/#leslie-1
|
// https://tidalcycles.org/docs/reference/audio_effects/#leslie-1
|
||||||
// https://tidalcycles.org/docs/reference/audio_effects/#leslie
|
// https://tidalcycles.org/docs/reference/audio_effects/#leslie
|
||||||
@ -468,7 +443,7 @@ const generic_params = [
|
|||||||
* @superdirtOnly
|
* @superdirtOnly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'leslie', ''],
|
['leslie'],
|
||||||
/**
|
/**
|
||||||
* Rate of modulation / rotation for leslie effect
|
* Rate of modulation / rotation for leslie effect
|
||||||
*
|
*
|
||||||
@ -480,7 +455,7 @@ const generic_params = [
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// TODO: the rate seems to "lag" (in the example, 1 will be fast)
|
// TODO: the rate seems to "lag" (in the example, 1 will be fast)
|
||||||
['f', 'lrate', ''],
|
['lrate'],
|
||||||
/**
|
/**
|
||||||
* Physical size of the cabinet in meters. Be careful, it might be slightly larger than your computer. Affects the Doppler amount (pitch warble)
|
* Physical size of the cabinet in meters. Be careful, it might be slightly larger than your computer. Affects the Doppler amount (pitch warble)
|
||||||
*
|
*
|
||||||
@ -491,31 +466,28 @@ const generic_params = [
|
|||||||
* @superdirtOnly
|
* @superdirtOnly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'lsize', ''],
|
['lsize'],
|
||||||
// ['f', 'lfo', ''],
|
// ['lfo'],
|
||||||
// ['f', 'lfocutoffint', ''],
|
// ['lfocutoffint'],
|
||||||
// ['f', 'lfodelay', ''],
|
// ['lfodelay'],
|
||||||
// ['f', 'lfoint', ''],
|
// ['lfoint'],
|
||||||
// ['f', 'lfopitchint', ''],
|
// ['lfopitchint'],
|
||||||
// ['f', 'lfoshape', ''],
|
// ['lfoshape'],
|
||||||
// ['f', 'lfosync', ''],
|
// ['lfosync'],
|
||||||
// ['f', 'lhitom', ''],
|
// ['lhitom'],
|
||||||
// ['f', 'lkick', ''],
|
// ['lkick'],
|
||||||
// ['f', 'llotom', ''],
|
// ['llotom'],
|
||||||
// ['f', 'lophat', ''],
|
// ['lophat'],
|
||||||
// ['f', 'lsnare', ''],
|
// ['lsnare'],
|
||||||
['f', 'degree', ''], // TODO: what is this? not found in tidal doc
|
['degree'], // TODO: what is this? not found in tidal doc
|
||||||
['f', 'mtranspose', ''], // TODO: what is this? not found in tidal doc
|
['mtranspose'], // TODO: what is this? not found in tidal doc
|
||||||
['f', 'ctranspose', ''], // TODO: what is this? not found in tidal doc
|
['ctranspose'], // TODO: what is this? not found in tidal doc
|
||||||
['f', 'harmonic', ''], // TODO: what is this? not found in tidal doc
|
['harmonic'], // TODO: what is this? not found in tidal doc
|
||||||
['f', 'stepsPerOctave', ''], // TODO: what is this? not found in tidal doc
|
['stepsPerOctave'], // TODO: what is this? not found in tidal doc
|
||||||
['f', 'octaveR', ''], // TODO: what is this? not found in tidal doc
|
['octaveR'], // TODO: what is this? not found in tidal doc
|
||||||
// TODO: why is this needed? what's the difference to late / early?
|
// TODO: why is this needed? what's the difference to late / early? Answer: it's in seconds, and delays the message at
|
||||||
[
|
// OSC time (so can't be negative, at least not beyond the latency value)
|
||||||
'f',
|
['nudge'],
|
||||||
'nudge',
|
|
||||||
'Nudges events into the future by the specified number of seconds. Negative numbers work up to a point as well (due to internal latency)',
|
|
||||||
],
|
|
||||||
// TODO: the following doc is just a guess, it's not documented in tidal doc.
|
// TODO: the following doc is just a guess, it's not documented in tidal doc.
|
||||||
/**
|
/**
|
||||||
* Sets the default octave of a synth.
|
* Sets the default octave of a synth.
|
||||||
@ -526,9 +498,9 @@ const generic_params = [
|
|||||||
* n("0,4,7").s('supersquare').octave("<3 4 5 6>").osc()
|
* n("0,4,7").s('supersquare').octave("<3 4 5 6>").osc()
|
||||||
* @superDirtOnly
|
* @superDirtOnly
|
||||||
*/
|
*/
|
||||||
['i', 'octave', ''],
|
['octave'],
|
||||||
['f', 'offset', ''], // TODO: what is this? not found in tidal doc
|
['offset'], // TODO: what is this? not found in tidal doc
|
||||||
// ['f', 'ophatdecay', ''],
|
// ['ophatdecay'],
|
||||||
// TODO: example
|
// TODO: example
|
||||||
/**
|
/**
|
||||||
* An `orbit` is a global parameter context for patterns. Patterns with the same orbit will share the same global effects.
|
* An `orbit` is a global parameter context for patterns. Patterns with the same orbit will share the same global effects.
|
||||||
@ -541,13 +513,9 @@ const generic_params = [
|
|||||||
* s("~ sd").delay(.5).delaytime(.125).orbit(2)
|
* s("~ sd").delay(.5).delaytime(.125).orbit(2)
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
[
|
['orbit'],
|
||||||
'i',
|
['overgain'], // TODO: what is this? not found in tidal doc Answer: gain is limited to maximum of 2. This allows you to go over that
|
||||||
'orbit',
|
['overshape'], // TODO: what is this? not found in tidal doc. Similar to above, but limited to 1
|
||||||
'a pattern of numbers. An `orbit` is a global parameter context for patterns. Patterns with the same orbit will share hardware output bus offset and global effects, e.g. reverb and delay. The maximum number of orbits is specified in the superdirt startup, numbers higher than maximum will wrap around.',
|
|
||||||
],
|
|
||||||
['f', 'overgain', ''], // TODO: what is this? not found in tidal doc
|
|
||||||
['f', 'overshape', ''], // TODO: what is this? not found in tidal doc
|
|
||||||
/**
|
/**
|
||||||
* Sets position in stereo.
|
* Sets position in stereo.
|
||||||
*
|
*
|
||||||
@ -557,11 +525,7 @@ const generic_params = [
|
|||||||
* s("[bd hh]*2").pan("<.5 1 .5 0>")
|
* s("[bd hh]*2").pan("<.5 1 .5 0>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['pan'],
|
||||||
'f',
|
|
||||||
'pan',
|
|
||||||
'a pattern of numbers between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel)',
|
|
||||||
],
|
|
||||||
// TODO: this has no effect (see example)
|
// TODO: this has no effect (see example)
|
||||||
/*
|
/*
|
||||||
* Controls how much multichannel output is fanned out
|
* Controls how much multichannel output is fanned out
|
||||||
@ -572,11 +536,7 @@ const generic_params = [
|
|||||||
* s("[bd hh]*2").pan("<.5 1 .5 0>").panspan("<0 .5 1>").osc()
|
* s("[bd hh]*2").pan("<.5 1 .5 0>").panspan("<0 .5 1>").osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['panspan'],
|
||||||
'f',
|
|
||||||
'panspan',
|
|
||||||
'a pattern of numbers between -inf and inf, which controls how much multichannel output is fanned out (negative is backwards ordering)',
|
|
||||||
],
|
|
||||||
// TODO: this has no effect (see example)
|
// TODO: this has no effect (see example)
|
||||||
/*
|
/*
|
||||||
* Controls how much multichannel output is spread
|
* Controls how much multichannel output is spread
|
||||||
@ -587,50 +547,42 @@ const generic_params = [
|
|||||||
* s("[bd hh]*2").pan("<.5 1 .5 0>").pansplay("<0 .5 1>").osc()
|
* s("[bd hh]*2").pan("<.5 1 .5 0>").pansplay("<0 .5 1>").osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['pansplay'],
|
||||||
'f',
|
['panwidth'],
|
||||||
'pansplay',
|
['panorient'],
|
||||||
'a pattern of numbers between 0.0 and 1.0, which controls the multichannel spread range (multichannel only)',
|
// ['pitch1'],
|
||||||
],
|
// ['pitch2'],
|
||||||
[
|
// ['pitch3'],
|
||||||
'f',
|
// ['portamento'],
|
||||||
'panwidth',
|
|
||||||
'a pattern of numbers between 0.0 and inf, which controls how much each channel is distributed over neighbours (multichannel only)',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'f',
|
|
||||||
'panorient',
|
|
||||||
'a pattern of numbers between -1.0 and 1.0, which controls the relative position of the centre pan in a pair of adjacent speakers (multichannel only)',
|
|
||||||
],
|
|
||||||
// ['f', 'pitch1', ''],
|
|
||||||
// ['f', 'pitch2', ''],
|
|
||||||
// ['f', 'pitch3', ''],
|
|
||||||
// ['f', 'portamento', ''],
|
|
||||||
// TODO: LFO rate see https://tidalcycles.org/docs/patternlib/tutorials/synthesizers/#supersquare
|
// TODO: LFO rate see https://tidalcycles.org/docs/patternlib/tutorials/synthesizers/#supersquare
|
||||||
['f', 'rate', "used in SuperDirt softsynths as a control rate or 'speed'"],
|
['rate'],
|
||||||
// TODO: slide param for certain synths
|
// TODO: slide param for certain synths
|
||||||
['f', 'slide', ''],
|
['slide'],
|
||||||
// TODO: detune? https://tidalcycles.org/docs/patternlib/tutorials/synthesizers/#supersquare
|
// TODO: detune? https://tidalcycles.org/docs/patternlib/tutorials/synthesizers/#supersquare
|
||||||
['f', 'semitone', ''],
|
['semitone'],
|
||||||
// TODO: dedup with synth param, see https://tidalcycles.org/docs/reference/synthesizers/#superpiano
|
// TODO: dedup with synth param, see https://tidalcycles.org/docs/reference/synthesizers/#superpiano
|
||||||
// ['f', 'velocity', ''],
|
// ['velocity'],
|
||||||
['f', 'voice', ''], // TODO: synth param
|
['voice'], // TODO: synth param
|
||||||
/**
|
/**
|
||||||
* Sets the level of reverb.
|
* Sets the level of reverb.
|
||||||
*
|
*
|
||||||
|
* When using mininotation, you can also optionally add the 'size' parameter, separated by ':'.
|
||||||
|
*
|
||||||
* @name room
|
* @name room
|
||||||
* @param {number | Pattern} level between 0 and 1
|
* @param {number | Pattern} level between 0 and 1
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd").room("<0 .2 .4 .6 .8 1>")
|
* s("bd sd").room("<0 .2 .4 .6 .8 1>")
|
||||||
|
* @example
|
||||||
|
* s("bd sd").room("<0.9:1 0.9:4>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'room', 'a pattern of numbers from 0 to 1. Sets the level of reverb.'],
|
[['room', 'size']],
|
||||||
/**
|
/**
|
||||||
* Sets the room size of the reverb, see {@link room}.
|
* Sets the room size of the reverb, see {@link room}.
|
||||||
*
|
*
|
||||||
* @name roomsize
|
* @name roomsize
|
||||||
* @synonyms size
|
|
||||||
* @param {number | Pattern} size between 0 and 10
|
* @param {number | Pattern} size between 0 and 10
|
||||||
|
* @synonyms size, sz
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd").room(.8).roomsize("<0 1 2 4 8>")
|
* s("bd sd").room(.8).roomsize("<0 1 2 4 8>")
|
||||||
*
|
*
|
||||||
@ -638,20 +590,11 @@ const generic_params = [
|
|||||||
// TODO: find out why :
|
// TODO: find out why :
|
||||||
// s("bd sd").room(.8).roomsize("<0 .2 .4 .6 .8 [1,0]>").osc()
|
// s("bd sd").room(.8).roomsize("<0 .2 .4 .6 .8 [1,0]>").osc()
|
||||||
// .. does not work. Is it because room is only one effect?
|
// .. does not work. Is it because room is only one effect?
|
||||||
[
|
['size', 'sz', 'roomsize'],
|
||||||
'f',
|
// ['sagogo'],
|
||||||
'size',
|
// ['sclap'],
|
||||||
'a pattern of numbers from 0 to 1. Sets the perceptual size (reverb time) of the `room` to be used in reverb.',
|
// ['sclaves'],
|
||||||
],
|
// ['scrash'],
|
||||||
[
|
|
||||||
'f',
|
|
||||||
'roomsize',
|
|
||||||
'a pattern of numbers from 0 to 1. Sets the perceptual size (reverb time) of the `room` to be used in reverb.',
|
|
||||||
],
|
|
||||||
// ['f', 'sagogo', ''],
|
|
||||||
// ['f', 'sclap', ''],
|
|
||||||
// ['f', 'sclaves', ''],
|
|
||||||
// ['f', 'scrash', ''],
|
|
||||||
/**
|
/**
|
||||||
* Wave shaping distortion. CAUTION: it might get loud
|
* Wave shaping distortion. CAUTION: it might get loud
|
||||||
*
|
*
|
||||||
@ -661,11 +604,7 @@ const generic_params = [
|
|||||||
* s("bd sd,hh*4").shape("<0 .2 .4 .6 .8>")
|
* s("bd sd,hh*4").shape("<0 .2 .4 .6 .8>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['shape'],
|
||||||
'f',
|
|
||||||
'shape',
|
|
||||||
'wave shaping distortion, a pattern of numbers from 0 for no distortion up to 1 for loads of distortion.',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* Changes the speed of sample playback, i.e. a cheap way of changing pitch.
|
* Changes the speed of sample playback, i.e. a cheap way of changing pitch.
|
||||||
*
|
*
|
||||||
@ -677,11 +616,7 @@ const generic_params = [
|
|||||||
* speed("1 1.5*2 [2 1.1]").s("piano").clip(1)
|
* speed("1 1.5*2 [2 1.1]").s("piano").clip(1)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['speed'],
|
||||||
'f',
|
|
||||||
'speed',
|
|
||||||
'a pattern of numbers which changes the speed of sample playback, i.e. a cheap way of changing pitch. Negative values will play the sample backwards!',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* Used in conjunction with {@link speed}, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds). Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle. Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.
|
* Used in conjunction with {@link speed}, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds). Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle. Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.
|
||||||
*
|
*
|
||||||
@ -692,11 +627,7 @@ const generic_params = [
|
|||||||
* @superdirtOnly
|
* @superdirtOnly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['unit'],
|
||||||
's',
|
|
||||||
'unit',
|
|
||||||
'used in conjunction with `speed`, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds). Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle. Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.',
|
|
||||||
],
|
|
||||||
/**
|
/**
|
||||||
* Made by Calum Gunn. Reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter. The SuperCollider manual defines Squiz as:
|
* Made by Calum Gunn. Reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter. The SuperCollider manual defines Squiz as:
|
||||||
*
|
*
|
||||||
@ -709,14 +640,14 @@ const generic_params = [
|
|||||||
* @superdirtOnly
|
* @superdirtOnly
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'squiz', ''],
|
['squiz'],
|
||||||
['f', 'stutterdepth', ''], // TODO: what is this? not found in tidal doc
|
// ['stutterdepth'], // TODO: what is this? not found in tidal doc
|
||||||
['f', 'stuttertime', ''], // TODO: what is this? not found in tidal doc
|
// ['stuttertime'], // TODO: what is this? not found in tidal doc
|
||||||
['f', 'timescale', ''], // TODO: what is this? not found in tidal doc
|
// ['timescale'], // TODO: what is this? not found in tidal doc
|
||||||
['f', 'timescalewin', ''], // TODO: what is this? not found in tidal doc
|
// ['timescalewin'], // TODO: what is this? not found in tidal doc
|
||||||
// ['f', 'tomdecay', ''],
|
// ['tomdecay'],
|
||||||
// ['f', 'vcfegint', ''],
|
// ['vcfegint'],
|
||||||
// ['f', 'vcoegint', ''],
|
// ['vcoegint'],
|
||||||
// TODO: Use a rest (~) to override the effect <- vowel
|
// TODO: Use a rest (~) to override the effect <- vowel
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -729,11 +660,7 @@ const generic_params = [
|
|||||||
* .vowel("<a e i <o u>>")
|
* .vowel("<a e i <o u>>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
[
|
['vowel'],
|
||||||
's',
|
|
||||||
'vowel',
|
|
||||||
'formant filter to make things sound like vowels, a pattern of either `a`, `e`, `i`, `o` or `u`. Use a rest (`~`) for no effect.',
|
|
||||||
],
|
|
||||||
/* // TODO: find out how it works
|
/* // TODO: find out how it works
|
||||||
* Made by Calum Gunn. Divides an audio stream into tiny segments, using the signal's zero-crossings as segment boundaries, and discards a fraction of them. Takes a number between 1 and 100, denoted the percentage of segments to drop. The SuperCollider manual describes the Waveloss effect this way:
|
* Made by Calum Gunn. Divides an audio stream into tiny segments, using the signal's zero-crossings as segment boundaries, and discards a fraction of them. Takes a number between 1 and 100, denoted the percentage of segments to drop. The SuperCollider manual describes the Waveloss effect this way:
|
||||||
*
|
*
|
||||||
@ -744,12 +671,12 @@ const generic_params = [
|
|||||||
*
|
*
|
||||||
* @name waveloss
|
* @name waveloss
|
||||||
*/
|
*/
|
||||||
['f', 'waveloss', ''],
|
['waveloss'],
|
||||||
// TODO: midi effects?
|
// TODO: midi effects?
|
||||||
['f', 'dur', ''],
|
['dur'],
|
||||||
// ['f', 'modwheel', ''],
|
// ['modwheel'],
|
||||||
['f', 'expression', ''],
|
['expression'],
|
||||||
['f', 'sustainpedal', ''],
|
['sustainpedal'],
|
||||||
/* // TODO: doesn't seem to do anything
|
/* // TODO: doesn't seem to do anything
|
||||||
*
|
*
|
||||||
* Tremolo Audio DSP effect
|
* Tremolo Audio DSP effect
|
||||||
@ -760,59 +687,58 @@ const generic_params = [
|
|||||||
* n("0,4,7").tremolodepth("<0 .3 .6 .9>").osc()
|
* n("0,4,7").tremolodepth("<0 .3 .6 .9>").osc()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
// TODO: tremdp alias
|
['tremolodepth', 'tremdp'],
|
||||||
['f', 'tremolodepth', "Tremolo Audio DSP effect | params are 'tremolorate' and 'tremolodepth'"],
|
['tremolorate', 'tremr'],
|
||||||
['f', 'tremolorate', "Tremolo Audio DSP effect | params are 'tremolorate' and 'tremolodepth'"],
|
|
||||||
// TODO: doesn't seem to do anything
|
// TODO: doesn't seem to do anything
|
||||||
['f', 'phaserdepth', "Phaser Audio DSP effect | params are 'phaserrate' and 'phaserdepth'"],
|
['phaserdepth', 'phasdp'],
|
||||||
['f', 'phaserrate', "Phaser Audio DSP effect | params are 'phaserrate' and 'phaserdepth'"],
|
['phaserrate', 'phasr'],
|
||||||
|
|
||||||
['f', 'fshift', 'frequency shifter'],
|
['fshift'],
|
||||||
['f', 'fshiftnote', 'frequency shifter'],
|
['fshiftnote'],
|
||||||
['f', 'fshiftphase', 'frequency shifter'],
|
['fshiftphase'],
|
||||||
|
|
||||||
['f', 'triode', 'tube distortion'],
|
['triode'],
|
||||||
['f', 'krush', 'shape/bass enhancer'],
|
['krush'],
|
||||||
['f', 'kcutoff', ''],
|
['kcutoff'],
|
||||||
['f', 'octer', 'octaver effect'],
|
['octer'],
|
||||||
['f', 'octersub', 'octaver effect'],
|
['octersub'],
|
||||||
['f', 'octersubsub', 'octaver effect'],
|
['octersubsub'],
|
||||||
['f', 'ring', 'ring modulation'],
|
['ring'],
|
||||||
['f', 'ringf', 'ring modulation'],
|
['ringf'],
|
||||||
['f', 'ringdf', 'ring modulation'],
|
['ringdf'],
|
||||||
['f', 'distort', 'noisy fuzzy distortion'],
|
['distort'],
|
||||||
['f', 'freeze', 'Spectral freeze'],
|
['freeze'],
|
||||||
['f', 'xsdelay', ''],
|
['xsdelay'],
|
||||||
['f', 'tsdelay', ''],
|
['tsdelay'],
|
||||||
['f', 'real', 'Spectral conform'],
|
['real'],
|
||||||
['f', 'imag', ''],
|
['imag'],
|
||||||
['f', 'enhance', 'Spectral enhance'],
|
['enhance'],
|
||||||
['f', 'partials', ''],
|
['partials'],
|
||||||
['f', 'comb', 'Spectral comb'],
|
['comb'],
|
||||||
['f', 'smear', 'Spectral smear'],
|
['smear'],
|
||||||
['f', 'scram', 'Spectral scramble'],
|
['scram'],
|
||||||
['f', 'binshift', 'Spectral binshift'],
|
['binshift'],
|
||||||
['f', 'hbrick', 'High pass sort of spectral filter'],
|
['hbrick'],
|
||||||
['f', 'lbrick', 'Low pass sort of spectral filter'],
|
['lbrick'],
|
||||||
['f', 'midichan', ''],
|
['midichan'],
|
||||||
['f', 'control', ''],
|
['control'],
|
||||||
['f', 'ccn', ''],
|
['ccn'],
|
||||||
['f', 'ccv', ''],
|
['ccv'],
|
||||||
['f', 'polyTouch', ''],
|
['polyTouch'],
|
||||||
['f', 'midibend', ''],
|
['midibend'],
|
||||||
['f', 'miditouch', ''],
|
['miditouch'],
|
||||||
['f', 'ctlNum', ''],
|
['ctlNum'],
|
||||||
['f', 'frameRate', ''],
|
['frameRate'],
|
||||||
['f', 'frames', ''],
|
['frames'],
|
||||||
['f', 'hours', ''],
|
['hours'],
|
||||||
['s', 'midicmd', ''],
|
['midicmd'],
|
||||||
['f', 'minutes', ''],
|
['minutes'],
|
||||||
['f', 'progNum', ''],
|
['progNum'],
|
||||||
['f', 'seconds', ''],
|
['seconds'],
|
||||||
['f', 'songPtr', ''],
|
['songPtr'],
|
||||||
['f', 'uid', ''],
|
['uid'],
|
||||||
['f', 'val', ''],
|
['val'],
|
||||||
['f', 'cps', ''],
|
['cps'],
|
||||||
/**
|
/**
|
||||||
* If set to 1, samples will be cut to the duration of their event.
|
* If set to 1, samples will be cut to the duration of their event.
|
||||||
* In tidal, this would be done with legato, which [is about to land in strudel too](https://github.com/tidalcycles/strudel/issues/111)
|
* In tidal, this would be done with legato, which [is about to land in strudel too](https://github.com/tidalcycles/strudel/issues/111)
|
||||||
@ -823,32 +749,54 @@ const generic_params = [
|
|||||||
* note("c a f e ~").s("piano").clip(1)
|
* note("c a f e ~").s("piano").clip(1)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['f', 'clip', ''],
|
['clip'],
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: slice / splice https://www.youtube.com/watch?v=hKhPdO0RKDQ&list=PL2lW1zNIIwj3bDkh-Y3LUGDuRcoUigoDs&index=13
|
// TODO: slice / splice https://www.youtube.com/watch?v=hKhPdO0RKDQ&list=PL2lW1zNIIwj3bDkh-Y3LUGDuRcoUigoDs&index=13
|
||||||
|
|
||||||
const makeControl = function (name) {
|
controls.createParam = function (names) {
|
||||||
const func = (...pats) => sequence(...pats).withValue((x) => ({ [name]: x }));
|
const name = Array.isArray(names) ? names[0] : names;
|
||||||
|
|
||||||
|
var withVal;
|
||||||
|
if (Array.isArray(names)) {
|
||||||
|
withVal = (xs) => {
|
||||||
|
if (Array.isArray(xs)) {
|
||||||
|
const result = {};
|
||||||
|
xs.forEach((x, i) => {
|
||||||
|
if (i < names.length) {
|
||||||
|
result[names[i]] = x;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return { [name]: xs };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
withVal = (x) => ({ [name]: x });
|
||||||
|
}
|
||||||
|
|
||||||
|
const func = (...pats) => sequence(...pats).withValue(withVal);
|
||||||
|
|
||||||
const setter = function (...pats) {
|
const setter = function (...pats) {
|
||||||
if (!pats.length) {
|
if (!pats.length) {
|
||||||
return this.fmap((value) => ({ [name]: value }));
|
return this.fmap(withVal);
|
||||||
}
|
}
|
||||||
return this.set(func(...pats));
|
return this.set(func(...pats));
|
||||||
};
|
};
|
||||||
Pattern.prototype[name] = setter;
|
Pattern.prototype[name] = setter;
|
||||||
registerControl(name, func);
|
|
||||||
return func;
|
return func;
|
||||||
};
|
};
|
||||||
|
|
||||||
generic_params.forEach(([type, name, description]) => {
|
generic_params.forEach(([names, ...aliases]) => {
|
||||||
controls[name] = makeControl(name);
|
const name = Array.isArray(names) ? names[0] : names;
|
||||||
});
|
controls[name] = controls.createParam(names);
|
||||||
|
|
||||||
// create custom param
|
aliases.forEach((alias) => {
|
||||||
controls.createParam = (name) => {
|
controls[alias] = controls[name];
|
||||||
return makeControl(name);
|
Pattern.prototype[alias] = Pattern.prototype[name];
|
||||||
};
|
});
|
||||||
|
});
|
||||||
|
|
||||||
controls.createParams = (...names) =>
|
controls.createParams = (...names) =>
|
||||||
names.reduce((acc, name) => Object.assign(acc, { [name]: controls.createParam(name) }), {});
|
names.reduce((acc, name) => Object.assign(acc, { [name]: controls.createParam(name) }), {});
|
||||||
|
|||||||
@ -10,44 +10,49 @@ import { logger } from './logger.mjs';
|
|||||||
export class Cyclist {
|
export class Cyclist {
|
||||||
constructor({ interval, onTrigger, onToggle, onError, getTime, latency = 0.1 }) {
|
constructor({ interval, onTrigger, onToggle, onError, getTime, latency = 0.1 }) {
|
||||||
this.started = false;
|
this.started = false;
|
||||||
this.cps = 1; // TODO
|
this.cps = 1;
|
||||||
this.phase = 0;
|
this.lastTick = 0; // absolute time when last tick (clock callback) happened
|
||||||
this.getTime = getTime;
|
this.lastBegin = 0; // query begin of last tick
|
||||||
|
this.lastEnd = 0; // query end of last tick
|
||||||
|
this.getTime = getTime; // get absolute time
|
||||||
this.onToggle = onToggle;
|
this.onToggle = onToggle;
|
||||||
this.latency = latency;
|
this.latency = latency; // fixed trigger time offset
|
||||||
const round = (x) => Math.round(x * 1000) / 1000;
|
const round = (x) => Math.round(x * 1000) / 1000;
|
||||||
this.clock = createClock(
|
this.clock = createClock(
|
||||||
getTime,
|
getTime,
|
||||||
|
// called slightly before each cycle
|
||||||
(phase, duration, tick) => {
|
(phase, duration, tick) => {
|
||||||
if (tick === 0) {
|
if (tick === 0) {
|
||||||
this.origin = phase;
|
this.origin = phase;
|
||||||
}
|
}
|
||||||
const begin = round(phase - this.origin);
|
|
||||||
this.phase = begin - latency;
|
|
||||||
const end = round(begin + duration);
|
|
||||||
const time = getTime();
|
|
||||||
try {
|
try {
|
||||||
const haps = this.pattern.queryArc(begin, end); // get Haps
|
const time = getTime();
|
||||||
|
const begin = this.lastEnd;
|
||||||
|
this.lastBegin = begin;
|
||||||
|
const end = round(begin + duration * this.cps);
|
||||||
|
this.lastEnd = end;
|
||||||
|
const haps = this.pattern.queryArc(begin, end);
|
||||||
|
const tickdeadline = phase - time; // time left till phase begins
|
||||||
|
this.lastTick = time + tickdeadline;
|
||||||
|
|
||||||
haps.forEach((hap) => {
|
haps.forEach((hap) => {
|
||||||
if (hap.part.begin.equals(hap.whole.begin)) {
|
if (hap.part.begin.equals(hap.whole.begin)) {
|
||||||
const deadline = hap.whole.begin + this.origin - time + latency;
|
const deadline = (hap.whole.begin - begin) / this.cps + tickdeadline + latency;
|
||||||
const duration = hap.duration * 1;
|
const duration = hap.duration / this.cps;
|
||||||
onTrigger?.(hap, deadline, duration);
|
onTrigger?.(hap, deadline, duration, this.cps);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger(`[cyclist] error: ${e.message}`);
|
logger(`[cyclist] error: ${e.message}`);
|
||||||
onError?.(e);
|
onError?.(e);
|
||||||
}
|
}
|
||||||
}, // called slightly before each cycle
|
},
|
||||||
interval, // duration of each cycle
|
interval, // duration of each cycle
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
getPhase() {
|
|
||||||
return this.getTime() - this.origin - this.latency;
|
|
||||||
}
|
|
||||||
now() {
|
now() {
|
||||||
return this.getTime() - this.origin + this.clock.minLatency;
|
const secondsSinceLastTick = this.getTime() - this.lastTick - this.clock.duration;
|
||||||
|
return this.lastBegin + secondsSinceLastTick * this.cps; // + this.clock.minLatency;
|
||||||
}
|
}
|
||||||
setStarted(v) {
|
setStarted(v) {
|
||||||
this.started = v;
|
this.started = v;
|
||||||
|
|||||||
@ -6,12 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
|
|
||||||
import { isPattern } from './index.mjs';
|
import { isPattern } from './index.mjs';
|
||||||
|
|
||||||
let scoped = false;
|
|
||||||
export const evalScope = async (...args) => {
|
export const evalScope = async (...args) => {
|
||||||
if (scoped) {
|
|
||||||
console.warn('evalScope was called more than once.');
|
|
||||||
}
|
|
||||||
scoped = true;
|
|
||||||
const results = await Promise.allSettled(args);
|
const results = await Promise.allSettled(args);
|
||||||
const modules = results.filter((result) => result.status === 'fulfilled').map((r) => r.value);
|
const modules = results.filter((result) => result.status === 'fulfilled').map((r) => r.value);
|
||||||
results.forEach((result, i) => {
|
results.forEach((result, i) => {
|
||||||
@ -42,9 +37,6 @@ function safeEval(str, options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const evaluate = async (code, transpiler) => {
|
export const evaluate = async (code, transpiler) => {
|
||||||
if (!scoped) {
|
|
||||||
await evalScope(); // at least scope Pattern.prototype.boostrap
|
|
||||||
}
|
|
||||||
if (transpiler) {
|
if (transpiler) {
|
||||||
code = transpiler(code); // transform syntactically correct js code to semantically usable code
|
code = transpiler(code); // transform syntactically correct js code to semantically usable code
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,6 +126,19 @@ export class Hap {
|
|||||||
setContext(context) {
|
setContext(context) {
|
||||||
return new Hap(this.whole, this.part, this.value, context);
|
return new Hap(this.whole, this.part, this.value, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensureObjectValue() {
|
||||||
|
/* if (isNote(hap.value)) {
|
||||||
|
// supports primitive hap values that look like notes
|
||||||
|
hap.value = { note: hap.value };
|
||||||
|
} */
|
||||||
|
if (typeof this.value !== 'object') {
|
||||||
|
throw new Error(
|
||||||
|
`expected hap.value to be an object, but got "${this.value}". Hint: append .note() or .s() to the end`,
|
||||||
|
'error',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Hap;
|
export default Hap;
|
||||||
|
|||||||
@ -21,141 +21,6 @@ let stringParser;
|
|||||||
// intended to use with mini to automatically interpret all strings as mini notation
|
// intended to use with mini to automatically interpret all strings as mini notation
|
||||||
export const setStringParser = (parser) => (stringParser = parser);
|
export const setStringParser = (parser) => (stringParser = parser);
|
||||||
|
|
||||||
const alignments = ['in', 'out', 'mix', 'squeeze', 'squeezeout', 'trig', 'trigzero'];
|
|
||||||
|
|
||||||
const methodRegistry = [];
|
|
||||||
const getterRegistry = [];
|
|
||||||
const controlRegistry = [];
|
|
||||||
const controlSubscribers = [];
|
|
||||||
const composifiedRegistry = [];
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// Magic for supporting higher order composition of method chains
|
|
||||||
|
|
||||||
// Dresses the given (unary) function with methods for composition chaining, so e.g.
|
|
||||||
// `fast(2).iter(4)` composes to pattern functions into a new one.
|
|
||||||
function composify(func) {
|
|
||||||
if (!func.__composified) {
|
|
||||||
for (const [name, method] of methodRegistry) {
|
|
||||||
func[name] = method;
|
|
||||||
}
|
|
||||||
for (const [name, getter] of getterRegistry) {
|
|
||||||
Object.defineProperty(func, name, getter);
|
|
||||||
}
|
|
||||||
func.__composified = true;
|
|
||||||
composifiedRegistry.push(func);
|
|
||||||
} else {
|
|
||||||
console.log('Warning: attempt at composifying a function more than once');
|
|
||||||
}
|
|
||||||
return func;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function registerMethod(name, addAlignments = false, addControls = false) {
|
|
||||||
if (addAlignments || addControls) {
|
|
||||||
// This method needs to make its 'this' object available to chained alignments and/or
|
|
||||||
// control parameters, so it has to be implemented as a getter
|
|
||||||
const getter = {
|
|
||||||
get: function () {
|
|
||||||
const func = this;
|
|
||||||
const wrapped = function (...args) {
|
|
||||||
const composed = (pat) => func(pat)[name](...args);
|
|
||||||
return composify(composed);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (addAlignments) {
|
|
||||||
for (const alignment of alignments) {
|
|
||||||
wrapped[alignment] = function (...args) {
|
|
||||||
const composed = (pat) => func(pat)[name][alignment](...args);
|
|
||||||
return composify(composed);
|
|
||||||
};
|
|
||||||
for (const [controlname, controlfunc] of controlRegistry) {
|
|
||||||
wrapped[alignment][controlname] = function (...args) {
|
|
||||||
const composed = (pat) => func(pat)[name][alignment](controlfunc(...args));
|
|
||||||
return composify(composed);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (addControls) {
|
|
||||||
for (const [controlname, controlfunc] of controlRegistry) {
|
|
||||||
wrapped[controlname] = function (...args) {
|
|
||||||
const composed = (pat) => func(pat)[name](controlfunc(...args));
|
|
||||||
return composify(composed);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return wrapped;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
getterRegistry.push([name, getter]);
|
|
||||||
|
|
||||||
// Add to functions already 'composified'
|
|
||||||
for (const composified of composifiedRegistry) {
|
|
||||||
Object.defineProperty(composified, name, getter);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No chained alignments/controls needed, so we can just add as a plain method,
|
|
||||||
// probably more efficient this way?
|
|
||||||
const method = function (...args) {
|
|
||||||
const func = this;
|
|
||||||
const composed = (pat) => func(pat)[name](...args);
|
|
||||||
return composify(composed);
|
|
||||||
};
|
|
||||||
|
|
||||||
methodRegistry.push([name, method]);
|
|
||||||
|
|
||||||
// Add to functions already 'composified'
|
|
||||||
for (const composified of composifiedRegistry) {
|
|
||||||
composified[name] = method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function registerControl(controlname, controlfunc) {
|
|
||||||
registerMethod(controlname);
|
|
||||||
controlRegistry.push([controlname, controlfunc]);
|
|
||||||
for (const subscriber of controlSubscribers) {
|
|
||||||
subscriber(controlname, controlfunc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function withControls(func) {
|
|
||||||
for (const [controlname, controlfunc] of controlRegistry) {
|
|
||||||
func(controlname, controlfunc);
|
|
||||||
}
|
|
||||||
controlSubscribers.push(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addToPrototype(name, func) {
|
|
||||||
Pattern.prototype[name] = func;
|
|
||||||
registerMethod(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function curryPattern(func, arity = func.length) {
|
|
||||||
const fn = function curried(...args) {
|
|
||||||
if (args.length >= arity) {
|
|
||||||
return func.apply(this, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
const partial = function (...args2) {
|
|
||||||
return curried.apply(this, args.concat(args2));
|
|
||||||
};
|
|
||||||
if (args.length == arity - 1) {
|
|
||||||
return composify(partial);
|
|
||||||
}
|
|
||||||
|
|
||||||
return partial;
|
|
||||||
};
|
|
||||||
if (arity == 1) {
|
|
||||||
composify(fn);
|
|
||||||
}
|
|
||||||
return fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// The core Pattern class
|
|
||||||
|
|
||||||
/** @class Class representing a pattern. */
|
/** @class Class representing a pattern. */
|
||||||
export class Pattern {
|
export class Pattern {
|
||||||
/**
|
/**
|
||||||
@ -778,9 +643,7 @@ export class Pattern {
|
|||||||
* @noAutocomplete
|
* @noAutocomplete
|
||||||
*/
|
*/
|
||||||
get firstCycleValues() {
|
get firstCycleValues() {
|
||||||
return this.sortHapsByPart()
|
return this.firstCycle().map((hap) => hap.value);
|
||||||
.firstCycle()
|
|
||||||
.map((hap) => hap.value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -830,7 +693,7 @@ export class Pattern {
|
|||||||
const otherPat = reify(other);
|
const otherPat = reify(other);
|
||||||
return this.fmap((a) => otherPat.fmap((b) => func(a)(b))).squeezeJoin();
|
return this.fmap((a) => otherPat.fmap((b) => func(a)(b))).squeezeJoin();
|
||||||
}
|
}
|
||||||
_opSqueezeout(other, func) {
|
_opSqueezeOut(other, func) {
|
||||||
const thisPat = this;
|
const thisPat = this;
|
||||||
const otherPat = reify(other);
|
const otherPat = reify(other);
|
||||||
return otherPat.fmap((a) => thisPat.fmap((b) => func(b)(a))).squeezeJoin();
|
return otherPat.fmap((a) => thisPat.fmap((b) => func(b)(a))).squeezeJoin();
|
||||||
@ -997,11 +860,11 @@ function groupHapsBy(eq, haps) {
|
|||||||
const congruent = (a, b) => a.spanEquals(b);
|
const congruent = (a, b) => a.spanEquals(b);
|
||||||
// Pattern<Hap<T>> -> Pattern<Hap<T[]>>
|
// Pattern<Hap<T>> -> Pattern<Hap<T[]>>
|
||||||
// returned pattern contains arrays of congruent haps
|
// returned pattern contains arrays of congruent haps
|
||||||
addToPrototype('collect', function () {
|
Pattern.prototype.collect = function () {
|
||||||
return this.withHaps((haps) =>
|
return this.withHaps((haps) =>
|
||||||
groupHapsBy(congruent, haps).map((_haps) => new Hap(_haps[0].whole, _haps[0].part, _haps, {})),
|
groupHapsBy(congruent, haps).map((_haps) => new Hap(_haps[0].whole, _haps[0].part, _haps, {})),
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects indices in in stacked notes.
|
* Selects indices in in stacked notes.
|
||||||
@ -1009,12 +872,12 @@ addToPrototype('collect', function () {
|
|||||||
* note("<[c,eb,g]!2 [c,f,ab] [d,f,ab]>")
|
* note("<[c,eb,g]!2 [c,f,ab] [d,f,ab]>")
|
||||||
* .arpWith(haps => haps[2])
|
* .arpWith(haps => haps[2])
|
||||||
* */
|
* */
|
||||||
addToPrototype('arpWith', function (func) {
|
Pattern.prototype.arpWith = function (func) {
|
||||||
return this.collect()
|
return this.collect()
|
||||||
.fmap((v) => reify(func(v)))
|
.fmap((v) => reify(func(v)))
|
||||||
.innerJoin()
|
.innerJoin()
|
||||||
.withHap((h) => new Hap(h.whole, h.part, h.value.value, h.combineContext(h.value)));
|
.withHap((h) => new Hap(h.whole, h.part, h.value.value, h.combineContext(h.value)));
|
||||||
});
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects indices in in stacked notes.
|
* Selects indices in in stacked notes.
|
||||||
@ -1022,28 +885,27 @@ addToPrototype('arpWith', function (func) {
|
|||||||
* note("<[c,eb,g]!2 [c,f,ab] [d,f,ab]>")
|
* note("<[c,eb,g]!2 [c,f,ab] [d,f,ab]>")
|
||||||
* .arp("0 [0,2] 1 [0,2]").slow(2)
|
* .arp("0 [0,2] 1 [0,2]").slow(2)
|
||||||
* */
|
* */
|
||||||
addToPrototype('arp', function (pat) {
|
Pattern.prototype.arp = function (pat) {
|
||||||
return this.arpWith((haps) => pat.fmap((i) => haps[i % haps.length]));
|
return this.arpWith((haps) => pat.fmap((i) => haps[i % haps.length]));
|
||||||
});
|
};
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Takes a time duration followed by one or more patterns, and shifts the given patterns in time, so they are
|
* Takes a time duration followed by one or more patterns, and shifts the given patterns in time, so they are
|
||||||
* distributed equally over the given time duration. They are then combined with the pattern 'weave' is called on, after it has been stretched out (i.e. slowed down by) the time duration.
|
* distributed equally over the given time duration. They are then combined with the pattern 'weave' is called on, after it has been stretched out (i.e. slowed down by) the time duration.
|
||||||
* @name weave
|
* @name weave
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @example pan(saw).weave(4, s("bd(3,8)"), s("~ sd"))
|
* @example pan(saw).weave(4, s("bd(3,8)"), s("~ sd"))
|
||||||
* @example n("0 1 2 3 4 5 6 7").weave(8, s("bd(3,8)"), s("~ sd"))
|
* @example n("0 1 2 3 4 5 6 7").weave(8, s("bd(3,8)"), s("~ sd"))
|
||||||
*/
|
|
||||||
|
|
||||||
addToPrototype('weave', function (t, ...pats) {
|
addToPrototype('weave', function (t, ...pats) {
|
||||||
return this.weaveWith(t, ...pats.map((x) => set.out(x)));
|
return this.weaveWith(t, ...pats.map((x) => set.out(x)));
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
*/
|
||||||
|
/*
|
||||||
* Like 'weave', but accepts functions rather than patterns, which are applied to the pattern.
|
* Like 'weave', but accepts functions rather than patterns, which are applied to the pattern.
|
||||||
* @name weaveWith
|
* @name weaveWith
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
*/
|
|
||||||
|
|
||||||
addToPrototype('weaveWith', function (t, ...funcs) {
|
addToPrototype('weaveWith', function (t, ...funcs) {
|
||||||
const pat = this;
|
const pat = this;
|
||||||
@ -1054,6 +916,7 @@ addToPrototype('weaveWith', function (t, ...funcs) {
|
|||||||
}
|
}
|
||||||
return stack(...funcs.map((func, i) => pat.inside(t, func).early(Fraction(i).div(l))))._slow(t);
|
return stack(...funcs.map((func, i) => pat.inside(t, func).early(Fraction(i).div(l))))._slow(t);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// compose matrix functions
|
// compose matrix functions
|
||||||
@ -1151,15 +1014,15 @@ function _composeOp(a, b, func) {
|
|||||||
func: [(a, b) => b(a)],
|
func: [(a, b) => b(a)],
|
||||||
};
|
};
|
||||||
|
|
||||||
const hows = alignments.map((x) => x.charAt(0).toUpperCase() + x.slice(1));
|
const hows = ['In', 'Out', 'Mix', 'Squeeze', 'SqueezeOut', 'Trig', 'Trigzero'];
|
||||||
|
|
||||||
// generate methods to do what and how
|
// generate methods to do what and how
|
||||||
for (const [what, [op, preprocess]] of Object.entries(composers)) {
|
for (const [what, [op, preprocess]] of Object.entries(composers)) {
|
||||||
// make plain version, e.g. pat._add(value) adds that plain value
|
// make plain version, e.g. pat._add(value) adds that plain value
|
||||||
// to all the values in pat
|
// to all the values in pat
|
||||||
addToPrototype('_' + what, function (value) {
|
Pattern.prototype['_' + what] = function (value) {
|
||||||
return this.fmap((x) => op(x, value));
|
return this.fmap((x) => op(x, value));
|
||||||
});
|
};
|
||||||
|
|
||||||
// make patternified monster version
|
// make patternified monster version
|
||||||
Object.defineProperty(Pattern.prototype, what, {
|
Object.defineProperty(Pattern.prototype, what, {
|
||||||
@ -1173,7 +1036,7 @@ function _composeOp(a, b, func) {
|
|||||||
|
|
||||||
// add methods to that function for each behaviour
|
// add methods to that function for each behaviour
|
||||||
for (const how of hows) {
|
for (const how of hows) {
|
||||||
const howfunc = function (...other) {
|
wrapper[how.toLowerCase()] = function (...other) {
|
||||||
var howpat = pat;
|
var howpat = pat;
|
||||||
other = sequence(other);
|
other = sequence(other);
|
||||||
if (preprocess) {
|
if (preprocess) {
|
||||||
@ -1191,41 +1054,19 @@ function _composeOp(a, b, func) {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const [controlname, controlfunc] of controlRegistry) {
|
|
||||||
howfunc[controlname] = (...args) => howfunc(controlfunc(...args));
|
|
||||||
}
|
|
||||||
wrapper[how.toLowerCase()] = howfunc;
|
|
||||||
}
|
}
|
||||||
wrapper.squeezein = wrapper.squeeze;
|
wrapper.squeezein = wrapper.squeeze;
|
||||||
|
|
||||||
for (const [controlname, controlfunc] of controlRegistry) {
|
|
||||||
wrapper[controlname] = (...args) => wrapper.in(controlfunc(...args));
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrapper;
|
return wrapper;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
registerMethod(what, true, true);
|
// Default op to 'set', e.g. pat.squeeze(pat2) = pat.set.squeeze(pat2)
|
||||||
}
|
for (const how of hows) {
|
||||||
|
Pattern.prototype[how.toLowerCase()] = function (...args) {
|
||||||
// Default op to 'set', e.g. pat.squeeze(pat2) = pat.set.squeeze(pat2)
|
return this.set[how.toLowerCase()](args);
|
||||||
for (const howLower of alignments) {
|
};
|
||||||
// Using a 'get'ted function so that all the controls are added
|
}
|
||||||
Object.defineProperty(Pattern.prototype, howLower, {
|
|
||||||
get: function () {
|
|
||||||
const pat = this;
|
|
||||||
const howfunc = function (...args) {
|
|
||||||
return pat.set[howLower](args);
|
|
||||||
};
|
|
||||||
for (const [controlname, controlfunc] of controlRegistry) {
|
|
||||||
howfunc[controlname] = (...args) => howfunc(controlfunc(...args));
|
|
||||||
}
|
|
||||||
return howfunc;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
registerMethod(howLower, false, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// binary composers
|
// binary composers
|
||||||
@ -1237,36 +1078,36 @@ function _composeOp(a, b, func) {
|
|||||||
* .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~")
|
* .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~")
|
||||||
* .slow(4)
|
* .slow(4)
|
||||||
*/
|
*/
|
||||||
addToPrototype('struct', function (...args) {
|
Pattern.prototype.struct = function (...args) {
|
||||||
return this.keepif.out(...args);
|
return this.keepif.out(...args);
|
||||||
});
|
};
|
||||||
addToPrototype('structAll', function (...args) {
|
Pattern.prototype.structAll = function (...args) {
|
||||||
return this.keep.out(...args);
|
return this.keep.out(...args);
|
||||||
});
|
};
|
||||||
/**
|
/**
|
||||||
* Returns silence when mask is 0 or "~"
|
* Returns silence when mask is 0 or "~"
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* note("c [eb,g] d [eb,g]").mask("<1 [0 1]>").slow(2)
|
* note("c [eb,g] d [eb,g]").mask("<1 [0 1]>").slow(2)
|
||||||
*/
|
*/
|
||||||
addToPrototype('mask', function (...args) {
|
Pattern.prototype.mask = function (...args) {
|
||||||
return this.keepif.in(...args);
|
return this.keepif.in(...args);
|
||||||
});
|
};
|
||||||
addToPrototype('maskAll', function (...args) {
|
Pattern.prototype.maskAll = function (...args) {
|
||||||
return this.keep.in(...args);
|
return this.keep.in(...args);
|
||||||
});
|
};
|
||||||
/**
|
/**
|
||||||
* Resets the pattern to the start of the cycle for each onset of the reset pattern.
|
* Resets the pattern to the start of the cycle for each onset of the reset pattern.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* s("<bd lt> sd, hh*4").reset("<x@3 x(3,8)>")
|
* s("<bd lt> sd, hh*4").reset("<x@3 x(3,8)>")
|
||||||
*/
|
*/
|
||||||
addToPrototype('reset', function (...args) {
|
Pattern.prototype.reset = function (...args) {
|
||||||
return this.keepif.trig(...args);
|
return this.keepif.trig(...args);
|
||||||
});
|
};
|
||||||
addToPrototype('resetAll', function (...args) {
|
Pattern.prototype.resetAll = function (...args) {
|
||||||
return this.keep.trig(...args);
|
return this.keep.trig(...args);
|
||||||
});
|
};
|
||||||
/**
|
/**
|
||||||
* Restarts the pattern for each onset of the restart pattern.
|
* Restarts the pattern for each onset of the restart pattern.
|
||||||
* While reset will only reset the current cycle, restart will start from cycle 0.
|
* While reset will only reset the current cycle, restart will start from cycle 0.
|
||||||
@ -1274,12 +1115,12 @@ function _composeOp(a, b, func) {
|
|||||||
* @example
|
* @example
|
||||||
* s("<bd lt> sd, hh*4").restart("<x@3 x(3,8)>")
|
* s("<bd lt> sd, hh*4").restart("<x@3 x(3,8)>")
|
||||||
*/
|
*/
|
||||||
addToPrototype('restart', function (...args) {
|
Pattern.prototype.restart = function (...args) {
|
||||||
return this.keepif.trigzero(...args);
|
return this.keepif.trigzero(...args);
|
||||||
});
|
};
|
||||||
addToPrototype('restartAll', function (...args) {
|
Pattern.prototype.restartAll = function (...args) {
|
||||||
return this.keep.trigzero(...args);
|
return this.keep.trigzero(...args);
|
||||||
});
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// aliases
|
// aliases
|
||||||
@ -1443,6 +1284,20 @@ export function timeCat(...timepats) {
|
|||||||
return stack(...pats);
|
return stack(...pats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to arrange multiple patterns together over multiple cycles.
|
||||||
|
* Takes a variable number of arrays with two elements specifying the number of cycles and the pattern to use.
|
||||||
|
*
|
||||||
|
* @return {Pattern}
|
||||||
|
* @example
|
||||||
|
* arrange([4, "<c a f e>(3,8)"],[2, "<g a>(5,8)"]).note()
|
||||||
|
*/
|
||||||
|
export function arrange(...sections) {
|
||||||
|
const total = sections.reduce((sum, [cycles]) => sum + cycles, 0);
|
||||||
|
sections = sections.map(([cycles, section]) => [cycles, section.fast(cycles)]);
|
||||||
|
return timeCat(...sections).slow(total);
|
||||||
|
}
|
||||||
|
|
||||||
export function fastcat(...pats) {
|
export function fastcat(...pats) {
|
||||||
return slowcat(...pats)._fast(pats.length);
|
return slowcat(...pats)._fast(pats.length);
|
||||||
}
|
}
|
||||||
@ -1524,68 +1379,36 @@ export function pm(...args) {
|
|||||||
polymeter(...args);
|
polymeter(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mask = curryPattern((a, b) => reify(b).mask(a));
|
export const mask = curry((a, b) => reify(b).mask(a));
|
||||||
export const struct = curryPattern((a, b) => reify(b).struct(a));
|
export const struct = curry((a, b) => reify(b).struct(a));
|
||||||
export const superimpose = curryPattern((a, b) => reify(b).superimpose(...a));
|
export const superimpose = curry((a, b) => reify(b).superimpose(...a));
|
||||||
|
|
||||||
const methodToFunction = function (name, addAlignments = false) {
|
|
||||||
const func = curryPattern((a, b) => reify(b)[name](a));
|
|
||||||
|
|
||||||
withControls((controlname, controlfunc) => {
|
|
||||||
func[controlname] = function (...pats) {
|
|
||||||
return func(controlfunc(...pats));
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
if (addAlignments) {
|
|
||||||
for (const alignment of alignments) {
|
|
||||||
func[alignment] = curryPattern((a, b) => reify(b)[name][alignment](a));
|
|
||||||
withControls((controlname, controlfunc) => {
|
|
||||||
func[alignment][controlname] = function (...pats) {
|
|
||||||
return func[alignment](controlfunc(...pats));
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return func;
|
|
||||||
};
|
|
||||||
|
|
||||||
// operators
|
// operators
|
||||||
export const set = methodToFunction('set', true);
|
export const set = curry((a, b) => reify(b).set(a));
|
||||||
export const keep = methodToFunction('keep', true);
|
export const keep = curry((a, b) => reify(b).keep(a));
|
||||||
export const keepif = methodToFunction('keepif', true);
|
export const keepif = curry((a, b) => reify(b).keepif(a));
|
||||||
export const add = methodToFunction('add', true);
|
export const add = curry((a, b) => reify(b).add(a));
|
||||||
export const sub = methodToFunction('sub', true);
|
export const sub = curry((a, b) => reify(b).sub(a));
|
||||||
export const mul = methodToFunction('mul', true);
|
export const mul = curry((a, b) => reify(b).mul(a));
|
||||||
export const div = methodToFunction('div', true);
|
export const div = curry((a, b) => reify(b).div(a));
|
||||||
export const mod = methodToFunction('mod', true);
|
export const mod = curry((a, b) => reify(b).mod(a));
|
||||||
export const pow = methodToFunction('pow', true);
|
export const pow = curry((a, b) => reify(b).pow(a));
|
||||||
export const band = methodToFunction('band', true);
|
export const band = curry((a, b) => reify(b).band(a));
|
||||||
export const bor = methodToFunction('bor', true);
|
export const bor = curry((a, b) => reify(b).bor(a));
|
||||||
export const bxor = methodToFunction('bxor', true);
|
export const bxor = curry((a, b) => reify(b).bxor(a));
|
||||||
export const blshift = methodToFunction('blshift', true);
|
export const blshift = curry((a, b) => reify(b).blshift(a));
|
||||||
export const brshift = methodToFunction('brshift', true);
|
export const brshift = curry((a, b) => reify(b).brshift(a));
|
||||||
export const lt = methodToFunction('lt', true);
|
export const lt = curry((a, b) => reify(b).lt(a));
|
||||||
export const gt = methodToFunction('gt', true);
|
export const gt = curry((a, b) => reify(b).gt(a));
|
||||||
export const lte = methodToFunction('lte', true);
|
export const lte = curry((a, b) => reify(b).lte(a));
|
||||||
export const gte = methodToFunction('gte', true);
|
export const gte = curry((a, b) => reify(b).gte(a));
|
||||||
export const eq = methodToFunction('eq', true);
|
export const eq = curry((a, b) => reify(b).eq(a));
|
||||||
export const eqt = methodToFunction('eqt', true);
|
export const eqt = curry((a, b) => reify(b).eqt(a));
|
||||||
export const ne = methodToFunction('ne', true);
|
export const ne = curry((a, b) => reify(b).ne(a));
|
||||||
export const net = methodToFunction('net', true);
|
export const net = curry((a, b) => reify(b).net(a));
|
||||||
export const and = methodToFunction('and', true);
|
export const and = curry((a, b) => reify(b).and(a));
|
||||||
export const or = methodToFunction('or', true);
|
export const or = curry((a, b) => reify(b).or(a));
|
||||||
export const func = methodToFunction('func', true);
|
export const func = curry((a, b) => reify(b).func(a));
|
||||||
|
|
||||||
// alignments
|
|
||||||
// export const in = methodToFunction('in'); // reserved word :(
|
|
||||||
export const out = methodToFunction('out');
|
|
||||||
export const mix = methodToFunction('mix');
|
|
||||||
export const squeeze = methodToFunction('squeeze');
|
|
||||||
export const squeezeout = methodToFunction('squeezeout');
|
|
||||||
export const trig = methodToFunction('trig');
|
|
||||||
export const trigzero = methodToFunction('trigzero');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a new pattern method. The method is added to the Pattern class + the standalone function is returned from register.
|
* Registers a new pattern method. The method is added to the Pattern class + the standalone function is returned from register.
|
||||||
@ -1604,10 +1427,7 @@ export function register(name, func, patternify = true) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
const arity = func.length;
|
const arity = func.length;
|
||||||
|
var pfunc; // the patternified function
|
||||||
registerMethod(name);
|
|
||||||
|
|
||||||
var pfunc;
|
|
||||||
|
|
||||||
if (patternify) {
|
if (patternify) {
|
||||||
pfunc = function (...args) {
|
pfunc = function (...args) {
|
||||||
@ -1626,14 +1446,8 @@ export function register(name, func, patternify = true) {
|
|||||||
.map((_, i) => args[i] ?? undefined);
|
.map((_, i) => args[i] ?? undefined);
|
||||||
return func(...args, pat);
|
return func(...args, pat);
|
||||||
};
|
};
|
||||||
mapFn = curryPattern(mapFn, arity - 1);
|
mapFn = curry(mapFn, null, arity - 1);
|
||||||
|
return right.reduce((acc, p) => acc.appLeft(p), left.fmap(mapFn)).innerJoin();
|
||||||
const app = function (acc, p, i) {
|
|
||||||
return acc.appLeft(p);
|
|
||||||
};
|
|
||||||
const start = left.fmap(mapFn);
|
|
||||||
|
|
||||||
return right.reduce(app, start).innerJoin();
|
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
pfunc = function (...args) {
|
pfunc = function (...args) {
|
||||||
@ -1643,7 +1457,6 @@ export function register(name, func, patternify = true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Pattern.prototype[name] = function (...args) {
|
Pattern.prototype[name] = function (...args) {
|
||||||
args = args.map(reify);
|
|
||||||
// For methods that take a single argument (plus 'this'), allow
|
// For methods that take a single argument (plus 'this'), allow
|
||||||
// multiple arguments but sequence them
|
// multiple arguments but sequence them
|
||||||
if (arity === 2 && args.length !== 1) {
|
if (arity === 2 && args.length !== 1) {
|
||||||
@ -1651,6 +1464,7 @@ export function register(name, func, patternify = true) {
|
|||||||
} else if (arity !== args.length + 1) {
|
} else if (arity !== args.length + 1) {
|
||||||
throw new Error(`.${name}() expects ${arity - 1} inputs but got ${args.length}.`);
|
throw new Error(`.${name}() expects ${arity - 1} inputs but got ${args.length}.`);
|
||||||
}
|
}
|
||||||
|
args = args.map(reify);
|
||||||
return pfunc(...args, this);
|
return pfunc(...args, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1664,7 +1478,7 @@ export function register(name, func, patternify = true) {
|
|||||||
|
|
||||||
// toplevel functions get curried as well as patternified
|
// toplevel functions get curried as well as patternified
|
||||||
// because pfunc uses spread args, we need to state the arity explicitly!
|
// because pfunc uses spread args, we need to state the arity explicitly!
|
||||||
return curryPattern(pfunc, arity);
|
return curry(pfunc, null, arity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -2430,7 +2244,7 @@ const _loopAt = function (factor, pat, cps = 1) {
|
|||||||
.slow(factor);
|
.slow(factor);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Chops samples into the given number of slices, triggering those slices with a given pattern of slice numbers.
|
* Chops samples into the given number of slices, triggering those slices with a given pattern of slice numbers.
|
||||||
* @name slice
|
* @name slice
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
@ -2439,6 +2253,7 @@ const _loopAt = function (factor, pat, cps = 1) {
|
|||||||
* await samples('github:tidalcycles/Dirt-Samples/master')
|
* await samples('github:tidalcycles/Dirt-Samples/master')
|
||||||
* s("breaks165").slice(8, "0 1 <2 2*2> 3 [4 0] 5 6 7".every(3, rev)).slow(1.5)
|
* s("breaks165").slice(8, "0 1 <2 2*2> 3 [4 0] 5 6 7".every(3, rev)).slow(1.5)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const slice = register(
|
const slice = register(
|
||||||
'slice',
|
'slice',
|
||||||
function (npat, ipat, opat) {
|
function (npat, ipat, opat) {
|
||||||
@ -2457,7 +2272,7 @@ const slice = register(
|
|||||||
false, // turns off auto-patternification
|
false, // turns off auto-patternification
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Works the same as slice, but changes the playback speed of each slice to match the duration of its step.
|
* Works the same as slice, but changes the playback speed of each slice to match the duration of its step.
|
||||||
* @name splice
|
* @name splice
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
@ -2466,6 +2281,7 @@ const slice = register(
|
|||||||
* await samples('github:tidalcycles/Dirt-Samples/master')
|
* await samples('github:tidalcycles/Dirt-Samples/master')
|
||||||
* s("breaks165").splice(8, "0 1 [2 3 0]@2 3 0@2 7").hurry(0.65)
|
* s("breaks165").splice(8, "0 1 [2 3 0]@2 3 0@2 7").hurry(0.65)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const splice = register(
|
const splice = register(
|
||||||
'splice',
|
'splice',
|
||||||
function (npat, ipat, opat) {
|
function (npat, ipat, opat) {
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Cyclist } from './cyclist.mjs';
|
|||||||
import { evaluate as _evaluate } from './evaluate.mjs';
|
import { evaluate as _evaluate } from './evaluate.mjs';
|
||||||
import { logger } from './logger.mjs';
|
import { logger } from './logger.mjs';
|
||||||
import { setTime } from './time.mjs';
|
import { setTime } from './time.mjs';
|
||||||
|
import { evalScope } from './evaluate.mjs';
|
||||||
|
|
||||||
export function repl({
|
export function repl({
|
||||||
interval,
|
interval,
|
||||||
@ -17,13 +18,12 @@ export function repl({
|
|||||||
}) {
|
}) {
|
||||||
const scheduler = new Cyclist({
|
const scheduler = new Cyclist({
|
||||||
interval,
|
interval,
|
||||||
onTrigger: async (hap, deadline, duration) => {
|
onTrigger: async (hap, deadline, duration, cps) => {
|
||||||
try {
|
try {
|
||||||
if (!hap.context.onTrigger || !hap.context.dominantTrigger) {
|
if (!hap.context.onTrigger || !hap.context.dominantTrigger) {
|
||||||
await defaultOutput(hap, deadline, duration);
|
await defaultOutput(hap, deadline, duration, cps);
|
||||||
}
|
}
|
||||||
if (hap.context.onTrigger) {
|
if (hap.context.onTrigger) {
|
||||||
const cps = 1;
|
|
||||||
// call signature of output / onTrigger is different...
|
// call signature of output / onTrigger is different...
|
||||||
await hap.context.onTrigger(getTime() + deadline, hap, getTime(), cps);
|
await hap.context.onTrigger(getTime() + deadline, hap, getTime(), cps);
|
||||||
}
|
}
|
||||||
@ -42,6 +42,17 @@ export function repl({
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
beforeEval?.({ code });
|
beforeEval?.({ code });
|
||||||
|
scheduler.setCps(1); // reset cps in case the code does not contain a setCps call
|
||||||
|
// problem: when the code does contain a setCps after an awaited promise,
|
||||||
|
// the cps will be 1 until the promise resolves
|
||||||
|
// example:
|
||||||
|
/*
|
||||||
|
await new Promise(resolve => setTimeout(resolve,1000))
|
||||||
|
setCps(.5)
|
||||||
|
note("c a f e")
|
||||||
|
*/
|
||||||
|
// to make sure the setCps inside the code is called immediately,
|
||||||
|
// it has to be placed first
|
||||||
let { pattern } = await _evaluate(code, transpiler);
|
let { pattern } = await _evaluate(code, transpiler);
|
||||||
|
|
||||||
logger(`[eval] code updated`);
|
logger(`[eval] code updated`);
|
||||||
@ -58,5 +69,10 @@ export function repl({
|
|||||||
const stop = () => scheduler.stop();
|
const stop = () => scheduler.stop();
|
||||||
const start = () => scheduler.start();
|
const start = () => scheduler.start();
|
||||||
const pause = () => scheduler.pause();
|
const pause = () => scheduler.pause();
|
||||||
return { scheduler, evaluate, start, stop, pause };
|
const setCps = (cps) => scheduler.setCps(cps);
|
||||||
|
evalScope({
|
||||||
|
setCps,
|
||||||
|
setcps: setCps,
|
||||||
|
});
|
||||||
|
return { scheduler, evaluate, start, stop, pause, setCps };
|
||||||
}
|
}
|
||||||
|
|||||||
28
packages/core/test/controls.test.mjs
Normal file
28
packages/core/test/controls.test.mjs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
controls.test.mjs - <short description TODO>
|
||||||
|
Copyright (C) 2023 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/test/controls.test.mjs>
|
||||||
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import controls from '../controls.mjs';
|
||||||
|
import { mini } from '../../mini/mini.mjs';
|
||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
|
||||||
|
describe('controls', () => {
|
||||||
|
it('should support controls', () => {
|
||||||
|
expect(controls.s('bd').firstCycleValues).toEqual([{ s: 'bd' }]);
|
||||||
|
});
|
||||||
|
it('should support compound controls', () => {
|
||||||
|
expect(controls.s(mini('bd:3')).firstCycleValues).toEqual([{ s: 'bd', n: 3 }]);
|
||||||
|
expect(controls.s(mini('bd:3 sd:4:1.4')).firstCycleValues).toEqual([
|
||||||
|
{ s: 'bd', n: 3 },
|
||||||
|
{ s: 'sd', n: 4, gain: 1.4 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('should support ignore extra elements in compound controls', () => {
|
||||||
|
expect(controls.s(mini('bd:3:0.4 sd:4:0.5:3:17')).firstCycleValues).toEqual([
|
||||||
|
{ s: 'bd', n: 3, gain: 0.4 },
|
||||||
|
{ s: 'sd', n: 4, gain: 0.5 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -45,9 +45,6 @@ import {
|
|||||||
rev,
|
rev,
|
||||||
time,
|
time,
|
||||||
run,
|
run,
|
||||||
hitch,
|
|
||||||
set,
|
|
||||||
begin,
|
|
||||||
} from '../index.mjs';
|
} from '../index.mjs';
|
||||||
|
|
||||||
import { steady } from '../signal.mjs';
|
import { steady } from '../signal.mjs';
|
||||||
@ -207,7 +204,7 @@ describe('Pattern', () => {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('can squeezeout() structure', () => {
|
it('can SqueezeOut() structure', () => {
|
||||||
sameFirst(
|
sameFirst(
|
||||||
sequence(1, [2, 3]).add.squeezeout(10, 20, 30),
|
sequence(1, [2, 3]).add.squeezeout(10, 20, 30),
|
||||||
sequence([11, [12, 13]], [21, [22, 23]], [31, [32, 33]]),
|
sequence([11, [12, 13]], [21, [22, 23]], [31, [32, 33]]),
|
||||||
@ -255,7 +252,7 @@ describe('Pattern', () => {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('can squeezeout() structure', () => {
|
it('can SqueezeOut() structure', () => {
|
||||||
sameFirst(sequence(1, [2, 3]).keep.squeezeout(10, 20, 30), sequence([1, [2, 3]], [1, [2, 3]], [1, [2, 3]]));
|
sameFirst(sequence(1, [2, 3]).keep.squeezeout(10, 20, 30), sequence([1, [2, 3]], [1, [2, 3]], [1, [2, 3]]));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -297,7 +294,7 @@ describe('Pattern', () => {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('can squeezeout() structure', () => {
|
it('can SqueezeOut() structure', () => {
|
||||||
sameFirst(sequence(1, [2, 3]).keepif.squeezeout(true, true, false), sequence([1, [2, 3]], [1, [2, 3]], silence));
|
sameFirst(sequence(1, [2, 3]).keepif.squeezeout(true, true, false), sequence([1, [2, 3]], [1, [2, 3]], silence));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -932,14 +929,6 @@ describe('Pattern', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('alignments', () => {
|
describe('alignments', () => {
|
||||||
it('Can combine controls', () => {
|
|
||||||
sameFirst(s('bd').set.in.n(3), s('bd').n(3));
|
|
||||||
sameFirst(s('bd').set.squeeze.n(3, 4), sequence(s('bd').n(3), s('bd').n(4)));
|
|
||||||
});
|
|
||||||
it('Can combine functions with alignmed controls', () => {
|
|
||||||
sameFirst(s('bd').apply(fast(2).set(n(3))), s('bd').fast(2).set.in.n(3));
|
|
||||||
sameFirst(s('bd').apply(fast(2).set.in.n(3)), s('bd').fast(2).set.in.n(3));
|
|
||||||
});
|
|
||||||
it('Can squeeze arguments', () => {
|
it('Can squeeze arguments', () => {
|
||||||
expect(sequence(1, 2).add.squeeze(4, 5).firstCycle()).toStrictEqual(sequence(5, 6, 6, 7).firstCycle());
|
expect(sequence(1, 2).add.squeeze(4, 5).firstCycle()).toStrictEqual(sequence(5, 6, 6, 7).firstCycle());
|
||||||
});
|
});
|
||||||
@ -970,7 +959,7 @@ describe('Pattern', () => {
|
|||||||
sameFirst(s('a', 'b').hurry(2), s('a', 'b').fast(2).speed(2));
|
sameFirst(s('a', 'b').hurry(2), s('a', 'b').fast(2).speed(2));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('composable functions', () => {
|
/*describe('composable functions', () => {
|
||||||
it('Can compose functions', () => {
|
it('Can compose functions', () => {
|
||||||
sameFirst(sequence(3, 4).fast(2).rev().fast(2), fast(2).rev().fast(2)(sequence(3, 4)));
|
sameFirst(sequence(3, 4).fast(2).rev().fast(2), fast(2).rev().fast(2)(sequence(3, 4)));
|
||||||
});
|
});
|
||||||
@ -987,6 +976,7 @@ describe('Pattern', () => {
|
|||||||
sameFirst(n(0, 1).weave(2, s('bd', silence), s(silence, 'sd')), sequence(s('bd').n(0), s('sd').n(1)));
|
sameFirst(n(0, 1).weave(2, s('bd', silence), s(silence, 'sd')), sequence(s('bd').n(0), s('sd').n(1)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
describe('slice', () => {
|
describe('slice', () => {
|
||||||
it('Can slice a sample', () => {
|
it('Can slice a sample', () => {
|
||||||
sameFirst(
|
sameFirst(
|
||||||
|
|||||||
@ -139,7 +139,7 @@ export const removeUndefineds = (xs) => xs.filter((x) => x != undefined);
|
|||||||
export const flatten = (arr) => [].concat(...arr);
|
export const flatten = (arr) => [].concat(...arr);
|
||||||
|
|
||||||
export const id = (a) => a;
|
export const id = (a) => a;
|
||||||
export const constant = curry((a, b) => a);
|
export const constant = (a, b) => a;
|
||||||
|
|
||||||
export const listRange = (min, max) => Array.from({ length: max - min + 1 }, (_, i) => i + min);
|
export const listRange = (min, max) => Array.from({ length: max - min + 1 }, (_, i) => i + min);
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,6 @@ function createClock(
|
|||||||
};
|
};
|
||||||
const getPhase = () => phase;
|
const getPhase = () => phase;
|
||||||
// setCallback
|
// setCallback
|
||||||
return { setDuration, start, stop, pause, duration, getPhase, minLatency };
|
return { setDuration, start, stop, pause, duration, interval, getPhase, minLatency };
|
||||||
}
|
}
|
||||||
export default createClock;
|
export default createClock;
|
||||||
|
|||||||
@ -28,9 +28,7 @@ export const csound = register('csound', (instrument, pat) => {
|
|||||||
logger('[csound] not loaded yet', 'warning');
|
logger('[csound] not loaded yet', 'warning');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeof hap.value !== 'object') {
|
hap.ensureObjectValue();
|
||||||
throw new Error('csound only support objects as hap values');
|
|
||||||
}
|
|
||||||
let { gain = 0.8 } = hap.value;
|
let { gain = 0.8 } = hap.value;
|
||||||
gain *= 0.2;
|
gain *= 0.2;
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,9 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as _WebMidi from 'webmidi';
|
import * as _WebMidi from 'webmidi';
|
||||||
import { Pattern, isPattern, isNote, getPlayableNoteValue, logger } from '@strudel.cycles/core';
|
import { Pattern, isPattern, logger } from '@strudel.cycles/core';
|
||||||
import { getAudioContext } from '@strudel.cycles/webaudio';
|
import { getAudioContext } from '@strudel.cycles/webaudio';
|
||||||
|
import { toMidi } from '@strudel.cycles/core';
|
||||||
|
|
||||||
// if you use WebMidi from outside of this package, make sure to import that instance:
|
// if you use WebMidi from outside of this package, make sure to import that instance:
|
||||||
export const { WebMidi } = _WebMidi;
|
export const { WebMidi } = _WebMidi;
|
||||||
@ -63,7 +64,7 @@ function getDevice(output, outputs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pattern.prototype.midi = function (output: string | number, channel = 1) {
|
// Pattern.prototype.midi = function (output: string | number, channel = 1) {
|
||||||
Pattern.prototype.midi = function (output, channel = 1) {
|
Pattern.prototype.midi = function (output) {
|
||||||
if (!supportsMidi()) {
|
if (!supportsMidi()) {
|
||||||
throw new Error(`🎹 WebMidi is not enabled. Supported Browsers: https://caniuse.com/?search=webmidi`);
|
throw new Error(`🎹 WebMidi is not enabled. Supported Browsers: https://caniuse.com/?search=webmidi`);
|
||||||
}
|
}
|
||||||
@ -90,11 +91,6 @@ Pattern.prototype.midi = function (output, channel = 1) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return this.onTrigger((time, hap) => {
|
return this.onTrigger((time, hap) => {
|
||||||
let note = getPlayableNoteValue(hap);
|
|
||||||
const velocity = hap.context?.velocity ?? 0.9;
|
|
||||||
if (!isNote(note)) {
|
|
||||||
throw new Error('not a note: ' + note);
|
|
||||||
}
|
|
||||||
if (!midiReady) {
|
if (!midiReady) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -106,15 +102,34 @@ Pattern.prototype.midi = function (output, channel = 1) {
|
|||||||
.join(' | ')}`,
|
.join(' | ')}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// console.log('midi', value, output);
|
hap.ensureObjectValue();
|
||||||
|
|
||||||
|
// calculate time
|
||||||
const timingOffset = WebMidi.time - getAudioContext().currentTime * 1000;
|
const timingOffset = WebMidi.time - getAudioContext().currentTime * 1000;
|
||||||
time = time * 1000 + timingOffset;
|
time = time * 1000 + timingOffset;
|
||||||
// const inMs = '+' + (time - Tone.getContext().currentTime) * 1000;
|
|
||||||
// await enableWebMidi()
|
// destructure value
|
||||||
device.playNote(note, channel, {
|
const { note, nrpnn, nrpv, ccn, ccv, midichan = 1 } = hap.value;
|
||||||
time,
|
const velocity = hap.context?.velocity ?? 0.9; // TODO: refactor velocity
|
||||||
duration: hap.duration.valueOf() * 1000 - 5,
|
const duration = hap.duration.valueOf() * 1000 - 5;
|
||||||
attack: velocity,
|
|
||||||
});
|
if (note) {
|
||||||
|
const midiNumber = toMidi(note);
|
||||||
|
device.playNote(midiNumber, midichan, {
|
||||||
|
time,
|
||||||
|
duration,
|
||||||
|
attack: velocity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (ccv && ccn) {
|
||||||
|
if (typeof ccv !== 'number' || ccv < 0 || ccv > 1) {
|
||||||
|
throw new Error('expected ccv to be a number between 0 and 1');
|
||||||
|
}
|
||||||
|
if (!['string', 'number'].includes(typeof ccn)) {
|
||||||
|
throw new Error('expected ccn to be a number or a string');
|
||||||
|
}
|
||||||
|
const scaled = Math.round(ccv * 127);
|
||||||
|
device.sendControlChange(ccn, scaled, midichan, { time });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -182,21 +182,21 @@ function peg$parse(input, options) {
|
|||||||
var peg$c8 = "#";
|
var peg$c8 = "#";
|
||||||
var peg$c9 = "^";
|
var peg$c9 = "^";
|
||||||
var peg$c10 = "_";
|
var peg$c10 = "_";
|
||||||
var peg$c11 = ":";
|
var peg$c11 = "[";
|
||||||
var peg$c12 = "[";
|
var peg$c12 = "]";
|
||||||
var peg$c13 = "]";
|
var peg$c13 = "{";
|
||||||
var peg$c14 = "{";
|
var peg$c14 = "}";
|
||||||
var peg$c15 = "}";
|
var peg$c15 = "%";
|
||||||
var peg$c16 = "%";
|
var peg$c16 = "<";
|
||||||
var peg$c17 = "<";
|
var peg$c17 = ">";
|
||||||
var peg$c18 = ">";
|
var peg$c18 = "@";
|
||||||
var peg$c19 = "@";
|
var peg$c19 = "!";
|
||||||
var peg$c20 = "!";
|
var peg$c20 = "(";
|
||||||
var peg$c21 = "(";
|
var peg$c21 = ")";
|
||||||
var peg$c22 = ")";
|
var peg$c22 = "/";
|
||||||
var peg$c23 = "/";
|
var peg$c23 = "*";
|
||||||
var peg$c24 = "*";
|
var peg$c24 = "?";
|
||||||
var peg$c25 = "?";
|
var peg$c25 = ":";
|
||||||
var peg$c26 = "struct";
|
var peg$c26 = "struct";
|
||||||
var peg$c27 = "target";
|
var peg$c27 = "target";
|
||||||
var peg$c28 = "euclid";
|
var peg$c28 = "euclid";
|
||||||
@ -237,21 +237,21 @@ function peg$parse(input, options) {
|
|||||||
var peg$e15 = peg$literalExpectation("#", false);
|
var peg$e15 = peg$literalExpectation("#", false);
|
||||||
var peg$e16 = peg$literalExpectation("^", false);
|
var peg$e16 = peg$literalExpectation("^", false);
|
||||||
var peg$e17 = peg$literalExpectation("_", false);
|
var peg$e17 = peg$literalExpectation("_", false);
|
||||||
var peg$e18 = peg$literalExpectation(":", false);
|
var peg$e18 = peg$literalExpectation("[", false);
|
||||||
var peg$e19 = peg$literalExpectation("[", false);
|
var peg$e19 = peg$literalExpectation("]", false);
|
||||||
var peg$e20 = peg$literalExpectation("]", false);
|
var peg$e20 = peg$literalExpectation("{", false);
|
||||||
var peg$e21 = peg$literalExpectation("{", false);
|
var peg$e21 = peg$literalExpectation("}", false);
|
||||||
var peg$e22 = peg$literalExpectation("}", false);
|
var peg$e22 = peg$literalExpectation("%", false);
|
||||||
var peg$e23 = peg$literalExpectation("%", false);
|
var peg$e23 = peg$literalExpectation("<", false);
|
||||||
var peg$e24 = peg$literalExpectation("<", false);
|
var peg$e24 = peg$literalExpectation(">", false);
|
||||||
var peg$e25 = peg$literalExpectation(">", false);
|
var peg$e25 = peg$literalExpectation("@", false);
|
||||||
var peg$e26 = peg$literalExpectation("@", false);
|
var peg$e26 = peg$literalExpectation("!", false);
|
||||||
var peg$e27 = peg$literalExpectation("!", false);
|
var peg$e27 = peg$literalExpectation("(", false);
|
||||||
var peg$e28 = peg$literalExpectation("(", false);
|
var peg$e28 = peg$literalExpectation(")", false);
|
||||||
var peg$e29 = peg$literalExpectation(")", false);
|
var peg$e29 = peg$literalExpectation("/", false);
|
||||||
var peg$e30 = peg$literalExpectation("/", false);
|
var peg$e30 = peg$literalExpectation("*", false);
|
||||||
var peg$e31 = peg$literalExpectation("*", false);
|
var peg$e31 = peg$literalExpectation("?", false);
|
||||||
var peg$e32 = peg$literalExpectation("?", false);
|
var peg$e32 = peg$literalExpectation(":", false);
|
||||||
var peg$e33 = peg$literalExpectation("struct", false);
|
var peg$e33 = peg$literalExpectation("struct", false);
|
||||||
var peg$e34 = peg$literalExpectation("target", false);
|
var peg$e34 = peg$literalExpectation("target", false);
|
||||||
var peg$e35 = peg$literalExpectation("euclid", false);
|
var peg$e35 = peg$literalExpectation("euclid", false);
|
||||||
@ -280,35 +280,36 @@ function peg$parse(input, options) {
|
|||||||
var peg$f9 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'slow' }}) };
|
var peg$f9 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'slow' }}) };
|
||||||
var peg$f10 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'fast' }}) };
|
var peg$f10 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'fast' }}) };
|
||||||
var peg$f11 = function(a) { return x => x.options_['ops'].push({ type_: "degradeBy", arguments_ :{ amount:a } }) };
|
var peg$f11 = function(a) { return x => x.options_['ops'].push({ type_: "degradeBy", arguments_ :{ amount:a } }) };
|
||||||
var peg$f12 = function(s, ops) { const result = new ElementStub(s, {ops: [], weight: 1, reps: 1});
|
var peg$f12 = function(s) { return x => x.options_['ops'].push({ type_: "tail", arguments_ :{ element:s } }) };
|
||||||
|
var peg$f13 = function(s, ops) { const result = new ElementStub(s, {ops: [], weight: 1, reps: 1});
|
||||||
for (const op of ops) {
|
for (const op of ops) {
|
||||||
op(result);
|
op(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
var peg$f13 = function(s) { return new PatternStub(s, 'fastcat'); };
|
var peg$f14 = function(s) { return new PatternStub(s, 'fastcat'); };
|
||||||
var peg$f14 = function(tail) { return { alignment: 'stack', list: tail }; };
|
var peg$f15 = function(tail) { return { alignment: 'stack', list: tail }; };
|
||||||
var peg$f15 = function(tail) { return { alignment: 'rand', list: tail }; };
|
var peg$f16 = function(tail) { return { alignment: 'rand', list: tail }; };
|
||||||
var peg$f16 = function(head, tail) { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment); } else { return head; } };
|
var peg$f17 = function(head, tail) { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment); } else { return head; } };
|
||||||
var peg$f17 = function(head, tail) { return new PatternStub(tail ? [head, ...tail.list] : [head], 'polymeter'); };
|
var peg$f18 = function(head, tail) { return new PatternStub(tail ? [head, ...tail.list] : [head], 'polymeter'); };
|
||||||
var peg$f18 = function(sc) { return sc; };
|
var peg$f19 = function(sc) { return sc; };
|
||||||
var peg$f19 = function(s) { return { name: "struct", args: { mini:s }}};
|
var peg$f20 = function(s) { return { name: "struct", args: { mini:s }}};
|
||||||
var peg$f20 = function(s) { return { name: "target", args : { name:s}}};
|
var peg$f21 = function(s) { return { name: "target", args : { name:s}}};
|
||||||
var peg$f21 = function(p, s, r) { return { name: "bjorklund", args :{ pulse: p, step:parseInt(s) }}};
|
var peg$f22 = function(p, s, r) { return { name: "bjorklund", args :{ pulse: p, step:parseInt(s) }}};
|
||||||
var peg$f22 = function(a) { return { name: "stretch", args :{ amount: a}}};
|
var peg$f23 = function(a) { return { name: "stretch", args :{ amount: a}}};
|
||||||
var peg$f23 = function(a) { return { name: "shift", args :{ amount: "-"+a}}};
|
var peg$f24 = function(a) { return { name: "shift", args :{ amount: "-"+a}}};
|
||||||
var peg$f24 = function(a) { return { name: "shift", args :{ amount: a}}};
|
var peg$f25 = function(a) { return { name: "shift", args :{ amount: a}}};
|
||||||
var peg$f25 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}};
|
var peg$f26 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}};
|
||||||
var peg$f26 = function(s) { return { name: "scale", args :{ scale: s.join("")}}};
|
var peg$f27 = function(s) { return { name: "scale", args :{ scale: s.join("")}}};
|
||||||
var peg$f27 = function(s, v) { return v};
|
var peg$f28 = function(s, v) { return v};
|
||||||
var peg$f28 = function(s, ss) { ss.unshift(s); return new PatternStub(ss, 'slowcat'); };
|
var peg$f29 = function(s, ss) { ss.unshift(s); return new PatternStub(ss, 'slowcat'); };
|
||||||
var peg$f29 = function(sg) {return sg};
|
var peg$f30 = function(sg) {return sg};
|
||||||
var peg$f30 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)};
|
var peg$f31 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)};
|
||||||
var peg$f31 = function(sc) { return sc };
|
var peg$f32 = function(sc) { return sc };
|
||||||
var peg$f32 = function(c) { return c };
|
var peg$f33 = function(c) { return c };
|
||||||
var peg$f33 = function(v) { return new CommandStub("setcps", { value: v})};
|
var peg$f34 = function(v) { return new CommandStub("setcps", { value: v})};
|
||||||
var peg$f34 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})};
|
var peg$f35 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})};
|
||||||
var peg$f35 = function() { return new CommandStub("hush")};
|
var peg$f36 = function() { return new CommandStub("hush")};
|
||||||
var peg$currPos = 0;
|
var peg$currPos = 0;
|
||||||
var peg$savedPos = 0;
|
var peg$savedPos = 0;
|
||||||
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
||||||
@ -848,15 +849,6 @@ function peg$parse(input, options) {
|
|||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e17); }
|
if (peg$silentFails === 0) { peg$fail(peg$e17); }
|
||||||
}
|
}
|
||||||
if (s0 === peg$FAILED) {
|
|
||||||
if (input.charCodeAt(peg$currPos) === 58) {
|
|
||||||
s0 = peg$c11;
|
|
||||||
peg$currPos++;
|
|
||||||
} else {
|
|
||||||
s0 = peg$FAILED;
|
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -899,11 +891,11 @@ function peg$parse(input, options) {
|
|||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
s1 = peg$parsews();
|
s1 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 91) {
|
if (input.charCodeAt(peg$currPos) === 91) {
|
||||||
s2 = peg$c12;
|
s2 = peg$c11;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s2 = peg$FAILED;
|
s2 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e19); }
|
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
||||||
}
|
}
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s3 = peg$parsews();
|
s3 = peg$parsews();
|
||||||
@ -911,11 +903,11 @@ function peg$parse(input, options) {
|
|||||||
if (s4 !== peg$FAILED) {
|
if (s4 !== peg$FAILED) {
|
||||||
s5 = peg$parsews();
|
s5 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 93) {
|
if (input.charCodeAt(peg$currPos) === 93) {
|
||||||
s6 = peg$c13;
|
s6 = peg$c12;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s6 = peg$FAILED;
|
s6 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
if (peg$silentFails === 0) { peg$fail(peg$e19); }
|
||||||
}
|
}
|
||||||
if (s6 !== peg$FAILED) {
|
if (s6 !== peg$FAILED) {
|
||||||
s7 = peg$parsews();
|
s7 = peg$parsews();
|
||||||
@ -943,11 +935,11 @@ function peg$parse(input, options) {
|
|||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
s1 = peg$parsews();
|
s1 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 123) {
|
if (input.charCodeAt(peg$currPos) === 123) {
|
||||||
s2 = peg$c14;
|
s2 = peg$c13;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s2 = peg$FAILED;
|
s2 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e21); }
|
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
||||||
}
|
}
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s3 = peg$parsews();
|
s3 = peg$parsews();
|
||||||
@ -955,11 +947,11 @@ function peg$parse(input, options) {
|
|||||||
if (s4 !== peg$FAILED) {
|
if (s4 !== peg$FAILED) {
|
||||||
s5 = peg$parsews();
|
s5 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 125) {
|
if (input.charCodeAt(peg$currPos) === 125) {
|
||||||
s6 = peg$c15;
|
s6 = peg$c14;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s6 = peg$FAILED;
|
s6 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e22); }
|
if (peg$silentFails === 0) { peg$fail(peg$e21); }
|
||||||
}
|
}
|
||||||
if (s6 !== peg$FAILED) {
|
if (s6 !== peg$FAILED) {
|
||||||
s7 = peg$parsepolymeter_steps();
|
s7 = peg$parsepolymeter_steps();
|
||||||
@ -990,11 +982,11 @@ function peg$parse(input, options) {
|
|||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
if (input.charCodeAt(peg$currPos) === 37) {
|
if (input.charCodeAt(peg$currPos) === 37) {
|
||||||
s1 = peg$c16;
|
s1 = peg$c15;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s1 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e23); }
|
if (peg$silentFails === 0) { peg$fail(peg$e22); }
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = peg$parseslice();
|
s2 = peg$parseslice();
|
||||||
@ -1019,11 +1011,11 @@ function peg$parse(input, options) {
|
|||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
s1 = peg$parsews();
|
s1 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 60) {
|
if (input.charCodeAt(peg$currPos) === 60) {
|
||||||
s2 = peg$c17;
|
s2 = peg$c16;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s2 = peg$FAILED;
|
s2 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e24); }
|
if (peg$silentFails === 0) { peg$fail(peg$e23); }
|
||||||
}
|
}
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s3 = peg$parsews();
|
s3 = peg$parsews();
|
||||||
@ -1031,11 +1023,11 @@ function peg$parse(input, options) {
|
|||||||
if (s4 !== peg$FAILED) {
|
if (s4 !== peg$FAILED) {
|
||||||
s5 = peg$parsews();
|
s5 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 62) {
|
if (input.charCodeAt(peg$currPos) === 62) {
|
||||||
s6 = peg$c18;
|
s6 = peg$c17;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s6 = peg$FAILED;
|
s6 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
if (peg$silentFails === 0) { peg$fail(peg$e24); }
|
||||||
}
|
}
|
||||||
if (s6 !== peg$FAILED) {
|
if (s6 !== peg$FAILED) {
|
||||||
s7 = peg$parsews();
|
s7 = peg$parsews();
|
||||||
@ -1088,6 +1080,9 @@ function peg$parse(input, options) {
|
|||||||
s0 = peg$parseop_replicate();
|
s0 = peg$parseop_replicate();
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
s0 = peg$parseop_degrade();
|
s0 = peg$parseop_degrade();
|
||||||
|
if (s0 === peg$FAILED) {
|
||||||
|
s0 = peg$parseop_tail();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1102,11 +1097,11 @@ function peg$parse(input, options) {
|
|||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
if (input.charCodeAt(peg$currPos) === 64) {
|
if (input.charCodeAt(peg$currPos) === 64) {
|
||||||
s1 = peg$c19;
|
s1 = peg$c18;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s1 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e26); }
|
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = peg$parsenumber();
|
s2 = peg$parsenumber();
|
||||||
@ -1130,11 +1125,11 @@ function peg$parse(input, options) {
|
|||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
if (input.charCodeAt(peg$currPos) === 33) {
|
if (input.charCodeAt(peg$currPos) === 33) {
|
||||||
s1 = peg$c20;
|
s1 = peg$c19;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s1 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e27); }
|
if (peg$silentFails === 0) { peg$fail(peg$e26); }
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = peg$parsenumber();
|
s2 = peg$parsenumber();
|
||||||
@ -1158,11 +1153,11 @@ function peg$parse(input, options) {
|
|||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
if (input.charCodeAt(peg$currPos) === 40) {
|
if (input.charCodeAt(peg$currPos) === 40) {
|
||||||
s1 = peg$c21;
|
s1 = peg$c20;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s1 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e28); }
|
if (peg$silentFails === 0) { peg$fail(peg$e27); }
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = peg$parsews();
|
s2 = peg$parsews();
|
||||||
@ -1186,11 +1181,11 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
s12 = peg$parsews();
|
s12 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 41) {
|
if (input.charCodeAt(peg$currPos) === 41) {
|
||||||
s13 = peg$c22;
|
s13 = peg$c21;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s13 = peg$FAILED;
|
s13 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e29); }
|
if (peg$silentFails === 0) { peg$fail(peg$e28); }
|
||||||
}
|
}
|
||||||
if (s13 !== peg$FAILED) {
|
if (s13 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
@ -1224,11 +1219,11 @@ function peg$parse(input, options) {
|
|||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
if (input.charCodeAt(peg$currPos) === 47) {
|
if (input.charCodeAt(peg$currPos) === 47) {
|
||||||
s1 = peg$c23;
|
s1 = peg$c22;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s1 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
if (peg$silentFails === 0) { peg$fail(peg$e29); }
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = peg$parseslice();
|
s2 = peg$parseslice();
|
||||||
@ -1252,11 +1247,11 @@ function peg$parse(input, options) {
|
|||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
if (input.charCodeAt(peg$currPos) === 42) {
|
if (input.charCodeAt(peg$currPos) === 42) {
|
||||||
s1 = peg$c24;
|
s1 = peg$c23;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s1 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = peg$parseslice();
|
s2 = peg$parseslice();
|
||||||
@ -1280,11 +1275,11 @@ function peg$parse(input, options) {
|
|||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
if (input.charCodeAt(peg$currPos) === 63) {
|
if (input.charCodeAt(peg$currPos) === 63) {
|
||||||
s1 = peg$c25;
|
s1 = peg$c24;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s1 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e32); }
|
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = peg$parsenumber();
|
s2 = peg$parsenumber();
|
||||||
@ -1301,6 +1296,34 @@ function peg$parse(input, options) {
|
|||||||
return s0;
|
return s0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function peg$parseop_tail() {
|
||||||
|
var s0, s1, s2;
|
||||||
|
|
||||||
|
s0 = peg$currPos;
|
||||||
|
if (input.charCodeAt(peg$currPos) === 58) {
|
||||||
|
s1 = peg$c25;
|
||||||
|
peg$currPos++;
|
||||||
|
} else {
|
||||||
|
s1 = peg$FAILED;
|
||||||
|
if (peg$silentFails === 0) { peg$fail(peg$e32); }
|
||||||
|
}
|
||||||
|
if (s1 !== peg$FAILED) {
|
||||||
|
s2 = peg$parseslice();
|
||||||
|
if (s2 !== peg$FAILED) {
|
||||||
|
peg$savedPos = s0;
|
||||||
|
s0 = peg$f12(s2);
|
||||||
|
} else {
|
||||||
|
peg$currPos = s0;
|
||||||
|
s0 = peg$FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
peg$currPos = s0;
|
||||||
|
s0 = peg$FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s0;
|
||||||
|
}
|
||||||
|
|
||||||
function peg$parseslice_with_ops() {
|
function peg$parseslice_with_ops() {
|
||||||
var s0, s1, s2, s3;
|
var s0, s1, s2, s3;
|
||||||
|
|
||||||
@ -1314,7 +1337,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parseslice_op();
|
s3 = peg$parseslice_op();
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f12(s1, s2);
|
s0 = peg$f13(s1, s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1339,7 +1362,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f13(s1);
|
s1 = peg$f14(s1);
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
|
|
||||||
@ -1388,7 +1411,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f14(s1);
|
s1 = peg$f15(s1);
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
|
|
||||||
@ -1437,7 +1460,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f15(s1);
|
s1 = peg$f16(s1);
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
|
|
||||||
@ -1458,7 +1481,7 @@ function peg$parse(input, options) {
|
|||||||
s2 = null;
|
s2 = null;
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f16(s1, s2);
|
s0 = peg$f17(s1, s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1478,7 +1501,7 @@ function peg$parse(input, options) {
|
|||||||
s2 = null;
|
s2 = null;
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f17(s1, s2);
|
s0 = peg$f18(s1, s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1499,7 +1522,7 @@ function peg$parse(input, options) {
|
|||||||
s4 = peg$parsequote();
|
s4 = peg$parsequote();
|
||||||
if (s4 !== peg$FAILED) {
|
if (s4 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f18(s3);
|
s0 = peg$f19(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1561,7 +1584,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsemini_or_operator();
|
s3 = peg$parsemini_or_operator();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f19(s3);
|
s0 = peg$f20(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1594,7 +1617,7 @@ function peg$parse(input, options) {
|
|||||||
s5 = peg$parsequote();
|
s5 = peg$parsequote();
|
||||||
if (s5 !== peg$FAILED) {
|
if (s5 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f20(s4);
|
s0 = peg$f21(s4);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1639,7 +1662,7 @@ function peg$parse(input, options) {
|
|||||||
s7 = null;
|
s7 = null;
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f21(s3, s5, s7);
|
s0 = peg$f22(s3, s5, s7);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1672,7 +1695,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f22(s3);
|
s0 = peg$f23(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1701,7 +1724,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f23(s3);
|
s0 = peg$f24(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1730,7 +1753,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f24(s3);
|
s0 = peg$f25(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1759,7 +1782,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f25(s3);
|
s0 = peg$f26(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1801,7 +1824,7 @@ function peg$parse(input, options) {
|
|||||||
s5 = peg$parsequote();
|
s5 = peg$parsequote();
|
||||||
if (s5 !== peg$FAILED) {
|
if (s5 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f26(s4);
|
s0 = peg$f27(s4);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1876,11 +1899,11 @@ function peg$parse(input, options) {
|
|||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = peg$parsews();
|
s2 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 91) {
|
if (input.charCodeAt(peg$currPos) === 91) {
|
||||||
s3 = peg$c12;
|
s3 = peg$c11;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s3 = peg$FAILED;
|
s3 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e19); }
|
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
||||||
}
|
}
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
s4 = peg$parsews();
|
s4 = peg$parsews();
|
||||||
@ -1893,7 +1916,7 @@ function peg$parse(input, options) {
|
|||||||
s9 = peg$parsemini_or_operator();
|
s9 = peg$parsemini_or_operator();
|
||||||
if (s9 !== peg$FAILED) {
|
if (s9 !== peg$FAILED) {
|
||||||
peg$savedPos = s7;
|
peg$savedPos = s7;
|
||||||
s7 = peg$f27(s5, s9);
|
s7 = peg$f28(s5, s9);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s7;
|
peg$currPos = s7;
|
||||||
s7 = peg$FAILED;
|
s7 = peg$FAILED;
|
||||||
@ -1910,7 +1933,7 @@ function peg$parse(input, options) {
|
|||||||
s9 = peg$parsemini_or_operator();
|
s9 = peg$parsemini_or_operator();
|
||||||
if (s9 !== peg$FAILED) {
|
if (s9 !== peg$FAILED) {
|
||||||
peg$savedPos = s7;
|
peg$savedPos = s7;
|
||||||
s7 = peg$f27(s5, s9);
|
s7 = peg$f28(s5, s9);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s7;
|
peg$currPos = s7;
|
||||||
s7 = peg$FAILED;
|
s7 = peg$FAILED;
|
||||||
@ -1922,15 +1945,15 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
s7 = peg$parsews();
|
s7 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 93) {
|
if (input.charCodeAt(peg$currPos) === 93) {
|
||||||
s8 = peg$c13;
|
s8 = peg$c12;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s8 = peg$FAILED;
|
s8 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
if (peg$silentFails === 0) { peg$fail(peg$e19); }
|
||||||
}
|
}
|
||||||
if (s8 !== peg$FAILED) {
|
if (s8 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f28(s5, s6);
|
s0 = peg$f29(s5, s6);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1976,7 +1999,7 @@ function peg$parse(input, options) {
|
|||||||
s4 = peg$parsecomment();
|
s4 = peg$parsecomment();
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f29(s1);
|
s0 = peg$f30(s1);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1998,7 +2021,7 @@ function peg$parse(input, options) {
|
|||||||
s5 = peg$parsemini_or_operator();
|
s5 = peg$parsemini_or_operator();
|
||||||
if (s5 !== peg$FAILED) {
|
if (s5 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f30(s1, s5);
|
s0 = peg$f31(s1, s5);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -2023,7 +2046,7 @@ function peg$parse(input, options) {
|
|||||||
s1 = peg$parsemini_or_operator();
|
s1 = peg$parsemini_or_operator();
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f31(s1);
|
s1 = peg$f32(s1);
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
@ -2056,7 +2079,7 @@ function peg$parse(input, options) {
|
|||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s3 = peg$parsews();
|
s3 = peg$parsews();
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f32(s2);
|
s0 = peg$f33(s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -2081,7 +2104,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f33(s3);
|
s0 = peg$f34(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -2110,7 +2133,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f34(s3);
|
s0 = peg$f35(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -2136,7 +2159,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f35();
|
s1 = peg$f36();
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
|
|
||||||
|
|||||||
@ -96,7 +96,7 @@ quote = '"' / "'"
|
|||||||
// ------------------ steps and cycles ---------------------------
|
// ------------------ steps and cycles ---------------------------
|
||||||
|
|
||||||
// single step definition (e.g bd)
|
// single step definition (e.g bd)
|
||||||
step_char = [0-9a-zA-Z~] / "-" / "#" / "." / "^" / "_" / ":"
|
step_char = [0-9a-zA-Z~] / "-" / "#" / "." / "^" / "_"
|
||||||
step = ws chars:step_char+ ws { return new AtomStub(chars.join("")) }
|
step = ws chars:step_char+ ws { return new AtomStub(chars.join("")) }
|
||||||
|
|
||||||
// define a sub cycle e.g. [1 2, 3 [4]]
|
// define a sub cycle e.g. [1 2, 3 [4]]
|
||||||
@ -119,7 +119,7 @@ slice = step / sub_cycle / polymeter / slow_sequence
|
|||||||
|
|
||||||
// slice modifier affects the timing/size of a slice (e.g. [a b c]@3)
|
// slice modifier affects the timing/size of a slice (e.g. [a b c]@3)
|
||||||
// at this point, we assume we can represent them as regular sequence operators
|
// at this point, we assume we can represent them as regular sequence operators
|
||||||
slice_op = op_weight / op_bjorklund / op_slow / op_fast / op_replicate / op_degrade
|
slice_op = op_weight / op_bjorklund / op_slow / op_fast / op_replicate / op_degrade / op_tail
|
||||||
|
|
||||||
op_weight = "@" a:number
|
op_weight = "@" a:number
|
||||||
{ return x => x.options_['weight'] = a }
|
{ return x => x.options_['weight'] = a }
|
||||||
@ -139,6 +139,9 @@ op_fast = "*"a:slice
|
|||||||
op_degrade = "?"a:number?
|
op_degrade = "?"a:number?
|
||||||
{ return x => x.options_['ops'].push({ type_: "degradeBy", arguments_ :{ amount:a } }) }
|
{ return x => x.options_['ops'].push({ type_: "degradeBy", arguments_ :{ amount:a } }) }
|
||||||
|
|
||||||
|
op_tail = ":" s:slice
|
||||||
|
{ return x => x.options_['ops'].push({ type_: "tail", arguments_ :{ element:s } }) }
|
||||||
|
|
||||||
// a slice with an modifier applied i.e [bd@4 sd@3]@2 hh]
|
// a slice with an modifier applied i.e [bd@4 sd@3]@2 hh]
|
||||||
slice_with_ops = s:slice ops:slice_op*
|
slice_with_ops = s:slice ops:slice_op*
|
||||||
{ const result = new ElementStub(s, {ops: [], weight: 1, reps: 1});
|
{ const result = new ElementStub(s, {ops: [], weight: 1, reps: 1});
|
||||||
|
|||||||
@ -18,6 +18,7 @@ const applyOptions = (parent, code) => (pat, i) => {
|
|||||||
const ast = parent.source_[i];
|
const ast = parent.source_[i];
|
||||||
const options = ast.options_;
|
const options = ast.options_;
|
||||||
const ops = options?.ops;
|
const ops = options?.ops;
|
||||||
|
|
||||||
if (ops) {
|
if (ops) {
|
||||||
for (const op of ops) {
|
for (const op of ops) {
|
||||||
switch (op.type_) {
|
switch (op.type_) {
|
||||||
@ -66,6 +67,11 @@ const applyOptions = (parent, code) => (pat, i) => {
|
|||||||
pat = strudel.reify(pat).degradeBy(op.arguments_.amount === null ? 0.5 : op.arguments_.amount);
|
pat = strudel.reify(pat).degradeBy(op.arguments_.amount === null ? 0.5 : op.arguments_.amount);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'tail': {
|
||||||
|
const friend = patternifyAST(op.arguments_.element, code);
|
||||||
|
pat = pat.fmap((a) => (b) => Array.isArray(a) ? [...a, b] : [a, b]).appLeft(friend);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
console.warn(`operator "${op.type_}" not implemented`);
|
console.warn(`operator "${op.type_}" not implemented`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,6 +140,9 @@ describe('mini', () => {
|
|||||||
expect(haps.length < 230).toBe(true);
|
expect(haps.length < 230).toBe(true);
|
||||||
// 'Had too many cycles remaining after degradeBy 0.8');
|
// 'Had too many cycles remaining after degradeBy 0.8');
|
||||||
});
|
});
|
||||||
|
it('supports lists', () => {
|
||||||
|
expect(minV('a:b c:d:[e:f] g')).toEqual([['a', 'b'], ['c', 'd', ['e', 'f']], 'g']);
|
||||||
|
});
|
||||||
/*it('supports the random choice operator ("|") with nesting', () => {
|
/*it('supports the random choice operator ("|") with nesting', () => {
|
||||||
const numCycles = 900;
|
const numCycles = 900;
|
||||||
const haps = mini('a | [b | c] | [d | e | f]').queryArc(0, numCycles);
|
const haps = mini('a | [b | c] | [d | e | f]').queryArc(0, numCycles);
|
||||||
|
|||||||
@ -47,6 +47,7 @@ let startedAt = -1;
|
|||||||
*/
|
*/
|
||||||
Pattern.prototype.osc = function () {
|
Pattern.prototype.osc = function () {
|
||||||
return this.onTrigger(async (time, hap, currentTime, cps = 1) => {
|
return this.onTrigger(async (time, hap, currentTime, cps = 1) => {
|
||||||
|
hap.ensureObjectValue();
|
||||||
const osc = await connect();
|
const osc = await connect();
|
||||||
const cycle = hap.wholeOrPart().begin.valueOf();
|
const cycle = hap.wholeOrPart().begin.valueOf();
|
||||||
const delta = hap.duration.valueOf();
|
const delta = hap.duration.valueOf();
|
||||||
|
|||||||
@ -13,24 +13,43 @@ npm i @strudel.cycles/react
|
|||||||
Here is a minimal example of how to set up a MiniRepl:
|
Here is a minimal example of how to set up a MiniRepl:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { evalScope, controls } from '@strudel.cycles/core';
|
import * as React from 'react';
|
||||||
|
import '@strudel.cycles/react/dist/style.css';
|
||||||
import { MiniRepl } from '@strudel.cycles/react';
|
import { MiniRepl } from '@strudel.cycles/react';
|
||||||
import { prebake } from '../repl/src/prebake.mjs';
|
import { evalScope, controls } from '@strudel.cycles/core';
|
||||||
|
import { samples, initAudioOnFirstClick } from '@strudel.cycles/webaudio';
|
||||||
|
|
||||||
evalScope(
|
async function prebake() {
|
||||||
controls,
|
await samples(
|
||||||
import('@strudel.cycles/core'),
|
'https://strudel.tidalcycles.org/tidal-drum-machines.json',
|
||||||
import('@strudel.cycles/tonal'),
|
'github:ritchse/tidal-drum-machines/main/machines/'
|
||||||
import('@strudel.cycles/mini'),
|
);
|
||||||
import('@strudel.cycles/webaudio'),
|
await samples(
|
||||||
/* probably import other strudel packages */
|
'https://strudel.tidalcycles.org/EmuSP12.json',
|
||||||
);
|
'https://strudel.tidalcycles.org/EmuSP12/'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
prebake();
|
async function init() {
|
||||||
|
await evalScope(
|
||||||
|
controls,
|
||||||
|
import('@strudel.cycles/core'),
|
||||||
|
import('@strudel.cycles/mini'),
|
||||||
|
import('@strudel.cycles/webaudio'),
|
||||||
|
import('@strudel.cycles/tonal')
|
||||||
|
);
|
||||||
|
await prebake();
|
||||||
|
initAudioOnFirstClick();
|
||||||
|
}
|
||||||
|
|
||||||
export function Repl({ tune }) {
|
if (typeof window !== 'undefined') {
|
||||||
return <MiniRepl tune={tune} hideOutsideView={true} />;
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return <MiniRepl tune={`s("bd sd,hh*4")`} />;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For a more sophisticated example, check out the [nano-repl](./examples/nano-repl/)!
|
- Open [example on stackblitz](https://stackblitz.com/edit/react-ts-saaair?file=tune.tsx,App.tsx)
|
||||||
|
- Also check out the [nano-repl](./examples/nano-repl/) for a more sophisticated example
|
||||||
|
|||||||
15
packages/react/examples/nano-repl/README.md
Normal file
15
packages/react/examples/nano-repl/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# nano-repl
|
||||||
|
|
||||||
|
this is an example of how to create a repl with strudel and react.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
after cloning the strudel repo:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pnpm i
|
||||||
|
cd packages/react/examples/nano-repl
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
you should now have a repl running at `http://localhost:5173/`
|
||||||
@ -66,7 +66,7 @@ function App() {
|
|||||||
const [code, setCode] = useState(defaultTune);
|
const [code, setCode] = useState(defaultTune);
|
||||||
const [view, setView] = useState();
|
const [view, setView] = useState();
|
||||||
// const [code, setCode] = useState(`"c3".note().slow(2)`);
|
// const [code, setCode] = useState(`"c3".note().slow(2)`);
|
||||||
const { scheduler, evaluate, schedulerError, evalError, isDirty, activeCode, pattern } = useStrudel({
|
const { scheduler, evaluate, schedulerError, evalError, isDirty, activeCode, pattern, started } = useStrudel({
|
||||||
code,
|
code,
|
||||||
defaultOutput: webaudioOutput,
|
defaultOutput: webaudioOutput,
|
||||||
getTime,
|
getTime,
|
||||||
@ -75,8 +75,8 @@ function App() {
|
|||||||
useHighlighting({
|
useHighlighting({
|
||||||
view,
|
view,
|
||||||
pattern,
|
pattern,
|
||||||
active: !activeCode?.includes('strudel disable-highlighting'),
|
active: started && !activeCode?.includes('strudel disable-highlighting'),
|
||||||
getTime: () => scheduler.getPhase(),
|
getTime: () => scheduler.now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const error = evalError || schedulerError;
|
const error = evalError || schedulerError;
|
||||||
|
|||||||
@ -2,6 +2,18 @@
|
|||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background: #222;
|
||||||
|
--lineBackground: #22222250;
|
||||||
|
--foreground: #fff;
|
||||||
|
--caret: #ffcc00;
|
||||||
|
--selection: rgba(128, 203, 196, 0.5);
|
||||||
|
--selectionMatch: #036dd626;
|
||||||
|
--lineHighlight: #00000050;
|
||||||
|
--gutterBackground: transparent;
|
||||||
|
--gutterForeground: #8a919966;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: #123;
|
background: #123;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,9 +6,23 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// TODO: find out if leaving out tutorial path works now
|
// TODO: find out if leaving out tutorial path works now
|
||||||
content: ['./src/**/*.{js,jsx,ts,tsx}'],
|
content: ['./src/**/*.{js,jsx,ts,tsx}', '../../src/**/*.{html,js,jsx,md,mdx,ts,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {
|
||||||
|
colors: {
|
||||||
|
// codemirror-theme settings
|
||||||
|
background: 'var(--background)',
|
||||||
|
lineBackground: 'var(--lineBackground)',
|
||||||
|
foreground: 'var(--foreground)',
|
||||||
|
caret: 'var(--caret)',
|
||||||
|
selection: 'var(--selection)',
|
||||||
|
selectionMatch: 'var(--selectionMatch)',
|
||||||
|
gutterBackground: 'var(--gutterBackground)',
|
||||||
|
gutterForeground: 'var(--gutterForeground)',
|
||||||
|
gutterBorder: 'var(--gutterBorder)',
|
||||||
|
lineHighlight: 'var(--lineHighlight)',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/react",
|
"name": "@strudel.cycles/react",
|
||||||
"version": "0.6.0",
|
"version": "0.6.4",
|
||||||
"description": "React components for strudel",
|
"description": "React components for strudel",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@ -47,17 +47,17 @@
|
|||||||
"react-hook-inview": "^4.5.0"
|
"react-hook-inview": "^4.5.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^17.0.2",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^17.0.2"
|
"react-dom": "^18.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^17.0.2",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^17.0.2",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@vitejs/plugin-react": "^2.2.0",
|
"@vitejs/plugin-react": "^2.2.0",
|
||||||
"autoprefixer": "^10.4.7",
|
"autoprefixer": "^10.4.7",
|
||||||
"postcss": "^8.4.18",
|
"postcss": "^8.4.18",
|
||||||
"react": "^17.0.2",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.2.0",
|
||||||
"tailwindcss": "^3.0.24",
|
"tailwindcss": "^3.0.24",
|
||||||
"vite": "^3.2.2"
|
"vite": "^3.2.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,6 @@ evalScope(
|
|||||||
import('@strudel.cycles/core'),
|
import('@strudel.cycles/core'),
|
||||||
import('@strudel.cycles/tonal'),
|
import('@strudel.cycles/tonal'),
|
||||||
import('@strudel.cycles/mini'),
|
import('@strudel.cycles/mini'),
|
||||||
import('@strudel.cycles/midi'),
|
|
||||||
import('@strudel.cycles/xen'),
|
|
||||||
import('@strudel.cycles/webaudio'),
|
import('@strudel.cycles/webaudio'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import strudelTheme from '../themes/strudel-theme';
|
|||||||
import './style.css';
|
import './style.css';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { autocompletion } from '@codemirror/autocomplete';
|
import { autocompletion } from '@codemirror/autocomplete';
|
||||||
import { strudelAutocomplete } from './Autocomplete';
|
//import { strudelAutocomplete } from './Autocomplete';
|
||||||
import { vim } from '@replit/codemirror-vim';
|
import { vim } from '@replit/codemirror-vim';
|
||||||
import { emacs } from '@replit/codemirror-emacs';
|
import { emacs } from '@replit/codemirror-emacs';
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import useHighlighting from '../hooks/useHighlighting.mjs';
|
|||||||
import useStrudel from '../hooks/useStrudel.mjs';
|
import useStrudel from '../hooks/useStrudel.mjs';
|
||||||
import CodeMirror6, { flash } from './CodeMirror6';
|
import CodeMirror6, { flash } from './CodeMirror6';
|
||||||
import { Icon } from './Icon';
|
import { Icon } from './Icon';
|
||||||
import styles from './MiniRepl.module.css';
|
|
||||||
import './style.css';
|
import './style.css';
|
||||||
import { logger } from '@strudel.cycles/core';
|
import { logger } from '@strudel.cycles/core';
|
||||||
import useEvent from '../hooks/useEvent.mjs';
|
import useEvent from '../hooks/useEvent.mjs';
|
||||||
@ -129,19 +128,31 @@ export function MiniRepl({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container} ref={ref}>
|
<div className="overflow-hidden rounded-t-md bg-background border border-lineHighlight" ref={ref}>
|
||||||
<div className={styles.header}>
|
<div className="flex justify-between bg-lineHighlight">
|
||||||
<div className={styles.buttons}>
|
<div className="flex">
|
||||||
<button className={cx(styles.button, started ? 'animate-pulse' : '')} onClick={() => togglePlay()}>
|
<button
|
||||||
|
className={cx(
|
||||||
|
'cursor-pointer w-16 flex items-center justify-center p-1 border-r border-lineHighlight text-foreground bg-lineHighlight hover:bg-background',
|
||||||
|
started ? 'animate-pulse' : '',
|
||||||
|
)}
|
||||||
|
onClick={() => togglePlay()}
|
||||||
|
>
|
||||||
<Icon type={started ? 'stop' : 'play'} />
|
<Icon type={started ? 'stop' : 'play'} />
|
||||||
</button>
|
</button>
|
||||||
<button className={cx(isDirty ? styles.button : styles.buttonDisabled)} onClick={() => activateCode()}>
|
<button
|
||||||
|
className={cx(
|
||||||
|
'w-16 flex items-center justify-center p-1 text-foreground border-lineHighlight bg-lineHighlight',
|
||||||
|
isDirty ? 'text-foreground hover:bg-background cursor-pointer' : 'opacity-50 cursor-not-allowed',
|
||||||
|
)}
|
||||||
|
onClick={() => activateCode()}
|
||||||
|
>
|
||||||
<Icon type="refresh" />
|
<Icon type="refresh" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{error && <div className={styles.error}>{error.message}</div>}
|
{error && <div className="text-right p-1 text-sm text-red-200">{error.message}</div>}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.body}>
|
<div className="overflow-auto relative">
|
||||||
{show && <CodeMirror6 value={code} onChange={setCode} onViewChanged={setView} theme={theme} />}
|
{show && <CodeMirror6 value={code} onChange={setCode} onViewChanged={setView} theme={theme} />}
|
||||||
</div>
|
</div>
|
||||||
{drawTime && (
|
{drawTime && (
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
.container {
|
|
||||||
@apply overflow-hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
@apply flex justify-between bg-lineHighlight border-t border-l border-r border-lineHighlight rounded-t-md overflow-hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
@apply flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
@apply cursor-pointer w-16 flex items-center justify-center p-1 border-r border-lineHighlight text-foreground hover:bg-background;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttonDisabled {
|
|
||||||
@apply w-16 flex items-center justify-center p-1 opacity-50 cursor-not-allowed border-r border-lineHighlight;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
|
||||||
@apply text-right p-1 text-sm text-red-200;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body {
|
|
||||||
@apply overflow-auto relative;
|
|
||||||
}
|
|
||||||
@ -1,3 +1,15 @@
|
|||||||
|
:root {
|
||||||
|
--background: #222;
|
||||||
|
--lineBackground: #22222250;
|
||||||
|
--foreground: #fff;
|
||||||
|
--caret: #ffcc00;
|
||||||
|
--selection: rgba(128, 203, 196, 0.5);
|
||||||
|
--selectionMatch: #036dd626;
|
||||||
|
--lineHighlight: #00000050;
|
||||||
|
--gutterBackground: transparent;
|
||||||
|
--gutterForeground: #8a919966;
|
||||||
|
}
|
||||||
|
|
||||||
.cm-editor {
|
.cm-editor {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { setHighlights } from '../components/CodeMirror6';
|
import { setHighlights } from '../components/CodeMirror6';
|
||||||
|
const round = (x) => Math.round(x * 1000) / 1000;
|
||||||
|
|
||||||
function useHighlighting({ view, pattern, active, getTime }) {
|
function useHighlighting({ view, pattern, active, getTime }) {
|
||||||
const highlights = useRef([]);
|
const highlights = useRef([]);
|
||||||
@ -14,7 +15,7 @@ function useHighlighting({ view, pattern, active, getTime }) {
|
|||||||
// force min framerate of 10 fps => fixes crash on tab refocus, where lastEnd could be far away
|
// force min framerate of 10 fps => fixes crash on tab refocus, where lastEnd could be far away
|
||||||
// see https://github.com/tidalcycles/strudel/issues/108
|
// see https://github.com/tidalcycles/strudel/issues/108
|
||||||
const begin = Math.max(lastEnd.current ?? audioTime, audioTime - 1 / 10, -0.01); // negative time seems buggy
|
const begin = Math.max(lastEnd.current ?? audioTime, audioTime - 1 / 10, -0.01); // negative time seems buggy
|
||||||
const span = [begin, audioTime + 1 / 60];
|
const span = [round(begin), round(audioTime + 1 / 60)];
|
||||||
lastEnd.current = span[1];
|
lastEnd.current = span[1];
|
||||||
highlights.current = highlights.current.filter((hap) => hap.whole.end > audioTime); // keep only highlights that are still active
|
highlights.current = highlights.current.filter((hap) => hap.whole.end > audioTime); // keep only highlights that are still active
|
||||||
const haps = pattern.queryArc(...span).filter((hap) => hap.hasOnset());
|
const haps = pattern.queryArc(...span).filter((hap) => hap.hasOnset());
|
||||||
|
|||||||
@ -32,7 +32,7 @@ function useStrudel({
|
|||||||
const shouldPaint = useCallback((pat) => !!(pat?.context?.onPaint && drawContext), [drawContext]);
|
const shouldPaint = useCallback((pat) => !!(pat?.context?.onPaint && drawContext), [drawContext]);
|
||||||
|
|
||||||
// TODO: make sure this hook reruns when scheduler.started changes
|
// TODO: make sure this hook reruns when scheduler.started changes
|
||||||
const { scheduler, evaluate, start, stop, pause } = useMemo(
|
const { scheduler, evaluate, start, stop, pause, setCps } = useMemo(
|
||||||
() =>
|
() =>
|
||||||
repl({
|
repl({
|
||||||
interval,
|
interval,
|
||||||
@ -153,6 +153,7 @@ function useStrudel({
|
|||||||
stop,
|
stop,
|
||||||
pause,
|
pause,
|
||||||
togglePlay,
|
togglePlay,
|
||||||
|
setCps,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
ReactDOM.render(
|
createRoot(document.getElementById('root')).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<App />
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById('root'),
|
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,7 +1,21 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
content: ['./src/**/*.{js,jsx,ts,tsx}'],
|
content: ['./src/**/*.{js,jsx,ts,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {
|
||||||
|
colors: {
|
||||||
|
// codemirror-theme settings
|
||||||
|
background: 'var(--background)',
|
||||||
|
lineBackground: 'var(--lineBackground)',
|
||||||
|
foreground: 'var(--foreground)',
|
||||||
|
caret: 'var(--caret)',
|
||||||
|
selection: 'var(--selection)',
|
||||||
|
selectionMatch: 'var(--selectionMatch)',
|
||||||
|
gutterBackground: 'var(--gutterBackground)',
|
||||||
|
gutterForeground: 'var(--gutterForeground)',
|
||||||
|
gutterBorder: 'var(--gutterBorder)',
|
||||||
|
lineHighlight: 'var(--lineHighlight)',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
corePlugins: {
|
corePlugins: {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
import '../tonal.mjs'; // need to import this to add prototypes
|
import '../tonal.mjs'; // need to import this to add prototypes
|
||||||
import { pure, controls, seq } from '@strudel.cycles/core';
|
import { pure, controls, seq } from '@strudel.cycles/core';
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { mini } from '../../mini/mini.mjs';
|
||||||
const { n } = controls;
|
const { n } = controls;
|
||||||
|
|
||||||
describe('tonal', () => {
|
describe('tonal', () => {
|
||||||
@ -30,4 +31,18 @@ describe('tonal', () => {
|
|||||||
.firstCycleValues.map((h) => h.note),
|
.firstCycleValues.map((h) => h.note),
|
||||||
).toEqual(['C3', 'D3', 'E3']);
|
).toEqual(['C3', 'D3', 'E3']);
|
||||||
});
|
});
|
||||||
|
it('scale with colon', () => {
|
||||||
|
expect(
|
||||||
|
n(0, 1, 2)
|
||||||
|
.scale('C:major')
|
||||||
|
.firstCycleValues.map((h) => h.note),
|
||||||
|
).toEqual(['C3', 'D3', 'E3']);
|
||||||
|
});
|
||||||
|
it('scale with mininotation colon', () => {
|
||||||
|
expect(
|
||||||
|
n(0, 1, 2)
|
||||||
|
.scale(mini('C:major'))
|
||||||
|
.firstCycleValues.map((h) => h.note),
|
||||||
|
).toEqual(['C3', 'D3', 'E3']);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -123,29 +123,37 @@ export const scaleTranspose = register('scaleTranspose', function (offset /* : n
|
|||||||
/**
|
/**
|
||||||
* Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like {@link Pattern#scaleTranspose}.
|
* Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like {@link Pattern#scaleTranspose}.
|
||||||
*
|
*
|
||||||
* A scale consists of a root note (e.g. `c4`, `c`, `f#`, `bb4`) followed by a [scale type](https://github.com/tonaljs/tonal/blob/main/packages/scale-type/data.ts).
|
* A scale consists of a root note (e.g. `c4`, `c`, `f#`, `bb4`) followed by semicolon (':') and then a [scale type](https://github.com/tonaljs/tonal/blob/main/packages/scale-type/data.ts).
|
||||||
|
*
|
||||||
* The root note defaults to octave 3, if no octave number is given.
|
* The root note defaults to octave 3, if no octave number is given.
|
||||||
* Note that you currently cannot pattern `scale` with the mini notation, because the scale name includes a space.
|
|
||||||
* This will be improved in the future. Until then, use a sequence function like `cat` or `seq`.
|
|
||||||
*
|
*
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @name scale
|
* @name scale
|
||||||
* @param {string} scale Name of scale
|
* @param {string} scale Name of scale
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "0 2 4 6 4 2".scale('C2 major').note()
|
* "0 2 4 6 4 2".scale("C2:major").note()
|
||||||
* @example
|
* @example
|
||||||
* "0 2 4 6 4 2"
|
* "0 2 4 6 4 2"
|
||||||
* .scale(seq('C2 major', 'C2 minor').slow(2))
|
* .scale("C2:<major minor>")
|
||||||
* .note()
|
* .note()
|
||||||
|
* @example
|
||||||
|
* "0 1 2 3 4 5 6 7".rev().scale("C2:<major minor>").note()
|
||||||
|
* .s("folkharp")
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const scale = register('scale', function (scale /* : string */, pat) {
|
export const scale = register('scale', function (scale, pat) {
|
||||||
|
// Supports ':' list syntax in mininotation
|
||||||
|
if (Array.isArray(scale)) {
|
||||||
|
scale = scale.join(' ');
|
||||||
|
}
|
||||||
return pat.withHap((hap) => {
|
return pat.withHap((hap) => {
|
||||||
const isObject = typeof hap.value === 'object';
|
const isObject = typeof hap.value === 'object';
|
||||||
let note = isObject ? hap.value.n : hap.value;
|
let note = isObject ? hap.value.n : hap.value;
|
||||||
const asNumber = Number(note);
|
const asNumber = Number(note);
|
||||||
if (!isNaN(asNumber)) {
|
if (!isNaN(asNumber)) {
|
||||||
|
// TODO: worth keeping for supporting ':' in (non-mininotation) strings?
|
||||||
|
scale = scale.replaceAll(':', ' ');
|
||||||
let [tonic, scaleName] = Scale.tokenize(scale);
|
let [tonic, scaleName] = Scale.tokenize(scale);
|
||||||
const { pc, oct = 3 } = Note.get(tonic);
|
const { pc, oct = 3 } = Note.get(tonic);
|
||||||
note = scaleOffset(pc + ' ' + scaleName, asNumber, pc + oct);
|
note = scaleOffset(pc + ' ' + scaleName, asNumber, pc + oct);
|
||||||
|
|||||||
@ -97,17 +97,6 @@ const getSoundfontKey = (s) => {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
const splitSN = (s, n) => {
|
|
||||||
if (!s.includes(':')) {
|
|
||||||
return [s, n];
|
|
||||||
}
|
|
||||||
let [s2, n2] = s.split(':');
|
|
||||||
if (isNaN(Number(n2))) {
|
|
||||||
return [s, n];
|
|
||||||
}
|
|
||||||
return [s2, n2];
|
|
||||||
};
|
|
||||||
|
|
||||||
let workletsLoading;
|
let workletsLoading;
|
||||||
function loadWorklets() {
|
function loadWorklets() {
|
||||||
if (workletsLoading) {
|
if (workletsLoading) {
|
||||||
@ -191,23 +180,11 @@ function effectSend(input, effect, wet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// export const webaudioOutput = async (t, hap, ct, cps) => {
|
// export const webaudioOutput = async (t, hap, ct, cps) => {
|
||||||
export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
export const webaudioOutput = async (hap, deadline, hapDuration, cps) => {
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
/* if (isNote(hap.value)) {
|
hap.ensureObjectValue();
|
||||||
// supports primitive hap values that look like notes
|
|
||||||
hap.value = { note: hap.value };
|
// calculate absolute time
|
||||||
} */
|
|
||||||
if (typeof hap.value !== 'object') {
|
|
||||||
logger(
|
|
||||||
`hap.value "${hap.value}" is not supported by webaudio output. Hint: append .note() or .s() to the end`,
|
|
||||||
'error',
|
|
||||||
);
|
|
||||||
/* throw new Error(
|
|
||||||
`hap.value "${hap.value}"" is not supported by webaudio output. Hint: append .note() or .s() to the end`,
|
|
||||||
); */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// calculate correct time (tone.js workaround)
|
|
||||||
let t = ac.currentTime + deadline;
|
let t = ac.currentTime + deadline;
|
||||||
// destructure value
|
// destructure value
|
||||||
let {
|
let {
|
||||||
@ -220,20 +197,14 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
|||||||
note,
|
note,
|
||||||
gain = 0.8,
|
gain = 0.8,
|
||||||
// low pass
|
// low pass
|
||||||
lpf,
|
cutoff,
|
||||||
cutoff = lpf,
|
resonance = 1,
|
||||||
lpq = 1,
|
|
||||||
resonance = lpq,
|
|
||||||
// high pass
|
// high pass
|
||||||
hpf,
|
hcutoff,
|
||||||
hcutoff = hpf,
|
hresonance = 1,
|
||||||
hpq = 1,
|
|
||||||
hresonance = hpq,
|
|
||||||
// band pass
|
// band pass
|
||||||
bpf,
|
bandf,
|
||||||
bandf = bpf,
|
bandq = 1,
|
||||||
bpq = 1,
|
|
||||||
bandq = bpq,
|
|
||||||
//
|
//
|
||||||
coarse,
|
coarse,
|
||||||
crush,
|
crush,
|
||||||
@ -253,7 +224,6 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
|||||||
orbit = 1,
|
orbit = 1,
|
||||||
room,
|
room,
|
||||||
size = 2,
|
size = 2,
|
||||||
roomsize = size,
|
|
||||||
} = hap.value;
|
} = hap.value;
|
||||||
const { velocity = 1 } = hap.context;
|
const { velocity = 1 } = hap.context;
|
||||||
gain *= velocity; // legacy fix for velocity
|
gain *= velocity; // legacy fix for velocity
|
||||||
@ -262,12 +232,6 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
|||||||
if (bank && s) {
|
if (bank && s) {
|
||||||
s = `${bank}_${s}`;
|
s = `${bank}_${s}`;
|
||||||
}
|
}
|
||||||
if (typeof s === 'string') {
|
|
||||||
[s, n] = splitSN(s, n);
|
|
||||||
}
|
|
||||||
if (typeof note === 'string') {
|
|
||||||
[note, n] = splitSN(note, n);
|
|
||||||
}
|
|
||||||
if (!s || ['sine', 'square', 'triangle', 'sawtooth'].includes(s)) {
|
if (!s || ['sine', 'square', 'triangle', 'sawtooth'].includes(s)) {
|
||||||
// destructure adsr here, because the default should be different for synths and samples
|
// destructure adsr here, because the default should be different for synths and samples
|
||||||
const { attack = 0.001, decay = 0.05, sustain = 0.6, release = 0.01 } = hap.value;
|
const { attack = 0.001, decay = 0.05, sustain = 0.6, release = 0.01 } = hap.value;
|
||||||
@ -324,7 +288,7 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
|||||||
bufferSource.playbackRate.value = Math.abs(speed) * bufferSource.playbackRate.value;
|
bufferSource.playbackRate.value = Math.abs(speed) * bufferSource.playbackRate.value;
|
||||||
if (unit === 'c') {
|
if (unit === 'c') {
|
||||||
// are there other units?
|
// are there other units?
|
||||||
bufferSource.playbackRate.value = bufferSource.playbackRate.value * bufferSource.buffer.duration;
|
bufferSource.playbackRate.value = bufferSource.playbackRate.value * bufferSource.buffer.duration * cps;
|
||||||
}
|
}
|
||||||
let duration = soundfont || clip ? hapDuration : bufferSource.buffer.duration / bufferSource.playbackRate.value;
|
let duration = soundfont || clip ? hapDuration : bufferSource.buffer.duration / bufferSource.playbackRate.value;
|
||||||
// "The computation of the offset into the sound is performed using the sound buffer's natural sample rate,
|
// "The computation of the offset into the sound is performed using the sound buffer's natural sample rate,
|
||||||
@ -385,8 +349,8 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
|||||||
}
|
}
|
||||||
// reverb
|
// reverb
|
||||||
let reverbSend;
|
let reverbSend;
|
||||||
if (room > 0 && roomsize > 0) {
|
if (room > 0 && size > 0) {
|
||||||
const reverbNode = getReverb(orbit, roomsize);
|
const reverbNode = getReverb(orbit, size);
|
||||||
reverbSend = effectSend(post, reverbNode, room);
|
reverbSend = effectSend(post, reverbNode, room);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +361,7 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
|||||||
chain[0].onended = () => chain.concat([delaySend, reverbSend]).forEach((n) => n?.disconnect());
|
chain[0].onended = () => chain.concat([delaySend, reverbSend]).forEach((n) => n?.disconnect());
|
||||||
};
|
};
|
||||||
|
|
||||||
export const webaudioOutputTrigger = (t, hap, ct, cps) => webaudioOutput(hap, t - ct, hap.duration / cps);
|
export const webaudioOutputTrigger = (t, hap, ct, cps) => webaudioOutput(hap, t - ct, hap.duration / cps, cps);
|
||||||
|
|
||||||
Pattern.prototype.webaudio = function () {
|
Pattern.prototype.webaudio = function () {
|
||||||
// TODO: refactor (t, hap, ct, cps) to (hap, deadline, duration) ?
|
// TODO: refactor (t, hap, ct, cps) to (hap, deadline, duration) ?
|
||||||
|
|||||||
141
pnpm-lock.yaml
generated
141
pnpm-lock.yaml
generated
@ -11,6 +11,7 @@ importers:
|
|||||||
'@strudel.cycles/webaudio': workspace:*
|
'@strudel.cycles/webaudio': workspace:*
|
||||||
'@strudel.cycles/xen': workspace:*
|
'@strudel.cycles/xen': workspace:*
|
||||||
'@vitest/ui': ^0.25.7
|
'@vitest/ui': ^0.25.7
|
||||||
|
acorn: ^8.8.1
|
||||||
c8: ^7.12.0
|
c8: ^7.12.0
|
||||||
canvas: ^2.11.0
|
canvas: ^2.11.0
|
||||||
dependency-tree: ^9.0.0
|
dependency-tree: ^9.0.0
|
||||||
@ -32,6 +33,7 @@ importers:
|
|||||||
'@strudel.cycles/transpiler': link:packages/transpiler
|
'@strudel.cycles/transpiler': link:packages/transpiler
|
||||||
'@strudel.cycles/webaudio': link:packages/webaudio
|
'@strudel.cycles/webaudio': link:packages/webaudio
|
||||||
'@strudel.cycles/xen': link:packages/xen
|
'@strudel.cycles/xen': link:packages/xen
|
||||||
|
acorn: 8.8.2
|
||||||
dependency-tree: 9.0.0
|
dependency-tree: 9.0.0
|
||||||
vitest: 0.25.8_@vitest+ui@0.25.8
|
vitest: 0.25.8_@vitest+ui@0.25.8
|
||||||
devDependencies:
|
devDependencies:
|
||||||
@ -169,15 +171,15 @@ importers:
|
|||||||
'@strudel.cycles/core': workspace:*
|
'@strudel.cycles/core': workspace:*
|
||||||
'@strudel.cycles/transpiler': workspace:*
|
'@strudel.cycles/transpiler': workspace:*
|
||||||
'@strudel.cycles/webaudio': workspace:*
|
'@strudel.cycles/webaudio': workspace:*
|
||||||
'@types/react': ^17.0.2
|
'@types/react': ^18.0.28
|
||||||
'@types/react-dom': ^17.0.2
|
'@types/react-dom': ^18.0.11
|
||||||
'@uiw/codemirror-themes': ^4.12.4
|
'@uiw/codemirror-themes': ^4.12.4
|
||||||
'@uiw/react-codemirror': ^4.12.4
|
'@uiw/react-codemirror': ^4.12.4
|
||||||
'@vitejs/plugin-react': ^2.2.0
|
'@vitejs/plugin-react': ^2.2.0
|
||||||
autoprefixer: ^10.4.7
|
autoprefixer: ^10.4.7
|
||||||
postcss: ^8.4.18
|
postcss: ^8.4.18
|
||||||
react: ^17.0.2
|
react: ^18.2.0
|
||||||
react-dom: ^17.0.2
|
react-dom: ^18.2.0
|
||||||
react-hook-inview: ^4.5.0
|
react-hook-inview: ^4.5.0
|
||||||
tailwindcss: ^3.0.24
|
tailwindcss: ^3.0.24
|
||||||
vite: ^3.2.2
|
vite: ^3.2.2
|
||||||
@ -193,16 +195,16 @@ importers:
|
|||||||
'@strudel.cycles/transpiler': link:../transpiler
|
'@strudel.cycles/transpiler': link:../transpiler
|
||||||
'@strudel.cycles/webaudio': link:../webaudio
|
'@strudel.cycles/webaudio': link:../webaudio
|
||||||
'@uiw/codemirror-themes': 4.19.7_a4vbhepr4qhxm5cldqd4jpyase
|
'@uiw/codemirror-themes': 4.19.7_a4vbhepr4qhxm5cldqd4jpyase
|
||||||
'@uiw/react-codemirror': 4.19.7_r3x7zzmc35ug7i3c2vv4bf5iey
|
'@uiw/react-codemirror': 4.19.7_mtfgmdsccde6vjsd2vdv2ar7qq
|
||||||
react-hook-inview: 4.5.0_sfoxds7t5ydpegc3knd667wn6m
|
react-hook-inview: 4.5.0_biqbaboplfbrettd7655fr4n2y
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/react': 17.0.53
|
'@types/react': 18.0.28
|
||||||
'@types/react-dom': 17.0.18
|
'@types/react-dom': 18.0.11
|
||||||
'@vitejs/plugin-react': 2.2.0_vite@3.2.5
|
'@vitejs/plugin-react': 2.2.0_vite@3.2.5
|
||||||
autoprefixer: 10.4.13_postcss@8.4.21
|
autoprefixer: 10.4.13_postcss@8.4.21
|
||||||
postcss: 8.4.21
|
postcss: 8.4.21
|
||||||
react: 17.0.2
|
react: 18.2.0
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 18.2.0_react@18.2.0
|
||||||
tailwindcss: 3.2.4_postcss@8.4.21
|
tailwindcss: 3.2.4_postcss@8.4.21
|
||||||
vite: 3.2.5
|
vite: 3.2.5
|
||||||
|
|
||||||
@ -3965,23 +3967,15 @@ packages:
|
|||||||
/@types/prop-types/15.7.5:
|
/@types/prop-types/15.7.5:
|
||||||
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
|
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
|
||||||
|
|
||||||
/@types/react-dom/17.0.18:
|
|
||||||
resolution: {integrity: sha512-rLVtIfbwyur2iFKykP2w0pl/1unw26b5td16d5xMgp7/yjTHomkyxPYChFoCr/FtEX1lN9wY6lFj1qvKdS5kDw==}
|
|
||||||
dependencies:
|
|
||||||
'@types/react': 17.0.53
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/react-dom/18.0.10:
|
/@types/react-dom/18.0.10:
|
||||||
resolution: {integrity: sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==}
|
resolution: {integrity: sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 18.0.27
|
'@types/react': 18.0.28
|
||||||
|
|
||||||
/@types/react/17.0.53:
|
/@types/react-dom/18.0.11:
|
||||||
resolution: {integrity: sha512-1yIpQR2zdYu1Z/dc1OxC+MA6GR240u3gcnP4l6mvj/PJiVaqHsQPmWttsvHsfnhfPbU2FuGmo0wSITPygjBmsw==}
|
resolution: {integrity: sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/prop-types': 15.7.5
|
'@types/react': 18.0.28
|
||||||
'@types/scheduler': 0.16.2
|
|
||||||
csstype: 3.1.1
|
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/react/18.0.27:
|
/@types/react/18.0.27:
|
||||||
@ -3991,6 +3985,13 @@ packages:
|
|||||||
'@types/scheduler': 0.16.2
|
'@types/scheduler': 0.16.2
|
||||||
csstype: 3.1.1
|
csstype: 3.1.1
|
||||||
|
|
||||||
|
/@types/react/18.0.28:
|
||||||
|
resolution: {integrity: sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==}
|
||||||
|
dependencies:
|
||||||
|
'@types/prop-types': 15.7.5
|
||||||
|
'@types/scheduler': 0.16.2
|
||||||
|
csstype: 3.1.1
|
||||||
|
|
||||||
/@types/resolve/1.17.1:
|
/@types/resolve/1.17.1:
|
||||||
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
|
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4256,7 +4257,7 @@ packages:
|
|||||||
'@codemirror/view': 6.7.3
|
'@codemirror/view': 6.7.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@uiw/react-codemirror/4.19.7_r3x7zzmc35ug7i3c2vv4bf5iey:
|
/@uiw/react-codemirror/4.19.7_mtfgmdsccde6vjsd2vdv2ar7qq:
|
||||||
resolution: {integrity: sha512-IHvpYWVSdiaHX0Fk6oY6YyAJigDnyvSpWKNUTRzsMNxB+8/wqZ8lior4TprXH0zyLxW5F1+bTyifFFTeg+X3Sw==}
|
resolution: {integrity: sha512-IHvpYWVSdiaHX0Fk6oY6YyAJigDnyvSpWKNUTRzsMNxB+8/wqZ8lior4TprXH0zyLxW5F1+bTyifFFTeg+X3Sw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@codemirror/state': '>=6.0.0'
|
'@codemirror/state': '>=6.0.0'
|
||||||
@ -4271,8 +4272,8 @@ packages:
|
|||||||
'@codemirror/view': 6.7.3
|
'@codemirror/view': 6.7.3
|
||||||
'@uiw/codemirror-extensions-basic-setup': 4.19.7_cgfc5aojxuwjajwhkrgidrzxoa
|
'@uiw/codemirror-extensions-basic-setup': 4.19.7_cgfc5aojxuwjajwhkrgidrzxoa
|
||||||
codemirror: 6.0.1
|
codemirror: 6.0.1
|
||||||
react: 17.0.2
|
react: 18.2.0
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 18.2.0_react@18.2.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@codemirror/autocomplete'
|
- '@codemirror/autocomplete'
|
||||||
dev: false
|
dev: false
|
||||||
@ -10492,6 +10493,17 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/postcss-import/14.1.0:
|
||||||
|
resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==}
|
||||||
|
engines: {node: '>=10.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.0.0
|
||||||
|
dependencies:
|
||||||
|
postcss-value-parser: 4.2.0
|
||||||
|
read-cache: 1.0.0
|
||||||
|
resolve: 1.22.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/postcss-import/14.1.0_postcss@8.4.21:
|
/postcss-import/14.1.0_postcss@8.4.21:
|
||||||
resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==}
|
resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
@ -10502,6 +10514,16 @@ packages:
|
|||||||
postcss-value-parser: 4.2.0
|
postcss-value-parser: 4.2.0
|
||||||
read-cache: 1.0.0
|
read-cache: 1.0.0
|
||||||
resolve: 1.22.1
|
resolve: 1.22.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/postcss-js/4.0.0:
|
||||||
|
resolution: {integrity: sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==}
|
||||||
|
engines: {node: ^12 || ^14 || >= 16}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.3.3
|
||||||
|
dependencies:
|
||||||
|
camelcase-css: 2.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/postcss-js/4.0.0_postcss@8.4.21:
|
/postcss-js/4.0.0_postcss@8.4.21:
|
||||||
resolution: {integrity: sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==}
|
resolution: {integrity: sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==}
|
||||||
@ -10511,6 +10533,23 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
camelcase-css: 2.0.1
|
camelcase-css: 2.0.1
|
||||||
postcss: 8.4.21
|
postcss: 8.4.21
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/postcss-load-config/3.1.4:
|
||||||
|
resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: '>=8.0.9'
|
||||||
|
ts-node: '>=9.0.0'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
postcss:
|
||||||
|
optional: true
|
||||||
|
ts-node:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
lilconfig: 2.0.6
|
||||||
|
yaml: 1.10.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/postcss-load-config/3.1.4_postcss@8.4.21:
|
/postcss-load-config/3.1.4_postcss@8.4.21:
|
||||||
resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
|
resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
|
||||||
@ -10528,6 +10567,15 @@ packages:
|
|||||||
postcss: 8.4.21
|
postcss: 8.4.21
|
||||||
yaml: 1.10.2
|
yaml: 1.10.2
|
||||||
|
|
||||||
|
/postcss-nested/6.0.0:
|
||||||
|
resolution: {integrity: sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==}
|
||||||
|
engines: {node: '>=12.0'}
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.2.14
|
||||||
|
dependencies:
|
||||||
|
postcss-selector-parser: 6.0.11
|
||||||
|
dev: false
|
||||||
|
|
||||||
/postcss-nested/6.0.0_postcss@8.4.21:
|
/postcss-nested/6.0.0_postcss@8.4.21:
|
||||||
resolution: {integrity: sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==}
|
resolution: {integrity: sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==}
|
||||||
engines: {node: '>=12.0'}
|
engines: {node: '>=12.0'}
|
||||||
@ -10536,6 +10584,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
postcss: 8.4.21
|
postcss: 8.4.21
|
||||||
postcss-selector-parser: 6.0.11
|
postcss-selector-parser: 6.0.11
|
||||||
|
dev: true
|
||||||
|
|
||||||
/postcss-selector-parser/6.0.10:
|
/postcss-selector-parser/6.0.10:
|
||||||
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
|
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
|
||||||
@ -10817,16 +10866,6 @@ packages:
|
|||||||
strip-json-comments: 2.0.1
|
strip-json-comments: 2.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/react-dom/17.0.2_react@17.0.2:
|
|
||||||
resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==}
|
|
||||||
peerDependencies:
|
|
||||||
react: 17.0.2
|
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
object-assign: 4.1.1
|
|
||||||
react: 17.0.2
|
|
||||||
scheduler: 0.20.2
|
|
||||||
|
|
||||||
/react-dom/18.2.0_react@18.2.0:
|
/react-dom/18.2.0_react@18.2.0:
|
||||||
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
|
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -10835,16 +10874,15 @@ packages:
|
|||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
scheduler: 0.23.0
|
scheduler: 0.23.0
|
||||||
dev: false
|
|
||||||
|
|
||||||
/react-hook-inview/4.5.0_sfoxds7t5ydpegc3knd667wn6m:
|
/react-hook-inview/4.5.0_biqbaboplfbrettd7655fr4n2y:
|
||||||
resolution: {integrity: sha512-Hm61BK32/K2Cc3bjBe2bQkndHbQP6NhHvWVX7zYitaitB6T28uUV+wlgxbXU9twxUt7+17HyHq6aezpMUCijQQ==}
|
resolution: {integrity: sha512-Hm61BK32/K2Cc3bjBe2bQkndHbQP6NhHvWVX7zYitaitB6T28uUV+wlgxbXU9twxUt7+17HyHq6aezpMUCijQQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 17.0.2
|
react: 18.2.0
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 18.2.0_react@18.2.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/react-refresh/0.14.0:
|
/react-refresh/0.14.0:
|
||||||
@ -10852,19 +10890,11 @@ packages:
|
|||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/react/17.0.2:
|
|
||||||
resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
object-assign: 4.1.1
|
|
||||||
|
|
||||||
/react/18.2.0:
|
/react/18.2.0:
|
||||||
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
dev: false
|
|
||||||
|
|
||||||
/read-cache/1.0.0:
|
/read-cache/1.0.0:
|
||||||
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
|
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
|
||||||
@ -11521,17 +11551,10 @@ packages:
|
|||||||
commander: 2.20.3
|
commander: 2.20.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/scheduler/0.20.2:
|
|
||||||
resolution: {integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==}
|
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
object-assign: 4.1.1
|
|
||||||
|
|
||||||
/scheduler/0.23.0:
|
/scheduler/0.23.0:
|
||||||
resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
|
resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
dev: false
|
|
||||||
|
|
||||||
/section-matter/1.0.0:
|
/section-matter/1.0.0:
|
||||||
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
|
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
|
||||||
@ -12158,6 +12181,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==}
|
resolution: {integrity: sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==}
|
||||||
engines: {node: '>=12.13.0'}
|
engines: {node: '>=12.13.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
postcss: ^8.0.9
|
||||||
dependencies:
|
dependencies:
|
||||||
arg: 5.0.2
|
arg: 5.0.2
|
||||||
chokidar: 3.5.3
|
chokidar: 3.5.3
|
||||||
@ -12174,10 +12199,10 @@ packages:
|
|||||||
object-hash: 3.0.0
|
object-hash: 3.0.0
|
||||||
picocolors: 1.0.0
|
picocolors: 1.0.0
|
||||||
postcss: 8.4.21
|
postcss: 8.4.21
|
||||||
postcss-import: 14.1.0_postcss@8.4.21
|
postcss-import: 14.1.0
|
||||||
postcss-js: 4.0.0_postcss@8.4.21
|
postcss-js: 4.0.0
|
||||||
postcss-load-config: 3.1.4_postcss@8.4.21
|
postcss-load-config: 3.1.4
|
||||||
postcss-nested: 6.0.0_postcss@8.4.21
|
postcss-nested: 6.0.0
|
||||||
postcss-selector-parser: 6.0.11
|
postcss-selector-parser: 6.0.11
|
||||||
postcss-value-parser: 4.2.0
|
postcss-value-parser: 4.2.0
|
||||||
quick-lru: 5.1.1
|
quick-lru: 5.1.1
|
||||||
|
|||||||
@ -848,6 +848,23 @@ exports[`runs examples > example "arpWith" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "arrange" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/8 | note:c ]",
|
||||||
|
"[ 3/8 → 1/2 | note:c ]",
|
||||||
|
"[ 3/4 → 7/8 | note:c ]",
|
||||||
|
"[ 1/1 → 9/8 | note:a ]",
|
||||||
|
"[ 11/8 → 3/2 | note:a ]",
|
||||||
|
"[ 7/4 → 15/8 | note:a ]",
|
||||||
|
"[ 2/1 → 17/8 | note:f ]",
|
||||||
|
"[ 19/8 → 5/2 | note:f ]",
|
||||||
|
"[ 11/4 → 23/8 | note:f ]",
|
||||||
|
"[ 3/1 → 25/8 | note:e ]",
|
||||||
|
"[ 27/8 → 7/2 | note:e ]",
|
||||||
|
"[ 15/4 → 31/8 | note:e ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "attack" example index 0 1`] = `
|
exports[`runs examples > example "attack" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | note:c3 attack:0 ]",
|
"[ 0/1 → 1/2 | note:c3 attack:0 ]",
|
||||||
@ -885,39 +902,39 @@ exports[`runs examples > example "begin" example index 0 1`] = `
|
|||||||
|
|
||||||
exports[`runs examples > example "bpf" example index 0 1`] = `
|
exports[`runs examples > example "bpf" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd bpf:1000 ]",
|
"[ 0/1 → 1/2 | s:bd bandf:1000 ]",
|
||||||
"[ 1/2 → 1/1 | s:sd bpf:1000 ]",
|
"[ 1/2 → 1/1 | s:sd bandf:1000 ]",
|
||||||
"[ 0/1 → 1/3 | s:hh bpf:1000 ]",
|
"[ 0/1 → 1/3 | s:hh bandf:1000 ]",
|
||||||
"[ 1/3 → 2/3 | s:hh bpf:1000 ]",
|
"[ 1/3 → 2/3 | s:hh bandf:1000 ]",
|
||||||
"[ 2/3 → 1/1 | s:hh bpf:1000 ]",
|
"[ 2/3 → 1/1 | s:hh bandf:1000 ]",
|
||||||
"[ 1/1 → 3/2 | s:bd bpf:2000 ]",
|
"[ 1/1 → 3/2 | s:bd bandf:2000 ]",
|
||||||
"[ 3/2 → 2/1 | s:sd bpf:2000 ]",
|
"[ 3/2 → 2/1 | s:sd bandf:2000 ]",
|
||||||
"[ 1/1 → 4/3 | s:hh bpf:2000 ]",
|
"[ 1/1 → 4/3 | s:hh bandf:2000 ]",
|
||||||
"[ 4/3 → 5/3 | s:hh bpf:2000 ]",
|
"[ 4/3 → 5/3 | s:hh bandf:2000 ]",
|
||||||
"[ 5/3 → 2/1 | s:hh bpf:2000 ]",
|
"[ 5/3 → 2/1 | s:hh bandf:2000 ]",
|
||||||
"[ 2/1 → 5/2 | s:bd bpf:4000 ]",
|
"[ 2/1 → 5/2 | s:bd bandf:4000 ]",
|
||||||
"[ 5/2 → 3/1 | s:sd bpf:4000 ]",
|
"[ 5/2 → 3/1 | s:sd bandf:4000 ]",
|
||||||
"[ 2/1 → 7/3 | s:hh bpf:4000 ]",
|
"[ 2/1 → 7/3 | s:hh bandf:4000 ]",
|
||||||
"[ 7/3 → 8/3 | s:hh bpf:4000 ]",
|
"[ 7/3 → 8/3 | s:hh bandf:4000 ]",
|
||||||
"[ 8/3 → 3/1 | s:hh bpf:4000 ]",
|
"[ 8/3 → 3/1 | s:hh bandf:4000 ]",
|
||||||
"[ 3/1 → 7/2 | s:bd bpf:8000 ]",
|
"[ 3/1 → 7/2 | s:bd bandf:8000 ]",
|
||||||
"[ 7/2 → 4/1 | s:sd bpf:8000 ]",
|
"[ 7/2 → 4/1 | s:sd bandf:8000 ]",
|
||||||
"[ 3/1 → 10/3 | s:hh bpf:8000 ]",
|
"[ 3/1 → 10/3 | s:hh bandf:8000 ]",
|
||||||
"[ 10/3 → 11/3 | s:hh bpf:8000 ]",
|
"[ 10/3 → 11/3 | s:hh bandf:8000 ]",
|
||||||
"[ 11/3 → 4/1 | s:hh bpf:8000 ]",
|
"[ 11/3 → 4/1 | s:hh bandf:8000 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "bpq" example index 0 1`] = `
|
exports[`runs examples > example "bpq" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd bpf:500 bpq:0 ]",
|
"[ 0/1 → 1/2 | s:bd bandf:500 bandq:0 ]",
|
||||||
"[ 1/2 → 1/1 | s:sd bpf:500 bpq:0 ]",
|
"[ 1/2 → 1/1 | s:sd bandf:500 bandq:0 ]",
|
||||||
"[ 1/1 → 3/2 | s:bd bpf:500 bpq:1 ]",
|
"[ 1/1 → 3/2 | s:bd bandf:500 bandq:1 ]",
|
||||||
"[ 3/2 → 2/1 | s:sd bpf:500 bpq:1 ]",
|
"[ 3/2 → 2/1 | s:sd bandf:500 bandq:1 ]",
|
||||||
"[ 2/1 → 5/2 | s:bd bpf:500 bpq:2 ]",
|
"[ 2/1 → 5/2 | s:bd bandf:500 bandq:2 ]",
|
||||||
"[ 5/2 → 3/1 | s:sd bpf:500 bpq:2 ]",
|
"[ 5/2 → 3/1 | s:sd bandf:500 bandq:2 ]",
|
||||||
"[ 3/1 → 7/2 | s:bd bpf:500 bpq:3 ]",
|
"[ 3/1 → 7/2 | s:bd bandf:500 bandq:3 ]",
|
||||||
"[ 7/2 → 4/1 | s:sd bpf:500 bpq:3 ]",
|
"[ 7/2 → 4/1 | s:sd bandf:500 bandq:3 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -1399,6 +1416,19 @@ exports[`runs examples > example "delay" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "delay" example index 1 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/2 | s:bd delay:0.65 delaytime:0.25 delayfeedback:0.9 ]",
|
||||||
|
"[ 1/2 → 1/1 | s:bd delay:0.65 delaytime:0.125 delayfeedback:0.7 ]",
|
||||||
|
"[ 1/1 → 3/2 | s:bd delay:0.65 delaytime:0.25 delayfeedback:0.9 ]",
|
||||||
|
"[ 3/2 → 2/1 | s:bd delay:0.65 delaytime:0.125 delayfeedback:0.7 ]",
|
||||||
|
"[ 2/1 → 5/2 | s:bd delay:0.65 delaytime:0.25 delayfeedback:0.9 ]",
|
||||||
|
"[ 5/2 → 3/1 | s:bd delay:0.65 delaytime:0.125 delayfeedback:0.7 ]",
|
||||||
|
"[ 3/1 → 7/2 | s:bd delay:0.65 delaytime:0.25 delayfeedback:0.9 ]",
|
||||||
|
"[ 7/2 → 4/1 | s:bd delay:0.65 delaytime:0.125 delayfeedback:0.7 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "delayfeedback" example index 0 1`] = `
|
exports[`runs examples > example "delayfeedback" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ (0/1 → 1/1) ⇝ 2/1 | s:bd delay:0.25 delayfeedback:0.25 ]",
|
"[ (0/1 → 1/1) ⇝ 2/1 | s:bd delay:0.25 delayfeedback:0.25 ]",
|
||||||
@ -1896,78 +1926,107 @@ exports[`runs examples > example "gain" example index 0 1`] = `
|
|||||||
|
|
||||||
exports[`runs examples > example "hpf" example index 0 1`] = `
|
exports[`runs examples > example "hpf" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd hpf:4000 ]",
|
"[ 0/1 → 1/2 | s:bd hcutoff:4000 ]",
|
||||||
"[ 1/2 → 1/1 | s:sd hpf:4000 ]",
|
"[ 1/2 → 1/1 | s:sd hcutoff:4000 ]",
|
||||||
"[ 0/1 → 1/4 | s:hh hpf:4000 ]",
|
"[ 0/1 → 1/4 | s:hh hcutoff:4000 ]",
|
||||||
"[ 1/4 → 1/2 | s:hh hpf:4000 ]",
|
"[ 1/4 → 1/2 | s:hh hcutoff:4000 ]",
|
||||||
"[ 1/2 → 3/4 | s:hh hpf:4000 ]",
|
"[ 1/2 → 3/4 | s:hh hcutoff:4000 ]",
|
||||||
"[ 3/4 → 1/1 | s:hh hpf:4000 ]",
|
"[ 3/4 → 1/1 | s:hh hcutoff:4000 ]",
|
||||||
"[ 1/1 → 3/2 | s:bd hpf:2000 ]",
|
"[ 1/1 → 3/2 | s:bd hcutoff:2000 ]",
|
||||||
"[ 3/2 → 2/1 | s:sd hpf:2000 ]",
|
"[ 3/2 → 2/1 | s:sd hcutoff:2000 ]",
|
||||||
"[ 1/1 → 5/4 | s:hh hpf:2000 ]",
|
"[ 1/1 → 5/4 | s:hh hcutoff:2000 ]",
|
||||||
"[ 5/4 → 3/2 | s:hh hpf:2000 ]",
|
"[ 5/4 → 3/2 | s:hh hcutoff:2000 ]",
|
||||||
"[ 3/2 → 7/4 | s:hh hpf:2000 ]",
|
"[ 3/2 → 7/4 | s:hh hcutoff:2000 ]",
|
||||||
"[ 7/4 → 2/1 | s:hh hpf:2000 ]",
|
"[ 7/4 → 2/1 | s:hh hcutoff:2000 ]",
|
||||||
"[ 2/1 → 5/2 | s:bd hpf:1000 ]",
|
"[ 2/1 → 5/2 | s:bd hcutoff:1000 ]",
|
||||||
"[ 5/2 → 3/1 | s:sd hpf:1000 ]",
|
"[ 5/2 → 3/1 | s:sd hcutoff:1000 ]",
|
||||||
"[ 2/1 → 9/4 | s:hh hpf:1000 ]",
|
"[ 2/1 → 9/4 | s:hh hcutoff:1000 ]",
|
||||||
"[ 9/4 → 5/2 | s:hh hpf:1000 ]",
|
"[ 9/4 → 5/2 | s:hh hcutoff:1000 ]",
|
||||||
"[ 5/2 → 11/4 | s:hh hpf:1000 ]",
|
"[ 5/2 → 11/4 | s:hh hcutoff:1000 ]",
|
||||||
"[ 11/4 → 3/1 | s:hh hpf:1000 ]",
|
"[ 11/4 → 3/1 | s:hh hcutoff:1000 ]",
|
||||||
"[ 3/1 → 7/2 | s:bd hpf:500 ]",
|
"[ 3/1 → 7/2 | s:bd hcutoff:500 ]",
|
||||||
"[ 7/2 → 4/1 | s:sd hpf:500 ]",
|
"[ 7/2 → 4/1 | s:sd hcutoff:500 ]",
|
||||||
"[ 3/1 → 13/4 | s:hh hpf:500 ]",
|
"[ 3/1 → 13/4 | s:hh hcutoff:500 ]",
|
||||||
"[ 13/4 → 7/2 | s:hh hpf:500 ]",
|
"[ 13/4 → 7/2 | s:hh hcutoff:500 ]",
|
||||||
"[ 7/2 → 15/4 | s:hh hpf:500 ]",
|
"[ 7/2 → 15/4 | s:hh hcutoff:500 ]",
|
||||||
"[ 15/4 → 4/1 | s:hh hpf:500 ]",
|
"[ 15/4 → 4/1 | s:hh hcutoff:500 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "hpf" example index 1 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/2 | s:bd hcutoff:2000 ]",
|
||||||
|
"[ 1/2 → 1/1 | s:sd hcutoff:2000 ]",
|
||||||
|
"[ 0/1 → 1/4 | s:hh hcutoff:2000 ]",
|
||||||
|
"[ 1/4 → 1/2 | s:hh hcutoff:2000 ]",
|
||||||
|
"[ 1/2 → 3/4 | s:hh hcutoff:2000 ]",
|
||||||
|
"[ 3/4 → 1/1 | s:hh hcutoff:2000 ]",
|
||||||
|
"[ 1/1 → 3/2 | s:bd hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 3/2 → 2/1 | s:sd hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 1/1 → 5/4 | s:hh hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 5/4 → 3/2 | s:hh hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 3/2 → 7/4 | s:hh hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 7/4 → 2/1 | s:hh hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 2/1 → 5/2 | s:bd hcutoff:2000 ]",
|
||||||
|
"[ 5/2 → 3/1 | s:sd hcutoff:2000 ]",
|
||||||
|
"[ 2/1 → 9/4 | s:hh hcutoff:2000 ]",
|
||||||
|
"[ 9/4 → 5/2 | s:hh hcutoff:2000 ]",
|
||||||
|
"[ 5/2 → 11/4 | s:hh hcutoff:2000 ]",
|
||||||
|
"[ 11/4 → 3/1 | s:hh hcutoff:2000 ]",
|
||||||
|
"[ 3/1 → 7/2 | s:bd hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 7/2 → 4/1 | s:sd hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 3/1 → 13/4 | s:hh hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 13/4 → 7/2 | s:hh hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 7/2 → 15/4 | s:hh hcutoff:2000 hresonance:25 ]",
|
||||||
|
"[ 15/4 → 4/1 | s:hh hcutoff:2000 hresonance:25 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "hpq" example index 0 1`] = `
|
exports[`runs examples > example "hpq" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd hpf:2000 hpq:0 ]",
|
"[ 0/1 → 1/2 | s:bd hcutoff:2000 hresonance:0 ]",
|
||||||
"[ 1/2 → 1/1 | s:sd hpf:2000 hpq:0 ]",
|
"[ 1/2 → 1/1 | s:sd hcutoff:2000 hresonance:0 ]",
|
||||||
"[ 0/1 → 1/4 | s:hh hpf:2000 hpq:0 ]",
|
"[ 0/1 → 1/4 | s:hh hcutoff:2000 hresonance:0 ]",
|
||||||
"[ 1/4 → 1/2 | s:hh hpf:2000 hpq:0 ]",
|
"[ 1/4 → 1/2 | s:hh hcutoff:2000 hresonance:0 ]",
|
||||||
"[ 1/2 → 3/4 | s:hh hpf:2000 hpq:0 ]",
|
"[ 1/2 → 3/4 | s:hh hcutoff:2000 hresonance:0 ]",
|
||||||
"[ 3/4 → 1/1 | s:hh hpf:2000 hpq:0 ]",
|
"[ 3/4 → 1/1 | s:hh hcutoff:2000 hresonance:0 ]",
|
||||||
"[ 1/1 → 3/2 | s:bd hpf:2000 hpq:10 ]",
|
"[ 1/1 → 3/2 | s:bd hcutoff:2000 hresonance:10 ]",
|
||||||
"[ 3/2 → 2/1 | s:sd hpf:2000 hpq:10 ]",
|
"[ 3/2 → 2/1 | s:sd hcutoff:2000 hresonance:10 ]",
|
||||||
"[ 1/1 → 5/4 | s:hh hpf:2000 hpq:10 ]",
|
"[ 1/1 → 5/4 | s:hh hcutoff:2000 hresonance:10 ]",
|
||||||
"[ 5/4 → 3/2 | s:hh hpf:2000 hpq:10 ]",
|
"[ 5/4 → 3/2 | s:hh hcutoff:2000 hresonance:10 ]",
|
||||||
"[ 3/2 → 7/4 | s:hh hpf:2000 hpq:10 ]",
|
"[ 3/2 → 7/4 | s:hh hcutoff:2000 hresonance:10 ]",
|
||||||
"[ 7/4 → 2/1 | s:hh hpf:2000 hpq:10 ]",
|
"[ 7/4 → 2/1 | s:hh hcutoff:2000 hresonance:10 ]",
|
||||||
"[ 2/1 → 5/2 | s:bd hpf:2000 hpq:20 ]",
|
"[ 2/1 → 5/2 | s:bd hcutoff:2000 hresonance:20 ]",
|
||||||
"[ 5/2 → 3/1 | s:sd hpf:2000 hpq:20 ]",
|
"[ 5/2 → 3/1 | s:sd hcutoff:2000 hresonance:20 ]",
|
||||||
"[ 2/1 → 9/4 | s:hh hpf:2000 hpq:20 ]",
|
"[ 2/1 → 9/4 | s:hh hcutoff:2000 hresonance:20 ]",
|
||||||
"[ 9/4 → 5/2 | s:hh hpf:2000 hpq:20 ]",
|
"[ 9/4 → 5/2 | s:hh hcutoff:2000 hresonance:20 ]",
|
||||||
"[ 5/2 → 11/4 | s:hh hpf:2000 hpq:20 ]",
|
"[ 5/2 → 11/4 | s:hh hcutoff:2000 hresonance:20 ]",
|
||||||
"[ 11/4 → 3/1 | s:hh hpf:2000 hpq:20 ]",
|
"[ 11/4 → 3/1 | s:hh hcutoff:2000 hresonance:20 ]",
|
||||||
"[ 3/1 → 7/2 | s:bd hpf:2000 hpq:30 ]",
|
"[ 3/1 → 7/2 | s:bd hcutoff:2000 hresonance:30 ]",
|
||||||
"[ 7/2 → 4/1 | s:sd hpf:2000 hpq:30 ]",
|
"[ 7/2 → 4/1 | s:sd hcutoff:2000 hresonance:30 ]",
|
||||||
"[ 3/1 → 13/4 | s:hh hpf:2000 hpq:30 ]",
|
"[ 3/1 → 13/4 | s:hh hcutoff:2000 hresonance:30 ]",
|
||||||
"[ 13/4 → 7/2 | s:hh hpf:2000 hpq:30 ]",
|
"[ 13/4 → 7/2 | s:hh hcutoff:2000 hresonance:30 ]",
|
||||||
"[ 7/2 → 15/4 | s:hh hpf:2000 hpq:30 ]",
|
"[ 7/2 → 15/4 | s:hh hcutoff:2000 hresonance:30 ]",
|
||||||
"[ 15/4 → 4/1 | s:hh hpf:2000 hpq:30 ]",
|
"[ 15/4 → 4/1 | s:hh hcutoff:2000 hresonance:30 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "hurry" example index 0 1`] = `
|
exports[`runs examples > example "hurry" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 3/4 | s:bd speed:1 ]",
|
"[ 0/1 → 3/4 | s:bd speed:1 ]",
|
||||||
"[ (3/4 → 1/1) ⇝ 3/2 | s:sd:2 speed:1 ]",
|
"[ (3/4 → 1/1) ⇝ 3/2 | s:sd n:2 speed:1 ]",
|
||||||
"[ 3/4 ⇜ (1/1 → 3/2) | s:sd:2 speed:1 ]",
|
"[ 3/4 ⇜ (1/1 → 3/2) | s:sd n:2 speed:1 ]",
|
||||||
"[ 3/2 → 15/8 | s:bd speed:2 ]",
|
"[ 3/2 → 15/8 | s:bd speed:2 ]",
|
||||||
"[ (15/8 → 2/1) ⇝ 9/4 | s:sd:2 speed:2 ]",
|
"[ (15/8 → 2/1) ⇝ 9/4 | s:sd n:2 speed:2 ]",
|
||||||
"[ 15/8 ⇜ (2/1 → 9/4) | s:sd:2 speed:2 ]",
|
"[ 15/8 ⇜ (2/1 → 9/4) | s:sd n:2 speed:2 ]",
|
||||||
"[ 9/4 → 21/8 | s:bd speed:2 ]",
|
"[ 9/4 → 21/8 | s:bd speed:2 ]",
|
||||||
"[ 21/8 → 3/1 | s:sd:2 speed:2 ]",
|
"[ 21/8 → 3/1 | s:sd n:2 speed:2 ]",
|
||||||
"[ 3/1 → 51/16 | s:bd speed:4 ]",
|
"[ 3/1 → 51/16 | s:bd speed:4 ]",
|
||||||
"[ 51/16 → 27/8 | s:sd:2 speed:4 ]",
|
"[ 51/16 → 27/8 | s:sd n:2 speed:4 ]",
|
||||||
"[ 27/8 → 57/16 | s:bd speed:4 ]",
|
"[ 27/8 → 57/16 | s:bd speed:4 ]",
|
||||||
"[ 57/16 → 15/4 | s:sd:2 speed:4 ]",
|
"[ 57/16 → 15/4 | s:sd n:2 speed:4 ]",
|
||||||
"[ 15/4 → 63/16 | s:bd speed:4 ]",
|
"[ 15/4 → 63/16 | s:bd speed:4 ]",
|
||||||
"[ (63/16 → 4/1) ⇝ 33/8 | s:sd:2 speed:4 ]",
|
"[ (63/16 → 4/1) ⇝ 33/8 | s:sd n:2 speed:4 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -2383,55 +2442,92 @@ exports[`runs examples > example "loopAtCps" example index 0 1`] = `
|
|||||||
|
|
||||||
exports[`runs examples > example "lpf" example index 0 1`] = `
|
exports[`runs examples > example "lpf" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd lpf:4000 ]",
|
"[ 0/1 → 1/2 | s:bd cutoff:4000 ]",
|
||||||
"[ 1/2 → 1/1 | s:sd lpf:4000 ]",
|
"[ 1/2 → 1/1 | s:sd cutoff:4000 ]",
|
||||||
"[ 0/1 → 1/3 | s:hh lpf:4000 ]",
|
"[ 0/1 → 1/3 | s:hh cutoff:4000 ]",
|
||||||
"[ 1/3 → 2/3 | s:hh lpf:4000 ]",
|
"[ 1/3 → 2/3 | s:hh cutoff:4000 ]",
|
||||||
"[ 2/3 → 1/1 | s:hh lpf:4000 ]",
|
"[ 2/3 → 1/1 | s:hh cutoff:4000 ]",
|
||||||
"[ 1/1 → 3/2 | s:bd lpf:2000 ]",
|
"[ 1/1 → 3/2 | s:bd cutoff:2000 ]",
|
||||||
"[ 3/2 → 2/1 | s:sd lpf:2000 ]",
|
"[ 3/2 → 2/1 | s:sd cutoff:2000 ]",
|
||||||
"[ 1/1 → 4/3 | s:hh lpf:2000 ]",
|
"[ 1/1 → 4/3 | s:hh cutoff:2000 ]",
|
||||||
"[ 4/3 → 5/3 | s:hh lpf:2000 ]",
|
"[ 4/3 → 5/3 | s:hh cutoff:2000 ]",
|
||||||
"[ 5/3 → 2/1 | s:hh lpf:2000 ]",
|
"[ 5/3 → 2/1 | s:hh cutoff:2000 ]",
|
||||||
"[ 2/1 → 5/2 | s:bd lpf:1000 ]",
|
"[ 2/1 → 5/2 | s:bd cutoff:1000 ]",
|
||||||
"[ 5/2 → 3/1 | s:sd lpf:1000 ]",
|
"[ 5/2 → 3/1 | s:sd cutoff:1000 ]",
|
||||||
"[ 2/1 → 7/3 | s:hh lpf:1000 ]",
|
"[ 2/1 → 7/3 | s:hh cutoff:1000 ]",
|
||||||
"[ 7/3 → 8/3 | s:hh lpf:1000 ]",
|
"[ 7/3 → 8/3 | s:hh cutoff:1000 ]",
|
||||||
"[ 8/3 → 3/1 | s:hh lpf:1000 ]",
|
"[ 8/3 → 3/1 | s:hh cutoff:1000 ]",
|
||||||
"[ 3/1 → 7/2 | s:bd lpf:500 ]",
|
"[ 3/1 → 7/2 | s:bd cutoff:500 ]",
|
||||||
"[ 7/2 → 4/1 | s:sd lpf:500 ]",
|
"[ 7/2 → 4/1 | s:sd cutoff:500 ]",
|
||||||
"[ 3/1 → 10/3 | s:hh lpf:500 ]",
|
"[ 3/1 → 10/3 | s:hh cutoff:500 ]",
|
||||||
"[ 10/3 → 11/3 | s:hh lpf:500 ]",
|
"[ 10/3 → 11/3 | s:hh cutoff:500 ]",
|
||||||
"[ 11/3 → 4/1 | s:hh lpf:500 ]",
|
"[ 11/3 → 4/1 | s:hh cutoff:500 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "lpf" example index 1 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/8 | s:bd cutoff:1000 resonance:0 ]",
|
||||||
|
"[ 1/8 → 1/4 | s:bd cutoff:1000 resonance:0 ]",
|
||||||
|
"[ 1/4 → 3/8 | s:bd cutoff:1000 resonance:10 ]",
|
||||||
|
"[ 3/8 → 1/2 | s:bd cutoff:1000 resonance:10 ]",
|
||||||
|
"[ 1/2 → 5/8 | s:bd cutoff:1000 resonance:20 ]",
|
||||||
|
"[ 5/8 → 3/4 | s:bd cutoff:1000 resonance:20 ]",
|
||||||
|
"[ 3/4 → 7/8 | s:bd cutoff:1000 resonance:30 ]",
|
||||||
|
"[ 7/8 → 1/1 | s:bd cutoff:1000 resonance:30 ]",
|
||||||
|
"[ 1/1 → 9/8 | s:bd cutoff:1000 resonance:0 ]",
|
||||||
|
"[ 9/8 → 5/4 | s:bd cutoff:1000 resonance:0 ]",
|
||||||
|
"[ 5/4 → 11/8 | s:bd cutoff:1000 resonance:10 ]",
|
||||||
|
"[ 11/8 → 3/2 | s:bd cutoff:1000 resonance:10 ]",
|
||||||
|
"[ 3/2 → 13/8 | s:bd cutoff:1000 resonance:20 ]",
|
||||||
|
"[ 13/8 → 7/4 | s:bd cutoff:1000 resonance:20 ]",
|
||||||
|
"[ 7/4 → 15/8 | s:bd cutoff:1000 resonance:30 ]",
|
||||||
|
"[ 15/8 → 2/1 | s:bd cutoff:1000 resonance:30 ]",
|
||||||
|
"[ 2/1 → 17/8 | s:bd cutoff:1000 resonance:0 ]",
|
||||||
|
"[ 17/8 → 9/4 | s:bd cutoff:1000 resonance:0 ]",
|
||||||
|
"[ 9/4 → 19/8 | s:bd cutoff:1000 resonance:10 ]",
|
||||||
|
"[ 19/8 → 5/2 | s:bd cutoff:1000 resonance:10 ]",
|
||||||
|
"[ 5/2 → 21/8 | s:bd cutoff:1000 resonance:20 ]",
|
||||||
|
"[ 21/8 → 11/4 | s:bd cutoff:1000 resonance:20 ]",
|
||||||
|
"[ 11/4 → 23/8 | s:bd cutoff:1000 resonance:30 ]",
|
||||||
|
"[ 23/8 → 3/1 | s:bd cutoff:1000 resonance:30 ]",
|
||||||
|
"[ 3/1 → 25/8 | s:bd cutoff:1000 resonance:0 ]",
|
||||||
|
"[ 25/8 → 13/4 | s:bd cutoff:1000 resonance:0 ]",
|
||||||
|
"[ 13/4 → 27/8 | s:bd cutoff:1000 resonance:10 ]",
|
||||||
|
"[ 27/8 → 7/2 | s:bd cutoff:1000 resonance:10 ]",
|
||||||
|
"[ 7/2 → 29/8 | s:bd cutoff:1000 resonance:20 ]",
|
||||||
|
"[ 29/8 → 15/4 | s:bd cutoff:1000 resonance:20 ]",
|
||||||
|
"[ 15/4 → 31/8 | s:bd cutoff:1000 resonance:30 ]",
|
||||||
|
"[ 31/8 → 4/1 | s:bd cutoff:1000 resonance:30 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "lpq" example index 0 1`] = `
|
exports[`runs examples > example "lpq" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd lpf:2000 lpq:0 ]",
|
"[ 0/1 → 1/2 | s:bd cutoff:2000 resonance:0 ]",
|
||||||
"[ 1/2 → 1/1 | s:sd lpf:2000 lpq:0 ]",
|
"[ 1/2 → 1/1 | s:sd cutoff:2000 resonance:0 ]",
|
||||||
"[ 0/1 → 1/4 | s:hh lpf:2000 lpq:0 ]",
|
"[ 0/1 → 1/4 | s:hh cutoff:2000 resonance:0 ]",
|
||||||
"[ 1/4 → 1/2 | s:hh lpf:2000 lpq:0 ]",
|
"[ 1/4 → 1/2 | s:hh cutoff:2000 resonance:0 ]",
|
||||||
"[ 1/2 → 3/4 | s:hh lpf:2000 lpq:0 ]",
|
"[ 1/2 → 3/4 | s:hh cutoff:2000 resonance:0 ]",
|
||||||
"[ 3/4 → 1/1 | s:hh lpf:2000 lpq:0 ]",
|
"[ 3/4 → 1/1 | s:hh cutoff:2000 resonance:0 ]",
|
||||||
"[ 1/1 → 3/2 | s:bd lpf:2000 lpq:10 ]",
|
"[ 1/1 → 3/2 | s:bd cutoff:2000 resonance:10 ]",
|
||||||
"[ 3/2 → 2/1 | s:sd lpf:2000 lpq:10 ]",
|
"[ 3/2 → 2/1 | s:sd cutoff:2000 resonance:10 ]",
|
||||||
"[ 1/1 → 5/4 | s:hh lpf:2000 lpq:10 ]",
|
"[ 1/1 → 5/4 | s:hh cutoff:2000 resonance:10 ]",
|
||||||
"[ 5/4 → 3/2 | s:hh lpf:2000 lpq:10 ]",
|
"[ 5/4 → 3/2 | s:hh cutoff:2000 resonance:10 ]",
|
||||||
"[ 3/2 → 7/4 | s:hh lpf:2000 lpq:10 ]",
|
"[ 3/2 → 7/4 | s:hh cutoff:2000 resonance:10 ]",
|
||||||
"[ 7/4 → 2/1 | s:hh lpf:2000 lpq:10 ]",
|
"[ 7/4 → 2/1 | s:hh cutoff:2000 resonance:10 ]",
|
||||||
"[ 2/1 → 5/2 | s:bd lpf:2000 lpq:20 ]",
|
"[ 2/1 → 5/2 | s:bd cutoff:2000 resonance:20 ]",
|
||||||
"[ 5/2 → 3/1 | s:sd lpf:2000 lpq:20 ]",
|
"[ 5/2 → 3/1 | s:sd cutoff:2000 resonance:20 ]",
|
||||||
"[ 2/1 → 9/4 | s:hh lpf:2000 lpq:20 ]",
|
"[ 2/1 → 9/4 | s:hh cutoff:2000 resonance:20 ]",
|
||||||
"[ 9/4 → 5/2 | s:hh lpf:2000 lpq:20 ]",
|
"[ 9/4 → 5/2 | s:hh cutoff:2000 resonance:20 ]",
|
||||||
"[ 5/2 → 11/4 | s:hh lpf:2000 lpq:20 ]",
|
"[ 5/2 → 11/4 | s:hh cutoff:2000 resonance:20 ]",
|
||||||
"[ 11/4 → 3/1 | s:hh lpf:2000 lpq:20 ]",
|
"[ 11/4 → 3/1 | s:hh cutoff:2000 resonance:20 ]",
|
||||||
"[ 3/1 → 7/2 | s:bd lpf:2000 lpq:30 ]",
|
"[ 3/1 → 7/2 | s:bd cutoff:2000 resonance:30 ]",
|
||||||
"[ 7/2 → 4/1 | s:sd lpf:2000 lpq:30 ]",
|
"[ 7/2 → 4/1 | s:sd cutoff:2000 resonance:30 ]",
|
||||||
"[ 3/1 → 13/4 | s:hh lpf:2000 lpq:30 ]",
|
"[ 3/1 → 13/4 | s:hh cutoff:2000 resonance:30 ]",
|
||||||
"[ 13/4 → 7/2 | s:hh lpf:2000 lpq:30 ]",
|
"[ 13/4 → 7/2 | s:hh cutoff:2000 resonance:30 ]",
|
||||||
"[ 7/2 → 15/4 | s:hh lpf:2000 lpq:30 ]",
|
"[ 7/2 → 15/4 | s:hh cutoff:2000 resonance:30 ]",
|
||||||
"[ 15/4 → 4/1 | s:hh lpf:2000 lpq:30 ]",
|
"[ 15/4 → 4/1 | s:hh cutoff:2000 resonance:30 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -3231,16 +3327,29 @@ exports[`runs examples > example "room" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "room" example index 1 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/2 | s:bd room:0.9 size:1 ]",
|
||||||
|
"[ 1/2 → 1/1 | s:sd room:0.9 size:1 ]",
|
||||||
|
"[ 1/1 → 3/2 | s:bd room:0.9 size:4 ]",
|
||||||
|
"[ 3/2 → 2/1 | s:sd room:0.9 size:4 ]",
|
||||||
|
"[ 2/1 → 5/2 | s:bd room:0.9 size:1 ]",
|
||||||
|
"[ 5/2 → 3/1 | s:sd room:0.9 size:1 ]",
|
||||||
|
"[ 3/1 → 7/2 | s:bd room:0.9 size:4 ]",
|
||||||
|
"[ 7/2 → 4/1 | s:sd room:0.9 size:4 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "roomsize" example index 0 1`] = `
|
exports[`runs examples > example "roomsize" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd room:0.8 roomsize:0 ]",
|
"[ 0/1 → 1/2 | s:bd room:0.8 size:0 ]",
|
||||||
"[ 1/2 → 1/1 | s:sd room:0.8 roomsize:0 ]",
|
"[ 1/2 → 1/1 | s:sd room:0.8 size:0 ]",
|
||||||
"[ 1/1 → 3/2 | s:bd room:0.8 roomsize:1 ]",
|
"[ 1/1 → 3/2 | s:bd room:0.8 size:1 ]",
|
||||||
"[ 3/2 → 2/1 | s:sd room:0.8 roomsize:1 ]",
|
"[ 3/2 → 2/1 | s:sd room:0.8 size:1 ]",
|
||||||
"[ 2/1 → 5/2 | s:bd room:0.8 roomsize:2 ]",
|
"[ 2/1 → 5/2 | s:bd room:0.8 size:2 ]",
|
||||||
"[ 5/2 → 3/1 | s:sd room:0.8 roomsize:2 ]",
|
"[ 5/2 → 3/1 | s:sd room:0.8 size:2 ]",
|
||||||
"[ 3/1 → 7/2 | s:bd room:0.8 roomsize:4 ]",
|
"[ 3/1 → 7/2 | s:bd room:0.8 size:4 ]",
|
||||||
"[ 7/2 → 4/1 | s:sd room:0.8 roomsize:4 ]",
|
"[ 7/2 → 4/1 | s:sd room:0.8 size:4 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -3304,6 +3413,27 @@ exports[`runs examples > example "s" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "s" example index 1 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/4 | s:bd n:0 ]",
|
||||||
|
"[ 1/4 → 1/2 | s:bd n:1 ]",
|
||||||
|
"[ 1/2 → 3/4 | s:bd n:0 gain:0.3 ]",
|
||||||
|
"[ 3/4 → 1/1 | s:bd n:1 gain:1.4 ]",
|
||||||
|
"[ 1/1 → 5/4 | s:bd n:0 ]",
|
||||||
|
"[ 5/4 → 3/2 | s:bd n:1 ]",
|
||||||
|
"[ 3/2 → 7/4 | s:bd n:0 gain:0.3 ]",
|
||||||
|
"[ 7/4 → 2/1 | s:bd n:1 gain:1.4 ]",
|
||||||
|
"[ 2/1 → 9/4 | s:bd n:0 ]",
|
||||||
|
"[ 9/4 → 5/2 | s:bd n:1 ]",
|
||||||
|
"[ 5/2 → 11/4 | s:bd n:0 gain:0.3 ]",
|
||||||
|
"[ 11/4 → 3/1 | s:bd n:1 gain:1.4 ]",
|
||||||
|
"[ 3/1 → 13/4 | s:bd n:0 ]",
|
||||||
|
"[ 13/4 → 7/2 | s:bd n:1 ]",
|
||||||
|
"[ 7/2 → 15/4 | s:bd n:0 gain:0.3 ]",
|
||||||
|
"[ 15/4 → 4/1 | s:bd n:1 gain:1.4 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "samples" example index 0 1`] = `
|
exports[`runs examples > example "samples" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/4 | s:bd ]",
|
"[ 0/1 → 1/4 | s:bd ]",
|
||||||
@ -3454,6 +3584,43 @@ exports[`runs examples > example "scale" example index 1 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "scale" example index 2 1`] = `
|
||||||
|
[
|
||||||
|
"[ 7/8 → 1/1 | note:C2 s:folkharp ]",
|
||||||
|
"[ 3/4 → 7/8 | note:D2 s:folkharp ]",
|
||||||
|
"[ 5/8 → 3/4 | note:E2 s:folkharp ]",
|
||||||
|
"[ 1/2 → 5/8 | note:F2 s:folkharp ]",
|
||||||
|
"[ 3/8 → 1/2 | note:G2 s:folkharp ]",
|
||||||
|
"[ 1/4 → 3/8 | note:A2 s:folkharp ]",
|
||||||
|
"[ 1/8 → 1/4 | note:B2 s:folkharp ]",
|
||||||
|
"[ 0/1 → 1/8 | note:C3 s:folkharp ]",
|
||||||
|
"[ 15/8 → 2/1 | note:C2 s:folkharp ]",
|
||||||
|
"[ 7/4 → 15/8 | note:D2 s:folkharp ]",
|
||||||
|
"[ 13/8 → 7/4 | note:Eb2 s:folkharp ]",
|
||||||
|
"[ 3/2 → 13/8 | note:F2 s:folkharp ]",
|
||||||
|
"[ 11/8 → 3/2 | note:G2 s:folkharp ]",
|
||||||
|
"[ 5/4 → 11/8 | note:Ab2 s:folkharp ]",
|
||||||
|
"[ 9/8 → 5/4 | note:Bb2 s:folkharp ]",
|
||||||
|
"[ 1/1 → 9/8 | note:C3 s:folkharp ]",
|
||||||
|
"[ 23/8 → 3/1 | note:C2 s:folkharp ]",
|
||||||
|
"[ 11/4 → 23/8 | note:D2 s:folkharp ]",
|
||||||
|
"[ 21/8 → 11/4 | note:E2 s:folkharp ]",
|
||||||
|
"[ 5/2 → 21/8 | note:F2 s:folkharp ]",
|
||||||
|
"[ 19/8 → 5/2 | note:G2 s:folkharp ]",
|
||||||
|
"[ 9/4 → 19/8 | note:A2 s:folkharp ]",
|
||||||
|
"[ 17/8 → 9/4 | note:B2 s:folkharp ]",
|
||||||
|
"[ 2/1 → 17/8 | note:C3 s:folkharp ]",
|
||||||
|
"[ 31/8 → 4/1 | note:C2 s:folkharp ]",
|
||||||
|
"[ 15/4 → 31/8 | note:D2 s:folkharp ]",
|
||||||
|
"[ 29/8 → 15/4 | note:Eb2 s:folkharp ]",
|
||||||
|
"[ 7/2 → 29/8 | note:F2 s:folkharp ]",
|
||||||
|
"[ 27/8 → 7/2 | note:G2 s:folkharp ]",
|
||||||
|
"[ 13/4 → 27/8 | note:Ab2 s:folkharp ]",
|
||||||
|
"[ 25/8 → 13/4 | note:Bb2 s:folkharp ]",
|
||||||
|
"[ 3/1 → 25/8 | note:C3 s:folkharp ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "scaleTranspose" example index 0 1`] = `
|
exports[`runs examples > example "scaleTranspose" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | note:C3 ]",
|
"[ 0/1 → 1/2 | note:C3 ]",
|
||||||
@ -3690,39 +3857,6 @@ exports[`runs examples > example "sine" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "slice" example index 0 1`] = `
|
|
||||||
[
|
|
||||||
"[ (15/16 → 1/1) ⇝ 9/8 | begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 3/4 → 15/16 | begin:0.375 end:0.5 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 21/32 → 3/4 | begin:0.5 end:0.625 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 9/16 → 21/32 | begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 3/8 → 9/16 | begin:0.625 end:0.75 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 3/16 → 3/8 | begin:0.75 end:0.875 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 0/1 → 3/16 | begin:0.875 end:1 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 21/16 → 3/2 | begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 9/8 → 21/16 | begin:0.125 end:0.25 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 15/16 ⇜ (1/1 → 9/8) | begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 3/2 → 27/16 | begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 27/16 → 15/8 | begin:0.125 end:0.25 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 15/8 → 63/32 | begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ (63/32 → 2/1) ⇝ 33/16 | begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 63/32 ⇜ (2/1 → 33/16) | begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 33/16 → 9/4 | begin:0.375 end:0.5 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 9/4 → 75/32 | begin:0.5 end:0.625 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 75/32 → 39/16 | begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 39/16 → 21/8 | begin:0.625 end:0.75 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 21/8 → 45/16 | begin:0.75 end:0.875 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 45/16 → 3/1 | begin:0.875 end:1 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 3/1 → 51/16 | begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 51/16 → 27/8 | begin:0.125 end:0.25 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 27/8 → 57/16 | begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 57/16 → 15/4 | begin:0.375 end:0.5 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 15/4 → 123/32 | begin:0.5 end:0.625 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 123/32 → 63/16 | begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ (63/16 → 4/1) ⇝ 33/8 | begin:0.625 end:0.75 _slices:8 s:breaks165 ]",
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`runs examples > example "slow" example index 0 1`] = `
|
exports[`runs examples > example "slow" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/1 | s:bd ]",
|
"[ 0/1 → 1/1 | s:bd ]",
|
||||||
@ -3848,36 +3982,6 @@ exports[`runs examples > example "speed" example index 1 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "splice" example index 0 1`] = `
|
|
||||||
[
|
|
||||||
"[ 0/1 → 5/26 | speed:0.65 unit:c begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 5/26 → 5/13 | speed:0.65 unit:c begin:0.125 end:0.25 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 5/13 → 20/39 | speed:0.9750000000000001 unit:c begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 20/39 → 25/39 | speed:0.9750000000000001 unit:c begin:0.375 end:0.5 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 25/39 → 10/13 | speed:0.9750000000000001 unit:c begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 10/13 → 25/26 | speed:0.65 unit:c begin:0.375 end:0.5 _slices:8 s:breaks165 ]",
|
|
||||||
"[ (25/26 → 1/1) ⇝ 35/26 | speed:0.325 unit:c begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 25/26 ⇜ (1/1 → 35/26) | speed:0.325 unit:c begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 35/26 → 20/13 | speed:0.65 unit:c begin:0.875 end:1 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 20/13 → 45/26 | speed:0.65 unit:c begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 45/26 → 25/13 | speed:0.65 unit:c begin:0.125 end:0.25 _slices:8 s:breaks165 ]",
|
|
||||||
"[ (25/13 → 2/1) ⇝ 80/39 | speed:0.9750000000000001 unit:c begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 25/13 ⇜ (2/1 → 80/39) | speed:0.9750000000000001 unit:c begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 80/39 → 85/39 | speed:0.9750000000000001 unit:c begin:0.375 end:0.5 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 85/39 → 30/13 | speed:0.9750000000000001 unit:c begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 30/13 → 5/2 | speed:0.65 unit:c begin:0.375 end:0.5 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 5/2 → 75/26 | speed:0.325 unit:c begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ (75/26 → 3/1) ⇝ 40/13 | speed:0.65 unit:c begin:0.875 end:1 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 75/26 ⇜ (3/1 → 40/13) | speed:0.65 unit:c begin:0.875 end:1 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 40/13 → 85/26 | speed:0.65 unit:c begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 85/26 → 45/13 | speed:0.65 unit:c begin:0.125 end:0.25 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 45/13 → 140/39 | speed:0.9750000000000001 unit:c begin:0.25 end:0.375 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 140/39 → 145/39 | speed:0.9750000000000001 unit:c begin:0.375 end:0.5 _slices:8 s:breaks165 ]",
|
|
||||||
"[ 145/39 → 50/13 | speed:0.9750000000000001 unit:c begin:0 end:0.125 _slices:8 s:breaks165 ]",
|
|
||||||
"[ (50/13 → 4/1) ⇝ 105/26 | speed:0.65 unit:c begin:0.375 end:0.5 _slices:8 s:breaks165 ]",
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`runs examples > example "square" example index 0 1`] = `
|
exports[`runs examples > example "square" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | note:C3 ]",
|
"[ 0/1 → 1/2 | note:C3 ]",
|
||||||
@ -4294,48 +4398,6 @@ exports[`runs examples > example "vowel" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "weave" example index 0 1`] = `
|
|
||||||
[
|
|
||||||
"[ 0/1 → 1/8 | pan:0.015625 s:bd ]",
|
|
||||||
"[ 3/8 → 1/2 | pan:0.109375 s:bd ]",
|
|
||||||
"[ 3/4 → 7/8 | pan:0.203125 s:bd ]",
|
|
||||||
"[ 1/1 → 9/8 | pan:0.265625 s:bd ]",
|
|
||||||
"[ 11/8 → 3/2 | pan:0.359375 s:bd ]",
|
|
||||||
"[ 7/4 → 15/8 | pan:0.453125 s:bd ]",
|
|
||||||
"[ 2/1 → 17/8 | pan:0.515625 s:bd ]",
|
|
||||||
"[ 19/8 → 5/2 | pan:0.609375 s:bd ]",
|
|
||||||
"[ 11/4 → 23/8 | pan:0.703125 s:bd ]",
|
|
||||||
"[ 3/1 → 25/8 | pan:0.765625 s:bd ]",
|
|
||||||
"[ 27/8 → 7/2 | pan:0.859375 s:bd ]",
|
|
||||||
"[ 15/4 → 31/8 | pan:0.953125 s:bd ]",
|
|
||||||
"[ 1/2 → 1/1 | pan:0.6875 s:sd ]",
|
|
||||||
"[ 3/2 → 2/1 | pan:0.9375 s:sd ]",
|
|
||||||
"[ 5/2 → 3/1 | pan:0.1875 s:sd ]",
|
|
||||||
"[ 7/2 → 4/1 | pan:0.4375 s:sd ]",
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`runs examples > example "weave" example index 1 1`] = `
|
|
||||||
[
|
|
||||||
"[ 0/1 → 1/8 | n:0 s:bd ]",
|
|
||||||
"[ 3/8 → 1/2 | n:0 s:bd ]",
|
|
||||||
"[ 3/4 → 7/8 | n:0 s:bd ]",
|
|
||||||
"[ 1/1 → 9/8 | n:1 s:bd ]",
|
|
||||||
"[ 11/8 → 3/2 | n:1 s:bd ]",
|
|
||||||
"[ 7/4 → 15/8 | n:1 s:bd ]",
|
|
||||||
"[ 2/1 → 17/8 | n:2 s:bd ]",
|
|
||||||
"[ 19/8 → 5/2 | n:2 s:bd ]",
|
|
||||||
"[ 11/4 → 23/8 | n:2 s:bd ]",
|
|
||||||
"[ 3/1 → 25/8 | n:3 s:bd ]",
|
|
||||||
"[ 27/8 → 7/2 | n:3 s:bd ]",
|
|
||||||
"[ 15/4 → 31/8 | n:3 s:bd ]",
|
|
||||||
"[ 1/2 → 1/1 | n:4 s:sd ]",
|
|
||||||
"[ 3/2 → 2/1 | n:5 s:sd ]",
|
|
||||||
"[ 5/2 → 3/1 | n:6 s:sd ]",
|
|
||||||
"[ 7/2 → 4/1 | n:7 s:sd ]",
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`runs examples > example "webdirt" example index 0 1`] = `
|
exports[`runs examples > example "webdirt" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/8 | s:bd n:0 ]",
|
"[ 0/1 → 1/8 | s:bd n:0 ]",
|
||||||
|
|||||||
@ -298,11 +298,11 @@ exports[`renders tunes > tune: bassFuge 1`] = `
|
|||||||
"[ -3/4 ⇜ (0/1 → 3/4) ⇝ 5/4 | note:C5 s:flbass n:0 gain:0.3 cutoff:2924.3791043233605 resonance:10 clip:1 ]",
|
"[ -3/4 ⇜ (0/1 → 3/4) ⇝ 5/4 | note:C5 s:flbass n:0 gain:0.3 cutoff:2924.3791043233605 resonance:10 clip:1 ]",
|
||||||
"[ -3/4 ⇜ (3/4 → 1/1) ⇝ 5/4 | note:A4 s:flbass n:0 gain:0.3 cutoff:2924.3791043233605 resonance:10 clip:1 ]",
|
"[ -3/4 ⇜ (3/4 → 1/1) ⇝ 5/4 | note:A4 s:flbass n:0 gain:0.3 cutoff:2924.3791043233605 resonance:10 clip:1 ]",
|
||||||
"[ -3/4 ⇜ (3/4 → 1/1) ⇝ 5/4 | note:C5 s:flbass n:0 gain:0.3 cutoff:2924.3791043233605 resonance:10 clip:1 ]",
|
"[ -3/4 ⇜ (3/4 → 1/1) ⇝ 5/4 | note:C5 s:flbass n:0 gain:0.3 cutoff:2924.3791043233605 resonance:10 clip:1 ]",
|
||||||
"[ 0/1 → 1/2 | s:bd:1 ]",
|
"[ 0/1 → 1/2 | s:bd n:1 ]",
|
||||||
"[ 1/2 → 1/1 | s:bd:1 ]",
|
"[ 1/2 → 1/1 | s:bd n:1 ]",
|
||||||
"[ 1/2 → 1/1 | s:sd:0 ]",
|
"[ 1/2 → 1/1 | s:sd n:0 ]",
|
||||||
"[ 1/4 → 1/2 | s:hh:0 ]",
|
"[ 1/4 → 1/2 | s:hh n:0 ]",
|
||||||
"[ 3/4 → 1/1 | s:hh:0 ]",
|
"[ 3/4 → 1/1 | s:hh n:0 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -313,7 +313,7 @@ exports[`renders tunes > tune: belldub 1`] = `
|
|||||||
"[ (5/8 → 1/1) ⇝ 5/4 | s:hh room:0 end:0.04483079938329212 ]",
|
"[ (5/8 → 1/1) ⇝ 5/4 | s:hh room:0 end:0.04483079938329212 ]",
|
||||||
"[ 0/1 → 5/16 | s:mt gain:0.5 room:0.5 ]",
|
"[ 0/1 → 5/16 | s:mt gain:0.5 room:0.5 ]",
|
||||||
"[ (15/16 → 1/1) ⇝ 5/4 | s:lt gain:0.5 room:0.5 ]",
|
"[ (15/16 → 1/1) ⇝ 5/4 | s:lt gain:0.5 room:0.5 ]",
|
||||||
"[ (0/1 → 1/1) ⇝ 5/1 | s:misc:2 speed:1 delay:0.5 delaytime:0.3333333333333333 gain:0.4 ]",
|
"[ (0/1 → 1/1) ⇝ 5/1 | s:misc n:2 speed:1 delay:0.5 delaytime:0.3333333333333333 gain:0.4 ]",
|
||||||
"[ (5/8 → 1/1) ⇝ 5/4 | note:F3 s:sawtooth gain:0.5 cutoff:400.16785462816676 decay:0.05380063255866716 sustain:0 delay:0.9 room:1 ]",
|
"[ (5/8 → 1/1) ⇝ 5/4 | note:F3 s:sawtooth gain:0.5 cutoff:400.16785462816676 decay:0.05380063255866716 sustain:0 delay:0.9 room:1 ]",
|
||||||
"[ (5/8 → 1/1) ⇝ 5/4 | note:A3 s:sawtooth gain:0.5 cutoff:400.16785462816676 decay:0.05380063255866716 sustain:0 delay:0.9 room:1 ]",
|
"[ (5/8 → 1/1) ⇝ 5/4 | note:A3 s:sawtooth gain:0.5 cutoff:400.16785462816676 decay:0.05380063255866716 sustain:0 delay:0.9 room:1 ]",
|
||||||
"[ (5/8 → 1/1) ⇝ 5/4 | note:Bb3 s:sawtooth gain:0.5 cutoff:400.16785462816676 decay:0.05380063255866716 sustain:0 delay:0.9 room:1 ]",
|
"[ (5/8 → 1/1) ⇝ 5/4 | note:Bb3 s:sawtooth gain:0.5 cutoff:400.16785462816676 decay:0.05380063255866716 sustain:0 delay:0.9 room:1 ]",
|
||||||
@ -6974,16 +6974,16 @@ exports[`renders tunes > tune: flatrave 1`] = `
|
|||||||
"[ 1/2 → 1/1 | s:bd bank:RolandTR909 ]",
|
"[ 1/2 → 1/1 | s:bd bank:RolandTR909 ]",
|
||||||
"[ 1/2 → 1/1 | s:cp bank:RolandTR909 ]",
|
"[ 1/2 → 1/1 | s:cp bank:RolandTR909 ]",
|
||||||
"[ 1/2 → 1/1 | s:sd bank:RolandTR909 ]",
|
"[ 1/2 → 1/1 | s:sd bank:RolandTR909 ]",
|
||||||
"[ 0/1 → 1/4 | s:hh:1 end:0.02000058072071123 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 0/1 → 1/4 | s:hh n:1 end:0.02000058072071123 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 0/1 ⇜ (1/8 → 1/4) | s:hh:1 end:0.02000058072071123 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 0/1 ⇜ (1/8 → 1/4) | s:hh n:1 end:0.02000058072071123 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 1/4 → 3/8 | s:hh:1 end:0.02000875429921906 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 1/4 → 3/8 | s:hh n:1 end:0.02000875429921906 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 1/4 → 3/8 | s:hh:1 end:0.02000875429921906 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 1/4 → 3/8 | s:hh n:1 end:0.02000875429921906 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 3/8 → 1/2 | s:hh:1 end:0.020023446730265706 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 3/8 → 1/2 | s:hh n:1 end:0.020023446730265706 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 5/8 → 3/4 | s:hh:1 end:0.020086608138500644 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 5/8 → 3/4 | s:hh n:1 end:0.020086608138500644 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 5/8 → 3/4 | s:hh:1 end:0.020086608138500644 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 5/8 → 3/4 | s:hh n:1 end:0.020086608138500644 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 3/4 → 7/8 | s:hh:1 end:0.02013941880355398 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 3/4 → 7/8 | s:hh n:1 end:0.02013941880355398 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 1/8 → 1/4 | s:hh:1 speed:0.5 delay:0.5 end:0.020001936784171157 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 1/8 → 1/4 | s:hh n:1 speed:0.5 delay:0.5 end:0.020001936784171157 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 1/8 → 1/4 | s:hh:1 speed:0.5 delay:0.5 end:0.020001936784171157 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
"[ 1/8 → 1/4 | s:hh n:1 speed:0.5 delay:0.5 end:0.020001936784171157 bank:RolandTR909 room:0.5 gain:0.4 ]",
|
||||||
"[ 1/8 → 1/4 | note:G1 s:sawtooth decay:0.1 sustain:0 ]",
|
"[ 1/8 → 1/4 | note:G1 s:sawtooth decay:0.1 sustain:0 ]",
|
||||||
"[ 1/4 → 3/8 | note:G1 s:sawtooth decay:0.1 sustain:0 ]",
|
"[ 1/4 → 3/8 | note:G1 s:sawtooth decay:0.1 sustain:0 ]",
|
||||||
"[ 1/2 → 5/8 | note:G1 s:sawtooth decay:0.1 sustain:0 ]",
|
"[ 1/2 → 5/8 | note:G1 s:sawtooth decay:0.1 sustain:0 ]",
|
||||||
@ -8127,8 +8127,8 @@ exports[`renders tunes > tune: loungeSponge 1`] = `
|
|||||||
|
|
||||||
exports[`renders tunes > tune: meltingsubmarine 1`] = `
|
exports[`renders tunes > tune: meltingsubmarine 1`] = `
|
||||||
[
|
[
|
||||||
"[ (0/1 → 1/1) ⇝ 3/2 | s:bd:5 speed:0.7519542165100574 ]",
|
"[ (0/1 → 1/1) ⇝ 3/2 | s:bd n:5 speed:0.7519542165100574 ]",
|
||||||
"[ (3/4 → 1/1) ⇝ 3/2 | s:sd:1 speed:0.7931522866332671 ]",
|
"[ (3/4 → 1/1) ⇝ 3/2 | s:sd n:1 speed:0.7931522866332671 ]",
|
||||||
"[ 3/8 → 3/4 | s:hh27 speed:0.7285963821098448 ]",
|
"[ 3/8 → 3/4 | s:hh27 speed:0.7285963821098448 ]",
|
||||||
"[ (3/4 → 1/1) ⇝ 9/8 | s:hh27 speed:0.77531205091027 ]",
|
"[ (3/4 → 1/1) ⇝ 9/8 | s:hh27 speed:0.77531205091027 ]",
|
||||||
"[ (0/1 → 1/1) ⇝ 3/2 | note:33.129885541275144 decay:0.15 sustain:0 s:sawtooth gain:0.4 cutoff:3669.6267869262615 ]",
|
"[ (0/1 → 1/1) ⇝ 3/2 | note:33.129885541275144 decay:0.15 sustain:0 s:sawtooth gain:0.4 cutoff:3669.6267869262615 ]",
|
||||||
@ -8364,15 +8364,15 @@ exports[`renders tunes > tune: randomBells 1`] = `
|
|||||||
|
|
||||||
exports[`renders tunes > tune: sampleDemo 1`] = `
|
exports[`renders tunes > tune: sampleDemo 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/4 | s:woodblock:1 ]",
|
"[ 0/1 → 1/4 | s:woodblock n:1 ]",
|
||||||
"[ 1/4 → 3/8 | s:woodblock:2 ]",
|
"[ 1/4 → 3/8 | s:woodblock n:2 ]",
|
||||||
"[ 0/1 → 1/8 | s:brakedrum:1 ]",
|
"[ 0/1 → 1/8 | s:brakedrum n:1 ]",
|
||||||
"[ 3/4 → 7/8 | s:brakedrum:1 ]",
|
"[ 3/4 → 7/8 | s:brakedrum n:1 ]",
|
||||||
"[ 3/8 → 1/2 | s:woodblock:2 speed:2 ]",
|
"[ 3/8 → 1/2 | s:woodblock n:2 speed:2 ]",
|
||||||
"[ 1/2 → 1/1 | s:snare_rim:0 speed:2 ]",
|
"[ 1/2 → 1/1 | s:snare_rim n:0 speed:2 ]",
|
||||||
"[ (0/1 → 1/1) ⇝ 8/1 | s:gong speed:2 ]",
|
"[ (0/1 → 1/1) ⇝ 8/1 | s:gong speed:2 ]",
|
||||||
"[ 3/8 → 1/2 | s:brakedrum:1 speed:2 ]",
|
"[ 3/8 → 1/2 | s:brakedrum n:1 speed:2 ]",
|
||||||
"[ 3/4 → 1/1 | s:cowbell:3 speed:2 ]",
|
"[ 3/4 → 1/1 | s:cowbell n:3 speed:2 ]",
|
||||||
"[ -3/4 ⇜ (0/1 → 1/4) | note:Bb3 s:clavisynth gain:0.2 delay:0.25 pan:0 ]",
|
"[ -3/4 ⇜ (0/1 → 1/4) | note:Bb3 s:clavisynth gain:0.2 delay:0.25 pan:0 ]",
|
||||||
"[ (3/4 → 1/1) ⇝ 7/4 | note:Bb3 s:clavisynth gain:0.2 delay:0.25 pan:1 ]",
|
"[ (3/4 → 1/1) ⇝ 7/4 | note:Bb3 s:clavisynth gain:0.2 delay:0.25 pan:1 ]",
|
||||||
"[ -1/4 ⇜ (0/1 → 3/4) | note:F3 s:clavisynth gain:0.2 delay:0.25 pan:1 ]",
|
"[ -1/4 ⇜ (0/1 → 3/4) | note:F3 s:clavisynth gain:0.2 delay:0.25 pan:1 ]",
|
||||||
|
|||||||
326
website/public/dependencygraph.svg
Normal file
326
website/public/dependencygraph.svg
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
<svg height="100%" viewBox="0.00 0.00 538.13 507.20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet">
|
||||||
|
<defs><pattern id="warning" width="12" height="12" patternUnits="userSpaceOnUse" patternTransform="rotate(45 50 50)">
|
||||||
|
<line class="line0" stroke-width="6px" x1="3" x2="3" y2="12"></line>
|
||||||
|
<line class="line1" stroke-width="6px" x1="9" x2="9" y2="12"></line>
|
||||||
|
</pattern></defs><g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 503.2)">
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/core@0.6.8 -->
|
||||||
|
<g id="node1" class="node module-_strudel_cycles_core maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/core@0.6.8">
|
||||||
|
<title>@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M174.8,-37.3C174.8,-37.3 56.9,-37.3 56.9,-37.3 53.66,-37.3 50.43,-34.07 50.43,-30.83 50.43,-30.83 50.43,-24.37 50.43,-24.37 50.43,-21.13 53.66,-17.9 56.9,-17.9 56.9,-17.9 174.8,-17.9 174.8,-17.9 178.03,-17.9 181.26,-21.13 181.26,-24.37 181.26,-24.37 181.26,-30.83 181.26,-30.83 181.26,-34.07 178.03,-37.3 174.8,-37.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-24.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/core@0.6.8</text>
|
||||||
|
</g>
|
||||||
|
<!-- fraction.js@4.2.0 -->
|
||||||
|
<g id="node21" class="node module-fraction_js maintainer-infusion license-mit" data-module="fraction.js@4.2.0">
|
||||||
|
<title>fraction.js@4.2.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M343.81,-19.3C343.81,-19.3 273.9,-19.3 273.9,-19.3 270.67,-19.3 267.44,-16.07 267.44,-12.83 267.44,-12.83 267.44,-6.37 267.44,-6.37 267.44,-3.13 270.67,0.1 273.9,0.1 273.9,0.1 343.81,0.1 343.81,0.1 347.05,0.1 350.28,-3.13 350.28,-6.37 350.28,-6.37 350.28,-12.83 350.28,-12.83 350.28,-16.07 347.05,-19.3 343.81,-19.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-6.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">fraction.js@4.2.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/core@0.6.8->fraction.js@4.2.0 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/csound@0.6.2 -->
|
||||||
|
<g id="node2" class="node module-_strudel_cycles_csound maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/csound@0.6.2">
|
||||||
|
<title>@strudel.cycles/csound@0.6.2</title>
|
||||||
|
<path fill="none" stroke="black" d="M180.53,-296.3C180.53,-296.3 51.16,-296.3 51.16,-296.3 47.93,-296.3 44.7,-293.07 44.7,-289.83 44.7,-289.83 44.7,-283.37 44.7,-283.37 44.7,-280.13 47.93,-276.9 51.16,-276.9 51.16,-276.9 180.53,-276.9 180.53,-276.9 183.77,-276.9 187,-280.13 187,-283.37 187,-283.37 187,-289.83 187,-289.83 187,-293.07 183.77,-296.3 180.53,-296.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-283.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/csound@0.6.2</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/csound@0.6.2->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/webaudio@0.6.1 -->
|
||||||
|
<g id="node12" class="node module-_strudel_cycles_webaudio maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/webaudio@0.6.1">
|
||||||
|
<title>@strudel.cycles/webaudio@0.6.1</title>
|
||||||
|
<path fill="none" stroke="black" d="M186.63,-259.3C186.63,-259.3 45.06,-259.3 45.06,-259.3 41.83,-259.3 38.59,-256.07 38.59,-252.83 38.59,-252.83 38.59,-246.37 38.59,-246.37 38.59,-243.13 41.83,-239.9 45.06,-239.9 45.06,-239.9 186.63,-239.9 186.63,-239.9 189.87,-239.9 193.1,-243.13 193.1,-246.37 193.1,-246.37 193.1,-252.83 193.1,-252.83 193.1,-256.07 189.87,-259.3 186.63,-259.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-246.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/webaudio@0.6.1</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/csound@0.6.2->@strudel.cycles/webaudio@0.6.1 -->
|
||||||
|
|
||||||
|
<!-- @csound/browser@6.18.5 -->
|
||||||
|
<g id="node14" class="node module-_csound_browser collapsed maintainer-skyne maintainer-kunstmusik maintainer-eddyc maintainer-hlolli license-lgpl_2_1" data-module="@csound/browser@6.18.5">
|
||||||
|
<title>@csound/browser@6.18.5</title>
|
||||||
|
<path fill="none" stroke="black" d="M364.3,-257.3C364.3,-257.3 253.41,-257.3 253.41,-257.3 250.18,-257.3 246.95,-254.07 246.95,-250.83 246.95,-250.83 246.95,-244.37 246.95,-244.37 246.95,-241.13 250.18,-237.9 253.41,-237.9 253.41,-237.9 364.3,-237.9 364.3,-237.9 367.54,-237.9 370.77,-241.13 370.77,-244.37 370.77,-244.37 370.77,-250.83 370.77,-250.83 370.77,-254.07 367.54,-257.3 364.3,-257.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-244.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@csound/browser@6.18.5</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/csound@0.6.2->@csound/browser@6.18.5 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/embed@0.2.0 -->
|
||||||
|
<g id="node3" class="node module-_strudel_cycles_embed maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/embed@0.2.0">
|
||||||
|
<title>@strudel.cycles/embed@0.2.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M179.69,-462.3C179.69,-462.3 52.01,-462.3 52.01,-462.3 48.77,-462.3 45.54,-459.07 45.54,-455.83 45.54,-455.83 45.54,-449.37 45.54,-449.37 45.54,-446.13 48.77,-442.9 52.01,-442.9 52.01,-442.9 179.69,-442.9 179.69,-442.9 182.92,-442.9 186.16,-446.13 186.16,-449.37 186.16,-449.37 186.16,-455.83 186.16,-455.83 186.16,-459.07 182.92,-462.3 179.69,-462.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-449.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/embed@0.2.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/midi@0.6.0 -->
|
||||||
|
<g id="node4" class="node module-_strudel_cycles_midi maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/midi@0.6.0">
|
||||||
|
<title>@strudel.cycles/midi@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M175.04,-370.3C175.04,-370.3 56.66,-370.3 56.66,-370.3 53.42,-370.3 50.19,-367.07 50.19,-363.83 50.19,-363.83 50.19,-357.37 50.19,-357.37 50.19,-354.13 53.42,-350.9 56.66,-350.9 56.66,-350.9 175.04,-350.9 175.04,-350.9 178.27,-350.9 181.5,-354.13 181.5,-357.37 181.5,-357.37 181.5,-363.83 181.5,-363.83 181.5,-367.07 178.27,-370.3 175.04,-370.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-357.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/midi@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/midi@0.6.0->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/webaudio@0.6.0 -->
|
||||||
|
<g id="node15" class="node module-_strudel_cycles_webaudio maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/webaudio@0.6.0">
|
||||||
|
<title>@strudel.cycles/webaudio@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M379.64,-370.3C379.64,-370.3 238.07,-370.3 238.07,-370.3 234.84,-370.3 231.6,-367.07 231.6,-363.83 231.6,-363.83 231.6,-357.37 231.6,-357.37 231.6,-354.13 234.84,-350.9 238.07,-350.9 238.07,-350.9 379.64,-350.9 379.64,-350.9 382.88,-350.9 386.11,-354.13 386.11,-357.37 386.11,-357.37 386.11,-363.83 386.11,-363.83 386.11,-367.07 382.88,-370.3 379.64,-370.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-357.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/webaudio@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/midi@0.6.0->@strudel.cycles/webaudio@0.6.0 -->
|
||||||
|
|
||||||
|
<!-- webmidi@3.1.4 -->
|
||||||
|
<g id="node25" class="node module-webmidi collapsed maintainer-djipco license-apache_2_0" data-module="webmidi@3.1.4">
|
||||||
|
<title>webmidi@3.1.4</title>
|
||||||
|
<path fill="none" stroke="black" d="M340.52,-407.3C340.52,-407.3 277.2,-407.3 277.2,-407.3 273.97,-407.3 270.73,-404.07 270.73,-400.83 270.73,-400.83 270.73,-394.37 270.73,-394.37 270.73,-391.13 273.97,-387.9 277.2,-387.9 277.2,-387.9 340.52,-387.9 340.52,-387.9 343.75,-387.9 346.98,-391.13 346.98,-394.37 346.98,-394.37 346.98,-400.83 346.98,-400.83 346.98,-404.07 343.75,-407.3 340.52,-407.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-394.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">webmidi@3.1.4</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/midi@0.6.0->webmidi@3.1.4 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/mini@0.6.0 -->
|
||||||
|
<g id="node5" class="node module-_strudel_cycles_mini maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/mini@0.6.0">
|
||||||
|
<title>@strudel.cycles/mini@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M175.04,-111.3C175.04,-111.3 56.66,-111.3 56.66,-111.3 53.42,-111.3 50.19,-108.07 50.19,-104.83 50.19,-104.83 50.19,-98.37 50.19,-98.37 50.19,-95.13 53.42,-91.9 56.66,-91.9 56.66,-91.9 175.04,-91.9 175.04,-91.9 178.27,-91.9 181.5,-95.13 181.5,-98.37 181.5,-98.37 181.5,-104.83 181.5,-104.83 181.5,-108.07 178.27,-111.3 175.04,-111.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-98.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/mini@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/mini@0.6.0->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/osc@0.6.0 -->
|
||||||
|
<g id="node6" class="node module-_strudel_cycles_osc maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/osc@0.6.0">
|
||||||
|
<title>@strudel.cycles/osc@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M172.53,-222.3C172.53,-222.3 59.16,-222.3 59.16,-222.3 55.93,-222.3 52.7,-219.07 52.7,-215.83 52.7,-215.83 52.7,-209.37 52.7,-209.37 52.7,-206.13 55.93,-202.9 59.16,-202.9 59.16,-202.9 172.53,-202.9 172.53,-202.9 175.76,-202.9 179,-206.13 179,-209.37 179,-209.37 179,-215.83 179,-215.83 179,-219.07 175.76,-222.3 172.53,-222.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-209.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/osc@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/osc@0.6.0->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- osc-js@2.4.0 -->
|
||||||
|
<g id="node22" class="node module-osc_js collapsed maintainer-andreasdz license-mit" data-module="osc-js@2.4.0">
|
||||||
|
<title>osc-js@2.4.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M334.18,-220.3C334.18,-220.3 283.53,-220.3 283.53,-220.3 280.3,-220.3 277.06,-217.07 277.06,-213.83 277.06,-213.83 277.06,-207.37 277.06,-207.37 277.06,-204.13 280.3,-200.9 283.53,-200.9 283.53,-200.9 334.18,-200.9 334.18,-200.9 337.42,-200.9 340.65,-204.13 340.65,-207.37 340.65,-207.37 340.65,-213.83 340.65,-213.83 340.65,-217.07 337.42,-220.3 334.18,-220.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-207.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">osc-js@2.4.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/osc@0.6.0->osc-js@2.4.0 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/react@0.6.0 -->
|
||||||
|
<g id="node7" class="node module-_strudel_cycles_react collapsed maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/react@0.6.0">
|
||||||
|
<title>@strudel.cycles/react@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M175.73,-499.3C175.73,-499.3 55.96,-499.3 55.96,-499.3 52.73,-499.3 49.49,-496.07 49.49,-492.83 49.49,-492.83 49.49,-486.37 49.49,-486.37 49.49,-483.13 52.73,-479.9 55.96,-479.9 55.96,-479.9 175.73,-479.9 175.73,-479.9 178.97,-479.9 182.2,-483.13 182.2,-486.37 182.2,-486.37 182.2,-492.83 182.2,-492.83 182.2,-496.07 178.97,-499.3 175.73,-499.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-486.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/react@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/serial@0.6.0 -->
|
||||||
|
<g id="node8" class="node module-_strudel_cycles_serial maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/serial@0.6.0">
|
||||||
|
<title>@strudel.cycles/serial@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M177.19,-148.3C177.19,-148.3 54.5,-148.3 54.5,-148.3 51.27,-148.3 48.04,-145.07 48.04,-141.83 48.04,-141.83 48.04,-135.37 48.04,-135.37 48.04,-132.13 51.27,-128.9 54.5,-128.9 54.5,-128.9 177.19,-128.9 177.19,-128.9 180.42,-128.9 183.66,-132.13 183.66,-135.37 183.66,-135.37 183.66,-141.83 183.66,-141.83 183.66,-145.07 180.42,-148.3 177.19,-148.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-135.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/serial@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/serial@0.6.0->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/soundfonts@0.6.0 -->
|
||||||
|
<g id="node9" class="node module-_strudel_cycles_soundfonts maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/soundfonts@0.6.0">
|
||||||
|
<title>@strudel.cycles/soundfonts@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M189.15,-333.3C189.15,-333.3 42.55,-333.3 42.55,-333.3 39.31,-333.3 36.08,-330.07 36.08,-326.83 36.08,-326.83 36.08,-320.37 36.08,-320.37 36.08,-317.13 39.31,-313.9 42.55,-313.9 42.55,-313.9 189.15,-313.9 189.15,-313.9 192.38,-313.9 195.62,-317.13 195.62,-320.37 195.62,-320.37 195.62,-326.83 195.62,-326.83 195.62,-330.07 192.38,-333.3 189.15,-333.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-320.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/soundfonts@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/soundfonts@0.6.0->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/soundfonts@0.6.0->@strudel.cycles/webaudio@0.6.0 -->
|
||||||
|
|
||||||
|
<!-- sfumato@0.1.2 -->
|
||||||
|
<g id="node23" class="node module-sfumato maintainer-felixroos license-isc" data-module="sfumato@0.1.2">
|
||||||
|
<title>sfumato@0.1.2</title>
|
||||||
|
<path fill="none" stroke="black" d="M338.96,-333.3C338.96,-333.3 278.76,-333.3 278.76,-333.3 275.52,-333.3 272.29,-330.07 272.29,-326.83 272.29,-326.83 272.29,-320.37 272.29,-320.37 272.29,-317.13 275.52,-313.9 278.76,-313.9 278.76,-313.9 338.96,-313.9 338.96,-313.9 342.19,-313.9 345.43,-317.13 345.43,-320.37 345.43,-320.37 345.43,-326.83 345.43,-326.83 345.43,-330.07 342.19,-333.3 338.96,-333.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-320.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">sfumato@0.1.2</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/soundfonts@0.6.0->sfumato@0.1.2 -->
|
||||||
|
|
||||||
|
<!-- soundfont2@0.4.0 -->
|
||||||
|
<g id="node24" class="node module-soundfont2 maintainer-mrten license-mit" data-module="soundfont2@0.4.0">
|
||||||
|
<title>soundfont2@0.4.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M513.22,-314.3C513.22,-314.3 438.89,-314.3 438.89,-314.3 435.66,-314.3 432.42,-311.07 432.42,-307.83 432.42,-307.83 432.42,-301.37 432.42,-301.37 432.42,-298.13 435.66,-294.9 438.89,-294.9 438.89,-294.9 513.22,-294.9 513.22,-294.9 516.45,-294.9 519.69,-298.13 519.69,-301.37 519.69,-301.37 519.69,-307.83 519.69,-307.83 519.69,-311.07 516.45,-314.3 513.22,-314.3"></path>
|
||||||
|
<text text-anchor="middle" x="476.06" y="-301.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">soundfont2@0.4.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/soundfonts@0.6.0->soundfont2@0.4.0 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/tonal@0.6.0 -->
|
||||||
|
<g id="node10" class="node module-_strudel_cycles_tonal maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/tonal@0.6.0">
|
||||||
|
<title>@strudel.cycles/tonal@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M176.36,-425.3C176.36,-425.3 55.33,-425.3 55.33,-425.3 52.1,-425.3 48.86,-422.07 48.86,-418.83 48.86,-418.83 48.86,-412.37 48.86,-412.37 48.86,-409.13 52.1,-405.9 55.33,-405.9 55.33,-405.9 176.36,-405.9 176.36,-405.9 179.6,-405.9 182.83,-409.13 182.83,-412.37 182.83,-412.37 182.83,-418.83 182.83,-418.83 182.83,-422.07 179.6,-425.3 176.36,-425.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-412.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/tonal@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/tonal@0.6.0->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- @tonaljs/tonal@4.10.0 -->
|
||||||
|
<g id="node16" class="node module-_tonaljs_tonal collapsed maintainer-danigb license-mit" data-module="@tonaljs/tonal@4.10.0">
|
||||||
|
<title>@tonaljs/tonal@4.10.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M523.73,-463.3C523.73,-463.3 428.38,-463.3 428.38,-463.3 425.15,-463.3 421.91,-460.07 421.91,-456.83 421.91,-456.83 421.91,-450.37 421.91,-450.37 421.91,-447.13 425.15,-443.9 428.38,-443.9 428.38,-443.9 523.73,-443.9 523.73,-443.9 526.96,-443.9 530.2,-447.13 530.2,-450.37 530.2,-450.37 530.2,-456.83 530.2,-456.83 530.2,-460.07 526.96,-463.3 523.73,-463.3"></path>
|
||||||
|
<text text-anchor="middle" x="476.06" y="-450.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@tonaljs/tonal@4.10.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/tonal@0.6.0->@tonaljs/tonal@4.10.0 -->
|
||||||
|
|
||||||
|
<!-- chord-voicings@0.0.1 -->
|
||||||
|
<g id="node18" class="node module-chord_voicings maintainer-felixroos license-isc" data-module="chord-voicings@0.0.1">
|
||||||
|
<title>chord-voicings@0.0.1</title>
|
||||||
|
<path fill="none" stroke="black" d="M354.5,-444.3C354.5,-444.3 263.21,-444.3 263.21,-444.3 259.98,-444.3 256.74,-441.07 256.74,-437.83 256.74,-437.83 256.74,-431.37 256.74,-431.37 256.74,-428.13 259.98,-424.9 263.21,-424.9 263.21,-424.9 354.5,-424.9 354.5,-424.9 357.74,-424.9 360.97,-428.13 360.97,-431.37 360.97,-431.37 360.97,-437.83 360.97,-437.83 360.97,-441.07 357.74,-444.3 354.5,-444.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-431.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">chord-voicings@0.0.1</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/tonal@0.6.0->chord-voicings@0.0.1 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/tonal@0.6.0->webmidi@3.1.4 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/transpiler@0.6.0 -->
|
||||||
|
<g id="node11" class="node module-_strudel_cycles_transpiler maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/transpiler@0.6.0">
|
||||||
|
<title>@strudel.cycles/transpiler@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M185.91,-74.3C185.91,-74.3 45.79,-74.3 45.79,-74.3 42.55,-74.3 39.32,-71.07 39.32,-67.83 39.32,-67.83 39.32,-61.37 39.32,-61.37 39.32,-58.13 42.55,-54.9 45.79,-54.9 45.79,-54.9 185.91,-54.9 185.91,-54.9 189.14,-54.9 192.38,-58.13 192.38,-61.37 192.38,-61.37 192.38,-67.83 192.38,-67.83 192.38,-71.07 189.14,-74.3 185.91,-74.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-61.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/transpiler@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/transpiler@0.6.0->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- acorn@8.8.2 -->
|
||||||
|
<g id="node17" class="node module-acorn collapsed maintainer-marijn maintainer-adrianheine maintainer-rreverser license-mit" data-module="acorn@8.8.2">
|
||||||
|
<title>acorn@8.8.2</title>
|
||||||
|
<path fill="none" stroke="black" d="M333.45,-130.3C333.45,-130.3 284.27,-130.3 284.27,-130.3 281.03,-130.3 277.8,-127.07 277.8,-123.83 277.8,-123.83 277.8,-117.37 277.8,-117.37 277.8,-114.13 281.03,-110.9 284.27,-110.9 284.27,-110.9 333.45,-110.9 333.45,-110.9 336.68,-110.9 339.92,-114.13 339.92,-117.37 339.92,-117.37 339.92,-123.83 339.92,-123.83 339.92,-127.07 336.68,-130.3 333.45,-130.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-117.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">acorn@8.8.2</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/transpiler@0.6.0->acorn@8.8.2 -->
|
||||||
|
|
||||||
|
<!-- escodegen@2.0.0 -->
|
||||||
|
<g id="node19" class="node module-escodegen collapsed maintainer-constellation maintainer-michaelficarra license-bsd_2_clause" data-module="escodegen@2.0.0">
|
||||||
|
<title>escodegen@2.0.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M344.33,-93.3C344.33,-93.3 273.39,-93.3 273.39,-93.3 270.15,-93.3 266.92,-90.07 266.92,-86.83 266.92,-86.83 266.92,-80.37 266.92,-80.37 266.92,-77.13 270.15,-73.9 273.39,-73.9 273.39,-73.9 344.33,-73.9 344.33,-73.9 347.56,-73.9 350.8,-77.13 350.8,-80.37 350.8,-80.37 350.8,-86.83 350.8,-86.83 350.8,-90.07 347.56,-93.3 344.33,-93.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-80.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">escodegen@2.0.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/transpiler@0.6.0->escodegen@2.0.0 -->
|
||||||
|
|
||||||
|
<!-- estree-walker@3.0.3 -->
|
||||||
|
<g id="node20" class="node module-estree_walker collapsed maintainer-rich_harris license-mit" data-module="estree-walker@3.0.3">
|
||||||
|
<title>estree-walker@3.0.3</title>
|
||||||
|
<path fill="none" stroke="black" d="M351.26,-56.3C351.26,-56.3 266.46,-56.3 266.46,-56.3 263.22,-56.3 259.99,-53.07 259.99,-49.83 259.99,-49.83 259.99,-43.37 259.99,-43.37 259.99,-40.13 263.22,-36.9 266.46,-36.9 266.46,-36.9 351.26,-36.9 351.26,-36.9 354.49,-36.9 357.73,-40.13 357.73,-43.37 357.73,-43.37 357.73,-49.83 357.73,-49.83 357.73,-53.07 354.49,-56.3 351.26,-56.3"></path>
|
||||||
|
<text text-anchor="middle" x="308.86" y="-43.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">estree-walker@3.0.3</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/transpiler@0.6.0->estree-walker@3.0.3 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/webaudio@0.6.1->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/xen@0.6.0 -->
|
||||||
|
<g id="node13" class="node module-_strudel_cycles_xen maintainer-yaxupaxo maintainer-felixroos license-agpl_3_0_or_later" data-module="@strudel.cycles/xen@0.6.0">
|
||||||
|
<title>@strudel.cycles/xen@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M173.25,-185.3C173.25,-185.3 58.44,-185.3 58.44,-185.3 55.21,-185.3 51.98,-182.07 51.98,-178.83 51.98,-178.83 51.98,-172.37 51.98,-172.37 51.98,-169.13 55.21,-165.9 58.44,-165.9 58.44,-165.9 173.25,-165.9 173.25,-165.9 176.48,-165.9 179.72,-169.13 179.72,-172.37 179.72,-172.37 179.72,-178.83 179.72,-178.83 179.72,-182.07 176.48,-185.3 173.25,-185.3"></path>
|
||||||
|
<text text-anchor="middle" x="115.85" y="-172.3" font-family="Roboto Condensed, sans-serif" font-size="11.00">@strudel.cycles/xen@0.6.0</text>
|
||||||
|
</g>
|
||||||
|
<!-- @strudel.cycles/xen@0.6.0->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- @strudel.cycles/webaudio@0.6.0->@strudel.cycles/core@0.6.8 -->
|
||||||
|
|
||||||
|
<!-- chord-voicings@0.0.1->@tonaljs/tonal@4.10.0 -->
|
||||||
|
<g id="edge27" class="edge">
|
||||||
|
<title>chord-voicings@0.0.1->@tonaljs/tonal@4.10.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M361.22,-440.51C377.14,-442.34 394.88,-444.38 411.53,-446.29"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="411.39,-449.8 421.73,-447.47 412.19,-442.85 411.39,-449.8"></polygon>
|
||||||
|
</g>
|
||||||
|
<!-- sfumato@0.1.2->soundfont2@0.4.0 -->
|
||||||
|
<g id="edge28" class="edge">
|
||||||
|
<title>sfumato@0.1.2->soundfont2@0.4.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M345.7,-319.48C368.06,-316.91 397.22,-313.55 422.19,-310.68"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="422.72,-314.14 432.25,-309.52 421.92,-307.19 422.72,-314.14"></polygon>
|
||||||
|
</g>
|
||||||
|
<g id="edge1" class="edge">
|
||||||
|
<title>@strudel.cycles/core@0.6.8->fraction.js@4.2.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M181.25,-21.53C206.16,-19.18 234.23,-16.54 257.6,-14.34"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="258.02,-17.81 267.64,-13.39 257.36,-10.84 258.02,-17.81"></polygon>
|
||||||
|
</g><g id="edge3" class="edge">
|
||||||
|
<title>@strudel.cycles/csound@0.6.2->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M44.23,-280.41C33.55,-276.09 24.08,-269.5 17.96,-259.6 -5.99,-220.85 -5.99,-93.35 17.96,-54.6 23.42,-45.77 31.54,-39.58 40.82,-35.27"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="42.35,-38.43 50.42,-31.56 39.83,-31.9 42.35,-38.43"></polygon>
|
||||||
|
</g><g id="edge4" class="edge">
|
||||||
|
<title>@strudel.cycles/csound@0.6.2->@strudel.cycles/webaudio@0.6.1</title>
|
||||||
|
<path fill="none" stroke="black" d="M115.85,-276.84C115.85,-274.39 115.85,-271.94 115.85,-269.49"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="119.35,-269.43 115.85,-259.43 112.35,-269.43 119.35,-269.43"></polygon>
|
||||||
|
</g><g id="edge6" class="edge">
|
||||||
|
<title>@strudel.cycles/midi@0.6.0->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M50.17,-356.56C37.1,-352.37 25.19,-345.3 17.96,-333.6 1.66,-307.23 1.66,-80.97 17.96,-54.6 23.42,-45.77 31.54,-39.58 40.82,-35.27"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="42.35,-38.43 50.42,-31.56 39.83,-31.9 42.35,-38.43"></polygon>
|
||||||
|
</g><g id="edge7" class="edge">
|
||||||
|
<title>@strudel.cycles/midi@0.6.0->@strudel.cycles/webaudio@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M181.51,-360.6C194.37,-360.6 208.05,-360.6 221.49,-360.6"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="221.71,-364.1 231.7,-360.6 221.7,-357.1 221.71,-364.1"></polygon>
|
||||||
|
</g><g id="edge5" class="edge">
|
||||||
|
<title>@strudel.cycles/midi@0.6.0->webmidi@3.1.4</title>
|
||||||
|
<path fill="none" stroke="black" d="M166.53,-370.22C195.48,-375.83 231.78,-382.86 260.34,-388.4"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="260.01,-391.9 270.49,-390.36 261.34,-385.02 260.01,-391.9"></polygon>
|
||||||
|
</g><g id="edge8" class="edge">
|
||||||
|
<title>@strudel.cycles/mini@0.6.0->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M50.17,-97.56C37.1,-93.37 25.19,-86.3 17.96,-74.6 7.78,-58.12 21.54,-47.3 41.67,-40.25"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="42.78,-43.57 51.3,-37.27 40.71,-36.88 42.78,-43.57"></polygon>
|
||||||
|
</g><g id="edge10" class="edge">
|
||||||
|
<title>@strudel.cycles/osc@0.6.0->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M52.7,-209.33C38.65,-205.26 25.65,-198.05 17.96,-185.6 2.66,-160.84 2.66,-79.36 17.96,-54.6 23.42,-45.77 31.54,-39.58 40.82,-35.27"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="42.35,-38.43 50.42,-31.56 39.83,-31.9 42.35,-38.43"></polygon>
|
||||||
|
</g><g id="edge9" class="edge">
|
||||||
|
<title>@strudel.cycles/osc@0.6.0->osc-js@2.4.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M179.13,-211.95C207.93,-211.65 241.33,-211.3 266.9,-211.03"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="267.02,-214.53 276.99,-210.92 266.95,-207.53 267.02,-214.53"></polygon>
|
||||||
|
</g><g id="edge11" class="edge">
|
||||||
|
<title>@strudel.cycles/serial@0.6.0->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M48.17,-133.89C35.89,-129.63 24.82,-122.7 17.96,-111.6 4.64,-90.05 4.64,-76.15 17.96,-54.6 23.42,-45.77 31.54,-39.58 40.82,-35.27"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="42.35,-38.43 50.42,-31.56 39.83,-31.9 42.35,-38.43"></polygon>
|
||||||
|
</g><g id="edge14" class="edge">
|
||||||
|
<title>@strudel.cycles/soundfonts@0.6.0->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M36.71,-313.85C29.15,-309.7 22.6,-304.1 17.96,-296.6 3.83,-273.73 3.83,-77.47 17.96,-54.6 23.42,-45.77 31.54,-39.58 40.82,-35.27"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="42.35,-38.43 50.42,-31.56 39.83,-31.9 42.35,-38.43"></polygon>
|
||||||
|
</g><g id="edge15" class="edge">
|
||||||
|
<title>@strudel.cycles/soundfonts@0.6.0->@strudel.cycles/webaudio@0.6.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M166.53,-333.22C191.53,-338.07 222.01,-343.97 248.26,-349.05"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="247.6,-352.49 258.09,-350.96 248.94,-345.62 247.6,-352.49"></polygon>
|
||||||
|
</g><g id="edge12" class="edge">
|
||||||
|
<title>@strudel.cycles/soundfonts@0.6.0->sfumato@0.1.2</title>
|
||||||
|
<path fill="none" stroke="black" d="M195.64,-323.6C218.22,-323.6 242.08,-323.6 261.97,-323.6"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="261.98,-327.1 271.98,-323.6 261.98,-320.1 261.98,-327.1"></polygon>
|
||||||
|
</g><g id="edge13" class="edge">
|
||||||
|
<title>@strudel.cycles/soundfonts@0.6.0->soundfont2@0.4.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M164.14,-313.99C184.8,-310.25 209.37,-306.44 231.73,-304.6 297.18,-299.22 372.86,-300.38 422.21,-302.11"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="422.21,-305.61 432.33,-302.49 422.47,-298.62 422.21,-305.61"></polygon>
|
||||||
|
</g><g id="edge19" class="edge">
|
||||||
|
<title>@strudel.cycles/tonal@0.6.0->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M68.74,-405.99C49.45,-399.45 29.07,-388.58 17.96,-370.6 -0.5,-340.73 -0.5,-84.47 17.96,-54.6 23.42,-45.77 31.54,-39.58 40.82,-35.27"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="42.35,-38.43 50.42,-31.56 39.83,-31.9 42.35,-38.43"></polygon>
|
||||||
|
</g><g id="edge16" class="edge">
|
||||||
|
<title>@strudel.cycles/tonal@0.6.0->@tonaljs/tonal@4.10.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M168.82,-425.25C177.92,-427.57 187.2,-430.33 195.73,-433.6 212.82,-440.15 214.01,-449.01 231.73,-453.6 291.41,-469.07 362.13,-466.9 411.9,-462.17"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="412.28,-465.65 421.88,-461.17 411.58,-458.69 412.28,-465.65"></polygon>
|
||||||
|
</g><g id="edge17" class="edge">
|
||||||
|
<title>@strudel.cycles/tonal@0.6.0->chord-voicings@0.0.1</title>
|
||||||
|
<path fill="none" stroke="black" d="M182.85,-422.17C203.51,-424.22 226.22,-426.48 246.55,-428.5"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="246.33,-432 256.62,-429.5 247.02,-425.03 246.33,-432"></polygon>
|
||||||
|
</g><g id="edge18" class="edge">
|
||||||
|
<title>@strudel.cycles/tonal@0.6.0->webmidi@3.1.4</title>
|
||||||
|
<path fill="none" stroke="black" d="M182.85,-409.38C208.4,-406.97 237.07,-404.27 260.51,-402.06"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="260.91,-405.54 270.54,-401.12 260.26,-398.57 260.91,-405.54"></polygon>
|
||||||
|
</g><g id="edge23" class="edge">
|
||||||
|
<title>@strudel.cycles/transpiler@0.6.0->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M115.85,-54.84C115.85,-52.39 115.85,-49.94 115.85,-47.49"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="119.35,-47.43 115.85,-37.43 112.35,-47.43 119.35,-47.43"></polygon>
|
||||||
|
</g><g id="edge20" class="edge">
|
||||||
|
<title>@strudel.cycles/transpiler@0.6.0->acorn@8.8.2</title>
|
||||||
|
<path fill="none" stroke="black" d="M168.82,-74.25C177.92,-76.57 187.2,-79.33 195.73,-82.6 212.82,-89.15 214.66,-95.99 231.73,-102.6 243.09,-107 255.84,-110.53 267.61,-113.25"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="267.12,-116.73 277.64,-115.44 268.61,-109.89 267.12,-116.73"></polygon>
|
||||||
|
</g><g id="edge21" class="edge">
|
||||||
|
<title>@strudel.cycles/transpiler@0.6.0->escodegen@2.0.0</title>
|
||||||
|
<path fill="none" stroke="black" d="M192.61,-72.14C214.17,-74.28 237.12,-76.56 256.83,-78.52"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="256.51,-82.01 266.81,-79.52 257.21,-75.04 256.51,-82.01"></polygon>
|
||||||
|
</g><g id="edge22" class="edge">
|
||||||
|
<title>@strudel.cycles/transpiler@0.6.0->estree-walker@3.0.3</title>
|
||||||
|
<path fill="none" stroke="black" d="M192.61,-57.46C211.68,-55.66 231.85,-53.76 249.89,-52.06"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="250.33,-55.54 259.96,-51.11 249.68,-48.57 250.33,-55.54"></polygon>
|
||||||
|
</g><g id="edge24" class="edge">
|
||||||
|
<title>@strudel.cycles/webaudio@0.6.1->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M38.54,-240.82C30.22,-236.58 22.97,-230.7 17.96,-222.6 -1.66,-190.84 -1.66,-86.36 17.96,-54.6 23.42,-45.77 31.54,-39.58 40.82,-35.27"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="42.35,-38.43 50.42,-31.56 39.83,-31.9 42.35,-38.43"></polygon>
|
||||||
|
</g><g id="edge25" class="edge">
|
||||||
|
<title>@strudel.cycles/xen@0.6.0->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M51.94,-172.1C38.18,-168 25.52,-160.82 17.96,-148.6 -4,-113.06 -4,-90.14 17.96,-54.6 23.42,-45.77 31.54,-39.58 40.82,-35.27"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="42.35,-38.43 50.42,-31.56 39.83,-31.9 42.35,-38.43"></polygon>
|
||||||
|
</g><g id="edge26" class="edge">
|
||||||
|
<title>@strudel.cycles/webaudio@0.6.0->@strudel.cycles/core@0.6.8</title>
|
||||||
|
<path fill="none" stroke="black" d="M241.66,-350.81C237.99,-348.55 234.63,-345.84 231.73,-342.6 143.1,-243.48 284.75,-144.37 195.73,-45.6 193.96,-43.64 192.03,-41.87 189.96,-40.27"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="191.74,-37.25 181.4,-34.93 188.03,-43.19 191.74,-37.25"></polygon>
|
||||||
|
</g><g id="edge2" class="edge">
|
||||||
|
<title>@strudel.cycles/csound@0.6.2->@csound/browser@6.18.5</title>
|
||||||
|
<path fill="none" stroke="black" d="M164.06,-276.96C190.24,-271.62 222.97,-264.93 250.6,-259.29"></path>
|
||||||
|
<polygon fill="black" stroke="black" points="251.43,-262.69 260.52,-257.26 250.02,-255.84 251.43,-262.69"></polygon>
|
||||||
|
</g></g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 31 KiB |
BIN
website/public/pwa/strudel-linux.png
Normal file
BIN
website/public/pwa/strudel-linux.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
BIN
website/public/pwa/strudel-macos.png
Normal file
BIN
website/public/pwa/strudel-macos.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 520 KiB |
@ -78,7 +78,7 @@ const base = BASE_URL;
|
|||||||
// https://medium.com/quick-code/100vh-problem-with-ios-safari-92ab23c852a8
|
// https://medium.com/quick-code/100vh-problem-with-ios-safari-92ab23c852a8
|
||||||
const appHeight = () => {
|
const appHeight = () => {
|
||||||
const doc = document.documentElement;
|
const doc = document.documentElement;
|
||||||
doc.style.setProperty('--app-height', `${window.innerHeight}px`);
|
doc.style.setProperty('--app-height', `${window.innerHeight - 1}px`);
|
||||||
};
|
};
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
window.addEventListener('resize', appHeight);
|
window.addEventListener('resize', appHeight);
|
||||||
|
|||||||
@ -19,7 +19,10 @@ const langCode = 'en'; // getLanguageFromURL(currentPage);
|
|||||||
const sidebar = SIDEBAR[langCode];
|
const sidebar = SIDEBAR[langCode];
|
||||||
---
|
---
|
||||||
|
|
||||||
<nav class="flex justify-between py-2 px-4 items-center h-14 max-h-14 bg-lineHighlight text-foreground" title="Top Navigation">
|
<nav
|
||||||
|
class="flex justify-between py-2 px-4 items-center h-14 max-h-14 bg-lineHighlight text-foreground"
|
||||||
|
title="Top Navigation"
|
||||||
|
>
|
||||||
<!-- <div class="menu-toggle">
|
<!-- <div class="menu-toggle">
|
||||||
<SidebarToggle client:idle />
|
<SidebarToggle client:idle />
|
||||||
</div> -->
|
</div> -->
|
||||||
@ -36,7 +39,7 @@ const sidebar = SIDEBAR[langCode];
|
|||||||
</div>
|
</div>
|
||||||
{/* KNOWN_LANGUAGE_CODES.length > 1 && <LanguageSelect lang={lang} client:idle /> */}
|
{/* KNOWN_LANGUAGE_CODES.length > 1 && <LanguageSelect lang={lang} client:idle /> */}
|
||||||
<div class="search-item h-10">
|
<div class="search-item h-10">
|
||||||
<!-- <Search client:idle /> -->
|
<!-- <Search client:idle /> -->
|
||||||
</div>
|
</div>
|
||||||
<a href="./" class="hidden md:flex cursor-pointer items-center space-x-1"
|
<a href="./" class="hidden md:flex cursor-pointer items-center space-x-1"
|
||||||
><CommandLineIcon className="w-5 h-5" /><span>go to REPL</span>
|
><CommandLineIcon className="w-5 h-5" /><span>go to REPL</span>
|
||||||
|
|||||||
@ -23,7 +23,7 @@ const sidebar = SIDEBAR[langCode];
|
|||||||
<h2>{header}</h2>
|
<h2>{header}</h2>
|
||||||
<ul>
|
<ul>
|
||||||
{children.map((child) => {
|
{children.map((child) => {
|
||||||
const url = '.' + Astro.site?.pathname + child.link;
|
const url = Astro.site?.pathname + child.link;
|
||||||
return (
|
return (
|
||||||
<li class="">
|
<li class="">
|
||||||
<a
|
<a
|
||||||
|
|||||||
@ -33,9 +33,9 @@ export const COMMUNITY_INVITE_URL = `https://discord.com/invite/HGEdXmRkzT`;
|
|||||||
|
|
||||||
// See "Algolia" section of the README for more information.
|
// See "Algolia" section of the README for more information.
|
||||||
export const ALGOLIA = {
|
export const ALGOLIA = {
|
||||||
indexName: 'XXXXXXXXXX',
|
indexName: 'strudel-tidalcycles',
|
||||||
appId: 'XXXXXXXXXX',
|
appId: 'SAZ71S8CLS',
|
||||||
apiKey: 'XXXXXXXXXX',
|
apiKey: 'd5044f9d21b80e7721e5b0067a8730b1',
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Sidebar = Record<(typeof KNOWN_LANGUAGE_CODES)[number], Record<string, { text: string; link: string }[]>>;
|
export type Sidebar = Record<(typeof KNOWN_LANGUAGE_CODES)[number], Record<string, { text: string; link: string }[]>>;
|
||||||
@ -73,9 +73,9 @@ export const SIDEBAR: Sidebar = {
|
|||||||
],
|
],
|
||||||
Development: [
|
Development: [
|
||||||
{ text: 'REPL', link: 'technical-manual/repl' },
|
{ text: 'REPL', link: 'technical-manual/repl' },
|
||||||
|
{ text: 'Packages', link: 'technical-manual/packages' },
|
||||||
{ text: 'Docs', link: 'technical-manual/docs' },
|
{ text: 'Docs', link: 'technical-manual/docs' },
|
||||||
{ text: 'Testing', link: 'technical-manual/testing' },
|
{ text: 'Testing', link: 'technical-manual/testing' },
|
||||||
// { text: 'Packages', link: 'technical-manual/packages' },
|
|
||||||
// { text: 'Internals', link: 'technical-manual/internals' },
|
// { text: 'Internals', link: 'technical-manual/internals' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -49,6 +49,10 @@ As a chained function:
|
|||||||
|
|
||||||
<JsDoc client:idle name="timeCat" h={0} />
|
<JsDoc client:idle name="timeCat" h={0} />
|
||||||
|
|
||||||
|
## arrange
|
||||||
|
|
||||||
|
<JsDoc client:idle name="arrange" h={0} />
|
||||||
|
|
||||||
## polymeter
|
## polymeter
|
||||||
|
|
||||||
<JsDoc client:idle name="polymeter" h={0} />
|
<JsDoc client:idle name="polymeter" h={0} />
|
||||||
|
|||||||
@ -22,12 +22,35 @@ If no outputName is given, it uses the first midi output it finds.
|
|||||||
|
|
||||||
<MiniRepl
|
<MiniRepl
|
||||||
client:idle
|
client:idle
|
||||||
tune={`stack("<C^7 A7 Dm7 G7>".voicings('lefthand'), "<C3 A2 D3 G2>")
|
tune={`stack("<C^7 A7 Dm7 G7>".voicings('lefthand'), "<C3 A2 D3 G2>").note()
|
||||||
.midi()`}
|
.midi()`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
In the console, you will see a log of the available MIDI devices as soon as you run the code, e.g. `Midi connected! Using "Midi Through Port-0".`
|
In the console, you will see a log of the available MIDI devices as soon as you run the code, e.g. `Midi connected! Using "Midi Through Port-0".`
|
||||||
|
|
||||||
|
## midichan(number)
|
||||||
|
|
||||||
|
Selects the MIDI channel to use. If not used, `.midi` will use channel 1 by default.
|
||||||
|
|
||||||
|
## ccn && ccv
|
||||||
|
|
||||||
|
- `ccn` sets the cc number. Depends on your synths midi mapping
|
||||||
|
- `ccv` sets the cc value. normalized from 0 to 1.
|
||||||
|
|
||||||
|
<MiniRepl client:idle tune={`note("c a f e").ccn(74).ccv(sine.slow(4)).midi()`} />
|
||||||
|
|
||||||
|
In the above snippet, `ccn` is set to 74, which is the filter cutoff for many synths. `ccv` is controlled by a saw pattern.
|
||||||
|
Having everything in one pattern, the `ccv` pattern will be aligned to the note pattern, because the structure comes from the left by default.
|
||||||
|
But you can also control cc messages separately like this:
|
||||||
|
|
||||||
|
<MiniRepl
|
||||||
|
client:idle
|
||||||
|
tune={`stack(
|
||||||
|
note("c a f e"),
|
||||||
|
ccv(sine.segment(16).slow(4)).ccn(74)
|
||||||
|
).midi()`}
|
||||||
|
/>
|
||||||
|
|
||||||
# SuperDirt API
|
# SuperDirt API
|
||||||
|
|
||||||
In mainline tidal, the actual sound is generated via [SuperDirt](https://github.com/musikinformatik/SuperDirt/), which runs inside SuperCollider.
|
In mainline tidal, the actual sound is generated via [SuperDirt](https://github.com/musikinformatik/SuperDirt/), which runs inside SuperCollider.
|
||||||
|
|||||||
@ -159,8 +159,6 @@ Using "!" we can repeat without speeding up:
|
|||||||
|
|
||||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} punchcard />
|
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} punchcard />
|
||||||
|
|
||||||
In essence, the `x!n` is like a shortcut for `[x*n]@n`.
|
|
||||||
|
|
||||||
## Mini-notation review
|
## Mini-notation review
|
||||||
|
|
||||||
To recap what we've learned so far, compare the following patterns:
|
To recap what we've learned so far, compare the following patterns:
|
||||||
|
|||||||
@ -7,5 +7,79 @@ layout: ../../layouts/MainLayout.astro
|
|||||||
|
|
||||||
You can use Strudel even without a network! When you first visit the [Strudel REPL](strudel.tidalcycles.org/),
|
You can use Strudel even without a network! When you first visit the [Strudel REPL](strudel.tidalcycles.org/),
|
||||||
your browser will download the whole web app including documentation.
|
your browser will download the whole web app including documentation.
|
||||||
|
When the download is finished (<1MB), you can visit the website even when offline,
|
||||||
|
getting the downloaded website instead of the online one.
|
||||||
|
|
||||||
|
When the site gets updated, your browser will download that update on the next online visit.
|
||||||
|
When an update is available, the site will refresh after the download is finished.
|
||||||
|
|
||||||
|
This works because Strudel is implemented as progessive web app (using [Vite PWA](https://vite-pwa-org.netlify.app/)).
|
||||||
|
|
||||||
|
## Samples
|
||||||
|
|
||||||
|
While the browser will download the app itself, samples are only downloaded when you're actively using them.
|
||||||
|
So to make sure a specific set of samples is available when offline, just use them.
|
||||||
|
Also, only samples from these domains will be cached for offline use:
|
||||||
|
|
||||||
|
- `https://raw.githubusercontent.com/*` for samples uploaded to github
|
||||||
|
- `https://freesound.org/*` / `https://cdn.freesound.org/*` for freesound
|
||||||
|
- `https://shabda.ndre.gr/.*` for shabda
|
||||||
|
|
||||||
|
## Inspecting / Clearing Cache
|
||||||
|
|
||||||
|
You can view all cached files in your browser.
|
||||||
|
|
||||||
|
### Firefox
|
||||||
|
|
||||||
|
- Open the Developer Tools (`Tools > Web Developer > Web Developer Tools`)
|
||||||
|
- go to `Storage` tab and expand `Cache Storage > https://strudel.tidalcycles.org`.
|
||||||
|
- or go to the `Application` tab and view the latest updates in `Service Workers`
|
||||||
|
|
||||||
|
### Chromium based Browsers
|
||||||
|
|
||||||
|
- Open Developer Tools (`Right Click > Inspect`)
|
||||||
|
- go to the `Application` tab
|
||||||
|
- view downloaded files under `Cache > Cache Storage`
|
||||||
|
- view the latest updates in `Service Workers`
|
||||||
|
|
||||||
|
## Strudel Standalone App
|
||||||
|
|
||||||
|
You can also install Strudel as a standalone app on most devices.
|
||||||
|
A standalone app has its own desktop / homescreen icon and launches in a separate window,
|
||||||
|
without the browser ui.
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src="./pwa/strudel-macos.png" alt="Strudel on MacOS" />
|
||||||
|
<figcaption>Strudel on MacOS</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
### Desktop
|
||||||
|
|
||||||
|
With a chromium based browser:
|
||||||
|
|
||||||
|
1. go to the [Strudel REPL](strudel.tidalcycles.org/).
|
||||||
|
2. on the right of the adress bar, click `install Strudel REPL`
|
||||||
|
3. the REPL should now run as a standalone chromium app
|
||||||
|
|
||||||
|
Without a chromium based browser, you can use [nativefier](https://github.com/nativefier/nativefier) to generate a desktop app:
|
||||||
|
|
||||||
|
1. make sure you have NodeJS installed
|
||||||
|
2. run `npx nativefier strudel.tidalcycles.org`
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img src="./pwa/strudel-linux.png" alt="Strudel on Linux" />
|
||||||
|
<figcaption>Strudel on Linux</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
### iOS
|
||||||
|
|
||||||
|
1. open to the [Strudel REPL](strudel.tidalcycles.org/) in safari
|
||||||
|
2. press the share icon and tab `Add to homescreen`
|
||||||
|
3. You should now have a strudel app icon that opens the repl in full screen
|
||||||
|
|
||||||
|
### Android
|
||||||
|
|
||||||
|
1. open to the [Strudel REPL](strudel.tidalcycles.org/)
|
||||||
|
2. Tab the install button at the bottom
|
||||||
|
|
||||||
Ok, what are [Patterns](/technical-manual/patterns) all about?
|
Ok, what are [Patterns](/technical-manual/patterns) all about?
|
||||||
|
|||||||
@ -5,75 +5,58 @@ layout: ../../layouts/MainLayout.astro
|
|||||||
|
|
||||||
import { MiniRepl } from '../../docs/MiniRepl';
|
import { MiniRepl } from '../../docs/MiniRepl';
|
||||||
|
|
||||||
## Strudel Packages
|
# Strudel Packages
|
||||||
|
|
||||||
The [strudel repo](github.com/tidalcycles/strudel) is organized into packages, using [npm workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces).
|
The [strudel repo](github.com/tidalcycles/strudel) is organized as a monorepo, containing multiple npm packages.
|
||||||
Publishing packages is done with [lerna](https://lerna.js.org/).
|
The purpose of the multiple packages is to
|
||||||
|
|
||||||
There are different packages for different purposes. They..
|
- organize the codebase into more modular, encapsulated pieces
|
||||||
|
- be able to opt out of certain functionalities
|
||||||
|
- keep the dependencies of the core packages small
|
||||||
|
|
||||||
- split up the code into smaller chunks
|
## Overview
|
||||||
- can be selectively used to implement some sort of time based system
|
|
||||||
|
|
||||||
[See the latest published packages on npm](https://www.npmjs.com/search?q=%40strudel.cycles).
|
[See the latest published packages on npm](https://www.npmjs.com/search?q=%40strudel.cycles).
|
||||||
|
Here is an overview of all the packages:
|
||||||
|
|
||||||
### Important bits
|
### Essential Packages
|
||||||
|
|
||||||
- The [root package.json](https://github.com/tidalcycles/strudel/blob/main/package.json) specifies `packages/*` as `workspaces`
|
These package are the most essential. You might want to use all of those if you're using strudel in your project:
|
||||||
- Each folder in `packages` comes with its own `package.json`, defining a package name of the format `@strudel.cycles/<name>`
|
|
||||||
- Running `npm i` from the root folder will symlink all packages to the `node_modules` folder, e.g. `node_modules/@strudel.cycles/core` symlinks `packages/core`
|
|
||||||
- These symlinks allow importing the packages with their package name, instead of a relative path, e.g. `import { seq } from '@strudel.cycles/core'`, instead of `import { seq } from '../core/`.
|
|
||||||
This works because the [bare module import](https://vitejs.dev/guide/features.html#npm-dependency-resolving-and-pre-bundling) `@strudel.cycles/core` is resolved to `node_modules/@strudel.cycles/core`.
|
|
||||||
In a project that installs the published packages from npm, these imports will still work, whereas relative ones might not.
|
|
||||||
- When a strudel package is importing from another strudel package, the package that is imported from should be listed in the `dependencies` field of the `package.json`.
|
|
||||||
For example, [@strudel.cycles/mini lists `@strudel.cycles/core` as a dependency](https://github.com/tidalcycles/strudel/blob/main/packages/mini/package.json).
|
|
||||||
- In development, files in any package can be changed and saved to instantly update the dev server via [hot module replacement](https://vitejs.dev/guide/features.html#hot-module-replacement)
|
|
||||||
- To publish packages, `npx lerna publish` will check which packages were changed since the last publish and publish only those.
|
|
||||||
The version numbers in the dependencies of each packages will be updated automatically to the latest version.
|
|
||||||
|
|
||||||
### Building & Publishing
|
- [core](https://github.com/tidalcycles/strudel/tree/main/packages/core#strudelcyclescore): tidal pattern engine with core primitives
|
||||||
|
- [mini](https://github.com/tidalcycles/strudel/tree/main/packages/mini#strudelcyclesmini): mini notation parser + core bindings
|
||||||
|
- [transpiler](https://github.com/tidalcycles/strudel/tree/main/packages/transpiler#strudelcyclestranspiler): user code transpiler. syntax sugar + highlighting
|
||||||
|
|
||||||
Currently, all packages are only published as ESM with vite flavour.
|
### Language Extensions
|
||||||
To build standardized ESM and CJS files, a `vite.config.js` like that is needed:
|
|
||||||
|
|
||||||
```js
|
These packages extend the pattern language by specific functions
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import { dependencies } from './package.json';
|
|
||||||
import { resolve } from 'path';
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
- [tonal](https://github.com/tidalcycles/strudel/tree/main/packages/tonal): tonal functions for scales and chords
|
||||||
export default defineConfig({
|
- [xen](https://github.com/tidalcycles/strudel/tree/main/packages/xen): microtonal / xenharmonic functions
|
||||||
plugins: [],
|
|
||||||
build: {
|
|
||||||
lib: {
|
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
|
||||||
formats: ['es', 'cjs'],
|
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' }[ext]),
|
|
||||||
},
|
|
||||||
rollupOptions: {
|
|
||||||
external: [...Object.keys(dependencies)],
|
|
||||||
},
|
|
||||||
target: 'esnext',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
This will build `index.mjs` (ESM) and `index.js` (CJS) to the dist folder.
|
### Outputs
|
||||||
|
|
||||||
### What's the main file?
|
These packages provide bindings for different ways to output strudel patterns:
|
||||||
|
|
||||||
Currently, each package uses the unbundled `index.mjs` as its main file, which must change for the published version.
|
- [webaudio](https://github.com/tidalcycles/strudel/tree/main/packages/webaudio#strudelcycleswebaudio): the default webaudio output
|
||||||
There are 2 ways to handle this:
|
- [osc](https://github.com/tidalcycles/strudel/tree/main/packages/osc#strudelcyclesosc): bindings to communicate via OSC
|
||||||
|
- [midi](https://github.com/tidalcycles/strudel/tree/main/packages/midi#strudelcyclesmidi): webmidi bindings
|
||||||
|
- [csound](https://github.com/tidalcycles/strudel/tree/main/packages/csound#strudelcyclescsound): csound bindings
|
||||||
|
- [soundfonts](https://github.com/tidalcycles/strudel/tree/main/packages/serial#strudelcyclessoundfonts): Soundfont support
|
||||||
|
- [serial](https://github.com/tidalcycles/strudel/tree/main/packages/serial#strudelcyclesserial): webserial bindings
|
||||||
|
|
||||||
1. `main` = `dist/index.js`, `module` = `dist/index.mjs`. The built files are used. This means that changing a source file won't take effect in the dev server without a rebuild.
|
### Others
|
||||||
2. Use different `package.json` files for dev vs publish. So the unbuilt `index.mjs` could be used in dev, while the built files can be used when publishing.
|
|
||||||
|
|
||||||
Option 1 could be done with [workspace watching](https://lerna.js.org/docs/features/workspace-watching), although it might make the dev server less snappy..
|
- [embed](https://github.com/tidalcycles/strudel/tree/main/packages/embed#strudelcyclesembed): embeddable REPL web component
|
||||||
Option 2 can be done by [publishing just the dist folder and copying over the `package.json` file](https://stackoverflow.com/questions/37862712/how-to-publish-contents-only-of-a-specific-folder).
|
- [react](https://github.com/tidalcycles/strudel/tree/main/packages/react#strudelcyclesreact): react hooks and components for strudel
|
||||||
Sadly, [this does not fit into how lerna works](https://github.com/lerna/lerna/issues/91).
|
|
||||||
|
|
||||||
https://github.com/changesets/changesets
|
### No Longer Maintained
|
||||||
|
|
||||||
https://turbo.build/repo/docs/handbook/publishing-packages/versioning-and-publishing
|
- [eval](https://github.com/tidalcycles/strudel/tree/main/packages/eval): old code transpiler
|
||||||
|
- [tone](https://github.com/tidalcycles/strudel/tree/main/packages/tone#strudelcyclestone): bindings for Tone.js instruments and effects
|
||||||
|
- [webdirt](https://github.com/tidalcycles/strudel/tree/main/packages/webdirt): webdirt bindings, replaced by webaudio package
|
||||||
|
|
||||||
https://pnpm.io/workspaces
|
## Tools
|
||||||
|
|
||||||
|
- [pnpm workspaces](https://pnpm.io/)
|
||||||
|
- Publishing packages is done with [lerna](https://lerna.js.org/).
|
||||||
|
|||||||
@ -92,7 +92,7 @@ export function Footer({ context }) {
|
|||||||
{activeFooter === 'console' && <ConsoleTab log={log} />}
|
{activeFooter === 'console' && <ConsoleTab log={log} />}
|
||||||
{activeFooter === 'samples' && <SamplesTab />}
|
{activeFooter === 'samples' && <SamplesTab />}
|
||||||
{activeFooter === 'reference' && <Reference />}
|
{activeFooter === 'reference' && <Reference />}
|
||||||
{activeFooter === 'settings' && <SettingsTab />}
|
{activeFooter === 'settings' && <SettingsTab scheduler={context.scheduler} />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</footer>
|
</footer>
|
||||||
@ -284,10 +284,28 @@ const fontFamilyOptions = {
|
|||||||
PressStart: 'PressStart2P',
|
PressStart: 'PressStart2P',
|
||||||
};
|
};
|
||||||
|
|
||||||
function SettingsTab() {
|
function SettingsTab({ scheduler }) {
|
||||||
const { theme, keybindings, fontSize, fontFamily } = useSettings();
|
const { theme, keybindings, fontSize, fontFamily } = useSettings();
|
||||||
return (
|
return (
|
||||||
<div className="text-foreground p-4 space-y-4">
|
<div className="text-foreground p-4 space-y-4">
|
||||||
|
{/* <FormItem label="Tempo">
|
||||||
|
<div className="space-x-4">
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
scheduler.setCps(scheduler.cps - 0.1);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
slower
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
scheduler.setCps(scheduler.cps + 0.1);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
faster
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</FormItem> */}
|
||||||
<FormItem label="Theme">
|
<FormItem label="Theme">
|
||||||
<SelectInput options={themeOptions} value={theme} onChange={(theme) => settingsMap.setKey('theme', theme)} />
|
<SelectInput options={themeOptions} value={theme} onChange={(theme) => settingsMap.setKey('theme', theme)} />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@ -242,6 +242,7 @@ export function Repl({ embedded = false }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const context = {
|
const context = {
|
||||||
|
scheduler,
|
||||||
embedded,
|
embedded,
|
||||||
started,
|
started,
|
||||||
pending,
|
pending,
|
||||||
@ -273,7 +274,10 @@ export function Repl({ embedded = false }) {
|
|||||||
fontSize={fontSize}
|
fontSize={fontSize}
|
||||||
fontFamily={fontFamily}
|
fontFamily={fontFamily}
|
||||||
onChange={handleChangeCode}
|
onChange={handleChangeCode}
|
||||||
onViewChanged={setView}
|
onViewChanged={(v) => {
|
||||||
|
setView(v);
|
||||||
|
// window.editorView = v;
|
||||||
|
}}
|
||||||
onSelectionChange={handleSelectionChange}
|
onSelectionChange={handleSelectionChange}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user