mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-13 22:35:15 -04:00
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a9975a2b41 | |||
| 4051fd5241 | |||
| 55ffb59b9c | |||
| b824ad16ae | |||
| 28db6d1fd4 | |||
| dc9cadc979 | |||
| f99b13efc2 | |||
| 0001d9c27b | |||
| d79d122f68 | |||
| 6e61f3cdb6 | |||
| 4993ec4cbf | |||
| 8e5ca57edd | |||
| 107a3acd3a | |||
| 1d887e81ef | |||
| 7f2860eb14 | |||
| 3364b9f05f | |||
| f9ed71fbf8 | |||
| e9ea0bc7cc | |||
| a87daf3d21 | |||
| 784b9c08ec | |||
| 139b5376fc | |||
| a052def314 | |||
| bcce1fa68a | |||
| 9a10cac8e9 | |||
| cf999462b7 | |||
| 9fc084b291 | |||
| cb46dd7840 | |||
| b684e183a0 | |||
| 84e4dde3d7 | |||
| 5f8d028d4f | |||
| e3abdd41c0 | |||
| bce6ffde08 | |||
| 35a3e32238 | |||
| 60b5024f63 | |||
| 4f14ff00d5 | |||
| 3d3130e880 | |||
| 83d542d06a | |||
| 6105d5027d | |||
| 7e34069021 | |||
| b75ca193a2 | |||
| afac1f62ca | |||
| de83805fd9 | |||
| 38b7bcb3d2 | |||
| 62bf9abed3 | |||
| 8ec1d4d034 | |||
| 6981638f70 | |||
| f5823ce981 | |||
| f8750901f0 | |||
| c1fd8c82c6 | |||
| 6e36bdfff7 | |||
| 8dbdd0a9b8 | |||
| f4c0281613 | |||
| f610965f43 | |||
| 17ef84ed70 | |||
| f0cb96dcad | |||
| 99cf256ee2 | |||
| 42d0bfadce | |||
| 22f78fbb2f | |||
| 77076a1c3e | |||
| a1d31df556 | |||
| f9d0e154e8 | |||
| 9ffd0e496f | |||
| 550d7ff6cb | |||
| 726e5ef14a | |||
| cc15e3cd36 | |||
| 2fa8ed1424 | |||
| b7827cb89f | |||
| 29fd541f1f | |||
| 0830a9df69 | |||
| 4159c8394d | |||
| 466bf819d8 | |||
| 7e4cbefc8f | |||
| 2483c673a4 | |||
| 69360b3ec8 | |||
| 96d0f2053e | |||
| b952e4c735 | |||
| a4212589e5 | |||
| ee1a894f3b | |||
| c62428ca27 | |||
| d516d765d5 | |||
| 5032b4e966 | |||
| a4d7803d43 | |||
| 4a395f372d | |||
| c754dab1ef | |||
| df54404733 |
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"devToolbar": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,13 @@ function defineTags(dictionary) {
|
||||
doclet.synonyms = doclet.synonyms_text.split(/[ ,]+/);
|
||||
},
|
||||
});
|
||||
|
||||
dictionary.defineTag('tags', {
|
||||
mustHaveValue: true,
|
||||
onTagged: function (doclet, tag) {
|
||||
doclet.tags = tag.value.split(/[ ,]+/);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { defineTags: defineTags };
|
||||
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
0 silly argv {
|
||||
0 silly argv _: [ 'version' ],
|
||||
0 silly argv private: false,
|
||||
0 silly argv lernaVersion: '8.1.9',
|
||||
0 silly argv '$0': 'node_modules/lerna/dist/cli.js'
|
||||
0 silly argv }
|
||||
1 notice cli v8.1.9
|
||||
2 verbose packageConfigs Explicit "packages" configuration found in lerna.json. Resolving packages using the configured glob(s): ["packages/*"]
|
||||
3 verbose rootPath /Users/jaderose/Documents/Github/cstrudel/strudel
|
||||
4 info versioning independent
|
||||
5 silly isAnythingCommitted
|
||||
6 verbose isAnythingCommitted 1
|
||||
7 silly getCurrentBranch
|
||||
8 verbose currentBranch main
|
||||
9 silly remoteBranchExists
|
||||
10 silly isBehindUpstream
|
||||
11 silly isBehindUpstream main is behind origin/main by 0 commit(s) and ahead by 4
|
||||
12 silly hasTags
|
||||
13 verbose hasTags true
|
||||
14 silly git-describe.sync "@strudel/codemirror@1.2.7-4-ga3ac9646" => {"lastTagName":"@strudel/codemirror@1.2.7","lastVersion":"1.2.7","refCount":"4","sha":"a3ac9646","isDirty":false}
|
||||
15 info Looking for changed packages since @strudel/codemirror@1.2.7
|
||||
16 silly checking diff packages/codemirror
|
||||
17 silly no diff found in @strudel/codemirror
|
||||
18 silly checking diff packages/core
|
||||
19 silly no diff found in @strudel/core
|
||||
20 silly checking diff packages/csound
|
||||
21 silly no diff found in @strudel/csound
|
||||
22 silly checking diff packages/desktopbridge
|
||||
23 silly no diff found in @strudel/desktopbridge
|
||||
24 silly checking diff packages/draw
|
||||
25 silly no diff found in @strudel/draw
|
||||
26 silly checking diff packages/embed
|
||||
27 silly no diff found in @strudel/embed
|
||||
28 silly checking diff packages/gamepad
|
||||
29 silly no diff found in @strudel/gamepad
|
||||
30 silly checking diff packages/hs2js
|
||||
31 silly no diff found in hs2js
|
||||
32 silly checking diff packages/hydra
|
||||
33 silly no diff found in @strudel/hydra
|
||||
34 silly checking diff packages/midi
|
||||
35 silly no diff found in @strudel/midi
|
||||
36 silly checking diff packages/mini
|
||||
37 silly no diff found in @strudel/mini
|
||||
38 silly checking diff packages/mondo
|
||||
39 silly no diff found in mondolang
|
||||
40 silly checking diff packages/mondough
|
||||
41 silly no diff found in @strudel/mondo
|
||||
42 silly checking diff packages/motion
|
||||
43 silly no diff found in @strudel/motion
|
||||
44 silly checking diff packages/mqtt
|
||||
45 silly no diff found in @strudel/mqtt
|
||||
46 silly checking diff packages/osc
|
||||
47 silly found diff in packages/osc/server.js
|
||||
48 verbose filtered diff [ 'packages/osc/server.js' ]
|
||||
49 silly checking diff packages/reference
|
||||
50 silly no diff found in @strudel/reference
|
||||
51 silly checking diff packages/repl
|
||||
52 silly no diff found in @strudel/repl
|
||||
53 silly checking diff packages/sampler
|
||||
54 silly no diff found in @strudel/sampler
|
||||
55 silly checking diff packages/serial
|
||||
56 silly no diff found in @strudel/serial
|
||||
57 silly checking diff packages/soundfonts
|
||||
58 silly no diff found in @strudel/soundfonts
|
||||
59 silly checking diff packages/superdough
|
||||
60 silly found diff in packages/superdough/package.json
|
||||
61 verbose filtered diff [ 'packages/superdough/package.json' ]
|
||||
62 silly checking diff packages/supradough
|
||||
63 silly found diff in packages/supradough/package.json
|
||||
64 verbose filtered diff [ 'packages/supradough/package.json' ]
|
||||
65 silly checking diff packages/tidal
|
||||
66 silly no diff found in @strudel/tidal
|
||||
67 silly checking diff packages/tonal
|
||||
68 silly no diff found in @strudel/tonal
|
||||
69 silly checking diff packages/transpiler
|
||||
70 silly no diff found in @strudel/transpiler
|
||||
71 silly checking diff packages/vite-plugin-bundle-audioworklet
|
||||
72 silly no diff found in vite-plugin-bundle-audioworklet
|
||||
73 silly checking diff packages/web
|
||||
74 silly no diff found in @strudel/web
|
||||
75 silly checking diff packages/webaudio
|
||||
76 silly found diff in packages/webaudio/package.json
|
||||
77 verbose filtered diff [ 'packages/webaudio/package.json' ]
|
||||
78 silly checking diff packages/xen
|
||||
79 silly no diff found in @strudel/xen
|
||||
80 verbose updated @strudel/codemirror
|
||||
81 verbose updated @strudel/csound
|
||||
82 verbose updated @strudel/midi
|
||||
83 verbose updated @strudel/osc
|
||||
84 verbose updated @strudel/repl
|
||||
85 verbose updated @strudel/soundfonts
|
||||
86 verbose updated superdough
|
||||
87 verbose updated supradough
|
||||
88 verbose updated @strudel/web
|
||||
89 verbose updated @strudel/webaudio
|
||||
90 verbose git-describe undefined => "@strudel/codemirror@1.2.7-4-ga3ac9646"
|
||||
91 silly git-describe parsed => {"lastTagName":"@strudel/codemirror@1.2.7","lastVersion":"1.2.7","refCount":"4","sha":"a3ac9646","isDirty":false}
|
||||
92 info execute Skipping releases
|
||||
93 silly lifecycle No script for "preversion" in "@strudel/monorepo", continuing
|
||||
94 silly lifecycle No script for "preversion" in "@strudel/osc", continuing
|
||||
95 silly lifecycle No script for "preversion" in "superdough", continuing
|
||||
96 silly lifecycle No script for "preversion" in "supradough", continuing
|
||||
97 verbose version supradough has no lockfile. Skipping lockfile update.
|
||||
98 verbose version @strudel/osc has no lockfile. Skipping lockfile update.
|
||||
99 verbose version superdough has no lockfile. Skipping lockfile update.
|
||||
100 silly lifecycle No script for "version" in "supradough", continuing
|
||||
101 silly lifecycle No script for "version" in "superdough", continuing
|
||||
102 silly lifecycle No script for "preversion" in "@strudel/codemirror", continuing
|
||||
103 silly lifecycle No script for "preversion" in "@strudel/webaudio", continuing
|
||||
104 silly lifecycle No script for "version" in "@strudel/osc", continuing
|
||||
105 verbose version @strudel/webaudio has no lockfile. Skipping lockfile update.
|
||||
106 verbose version @strudel/codemirror has no lockfile. Skipping lockfile update.
|
||||
107 silly lifecycle No script for "version" in "@strudel/codemirror", continuing
|
||||
108 silly lifecycle No script for "version" in "@strudel/webaudio", continuing
|
||||
109 silly lifecycle No script for "preversion" in "@strudel/csound", continuing
|
||||
110 silly lifecycle No script for "preversion" in "@strudel/midi", continuing
|
||||
111 silly lifecycle No script for "preversion" in "@strudel/soundfonts", continuing
|
||||
112 silly lifecycle No script for "preversion" in "@strudel/web", continuing
|
||||
113 verbose version @strudel/csound has no lockfile. Skipping lockfile update.
|
||||
114 verbose version @strudel/midi has no lockfile. Skipping lockfile update.
|
||||
115 verbose version @strudel/soundfonts has no lockfile. Skipping lockfile update.
|
||||
116 verbose version @strudel/web has no lockfile. Skipping lockfile update.
|
||||
117 silly lifecycle No script for "version" in "@strudel/midi", continuing
|
||||
118 silly lifecycle No script for "version" in "@strudel/csound", continuing
|
||||
119 silly lifecycle No script for "version" in "@strudel/soundfonts", continuing
|
||||
120 silly lifecycle No script for "preversion" in "@strudel/repl", continuing
|
||||
121 verbose version @strudel/repl has no lockfile. Skipping lockfile update.
|
||||
122 silly lifecycle No script for "version" in "@strudel/web", continuing
|
||||
123 silly lifecycle No script for "version" in "@strudel/repl", continuing
|
||||
124 silly lifecycle No script for "version" in "@strudel/monorepo", continuing
|
||||
125 verbose version Updating root pnpm-lock.yaml
|
||||
126 silly version Skipped applying prettier to ignored file: packages/supradough/package.json
|
||||
127 silly version Skipped applying prettier to ignored file: packages/superdough/package.json
|
||||
128 silly version Skipped applying prettier to ignored file: packages/osc/package.json
|
||||
129 silly version Skipped applying prettier to ignored file: packages/codemirror/package.json
|
||||
130 silly version Skipped applying prettier to ignored file: packages/webaudio/package.json
|
||||
131 silly version Skipped applying prettier to ignored file: packages/midi/package.json
|
||||
132 silly version Skipped applying prettier to ignored file: packages/csound/package.json
|
||||
133 silly version Skipped applying prettier to ignored file: packages/soundfonts/package.json
|
||||
134 silly version Skipped applying prettier to ignored file: packages/web/package.json
|
||||
135 silly version Skipped applying prettier to ignored file: packages/repl/package.json
|
||||
136 silly version Skipped applying prettier to ignored file: pnpm-lock.yaml
|
||||
137 silly gitAdd [
|
||||
137 silly gitAdd 'packages/supradough/package.json',
|
||||
137 silly gitAdd 'packages/superdough/package.json',
|
||||
137 silly gitAdd 'packages/osc/package.json',
|
||||
137 silly gitAdd 'packages/codemirror/package.json',
|
||||
137 silly gitAdd 'packages/webaudio/package.json',
|
||||
137 silly gitAdd 'packages/midi/package.json',
|
||||
137 silly gitAdd 'packages/csound/package.json',
|
||||
137 silly gitAdd 'packages/soundfonts/package.json',
|
||||
137 silly gitAdd 'packages/web/package.json',
|
||||
137 silly gitAdd 'packages/repl/package.json',
|
||||
137 silly gitAdd 'pnpm-lock.yaml'
|
||||
137 silly gitAdd ]
|
||||
138 silly gitCommit Publish
|
||||
138 silly gitCommit
|
||||
138 silly gitCommit - @strudel/codemirror@1.2.8
|
||||
138 silly gitCommit - @strudel/csound@1.2.8
|
||||
138 silly gitCommit - @strudel/midi@1.2.8
|
||||
138 silly gitCommit - @strudel/osc@1.3.2
|
||||
138 silly gitCommit - @strudel/repl@1.2.9
|
||||
138 silly gitCommit - @strudel/soundfonts@1.2.8
|
||||
138 silly gitCommit - superdough@1.2.5
|
||||
138 silly gitCommit - supradough@1.2.4
|
||||
138 silly gitCommit - @strudel/web@1.2.8
|
||||
138 silly gitCommit - @strudel/webaudio@1.2.9
|
||||
139 verbose git [
|
||||
139 verbose git 'commit',
|
||||
139 verbose git '-F',
|
||||
139 verbose git '/private/var/folders/hc/yf_zr55547sbcpz5rj7q85sc0000gn/T/3c85b5d4-56ae-40e9-8df7-db2bc1048402/lerna-commit.txt'
|
||||
139 verbose git ]
|
||||
140 silly gitTag @strudel/codemirror@1.2.8 git tag %s -m %s
|
||||
141 verbose git [
|
||||
141 verbose git 'tag',
|
||||
141 verbose git '@strudel/codemirror@1.2.8',
|
||||
141 verbose git '-m',
|
||||
141 verbose git '@strudel/codemirror@1.2.8'
|
||||
141 verbose git ]
|
||||
142 silly gitTag @strudel/csound@1.2.8 git tag %s -m %s
|
||||
143 verbose git [ 'tag', '@strudel/csound@1.2.8', '-m', '@strudel/csound@1.2.8' ]
|
||||
144 silly gitTag @strudel/midi@1.2.8 git tag %s -m %s
|
||||
145 verbose git [ 'tag', '@strudel/midi@1.2.8', '-m', '@strudel/midi@1.2.8' ]
|
||||
146 silly gitTag @strudel/osc@1.3.2 git tag %s -m %s
|
||||
147 verbose git [ 'tag', '@strudel/osc@1.3.2', '-m', '@strudel/osc@1.3.2' ]
|
||||
148 silly gitTag @strudel/repl@1.2.9 git tag %s -m %s
|
||||
149 verbose git [ 'tag', '@strudel/repl@1.2.9', '-m', '@strudel/repl@1.2.9' ]
|
||||
150 silly gitTag @strudel/soundfonts@1.2.8 git tag %s -m %s
|
||||
151 verbose git [
|
||||
151 verbose git 'tag',
|
||||
151 verbose git '@strudel/soundfonts@1.2.8',
|
||||
151 verbose git '-m',
|
||||
151 verbose git '@strudel/soundfonts@1.2.8'
|
||||
151 verbose git ]
|
||||
152 silly gitTag superdough@1.2.5 git tag %s -m %s
|
||||
153 verbose git [ 'tag', 'superdough@1.2.5', '-m', 'superdough@1.2.5' ]
|
||||
154 silly gitTag supradough@1.2.4 git tag %s -m %s
|
||||
155 verbose git [ 'tag', 'supradough@1.2.4', '-m', 'supradough@1.2.4' ]
|
||||
156 silly gitTag @strudel/web@1.2.8 git tag %s -m %s
|
||||
157 verbose git [ 'tag', '@strudel/web@1.2.8', '-m', '@strudel/web@1.2.8' ]
|
||||
158 silly gitTag @strudel/webaudio@1.2.9 git tag %s -m %s
|
||||
159 verbose git [ 'tag', '@strudel/webaudio@1.2.9', '-m', '@strudel/webaudio@1.2.9' ]
|
||||
160 error Error: Command failed with exit code 128: git tag superdough@1.2.5 -m superdough@1.2.5
|
||||
160 error fatal: tag 'superdough@1.2.5' already exists
|
||||
160 error at makeError (/Users/jaderose/Documents/Github/cstrudel/strudel/node_modules/.pnpm/execa@5.0.0/node_modules/execa/lib/error.js:59:11)
|
||||
160 error at handlePromise (/Users/jaderose/Documents/Github/cstrudel/strudel/node_modules/.pnpm/execa@5.0.0/node_modules/execa/index.js:114:26)
|
||||
160 error at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
|
||||
160 error at async Promise.all (index 6)
|
||||
160 error at async VersionCommand.gitCommitAndTagVersionForUpdates (/Users/jaderose/Documents/Github/cstrudel/strudel/node_modules/.pnpm/lerna@8.1.9_encoding@0.1.13/node_modules/lerna/dist/index.js:9957:11)
|
||||
160 error at async VersionCommand.commitAndTagUpdates (/Users/jaderose/Documents/Github/cstrudel/strudel/node_modules/.pnpm/lerna@8.1.9_encoding@0.1.13/node_modules/lerna/dist/index.js:9933:18)
|
||||
160 error at async Promise.all (index 0)
|
||||
@@ -434,6 +434,7 @@ function s4() {
|
||||
/**
|
||||
* Overrides the css of highlighted events. Make sure to use single quotes!
|
||||
* @name markcss
|
||||
* @tag visualization
|
||||
* @example
|
||||
* note("c a f e")
|
||||
* .markcss('text-decoration:underline')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/codemirror",
|
||||
"version": "1.2.8",
|
||||
"version": "1.3.0",
|
||||
"description": "Codemirror Extensions for Strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -117,6 +117,7 @@ export const sliderPlugin = ViewPlugin.fromClass(
|
||||
* Displays a slider widget to allow the user manipulate a value
|
||||
*
|
||||
* @name slider
|
||||
* @tags external_io, visualization
|
||||
* @param {number} value Initial value
|
||||
* @param {number} min Minimum value - optional, defaults to 0
|
||||
* @param {number} max Maximum value - optional, defaults to 1
|
||||
|
||||
Vendored
+1
@@ -198,6 +198,7 @@ export function activateTheme(name) {
|
||||
const themeSettings = settings[name] || settings.strudelTheme;
|
||||
// set css variables
|
||||
themeStyle.innerHTML = `:root {
|
||||
color-scheme: ${themeSettings.light ? 'light' : 'dark'};
|
||||
${Object.entries(themeSettings)
|
||||
// important to override fallback
|
||||
.map(([key, value]) => `--${key}: ${value} !important;`)
|
||||
|
||||
+3
-1
@@ -17,13 +17,15 @@ export const settings = {
|
||||
background: 'white',
|
||||
lineBackground: 'transparent',
|
||||
foreground: deepPurple,
|
||||
muted: deepPurple + '50',
|
||||
caret: '#797977',
|
||||
selection: yellowPink,
|
||||
selectionMatch: '#2B323D',
|
||||
gutterBackground: grey,
|
||||
gutterBackground: pinkAccent,
|
||||
gutterForeground: lightGrey,
|
||||
gutterBorder: 'transparent',
|
||||
lineHighlight: pinkAccent,
|
||||
light: true,
|
||||
};
|
||||
|
||||
export default createTheme({
|
||||
|
||||
+1
@@ -31,6 +31,7 @@ const palette = palettes['Sour Watermelon B'];
|
||||
export const settings = {
|
||||
background: palette[3],
|
||||
foreground: palette[1],
|
||||
muted: palette[1] + '50',
|
||||
caret: palette[0],
|
||||
selection: palette[0],
|
||||
selectionMatch: palette[1],
|
||||
|
||||
@@ -8,6 +8,7 @@ export const settings = {
|
||||
background: '#282b2e',
|
||||
lineBackground: '#282b2e99',
|
||||
foreground: '#a9b7c6',
|
||||
muted: '#a9b7c650',
|
||||
caret: '#00FF00',
|
||||
selection: '#343739',
|
||||
selectionMatch: '#343739',
|
||||
@@ -19,6 +20,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#282b2e',
|
||||
foreground: '#a9b7c6',
|
||||
muted: '#a9b7c650',
|
||||
caret: '#00FF00',
|
||||
selection: '#4e5254',
|
||||
selectionMatch: '#4e5254',
|
||||
|
||||
+1
@@ -12,6 +12,7 @@ export const settings = {
|
||||
background: hex[0],
|
||||
lineBackground: 'transparent',
|
||||
foreground: hex[1],
|
||||
muted: hex[2],
|
||||
selection: hex[2],
|
||||
selectionMatch: hex[0],
|
||||
gutterBackground: hex[0],
|
||||
|
||||
+2
@@ -11,6 +11,7 @@ export const settings = {
|
||||
background: '#272C35',
|
||||
lineBackground: '#272C3599',
|
||||
foreground: 'hsl(220, 14%, 71%)',
|
||||
muted: 'hsl(220, 14%, 41%)',
|
||||
caret: '#797977',
|
||||
selection: '#ffffff30',
|
||||
selectionMatch: '#2B323D',
|
||||
@@ -25,6 +26,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#272C35',
|
||||
foreground: '#9d9b97',
|
||||
muted: 'hsl(220, 14%, 41%)',
|
||||
caret: '#797977',
|
||||
selection: '#3d4c64',
|
||||
selectionMatch: '#3d4c64',
|
||||
|
||||
Vendored
+2
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#21202e',
|
||||
lineBackground: '#21202e99',
|
||||
foreground: '#edecee',
|
||||
muted: '#edecee50',
|
||||
caret: '#a277ff',
|
||||
selection: '#3d375e7f',
|
||||
selectionMatch: '#3d375e7f',
|
||||
@@ -18,6 +19,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#21202e',
|
||||
foreground: '#edecee',
|
||||
muted: '#edecee50',
|
||||
caret: '#a277ff',
|
||||
selection: '#5a51898f',
|
||||
selectionMatch: '#5a51898f',
|
||||
|
||||
+2
@@ -6,6 +6,7 @@ export const settings = {
|
||||
background: '#FFFFFF',
|
||||
lineBackground: '#FFFFFF99',
|
||||
foreground: '#000000',
|
||||
muted: '#00000050',
|
||||
caret: '#FBAC52',
|
||||
selection: '#FFD420',
|
||||
selectionMatch: '#FFD420',
|
||||
@@ -20,6 +21,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#FFFFFF',
|
||||
foreground: '#000000',
|
||||
muted: '#00000050',
|
||||
caret: '#FBAC52',
|
||||
selection: '#FFD420',
|
||||
selectionMatch: '#FFD420',
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@ import { tags as t } from '@lezer/highlight';
|
||||
import { createTheme } from './theme-helper.mjs';
|
||||
export const settings = {
|
||||
background: 'black',
|
||||
foreground: 'white', // whats that?
|
||||
foreground: 'white',
|
||||
muted: '#ffffff50',
|
||||
caret: 'white',
|
||||
selection: '#ffffff20',
|
||||
selectionMatch: '#036dd626',
|
||||
|
||||
+2
-1
@@ -3,7 +3,8 @@ import { createTheme } from './theme-helper.mjs';
|
||||
export const settings = {
|
||||
background: '#051DB5',
|
||||
lineBackground: '#051DB550',
|
||||
foreground: 'white', // whats that?
|
||||
foreground: 'white',
|
||||
muted: '#ffffff50',
|
||||
caret: 'white',
|
||||
selection: 'rgba(128, 203, 196, 0.5)',
|
||||
selectionMatch: '#036dd626',
|
||||
|
||||
@@ -11,6 +11,7 @@ export const settings = {
|
||||
background: hex[0],
|
||||
lineBackground: 'transparent',
|
||||
foreground: hex[2],
|
||||
muted: hex[3],
|
||||
selection: hex[3],
|
||||
selectionMatch: hex[0],
|
||||
gutterBackground: hex[0],
|
||||
|
||||
+2
@@ -9,6 +9,7 @@ export const settings = {
|
||||
background: '#242424',
|
||||
lineBackground: '#24242499',
|
||||
foreground: '#f8f8f2',
|
||||
muted: '#f8f8f250',
|
||||
caret: '#FFFFFF',
|
||||
selection: 'rgba(255, 255, 255, 0.1)',
|
||||
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
||||
@@ -23,6 +24,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#242424',
|
||||
foreground: '#f8f8f2',
|
||||
muted: '#f8f8f250',
|
||||
caret: '#FFFFFF',
|
||||
selection: 'rgba(255, 255, 255, 0.1)',
|
||||
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
||||
|
||||
+2
@@ -11,6 +11,7 @@ export const settings = {
|
||||
background: '#282a36',
|
||||
lineBackground: '#282a3699',
|
||||
foreground: '#f8f8f2',
|
||||
muted: '#f8f8f250',
|
||||
caret: '#f8f8f0',
|
||||
selection: 'rgba(255, 255, 255, 0.1)',
|
||||
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
||||
@@ -27,6 +28,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#282a36',
|
||||
foreground: '#f8f8f2',
|
||||
muted: '#f8f8f250',
|
||||
caret: '#f8f8f0',
|
||||
selection: 'rgba(255, 255, 255, 0.1)',
|
||||
selectionMatch: 'rgba(255, 255, 255, 0.2)',
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ export const settings = {
|
||||
background: '#2a2734',
|
||||
lineBackground: '#2a273499',
|
||||
foreground: '#eeebff',
|
||||
muted: '#eeebff50',
|
||||
caret: '#ffad5c',
|
||||
selection: 'rgba(255, 255, 255, 0.1)',
|
||||
gutterBackground: '#2a2734',
|
||||
@@ -22,6 +23,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#2a2734',
|
||||
foreground: '#6c6783',
|
||||
muted: '#eeebff50',
|
||||
caret: '#ffad5c',
|
||||
selection: '#9a86fd',
|
||||
selectionMatch: '#9a86fd',
|
||||
|
||||
+2
@@ -6,6 +6,7 @@ export const settings = {
|
||||
background: '#fff',
|
||||
lineBackground: '#ffffff99',
|
||||
foreground: '#000',
|
||||
muted: '#00000050',
|
||||
caret: '#FFFFFF',
|
||||
selection: '#d7d4f0',
|
||||
selectionMatch: '#d7d4f0',
|
||||
@@ -20,6 +21,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#fff',
|
||||
foreground: '#000',
|
||||
muted: '#00000050',
|
||||
caret: '#FFFFFF',
|
||||
selection: '#d7d4f0',
|
||||
selectionMatch: '#d7d4f0',
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ export const settings = {
|
||||
background: hex[0],
|
||||
lineBackground: 'transparent',
|
||||
foreground: hex[10],
|
||||
muted: hex[7],
|
||||
selection: hex[8],
|
||||
selectionMatch: hex[0],
|
||||
gutterBackground: hex[3],
|
||||
|
||||
+2
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#0d1117',
|
||||
lineBackground: '#0d111799',
|
||||
foreground: '#c9d1d9',
|
||||
muted: '#c9d1d950',
|
||||
caret: '#c9d1d9',
|
||||
selection: '#003d73',
|
||||
selectionMatch: '#003d73',
|
||||
@@ -16,6 +17,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#0d1117',
|
||||
foreground: '#c9d1d9',
|
||||
muted: '#c9d1d950',
|
||||
caret: '#c9d1d9',
|
||||
selection: '#003d73',
|
||||
selectionMatch: '#003d73',
|
||||
|
||||
+2
@@ -6,6 +6,7 @@ export const settings = {
|
||||
background: '#fff',
|
||||
lineBackground: '#ffffff99',
|
||||
foreground: '#24292e',
|
||||
muted: '#24292e50',
|
||||
selection: '#BBDFFF',
|
||||
selectionMatch: '#BBDFFF',
|
||||
gutterBackground: '#fff',
|
||||
@@ -17,6 +18,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#fff',
|
||||
foreground: '#24292e',
|
||||
muted: '#24292e50',
|
||||
selection: '#BBDFFF',
|
||||
selectionMatch: '#BBDFFF',
|
||||
gutterBackground: '#fff',
|
||||
|
||||
+1
@@ -13,6 +13,7 @@ export const settings = {
|
||||
background: hex[0],
|
||||
lineBackground: 'transparent',
|
||||
foreground: hex[2],
|
||||
muted: hex[2] + '50',
|
||||
selection: hex[4],
|
||||
selectionMatch: hex[0],
|
||||
gutterBackground: hex[0],
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ export const settings = {
|
||||
background: '#282828',
|
||||
lineBackground: '#28282899',
|
||||
foreground: '#ebdbb2',
|
||||
muted: '#ebdbb250',
|
||||
caret: '#ebdbb2',
|
||||
selection: '#bdae93',
|
||||
selectionMatch: '#bdae93',
|
||||
@@ -23,6 +24,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#282828',
|
||||
foreground: '#ebdbb2',
|
||||
muted: '#ebdbb250',
|
||||
caret: '#ebdbb2',
|
||||
selection: '#b99d555c',
|
||||
selectionMatch: '#b99d555c',
|
||||
|
||||
+2
@@ -11,6 +11,7 @@ export const settings = {
|
||||
background: '#fbf1c7',
|
||||
lineBackground: '#fbf1c799',
|
||||
foreground: '#3c3836',
|
||||
muted: '#3c383650',
|
||||
caret: '#af3a03',
|
||||
selection: '#ebdbb2',
|
||||
selectionMatch: '#bdae93',
|
||||
@@ -25,6 +26,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#fbf1c7',
|
||||
foreground: '#3c3836',
|
||||
muted: '#3c383650',
|
||||
caret: '#af3a03',
|
||||
selection: '#bdae9391',
|
||||
selectionMatch: '#bdae9391',
|
||||
|
||||
+2
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#212121',
|
||||
lineBackground: '#21212199',
|
||||
foreground: '#bdbdbd',
|
||||
muted: '#bdbdbd50',
|
||||
caret: '#a0a4ae',
|
||||
selection: '#d7d4f0',
|
||||
selectionMatch: '#d7d4f0',
|
||||
@@ -19,6 +20,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#212121',
|
||||
foreground: '#bdbdbd',
|
||||
muted: '#bdbdbd50',
|
||||
caret: '#a0a4ae',
|
||||
selection: '#d7d4f063',
|
||||
selectionMatch: '#d7d4f063',
|
||||
|
||||
+3
-1
@@ -5,7 +5,8 @@ export const settings = {
|
||||
light: true,
|
||||
background: '#FAFAFA',
|
||||
lineBackground: '#FAFAFA99',
|
||||
foreground: '#90A4AE',
|
||||
foreground: '#6182B8',
|
||||
muted: '#6182B850',
|
||||
caret: '#272727',
|
||||
selection: '#80CBC440',
|
||||
selectionMatch: '#FAFAFA',
|
||||
@@ -19,6 +20,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#FAFAFA',
|
||||
foreground: '#90A4AE',
|
||||
muted: '#6182B850',
|
||||
caret: '#272727',
|
||||
selection: '#80CBC440',
|
||||
selectionMatch: '#80CBC440',
|
||||
|
||||
+2
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#272822',
|
||||
lineBackground: '#27282299',
|
||||
foreground: '#FFFFFF',
|
||||
muted: '#FFFFFF50',
|
||||
caret: '#FFFFFF',
|
||||
selection: '#49483E',
|
||||
selectionMatch: '#49483E',
|
||||
@@ -18,6 +19,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#272822',
|
||||
foreground: '#FFFFFF',
|
||||
muted: '#FFFFFF50',
|
||||
caret: '#FFFFFF',
|
||||
selection: '#49483E',
|
||||
selectionMatch: '#49483E',
|
||||
|
||||
+2
@@ -6,6 +6,7 @@ export const settings = {
|
||||
background: '#f2f1f8',
|
||||
lineBackground: '#f2f1f899',
|
||||
foreground: '#0c006b',
|
||||
muted: '#0c006b50',
|
||||
caret: '#5c49e9',
|
||||
selection: '#d5d1f2',
|
||||
selectionMatch: '#d5d1f2',
|
||||
@@ -19,6 +20,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#f2f1f8',
|
||||
foreground: '#0c006b',
|
||||
muted: '#0c006b50',
|
||||
caret: '#5c49e9',
|
||||
selection: '#d5d1f2',
|
||||
selectionMatch: '#d5d1f2',
|
||||
|
||||
Vendored
+2
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#2e3440',
|
||||
lineBackground: '#2e344099',
|
||||
foreground: '#FFFFFF',
|
||||
muted: '#FFFFFF50',
|
||||
caret: '#FFFFFF',
|
||||
selection: '#3b4252',
|
||||
selectionMatch: '#e5e9f0',
|
||||
@@ -20,6 +21,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#2e3440',
|
||||
foreground: '#FFFFFF',
|
||||
muted: '#FFFFFF50',
|
||||
caret: '#FFFFFF',
|
||||
selection: '#00000073',
|
||||
selectionMatch: '#00000073',
|
||||
|
||||
+1
@@ -13,6 +13,7 @@ export const settings = {
|
||||
background: hex[0],
|
||||
lineBackground: 'transparent',
|
||||
foreground: hex[2],
|
||||
muted: hex[2] + '50',
|
||||
selection: hex[4],
|
||||
selectionMatch: hex[0],
|
||||
gutterBackground: hex[0],
|
||||
|
||||
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#002b36',
|
||||
lineBackground: '#002b3699',
|
||||
foreground: '#93a1a1',
|
||||
muted: '#93a1a150',
|
||||
caret: '#839496',
|
||||
selection: '#173541',
|
||||
selectionMatch: '#aafe661a',
|
||||
@@ -45,6 +46,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: c.background,
|
||||
foreground: c.foreground,
|
||||
muted: c.muted,
|
||||
caret: c.cursor,
|
||||
selection: c.selection,
|
||||
selectionMatch: c.selection,
|
||||
|
||||
@@ -8,6 +8,7 @@ export const settings = {
|
||||
background: '#fdf6e3',
|
||||
lineBackground: '#fdf6e399',
|
||||
foreground: '#657b83',
|
||||
muted: '#657b8350',
|
||||
caret: '#586e75',
|
||||
selection: '#dfd9c8',
|
||||
selectionMatch: '#dfd9c8',
|
||||
@@ -19,6 +20,7 @@ export const settings = {
|
||||
const c = {
|
||||
background: '#FDF6E3',
|
||||
foreground: '#657B83',
|
||||
muted: '#657b8350',
|
||||
selection: '#EEE8D5',
|
||||
selectionMatch: '#EEE8D5',
|
||||
cursor: '#657B83',
|
||||
|
||||
+1
@@ -13,6 +13,7 @@ export const settings = {
|
||||
background: '#000000',
|
||||
lineBackground: 'transparent',
|
||||
foreground: hex[4],
|
||||
muted: hex[6],
|
||||
selection: hex[6],
|
||||
gutterBackground: hex[0],
|
||||
gutterForeground: hex[5],
|
||||
|
||||
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#222',
|
||||
lineBackground: '#22222299',
|
||||
foreground: '#fff',
|
||||
muted: '#8a919966',
|
||||
caret: '#ffcc00',
|
||||
selection: 'rgba(128, 203, 196, 0.5)',
|
||||
selectionMatch: '#036dd626',
|
||||
|
||||
+2
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#303841',
|
||||
lineBackground: '#30384199',
|
||||
foreground: '#FFFFFF',
|
||||
muted: '#FFFFFF50',
|
||||
caret: '#FBAC52',
|
||||
selection: '#4C5964',
|
||||
selectionMatch: '#3A546E',
|
||||
@@ -18,6 +19,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#303841',
|
||||
foreground: '#FFFFFF',
|
||||
muted: '#FFFFFF50',
|
||||
caret: '#FBAC52',
|
||||
selection: '#4C5964',
|
||||
selectionMatch: '#3A546E',
|
||||
|
||||
+2
-1
@@ -9,7 +9,8 @@ let colorD = '#f8fc55';
|
||||
|
||||
export const settings = {
|
||||
background: '#000000',
|
||||
foreground: colorA, // whats that?
|
||||
foreground: colorA,
|
||||
muted: colorA + '50',
|
||||
caret: colorC,
|
||||
selection: colorD,
|
||||
selectionMatch: colorA,
|
||||
|
||||
+4
-2
@@ -4,7 +4,8 @@ import { createTheme } from './theme-helper.mjs';
|
||||
export const settings = {
|
||||
background: '#24283b',
|
||||
lineBackground: '#24283b99',
|
||||
foreground: '#7982a9',
|
||||
foreground: '#f9f2f9',
|
||||
muted: '#f9f2f950',
|
||||
caret: '#c0caf5',
|
||||
selection: '#6f7bb630',
|
||||
selectionMatch: '#1f2335',
|
||||
@@ -18,7 +19,8 @@ export default createTheme({
|
||||
theme: 'dark',
|
||||
settings: {
|
||||
background: '#24283b',
|
||||
foreground: '#7982a9',
|
||||
foreground: '#f9f2f9',
|
||||
muted: '#f9f2f950',
|
||||
caret: '#c0caf5',
|
||||
selection: '#6f7bb630',
|
||||
selectionMatch: '#343b5f',
|
||||
|
||||
+4
-2
@@ -4,7 +4,8 @@ import { createTheme } from './theme-helper.mjs';
|
||||
export const settings = {
|
||||
background: '#1a1b26',
|
||||
lineBackground: '#1a1b2699',
|
||||
foreground: '#787c99',
|
||||
foreground: '#f8fcf9',
|
||||
muted: '#f8fcf950',
|
||||
caret: '#c0caf5',
|
||||
selection: '#515c7e40',
|
||||
selectionMatch: '#16161e',
|
||||
@@ -18,7 +19,8 @@ export default createTheme({
|
||||
theme: 'dark',
|
||||
settings: {
|
||||
background: '#1a1b26',
|
||||
foreground: '#787c99',
|
||||
foreground: '#f8fcf9',
|
||||
muted: '#f8fcf950',
|
||||
caret: '#c0caf5',
|
||||
selection: '#515c7e40',
|
||||
selectionMatch: '#16161e',
|
||||
|
||||
@@ -6,6 +6,7 @@ export const settings = {
|
||||
background: '#e1e2e7',
|
||||
lineBackground: '#e1e2e799',
|
||||
foreground: '#3760bf',
|
||||
muted: '#3760bf50',
|
||||
caret: '#3760bf',
|
||||
selection: '#99a7df',
|
||||
selectionMatch: '#99a7df',
|
||||
@@ -20,6 +21,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#e1e2e7',
|
||||
foreground: '#3760bf',
|
||||
muted: '#3760bf50',
|
||||
caret: '#3760bf',
|
||||
selection: '#99a7df',
|
||||
selectionMatch: '#99a7df',
|
||||
|
||||
+2
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#1e1e1e',
|
||||
lineBackground: '#1e1e1e99',
|
||||
foreground: '#fff',
|
||||
muted: '#ffffff50',
|
||||
caret: '#c6c6c6',
|
||||
selection: '#6199ff2f',
|
||||
selectionMatch: '#72a1ff59',
|
||||
@@ -19,6 +20,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#1e1e1e',
|
||||
foreground: '#fff',
|
||||
muted: '#ffffff50',
|
||||
caret: '#c6c6c6',
|
||||
selection: '#6199ff2f',
|
||||
selectionMatch: '#72a1ff59',
|
||||
|
||||
+2
@@ -5,6 +5,7 @@ export const settings = {
|
||||
background: '#ffffff',
|
||||
lineBackground: '#ffffff50',
|
||||
foreground: '#383a42',
|
||||
muted: '#383a4250',
|
||||
caret: '#000',
|
||||
selection: '#add6ff',
|
||||
selectionMatch: '#a8ac94',
|
||||
@@ -20,6 +21,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#ffffff',
|
||||
foreground: '#383a42',
|
||||
muted: '#383a4250',
|
||||
caret: '#000',
|
||||
selection: '#add6ff',
|
||||
selectionMatch: '#a8ac94',
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@ import { tags as t } from '@lezer/highlight';
|
||||
import { createTheme } from './theme-helper.mjs';
|
||||
export const settings = {
|
||||
background: 'white',
|
||||
foreground: 'black', // whats that?
|
||||
foreground: 'black',
|
||||
muted: '#00000050',
|
||||
caret: 'black',
|
||||
selection: 'rgba(128, 203, 196, 0.5)',
|
||||
selectionMatch: '#ffffff26',
|
||||
|
||||
+2
@@ -6,6 +6,7 @@ export const settings = {
|
||||
background: '#fff',
|
||||
lineBackground: '#ffffff99',
|
||||
foreground: '#3D3D3D',
|
||||
muted: '#3D3D3D50',
|
||||
selection: '#BBDFFF',
|
||||
selectionMatch: '#BBDFFF',
|
||||
gutterBackground: '#fff',
|
||||
@@ -18,6 +19,7 @@ export default createTheme({
|
||||
settings: {
|
||||
background: '#fff',
|
||||
foreground: '#3D3D3D',
|
||||
muted: '#3D3D3D50',
|
||||
selection: '#BBDFFF',
|
||||
selectionMatch: '#BBDFFF',
|
||||
gutterBackground: '#fff',
|
||||
|
||||
+237
-29
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@ import Fraction, { gcd } from './fraction.mjs';
|
||||
* - "-" hold previous value
|
||||
* - "." silence
|
||||
*
|
||||
* @tags visualization
|
||||
* @param {Pattern} pattern the pattern to use
|
||||
* @param {number} chars max number of characters (approximately)
|
||||
* @returns string
|
||||
|
||||
@@ -61,6 +61,7 @@ export const bjorklund = function (ons, steps) {
|
||||
*
|
||||
* @memberof Pattern
|
||||
* @name euclid
|
||||
* @tags temporal
|
||||
* @param {number} pulses the number of onsets/beats
|
||||
* @param {number} steps the number of steps to fill
|
||||
* @returns Pattern
|
||||
@@ -73,6 +74,7 @@ export const bjorklund = function (ons, steps) {
|
||||
* Like `euclid`, but has an additional parameter for 'rotating' the resulting sequence.
|
||||
* @memberof Pattern
|
||||
* @name euclidRot
|
||||
* @tags temporal
|
||||
* @param {number} pulses the number of onsets/beats
|
||||
* @param {number} steps the number of steps to fill
|
||||
* @param {number} rotation offset in steps
|
||||
@@ -156,6 +158,7 @@ export const { euclidrot, euclidRot } = register(['euclidrot', 'euclidRot'], fun
|
||||
* so there will be no gaps.
|
||||
* @name euclidLegato
|
||||
* @memberof Pattern
|
||||
* @tags temporal
|
||||
* @param {number} pulses the number of onsets/beats
|
||||
* @param {number} steps the number of steps to fill
|
||||
* @param rotation offset in steps
|
||||
@@ -187,6 +190,7 @@ export const euclidLegato = register(['euclidLegato'], function (pulses, steps,
|
||||
* the resulting sequence
|
||||
* @name euclidLegatoRot
|
||||
* @memberof Pattern
|
||||
* @tags temporal
|
||||
* @param {number} pulses the number of onsets/beats
|
||||
* @param {number} steps the number of steps to fill
|
||||
* @param {number} rotation offset in steps
|
||||
@@ -208,6 +212,7 @@ export const euclidLegatoRot = register(['euclidLegatoRot'], function (pulses, s
|
||||
* @name euclidish
|
||||
* @synonyms eish
|
||||
* @memberof Pattern
|
||||
* @tags temporal
|
||||
* @param {number} pulses the number of onsets
|
||||
* @param {number} steps the number of steps to fill
|
||||
* @param {number} groove exists between the extremes of 0 (straight euclidian) and 1 (straight pulse)
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
},
|
||||
"homepage": "https://strudel.cc",
|
||||
"dependencies": {
|
||||
"@kabelsalat/web": "^0.4.1",
|
||||
"fraction.js": "^5.2.1"
|
||||
},
|
||||
"gitHead": "0e26d4e741500f5bae35b023608f062a794905c2",
|
||||
|
||||
+295
-109
File diff suppressed because it is too large
Load Diff
+29
-14
@@ -28,6 +28,7 @@ const _pick = function (lookup, pat, modulo = true) {
|
||||
|
||||
/** * Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
||||
* Similar to `inhabit`, but maintains the structure of the original patterns.
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -57,6 +58,7 @@ const __pick = register('pick', function (lookup, pat) {
|
||||
* it wraps around, rather than sticking at the maximum value.
|
||||
* For example, if you pick the fifth pattern of a list of three, you'll get the
|
||||
* second one.
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -67,6 +69,7 @@ export const pickmod = register('pickmod', function (lookup, pat) {
|
||||
});
|
||||
|
||||
/** * pickF lets you use a pattern of numbers to pick which function to apply to another pattern.
|
||||
* @tags combiners, functional
|
||||
* @param {Pattern} pat
|
||||
* @param {Pattern} lookup a pattern of indices
|
||||
* @param {function[]} funcs the array of functions from which to pull
|
||||
@@ -75,7 +78,7 @@ export const pickmod = register('pickmod', function (lookup, pat) {
|
||||
* s("bd [rim hh]").pickF("<0 1 2>", [rev,jux(rev),fast(2)])
|
||||
* @example
|
||||
* note("<c2 d2>(3,8)").s("square")
|
||||
* .pickF("<0 2> 1", [jux(rev),fast(2),x=>x.lpf(800)])
|
||||
* .pickF("<0 2> 1", [jux(rev), fast(2), x=>x.lpf(800)])
|
||||
*/
|
||||
export const pickF = register('pickF', function (lookup, funcs, pat) {
|
||||
return pat.apply(pick(lookup, funcs));
|
||||
@@ -83,6 +86,7 @@ export const pickF = register('pickF', function (lookup, funcs, pat) {
|
||||
|
||||
/** * The same as `pickF`, but if you pick a number greater than the size of the functions list,
|
||||
* it wraps around, rather than sticking at the maximum value.
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {Pattern} lookup a pattern of indices
|
||||
* @param {function[]} funcs the array of functions from which to pull
|
||||
@@ -93,6 +97,7 @@ export const pickmodF = register('pickmodF', function (lookup, funcs, pat) {
|
||||
});
|
||||
|
||||
/** * Similar to `pick`, but it applies an outerJoin instead of an innerJoin.
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -103,6 +108,7 @@ export const pickOut = register('pickOut', function (lookup, pat) {
|
||||
|
||||
/** * The same as `pickOut`, but if you pick a number greater than the size of the list,
|
||||
* it wraps around, rather than sticking at the maximum value.
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -112,6 +118,7 @@ export const pickmodOut = register('pickmodOut', function (lookup, pat) {
|
||||
});
|
||||
|
||||
/** * Similar to `pick`, but the choosen pattern is restarted when its index is triggered.
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -122,6 +129,7 @@ export const pickRestart = register('pickRestart', function (lookup, pat) {
|
||||
|
||||
/** * The same as `pickRestart`, but if you pick a number greater than the size of the list,
|
||||
* it wraps around, rather than sticking at the maximum value.
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -138,6 +146,7 @@ export const pickmodRestart = register('pickmodRestart', function (lookup, pat)
|
||||
});
|
||||
|
||||
/** * Similar to `pick`, but the choosen pattern is reset when its index is triggered.
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -148,6 +157,7 @@ export const pickReset = register('pickReset', function (lookup, pat) {
|
||||
|
||||
/** * The same as `pickReset`, but if you pick a number greater than the size of the list,
|
||||
* it wraps around, rather than sticking at the maximum value.
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -157,19 +167,22 @@ export const pickmodReset = register('pickmodReset', function (lookup, pat) {
|
||||
});
|
||||
|
||||
/** Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
||||
* Similar to `pick`, but cycles are squeezed into the target ('inhabited') pattern.
|
||||
* @name inhabit
|
||||
* @synonyms pickSqueeze
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
* @example
|
||||
* "<a b [a,b]>".inhabit({a: s("bd(3,8)"),
|
||||
b: s("cp sd")
|
||||
})
|
||||
* @example
|
||||
* s("a@2 [a b] a".inhabit({a: "bd(3,8)", b: "sd sd"})).slow(4)
|
||||
*/
|
||||
* Similar to `pick`, but cycles are squeezed into the target ('inhabited') pattern.
|
||||
* @name inhabit
|
||||
* @tags combiners
|
||||
* @synonyms pickSqueeze
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
* @example
|
||||
* let a = s("bd(3,8)")
|
||||
* let b = s("cp sd")
|
||||
* "<a b [a,b]>".inhabit({ a, b })
|
||||
* @example
|
||||
* s("a@2 [a b] a"
|
||||
* .inhabit({a: "bd(3,8)", b: "sd sd"}))
|
||||
* .slow(4)
|
||||
*/
|
||||
export const { inhabit, pickSqueeze } = register(['inhabit', 'pickSqueeze'], function (lookup, pat) {
|
||||
return _pick(lookup, pat, false).squeezeJoin();
|
||||
});
|
||||
@@ -180,6 +193,7 @@ export const { inhabit, pickSqueeze } = register(['inhabit', 'pickSqueeze'], fun
|
||||
* second one.
|
||||
* @name inhabitmod
|
||||
* @synonyms pickmodSqueeze
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -192,6 +206,7 @@ export const { inhabitmod, pickmodSqueeze } = register(['inhabitmod', 'pickmodSq
|
||||
/**
|
||||
* Pick from the list of values (or patterns of values) via the index using the given
|
||||
* pattern of integers. The selected pattern will be compressed to fit the duration of the selecting event
|
||||
* @tags combiners
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
|
||||
+8
-10
@@ -12,7 +12,6 @@ import {
|
||||
import { evalScope } from './evaluate.mjs';
|
||||
import { register, Pattern, isPattern, silence, stack } from './pattern.mjs';
|
||||
import { reset_state } from './impure.mjs';
|
||||
import { SalatRepl } from '@kabelsalat/web';
|
||||
|
||||
export function repl({
|
||||
defaultOutput,
|
||||
@@ -31,7 +30,6 @@ export function repl({
|
||||
id,
|
||||
mondo = false,
|
||||
}) {
|
||||
const kabel = new SalatRepl({ localScope: true });
|
||||
const state = {
|
||||
schedulerError: undefined,
|
||||
evalError: undefined,
|
||||
@@ -89,11 +87,6 @@ export function repl({
|
||||
return silence;
|
||||
};
|
||||
|
||||
const compileKabel = (code) => {
|
||||
const node = kabel.evaluate(code);
|
||||
return node.compile({ log: false });
|
||||
};
|
||||
|
||||
// helper to get a patternified pure value out
|
||||
function unpure(pat) {
|
||||
if (pat._Pattern) {
|
||||
@@ -123,6 +116,7 @@ export function repl({
|
||||
* Changes the global tempo to the given cycles per minute
|
||||
*
|
||||
* @name setcpm
|
||||
* @tags temporal
|
||||
* @alias setCpm
|
||||
* @param {number} cpm cycles per minute
|
||||
* @example
|
||||
@@ -136,7 +130,9 @@ export function repl({
|
||||
|
||||
// TODO - not documented as jsdoc examples as the test framework doesn't simulate enough context for `each` and `all`..
|
||||
|
||||
/** Applies a function to all the running patterns. Note that the patterns are groups together into a single `stack` before the function is applied. This is probably what you want, but see `each` for
|
||||
let allTransforms = [];
|
||||
/**
|
||||
* Applies a function to all the running patterns. Note that the patterns are groups together into a single `stack` before the function is applied. This is probably what you want, but see `each` for
|
||||
* a version that applies the function to each pattern separately.
|
||||
* ```
|
||||
* $: sound("bd - cp sd")
|
||||
@@ -148,18 +144,21 @@ export function repl({
|
||||
* $: sound("hh*8")
|
||||
* all(x => x.pianoroll())
|
||||
* ```
|
||||
*
|
||||
* @tags combiners
|
||||
*/
|
||||
let allTransforms = [];
|
||||
const all = function (transform) {
|
||||
allTransforms.push(transform);
|
||||
return silence;
|
||||
};
|
||||
/** Applies a function to each of the running patterns separately. This is intended for future use with upcoming 'stepwise' features. See `all` for a version that applies the function to all the patterns stacked together into a single pattern.
|
||||
*
|
||||
* ```
|
||||
* $: sound("bd - cp sd")
|
||||
* $: sound("hh*8")
|
||||
* each(fast("<2 3>"))
|
||||
* ```
|
||||
* @tags combiners
|
||||
*/
|
||||
const each = function (transform) {
|
||||
eachTransform = transform;
|
||||
@@ -215,7 +214,6 @@ export function repl({
|
||||
setcps: setCps,
|
||||
setCpm,
|
||||
setcpm: setCpm,
|
||||
compileKabel,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ export const signal = (func) => {
|
||||
* A sawtooth signal between 0 and 1.
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
* @example
|
||||
* note("<c3 [eb3,g3] g2 [g3,bb3]>*8")
|
||||
* .clip(saw.slow(2))
|
||||
@@ -38,6 +39,7 @@ export const saw = signal((t) => t % 1);
|
||||
* A sawtooth signal between -1 and 1 (like `saw`, but bipolar).
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
*/
|
||||
export const saw2 = saw.toBipolar();
|
||||
|
||||
@@ -45,6 +47,7 @@ export const saw2 = saw.toBipolar();
|
||||
* A sawtooth signal between 1 and 0 (like `saw`, but flipped).
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
* @example
|
||||
* note("<c3 [eb3,g3] g2 [g3,bb3]>*8")
|
||||
* .clip(isaw.slow(2))
|
||||
@@ -59,6 +62,7 @@ export const isaw = signal((t) => 1 - (t % 1));
|
||||
* A sawtooth signal between 1 and -1 (like `saw2`, but flipped).
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
*/
|
||||
export const isaw2 = isaw.toBipolar();
|
||||
|
||||
@@ -66,12 +70,14 @@ export const isaw2 = isaw.toBipolar();
|
||||
* A sine signal between -1 and 1 (like `sine`, but bipolar).
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
*/
|
||||
export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
|
||||
|
||||
/**
|
||||
* A sine signal between 0 and 1.
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
* @example
|
||||
* n(sine.segment(16).range(0,15))
|
||||
* .scale("C:minor")
|
||||
@@ -83,6 +89,7 @@ export const sine = sine2.fromBipolar();
|
||||
* A cosine signal between 0 and 1.
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
* @example
|
||||
* n(stack(sine,cosine).segment(16).range(0,15))
|
||||
* .scale("C:minor")
|
||||
@@ -94,12 +101,14 @@ export const cosine = sine._early(Fraction(1).div(4));
|
||||
* A cosine signal between -1 and 1 (like `cosine`, but bipolar).
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
*/
|
||||
export const cosine2 = sine2._early(Fraction(1).div(4));
|
||||
|
||||
/**
|
||||
* A square signal between 0 and 1.
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
* @example
|
||||
* n(square.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -110,6 +119,7 @@ export const square = signal((t) => Math.floor((t * 2) % 2));
|
||||
* A square signal between -1 and 1 (like `square`, but bipolar).
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
*/
|
||||
export const square2 = square.toBipolar();
|
||||
|
||||
@@ -117,6 +127,7 @@ export const square2 = square.toBipolar();
|
||||
* A triangle signal between 0 and 1.
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
* @example
|
||||
* n(tri.segment(8).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -127,6 +138,7 @@ export const tri = fastcat(saw, isaw);
|
||||
* A triangle signal between -1 and 1 (like `tri`, but bipolar).
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
*/
|
||||
export const tri2 = fastcat(saw2, isaw2);
|
||||
|
||||
@@ -134,6 +146,7 @@ export const tri2 = fastcat(saw2, isaw2);
|
||||
* An inverted triangle signal between 1 and 0 (like `tri`, but flipped).
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
* @example
|
||||
* n(itri.segment(8).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -144,6 +157,7 @@ export const itri = fastcat(isaw, saw);
|
||||
* An inverted triangle signal between -1 and 1 (like `itri`, but bipolar).
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
*/
|
||||
export const itri2 = fastcat(isaw2, saw2);
|
||||
|
||||
@@ -151,6 +165,7 @@ export const itri2 = fastcat(isaw2, saw2);
|
||||
* A signal representing the cycle time.
|
||||
*
|
||||
* @return {Pattern}
|
||||
* @tags generators
|
||||
*/
|
||||
export const time = signal(id);
|
||||
|
||||
@@ -158,6 +173,7 @@ export const time = signal(id);
|
||||
* The mouse's x position value ranges from 0 to 1.
|
||||
* @name mousex
|
||||
* @return {Pattern}
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(mousex.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -167,6 +183,7 @@ export const time = signal(id);
|
||||
* The mouse's y position value ranges from 0 to 1.
|
||||
* @name mousey
|
||||
* @return {Pattern}
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(mousey.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -269,6 +286,7 @@ export const getRandsAtTime = (t, n = 1, seed = 0) => {
|
||||
* precise RNG, try `useRNG('precise')`.
|
||||
*
|
||||
* @name useRNG
|
||||
* @tags generators, math
|
||||
* @param {string} mod - Mode. One of 'legacy', 'precise'
|
||||
* @example
|
||||
* useRNG('legacy')
|
||||
@@ -280,6 +298,7 @@ export const useRNG = (mode = 'legacy') => (RNG_MODE = mode);
|
||||
|
||||
/**
|
||||
* A discrete pattern of numbers from 0 to n-1
|
||||
* @tags generators
|
||||
* @example
|
||||
* n(run(4)).scale("C4:pentatonic")
|
||||
* // n("0 1 2 3").scale("C4:pentatonic")
|
||||
@@ -290,6 +309,7 @@ export const run = (n) => saw.range(0, n).round().segment(n);
|
||||
* Creates a binary pattern from a number.
|
||||
*
|
||||
* @name binary
|
||||
* @tags generators
|
||||
* @param {number} n - input number to convert to binary
|
||||
* @example
|
||||
* "hh".s().struct(binary(5))
|
||||
@@ -304,6 +324,7 @@ export const binary = (n) => {
|
||||
* Creates a binary pattern from a number, padded to n bits long.
|
||||
*
|
||||
* @name binaryN
|
||||
* @tags generators
|
||||
* @param {number} n - input number to convert to binary
|
||||
* @param {number} nBits - pattern length, defaults to 16
|
||||
* @example
|
||||
@@ -321,6 +342,7 @@ export const binaryN = (n, nBits = 16) => {
|
||||
* Creates a binary list pattern from a number.
|
||||
*
|
||||
* @name binaryL
|
||||
* @tags generators
|
||||
* @param {number} n - input number to convert to binary
|
||||
* s("saw").seg(8)
|
||||
* .partials(binaryL(irand(4096).add(1)))
|
||||
@@ -334,6 +356,7 @@ export const binaryL = (n) => {
|
||||
* Creates a binary list pattern from a number, padded to n bits long.
|
||||
*
|
||||
* @name binaryNL
|
||||
* @tags generators
|
||||
* @param {number} n - input number to convert to binary
|
||||
* @param {number} nBits - pattern length, defaults to 16
|
||||
*/
|
||||
@@ -353,6 +376,7 @@ export const binaryNL = (n, nBits = 16) => {
|
||||
* Creates a list of random numbers of the given length
|
||||
*
|
||||
* @name randL
|
||||
* @tags generators
|
||||
* @param {number} n Number of random numbers to sample
|
||||
* @example
|
||||
* s("saw").seg(16).n(irand(12)).scale("F1:minor")
|
||||
@@ -384,6 +408,7 @@ const _rearrangeWith = (ipat, n, pat) => {
|
||||
* Slices a pattern into the given number of parts, then plays those parts in random order.
|
||||
* Each part will be played exactly once per cycle.
|
||||
* @name shuffle
|
||||
* @tags temporal
|
||||
* @example
|
||||
* note("c d e f").sound("piano").shuffle(4)
|
||||
* @example
|
||||
@@ -397,6 +422,7 @@ export const shuffle = register('shuffle', (n, pat) => {
|
||||
* Slices a pattern into the given number of parts, then plays those parts at random. Similar to `shuffle`,
|
||||
* but parts might be played more than once, or not at all, per cycle.
|
||||
* @name scramble
|
||||
* @tags temporal
|
||||
* @example
|
||||
* note("c d e f").sound("piano").scramble(4)
|
||||
* @example
|
||||
@@ -409,6 +435,7 @@ export const scramble = register('scramble', (n, pat) => {
|
||||
/**
|
||||
* Modify a pattern by applying a function to the `randomSeed` control if present
|
||||
*
|
||||
* @tags math
|
||||
* @param {Function} func Function from seed (or undefined) to seed (or undefined)
|
||||
* @param {Pattern} pat Pattern to update
|
||||
* @returns Pattern
|
||||
@@ -428,6 +455,7 @@ export const withSeed = (func, pat) => {
|
||||
* that use randomness, like `shuffle` and `sometimes`.
|
||||
*
|
||||
* @name seed
|
||||
* @tags math
|
||||
* @param {number} n A new seed. Can be any number.
|
||||
* @example
|
||||
* $: s("hh*4").degrade();
|
||||
@@ -441,6 +469,7 @@ export const seed = register('seed', (n, pat) => {
|
||||
* A continuous pattern of random numbers, between 0 and 1.
|
||||
*
|
||||
* @name rand
|
||||
* @tags generators
|
||||
* @example
|
||||
* // randomly change the cutoff
|
||||
* s("bd*4,hh*8").cutoff(rand.range(500,8000))
|
||||
@@ -449,6 +478,7 @@ export const seed = register('seed', (n, pat) => {
|
||||
export const rand = signal((t, controls) => getRandsAtTime(t, 1, controls.randSeed));
|
||||
/**
|
||||
* A continuous pattern of random numbers, between -1 and 1
|
||||
* @tags generators
|
||||
*/
|
||||
export const rand2 = rand.toBipolar();
|
||||
|
||||
@@ -458,6 +488,7 @@ export const _brandBy = (p) => rand.fmap((x) => x < p);
|
||||
* A continuous pattern of 0 or 1 (binary random), with a probability for the value being 1
|
||||
*
|
||||
* @name brandBy
|
||||
* @tags generators
|
||||
* @param {number} probability - a number between 0 and 1
|
||||
* @example
|
||||
* s("hh*10").pan(brandBy(0.2))
|
||||
@@ -468,6 +499,7 @@ export const brandBy = (pPat) => reify(pPat).fmap(_brandBy).innerJoin();
|
||||
* A continuous pattern of 0 or 1 (binary random)
|
||||
*
|
||||
* @name brand
|
||||
* @tags generators
|
||||
* @example
|
||||
* s("hh*10").pan(brand)
|
||||
*/
|
||||
@@ -479,6 +511,7 @@ export const _irand = (i) => rand.fmap((x) => Math.trunc(x * i));
|
||||
* A continuous pattern of random integers, between 0 and n-1.
|
||||
*
|
||||
* @name irand
|
||||
* @tags generators
|
||||
* @param {number} n max value (exclusive)
|
||||
* @example
|
||||
* // randomly select scale notes from 0 - 7 (= C to C)
|
||||
@@ -501,6 +534,7 @@ export const __chooseWith = (pat, xs) => {
|
||||
/**
|
||||
* Choose from the list of values (or patterns of values) using the given
|
||||
* pattern of numbers, which should be in the range of 0..1
|
||||
* @tags temporal
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -514,6 +548,7 @@ export const chooseWith = (pat, xs) => {
|
||||
/**
|
||||
* As with {chooseWith}, but the structure comes from the chosen values, rather
|
||||
* than the pattern you're using to choose with.
|
||||
* @tags temporal
|
||||
* @param {Pattern} pat
|
||||
* @param {*} xs
|
||||
* @returns {Pattern}
|
||||
@@ -524,6 +559,7 @@ export const chooseInWith = (pat, xs) => {
|
||||
|
||||
/**
|
||||
* Chooses randomly from the given list of elements.
|
||||
* @tags temporal
|
||||
* @param {...any} xs values / patterns to choose from.
|
||||
* @returns {Pattern} - a continuous pattern.
|
||||
* @example
|
||||
@@ -539,6 +575,7 @@ export const chooseOut = choose;
|
||||
* Chooses from the given list of values (or patterns of values), according
|
||||
* to the pattern that the method is called on. The pattern should be in
|
||||
* the range 0 .. 1.
|
||||
* @tags temporal
|
||||
* @param {...any} xs
|
||||
* @returns {Pattern}
|
||||
*/
|
||||
@@ -549,6 +586,7 @@ Pattern.prototype.choose = function (...xs) {
|
||||
/**
|
||||
* As with choose, but the pattern that this method is called on should be
|
||||
* in the range -1 .. 1
|
||||
* @tags temporal
|
||||
* @param {...any} xs
|
||||
* @returns {Pattern}
|
||||
*/
|
||||
@@ -558,6 +596,7 @@ Pattern.prototype.choose2 = function (...xs) {
|
||||
|
||||
/**
|
||||
* Picks one of the elements at random each cycle.
|
||||
* @tags temporal
|
||||
* @synonyms randcat
|
||||
* @returns {Pattern}
|
||||
* @example
|
||||
@@ -600,6 +639,7 @@ const wchooseWith = (...args) => _wchooseWith(...args).outerJoin();
|
||||
|
||||
/**
|
||||
* Chooses randomly from the given list of elements by giving a probability to each element
|
||||
* @tags temporal
|
||||
* @param {...any} pairs arrays of value and weight
|
||||
* @returns {Pattern} - a continuous pattern.
|
||||
* @example
|
||||
@@ -609,6 +649,7 @@ export const wchoose = (...pairs) => wchooseWith(rand, ...pairs);
|
||||
|
||||
/**
|
||||
* Picks one of the elements at random each cycle by giving a probability to each element
|
||||
* @tags temporal
|
||||
* @synonyms wrandcat
|
||||
* @returns {Pattern}
|
||||
* @example
|
||||
@@ -652,6 +693,7 @@ function _berlin(t, seed = 0) {
|
||||
/**
|
||||
* Generates a continuous pattern of [perlin noise](https://en.wikipedia.org/wiki/Perlin_noise), in the range 0..1.
|
||||
*
|
||||
* @tags generators
|
||||
* @name perlin
|
||||
* @example
|
||||
* // randomly change the cutoff
|
||||
@@ -664,6 +706,7 @@ export const perlin = signal((t, controls) => _perlin(t, controls.randSeed));
|
||||
* Generates a continuous pattern of [berlin noise](conceived by Jame Coyne and Jade Rowland as a joke but turned out to be surprisingly cool and useful,
|
||||
* like perlin noise but with sawtooth waves), in the range 0..1.
|
||||
*
|
||||
* @tags generators
|
||||
* @name berlin
|
||||
* @example
|
||||
* // ascending arpeggios
|
||||
@@ -684,6 +727,7 @@ export const degradeByWith = register(
|
||||
* 0 = 0% chance of removal
|
||||
* 1 = 100% chance of removal
|
||||
*
|
||||
* @tags temporal
|
||||
* @name degradeBy
|
||||
* @memberof Pattern
|
||||
* @param {number} amount - a number between 0 and 1
|
||||
@@ -709,6 +753,7 @@ export const degradeBy = register(
|
||||
*
|
||||
* Randomly removes 50% of events from the pattern. Shorthand for `.degradeBy(0.5)`
|
||||
*
|
||||
* @tags temporal
|
||||
* @name degrade
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
@@ -725,6 +770,7 @@ export const degrade = register('degrade', (pat) => pat._degradeBy(0.5), true, t
|
||||
* 1 = 0% chance of removal
|
||||
* Events that would be removed by degradeBy are let through by undegradeBy and vice versa (see second example).
|
||||
*
|
||||
* @tags temporal
|
||||
* @name undegradeBy
|
||||
* @memberof Pattern
|
||||
* @param {number} amount - a number between 0 and 1
|
||||
@@ -753,6 +799,7 @@ export const undegradeBy = register(
|
||||
* Inverse of `degrade`: Randomly removes 50% of events from the pattern. Shorthand for `.undegradeBy(0.5)`
|
||||
* Events that would be removed by degrade are let through by undegrade and vice versa (see second example).
|
||||
*
|
||||
* @tags temporal
|
||||
* @name undegrade
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
@@ -771,6 +818,7 @@ export const undegrade = register('undegrade', (pat) => pat._undegradeBy(0.5), t
|
||||
* Randomly applies the given function by the given probability.
|
||||
* Similar to `someCyclesBy`
|
||||
*
|
||||
* @tags temporal
|
||||
* @name sometimesBy
|
||||
* @memberof Pattern
|
||||
* @param {number | Pattern} probability - a number between 0 and 1
|
||||
@@ -790,6 +838,7 @@ export const sometimesBy = register('sometimesBy', function (patx, func, pat) {
|
||||
*
|
||||
* Applies the given function with a 50% chance
|
||||
*
|
||||
* @tags temporal
|
||||
* @name sometimes
|
||||
* @memberof Pattern
|
||||
* @param {function} function - the transformation to apply
|
||||
@@ -811,6 +860,7 @@ export const sometimes = register('sometimes', function (func, pat) {
|
||||
* @param {number | Pattern} probability - a number between 0 and 1
|
||||
* @param {function} function - the transformation to apply
|
||||
* @returns Pattern
|
||||
* @tags temporal
|
||||
* @example
|
||||
* s("bd,hh*8").someCyclesBy(.3, x=>x.speed("0.5"))
|
||||
*/
|
||||
@@ -833,6 +883,7 @@ export const someCyclesBy = register('someCyclesBy', function (patx, func, pat)
|
||||
* @name someCycles
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
* @tags temporal
|
||||
* @example
|
||||
* s("bd,hh*8").someCycles(x=>x.speed("0.5"))
|
||||
*/
|
||||
@@ -847,6 +898,7 @@ export const someCycles = register('someCycles', function (func, pat) {
|
||||
* @name often
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
* @tags temporal
|
||||
* @example
|
||||
* s("hh*8").often(x=>x.speed("0.5"))
|
||||
*/
|
||||
@@ -861,6 +913,7 @@ export const often = register('often', function (func, pat) {
|
||||
* @name rarely
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
* @tags temporal
|
||||
* @example
|
||||
* s("hh*8").rarely(x=>x.speed("0.5"))
|
||||
*/
|
||||
@@ -872,6 +925,7 @@ export const rarely = register('rarely', function (func, pat) {
|
||||
*
|
||||
* Shorthand for `.sometimesBy(0.1, fn)`
|
||||
*
|
||||
* @tags temporal
|
||||
* @name almostNever
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
@@ -886,6 +940,7 @@ export const almostNever = register('almostNever', function (func, pat) {
|
||||
*
|
||||
* Shorthand for `.sometimesBy(0.9, fn)`
|
||||
*
|
||||
* @tags temporal
|
||||
* @name almostAlways
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
@@ -900,6 +955,7 @@ export const almostAlways = register('almostAlways', function (func, pat) {
|
||||
*
|
||||
* Shorthand for `.sometimesBy(0, fn)` (never calls fn)
|
||||
*
|
||||
* @tags temporal
|
||||
* @name never
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
@@ -914,6 +970,7 @@ export const never = register('never', function (_, pat) {
|
||||
*
|
||||
* Shorthand for `.sometimesBy(1, fn)` (always calls fn)
|
||||
*
|
||||
* @tags temporal
|
||||
* @name always
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
@@ -942,6 +999,7 @@ export function _keyDown(keyname) {
|
||||
* Do something on a keypress, or array of keypresses
|
||||
* [Key name reference](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values)
|
||||
*
|
||||
* @tags external_io
|
||||
* @name whenKey
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
@@ -958,6 +1016,7 @@ export const whenKey = register('whenKey', function (input, func, pat) {
|
||||
* returns true when a key or array of keys is held
|
||||
* [Key name reference](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values)
|
||||
*
|
||||
* @tags external_io
|
||||
* @name keyDown
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
@@ -975,6 +1034,8 @@ export const keyDown = register('keyDown', function (pat) {
|
||||
* event durations, from the pattern that it is combined with.
|
||||
* For example `cyclesPer.struct("1 1 [1 1] 1")` would give the same as `"0.25 0.25 [0.125 0.125] 0.25"`.
|
||||
* See also its reciprocal, `per`, also known as `perCycle`.
|
||||
*
|
||||
* @tags temporal
|
||||
* @example
|
||||
* // Shorter events are lower in pitch
|
||||
* sound("saw saw [saw saw] saw")
|
||||
@@ -993,6 +1054,7 @@ export const cyclesPer = new Pattern(function (state) {
|
||||
* event durations, from the pattern that it is combined with.
|
||||
* For example `per.struct("1 1 [1 1] 1")` would give the same as `"4 4 [8 8] 4"`.
|
||||
* See also its reciprocal, `cyclesPer`.
|
||||
* @tags temporal
|
||||
* @synonyms perCycle
|
||||
* @example
|
||||
* // Shorter events are more distorted
|
||||
@@ -1010,6 +1072,7 @@ export const perCycle = per;
|
||||
* particular, where the event duration halves, the
|
||||
* returned value increases by one. `perx.struct("1 1 [1 [1 1]] 1")` would therefore be
|
||||
* the same as `"3 3 [4 [5 5]] 3"`.
|
||||
* @tags temporal
|
||||
*/
|
||||
export const perx = new Pattern(function (state) {
|
||||
const n = Fraction(1).div(state.span.duration);
|
||||
|
||||
@@ -135,6 +135,8 @@ export async function loadOrc(url) {
|
||||
* p4 -- MIDI key number (as a real number, not an integer but in [0, 127].
|
||||
* p5 -- MIDI velocity (as a real number, not an integer but in [0, 127].
|
||||
* p6 -- Strudel controls, as a string.
|
||||
*
|
||||
* @tags external_io
|
||||
*/
|
||||
export const csoundm = register('csoundm', (instrument, pat) => {
|
||||
let p1 = instrument;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/csound",
|
||||
"version": "1.2.8",
|
||||
"version": "1.3.0",
|
||||
"description": "csound bindings for strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
|
||||
@@ -42,6 +42,7 @@ const getValue = (e) => {
|
||||
*
|
||||
* @name pianoroll
|
||||
* @synonyms punchcard
|
||||
* @tags visualization
|
||||
* @param {Object} options Object containing all the optional following parameters as key value pairs:
|
||||
* @param {integer} cycles number of cycles to be displayed at the same time - defaults to 4
|
||||
* @param {number} playhead location of the active notes on the time axis - 0 to 1, defaults to 0.5
|
||||
@@ -299,6 +300,7 @@ Pattern.prototype.punchcard = function (options) {
|
||||
* Supports all the same options as pianoroll.
|
||||
*
|
||||
* @name wordfall
|
||||
* @tags visualization
|
||||
*/
|
||||
Pattern.prototype.wordfall = function (options) {
|
||||
return this.punchcard({ vertical: 1, labels: 1, stroke: 0, fillActive: 1, active: 'white', ...options });
|
||||
|
||||
@@ -116,6 +116,7 @@ export function pitchwheel({
|
||||
/**
|
||||
* Renders a pitch circle to visualize frequencies within one octave
|
||||
* @name pitchwheel
|
||||
* @tags visualization
|
||||
* @param {number} hapcircles
|
||||
* @param {number} circle
|
||||
* @param {number} edo
|
||||
|
||||
@@ -129,6 +129,7 @@ function drawSpiral(options) {
|
||||
* Displays a spiral visual.
|
||||
*
|
||||
* @name spiral
|
||||
* @tags visualization
|
||||
* @param {Object} options Object containing all the optional following parameters as key value pairs:
|
||||
* @param {number} stretch controls the rotations per cycle ratio, where 1 = 1 cycle / 360 degrees
|
||||
* @param {number} size the diameter of the spiral
|
||||
|
||||
@@ -138,6 +138,7 @@ function githubPath(base, subpath = '') {
|
||||
|
||||
/**
|
||||
* configures the default midimap, which is used when no "midimap" port is set
|
||||
* @tags external_io, midi
|
||||
* @example
|
||||
* defaultmidimap({ lpf: 74 })
|
||||
* $: note("c a f e").midi();
|
||||
@@ -151,6 +152,7 @@ let loadCache = {};
|
||||
|
||||
/**
|
||||
* Adds midimaps to the registry. Inside each midimap, control names (e.g. lpf) are mapped to cc numbers.
|
||||
* @tags external_io, midi
|
||||
* @example
|
||||
* midimaps({ mymap: { lpf: 74 } })
|
||||
* $: note("c a f e")
|
||||
@@ -305,6 +307,7 @@ function sendNote(note, velocity, duration, device, midichan, targetTime) {
|
||||
|
||||
/**
|
||||
* MIDI output: Opens a MIDI output port.
|
||||
* @tags external_io
|
||||
* @param {string | number} midiport MIDI device name or index defaulting to 0
|
||||
* @param {object} options Additional MIDI configuration options
|
||||
* @example
|
||||
@@ -526,6 +529,7 @@ async function _initialize(input) {
|
||||
* The output is a function that accepts a midi cc value to query as well as (optionally) a midi channel
|
||||
*
|
||||
* @name midin
|
||||
* @tags external_io, midi
|
||||
* @param {string | number} input MIDI device name or index defaulting to 0
|
||||
* @returns {function(number, number=): Pattern} A function from (cc, channel?) to a pattern.
|
||||
* When queried, the pattern will produces the most recently received midi value (normalized to 0 to 1)
|
||||
@@ -573,6 +577,7 @@ export async function midin(input) {
|
||||
* note durations
|
||||
*
|
||||
* @name midikeys
|
||||
* @tags external_io, midi
|
||||
* @param {string | number} input MIDI device name or index defaulting to 0
|
||||
* @returns {function((number | Pattern)=): Pattern} A function that produces a pattern.
|
||||
* When queried, the pattern will produces the most recently played midi notes and velocities,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/midi",
|
||||
"version": "1.2.8",
|
||||
"version": "1.3.0",
|
||||
"description": "Midi API for strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
|
||||
@@ -7,6 +7,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name accelerationX
|
||||
* @return {Pattern}
|
||||
* @synonyms accX
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(accelerationX.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -17,6 +18,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name accelerationY
|
||||
* @return {Pattern}
|
||||
* @synonyms accY
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(accelerationY.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -27,6 +29,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name accelerationZ
|
||||
* @return {Pattern}
|
||||
* @synonyms accZ
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(accelerationZ.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -37,6 +40,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name gravityX
|
||||
* @return {Pattern}
|
||||
* @synonyms gravX
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(gravityX.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -47,6 +51,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name gravityY
|
||||
* @return {Pattern}
|
||||
* @synonyms gravY
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(gravityY.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -57,6 +62,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name gravityZ
|
||||
* @return {Pattern}
|
||||
* @synonyms gravZ
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(gravityZ.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -67,6 +73,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name rotationAlpha
|
||||
* @return {Pattern}
|
||||
* @synonyms rotA, rotZ, rotationZ
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(rotationAlpha.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -77,6 +84,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name rotationBeta
|
||||
* @return {Pattern}
|
||||
* @synonyms rotB, rotX, rotationX
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(rotationBeta.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -87,6 +95,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name rotationGamma
|
||||
* @return {Pattern}
|
||||
* @synonyms rotG, rotY, rotationY
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(rotationGamma.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -97,6 +106,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name orientationAlpha
|
||||
* @return {Pattern}
|
||||
* @synonyms oriA, oriZ, orientationZ
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(orientationAlpha.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -107,6 +117,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name orientationBeta
|
||||
* @return {Pattern}
|
||||
* @synonyms oriB, oriX, orientationX
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(orientationBeta.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -117,6 +128,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name orientationGamma
|
||||
* @return {Pattern}
|
||||
* @synonyms oriG, oriY, orientationY
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(orientationGamma.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -127,6 +139,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name absoluteOrientationAlpha
|
||||
* @return {Pattern}
|
||||
* @synonyms absOriA, absOriZ, absoluteOrientationZ
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(absoluteOrientationAlpha.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -137,6 +150,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name absoluteOrientationBeta
|
||||
* @return {Pattern}
|
||||
* @synonyms absOriB, absOriX, absoluteOrientationX
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(absoluteOrientationBeta.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
@@ -147,6 +161,7 @@ import { signal } from '../core/signal.mjs';
|
||||
* @name absoluteOrientationGamma
|
||||
* @return {Pattern}
|
||||
* @synonyms absOriG, absOriY, absoluteOrientationY
|
||||
* @tags external_io
|
||||
* @example
|
||||
* n(absoluteOrientationGamma.segment(4).range(0,7)).scale("C:minor")
|
||||
*
|
||||
|
||||
@@ -79,6 +79,7 @@ export async function oscTrigger(hap, currentTime, cps = 1, targetTime) {
|
||||
* For more info, read [MIDI & OSC in the docs](https://strudel.cc/learn/input-output/)
|
||||
*
|
||||
* @name osc
|
||||
* @tags external_io
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/repl",
|
||||
"version": "1.2.9",
|
||||
"version": "1.3.0",
|
||||
"description": "Strudel REPL as a Web Component",
|
||||
"module": "index.mjs",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/soundfonts",
|
||||
"version": "1.2.8",
|
||||
"version": "1.3.0",
|
||||
"description": "Soundsfont support for strudel",
|
||||
"main": "index.mjs",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -172,6 +172,7 @@ export const getADSRValues = (params, curve = 'linear', defaultValues) => {
|
||||
if (a == null && d == null && s == null && r == null) {
|
||||
return defaultValues ?? [envmin, envmin, envmax, releaseMin];
|
||||
}
|
||||
|
||||
const sustain = s != null ? s : (a != null && d == null) || (a == null && d == null) ? envmax : envmin;
|
||||
return [Math.max(a ?? 0, envmin), Math.max(d ?? 0, envmin), Math.min(sustain, envmax), Math.max(r ?? 0, releaseMin)];
|
||||
};
|
||||
|
||||
@@ -98,6 +98,7 @@ export const connectLFO = (id, params, nodeTracker) => {
|
||||
fxi = 'main',
|
||||
depth = 1,
|
||||
depthabs,
|
||||
retrig = 0,
|
||||
...filteredParams
|
||||
} = params;
|
||||
const { targetParams, paramName } = getTargetParamsForControl(control, nodeTracker[fxi], subControl);
|
||||
@@ -109,7 +110,7 @@ export const connectLFO = (id, params, nodeTracker) => {
|
||||
const modParams = {
|
||||
...filteredParams,
|
||||
frequency: sync !== undefined ? sync * cps : rate,
|
||||
time: cycle / cps,
|
||||
time: retrig > 0.5 ? 0 : cycle / cps,
|
||||
depth: depthValue,
|
||||
min,
|
||||
max,
|
||||
|
||||
@@ -35,7 +35,9 @@ class OLAProcessor extends AudioWorkletProcessor {
|
||||
}
|
||||
|
||||
/** Handles dynamic reallocation of input/output channels buffer
|
||||
(channel numbers may lety during lifecycle) **/
|
||||
* (channel numbers may vary during lifecycle)
|
||||
* @tags internals
|
||||
**/
|
||||
reallocateChannelsIfNeeded(inputs, outputs) {
|
||||
for (let i = 0; i < this.nbInputs; i++) {
|
||||
let nbChannels = inputs[i].length;
|
||||
@@ -88,7 +90,10 @@ class OLAProcessor extends AudioWorkletProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/** Read next web audio block to input buffers **/
|
||||
/**
|
||||
* Read next web audio block to input buffers
|
||||
* @tags internals
|
||||
**/
|
||||
readInputs(inputs) {
|
||||
// when playback is paused, we may stop receiving new samples
|
||||
if (inputs[0].length && inputs[0][0].length == 0) {
|
||||
@@ -108,7 +113,9 @@ class OLAProcessor extends AudioWorkletProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/** Write next web audio block from output buffers **/
|
||||
/** Write next web audio block from output buffers
|
||||
* @tags internals
|
||||
**/
|
||||
writeOutputs(outputs) {
|
||||
for (let i = 0; i < this.nbInputs; i++) {
|
||||
for (let j = 0; j < this.inputBuffers[i].length; j++) {
|
||||
@@ -118,7 +125,9 @@ class OLAProcessor extends AudioWorkletProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/** Shift left content of input buffers to receive new web audio block **/
|
||||
/** Shift left content of input buffers to receive new web audio block
|
||||
* @tags internals
|
||||
**/
|
||||
shiftInputBuffers() {
|
||||
for (let i = 0; i < this.nbInputs; i++) {
|
||||
for (let j = 0; j < this.inputBuffers[i].length; j++) {
|
||||
@@ -127,7 +136,9 @@ class OLAProcessor extends AudioWorkletProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/** Shift left content of output buffers to receive new web audio block **/
|
||||
/** Shift left content of output buffers to receive new web audio block
|
||||
* @tags internals
|
||||
**/
|
||||
shiftOutputBuffers() {
|
||||
for (let i = 0; i < this.nbOutputs; i++) {
|
||||
for (let j = 0; j < this.outputBuffers[i].length; j++) {
|
||||
@@ -137,7 +148,9 @@ class OLAProcessor extends AudioWorkletProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/** Copy contents of input buffers to buffer actually sent to process **/
|
||||
/** Copy contents of input buffers to buffer actually sent to process
|
||||
* @tags internals
|
||||
**/
|
||||
prepareInputBuffersToSend() {
|
||||
for (let i = 0; i < this.nbInputs; i++) {
|
||||
for (let j = 0; j < this.inputBuffers[i].length; j++) {
|
||||
@@ -146,7 +159,9 @@ class OLAProcessor extends AudioWorkletProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/** Add contents of output buffers just processed to output buffers **/
|
||||
/** Add contents of output buffers just processed to output buffers
|
||||
* @tags internals
|
||||
**/
|
||||
handleOutputBuffersToRetrieve() {
|
||||
for (let i = 0; i < this.nbOutputs; i++) {
|
||||
for (let j = 0; j < this.outputBuffers[i].length; j++) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "superdough",
|
||||
"version": "1.2.5",
|
||||
"version": "1.3.0",
|
||||
"description": "simple web audio synth and sampler intended for live coding. inspired by superdirt and webdirt.",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
@@ -37,6 +37,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@kabelsalat/lib": "^0.4.1",
|
||||
"@kabelsalat/web": "^0.4.1",
|
||||
"nanostores": "^0.11.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -18,6 +18,7 @@ var reverbGen = {};
|
||||
|
||||
/** Generates a reverb impulse response.
|
||||
|
||||
@tags internals
|
||||
@param {!Object} params TODO: Document the properties.
|
||||
@param {!function(!AudioBuffer)} callback Function to call when
|
||||
the impulse response has been generated. The impulse response
|
||||
@@ -50,7 +51,7 @@ reverbGen.generateReverb = function (params, callback) {
|
||||
|
||||
/** Creates a canvas element showing a graph of the given data.
|
||||
|
||||
|
||||
@tags internals
|
||||
@param {!Float32Array} data An array of numbers, or a Float32Array.
|
||||
@param {number} width Width in pixels of the canvas.
|
||||
@param {number} height Height in pixels of the canvas.
|
||||
@@ -81,7 +82,9 @@ reverbGen.generateGraph = function (data, width, height, min, max) {
|
||||
@param {number} lpFreqEnd
|
||||
@param {number} lpFreqEndAt
|
||||
@param {!function(!AudioBuffer)} callback May be called
|
||||
immediately within the current execution context, or later.*/
|
||||
immediately within the current execution context, or later.
|
||||
@tags internals
|
||||
*/
|
||||
var applyGradualLowpass = function (input, lpFreqStart, lpFreqEnd, lpFreqEndAt, callback) {
|
||||
if (lpFreqStart == 0) {
|
||||
callback(input);
|
||||
|
||||
@@ -235,6 +235,7 @@ export async function fetchSampleMap(url) {
|
||||
|
||||
/**
|
||||
* Loads a collection of samples to use with `s`
|
||||
* @tags samples
|
||||
* @example
|
||||
* samples('github:tidalcycles/dirt-samples');
|
||||
* s("[bd ~]*2, [~ hh]*2, ~ sd")
|
||||
|
||||
@@ -40,6 +40,7 @@ export let maxPolyphony = DEFAULT_MAX_POLYPHONY;
|
||||
* start to die out in first-in-first-out order once the max polyphony has been hit
|
||||
*
|
||||
* @name setMaxPolyphony
|
||||
* @tags superdough
|
||||
* @param {number} Max polyphony. Defaults to 128
|
||||
* @example
|
||||
* setMaxPolyphony(4)
|
||||
@@ -73,6 +74,7 @@ export function applyGainCurve(val) {
|
||||
* quadratic, exponential, etc. rather than linear
|
||||
*
|
||||
* @name setGainCurve
|
||||
* @tags amplitude, superdough
|
||||
* @param {Function} function to apply to all gain values
|
||||
* @example
|
||||
* setGainCurve((x) => x * x) // quadratic gain
|
||||
@@ -128,6 +130,8 @@ async function aliasBankPath(path) {
|
||||
* Optionally accepts a single argument string of a path to a JSON file containing bank aliases.
|
||||
* @param {string} bank - The bank to alias
|
||||
* @param {string} alias - The alias to use for the bank
|
||||
*
|
||||
* @tags samples
|
||||
*/
|
||||
export async function aliasBank(...args) {
|
||||
switch (args.length) {
|
||||
@@ -146,6 +150,7 @@ export async function aliasBank(...args) {
|
||||
|
||||
/**
|
||||
* Register an alias for a sound.
|
||||
* @tags samples
|
||||
* @param {string} original - The original sound name
|
||||
* @param {string} alias - The alias to use for the sound
|
||||
*/
|
||||
@@ -255,6 +260,14 @@ export function loadWorklets() {
|
||||
return workletsLoading;
|
||||
}
|
||||
|
||||
let kabel;
|
||||
async function initKabelsalat() {
|
||||
const { SalatRepl } = await import('@kabelsalat/web');
|
||||
logger('[kabelsalat] ready');
|
||||
kabel = new SalatRepl({ localScope: true });
|
||||
return kabel;
|
||||
}
|
||||
|
||||
// this function should be called on first user interaction (to avoid console warning)
|
||||
export async function initAudio(options = {}) {
|
||||
const {
|
||||
@@ -301,6 +314,7 @@ export async function initAudio(options = {}) {
|
||||
} catch (err) {
|
||||
console.warn('could not load AudioWorklet effects', err);
|
||||
}
|
||||
await initKabelsalat();
|
||||
logger('[superdough] ready');
|
||||
}
|
||||
let audioReady;
|
||||
@@ -436,6 +450,14 @@ class Chain {
|
||||
}
|
||||
}
|
||||
|
||||
const compileKabel = (code) => {
|
||||
if (!kabel) {
|
||||
throw new Error('kabelsalat not loaded');
|
||||
}
|
||||
const node = kabel.evaluate(code);
|
||||
return node.compile({ log: false });
|
||||
};
|
||||
|
||||
export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) => {
|
||||
// mapping from main FX and numbered FX chains to nodes
|
||||
const nodes = { main: {} };
|
||||
|
||||
@@ -110,7 +110,9 @@ export function getCommonSampleInfo(hapValue, bank) {
|
||||
return { transpose, url, index, midi, label };
|
||||
}
|
||||
|
||||
/** Selects entries from `source` and renames them via `map` */
|
||||
/** Selects entries from `source` and renames them via `map`
|
||||
* @tags internals
|
||||
*/
|
||||
export const pickAndRename = (source, map) => {
|
||||
return Object.fromEntries(Object.entries(map).map(([newKey, oldKey]) => [newKey, source[oldKey]]));
|
||||
};
|
||||
|
||||
@@ -186,6 +186,7 @@ export function registerWaveTable(key, tables, params) {
|
||||
* Loads a collection of wavetables to use with `s`
|
||||
*
|
||||
* @name tables
|
||||
* @tags wavetable
|
||||
*/
|
||||
export const tables = async (url, frameLen, json, options = {}) => {
|
||||
if (json !== undefined) return _processTables(json, url, frameLen);
|
||||
|
||||
@@ -646,14 +646,18 @@ class PhaseVocoderProcessor extends OLAProcessor {
|
||||
this.timeCursor += this.hopSize;
|
||||
}
|
||||
|
||||
/** Apply Hann window in-place */
|
||||
/** Apply Hann window in-place
|
||||
* @tags internals
|
||||
*/
|
||||
applyHannWindow(input) {
|
||||
for (let i = 0; i < this.blockSize; i++) {
|
||||
input[i] *= this.hannWindow[i] * 1.62;
|
||||
}
|
||||
}
|
||||
|
||||
/** Compute squared magnitudes for peak finding **/
|
||||
/** Compute squared magnitudes for peak finding
|
||||
* @tags internals
|
||||
**/
|
||||
computeMagnitudes() {
|
||||
let i = 0,
|
||||
j = 0;
|
||||
@@ -667,7 +671,9 @@ class PhaseVocoderProcessor extends OLAProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/** Find peaks in spectrum magnitudes **/
|
||||
/** Find peaks in spectrum magnitudes
|
||||
* @tags internals
|
||||
**/
|
||||
findPeaks() {
|
||||
this.nbPeaks = 0;
|
||||
let i = 2;
|
||||
@@ -688,7 +694,9 @@ class PhaseVocoderProcessor extends OLAProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/** Shift peaks and regions of influence by pitchFactor into new specturm */
|
||||
/** Shift peaks and regions of influence by pitchFactor into new specturm
|
||||
* @tags internals
|
||||
*/
|
||||
shiftPeaks(pitchFactor) {
|
||||
// zero-fill new spectrum
|
||||
this.freqComplexBufferShifted.fill(0);
|
||||
@@ -841,7 +849,9 @@ class PulseOscillatorProcessor extends AudioWorkletProcessor {
|
||||
|
||||
registerProcessor('pulse-oscillator', PulseOscillatorProcessor);
|
||||
|
||||
/** BYTE BEATS */
|
||||
/** BYTE BEATS
|
||||
* @tags internals
|
||||
*/
|
||||
const chyx = {
|
||||
/*bit*/ bitC: function (x, y, z) {
|
||||
return x & y ? z : 0;
|
||||
|
||||
@@ -19,6 +19,7 @@ function applyGainCurve(val) {
|
||||
* @param {number} a - Signal A (can be a single value or an array value in buffer processing).
|
||||
* @param {number} b - Signal B (can be a single value or an array value in buffer processing).
|
||||
* @param {number} m - Crossfade parameter (0.0 = all A, 1.0 = all B, 0.5 = equal mix).
|
||||
* @tags internals
|
||||
* @returns {number} Crossfaded output value.
|
||||
*/
|
||||
function crossfade(a, b, m) {
|
||||
|
||||
@@ -100,6 +100,7 @@ function scaleOffset(scale, offset, note) {
|
||||
* - 5P = perfect fifth
|
||||
* - 5d = diminished fifth
|
||||
*
|
||||
* @tags tonal
|
||||
* @param {string | number} amount Either number of semitones or interval string.
|
||||
* @returns Pattern
|
||||
* @memberof Pattern
|
||||
@@ -154,6 +155,7 @@ export const { transpose, trans } = register(['transpose', 'trans'], function tr
|
||||
*
|
||||
* @memberof Pattern
|
||||
* @name scaleTranspose
|
||||
* @tags tonal
|
||||
* @param {offset} offset number of steps inside the scale
|
||||
* @returns Pattern
|
||||
* @synonyms scaleTrans, strans
|
||||
@@ -244,6 +246,7 @@ function _getNearestScaleNote(scaleName, note, preferHigher = true) {
|
||||
* The root note defaults to octave 3, if no octave number is given.
|
||||
*
|
||||
* @name scale
|
||||
* @tags tonal
|
||||
* @param {string} scale Name of scale
|
||||
* @returns Pattern
|
||||
* @example
|
||||
|
||||
@@ -90,6 +90,7 @@ export const setVoicingRange = (name, range) => addVoicings(name, voicingRegistr
|
||||
* Adds a new custom voicing dictionary.
|
||||
*
|
||||
* @name addVoicings
|
||||
* @tags tonal
|
||||
* @memberof Pattern
|
||||
* @param {string} name identifier for the voicing dictionary
|
||||
* @param {Object} dictionary maps chord symbol to possible voicings
|
||||
@@ -133,6 +134,7 @@ const getVoicing = (chord, dictionaryName, lastVoicing) => {
|
||||
* Uses [chord-voicings package](https://github.com/felixroos/chord-voicings#chord-voicings).
|
||||
*
|
||||
* @name voicings
|
||||
* @tags tonal
|
||||
* @memberof Pattern
|
||||
* @param {string} dictionary which voicing dictionary to use.
|
||||
* @returns Pattern
|
||||
@@ -157,6 +159,7 @@ export const voicings = register('voicings', function (dictionary, pat) {
|
||||
* Maps the chords of the incoming pattern to root notes in the given octave.
|
||||
*
|
||||
* @name rootNotes
|
||||
* @tags tonal
|
||||
* @memberof Pattern
|
||||
* @param {octave} octave octave to use
|
||||
* @returns Pattern
|
||||
@@ -189,6 +192,7 @@ export const rootNotes = register('rootNotes', function (octave, pat) {
|
||||
* If you pass a pattern of strings to voicing, they will be interpreted as chords.
|
||||
*
|
||||
* @name voicing
|
||||
* @tags tonal
|
||||
* @returns Pattern
|
||||
* @example
|
||||
* n("0 1 2 3").chord("<C Am F G>").voicing()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/web",
|
||||
"version": "1.2.8",
|
||||
"version": "1.3.0",
|
||||
"description": "Easy to setup, opiniated bundle of Strudel for the browser.",
|
||||
"module": "web.mjs",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@strudel/webaudio",
|
||||
"version": "1.2.9",
|
||||
"version": "1.3.0",
|
||||
"description": "Web Audio helpers for Strudel",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
|
||||
@@ -98,6 +98,7 @@ function clearScreen(smear = 0, smearRGB = `0,0,0`, ctx = getDrawContext()) {
|
||||
/**
|
||||
* Renders an oscilloscope for the frequency domain of the audio signal.
|
||||
* @name fscope
|
||||
* @tags visualization
|
||||
* @param {string} color line color as hex or color name. defaults to white.
|
||||
* @param {number} scale scales the y-axis. Defaults to 0.25
|
||||
* @param {number} pos y-position relative to screen height. 0 = top, 1 = bottom of screen
|
||||
@@ -122,6 +123,7 @@ Pattern.prototype.fscope = function (config = {}) {
|
||||
* Renders an oscilloscope for the time domain of the audio signal.
|
||||
* @name scope
|
||||
* @synonyms tscope
|
||||
* @tags visualization
|
||||
* @param {object} config optional config with options:
|
||||
* @param {boolean} align if 1, the scope will be aligned to the first zero crossing. defaults to 1
|
||||
* @param {string} color line color as hex or color name. defaults to white.
|
||||
|
||||
@@ -5,6 +5,7 @@ import { analysers, getAnalyzerData } from 'superdough';
|
||||
/**
|
||||
* Renders a spectrum analyzer for the incoming audio signal.
|
||||
* @name spectrum
|
||||
* @tags visualization
|
||||
* @param {object} config optional config with options:
|
||||
* @param {integer} thickness line thickness in px (default 3)
|
||||
* @param {integer} speed scroll speed (default 1)
|
||||
|
||||
Generated
+3
-3
@@ -234,9 +234,6 @@ importers:
|
||||
|
||||
packages/core:
|
||||
dependencies:
|
||||
'@kabelsalat/web':
|
||||
specifier: ^0.4.1
|
||||
version: 0.4.1
|
||||
fraction.js:
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1
|
||||
@@ -524,6 +521,9 @@ importers:
|
||||
'@kabelsalat/lib':
|
||||
specifier: ^0.4.1
|
||||
version: 0.4.1
|
||||
'@kabelsalat/web':
|
||||
specifier: ^0.4.1
|
||||
version: 0.4.1
|
||||
nanostores:
|
||||
specifier: ^0.11.3
|
||||
version: 0.11.3
|
||||
|
||||
@@ -1037,6 +1037,43 @@ exports[`runs examples > example "anchor" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "anchor" example index 1 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/8 | anchor:c4 note:60 ]",
|
||||
"[ 1/8 → 1/4 | anchor:c4 note:62 ]",
|
||||
"[ 1/4 → 3/8 | anchor:c4 note:64 ]",
|
||||
"[ 3/8 → 1/2 | anchor:c4 note:65 ]",
|
||||
"[ 1/2 → 5/8 | anchor:c4 note:67 ]",
|
||||
"[ 5/8 → 3/4 | anchor:c4 note:69 ]",
|
||||
"[ 3/4 → 7/8 | anchor:c4 note:71 ]",
|
||||
"[ 7/8 → 1/1 | anchor:c4 note:72 ]",
|
||||
"[ 1/1 → 9/8 | anchor:g4 note:67 ]",
|
||||
"[ 9/8 → 5/4 | anchor:g4 note:68 ]",
|
||||
"[ 5/4 → 11/8 | anchor:g4 note:70 ]",
|
||||
"[ 11/8 → 3/2 | anchor:g4 note:72 ]",
|
||||
"[ 3/2 → 13/8 | anchor:g4 note:73 ]",
|
||||
"[ 13/8 → 7/4 | anchor:g4 note:75 ]",
|
||||
"[ 7/4 → 15/8 | anchor:g4 note:77 ]",
|
||||
"[ 15/8 → 2/1 | anchor:g4 note:79 ]",
|
||||
"[ 2/1 → 17/8 | anchor:c5 note:72 ]",
|
||||
"[ 17/8 → 9/4 | anchor:c5 note:74 ]",
|
||||
"[ 9/4 → 19/8 | anchor:c5 note:76 ]",
|
||||
"[ 19/8 → 5/2 | anchor:c5 note:77 ]",
|
||||
"[ 5/2 → 21/8 | anchor:c5 note:79 ]",
|
||||
"[ 21/8 → 11/4 | anchor:c5 note:81 ]",
|
||||
"[ 11/4 → 23/8 | anchor:c5 note:83 ]",
|
||||
"[ 23/8 → 3/1 | anchor:c5 note:84 ]",
|
||||
"[ 3/1 → 25/8 | anchor:g5 note:79 ]",
|
||||
"[ 25/8 → 13/4 | anchor:g5 note:80 ]",
|
||||
"[ 13/4 → 27/8 | anchor:g5 note:82 ]",
|
||||
"[ 27/8 → 7/2 | anchor:g5 note:84 ]",
|
||||
"[ 7/2 → 29/8 | anchor:g5 note:85 ]",
|
||||
"[ 29/8 → 15/4 | anchor:g5 note:87 ]",
|
||||
"[ 15/4 → 31/8 | anchor:g5 note:89 ]",
|
||||
"[ 31/8 → 4/1 | anchor:g5 note:91 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "apply" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/1 | note:C3 ]",
|
||||
@@ -4193,6 +4230,27 @@ exports[`runs examples > example "extend" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "fadeTime" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:oh end:0.1 fadeTime:0 ]",
|
||||
"[ 1/4 → 1/2 | s:oh end:0.1 fadeTime:0 ]",
|
||||
"[ 1/2 → 3/4 | s:oh end:0.1 fadeTime:0 ]",
|
||||
"[ 3/4 → 1/1 | s:oh end:0.1 fadeTime:0 ]",
|
||||
"[ 1/1 → 5/4 | s:oh end:0.1 fadeTime:0.2 ]",
|
||||
"[ 5/4 → 3/2 | s:oh end:0.1 fadeTime:0.2 ]",
|
||||
"[ 3/2 → 7/4 | s:oh end:0.1 fadeTime:0.2 ]",
|
||||
"[ 7/4 → 2/1 | s:oh end:0.1 fadeTime:0.2 ]",
|
||||
"[ 2/1 → 9/4 | s:oh end:0.1 fadeTime:0.4 ]",
|
||||
"[ 9/4 → 5/2 | s:oh end:0.1 fadeTime:0.4 ]",
|
||||
"[ 5/2 → 11/4 | s:oh end:0.1 fadeTime:0.4 ]",
|
||||
"[ 11/4 → 3/1 | s:oh end:0.1 fadeTime:0.4 ]",
|
||||
"[ 3/1 → 13/4 | s:oh end:0.1 fadeTime:0.8 ]",
|
||||
"[ 13/4 → 7/2 | s:oh end:0.1 fadeTime:0.8 ]",
|
||||
"[ 7/2 → 15/4 | s:oh end:0.1 fadeTime:0.8 ]",
|
||||
"[ 15/4 → 4/1 | s:oh end:0.1 fadeTime:0.8 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "fanchor" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/8 | note:f s:sawtooth cutoff:1000 lpenv:8 fanchor:0 ]",
|
||||
@@ -8099,6 +8157,48 @@ exports[`runs examples > example "panchor" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "panspan" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd pan:0.5 panspan:0 ]",
|
||||
"[ 1/4 → 1/2 | s:hh pan:0.5 panspan:0 ]",
|
||||
"[ 1/2 → 3/4 | s:bd pan:0.5 panspan:0 ]",
|
||||
"[ 3/4 → 1/1 | s:hh pan:0.5 panspan:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd pan:1 panspan:0.5 ]",
|
||||
"[ 5/4 → 3/2 | s:hh pan:1 panspan:0.5 ]",
|
||||
"[ 3/2 → 7/4 | s:bd pan:1 panspan:0.5 ]",
|
||||
"[ 7/4 → 2/1 | s:hh pan:1 panspan:0.5 ]",
|
||||
"[ 2/1 → 9/4 | s:bd pan:0.5 panspan:1 ]",
|
||||
"[ 9/4 → 5/2 | s:hh pan:0.5 panspan:1 ]",
|
||||
"[ 5/2 → 11/4 | s:bd pan:0.5 panspan:1 ]",
|
||||
"[ 11/4 → 3/1 | s:hh pan:0.5 panspan:1 ]",
|
||||
"[ 3/1 → 13/4 | s:bd pan:0 panspan:0 ]",
|
||||
"[ 13/4 → 7/2 | s:hh pan:0 panspan:0 ]",
|
||||
"[ 7/2 → 15/4 | s:bd pan:0 panspan:0 ]",
|
||||
"[ 15/4 → 4/1 | s:hh pan:0 panspan:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "pansplay" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd pan:0.5 pansplay:0 ]",
|
||||
"[ 1/4 → 1/2 | s:hh pan:0.5 pansplay:0 ]",
|
||||
"[ 1/2 → 3/4 | s:bd pan:0.5 pansplay:0 ]",
|
||||
"[ 3/4 → 1/1 | s:hh pan:0.5 pansplay:0 ]",
|
||||
"[ 1/1 → 5/4 | s:bd pan:1 pansplay:0.5 ]",
|
||||
"[ 5/4 → 3/2 | s:hh pan:1 pansplay:0.5 ]",
|
||||
"[ 3/2 → 7/4 | s:bd pan:1 pansplay:0.5 ]",
|
||||
"[ 7/4 → 2/1 | s:hh pan:1 pansplay:0.5 ]",
|
||||
"[ 2/1 → 9/4 | s:bd pan:0.5 pansplay:1 ]",
|
||||
"[ 9/4 → 5/2 | s:hh pan:0.5 pansplay:1 ]",
|
||||
"[ 5/2 → 11/4 | s:bd pan:0.5 pansplay:1 ]",
|
||||
"[ 11/4 → 3/1 | s:hh pan:0.5 pansplay:1 ]",
|
||||
"[ 3/1 → 13/4 | s:bd pan:0 pansplay:0 ]",
|
||||
"[ 13/4 → 7/2 | s:hh pan:0 pansplay:0 ]",
|
||||
"[ 7/2 → 15/4 | s:bd pan:0 pansplay:0 ]",
|
||||
"[ 15/4 → 4/1 | s:hh pan:0 pansplay:0 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "partials" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/16 | s:user note:A3 partials:[1 0 1 0 0 1] ]",
|
||||
@@ -10874,6 +10974,35 @@ exports[`runs examples > example "seqPLoop" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "setDefaultJoin" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:saw velocity:1 note:F delay:0 ]",
|
||||
"[ 1/4 → 1/3 | s:saw velocity:1 note:A delay:0 ]",
|
||||
"[ 1/3 → 1/2 | s:saw velocity:1 note:A delay:0.2 ]",
|
||||
"[ 1/2 → 2/3 | s:saw velocity:0.5 note:C delay:0.2 ]",
|
||||
"[ 2/3 → 3/4 | s:saw velocity:0.5 note:C delay:0.3 ]",
|
||||
"[ 3/4 → 1/1 | s:saw velocity:0.5 note:E delay:0.3 ]",
|
||||
"[ 1/1 → 5/4 | s:saw velocity:1 note:F delay:0 ]",
|
||||
"[ 5/4 → 4/3 | s:saw velocity:1 note:A delay:0 ]",
|
||||
"[ 4/3 → 3/2 | s:saw velocity:1 note:A delay:0.2 ]",
|
||||
"[ 3/2 → 5/3 | s:saw velocity:0.5 note:C delay:0.2 ]",
|
||||
"[ 5/3 → 7/4 | s:saw velocity:0.5 note:C delay:0.3 ]",
|
||||
"[ 7/4 → 2/1 | s:saw velocity:0.5 note:E delay:0.3 ]",
|
||||
"[ 2/1 → 9/4 | s:saw velocity:1 note:F delay:0 ]",
|
||||
"[ 9/4 → 7/3 | s:saw velocity:1 note:A delay:0 ]",
|
||||
"[ 7/3 → 5/2 | s:saw velocity:1 note:A delay:0.2 ]",
|
||||
"[ 5/2 → 8/3 | s:saw velocity:0.5 note:C delay:0.2 ]",
|
||||
"[ 8/3 → 11/4 | s:saw velocity:0.5 note:C delay:0.3 ]",
|
||||
"[ 11/4 → 3/1 | s:saw velocity:0.5 note:E delay:0.3 ]",
|
||||
"[ 3/1 → 13/4 | s:saw velocity:1 note:F delay:0 ]",
|
||||
"[ 13/4 → 10/3 | s:saw velocity:1 note:A delay:0 ]",
|
||||
"[ 10/3 → 7/2 | s:saw velocity:1 note:A delay:0.2 ]",
|
||||
"[ 7/2 → 11/3 | s:saw velocity:0.5 note:C delay:0.2 ]",
|
||||
"[ 11/3 → 15/4 | s:saw velocity:0.5 note:C delay:0.3 ]",
|
||||
"[ 15/4 → 4/1 | s:saw velocity:0.5 note:E delay:0.3 ]",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "setGainCurve" example index 0 1`] = `
|
||||
[
|
||||
"[ 0/1 → 1/4 | s:bd gain:0.5 ]",
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { afterEach } from 'vitest';
|
||||
import { useRNG } from './packages/core/signal.mjs';
|
||||
import { setDefaultJoin } from './packages/core/pattern.mjs';
|
||||
|
||||
afterEach(() => {
|
||||
// Avoid bleed between tests
|
||||
useRNG('legacy');
|
||||
setDefaultJoin('in');
|
||||
});
|
||||
|
||||
@@ -33,6 +33,7 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL
|
||||
<!-- the following variables are just a fallback to make sure everything is readable without JS -->
|
||||
<style is:global>
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
--background: #222;
|
||||
--lineBackground: #22222299;
|
||||
--foreground: #fff;
|
||||
|
||||
@@ -32,6 +32,7 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL
|
||||
<!-- the following variables are just a fallback to make sure everything is readable without JS -->
|
||||
<style is:global>
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
--background: #222;
|
||||
--lineBackground: #22222299;
|
||||
--foreground: #fff;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Loader from '@src/repl/components/Loader';
|
||||
import { HorizontalPanel } from '@src/repl/components/panel/Panel';
|
||||
import { BottomPanel } from '@src/repl/components/panel/Panel';
|
||||
import { Code } from '@src/repl/components/Code';
|
||||
import BigPlayButton from '@src/repl/components/BigPlayButton';
|
||||
import UserFacingErrorMessage from '@src/repl/components/UserFacingErrorMessage';
|
||||
@@ -20,7 +20,7 @@ export default function UdelsEditor(Props) {
|
||||
<Code containerRef={containerRef} editorRef={editorRef} init={init} />
|
||||
</div>
|
||||
<UserFacingErrorMessage error={error} />
|
||||
<HorizontalPanel context={context} />
|
||||
<BottomPanel context={context} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
:root {
|
||||
--background: #222;
|
||||
--lineBackground: #22222299;
|
||||
--foreground: #fff;
|
||||
--caret: #ffcc00;
|
||||
--selection: rgba(128, 203, 196, 0.5);
|
||||
--selectionMatch: #036dd626;
|
||||
--lineHighlight: #00000050;
|
||||
--gutterBackground: transparent;
|
||||
--gutterForeground: #8a919966;
|
||||
}
|
||||
|
||||
.darken::before {
|
||||
content: ' ';
|
||||
position: fixed;
|
||||
|
||||
@@ -8,7 +8,7 @@ export function Code(Props) {
|
||||
|
||||
return (
|
||||
<section
|
||||
className={'text-gray-100 cursor-text pb-0 overflow-auto grow'}
|
||||
className={'text-gray-100 cursor-text pb-0 overflow-auto grow z-10'}
|
||||
id="code"
|
||||
ref={(el) => {
|
||||
containerRef.current = el;
|
||||
|
||||
@@ -2,7 +2,7 @@ import Loader from '@src/repl/components/Loader';
|
||||
import { Code } from '@src/repl/components/Code';
|
||||
import BigPlayButton from '@src/repl/components/BigPlayButton';
|
||||
import UserFacingErrorMessage from '@src/repl/components/UserFacingErrorMessage';
|
||||
import { Header } from './Header';
|
||||
import { MainPanel } from './panel/Panel';
|
||||
|
||||
// type Props = {
|
||||
// context: replcontext,
|
||||
@@ -14,7 +14,7 @@ export default function EmbeddedReplEditor(Props) {
|
||||
return (
|
||||
<div className="h-full flex flex-col relative" {...editorProps}>
|
||||
<Loader active={pending} />
|
||||
<Header context={context} embedded={true} />
|
||||
<MainPanel context={context} embedded={true} />
|
||||
<BigPlayButton started={started} handleTogglePlay={handleTogglePlay} />
|
||||
<div className="grow flex relative overflow-hidden">
|
||||
<Code containerRef={containerRef} editorRef={editorRef} init={init} />
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
|
||||
import StopCircleIcon from '@heroicons/react/20/solid/StopCircleIcon';
|
||||
import cx from '@src/cx.mjs';
|
||||
import { useSettings, setIsZen } from '../../settings.mjs';
|
||||
import '../Repl.css';
|
||||
|
||||
const { BASE_URL } = import.meta.env;
|
||||
const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL;
|
||||
|
||||
export function Header({ context, embedded = false }) {
|
||||
const { started, pending, isDirty, activeCode, handleTogglePlay, handleEvaluate, handleShuffle, handleShare } =
|
||||
context;
|
||||
const isEmbedded = typeof window !== 'undefined' && (embedded || window.location !== window.parent.location);
|
||||
const { isZen, isButtonRowHidden, isCSSAnimationDisabled, fontFamily } = useSettings();
|
||||
|
||||
return (
|
||||
<header
|
||||
id="header"
|
||||
className={cx(
|
||||
'flex-none text-black z-[100] text-lg select-none h-20 md:h-14',
|
||||
!isZen && !isEmbedded && 'bg-lineHighlight',
|
||||
isZen ? 'h-12 w-8 fixed top-0 left-0' : 'sticky top-0 w-full py-1 justify-between',
|
||||
isEmbedded ? 'flex' : 'md:flex',
|
||||
)}
|
||||
style={{ fontFamily }}
|
||||
>
|
||||
<div className="px-4 flex space-x-2 md:pt-0 select-none">
|
||||
<h1
|
||||
onClick={() => {
|
||||
if (isEmbedded) window.open(window.location.href.replace('embed', ''));
|
||||
}}
|
||||
className={cx(
|
||||
isEmbedded ? 'text-l cursor-pointer' : 'text-xl',
|
||||
'text-foreground font-bold flex space-x-2 items-center',
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cx(
|
||||
'mt-[1px]',
|
||||
started && !isCSSAnimationDisabled && 'animate-spin',
|
||||
'cursor-pointer text-blue-500',
|
||||
isZen && 'fixed top-2 right-4',
|
||||
)}
|
||||
onClick={() => {
|
||||
if (!isEmbedded) {
|
||||
setIsZen(!isZen);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span className="block text-foreground rotate-90">꩜</span>
|
||||
</div>
|
||||
{!isZen && (
|
||||
<div className="space-x-2">
|
||||
<span className="">strudel</span>
|
||||
<span className="text-sm font-medium">REPL</span>
|
||||
{!isEmbedded && isButtonRowHidden && (
|
||||
<a href={`${baseNoTrailing}/learn`} className="text-sm opacity-25 font-medium">
|
||||
DOCS
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</h1>
|
||||
</div>
|
||||
{!isZen && !isButtonRowHidden && (
|
||||
<div className="flex max-w-full overflow-auto text-foreground px-1 md:px-2">
|
||||
<button
|
||||
onClick={handleTogglePlay}
|
||||
title={started ? 'stop' : 'play'}
|
||||
className={cx(
|
||||
!isEmbedded ? 'p-2' : 'px-2',
|
||||
'hover:opacity-50',
|
||||
!started && !isCSSAnimationDisabled && 'animate-pulse',
|
||||
)}
|
||||
>
|
||||
{!pending ? (
|
||||
<span className={cx('flex items-center space-x-2')}>
|
||||
{started ? <StopCircleIcon className="w-6 h-6" /> : <PlayCircleIcon className="w-6 h-6" />}
|
||||
{!isEmbedded && <span>{started ? 'stop' : 'play'}</span>}
|
||||
</span>
|
||||
) : (
|
||||
<>loading...</>
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleEvaluate}
|
||||
title="update"
|
||||
className={cx(
|
||||
'flex items-center space-x-1',
|
||||
!isEmbedded ? 'p-2' : 'px-2',
|
||||
!isDirty || !activeCode ? 'opacity-50' : 'hover:opacity-50',
|
||||
)}
|
||||
>
|
||||
{!isEmbedded && <span>update</span>}
|
||||
</button>
|
||||
{/* !isEmbedded && (
|
||||
<button
|
||||
title="shuffle"
|
||||
className="hover:opacity-50 p-2 flex items-center space-x-1"
|
||||
onClick={handleShuffle}
|
||||
>
|
||||
<span> shuffle</span>
|
||||
</button>
|
||||
) */}
|
||||
{!isEmbedded && (
|
||||
<button
|
||||
title="share"
|
||||
className={cx(
|
||||
'cursor-pointer hover:opacity-50 flex items-center space-x-1',
|
||||
!isEmbedded ? 'p-2' : 'px-2',
|
||||
)}
|
||||
onClick={handleShare}
|
||||
>
|
||||
<span>share</span>
|
||||
</button>
|
||||
)}
|
||||
{!isEmbedded && (
|
||||
<a
|
||||
title="learn"
|
||||
href={`${baseNoTrailing}/workshop/getting-started/`}
|
||||
className={cx('hover:opacity-50 flex items-center space-x-1', !isEmbedded ? 'p-2' : 'px-2')}
|
||||
>
|
||||
<span>learn</span>
|
||||
</a>
|
||||
)}
|
||||
{/* {isEmbedded && (
|
||||
<button className={cx('hover:opacity-50 px-2')}>
|
||||
<a href={window.location.href} target="_blank" rel="noopener noreferrer" title="Open in REPL">
|
||||
🚀
|
||||
</a>
|
||||
</button>
|
||||
)}
|
||||
{isEmbedded && (
|
||||
<button className={cx('hover:opacity-50 px-2')}>
|
||||
<a
|
||||
onClick={() => {
|
||||
window.location.href = initialUrl;
|
||||
window.location.reload();
|
||||
}}
|
||||
title="Reset"
|
||||
>
|
||||
💔
|
||||
</a>
|
||||
</button>
|
||||
)} */}
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
import Loader from '@src/repl/components/Loader';
|
||||
import { HorizontalPanel, VerticalPanel } from '@src/repl/components/panel/Panel';
|
||||
import { Code } from '@src/repl/components/Code';
|
||||
import Loader from '@src/repl/components/Loader';
|
||||
import { BottomPanel, MainPanel, RightPanel } from '@src/repl/components/panel/Panel';
|
||||
import UserFacingErrorMessage from '@src/repl/components/UserFacingErrorMessage';
|
||||
import { Header } from './Header';
|
||||
import { useSettings } from '@src/settings.mjs';
|
||||
|
||||
// type Props = {
|
||||
@@ -14,17 +13,22 @@ export default function ReplEditor(Props) {
|
||||
const { containerRef, editorRef, error, init, pending } = context;
|
||||
const settings = useSettings();
|
||||
const { panelPosition, isZen } = settings;
|
||||
const isEmbedded = typeof window !== 'undefined' && window.location !== window.parent.location;
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col relative" {...editorProps}>
|
||||
<Loader active={pending} />
|
||||
<Header context={context} />
|
||||
<div className="grow flex relative overflow-hidden">
|
||||
<Code containerRef={containerRef} editorRef={editorRef} init={init} />
|
||||
{!isZen && panelPosition === 'right' && <VerticalPanel context={context} />}
|
||||
<div className="flex flex-col grow overflow-hidden">
|
||||
{/* <MainPanel context={context} isEmbedded={isEmbedded} className="hidden sm:block" /> */}
|
||||
<MainPanel context={context} isEmbedded={isEmbedded} />
|
||||
<div className="flex overflow-hidden h-full">
|
||||
<Code containerRef={containerRef} editorRef={editorRef} init={init} />
|
||||
{!isZen && panelPosition === 'right' && <RightPanel context={context} />}
|
||||
</div>
|
||||
</div>
|
||||
<UserFacingErrorMessage error={error} />
|
||||
{!isZen && panelPosition === 'bottom' && <HorizontalPanel context={context} />}
|
||||
{!isZen && panelPosition === 'bottom' && <BottomPanel context={context} />}
|
||||
{/* <MainPanel context={context} isEmbedded={isEmbedded} className="block sm:hidden" /> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import cx from '@src/cx.mjs';
|
||||
|
||||
export function ActionButton({ children, label, labelIsHidden, className, ...buttonProps }) {
|
||||
return (
|
||||
<button className={cx('hover:opacity-50 text-nowrap w-fit', className)} title={label} {...buttonProps}>
|
||||
<button className={cx('hover:opacity-50 text-xs text-nowrap w-fit', className)} title={label} {...buttonProps}>
|
||||
{labelIsHidden !== true && label}
|
||||
{children}
|
||||
</button>
|
||||
@@ -13,16 +13,13 @@ export function SpecialActionButton(props) {
|
||||
const { className, ...buttonProps } = props;
|
||||
|
||||
return (
|
||||
<ActionButton
|
||||
{...buttonProps}
|
||||
className={cx('bg-background p-2 max-w-[300px] rounded-md hover:opacity-50', className)}
|
||||
/>
|
||||
<ActionButton {...buttonProps} className={cx('bg-background p-2 max-w-[300px] hover:opacity-50', className)} />
|
||||
);
|
||||
}
|
||||
|
||||
export function ActionInput({ label, className, ...props }) {
|
||||
return (
|
||||
<label className={cx('inline-flex items-center cursor-pointer', className)}>
|
||||
<label className={cx('inline-flex items-center cursor-pointer ', className)}>
|
||||
<input {...props} className="sr-only peer" />
|
||||
|
||||
<span className="inline-flex items-center peer-hover:opacity-50">{label}</span>
|
||||
@@ -35,7 +32,7 @@ export function SpecialActionInput({ className, ...props }) {
|
||||
<ActionInput
|
||||
{...props}
|
||||
className={className}
|
||||
label={<span className="bg-background p-2 max-w-[300px] rounded-md">{props.label}</span>}
|
||||
label={<span className="bg-background p-2 max-w-[300px]">{props.label}</span>}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
export function SidebarIcon() {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-panel-right-icon lucide-panel-right"
|
||||
>
|
||||
<rect width="18" height="18" x="3" y="3" rx="2" />
|
||||
<path d="M15 3v18" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Source: https://commons.wikimedia.org/wiki/File:CHAM_PUNCTUATION_SPIRAL.svg
|
||||
// License: SIL Open Font License, Version 1.1. The license text is available at https://openfontlicense.org/open-font-license-official-text/
|
||||
export function StrudelIcon({ className = '' }) {
|
||||
return (
|
||||
<svg className={className} width="100%" height="100%" viewBox="0 0 213 213">
|
||||
<g>
|
||||
<g id="_1" serif:id="1">
|
||||
<path d="M199.905,102.467c-0,17.959 -3.695,33.45 -11.078,46.468c-7.369,13.024 -17.9,23.079 -31.586,30.173c-13.673,7.093 -29.994,10.64 -48.961,10.64c-19.964,0 -37.183,-3.874 -51.66,-11.617c-14.482,-7.749 -25.592,-18.775 -33.334,-33.103c-7.749,-14.322 -11.617,-31.407 -11.617,-51.248l17.143,-0c-0,16.95 3.187,31.503 9.561,43.666c6.373,12.15 15.485,21.48 27.346,27.989c11.874,6.509 26.061,9.766 42.561,9.766c15.485,0 28.798,-2.898 39.94,-8.687c11.154,-5.789 19.693,-14.11 25.624,-24.956c5.943,-10.858 8.918,-23.812 8.918,-38.86c-0,-20.85 -5.5,-37.202 -16.5,-49.063c-11,-11.874 -26.344,-17.811 -46.031,-17.811c-17.515,-0 -31.266,4.883 -41.251,14.649c-9.991,9.767 -14.983,23.337 -14.983,40.711c-0,15.781 4.015,28.13 12.054,37.035c8.031,8.893 19.07,13.339 33.103,13.339c12.452,0 22.186,-3.431 29.196,-10.306c7.023,-6.888 10.538,-16.333 10.538,-28.348c-0,-10.281 -2.57,-18.415 -7.711,-24.416c-5.14,-6.014 -12.413,-9.021 -21.82,-9.021c-7.813,-0 -13.93,2.178 -18.351,6.528c-4.407,4.337 -6.605,10.197 -6.605,17.579c0,1.44 0.064,2.815 0.206,4.112c4.485,-7.363 11.141,-11.051 19.97,-11.051c5.5,-0 9.875,1.561 13.133,4.678c3.27,3.103 4.909,7.324 4.909,12.67c-0,5.796 -1.966,10.506 -5.886,14.136c-3.906,3.617 -9.265,5.423 -16.063,5.423c-8.533,-0 -15.337,-2.814 -20.407,-8.456c-5.076,-5.654 -7.607,-13.114 -7.607,-22.386c-0,-11.135 3.431,-19.957 10.306,-26.472c6.888,-6.528 16.121,-9.792 27.706,-9.792c13.467,0 24.03,4.164 31.689,12.491c7.672,8.327 11.515,19.584 11.515,33.771c-0,16.057 -4.884,28.753 -14.65,38.089c-9.767,9.343 -23.195,14.008 -40.274,14.008c-12.594,-0 -23.491,-2.603 -32.692,-7.814c-9.188,-5.204 -16.243,-12.625 -21.178,-22.257c-4.921,-9.625 -7.376,-21.023 -7.376,-34.182c0,-14.342 2.93,-26.64 8.79,-36.907c5.873,-10.281 14.271,-18.203 25.187,-23.774c10.93,-5.584 23.928,-8.379 38.989,-8.379c16.359,0 30.469,3.258 42.33,9.767c11.874,6.515 20.985,15.819 27.346,27.911c6.374,12.08 9.561,26.518 9.561,43.307Zm-86.408,-6.939c-7.235,-0 -11.867,4.491 -13.904,13.467c2.756,3.033 6.528,4.549 11.308,4.549c7.659,0 11.489,-3.11 11.489,-9.329c-0,-2.757 -0.797,-4.89 -2.39,-6.4c-1.581,-1.523 -3.746,-2.287 -6.503,-2.287Z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Textbox } from '../textbox/Textbox';
|
||||
import { Textbox } from '@src/repl/components/panel/SettingsTab';
|
||||
import cx from '@src/cx.mjs';
|
||||
|
||||
function IncButton({ children, className, ...buttonProps }) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { SelectInput } from './SelectInput';
|
||||
import { SelectInputDuplicate } from '@src/repl/components/panel/SettingsTab';
|
||||
import { getAudioDevices } from '@strudel/webaudio';
|
||||
|
||||
const initdevices = new Map();
|
||||
@@ -29,7 +29,7 @@ export function AudioDeviceSelector({ audioDeviceName, onChange, isDisabled }) {
|
||||
options.set(deviceName, deviceName);
|
||||
});
|
||||
return (
|
||||
<SelectInput
|
||||
<SelectInputDuplicate
|
||||
isDisabled={isDisabled}
|
||||
options={options}
|
||||
onClick={onClick}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { audioEngineTargets } from '../../../settings.mjs';
|
||||
import { SelectInput } from './SelectInput';
|
||||
import { SelectInputDuplicate } from '@src/repl/components/panel/SettingsTab';
|
||||
|
||||
// Allows the user to select an audio interface for Strudel to play through
|
||||
export function AudioEngineTargetSelector({ target, onChange, isDisabled }) {
|
||||
@@ -12,8 +12,8 @@ export function AudioEngineTargetSelector({ target, onChange, isDisabled }) {
|
||||
[audioEngineTargets.osc, audioEngineTargets.osc],
|
||||
]);
|
||||
return (
|
||||
<div className=" flex flex-col gap-1">
|
||||
<SelectInput isDisabled={isDisabled} options={options} value={target} onChange={onTargetChange} />
|
||||
<div className="flex flex-col gap-1">
|
||||
<SelectInputDuplicate isDisabled={isDisabled} options={options} value={target} onChange={onTargetChange} />
|
||||
{target === audioEngineTargets.osc && (
|
||||
<div>
|
||||
<p className="text-sm italic">
|
||||
|
||||
@@ -2,13 +2,23 @@ import cx from '@src/cx.mjs';
|
||||
import { useSettings } from '../../../settings.mjs';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { $strudel_log_history } from '../useLogger';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
export function ConsoleTab() {
|
||||
const log = useStore($strudel_log_history);
|
||||
const { fontFamily } = useSettings();
|
||||
const scrollRef = useRef();
|
||||
// scroll to bottom when log changes
|
||||
useEffect(() => {
|
||||
if (scrollRef.current) {
|
||||
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
||||
}
|
||||
}, [log]);
|
||||
return (
|
||||
<div id="console-tab" className="break-all w-full first-line:text-sm p-2 h-full" style={{ fontFamily }}>
|
||||
<div className="bg-background h-full w-full overflow-auto space-y-1 p-2 rounded-md">
|
||||
<div id="console-tab" className="break-all w-full h-full" style={{ fontFamily }}>
|
||||
<div className="h-full w-full overflow-auto space-y-1 p-2 rounded-md" ref={scrollRef}>
|
||||
{' '}
|
||||
{/* bg-background */}
|
||||
{log.map((l, i) => {
|
||||
const message = linkify(l.message);
|
||||
const color = l.data?.hap?.value?.color;
|
||||
@@ -16,12 +26,13 @@ export function ConsoleTab() {
|
||||
<div
|
||||
key={l.id}
|
||||
className={cx(
|
||||
'whitespace-nowrap',
|
||||
l.type === 'error' ? 'text-background bg-foreground' : 'text-foreground',
|
||||
l.type === 'highlight' && 'underline',
|
||||
)}
|
||||
style={color ? { color } : {}}
|
||||
>
|
||||
<span dangerouslySetInnerHTML={{ __html: message }} />
|
||||
<span dangerouslySetInnerHTML={{ __html: message }} className="whitespace-nowrap" />
|
||||
{l.count ? ` (${l.count})` : ''}
|
||||
</div>
|
||||
);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user