diff --git a/.gitignore b/.gitignore index 7fcf9d28..cbe4c324 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,5 @@ mytunes.ts doc out .parcel-cache -repl_old \ No newline at end of file +repl_old +tutorial.rendered.mdx \ No newline at end of file diff --git a/doc.json b/doc.json index f30bd098..af56ea59 100644 --- a/doc.json +++ b/doc.json @@ -1,18 +1,1367 @@ { "docs": [ + { + "comment": "/**\n * Select a sound / sample by name.\n *\n *
\n * show all sounds\n *\n * 808 (6) 808bd (25) 808cy (25) 808hc (5) 808ht (5) 808lc (5) 808lt (5) 808mc (5) 808mt (5) 808oh (5) 808sd (25) 909 (1) ab (12) ade (10) ades2 (9) ades3 (7) ades4 (6) alex (2) alphabet (26) amencutup (32) armora (7) arp (2) arpy (11) auto (11) baa (7) baa2 (7) bass (4) bass0 (3) bass1 (30) bass2 (5) bass3 (11) bassdm (24) bassfoo (3) battles (2) bd (24) bend (4) bev (2) bin (2) birds (10) birds3 (19) bleep (13) blip (2) blue (2) bottle (13) breaks125 (2) breaks152 (1) breaks157 (1) breaks165 (1) breath (1) bubble (8) can (14) casio (3) cb (1) cc (6) chin (4) circus (3) clak (2) click (4) clubkick (5) co (4) coins (1) control (2) cosmicg (15) cp (2) cr (6) crow (4) d (4) db (13) diphone (38) diphone2 (12) dist (16) dork2 (4) dorkbot (2) dr (42) dr2 (6) dr55 (4) dr_few (8) drum (6) drumtraks (13) e (8) east (9) electro1 (13) em2 (6) erk (1) f (1) feel (7) feelfx (8) fest (1) fire (1) flick (17) fm (17) foo (27) future (17) gab (10) gabba (4) gabbaloud (4) gabbalouder (4) glasstap (3) glitch (8) glitch2 (8) gretsch (24) gtr (3) h (7) hand (17) hardcore (12) hardkick (6) haw (6) hc (6) hh (13) hh27 (13) hit (6) hmm (1) ho (6) hoover (6) house (8) ht (16) if (5) ifdrums (3) incoming (8) industrial (32) insect (3) invaders (18) jazz (8) jungbass (20) jungle (13) juno (12) jvbass (13) kicklinn (1) koy (2) kurt (7) latibro (8) led (1) less (4) lighter (33) linnhats (6) lt (16) made (7) made2 (1) mash (2) mash2 (4) metal (10) miniyeah (4) monsterb (6) moog (7) mouth (15) mp3 (4) msg (9) mt (16) mute (28) newnotes (15) noise (1) noise2 (8) notes (15) numbers (9) oc (4) odx (15) off (1) outdoor (6) pad (3) padlong (1) pebbles (1) perc (6) peri (15) pluck (17) popkick (10) print (11) proc (2) procshort (8) psr (30) rave (8) rave2 (4) ravemono (2) realclaps (4) reverbkick (1) rm (2) rs (1) sax (22) sd (2) seawolf (3) sequential (8) sf (18) sheffield (1) short (5) sid (12) sine (6) sitar (8) sn (52) space (18) speakspell (12) speech (7) speechless (10) speedupdown (9) stab (23) stomp (10) subroc3d (11) sugar (2) sundance (6) tabla (26) tabla2 (46) tablex (3) tacscan (22) tech (13) techno (7) tink (5) tok (4) toys (13) trump (11) ul (10) ulgab (5) uxay (3) v (6) voodoo (5) wind (10) wobble (1) world (3) xmas (1) yeah (31)\n *\n * more info\n *\n *
\n *\n * @name s\n * @param {string | Pattern} sound The sound / pattern of sounds to pick\n * @example\n * s(\"bd hh\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 11, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Select a sound / sample by name.

\n
\nshow all sounds\n

808 (6) 808bd (25) 808cy (25) 808hc (5) 808ht (5) 808lc (5) 808lt (5) 808mc (5) 808mt (5) 808oh (5) 808sd (25) 909 (1) ab (12) ade (10) ades2 (9) ades3 (7) ades4 (6) alex (2) alphabet (26) amencutup (32) armora (7) arp (2) arpy (11) auto (11) baa (7) baa2 (7) bass (4) bass0 (3) bass1 (30) bass2 (5) bass3 (11) bassdm (24) bassfoo (3) battles (2) bd (24) bend (4) bev (2) bin (2) birds (10) birds3 (19) bleep (13) blip (2) blue (2) bottle (13) breaks125 (2) breaks152 (1) breaks157 (1) breaks165 (1) breath (1) bubble (8) can (14) casio (3) cb (1) cc (6) chin (4) circus (3) clak (2) click (4) clubkick (5) co (4) coins (1) control (2) cosmicg (15) cp (2) cr (6) crow (4) d (4) db (13) diphone (38) diphone2 (12) dist (16) dork2 (4) dorkbot (2) dr (42) dr2 (6) dr55 (4) dr_few (8) drum (6) drumtraks (13) e (8) east (9) electro1 (13) em2 (6) erk (1) f (1) feel (7) feelfx (8) fest (1) fire (1) flick (17) fm (17) foo (27) future (17) gab (10) gabba (4) gabbaloud (4) gabbalouder (4) glasstap (3) glitch (8) glitch2 (8) gretsch (24) gtr (3) h (7) hand (17) hardcore (12) hardkick (6) haw (6) hc (6) hh (13) hh27 (13) hit (6) hmm (1) ho (6) hoover (6) house (8) ht (16) if (5) ifdrums (3) incoming (8) industrial (32) insect (3) invaders (18) jazz (8) jungbass (20) jungle (13) juno (12) jvbass (13) kicklinn (1) koy (2) kurt (7) latibro (8) led (1) less (4) lighter (33) linnhats (6) lt (16) made (7) made2 (1) mash (2) mash2 (4) metal (10) miniyeah (4) monsterb (6) moog (7) mouth (15) mp3 (4) msg (9) mt (16) mute (28) newnotes (15) noise (1) noise2 (8) notes (15) numbers (9) oc (4) odx (15) off (1) outdoor (6) pad (3) padlong (1) pebbles (1) perc (6) peri (15) pluck (17) popkick (10) print (11) proc (2) procshort (8) psr (30) rave (8) rave2 (4) ravemono (2) realclaps (4) reverbkick (1) rm (2) rs (1) sax (22) sd (2) seawolf (3) sequential (8) sf (18) sheffield (1) short (5) sid (12) sine (6) sitar (8) sn (52) space (18) speakspell (12) speech (7) speechless (10) speedupdown (9) stab (23) stomp (10) subroc3d (11) sugar (2) sundance (6) tabla (26) tabla2 (46) tablex (3) tacscan (22) tech (13) techno (7) tink (5) tok (4) toys (13) trump (11) ul (10) ulgab (5) uxay (3) v (6) voodoo (5) wind (10) wobble (1) world (3) xmas (1) yeah (31)

\n

more info

\n
", + "name": "s", + "params": [ + { + "type": { + "names": [ + "string", + "Pattern" + ] + }, + "description": "

The sound / pattern of sounds to pick

", + "name": "sound" + } + ], + "examples": [ + "s(\"bd hh\").osc()" + ], + "longname": "s", + "kind": "member", + "scope": "global", + "___id": "T000002R000004", + "___s": true + }, + { + "comment": "/**\n * The note or sample number to choose for a synth or sampleset\n * Note names currently not working yet, but will hopefully soon. Just stick to numbers for now\n *\n * @name n\n * @param {string | number | Pattern} value note name, note number or sample number\n * @example\n * s('superpiano').n(\"<0 1 2 3>\").osc()\n * @example\n * s('superpiano').n(\"\").osc()\n * @example\n * n(\"0 1 2 3\").s('east').osc()\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 30, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

The note or sample number to choose for a synth or sampleset\nNote names currently not working yet, but will hopefully soon. Just stick to numbers for now

", + "name": "n", + "params": [ + { + "type": { + "names": [ + "string", + "number", + "Pattern" + ] + }, + "description": "

note name, note number or sample number

", + "name": "value" + } + ], + "examples": [ + "s('superpiano').n(\"<0 1 2 3>\").osc()", + "s('superpiano').n(\"\").osc()", + "n(\"0 1 2 3\").s('east').osc()" + ], + "longname": "n", + "kind": "member", + "scope": "global", + "___id": "T000002R000005", + "___s": true + }, + { + "comment": "/**\n * A pattern of numbers that speed up (or slow down) samples while they play. Currently only supported by osc / superdirt.\n *\n * @name accelerate\n * @param {number | Pattern} amount acceleration.\n * @example\n * s(\"sax\").accelerate(\"<0 1 2 4 8 16>\").slow(2).osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 54, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

A pattern of numbers that speed up (or slow down) samples while they play. Currently only supported by osc / superdirt.

", + "name": "accelerate", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

acceleration.

", + "name": "amount" + } + ], + "examples": [ + "s(\"sax\").accelerate(\"<0 1 2 4 8 16>\").slow(2).osc()" + ], + "longname": "accelerate", + "kind": "member", + "scope": "global", + "___id": "T000002R000006", + "___s": true + }, + { + "comment": "/**\n * Like {@link amp}, but exponential.\n *\n * @name gain\n * @param {number | Pattern} amount gain.\n * @example\n * s(\"bd*8\").gain(\".7*2 1 .7*2 1 .7 1\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 64, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Like {@link amp}, but exponential.

", + "name": "gain", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

gain.

", + "name": "amount" + } + ], + "examples": [ + "s(\"bd*8\").gain(\".7*2 1 .7*2 1 .7 1\").osc()" + ], + "longname": "gain", + "kind": "member", + "scope": "global", + "___id": "T000002R000007", + "___s": true + }, + { + "comment": "/**\n * Like {@link gain}, but linear.\n *\n * @name amp\n * @param {number | Pattern} amount gain.\n * @example\n * s(\"bd*8\").amp(\".1*2 .5 .1*2 .5 .1 .5\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 78, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Like {@link gain}, but linear.

", + "name": "amp", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

gain.

", + "name": "amount" + } + ], + "examples": [ + "s(\"bd*8\").amp(\".1*2 .5 .1*2 .5 .1 .5\").osc()" + ], + "longname": "amp", + "kind": "member", + "scope": "global", + "___id": "T000002R000008", + "___s": true + }, + { + "comment": "/**\n * Sets the center frequency of the band-pass filter.\n *\n * @name bandf\n * @param {number | Pattern} frequency center frequency\n * @example\n * s(\"bd sd\").bandf(\"<1000 2000 4000 8000>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 126, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Sets the center frequency of the band-pass filter.

", + "name": "bandf", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

center frequency

", + "name": "frequency" + } + ], + "examples": [ + "s(\"bd sd\").bandf(\"<1000 2000 4000 8000>\").osc()" + ], + "longname": "bandf", + "kind": "member", + "scope": "global", + "___id": "T000002R000009", + "___s": true + }, + { + "comment": "/**\n * Sets the q-factor of the band-pass filter\n *\n * @name bandq\n * @param {number | Pattern} q q factor\n * @example\n * s(\"bd sd\").bandf(2000).bandq(\"<.2 .9>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 137, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Sets the q-factor of the band-pass filter

", + "name": "bandq", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

q factor

", + "name": "q" + } + ], + "examples": [ + "s(\"bd sd\").bandf(2000).bandq(\"<.2 .9>\").osc()" + ], + "longname": "bandq", + "kind": "member", + "scope": "global", + "___id": "T000002R000010", + "___s": true + }, + { + "comment": "/**\n * 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.\n *\n * @name begin\n * @param {number | Pattern} amount between 0 and 1, where 1 is the length of the sample\n * @example\n * s(\"rave\").begin(\"<0 .25 .5 .75>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 147, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

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.

", + "name": "begin", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

between 0 and 1, where 1 is the length of the sample

", + "name": "amount" + } + ], + "examples": [ + "s(\"rave\").begin(\"<0 .25 .5 .75>\").osc()" + ], + "longname": "begin", + "kind": "member", + "scope": "global", + "___id": "T000002R000011", + "___s": true + }, + { + "comment": "/**\n * The same as {@link begin}, but cuts off the end off each sample.\n *\n * @name end\n * @param {number | Pattern} length 1 = whole sample, .5 = half sample, .25 = quarter sample etc..\n * @example\n * s(\"bd*2,ho*4\").end(\"<.1 .2 .5 1>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 161, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

The same as {@link begin}, but cuts off the end off each sample.

", + "name": "end", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

1 = whole sample, .5 = half sample, .25 = quarter sample etc..

", + "name": "length" + } + ], + "examples": [ + "s(\"bd*2,ho*4\").end(\"<.1 .2 .5 1>\").osc()" + ], + "longname": "end", + "kind": "member", + "scope": "global", + "___id": "T000002R000012", + "___s": true + }, + { + "comment": "/**\n * Loops the sample (from `begin` to `end`) the specified number of times.\n * Note that the tempo of the loop is not synced with the cycle tempo.\n *\n * @name loop\n * @param {number | Pattern} times How often the sample is looped\n * @example\n * s(\"bd\").loop(\"<1 2 3 4>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 175, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Loops the sample (from begin to end) the specified number of times.\nNote that the tempo of the loop is not synced with the cycle tempo.

", + "name": "loop", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

How often the sample is looped

", + "name": "times" + } + ], + "examples": [ + "s(\"bd\").loop(\"<1 2 3 4>\").osc()" + ], + "longname": "loop", + "kind": "member", + "scope": "global", + "___id": "T000002R000013", + "___s": true + }, + { + "comment": "/**\n * 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.\n *\n * @name legato\n * @param {number | Pattern} duration between 0 and 1, where 1 is the length of the whole hap time\n * @example\n * \"c4 eb4 g4 bb4\".legato(\"<0.125 .25 .5 .75 1 2 4>\")\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 188, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

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.

", + "name": "legato", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

between 0 and 1, where 1 is the length of the whole hap time

", + "name": "duration" + } + ], + "examples": [ + "\"c4 eb4 g4 bb4\".legato(\"<0.125 .25 .5 .75 1 2 4>\")" + ], + "longname": "legato", + "kind": "member", + "scope": "global", + "___id": "T000002R000014", + "___s": true + }, + { + "comment": "/**\n * bit crusher effect.\n *\n * @name crush\n * @param {number | Pattern} depth between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).\n * @example\n * s(\",hh*3,jvbass*2\").fast(2).crush(\"<16 8 7 6 5 4 3 2>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 199, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

bit crusher effect.

", + "name": "crush", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).

", + "name": "depth" + } + ], + "examples": [ + "s(\",hh*3,jvbass*2\").fast(2).crush(\"<16 8 7 6 5 4 3 2>\").osc()" + ], + "longname": "crush", + "kind": "member", + "scope": "global", + "___id": "T000002R000015", + "___s": true + }, + { + "comment": "/**\n * fake-resampling for lowering the sample rate\n *\n * @name coarse\n * @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on.\n * @example\n * s(\"xmas\").coarse(\"<1 4 8 16 32>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 213, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

fake-resampling for lowering the sample rate

", + "name": "coarse", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

1 for original 2 for half, 3 for a third and so on.

", + "name": "factor" + } + ], + "examples": [ + "s(\"xmas\").coarse(\"<1 4 8 16 32>\").osc()" + ], + "longname": "coarse", + "kind": "member", + "scope": "global", + "___id": "T000002R000016", + "___s": true + }, + { + "comment": "/**\n * choose the channel the pattern is sent to in superdirt\n *\n * @name channel\n * @param {number | Pattern} channel channel number\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 228, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

choose the channel the pattern is sent to in superdirt

", + "name": "channel", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

channel number

", + "name": "channel" + } + ], + "longname": "channel", + "kind": "member", + "scope": "global", + "___id": "T000002R000017", + "___s": true + }, + { + "comment": "/**\n * 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.\n *\n * @name cut\n * @param {number | Pattern} group cut group number\n * @example\n * s(\"bd sax\").cut(1).osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 236, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

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.

", + "name": "cut", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

cut group number

", + "name": "group" + } + ], + "examples": [ + "s(\"bd sax\").cut(1).osc()" + ], + "longname": "cut", + "kind": "member", + "scope": "global", + "___id": "T000002R000018", + "___s": true + }, + { + "comment": "/**\n * Applies the cutoff frequency of the low-pass filter.\n *\n * @name cutoff\n * @param {number | Pattern} frequency audible between 0 and 20000\n * @example\n * s(\"bd,hh*2,<~ sd>\").fast(2).cutoff(\"<4000 2000 1000 500 200 100>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 250, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Applies the cutoff frequency of the low-pass filter.

", + "name": "cutoff", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

audible between 0 and 20000

", + "name": "frequency" + } + ], + "examples": [ + "s(\"bd,hh*2,<~ sd>\").fast(2).cutoff(\"<4000 2000 1000 500 200 100>\").osc()" + ], + "longname": "cutoff", + "kind": "member", + "scope": "global", + "___id": "T000002R000019", + "___s": true + }, + { + "comment": "/**\n * Applies the cutoff frequency of the high-pass filter.\n *\n * @name hcutoff\n * @param {number | Pattern} frequency audible between 0 and 20000\n * @example\n * s(\"bd,hh*2,<~ sd>\").fast(2).hcutoff(\"<4000 2000 1000 500 200 100>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 261, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Applies the cutoff frequency of the high-pass filter.

", + "name": "hcutoff", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

audible between 0 and 20000

", + "name": "frequency" + } + ], + "examples": [ + "s(\"bd,hh*2,<~ sd>\").fast(2).hcutoff(\"<4000 2000 1000 500 200 100>\").osc()" + ], + "longname": "hcutoff", + "kind": "member", + "scope": "global", + "___id": "T000002R000020", + "___s": true + }, + { + "comment": "/**\n * Applies the cutoff frequency of the high-pass filter.\n *\n * @name hresonance\n * @param {number | Pattern} q resonance factor between 0 and 1\n * @example\n * s(\"bd,hh*2,<~ sd>\").fast(2).hcutoff(2000).hresonance(\"<0 .2 .4 .6>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 276, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Applies the cutoff frequency of the high-pass filter.

", + "name": "hresonance", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

resonance factor between 0 and 1

", + "name": "q" + } + ], + "examples": [ + "s(\"bd,hh*2,<~ sd>\").fast(2).hcutoff(2000).hresonance(\"<0 .2 .4 .6>\").osc()" + ], + "longname": "hresonance", + "kind": "member", + "scope": "global", + "___id": "T000002R000021", + "___s": true + }, + { + "comment": "/**\n * Applies the cutoff frequency of the low-pass filter.\n *\n * @name resonance\n * @param {number | Pattern} q resonance factor between 0 and 1\n * @example\n * s(\"bd,hh*2,<~ sd>\").fast(2).cutoff(2000).resonance(\"<0 .2 .4 .6>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 291, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Applies the cutoff frequency of the low-pass filter.

", + "name": "resonance", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

resonance factor between 0 and 1

", + "name": "q" + } + ], + "examples": [ + "s(\"bd,hh*2,<~ sd>\").fast(2).cutoff(2000).resonance(\"<0 .2 .4 .6>\").osc()" + ], + "longname": "resonance", + "kind": "member", + "scope": "global", + "___id": "T000002R000022", + "___s": true + }, + { + "comment": "/**\n * Set detune of oscillators. Works only with some synths, see tidal doc\n *\n * @name djf\n * @param {number | Pattern} cutoff below 0.5 is low pass filter, above is high pass filter\n * @example\n * n(\"0 3 7 [10,24]\").s('superzow').octave(3).djf(\"<.5 .25 .5 .75>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 302, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Set detune of oscillators. Works only with some synths, see tidal doc

", + "name": "djf", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

below 0.5 is low pass filter, above is high pass filter

", + "name": "cutoff" + } + ], + "examples": [ + "n(\"0 3 7 [10,24]\").s('superzow').octave(3).djf(\"<.5 .25 .5 .75>\").osc()" + ], + "longname": "djf", + "kind": "member", + "scope": "global", + "___id": "T000002R000023", + "___s": true + }, + { + "comment": "/**\n * Set detune of oscillators. Works only with some synths, see tidal doc\n *\n * @name detune\n * @param {number | Pattern} amount between 0 and 1\n * @example\n * n(\"0 3 7\").s('superzow').octave(3).detune(\"<0 .25 .5 1 2>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 340, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Set detune of oscillators. Works only with some synths, see tidal doc

", + "name": "detune", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

between 0 and 1

", + "name": "amount" + } + ], + "examples": [ + "n(\"0 3 7\").s('superzow').octave(3).detune(\"<0 .25 .5 1 2>\").osc()" + ], + "longname": "detune", + "kind": "member", + "scope": "global", + "___id": "T000002R000024", + "___s": true + }, + { + "comment": "/**\n * Set dryness of reverb. See {@link room} and {@link size} for more information about reverb.\n *\n * @name dry\n * @param {number | Pattern} dry 0 = wet, 1 = dry\n * @example\n * n(\"[0,3,7](3,8)\").s(\"superpiano\").room(.7).dry(\"<0 .5 .75 1>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 350, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Set dryness of reverb. See {@link room} and {@link size} for more information about reverb.

", + "name": "dry", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

0 = wet, 1 = dry

", + "name": "dry" + } + ], + "examples": [ + "n(\"[0,3,7](3,8)\").s(\"superpiano\").room(.7).dry(\"<0 .5 .75 1>\").osc()" + ], + "longname": "dry", + "kind": "member", + "scope": "global", + "___id": "T000002R000025", + "___s": true + }, + { + "comment": "/**\n * Set frequency of sound.\n *\n * @name freq\n * @param {number | Pattern} frequency in Hz. the audible range is between 20 and 20000 Hz\n * @example\n * freq(\"220 110 440 110\").s(\"superzow\").osc()\n * @example\n * freq(\"110\".mulOut(\".5 1.5 .6 [2 3]\")).s(\"superzow\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 385, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Set frequency of sound.

", + "name": "freq", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

in Hz. the audible range is between 20 and 20000 Hz

", + "name": "frequency" + } + ], + "examples": [ + "freq(\"220 110 440 110\").s(\"superzow\").osc()", + "freq(\"110\".mulOut(\".5 1.5 .6 [2 3]\")).s(\"superzow\").osc()" + ], + "longname": "freq", + "kind": "member", + "scope": "global", + "___id": "T000002R000026", + "___s": true + }, + { + "comment": "/**\n * Emulation of a Leslie speaker: speakers rotating in a wooden amplified cabinet.\n *\n * @name leslie\n * @param {number | Pattern} wet between 0 and 1\n * @example\n * n(\"0,4,7\").s(\"supersquare\").leslie(\"<0 .4 .6 1>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 408, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Emulation of a Leslie speaker: speakers rotating in a wooden amplified cabinet.

", + "name": "leslie", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

between 0 and 1

", + "name": "wet" + } + ], + "examples": [ + "n(\"0,4,7\").s(\"supersquare\").leslie(\"<0 .4 .6 1>\").osc()" + ], + "longname": "leslie", + "kind": "member", + "scope": "global", + "___id": "T000002R000027", + "___s": true + }, + { + "comment": "/**\n * Rate of modulation / rotation for leslie effect\n *\n * @name lrate\n * @param {number | Pattern} rate 6.7 for fast, 0.7 for slow\n * @example\n * n(\"0,4,7\").s(\"supersquare\").leslie(1).lrate(\"<1 2 4 8>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 418, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Rate of modulation / rotation for leslie effect

", + "name": "lrate", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

6.7 for fast, 0.7 for slow

", + "name": "rate" + } + ], + "examples": [ + "n(\"0,4,7\").s(\"supersquare\").leslie(1).lrate(\"<1 2 4 8>\").osc()" + ], + "longname": "lrate", + "kind": "member", + "scope": "global", + "___id": "T000002R000028", + "___s": true + }, + { + "comment": "/**\n * Physical size of the cabinet in meters. Be careful, it might be slightly larger than your computer. Affects the Doppler amount (pitch warble)\n *\n * @name lsize\n * @param {number | Pattern} meters somewhere between 0 and 1\n * @example\n * n(\"0,4,7\").s(\"supersquare\").leslie(1).lrate(2).lsize(\"<.1 .5 1>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 429, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Physical size of the cabinet in meters. Be careful, it might be slightly larger than your computer. Affects the Doppler amount (pitch warble)

", + "name": "lsize", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

somewhere between 0 and 1

", + "name": "meters" + } + ], + "examples": [ + "n(\"0,4,7\").s(\"supersquare\").leslie(1).lrate(2).lsize(\"<.1 .5 1>\").osc()" + ], + "longname": "lsize", + "kind": "member", + "scope": "global", + "___id": "T000002R000029", + "___s": true + }, + { + "comment": "/**\n * Sets the default octave of a synth.\n *\n * @name octave\n * @param {number | Pattern} octave octave number\n * @example\n * n(\"0,4,7\").s('supersquare').octave(\"<3 4 5 6>\").osc()\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 464, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Sets the default octave of a synth.

", + "name": "octave", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

octave number

", + "name": "octave" + } + ], + "examples": [ + "n(\"0,4,7\").s('supersquare').octave(\"<3 4 5 6>\").osc()" + ], + "longname": "octave", + "kind": "member", + "scope": "global", + "___id": "T000002R000030", + "___s": true + }, + { + "comment": "/**\n * 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.\n *\n * @name orbit\n * @param {number | Pattern} number\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 476, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

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.

", + "name": "orbit", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "name": "number" + } + ], + "longname": "orbit", + "kind": "member", + "scope": "global", + "___id": "T000002R000031", + "___s": true + }, + { + "comment": "/**\n * Sets position in stereo.\n *\n * @name pan\n * @param {number | Pattern} pan between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel)\n * @example\n * s(\"[bd hh]*2\").pan(\"<.5 1 .5 0>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 490, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Sets position in stereo.

", + "name": "pan", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel)

", + "name": "pan" + } + ], + "examples": [ + "s(\"[bd hh]*2\").pan(\"<.5 1 .5 0>\").osc()" + ], + "longname": "pan", + "kind": "member", + "scope": "global", + "___id": "T000002R000032", + "___s": true + }, + { + "comment": "/**\n * Sets the level of reverb.\n *\n * @name room\n * @param {number | Pattern} level between 0 and 1\n * @example\n * s(\"bd sd\").room(\"<0 .2 .4 .6 .8 1>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 557, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Sets the level of reverb.

", + "name": "room", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

between 0 and 1

", + "name": "level" + } + ], + "examples": [ + "s(\"bd sd\").room(\"<0 .2 .4 .6 .8 1>\").osc()" + ], + "longname": "room", + "kind": "member", + "scope": "global", + "___id": "T000002R000033", + "___s": true + }, + { + "comment": "/**\n * Sets the room size of the reverb, see {@link room}.\n *\n * @name size\n * @param {number | Pattern} size between 0 and 1\n * @example\n * s(\"bd sd\").room(.8).size(\"<0 .2 .4 .6 .8 1>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 567, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Sets the room size of the reverb, see {@link room}.

", + "name": "size", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

between 0 and 1

", + "name": "size" + } + ], + "examples": [ + "s(\"bd sd\").room(.8).size(\"<0 .2 .4 .6 .8 1>\").osc()" + ], + "longname": "size", + "kind": "member", + "scope": "global", + "___id": "T000002R000034", + "___s": true + }, + { + "comment": "/**\n * Wave shaping distortion. CAUTION: it might get loud\n *\n * @name shape\n * @param {number | Pattern} distortion between 0 and 1\n * @example\n * s(\"bd sd\").shape(\"<0 .2 .4 .6 .8 1>\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 588, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Wave shaping distortion. CAUTION: it might get loud

", + "name": "shape", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

between 0 and 1

", + "name": "distortion" + } + ], + "examples": [ + "s(\"bd sd\").shape(\"<0 .2 .4 .6 .8 1>\").osc()" + ], + "longname": "shape", + "kind": "member", + "scope": "global", + "___id": "T000002R000035", + "___s": true + }, + { + "comment": "/**\n * Changes the speed of sample playback, i.e. a cheap way of changing pitch.\n *\n * @name speed\n * @param {number | Pattern} speed -inf to inf, negative numbers play the sample backwards.\n * @example\n * s(\"bd\").speed(\"<1 2 4 1 -2 -4>\").osc()\n * @example\n * speed(\"1 1.5*2 [2 1.1]\").s(\"sax\").cut(1).osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 602, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Changes the speed of sample playback, i.e. a cheap way of changing pitch.

", + "name": "speed", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

inf to inf, negative numbers play the sample backwards.

", + "name": "speed" + } + ], + "examples": [ + "s(\"bd\").speed(\"<1 2 4 1 -2 -4>\").osc()", + "speed(\"1 1.5*2 [2 1.1]\").s(\"sax\").cut(1).osc()" + ], + "longname": "speed", + "kind": "member", + "scope": "global", + "___id": "T000002R000036", + "___s": true + }, + { + "comment": "/**\n * 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`.\n *\n * @name unit\n * @param {number | string | Pattern} unit see description above\n * @example\n * speed(\"1 2 .5 3\").s(\"bd\").unit(\"c\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 618, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

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.

", + "name": "unit", + "params": [ + { + "type": { + "names": [ + "number", + "string", + "Pattern" + ] + }, + "description": "

see description above

", + "name": "unit" + } + ], + "examples": [ + "speed(\"1 2 .5 3\").s(\"bd\").unit(\"c\").osc()" + ], + "longname": "unit", + "kind": "member", + "scope": "global", + "___id": "T000002R000037", + "___s": true + }, + { + "comment": "/**\n * Made by Calum Gunn. Reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter. The SuperCollider manual defines Squiz as:\n *\n * \"A simplistic pitch-raising algorithm. It's not meant to sound natural; its sound is reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter, depending on the input. The algorithm works by cutting the signal into fragments (delimited by upwards-going zero-crossings) and squeezing those fragments in the time domain (i.e. simply playing them back faster than they came in), leaving silences inbetween. All the parameters apart from memlen can be modulated.\"\n *\n * @name squiz\n * @param {number | Pattern} squiz Try passing multiples of 2 to it - 2, 4, 8 etc.\n * @example\n * squiz(\"2 4/2 6 [8 16]\").s(\"bd\").osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 632, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Made by Calum Gunn. Reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter. The SuperCollider manual defines Squiz as:

\n

"A simplistic pitch-raising algorithm. It's not meant to sound natural; its sound is reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter, depending on the input. The algorithm works by cutting the signal into fragments (delimited by upwards-going zero-crossings) and squeezing those fragments in the time domain (i.e. simply playing them back faster than they came in), leaving silences inbetween. All the parameters apart from memlen can be modulated."

", + "name": "squiz", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

Try passing multiples of 2 to it - 2, 4, 8 etc.

", + "name": "squiz" + } + ], + "examples": [ + "squiz(\"2 4/2 6 [8 16]\").s(\"bd\").osc()" + ], + "longname": "squiz", + "kind": "member", + "scope": "global", + "___id": "T000002R000038", + "___s": true + }, + { + "comment": "/**\n *\n * Formant filter to make things sound like vowels.\n *\n * @name vowel\n * @param {string | Pattern} vowel You can use a e i o u. Use a rest (~) to override the effect\n * @example\n * vowel(\"a e i [o u]\").slow(2)\n * .n(\"<[0,7]!4 [2,7]!4>\")\n * .s('supersquare').osc()\n *\n */", + "meta": { + "filename": "controls.mjs", + "lineno": 651, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Formant filter to make things sound like vowels.

", + "name": "vowel", + "params": [ + { + "type": { + "names": [ + "string", + "Pattern" + ] + }, + "description": "

You can use a e i o u. Use a rest (~) to override the effect

", + "name": "vowel" + } + ], + "examples": [ + "vowel(\"a e i [o u]\").slow(2)\n.n(\"<[0,7]!4 [2,7]!4>\")\n.s('supersquare').osc()" + ], + "longname": "vowel", + "kind": "member", + "scope": "global", + "___id": "T000002R000039", + "___s": true + }, + { + "comment": "/**\n * Intended for a debugging, drawLine renders the pattern as a string, where each character represents the same time span.\n * Should only be used with single characters as values, otherwise the character slots will be messed up.\n * Character legend:\n *\n * - \"|\" cycle separator\n * - \"-\" hold previous value\n * - \".\" silence\n *\n * @param {Pattern} pattern the pattern to use\n * @param {number} chars max number of characters (approximately)\n * @returns string\n * @example\n * const line = drawLine(\"0 [1 2 3]\", 10); // |0--123|0--123\n * console.log(line);\n */", + "meta": { + "range": [ + 1414, + 2784 + ], + "filename": "drawLine.mjs", + "lineno": 25, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000596", + "name": "drawLine", + "type": "FunctionDeclaration", + "paramnames": [ + "pat", + "chars" + ] + }, + "vars": { + "cycle": "drawLine~cycle", + "pos": "drawLine~pos", + "lines": "drawLine~lines", + "emptyLine": "drawLine~emptyLine", + "haps": "drawLine~haps", + "durations": "drawLine~durations", + "": null, + "charFraction": "drawLine~charFraction", + "totalSlots": "drawLine~totalSlots", + "i": "drawLine~i", + "undefined": null, + "matches": "drawLine~matches", + "missingLines": "drawLine~missingLines" + } + }, + "description": "

Intended for a debugging, drawLine renders the pattern as a string, where each character represents the same time span.\nShould only be used with single characters as values, otherwise the character slots will be messed up.\nCharacter legend:

\n
    \n
  • "|" cycle separator
  • \n
  • "-" hold previous value
  • \n
  • "." silence
  • \n
", + "params": [ + { + "type": { + "names": [ + "Pattern" + ] + }, + "description": "

the pattern to use

", + "name": "pattern" + }, + { + "type": { + "names": [ + "number" + ] + }, + "description": "

max number of characters (approximately)

", + "name": "chars" + } + ], + "returns": [ + { + "description": "

string

" + } + ], + "examples": [ + "const line = drawLine(\"0 [1 2 3]\", 10); // |0--123|0--123\nconsole.log(line);" + ], + "name": "drawLine", + "longname": "drawLine", + "kind": "function", + "scope": "global", + "___id": "T000002R000046", + "___s": true + }, + { + "comment": "/**\n * Changes the structure of the pattern to form an euclidean rhythm.\n * Euclidian rhythms are rhythms obtained using the greatest common divisor of two numbers.\n * They were described in 2004 by Godfried Toussaint, a canadian computer scientist.\n * Euclidian rhythms are really useful for computer/algorithmic music because they can accurately\n * describe a large number of rhythms used in the most important music world traditions.\n *\n * @memberof Pattern\n * @param {number} pulses the number of onsets / beats\n * @param {number} steps the number of steps to fill\n * @param {number} rotation (optional) offset in steps\n * @returns Pattern\n * @example // The Cuban tresillo pattern.\n * \"c3\".euclid(3,8)\n * @example // A thirteenth century Persian rhythm called Khafif-e-ramal.\n * \"c3\".euclid(2,5)\n * @example // The archetypal pattern of the Cumbia from Colombia, as well as a Calypso rhythm from Trinidad.\n * \"c3\".euclid(3,4)\n * @example // Another thirteenth century Persian rhythm by the name of Khafif-e-ramal, as well as a Rumanian folk-dance rhythm.\n * \"c3\".euclid(3,5,2)\n * @example // A Ruchenitza rhythm used in a Bulgarian folk-dance.\n * \"c3\".euclid(3,7)\n * @example // The Cuban tresillo pattern.\n * \"c3\".euclid(3,8)\n * @example // Another Ruchenitza Bulgarian folk-dance rhythm.\n * \"c3\".euclid(4,7)\n * @example // The Aksak rhythm of Turkey.\n * \"c3\".euclid(4,9)\n * @example // The metric pattern used by Frank Zappa in his piece titled Outside Now.\n * \"c3\".euclid(4,11)\n * @example // Yields the York-Samai pattern, a popular Arab rhythm.\n * \"c3\".euclid(5,6)\n * @example // The Nawakhat pattern, another popular Arab rhythm.\n * \"c3\".euclid(5,7)\n * @example // The Cuban cinquillo pattern.\n * \"c3\".euclid(5,8)\n * @example // A popular Arab rhythm called Agsag-Samai.\n * \"c3\".euclid(5,9)\n * @example // The metric pattern used by Moussorgsky in Pictures at an Exhibition.\n * \"c3\".euclid(5,11)\n * @example // The Venda clapping pattern of a South African children’s song.\n * \"c3\".euclid(5,12)\n * @example // The Bossa-Nova rhythm necklace of Brazil.\n * \"c3\".euclid(5,16)\n * @example // A typical rhythm played on the Bendir (frame drum).\n * \"c3\".euclid(7,8)\n * @example // A common West African bell pattern.\n * \"c3\".euclid(7,12)\n * @example // A Samba rhythm necklace from Brazil.\n * \"c3\".euclid(7,16,14)\n * @example // A rhythm necklace used in the Central African Republic.\n * \"c3\".euclid(9,16)\n * @example // A rhythm necklace of the Aka Pygmies of Central Africa.\n * \"c3\".euclid(11,24,14)\n * @example // Another rhythm necklace of the Aka Pygmies of the upper Sangha.\n * \"c3\".euclid(13,24,5)\n */", + "meta": { + "range": [ + 3722, + 3846 + ], + "filename": "euclid.mjs", + "lineno": 77, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000894", + "name": "Pattern.prototype.euclid", + "type": "FunctionExpression", + "paramnames": [ + "pulses", + "steps", + "rotation" + ] + } + }, + "description": "

Changes the structure of the pattern to form an euclidean rhythm.\nEuclidian rhythms are rhythms obtained using the greatest common divisor of two numbers.\nThey were described in 2004 by Godfried Toussaint, a canadian computer scientist.\nEuclidian rhythms are really useful for computer/algorithmic music because they can accurately\ndescribe a large number of rhythms used in the most important music world traditions.

", + "memberof": "Pattern", + "params": [ + { + "type": { + "names": [ + "number" + ] + }, + "description": "

the number of onsets / beats

", + "name": "pulses" + }, + { + "type": { + "names": [ + "number" + ] + }, + "description": "

the number of steps to fill

", + "name": "steps" + }, + { + "type": { + "names": [ + "number" + ] + }, + "description": "

(optional) offset in steps

", + "name": "rotation" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "examples": [ + "// The Cuban tresillo pattern.\n\"c3\".euclid(3,8)", + "// A thirteenth century Persian rhythm called Khafif-e-ramal.\n\"c3\".euclid(2,5)", + "// The archetypal pattern of the Cumbia from Colombia, as well as a Calypso rhythm from Trinidad.\n\"c3\".euclid(3,4)", + "// Another thirteenth century Persian rhythm by the name of Khafif-e-ramal, as well as a Rumanian folk-dance rhythm.\n\"c3\".euclid(3,5,2)", + "// A Ruchenitza rhythm used in a Bulgarian folk-dance.\n\"c3\".euclid(3,7)", + "// The Cuban tresillo pattern.\n\"c3\".euclid(3,8)", + "// Another Ruchenitza Bulgarian folk-dance rhythm.\n\"c3\".euclid(4,7)", + "// The Aksak rhythm of Turkey.\n\"c3\".euclid(4,9)", + "// The metric pattern used by Frank Zappa in his piece titled Outside Now.\n\"c3\".euclid(4,11)", + "// Yields the York-Samai pattern, a popular Arab rhythm.\n\"c3\".euclid(5,6)", + "// The Nawakhat pattern, another popular Arab rhythm.\n\"c3\".euclid(5,7)", + "// The Cuban cinquillo pattern.\n\"c3\".euclid(5,8)", + "// A popular Arab rhythm called Agsag-Samai.\n\"c3\".euclid(5,9)", + "// The metric pattern used by Moussorgsky in Pictures at an Exhibition.\n\"c3\".euclid(5,11)", + "// The Venda clapping pattern of a South African children’s song.\n\"c3\".euclid(5,12)", + "// The Bossa-Nova rhythm necklace of Brazil.\n\"c3\".euclid(5,16)", + "// A typical rhythm played on the Bendir (frame drum).\n\"c3\".euclid(7,8)", + "// A common West African bell pattern.\n\"c3\".euclid(7,12)", + "// A Samba rhythm necklace from Brazil.\n\"c3\".euclid(7,16,14)", + "// A rhythm necklace used in the Central African Republic.\n\"c3\".euclid(9,16)", + "// A rhythm necklace of the Aka Pygmies of Central Africa.\n\"c3\".euclid(11,24,14)", + "// Another rhythm necklace of the Aka Pygmies of the upper Sangha.\n\"c3\".euclid(13,24,5)" + ], + "name": "euclid", + "longname": "Pattern#euclid", + "kind": "function", + "scope": "instance", + "___id": "T000002R000070", + "___s": true + }, + { + "comment": "/**\n * Similar to {@link Pattern#euclid}, but each pulse is held until the next pulse, so there will be no gaps.\n */", + "meta": { + "range": [ + 3966, + 4337 + ], + "filename": "euclid.mjs", + "lineno": 84, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000918", + "name": "Pattern.prototype.euclidLegato", + "type": "FunctionExpression", + "paramnames": [ + "pulses", + "steps", + "rotation" + ] + }, + "vars": { + "bin_pat": "Pattern#euclidLegato~bin_pat", + "firstOne": "Pattern#euclidLegato~firstOne", + "gapless": "Pattern#euclidLegato~gapless", + "": null + } + }, + "description": "

Similar to {@link Pattern#euclid}, but each pulse is held until the next pulse, so there will be no gaps.

", + "name": "euclidLegato", + "longname": "Pattern#euclidLegato", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000071", + "___s": true + }, { "comment": "/** @class Class representing a pattern. */", "meta": { "range": [ 1178, - 27040 + 31915 ], "filename": "pattern.mjs", "lineno": 17, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100001837", + "id": "astnode100005731", "name": "exports.Pattern", "type": "ClassDeclaration" } @@ -22,7 +1371,7 @@ "kind": "class", "classdesc": "

Class representing a pattern.

", "scope": "global", - "description": "

Create a pattern.

", + "description": "

Create a pattern. As an end user, you will most likely not create a Pattern directly.

", "memberof": "Pattern", "params": [ { @@ -31,26 +1380,26 @@ "function" ] }, - "description": "

The function that maps a State to Haps .

", + "description": "

The function that maps a {@link State} to an array of {@link Hap}.

", "name": "query" } ], - "___id": "T000002R000098", + "___id": "T000002R000531", "___s": true }, { - "comment": "/**\n * query events insude the tiven time span\n *\n * @param {Fraction | number} begin from time\n * @param {Fraction | number} end to time\n * @returns Hap[]\n * @example\n * const pattern = sequence('a', ['b', 'c']);\n * const events = pattern.queryArc(0, 1);\n */", + "comment": "/**\n * query haps insude the tiven time span\n *\n * @param {Fraction | number} begin from time\n * @param {Fraction | number} end to time\n * @returns Hap[]\n * @example\n * const pattern = sequence('a', ['b', 'c']);\n * const haps = pattern.queryArc(0, 1);\n */", "meta": { "range": [ - 1642, - 1728 + 1737, + 1823 ], "filename": "pattern.mjs", - "lineno": 36, + "lineno": 37, "columnno": 2, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100001852", + "id": "astnode100005746", "name": "Pattern#queryArc", "type": "MethodDefinition", "paramnames": [ @@ -62,7 +1411,7 @@ "": null } }, - "description": "

query events insude the tiven time span

", + "description": "

query haps insude the tiven time span

", "params": [ { "type": { @@ -91,29 +1440,29 @@ } ], "examples": [ - "const pattern = sequence('a', ['b', 'c']);\nconst events = pattern.queryArc(0, 1);" + "const pattern = sequence('a', ['b', 'c']);\nconst haps = pattern.queryArc(0, 1);" ], "name": "queryArc", "longname": "Pattern#queryArc", "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000100", + "___id": "T000002R000533", "___s": true }, { - "comment": "/**\n * Returns a new pattern, with queries split at cycle boundaries. This makes\n * some calculations easier to express, as all events are then constrained to\n * happen within a cycle.\n * @returns Pattern\n */", + "comment": "/**\n * Returns a new pattern, with queries split at cycle boundaries. This makes\n * some calculations easier to express, as all haps are then constrained to\n * happen within a cycle.\n * @returns Pattern\n */", "meta": { "range": [ - 1953, - 2154 + 2046, + 2247 ], "filename": "pattern.mjs", - "lineno": 46, + "lineno": 47, "columnno": 2, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100001869", + "id": "astnode100005763", "name": "Pattern#_splitQueries", "type": "MethodDefinition", "paramnames": [] @@ -122,7 +1471,7 @@ "": null } }, - "description": "

Returns a new pattern, with queries split at cycle boundaries. This makes\nsome calculations easier to express, as all events are then constrained to\nhappen within a cycle.

", + "description": "

Returns a new pattern, with queries split at cycle boundaries. This makes\nsome calculations easier to express, as all haps are then constrained to\nhappen within a cycle.

", "returns": [ { "description": "

Pattern

" @@ -134,22 +1483,22 @@ "memberof": "Pattern", "scope": "instance", "params": [], - "___id": "T000002R000101", + "___id": "T000002R000534", "___s": true }, { "comment": "/**\n * Returns a new pattern, where the given function is applied to the query\n * timespan before passing it to the original pattern.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", "meta": { "range": [ - 2376, - 2470 + 2469, + 2563 ], "filename": "pattern.mjs", - "lineno": 60, + "lineno": 61, "columnno": 2, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100001909", + "id": "astnode100005803", "name": "Pattern#withQuerySpan", "type": "MethodDefinition", "paramnames": [ @@ -182,22 +1531,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000104", + "___id": "T000002R000537", "___s": true }, { - "comment": "/**\n * As with {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to both the\n * begin and end time of the query timespan.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", + "comment": "/**\n * As with {@link Pattern#withQuerySpan}, but the function is applied to both the\n * begin and end time of the query timespan.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", "meta": { "range": [ - 2704, - 2823 + 2782, + 2901 ], "filename": "pattern.mjs", - "lineno": 70, - "columnno": 3, - "path": "/Users/felix/projects/strudel/packages/core", + "lineno": 71, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100001928", + "id": "astnode100005822", "name": "Pattern#withQueryTime", "type": "MethodDefinition", "paramnames": [ @@ -208,7 +1557,7 @@ "": null } }, - "description": "

As with {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to both the\nbegin and end time of the query timespan.

", + "description": "

As with {@link Pattern#withQuerySpan}, but the function is applied to both the\nbegin and end time of the query timespan.

", "params": [ { "type": { @@ -230,23 +1579,23 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000105", + "___id": "T000002R000538", "___s": true }, { - "comment": "/**\n * Similar to {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to the timespans\n * of all haps returned by pattern queries (both `part` timespans, and where\n * present, `whole` timespans).\n * @param {Function} func \n * @returns Pattern\n */", + "comment": "/**\n * Similar to {@link Pattern#withQuerySpan}, but the function is applied to the timespans\n * of all haps returned by pattern queries (both `part` timespans, and where\n * present, `whole` timespans).\n * @param {Function} func\n * @returns Pattern\n */", "meta": { "range": [ - 3109, - 3221 + 3172, + 3282 ], "filename": "pattern.mjs", - "lineno": 81, + "lineno": 82, "columnno": 2, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100001953", - "name": "Pattern#withEventSpan", + "id": "astnode100005847", + "name": "Pattern#withHapSpan", "type": "MethodDefinition", "paramnames": [ "func" @@ -256,7 +1605,7 @@ "": null } }, - "description": "

Similar to {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to the timespans\nof all haps returned by pattern queries (both part timespans, and where\npresent, whole timespans).

", + "description": "

Similar to {@link Pattern#withQuerySpan}, but the function is applied to the timespans\nof all haps returned by pattern queries (both part timespans, and where\npresent, whole timespans).

", "params": [ { "type": { @@ -272,28 +1621,28 @@ "description": "

Pattern

" } ], - "name": "withEventSpan", - "longname": "Pattern#withEventSpan", + "name": "withHapSpan", + "longname": "Pattern#withHapSpan", "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000106", + "___id": "T000002R000539", "___s": true }, { - "comment": "/**\n * As with {@link Pattern#withEventSpan|withEventSpan}, but the function is applied to both the\n * begin and end time of the hap timespans.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", + "comment": "/**\n * As with {@link Pattern#withHapSpan}, but the function is applied to both the\n * begin and end time of the hap timespans.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", "meta": { "range": [ - 3454, - 3654 + 3498, + 3581 ], "filename": "pattern.mjs", - "lineno": 91, - "columnno": 3, - "path": "/Users/felix/projects/strudel/packages/core", + "lineno": 92, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100001978", - "name": "Pattern#withEventTime", + "id": "astnode100005872", + "name": "Pattern#withHapTime", "type": "MethodDefinition", "paramnames": [ "func" @@ -303,7 +1652,7 @@ "": null } }, - "description": "

As with {@link Pattern#withEventSpan|withEventSpan}, but the function is applied to both the\nbegin and end time of the hap timespans.

", + "description": "

As with {@link Pattern#withHapSpan}, but the function is applied to both the\nbegin and end time of the hap timespans.

", "params": [ { "type": { @@ -320,27 +1669,307 @@ "description": "

Pattern

" } ], - "name": "withEventTime", - "longname": "Pattern#withEventTime", + "name": "withHapTime", + "longname": "Pattern#withHapTime", "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000107", + "___id": "T000002R000540", "___s": true }, { - "comment": "/**\n * Returns a new pattern, with the function applied to the value of\n * each event. It has the alias {@link Pattern#fmap|fmap}.\n * @param {Function} func \n * @returns Pattern\n */", + "comment": "/**\n * Returns a new pattern with the given function applied to the list of haps returned by every query.\n * @param {Function} func\n * @returns Pattern\n */", "meta": { "range": [ - 5493, - 5602 + 3751, + 3832 ], "filename": "pattern.mjs", - "lineno": 160, + "lineno": 101, "columnno": 2, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100002295", + "id": "astnode100005889", + "name": "Pattern#_withHaps", + "type": "MethodDefinition", + "paramnames": [ + "func" + ] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern with the given function applied to the list of haps returned by every query.

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "name": "func" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_withHaps", + "longname": "Pattern#_withHaps", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000541", + "___s": true + }, + { + "comment": "/**\n * As with {@link Pattern#_withHaps}, but applies the function to every hap, rather than every list of haps.\n * @param {Function} func\n * @returns Pattern\n */", + "meta": { + "range": [ + 4009, + 4082 + ], + "filename": "pattern.mjs", + "lineno": 110, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100005906", + "name": "Pattern#_withHap", + "type": "MethodDefinition", + "paramnames": [ + "func" + ] + }, + "vars": { + "": null + } + }, + "description": "

As with {@link Pattern#_withHaps}, but applies the function to every hap, rather than every list of haps.

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "name": "func" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_withHap", + "longname": "Pattern#_withHap", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000542", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern with the context field set to every hap set to the given value.\n * @param {*} context\n * @returns Pattern\n */", + "meta": { + "range": [ + 4235, + 4321 + ], + "filename": "pattern.mjs", + "lineno": 119, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100005923", + "name": "Pattern#_setContext", + "type": "MethodDefinition", + "paramnames": [ + "context" + ] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern with the context field set to every hap set to the given value.

", + "params": [ + { + "type": { + "names": [ + "*" + ] + }, + "name": "context" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_setContext", + "longname": "Pattern#_setContext", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000543", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern with the given function applied to the context field of every hap.\n * @param {Function} func\n * @returns Pattern\n */", + "meta": { + "range": [ + 4481, + 4575 + ], + "filename": "pattern.mjs", + "lineno": 128, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100005940", + "name": "Pattern#_withContext", + "type": "MethodDefinition", + "paramnames": [ + "func" + ] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern with the given function applied to the context field of every hap.

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "name": "func" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_withContext", + "longname": "Pattern#_withContext", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000544", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern with the context field of every hap set to an empty object.\n * @returns Pattern\n */", + "meta": { + "range": [ + 4700, + 4776 + ], + "filename": "pattern.mjs", + "lineno": 136, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100005961", + "name": "Pattern#_stripContext", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern with the context field of every hap set to an empty object.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_stripContext", + "longname": "Pattern#_stripContext", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000545", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern with the given location information added to the\n * context of every hap.\n * @param {Number} start\n * @param {Number} end\n * @returns Pattern\n */", + "meta": { + "range": [ + 4969, + 5321 + ], + "filename": "pattern.mjs", + "lineno": 147, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100005977", + "name": "Pattern#withLocation", + "type": "MethodDefinition", + "paramnames": [ + "start", + "end" + ] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern with the given location information added to the\ncontext of every hap.

", + "params": [ + { + "type": { + "names": [ + "Number" + ] + }, + "name": "start" + }, + { + "type": { + "names": [ + "Number" + ] + }, + "name": "end" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "withLocation", + "longname": "Pattern#withLocation", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000546", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern, with the function applied to the value of\n * each hap. It has the alias {@link Pattern#fmap}.\n * @param {Function} func\n * @returns Pattern\n */", + "meta": { + "range": [ + 6336, + 6445 + ], + "filename": "pattern.mjs", + "lineno": 190, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100006189", "name": "Pattern#withValue", "type": "MethodDefinition", "paramnames": [ @@ -351,7 +1980,7 @@ "": null } }, - "description": "

Returns a new pattern, with the function applied to the value of\neach event. It has the alias {@link Pattern#fmap|fmap}.

", + "description": "

Returns a new pattern, with the function applied to the value of\neach hap. It has the alias {@link Pattern#fmap}.

", "params": [ { "type": { @@ -372,22 +2001,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000147", + "___id": "T000002R000580", "___s": true }, { - "comment": "/**\n * see {@link Pattern#withValue|withValue}\n */", + "comment": "/**\n * see {@link Pattern#withValue}\n */", "meta": { "range": [ - 5664, - 5713 + 6496, + 6545 ], "filename": "pattern.mjs", - "lineno": 167, - "columnno": 3, - "path": "/Users/felix/projects/strudel/packages/core", + "lineno": 197, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100002320", + "id": "astnode100006214", "name": "Pattern#fmap", "type": "MethodDefinition", "paramnames": [ @@ -398,29 +2027,160 @@ "": null } }, - "description": "

see {@link Pattern#withValue|withValue}

", + "description": "

see {@link Pattern#withValue}

", "name": "fmap", "longname": "Pattern#fmap", "kind": "function", "memberof": "Pattern", "scope": "instance", "params": [], - "___id": "T000002R000148", + "___id": "T000002R000581", + "___s": true + }, + { + "comment": "/**\n * Returns a new Pattern, which only returns haps that meet the given test.\n * @param {Function} hap_test - a function which returns false for haps to be removed from the pattern\n * @returns Pattern\n */", + "meta": { + "range": [ + 6766, + 6864 + ], + "filename": "pattern.mjs", + "lineno": 206, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100006225", + "name": "Pattern#_filterHaps", + "type": "MethodDefinition", + "paramnames": [ + "hap_test" + ] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new Pattern, which only returns haps that meet the given test.

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "description": "

a function which returns false for haps to be removed from the pattern

", + "name": "hap_test" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_filterHaps", + "longname": "Pattern#_filterHaps", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000582", + "___s": true + }, + { + "comment": "/**\n * As with {@link Pattern#_filterHaps}, but the function is applied to values\n * inside haps.\n * @param {Function} value_test\n * @returns Pattern\n */", + "meta": { + "range": [ + 7034, + 7158 + ], + "filename": "pattern.mjs", + "lineno": 216, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100006244", + "name": "Pattern#_filterValues", + "type": "MethodDefinition", + "paramnames": [ + "value_test" + ] + }, + "vars": { + "": null + } + }, + "description": "

As with {@link Pattern#_filterHaps}, but the function is applied to values\ninside haps.

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "name": "value_test" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_filterValues", + "longname": "Pattern#_filterValues", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000583", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern, with haps containing undefined values removed from\n * query results.\n * @returns Pattern\n */", + "meta": { + "range": [ + 7295, + 7378 + ], + "filename": "pattern.mjs", + "lineno": 225, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100006269", + "name": "Pattern#_removeUndefineds", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern, with haps containing undefined values removed from\nquery results.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_removeUndefineds", + "longname": "Pattern#_removeUndefineds", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000584", "___s": true }, { "comment": "/**\n * Returns a new pattern, with all haps without onsets filtered out. A hap\n * with an onset is one with a `whole` timespan that begins at the same time\n * as its `part` timespan.\n * @returns Pattern\n */", "meta": { "range": [ - 6260, - 6532 + 7601, + 7867 ], "filename": "pattern.mjs", - "lineno": 189, - "columnno": 3, - "path": "/Users/felix/projects/strudel/packages/core", + "lineno": 235, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100002389", + "id": "astnode100006283", "name": "Pattern#onsetsOnly", "type": "MethodDefinition", "paramnames": [] @@ -441,22 +2201,58 @@ "memberof": "Pattern", "scope": "instance", "params": [], - "___id": "T000002R000152", + "___id": "T000002R000585", "___s": true }, { - "comment": "/**\n * When this method is called on a pattern of functions, it matches its haps\n * with those in the given pattern of values. A new pattern is returned, with\n * each matching value applied to the corresponding function. \n *\n * In this `appBoth` variant, where timespans of the function and value haps\n * are not the same but do intersect, the resulting hap has a timespan of the\n * intersection. This applies to both the part and the whole timespan.\n * @param {Pattern} pat_val \n * @returns Pattern\n */", + "comment": "/**\n * Returns a new pattern, with 'continuous' haps (those without 'whole'\n * timespans) removed from query results.\n * @returns Pattern\n */", "meta": { "range": [ - 8156, - 8437 + 8023, + 8158 ], "filename": "pattern.mjs", - "lineno": 239, + "lineno": 247, "columnno": 2, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100002525", + "id": "astnode100006298", + "name": "Pattern#discreteOnly", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern, with 'continuous' haps (those without 'whole'\ntimespans) removed from query results.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "discreteOnly", + "longname": "Pattern#discreteOnly", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000586", + "___s": true + }, + { + "comment": "/**\n * When this method is called on a pattern of functions, it matches its haps\n * with those in the given pattern of values. A new pattern is returned, with\n * each matching value applied to the corresponding function.\n *\n * In this `appBoth` variant, where timespans of the function and value haps\n * are not the same but do intersect, the resulting hap has a timespan of the\n * intersection. This applies to both the part and the whole timespan.\n * @param {Pattern} pat_val\n * @returns Pattern\n */", + "meta": { + "range": [ + 9601, + 9882 + ], + "filename": "pattern.mjs", + "lineno": 290, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100006419", "name": "Pattern#appBoth", "type": "MethodDefinition", "paramnames": [ @@ -488,22 +2284,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000161", + "___id": "T000002R000594", "___s": true }, { - "comment": "/**\n * As with {@link Pattern#appBoth|appBoth}, but the `whole` timespan is not the intersection,\n * but the timespan from the function of patterns that this method is called\n * on. In practice, this means that the pattern structure, including onsets,\n * are preserved from the pattern of functions (often referred to as the left\n * hand or inner pattern).\n * @param {Pattern} pat_val \n * @returns Pattern\n */", + "comment": "/**\n * As with {@link Pattern#appBoth}, but the `whole` timespan is not the intersection,\n * but the timespan from the function of patterns that this method is called\n * on. In practice, this means that the pattern structure, including onsets,\n * are preserved from the pattern of functions (often referred to as the left\n * hand or inner pattern).\n * @param {Pattern} pat_val\n * @returns Pattern\n */", "meta": { "range": [ - 8869, - 9617 + 10305, + 11049 ], "filename": "pattern.mjs", - "lineno": 259, + "lineno": 310, "columnno": 2, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100002561", + "id": "astnode100006455", "name": "Pattern#appLeft", "type": "MethodDefinition", "paramnames": [ @@ -514,7 +2310,7 @@ "": null } }, - "description": "

As with {@link Pattern#appBoth|appBoth}, but the whole timespan is not the intersection,\nbut the timespan from the function of patterns that this method is called\non. In practice, this means that the pattern structure, including onsets,\nare preserved from the pattern of functions (often referred to as the left\nhand or inner pattern).

", + "description": "

As with {@link Pattern#appBoth}, but the whole timespan is not the intersection,\nbut the timespan from the function of patterns that this method is called\non. In practice, this means that the pattern structure, including onsets,\nare preserved from the pattern of functions (often referred to as the left\nhand or inner pattern).

", "params": [ { "type": { @@ -535,22 +2331,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000163", + "___id": "T000002R000596", "___s": true }, { - "comment": "/**\n * As with {@link Pattern#appLeft|appLeft}, but `whole` timespans are instead taken from the\n * pattern of values, i.e. structure is preserved from the right hand/outer\n * pattern.\n * @param {Pattern} pat_val \n * @returns Pattern\n */", + "comment": "/**\n * As with {@link Pattern#appLeft}, but `whole` timespans are instead taken from the\n * pattern of values, i.e. structure is preserved from the right hand/outer\n * pattern.\n * @param {Pattern} pat_val\n * @returns Pattern\n */", "meta": { "range": [ - 9873, - 10618 + 11296, + 12041 ], "filename": "pattern.mjs", - "lineno": 289, + "lineno": 340, "columnno": 2, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100002671", + "id": "astnode100006565", "name": "Pattern#appRight", "type": "MethodDefinition", "paramnames": [ @@ -561,7 +2357,7 @@ "": null } }, - "description": "

As with {@link Pattern#appLeft|appLeft}, but whole timespans are instead taken from the\npattern of values, i.e. structure is preserved from the right hand/outer\npattern.

", + "description": "

As with {@link Pattern#appLeft}, but whole timespans are instead taken from the\npattern of values, i.e. structure is preserved from the right hand/outer\npattern.

", "params": [ { "type": { @@ -582,22 +2378,679 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000175", + "___id": "T000002R000608", + "___s": true + }, + { + "comment": "/**\n * Queries the pattern for the first cycle, returning Haps. Mainly of use when\n * debugging a pattern.\n * @param {Boolean} with_context - set to true, otherwise the context field\n * will be stripped from the resulting haps.\n * @returns [Hap]\n */", + "meta": { + "range": [ + 12309, + 12508 + ], + "filename": "pattern.mjs", + "lineno": 370, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100006675", + "name": "Pattern#firstCycle", + "type": "MethodDefinition", + "paramnames": [ + "with_context" + ] + }, + "vars": { + "": null + } + }, + "description": "

Queries the pattern for the first cycle, returning Haps. Mainly of use when\ndebugging a pattern.

", + "params": [ + { + "type": { + "names": [ + "Boolean" + ] + }, + "description": "

set to true, otherwise the context field\nwill be stripped from the resulting haps.

", + "name": "with_context", + "defaultvalue": false + } + ], + "returns": [ + { + "description": "

[Hap]

" + } + ], + "name": "firstCycle", + "longname": "Pattern#firstCycle", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000620", + "___s": true + }, + { + "comment": "/**\n * Accessor for a list of values returned by querying the first cycle.\n */", + "meta": { + "range": [ + 12597, + 12680 + ], + "filename": "pattern.mjs", + "lineno": 381, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100006712", + "name": "Pattern#_firstCycleValues", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Accessor for a list of values returned by querying the first cycle.

", + "name": "_firstCycleValues", + "longname": "Pattern#_firstCycleValues", + "kind": "member", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000623", + "___s": true + }, + { + "comment": "/**\n * More human-readable version of the {@link Pattern#_firstCycleValues} accessor.\n */", + "meta": { + "range": [ + 12780, + 12944 + ], + "filename": "pattern.mjs", + "lineno": 388, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100006729", + "name": "Pattern#_showFirstCycle", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

More human-readable version of the {@link Pattern#_firstCycleValues} accessor.

", + "name": "_showFirstCycle", + "longname": "Pattern#_showFirstCycle", + "kind": "member", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000624", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern, which returns haps sorted in temporal order. Mainly\n * of use when comparing two patterns for equality, in tests.\n * @returns Pattern\n */", + "meta": { + "range": [ + 13126, + 13401 + ], + "filename": "pattern.mjs", + "lineno": 399, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100006767", + "name": "Pattern#_sortHapsByPart", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern, which returns haps sorted in temporal order. Mainly\nof use when comparing two patterns for equality, in tests.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_sortHapsByPart", + "longname": "Pattern#_sortHapsByPart", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000625", + "___s": true + }, + { + "comment": "/**\n * Assumes a numerical pattern. Returns a new pattern with all values rounded\n * to the nearest integer.\n * @returns Pattern\n */", + "meta": { + "range": [ + 15309, + 15378 + ], + "filename": "pattern.mjs", + "lineno": 472, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007154", + "name": "Pattern#round", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Assumes a numerical pattern. Returns a new pattern with all values rounded\nto the nearest integer.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "round", + "longname": "Pattern#round", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000644", + "___s": true + }, + { + "comment": "/**\n * Assumes a numerical pattern. Returns a new pattern with all values set to\n * their mathematical floor. E.g. `3.7` replaced with to `3`, and `-4.2`\n * replaced with `-5`.\n * @returns Pattern\n */", + "meta": { + "range": [ + 15595, + 15664 + ], + "filename": "pattern.mjs", + "lineno": 482, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007173", + "name": "Pattern#floor", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Assumes a numerical pattern. Returns a new pattern with all values set to\ntheir mathematical floor. E.g. 3.7 replaced with to 3, and -4.2\nreplaced with -5.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "floor", + "longname": "Pattern#floor", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000645", + "___s": true + }, + { + "comment": "/**\n * Assumes a numerical pattern. Returns a new pattern with all values set to\n * their mathematical ceiling. E.g. `3.2` replaced with `4`, and `-4.2`\n * replaced with `-4`.\n * @returns Pattern\n */", + "meta": { + "range": [ + 15880, + 15947 + ], + "filename": "pattern.mjs", + "lineno": 492, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007192", + "name": "Pattern#ceil", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Assumes a numerical pattern. Returns a new pattern with all values set to\ntheir mathematical ceiling. E.g. 3.2 replaced with 4, and -4.2\nreplaced with -4.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "ceil", + "longname": "Pattern#ceil", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000646", + "___s": true + }, + { + "comment": "/**\n * Assumes a numerical pattern, containing unipolar values in the range 0 ..\n * 1. Returns a new pattern with values scaled to the bipolar range -1 .. 1\n * @returns Pattern\n */", + "meta": { + "range": [ + 16142, + 16200 + ], + "filename": "pattern.mjs", + "lineno": 501, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007211", + "name": "Pattern#_toBipolar", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Assumes a numerical pattern, containing unipolar values in the range 0 ..

\n
    \n
  1. Returns a new pattern with values scaled to the bipolar range -1 .. 1
  2. \n
", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_toBipolar", + "longname": "Pattern#_toBipolar", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000647", + "___s": true + }, + { + "comment": "/**\n * Assumes a numerical pattern, containing bipolar values in the range -1 ..\n * 1. Returns a new pattern with values scaled to the unipolar range 0 .. 1\n * @returns Pattern\n */", + "meta": { + "range": [ + 16395, + 16457 + ], + "filename": "pattern.mjs", + "lineno": 510, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007227", + "name": "Pattern#_fromBipolar", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Assumes a numerical pattern, containing bipolar values in the range -1 ..

\n
    \n
  1. Returns a new pattern with values scaled to the unipolar range 0 .. 1
  2. \n
", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_fromBipolar", + "longname": "Pattern#_fromBipolar", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000648", + "___s": true + }, + { + "comment": "/**\n * Assumes a numerical pattern, containing unipolar values in the range 0 ..\n * 1. Returns a new pattern with values scaled to the given min/max range.\n * @param {Number} min\n * @param {Number} max\n * @returns Pattern\n */", + "meta": { + "range": [ + 16701, + 16763 + ], + "filename": "pattern.mjs", + "lineno": 521, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007243", + "name": "Pattern#range", + "type": "MethodDefinition", + "paramnames": [ + "min", + "max" + ] + }, + "vars": { + "": null + } + }, + "description": "

Assumes a numerical pattern, containing unipolar values in the range 0 ..

\n
    \n
  1. Returns a new pattern with values scaled to the given min/max range.
  2. \n
", + "params": [ + { + "type": { + "names": [ + "Number" + ] + }, + "name": "min" + }, + { + "type": { + "names": [ + "Number" + ] + }, + "name": "max" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "range", + "longname": "Pattern#range", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000649", + "___s": true + }, + { + "comment": "/**\n * Assumes a numerical pattern, containing unipolar values in the range 0 ..\n * 1. Returns a new pattern with values scaled to the given min/max range,\n * following an exponential curve.\n * @param {Number} min\n * @param {Number} max\n * @returns Pattern\n */", + "meta": { + "range": [ + 17044, + 17134 + ], + "filename": "pattern.mjs", + "lineno": 533, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007261", + "name": "Pattern#rangex", + "type": "MethodDefinition", + "paramnames": [ + "min", + "max" + ] + }, + "vars": { + "": null + } + }, + "description": "

Assumes a numerical pattern, containing unipolar values in the range 0 ..

\n
    \n
  1. Returns a new pattern with values scaled to the given min/max range,\nfollowing an exponential curve.
  2. \n
", + "params": [ + { + "type": { + "names": [ + "Number" + ] + }, + "name": "min" + }, + { + "type": { + "names": [ + "Number" + ] + }, + "name": "max" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "rangex", + "longname": "Pattern#rangex", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000650", + "___s": true + }, + { + "comment": "/**\n * Assumes a numerical pattern, containing bipolar values in the range -1 ..\n * 1. Returns a new pattern with values scaled to the given min/max range.\n * @param {Number} min\n * @param {Number} max\n * @returns Pattern\n */", + "meta": { + "range": [ + 17378, + 17448 + ], + "filename": "pattern.mjs", + "lineno": 544, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007288", + "name": "Pattern#range2", + "type": "MethodDefinition", + "paramnames": [ + "min", + "max" + ] + }, + "vars": { + "": null + } + }, + "description": "

Assumes a numerical pattern, containing bipolar values in the range -1 ..

\n
    \n
  1. Returns a new pattern with values scaled to the given min/max range.
  2. \n
", + "params": [ + { + "type": { + "names": [ + "Number" + ] + }, + "name": "min" + }, + { + "type": { + "names": [ + "Number" + ] + }, + "name": "max" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "range2", + "longname": "Pattern#range2", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000651", + "___s": true + }, + { + "comment": "/**\n *\n * @param {...any} funcs\n * @returns Pattern\n * @example\n * \"<[0 1 2 0]!2 [2 3 4 ~]!2 [[4 5] [4 3] 2 [0 ~]]!2 [0 -3 0 ~]!2>\"\n * .layer(\n * x=>x,\n * x=>x.add(7).late(2),\n * x=>x.add(14).late(4),\n * x=>x.add(21).late(6),\n * )\n * .slow(3)\n * .scale('C2 major')\n * .tone((await piano()).toDestination())\n */", + "meta": { + "range": [ + 21980, + 22055 + ], + "filename": "pattern.mjs", + "lineno": 700, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100007825", + "name": "Pattern#layer", + "type": "MethodDefinition", + "paramnames": [ + "funcs" + ] + }, + "vars": { + "": null + } + }, + "params": [ + { + "type": { + "names": [ + "any" + ] + }, + "variable": true, + "name": "funcs" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "examples": [ + "\"<[0 1 2 0]!2 [2 3 4 ~]!2 [[4 5] [4 3] 2 [0 ~]]!2 [0 -3 0 ~]!2>\"\n.layer(\n x=>x,\n x=>x.add(7).late(2),\n x=>x.add(14).late(4),\n x=>x.add(21).late(6),\n)\n.slow(3)\n.scale('C2 major')\n.tone((await piano()).toDestination())" + ], + "name": "layer", + "longname": "Pattern#layer", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000683", + "___s": true + }, + { + "comment": "/**\n * Speed up a pattern by the given factor.\n *\n * @name fast\n * @memberof Pattern\n * @param {number | Pattern} factor speed up factor\n * @returns Pattern\n * @example\n * seq(e5, b4, d5, c5).fast(2)\n */", + "meta": { + "filename": "pattern.mjs", + "lineno": 750, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Speed up a pattern by the given factor.

", + "name": "fast", + "memberof": "Pattern", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

speed up factor

", + "name": "factor" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "examples": [ + "seq(e5, b4, d5, c5).fast(2)" + ], + "scope": "static", + "longname": "Pattern.fast", + "kind": "member", + "___id": "T000002R000700", + "___s": true + }, + { + "comment": "/**\n * Slow down a pattern over the given number of cycles.\n *\n * @name slow\n * @memberof Pattern\n * @param {number | Pattern} factor slow down factor\n * @returns Pattern\n * @example\n * seq(e5, b4, d5, c5).slow(2)\n */", + "meta": { + "filename": "pattern.mjs", + "lineno": 765, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": {} + }, + "description": "

Slow down a pattern over the given number of cycles.

", + "name": "slow", + "memberof": "Pattern", + "params": [ + { + "type": { + "names": [ + "number", + "Pattern" + ] + }, + "description": "

slow down factor

", + "name": "factor" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "examples": [ + "seq(e5, b4, d5, c5).slow(2)" + ], + "scope": "static", + "longname": "Pattern.slow", + "kind": "member", + "___id": "T000002R000703", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern where every other cycle is played once, twice as\n * fast, and offset in time by one quarter of a cycle. Creates a kind of\n * breakbeat feel.\n * @returns Pattern\n */", + "meta": { + "range": [ + 28139, + 28235 + ], + "filename": "pattern.mjs", + "lineno": 919, + "columnno": 2, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100008779", + "name": "Pattern#brak", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern where every other cycle is played once, twice as\nfast, and offset in time by one quarter of a cycle. Creates a kind of\nbreakbeat feel.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "brak", + "longname": "Pattern#brak", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000750", "___s": true }, { "comment": "/** A discrete value that repeats once per cycle:\n *\n * @param {any} value - The value to repeat\n * @returns {Pattern}\n * @example\n * pure('e4')\n */", "meta": { "range": [ - 31120, - 31324 + 35996, + 36200 ], "filename": "pattern.mjs", - "lineno": 1044, + "lineno": 1217, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100006158", + "id": "astnode100010127", "name": "exports.pure", "type": "FunctionDeclaration", "paramnames": [ @@ -633,22 +3086,22 @@ "longname": "pure", "kind": "function", "scope": "global", - "___id": "T000002R000429", + "___id": "T000002R000868", "___s": true }, { "comment": "/** The given items are played at the same time at the same length:\n *\n * @param {...any} items - The items to stack\n * @return {Pattern}\n * @example\n * stack(g3, b3, [e4, d4])\n */", "meta": { "range": [ - 31837, - 32110 + 36713, + 36986 ], "filename": "pattern.mjs", - "lineno": 1071, + "lineno": 1244, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100006219", + "id": "astnode100010188", "name": "exports.stack", "type": "FunctionDeclaration", "paramnames": [ @@ -685,22 +3138,22 @@ "longname": "stack", "kind": "function", "scope": "global", - "___id": "T000002R000436", + "___id": "T000002R000875", "___s": true }, { "comment": "/** Concatenation: combines a list of patterns, switching between them successively, one per cycle:\n *\n * synonyms: {@link cat}\n *\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n * @example\n * slowcat(e5, b4, [d5, c5])\n *\n */", "meta": { "range": [ - 32364, - 33277 + 37240, + 38151 ], "filename": "pattern.mjs", - "lineno": 1088, + "lineno": 1261, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100006269", + "id": "astnode100010238", "name": "exports.slowcat", "type": "FunctionDeclaration", "paramnames": [ @@ -737,22 +3190,22 @@ "longname": "slowcat", "kind": "function", "scope": "global", - "___id": "T000002R000440", + "___id": "T000002R000879", "___s": true }, { "comment": "/** Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n */", "meta": { "range": [ - 33503, - 33775 + 38377, + 38649 ], "filename": "pattern.mjs", - "lineno": 1113, + "lineno": 1286, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100006396", + "id": "astnode100010365", "name": "exports.slowcatPrime", "type": "FunctionDeclaration", "paramnames": [ @@ -786,22 +3239,22 @@ "longname": "slowcatPrime", "kind": "function", "scope": "global", - "___id": "T000002R000448", + "___id": "T000002R000887", "___s": true }, { - "comment": "/** Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle\n *\n * Synonyms: {@link seq}, {@link sequence}\n *\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n * @example\n * fastcat(e5, b4, [d5, c5])\n * sequence(e5, b4, [d5, c5])\n * seq(e5, b4, [d5, c5])\n */", + "comment": "/** Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle\n *\n * Synonyms: {@link seq}, {@link sequence}\n *\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n * @example\n * fastcat(e5, b4, [d5, c5])\n * // sequence(e5, b4, [d5, c5])\n * // seq(e5, b4, [d5, c5])\n */", "meta": { "range": [ - 34097, - 34179 + 38977, + 39059 ], "filename": "pattern.mjs", - "lineno": 1134, + "lineno": 1307, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100006451", + "id": "astnode100010420", "name": "exports.fastcat", "type": "FunctionDeclaration", "paramnames": [ @@ -832,28 +3285,28 @@ } ], "examples": [ - "fastcat(e5, b4, [d5, c5])\nsequence(e5, b4, [d5, c5])\nseq(e5, b4, [d5, c5])" + "fastcat(e5, b4, [d5, c5])\n// sequence(e5, b4, [d5, c5])\n// seq(e5, b4, [d5, c5])" ], "name": "fastcat", "longname": "fastcat", "kind": "function", "scope": "global", - "___id": "T000002R000454", + "___id": "T000002R000893", "___s": true }, { "comment": "/** See {@link slowcat} */", "meta": { "range": [ - 34208, - 34267 + 39088, + 39147 ], "filename": "pattern.mjs", - "lineno": 1139, + "lineno": 1312, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100006468", + "id": "astnode100010437", "name": "exports.cat", "type": "FunctionDeclaration", "paramnames": [ @@ -866,22 +3319,22 @@ "longname": "cat", "kind": "function", "scope": "global", - "___id": "T000002R000456", + "___id": "T000002R000895", "___s": true }, { "comment": "/** Like {@link fastcat}, but where each step has a temporal weight:\n * @param {...Array} items - The items to concatenate\n * @return {Pattern}\n * @example\n * timeCat([3,e3],[1, g3])\n */", "meta": { "range": [ - 34456, - 34815 + 39336, + 39695 ], "filename": "pattern.mjs", - "lineno": 1149, + "lineno": 1322, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100006479", + "id": "astnode100010448", "name": "exports.timeCat", "type": "FunctionDeclaration", "paramnames": [ @@ -918,22 +3371,22 @@ "longname": "timeCat", "kind": "function", "scope": "global", - "___id": "T000002R000458", + "___id": "T000002R000897", "___s": true }, { "comment": "/** See {@link fastcat} */", "meta": { "range": [ - 34844, - 34908 + 39724, + 39788 ], "filename": "pattern.mjs", - "lineno": 1162, + "lineno": 1335, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100006565", + "id": "astnode100010534", "name": "exports.sequence", "type": "FunctionDeclaration", "paramnames": [ @@ -946,22 +3399,22 @@ "longname": "sequence", "kind": "function", "scope": "global", - "___id": "T000002R000465", + "___id": "T000002R000904", "___s": true }, { "comment": "/** See {@link fastcat} */", "meta": { "range": [ - 34937, - 34996 + 39817, + 39876 ], "filename": "pattern.mjs", - "lineno": 1167, + "lineno": 1340, "columnno": 0, - "path": "/Users/felix/projects/strudel/packages/core", + "path": "/home/felix/projects/strudel/packages/core", "code": { - "id": "astnode100006576", + "id": "astnode100010545", "name": "exports.seq", "type": "FunctionDeclaration", "paramnames": [ @@ -974,63 +3427,448 @@ "longname": "seq", "kind": "function", "scope": "global", - "___id": "T000002R000467", + "___id": "T000002R000906", + "___s": true + }, + { + "comment": "/**\n * A sawtooth signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * \"c3 [eb3,g3] g2 [g3,bb3]\".legato(saw.slow(4))\n * @example\n * saw.range(0,8).segment(8).scale('C major').slow(4)\n *\n */", + "meta": { + "range": [ + 1558, + 1598 + ], + "filename": "signal.mjs", + "lineno": 35, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100011947", + "name": "exports.saw", + "type": "VariableDeclaration" + } + }, + "description": "

A sawtooth signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "\"c3 [eb3,g3] g2 [g3,bb3]\".legato(saw.slow(4))", + "saw.range(0,8).segment(8).scale('C major').slow(4)" + ], + "name": "saw", + "longname": "saw", + "kind": "constant", + "scope": "global", + "___id": "T000002R001036", + "___s": true + }, + { + "comment": "/**\n * A sine signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * sine.segment(16).range(0,15).slow(2).scale('C minor')\n *\n */", + "meta": { + "range": [ + 1841, + 1882 + ], + "filename": "signal.mjs", + "lineno": 48, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100011985", + "name": "exports.sine", + "type": "VariableDeclaration" + } + }, + "description": "

A sine signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "sine.segment(16).range(0,15).slow(2).scale('C minor')" + ], + "name": "sine", + "longname": "sine", + "kind": "constant", + "scope": "global", + "___id": "T000002R001042", + "___s": true + }, + { + "comment": "/**\n * A cosine signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * stack(sine,cosine).segment(16).range(0,15).slow(2).scale('C minor')\n *\n */", + "meta": { + "range": [ + 2040, + 2094 + ], + "filename": "signal.mjs", + "lineno": 59, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100011993", + "name": "exports.cosine", + "type": "VariableDeclaration" + } + }, + "description": "

A cosine signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "stack(sine,cosine).segment(16).range(0,15).slow(2).scale('C minor')" + ], + "name": "cosine", + "longname": "cosine", + "kind": "constant", + "scope": "global", + "___id": "T000002R001044", + "___s": true + }, + { + "comment": "/**\n * A square signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * square.segment(2).range(0,7).scale('C minor')\n *\n */", + "meta": { + "range": [ + 2287, + 2348 + ], + "filename": "signal.mjs", + "lineno": 71, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100012023", + "name": "exports.square", + "type": "VariableDeclaration" + } + }, + "description": "

A square signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "square.segment(2).range(0,7).scale('C minor')" + ], + "name": "square", + "longname": "square", + "kind": "constant", + "scope": "global", + "___id": "T000002R001048", + "___s": true + }, + { + "comment": "/**\n * A triangle signal between 0 and 1.\n *\n * @return {Pattern}\n * @example\n * triangle.segment(2).range(0,7).scale('C minor')\n *\n */", + "meta": { + "range": [ + 2531, + 2569 + ], + "filename": "signal.mjs", + "lineno": 82, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100012048", + "name": "exports.tri", + "type": "VariableDeclaration" + } + }, + "description": "

A triangle signal between 0 and 1.

", + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "triangle.segment(2).range(0,7).scale('C minor')" + ], + "name": "tri", + "longname": "tri", + "kind": "constant", + "scope": "global", + "___id": "T000002R001052", + "___s": true + }, + { + "comment": "/**\n *\n * Sends each hap as an OSC message, which can be picked up by SuperCollider or any other OSC-enabled software.\n *\n * @name osc\n * @memberof Pattern\n * @returns Pattern\n */", + "meta": { + "filename": "osc.mjs", + "lineno": 15, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/osc", + "code": {} + }, + "description": "

Sends each hap as an OSC message, which can be picked up by SuperCollider or any other OSC-enabled software.

", + "name": "osc", + "memberof": "Pattern", + "returns": [ + { + "description": "

Pattern

" + } + ], + "scope": "static", + "longname": "Pattern.osc", + "kind": "member", + "___id": "T000002R002650", + "___s": true + }, + { + "comment": "/**\n * Change the pitch of each value by the given amount. Expects numbers or note strings as values.\n * The amount can be given as a number of semitones or as a string in interval short notation.\n * If you don't care about enharmonic correctness, just use numbers. Otherwise, pass the interval of\n * the form: ST where S is the degree number and T the type of interval with\n *\n * - M = major\n * - m = minor\n * - P = perfect\n * - A = augmented\n * - d = diminished\n *\n * Examples intervals:\n *\n * - 1P = unison\n * - 3M = major third\n * - 3m = minor third\n * - 4P = perfect fourth\n * - 4A = augmented fourth\n * - 5P = perfect fifth\n * - 5d = diminished fifth\n *\n * @param {string | number} amount Either number of semitones or interval string.\n * @returns Pattern\n * @memberof Pattern\n * @name transpose\n * @example\n * \"c2 c3\".fast(2).transpose(\"<0 -2 5 3>\".slow(2)).transpose(0)\n * @example\n * \"c2 c3\".fast(2).transpose(\"<1P -2M 4P 3m>\".slow(2)).transpose(0)\n */", + "meta": { + "filename": "tonal.mjs", + "lineno": 46, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/tonal", + "code": {} + }, + "description": "

Change the pitch of each value by the given amount. Expects numbers or note strings as values.\nThe amount can be given as a number of semitones or as a string in interval short notation.\nIf you don't care about enharmonic correctness, just use numbers. Otherwise, pass the interval of\nthe form: ST where S is the degree number and T the type of interval with

\n
    \n
  • M = major
  • \n
  • m = minor
  • \n
  • P = perfect
  • \n
  • A = augmented
  • \n
  • d = diminished
  • \n
\n

Examples intervals:

\n
    \n
  • 1P = unison
  • \n
  • 3M = major third
  • \n
  • 3m = minor third
  • \n
  • 4P = perfect fourth
  • \n
  • 4A = augmented fourth
  • \n
  • 5P = perfect fifth
  • \n
  • 5d = diminished fifth
  • \n
", + "params": [ + { + "type": { + "names": [ + "string", + "number" + ] + }, + "description": "

Either number of semitones or interval string.

", + "name": "amount" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "memberof": "Pattern", + "name": "transpose", + "examples": [ + "\"c2 c3\".fast(2).transpose(\"<0 -2 5 3>\".slow(2)).transpose(0)", + "\"c2 c3\".fast(2).transpose(\"<1P -2M 4P 3m>\".slow(2)).transpose(0)" + ], + "scope": "static", + "longname": "Pattern.transpose", + "kind": "member", + "___id": "T000002R003717", + "___s": true + }, + { + "comment": "/**\n * Transposes notes inside the scale by the number of steps.\n * Expected to be called on a Pattern which already has a {@link Pattern#scale}\n *\n * @memberof Pattern\n * @name scaleTranspose\n * @param {offset} offset number of steps inside the scale\n * @returns Pattern\n * @example\n * \"-8 [2,4,6]\"\n * .scale('C4 bebop major')\n * .scaleTranspose(\"<0 -1 -2 -3 -4 -5 -6 -4>\")\n */", + "meta": { + "filename": "tonal.mjs", + "lineno": 99, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/tonal", + "code": {} + }, + "description": "

Transposes notes inside the scale by the number of steps.\nExpected to be called on a Pattern which already has a {@link Pattern#scale}

", + "memberof": "Pattern", + "name": "scaleTranspose", + "params": [ + { + "type": { + "names": [ + "offset" + ] + }, + "description": "

number of steps inside the scale

", + "name": "offset" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "examples": [ + "\"-8 [2,4,6]\"\n.scale('C4 bebop major')\n.scaleTranspose(\"<0 -1 -2 -3 -4 -5 -6 -4>\")" + ], + "scope": "static", + "longname": "Pattern.scaleTranspose", + "kind": "member", + "___id": "T000002R003721", + "___s": true + }, + { + "comment": "/**\n * Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like {@link Pattern#scaleTranspose}.\n *\n * The scale name has the form \"TO? N\" wher\n *\n * - T = Tonic\n * - O = Octave (optional, defaults to 3)\n * - N = Name of scale, available names can be found [here](https://github.com/tonaljs/tonal/blob/main/packages/scale-type/data.ts).\n *\n * @memberof Pattern\n * @name scale\n * @param {string} scale Name of scale\n * @returns Pattern\n * @example \n * \"0 2 4 6 4 2\"\n * .scale(seq('C2 major', 'C2 minor').slow(2))\n */", + "meta": { + "filename": "tonal.mjs", + "lineno": 125, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/tonal", + "code": {} + }, + "description": "

Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like {@link Pattern#scaleTranspose}.

\n

The scale name has the form "TO? N" wher

\n
    \n
  • T = Tonic
  • \n
  • O = Octave (optional, defaults to 3)
  • \n
  • N = Name of scale, available names can be found here.
  • \n
", + "memberof": "Pattern", + "name": "scale", + "params": [ + { + "type": { + "names": [ + "string" + ] + }, + "description": "

Name of scale

", + "name": "scale" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "examples": [ + "\"0 2 4 6 4 2\"\n.scale(seq('C2 major', 'C2 minor').slow(2))" + ], + "scope": "static", + "longname": "Pattern.scale", + "kind": "member", + "___id": "T000002R003723", + "___s": true + }, + { + "comment": "/**\n * Turns chord symbols into voicings, using the smoothest voice leading possible.\n * Uses [chord-voicings package](https://github.com/felixroos/chord-voicings#chord-voicings).\n *\n * @name voicings\n * @memberof Pattern\n * @param {range} range note range for possible voicings (optional, defaults to `['F3', 'A4']`)\n * @returns Pattern\n * @example\n * stack(\"\".voicings(), \"\")\n */", + "meta": { + "filename": "voicings.mjs", + "lineno": 34, + "columnno": 0, + "path": "/home/felix/projects/strudel/packages/tonal", + "code": {} + }, + "description": "

Turns chord symbols into voicings, using the smoothest voice leading possible.\nUses chord-voicings package.

", + "name": "voicings", + "memberof": "Pattern", + "params": [ + { + "type": { + "names": [ + "range" + ] + }, + "description": "

note range for possible voicings (optional, defaults to ['F3', 'A4'])

", + "name": "range" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "examples": [ + "stack(\"\".voicings(), \"\")" + ], + "scope": "static", + "longname": "Pattern.voicings", + "kind": "member", + "___id": "T000002R003748", "___s": true }, { "kind": "package", "longname": "package:undefined", "files": [ - "/Users/felix/projects/strudel/packages/core/controls.mjs", - "/Users/felix/projects/strudel/packages/core/drawLine.mjs", - "/Users/felix/projects/strudel/packages/core/euclid.mjs", - "/Users/felix/projects/strudel/packages/core/fraction.mjs", - "/Users/felix/projects/strudel/packages/core/gist.js", - "/Users/felix/projects/strudel/packages/core/hap.mjs", - "/Users/felix/projects/strudel/packages/core/index.mjs", - "/Users/felix/projects/strudel/packages/core/pattern.mjs", - "/Users/felix/projects/strudel/packages/core/signal.mjs", - "/Users/felix/projects/strudel/packages/core/speak.mjs", - "/Users/felix/projects/strudel/packages/core/state.mjs", - "/Users/felix/projects/strudel/packages/core/test/drawLine.test.mjs", - "/Users/felix/projects/strudel/packages/core/test/fraction.test.mjs", - "/Users/felix/projects/strudel/packages/core/test/pattern.test.mjs", - "/Users/felix/projects/strudel/packages/core/test/util.test.mjs", - "/Users/felix/projects/strudel/packages/core/test/value.test.mjs", - "/Users/felix/projects/strudel/packages/core/timespan.mjs", - "/Users/felix/projects/strudel/packages/core/util.mjs", - "/Users/felix/projects/strudel/packages/core/value.mjs", - "/Users/felix/projects/strudel/packages/embed/embed.js", - "/Users/felix/projects/strudel/packages/eval/evaluate.mjs", - "/Users/felix/projects/strudel/packages/eval/shapeshifter.mjs", - "/Users/felix/projects/strudel/packages/eval/test/evaluate.test.mjs", - "/Users/felix/projects/strudel/packages/eval/test/shapeshifter.test.mjs", - "/Users/felix/projects/strudel/packages/midi/midi.mjs", - "/Users/felix/projects/strudel/packages/mini/krill-parser.js", - "/Users/felix/projects/strudel/packages/mini/mini.mjs", - "/Users/felix/projects/strudel/packages/mini/test/mini.test.mjs", - "/Users/felix/projects/strudel/packages/osc/osc.mjs", - "/Users/felix/projects/strudel/packages/osc/server.js", - "/Users/felix/projects/strudel/packages/osc/tidal-sniffer.js", - "/Users/felix/projects/strudel/packages/serial/serial.mjs", - "/Users/felix/projects/strudel/packages/tonal/test/tonal.test.mjs", - "/Users/felix/projects/strudel/packages/tonal/tonal.mjs", - "/Users/felix/projects/strudel/packages/tonal/voicings.mjs", - "/Users/felix/projects/strudel/packages/tone/draw.mjs", - "/Users/felix/projects/strudel/packages/tone/pianoroll.mjs", - "/Users/felix/projects/strudel/packages/tone/test/tone.test.mjs", - "/Users/felix/projects/strudel/packages/tone/tone.mjs", - "/Users/felix/projects/strudel/packages/tone/ui.mjs", - "/Users/felix/projects/strudel/packages/webaudio/clockworker.mjs", - "/Users/felix/projects/strudel/packages/webaudio/index.mjs", - "/Users/felix/projects/strudel/packages/webaudio/scheduler.mjs", - "/Users/felix/projects/strudel/packages/webaudio/webaudio.mjs", - "/Users/felix/projects/strudel/packages/xen/test/xen.test.mjs", - "/Users/felix/projects/strudel/packages/xen/tune.mjs", - "/Users/felix/projects/strudel/packages/xen/tunejs.js", - "/Users/felix/projects/strudel/packages/xen/xen.mjs" + "/home/felix/projects/strudel/packages/core/controls.mjs", + "/home/felix/projects/strudel/packages/core/drawLine.mjs", + "/home/felix/projects/strudel/packages/core/euclid.mjs", + "/home/felix/projects/strudel/packages/core/fraction.mjs", + "/home/felix/projects/strudel/packages/core/gist.js", + "/home/felix/projects/strudel/packages/core/hap.mjs", + "/home/felix/projects/strudel/packages/core/index.mjs", + "/home/felix/projects/strudel/packages/core/out/scripts/linenumber.js", + "/home/felix/projects/strudel/packages/core/out/scripts/prettify/lang-css.js", + "/home/felix/projects/strudel/packages/core/out/scripts/prettify/prettify.js", + "/home/felix/projects/strudel/packages/core/pattern.mjs", + "/home/felix/projects/strudel/packages/core/signal.mjs", + "/home/felix/projects/strudel/packages/core/speak.mjs", + "/home/felix/projects/strudel/packages/core/state.mjs", + "/home/felix/projects/strudel/packages/core/test/drawLine.test.mjs", + "/home/felix/projects/strudel/packages/core/test/fraction.test.mjs", + "/home/felix/projects/strudel/packages/core/test/pattern.test.mjs", + "/home/felix/projects/strudel/packages/core/test/util.test.mjs", + "/home/felix/projects/strudel/packages/core/test/value.test.mjs", + "/home/felix/projects/strudel/packages/core/timespan.mjs", + "/home/felix/projects/strudel/packages/core/util.mjs", + "/home/felix/projects/strudel/packages/core/value.mjs", + "/home/felix/projects/strudel/packages/embed/embed.js", + "/home/felix/projects/strudel/packages/eval/evaluate.mjs", + "/home/felix/projects/strudel/packages/eval/index.mjs", + "/home/felix/projects/strudel/packages/eval/shapeshifter.mjs", + "/home/felix/projects/strudel/packages/eval/test/evaluate.test.mjs", + "/home/felix/projects/strudel/packages/eval/test/shapeshifter.test.mjs", + "/home/felix/projects/strudel/packages/midi/index.mjs", + "/home/felix/projects/strudel/packages/midi/midi.mjs", + "/home/felix/projects/strudel/packages/mini/index.mjs", + "/home/felix/projects/strudel/packages/mini/krill-parser.js", + "/home/felix/projects/strudel/packages/mini/mini.mjs", + "/home/felix/projects/strudel/packages/mini/test/mini.test.mjs", + "/home/felix/projects/strudel/packages/osc/osc.mjs", + "/home/felix/projects/strudel/packages/osc/server.js", + "/home/felix/projects/strudel/packages/osc/tidal-sniffer.js", + "/home/felix/projects/strudel/packages/react/dist/index.cjs.js", + "/home/felix/projects/strudel/packages/react/dist/index.es.js", + "/home/felix/projects/strudel/packages/react/postcss.config.js", + "/home/felix/projects/strudel/packages/react/src/App.jsx", + "/home/felix/projects/strudel/packages/react/src/components/CodeMirror6.jsx", + "/home/felix/projects/strudel/packages/react/src/components/MiniRepl.jsx", + "/home/felix/projects/strudel/packages/react/src/cx.js", + "/home/felix/projects/strudel/packages/react/src/hooks/useCycle.mjs", + "/home/felix/projects/strudel/packages/react/src/hooks/useHighlighting.mjs", + "/home/felix/projects/strudel/packages/react/src/hooks/usePostMessage.mjs", + "/home/felix/projects/strudel/packages/react/src/hooks/useRepl.mjs", + "/home/felix/projects/strudel/packages/react/src/hooks/useWebMidi.mjs", + "/home/felix/projects/strudel/packages/react/src/index.js", + "/home/felix/projects/strudel/packages/react/src/main.jsx", + "/home/felix/projects/strudel/packages/react/src/themes/material-palenight.js", + "/home/felix/projects/strudel/packages/react/tailwind.config.js", + "/home/felix/projects/strudel/packages/react/vite.config.js", + "/home/felix/projects/strudel/packages/serial/serial.mjs", + "/home/felix/projects/strudel/packages/tonal/index.mjs", + "/home/felix/projects/strudel/packages/tonal/test/tonal.test.mjs", + "/home/felix/projects/strudel/packages/tonal/tonal.mjs", + "/home/felix/projects/strudel/packages/tonal/voicings.mjs", + "/home/felix/projects/strudel/packages/tone/draw.mjs", + "/home/felix/projects/strudel/packages/tone/index.mjs", + "/home/felix/projects/strudel/packages/tone/pianoroll.mjs", + "/home/felix/projects/strudel/packages/tone/test/tone.test.mjs", + "/home/felix/projects/strudel/packages/tone/tone.mjs", + "/home/felix/projects/strudel/packages/tone/ui.mjs", + "/home/felix/projects/strudel/packages/webaudio/clockworker.mjs", + "/home/felix/projects/strudel/packages/webaudio/index.mjs", + "/home/felix/projects/strudel/packages/webaudio/scheduler.mjs", + "/home/felix/projects/strudel/packages/webaudio/webaudio.mjs", + "/home/felix/projects/strudel/packages/xen/index.mjs", + "/home/felix/projects/strudel/packages/xen/test/xen.test.mjs", + "/home/felix/projects/strudel/packages/xen/tune.mjs", + "/home/felix/projects/strudel/packages/xen/tunejs.js", + "/home/felix/projects/strudel/packages/xen/xen.mjs" ], - "___id": "T000002R012553", + "___id": "T000002R014017", "___s": true } ] diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 5b09766d..e59d4cc7 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -8,100 +8,433 @@ import { Pattern, sequence } from './pattern.mjs'; const controls = {}; const generic_params = [ + /** + * Select a sound / sample by name. + * + *
+ * show all sounds + * + * 808 (6) 808bd (25) 808cy (25) 808hc (5) 808ht (5) 808lc (5) 808lt (5) 808mc (5) 808mt (5) 808oh (5) 808sd (25) 909 (1) ab (12) ade (10) ades2 (9) ades3 (7) ades4 (6) alex (2) alphabet (26) amencutup (32) armora (7) arp (2) arpy (11) auto (11) baa (7) baa2 (7) bass (4) bass0 (3) bass1 (30) bass2 (5) bass3 (11) bassdm (24) bassfoo (3) battles (2) bd (24) bend (4) bev (2) bin (2) birds (10) birds3 (19) bleep (13) blip (2) blue (2) bottle (13) breaks125 (2) breaks152 (1) breaks157 (1) breaks165 (1) breath (1) bubble (8) can (14) casio (3) cb (1) cc (6) chin (4) circus (3) clak (2) click (4) clubkick (5) co (4) coins (1) control (2) cosmicg (15) cp (2) cr (6) crow (4) d (4) db (13) diphone (38) diphone2 (12) dist (16) dork2 (4) dorkbot (2) dr (42) dr2 (6) dr55 (4) dr_few (8) drum (6) drumtraks (13) e (8) east (9) electro1 (13) em2 (6) erk (1) f (1) feel (7) feelfx (8) fest (1) fire (1) flick (17) fm (17) foo (27) future (17) gab (10) gabba (4) gabbaloud (4) gabbalouder (4) glasstap (3) glitch (8) glitch2 (8) gretsch (24) gtr (3) h (7) hand (17) hardcore (12) hardkick (6) haw (6) hc (6) hh (13) hh27 (13) hit (6) hmm (1) ho (6) hoover (6) house (8) ht (16) if (5) ifdrums (3) incoming (8) industrial (32) insect (3) invaders (18) jazz (8) jungbass (20) jungle (13) juno (12) jvbass (13) kicklinn (1) koy (2) kurt (7) latibro (8) led (1) less (4) lighter (33) linnhats (6) lt (16) made (7) made2 (1) mash (2) mash2 (4) metal (10) miniyeah (4) monsterb (6) moog (7) mouth (15) mp3 (4) msg (9) mt (16) mute (28) newnotes (15) noise (1) noise2 (8) notes (15) numbers (9) oc (4) odx (15) off (1) outdoor (6) pad (3) padlong (1) pebbles (1) perc (6) peri (15) pluck (17) popkick (10) print (11) proc (2) procshort (8) psr (30) rave (8) rave2 (4) ravemono (2) realclaps (4) reverbkick (1) rm (2) rs (1) sax (22) sd (2) seawolf (3) sequential (8) sf (18) sheffield (1) short (5) sid (12) sine (6) sitar (8) sn (52) space (18) speakspell (12) speech (7) speechless (10) speedupdown (9) stab (23) stomp (10) subroc3d (11) sugar (2) sundance (6) tabla (26) tabla2 (46) tablex (3) tacscan (22) tech (13) techno (7) tink (5) tok (4) toys (13) trump (11) ul (10) ulgab (5) uxay (3) v (6) voodoo (5) wind (10) wobble (1) world (3) xmas (1) yeah (31) + * + * more info + * + *
+ * + * @name s + * @param {string | Pattern} sound The sound / pattern of sounds to pick + * @example + * s("bd hh").osc() + * + */ ['s', 's', 'sound'], + /** + * The note or sample number to choose for a synth or sampleset + * Note names currently not working yet, but will hopefully soon. Just stick to numbers for now + * + * @name n + * @param {string | number | Pattern} value note name, note number or sample number + * @example + * s('superpiano').n("<0 1 2 3>").osc() + * @example + * s('superpiano').n("").osc() + * @example + * n("0 1 2 3").s('east').osc() + */ + // TODO: nOut does not work + // TODO: notes don't work as expected + // current "workaround" for notes: + // s('superpiano').n(""._asNumber()).osc() + // -> .n or .osc (or .superdirt) would need to convert note strings to numbers + // also see https://github.com/tidalcycles/strudel/pull/63 + ['f', 'n', 'The note or sample number to choose for a synth or sampleset'], + ['f', 'note', 'The note or pitch to play a sound or synth with'], //['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. + * + * @name accelerate + * @param {number | Pattern} amount acceleration. + * @example + * 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.'], - ['f', 'amp', 'like @gain@, but linear.'], - [ - 'f', - 'attack', - 'a pattern of numbers to specify the attack time (in seconds) of an envelope applied to each sample.', - ], - ['f', 'bandf', 'a pattern of numbers from 0 to 1. Sets the center frequency of the band-pass filter.'], - ['f', 'bandq', 'a pattern of anumbers from 0 to 1. Sets the q-factor of the band-pass filter.'], - [ - '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.', - ], - ['f', 'legato', 'controls the amount of overlap between two adjacent sounds'], - // ['f', 'clhatdecay', ''], - [ - 'f', - 'crush', - 'bit crushing, a pattern of numbers from 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).', - ], - [ - '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.', - ], - ['i', 'channel', 'choose the channel the pattern is sent to in superdirt'], - [ - '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.', - ], - ['f', 'cutoff', 'a pattern of numbers from 0 to 1. Applies the cutoff frequency of the low-pass filter.'], - // ['f', 'cutoffegint', ''], - ['f', 'decay', ''], - ['f', 'delay', 'a pattern of numbers from 0 to 1. Sets the level of the delay signal.'], - ['f', 'delayfeedback', 'a pattern of numbers from 0 to 1. Sets the amount of delay feedback.'], - ['f', 'delaytime', 'a pattern of numbers from 0 to 1. Sets the length of the delay.'], - ['f', 'detune', ''], - ['f', 'djf', 'DJ filter, below 0.5 is low pass filter, above is high pass filter.'], - [ - 'f', - 'dry', - 'when set to `1` will disable all reverb for this pattern. See `room` and `size` for more information about reverb.', - ], - [ - '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.', - ], - [ - 'f', - 'fadeTime', - "Used when using begin/end or chop/striate and friends, to change the fade out time of the 'grain' envelope.", - ], - [ - '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.', - ], - ['f', 'freq', ''], + /** + * Like {@link amp}, but exponential. + * + * @name gain + * @param {number | Pattern} amount gain. + * @example + * s("bd*8").gain(".7*2 1 .7*2 1 .7 1").osc() + * + */ [ '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@.', ], - ['f', 'gate', ''], - // ['f', 'hatgrain', ''], + /** + * Like {@link gain}, but linear. + * + * @name amp + * @param {number | Pattern} amount gain. + * @example + * s("bd*8").amp(".1*2 .5 .1*2 .5 .1 .5").osc() + * + */ + ['f', 'amp', 'like @gain@, but linear.'], + // TODO: find out why 0 does not work, and it generally seems not right + /* + * A pattern of numbers to specify the attack time of an envelope applied to each sample. + * + * @name attack + * @param {number | Pattern} attack time in seconds. + * @example + * n("c5 e5").s('superpiano').attack("<0 .1>").osc() + * + */ [ 'f', - 'hcutoff', - 'a pattern of numbers from 0 to 1. Applies the cutoff frequency of the high-pass filter. Also has alias @hpf@', + 'attack', + 'a pattern of numbers to specify the attack time (in seconds) of an envelope applied to each sample.', + ], + // TODO: find out how this works? + /* + * Envelope decay time = the time it takes after the attack time to reach the sustain level. + * + * @name decay + * @param {number | Pattern} time decay time in seconds + * @example + * s("sax").cut(1).decay("<.1 .2 .3 .4>").sustain(0).osc() + * + */ + ['f', 'decay', ''], + ['f', 'sustain', ''], + [ + 'f', + '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 + /** + * Sets the center frequency of the band-pass filter. + * + * @name bandf + * @param {number | Pattern} frequency center frequency + * @example + * s("bd sd").bandf("<1000 2000 4000 8000>").osc() + * + */ + ['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 + /** + * Sets the q-factor of the band-pass filter + * + * @name bandq + * @param {number | Pattern} q q factor + * @example + * s("bd sd").bandf(2000).bandq("<.2 .9>").osc() + * + */ + ['f', 'bandq', 'a pattern of anumbers from 0 to 1. Sets the q-factor of the band-pass filter.'], + /** + * 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. + * + * @name begin + * @param {number | Pattern} amount between 0 and 1, where 1 is the length of the sample + * @example + * s("rave").begin("<0 .25 .5 .75>").osc() + * + */ + [ + '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 {@link begin}, but cuts off the end off each sample. + * + * @name end + * @param {number | Pattern} length 1 = whole sample, .5 = half sample, .25 = quarter sample etc.. + * @example + * s("bd*2,ho*4").end("<.1 .2 .5 1>").osc() + * + */ + [ + '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. + * Note that the tempo of the loop is not synced with the cycle tempo. + * + * @name loop + * @param {number | Pattern} times How often the sample is looped + * @example + * s("bd").loop("<1 2 3 4>").osc() + * + */ + ['f', 'loop', 'loops the sample (from `begin` to `end`) the specified number of times.'], + // TODO: currently duplicated with "native" legato + // TODO: superdirt legato will do more: https://youtu.be/dQPmE1WaD1k?t=419 + /** + * 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. + * + * @name legato + * @param {number | Pattern} duration between 0 and 1, where 1 is the length of the whole hap time + * @example + * "c4 eb4 g4 bb4".legato("<0.125 .25 .5 .75 1 2 4>") + * + */ + ['f', 'legato', 'controls the amount of overlap between two adjacent sounds'], + // ['f', 'clhatdecay', ''], + /** + * bit crusher effect. + * + * @name crush + * @param {number | Pattern} depth between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction). + * @example + * s(",hh*3,jvbass*2").fast(2).crush("<16 8 7 6 5 4 3 2>").osc() + * + */ + [ + '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 + * + * @name coarse + * @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on. + * @example + * s("xmas").coarse("<1 4 8 16 32>").osc() + * + */ + [ + '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 + * + * @name channel + * @param {number | Pattern} channel channel number + * + */ + ['i', 'channel', 'choose the channel the pattern is sent to in superdirt'], + /** + * 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. + * + * @name cut + * @param {number | Pattern} group cut group number + * @example + * s("bd sax").cut(1).osc() + * + */ + [ + '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 low-pass filter. + * + * @name cutoff + * @param {number | Pattern} frequency audible between 0 and 20000 + * @example + * s("bd,hh*2,<~ sd>").fast(2).cutoff("<4000 2000 1000 500 200 100>").osc() + * + */ + // TODO: add lpf synonym + ['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 high-pass filter. + * + * @name hcutoff + * @param {number | Pattern} frequency audible between 0 and 20000 + * @example + * s("bd,hh*2,<~ sd>").fast(2).hcutoff("<4000 2000 1000 500 200 100>").osc() + * + */ + // TODO: add hpf synonym + [ + 'f', + 'hcutoff', + 'a pattern of numbers from 0 to 1. Applies the cutoff frequency of the high-pass filter. Also has alias @hpf@', + ], + /** + * Applies the cutoff frequency of the high-pass filter. + * + * @name hresonance + * @param {number | Pattern} q resonance factor between 0 and 1 + * @example + * s("bd,hh*2,<~ sd>").fast(2).hcutoff(2000).hresonance("<0 .2 .4 .6>").osc() + * + */ [ 'f', 'hresonance', 'a pattern of numbers from 0 to 1. Applies the resonance of the high-pass filter. Has alias @hpq@', ], + // TODO: add hpq synonym + /** + * Applies the cutoff frequency of the low-pass filter. + * + * @name resonance + * @param {number | Pattern} q resonance factor between 0 and 1 + * @example + * s("bd,hh*2,<~ sd>").fast(2).cutoff(2000).resonance("<0 .2 .4 .6>").osc() + * + */ + ['f', 'resonance', 'a pattern of numbers from 0 to 1. Specifies the resonance of the low-pass filter.'], + // TODO: add lpq synonym? + /** + * Set detune of oscillators. Works only with some synths, see tidal doc + * + * @name djf + * @param {number | Pattern} cutoff below 0.5 is low pass filter, above is high pass filter + * @example + * 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.'], + // ['f', 'cutoffegint', ''], + // TODO: does not seem to work + /* + * Sets the level of the delay signal. + * + * @name delay + * @param {number | Pattern} level between 0 and 1 + * @example + * s("bd").delay("<0 .5 .75 1>").osc() + * + */ + ['f', 'delay', 'a pattern of numbers from 0 to 1. Sets the level of the delay signal.'], + ['f', 'delayfeedback', 'a pattern of numbers from 0 to 1. Sets the amount of delay feedback.'], + ['f', 'delaytime', 'a pattern of numbers from 0 to 1. Sets the length of the delay.'], + /* // TODO: test + * Specifies whether delaytime is calculated relative to cps. + * + * @name lock + * @param {number | Pattern} enable When set to 1, delaytime is a direct multiple of a cycle. + * @example + * s("sd").delay().lock(1).osc() + * + */ + [ + '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 tidal doc + * + * @name detune + * @param {number | Pattern} amount between 0 and 1 + * @example + * n("0 3 7").s('superzow').octave(3).detune("<0 .25 .5 1 2>").osc() + * + */ + ['f', 'detune', ''], + /** + * Set dryness of reverb. See {@link room} and {@link size} for more information about reverb. + * + * @name dry + * @param {number | Pattern} dry 0 = wet, 1 = dry + * @example + * n("[0,3,7](3,8)").s("superpiano").room(.7).dry("<0 .5 .75 1>").osc() + * + */ + [ + '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 + /* + * Used when using {@link begin}/{@link end} or {@link chop}/{@link striate} and friends, to change the fade out time of the 'grain' envelope. + * + * @name fadeTime + * @param {number | Pattern} time between 0 and 1 + * @example + * s("ho*4").end(.1).fadeTime("<0 .2 .4 .8>").osc() + * + */ + [ + '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 + [ + '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. + * + * @name freq + * @param {number | Pattern} frequency in Hz. the audible range is between 20 and 20000 Hz + * @example + * freq("220 110 440 110").s("superzow").osc() + * @example + * freq("110".mulOut(".5 1.5 .6 [2 3]")).s("superzow").osc() + * + */ + ['f', 'freq', ''], + // TODO: https://tidalcycles.org/docs/configuration/MIDIOSC/control-voltage/#gate + ['f', 'gate', ''], + // ['f', 'hatgrain', ''], // ['f', 'lagogo', ''], // ['f', 'lclap', ''], // ['f', 'lclaves', ''], // ['f', 'lclhat', ''], // ['f', 'lcrash', ''], + // TODO: + // https://tidalcycles.org/docs/reference/audio_effects/#leslie-1 + // https://tidalcycles.org/docs/reference/audio_effects/#leslie + /** + * Emulation of a Leslie speaker: speakers rotating in a wooden amplified cabinet. + * + * @name leslie + * @param {number | Pattern} wet between 0 and 1 + * @example + * n("0,4,7").s("supersquare").leslie("<0 .4 .6 1>").osc() + * + */ ['f', 'leslie', ''], + /** + * Rate of modulation / rotation for leslie effect + * + * @name lrate + * @param {number | Pattern} rate 6.7 for fast, 0.7 for slow + * @example + * n("0,4,7").s("supersquare").leslie(1).lrate("<1 2 4 8>").osc() + * + */ + // TODO: the rate seems to "lag" (in the example, 1 will be fast) ['f', 'lrate', ''], + /** + * Physical size of the cabinet in meters. Be careful, it might be slightly larger than your computer. Affects the Doppler amount (pitch warble) + * + * @name lsize + * @param {number | Pattern} meters somewhere between 0 and 1 + * @example + * n("0,4,7").s("supersquare").leslie(1).lrate(2).lsize("<.1 .5 1>").osc() + * + */ ['f', 'lsize', ''], // ['f', 'lfo', ''], // ['f', 'lfocutoffint', ''], @@ -113,47 +446,86 @@ const generic_params = [ // ['f', 'lhitom', ''], // ['f', 'lkick', ''], // ['f', 'llotom', ''], - [ - '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.', - ], - ['f', 'loop', 'loops the sample (from `begin` to `end`) the specified number of times.'], // ['f', 'lophat', ''], // ['f', 'lsnare', ''], - ['f', 'n', 'The note or sample number to choose for a synth or sampleset'], - ['f', 'note', 'The note or pitch to play a sound or synth with'], - ['f', 'degree', ''], - ['f', 'mtranspose', ''], - ['f', 'ctranspose', ''], - ['f', 'harmonic', ''], - ['f', 'stepsPerOctave', ''], - ['f', 'octaveR', ''], + ['f', 'degree', ''], // TODO: what is this? not found in tidal doc + ['f', 'mtranspose', ''], // TODO: what is this? not found in tidal doc + ['f', 'ctranspose', ''], // TODO: what is this? not found in tidal doc + ['f', 'harmonic', ''], // TODO: what is this? not found in tidal doc + ['f', 'stepsPerOctave', ''], // TODO: what is this? not found in tidal doc + ['f', 'octaveR', ''], // TODO: what is this? not found in tidal doc + // TODO: why is this needed? what's the difference to late / early? [ 'f', '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. + /** + * Sets the default octave of a synth. + * + * @name octave + * @param {number | Pattern} octave octave number + * @example + * n("0,4,7").s('supersquare').octave("<3 4 5 6>").osc() + */ ['i', 'octave', ''], - ['f', 'offset', ''], + ['f', 'offset', ''], // TODO: what is this? not found in tidal doc // ['f', 'ophatdecay', ''], + // TODO: example + /** + * 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. + * + * @name orbit + * @param {number | Pattern} number + * + */ [ 'i', 'orbit', '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', ''], - ['f', 'overshape', ''], + ['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. + * + * @name pan + * @param {number | Pattern} pan between 0 and 1, from left to right (assuming stereo), once round a circle (assuming multichannel) + * @example + * s("[bd hh]*2").pan("<.5 1 .5 0>").osc() + * + */ [ '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) + /* + * Controls how much multichannel output is fanned out + * + * @name panspan + * @param {number | Pattern} span between -inf and inf, negative is backwards ordering + * @example + * s("[bd hh]*2").pan("<.5 1 .5 0>").panspan("<0 .5 1>").osc() + * + */ [ '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) + /* + * Controls how much multichannel output is spread + * + * @name pansplay + * @param {number | Pattern} spread between 0 and 1 + * @example + * s("[bd hh]*2").pan("<.5 1 .5 0>").pansplay("<0 .5 1>").osc() + * + */ [ 'f', 'pansplay', @@ -173,68 +545,163 @@ const generic_params = [ // ['f', 'pitch2', ''], // ['f', 'pitch3', ''], // ['f', 'portamento', ''], + // TODO: LFO rate see https://tidalcycles.org/docs/patternlib/tutorials/synthesizers/#supersquare ['f', 'rate', "used in SuperDirt softsynths as a control rate or 'speed'"], - [ - 'f', - 'release', - 'a pattern of numbers to specify the release time (in seconds) of an envelope applied to each sample.', - ], - ['f', 'resonance', 'a pattern of numbers from 0 to 1. Specifies the resonance of the low-pass filter.'], - ['f', 'room', 'a pattern of numbers from 0 to 1. Sets the level of reverb.'], - // ['f', 'sagogo', ''], - // ['f', 'sclap', ''], - // ['f', 'sclaves', ''], - // ['f', 'scrash', ''], + // TODO: slide param for certain synths + ['f', 'slide', ''], + // TODO: detune? https://tidalcycles.org/docs/patternlib/tutorials/synthesizers/#supersquare ['f', 'semitone', ''], - [ - 'f', - 'shape', - 'wave shaping distortion, a pattern of numbers from 0 for no distortion up to 1 for loads of distortion.', - ], + // TODO: dedup with synth param, see https://tidalcycles.org/docs/reference/synthesizers/#superpiano + ['f', 'velocity', ''], + ['f', 'voice', ''], // TODO: synth param + /** + * Sets the level of reverb. + * + * @name room + * @param {number | Pattern} level between 0 and 1 + * @example + * s("bd sd").room("<0 .2 .4 .6 .8 1>").osc() + * + */ + ['f', 'room', 'a pattern of numbers from 0 to 1. Sets the level of reverb.'], + /** + * Sets the room size of the reverb, see {@link room}. + * + * @name size + * @param {number | Pattern} size between 0 and 1 + * @example + * s("bd sd").room(.8).size("<0 .2 .4 .6 .8 1>").osc() + * + */ + // TODO: find out why : + // s("bd sd").room(.8).size("<0 .2 .4 .6 .8 [1,0]>").osc() + // .. does not work. Is it because room is only one effect? [ 'f', 'size', 'a pattern of numbers from 0 to 1. Sets the perceptual size (reverb time) of the `room` to be used in reverb.', ], - ['f', 'slide', ''], + // ['f', 'sagogo', ''], + // ['f', 'sclap', ''], + // ['f', 'sclaves', ''], + // ['f', 'scrash', ''], + /** + * Wave shaping distortion. CAUTION: it might get loud + * + * @name shape + * @param {number | Pattern} distortion between 0 and 1 + * @example + * s("bd sd").shape("<0 .2 .4 .6 .8 1>").osc() + * + */ + [ + '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. + * + * @name speed + * @param {number | Pattern} speed -inf to inf, negative numbers play the sample backwards. + * @example + * s("bd").speed("<1 2 4 1 -2 -4>").osc() + * @example + * speed("1 1.5*2 [2 1.1]").s("sax").cut(1).osc() + * + */ [ '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!', ], - ['f', 'squiz', ''], - ['f', 'stutterdepth', ''], - ['f', 'stuttertime', ''], - ['f', 'sustain', ''], - ['f', 'timescale', ''], - ['f', 'timescalewin', ''], - // ['f', 'tomdecay', ''], + /** + * 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`. + * + * @name unit + * @param {number | string | Pattern} unit see description above + * @example + * speed("1 2 .5 3").s("bd").unit("c").osc() + * + */ [ '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`.', ], - ['f', 'velocity', ''], + /** + * Made by Calum Gunn. Reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter. The SuperCollider manual defines Squiz as: + * + * "A simplistic pitch-raising algorithm. It's not meant to sound natural; its sound is reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter, depending on the input. The algorithm works by cutting the signal into fragments (delimited by upwards-going zero-crossings) and squeezing those fragments in the time domain (i.e. simply playing them back faster than they came in), leaving silences inbetween. All the parameters apart from memlen can be modulated." + * + * @name squiz + * @param {number | Pattern} squiz Try passing multiples of 2 to it - 2, 4, 8 etc. + * @example + * squiz("2 4/2 6 [8 16]").s("bd").osc() + * + */ + ['f', 'squiz', ''], + ['f', 'stutterdepth', ''], // TODO: what is this? not found in tidal doc + ['f', 'stuttertime', ''], // TODO: what is this? not found in tidal doc + ['f', 'timescale', ''], // TODO: what is this? not found in tidal doc + ['f', 'timescalewin', ''], // TODO: what is this? not found in tidal doc + // ['f', 'tomdecay', ''], // ['f', 'vcfegint', ''], // ['f', 'vcoegint', ''], - ['f', 'voice', ''], + /** + * + * Formant filter to make things sound like vowels. + * + * @name vowel + * @param {string | Pattern} vowel You can use a e i o u. Use a rest (~) to override the effect + * @example + * vowel("a e i [o u]").slow(2) + * .n("<[0,7]!4 [2,7]!4>") + * .s('supersquare').osc() + * + */ [ '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 + * 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: + * + * Divide an audio stream into tiny segments, using the signal's zero-crossings as segment boundaries, and discard a fraction of them (i.e. replace them with silence of the same length). The technique was described by Trevor Wishart in a lecture. Parameters: the filter drops drop out of out of chunks. mode can be 1 to drop chunks in a simple deterministic fashion (e.g. always dropping the first 30 out of a set of 40 segments), or 2 to drop chunks randomly but in an appropriate proportion.) + * + * mode: ? + * waveloss: ? + * + * @name waveloss + */ ['f', 'waveloss', ''], + // TODO: midi effects? ['f', 'dur', ''], // ['f', 'modwheel', ''], ['f', 'expression', ''], ['f', 'sustainpedal', ''], + /* // TODO: doesn't seem to do anything + * + * Tremolo Audio DSP effect + * + * @name tremolodepth + * @param {number | Pattern} depth between 0 and 1 + * @example + * n("0,4,7").tremolodepth("<0 .3 .6 .9>").osc() + * + */ + // TODO: tremdp alias ['f', 'tremolodepth', "Tremolo Audio DSP effect | params are 'tremolorate' and 'tremolodepth'"], ['f', 'tremolorate', "Tremolo Audio DSP effect | params are 'tremolorate' and 'tremolodepth'"], + // TODO: doesn't seem to do anything ['f', 'phaserdepth', "Phaser Audio DSP effect | params are 'phaserrate' and 'phaserdepth'"], ['f', 'phaserrate', "Phaser Audio DSP effect | params are 'phaserrate' and 'phaserdepth'"], + ['f', 'fshift', 'frequency shifter'], ['f', 'fshiftnote', 'frequency shifter'], ['f', 'fshiftphase', 'frequency shifter'], + ['f', 'triode', 'tube distortion'], ['f', 'krush', 'shape/bass enhancer'], ['f', 'kcutoff', ''], @@ -279,6 +746,8 @@ const generic_params = [ ['f', 'cps', ''], ]; +// TODO: slice / splice https://www.youtube.com/watch?v=hKhPdO0RKDQ&list=PL2lW1zNIIwj3bDkh-Y3LUGDuRcoUigoDs&index=13 + const _name = (name, ...pats) => sequence(...pats).withValue((x) => ({ [name]: x })); const _setter = (func) => diff --git a/packages/core/drawLine.mjs b/packages/core/drawLine.mjs index 0bfe458c..da424236 100644 --- a/packages/core/drawLine.mjs +++ b/packages/core/drawLine.mjs @@ -6,6 +6,22 @@ This program is free software: you can redistribute it and/or modify it under th import Fraction, { gcd } from './fraction.mjs'; +/** + * Intended for a debugging, drawLine renders the pattern as a string, where each character represents the same time span. + * Should only be used with single characters as values, otherwise the character slots will be messed up. + * Character legend: + * + * - "|" cycle separator + * - "-" hold previous value + * - "." silence + * + * @param {Pattern} pattern the pattern to use + * @param {number} chars max number of characters (approximately) + * @returns string + * @example + * const line = drawLine("0 [1 2 3]", 10); // |0--123|0--123 + * console.log(line); + */ function drawLine(pat, chars = 60) { let cycle = 0; let pos = Fraction(0); diff --git a/packages/core/euclid.mjs b/packages/core/euclid.mjs index 4e4e3bcf..c95b3409 100644 --- a/packages/core/euclid.mjs +++ b/packages/core/euclid.mjs @@ -17,10 +17,70 @@ const euclid = (pulses, steps, rotation = 0) => { return b; }; +/** + * Changes the structure of the pattern to form an euclidean rhythm. + * Euclidian rhythms are rhythms obtained using the greatest common divisor of two numbers. + * They were described in 2004 by Godfried Toussaint, a canadian computer scientist. + * Euclidian rhythms are really useful for computer/algorithmic music because they can accurately + * describe a large number of rhythms used in the most important music world traditions. + * + * @memberof Pattern + * @param {number} pulses the number of onsets / beats + * @param {number} steps the number of steps to fill + * @param {number} rotation (optional) offset in steps + * @returns Pattern + * @example // The Cuban tresillo pattern. + * "c3".euclid(3,8) + * @example // A thirteenth century Persian rhythm called Khafif-e-ramal. + * "c3".euclid(2,5) + * @example // The archetypal pattern of the Cumbia from Colombia, as well as a Calypso rhythm from Trinidad. + * "c3".euclid(3,4) + * @example // Another thirteenth century Persian rhythm by the name of Khafif-e-ramal, as well as a Rumanian folk-dance rhythm. + * "c3".euclid(3,5,2) + * @example // A Ruchenitza rhythm used in a Bulgarian folk-dance. + * "c3".euclid(3,7) + * @example // The Cuban tresillo pattern. + * "c3".euclid(3,8) + * @example // Another Ruchenitza Bulgarian folk-dance rhythm. + * "c3".euclid(4,7) + * @example // The Aksak rhythm of Turkey. + * "c3".euclid(4,9) + * @example // The metric pattern used by Frank Zappa in his piece titled Outside Now. + * "c3".euclid(4,11) + * @example // Yields the York-Samai pattern, a popular Arab rhythm. + * "c3".euclid(5,6) + * @example // The Nawakhat pattern, another popular Arab rhythm. + * "c3".euclid(5,7) + * @example // The Cuban cinquillo pattern. + * "c3".euclid(5,8) + * @example // A popular Arab rhythm called Agsag-Samai. + * "c3".euclid(5,9) + * @example // The metric pattern used by Moussorgsky in Pictures at an Exhibition. + * "c3".euclid(5,11) + * @example // The Venda clapping pattern of a South African children’s song. + * "c3".euclid(5,12) + * @example // The Bossa-Nova rhythm necklace of Brazil. + * "c3".euclid(5,16) + * @example // A typical rhythm played on the Bendir (frame drum). + * "c3".euclid(7,8) + * @example // A common West African bell pattern. + * "c3".euclid(7,12) + * @example // A Samba rhythm necklace from Brazil. + * "c3".euclid(7,16,14) + * @example // A rhythm necklace used in the Central African Republic. + * "c3".euclid(9,16) + * @example // A rhythm necklace of the Aka Pygmies of Central Africa. + * "c3".euclid(11,24,14) + * @example // Another rhythm necklace of the Aka Pygmies of the upper Sangha. + * "c3".euclid(13,24,5) + */ Pattern.prototype.euclid = function (pulses, steps, rotation = 0) { return this.struct(euclid(pulses, steps, rotation)); }; +/** + * Similar to {@link Pattern#euclid}, but each pulse is held until the next pulse, so there will be no gaps. + */ Pattern.prototype.euclidLegato = function (pulses, steps, rotation = 0) { const bin_pat = euclid(pulses, steps, rotation); const firstOne = bin_pat.indexOf(1); diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 59b33816..f6afb7df 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -16,8 +16,9 @@ import drawLine from './drawLine.mjs'; /** @class Class representing a pattern. */ export class Pattern { /** - * Create a pattern. - * @param {function} query - The function that maps a State to Haps . + * Create a pattern. As an end user, you will most likely not create a Pattern directly. + * + * @param {function} query - The function that maps a {@link State} to an array of {@link Hap}. */ constructor(query) { this.query = query; @@ -62,7 +63,7 @@ export class Pattern { } /** - * As with {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to both the + * As with {@link Pattern#withQuerySpan}, but the function is applied to both the * begin and end time of the query timespan. * @param {Function} func the function to apply * @returns Pattern @@ -72,7 +73,7 @@ export class Pattern { } /** - * Similar to {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to the timespans + * Similar to {@link Pattern#withQuerySpan}, but the function is applied to the timespans * of all haps returned by pattern queries (both `part` timespans, and where * present, `whole` timespans). * @param {Function} func @@ -83,7 +84,7 @@ export class Pattern { } /** - * As with {@link Pattern#withHapSpan|withHapSpan}, but the function is applied to both the + * As with {@link Pattern#withHapSpan}, but the function is applied to both the * begin and end time of the hap timespans. * @param {Function} func the function to apply * @returns Pattern @@ -182,7 +183,7 @@ export class Pattern { /** * Returns a new pattern, with the function applied to the value of - * each hap. It has the alias {@link Pattern#fmap|fmap}. + * each hap. It has the alias {@link Pattern#fmap}. * @param {Function} func * @returns Pattern */ @@ -191,7 +192,7 @@ export class Pattern { } /** - * see {@link Pattern#withValue|withValue} + * see {@link Pattern#withValue} */ fmap(func) { return this.withValue(func); @@ -298,7 +299,7 @@ export class Pattern { } /** - * As with {@link Pattern#appBoth|appBoth}, but the `whole` timespan is not the intersection, + * As with {@link Pattern#appBoth}, but the `whole` timespan is not the intersection, * but the timespan from the function of patterns that this method is called * on. In practice, this means that the pattern structure, including onsets, * are preserved from the pattern of functions (often referred to as the left @@ -330,7 +331,7 @@ export class Pattern { } /** - * As with {@link Pattern#appLeft|appLeft}, but `whole` timespans are instead taken from the + * As with {@link Pattern#appLeft}, but `whole` timespans are instead taken from the * pattern of values, i.e. structure is preserved from the right hand/outer * pattern. * @param {Pattern} pat_val @@ -463,35 +464,83 @@ export class Pattern { }); } + /** + * Assumes a numerical pattern. Returns a new pattern with all values rounded + * to the nearest integer. + * @returns Pattern + */ round() { return this._asNumber().fmap((v) => Math.round(v)); } + /** + * Assumes a numerical pattern. Returns a new pattern with all values set to + * their mathematical floor. E.g. `3.7` replaced with to `3`, and `-4.2` + * replaced with `-5`. + * @returns Pattern + */ floor() { return this._asNumber().fmap((v) => Math.floor(v)); } + /** + * Assumes a numerical pattern. Returns a new pattern with all values set to + * their mathematical ceiling. E.g. `3.2` replaced with `4`, and `-4.2` + * replaced with `-4`. + * @returns Pattern + */ ceil() { return this._asNumber().fmap((v) => Math.ceil(v)); } + /** + * Assumes a numerical pattern, containing unipolar values in the range 0 .. + * 1. Returns a new pattern with values scaled to the bipolar range -1 .. 1 + * @returns Pattern + */ _toBipolar() { return this.fmap((x) => x * 2 - 1); } + + /** + * Assumes a numerical pattern, containing bipolar values in the range -1 .. + * 1. Returns a new pattern with values scaled to the unipolar range 0 .. 1 + * @returns Pattern + */ _fromBipolar() { return this.fmap((x) => (x + 1) / 2); } - // Assumes source pattern of numbers in range 0..1 + /** + * Assumes a numerical pattern, containing unipolar values in the range 0 .. + * 1. Returns a new pattern with values scaled to the given min/max range. + * @param {Number} min + * @param {Number} max + * @returns Pattern + */ range(min, max) { return this.mul(max - min).add(min); } + /** + * Assumes a numerical pattern, containing unipolar values in the range 0 .. + * 1. Returns a new pattern with values scaled to the given min/max range, + * following an exponential curve. + * @param {Number} min + * @param {Number} max + * @returns Pattern + */ rangex(min, max) { return this.range(Math.log(min), Math.log(max)).fmap(Math.exp); } - // Assumes source pattern of numbers in range -1..1 + /** + * Assumes a numerical pattern, containing bipolar values in the range -1 .. + * 1. Returns a new pattern with values scaled to the given min/max range. + * @param {Number} min + * @param {Number} max + * @returns Pattern + */ range2(min, max) { return this._fromBipolar().range(min, max); } @@ -683,11 +732,31 @@ export class Pattern { return this._compress(span.begin, span.end); } + /** + * Speed up a pattern by the given factor. + * + * @name fast + * @memberof Pattern + * @param {number | Pattern} factor speed up factor + * @returns Pattern + * @example + * seq(e5, b4, d5, c5).fast(2) + */ _fast(factor) { const fastQuery = this.withQueryTime((t) => t.mul(factor)); return fastQuery.withHapTime((t) => t.div(factor)); } + /** + * Slow down a pattern over the given number of cycles. + * + * @name slow + * @memberof Pattern + * @param {number | Pattern} factor slow down factor + * @returns Pattern + * @example + * seq(e5, b4, d5, c5).slow(2) + */ _slow(factor) { return this._fast(Fraction(1).div(factor)); } @@ -974,8 +1043,11 @@ export class Pattern { return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity })); } - _loopAt(factor,cps=1) { - return this.speed((1/factor)*cps).unit("c").slow(factor) + // move this to controls? (speed and unit are controls) + _loopAt(factor, cps = 1) { + return this.speed((1 / factor) * cps) + .unit('c') + .slow(factor); } } @@ -1215,8 +1287,8 @@ export function slowcatPrime(...pats) { * @return {Pattern} * @example * fastcat(e5, b4, [d5, c5]) - * sequence(e5, b4, [d5, c5]) - * seq(e5, b4, [d5, c5]) + * // sequence(e5, b4, [d5, c5]) + * // seq(e5, b4, [d5, c5]) */ export function fastcat(...pats) { return slowcat(...pats)._fast(pats.length); diff --git a/packages/core/signal.mjs b/packages/core/signal.mjs index 01fdd768..b3eb2d3b 100644 --- a/packages/core/signal.mjs +++ b/packages/core/signal.mjs @@ -22,17 +22,63 @@ export const signal = (func) => { export const isaw = signal((t) => 1 - (t % 1)); export const isaw2 = isaw._toBipolar(); +/** + * A sawtooth signal between 0 and 1. + * + * @return {Pattern} + * @example + * "c3 [eb3,g3] g2 [g3,bb3]".legato(saw.slow(4)) + * @example + * saw.range(0,8).segment(8).scale('C major').slow(4) + * + */ export const saw = signal((t) => t % 1); export const saw2 = saw._toBipolar(); export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t)); + +/** + * A sine signal between 0 and 1. + * + * @return {Pattern} + * @example + * sine.segment(16).range(0,15).slow(2).scale('C minor') + * + */ export const sine = sine2._fromBipolar(); + + +/** + * A cosine signal between 0 and 1. + * + * @return {Pattern} + * @example + * stack(sine,cosine).segment(16).range(0,15).slow(2).scale('C minor') + * + */ export const cosine = sine._early(Fraction(1).div(4)); export const cosine2 = sine2._early(Fraction(1).div(4)); + +/** + * A square signal between 0 and 1. + * + * @return {Pattern} + * @example + * square.segment(2).range(0,7).scale('C minor') + * + */ export const square = signal((t) => Math.floor((t * 2) % 2)); export const square2 = square._toBipolar(); +/** + * A triangle signal between 0 and 1. + * + * @return {Pattern} + * @example + * triangle.segment(2).range(0,7).scale('C minor') + * + */ export const tri = fastcat(isaw, saw); export const tri2 = fastcat(isaw2, saw2); diff --git a/packages/osc/osc.mjs b/packages/osc/osc.mjs index 4d4ed55b..e3b12823 100644 --- a/packages/osc/osc.mjs +++ b/packages/osc/osc.mjs @@ -12,17 +12,25 @@ comm.open(); const latency = 0.1; let startedAt = -1; +/** + * + * Sends each hap as an OSC message, which can be picked up by SuperCollider or any other OSC-enabled software. + * + * @name osc + * @memberof Pattern + * @returns Pattern + */ Pattern.prototype.osc = function () { return this._withHap((hap) => { const onTrigger = (time, hap, currentTime, cps, cycle, delta) => { // time should be audio time of onset // currentTime should be current time of audio context (slightly before time) if (startedAt < 0) { - startedAt = Date.now() - (currentTime * 1000); + startedAt = Date.now() - currentTime * 1000; } const controls = Object.assign({}, { cps: cps, cycle: cycle, delta: delta }, hap.value); const keyvals = Object.entries(controls).flat(); - const ts = Math.floor(startedAt + ((time + latency) * 1000)); + const ts = Math.floor(startedAt + (time + latency) * 1000); const message = new OSC.Message('/dirt/play', ...keyvals); const bundle = new OSC.Bundle([message], ts); bundle.timestamp(ts); // workaround for https://github.com/adzialocha/osc-js/issues/60 diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs index 05979d5e..10140e78 100644 --- a/packages/tonal/tonal.mjs +++ b/packages/tonal/tonal.mjs @@ -42,6 +42,38 @@ function scaleOffset(scale, offset, note) { } // Pattern.prototype._transpose = function (intervalOrSemitones: string | number) { +/** + * Change the pitch of each value by the given amount. Expects numbers or note strings as values. + * The amount can be given as a number of semitones or as a string in interval short notation. + * If you don't care about enharmonic correctness, just use numbers. Otherwise, pass the interval of + * the form: ST where S is the degree number and T the type of interval with + * + * - M = major + * - m = minor + * - P = perfect + * - A = augmented + * - d = diminished + * + * Examples intervals: + * + * - 1P = unison + * - 3M = major third + * - 3m = minor third + * - 4P = perfect fourth + * - 4A = augmented fourth + * - 5P = perfect fifth + * - 5d = diminished fifth + * + * @param {string | number} amount Either number of semitones or interval string. + * @returns Pattern + * @memberof Pattern + * @name transpose + * @example + * "c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).transpose(0) + * @example + * "c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).transpose(0) + */ + Pattern.prototype._transpose = function (intervalOrSemitones) { return this._withHap((hap) => { const interval = !isNaN(Number(intervalOrSemitones)) @@ -63,6 +95,20 @@ Pattern.prototype._transpose = function (intervalOrSemitones) { // e.g. `stack(c3).superimpose(transpose(slowcat(7, 5)))` or // or even `stack(c3).superimpose(transpose.slowcat(7, 5))` or +/** + * Transposes notes inside the scale by the number of steps. + * Expected to be called on a Pattern which already has a {@link Pattern#scale} + * + * @memberof Pattern + * @name scaleTranspose + * @param {offset} offset number of steps inside the scale + * @returns Pattern + * @example + * "-8 [2,4,6]" + * .scale('C4 bebop major') + * .scaleTranspose("<0 -1 -2 -3 -4 -5 -6 -4>") + */ + Pattern.prototype._scaleTranspose = function (offset /* : number | string */) { return this._withHap((hap) => { if (!hap.context.scale) { @@ -74,6 +120,25 @@ Pattern.prototype._scaleTranspose = function (offset /* : number | string */) { return hap.withValue(() => scaleOffset(hap.context.scale, Number(offset), hap.value)); }); }; + +/** + * Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like {@link Pattern#scaleTranspose}. + * + * The scale name has the form "TO? N" wher + * + * - T = Tonic + * - O = Octave (optional, defaults to 3) + * - N = Name of scale, available names can be found [here](https://github.com/tonaljs/tonal/blob/main/packages/scale-type/data.ts). + * + * @memberof Pattern + * @name scale + * @param {string} scale Name of scale + * @returns Pattern + * @example + * "0 2 4 6 4 2" + * .scale(seq('C2 major', 'C2 minor').slow(2)) + */ + Pattern.prototype._scale = function (scale /* : string */) { return this._withHap((hap) => { let note = hap.value; diff --git a/packages/tonal/voicings.mjs b/packages/tonal/voicings.mjs index 5859c3bc..046fa02b 100644 --- a/packages/tonal/voicings.mjs +++ b/packages/tonal/voicings.mjs @@ -31,6 +31,18 @@ Pattern.prototype.fmapNested = function (func) { ); }; +/** + * Turns chord symbols into voicings, using the smoothest voice leading possible. + * Uses [chord-voicings package](https://github.com/felixroos/chord-voicings#chord-voicings). + * + * @name voicings + * @memberof Pattern + * @param {range} range note range for possible voicings (optional, defaults to `['F3', 'A4']`) + * @returns Pattern + * @example + * stack("".voicings(), "") + */ + Pattern.prototype.voicings = function (range) { let lastVoicing; if (!range?.length) { diff --git a/tutorial/ApiDoc.jsx b/tutorial/ApiDoc.jsx new file mode 100644 index 00000000..ef9a35fb --- /dev/null +++ b/tutorial/ApiDoc.jsx @@ -0,0 +1,60 @@ +import React, { Fragment } from 'react'; +import { docs } from '../doc.json'; +import { MiniRepl } from './MiniRepl'; + +const visible = window.location.href.includes('?api=true'); + +function ApiDoc() { + if (!visible) { + return ( +

+ There remaining function documentation is a work in progress, but you can preview it by clicking{' '} + here. Beware that everything is not properly ordered from this point. +

+ ); + } + // console.log('docJson', docs); + return ( +
+

+ The following Chapter is autogenerated from the jsdoc comments in the source files.{' '} + hide. Beware that everything is not properly ordered from this point. +

+ {docs + .filter((item) => !item.name?.startsWith('_') && item.kind !== 'package') + .map((item, i) => ( + + {' '} +

+ {item.memberof && item.memberof !== item.name ? `${item.memberof}.` : ''} + {item.name} +

+
{ + // console.log(_, 'a', a, 'b', b); + return `${a}${b ? `#${b}` : ''}`; + }), + }} + /> + {!!item.params?.length &&

Parameters

} +
    + {item.params?.map((param, i) => ( +
  • + {param.name} ({param.type?.names?.join('|')}): {param.description?.replace(/(<([^>]+)>)/gi, '')} +
  • + ))} +
+ {item.examples?.length &&

Examples

} +
+ {item.examples?.map((example, k) => ( + + ))} +
+ + ))} +
+ ); +} + +export default ApiDoc; diff --git a/tutorial/MiniRepl.jsx b/tutorial/MiniRepl.jsx index 866e1c7f..a01a2f8b 100644 --- a/tutorial/MiniRepl.jsx +++ b/tutorial/MiniRepl.jsx @@ -1,6 +1,7 @@ import { Tone } from '@strudel.cycles/tone'; import { evalScope } from '@strudel.cycles/eval'; import { MiniRepl as _MiniRepl } from '@strudel.cycles/react'; +import controls from '@strudel.cycles/core/controls.mjs'; export const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.Destination).set({ oscillator: { type: 'triangle' }, @@ -11,6 +12,7 @@ export const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone. evalScope( Tone, + controls, import('@strudel.cycles/core'), import('@strudel.cycles/tone'), import('@strudel.cycles/tonal'), @@ -18,6 +20,7 @@ evalScope( import('@strudel.cycles/midi'), import('@strudel.cycles/xen'), import('@strudel.cycles/webaudio'), + import('@strudel.cycles/osc'), ); export function MiniRepl({ tune }) { diff --git a/tutorial/Tutorial.jsx b/tutorial/Tutorial.jsx index 2e77a327..f41489a4 100644 --- a/tutorial/Tutorial.jsx +++ b/tutorial/Tutorial.jsx @@ -6,7 +6,8 @@ This program is free software: you can redistribute it and/or modify it under th import React from 'react'; import ReactDOM from 'react-dom'; -import Tutorial from './tutorial.mdx'; +import Tutorial from './tutorial.rendered.mdx'; +// import ApiDoc from './ApiDoc'; import './style.scss'; import '@strudel.cycles/react/dist/style.css'; @@ -30,6 +31,7 @@ ReactDOM.render(
+ {/* */}
, diff --git a/tutorial/package-lock.json b/tutorial/package-lock.json index de2d597f..42f547fa 100644 --- a/tutorial/package-lock.json +++ b/tutorial/package-lock.json @@ -21,6 +21,7 @@ "autoprefixer": "^10.4.7", "install": "^0.13.0", "npm": "^8.10.0", + "nunjucks": "^3.2.3", "postcss": "^8.4.13", "rehype-autolink-headings": "^6.1.1", "rehype-slug": "^5.0.1", @@ -795,6 +796,12 @@ "semver": "bin/semver.js" } }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true + }, "node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -858,6 +865,12 @@ "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", "dev": true }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, "node_modules/autoprefixer": { "version": "10.4.7", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", @@ -1146,6 +1159,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", @@ -4825,6 +4847,31 @@ "inBundle": true, "license": "ISC" }, + "node_modules/nunjucks": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.3.tgz", + "integrity": "sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ==", + "dev": true, + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6992,6 +7039,12 @@ } } }, + "a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true + }, "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -7040,6 +7093,12 @@ "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", "dev": true }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, "autoprefixer": { "version": "10.4.7", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", @@ -7224,6 +7283,12 @@ "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", "dev": true }, + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + }, "convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", @@ -9740,6 +9805,17 @@ } } }, + "nunjucks": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.3.tgz", + "integrity": "sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ==", + "dev": true, + "requires": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", diff --git a/tutorial/package.json b/tutorial/package.json index 5a524a84..cdee3c3a 100644 --- a/tutorial/package.json +++ b/tutorial/package.json @@ -3,10 +3,12 @@ "private": true, "version": "0.0.0", "scripts": { - "dev": "vite", + "dev": "npm run render && vite", "start": "vite", - "build": "vite build", - "preview": "vite preview" + "build": "npm run render && vite build", + "preview": "vite preview", + "jsdoc-json": "jsdoc ../packages/ --template ../node_modules/jsdoc-json --destination ../doc.json -c ../jsdoc.config.json", + "render": "npm run jsdoc-json && node ./render.js > tutorial.rendered.mdx" }, "type": "module", "dependencies": { @@ -23,6 +25,7 @@ "autoprefixer": "^10.4.7", "install": "^0.13.0", "npm": "^8.10.0", + "nunjucks": "^3.2.3", "postcss": "^8.4.13", "rehype-autolink-headings": "^6.1.1", "rehype-slug": "^5.0.1", diff --git a/tutorial/render.js b/tutorial/render.js new file mode 100644 index 00000000..38b24020 --- /dev/null +++ b/tutorial/render.js @@ -0,0 +1,49 @@ +import nunjucks from 'nunjucks'; +import jsdoc from '../doc.json' assert { type: 'json' }; + +// TODO: load tutorial.mdx and append rendered api.mdx to the bottom (to make sure TOC works) +// TODO: split + +const env = nunjucks.configure('.', { autoescape: false }); + +const docs = jsdoc.docs.reduce((acc, obj) => Object.assign(acc, { [obj.longname]: obj }), {}); + +function renderAsMDX(name) { + const item = docs[name]; + if (!item) { + console.warn('Not found: ' + name); + return ''; + } + return `### ${item.longname} + +${item.description.replaceAll(/\{\@link ([a-zA-Z]+)?\#?([a-zA-Z]*)\}/g, (_, a, b) => { + // console.log(_, 'a', a, 'b', b); + return `${a}${b ? `#${b}` : ''}`; +})} + +${!!item.params?.length ? '**Parameters**' : ''} + +${ + item.params + ?.map( + (param, i) => + `- ${param.name} (${param.type?.names?.join('|')}): ${param.description?.replace(/(<([^>]+)>)/gi, '')}`, + ) + .join('\n') || '' +} + +${ + item.examples?.length + ? `**Examples** + +
+ ${item.examples?.map((example, k) => ``).join('\n\n')} +
` + : '' +}`; +} + +env.addFilter('jsdoc', renderAsMDX); + +const rendered = nunjucks.render('tutorial.mdx', { docs }); +console.log(rendered); diff --git a/tutorial/tutorial.mdx b/tutorial/tutorial.mdx index 503b682a..077d6f6d 100644 --- a/tutorial/tutorial.mdx +++ b/tutorial/tutorial.mdx @@ -693,3 +693,199 @@ If you want to contribute in another way, either - [fork strudel repo on GitHub](https://github.com/tidalcycles/strudel) - [Join the Discord Channel](https://discord.gg/remJ6gQA) - [play with the Strudel REPL](https://strudel.tidalcycles.org/) + +
+
+ +# API Docs + +The following is generated from the source documentation. + +## Pattern Factories + +The following functions will return a pattern. We will see later what that means. + +{{ 'pure' | jsdoc }} + +{{ 'slowcat' | jsdoc }} + +{{ 'fastcat' | jsdoc }} + +{{ 'stack' | jsdoc }} + +{{ 'timeCat' | jsdoc }} + +{{ 'polyrhythm' | jsdoc }} + +## Pattern Modifiers + +{{ 'Pattern.slow' | jsdoc }} + +{{ 'Pattern.fast' | jsdoc }} + +{{ 'Pattern.early' | jsdoc }} + +{{ 'Pattern.late' | jsdoc }} + +{{ 'Pattern.rev' | jsdoc }} + +{{ 'Pattern.legato' | jsdoc }} + +## Continuous Signals + +Signals are patterns with continuous values, meaning they have theoretically infinite steps. +They can provide streams of numbers that can be sampled at discrete points in time. + +{{ 'Pattern.range' | jsdoc }} + +{{ 'saw' | jsdoc }} + +{{ 'saw2' | jsdoc }} + +{{ 'sine' | jsdoc }} + +{{ 'sine2' | jsdoc }} + +{{ 'cosine' | jsdoc }} + +{{ 'cosine2' | jsdoc }} + +{{ 'tri' | jsdoc }} + +{{ 'tri2' | jsdoc }} + +{{ 'square' | jsdoc }} + +{{ 'square2' | jsdoc }} + +## Using Superdirt via OSC + +In mainline tidal, the actual sound is generated via Superdirt, which runs inside Supercollider. +Strudel also supports using Superdirt as a backend, although it requires some developer tooling to run. + +### Getting Started + +Getting Superdirt to work with Strudel, you need to + +1. install SuperCollider + sc3 plugins, see [Tidal Docs](https://tidalcycles.org/docs/) (Install Tidal) for more info. +2. install [node.js](https://nodejs.org/en/) +3. download [Strudel Repo](https://github.com/tidalcycles/strudel/) (or git clone, if you have git installed) +4. run `npm i` in the strudel directory +5. run `npm run osc` to start the osc server, which forwards OSC messages from Strudel REPL to SuperCollider + +Now you're all set! + +### Usage + +1. Start SuperCollider, either using SuperCollider IDE or by running `sclang` in a terminal +2. Open the [Strudel REPL](https://strudel.tidalcycles.org/#cygiYmQgc2QiKS5vc2MoKQ%3D%3D) + +...or test it here: + + + +If you now hear sound, congratulations! If not, you can get help on the [#strudel channel in the TidalCycles discord](https://discord.com/invite/HGEdXmRkzT). + +{{ 'Pattern.osc' | jsdoc }} + +# Superdirt Params + +The following functions are specific to SuperDirt and won't work with other Strudel outputs. + +## Basic Types + +{{ 's' | jsdoc }} + +{{ 'n' | jsdoc }} + +{{ 'freq' | jsdoc }} + +{{ 'channel' | jsdoc }} + +{{ 'orbit' | jsdoc }} + +## Filters + +{{ 'cutoff' | jsdoc }} + +{{ 'resonance' | jsdoc }} + +{{ 'hcutoff' | jsdoc }} + +{{ 'hresonance' | jsdoc }} + +{{ 'bandf' | jsdoc }} + +{{ 'bandq' | jsdoc }} + +{{ 'djf' | jsdoc }} + +{{ 'vowel' | jsdoc }} + +## Sample Editing + +{{ 'cut' | jsdoc }} + +{{ 'begin' | jsdoc }} + +{{ 'end' | jsdoc }} + +{{ 'loop' | jsdoc }} + +{{ 'fadeTime' | jsdoc }} + +{{ 'speed' | jsdoc }} + +{{ 'unit' | jsdoc }} + +## Audio Effects + +{{ 'gain' | jsdoc }} + +{{ 'amp' | jsdoc }} + +{{ 'accelerate' | jsdoc }} + +{{ 'crush' | jsdoc }} + +{{ 'coarse' | jsdoc }} + +{{ 'delay' | jsdoc }} + +{{ 'lock' | jsdoc }} + +{{ 'leslie' | jsdoc }} + +{{ 'lrate' | jsdoc }} + +{{ 'lsize' | jsdoc }} + +{{ 'pan' | jsdoc }} + +{{ 'panspan' | jsdoc }} + +{{ 'pansplay' | jsdoc }} + +{{ 'room' | jsdoc }} + +{{ 'size' | jsdoc }} + +{{ 'dry' | jsdoc }} + +{{ 'shape' | jsdoc }} + +{{ 'squiz' | jsdoc }} + +{{ 'waveloss' | jsdoc }} + +{{ 'attack' | jsdoc }} + +{{ 'decay' | jsdoc }} + +## Synth Effects + +{{ 'octave' | jsdoc }} + +{{ 'detune' | jsdoc }} + +{{ 'tremolodepth' | jsdoc }}