Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 90a58858ca | |||
| 8149b85a55 | |||
| e79b6c514a | |||
| aaa894d74b | |||
| b55721f16f | |||
| b39d948d71 | |||
| 0fee279e3d | |||
| c7d8a9cb82 | |||
| b50075f102 | |||
| fb3ca9f960 | |||
| 058b971870 | |||
| 610ea414c1 | |||
| cc6997baec | |||
| d126c28b85 | |||
| c1649b9dc0 | |||
| b0a8d12112 | |||
| b5160d38cb | |||
| 360e9b5936 | |||
| 85a6cd828e | |||
| e698f19a64 | |||
| 83c1b580dd | |||
| 9273e1f8ed | |||
| 5287825279 | |||
| 5567959afd | |||
| eaab36b051 | |||
| 9a4f3af580 | |||
| b83664dfce | |||
| 349f7ae965 | |||
| 6f41716ab5 | |||
| abeb62dea8 | |||
| 7cfed80443 | |||
| 36aa7d9b25 | |||
| 2a449ad3c0 | |||
| a71c5957cc | |||
| eef6c7d55e | |||
| 3872322da1 | |||
| f1e850a62a | |||
| 8d9278419d | |||
| 0862827a51 | |||
| f37a220a05 | |||
| aa51c2b6dd | |||
| 92da70a7ae | |||
| a55862fc25 | |||
| 09b14a5702 | |||
| 260b831815 | |||
| 665cf6ac65 | |||
| 5e90021698 | |||
| 16aeb7e12c | |||
| b4cbec173b | |||
| 8c9e06c329 | |||
| e4a35fdd72 | |||
| 370d82e66c | |||
| 876e851517 | |||
| 190fe37a9f | |||
| 623661f8d2 | |||
| f31bc3f8c5 | |||
| 12fc48544c | |||
| 3b4e44a9fd | |||
| 7850fb727e | |||
| 9b3122837e | |||
| d4c59cc73b | |||
| fe36bf54b2 | |||
| 11f26c1e2c | |||
| 5e09c3c318 | |||
| 8e6909478c | |||
| 2d2d0cabb3 | |||
| 6f04a1b8fa | |||
| a9ad3a56ad | |||
| 3069b14e9c | |||
| b6d1f96930 | |||
| b63f4eb503 | |||
| cd7bc09f9c | |||
| ccf775e976 | |||
| 811346e83d | |||
| 74ad521fc9 |
@@ -0,0 +1,62 @@
|
|||||||
|
name: Tauri Builder
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
platform: [macos-latest, ubuntu-latest, windows-latest]
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
rust_target: x86_64-unknown-linux-gnu
|
||||||
|
- os: macos-latest
|
||||||
|
rust_target: x86_64-apple-darwin
|
||||||
|
- os: macos-latest
|
||||||
|
rust_target: aarch64-apple-darwin
|
||||||
|
- os: windows-latest
|
||||||
|
rust_target: x86_64-pc-windows-msvc
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- uses: pnpm/action-setup@v2
|
||||||
|
with:
|
||||||
|
version: 8.6.2
|
||||||
|
|
||||||
|
- name: Node.js setup
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: latest
|
||||||
|
# node-version-file: '.nvmrc'
|
||||||
|
|
||||||
|
- name: Install Rust (Stable)
|
||||||
|
run:
|
||||||
|
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||||
|
|
||||||
|
- name: Install dependencies (ubuntu only)
|
||||||
|
if: matrix.platform == 'ubuntu-latest'
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf
|
||||||
|
|
||||||
|
- name: Install app dependencies from lockfile and build web
|
||||||
|
run: pnpm install
|
||||||
|
|
||||||
|
- name: Build the app
|
||||||
|
uses: tauri-apps/tauri-action@v0
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
# tauri-action replaces \_\_VERSION\_\_ with the app version
|
||||||
|
tagName: ${{ github.ref_name }}
|
||||||
|
releaseName: "Strudel v__VERSION__"
|
||||||
|
releaseBody: |
|
||||||
|
See the assets to download this version and install.
|
||||||
|
releaseDraft: true
|
||||||
|
prerelease: false
|
||||||
@@ -43,3 +43,4 @@ dev-dist
|
|||||||
Dirt-Samples
|
Dirt-Samples
|
||||||
tidal-drum-machines
|
tidal-drum-machines
|
||||||
webaudiofontdata
|
webaudiofontdata
|
||||||
|
src-tauri/target
|
||||||
@@ -31,7 +31,7 @@ Use one of the Communication Channels listed above.
|
|||||||
|
|
||||||
## Improve the Docs
|
## Improve the Docs
|
||||||
|
|
||||||
If you find some weak spots in the [docs](https://strudel.tidalcycles.org/learn/getting-started),
|
If you find some weak spots in the [docs](https://strudel.tidalcycles.org/workshop/getting-started/),
|
||||||
you can edit each file directly on github via the "Edit this page" link located in the right sidebar.
|
you can edit each file directly on github via the "Edit this page" link located in the right sidebar.
|
||||||
|
|
||||||
## Propose a Feature
|
## Propose a Feature
|
||||||
|
|||||||
@@ -52,10 +52,10 @@
|
|||||||
"@strudel.cycles/webaudio": "workspace:*",
|
"@strudel.cycles/webaudio": "workspace:*",
|
||||||
"@strudel.cycles/xen": "workspace:*",
|
"@strudel.cycles/xen": "workspace:*",
|
||||||
"acorn": "^8.8.1",
|
"acorn": "^8.8.1",
|
||||||
"dependency-tree": "^9.0.0",
|
"dependency-tree": "^9.0.0"
|
||||||
"vitest": "^0.28.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@tauri-apps/cli": "^1.4.0",
|
||||||
"@vitest/ui": "^0.28.0",
|
"@vitest/ui": "^0.28.0",
|
||||||
"canvas": "^2.11.2",
|
"canvas": "^2.11.2",
|
||||||
"eslint": "^8.39.0",
|
"eslint": "^8.39.0",
|
||||||
@@ -66,6 +66,7 @@
|
|||||||
"jsdoc-to-markdown": "^8.0.0",
|
"jsdoc-to-markdown": "^8.0.0",
|
||||||
"lerna": "^6.6.1",
|
"lerna": "^6.6.1",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"rollup-plugin-visualizer": "^5.8.1"
|
"rollup-plugin-visualizer": "^5.8.1",
|
||||||
|
"vitest": "^0.28.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ export class StrudelMirror {
|
|||||||
this.code = initialCode;
|
this.code = initialCode;
|
||||||
|
|
||||||
this.drawer = new Drawer((haps, time) => {
|
this.drawer = new Drawer((haps, time) => {
|
||||||
const currentFrame = haps.filter((hap) => time >= hap.whole.begin && time <= hap.whole.end);
|
const currentFrame = haps.filter((hap) => time >= hap.whole.begin && time <= hap.endClipped);
|
||||||
this.highlight(currentFrame);
|
this.highlight(currentFrame);
|
||||||
onDraw?.(haps, time, currentFrame);
|
onDraw?.(haps, time, currentFrame);
|
||||||
}, drawTime);
|
}, drawTime);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/codemirror",
|
"name": "@strudel/codemirror",
|
||||||
"version": "0.8.3",
|
"version": "0.8.4",
|
||||||
"description": "Codemirror Extensions for Strudel",
|
"description": "Codemirror Extensions for Strudel",
|
||||||
"main": "codemirror.mjs",
|
"main": "codemirror.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ const generic_params = [
|
|||||||
*
|
*
|
||||||
* @name legato
|
* @name legato
|
||||||
* @param {number | Pattern} duration between 0 and 1, where 1 is the length of the whole hap time
|
* @param {number | Pattern} duration between 0 and 1, where 1 is the length of the whole hap time
|
||||||
|
* @noAutocomplete
|
||||||
* @example
|
* @example
|
||||||
* "c4 eb4 g4 bb4".legato("<0.125 .25 .5 .75 1 2 4>")
|
* "c4 eb4 g4 bb4".legato("<0.125 .25 .5 .75 1 2 4>")
|
||||||
*
|
*
|
||||||
@@ -749,13 +750,14 @@ const generic_params = [
|
|||||||
['val'],
|
['val'],
|
||||||
['cps'],
|
['cps'],
|
||||||
/**
|
/**
|
||||||
* If set to 1, samples will be cut to the duration of their event.
|
* Multiplies the duration with the given number. Also cuts samples off at the end if they exceed the duration.
|
||||||
* In tidal, this would be done with legato, which [is about to land in strudel too](https://github.com/tidalcycles/strudel/issues/111)
|
* In tidal, this would be done with legato, [which has a complicated history in strudel](https://github.com/tidalcycles/strudel/issues/111).
|
||||||
|
* For now, if you're coming from tidal, just think clip = legato.
|
||||||
*
|
*
|
||||||
* @name clip
|
* @name clip
|
||||||
* @param {number | Pattern} active 1 or 0
|
* @param {number | Pattern} factor >= 0
|
||||||
* @example
|
* @example
|
||||||
* note("c a f e ~").s("piano").clip(1)
|
* note("c a f e").s("piano").clip("<.5 1 2>")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['clip'],
|
['clip'],
|
||||||
|
|||||||
@@ -32,7 +32,11 @@ export class Hap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get duration() {
|
get duration() {
|
||||||
return this.whole.end.sub(this.whole.begin);
|
return this.whole.end.sub(this.whole.begin).mul(typeof this.value?.clip === 'number' ? this.value?.clip : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
get endClipped() {
|
||||||
|
return this.whole.begin.add(this.duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
wholeOrPart() {
|
wholeOrPart() {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export * from './time.mjs';
|
|||||||
export * from './draw.mjs';
|
export * from './draw.mjs';
|
||||||
export * from './animate.mjs';
|
export * from './animate.mjs';
|
||||||
export * from './pianoroll.mjs';
|
export * from './pianoroll.mjs';
|
||||||
|
export * from './spiral.mjs';
|
||||||
export * from './ui.mjs';
|
export * from './ui.mjs';
|
||||||
export { default as drawLine } from './drawLine.mjs';
|
export { default as drawLine } from './drawLine.mjs';
|
||||||
export { default as gist } from './gist.js';
|
export { default as gist } from './gist.js';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/core",
|
"name": "@strudel.cycles/core",
|
||||||
"version": "0.8.1",
|
"version": "0.8.2",
|
||||||
"description": "Port of Tidal Cycles to JavaScript",
|
"description": "Port of Tidal Cycles to JavaScript",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1582,6 +1582,24 @@ export const range2 = register('range2', function (min, max, pat) {
|
|||||||
return pat.fromBipolar()._range(min, max);
|
return pat.fromBipolar()._range(min, max);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows dividing numbers via list notation using ":".
|
||||||
|
* Returns a new pattern with just numbers.
|
||||||
|
* @name ratio
|
||||||
|
* @memberof Pattern
|
||||||
|
* @returns Pattern
|
||||||
|
* @example
|
||||||
|
* ratio("1, 5:4, 3:2").mul(110).freq().s("piano").slow(2)
|
||||||
|
*/
|
||||||
|
export const ratio = register('ratio', (pat) =>
|
||||||
|
pat.fmap((v) => {
|
||||||
|
if (!Array.isArray(v)) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
return v.slice(1).reduce((acc, n) => acc / n, v[0]);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Structural and temporal transformations
|
// Structural and temporal transformations
|
||||||
|
|
||||||
@@ -1677,6 +1695,9 @@ export const ply = register('ply', function (factor, pat) {
|
|||||||
* s("<bd sd> hh").fast(2) // s("[<bd sd> hh]*2")
|
* s("<bd sd> hh").fast(2) // s("[<bd sd> hh]*2")
|
||||||
*/
|
*/
|
||||||
export const { fast, density } = register(['fast', 'density'], function (factor, pat) {
|
export const { fast, density } = register(['fast', 'density'], function (factor, pat) {
|
||||||
|
if (factor === 0) {
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
factor = Fraction(factor);
|
factor = Fraction(factor);
|
||||||
const fastQuery = pat.withQueryTime((t) => t.mul(factor));
|
const fastQuery = pat.withQueryTime((t) => t.mul(factor));
|
||||||
return fastQuery.withHapTime((t) => t.div(factor));
|
return fastQuery.withHapTime((t) => t.div(factor));
|
||||||
@@ -1703,6 +1724,9 @@ export const hurry = register('hurry', function (r, pat) {
|
|||||||
* s("<bd sd> hh").slow(2) // s("[<bd sd> hh]/2")
|
* s("<bd sd> hh").slow(2) // s("[<bd sd> hh]/2")
|
||||||
*/
|
*/
|
||||||
export const { slow, sparsity } = register(['slow', 'sparsity'], function (factor, pat) {
|
export const { slow, sparsity } = register(['slow', 'sparsity'], function (factor, pat) {
|
||||||
|
if (factor === 0) {
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
return pat._fast(Fraction(1).div(factor));
|
return pat._fast(Fraction(1).div(factor));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2029,7 +2053,7 @@ export const jux = register('jux', function (func, pat) {
|
|||||||
* @example
|
* @example
|
||||||
* "<0 [2 4]>"
|
* "<0 [2 4]>"
|
||||||
* .echoWith(4, 1/8, (p,n) => p.add(n*2))
|
* .echoWith(4, 1/8, (p,n) => p.add(n*2))
|
||||||
* .scale('C minor').note().legato(.2)
|
* .scale('C minor').note().clip(.2)
|
||||||
*/
|
*/
|
||||||
export const { echoWith, echowith, stutWith, stutwith } = register(
|
export const { echoWith, echowith, stutWith, stutwith } = register(
|
||||||
['echoWith', 'echowith', 'stutWith', 'stutwith'],
|
['echoWith', 'echowith', 'stutWith', 'stutwith'],
|
||||||
@@ -2179,6 +2203,7 @@ export const velocity = register('velocity', function (velocity, pat) {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Multiplies the hap duration with the given factor.
|
* Multiplies the hap duration with the given factor.
|
||||||
|
* With samples, `clip` might be a better function to use ([more info](https://github.com/tidalcycles/strudel/pull/598))
|
||||||
* @name legato
|
* @name legato
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @example
|
* @example
|
||||||
@@ -2251,7 +2276,7 @@ const _loopAt = function (factor, pat, cps = 1) {
|
|||||||
* s("breaks165").slice(8, "0 1 <2 2*2> 3 [4 0] 5 6 7".every(3, rev)).slow(1.5)
|
* s("breaks165").slice(8, "0 1 <2 2*2> 3 [4 0] 5 6 7".every(3, rev)).slow(1.5)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const slice = register(
|
export const slice = register(
|
||||||
'slice',
|
'slice',
|
||||||
function (npat, ipat, opat) {
|
function (npat, ipat, opat) {
|
||||||
return npat.innerBind((n) =>
|
return npat.innerBind((n) =>
|
||||||
@@ -2279,7 +2304,7 @@ const slice = register(
|
|||||||
* s("breaks165").splice(8, "0 1 [2 3 0]@2 3 0@2 7").hurry(0.65)
|
* s("breaks165").splice(8, "0 1 [2 3 0]@2 3 0@2 7").hurry(0.65)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const splice = register(
|
export const splice = register(
|
||||||
'splice',
|
'splice',
|
||||||
function (npat, ipat, opat) {
|
function (npat, ipat, opat) {
|
||||||
const sliced = slice(npat, ipat, opat);
|
const sliced = slice(npat, ipat, opat);
|
||||||
@@ -2296,7 +2321,10 @@ const splice = register(
|
|||||||
false, // turns off auto-patternification
|
false, // turns off auto-patternification
|
||||||
);
|
);
|
||||||
|
|
||||||
const { loopAt, loopat } = register(['loopAt', 'loopat'], function (factor, pat) {
|
// this function will be redefined in repl.mjs to use the correct cps value.
|
||||||
|
// It is still here to work in cases where repl.mjs is not used
|
||||||
|
|
||||||
|
export const { loopAt, loopat } = register(['loopAt', 'loopat'], function (factor, pat) {
|
||||||
return _loopAt(factor, pat, 1);
|
return _loopAt(factor, pat, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2313,6 +2341,6 @@ const { loopAt, loopat } = register(['loopAt', 'loopat'], function (factor, pat)
|
|||||||
* s("rhodes").loopAtCps(4,1.5).cps(1.5)
|
* s("rhodes").loopAtCps(4,1.5).cps(1.5)
|
||||||
*/
|
*/
|
||||||
// TODO - global cps clock
|
// TODO - global cps clock
|
||||||
const { loopAtCps, loopatcps } = register(['loopAtCps', 'loopatcps'], function (factor, cps, pat) {
|
export const { loopAtCps, loopatcps } = register(['loopAtCps', 'loopatcps'], function (factor, cps, pat) {
|
||||||
return _loopAt(factor, pat, cps);
|
return _loopAt(factor, pat, cps);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ Pattern.prototype.pianoroll = function ({
|
|||||||
ctx.fillRect(0, 0, w, h);
|
ctx.fillRect(0, 0, w, h);
|
||||||
}
|
}
|
||||||
const inFrame = (event) =>
|
const inFrame = (event) =>
|
||||||
(!hideNegative || event.whole.begin >= 0) && event.whole.begin <= t + to && event.whole.end >= t + from;
|
(!hideNegative || event.whole.begin >= 0) && event.whole.begin <= t + to && event.endClipped >= t + from;
|
||||||
events.filter(inFrame).forEach((event) => {
|
events.filter(inFrame).forEach((event) => {
|
||||||
const isActive = event.whole.begin <= t && event.whole.end > t;
|
const isActive = event.whole.begin <= t && event.endClipped > t;
|
||||||
ctx.fillStyle = event.context?.color || inactive;
|
ctx.fillStyle = event.context?.color || inactive;
|
||||||
ctx.strokeStyle = event.context?.color || active;
|
ctx.strokeStyle = event.context?.color || active;
|
||||||
ctx.globalAlpha = event.context.velocity ?? event.value?.gain ?? 1;
|
ctx.globalAlpha = event.context.velocity ?? event.value?.gain ?? 1;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { evaluate as _evaluate } from './evaluate.mjs';
|
|||||||
import { logger } from './logger.mjs';
|
import { logger } from './logger.mjs';
|
||||||
import { setTime } from './time.mjs';
|
import { setTime } from './time.mjs';
|
||||||
import { evalScope } from './evaluate.mjs';
|
import { evalScope } from './evaluate.mjs';
|
||||||
|
import { register } from './pattern.mjs';
|
||||||
|
|
||||||
export function repl({
|
export function repl({
|
||||||
interval,
|
interval,
|
||||||
@@ -50,10 +51,32 @@ export function repl({
|
|||||||
const start = () => scheduler.start();
|
const start = () => scheduler.start();
|
||||||
const pause = () => scheduler.pause();
|
const pause = () => scheduler.pause();
|
||||||
const setCps = (cps) => scheduler.setCps(cps);
|
const setCps = (cps) => scheduler.setCps(cps);
|
||||||
|
const setCpm = (cpm) => scheduler.setCps(cpm / 60);
|
||||||
|
|
||||||
|
// the following functions use the cps value, which is why they are defined here..
|
||||||
|
const loopAt = register('loopAt', (cycles, pat) => {
|
||||||
|
return pat.loopAtCps(cycles, scheduler.cps);
|
||||||
|
});
|
||||||
|
|
||||||
|
const fit = register('fit', (pat) =>
|
||||||
|
pat.withHap((hap) =>
|
||||||
|
hap.withValue((v) => ({
|
||||||
|
...v,
|
||||||
|
speed: scheduler.cps / hap.whole.duration, // overwrite speed completely?
|
||||||
|
unit: 'c',
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
evalScope({
|
evalScope({
|
||||||
|
loopAt,
|
||||||
|
fit,
|
||||||
setCps,
|
setCps,
|
||||||
setcps: setCps,
|
setcps: setCps,
|
||||||
|
setCpm,
|
||||||
|
setcpm: setCpm,
|
||||||
});
|
});
|
||||||
|
|
||||||
return { scheduler, evaluate, start, stop, pause, setCps, setPattern };
|
return { scheduler, evaluate, start, stop, pause, setCps, setPattern };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const isaw2 = isaw.toBipolar();
|
|||||||
*
|
*
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* "c3 [eb3,g3] g2 [g3,bb3]".legato(saw.slow(4)).note()
|
* "c3 [eb3,g3] g2 [g3,bb3]".note().clip(saw.slow(4))
|
||||||
* @example
|
* @example
|
||||||
* saw.range(0,8).segment(8).scale('C major').slow(4).note()
|
* saw.range(0,8).segment(8).scale('C major').slow(4).note()
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
import { Pattern } from './index.mjs';
|
||||||
|
|
||||||
|
// polar coords -> xy
|
||||||
|
function fromPolar(angle, radius, cx, cy) {
|
||||||
|
const radians = ((angle - 90) * Math.PI) / 180;
|
||||||
|
return [cx + Math.cos(radians) * radius, cy + Math.sin(radians) * radius];
|
||||||
|
}
|
||||||
|
|
||||||
|
const xyOnSpiral = (angle, margin, cx, cy, rotate = 0) => fromPolar((angle + rotate) * 360, margin * angle, cx, cy); // TODO: logSpiral
|
||||||
|
|
||||||
|
// draw spiral / segment of spiral
|
||||||
|
function spiralSegment(options) {
|
||||||
|
let {
|
||||||
|
ctx,
|
||||||
|
from = 0,
|
||||||
|
to = 3,
|
||||||
|
margin = 50,
|
||||||
|
cx = 100,
|
||||||
|
cy = 100,
|
||||||
|
rotate = 0,
|
||||||
|
thickness = margin / 2,
|
||||||
|
color = '#0000ff30',
|
||||||
|
cap = 'round',
|
||||||
|
stretch = 1,
|
||||||
|
fromOpacity = 1,
|
||||||
|
toOpacity = 1,
|
||||||
|
} = options;
|
||||||
|
from *= stretch;
|
||||||
|
to *= stretch;
|
||||||
|
rotate *= stretch;
|
||||||
|
ctx.lineWidth = thickness;
|
||||||
|
ctx.lineCap = cap;
|
||||||
|
ctx.strokeStyle = color;
|
||||||
|
ctx.globalAlpha = fromOpacity;
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
let [sx, sy] = xyOnSpiral(from, margin, cx, cy, rotate);
|
||||||
|
ctx.moveTo(sx, sy);
|
||||||
|
|
||||||
|
const increment = 1 / 60;
|
||||||
|
let angle = from;
|
||||||
|
while (angle <= to) {
|
||||||
|
const [x, y] = xyOnSpiral(angle, margin, cx, cy, rotate);
|
||||||
|
//ctx.lineWidth = angle*thickness;
|
||||||
|
ctx.globalAlpha = ((angle - from) / (to - from)) * toOpacity;
|
||||||
|
ctx.lineTo(x, y);
|
||||||
|
angle += increment;
|
||||||
|
}
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
Pattern.prototype.spiral = function (options = {}) {
|
||||||
|
const {
|
||||||
|
stretch = 1,
|
||||||
|
size = 80,
|
||||||
|
thickness = size / 2,
|
||||||
|
cap = 'butt', // round butt squar,
|
||||||
|
inset = 3, // start angl,
|
||||||
|
playheadColor = '#ffffff90',
|
||||||
|
playheadLength = 0.02,
|
||||||
|
playheadThickness = thickness,
|
||||||
|
padding = 0,
|
||||||
|
steady = 1,
|
||||||
|
inactiveColor = '#ffffff20',
|
||||||
|
colorizeInactive = 0,
|
||||||
|
fade = true,
|
||||||
|
// logSpiral = true,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
function spiral({ ctx, time, haps, drawTime }) {
|
||||||
|
ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
|
||||||
|
const [cx, cy] = [ctx.canvas.width / 2, ctx.canvas.height / 2];
|
||||||
|
const settings = {
|
||||||
|
margin: size / stretch,
|
||||||
|
cx,
|
||||||
|
cy,
|
||||||
|
stretch,
|
||||||
|
cap,
|
||||||
|
thickness,
|
||||||
|
};
|
||||||
|
|
||||||
|
const playhead = {
|
||||||
|
...settings,
|
||||||
|
thickness: playheadThickness,
|
||||||
|
from: inset - playheadLength,
|
||||||
|
to: inset,
|
||||||
|
color: playheadColor,
|
||||||
|
};
|
||||||
|
|
||||||
|
const [min] = drawTime;
|
||||||
|
const rotate = steady * time;
|
||||||
|
haps.forEach((hap) => {
|
||||||
|
const isActive = hap.whole.begin <= time && hap.endClipped > time;
|
||||||
|
const from = hap.whole.begin - time + inset;
|
||||||
|
const to = hap.endClipped - time + inset - padding;
|
||||||
|
const { color } = hap.context;
|
||||||
|
const opacity = fade ? 1 - Math.abs((hap.whole.begin - time) / min) : 1;
|
||||||
|
spiralSegment({
|
||||||
|
ctx,
|
||||||
|
...settings,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
rotate,
|
||||||
|
color: colorizeInactive || isActive ? color : inactiveColor,
|
||||||
|
fromOpacity: opacity,
|
||||||
|
toOpacity: opacity,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
spiralSegment({
|
||||||
|
ctx,
|
||||||
|
...playhead,
|
||||||
|
rotate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.onPaint((ctx, time, haps, drawTime) => spiral({ ctx, time, haps, drawTime }));
|
||||||
|
};
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*test for issue 302 support alternative solmization types */
|
||||||
|
import { sol2note } from '../util.mjs';
|
||||||
|
import { test } from 'vitest';
|
||||||
|
import assert from 'assert';
|
||||||
|
|
||||||
|
test('solmization - letters', () => {
|
||||||
|
const result = sol2note(60, 'letters');
|
||||||
|
const expected = 'C4';
|
||||||
|
assert.equal(result, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('solmization - solfeggio', () => {
|
||||||
|
const result = sol2note(60, 'solfeggio');
|
||||||
|
const expected = 'Do4';
|
||||||
|
assert.equal(result, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('solmization - indian', () => {
|
||||||
|
const result = sol2note(60, 'indian');
|
||||||
|
const expected = 'Sa4';
|
||||||
|
assert.equal(result, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('solmization - german', () => {
|
||||||
|
const result = sol2note(60, 'german');
|
||||||
|
const expected = 'C4';
|
||||||
|
assert.equal(result, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('solmization - byzantine', () => {
|
||||||
|
const result = sol2note(60, 'byzantine');
|
||||||
|
const expected = 'Ni4';
|
||||||
|
assert.equal(result, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('solmization - japanese', () => {
|
||||||
|
const result = sol2note(60, 'japanese');
|
||||||
|
const expected = 'I4';
|
||||||
|
assert.equal(result, expected);
|
||||||
|
});
|
||||||
@@ -6,12 +6,12 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
|
|
||||||
// returns true if the given string is a note
|
// returns true if the given string is a note
|
||||||
export const isNoteWithOctave = (name) => /^[a-gA-G][#bs]*[0-9]$/.test(name);
|
export const isNoteWithOctave = (name) => /^[a-gA-G][#bs]*[0-9]$/.test(name);
|
||||||
export const isNote = (name) => /^[a-gA-G][#bs]*[0-9]?$/.test(name);
|
export const isNote = (name) => /^[a-gA-G][#bsf]*[0-9]?$/.test(name);
|
||||||
export const tokenizeNote = (note) => {
|
export const tokenizeNote = (note) => {
|
||||||
if (typeof note !== 'string') {
|
if (typeof note !== 'string') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const [pc, acc = '', oct] = note.match(/^([a-gA-G])([#bs]*)([0-9])?$/)?.slice(1) || [];
|
const [pc, acc = '', oct] = note.match(/^([a-gA-G])([#bsf]*)([0-9])?$/)?.slice(1) || [];
|
||||||
if (!pc) {
|
if (!pc) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ export const noteToMidi = (note) => {
|
|||||||
throw new Error('not a note: "' + note + '"');
|
throw new Error('not a note: "' + note + '"');
|
||||||
}
|
}
|
||||||
const chroma = { c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11 }[pc.toLowerCase()];
|
const chroma = { c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11 }[pc.toLowerCase()];
|
||||||
const offset = acc?.split('').reduce((o, char) => o + { '#': 1, b: -1, s: 1 }[char], 0) || 0;
|
const offset = acc?.split('').reduce((o, char) => o + { '#': 1, b: -1, s: 1, f: -1 }[char], 0) || 0;
|
||||||
return (Number(oct) + 1) * 12 + chroma + offset;
|
return (Number(oct) + 1) * 12 + chroma + offset;
|
||||||
};
|
};
|
||||||
export const midiToFreq = (n) => {
|
export const midiToFreq = (n) => {
|
||||||
@@ -69,7 +69,7 @@ export const getFreq = (noteOrMidi) => {
|
|||||||
|
|
||||||
const pcs = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'];
|
const pcs = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'];
|
||||||
/**
|
/**
|
||||||
* @deprecated does not appear to be referenced or invoked anywhere in the codebase
|
* @deprecated only used in workshop (first-notes)
|
||||||
* @noAutocomplete
|
* @noAutocomplete
|
||||||
*/
|
*/
|
||||||
export const midi2note = (n) => {
|
export const midi2note = (n) => {
|
||||||
@@ -215,3 +215,59 @@ export const splitAt = function (index, value) {
|
|||||||
export const zipWith = (f, xs, ys) => xs.map((n, i) => f(n, ys[i]));
|
export const zipWith = (f, xs, ys) => xs.map((n, i) => f(n, ys[i]));
|
||||||
|
|
||||||
export const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
export const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
||||||
|
|
||||||
|
/* solmization, not used yet */
|
||||||
|
const solfeggio = ['Do', 'Reb', 'Re', 'Mib', 'Mi', 'Fa', 'Solb', 'Sol', 'Lab', 'La', 'Sib', 'Si']; /*solffegio notes*/
|
||||||
|
const indian = [
|
||||||
|
'Sa',
|
||||||
|
'Re',
|
||||||
|
'Ga',
|
||||||
|
'Ma',
|
||||||
|
'Pa',
|
||||||
|
'Dha',
|
||||||
|
'Ni',
|
||||||
|
]; /*indian musical notes, seems like they do not use flats or sharps*/
|
||||||
|
const german = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Hb', 'H']; /*german & dutch musical notes*/
|
||||||
|
const byzantine = [
|
||||||
|
'Ni',
|
||||||
|
'Pab',
|
||||||
|
'Pa',
|
||||||
|
'Voub',
|
||||||
|
'Vou',
|
||||||
|
'Ga',
|
||||||
|
'Dib',
|
||||||
|
'Di',
|
||||||
|
'Keb',
|
||||||
|
'Ke',
|
||||||
|
'Zob',
|
||||||
|
'Zo',
|
||||||
|
]; /*byzantine musical notes*/
|
||||||
|
const japanese = [
|
||||||
|
'I',
|
||||||
|
'Ro',
|
||||||
|
'Ha',
|
||||||
|
'Ni',
|
||||||
|
'Ho',
|
||||||
|
'He',
|
||||||
|
'To',
|
||||||
|
]; /*traditional japanese musical notes, seems like they do not use falts or sharps*/
|
||||||
|
|
||||||
|
const english = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'];
|
||||||
|
|
||||||
|
export const sol2note = (n, notation = 'letters') => {
|
||||||
|
const pc =
|
||||||
|
notation === 'solfeggio'
|
||||||
|
? solfeggio /*check if its is any of the following*/
|
||||||
|
: notation === 'indian'
|
||||||
|
? indian
|
||||||
|
: notation === 'german'
|
||||||
|
? german
|
||||||
|
: notation === 'byzantine'
|
||||||
|
? byzantine
|
||||||
|
: notation === 'japanese'
|
||||||
|
? japanese
|
||||||
|
: english; /*if not use standard version*/
|
||||||
|
const note = pc[n % 12]; /*calculating the midi value to the note*/
|
||||||
|
const oct = Math.floor(n / 12) - 1;
|
||||||
|
return note + oct;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/csound",
|
"name": "@strudel.cycles/csound",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "csound bindings for strudel",
|
"description": "csound bindings for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/eval",
|
"name": "@strudel.cycles/eval",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "Code evaluator for strudel",
|
"description": "Code evaluator for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ Pattern.prototype.midi = function (output) {
|
|||||||
hap.ensureObjectValue();
|
hap.ensureObjectValue();
|
||||||
|
|
||||||
// calculate time
|
// calculate time
|
||||||
const timingOffset = WebMidi.time - getAudioContext().currentTime * 1000;
|
const timingOffset = WebMidi.time - getAudioContext().getOutputTimestamp().contextTime * 1000;
|
||||||
time = time * 1000 + timingOffset;
|
time = time * 1000 + timingOffset;
|
||||||
|
|
||||||
// destructure value
|
// destructure value
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/midi",
|
"name": "@strudel.cycles/midi",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "Midi API for strudel",
|
"description": "Midi API for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/mini",
|
"name": "@strudel.cycles/mini",
|
||||||
"version": "0.8.1",
|
"version": "0.8.2",
|
||||||
"description": "Mini notation for strudel",
|
"description": "Mini notation for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/osc",
|
"name": "@strudel.cycles/osc",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "OSC messaging for strudel",
|
"description": "OSC messaging for strudel",
|
||||||
"main": "osc.mjs",
|
"main": "osc.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/react",
|
"name": "@strudel.cycles/react",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "React components for strudel",
|
"description": "React components for strudel",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import React, { useMemo } from 'react';
|
|||||||
import _CodeMirror from '@uiw/react-codemirror';
|
import _CodeMirror from '@uiw/react-codemirror';
|
||||||
import { EditorView, Decoration } from '@codemirror/view';
|
import { EditorView, Decoration } from '@codemirror/view';
|
||||||
import { StateField, StateEffect } from '@codemirror/state';
|
import { StateField, StateEffect } from '@codemirror/state';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
import { javascript, javascriptLanguage } from '@codemirror/lang-javascript';
|
||||||
import strudelTheme from '../themes/strudel-theme';
|
import strudelTheme from '../themes/strudel-theme';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { autocompletion } from '@codemirror/autocomplete';
|
import { autocompletion } from '@codemirror/autocomplete';
|
||||||
//import { strudelAutocomplete } from './Autocomplete';
|
import { strudelAutocomplete } from './Autocomplete';
|
||||||
import { vim } from '@replit/codemirror-vim';
|
import { vim } from '@replit/codemirror-vim';
|
||||||
import { emacs } from '@replit/codemirror-emacs';
|
import { emacs } from '@replit/codemirror-emacs';
|
||||||
|
|
||||||
@@ -88,14 +88,7 @@ const highlightField = StateField.define({
|
|||||||
provide: (f) => EditorView.decorations.from(f),
|
provide: (f) => EditorView.decorations.from(f),
|
||||||
});
|
});
|
||||||
|
|
||||||
const staticExtensions = [
|
const staticExtensions = [javascript(), highlightField, flashField];
|
||||||
javascript(),
|
|
||||||
highlightField,
|
|
||||||
flashField,
|
|
||||||
// javascriptLanguage.data.of({ autocomplete: strudelAutocomplete }),
|
|
||||||
// autocompletion({ override: [strudelAutocomplete] }),
|
|
||||||
autocompletion({ override: [] }), // wait for https://github.com/uiwjs/react-codemirror/pull/458
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function CodeMirror({
|
export default function CodeMirror({
|
||||||
value,
|
value,
|
||||||
@@ -105,6 +98,8 @@ export default function CodeMirror({
|
|||||||
theme,
|
theme,
|
||||||
keybindings,
|
keybindings,
|
||||||
isLineNumbersDisplayed,
|
isLineNumbersDisplayed,
|
||||||
|
isAutoCompletionEnabled,
|
||||||
|
isLineWrappingEnabled,
|
||||||
fontSize = 18,
|
fontSize = 18,
|
||||||
fontFamily = 'monospace',
|
fontFamily = 'monospace',
|
||||||
options,
|
options,
|
||||||
@@ -116,12 +111,14 @@ export default function CodeMirror({
|
|||||||
},
|
},
|
||||||
[onChange],
|
[onChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleOnCreateEditor = useCallback(
|
const handleOnCreateEditor = useCallback(
|
||||||
(view) => {
|
(view) => {
|
||||||
onViewChanged?.(view);
|
onViewChanged?.(view);
|
||||||
},
|
},
|
||||||
[onViewChanged],
|
[onViewChanged],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleOnUpdate = useCallback(
|
const handleOnUpdate = useCallback(
|
||||||
(viewUpdate) => {
|
(viewUpdate) => {
|
||||||
if (viewUpdate.selectionSet && onSelectionChange) {
|
if (viewUpdate.selectionSet && onSelectionChange) {
|
||||||
@@ -130,16 +127,31 @@ export default function CodeMirror({
|
|||||||
},
|
},
|
||||||
[onSelectionChange],
|
[onSelectionChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
const extensions = useMemo(() => {
|
const extensions = useMemo(() => {
|
||||||
|
let _extensions = [...staticExtensions];
|
||||||
let bindings = {
|
let bindings = {
|
||||||
vim,
|
vim,
|
||||||
emacs,
|
emacs,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (bindings[keybindings]) {
|
if (bindings[keybindings]) {
|
||||||
return [...staticExtensions, bindings[keybindings]()];
|
_extensions.push(bindings[keybindings]());
|
||||||
}
|
}
|
||||||
return staticExtensions;
|
|
||||||
}, [keybindings]);
|
if (isAutoCompletionEnabled) {
|
||||||
|
_extensions.push(javascriptLanguage.data.of({ autocomplete: strudelAutocomplete }));
|
||||||
|
} else {
|
||||||
|
_extensions.push(autocompletion({ override: [] }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLineWrappingEnabled) {
|
||||||
|
_extensions.push(EditorView.lineWrapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _extensions;
|
||||||
|
}, [keybindings, isAutoCompletionEnabled, isLineWrappingEnabled]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ fontSize, fontFamily }} className="w-full">
|
<div style={{ fontSize, fontFamily }} className="w-full">
|
||||||
<_CodeMirror
|
<_CodeMirror
|
||||||
|
|||||||
@@ -24,3 +24,7 @@
|
|||||||
.cm-theme-light {
|
.cm-theme-light {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
z-index: 0 !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ function useHighlighting({ view, pattern, active, getTime }) {
|
|||||||
const begin = Math.max(lastEnd.current ?? audioTime, audioTime - 1 / 10, -0.01); // negative time seems buggy
|
const begin = Math.max(lastEnd.current ?? audioTime, audioTime - 1 / 10, -0.01); // negative time seems buggy
|
||||||
const span = [round(begin), round(audioTime + 1 / 60)];
|
const span = [round(begin), round(audioTime + 1 / 60)];
|
||||||
lastEnd.current = span[1];
|
lastEnd.current = span[1];
|
||||||
highlights.current = highlights.current.filter((hap) => hap.whole.end > audioTime); // keep only highlights that are still active
|
highlights.current = highlights.current.filter((hap) => hap.endClipped > audioTime); // keep only highlights that are still active
|
||||||
const haps = pattern.queryArc(...span).filter((hap) => hap.hasOnset());
|
const haps = pattern.queryArc(...span).filter((hap) => hap.hasOnset());
|
||||||
highlights.current = highlights.current.concat(haps); // add potential new onsets
|
highlights.current = highlights.current.concat(haps); // add potential new onsets
|
||||||
view.dispatch({ effects: setHighlights.of({ haps: highlights.current }) }); // highlight all still active + new active haps
|
view.dispatch({ effects: setHighlights.of({ haps: highlights.current }) }); // highlight all still active + new active haps
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/serial",
|
"name": "@strudel.cycles/serial",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "Webserial API for strudel",
|
"description": "Webserial API for strudel",
|
||||||
"main": "serial.mjs",
|
"main": "serial.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/soundfonts",
|
"name": "@strudel.cycles/soundfonts",
|
||||||
"version": "0.8.1",
|
"version": "0.8.2",
|
||||||
"description": "Soundsfont support for strudel",
|
"description": "Soundsfont support for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/tonal",
|
"name": "@strudel.cycles/tonal",
|
||||||
"version": "0.8.1",
|
"version": "0.8.2",
|
||||||
"description": "Tonal functions for strudel",
|
"description": "Tonal functions for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ export const scaleTranspose = register('scaleTranspose', function (offset /* : n
|
|||||||
export const scale = register('scale', function (scale, pat) {
|
export const scale = register('scale', function (scale, pat) {
|
||||||
// Supports ':' list syntax in mininotation
|
// Supports ':' list syntax in mininotation
|
||||||
if (Array.isArray(scale)) {
|
if (Array.isArray(scale)) {
|
||||||
scale = scale.join(' ');
|
scale = scale.flat().join(' ');
|
||||||
}
|
}
|
||||||
return pat.withHap((hap) => {
|
return pat.withHap((hap) => {
|
||||||
const isObject = typeof hap.value === 'object';
|
const isObject = typeof hap.value === 'object';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/tone",
|
"name": "@strudel.cycles/tone",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "Tone.js API for strudel",
|
"description": "Tone.js API for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/transpiler",
|
"name": "@strudel.cycles/transpiler",
|
||||||
"version": "0.8.1",
|
"version": "0.8.2",
|
||||||
"description": "Transpiler for strudel user code. Converts syntactically correct but semantically meaningless JS into evaluatable strudel code.",
|
"description": "Transpiler for strudel user code. Converts syntactically correct but semantically meaningless JS into evaluatable strudel code.",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/web",
|
"name": "@strudel/web",
|
||||||
"version": "0.8.2",
|
"version": "0.8.3",
|
||||||
"description": "Easy to setup, opiniated bundle of Strudel for the browser.",
|
"description": "Easy to setup, opiniated bundle of Strudel for the browser.",
|
||||||
"main": "web.mjs",
|
"main": "web.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -34,10 +34,10 @@
|
|||||||
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
"homepage": "https://github.com/tidalcycles/strudel#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strudel.cycles/core": "workspace:*",
|
"@strudel.cycles/core": "workspace:*",
|
||||||
"@strudel.cycles/webaudio": "workspace:*",
|
|
||||||
"@strudel.cycles/mini": "workspace:*",
|
"@strudel.cycles/mini": "workspace:*",
|
||||||
"@strudel.cycles/tonal": "workspace:*",
|
"@strudel.cycles/tonal": "workspace:*",
|
||||||
"@strudel.cycles/transpiler": "workspace:*"
|
"@strudel.cycles/transpiler": "workspace:*",
|
||||||
|
"@strudel.cycles/webaudio": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^4.3.3"
|
"vite": "^4.3.3"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/webaudio",
|
"name": "@strudel.cycles/webaudio",
|
||||||
"version": "0.8.1",
|
"version": "0.8.2",
|
||||||
"description": "Web Audio helpers for Strudel",
|
"description": "Web Audio helpers for Strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function humanFileSize(bytes, si) {
|
|||||||
return bytes.toFixed(1) + ' ' + units[u];
|
return bytes.toFixed(1) + ' ' + units[u];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getSampleBufferSource = async (s, n, note, speed, freq, bank) => {
|
export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resolveUrl) => {
|
||||||
let transpose = 0;
|
let transpose = 0;
|
||||||
if (freq !== undefined && note !== undefined) {
|
if (freq !== undefined && note !== undefined) {
|
||||||
logger('[sampler] hap has note and freq. ignoring note', 'warning');
|
logger('[sampler] hap has note and freq. ignoring note', 'warning');
|
||||||
@@ -45,6 +45,9 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, bank) => {
|
|||||||
transpose = -midiDiff(closest); // semitones to repitch
|
transpose = -midiDiff(closest); // semitones to repitch
|
||||||
sampleUrl = bank[closest][n % bank[closest].length];
|
sampleUrl = bank[closest][n % bank[closest].length];
|
||||||
}
|
}
|
||||||
|
if (resolveUrl) {
|
||||||
|
sampleUrl = await resolveUrl(sampleUrl);
|
||||||
|
}
|
||||||
let buffer = await loadBuffer(sampleUrl, ac, s, n);
|
let buffer = await loadBuffer(sampleUrl, ac, s, n);
|
||||||
if (speed < 0) {
|
if (speed < 0) {
|
||||||
// should this be cached?
|
// should this be cached?
|
||||||
@@ -91,6 +94,46 @@ export const getLoadedBuffer = (url) => {
|
|||||||
return bufferCache[url];
|
return bufferCache[url];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const processSampleMap = (sampleMap, fn, baseUrl = sampleMap._base || '') => {
|
||||||
|
return Object.entries(sampleMap).forEach(([key, value]) => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
value = [value];
|
||||||
|
}
|
||||||
|
if (typeof value !== 'object') {
|
||||||
|
throw new Error('wrong sample map format for ' + key);
|
||||||
|
}
|
||||||
|
baseUrl = value._base || baseUrl;
|
||||||
|
const replaceUrl = (v) => (baseUrl + v).replace('github:', 'https://raw.githubusercontent.com/');
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
//return [key, value.map(replaceUrl)];
|
||||||
|
value = value.map(replaceUrl);
|
||||||
|
} else {
|
||||||
|
// must be object
|
||||||
|
value = Object.fromEntries(
|
||||||
|
Object.entries(value).map(([note, samples]) => {
|
||||||
|
return [note, (typeof samples === 'string' ? [samples] : samples).map(replaceUrl)];
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fn(key, value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// allows adding a custom url prefix handler
|
||||||
|
// for example, it is used by the desktop app to load samples starting with '~/music'
|
||||||
|
let resourcePrefixHandlers = {};
|
||||||
|
export function registerSamplesPrefix(prefix, resolve) {
|
||||||
|
resourcePrefixHandlers[prefix] = resolve;
|
||||||
|
}
|
||||||
|
// finds a prefix handler for the given url (if any)
|
||||||
|
function getSamplesPrefixHandler(url) {
|
||||||
|
const handler = Object.entries(resourcePrefixHandlers).find(([key]) => url.startsWith(key));
|
||||||
|
if (handler) {
|
||||||
|
return handler[1];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a collection of samples to use with `s`
|
* Loads a collection of samples to use with `s`
|
||||||
* @example
|
* @example
|
||||||
@@ -107,6 +150,11 @@ export const getLoadedBuffer = (url) => {
|
|||||||
|
|
||||||
export const samples = async (sampleMap, baseUrl = sampleMap._base || '', options = {}) => {
|
export const samples = async (sampleMap, baseUrl = sampleMap._base || '', options = {}) => {
|
||||||
if (typeof sampleMap === 'string') {
|
if (typeof sampleMap === 'string') {
|
||||||
|
// check if custom prefix handler
|
||||||
|
const handler = getSamplesPrefixHandler(sampleMap);
|
||||||
|
if (handler) {
|
||||||
|
return handler(sampleMap);
|
||||||
|
}
|
||||||
if (sampleMap.startsWith('github:')) {
|
if (sampleMap.startsWith('github:')) {
|
||||||
let [_, path] = sampleMap.split('github:');
|
let [_, path] = sampleMap.split('github:');
|
||||||
path = path.endsWith('/') ? path.slice(0, -1) : path;
|
path = path.endsWith('/') ? path.slice(0, -1) : path;
|
||||||
@@ -130,39 +178,23 @@ export const samples = async (sampleMap, baseUrl = sampleMap._base || '', option
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const { prebake, tag } = options;
|
const { prebake, tag } = options;
|
||||||
Object.entries(sampleMap).forEach(([key, value]) => {
|
processSampleMap(
|
||||||
if (typeof value === 'string') {
|
sampleMap,
|
||||||
value = [value];
|
(key, value) =>
|
||||||
}
|
registerSound(key, (t, hapValue, onended) => onTriggerSample(t, hapValue, onended, value), {
|
||||||
if (typeof value !== 'object') {
|
type: 'sample',
|
||||||
throw new Error('wrong sample map format for ' + key);
|
samples: value,
|
||||||
}
|
baseUrl,
|
||||||
baseUrl = value._base || baseUrl;
|
prebake,
|
||||||
const replaceUrl = (v) => (baseUrl + v).replace('github:', 'https://raw.githubusercontent.com/');
|
tag,
|
||||||
if (Array.isArray(value)) {
|
}),
|
||||||
//return [key, value.map(replaceUrl)];
|
baseUrl,
|
||||||
value = value.map(replaceUrl);
|
);
|
||||||
} else {
|
|
||||||
// must be object
|
|
||||||
value = Object.fromEntries(
|
|
||||||
Object.entries(value).map(([note, samples]) => {
|
|
||||||
return [note, (typeof samples === 'string' ? [samples] : samples).map(replaceUrl)];
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
registerSound(key, (t, hapValue, onended) => onTriggerSample(t, hapValue, onended, value), {
|
|
||||||
type: 'sample',
|
|
||||||
samples: value,
|
|
||||||
baseUrl,
|
|
||||||
prebake,
|
|
||||||
tag,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const cutGroups = [];
|
const cutGroups = [];
|
||||||
|
|
||||||
export async function onTriggerSample(t, value, onended, bank) {
|
export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
||||||
const {
|
const {
|
||||||
s,
|
s,
|
||||||
freq,
|
freq,
|
||||||
@@ -170,7 +202,7 @@ export async function onTriggerSample(t, value, onended, bank) {
|
|||||||
nudge = 0, // TODO: is this in seconds?
|
nudge = 0, // TODO: is this in seconds?
|
||||||
cut,
|
cut,
|
||||||
loop,
|
loop,
|
||||||
clip = 0, // if 1, samples will be cut off when the hap ends
|
clip = undefined, // if 1, samples will be cut off when the hap ends
|
||||||
n = 0,
|
n = 0,
|
||||||
note,
|
note,
|
||||||
speed = 1, // sample playback speed
|
speed = 1, // sample playback speed
|
||||||
@@ -188,7 +220,7 @@ export async function onTriggerSample(t, value, onended, bank) {
|
|||||||
//const soundfont = getSoundfontKey(s);
|
//const soundfont = getSoundfontKey(s);
|
||||||
const time = t + nudge;
|
const time = t + nudge;
|
||||||
|
|
||||||
const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, bank);
|
const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, bank, resolveUrl);
|
||||||
|
|
||||||
// asny stuff above took too long?
|
// asny stuff above took too long?
|
||||||
if (ac.currentTime > t) {
|
if (ac.currentTime > t) {
|
||||||
@@ -232,7 +264,7 @@ export async function onTriggerSample(t, value, onended, bank) {
|
|||||||
out.disconnect();
|
out.disconnect();
|
||||||
onended();
|
onended();
|
||||||
};
|
};
|
||||||
const stop = (endTime, playWholeBuffer = !clip) => {
|
const stop = (endTime, playWholeBuffer = clip === undefined) => {
|
||||||
let releaseTime = endTime;
|
let releaseTime = endTime;
|
||||||
if (playWholeBuffer) {
|
if (playWholeBuffer) {
|
||||||
releaseTime = t + (end - begin) * bufferDuration;
|
releaseTime = t + (end - begin) * bufferDuration;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/webdirt",
|
"name": "@strudel.cycles/webdirt",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "WebDirt integration for Strudel",
|
"description": "WebDirt integration for Strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel.cycles/xen",
|
"name": "@strudel.cycles/xen",
|
||||||
"version": "0.7.1",
|
"version": "0.8.0",
|
||||||
"description": "Xenharmonic API for strudel",
|
"description": "Xenharmonic API for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ importers:
|
|||||||
dependency-tree:
|
dependency-tree:
|
||||||
specifier: ^9.0.0
|
specifier: ^9.0.0
|
||||||
version: 9.0.0
|
version: 9.0.0
|
||||||
vitest:
|
|
||||||
specifier: ^0.28.0
|
|
||||||
version: 0.28.0(@vitest/ui@0.28.0)
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@tauri-apps/cli':
|
||||||
|
specifier: ^1.4.0
|
||||||
|
version: 1.4.0
|
||||||
'@vitest/ui':
|
'@vitest/ui':
|
||||||
specifier: ^0.28.0
|
specifier: ^0.28.0
|
||||||
version: 0.28.0
|
version: 0.28.0
|
||||||
@@ -65,6 +65,9 @@ importers:
|
|||||||
rollup-plugin-visualizer:
|
rollup-plugin-visualizer:
|
||||||
specifier: ^5.8.1
|
specifier: ^5.8.1
|
||||||
version: 5.9.0
|
version: 5.9.0
|
||||||
|
vitest:
|
||||||
|
specifier: ^0.28.0
|
||||||
|
version: 0.28.0(@vitest/ui@0.28.0)
|
||||||
|
|
||||||
packages/codemirror:
|
packages/codemirror:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -92,7 +95,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/core:
|
packages/core:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -102,7 +105,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^0.28.0
|
specifier: ^0.28.0
|
||||||
version: 0.28.0(@vitest/ui@0.28.0)
|
version: 0.28.0(@vitest/ui@0.28.0)
|
||||||
@@ -127,7 +130,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/core/examples/vite-vanilla-repl-cm6:
|
packages/core/examples/vite-vanilla-repl-cm6:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -155,7 +158,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.2
|
specifier: ^4.3.2
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/csound:
|
packages/csound:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -171,7 +174,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/embed: {}
|
packages/embed: {}
|
||||||
|
|
||||||
@@ -204,7 +207,7 @@ importers:
|
|||||||
version: link:../mini
|
version: link:../mini
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^0.28.0
|
specifier: ^0.28.0
|
||||||
version: 0.28.0(@vitest/ui@0.28.0)
|
version: 0.28.0(@vitest/ui@0.28.0)
|
||||||
@@ -223,7 +226,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/mini:
|
packages/mini:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -236,7 +239,7 @@ importers:
|
|||||||
version: 3.0.2
|
version: 3.0.2
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^0.28.0
|
specifier: ^0.28.0
|
||||||
version: 0.28.0(@vitest/ui@0.28.0)
|
version: 0.28.0(@vitest/ui@0.28.0)
|
||||||
@@ -255,7 +258,7 @@ importers:
|
|||||||
version: 5.8.1
|
version: 5.8.1
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/react:
|
packages/react:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -325,7 +328,7 @@ importers:
|
|||||||
version: 3.3.2
|
version: 3.3.2
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/react/examples/nano-repl:
|
packages/react/examples/nano-repl:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -380,7 +383,7 @@ importers:
|
|||||||
version: 3.3.2
|
version: 3.3.2
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/serial:
|
packages/serial:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -390,7 +393,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/soundfonts:
|
packages/soundfonts:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -412,7 +415,7 @@ importers:
|
|||||||
version: 3.3.1
|
version: 3.3.1
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/tonal:
|
packages/tonal:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -431,7 +434,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^0.28.0
|
specifier: ^0.28.0
|
||||||
version: 0.28.0(@vitest/ui@0.28.0)
|
version: 0.28.0(@vitest/ui@0.28.0)
|
||||||
@@ -447,7 +450,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^0.28.0
|
specifier: ^0.28.0
|
||||||
version: 0.28.0(@vitest/ui@0.28.0)
|
version: 0.28.0(@vitest/ui@0.28.0)
|
||||||
@@ -469,7 +472,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^0.28.0
|
specifier: ^0.28.0
|
||||||
version: 0.28.0(@vitest/ui@0.28.0)
|
version: 0.28.0(@vitest/ui@0.28.0)
|
||||||
@@ -494,7 +497,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/web/examples/repl-example:
|
packages/web/examples/repl-example:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -504,7 +507,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.2
|
specifier: ^4.3.2
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/webaudio:
|
packages/webaudio:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -517,7 +520,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
|
|
||||||
packages/webdirt:
|
packages/webdirt:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -533,7 +536,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^0.28.0
|
specifier: ^0.28.0
|
||||||
version: 0.28.0(@vitest/ui@0.28.0)
|
version: 0.28.0(@vitest/ui@0.28.0)
|
||||||
@@ -546,7 +549,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
version: 4.3.3(@types/node@18.11.18)
|
version: 4.3.3(@types/node@18.16.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^0.28.0
|
specifier: ^0.28.0
|
||||||
version: 0.28.0(@vitest/ui@0.28.0)
|
version: 0.28.0(@vitest/ui@0.28.0)
|
||||||
@@ -3537,6 +3540,7 @@ packages:
|
|||||||
|
|
||||||
/@polka/url@1.0.0-next.21:
|
/@polka/url@1.0.0-next.21:
|
||||||
resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
|
resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@proload/core@0.3.3:
|
/@proload/core@0.3.3:
|
||||||
resolution: {integrity: sha512-7dAFWsIK84C90AMl24+N/ProHKm4iw0akcnoKjRvbfHifJZBLhaDsDus1QJmhG12lXj4e/uB/8mB/0aduCW+NQ==}
|
resolution: {integrity: sha512-7dAFWsIK84C90AMl24+N/ProHKm4iw0akcnoKjRvbfHifJZBLhaDsDus1QJmhG12lXj4e/uB/8mB/0aduCW+NQ==}
|
||||||
@@ -3770,6 +3774,113 @@ packages:
|
|||||||
tailwindcss: 3.3.2
|
tailwindcss: 3.3.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@tauri-apps/cli-darwin-arm64@1.4.0:
|
||||||
|
resolution: {integrity: sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli-darwin-x64@1.4.0:
|
||||||
|
resolution: {integrity: sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli-linux-arm-gnueabihf@1.4.0:
|
||||||
|
resolution: {integrity: sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli-linux-arm64-gnu@1.4.0:
|
||||||
|
resolution: {integrity: sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli-linux-arm64-musl@1.4.0:
|
||||||
|
resolution: {integrity: sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli-linux-x64-gnu@1.4.0:
|
||||||
|
resolution: {integrity: sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli-linux-x64-musl@1.4.0:
|
||||||
|
resolution: {integrity: sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli-win32-arm64-msvc@1.4.0:
|
||||||
|
resolution: {integrity: sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli-win32-ia32-msvc@1.4.0:
|
||||||
|
resolution: {integrity: sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli-win32-x64-msvc@1.4.0:
|
||||||
|
resolution: {integrity: sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@tauri-apps/cli@1.4.0:
|
||||||
|
resolution: {integrity: sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
hasBin: true
|
||||||
|
optionalDependencies:
|
||||||
|
'@tauri-apps/cli-darwin-arm64': 1.4.0
|
||||||
|
'@tauri-apps/cli-darwin-x64': 1.4.0
|
||||||
|
'@tauri-apps/cli-linux-arm-gnueabihf': 1.4.0
|
||||||
|
'@tauri-apps/cli-linux-arm64-gnu': 1.4.0
|
||||||
|
'@tauri-apps/cli-linux-arm64-musl': 1.4.0
|
||||||
|
'@tauri-apps/cli-linux-x64-gnu': 1.4.0
|
||||||
|
'@tauri-apps/cli-linux-x64-musl': 1.4.0
|
||||||
|
'@tauri-apps/cli-win32-arm64-msvc': 1.4.0
|
||||||
|
'@tauri-apps/cli-win32-ia32-msvc': 1.4.0
|
||||||
|
'@tauri-apps/cli-win32-x64-msvc': 1.4.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@tonaljs/abc-notation@4.8.0:
|
/@tonaljs/abc-notation@4.8.0:
|
||||||
resolution: {integrity: sha512-JggT/DW4rMxu+q1WkeACrg52is3acp9zaW4LJmCheFi3CmLa63sy7/6mgKnlScTOvcpAyTcSytu0VbQHRXyBDA==}
|
resolution: {integrity: sha512-JggT/DW4rMxu+q1WkeACrg52is3acp9zaW4LJmCheFi3CmLa63sy7/6mgKnlScTOvcpAyTcSytu0VbQHRXyBDA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3984,9 +4095,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
|
resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/chai': 4.3.4
|
'@types/chai': 4.3.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/chai@4.3.4:
|
/@types/chai@4.3.4:
|
||||||
resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==}
|
resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/debug@4.1.7:
|
/@types/debug@4.1.7:
|
||||||
resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==}
|
resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==}
|
||||||
@@ -4063,6 +4176,7 @@ packages:
|
|||||||
|
|
||||||
/@types/node@18.11.18:
|
/@types/node@18.11.18:
|
||||||
resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==}
|
resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/node@18.16.3:
|
/@types/node@18.16.3:
|
||||||
resolution: {integrity: sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==}
|
resolution: {integrity: sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==}
|
||||||
@@ -4505,7 +4619,7 @@ packages:
|
|||||||
'@babel/plugin-transform-react-jsx-self': 7.21.0(@babel/core@7.21.5)
|
'@babel/plugin-transform-react-jsx-self': 7.21.0(@babel/core@7.21.5)
|
||||||
'@babel/plugin-transform-react-jsx-source': 7.19.6(@babel/core@7.21.5)
|
'@babel/plugin-transform-react-jsx-source': 7.19.6(@babel/core@7.21.5)
|
||||||
react-refresh: 0.14.0
|
react-refresh: 0.14.0
|
||||||
vite: 4.3.3(@types/node@18.11.18)
|
vite: 4.3.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
@@ -4516,6 +4630,7 @@ packages:
|
|||||||
'@vitest/spy': 0.28.0
|
'@vitest/spy': 0.28.0
|
||||||
'@vitest/utils': 0.28.0
|
'@vitest/utils': 0.28.0
|
||||||
chai: 4.3.7
|
chai: 4.3.7
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@vitest/runner@0.28.0:
|
/@vitest/runner@0.28.0:
|
||||||
resolution: {integrity: sha512-SXQO9aubp7Hg4DV4D5DP70wJ/4o0krH1gAPrSt+rhEZQbQvMaBJAHWOxEibwzLkklgoHreaMEvETFILkGQWXww==}
|
resolution: {integrity: sha512-SXQO9aubp7Hg4DV4D5DP70wJ/4o0krH1gAPrSt+rhEZQbQvMaBJAHWOxEibwzLkklgoHreaMEvETFILkGQWXww==}
|
||||||
@@ -4523,11 +4638,13 @@ packages:
|
|||||||
'@vitest/utils': 0.28.0
|
'@vitest/utils': 0.28.0
|
||||||
p-limit: 4.0.0
|
p-limit: 4.0.0
|
||||||
pathe: 1.1.0
|
pathe: 1.1.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@vitest/spy@0.28.0:
|
/@vitest/spy@0.28.0:
|
||||||
resolution: {integrity: sha512-gYBDQIP0QDvxrscl2Id0BTbzLUbuAzFiFur3eHxH9Yt5cM6YCH/kxBrSHhmXTbu92UenLx53Gwq17u5N0zGNDQ==}
|
resolution: {integrity: sha512-gYBDQIP0QDvxrscl2Id0BTbzLUbuAzFiFur3eHxH9Yt5cM6YCH/kxBrSHhmXTbu92UenLx53Gwq17u5N0zGNDQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
tinyspy: 1.0.2
|
tinyspy: 1.0.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@vitest/ui@0.28.0:
|
/@vitest/ui@0.28.0:
|
||||||
resolution: {integrity: sha512-ihcVEx8t1gZXMboPGcIvoHk+PxiW5USxDMqnZOeUVIUm+XrRCtoJ96YDXdeR6MyPWeYLBPXfBWSxp5gMqoNSkw==}
|
resolution: {integrity: sha512-ihcVEx8t1gZXMboPGcIvoHk+PxiW5USxDMqnZOeUVIUm+XrRCtoJ96YDXdeR6MyPWeYLBPXfBWSxp5gMqoNSkw==}
|
||||||
@@ -4537,6 +4654,7 @@ packages:
|
|||||||
pathe: 1.1.0
|
pathe: 1.1.0
|
||||||
picocolors: 1.0.0
|
picocolors: 1.0.0
|
||||||
sirv: 2.0.2
|
sirv: 2.0.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@vitest/utils@0.28.0:
|
/@vitest/utils@0.28.0:
|
||||||
resolution: {integrity: sha512-Dt+jDZbwriZWzJ5Hi9nAUnz9IPgNb+ACE96tWiXPp/u9NmCYWIWcuNoUOYS8HQyGFz31GiNYGvaZ4ZEDjAgi1g==}
|
resolution: {integrity: sha512-Dt+jDZbwriZWzJ5Hi9nAUnz9IPgNb+ACE96tWiXPp/u9NmCYWIWcuNoUOYS8HQyGFz31GiNYGvaZ4ZEDjAgi1g==}
|
||||||
@@ -4546,6 +4664,7 @@ packages:
|
|||||||
loupe: 2.3.6
|
loupe: 2.3.6
|
||||||
picocolors: 1.0.0
|
picocolors: 1.0.0
|
||||||
pretty-format: 27.5.1
|
pretty-format: 27.5.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@vscode/emmet-helper@2.8.6:
|
/@vscode/emmet-helper@2.8.6:
|
||||||
resolution: {integrity: sha512-IIB8jbiKy37zN8bAIHx59YmnIelY78CGHtThnibD/d3tQOKRY83bYVi9blwmZVUZh6l9nfkYH3tvReaiNxY9EQ==}
|
resolution: {integrity: sha512-IIB8jbiKy37zN8bAIHx59YmnIelY78CGHtThnibD/d3tQOKRY83bYVi9blwmZVUZh6l9nfkYH3tvReaiNxY9EQ==}
|
||||||
@@ -4611,6 +4730,7 @@ packages:
|
|||||||
/acorn-walk@8.2.0:
|
/acorn-walk@8.2.0:
|
||||||
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
|
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/acorn@8.8.2:
|
/acorn@8.8.2:
|
||||||
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
|
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
|
||||||
@@ -4735,6 +4855,7 @@ packages:
|
|||||||
/ansi-styles@5.2.0:
|
/ansi-styles@5.2.0:
|
||||||
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
|
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ansi-styles@6.2.1:
|
/ansi-styles@6.2.1:
|
||||||
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
|
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
|
||||||
@@ -4884,6 +5005,7 @@ packages:
|
|||||||
|
|
||||||
/assertion-error@1.1.0:
|
/assertion-error@1.1.0:
|
||||||
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ast-module-types@3.0.0:
|
/ast-module-types@3.0.0:
|
||||||
resolution: {integrity: sha512-CMxMCOCS+4D+DkOQfuZf+vLrSEmY/7xtORwdxs4wtcC1wVgvk2MqFFTwQCFhvWsI4KPU9lcWXPI8DgRiz+xetQ==}
|
resolution: {integrity: sha512-CMxMCOCS+4D+DkOQfuZf+vLrSEmY/7xtORwdxs4wtcC1wVgvk2MqFFTwQCFhvWsI4KPU9lcWXPI8DgRiz+xetQ==}
|
||||||
@@ -5153,6 +5275,7 @@ packages:
|
|||||||
|
|
||||||
/buffer-from@1.1.2:
|
/buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/buffer@5.7.1:
|
/buffer@5.7.1:
|
||||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
||||||
@@ -5203,6 +5326,7 @@ packages:
|
|||||||
/cac@6.7.14:
|
/cac@6.7.14:
|
||||||
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/cacache@16.1.3:
|
/cacache@16.1.3:
|
||||||
resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==}
|
resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==}
|
||||||
@@ -5332,6 +5456,7 @@ packages:
|
|||||||
loupe: 2.3.6
|
loupe: 2.3.6
|
||||||
pathval: 1.1.1
|
pathval: 1.1.1
|
||||||
type-detect: 4.0.8
|
type-detect: 4.0.8
|
||||||
|
dev: true
|
||||||
|
|
||||||
/chalk@2.4.2:
|
/chalk@2.4.2:
|
||||||
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
|
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
|
||||||
@@ -5379,6 +5504,7 @@ packages:
|
|||||||
|
|
||||||
/check-error@1.0.2:
|
/check-error@1.0.2:
|
||||||
resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
|
resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/chokidar@3.5.3:
|
/chokidar@3.5.3:
|
||||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||||
@@ -5457,6 +5583,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
slice-ansi: 5.0.0
|
slice-ansi: 5.0.0
|
||||||
string-width: 5.1.2
|
string-width: 5.1.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/cli-width@3.0.0:
|
/cli-width@3.0.0:
|
||||||
resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
|
resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
|
||||||
@@ -5936,6 +6063,7 @@ packages:
|
|||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
dependencies:
|
dependencies:
|
||||||
type-detect: 4.0.8
|
type-detect: 4.0.8
|
||||||
|
dev: true
|
||||||
|
|
||||||
/deep-extend@0.6.0:
|
/deep-extend@0.6.0:
|
||||||
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
|
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
|
||||||
@@ -7134,6 +7262,7 @@ packages:
|
|||||||
|
|
||||||
/get-func-name@2.0.0:
|
/get-func-name@2.0.0:
|
||||||
resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
|
resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/get-intrinsic@1.2.0:
|
/get-intrinsic@1.2.0:
|
||||||
resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==}
|
resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==}
|
||||||
@@ -7965,6 +8094,7 @@ packages:
|
|||||||
/is-fullwidth-code-point@4.0.0:
|
/is-fullwidth-code-point@4.0.0:
|
||||||
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
|
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/is-glob@4.0.3:
|
/is-glob@4.0.3:
|
||||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||||
@@ -8608,6 +8738,7 @@ packages:
|
|||||||
/local-pkg@0.4.3:
|
/local-pkg@0.4.3:
|
||||||
resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
|
resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/locate-path@2.0.0:
|
/locate-path@2.0.0:
|
||||||
resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==}
|
resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==}
|
||||||
@@ -8700,6 +8831,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
|
resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
get-func-name: 2.0.0
|
get-func-name: 2.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/lru-cache@5.1.1:
|
/lru-cache@5.1.1:
|
||||||
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
||||||
@@ -9594,6 +9726,7 @@ packages:
|
|||||||
pathe: 1.1.0
|
pathe: 1.1.0
|
||||||
pkg-types: 1.0.2
|
pkg-types: 1.0.2
|
||||||
ufo: 1.1.1
|
ufo: 1.1.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/modify-values@1.0.1:
|
/modify-values@1.0.1:
|
||||||
resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==}
|
resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==}
|
||||||
@@ -9639,6 +9772,7 @@ packages:
|
|||||||
/mrmime@1.0.1:
|
/mrmime@1.0.1:
|
||||||
resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==}
|
resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ms@2.0.0:
|
/ms@2.0.0:
|
||||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||||
@@ -10319,6 +10453,7 @@ packages:
|
|||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
yocto-queue: 1.0.0
|
yocto-queue: 1.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/p-locate@2.0.0:
|
/p-locate@2.0.0:
|
||||||
resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==}
|
resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==}
|
||||||
@@ -10571,9 +10706,11 @@ packages:
|
|||||||
|
|
||||||
/pathe@1.1.0:
|
/pathe@1.1.0:
|
||||||
resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==}
|
resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/pathval@1.1.1:
|
/pathval@1.1.1:
|
||||||
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
|
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/peggy@3.0.2:
|
/peggy@3.0.2:
|
||||||
resolution: {integrity: sha512-n7chtCbEoGYRwZZ0i/O3t1cPr6o+d9Xx4Zwy2LYfzv0vjchMBU0tO+qYYyvZloBPcgRgzYvALzGWHe609JjEpg==}
|
resolution: {integrity: sha512-n7chtCbEoGYRwZZ0i/O3t1cPr6o+d9Xx4Zwy2LYfzv0vjchMBU0tO+qYYyvZloBPcgRgzYvALzGWHe609JjEpg==}
|
||||||
@@ -10650,6 +10787,7 @@ packages:
|
|||||||
jsonc-parser: 3.2.0
|
jsonc-parser: 3.2.0
|
||||||
mlly: 1.2.0
|
mlly: 1.2.0
|
||||||
pathe: 1.1.0
|
pathe: 1.1.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/pkg@5.8.1:
|
/pkg@5.8.1:
|
||||||
resolution: {integrity: sha512-CjBWtFStCfIiT4Bde9QpJy0KeH19jCfwZRJqHFDFXfhUklCx8JoFmMj3wgnEYIwGmZVNkhsStPHEOnrtrQhEXA==}
|
resolution: {integrity: sha512-CjBWtFStCfIiT4Bde9QpJy0KeH19jCfwZRJqHFDFXfhUklCx8JoFmMj3wgnEYIwGmZVNkhsStPHEOnrtrQhEXA==}
|
||||||
@@ -10851,6 +10989,7 @@ packages:
|
|||||||
ansi-regex: 5.0.1
|
ansi-regex: 5.0.1
|
||||||
ansi-styles: 5.2.0
|
ansi-styles: 5.2.0
|
||||||
react-is: 17.0.2
|
react-is: 17.0.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/pretty-format@29.4.3:
|
/pretty-format@29.4.3:
|
||||||
resolution: {integrity: sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==}
|
resolution: {integrity: sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==}
|
||||||
@@ -11010,6 +11149,7 @@ packages:
|
|||||||
|
|
||||||
/react-is@17.0.2:
|
/react-is@17.0.2:
|
||||||
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
|
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/react-is@18.2.0:
|
/react-is@18.2.0:
|
||||||
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
|
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
|
||||||
@@ -11763,6 +11903,7 @@ packages:
|
|||||||
|
|
||||||
/siginfo@2.0.0:
|
/siginfo@2.0.0:
|
||||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/signal-exit@3.0.7:
|
/signal-exit@3.0.7:
|
||||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||||
@@ -11810,6 +11951,7 @@ packages:
|
|||||||
'@polka/url': 1.0.0-next.21
|
'@polka/url': 1.0.0-next.21
|
||||||
mrmime: 1.0.1
|
mrmime: 1.0.1
|
||||||
totalist: 3.0.0
|
totalist: 3.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/sisteransi@1.0.5:
|
/sisteransi@1.0.5:
|
||||||
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
|
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
|
||||||
@@ -11828,6 +11970,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 6.2.1
|
ansi-styles: 6.2.1
|
||||||
is-fullwidth-code-point: 4.0.0
|
is-fullwidth-code-point: 4.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/smart-buffer@4.2.0:
|
/smart-buffer@4.2.0:
|
||||||
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
|
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
|
||||||
@@ -11886,6 +12029,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
buffer-from: 1.1.2
|
buffer-from: 1.1.2
|
||||||
source-map: 0.6.1
|
source-map: 0.6.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/source-map@0.5.7:
|
/source-map@0.5.7:
|
||||||
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
|
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
|
||||||
@@ -11968,6 +12112,7 @@ packages:
|
|||||||
|
|
||||||
/stackback@0.0.2:
|
/stackback@0.0.2:
|
||||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/standardized-audio-context@25.3.37:
|
/standardized-audio-context@25.3.37:
|
||||||
resolution: {integrity: sha512-lr0+RH/IJXYMts95oYKIJ+orTmstOZN3GXWVGmlkbMj8OLahREkRh7DhNGLYgBGDkBkhhc4ev5pYGSFN3gltHw==}
|
resolution: {integrity: sha512-lr0+RH/IJXYMts95oYKIJ+orTmstOZN3GXWVGmlkbMj8OLahREkRh7DhNGLYgBGDkBkhhc4ev5pYGSFN3gltHw==}
|
||||||
@@ -11979,6 +12124,7 @@ packages:
|
|||||||
|
|
||||||
/std-env@3.3.2:
|
/std-env@3.3.2:
|
||||||
resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==}
|
resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/stdopt@2.2.0:
|
/stdopt@2.2.0:
|
||||||
resolution: {integrity: sha512-D/p41NgXOkcj1SeGhfXOwv9z1K6EV3sjAUY5aeepVbgEHv7DpKWLTjhjScyzMWAQCAgUQys1mjH0eArm4cjRGw==}
|
resolution: {integrity: sha512-D/p41NgXOkcj1SeGhfXOwv9z1K6EV3sjAUY5aeepVbgEHv7DpKWLTjhjScyzMWAQCAgUQys1mjH0eArm4cjRGw==}
|
||||||
@@ -12149,6 +12295,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==}
|
resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.8.2
|
acorn: 8.8.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/strong-log-transformer@2.1.0:
|
/strong-log-transformer@2.1.0:
|
||||||
resolution: {integrity: sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==}
|
resolution: {integrity: sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==}
|
||||||
@@ -12435,14 +12582,17 @@ packages:
|
|||||||
|
|
||||||
/tinybench@2.5.0:
|
/tinybench@2.5.0:
|
||||||
resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==}
|
resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tinypool@0.3.1:
|
/tinypool@0.3.1:
|
||||||
resolution: {integrity: sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==}
|
resolution: {integrity: sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tinyspy@1.0.2:
|
/tinyspy@1.0.2:
|
||||||
resolution: {integrity: sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==}
|
resolution: {integrity: sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tmp@0.0.33:
|
/tmp@0.0.33:
|
||||||
resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
|
resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
|
||||||
@@ -12478,6 +12628,7 @@ packages:
|
|||||||
/totalist@3.0.0:
|
/totalist@3.0.0:
|
||||||
resolution: {integrity: sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==}
|
resolution: {integrity: sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tr46@0.0.3:
|
/tr46@0.0.3:
|
||||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||||
@@ -12584,6 +12735,7 @@ packages:
|
|||||||
/type-detect@4.0.8:
|
/type-detect@4.0.8:
|
||||||
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
|
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/type-fest@0.13.1:
|
/type-fest@0.13.1:
|
||||||
resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
|
resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
|
||||||
@@ -12684,6 +12836,7 @@ packages:
|
|||||||
|
|
||||||
/ufo@1.1.1:
|
/ufo@1.1.1:
|
||||||
resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==}
|
resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/uglify-js@3.17.4:
|
/uglify-js@3.17.4:
|
||||||
resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
|
resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
|
||||||
@@ -13059,6 +13212,7 @@ packages:
|
|||||||
- sugarss
|
- sugarss
|
||||||
- supports-color
|
- supports-color
|
||||||
- terser
|
- terser
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vite-plugin-pwa@0.14.7(vite@4.3.3)(workbox-build@6.5.4)(workbox-window@6.5.4):
|
/vite-plugin-pwa@0.14.7(vite@4.3.3)(workbox-build@6.5.4)(workbox-window@6.5.4):
|
||||||
resolution: {integrity: sha512-dNJaf0fYOWncmjxv9HiSa2xrSjipjff7IkYE5oIUJ2x5HKu3cXgA8LRgzOwTc5MhwyFYRSU0xyN0Phbx3NsQYw==}
|
resolution: {integrity: sha512-dNJaf0fYOWncmjxv9HiSa2xrSjipjff7IkYE5oIUJ2x5HKu3cXgA8LRgzOwTc5MhwyFYRSU0xyN0Phbx3NsQYw==}
|
||||||
@@ -13079,6 +13233,38 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vite@4.3.3:
|
||||||
|
resolution: {integrity: sha512-MwFlLBO4udZXd+VBcezo3u8mC77YQk+ik+fbc0GZWGgzfbPP+8Kf0fldhARqvSYmtIWoAJ5BXPClUbMTlqFxrA==}
|
||||||
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
'@types/node': '>= 14'
|
||||||
|
less: '*'
|
||||||
|
sass: '*'
|
||||||
|
stylus: '*'
|
||||||
|
sugarss: '*'
|
||||||
|
terser: ^5.4.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/node':
|
||||||
|
optional: true
|
||||||
|
less:
|
||||||
|
optional: true
|
||||||
|
sass:
|
||||||
|
optional: true
|
||||||
|
stylus:
|
||||||
|
optional: true
|
||||||
|
sugarss:
|
||||||
|
optional: true
|
||||||
|
terser:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
esbuild: 0.17.18
|
||||||
|
postcss: 8.4.23
|
||||||
|
rollup: 3.21.0
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents: 2.3.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vite@4.3.3(@types/node@18.11.18):
|
/vite@4.3.3(@types/node@18.11.18):
|
||||||
resolution: {integrity: sha512-MwFlLBO4udZXd+VBcezo3u8mC77YQk+ik+fbc0GZWGgzfbPP+8Kf0fldhARqvSYmtIWoAJ5BXPClUbMTlqFxrA==}
|
resolution: {integrity: sha512-MwFlLBO4udZXd+VBcezo3u8mC77YQk+ik+fbc0GZWGgzfbPP+8Kf0fldhARqvSYmtIWoAJ5BXPClUbMTlqFxrA==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
@@ -13110,6 +13296,7 @@ packages:
|
|||||||
rollup: 3.21.0
|
rollup: 3.21.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.2
|
fsevents: 2.3.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vite@4.3.3(@types/node@18.16.3):
|
/vite@4.3.3(@types/node@18.16.3):
|
||||||
resolution: {integrity: sha512-MwFlLBO4udZXd+VBcezo3u8mC77YQk+ik+fbc0GZWGgzfbPP+8Kf0fldhARqvSYmtIWoAJ5BXPClUbMTlqFxrA==}
|
resolution: {integrity: sha512-MwFlLBO4udZXd+VBcezo3u8mC77YQk+ik+fbc0GZWGgzfbPP+8Kf0fldhARqvSYmtIWoAJ5BXPClUbMTlqFxrA==}
|
||||||
@@ -13207,6 +13394,7 @@ packages:
|
|||||||
- sugarss
|
- sugarss
|
||||||
- supports-color
|
- supports-color
|
||||||
- terser
|
- terser
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vscode-css-languageservice@6.2.3:
|
/vscode-css-languageservice@6.2.3:
|
||||||
resolution: {integrity: sha512-EAyhyIVHpEaf+GjtI+tVe7SekdoANfG0aubnspsQwak3Qkimn/97FpAufNyXk636ngW05pjNKAR9zyTCzo6avQ==}
|
resolution: {integrity: sha512-EAyhyIVHpEaf+GjtI+tVe7SekdoANfG0aubnspsQwak3Qkimn/97FpAufNyXk636ngW05pjNKAR9zyTCzo6avQ==}
|
||||||
@@ -13394,6 +13582,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
siginfo: 2.0.0
|
siginfo: 2.0.0
|
||||||
stackback: 0.0.2
|
stackback: 0.0.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/wide-align@1.1.5:
|
/wide-align@1.1.5:
|
||||||
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
||||||
@@ -13727,6 +13916,7 @@ packages:
|
|||||||
/yocto-queue@1.0.0:
|
/yocto-queue@1.0.0:
|
||||||
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
|
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
|
||||||
engines: {node: '>=12.20'}
|
engines: {node: '>=12.20'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/zod@3.21.4:
|
/zod@3.21.4:
|
||||||
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
|
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
[package]
|
||||||
|
name = "app"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "A Tauri App"
|
||||||
|
authors = ["you"]
|
||||||
|
license = ""
|
||||||
|
repository = ""
|
||||||
|
default-run = "app"
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.60"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
tauri-build = { version = "1.4.0", features = [] }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde_json = "1.0"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
tauri = { version = "1.4.0", features = ["fs-all"] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
|
||||||
|
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
|
||||||
|
# DO NOT REMOVE!!
|
||||||
|
custom-protocol = ["tauri/custom-protocol"]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
codegen-units = 1
|
||||||
|
lto = true
|
||||||
|
opt-level = "s"
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# @strudel.cycles/tauri
|
||||||
|
|
||||||
|
Rust source files for building native desktop apps using Tauri
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Install [Rust](https://rustup.rs/) on your system.
|
||||||
|
|
||||||
|
From the project root:
|
||||||
|
|
||||||
|
- install Strudel dependencies
|
||||||
|
|
||||||
|
```js
|
||||||
|
pnpm i
|
||||||
|
```
|
||||||
|
|
||||||
|
- to run Strudel for development
|
||||||
|
|
||||||
|
```js
|
||||||
|
pnpm tauri dev
|
||||||
|
```
|
||||||
|
|
||||||
|
- to build the binary and installer/bundle
|
||||||
|
|
||||||
|
```js
|
||||||
|
pnpm tauri build
|
||||||
|
```
|
||||||
|
|
||||||
|
The binary and installer can be found in the 'src-tauri/target/release/bundle' directory
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
tauri_build::build()
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 70 KiB |
@@ -0,0 +1,8 @@
|
|||||||
|
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||||
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
tauri::Builder::default()
|
||||||
|
.run(tauri::generate_context!())
|
||||||
|
.expect("error while running tauri application");
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||||
|
"build": {
|
||||||
|
"beforeBuildCommand": "npm run build",
|
||||||
|
"beforeDevCommand": "npm run dev",
|
||||||
|
"devPath": "http://localhost:3000",
|
||||||
|
"distDir": "../website/dist",
|
||||||
|
"withGlobalTauri": true
|
||||||
|
},
|
||||||
|
"package": {
|
||||||
|
"productName": "Strudel",
|
||||||
|
"version": "0.1.0"
|
||||||
|
},
|
||||||
|
"tauri": {
|
||||||
|
"allowlist": {
|
||||||
|
"all": false,
|
||||||
|
"fs": {
|
||||||
|
"all": true,
|
||||||
|
"scope": ["$HOME/**", "$HOME", "$HOME/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bundle": {
|
||||||
|
"active": true,
|
||||||
|
"category": "DeveloperTool",
|
||||||
|
"copyright": "",
|
||||||
|
"deb": {
|
||||||
|
"depends": []
|
||||||
|
},
|
||||||
|
"externalBin": [],
|
||||||
|
"icon": [
|
||||||
|
"icons/32x32.png",
|
||||||
|
"icons/128x128.png",
|
||||||
|
"icons/128x128@2x.png",
|
||||||
|
"icons/icon.icns",
|
||||||
|
"icons/icon.ico"
|
||||||
|
],
|
||||||
|
"identifier": "com.strudel.dev",
|
||||||
|
"longDescription": "",
|
||||||
|
"macOS": {
|
||||||
|
"entitlements": null,
|
||||||
|
"exceptionDomain": "",
|
||||||
|
"frameworks": [],
|
||||||
|
"providerShortName": null,
|
||||||
|
"signingIdentity": null
|
||||||
|
},
|
||||||
|
"resources": [],
|
||||||
|
"shortDescription": "",
|
||||||
|
"targets": "all",
|
||||||
|
"windows": {
|
||||||
|
"certificateThumbprint": null,
|
||||||
|
"digestAlgorithm": "sha256",
|
||||||
|
"timestampUrl": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"csp": null
|
||||||
|
},
|
||||||
|
"updater": {
|
||||||
|
"active": false
|
||||||
|
},
|
||||||
|
"windows": [
|
||||||
|
{
|
||||||
|
"fullscreen": false,
|
||||||
|
"height": 1200,
|
||||||
|
"resizable": true,
|
||||||
|
"title": "Strudel REPL",
|
||||||
|
"width": 1800
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1079,22 +1079,22 @@ exports[`runs examples > example "chunkBack" example index 0 1`] = `
|
|||||||
|
|
||||||
exports[`runs examples > example "clip" example index 0 1`] = `
|
exports[`runs examples > example "clip" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/5 | note:c s:piano clip:1 ]",
|
"[ 0/1 → 1/4 | note:c s:piano clip:0.5 ]",
|
||||||
"[ 1/5 → 2/5 | note:a s:piano clip:1 ]",
|
"[ 1/4 → 1/2 | note:a s:piano clip:0.5 ]",
|
||||||
"[ 2/5 → 3/5 | note:f s:piano clip:1 ]",
|
"[ 1/2 → 3/4 | note:f s:piano clip:0.5 ]",
|
||||||
"[ 3/5 → 4/5 | note:e s:piano clip:1 ]",
|
"[ 3/4 → 1/1 | note:e s:piano clip:0.5 ]",
|
||||||
"[ 1/1 → 6/5 | note:c s:piano clip:1 ]",
|
"[ 1/1 → 5/4 | note:c s:piano clip:1 ]",
|
||||||
"[ 6/5 → 7/5 | note:a s:piano clip:1 ]",
|
"[ 5/4 → 3/2 | note:a s:piano clip:1 ]",
|
||||||
"[ 7/5 → 8/5 | note:f s:piano clip:1 ]",
|
"[ 3/2 → 7/4 | note:f s:piano clip:1 ]",
|
||||||
"[ 8/5 → 9/5 | note:e s:piano clip:1 ]",
|
"[ 7/4 → 2/1 | note:e s:piano clip:1 ]",
|
||||||
"[ 2/1 → 11/5 | note:c s:piano clip:1 ]",
|
"[ 2/1 → 9/4 | note:c s:piano clip:2 ]",
|
||||||
"[ 11/5 → 12/5 | note:a s:piano clip:1 ]",
|
"[ 9/4 → 5/2 | note:a s:piano clip:2 ]",
|
||||||
"[ 12/5 → 13/5 | note:f s:piano clip:1 ]",
|
"[ 5/2 → 11/4 | note:f s:piano clip:2 ]",
|
||||||
"[ 13/5 → 14/5 | note:e s:piano clip:1 ]",
|
"[ 11/4 → 3/1 | note:e s:piano clip:2 ]",
|
||||||
"[ 3/1 → 16/5 | note:c s:piano clip:1 ]",
|
"[ 3/1 → 13/4 | note:c s:piano clip:0.5 ]",
|
||||||
"[ 16/5 → 17/5 | note:a s:piano clip:1 ]",
|
"[ 13/4 → 7/2 | note:a s:piano clip:0.5 ]",
|
||||||
"[ 17/5 → 18/5 | note:f s:piano clip:1 ]",
|
"[ 7/2 → 15/4 | note:f s:piano clip:0.5 ]",
|
||||||
"[ 18/5 → 19/5 | note:e s:piano clip:1 ]",
|
"[ 15/4 → 4/1 | note:e s:piano clip:0.5 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -1588,42 +1588,42 @@ exports[`runs examples > example "echo" example index 0 1`] = `
|
|||||||
|
|
||||||
exports[`runs examples > example "echoWith" example index 0 1`] = `
|
exports[`runs examples > example "echoWith" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/5 | note:C3 ]",
|
"[ 0/1 → 1/1 | note:C3 clip:0.2 ]",
|
||||||
"[ -3/8 ⇜ (0/1 → 1/40) ⇝ -11/40 | note:Bb3 ]",
|
"[ -3/8 ⇜ (0/1 → 1/8) | note:Bb3 clip:0.2 ]",
|
||||||
"[ (1/8 → 3/10) ⇝ 13/40 | note:Eb3 ]",
|
"[ (1/8 → 1/1) ⇝ 9/8 | note:Eb3 clip:0.2 ]",
|
||||||
"[ -1/4 ⇜ (0/1 → 1/20) ⇝ -3/20 | note:D4 ]",
|
"[ -1/4 ⇜ (0/1 → 1/4) | note:D4 clip:0.2 ]",
|
||||||
"[ (1/4 → 2/5) ⇝ 9/20 | note:G3 ]",
|
"[ (1/4 → 1/1) ⇝ 5/4 | note:G3 clip:0.2 ]",
|
||||||
"[ -1/8 ⇜ (0/1 → 3/40) ⇝ -1/40 | note:F4 ]",
|
"[ -1/8 ⇜ (0/1 → 3/8) | note:F4 clip:0.2 ]",
|
||||||
"[ (3/8 → 1/2) ⇝ 23/40 | note:Bb3 ]",
|
"[ (3/8 → 1/1) ⇝ 11/8 | note:Bb3 clip:0.2 ]",
|
||||||
"[ 1/1 → 11/10 | note:Eb3 ]",
|
"[ 1/1 → 3/2 | note:Eb3 clip:0.2 ]",
|
||||||
"[ 3/2 → 8/5 | note:G3 ]",
|
"[ 3/2 → 2/1 | note:G3 clip:0.2 ]",
|
||||||
"[ 1/8 ⇜ (1/1 → 41/40) ⇝ 13/40 | note:Eb3 ]",
|
"[ 1/8 ⇜ (1/1 → 9/8) | note:Eb3 clip:0.2 ]",
|
||||||
"[ 9/8 → 49/40 | note:G3 ]",
|
"[ 9/8 → 13/8 | note:G3 clip:0.2 ]",
|
||||||
"[ (13/8 → 17/10) ⇝ 69/40 | note:Bb3 ]",
|
"[ (13/8 → 2/1) ⇝ 17/8 | note:Bb3 clip:0.2 ]",
|
||||||
"[ 1/4 ⇜ (1/1 → 21/20) ⇝ 9/20 | note:G3 ]",
|
"[ 1/4 ⇜ (1/1 → 5/4) | note:G3 clip:0.2 ]",
|
||||||
"[ 5/4 → 27/20 | note:Bb3 ]",
|
"[ 5/4 → 7/4 | note:Bb3 clip:0.2 ]",
|
||||||
"[ (7/4 → 9/5) ⇝ 37/20 | note:D4 ]",
|
"[ (7/4 → 2/1) ⇝ 9/4 | note:D4 clip:0.2 ]",
|
||||||
"[ 3/8 ⇜ (1/1 → 43/40) ⇝ 23/40 | note:Bb3 ]",
|
"[ 3/8 ⇜ (1/1 → 11/8) | note:Bb3 clip:0.2 ]",
|
||||||
"[ 11/8 → 59/40 | note:D4 ]",
|
"[ 11/8 → 15/8 | note:D4 clip:0.2 ]",
|
||||||
"[ (15/8 → 19/10) ⇝ 79/40 | note:F4 ]",
|
"[ (15/8 → 2/1) ⇝ 19/8 | note:F4 clip:0.2 ]",
|
||||||
"[ 2/1 → 11/5 | note:C3 ]",
|
"[ 2/1 → 3/1 | note:C3 clip:0.2 ]",
|
||||||
"[ 13/8 ⇜ (2/1 → 81/40) ⇝ 69/40 | note:Bb3 ]",
|
"[ 13/8 ⇜ (2/1 → 17/8) | note:Bb3 clip:0.2 ]",
|
||||||
"[ (17/8 → 23/10) ⇝ 93/40 | note:Eb3 ]",
|
"[ (17/8 → 3/1) ⇝ 25/8 | note:Eb3 clip:0.2 ]",
|
||||||
"[ 7/4 ⇜ (2/1 → 41/20) ⇝ 37/20 | note:D4 ]",
|
"[ 7/4 ⇜ (2/1 → 9/4) | note:D4 clip:0.2 ]",
|
||||||
"[ (9/4 → 12/5) ⇝ 49/20 | note:G3 ]",
|
"[ (9/4 → 3/1) ⇝ 13/4 | note:G3 clip:0.2 ]",
|
||||||
"[ 15/8 ⇜ (2/1 → 83/40) ⇝ 79/40 | note:F4 ]",
|
"[ 15/8 ⇜ (2/1 → 19/8) | note:F4 clip:0.2 ]",
|
||||||
"[ (19/8 → 5/2) ⇝ 103/40 | note:Bb3 ]",
|
"[ (19/8 → 3/1) ⇝ 27/8 | note:Bb3 clip:0.2 ]",
|
||||||
"[ 3/1 → 31/10 | note:Eb3 ]",
|
"[ 3/1 → 7/2 | note:Eb3 clip:0.2 ]",
|
||||||
"[ 7/2 → 18/5 | note:G3 ]",
|
"[ 7/2 → 4/1 | note:G3 clip:0.2 ]",
|
||||||
"[ 17/8 ⇜ (3/1 → 121/40) ⇝ 93/40 | note:Eb3 ]",
|
"[ 17/8 ⇜ (3/1 → 25/8) | note:Eb3 clip:0.2 ]",
|
||||||
"[ 25/8 → 129/40 | note:G3 ]",
|
"[ 25/8 → 29/8 | note:G3 clip:0.2 ]",
|
||||||
"[ (29/8 → 37/10) ⇝ 149/40 | note:Bb3 ]",
|
"[ (29/8 → 4/1) ⇝ 33/8 | note:Bb3 clip:0.2 ]",
|
||||||
"[ 9/4 ⇜ (3/1 → 61/20) ⇝ 49/20 | note:G3 ]",
|
"[ 9/4 ⇜ (3/1 → 13/4) | note:G3 clip:0.2 ]",
|
||||||
"[ 13/4 → 67/20 | note:Bb3 ]",
|
"[ 13/4 → 15/4 | note:Bb3 clip:0.2 ]",
|
||||||
"[ (15/4 → 19/5) ⇝ 77/20 | note:D4 ]",
|
"[ (15/4 → 4/1) ⇝ 17/4 | note:D4 clip:0.2 ]",
|
||||||
"[ 19/8 ⇜ (3/1 → 123/40) ⇝ 103/40 | note:Bb3 ]",
|
"[ 19/8 ⇜ (3/1 → 27/8) | note:Bb3 clip:0.2 ]",
|
||||||
"[ 27/8 → 139/40 | note:D4 ]",
|
"[ 27/8 → 31/8 | note:D4 clip:0.2 ]",
|
||||||
"[ (31/8 → 39/10) ⇝ 159/40 | note:F4 ]",
|
"[ (31/8 → 4/1) ⇝ 35/8 | note:F4 clip:0.2 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -3193,6 +3193,23 @@ exports[`runs examples > example "rarely" example index 0 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "ratio" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ (0/1 → 1/1) ⇝ 2/1 | freq:110 s:piano ]",
|
||||||
|
"[ (0/1 → 1/1) ⇝ 2/1 | freq:137.5 s:piano ]",
|
||||||
|
"[ (0/1 → 1/1) ⇝ 2/1 | freq:165 s:piano ]",
|
||||||
|
"[ 0/1 ⇜ (1/1 → 2/1) | freq:110 s:piano ]",
|
||||||
|
"[ 0/1 ⇜ (1/1 → 2/1) | freq:137.5 s:piano ]",
|
||||||
|
"[ 0/1 ⇜ (1/1 → 2/1) | freq:165 s:piano ]",
|
||||||
|
"[ (2/1 → 3/1) ⇝ 4/1 | freq:110 s:piano ]",
|
||||||
|
"[ (2/1 → 3/1) ⇝ 4/1 | freq:137.5 s:piano ]",
|
||||||
|
"[ (2/1 → 3/1) ⇝ 4/1 | freq:165 s:piano ]",
|
||||||
|
"[ 2/1 ⇜ (3/1 → 4/1) | freq:110 s:piano ]",
|
||||||
|
"[ 2/1 ⇜ (3/1 → 4/1) | freq:137.5 s:piano ]",
|
||||||
|
"[ 2/1 ⇜ (3/1 → 4/1) | freq:165 s:piano ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "release" example index 0 1`] = `
|
exports[`runs examples > example "release" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/4 | note:c3 release:0 ]",
|
"[ 0/1 → 1/4 | note:c3 release:0 ]",
|
||||||
@@ -3486,30 +3503,30 @@ exports[`runs examples > example "samples" example index 1 1`] = `
|
|||||||
|
|
||||||
exports[`runs examples > example "saw" example index 0 1`] = `
|
exports[`runs examples > example "saw" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/32 | note:c3 ]",
|
"[ 0/1 → 1/4 | note:c3 clip:0.03125 ]",
|
||||||
"[ 1/4 → 9/32 | note:eb3 ]",
|
"[ 1/4 → 1/2 | note:eb3 clip:0.09375 ]",
|
||||||
"[ 1/4 → 9/32 | note:g3 ]",
|
"[ 1/4 → 1/2 | note:g3 clip:0.09375 ]",
|
||||||
"[ 1/2 → 17/32 | note:g2 ]",
|
"[ 1/2 → 3/4 | note:g2 clip:0.15625 ]",
|
||||||
"[ 3/4 → 25/32 | note:g3 ]",
|
"[ 3/4 → 1/1 | note:g3 clip:0.21875 ]",
|
||||||
"[ 3/4 → 25/32 | note:bb3 ]",
|
"[ 3/4 → 1/1 | note:bb3 clip:0.21875 ]",
|
||||||
"[ 1/1 → 35/32 | note:c3 ]",
|
"[ 1/1 → 5/4 | note:c3 clip:0.28125 ]",
|
||||||
"[ 5/4 → 43/32 | note:eb3 ]",
|
"[ 5/4 → 3/2 | note:eb3 clip:0.34375 ]",
|
||||||
"[ 5/4 → 43/32 | note:g3 ]",
|
"[ 5/4 → 3/2 | note:g3 clip:0.34375 ]",
|
||||||
"[ 3/2 → 51/32 | note:g2 ]",
|
"[ 3/2 → 7/4 | note:g2 clip:0.40625 ]",
|
||||||
"[ 7/4 → 59/32 | note:g3 ]",
|
"[ 7/4 → 2/1 | note:g3 clip:0.46875 ]",
|
||||||
"[ 7/4 → 59/32 | note:bb3 ]",
|
"[ 7/4 → 2/1 | note:bb3 clip:0.46875 ]",
|
||||||
"[ 2/1 → 69/32 | note:c3 ]",
|
"[ 2/1 → 9/4 | note:c3 clip:0.53125 ]",
|
||||||
"[ 9/4 → 77/32 | note:eb3 ]",
|
"[ 9/4 → 5/2 | note:eb3 clip:0.59375 ]",
|
||||||
"[ 9/4 → 77/32 | note:g3 ]",
|
"[ 9/4 → 5/2 | note:g3 clip:0.59375 ]",
|
||||||
"[ 5/2 → 85/32 | note:g2 ]",
|
"[ 5/2 → 11/4 | note:g2 clip:0.65625 ]",
|
||||||
"[ 11/4 → 93/32 | note:g3 ]",
|
"[ 11/4 → 3/1 | note:g3 clip:0.71875 ]",
|
||||||
"[ 11/4 → 93/32 | note:bb3 ]",
|
"[ 11/4 → 3/1 | note:bb3 clip:0.71875 ]",
|
||||||
"[ 3/1 → 103/32 | note:c3 ]",
|
"[ 3/1 → 13/4 | note:c3 clip:0.78125 ]",
|
||||||
"[ 13/4 → 111/32 | note:eb3 ]",
|
"[ 13/4 → 7/2 | note:eb3 clip:0.84375 ]",
|
||||||
"[ 13/4 → 111/32 | note:g3 ]",
|
"[ 13/4 → 7/2 | note:g3 clip:0.84375 ]",
|
||||||
"[ 7/2 → 119/32 | note:g2 ]",
|
"[ 7/2 → 15/4 | note:g2 clip:0.90625 ]",
|
||||||
"[ 15/4 → 127/32 | note:g3 ]",
|
"[ 15/4 → 4/1 | note:g3 clip:0.96875 ]",
|
||||||
"[ 15/4 → 127/32 | note:bb3 ]",
|
"[ 15/4 → 4/1 | note:bb3 clip:0.96875 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ export const testCycles = {
|
|||||||
festivalOfFingers: 16,
|
festivalOfFingers: 16,
|
||||||
festivalOfFingers2: 22,
|
festivalOfFingers2: 22,
|
||||||
undergroundPlumber: 20,
|
undergroundPlumber: 20,
|
||||||
bridgeIsOver: 16,
|
bridgeIsOver: 8,
|
||||||
goodTimes: 16,
|
goodTimes: 16,
|
||||||
echoPiano: 8,
|
echoPiano: 8,
|
||||||
sml1: 48,
|
sml1: 48,
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ export const customTrigger = `// licensed with CC BY-NC-SA 4.0 https://creativec
|
|||||||
// by Felix Roos
|
// by Felix Roos
|
||||||
stack(
|
stack(
|
||||||
freq("55 [110,165] 110 [220,275]".mul("<1 <3/4 2/3>>").struct("x(3,8)").layer(x=>x.mul("1.006,.995"))),
|
freq("55 [110,165] 110 [220,275]".mul("<1 <3/4 2/3>>").struct("x(3,8)").layer(x=>x.mul("1.006,.995"))),
|
||||||
freq("440(5,8)".legato(.18).mul("<1 3/4 2 2/3>")).gain(perlin.range(.2,.8))
|
freq("440(5,8)".clip(.18).mul("<1 3/4 2 2/3>")).gain(perlin.range(.2,.8))
|
||||||
).s("<sawtooth square>/2")
|
).s("<sawtooth square>/2")
|
||||||
.onTrigger((t,hap,ct)=>{
|
.onTrigger((t,hap,ct)=>{
|
||||||
const ac = Tone.getContext().rawContext;
|
const ac = Tone.getContext().rawContext;
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ export const SIDEBAR: Sidebar = {
|
|||||||
{ text: 'Signals', link: 'learn/signals' },
|
{ text: 'Signals', link: 'learn/signals' },
|
||||||
{ text: 'Conditional Modifiers', link: 'learn/conditional-modifiers' },
|
{ text: 'Conditional Modifiers', link: 'learn/conditional-modifiers' },
|
||||||
{ text: 'Accumulation', link: 'learn/accumulation' },
|
{ text: 'Accumulation', link: 'learn/accumulation' },
|
||||||
{ text: 'Tonal Modifiers', link: 'learn/tonal' },
|
{ text: 'Tonal Functions', link: 'learn/tonal' },
|
||||||
],
|
],
|
||||||
Development: [
|
Development: [
|
||||||
{ text: 'REPL', link: 'technical-manual/repl' },
|
{ text: 'REPL', link: 'technical-manual/repl' },
|
||||||
|
|||||||
@@ -16,3 +16,11 @@
|
|||||||
.cm-gutters {
|
.cm-gutters {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cm-cursorLayer {
|
||||||
|
animation-name: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-cursor {
|
||||||
|
border-left: 2px solid currentcolor !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -361,11 +361,3 @@ insect [crow metal] ~ ~,
|
|||||||
|
|
||||||
Jetzt haben wir eine grundlegende Ahnung davon wie man mit Strudel Beats baut!
|
Jetzt haben wir eine grundlegende Ahnung davon wie man mit Strudel Beats baut!
|
||||||
Im nächsten Kapitel werden wir ein paar [Töne spielen](/de/workshop/first-notes).
|
Im nächsten Kapitel werden wir ein paar [Töne spielen](/de/workshop/first-notes).
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
- vllt mal das wörtchen `sound` behandeln
|
|
||||||
- was ist überhaupt casio??
|
|
||||||
- Strg = ctrl on mac "+" ist verwirrend
|
|
||||||
- cursor ist sehr undeutlich wenn nicht in emacs mode
|
|
||||||
- wieviele zahlen gibt es
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { MiniRepl } from '../../../docs/MiniRepl';
|
|||||||
<img src="/icons/strudel_icon.png" className="w-32 animate-pulse md:float-right ml-8" />
|
<img src="/icons/strudel_icon.png" className="w-32 animate-pulse md:float-right ml-8" />
|
||||||
|
|
||||||
Willkommen zum Strudel Workshop!
|
Willkommen zum Strudel Workshop!
|
||||||
Du hast den richtigen Ort gefunden wenn du lernen möchstest wie man mit Code Musik macht.
|
Du hast den richtigen Ort gefunden wenn du lernen möchtest wie man mit Code Musik macht.
|
||||||
|
|
||||||
## Was ist Strudel
|
## Was ist Strudel
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,10 @@ This group of functions allows to modify the value of events.
|
|||||||
|
|
||||||
<JsDoc client:idle name="Pattern.range2" h={0} />
|
<JsDoc client:idle name="Pattern.range2" h={0} />
|
||||||
|
|
||||||
|
## ratio
|
||||||
|
|
||||||
|
<JsDoc client:idle name="Pattern.ratio" h={0} />
|
||||||
|
|
||||||
# Custom Parameters
|
# Custom Parameters
|
||||||
|
|
||||||
You can also create your own parameters:
|
You can also create your own parameters:
|
||||||
|
|||||||
@@ -32,4 +32,4 @@ import { JsDoc } from '../../docs/JsDoc';
|
|||||||
|
|
||||||
<JsDoc client:idle name="stut" h={0} />
|
<JsDoc client:idle name="stut" h={0} />
|
||||||
|
|
||||||
There are also [Tonal Modifiers](/learn/tonal).
|
There are also [Tonal Functions](/learn/tonal).
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<script is:inline>
|
<script is:inline>
|
||||||
window.location.pathname = `/learn/getting-started`;
|
window.location.pathname = `/workshop/getting-started`;
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ Some of these have equivalent operators in the Mini Notation:
|
|||||||
|
|
||||||
<JsDoc client:idle name="Pattern.legato" h={0} />
|
<JsDoc client:idle name="Pattern.legato" h={0} />
|
||||||
|
|
||||||
|
## clip
|
||||||
|
|
||||||
|
<JsDoc client:idle name="clip" h={0} />
|
||||||
|
|
||||||
## euclid
|
## euclid
|
||||||
|
|
||||||
<JsDoc client:idle name="Pattern.euclid" h={0} />
|
<JsDoc client:idle name="Pattern.euclid" h={0} />
|
||||||
|
|||||||
@@ -1,14 +1,29 @@
|
|||||||
---
|
---
|
||||||
title: Tonal API
|
title: Tonal Functions
|
||||||
layout: ../../layouts/MainLayout.astro
|
layout: ../../layouts/MainLayout.astro
|
||||||
---
|
---
|
||||||
|
|
||||||
import { MiniRepl } from '../../docs/MiniRepl';
|
import { MiniRepl } from '../../docs/MiniRepl';
|
||||||
import { JsDoc } from '../../docs/JsDoc';
|
import { JsDoc } from '../../docs/JsDoc';
|
||||||
|
|
||||||
# Tonal API
|
# Tonal Functions
|
||||||
|
|
||||||
The Tonal API, uses [tonaljs](https://github.com/tonaljs/tonal) to provide helpers for musical operations.
|
These functions use [tonaljs](https://github.com/tonaljs/tonal) to provide helpers for musical operations.
|
||||||
|
|
||||||
|
### scale(name)
|
||||||
|
|
||||||
|
Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like scaleTranspose.
|
||||||
|
|
||||||
|
<MiniRepl
|
||||||
|
client:idle
|
||||||
|
tune={`"0 2 4 6 4 2"
|
||||||
|
.scale("C2:major C2:minor").slow(2))
|
||||||
|
.note().s("piano")`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
Note that the scale root is octaved here. You can also omit the octave, then index zero will default to octave 3.
|
||||||
|
|
||||||
|
All the available scale names can be found [here](https://github.com/tonaljs/tonal/blob/main/packages/scale-type/data.ts).
|
||||||
|
|
||||||
### transpose(semitones)
|
### transpose(semitones)
|
||||||
|
|
||||||
@@ -22,21 +37,6 @@ Instead of numbers, scientific interval notation can be used as well:
|
|||||||
|
|
||||||
<MiniRepl client:only="react" tune={`"c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note()`} />
|
<MiniRepl client:only="react" tune={`"c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note()`} />
|
||||||
|
|
||||||
### scale(name)
|
|
||||||
|
|
||||||
Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like scaleTranspose.
|
|
||||||
|
|
||||||
<MiniRepl
|
|
||||||
client:idle
|
|
||||||
tune={`"0 2 4 6 4 2"
|
|
||||||
.scale(seq('C2 major', 'C2 minor').slow(2))
|
|
||||||
.note()`}
|
|
||||||
/>
|
|
||||||
|
|
||||||
Note that the scale root is octaved here. You can also omit the octave, then index zero will default to octave 3.
|
|
||||||
|
|
||||||
All the available scale names can be found [here](https://github.com/tonaljs/tonal/blob/main/packages/scale-type/data.ts).
|
|
||||||
|
|
||||||
### scaleTranspose(steps)
|
### scaleTranspose(steps)
|
||||||
|
|
||||||
Transposes notes inside the scale by the number of steps:
|
Transposes notes inside the scale by the number of steps:
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
This section introduces you to Strudel in a technical sense. If you just want to _use_ Strudel, have a look at the [Tutorial](/learn/getting-started).
|
This section introduces you to Strudel in a technical sense. If you just want to _use_ Strudel, have a look at the [Tutorial](/workshop/getting-started).
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { MiniRepl } from '../../docs/MiniRepl';
|
|||||||
|
|
||||||
# Strudel Packages
|
# Strudel Packages
|
||||||
|
|
||||||
The [strudel repo](github.com/tidalcycles/strudel) is organized as a monorepo, containing multiple npm packages.
|
The [strudel repo](https://github.com/tidalcycles/strudel) is organized as a monorepo, containing multiple npm packages.
|
||||||
The purpose of the multiple packages is to
|
The purpose of the multiple packages is to
|
||||||
|
|
||||||
- organize the codebase into more modular, encapsulated pieces
|
- organize the codebase into more modular, encapsulated pieces
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<script is:inline>
|
<script is:inline>
|
||||||
window.location.pathname = `/learn/getting-started`;
|
window.location.pathname = `/workshop/getting-started`;
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ These letter combinations stand for different parts of a drum set:
|
|||||||
|
|
||||||
- `bd` = **b**ass **d**rum
|
- `bd` = **b**ass **d**rum
|
||||||
- `sd` = **s**nare **d**rum
|
- `sd` = **s**nare **d**rum
|
||||||
- `sd` = **sd**are
|
|
||||||
- `rim` = **rim**shot
|
- `rim` = **rim**shot
|
||||||
- `hh` = **h**i**h**at
|
- `hh` = **h**i**h**at
|
||||||
- `oh` = **o**pen **h**ihat
|
- `oh` = **o**pen **h**ihat
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { Fragment, useEffect } from 'react';
|
||||||
|
import React, { useMemo, useState } from 'react';
|
||||||
|
import { isAudioFile, readDir, dir, playFile } from './files.mjs';
|
||||||
|
|
||||||
|
export function FilesTab() {
|
||||||
|
const [path, setPath] = useState([]);
|
||||||
|
useEffect(() => {
|
||||||
|
let init = false;
|
||||||
|
readDir('', { dir, recursive: true })
|
||||||
|
.then((children) => setPath([{ name: '~/music', children }]))
|
||||||
|
.catch((err) => {
|
||||||
|
console.log('error loadin files', err);
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
init = true;
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
const current = useMemo(() => path[path.length - 1], [path]);
|
||||||
|
const subpath = useMemo(
|
||||||
|
() =>
|
||||||
|
path
|
||||||
|
.slice(1)
|
||||||
|
.map((p) => p.name)
|
||||||
|
.join('/'),
|
||||||
|
[path],
|
||||||
|
);
|
||||||
|
const folders = useMemo(() => current?.children.filter((e) => !!e.children), [current]);
|
||||||
|
const files = useMemo(() => current?.children.filter((e) => !e.children && isAudioFile(e.name)), [current]);
|
||||||
|
const select = (e) => setPath((p) => p.concat([e]));
|
||||||
|
return (
|
||||||
|
<div className="px-4 flex flex-col h-full">
|
||||||
|
<div className="flex justify-between font-mono pb-1">
|
||||||
|
<div>
|
||||||
|
<span>{`samples('`}</span>
|
||||||
|
{path?.map((p, i) => {
|
||||||
|
if (i < path.length - 1) {
|
||||||
|
return (
|
||||||
|
<Fragment key={i}>
|
||||||
|
<span className="cursor-pointer underline" onClick={() => setPath((p) => p.slice(0, i + 1))}>
|
||||||
|
{p.name}
|
||||||
|
</span>
|
||||||
|
<span>/</span>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<span className="cursor-pointer underline" key={i}>
|
||||||
|
{p.name}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
<span>{`')`}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="overflow-auto">
|
||||||
|
{!folders?.length && !files?.length && <span className="text-gray-500">Nothing here</span>}
|
||||||
|
{folders?.map((e, i) => (
|
||||||
|
<div className="cursor-pointer" key={i} onClick={() => select(e)}>
|
||||||
|
{e.name}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{files?.map((e, i) => (
|
||||||
|
<div
|
||||||
|
className="text-gray-500 cursor-pointer select-none"
|
||||||
|
key={i}
|
||||||
|
onClick={async () => playFile(`${subpath}/${e.name}`)}
|
||||||
|
>
|
||||||
|
{e.name}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -9,6 +9,9 @@ import { themes } from './themes.mjs';
|
|||||||
import { useSettings, settingsMap, setActiveFooter, defaultSettings } from '../settings.mjs';
|
import { useSettings, settingsMap, setActiveFooter, defaultSettings } from '../settings.mjs';
|
||||||
import { getAudioContext, soundMap } from '@strudel.cycles/webaudio';
|
import { getAudioContext, soundMap } from '@strudel.cycles/webaudio';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import { FilesTab } from './FilesTab';
|
||||||
|
|
||||||
|
const TAURI = window.__TAURI__;
|
||||||
|
|
||||||
export function Footer({ context }) {
|
export function Footer({ context }) {
|
||||||
const footerContent = useRef();
|
const footerContent = useRef();
|
||||||
@@ -77,6 +80,7 @@ export function Footer({ context }) {
|
|||||||
<FooterTab name="console" />
|
<FooterTab name="console" />
|
||||||
<FooterTab name="reference" />
|
<FooterTab name="reference" />
|
||||||
<FooterTab name="settings" />
|
<FooterTab name="settings" />
|
||||||
|
{TAURI && <FooterTab name="files" />}
|
||||||
</div>
|
</div>
|
||||||
{activeFooter !== '' && (
|
{activeFooter !== '' && (
|
||||||
<button onClick={() => setActiveFooter('')} className="text-foreground" aria-label="Close Panel">
|
<button onClick={() => setActiveFooter('')} className="text-foreground" aria-label="Close Panel">
|
||||||
@@ -91,6 +95,7 @@ export function Footer({ context }) {
|
|||||||
{activeFooter === 'sounds' && <SoundsTab />}
|
{activeFooter === 'sounds' && <SoundsTab />}
|
||||||
{activeFooter === 'reference' && <Reference />}
|
{activeFooter === 'reference' && <Reference />}
|
||||||
{activeFooter === 'settings' && <SettingsTab scheduler={context.scheduler} />}
|
{activeFooter === 'settings' && <SettingsTab scheduler={context.scheduler} />}
|
||||||
|
{activeFooter === 'files' && <FilesTab />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</footer>
|
</footer>
|
||||||
@@ -140,7 +145,7 @@ function WelcomeTab() {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
To learn more about what this all means, check out the{' '}
|
To learn more about what this all means, check out the{' '}
|
||||||
<a href="./learn/getting-started" target="_blank">
|
<a href="./workshop/getting-started" target="_blank">
|
||||||
interactive tutorial
|
interactive tutorial
|
||||||
</a>
|
</a>
|
||||||
. Also feel free to join the{' '}
|
. Also feel free to join the{' '}
|
||||||
@@ -364,7 +369,16 @@ const fontFamilyOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function SettingsTab({ scheduler }) {
|
function SettingsTab({ scheduler }) {
|
||||||
const { theme, keybindings, isLineNumbersDisplayed, fontSize, fontFamily } = useSettings();
|
const {
|
||||||
|
theme,
|
||||||
|
keybindings,
|
||||||
|
isLineNumbersDisplayed,
|
||||||
|
isAutoCompletionEnabled,
|
||||||
|
isLineWrappingEnabled,
|
||||||
|
fontSize,
|
||||||
|
fontFamily,
|
||||||
|
} = useSettings();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-foreground p-4 space-y-4">
|
<div className="text-foreground p-4 space-y-4">
|
||||||
{/* <FormItem label="Tempo">
|
{/* <FormItem label="Tempo">
|
||||||
@@ -406,7 +420,7 @@ function SettingsTab({ scheduler }) {
|
|||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||||
<FormItem label="Keybindings">
|
<FormItem label="Keybindings">
|
||||||
<ButtonGroup
|
<ButtonGroup
|
||||||
value={keybindings}
|
value={keybindings}
|
||||||
@@ -419,6 +433,16 @@ function SettingsTab({ scheduler }) {
|
|||||||
onChange={(cbEvent) => settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)}
|
onChange={(cbEvent) => settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)}
|
||||||
value={isLineNumbersDisplayed}
|
value={isLineNumbersDisplayed}
|
||||||
/>
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label="Enable auto-completion"
|
||||||
|
onChange={(cbEvent) => settingsMap.setKey('isAutoCompletionEnabled', cbEvent.target.checked)}
|
||||||
|
value={isAutoCompletionEnabled}
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label="Enable line wrapping"
|
||||||
|
onChange={(cbEvent) => settingsMap.setKey('isLineWrappingEnabled', cbEvent.target.checked)}
|
||||||
|
value={isLineWrappingEnabled}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<FormItem label="Reset Settings">
|
<FormItem label="Reset Settings">
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -45,3 +45,11 @@
|
|||||||
#code .cm-theme-light {
|
#code .cm-theme-light {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#code .cm-cursorLayer {
|
||||||
|
animation-name: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code .cm-cursor {
|
||||||
|
border-left: 2px solid currentcolor !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
|
|||||||
import { themes } from './themes.mjs';
|
import { themes } from './themes.mjs';
|
||||||
import { settingsMap, useSettings, setLatestCode } from '../settings.mjs';
|
import { settingsMap, useSettings, setLatestCode } from '../settings.mjs';
|
||||||
import Loader from './Loader';
|
import Loader from './Loader';
|
||||||
|
import { settingPatterns } from '../settings.mjs';
|
||||||
|
|
||||||
const { latestCode } = settingsMap.get();
|
const { latestCode } = settingsMap.get();
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ const modules = [
|
|||||||
|
|
||||||
const modulesLoading = evalScope(
|
const modulesLoading = evalScope(
|
||||||
controls, // sadly, this cannot be exported from core direclty
|
controls, // sadly, this cannot be exported from core direclty
|
||||||
|
settingPatterns,
|
||||||
...modules,
|
...modules,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -105,7 +107,15 @@ export function Repl({ embedded = false }) {
|
|||||||
const [lastShared, setLastShared] = useState();
|
const [lastShared, setLastShared] = useState();
|
||||||
const [pending, setPending] = useState(true);
|
const [pending, setPending] = useState(true);
|
||||||
|
|
||||||
const { theme, keybindings, fontSize, fontFamily, isLineNumbersDisplayed } = useSettings();
|
const {
|
||||||
|
theme,
|
||||||
|
keybindings,
|
||||||
|
fontSize,
|
||||||
|
fontFamily,
|
||||||
|
isLineNumbersDisplayed,
|
||||||
|
isAutoCompletionEnabled,
|
||||||
|
isLineWrappingEnabled,
|
||||||
|
} = useSettings();
|
||||||
|
|
||||||
const { code, setCode, scheduler, evaluate, activateCode, isDirty, activeCode, pattern, started, stop, error } =
|
const { code, setCode, scheduler, evaluate, activateCode, isDirty, activeCode, pattern, started, stop, error } =
|
||||||
useStrudel({
|
useStrudel({
|
||||||
@@ -157,7 +167,7 @@ export function Repl({ embedded = false }) {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
flash(view);
|
flash(view);
|
||||||
await activateCode();
|
await activateCode();
|
||||||
} else if (e.key === '.' || e.keyCode === 'Period') {
|
} else if (e.key === '.' || e.code === 'Period') {
|
||||||
stop();
|
stop();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
@@ -272,6 +282,8 @@ export function Repl({ embedded = false }) {
|
|||||||
value={code}
|
value={code}
|
||||||
keybindings={keybindings}
|
keybindings={keybindings}
|
||||||
isLineNumbersDisplayed={isLineNumbersDisplayed}
|
isLineNumbersDisplayed={isLineNumbersDisplayed}
|
||||||
|
isAutoCompletionEnabled={isAutoCompletionEnabled}
|
||||||
|
isLineWrappingEnabled={isLineWrappingEnabled}
|
||||||
fontSize={fontSize}
|
fontSize={fontSize}
|
||||||
fontFamily={fontFamily}
|
fontFamily={fontFamily}
|
||||||
onChange={handleChangeCode}
|
onChange={handleChangeCode}
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
import {
|
||||||
|
processSampleMap,
|
||||||
|
registerSamplesPrefix,
|
||||||
|
registerSound,
|
||||||
|
onTriggerSample,
|
||||||
|
getAudioContext,
|
||||||
|
loadBuffer,
|
||||||
|
} from '@strudel.cycles/webaudio';
|
||||||
|
|
||||||
|
let TAURI;
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
TAURI = window?.__TAURI__;
|
||||||
|
}
|
||||||
|
export const { BaseDirectory, readDir, readBinaryFile, writeTextFile, readTextFile, exists } = TAURI?.fs || {};
|
||||||
|
|
||||||
|
export const dir = BaseDirectory?.Audio; // https://tauri.app/v1/api/js/path#audiodir
|
||||||
|
const prefix = '~/music/';
|
||||||
|
|
||||||
|
async function hasStrudelJson(subpath) {
|
||||||
|
return exists(subpath + '/strudel.json', { dir });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadStrudelJson(subpath) {
|
||||||
|
const contents = await readTextFile(subpath + '/strudel.json', { dir });
|
||||||
|
const sampleMap = JSON.parse(contents);
|
||||||
|
processSampleMap(sampleMap, (key, value) => {
|
||||||
|
registerSound(key, (t, hapValue, onended) => onTriggerSample(t, hapValue, onended, value, fileResolver(subpath)), {
|
||||||
|
type: 'sample',
|
||||||
|
samples: value,
|
||||||
|
fileSystem: true,
|
||||||
|
tag: 'local',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeStrudelJson(subpath) {
|
||||||
|
const children = await readDir(subpath, { dir, recursive: true });
|
||||||
|
const name = subpath.split('/').slice(-1)[0];
|
||||||
|
const tree = { name, children };
|
||||||
|
|
||||||
|
let samples = {};
|
||||||
|
let count = 0;
|
||||||
|
walkFileTree(tree, (entry, parent) => {
|
||||||
|
if (['wav', 'mp3'].includes(entry.name.split('.').slice(-1)[0])) {
|
||||||
|
samples[parent.name] = samples[parent.name] || [];
|
||||||
|
count += 1;
|
||||||
|
samples[parent.name].push(entry.subpath.slice(1).concat([entry.name]).join('/'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const json = JSON.stringify(samples, null, 2);
|
||||||
|
const filepath = subpath + '/strudel.json';
|
||||||
|
await writeTextFile(filepath, json, { dir });
|
||||||
|
console.log(`wrote strudel.json with ${count} samples to ${subpath}!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerSamplesPrefix(prefix, async (path) => {
|
||||||
|
const subpath = path.replace(prefix, '');
|
||||||
|
const hasJson = await hasStrudelJson(subpath);
|
||||||
|
if (!hasJson) {
|
||||||
|
await writeStrudelJson(subpath);
|
||||||
|
}
|
||||||
|
return loadStrudelJson(subpath);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const walkFileTree = (node, fn) => {
|
||||||
|
if (!Array.isArray(node?.children)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const entry of node.children) {
|
||||||
|
entry.subpath = (node.subpath || []).concat([node.name]);
|
||||||
|
fn(entry, node);
|
||||||
|
if (entry.children) {
|
||||||
|
walkFileTree(entry, fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isAudioFile = (filename) => ['wav', 'mp3'].includes(filename.split('.').slice(-1)[0]);
|
||||||
|
|
||||||
|
function uint8ArrayToDataURL(uint8Array) {
|
||||||
|
const blob = new Blob([uint8Array], { type: 'audio/*' });
|
||||||
|
const dataURL = URL.createObjectURL(blob);
|
||||||
|
return dataURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadCache = {}; // caches local urls to data urls
|
||||||
|
export async function resolveFileURL(url) {
|
||||||
|
if (loadCache[url]) {
|
||||||
|
return loadCache[url];
|
||||||
|
}
|
||||||
|
loadCache[url] = (async () => {
|
||||||
|
const contents = await readBinaryFile(url, { dir });
|
||||||
|
return uint8ArrayToDataURL(contents);
|
||||||
|
})();
|
||||||
|
return loadCache[url];
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileResolver = (subpath) => (url) => resolveFileURL(subpath.endsWith('/') ? subpath + url : subpath + '/' + url);
|
||||||
|
|
||||||
|
export async function playFile(path) {
|
||||||
|
const url = await resolveFileURL(path);
|
||||||
|
const ac = getAudioContext();
|
||||||
|
const bufferSource = ac.createBufferSource();
|
||||||
|
bufferSource.buffer = await loadBuffer(url, ac);
|
||||||
|
bufferSource.connect(ac.destination);
|
||||||
|
bufferSource.start(ac.currentTime);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Pattern, noteToMidi, valueToMidi } from '@strudel.cycles/core';
|
import { Pattern, noteToMidi, valueToMidi } from '@strudel.cycles/core';
|
||||||
import { registerSynthSounds, samples } from '@strudel.cycles/webaudio';
|
import { registerSynthSounds, samples } from '@strudel.cycles/webaudio';
|
||||||
import './piano.mjs';
|
import './piano.mjs';
|
||||||
|
import './files.mjs';
|
||||||
|
|
||||||
export async function prebake() {
|
export async function prebake() {
|
||||||
// https://archive.org/details/SalamanderGrandPianoV3
|
// https://archive.org/details/SalamanderGrandPianoV3
|
||||||
@@ -118,7 +119,7 @@ const maxPan = noteToMidi('C8');
|
|||||||
const panwidth = (pan, width) => pan * width + (1 - width) / 2;
|
const panwidth = (pan, width) => pan * width + (1 - width) / 2;
|
||||||
|
|
||||||
Pattern.prototype.piano = function () {
|
Pattern.prototype.piano = function () {
|
||||||
return this.clip(1)
|
return this.fmap((v) => ({ ...v, clip: v.clip ?? 1 })) // set clip if not already set..
|
||||||
.s('piano')
|
.s('piano')
|
||||||
.release(0.1)
|
.release(0.1)
|
||||||
.fmap((value) => {
|
.fmap((value) => {
|
||||||
|
|||||||
@@ -205,27 +205,24 @@ samples({
|
|||||||
}
|
}
|
||||||
}, 'https://loophole-letters.vercel.app/')
|
}, 'https://loophole-letters.vercel.app/')
|
||||||
|
|
||||||
const scales = cat('C major', 'C mixolydian', 'F lydian', ['F minor', cat('Db major','Db mixolydian')])
|
|
||||||
|
|
||||||
stack(
|
stack(
|
||||||
s("<bd sn> <hh hh*2 hh*3>").color('#00B8D4'),
|
s("<bd sn> <hh hh*2 hh*3>").color('#00B8D4'),
|
||||||
"<g4 c5 a4 [ab4 <eb5 f5>]>"
|
"<g4 c5 a4 [ab4 <eb5 f5>]>"
|
||||||
.scale(scales)
|
.scale("<C:major C:mixolydian F:lydian [F:minor <Db:major Db:mixolydian>]>")
|
||||||
.struct("x*8")
|
.struct("x*8")
|
||||||
.scaleTranspose("0 [-5,-2] -7 [-9,-2]")
|
.scaleTranspose("0 [-5,-2] -7 [-9,-2]")
|
||||||
.legato(.3)
|
|
||||||
.slow(2)
|
.slow(2)
|
||||||
.note()
|
.note()
|
||||||
|
.clip(.3)
|
||||||
.s('rhodes')
|
.s('rhodes')
|
||||||
.clip(1)
|
|
||||||
.room(.5)
|
.room(.5)
|
||||||
.delay(.3)
|
.delay(.3)
|
||||||
.delayfeedback(.4)
|
.delayfeedback(.4)
|
||||||
.delaytime(1/12).gain(.5).color('#7ED321'),
|
.delaytime(1/12).gain(.5).color('#7ED321'),
|
||||||
"<c2 c3 f2 [[F2 C2] db2]>"
|
"<c2 c3 f2 [[F2 C2] db2]>/2"
|
||||||
.legato("<1@3 [.3 1]>")
|
.add("0,.02")
|
||||||
.slow(2).superimpose(x=>x.add(.02))
|
|
||||||
.note().gain(.3)
|
.note().gain(.3)
|
||||||
|
.clip("<1@3 [.3 1]>/2")
|
||||||
.s('sawtooth').cutoff(600).color('#F8E71C'),
|
.s('sawtooth').cutoff(600).color('#F8E71C'),
|
||||||
).fast(3/2)
|
).fast(3/2)
|
||||||
//.pianoroll({fold:1})`;
|
//.pianoroll({fold:1})`;
|
||||||
@@ -237,7 +234,7 @@ export const wavyKalimba = `// "Wavy kalimba"
|
|||||||
samples({
|
samples({
|
||||||
'kalimba': { c5:'https://freesound.org/data/previews/536/536549_11935698-lq.mp3' }
|
'kalimba': { c5:'https://freesound.org/data/previews/536/536549_11935698-lq.mp3' }
|
||||||
})
|
})
|
||||||
const scales = cat('C major', 'C mixolydian', 'F lydian', ['F minor', 'Db major'])
|
const scales = "<C:major C:mixolydian F:lydian [F:minor Db:major]>"
|
||||||
|
|
||||||
stack(
|
stack(
|
||||||
"[0 2 4 6 9 2 0 -2]*3"
|
"[0 2 4 6 9 2 0 -2]*3"
|
||||||
@@ -254,13 +251,11 @@ stack(
|
|||||||
.velocity(0.8)
|
.velocity(0.8)
|
||||||
.slow(2)
|
.slow(2)
|
||||||
)
|
)
|
||||||
.legato("<.4 .8 1 1.2 1.4 1.6 1.8 2>/8")
|
|
||||||
.fast(1)
|
.fast(1)
|
||||||
.note()
|
.note()
|
||||||
.clip(1)
|
.clip("<.4 .8 1 1.2 1.4 1.6 1.8 2>/8")
|
||||||
.s('kalimba')
|
.s('kalimba')
|
||||||
.delay(.2)
|
.delay(.2)`;
|
||||||
`;
|
|
||||||
|
|
||||||
export const festivalOfFingers = `// "Festival of fingers"
|
export const festivalOfFingers = `// "Festival of fingers"
|
||||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
@@ -293,19 +288,19 @@ stack(
|
|||||||
s("<<bd*2 bd> sn> hh").fast(2).gain(.7),
|
s("<<bd*2 bd> sn> hh").fast(2).gain(.7),
|
||||||
"[c2 a1 bb1 ~] ~"
|
"[c2 a1 bb1 ~] ~"
|
||||||
.echo(2, 1/16, 1)
|
.echo(2, 1/16, 1)
|
||||||
.legato(.4)
|
|
||||||
.slow(2)
|
.slow(2)
|
||||||
.layer(h)
|
.layer(h)
|
||||||
.note().s('square')
|
.note().s('square')
|
||||||
|
.clip(.4)
|
||||||
.cutoff(400).decay(.12).sustain(0)
|
.cutoff(400).decay(.12).sustain(0)
|
||||||
,
|
,
|
||||||
"[g2,[c3 eb3]]".iter(4)
|
"[g2,[c3 eb3]]".iter(4)
|
||||||
.echoWith(4, 1/8, (x,n)=>x.transpose(n*12).velocity(Math.pow(.4,n)))
|
.echoWith(4, 1/8, (x,n)=>x.transpose(n*12).velocity(Math.pow(.4,n)))
|
||||||
.legato(.1)
|
|
||||||
.layer(h).note()
|
.layer(h).note()
|
||||||
|
.clip(.1)
|
||||||
)
|
)
|
||||||
.fast(2/3)
|
.fast(2/3)
|
||||||
.pianoroll({})`;
|
.pianoroll()`;
|
||||||
|
|
||||||
export const bridgeIsOver = `// "Bridge is over"
|
export const bridgeIsOver = `// "Bridge is over"
|
||||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
@@ -314,19 +309,16 @@ export const bridgeIsOver = `// "Bridge is over"
|
|||||||
samples({mad:'https://freesound.org/data/previews/22/22274_109943-lq.mp3'})
|
samples({mad:'https://freesound.org/data/previews/22/22274_109943-lq.mp3'})
|
||||||
stack(
|
stack(
|
||||||
stack(
|
stack(
|
||||||
"c3*2 [[c3@1.4 bb2] ab2] gb2*2 <[[gb2@1.4 ab2] bb2] gb2>".legato(".5 1".fast(2)).velocity(.8),
|
note("c3*2 [[c3@1.4 bb2] ab2] gb2*2 <[[gb2@1.4 ab2] bb2] gb2>")
|
||||||
"0 ~".scale('c4 whole tone')
|
.gain(.8).clip("[.5 1]*2"),
|
||||||
.euclidLegato(3,8).slow(2).mask("x ~")
|
n("<0 1 2 3 4 3 2 1>")
|
||||||
.stutWith(8, 1/16, (x,n)=>x.scaleTranspose(n).velocity(Math.pow(.7,n)))
|
.clip(.5)
|
||||||
.scaleTranspose("<0 1 2 3 4 3 2 1>")
|
.echoWith(8, 1/32, (x,i)=>x.add(n(i)).velocity(Math.pow(.7,i)))
|
||||||
.fast(2)
|
.scale('c4 whole tone')
|
||||||
.velocity(.7)
|
.echo(3, 1/8, .5)
|
||||||
.legato(.5)
|
).piano(),
|
||||||
.stut(3, .5, 1/8)
|
|
||||||
).transpose(-1).note().piano(),
|
|
||||||
s("mad").slow(2)
|
s("mad").slow(2)
|
||||||
).cpm(78).slow(4)
|
).cpm(78).slow(4)
|
||||||
|
|
||||||
.pianoroll()
|
.pianoroll()
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -336,63 +328,39 @@ export const goodTimes = `// "Good times"
|
|||||||
|
|
||||||
const scale = cat('C3 dorian','Bb2 major').slow(4);
|
const scale = cat('C3 dorian','Bb2 major').slow(4);
|
||||||
stack(
|
stack(
|
||||||
"2*4".add(12).scale(scale)
|
n("2*4".add(12)).off(1/8, add(2))
|
||||||
.off(1/8, scaleTranspose("2")).fast(2)
|
|
||||||
.scaleTranspose("<0 1 2 1>").hush(),
|
|
||||||
"<0 1 2 3>(3,8,2)"
|
|
||||||
.scale(scale)
|
.scale(scale)
|
||||||
.off(1/4, scaleTranspose("2,4")),
|
.fast(2)
|
||||||
"<0 4>(5,8,-1)".scale(scale).transpose(-12)
|
.add("<0 1 2 1>").hush(),
|
||||||
|
"<0 1 2 3>(3,8,2)".off(1/4, add("2,4"))
|
||||||
|
.n().scale(scale),
|
||||||
|
n("<0 4>(5,8,-1)").scale(scale).sub(note(12))
|
||||||
)
|
)
|
||||||
.velocity(".6 .7".fast(4))
|
.velocity(".6 .7".fast(4))
|
||||||
.legato("2")
|
.add(note(4))
|
||||||
.scaleTranspose("<0>".slow(4))
|
.piano()
|
||||||
.transpose(5)
|
.clip(2)
|
||||||
.note().piano()
|
|
||||||
.velocity(.8)
|
.velocity(.8)
|
||||||
.slow(2)
|
.slow(2)
|
||||||
.pianoroll({maxMidi:100,minMidi:20})`;
|
.pianoroll()`;
|
||||||
|
|
||||||
/* // new style notation:
|
|
||||||
export const goodTimes = `// licensed with CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
|
||||||
// by Felix Roos
|
|
||||||
const scale = cat('C3 dorian','Bb2 major').slow(4);
|
|
||||||
stack(
|
|
||||||
n("2*4").add(12)
|
|
||||||
.off(1/8, add("2")).fast(2)
|
|
||||||
.add("<0 1 2 1>").hush(),
|
|
||||||
n("<0 1 2 3>(3,8,2)")
|
|
||||||
.off(1/4, add("2,4")),
|
|
||||||
n("<0 4>(5,8,-1)").sub(7)
|
|
||||||
)
|
|
||||||
.scale(scale)
|
|
||||||
.gain(".6 .7".fast(4))
|
|
||||||
.legato(2)
|
|
||||||
.add(note(5))
|
|
||||||
.piano()
|
|
||||||
.mul(gain(.8))
|
|
||||||
.slow(2)
|
|
||||||
.pianoroll({maxMidi:100,minMidi:20})`;
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const echoPiano = `// "Echo piano"
|
export const echoPiano = `// "Echo piano"
|
||||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
// @by Felix Roos
|
// @by Felix Roos
|
||||||
|
|
||||||
"<0 2 [4 6](3,4,2) 3*2>"
|
n("<0 2 [4 6](3,4,2) 3*2>").color('salmon')
|
||||||
|
.off(1/4, x=>x.add(2).color('green'))
|
||||||
|
.off(1/2, x=>x.add(6).color('steelblue'))
|
||||||
.scale('D minor')
|
.scale('D minor')
|
||||||
.color('salmon')
|
|
||||||
.off(1/4, x=>x.scaleTranspose(2).color('green'))
|
|
||||||
.off(1/2, x=>x.scaleTranspose(6).color('steelblue'))
|
|
||||||
.legato(.5)
|
|
||||||
.echo(4, 1/8, .5)
|
.echo(4, 1/8, .5)
|
||||||
.note().piano()
|
.clip(.5)
|
||||||
|
.piano()
|
||||||
.pianoroll()`;
|
.pianoroll()`;
|
||||||
|
|
||||||
export const sml1 = `// Hirokazu Tanaka - World 1-1
|
export const sml1 = `// Hirokazu Tanaka - World 1-1
|
||||||
stack(
|
stack(
|
||||||
// melody
|
// melody
|
||||||
\`<
|
note(\`<
|
||||||
[e5 ~] [[d5@2 c5] [~@2 e5]] ~ [~ [c5@2 d5]] [e5 e5] [d5 c5] [e5 f5] [g5 a5]
|
[e5 ~] [[d5@2 c5] [~@2 e5]] ~ [~ [c5@2 d5]] [e5 e5] [d5 c5] [e5 f5] [g5 a5]
|
||||||
[~ c5] [c5 d5] [e5 [c5@2 c5]] [~ c5] [f5 e5] [c5 d5] [~ g6] [g6 ~]
|
[~ c5] [c5 d5] [e5 [c5@2 c5]] [~ c5] [f5 e5] [c5 d5] [~ g6] [g6 ~]
|
||||||
[e5 ~] [[d5@2 c5] [~@2 e5]] ~ [~ [c5@2 d5]] [e5 e5] [d5 c5] [a5 g5] [c6 [e5@2 d5]]
|
[e5 ~] [[d5@2 c5] [~@2 e5]] ~ [~ [c5@2 d5]] [e5 e5] [d5 c5] [a5 g5] [c6 [e5@2 d5]]
|
||||||
@@ -401,28 +369,28 @@ stack(
|
|||||||
[f5 ~] [[g5@2 f5] ~] [[e5 ~] [f5 ~]] [[f#5 ~] [g5 ~]]
|
[f5 ~] [[g5@2 f5] ~] [[e5 ~] [f5 ~]] [[f#5 ~] [g5 ~]]
|
||||||
[~ a5] [b5 c6] [b5@2 ~@2 g5] ~
|
[~ a5] [b5 c6] [b5@2 ~@2 g5] ~
|
||||||
[eb6 d6] [~ c6] ~!2
|
[eb6 d6] [~ c6] ~!2
|
||||||
>\`
|
>\`)
|
||||||
.legato(.95),
|
.clip(.95),
|
||||||
// sub melody
|
// sub melody
|
||||||
\`<
|
note(\`<
|
||||||
[~ g4]!2 [~ ab4]!2 [~ a4]!2 [~ bb4]!2
|
[~ g4]!2 [~ ab4]!2 [~ a4]!2 [~ bb4]!2
|
||||||
[~ a4]!2 [~ g4]!2 [d4 e4] [f4 gb4] ~!2
|
[~ a4]!2 [~ g4]!2 [d4 e4] [f4 gb4] ~!2
|
||||||
[~ g4]!2 [~ ab4]!2 [~ a4]!2 [~ bb4]!2
|
[~ g4]!2 [~ ab4]!2 [~ a4]!2 [~ bb4]!2
|
||||||
[~ a4]!2 [~ g4]!2 [d4 e4] [f4 gb4] ~!2
|
[~ a4]!2 [~ g4]!2 [d4 e4] [f4 gb4] ~!2
|
||||||
[~ c5]!4 [~ a4]!2 [[c4 ~] [d4 ~]] [[eb4 ~] [e4 ~]]
|
[~ c5]!4 [~ a4]!2 [[c4 ~] [d4 ~]] [[eb4 ~] [e4 ~]]
|
||||||
[~ c5]!4 [~ eb5]!2 [g4*2 [f4 ~]] [[e4 ~] [d4 ~]]
|
[~ c5]!4 [~ eb5]!2 [g4*2 [f4 ~]] [[e4 ~] [d4 ~]]
|
||||||
>\`,
|
>\`),
|
||||||
// bass
|
// bass
|
||||||
\`<
|
note(\`<
|
||||||
c3!7 a3 f3!2
|
c3!7 a3 f3!2
|
||||||
e3!2 ~!4
|
e3!2 ~!4
|
||||||
c3!7 a3 f3!2
|
c3!7 a3 f3!2
|
||||||
e3!2 ~!4
|
e3!2 ~!4
|
||||||
f3!2 e3!2 d3!2 ~!2
|
f3!2 e3!2 d3!2 ~!2
|
||||||
f3!2 e3!2 ab3!2 ~!2
|
f3!2 e3!2 ab3!2 ~!2
|
||||||
>\`
|
>\`)
|
||||||
.legato(.5)
|
.clip(.5)
|
||||||
).fast(2).note()`;
|
).fast(2)`;
|
||||||
|
|
||||||
export const randomBells = `// "Random bells"
|
export const randomBells = `// "Random bells"
|
||||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
@@ -438,16 +406,14 @@ stack(
|
|||||||
"0".euclidLegato(3,8)
|
"0".euclidLegato(3,8)
|
||||||
.echo(3, 1/16, .5)
|
.echo(3, 1/16, .5)
|
||||||
.add(rand.range(0,12))
|
.add(rand.range(0,12))
|
||||||
|
.scale("D:minor:pentatonic").note()
|
||||||
.velocity(rand.range(.5,1))
|
.velocity(rand.range(.5,1))
|
||||||
.legato(rand.range(.4,3))
|
|
||||||
.scale(cat('D minor pentatonic')).note()
|
|
||||||
.s('bell').gain(.6).delay(.2).delaytime(1/3).delayfeedback(.8),
|
.s('bell').gain(.6).delay(.2).delaytime(1/3).delayfeedback(.8),
|
||||||
// bass
|
// bass
|
||||||
"<D2 A2 G2 F2>".euclidLegatoRot(6,8,4).note().s('bass').clip(1).gain(.8)
|
note("<D2 A2 G2 F2>").euclidLegatoRot(6,8,4).s('bass').clip(1).gain(.8)
|
||||||
)
|
)
|
||||||
.slow(6)
|
.slow(6)
|
||||||
.pianoroll({minMidi:20,maxMidi:120,background:'transparent'})
|
.pianoroll({vertical:1})`;
|
||||||
`;
|
|
||||||
|
|
||||||
export const waa2 = `// "Waa2"
|
export const waa2 = `// "Waa2"
|
||||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
@@ -460,7 +426,7 @@ n(
|
|||||||
.off(1/8,x=>x.add(12))
|
.off(1/8,x=>x.add(12))
|
||||||
)
|
)
|
||||||
.slow(2)
|
.slow(2)
|
||||||
.legato(sine.range(0.3, 2).slow(28))
|
.clip(sine.range(0.3, 2).slow(28))
|
||||||
.s("sawtooth square".fast(2))
|
.s("sawtooth square".fast(2))
|
||||||
.cutoff(cosine.range(500,4000).slow(16))
|
.cutoff(cosine.range(500,4000).slow(16))
|
||||||
.gain(.5)
|
.gain(.5)
|
||||||
@@ -524,20 +490,22 @@ export const festivalOfFingers3 = `// "Festival of fingers 3"
|
|||||||
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||||
// @by Felix Roos
|
// @by Felix Roos
|
||||||
|
|
||||||
"[-7*3],0,2,6,[8 7]"
|
n("[-7*3],0,2,6,[8 7]")
|
||||||
.echoWith(4,1/4, (x,n)=>x
|
.echoWith(
|
||||||
.add(n*7)
|
4, // echo 4 times
|
||||||
.velocity(1/(n+1))
|
1/4, // 1/4s between echos
|
||||||
.legato(1/(n+1)))
|
(x,i)=>x
|
||||||
.velocity(perlin.range(.5,.9).slow(8))
|
.add(n(i*7)) // add octaves
|
||||||
.stack("[22 25]*3"
|
.gain(1/(i+1)) // reduce gain
|
||||||
.legato(sine.range(.5,2).slow(8))
|
.clip(1/(i+1))
|
||||||
.velocity(sine.range(.4,.8).slow(5))
|
)
|
||||||
.echo(4,1/12,.5))
|
.velocity(perlin.range(.5,.9).slow(8))
|
||||||
.scale(cat('D dorian','G mixolydian','C dorian','F mixolydian'))
|
.stack(n("[22 25]*3")
|
||||||
.legato(1)
|
.clip(sine.range(.5,2).slow(8))
|
||||||
.slow(2)
|
.gain(sine.range(.4,.8).slow(5))
|
||||||
.note().piano()
|
.echo(4,1/12,.5))
|
||||||
|
.scale("<D:dorian G:mixolydian C:dorian F:mixolydian>")
|
||||||
|
.slow(2).piano()
|
||||||
//.pianoroll({maxMidi:160})`;
|
//.pianoroll({maxMidi:160})`;
|
||||||
|
|
||||||
export const meltingsubmarine = `// "Melting submarine"
|
export const meltingsubmarine = `// "Melting submarine"
|
||||||
@@ -897,9 +865,9 @@ stack(
|
|||||||
,
|
,
|
||||||
note("<C2 A1 D2 F2>/2").ply(8).csound('Bass').gain("1 4 1 4")
|
note("<C2 A1 D2 F2>/2").ply(8).csound('Bass').gain("1 4 1 4")
|
||||||
,
|
,
|
||||||
note("0 7 [4 3] 2".fast(2/3).off(".25 .125",add("<2 4 -3 -1>"))
|
n("0 7 [4 3] 2".fast(2/3).off(".25 .125", add("<2 4 -3 -1>"))
|
||||||
.slow(2).scale('A4 minor'))
|
.slow(2).scale('A4 minor'))
|
||||||
.legato(.25).csound('SynHarp')
|
.clip(.25).csound('SynHarp')
|
||||||
,
|
,
|
||||||
s("bd*2,[~ hh]*2,~ cp").bank('RolandTR909')
|
s("bd*2,[~ hh]*2,~ cp").bank('RolandTR909')
|
||||||
)`;
|
)`;
|
||||||
@@ -910,15 +878,15 @@ export const arpoon = `// "Arpoon"
|
|||||||
|
|
||||||
await samples('github:tidalcycles/Dirt-Samples/master')
|
await samples('github:tidalcycles/Dirt-Samples/master')
|
||||||
|
|
||||||
"<<Am7 C^7> C7 F^7 [Fm7 E7b9]>".voicings('lefthand')
|
note("<<Am7 C^7> C7 F^7 [Fm7 E7b9]>".voicings('lefthand'))
|
||||||
.arp("[0,3] 2 [1,3] 2".fast(3).lastOf(4, fast(2))).legato(2)
|
.arp("[0,3] 2 [1,3] 2".fast(3).lastOf(4, fast(2))).clip(2)
|
||||||
.add(perlin.range(0,0.2)).sub("<0 -12>/8")
|
.add(perlin.range(0,0.2).add("<0 12>/8").note())
|
||||||
.note().cutoff(perlin.range(500,4000)).resonance(12)
|
.cutoff(perlin.range(500,4000)).resonance(12)
|
||||||
.gain("<.5 .8>*16")
|
.gain("<.5 .8>*16")
|
||||||
.decay(.16).sustain(0.5)
|
.decay(.16).sustain(0.5)
|
||||||
.delay(.2)
|
.delay(.2)
|
||||||
.room(.5).pan(sine.range(.3,.6))
|
.room(.5).pan(sine.range(.3,.6))
|
||||||
.s('piano').clip(1)
|
.s('piano')
|
||||||
.stack("<<A1 C2>!2 F2 [F2 E2]>".add.out("0 -5".fast(2)).add("0,.12").note().s('sawtooth').clip(1).cutoff(300))
|
.stack("<<A1 C2>!2 F2 [F2 E2]>".add.out("0 -5".fast(2)).add("0,.12").note().s('sawtooth').clip(1).cutoff(300))
|
||||||
.slow(4)
|
.slow(4)
|
||||||
.stack(s("bd*4, [~ [hh hh? hh?]]*2,~ [sd ~ [sd:2? bd?]]").bank('RolandTR909').gain(.5).slow(2))
|
.stack(s("bd*4, [~ [hh hh? hh?]]*2,~ [sd ~ [sd:2? bd?]]").bank('RolandTR909').gain(.5).slow(2))
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import { persistentMap } from '@nanostores/persistent';
|
import { persistentMap } from '@nanostores/persistent';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
|
import { register } from '@strudel.cycles/core';
|
||||||
|
|
||||||
export const defaultSettings = {
|
export const defaultSettings = {
|
||||||
activeFooter: 'intro',
|
activeFooter: 'intro',
|
||||||
keybindings: 'codemirror',
|
keybindings: 'codemirror',
|
||||||
isLineNumbersDisplayed: true,
|
isLineNumbersDisplayed: true,
|
||||||
|
isAutoCompletionEnabled: false,
|
||||||
|
isLineWrappingEnabled: false,
|
||||||
theme: 'strudelTheme',
|
theme: 'strudelTheme',
|
||||||
fontFamily: 'monospace',
|
fontFamily: 'monospace',
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
@@ -21,6 +24,8 @@ export function useSettings() {
|
|||||||
...state,
|
...state,
|
||||||
isZen: [true, 'true'].includes(state.isZen) ? true : false,
|
isZen: [true, 'true'].includes(state.isZen) ? true : false,
|
||||||
isLineNumbersDisplayed: [true, 'true'].includes(state.isLineNumbersDisplayed) ? true : false,
|
isLineNumbersDisplayed: [true, 'true'].includes(state.isLineNumbersDisplayed) ? true : false,
|
||||||
|
isAutoCompletionEnabled: [true, 'true'].includes(state.isAutoCompletionEnabled) ? true : false,
|
||||||
|
isLineWrappingEnabled: [true, 'true'].includes(state.isLineWrappingEnabled) ? true : false,
|
||||||
fontSize: Number(state.fontSize),
|
fontSize: Number(state.fontSize),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -29,3 +34,18 @@ export const setActiveFooter = (tab) => settingsMap.setKey('activeFooter', tab);
|
|||||||
|
|
||||||
export const setLatestCode = (code) => settingsMap.setKey('latestCode', code);
|
export const setLatestCode = (code) => settingsMap.setKey('latestCode', code);
|
||||||
export const setIsZen = (active) => settingsMap.setKey('isZen', !!active);
|
export const setIsZen = (active) => settingsMap.setKey('isZen', !!active);
|
||||||
|
|
||||||
|
const patternSetting = (key) =>
|
||||||
|
register(key, (value, pat) => {
|
||||||
|
value = Array.isArray(value) ? value.join(' ') : value;
|
||||||
|
if (value !== settingsMap.get()[key]) {
|
||||||
|
settingsMap.setKey(key, value);
|
||||||
|
}
|
||||||
|
return pat;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const theme = patternSetting('theme');
|
||||||
|
export const fontFamily = patternSetting('fontFamily');
|
||||||
|
export const fontSize = patternSetting('fontSize');
|
||||||
|
|
||||||
|
export const settingPatterns = { theme, fontFamily, fontSize };
|
||||||
|
|||||||