mirror of
https://codeberg.org/uzu/strudel
synced 2026-10-03 08:07:34 -04:00
Compare commits
154 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3daacba2c3 | |||
| fa7c16dbe7 | |||
| 6a43eb6755 | |||
| c524ebc7f3 | |||
| 0deb905cdf | |||
| 4cadbcbbdf | |||
| 96eef75f74 | |||
| 51d9e02e07 | |||
| c4c21c4f0c | |||
| fcb247b62a | |||
| 7556da7839 | |||
| eb93a6c149 | |||
| b870ab204a | |||
| f779e81993 | |||
| 5c71bb95a0 | |||
| 1525992d73 | |||
| abe25be05e | |||
| 664a19a5c4 | |||
| 8efadd2547 | |||
| ed1f3e1e8c | |||
| 4aaf9eaed4 | |||
| 0416e4d212 | |||
| b9247db001 | |||
| 74ef157fa1 | |||
| d4724b0e12 | |||
| dbfdbcf2b7 | |||
| 0986b14508 | |||
| 325152c782 | |||
| c136d12194 | |||
| 7557952155 | |||
| b0b41e6718 | |||
| 22e3067b8c | |||
| e9ab01ab06 | |||
| 058e554b0f | |||
| 6d9327aebc | |||
| c23d7850c7 | |||
| 2854f0cf34 | |||
| a89e87ca2e | |||
| 5419ca431b | |||
| e8b674badd | |||
| 8af40a9c61 | |||
| f54aa3d823 | |||
| 5e91287e3e | |||
| 4e3d4a7060 | |||
| 3d80da9816 | |||
| bf63b716af | |||
| 38d389b838 | |||
| ebdca32c80 | |||
| c06a3710c1 | |||
| d5e67fe13f | |||
| 00c7da45c0 | |||
| 3347817350 | |||
| 88ece92a78 | |||
| 03a73fb95e | |||
| 23c55c9636 | |||
| 12c6f4e95f | |||
| a468ddb85b | |||
| 051bdaccc7 | |||
| 5dc04d9574 | |||
| 60129413d3 | |||
| d2bf9370ea | |||
| fd11aa5eec | |||
| fb7c2b61d3 | |||
| dd64bf0fc9 | |||
| 434eb3b256 | |||
| 6da98a5f31 | |||
| 8fef75385a | |||
| c66b9219a8 | |||
| 2a1f8823e8 | |||
| 3da65f90e3 | |||
| a36cc24087 | |||
| 1829d8cadf | |||
| 02efc090ef | |||
| b184348f55 | |||
| 06743cb072 | |||
| 6fa66fb1d0 | |||
| 23c0ab9648 | |||
| 6422047cff | |||
| 46c2c72637 | |||
| c088590244 | |||
| 192ba69682 | |||
| 2cc428e968 | |||
| 15c451a6d9 | |||
| b46e8c07be | |||
| 961e931c31 | |||
| b1d49552ae | |||
| d31d154841 | |||
| d03892bbcf | |||
| 0cf0c1c585 | |||
| 0695b4bee9 | |||
| 0cfec3a7bd | |||
| 6224cd40d4 | |||
| 18ae82174d | |||
| aa1b9d11dc | |||
| 0a82471112 | |||
| 8052e10f0c | |||
| 1146f6ba52 | |||
| 738cea0025 | |||
| 6c28398d20 | |||
| 4fe75143d0 | |||
| 3cd59cdea5 | |||
| 9dca7eb878 | |||
| b45fd5ce3a | |||
| 229b1470f7 | |||
| 0a349e1707 | |||
| d176e9ccf0 | |||
| 710c3acb5d | |||
| a7f5d0e0c1 | |||
| 9928526dda | |||
| 2f8111be0e | |||
| 68113937ff | |||
| c598fa026b | |||
| 491c99c348 | |||
| d49aa8242a | |||
| 9ffbc06cf9 | |||
| af52ac30ba | |||
| 7aea1b5fc8 | |||
| 500ddf3946 | |||
| 3431eaf309 | |||
| 9a13c58583 | |||
| 77a48e8351 | |||
| 6cb156d876 | |||
| d8677c6261 | |||
| 6ef9ca18e9 | |||
| 6667738dc9 | |||
| 4f7415b0ec | |||
| c6f3a8b7c7 | |||
| 4229d673c9 | |||
| 98b7859605 | |||
| a8db707440 | |||
| 873a412179 | |||
| 0778b4809e | |||
| f85fb35c66 | |||
| 5ada0daf40 | |||
| 2ed5f5aa65 | |||
| ae5e6e3ab8 | |||
| 9ba7b9b4d4 | |||
| a45f1fba45 | |||
| e6b47d2cf2 | |||
| 7adfe6f2df | |||
| 45df7bfea3 | |||
| 106772e480 | |||
| e7e60d3ed8 | |||
| 78f6fdf169 | |||
| e01c6dc18d | |||
| 51dd408733 | |||
| 1ff7548b52 | |||
| f7fe44063a | |||
| 0355c358b8 | |||
| 4e0a60db00 | |||
| 3604d3940c | |||
| 02b9bd82cf | |||
| 1bc86c359e | |||
| 1e2c26123b |
@@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
[](https://github.com/tidalcycles/strudel/actions)
|
[](https://github.com/tidalcycles/strudel/actions)
|
||||||
|
|
||||||
An experiment in making a [Tidal](https://github.com/tidalcycles/tidal/) using web technologies. This software is slowly stabilising, but please continue to tread carefully.
|
An experiment in making a [Tidal](https://github.com/tidalcycles/tidal/) using web technologies. This software is a bit more stable now, but please continue to tread carefully.
|
||||||
|
|
||||||
- Try it here: <https://strudel.cc>
|
- Try it here: <https://strudel.cc>
|
||||||
- Docs: <https://strudel.cc/learn>
|
- Docs: <https://strudel.cc/learn>
|
||||||
- Technical Blog Post: <https://loophole-letters.vercel.app/strudel>
|
- Technical Blog Post: <https://loophole-letters.vercel.app/strudel>
|
||||||
- 1 Year of Strudel Blog Post: <https://loophole-letters.vercel.app/strudel1year>
|
- 1 Year of Strudel Blog Post: <https://loophole-letters.vercel.app/strudel1year>
|
||||||
|
- 2 Years of Strudel Blog Post: <https://strudel.cc/blog/#year-2>
|
||||||
|
|
||||||
## Running Locally
|
## Running Locally
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
import { initStrudel } from 'https://cdn.skypack.dev/@strudel/web@0.8.2';
|
import { initStrudel } from 'https://cdn.skypack.dev/@strudel/web@0.8.2';
|
||||||
initStrudel({
|
initStrudel({
|
||||||
prebake: () => samples('github:tidalcycles/Dirt-Samples/master'),
|
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||||
});
|
});
|
||||||
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
|
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
|
||||||
click('a', () => evaluate(`s('bd,jvbass(3,8)').jux(rev)`));
|
click('a', () => evaluate(`s('bd,jvbass(3,8)').jux(rev)`));
|
||||||
|
|||||||
@@ -16,38 +16,45 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="output"></div>
|
<div id="output"></div>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { controls, repl, evalScope } from 'https://cdn.skypack.dev/@strudel.cycles/core@0.6.8';
|
// TODO: refactor to use newer version without controls import
|
||||||
import { mini } from 'https://cdn.skypack.dev/@strudel.cycles/mini@0.6.0';
|
import { controls, repl, evalScope } from 'https://cdn.skypack.dev/@strudel/core@0.11.0';
|
||||||
import { transpiler } from 'https://cdn.skypack.dev/@strudel.cycles/transpiler@0.6.0';
|
import { mini } from 'https://cdn.skypack.dev/@strudel/mini@0.11.0';
|
||||||
|
import { transpiler } from 'https://cdn.skypack.dev/@strudel/transpiler@0.11.0';
|
||||||
import {
|
import {
|
||||||
getAudioContext,
|
getAudioContext,
|
||||||
webaudioOutput,
|
webaudioOutput,
|
||||||
initAudioOnFirstClick,
|
initAudioOnFirstClick,
|
||||||
} from 'https://cdn.skypack.dev/@strudel.cycles/webaudio@0.6.0';
|
registerSynthSounds,
|
||||||
|
} from 'https://cdn.skypack.dev/@strudel/webaudio@0.11.0';
|
||||||
|
|
||||||
initAudioOnFirstClick();
|
|
||||||
const ctx = getAudioContext();
|
const ctx = getAudioContext();
|
||||||
const input = document.getElementById('text');
|
const input = document.getElementById('text');
|
||||||
input.innerHTML = getTune();
|
input.innerHTML = getTune();
|
||||||
|
|
||||||
evalScope(
|
const loadModules = evalScope(
|
||||||
controls,
|
controls,
|
||||||
import('https://cdn.skypack.dev/@strudel.cycles/core@0.6.8'),
|
import('https://cdn.skypack.dev/@strudel/core@0.11.0'),
|
||||||
import('https://cdn.skypack.dev/@strudel.cycles/mini@0.6.0'),
|
import('https://cdn.skypack.dev/@strudel/mini@0.11.0'),
|
||||||
import('https://cdn.skypack.dev/@strudel.cycles/tonal@0.6.0'),
|
import('https://cdn.skypack.dev/@strudel/tonal@0.11.0'),
|
||||||
import('https://cdn.skypack.dev/@strudel.cycles/webaudio@0.6.0'),
|
import('https://cdn.skypack.dev/@strudel/webaudio@0.11.0'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const initAudio = Promise.all([initAudioOnFirstClick(), registerSynthSounds()]);
|
||||||
|
|
||||||
const { evaluate } = repl({
|
const { evaluate } = repl({
|
||||||
defaultOutput: webaudioOutput,
|
defaultOutput: webaudioOutput,
|
||||||
getTime: () => ctx.currentTime,
|
getTime: () => ctx.currentTime,
|
||||||
transpiler,
|
transpiler,
|
||||||
});
|
});
|
||||||
document.getElementById('start').addEventListener('click', () => evaluate(input.value));
|
document.getElementById('start').addEventListener('click', async () => {
|
||||||
|
await loadModules;
|
||||||
|
await initAudio;
|
||||||
|
evaluate(input.value);
|
||||||
|
});
|
||||||
|
|
||||||
function getTune() {
|
function getTune() {
|
||||||
return `await samples('github:tidalcycles/Dirt-Samples/master')
|
return `samples('github:tidalcycles/dirt-samples')
|
||||||
|
setcps(1);
|
||||||
stack(
|
stack(
|
||||||
// amen
|
// amen
|
||||||
n("0 1 2 3 4 5 6 7")
|
n("0 1 2 3 4 5 6 7")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<script src="https://unpkg.com/@strudel.cycles/embed@latest"></script>
|
<script src="https://unpkg.com/@strudel/embed@0.11.0"></script>
|
||||||
<!-- <script src="./embed.js"></script> -->
|
<!-- <script src="./embed.js"></script> -->
|
||||||
<strudel-repl>
|
<strudel-repl>
|
||||||
<!--
|
<!--
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<script src="https://unpkg.com/@strudel/repl@0.9.4"></script>
|
<script src="https://unpkg.com/@strudel/repl@1.0.2"></script>
|
||||||
<strudel-editor>
|
<strudel-editor>
|
||||||
<!--
|
<!--
|
||||||
// @date 23-08-15
|
// @date 23-08-15
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<script src="https://unpkg.com/@strudel/web@1.0.3"></script>
|
||||||
|
<button id="play">PLAY</button>
|
||||||
|
<script>
|
||||||
|
initStrudel({
|
||||||
|
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||||
|
});
|
||||||
|
document.getElementById('play').addEventListener('click', () => s('bd sd').play());
|
||||||
|
</script>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { StrudelMirror } from '@strudel/codemirror';
|
import { StrudelMirror } from '@strudel/codemirror';
|
||||||
import { funk42 } from './tunes';
|
import { funk42 } from './tunes';
|
||||||
import { drawPianoroll, evalScope, controls } from '@strudel/core';
|
import { drawPianoroll, evalScope } from '@strudel/core';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
import { initAudioOnFirstClick } from '@strudel/webaudio';
|
import { initAudioOnFirstClick } from '@strudel/webaudio';
|
||||||
import { transpiler } from '@strudel/transpiler';
|
import { transpiler } from '@strudel/transpiler';
|
||||||
@@ -25,7 +25,6 @@ const editor = new StrudelMirror({
|
|||||||
prebake: async () => {
|
prebake: async () => {
|
||||||
initAudioOnFirstClick(); // needed to make the browser happy (don't await this here..)
|
initAudioOnFirstClick(); // needed to make the browser happy (don't await this here..)
|
||||||
const loadModules = evalScope(
|
const loadModules = evalScope(
|
||||||
controls,
|
|
||||||
import('@strudel/core'),
|
import('@strudel/core'),
|
||||||
import('@strudel/mini'),
|
import('@strudel/mini'),
|
||||||
import('@strudel/tonal'),
|
import('@strudel/tonal'),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
export const bumpStreet = `// froos - "22 bump street", licensed with CC BY-NC-SA 4.0
|
export const bumpStreet = `// froos - "22 bump street", licensed with CC BY-NC-SA 4.0
|
||||||
await samples('github:felixroos/samples/main')
|
samples('github:felixroos/samples')
|
||||||
await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
||||||
|
|
||||||
"<[0,<6 7 9>,13,<17 20 22 26>]!2>/2"
|
"<[0,<6 7 9>,13,<17 20 22 26>]!2>/2"
|
||||||
// make it 22 edo
|
// make it 22 edo
|
||||||
@@ -33,8 +33,8 @@ await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tid
|
|||||||
|
|
||||||
export const trafficFlam = `// froos - "traffic flam", licensed with CC BY-NC-SA 4.0
|
export const trafficFlam = `// froos - "traffic flam", licensed with CC BY-NC-SA 4.0
|
||||||
|
|
||||||
await samples('github:felixroos/samples/main')
|
samples('github:felixroos/samples')
|
||||||
await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
||||||
|
|
||||||
addVoicings('hip', {
|
addVoicings('hip', {
|
||||||
m11: ['2M 3m 4P 7m'],
|
m11: ['2M 3m 4P 7m'],
|
||||||
@@ -69,8 +69,8 @@ export const funk42 = `// froos - how to funk in 42 lines of code
|
|||||||
// adapted from "how to funk in two minutes" by marc rebillet https://www.youtube.com/watch?v=3vBwRfQbXkg
|
// adapted from "how to funk in two minutes" by marc rebillet https://www.youtube.com/watch?v=3vBwRfQbXkg
|
||||||
// thanks to peach for the transcription: https://www.youtube.com/watch?v=8eiPXvIgda4
|
// thanks to peach for the transcription: https://www.youtube.com/watch?v=8eiPXvIgda4
|
||||||
|
|
||||||
await samples('github:felixroos/samples/main')
|
samples('github:felixroos/samples')
|
||||||
await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
|
||||||
|
|
||||||
setcps(.5)
|
setcps(.5)
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
import { initStrudel } from '@strudel/web';
|
import { initStrudel } from '@strudel/web';
|
||||||
initStrudel({
|
initStrudel({
|
||||||
prebake: () => samples('github:tidalcycles/Dirt-Samples/master'),
|
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||||
});
|
});
|
||||||
|
|
||||||
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
|
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { controls, repl, evalScope } from '@strudel/core';
|
import { repl, evalScope } from '@strudel/core';
|
||||||
import { getAudioContext, webaudioOutput, initAudioOnFirstClick } from '@strudel/webaudio';
|
import { getAudioContext, webaudioOutput, initAudioOnFirstClick, registerSynthSounds } from '@strudel/webaudio';
|
||||||
import { transpiler } from '@strudel/transpiler';
|
import { transpiler } from '@strudel/transpiler';
|
||||||
import tune from './tune.mjs';
|
import tune from './tune.mjs';
|
||||||
|
|
||||||
@@ -7,14 +7,9 @@ const ctx = getAudioContext();
|
|||||||
const input = document.getElementById('text');
|
const input = document.getElementById('text');
|
||||||
input.innerHTML = tune;
|
input.innerHTML = tune;
|
||||||
initAudioOnFirstClick();
|
initAudioOnFirstClick();
|
||||||
|
registerSynthSounds();
|
||||||
|
|
||||||
evalScope(
|
evalScope(import('@strudel/core'), import('@strudel/mini'), import('@strudel/webaudio'), import('@strudel/tonal'));
|
||||||
controls,
|
|
||||||
import('@strudel/core'),
|
|
||||||
import('@strudel/mini'),
|
|
||||||
import('@strudel/webaudio'),
|
|
||||||
import('@strudel/tonal'),
|
|
||||||
);
|
|
||||||
|
|
||||||
const { evaluate } = repl({
|
const { evaluate } = repl({
|
||||||
defaultOutput: webaudioOutput,
|
defaultOutput: webaudioOutput,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export default `await samples('github:tidalcycles/Dirt-Samples/master')
|
export default `samples('github:tidalcycles/dirt-samples')
|
||||||
|
setcps(1)
|
||||||
stack(
|
stack(
|
||||||
// amen
|
// amen
|
||||||
n("0 1 2 3 4 5 6 7")
|
n("0 1 2 3 4 5 6 7")
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
const init = Promise.all([
|
const init = Promise.all([
|
||||||
initAudioOnFirstClick(),
|
initAudioOnFirstClick(),
|
||||||
samples('github:tidalcycles/Dirt-Samples/master'),
|
samples('github:tidalcycles/dirt-samples'),
|
||||||
registerSynthSounds(),
|
registerSynthSounds(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { closeBrackets } from '@codemirror/autocomplete';
|
|||||||
// import { search, highlightSelectionMatches } from '@codemirror/search';
|
// import { search, highlightSelectionMatches } from '@codemirror/search';
|
||||||
import { history } from '@codemirror/commands';
|
import { history } from '@codemirror/commands';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
import { defaultHighlightStyle, syntaxHighlighting, bracketMatching } from '@codemirror/language';
|
||||||
import { Compartment, EditorState, Prec } from '@codemirror/state';
|
import { Compartment, EditorState, Prec } from '@codemirror/state';
|
||||||
import {
|
import {
|
||||||
EditorView,
|
EditorView,
|
||||||
@@ -24,6 +24,7 @@ import { persistentAtom } from '@nanostores/persistent';
|
|||||||
|
|
||||||
const extensions = {
|
const extensions = {
|
||||||
isLineWrappingEnabled: (on) => (on ? EditorView.lineWrapping : []),
|
isLineWrappingEnabled: (on) => (on ? EditorView.lineWrapping : []),
|
||||||
|
isBracketMatchingEnabled: (on) => (on ? bracketMatching({ brackets: '()[]{}<>' }) : []),
|
||||||
isLineNumbersDisplayed: (on) => (on ? lineNumbers() : []),
|
isLineNumbersDisplayed: (on) => (on ? lineNumbers() : []),
|
||||||
theme,
|
theme,
|
||||||
isAutoCompletionEnabled,
|
isAutoCompletionEnabled,
|
||||||
@@ -37,6 +38,7 @@ const compartments = Object.fromEntries(Object.keys(extensions).map((key) => [ke
|
|||||||
|
|
||||||
export const defaultSettings = {
|
export const defaultSettings = {
|
||||||
keybindings: 'codemirror',
|
keybindings: 'codemirror',
|
||||||
|
isBracketMatchingEnabled: false,
|
||||||
isLineNumbersDisplayed: true,
|
isLineNumbersDisplayed: true,
|
||||||
isActiveLineHighlighted: false,
|
isActiveLineHighlighted: false,
|
||||||
isAutoCompletionEnabled: false,
|
isAutoCompletionEnabled: false,
|
||||||
@@ -290,6 +292,9 @@ export class StrudelMirror {
|
|||||||
setLineWrappingEnabled(enabled) {
|
setLineWrappingEnabled(enabled) {
|
||||||
this.reconfigureExtension('isLineWrappingEnabled', enabled);
|
this.reconfigureExtension('isLineWrappingEnabled', enabled);
|
||||||
}
|
}
|
||||||
|
setBracketMatchingEnabled(enabled) {
|
||||||
|
this.reconfigureExtension('isBracketMatchingEnabled', enabled);
|
||||||
|
}
|
||||||
setLineNumbersDisplayed(enabled) {
|
setLineNumbersDisplayed(enabled) {
|
||||||
this.reconfigureExtension('isLineNumbersDisplayed', enabled);
|
this.reconfigureExtension('isLineNumbersDisplayed', enabled);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ const visibleMiniLocations = StateField.define({
|
|||||||
// this is why we need to find a way to update the existing decorations, showing the ones that have an active range
|
// this is why we need to find a way to update the existing decorations, showing the ones that have an active range
|
||||||
const haps = new Map();
|
const haps = new Map();
|
||||||
for (let hap of e.value.haps) {
|
for (let hap of e.value.haps) {
|
||||||
|
if (!hap.context?.locations || !hap.whole) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (let { start, end } of hap.context.locations) {
|
for (let { start, end } of hap.context.locations) {
|
||||||
let id = `${start}:${end}`;
|
let id = `${start}:${end}`;
|
||||||
if (!haps.has(id) || haps.get(id).whole.begin.lt(hap.whole.begin)) {
|
if (!haps.has(id) || haps.get(id).whole.begin.lt(hap.whole.begin)) {
|
||||||
@@ -64,7 +67,6 @@ const visibleMiniLocations = StateField.define({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visible = { atTime: e.value.atTime, haps };
|
visible = { atTime: e.value.atTime, haps };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/codemirror",
|
"name": "@strudel/codemirror",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Codemirror Extensions for Strudel",
|
"description": "Codemirror Extensions for Strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { Pattern, getDrawContext, silence, register, pure } from './index.mjs';
|
import { Pattern, getDrawContext, silence, register, pure, createParams } from './index.mjs';
|
||||||
import controls from './controls.mjs'; // do not import from index.mjs as it breaks for some reason..
|
|
||||||
const { createParams } = controls;
|
|
||||||
|
|
||||||
let clearColor = '#22222210';
|
let clearColor = '#22222210';
|
||||||
|
|
||||||
|
|||||||
+1446
-1417
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ import { logger } from './logger.mjs';
|
|||||||
export class Cyclist {
|
export class Cyclist {
|
||||||
constructor({ interval, onTrigger, onToggle, onError, getTime, latency = 0.1 }) {
|
constructor({ interval, onTrigger, onToggle, onError, getTime, latency = 0.1 }) {
|
||||||
this.started = false;
|
this.started = false;
|
||||||
this.cps = 1;
|
this.cps = 0.5;
|
||||||
this.num_ticks_since_cps_change = 0;
|
this.num_ticks_since_cps_change = 0;
|
||||||
this.lastTick = 0; // absolute time when last tick (clock callback) happened
|
this.lastTick = 0; // absolute time when last tick (clock callback) happened
|
||||||
this.lastBegin = 0; // query begin of last tick
|
this.lastBegin = 0; // query begin of last tick
|
||||||
@@ -41,7 +41,7 @@ export class Cyclist {
|
|||||||
this.lastEnd = end;
|
this.lastEnd = end;
|
||||||
|
|
||||||
// query the pattern for events
|
// query the pattern for events
|
||||||
const haps = this.pattern.queryArc(begin, end);
|
const haps = this.pattern.queryArc(begin, end, { _cps: this.cps });
|
||||||
|
|
||||||
const tickdeadline = phase - time; // time left until the phase is a whole number
|
const tickdeadline = phase - time; // time left until the phase is a whole number
|
||||||
this.lastTick = time + tickdeadline;
|
this.lastTick = time + tickdeadline;
|
||||||
@@ -96,7 +96,7 @@ export class Cyclist {
|
|||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setCps(cps = 1) {
|
setCps(cps = 0.5) {
|
||||||
if (this.cps === cps) {
|
if (this.cps === cps) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export class Drawer {
|
|||||||
this.lastFrame = phase;
|
this.lastFrame = phase;
|
||||||
this.visibleHaps = (this.visibleHaps || [])
|
this.visibleHaps = (this.visibleHaps || [])
|
||||||
// filter out haps that are too far in the past (think left edge of screen for pianoroll)
|
// filter out haps that are too far in the past (think left edge of screen for pianoroll)
|
||||||
.filter((h) => h.whole.end >= phase - lookbehind - lookahead)
|
.filter((h) => h.endClipped >= phase - lookbehind - lookahead)
|
||||||
// add new haps with onset (think right edge bars scrolling in)
|
// add new haps with onset (think right edge bars scrolling in)
|
||||||
.concat(haps.filter((h) => h.hasOnset()));
|
.concat(haps.filter((h) => h.hasOnset()));
|
||||||
const time = phase - lookahead;
|
const time = phase - lookahead;
|
||||||
|
|||||||
@@ -41,11 +41,17 @@ const _bjork = function (n, x) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const bjork = function (ons, steps) {
|
export const bjork = function (ons, steps) {
|
||||||
|
const inverted = ons < 0;
|
||||||
|
ons = Math.abs(ons);
|
||||||
const offs = steps - ons;
|
const offs = steps - ons;
|
||||||
const x = Array(ons).fill([1]);
|
const x = Array(ons).fill([1]);
|
||||||
const y = Array(offs).fill([0]);
|
const y = Array(offs).fill([0]);
|
||||||
const result = _bjork([ons, offs], [x, y]);
|
const result = _bjork([ons, offs], [x, y]);
|
||||||
return flatten(result[1][0]).concat(flatten(result[1][1]));
|
const p = flatten(result[1][0]).concat(flatten(result[1][1]));
|
||||||
|
if (inverted) {
|
||||||
|
return p.map((x) => (x === 0 ? 1 : 0));
|
||||||
|
}
|
||||||
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,7 +154,7 @@ export const { euclidrot, euclidRot } = register(['euclidrot', 'euclidRot'], fun
|
|||||||
* @param {number} pulses the number of onsets / beats
|
* @param {number} pulses the number of onsets / beats
|
||||||
* @param {number} steps the number of steps to fill
|
* @param {number} steps the number of steps to fill
|
||||||
* @example
|
* @example
|
||||||
* n("g2").decay(.1).sustain(.3).euclidLegato(3,8)
|
* note("c3").euclidLegato(3,8)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const _euclidLegato = function (pulses, steps, rotation, pat) {
|
const _euclidLegato = function (pulses, steps, rotation, pat) {
|
||||||
|
|||||||
+11
-1
@@ -3,6 +3,7 @@ hap.mjs - <short description TODO>
|
|||||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/hap.mjs>
|
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/hap.mjs>
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
import Fraction from './fraction.mjs';
|
||||||
|
|
||||||
export class Hap {
|
export class Hap {
|
||||||
/*
|
/*
|
||||||
@@ -32,7 +33,16 @@ export class Hap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get duration() {
|
get duration() {
|
||||||
return this.whole.end.sub(this.whole.begin).mul(typeof this.value?.clip === 'number' ? this.value?.clip : 1);
|
let duration;
|
||||||
|
if (typeof this.value?.duration === 'number') {
|
||||||
|
duration = Fraction(this.value.duration);
|
||||||
|
} else {
|
||||||
|
duration = this.whole.end.sub(this.whole.begin);
|
||||||
|
}
|
||||||
|
if (typeof this.value?.clip === 'number') {
|
||||||
|
return duration.mul(this.value.clip);
|
||||||
|
}
|
||||||
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
get endClipped() {
|
get endClipped() {
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
|
|||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import controls from './controls.mjs';
|
import * as controls from './controls.mjs'; // legacy
|
||||||
export * from './euclid.mjs';
|
export * from './euclid.mjs';
|
||||||
import Fraction from './fraction.mjs';
|
import Fraction from './fraction.mjs';
|
||||||
import { logger } from './logger.mjs';
|
import { logger } from './logger.mjs';
|
||||||
export { Fraction, controls };
|
export { Fraction, controls };
|
||||||
|
export * from './controls.mjs';
|
||||||
export * from './hap.mjs';
|
export * from './hap.mjs';
|
||||||
export * from './pattern.mjs';
|
export * from './pattern.mjs';
|
||||||
export * from './signal.mjs';
|
export * from './signal.mjs';
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
export const logKey = 'strudel.log';
|
export const logKey = 'strudel.log';
|
||||||
|
|
||||||
|
let debounce = 1000,
|
||||||
|
lastMessage,
|
||||||
|
lastTime;
|
||||||
|
|
||||||
export function logger(message, type, data = {}) {
|
export function logger(message, type, data = {}) {
|
||||||
|
let t = performance.now();
|
||||||
|
if (lastMessage === message && t - lastTime < debounce) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastMessage = message;
|
||||||
|
lastTime = t;
|
||||||
console.log(`%c${message}`, 'background-color: black;color:white;border-radius:15px');
|
console.log(`%c${message}`, 'background-color: black;color:white;border-radius:15px');
|
||||||
if (typeof document !== 'undefined' && typeof CustomEvent !== 'undefined') {
|
if (typeof document !== 'undefined' && typeof CustomEvent !== 'undefined') {
|
||||||
document.dispatchEvent(
|
document.dispatchEvent(
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/core",
|
"name": "@strudel/core",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Port of Tidal Cycles to JavaScript",
|
"description": "Port of Tidal Cycles to JavaScript",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
|
|||||||
+123
-123
@@ -26,7 +26,7 @@ export class Pattern {
|
|||||||
/**
|
/**
|
||||||
* Create a pattern. As an end user, you will most likely not create a Pattern directly.
|
* Create a pattern. As an end user, you will most likely not create a Pattern directly.
|
||||||
*
|
*
|
||||||
* @param {function} query - The function that maps a {@link State} to an array of {@link Hap}.
|
* @param {function} query - The function that maps a `State` to an array of `Hap`.
|
||||||
* @noAutocomplete
|
* @noAutocomplete
|
||||||
*/
|
*/
|
||||||
constructor(query) {
|
constructor(query) {
|
||||||
@@ -39,7 +39,7 @@ export class Pattern {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new pattern, with the function applied to the value of
|
* Returns a new pattern, with the function applied to the value of
|
||||||
* each hap. It has the alias {@link Pattern#fmap}.
|
* each hap. It has the alias `fmap`.
|
||||||
* @synonyms fmap
|
* @synonyms fmap
|
||||||
* @param {Function} func to to apply to the value
|
* @param {Function} func to to apply to the value
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
@@ -51,7 +51,7 @@ export class Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* see {@link Pattern#withValue}
|
* see `withValue`
|
||||||
* @noAutocomplete
|
* @noAutocomplete
|
||||||
*/
|
*/
|
||||||
fmap(func) {
|
fmap(func) {
|
||||||
@@ -115,7 +115,7 @@ export class Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As with {@link Pattern#appBoth}, but the `whole` timespan is not the intersection,
|
* As with `appBoth`, but the `whole` timespan is not the intersection,
|
||||||
* but the timespan from the function of patterns that this method is called
|
* but the timespan from the function of patterns that this method is called
|
||||||
* on. In practice, this means that the pattern structure, including onsets,
|
* on. In practice, this means that the pattern structure, including onsets,
|
||||||
* are preserved from the pattern of functions (often referred to as the left
|
* are preserved from the pattern of functions (often referred to as the left
|
||||||
@@ -148,7 +148,7 @@ export class Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As with {@link Pattern#appLeft}, but `whole` timespans are instead taken from the
|
* As with `appLeft`, but `whole` timespans are instead taken from the
|
||||||
* pattern of values, i.e. structure is preserved from the right hand/outer
|
* pattern of values, i.e. structure is preserved from the right hand/outer
|
||||||
* pattern.
|
* pattern.
|
||||||
* @param {Pattern} pat_val
|
* @param {Pattern} pat_val
|
||||||
@@ -340,9 +340,9 @@ export class Pattern {
|
|||||||
* silence
|
* silence
|
||||||
* @noAutocomplete
|
* @noAutocomplete
|
||||||
*/
|
*/
|
||||||
queryArc(begin, end) {
|
queryArc(begin, end, controls = {}) {
|
||||||
try {
|
try {
|
||||||
return this.query(new State(new TimeSpan(begin, end)));
|
return this.query(new State(new TimeSpan(begin, end), controls));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger(`[query]: ${err.message}`, 'error');
|
logger(`[query]: ${err.message}`, 'error');
|
||||||
return [];
|
return [];
|
||||||
@@ -387,7 +387,7 @@ export class Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As with {@link Pattern#withQuerySpan}, but the function is applied to both the
|
* As with `withQuerySpan`, but the function is applied to both the
|
||||||
* begin and end time of the query timespan.
|
* begin and end time of the query timespan.
|
||||||
* @param {Function} func the function to apply
|
* @param {Function} func the function to apply
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
@@ -398,7 +398,7 @@ export class Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to {@link Pattern#withQuerySpan}, but the function is applied to the timespans
|
* Similar to `withQuerySpan`, but the function is applied to the timespans
|
||||||
* of all haps returned by pattern queries (both `part` timespans, and where
|
* of all haps returned by pattern queries (both `part` timespans, and where
|
||||||
* present, `whole` timespans).
|
* present, `whole` timespans).
|
||||||
* @param {Function} func
|
* @param {Function} func
|
||||||
@@ -410,7 +410,7 @@ export class Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As with {@link Pattern#withHapSpan}, but the function is applied to both the
|
* As with `withHapSpan`, but the function is applied to both the
|
||||||
* begin and end time of the hap timespans.
|
* begin and end time of the hap timespans.
|
||||||
* @param {Function} func the function to apply
|
* @param {Function} func the function to apply
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
@@ -427,11 +427,11 @@ export class Pattern {
|
|||||||
* @noAutocomplete
|
* @noAutocomplete
|
||||||
*/
|
*/
|
||||||
withHaps(func) {
|
withHaps(func) {
|
||||||
return new Pattern((state) => func(this.query(state)));
|
return new Pattern((state) => func(this.query(state), state));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As with {@link Pattern#withHaps}, but applies the function to every hap, rather than every list of haps.
|
* As with `withHaps`, but applies the function to every hap, rather than every list of haps.
|
||||||
* @param {Function} func
|
* @param {Function} func
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @noAutocomplete
|
* @noAutocomplete
|
||||||
@@ -499,7 +499,7 @@ export class Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As with {@link Pattern#filterHaps}, but the function is applied to values
|
* As with `filterHaps`, but the function is applied to values
|
||||||
* inside haps.
|
* inside haps.
|
||||||
* @param {Function} value_test
|
* @param {Function} value_test
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
@@ -621,7 +621,7 @@ export class Pattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* More human-readable version of the {@link Pattern#firstCycleValues} accessor.
|
* More human-readable version of the `firstCycleValues` accessor.
|
||||||
* @noAutocomplete
|
* @noAutocomplete
|
||||||
*/
|
*/
|
||||||
get showFirstCycle() {
|
get showFirstCycle() {
|
||||||
@@ -691,13 +691,13 @@ export class Pattern {
|
|||||||
// Methods without corresponding toplevel functions
|
// Methods without corresponding toplevel functions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layers the result of the given function(s). Like {@link Pattern.superimpose}, but without the original pattern:
|
* Layers the result of the given function(s). Like `superimpose`, but without the original pattern:
|
||||||
* @name layer
|
* @name layer
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @synonyms apply
|
* @synonyms apply
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*4"
|
* "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*8"
|
||||||
* .layer(x=>x.add("0,2"))
|
* .layer(x=>x.add("0,2"))
|
||||||
* .scale('C minor').note()
|
* .scale('C minor').note()
|
||||||
*/
|
*/
|
||||||
@@ -711,7 +711,7 @@ export class Pattern {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*4"
|
* "<0 2 4 6 ~ 4 ~ 2 0!3 ~!5>*8"
|
||||||
* .superimpose(x=>x.add(2))
|
* .superimpose(x=>x.add(2))
|
||||||
* .scale('C minor').note()
|
* .scale('C minor').note()
|
||||||
*/
|
*/
|
||||||
@@ -727,8 +727,8 @@ export class Pattern {
|
|||||||
* @name stack
|
* @name stack
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("hh*2").stack(
|
* s("hh*4").stack(
|
||||||
* note("c2(3,8)")
|
* note("c4(5,8)")
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
stack(...pats) {
|
stack(...pats) {
|
||||||
@@ -745,8 +745,8 @@ export class Pattern {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @synonyms sequence, fastcat
|
* @synonyms sequence, fastcat
|
||||||
* @example
|
* @example
|
||||||
* s("hh*2").seq(
|
* s("hh*4").seq(
|
||||||
* note("c2(3,8)")
|
* note("c4(5,8)")
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
seq(...pats) {
|
seq(...pats) {
|
||||||
@@ -759,8 +759,8 @@ export class Pattern {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @synonyms slowcat
|
* @synonyms slowcat
|
||||||
* @example
|
* @example
|
||||||
* s("hh*2").cat(
|
* s("hh*4").cat(
|
||||||
* note("c2(3,8)")
|
* note("c4(5,8)")
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
cat(...pats) {
|
cat(...pats) {
|
||||||
@@ -858,7 +858,7 @@ Pattern.prototype.arpWith = function (func) {
|
|||||||
* Selects indices in in stacked notes.
|
* Selects indices in in stacked notes.
|
||||||
* @example
|
* @example
|
||||||
* note("<[c,eb,g]!2 [c,f,ab] [d,f,ab]>")
|
* note("<[c,eb,g]!2 [c,f,ab] [d,f,ab]>")
|
||||||
* .arp("0 [0,2] 1 [0,2]").slow(2)
|
* .arp("0 [0,2] 1 [0,2]")
|
||||||
* */
|
* */
|
||||||
Pattern.prototype.arp = function (pat) {
|
Pattern.prototype.arp = function (pat) {
|
||||||
return this.arpWith((haps) => pat.fmap((i) => haps[i % haps.length]));
|
return this.arpWith((haps) => pat.fmap((i) => haps[i % haps.length]));
|
||||||
@@ -929,14 +929,14 @@ function _composeOp(a, b, func) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @example
|
* @example
|
||||||
* // Here, the triad 0, 2, 4 is shifted by different amounts
|
* // Here, the triad 0, 2, 4 is shifted by different amounts
|
||||||
* "0 2 4".add("<0 3 4 0>").scale('C major').note()
|
* n("0 2 4".add("<0 3 4 0>")).scale("C:major")
|
||||||
* // Without add, the equivalent would be:
|
* // Without add, the equivalent would be:
|
||||||
* // "<[0 2 4] [3 5 7] [4 6 8] [0 2 4]>".scale('C major').note()
|
* // n("<[0 2 4] [3 5 7] [4 6 8] [0 2 4]>").scale("C:major")
|
||||||
* @example
|
* @example
|
||||||
* // You can also use add with notes:
|
* // You can also use add with notes:
|
||||||
* "c3 e3 g3".add("<0 5 7 0>").note()
|
* note("c3 e3 g3".add("<0 5 7 0>"))
|
||||||
* // Behind the scenes, the notes are converted to midi numbers:
|
* // Behind the scenes, the notes are converted to midi numbers:
|
||||||
* // "48 52 55".add("<0 5 7 0>").note()
|
* // note("48 52 55".add("<0 5 7 0>"))
|
||||||
*/
|
*/
|
||||||
add: [numeralArgs((a, b) => a + b)], // support string concatenation
|
add: [numeralArgs((a, b) => a + b)], // support string concatenation
|
||||||
/**
|
/**
|
||||||
@@ -945,7 +945,7 @@ function _composeOp(a, b, func) {
|
|||||||
* @name sub
|
* @name sub
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @example
|
* @example
|
||||||
* "0 2 4".sub("<0 1 2 3>").scale('C4 minor').note()
|
* n("0 2 4".sub("<0 1 2 3>")).scale("C4:minor")
|
||||||
* // See add for more information.
|
* // See add for more information.
|
||||||
*/
|
*/
|
||||||
sub: [numeralArgs((a, b) => a - b)],
|
sub: [numeralArgs((a, b) => a - b)],
|
||||||
@@ -955,7 +955,7 @@ function _composeOp(a, b, func) {
|
|||||||
* @name mul
|
* @name mul
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @example
|
* @example
|
||||||
* "1 1.5 [1.66, <2 2.33>]".mul(150).freq()
|
* "<1 1.5 [1.66, <2 2.33>]>*4".mul(150).freq()
|
||||||
*/
|
*/
|
||||||
mul: [numeralArgs((a, b) => a * b)],
|
mul: [numeralArgs((a, b) => a * b)],
|
||||||
/**
|
/**
|
||||||
@@ -1049,9 +1049,9 @@ function _composeOp(a, b, func) {
|
|||||||
* Applies the given structure to the pattern:
|
* Applies the given structure to the pattern:
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* note("c3,eb3,g3")
|
* note("c,eb,g")
|
||||||
* .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~")
|
* .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~")
|
||||||
* .slow(4)
|
* .slow(2)
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.struct = function (...args) {
|
Pattern.prototype.struct = function (...args) {
|
||||||
return this.keepif.out(...args);
|
return this.keepif.out(...args);
|
||||||
@@ -1063,7 +1063,7 @@ function _composeOp(a, b, func) {
|
|||||||
* Returns silence when mask is 0 or "~"
|
* Returns silence when mask is 0 or "~"
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* note("c [eb,g] d [eb,g]").mask("<1 [0 1]>").slow(2)
|
* note("c [eb,g] d [eb,g]").mask("<1 [0 1]>")
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.mask = function (...args) {
|
Pattern.prototype.mask = function (...args) {
|
||||||
return this.keepif.in(...args);
|
return this.keepif.in(...args);
|
||||||
@@ -1075,7 +1075,7 @@ function _composeOp(a, b, func) {
|
|||||||
* Resets the pattern to the start of the cycle for each onset of the reset pattern.
|
* Resets the pattern to the start of the cycle for each onset of the reset pattern.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* s("<bd lt> sd, hh*4").reset("<x@3 x(3,8)>")
|
* s("[<bd lt> sd]*2, hh*8").reset("<x@3 x(5,8)>")
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.reset = function (...args) {
|
Pattern.prototype.reset = function (...args) {
|
||||||
return this.keepif.trig(...args);
|
return this.keepif.trig(...args);
|
||||||
@@ -1088,7 +1088,7 @@ function _composeOp(a, b, func) {
|
|||||||
* While reset will only reset the current cycle, restart will start from cycle 0.
|
* While reset will only reset the current cycle, restart will start from cycle 0.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* s("<bd lt> sd, hh*4").restart("<x@3 x(3,8)>")
|
* s("[<bd lt> sd]*2, hh*8").restart("<x@3 x(5,8)>")
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.restart = function (...args) {
|
Pattern.prototype.restart = function (...args) {
|
||||||
return this.keepif.trigzero(...args);
|
return this.keepif.trigzero(...args);
|
||||||
@@ -1178,7 +1178,8 @@ export function reify(thing) {
|
|||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @synonyms polyrhythm, pr
|
* @synonyms polyrhythm, pr
|
||||||
* @example
|
* @example
|
||||||
* stack("g3", "b3", ["e4", "d4"]).note() // "g3,b3,[e4,d4]".note()
|
* stack("g3", "b3", ["e4", "d4"]).note()
|
||||||
|
* // "g3,b3,[e4,d4]".note()
|
||||||
*/
|
*/
|
||||||
export function stack(...pats) {
|
export function stack(...pats) {
|
||||||
// Array test here is to avoid infinite recursions..
|
// Array test here is to avoid infinite recursions..
|
||||||
@@ -1189,7 +1190,7 @@ export function stack(...pats) {
|
|||||||
|
|
||||||
/** Concatenation: combines a list of patterns, switching between them successively, one per cycle:
|
/** Concatenation: combines a list of patterns, switching between them successively, one per cycle:
|
||||||
*
|
*
|
||||||
* synonyms: {@link cat}
|
* synonyms: `cat`
|
||||||
*
|
*
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
@@ -1237,17 +1238,19 @@ export function slowcatPrime(...pats) {
|
|||||||
* @synonyms slowcat
|
* @synonyms slowcat
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* cat("e5", "b4", ["d5", "c5"]).note() // "<e5 b4 [d5 c5]>".note()
|
* cat("e5", "b4", ["d5", "c5"]).note()
|
||||||
|
* // "<e5 b4 [d5 c5]>".note()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export function cat(...pats) {
|
export function cat(...pats) {
|
||||||
return slowcat(...pats);
|
return slowcat(...pats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Like {@link Pattern.seq}, but each step has a length, relative to the whole.
|
/** Like `seq`, but each step has a length, relative to the whole.
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* timeCat([3,"e3"],[1, "g3"]).note() // "e3@3 g3".note()
|
* timeCat([3,"e3"],[1, "g3"]).note()
|
||||||
|
* // "e3@3 g3".note()
|
||||||
*/
|
*/
|
||||||
export function timeCat(...timepats) {
|
export function timeCat(...timepats) {
|
||||||
const total = timepats.map((a) => a[0]).reduce((a, b) => a.add(b), Fraction(0));
|
const total = timepats.map((a) => a[0]).reduce((a, b) => a.add(b), Fraction(0));
|
||||||
@@ -1267,7 +1270,10 @@ export function timeCat(...timepats) {
|
|||||||
*
|
*
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* arrange([4, "<c a f e>(3,8)"],[2, "<g a>(5,8)"]).note()
|
* arrange(
|
||||||
|
* [4, "<c a f e>(3,8)"],
|
||||||
|
* [2, "<g a>(5,8)"]
|
||||||
|
* ).note()
|
||||||
*/
|
*/
|
||||||
export function arrange(...sections) {
|
export function arrange(...sections) {
|
||||||
const total = sections.reduce((sum, [cycles]) => sum + cycles, 0);
|
const total = sections.reduce((sum, [cycles]) => sum + cycles, 0);
|
||||||
@@ -1279,7 +1285,7 @@ export function fastcat(...pats) {
|
|||||||
return slowcat(...pats)._fast(pats.length);
|
return slowcat(...pats)._fast(pats.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** See {@link fastcat} */
|
/** See `fastcat` */
|
||||||
export function sequence(...pats) {
|
export function sequence(...pats) {
|
||||||
return fastcat(...pats);
|
return fastcat(...pats);
|
||||||
}
|
}
|
||||||
@@ -1287,7 +1293,8 @@ export function sequence(...pats) {
|
|||||||
/** Like **cat**, but the items are crammed into one cycle.
|
/** Like **cat**, but the items are crammed into one cycle.
|
||||||
* @synonyms fastcat, sequence
|
* @synonyms fastcat, sequence
|
||||||
* @example
|
* @example
|
||||||
* seq("e5", "b4", ["d5", "c5"]).note() // "e5 b4 [d5 c5]".note()
|
* seq("e5", "b4", ["d5", "c5"]).note()
|
||||||
|
* // "e5 b4 [d5 c5]".note()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export function seq(...pats) {
|
export function seq(...pats) {
|
||||||
@@ -1313,9 +1320,9 @@ function _sequenceCount(x) {
|
|||||||
* @param {number} steps how many items are placed in one cycle
|
* @param {number} steps how many items are placed in one cycle
|
||||||
* @param {any[]} sequences one or more arrays of Patterns / values
|
* @param {any[]} sequences one or more arrays of Patterns / values
|
||||||
* @example
|
* @example
|
||||||
* polymeterSteps(2, ["c", "d", "e", "f", "g", "f", "e", "d"])
|
* polymeterSteps(4, ["c", "d", "e"])
|
||||||
* .note().stack(s("bd")) // 1 cycle = 1 bd = 2 notes
|
* .note().stack(s("bd"))
|
||||||
* // note("{c d e f g f e d}%2").stack(s("bd"))
|
* // note("{c d e}%4").stack(s("bd"))
|
||||||
*/
|
*/
|
||||||
export function polymeterSteps(steps, ...args) {
|
export function polymeterSteps(steps, ...args) {
|
||||||
const seqs = args.map((a) => _sequenceCount(a));
|
const seqs = args.map((a) => _sequenceCount(a));
|
||||||
@@ -1463,7 +1470,7 @@ export function register(name, func, patternify = true) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "0.5 1.5 2.5".round().scale('C major').note()
|
* n("0.5 1.5 2.5".round()).scale("C:major")
|
||||||
*/
|
*/
|
||||||
export const round = register('round', function (pat) {
|
export const round = register('round', function (pat) {
|
||||||
return pat.asNumber().fmap((v) => Math.round(v));
|
return pat.asNumber().fmap((v) => Math.round(v));
|
||||||
@@ -1477,7 +1484,7 @@ export const round = register('round', function (pat) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "42 42.1 42.5 43".floor().note()
|
* note("42 42.1 42.5 43".floor())
|
||||||
*/
|
*/
|
||||||
export const floor = register('floor', function (pat) {
|
export const floor = register('floor', function (pat) {
|
||||||
return pat.asNumber().fmap((v) => Math.floor(v));
|
return pat.asNumber().fmap((v) => Math.floor(v));
|
||||||
@@ -1491,7 +1498,7 @@ export const floor = register('floor', function (pat) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "42 42.1 42.5 43".ceil().note()
|
* note("42 42.1 42.5 43".ceil())
|
||||||
*/
|
*/
|
||||||
export const ceil = register('ceil', function (pat) {
|
export const ceil = register('ceil', function (pat) {
|
||||||
return pat.asNumber().fmap((v) => Math.ceil(v));
|
return pat.asNumber().fmap((v) => Math.ceil(v));
|
||||||
@@ -1524,7 +1531,8 @@ export const fromBipolar = register('fromBipolar', function (pat) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd,hh*4").cutoff(sine.range(500,2000).slow(4))
|
* s("[bd sd]*2,hh*8")
|
||||||
|
* .cutoff(sine.range(500,4000))
|
||||||
*/
|
*/
|
||||||
export const range = register('range', function (min, max, pat) {
|
export const range = register('range', function (min, max, pat) {
|
||||||
return pat.mul(max - min).add(min);
|
return pat.mul(max - min).add(min);
|
||||||
@@ -1538,7 +1546,8 @@ export const range = register('range', function (min, max, pat) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd,hh*4").cutoff(sine.rangex(500,2000).slow(4))
|
* s("[bd sd]*2,hh*8")
|
||||||
|
* .cutoff(sine.rangex(500,4000))
|
||||||
*/
|
*/
|
||||||
export const rangex = register('rangex', function (min, max, pat) {
|
export const rangex = register('rangex', function (min, max, pat) {
|
||||||
return pat._range(Math.log(min), Math.log(max)).fmap(Math.exp);
|
return pat._range(Math.log(min), Math.log(max)).fmap(Math.exp);
|
||||||
@@ -1551,7 +1560,8 @@ export const rangex = register('rangex', function (min, max, pat) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("bd sd,hh*4").cutoff(sine2.range2(500,2000).slow(4))
|
* s("[bd sd]*2,hh*8")
|
||||||
|
* .cutoff(sine2.range2(500,4000))
|
||||||
*/
|
*/
|
||||||
export const range2 = register('range2', function (min, max, pat) {
|
export const range2 = register('range2', function (min, max, pat) {
|
||||||
return pat.fromBipolar()._range(min, max);
|
return pat.fromBipolar()._range(min, max);
|
||||||
@@ -1564,7 +1574,8 @@ export const range2 = register('range2', function (min, max, pat) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* ratio("1, 5:4, 3:2").mul(110).freq().s("piano").slow(2)
|
* ratio("1, 5:4, 3:2").mul(110)
|
||||||
|
* .freq().s("piano")
|
||||||
*/
|
*/
|
||||||
export const ratio = register('ratio', (pat) =>
|
export const ratio = register('ratio', (pat) =>
|
||||||
pat.fmap((v) => {
|
pat.fmap((v) => {
|
||||||
@@ -1636,7 +1647,7 @@ export const { fastGap, fastgap } = register(['fastGap', 'fastgap'], function (f
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to compress, but doesn't leave gaps, and the 'focus' can be bigger than a cycle
|
* Similar to `compress`, but doesn't leave gaps, and the 'focus' can be bigger than a cycle
|
||||||
* @example
|
* @example
|
||||||
* s("bd hh sd hh").focus(1/4, 3/4)
|
* s("bd hh sd hh").focus(1/4, 3/4)
|
||||||
*/
|
*/
|
||||||
@@ -1667,7 +1678,7 @@ export const ply = register('ply', function (factor, pat) {
|
|||||||
* @param {number | Pattern} factor speed up factor
|
* @param {number | Pattern} factor speed up factor
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("<bd sd> hh").fast(2) // s("[<bd sd> hh]*2")
|
* s("bd hh sd hh").fast(2) // s("[bd hh 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) {
|
if (factor === 0) {
|
||||||
@@ -1696,7 +1707,7 @@ export const hurry = register('hurry', function (r, pat) {
|
|||||||
* @param {number | Pattern} factor slow down factor
|
* @param {number | Pattern} factor slow down factor
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("<bd sd> hh").slow(2) // s("[<bd sd> hh]/2")
|
* s("bd hh sd hh").slow(2) // s("[bd hh 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) {
|
if (factor === 0) {
|
||||||
@@ -1753,7 +1764,7 @@ export const lastOf = register('lastOf', function (n, func, pat) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An alias for {@link firstOf}
|
* An alias for `firstOf`
|
||||||
* @name every
|
* @name every
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @param {number} n how many cycles
|
* @param {number} n how many cycles
|
||||||
@@ -1785,9 +1796,9 @@ export const apply = register('apply', function (func, pat) {
|
|||||||
* @example
|
* @example
|
||||||
* s("<bd sd>,hh*2").cpm(90) // = 90 bpm
|
* s("<bd sd>,hh*2").cpm(90) // = 90 bpm
|
||||||
*/
|
*/
|
||||||
// TODO - global clock
|
// this is redefined in repl.mjs, using the current cps as divisor
|
||||||
export const cpm = register('cpm', function (cpm, pat) {
|
export const cpm = register('cpm', function (cpm, pat) {
|
||||||
return pat._fast(cpm / 60);
|
return pat._fast(cpm / 60 / 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1860,7 +1871,7 @@ export const linger = register('linger', function (t, pat) {
|
|||||||
* Samples the pattern at a rate of n events per cycle. Useful for turning a continuous pattern into a discrete one.
|
* Samples the pattern at a rate of n events per cycle. Useful for turning a continuous pattern into a discrete one.
|
||||||
* @param {number} segments number of segments per cycle
|
* @param {number} segments number of segments per cycle
|
||||||
* @example
|
* @example
|
||||||
* note(saw.range(0,12).segment(24)).add(40)
|
* note(saw.range(40,52).segment(24))
|
||||||
*/
|
*/
|
||||||
export const segment = register('segment', function (rate, pat) {
|
export const segment = register('segment', function (rate, pat) {
|
||||||
return pat.struct(pure(true)._fast(rate));
|
return pat.struct(pure(true)._fast(rate));
|
||||||
@@ -1886,7 +1897,7 @@ export const { invert, inv } = register(['invert', 'inv'], function (pat) {
|
|||||||
* @param {function} func
|
* @param {function} func
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "c3 eb3 g3".when("<0 1>/2", x=>x.sub(5)).note()
|
* "c3 eb3 g3".when("<0 1>/2", x=>x.sub("5")).note()
|
||||||
*/
|
*/
|
||||||
export const when = register('when', function (on, func, pat) {
|
export const when = register('when', function (on, func, pat) {
|
||||||
return on ? func(pat) : pat;
|
return on ? func(pat) : pat;
|
||||||
@@ -1923,7 +1934,7 @@ export const brak = register('brak', function (pat) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* note("c3 d3 e3 g3").rev()
|
* note("c d e g").rev()
|
||||||
*/
|
*/
|
||||||
export const rev = register('rev', function (pat) {
|
export const rev = register('rev', function (pat) {
|
||||||
const query = function (state) {
|
const query = function (state) {
|
||||||
@@ -1993,7 +2004,7 @@ export const palindrome = register('palindrome', function (pat) {
|
|||||||
* @name juxBy
|
* @name juxBy
|
||||||
* @synonyms juxby
|
* @synonyms juxby
|
||||||
* @example
|
* @example
|
||||||
* s("lt ht mt ht hh").juxBy("<0 .5 1>/2", rev)
|
* s("bd lt [~ ht] mt cp ~ bd hh").juxBy("<0 .5 1>/2", rev)
|
||||||
*/
|
*/
|
||||||
export const { juxBy, juxby } = register(['juxBy', 'juxby'], function (by, func, pat) {
|
export const { juxBy, juxby } = register(['juxBy', 'juxby'], function (by, func, pat) {
|
||||||
by /= 2;
|
by /= 2;
|
||||||
@@ -2012,7 +2023,11 @@ export const { juxBy, juxby } = register(['juxBy', 'juxby'], function (by, func,
|
|||||||
/**
|
/**
|
||||||
* The jux function creates strange stereo effects, by applying a function to a pattern, but only in the right-hand channel.
|
* The jux function creates strange stereo effects, by applying a function to a pattern, but only in the right-hand channel.
|
||||||
* @example
|
* @example
|
||||||
* s("lt ht mt ht hh").jux(rev)
|
* s("bd lt [~ ht] mt cp ~ bd hh").jux(rev)
|
||||||
|
* @example
|
||||||
|
* s("bd lt [~ ht] mt cp ~ bd hh").jux(press)
|
||||||
|
* @example
|
||||||
|
* s("bd lt [~ ht] mt cp ~ bd hh").jux(iter(4))
|
||||||
*/
|
*/
|
||||||
export const jux = register('jux', function (func, pat) {
|
export const jux = register('jux', function (func, pat) {
|
||||||
return pat._juxBy(1, func, pat);
|
return pat._juxBy(1, func, pat);
|
||||||
@@ -2028,7 +2043,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().clip(.2)
|
* .scale("C:minor").note()
|
||||||
*/
|
*/
|
||||||
export const { echoWith, echowith, stutWith, stutwith } = register(
|
export const { echoWith, echowith, stutWith, stutwith } = register(
|
||||||
['echoWith', 'echowith', 'stutWith', 'stutwith'],
|
['echoWith', 'echowith', 'stutWith', 'stutwith'],
|
||||||
@@ -2121,7 +2136,8 @@ const { repeatCycles } = register('repeatCycles', _repeatCycles);
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "0 1 2 3".chunk(4, x=>x.add(7)).scale('A minor').note()
|
* "0 1 2 3".chunk(4, x=>x.add(7))
|
||||||
|
* .scale("A:minor").note()
|
||||||
*/
|
*/
|
||||||
const _chunk = function (n, func, pat, back = false, fast = false) {
|
const _chunk = function (n, func, pat, back = false, fast = false) {
|
||||||
const binary = Array(n - 1).fill(false);
|
const binary = Array(n - 1).fill(false);
|
||||||
@@ -2146,7 +2162,8 @@ const { chunk, slowchunk, slowChunk } = register(['chunk', 'slowchunk', 'slowChu
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "0 1 2 3".chunkBack(4, x=>x.add(7)).scale('A minor').note()
|
* "0 1 2 3".chunkBack(4, x=>x.add(7))
|
||||||
|
* .scale("A:minor").note()
|
||||||
*/
|
*/
|
||||||
export const { chunkBack, chunkback } = register(['chunkBack', 'chunkback'], function (n, func, pat) {
|
export const { chunkBack, chunkback } = register(['chunkBack', 'chunkback'], function (n, func, pat) {
|
||||||
return _chunk(n, func, pat, true);
|
return _chunk(n, func, pat, true);
|
||||||
@@ -2160,10 +2177,11 @@ export const { chunkBack, chunkback } = register(['chunkBack', 'chunkback'], fun
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* "<0 8> 1 2 3 4 5 6 7".fastChunk(4, x => x.color('red')).slow(4).scale("C2:major").note()
|
* "<0 8> 1 2 3 4 5 6 7"
|
||||||
.s("folkharp")
|
* .fastChunk(4, x => x.color('red')).slow(2)
|
||||||
|
* .scale("C2:major").note()
|
||||||
*/
|
*/
|
||||||
const { fastchunk, fastChunk } = register(['fastchunk', 'fastChunk'], function (n, func, pat) {
|
export const { fastchunk, fastChunk } = register(['fastchunk', 'fastChunk'], function (n, func, pat) {
|
||||||
return _chunk(n, func, pat, false, true);
|
return _chunk(n, func, pat, false, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2178,17 +2196,13 @@ export const bypass = register('bypass', function (on, pat) {
|
|||||||
* @param {number} offset start point of loop in cycles
|
* @param {number} offset start point of loop in cycles
|
||||||
* @param {number} cycles loop length in cycles
|
* @param {number} cycles loop length in cycles
|
||||||
* @example
|
* @example
|
||||||
|
* note("<c d e f>").ribbon(1, 2).fast(2)
|
||||||
|
* @example
|
||||||
* // Looping a portion of randomness
|
* // Looping a portion of randomness
|
||||||
* note(irand(8).segment(4).scale('C3 minor')).ribbon(1337, 2)
|
* note(irand(8).segment(4).scale('C3 minor')).ribbon(1337, 2)
|
||||||
*/
|
*/
|
||||||
export const ribbon = register('ribbon', (offset, cycles, pat) => pat.early(offset).restart(pure(1).slow(cycles)));
|
export const ribbon = register('ribbon', (offset, cycles, pat) => pat.early(offset).restart(pure(1).slow(cycles)));
|
||||||
|
|
||||||
// sets absolute duration of haps
|
|
||||||
// TODO - fix
|
|
||||||
export const duration = register('duration', function (value, pat) {
|
|
||||||
return pat.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(value)));
|
|
||||||
});
|
|
||||||
|
|
||||||
export const hsla = register('hsla', (h, s, l, a, pat) => {
|
export const hsla = register('hsla', (h, s, l, a, pat) => {
|
||||||
return pat.color(`hsla(${h}turn,${s * 100}%,${l * 100}%,${a})`);
|
return pat.color(`hsla(${h}turn,${s * 100}%,${l * 100}%,${a})`);
|
||||||
});
|
});
|
||||||
@@ -2221,21 +2235,6 @@ export const velocity = register('velocity', function (velocity, pat) {
|
|||||||
return pat.withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity }));
|
return pat.withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity }));
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* @memberof Pattern
|
|
||||||
* @example
|
|
||||||
* note("c3 eb3 g3 c4").legato("<.25 .5 1 2>")
|
|
||||||
*/
|
|
||||||
// TODO - fix
|
|
||||||
export const legato = register('legato', function (value, pat) {
|
|
||||||
value = Fraction(value);
|
|
||||||
return pat.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value))));
|
|
||||||
});
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Control-related functions, i.e. ones that manipulate patterns of
|
// Control-related functions, i.e. ones that manipulate patterns of
|
||||||
// objects
|
// objects
|
||||||
@@ -2251,7 +2250,7 @@ export const legato = register('legato', function (value, pat) {
|
|||||||
* s("rhodes")
|
* s("rhodes")
|
||||||
* .chop(4)
|
* .chop(4)
|
||||||
* .rev() // reverse order of chops
|
* .rev() // reverse order of chops
|
||||||
* .loopAt(4) // fit sample into 4 cycles
|
* .loopAt(2) // fit sample into 2 cycles
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const chop = register('chop', function (n, pat) {
|
export const chop = register('chop', function (n, pat) {
|
||||||
@@ -2269,7 +2268,7 @@ export const chop = register('chop', function (n, pat) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("numbers:0 numbers:1 numbers:2").striate(6).slow(6)
|
* s("numbers:0 numbers:1 numbers:2").striate(6).slow(3)
|
||||||
*/
|
*/
|
||||||
export const striate = register('striate', function (n, pat) {
|
export const striate = register('striate', function (n, pat) {
|
||||||
const slices = Array.from({ length: n }, (x, i) => i);
|
const slices = Array.from({ length: n }, (x, i) => i);
|
||||||
@@ -2285,10 +2284,10 @@ export const striate = register('striate', function (n, pat) {
|
|||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' })
|
* samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' })
|
||||||
* s("rhodes").loopAt(4)
|
* s("rhodes").loopAt(2)
|
||||||
*/
|
*/
|
||||||
// TODO - global cps clock
|
// TODO - global cps clock
|
||||||
const _loopAt = function (factor, pat, cps = 1) {
|
const _loopAt = function (factor, pat, cps = 0.5) {
|
||||||
return pat
|
return pat
|
||||||
.speed((1 / factor) * cps)
|
.speed((1 / factor) * cps)
|
||||||
.unit('c')
|
.unit('c')
|
||||||
@@ -2302,11 +2301,11 @@ const _loopAt = function (factor, pat, cps = 1) {
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* await samples('github:tidalcycles/Dirt-Samples/master')
|
* samples('github:tidalcycles/dirt-samples')
|
||||||
* 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(0.75)
|
||||||
* @example
|
* @example
|
||||||
* await samples('github:tidalcycles/Dirt-Samples/master')
|
* samples('github:tidalcycles/dirt-samples')
|
||||||
* s("breaks125/2").fit().slice([0,.25,.5,.75], "0 1 1 <2 3>")
|
* s("breaks125").fit().slice([0,.25,.5,.75], "0 1 1 <2 3>")
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const slice = register(
|
export const slice = register(
|
||||||
@@ -2331,53 +2330,54 @@ export const slice = register(
|
|||||||
* Works the same as slice, but changes the playback speed of each slice to match the duration of its step.
|
* Works the same as slice, but changes the playback speed of each slice to match the duration of its step.
|
||||||
* @name splice
|
* @name splice
|
||||||
* @example
|
* @example
|
||||||
* await samples('github:tidalcycles/Dirt-Samples/master')
|
* samples('github:tidalcycles/dirt-samples')
|
||||||
* s("breaks165")
|
* s("breaks165")
|
||||||
* .splice(8, "0 1 [2 3 0]@2 3 0@2 7")
|
* .splice(8, "0 1 [2 3 0]@2 3 0@2 7")
|
||||||
* .hurry(0.65)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export 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);
|
||||||
return sliced.withHap(function (hap) {
|
return new Pattern((state) => {
|
||||||
return hap.withValue((v) => ({
|
// TODO - default cps to 0.5
|
||||||
...{
|
const cps = state.controls._cps || 1;
|
||||||
speed: (1 / v._slices / hap.whole.duration) * (v.speed || 1),
|
const haps = sliced.query(state);
|
||||||
unit: 'c',
|
return haps.map((hap) =>
|
||||||
},
|
hap.withValue((v) => ({
|
||||||
...v,
|
...{
|
||||||
}));
|
speed: (cps / v._slices / hap.whole.duration) * (v.speed || 1),
|
||||||
|
unit: 'c',
|
||||||
|
},
|
||||||
|
...v,
|
||||||
|
})),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
false, // turns off auto-patternification
|
false, // turns off auto-patternification
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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) {
|
export const { loopAt, loopat } = register(['loopAt', 'loopat'], function (factor, pat) {
|
||||||
return _loopAt(factor, pat, 1);
|
return new Pattern((state) => _loopAt(factor, pat, state.controls._cps).query(state));
|
||||||
});
|
});
|
||||||
|
|
||||||
// the fit 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
|
|
||||||
/**
|
/**
|
||||||
* Makes the sample fit its event duration. Good for rhythmical loops like drum breaks.
|
* Makes the sample fit its event duration. Good for rhythmical loops like drum breaks.
|
||||||
* Similar to loopAt.
|
* Similar to `loopAt`.
|
||||||
* @name fit
|
* @name fit
|
||||||
* @example
|
* @example
|
||||||
* samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' })
|
* samples({ rhodes: 'https://cdn.freesound.org/previews/132/132051_316502-lq.mp3' })
|
||||||
* s("rhodes/4").fit()
|
* s("rhodes/2").fit()
|
||||||
*/
|
*/
|
||||||
export const fit = register('fit', (pat) =>
|
export const fit = register('fit', (pat) =>
|
||||||
pat.withHap((hap) =>
|
pat.withHaps((haps, state) =>
|
||||||
hap.withValue((v) => ({
|
haps.map((hap) =>
|
||||||
...v,
|
hap.withValue((v) => ({
|
||||||
speed: 1 / hap.whole.duration,
|
...v,
|
||||||
unit: 'c',
|
speed: (state.controls._cps || 1) / hap.whole.duration,
|
||||||
})),
|
unit: 'c',
|
||||||
|
})),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -160,8 +160,13 @@ export function pianoroll({
|
|||||||
maxMidi = max;
|
maxMidi = max;
|
||||||
valueExtent = maxMidi - minMidi + 1;
|
valueExtent = maxMidi - minMidi + 1;
|
||||||
}
|
}
|
||||||
// foldValues = values.sort((a, b) => a - b);
|
foldValues = values.sort((a, b) =>
|
||||||
foldValues = values.sort((a, b) => String(a).localeCompare(String(b)));
|
typeof a === 'number' && typeof b === 'number'
|
||||||
|
? a - b
|
||||||
|
: typeof a === 'number'
|
||||||
|
? 1
|
||||||
|
: String(a).localeCompare(String(b)),
|
||||||
|
);
|
||||||
barThickness = fold ? valueAxis / foldValues.length : valueAxis / valueExtent;
|
barThickness = fold ? valueAxis / foldValues.length : valueAxis / valueExtent;
|
||||||
ctx.fillStyle = background;
|
ctx.fillStyle = background;
|
||||||
ctx.globalAlpha = 1; // reset!
|
ctx.globalAlpha = 1; // reset!
|
||||||
|
|||||||
+55
-63
@@ -61,12 +61,67 @@ export function repl({
|
|||||||
scheduler.setPattern(pattern, autostart);
|
scheduler.setPattern(pattern, autostart);
|
||||||
};
|
};
|
||||||
setTime(() => scheduler.now()); // TODO: refactor?
|
setTime(() => scheduler.now()); // TODO: refactor?
|
||||||
|
|
||||||
|
const stop = () => scheduler.stop();
|
||||||
|
const start = () => scheduler.start();
|
||||||
|
const pause = () => scheduler.pause();
|
||||||
|
const toggle = () => scheduler.toggle();
|
||||||
|
const setCps = (cps) => scheduler.setCps(cps);
|
||||||
|
const setCpm = (cpm) => scheduler.setCps(cpm / 60);
|
||||||
|
const all = function (transform) {
|
||||||
|
allTransform = transform;
|
||||||
|
return silence;
|
||||||
|
};
|
||||||
|
|
||||||
|
// set pattern methods that use this repl via closure
|
||||||
|
const injectPatternMethods = () => {
|
||||||
|
Pattern.prototype.p = function (id) {
|
||||||
|
pPatterns[id] = this;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
Pattern.prototype.q = function (id) {
|
||||||
|
return silence;
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
for (let i = 1; i < 10; ++i) {
|
||||||
|
Object.defineProperty(Pattern.prototype, `d${i}`, {
|
||||||
|
get() {
|
||||||
|
return this.p(i);
|
||||||
|
},
|
||||||
|
configurable: true,
|
||||||
|
});
|
||||||
|
Object.defineProperty(Pattern.prototype, `p${i}`, {
|
||||||
|
get() {
|
||||||
|
return this.p(i);
|
||||||
|
},
|
||||||
|
configurable: true,
|
||||||
|
});
|
||||||
|
Pattern.prototype[`q${i}`] = silence;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('injectPatternMethods: error:', err);
|
||||||
|
}
|
||||||
|
const cpm = register('cpm', function (cpm, pat) {
|
||||||
|
return pat._fast(cpm / 60 / scheduler.cps);
|
||||||
|
});
|
||||||
|
evalScope({
|
||||||
|
all,
|
||||||
|
hush,
|
||||||
|
cpm,
|
||||||
|
setCps,
|
||||||
|
setcps: setCps,
|
||||||
|
setCpm,
|
||||||
|
setcpm: setCpm,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const evaluate = async (code, autostart = true, shouldHush = true) => {
|
const evaluate = async (code, autostart = true, shouldHush = true) => {
|
||||||
if (!code) {
|
if (!code) {
|
||||||
throw new Error('no code to evaluate');
|
throw new Error('no code to evaluate');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
updateState({ code, pending: true });
|
updateState({ code, pending: true });
|
||||||
|
injectPatternMethods();
|
||||||
await beforeEval?.({ code });
|
await beforeEval?.({ code });
|
||||||
shouldHush && hush();
|
shouldHush && hush();
|
||||||
let { pattern, meta } = await _evaluate(code, transpiler);
|
let { pattern, meta } = await _evaluate(code, transpiler);
|
||||||
@@ -94,74 +149,11 @@ export function repl({
|
|||||||
afterEval?.({ code, pattern, meta });
|
afterEval?.({ code, pattern, meta });
|
||||||
return pattern;
|
return pattern;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// console.warn(`[repl] eval error: ${err.message}`);
|
|
||||||
logger(`[eval] error: ${err.message}`, 'error');
|
logger(`[eval] error: ${err.message}`, 'error');
|
||||||
updateState({ evalError: err, pending: false });
|
updateState({ evalError: err, pending: false });
|
||||||
onEvalError?.(err);
|
onEvalError?.(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const stop = () => scheduler.stop();
|
|
||||||
const start = () => scheduler.start();
|
|
||||||
const pause = () => scheduler.pause();
|
|
||||||
const toggle = () => scheduler.toggle();
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
Pattern.prototype.p = function (id) {
|
|
||||||
pPatterns[id] = this;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
Pattern.prototype.q = function (id) {
|
|
||||||
return silence;
|
|
||||||
};
|
|
||||||
|
|
||||||
const all = function (transform) {
|
|
||||||
allTransform = transform;
|
|
||||||
return silence;
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
for (let i = 1; i < 10; ++i) {
|
|
||||||
Object.defineProperty(Pattern.prototype, `d${i}`, {
|
|
||||||
get() {
|
|
||||||
return this.p(i);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Object.defineProperty(Pattern.prototype, `p${i}`, {
|
|
||||||
get() {
|
|
||||||
return this.p(i);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Pattern.prototype[`q${i}`] = silence;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// already defined..
|
|
||||||
}
|
|
||||||
|
|
||||||
const fit = register('fit', (pat) =>
|
|
||||||
pat.withHap((hap) =>
|
|
||||||
hap.withValue((v) => ({
|
|
||||||
...v,
|
|
||||||
speed: scheduler.cps / hap.whole.duration, // overwrite speed completely?
|
|
||||||
unit: 'c',
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
evalScope({
|
|
||||||
loopAt,
|
|
||||||
fit,
|
|
||||||
all,
|
|
||||||
hush,
|
|
||||||
setCps,
|
|
||||||
setcps: setCps,
|
|
||||||
setCpm,
|
|
||||||
setcpm: setCpm,
|
|
||||||
});
|
|
||||||
const setCode = (code) => updateState({ code });
|
const setCode = (code) => updateState({ code });
|
||||||
return { scheduler, evaluate, start, stop, pause, setCps, setPattern, setCode, toggle, state };
|
return { scheduler, evaluate, start, stop, pause, setCps, setPattern, setCode, toggle, state };
|
||||||
}
|
}
|
||||||
|
|||||||
+192
-36
@@ -7,7 +7,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
import { Hap } from './hap.mjs';
|
import { Hap } from './hap.mjs';
|
||||||
import { Pattern, fastcat, reify, silence, stack, register } from './pattern.mjs';
|
import { Pattern, fastcat, reify, silence, stack, register } from './pattern.mjs';
|
||||||
import Fraction from './fraction.mjs';
|
import Fraction from './fraction.mjs';
|
||||||
import { id, _mod, clamp } from './util.mjs';
|
import { id, _mod, clamp, objectMap } from './util.mjs';
|
||||||
|
|
||||||
export function steady(value) {
|
export function steady(value) {
|
||||||
// A continuous value
|
// A continuous value
|
||||||
@@ -27,9 +27,11 @@ export const isaw2 = isaw.toBipolar();
|
|||||||
*
|
*
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* "c3 [eb3,g3] g2 [g3,bb3]".note().clip(saw.slow(4))
|
* note("<c3 [eb3,g3] g2 [g3,bb3]>*8")
|
||||||
|
* .clip(saw.slow(2))
|
||||||
* @example
|
* @example
|
||||||
* saw.range(0,8).segment(8).scale('C major').slow(4).note()
|
* n(saw.range(0,8).segment(8))
|
||||||
|
* .scale('C major')
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const saw = signal((t) => t % 1);
|
export const saw = signal((t) => t % 1);
|
||||||
@@ -42,7 +44,8 @@ export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
|
|||||||
*
|
*
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* sine.segment(16).range(0,15).slow(2).scale('C minor').note()
|
* n(sine.segment(16).range(0,15))
|
||||||
|
* .scale("C:minor")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const sine = sine2.fromBipolar();
|
export const sine = sine2.fromBipolar();
|
||||||
@@ -52,7 +55,8 @@ export const sine = sine2.fromBipolar();
|
|||||||
*
|
*
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* stack(sine,cosine).segment(16).range(0,15).slow(2).scale('C minor').note()
|
* n(stack(sine,cosine).segment(16).range(0,15))
|
||||||
|
* .scale("C:minor")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const cosine = sine._early(Fraction(1).div(4));
|
export const cosine = sine._early(Fraction(1).div(4));
|
||||||
@@ -63,7 +67,7 @@ export const cosine2 = sine2._early(Fraction(1).div(4));
|
|||||||
*
|
*
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* square.segment(2).range(0,7).scale('C minor').note()
|
* n(square.segment(4).range(0,7)).scale("C:minor")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const square = signal((t) => Math.floor((t * 2) % 2));
|
export const square = signal((t) => Math.floor((t * 2) % 2));
|
||||||
@@ -74,7 +78,7 @@ export const square2 = square.toBipolar();
|
|||||||
*
|
*
|
||||||
* @return {Pattern}
|
* @return {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* tri.segment(8).range(0,7).scale('C minor').note()
|
* n(tri.segment(8).range(0,7)).scale("C:minor")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const tri = fastcat(isaw, saw);
|
export const tri = fastcat(isaw, saw);
|
||||||
@@ -118,8 +122,8 @@ const timeToRands = (t, n) => timeToRandsPrime(timeToIntSeed(t), n);
|
|||||||
/**
|
/**
|
||||||
* A discrete pattern of numbers from 0 to n-1
|
* A discrete pattern of numbers from 0 to n-1
|
||||||
* @example
|
* @example
|
||||||
* run(4).scale('C4 major').note()
|
* n(run(4)).scale("C4:pentatonic")
|
||||||
* // "0 1 2 3".scale('C4 major').note()
|
* // n("0 1 2 3").scale("C4:pentatonic")
|
||||||
*/
|
*/
|
||||||
export const run = (n) => saw.range(0, n).floor().segment(n);
|
export const run = (n) => saw.range(0, n).floor().segment(n);
|
||||||
|
|
||||||
@@ -129,7 +133,7 @@ export const run = (n) => saw.range(0, n).floor().segment(n);
|
|||||||
* @name rand
|
* @name rand
|
||||||
* @example
|
* @example
|
||||||
* // randomly change the cutoff
|
* // randomly change the cutoff
|
||||||
* s("bd sd,hh*4").cutoff(rand.range(500,2000))
|
* s("bd*4,hh*8").cutoff(rand.range(500,8000))
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const rand = signal(timeToRand);
|
export const rand = signal(timeToRand);
|
||||||
@@ -151,36 +155,188 @@ export const _irand = (i) => rand.fmap((x) => Math.trunc(x * i));
|
|||||||
* @param {number} n max value (exclusive)
|
* @param {number} n max value (exclusive)
|
||||||
* @example
|
* @example
|
||||||
* // randomly select scale notes from 0 - 7 (= C to C)
|
* // randomly select scale notes from 0 - 7 (= C to C)
|
||||||
* irand(8).struct("x(3,8)").scale('C minor').note()
|
* n(irand(8)).struct("x x*2 x x*3").scale("C:minor")
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const irand = (ipat) => reify(ipat).fmap(_irand).innerJoin();
|
export const irand = (ipat) => reify(ipat).fmap(_irand).innerJoin();
|
||||||
|
|
||||||
/**
|
const _pick = function (lookup, pat, modulo = true) {
|
||||||
* pick from the list of values (or patterns of values) via the index using the given
|
const array = Array.isArray(lookup);
|
||||||
* pattern of integers
|
const len = Object.keys(lookup).length;
|
||||||
|
|
||||||
|
lookup = objectMap(lookup, reify);
|
||||||
|
|
||||||
|
if (len === 0) {
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
|
return pat.fmap((i) => {
|
||||||
|
let key = i;
|
||||||
|
if (array) {
|
||||||
|
key = modulo ? Math.round(key) % len : clamp(Math.round(key), 0, lookup.length - 1);
|
||||||
|
}
|
||||||
|
return lookup[key];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** * Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
||||||
|
* Similar to `inhabit`, but maintains the structure of the original patterns.
|
||||||
* @param {Pattern} pat
|
* @param {Pattern} pat
|
||||||
* @param {*} xs
|
* @param {*} xs
|
||||||
* @returns {Pattern}
|
* @returns {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* note(pick("<0 1 [2!2] 3>", ["g a", "e f", "f g f g" , "g a c d"]))
|
* note("<0 1 2!2 3>".pick(["g a", "e f", "f g f g" , "g c d"]))
|
||||||
|
* @example
|
||||||
|
* sound("<0 1 [2,0]>".pick(["bd sd", "cp cp", "hh hh"]))
|
||||||
|
* @example
|
||||||
|
* sound("<0!2 [0,1] 1>".pick(["bd(3,8)", "sd sd"]))
|
||||||
|
* @example
|
||||||
|
* s("<a!2 [a,b] b>".pick({a: "bd(3,8)", b: "sd sd"}))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const pick = (pat, xs) => {
|
export const pick = function (lookup, pat) {
|
||||||
xs = xs.map(reify);
|
// backward compatibility - the args used to be flipped
|
||||||
if (xs.length == 0) {
|
if (Array.isArray(pat)) {
|
||||||
return silence;
|
[pat, lookup] = [lookup, pat];
|
||||||
}
|
}
|
||||||
return pat
|
return __pick(lookup, pat);
|
||||||
.fmap((i) => {
|
|
||||||
const key = clamp(Math.round(i), 0, xs.length - 1);
|
|
||||||
return xs[key];
|
|
||||||
})
|
|
||||||
.innerJoin();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const __pick = register('pick', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).innerJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pick`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* For example, if you pick the fifth pattern of a list of three, you'll get the
|
||||||
|
* second one.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const pickmod = register('pickmod', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).innerJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * pickF lets you use a pattern of numbers to pick which function to apply to another pattern.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {Pattern} lookup a pattern of indices
|
||||||
|
* @param {function[]} funcs the array of functions from which to pull
|
||||||
|
* @returns {Pattern}
|
||||||
|
* @example
|
||||||
|
* s("bd [rim hh]").pickF("<0 1 2>", [rev,jux(rev),fast(2)])
|
||||||
|
* @example
|
||||||
|
* note("<c2 d2>(3,8)").s("square")
|
||||||
|
* .pickF("<0 2> 1", [jux(rev),fast(2),x=>x.lpf(800)])
|
||||||
|
*/
|
||||||
|
export const pickF = register('pickF', function (lookup, funcs, pat) {
|
||||||
|
return pat.apply(pick(lookup, funcs));
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pickF`, but if you pick a number greater than the size of the functions list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {Pattern} lookup a pattern of indices
|
||||||
|
* @param {function[]} funcs the array of functions from which to pull
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickmodF = register('pickmodF', function (lookup, funcs, pat) {
|
||||||
|
return pat.apply(pickmod(lookup, funcs));
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * Similar to `pick`, but it applies an outerJoin instead of an innerJoin.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickOut = register('pickOut', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).outerJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pickOut`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickmodOut = register('pickmodOut', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).outerJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * Similar to `pick`, but the choosen pattern is restarted when its index is triggered.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickRestart = register('pickRestart', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).trigzeroJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pickRestart`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickmodRestart = register('pickmodRestart', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).trigzeroJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * Similar to `pick`, but the choosen pattern is reset when its index is triggered.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickReset = register('pickReset', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).trigJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `pickReset`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
export const pickmodReset = register('pickmodReset', function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).trigJoin();
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pick from the list of values (or patterns of values) via the index using the given
|
/** * Picks patterns (or plain values) either from a list (by index) or a lookup table (by name).
|
||||||
|
* Similar to `pick`, but cycles are squeezed into the target ('inhabited') pattern.
|
||||||
|
* @name inhabit
|
||||||
|
* @synonyms pickSqueeze
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
* @example
|
||||||
|
* "<a b [a,b]>".inhabit({a: s("bd(3,8)"),
|
||||||
|
b: s("cp sd")
|
||||||
|
})
|
||||||
|
* @example
|
||||||
|
* s("a@2 [a b] a".inhabit({a: "bd(3,8)", b: "sd sd"})).slow(4)
|
||||||
|
*/
|
||||||
|
export const { inhabit, pickSqueeze } = register(['inhabit', 'pickSqueeze'], function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, false).squeezeJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/** * The same as `inhabit`, but if you pick a number greater than the size of the list,
|
||||||
|
* it wraps around, rather than sticking at the maximum value.
|
||||||
|
* For example, if you pick the fifth pattern of a list of three, you'll get the
|
||||||
|
* second one.
|
||||||
|
* @name inhabitmod
|
||||||
|
* @synonyms pickmodSqueeze
|
||||||
|
* @param {Pattern} pat
|
||||||
|
* @param {*} xs
|
||||||
|
* @returns {Pattern}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const { inhabitmod, pickmodSqueeze } = register(['inhabitmod', 'pickmodSqueeze'], function (lookup, pat) {
|
||||||
|
return _pick(lookup, pat, true).squeezeJoin();
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick from the list of values (or patterns of values) via the index using the given
|
||||||
* pattern of integers. The selected pattern will be compressed to fit the duration of the selecting event
|
* pattern of integers. The selected pattern will be compressed to fit the duration of the selecting event
|
||||||
* @param {Pattern} pat
|
* @param {Pattern} pat
|
||||||
* @param {*} xs
|
* @param {*} xs
|
||||||
@@ -269,9 +425,9 @@ Pattern.prototype.choose2 = function (...xs) {
|
|||||||
* Picks one of the elements at random each cycle.
|
* Picks one of the elements at random each cycle.
|
||||||
* @returns {Pattern}
|
* @returns {Pattern}
|
||||||
* @example
|
* @example
|
||||||
* chooseCycles("bd", "hh", "sd").s().fast(4)
|
* chooseCycles("bd", "hh", "sd").s().fast(8)
|
||||||
* @example
|
* @example
|
||||||
* "bd | hh | sd".s().fast(4)
|
* s("bd | hh | sd").fast(8)
|
||||||
*/
|
*/
|
||||||
export const chooseCycles = (...xs) => chooseInWith(rand.segment(1), xs);
|
export const chooseCycles = (...xs) => chooseInWith(rand.segment(1), xs);
|
||||||
|
|
||||||
@@ -314,7 +470,7 @@ export const perlinWith = (pat) => {
|
|||||||
* @name perlin
|
* @name perlin
|
||||||
* @example
|
* @example
|
||||||
* // randomly change the cutoff
|
* // randomly change the cutoff
|
||||||
* s("bd sd,hh*4").cutoff(perlin.range(500,2000))
|
* s("bd*4,hh*8").cutoff(perlin.range(500,8000))
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const perlin = perlinWith(time.fmap((v) => Number(v)));
|
export const perlin = perlinWith(time.fmap((v) => Number(v)));
|
||||||
@@ -356,7 +512,7 @@ export const degradeBy = register('degradeBy', function (x, pat) {
|
|||||||
export const degrade = register('degrade', (pat) => pat._degradeBy(0.5));
|
export const degrade = register('degrade', (pat) => pat._degradeBy(0.5));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inverse of {@link Pattern#degradeBy}: Randomly removes events from the pattern by a given amount.
|
* Inverse of `degradeBy`: Randomly removes events from the pattern by a given amount.
|
||||||
* 0 = 100% chance of removal
|
* 0 = 100% chance of removal
|
||||||
* 1 = 0% chance of removal
|
* 1 = 0% chance of removal
|
||||||
* Events that would be removed by degradeBy are let through by undegradeBy and vice versa (see second example).
|
* Events that would be removed by degradeBy are let through by undegradeBy and vice versa (see second example).
|
||||||
@@ -380,7 +536,7 @@ export const undegrade = register('undegrade', (pat) => pat._undegradeBy(0.5));
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Randomly applies the given function by the given probability.
|
* Randomly applies the given function by the given probability.
|
||||||
* Similar to {@link Pattern#someCyclesBy}
|
* Similar to `someCyclesBy`
|
||||||
*
|
*
|
||||||
* @name sometimesBy
|
* @name sometimesBy
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
@@ -388,7 +544,7 @@ export const undegrade = register('undegrade', (pat) => pat._undegradeBy(0.5));
|
|||||||
* @param {function} function - the transformation to apply
|
* @param {function} function - the transformation to apply
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("hh(3,8)").sometimesBy(.4, x=>x.speed("0.5"))
|
* s("hh*8").sometimesBy(.4, x=>x.speed("0.5"))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const sometimesBy = register('sometimesBy', function (patx, func, pat) {
|
export const sometimesBy = register('sometimesBy', function (patx, func, pat) {
|
||||||
@@ -406,7 +562,7 @@ export const sometimesBy = register('sometimesBy', function (patx, func, pat) {
|
|||||||
* @param {function} function - the transformation to apply
|
* @param {function} function - the transformation to apply
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("hh*4").sometimes(x=>x.speed("0.5"))
|
* s("hh*8").sometimes(x=>x.speed("0.5"))
|
||||||
*/
|
*/
|
||||||
export const sometimes = register('sometimes', function (func, pat) {
|
export const sometimes = register('sometimes', function (func, pat) {
|
||||||
return pat._sometimesBy(0.5, func);
|
return pat._sometimesBy(0.5, func);
|
||||||
@@ -415,7 +571,7 @@ export const sometimes = register('sometimes', function (func, pat) {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Randomly applies the given function by the given probability on a cycle by cycle basis.
|
* Randomly applies the given function by the given probability on a cycle by cycle basis.
|
||||||
* Similar to {@link Pattern#sometimesBy}
|
* Similar to `sometimesBy`
|
||||||
*
|
*
|
||||||
* @name someCyclesBy
|
* @name someCyclesBy
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
@@ -423,7 +579,7 @@ export const sometimes = register('sometimes', function (func, pat) {
|
|||||||
* @param {function} function - the transformation to apply
|
* @param {function} function - the transformation to apply
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("hh(3,8)").someCyclesBy(.3, x=>x.speed("0.5"))
|
* s("bd,hh*8").someCyclesBy(.3, x=>x.speed("0.5"))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const someCyclesBy = register('someCyclesBy', function (patx, func, pat) {
|
export const someCyclesBy = register('someCyclesBy', function (patx, func, pat) {
|
||||||
@@ -445,7 +601,7 @@ export const someCyclesBy = register('someCyclesBy', function (patx, func, pat)
|
|||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
* @example
|
* @example
|
||||||
* s("hh(3,8)").someCycles(x=>x.speed("0.5"))
|
* s("bd,hh*8").someCycles(x=>x.speed("0.5"))
|
||||||
*/
|
*/
|
||||||
export const someCycles = register('someCycles', function (func, pat) {
|
export const someCycles = register('someCycles', function (func, pat) {
|
||||||
return pat._someCyclesBy(0.5, func);
|
return pat._someCyclesBy(0.5, func);
|
||||||
|
|||||||
@@ -4,23 +4,23 @@ Copyright (C) 2023 Strudel contributors - see <https://github.com/tidalcycles/st
|
|||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import controls from '../controls.mjs';
|
import { s } from '../controls.mjs';
|
||||||
import { mini } from '../../mini/mini.mjs';
|
import { mini } from '../../mini/mini.mjs';
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
|
|
||||||
describe('controls', () => {
|
describe('controls', () => {
|
||||||
it('should support controls', () => {
|
it('should support controls', () => {
|
||||||
expect(controls.s('bd').firstCycleValues).toEqual([{ s: 'bd' }]);
|
expect(s('bd').firstCycleValues).toEqual([{ s: 'bd' }]);
|
||||||
});
|
});
|
||||||
it('should support compound controls', () => {
|
it('should support compound controls', () => {
|
||||||
expect(controls.s(mini('bd:3')).firstCycleValues).toEqual([{ s: 'bd', n: 3 }]);
|
expect(s(mini('bd:3')).firstCycleValues).toEqual([{ s: 'bd', n: 3 }]);
|
||||||
expect(controls.s(mini('bd:3 sd:4:1.4')).firstCycleValues).toEqual([
|
expect(s(mini('bd:3 sd:4:1.4')).firstCycleValues).toEqual([
|
||||||
{ s: 'bd', n: 3 },
|
{ s: 'bd', n: 3 },
|
||||||
{ s: 'sd', n: 4, gain: 1.4 },
|
{ s: 'sd', n: 4, gain: 1.4 },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should support ignore extra elements in compound controls', () => {
|
it('should support ignore extra elements in compound controls', () => {
|
||||||
expect(controls.s(mini('bd:3:0.4 sd:4:0.5:3:17')).firstCycleValues).toEqual([
|
expect(s(mini('bd:3:0.4 sd:4:0.5:3:17')).firstCycleValues).toEqual([
|
||||||
{ s: 'bd', n: 3, gain: 0.4 },
|
{ s: 'bd', n: 3, gain: 0.4 },
|
||||||
{ s: 'sd', n: 4, gain: 0.5 },
|
{ s: 'sd', n: 4, gain: 0.5 },
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ import {
|
|||||||
rev,
|
rev,
|
||||||
time,
|
time,
|
||||||
run,
|
run,
|
||||||
|
pick,
|
||||||
} from '../index.mjs';
|
} from '../index.mjs';
|
||||||
|
|
||||||
import { steady } from '../signal.mjs';
|
import { steady } from '../signal.mjs';
|
||||||
|
|
||||||
import controls from '../controls.mjs';
|
import { n, s } from '../controls.mjs';
|
||||||
|
|
||||||
const { n, s } = controls;
|
|
||||||
const st = (begin, end) => new State(ts(begin, end));
|
const st = (begin, end) => new State(ts(begin, end));
|
||||||
const ts = (begin, end) => new TimeSpan(Fraction(begin), Fraction(end));
|
const ts = (begin, end) => new TimeSpan(Fraction(begin), Fraction(end));
|
||||||
const hap = (whole, part, value, context = {}) => new Hap(whole, part, value, context);
|
const hap = (whole, part, value, context = {}) => new Hap(whole, part, value, context);
|
||||||
@@ -1057,4 +1057,63 @@ describe('Pattern', () => {
|
|||||||
expect(slowcat(0, 1).repeatCycles(2).fast(6).firstCycleValues).toStrictEqual([0, 0, 1, 1, 0, 0]);
|
expect(slowcat(0, 1).repeatCycles(2).fast(6).firstCycleValues).toStrictEqual([0, 0, 1, 1, 0, 0]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('inhabit', () => {
|
||||||
|
it('Can pattern named patterns', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(
|
||||||
|
sequence('a', 'b', stack('a', 'b')).inhabit({ a: sequence(1, 2), b: sequence(10, 20, 30) }),
|
||||||
|
sequence([1, 2], [10, 20, 30], stack([1, 2], [10, 20, 30])),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Can pattern indexed patterns', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(
|
||||||
|
sequence('0', '1', stack('0', '1')).inhabit([sequence(1, 2), sequence(10, 20, 30)]),
|
||||||
|
sequence([1, 2], [10, 20, 30], stack([1, 2], [10, 20, 30])),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('pick', () => {
|
||||||
|
it('Can pattern named patterns', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(
|
||||||
|
sequence('a', 'b', 'a', stack('a', 'b')).pick({ a: sequence(1, 2, 3, 4), b: sequence(10, 20, 30, 40) }),
|
||||||
|
sequence(1, 20, 3, stack(4, 40)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Can pattern indexed patterns', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(
|
||||||
|
sequence(0, 1, 0, stack(0, 1)).pick([sequence(1, 2, 3, 4), sequence(10, 20, 30, 40)]),
|
||||||
|
sequence(1, 20, 3, stack(4, 40)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Clamps indexes', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(sequence(0, 1, 2, 3).pick([sequence(1, 2, 3, 4), sequence(10, 20, 30, 40)]), sequence(1, 20, 30, 40)),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Is backwards compatible', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(
|
||||||
|
pick([sequence('a', 'b'), sequence('c', 'd')], sequence(0, 1)),
|
||||||
|
pick(sequence(0, 1), [sequence('a', 'b'), sequence('c', 'd')]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('pickmod', () => {
|
||||||
|
it('Wraps indexes', () => {
|
||||||
|
expect(
|
||||||
|
sameFirst(
|
||||||
|
sequence(0, 1, 2, 3).pickmod([sequence(1, 2, 3, 4), sequence(10, 20, 30, 40)]),
|
||||||
|
sequence(1, 20, 3, 40),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
|
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { map, valued, mul } from '../value.mjs';
|
import { map, valued, mul } from '../value.mjs';
|
||||||
import controls from '../controls.mjs';
|
import { n } from '../controls.mjs';
|
||||||
const { n } = controls;
|
|
||||||
|
|
||||||
describe('Value', () => {
|
describe('Value', () => {
|
||||||
it('unionWith', () => {
|
it('unionWith', () => {
|
||||||
|
|||||||
@@ -316,3 +316,10 @@ export function hash2code(hash) {
|
|||||||
return base64ToUnicode(decodeURIComponent(hash));
|
return base64ToUnicode(decodeURIComponent(hash));
|
||||||
//return atob(decodeURIComponent(codeParam || ''));
|
//return atob(decodeURIComponent(codeParam || ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function objectMap(obj, fn) {
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
return obj.map(fn);
|
||||||
|
}
|
||||||
|
return Object.fromEntries(Object.entries(obj).map(([k, v], i) => [k, fn(v, k, i)]));
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/csound",
|
"name": "@strudel/csound",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "csound bindings for strudel",
|
"description": "csound bindings for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ const OFF_MESSAGE = 0x80;
|
|||||||
const CC_MESSAGE = 0xb0;
|
const CC_MESSAGE = 0xb0;
|
||||||
|
|
||||||
Pattern.prototype.midi = function (output) {
|
Pattern.prototype.midi = function (output) {
|
||||||
return this.onTrigger((time, hap, currentTime) => {
|
return this.onTrigger((time, hap, currentTime, cps) => {
|
||||||
const { note, nrpnn, nrpv, ccn, ccv } = hap.value;
|
const { note, nrpnn, nrpv, ccn, ccv } = hap.value;
|
||||||
const offset = (time - currentTime) * 1000;
|
const offset = (time - currentTime) * 1000;
|
||||||
const velocity = Math.floor((hap.context?.velocity ?? 0.9) * 100); // TODO: refactor velocity
|
const velocity = Math.floor((hap.context?.velocity ?? 0.9) * 100); // TODO: refactor velocity
|
||||||
const duration = Math.floor(hap.duration.valueOf() * 1000 - 10);
|
const duration = Math.floor((hap.duration.valueOf() / cps) * 1000 - 10);
|
||||||
const roundedOffset = Math.round(offset);
|
const roundedOffset = Math.round(offset);
|
||||||
const midichan = (hap.value.midichan ?? 1) - 1;
|
const midichan = (hap.value.midichan ?? 1) - 1;
|
||||||
const requestedport = output ?? 'IAC';
|
const requestedport = output ?? 'IAC';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/embed",
|
"name": "@strudel/embed",
|
||||||
"version": "0.11.0",
|
"version": "1.0.0",
|
||||||
"description": "Embeddable Web Component to load a Strudel REPL into an iframe",
|
"description": "Embeddable Web Component to load a Strudel REPL into an iframe",
|
||||||
"main": "embed.js",
|
"main": "embed.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/hydra",
|
"name": "@strudel/hydra",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Hydra integration for strudel",
|
"description": "Hydra integration for strudel",
|
||||||
"main": "hydra.mjs",
|
"main": "hydra.mjs",
|
||||||
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"server": "node server.js",
|
"server": "node server.js",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'hydra.mjs'),
|
entry: resolve(__dirname, 'hydra.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ Pattern.prototype.midi = function (output) {
|
|||||||
const velocity = hap.context?.velocity ?? 0.9; // TODO: refactor velocity
|
const velocity = hap.context?.velocity ?? 0.9; // TODO: refactor velocity
|
||||||
|
|
||||||
// note off messages will often a few ms arrive late, try to prevent glitching by subtracting from the duration length
|
// note off messages will often a few ms arrive late, try to prevent glitching by subtracting from the duration length
|
||||||
const duration = Math.floor(hap.duration.valueOf() * 1000 - 10);
|
const duration = Math.floor((hap.duration.valueOf() / cps) * 1000 - 10);
|
||||||
if (note != null) {
|
if (note != null) {
|
||||||
const midiNumber = typeof note === 'number' ? note : noteToMidi(note);
|
const midiNumber = typeof note === 'number' ? note : noteToMidi(note);
|
||||||
const midiNote = new Note(midiNumber, { attack: velocity, duration });
|
const midiNote = new Note(midiNumber, { attack: velocity, duration });
|
||||||
@@ -167,10 +167,16 @@ let listeners = {};
|
|||||||
const refs = {};
|
const refs = {};
|
||||||
|
|
||||||
export async function midin(input) {
|
export async function midin(input) {
|
||||||
|
if (isPattern(input)) {
|
||||||
|
throw new Error(
|
||||||
|
`.midi does not accept Pattern input. Make sure to pass device name with single quotes. Example: .midi('${
|
||||||
|
WebMidi.outputs?.[0]?.name || 'IAC Driver Bus 1'
|
||||||
|
}')`,
|
||||||
|
);
|
||||||
|
}
|
||||||
const initial = await enableWebMidi(); // only returns on first init
|
const initial = await enableWebMidi(); // only returns on first init
|
||||||
const device = getDevice(input, WebMidi.inputs);
|
const device = getDevice(input, WebMidi.inputs);
|
||||||
|
if (initial || WebMidi.enabled) {
|
||||||
if (initial) {
|
|
||||||
const otherInputs = WebMidi.inputs.filter((o) => o.name !== device.name);
|
const otherInputs = WebMidi.inputs.filter((o) => o.name !== device.name);
|
||||||
logger(
|
logger(
|
||||||
`Midi enabled! Using "${device.name}". ${
|
`Midi enabled! Using "${device.name}". ${
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/midi",
|
"name": "@strudel/midi",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Midi API for strudel",
|
"description": "Midi API for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
+193
-96
@@ -288,48 +288,50 @@ function peg$parse(input, options) {
|
|||||||
|
|
||||||
var peg$f0 = function() { return parseFloat(text()); };
|
var peg$f0 = function() { return parseFloat(text()); };
|
||||||
var peg$f1 = function() { return parseInt(text()); };
|
var peg$f1 = function() { return parseInt(text()); };
|
||||||
var peg$f2 = function(chars) { return new AtomStub(chars.join("")) };
|
var peg$f2 = function(chars) { const s = chars.join(""); return (s === ".") || (s === "_") };
|
||||||
var peg$f3 = function(s) { return s };
|
var peg$f3 = function(chars) { return new AtomStub(chars.join("")) };
|
||||||
var peg$f4 = function(s, stepsPerCycle) { s.arguments_.stepsPerCycle = stepsPerCycle ; return s; };
|
var peg$f4 = function(s) { return s };
|
||||||
var peg$f5 = function(a) { return a };
|
var peg$f5 = function(s, stepsPerCycle) { s.arguments_.stepsPerCycle = stepsPerCycle ; return s; };
|
||||||
var peg$f6 = function(s) { s.arguments_.alignment = 'polymeter_slowcat'; return s; };
|
var peg$f6 = function(a) { return a };
|
||||||
var peg$f7 = function(a) { return x => x.options_['weight'] = a };
|
var peg$f7 = function(s) { s.arguments_.alignment = 'polymeter_slowcat'; return s; };
|
||||||
var peg$f8 = function(a) { return x => x.options_['reps'] = a };
|
var peg$f8 = function(a) { return x => x.options_['weight'] = (x.options_['weight'] ?? 1) + (a ?? 2) - 1 };
|
||||||
var peg$f9 = function(p, s, r) { return x => x.options_['ops'].push({ type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r }}) };
|
var peg$f9 = function(a) { return x => x.options_['reps'] = (x.options_['reps'] ?? 1) + (a ?? 2) - 1 };
|
||||||
var peg$f10 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'slow' }}) };
|
var peg$f10 = function(p, s, r) { return x => x.options_['ops'].push({ type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r }}) };
|
||||||
var peg$f11 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'fast' }}) };
|
var peg$f11 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'slow' }}) };
|
||||||
var peg$f12 = function(a) { return x => x.options_['ops'].push({ type_: "degradeBy", arguments_ :{ amount:a, seed: seed++ } }) };
|
var peg$f12 = function(a) { return x => x.options_['ops'].push({ type_: "stretch", arguments_ :{ amount:a, type: 'fast' }}) };
|
||||||
var peg$f13 = function(s) { return x => x.options_['ops'].push({ type_: "tail", arguments_ :{ element:s } }) };
|
var peg$f13 = function(a) { return x => x.options_['ops'].push({ type_: "degradeBy", arguments_ :{ amount:a, seed: seed++ } }) };
|
||||||
var peg$f14 = function(s) { return x => x.options_['ops'].push({ type_: "range", arguments_ :{ element:s } }) };
|
var peg$f14 = function(s) { return x => x.options_['ops'].push({ type_: "tail", arguments_ :{ element:s } }) };
|
||||||
var peg$f15 = function(s, ops) { const result = new ElementStub(s, {ops: [], weight: 1, reps: 1});
|
var peg$f15 = function(s) { return x => x.options_['ops'].push({ type_: "range", arguments_ :{ element:s } }) };
|
||||||
|
var peg$f16 = function(s, ops) { const result = new ElementStub(s, {ops: [], weight: 1, reps: 1});
|
||||||
for (const op of ops) {
|
for (const op of ops) {
|
||||||
op(result);
|
op(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
var peg$f16 = function(s) { return new PatternStub(s, 'fastcat'); };
|
var peg$f17 = function(s) { return new PatternStub(s, 'fastcat'); };
|
||||||
var peg$f17 = function(tail) { return { alignment: 'stack', list: tail }; };
|
var peg$f18 = function(tail) { return { alignment: 'stack', list: tail }; };
|
||||||
var peg$f18 = function(tail) { return { alignment: 'rand', list: tail, seed: seed++ }; };
|
var peg$f19 = function(tail) { return { alignment: 'rand', list: tail, seed: seed++ }; };
|
||||||
var peg$f19 = function(head, tail) { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment, tail.seed); } else { return head; } };
|
var peg$f20 = function(tail) { return { alignment: 'feet', list: tail, seed: seed++ }; };
|
||||||
var peg$f20 = function(head, tail) { return new PatternStub(tail ? [head, ...tail.list] : [head], 'polymeter'); };
|
var peg$f21 = function(head, tail) { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment, tail.seed); } else { return head; } };
|
||||||
var peg$f21 = function(sc) { return sc; };
|
var peg$f22 = function(head, tail) { return new PatternStub(tail ? [head, ...tail.list] : [head], 'polymeter'); };
|
||||||
var peg$f22 = function(s) { return { name: "struct", args: { mini:s }}};
|
var peg$f23 = function(sc) { return sc; };
|
||||||
var peg$f23 = function(s) { return { name: "target", args : { name:s}}};
|
var peg$f24 = function(s) { return { name: "struct", args: { mini:s }}};
|
||||||
var peg$f24 = function(p, s, r) { return { name: "bjorklund", args :{ pulse: p, step:parseInt(s) }}};
|
var peg$f25 = function(s) { return { name: "target", args : { name:s}}};
|
||||||
var peg$f25 = function(a) { return { name: "stretch", args :{ amount: a}}};
|
var peg$f26 = function(p, s, r) { return { name: "bjorklund", args :{ pulse: p, step:parseInt(s) }}};
|
||||||
var peg$f26 = function(a) { return { name: "shift", args :{ amount: "-"+a}}};
|
var peg$f27 = function(a) { return { name: "stretch", args :{ amount: a}}};
|
||||||
var peg$f27 = function(a) { return { name: "shift", args :{ amount: a}}};
|
var peg$f28 = function(a) { return { name: "shift", args :{ amount: "-"+a}}};
|
||||||
var peg$f28 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}};
|
var peg$f29 = function(a) { return { name: "shift", args :{ amount: a}}};
|
||||||
var peg$f29 = function(s) { return { name: "scale", args :{ scale: s.join("")}}};
|
var peg$f30 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}};
|
||||||
var peg$f30 = function(s, v) { return v};
|
var peg$f31 = function(s) { return { name: "scale", args :{ scale: s.join("")}}};
|
||||||
var peg$f31 = function(s, ss) { ss.unshift(s); return new PatternStub(ss, 'slowcat'); };
|
var peg$f32 = function(s, v) { return v};
|
||||||
var peg$f32 = function(sg) {return sg};
|
var peg$f33 = function(s, ss) { ss.unshift(s); return new PatternStub(ss, 'slowcat'); };
|
||||||
var peg$f33 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)};
|
var peg$f34 = function(sg) {return sg};
|
||||||
var peg$f34 = function(sc) { return sc };
|
var peg$f35 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)};
|
||||||
var peg$f35 = function(c) { return c };
|
var peg$f36 = function(sc) { return sc };
|
||||||
var peg$f36 = function(v) { return new CommandStub("setcps", { value: v})};
|
var peg$f37 = function(c) { return c };
|
||||||
var peg$f37 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})};
|
var peg$f38 = function(v) { return new CommandStub("setcps", { value: v})};
|
||||||
var peg$f38 = function() { return new CommandStub("hush")};
|
var peg$f39 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})};
|
||||||
|
var peg$f40 = function() { return new CommandStub("hush")};
|
||||||
var peg$currPos = 0;
|
var peg$currPos = 0;
|
||||||
var peg$savedPos = 0;
|
var peg$savedPos = 0;
|
||||||
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
||||||
@@ -821,6 +823,30 @@ function peg$parse(input, options) {
|
|||||||
return s0;
|
return s0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function peg$parsedot() {
|
||||||
|
var s0, s1, s2, s3;
|
||||||
|
|
||||||
|
s0 = peg$currPos;
|
||||||
|
s1 = peg$parsews();
|
||||||
|
if (input.charCodeAt(peg$currPos) === 46) {
|
||||||
|
s2 = peg$c0;
|
||||||
|
peg$currPos++;
|
||||||
|
} else {
|
||||||
|
s2 = peg$FAILED;
|
||||||
|
if (peg$silentFails === 0) { peg$fail(peg$e1); }
|
||||||
|
}
|
||||||
|
if (s2 !== peg$FAILED) {
|
||||||
|
s3 = peg$parsews();
|
||||||
|
s1 = [s1, s2, s3];
|
||||||
|
s0 = s1;
|
||||||
|
} else {
|
||||||
|
peg$currPos = s0;
|
||||||
|
s0 = peg$FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s0;
|
||||||
|
}
|
||||||
|
|
||||||
function peg$parsequote() {
|
function peg$parsequote() {
|
||||||
var s0;
|
var s0;
|
||||||
|
|
||||||
@@ -913,7 +939,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function peg$parsestep() {
|
function peg$parsestep() {
|
||||||
var s0, s1, s2, s3;
|
var s0, s1, s2, s3, s4;
|
||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
s1 = peg$parsews();
|
s1 = peg$parsews();
|
||||||
@@ -929,8 +955,20 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s3 = peg$parsews();
|
s3 = peg$parsews();
|
||||||
peg$savedPos = s0;
|
peg$savedPos = peg$currPos;
|
||||||
s0 = peg$f2(s2);
|
s4 = peg$f2(s2);
|
||||||
|
if (s4) {
|
||||||
|
s4 = peg$FAILED;
|
||||||
|
} else {
|
||||||
|
s4 = undefined;
|
||||||
|
}
|
||||||
|
if (s4 !== peg$FAILED) {
|
||||||
|
peg$savedPos = s0;
|
||||||
|
s0 = peg$f3(s2);
|
||||||
|
} else {
|
||||||
|
peg$currPos = s0;
|
||||||
|
s0 = peg$FAILED;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -966,7 +1004,7 @@ function peg$parse(input, options) {
|
|||||||
if (s6 !== peg$FAILED) {
|
if (s6 !== peg$FAILED) {
|
||||||
s7 = peg$parsews();
|
s7 = peg$parsews();
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f3(s4);
|
s0 = peg$f4(s4);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1014,7 +1052,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
s8 = peg$parsews();
|
s8 = peg$parsews();
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f4(s4, s7);
|
s0 = peg$f5(s4, s7);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1046,7 +1084,7 @@ function peg$parse(input, options) {
|
|||||||
s2 = peg$parseslice();
|
s2 = peg$parseslice();
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f5(s2);
|
s0 = peg$f6(s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1086,7 +1124,7 @@ function peg$parse(input, options) {
|
|||||||
if (s6 !== peg$FAILED) {
|
if (s6 !== peg$FAILED) {
|
||||||
s7 = peg$parsews();
|
s7 = peg$parsews();
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f6(s4);
|
s0 = peg$f7(s4);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1150,25 +1188,33 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function peg$parseop_weight() {
|
function peg$parseop_weight() {
|
||||||
var s0, s1, s2;
|
var s0, s1, s2, s3;
|
||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
|
s1 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 64) {
|
if (input.charCodeAt(peg$currPos) === 64) {
|
||||||
s1 = peg$c18;
|
s2 = peg$c18;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s2 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e26); }
|
if (peg$silentFails === 0) { peg$fail(peg$e26); }
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s2 === peg$FAILED) {
|
||||||
s2 = peg$parsenumber();
|
if (input.charCodeAt(peg$currPos) === 95) {
|
||||||
if (s2 !== peg$FAILED) {
|
s2 = peg$c10;
|
||||||
peg$savedPos = s0;
|
peg$currPos++;
|
||||||
s0 = peg$f7(s2);
|
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
s2 = peg$FAILED;
|
||||||
s0 = peg$FAILED;
|
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (s2 !== peg$FAILED) {
|
||||||
|
s3 = peg$parsenumber();
|
||||||
|
if (s3 === peg$FAILED) {
|
||||||
|
s3 = null;
|
||||||
|
}
|
||||||
|
peg$savedPos = s0;
|
||||||
|
s0 = peg$f8(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1178,25 +1224,24 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function peg$parseop_replicate() {
|
function peg$parseop_replicate() {
|
||||||
var s0, s1, s2;
|
var s0, s1, s2, s3;
|
||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
|
s1 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 33) {
|
if (input.charCodeAt(peg$currPos) === 33) {
|
||||||
s1 = peg$c19;
|
s2 = peg$c19;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s2 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e27); }
|
if (peg$silentFails === 0) { peg$fail(peg$e27); }
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s2 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s2 !== peg$FAILED) {
|
if (s3 === peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
s3 = null;
|
||||||
s0 = peg$f8(s2);
|
|
||||||
} else {
|
|
||||||
peg$currPos = s0;
|
|
||||||
s0 = peg$FAILED;
|
|
||||||
}
|
}
|
||||||
|
peg$savedPos = s0;
|
||||||
|
s0 = peg$f9(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1246,7 +1291,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s13 !== peg$FAILED) {
|
if (s13 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f9(s3, s7, s11);
|
s0 = peg$f10(s3, s7, s11);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1286,7 +1331,7 @@ function peg$parse(input, options) {
|
|||||||
s2 = peg$parseslice();
|
s2 = peg$parseslice();
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f10(s2);
|
s0 = peg$f11(s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1314,7 +1359,7 @@ function peg$parse(input, options) {
|
|||||||
s2 = peg$parseslice();
|
s2 = peg$parseslice();
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f11(s2);
|
s0 = peg$f12(s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1344,7 +1389,7 @@ function peg$parse(input, options) {
|
|||||||
s2 = null;
|
s2 = null;
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f12(s2);
|
s0 = peg$f13(s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1368,7 +1413,7 @@ function peg$parse(input, options) {
|
|||||||
s2 = peg$parseslice();
|
s2 = peg$parseslice();
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f13(s2);
|
s0 = peg$f14(s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1396,7 +1441,7 @@ function peg$parse(input, options) {
|
|||||||
s2 = peg$parseslice();
|
s2 = peg$parseslice();
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f14(s2);
|
s0 = peg$f15(s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1422,7 +1467,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parseslice_op();
|
s3 = peg$parseslice_op();
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f15(s1, s2);
|
s0 = peg$f16(s1, s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1447,7 +1492,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f16(s1);
|
s1 = peg$f17(s1);
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
|
|
||||||
@@ -1496,7 +1541,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f17(s1);
|
s1 = peg$f18(s1);
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
|
|
||||||
@@ -1545,7 +1590,56 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f18(s1);
|
s1 = peg$f19(s1);
|
||||||
|
}
|
||||||
|
s0 = s1;
|
||||||
|
|
||||||
|
return s0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function peg$parsedot_tail() {
|
||||||
|
var s0, s1, s2, s3, s4;
|
||||||
|
|
||||||
|
s0 = peg$currPos;
|
||||||
|
s1 = [];
|
||||||
|
s2 = peg$currPos;
|
||||||
|
s3 = peg$parsedot();
|
||||||
|
if (s3 !== peg$FAILED) {
|
||||||
|
s4 = peg$parsesequence();
|
||||||
|
if (s4 !== peg$FAILED) {
|
||||||
|
s2 = s4;
|
||||||
|
} else {
|
||||||
|
peg$currPos = s2;
|
||||||
|
s2 = peg$FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
peg$currPos = s2;
|
||||||
|
s2 = peg$FAILED;
|
||||||
|
}
|
||||||
|
if (s2 !== peg$FAILED) {
|
||||||
|
while (s2 !== peg$FAILED) {
|
||||||
|
s1.push(s2);
|
||||||
|
s2 = peg$currPos;
|
||||||
|
s3 = peg$parsedot();
|
||||||
|
if (s3 !== peg$FAILED) {
|
||||||
|
s4 = peg$parsesequence();
|
||||||
|
if (s4 !== peg$FAILED) {
|
||||||
|
s2 = s4;
|
||||||
|
} else {
|
||||||
|
peg$currPos = s2;
|
||||||
|
s2 = peg$FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
peg$currPos = s2;
|
||||||
|
s2 = peg$FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s1 = peg$FAILED;
|
||||||
|
}
|
||||||
|
if (s1 !== peg$FAILED) {
|
||||||
|
peg$savedPos = s0;
|
||||||
|
s1 = peg$f20(s1);
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
|
|
||||||
@@ -1561,12 +1655,15 @@ function peg$parse(input, options) {
|
|||||||
s2 = peg$parsestack_tail();
|
s2 = peg$parsestack_tail();
|
||||||
if (s2 === peg$FAILED) {
|
if (s2 === peg$FAILED) {
|
||||||
s2 = peg$parsechoose_tail();
|
s2 = peg$parsechoose_tail();
|
||||||
|
if (s2 === peg$FAILED) {
|
||||||
|
s2 = peg$parsedot_tail();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s2 === peg$FAILED) {
|
if (s2 === peg$FAILED) {
|
||||||
s2 = null;
|
s2 = null;
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f19(s1, s2);
|
s0 = peg$f21(s1, s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1586,7 +1683,7 @@ function peg$parse(input, options) {
|
|||||||
s2 = null;
|
s2 = null;
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f20(s1, s2);
|
s0 = peg$f22(s1, s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1609,7 +1706,7 @@ function peg$parse(input, options) {
|
|||||||
s6 = peg$parsequote();
|
s6 = peg$parsequote();
|
||||||
if (s6 !== peg$FAILED) {
|
if (s6 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f21(s4);
|
s0 = peg$f23(s4);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1671,7 +1768,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsemini_or_operator();
|
s3 = peg$parsemini_or_operator();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f22(s3);
|
s0 = peg$f24(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1704,7 +1801,7 @@ function peg$parse(input, options) {
|
|||||||
s5 = peg$parsequote();
|
s5 = peg$parsequote();
|
||||||
if (s5 !== peg$FAILED) {
|
if (s5 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f23(s4);
|
s0 = peg$f25(s4);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1749,7 +1846,7 @@ function peg$parse(input, options) {
|
|||||||
s7 = null;
|
s7 = null;
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f24(s3, s5, s7);
|
s0 = peg$f26(s3, s5, s7);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1782,7 +1879,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f25(s3);
|
s0 = peg$f27(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1811,7 +1908,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f26(s3);
|
s0 = peg$f28(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1840,7 +1937,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f27(s3);
|
s0 = peg$f29(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1869,7 +1966,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f28(s3);
|
s0 = peg$f30(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -1911,7 +2008,7 @@ function peg$parse(input, options) {
|
|||||||
s5 = peg$parsequote();
|
s5 = peg$parsequote();
|
||||||
if (s5 !== peg$FAILED) {
|
if (s5 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f29(s4);
|
s0 = peg$f31(s4);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -2003,7 +2100,7 @@ function peg$parse(input, options) {
|
|||||||
s9 = peg$parsemini_or_operator();
|
s9 = peg$parsemini_or_operator();
|
||||||
if (s9 !== peg$FAILED) {
|
if (s9 !== peg$FAILED) {
|
||||||
peg$savedPos = s7;
|
peg$savedPos = s7;
|
||||||
s7 = peg$f30(s5, s9);
|
s7 = peg$f32(s5, s9);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s7;
|
peg$currPos = s7;
|
||||||
s7 = peg$FAILED;
|
s7 = peg$FAILED;
|
||||||
@@ -2020,7 +2117,7 @@ function peg$parse(input, options) {
|
|||||||
s9 = peg$parsemini_or_operator();
|
s9 = peg$parsemini_or_operator();
|
||||||
if (s9 !== peg$FAILED) {
|
if (s9 !== peg$FAILED) {
|
||||||
peg$savedPos = s7;
|
peg$savedPos = s7;
|
||||||
s7 = peg$f30(s5, s9);
|
s7 = peg$f32(s5, s9);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s7;
|
peg$currPos = s7;
|
||||||
s7 = peg$FAILED;
|
s7 = peg$FAILED;
|
||||||
@@ -2040,7 +2137,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s8 !== peg$FAILED) {
|
if (s8 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f31(s5, s6);
|
s0 = peg$f33(s5, s6);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -2086,7 +2183,7 @@ function peg$parse(input, options) {
|
|||||||
s4 = peg$parsecomment();
|
s4 = peg$parsecomment();
|
||||||
}
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f32(s1);
|
s0 = peg$f34(s1);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -2108,7 +2205,7 @@ function peg$parse(input, options) {
|
|||||||
s5 = peg$parsemini_or_operator();
|
s5 = peg$parsemini_or_operator();
|
||||||
if (s5 !== peg$FAILED) {
|
if (s5 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f33(s1, s5);
|
s0 = peg$f35(s1, s5);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -2133,7 +2230,7 @@ function peg$parse(input, options) {
|
|||||||
s1 = peg$parsemini_or_operator();
|
s1 = peg$parsemini_or_operator();
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f34(s1);
|
s1 = peg$f36(s1);
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
@@ -2166,7 +2263,7 @@ function peg$parse(input, options) {
|
|||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s3 = peg$parsews();
|
s3 = peg$parsews();
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f35(s2);
|
s0 = peg$f37(s2);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -2191,7 +2288,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f36(s3);
|
s0 = peg$f38(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -2220,7 +2317,7 @@ function peg$parse(input, options) {
|
|||||||
s3 = peg$parsenumber();
|
s3 = peg$parsenumber();
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f37(s3);
|
s0 = peg$f39(s3);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@@ -2246,7 +2343,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s1 = peg$f38();
|
s1 = peg$f40();
|
||||||
}
|
}
|
||||||
s0 = s1;
|
s0 = s1;
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ DIGIT = [0-9]
|
|||||||
ws "whitespace" = [ \n\r\t\u00A0]*
|
ws "whitespace" = [ \n\r\t\u00A0]*
|
||||||
comma = ws "," ws
|
comma = ws "," ws
|
||||||
pipe = ws "|" ws
|
pipe = ws "|" ws
|
||||||
|
dot = ws "." ws
|
||||||
quote = '"' / "'"
|
quote = '"' / "'"
|
||||||
|
|
||||||
// ------------------ steps and cycles ---------------------------
|
// ------------------ steps and cycles ---------------------------
|
||||||
@@ -105,7 +106,8 @@ quote = '"' / "'"
|
|||||||
// single step definition (e.g bd)
|
// single step definition (e.g bd)
|
||||||
step_char "a letter, a number, \"-\", \"#\", \".\", \"^\", \"_\"" =
|
step_char "a letter, a number, \"-\", \"#\", \".\", \"^\", \"_\"" =
|
||||||
unicode_letter / [0-9~] / "-" / "#" / "." / "^" / "_"
|
unicode_letter / [0-9~] / "-" / "#" / "." / "^" / "_"
|
||||||
step = ws chars:step_char+ ws { return new AtomStub(chars.join("")) }
|
|
||||||
|
step = ws chars:step_char+ ws !{ const s = chars.join(""); return (s === ".") || (s === "_") } { return new AtomStub(chars.join("")) }
|
||||||
|
|
||||||
// define a sub cycle e.g. [1 2, 3 [4]]
|
// define a sub cycle e.g. [1 2, 3 [4]]
|
||||||
sub_cycle = ws "[" ws s:stack_or_choose ws "]" ws { return s }
|
sub_cycle = ws "[" ws s:stack_or_choose ws "]" ws { return s }
|
||||||
@@ -129,11 +131,11 @@ slice = step / sub_cycle / polymeter / slow_sequence
|
|||||||
// at this point, we assume we can represent them as regular sequence operators
|
// at this point, we assume we can represent them as regular sequence operators
|
||||||
slice_op = op_weight / op_bjorklund / op_slow / op_fast / op_replicate / op_degrade / op_tail / op_range
|
slice_op = op_weight / op_bjorklund / op_slow / op_fast / op_replicate / op_degrade / op_tail / op_range
|
||||||
|
|
||||||
op_weight = "@" a:number
|
op_weight = ws ("@" / "_") a:number?
|
||||||
{ return x => x.options_['weight'] = a }
|
{ return x => x.options_['weight'] = (x.options_['weight'] ?? 1) + (a ?? 2) - 1 }
|
||||||
|
|
||||||
op_replicate = "!"a:number
|
op_replicate = ws "!" a:number?
|
||||||
{ return x => x.options_['reps'] = a }
|
{ return x => x.options_['reps'] = (x.options_['reps'] ?? 1) + (a ?? 2) - 1 }
|
||||||
|
|
||||||
op_bjorklund = "(" ws p:slice_with_ops ws comma ws s:slice_with_ops ws comma? ws r:slice_with_ops? ws ")"
|
op_bjorklund = "(" ws p:slice_with_ops ws comma ws s:slice_with_ops ws comma? ws r:slice_with_ops? ws ")"
|
||||||
{ return x => x.options_['ops'].push({ type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r }}) }
|
{ return x => x.options_['ops'].push({ type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r }}) }
|
||||||
@@ -175,9 +177,13 @@ stack_tail = tail:(comma @sequence)+
|
|||||||
choose_tail = tail:(pipe @sequence)+
|
choose_tail = tail:(pipe @sequence)+
|
||||||
{ return { alignment: 'rand', list: tail, seed: seed++ }; }
|
{ return { alignment: 'rand', list: tail, seed: seed++ }; }
|
||||||
|
|
||||||
|
// a foot separates subsequences, as an alternative to wrapping them in []
|
||||||
|
dot_tail = tail:(dot @sequence)+
|
||||||
|
{ return { alignment: 'feet', list: tail, seed: seed++ }; }
|
||||||
|
|
||||||
// if the stack contains only one element, we don't create a stack but return the
|
// if the stack contains only one element, we don't create a stack but return the
|
||||||
// underlying element
|
// underlying element
|
||||||
stack_or_choose = head:sequence tail:(stack_tail / choose_tail)?
|
stack_or_choose = head:sequence tail:(stack_tail / choose_tail / dot_tail)?
|
||||||
{ if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment, tail.seed); } else { return head; } }
|
{ if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment, tail.seed); } else { return head; } }
|
||||||
|
|
||||||
polymeter_stack = head:sequence tail:stack_tail?
|
polymeter_stack = head:sequence tail:stack_tail?
|
||||||
@@ -287,4 +293,4 @@ Lt = [\u01C5\u01C8\u01CB\u01F2\u1F88-\u1F8F\u1F98-\u1F9F\u1FA8-\u1FAF\u1FBC\u1FC
|
|||||||
Lu = [\u0041-\u005A\u00C0-\u00D6\u00D8-\u00DE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178-\u0179\u017B\u017D\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018B\u018E-\u0191\u0193-\u0194\u0196-\u0198\u019C-\u019D\u019F-\u01A0\u01A2\u01A4\u01A6-\u01A7\u01A9\u01AC\u01AE-\u01AF\u01B1-\u01B3\u01B5\u01B7-\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A-\u023B\u023D-\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E-\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9-\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0-\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u13A0-\u13F5\u1C90-\u1CBA\u1CBD-\u1CBF\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E-\u213F\u2145\u2183\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D-\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AE\uA7B0-\uA7B4\uA7B6\uA7B8\uFF21-\uFF3A]
|
Lu = [\u0041-\u005A\u00C0-\u00D6\u00D8-\u00DE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178-\u0179\u017B\u017D\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018B\u018E-\u0191\u0193-\u0194\u0196-\u0198\u019C-\u019D\u019F-\u01A0\u01A2\u01A4\u01A6-\u01A7\u01A9\u01AC\u01AE-\u01AF\u01B1-\u01B3\u01B5\u01B7-\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A-\u023B\u023D-\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E-\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9-\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0-\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u13A0-\u13F5\u1C90-\u1CBA\u1CBD-\u1CBF\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E-\u213F\u2145\u2183\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D-\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AE\uA7B0-\uA7B4\uA7B6\uA7B8\uFF21-\uFF3A]
|
||||||
|
|
||||||
// Number, Letter
|
// Number, Letter
|
||||||
Nl = [\u16EE-\u16F0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303A\uA6E6-\uA6EF]
|
Nl = [\u16EE-\u16F0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303A\uA6E6-\uA6EF]
|
||||||
|
|||||||
@@ -107,6 +107,9 @@ export function patternifyAST(ast, code, onEnter, offset = 0) {
|
|||||||
if (alignment === 'rand') {
|
if (alignment === 'rand') {
|
||||||
return strudel.chooseInWith(strudel.rand.early(randOffset * ast.arguments_.seed).segment(1), children);
|
return strudel.chooseInWith(strudel.rand.early(randOffset * ast.arguments_.seed).segment(1), children);
|
||||||
}
|
}
|
||||||
|
if (alignment === 'feet') {
|
||||||
|
return strudel.fastcat(...children);
|
||||||
|
}
|
||||||
const weightedChildren = ast.source_.some((child) => !!child.options_?.weight);
|
const weightedChildren = ast.source_.some((child) => !!child.options_?.weight);
|
||||||
if (weightedChildren) {
|
if (weightedChildren) {
|
||||||
const weightSum = ast.source_.reduce((sum, child) => sum + (child.options_?.weight || 1), 0);
|
const weightSum = ast.source_.reduce((sum, child) => sum + (child.options_?.weight || 1), 0);
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/mini",
|
"name": "@strudel/mini",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Mini notation for strudel",
|
"description": "Mini notation for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ describe('mini', () => {
|
|||||||
expect(minS('a!3 b')).toEqual(['a: 0 - 1/4', 'a: 1/4 - 1/2', 'a: 1/2 - 3/4', 'b: 3/4 - 1']);
|
expect(minS('a!3 b')).toEqual(['a: 0 - 1/4', 'a: 1/4 - 1/2', 'a: 1/2 - 3/4', 'b: 3/4 - 1']);
|
||||||
expect(minS('[<a b c>]!3 d')).toEqual(minS('<a b c> <a b c> <a b c> d'));
|
expect(minS('[<a b c>]!3 d')).toEqual(minS('<a b c> <a b c> <a b c> d'));
|
||||||
});
|
});
|
||||||
|
it('supports replication via repeated !', () => {
|
||||||
|
expect(minS('a ! ! b')).toEqual(['a: 0 - 1/4', 'a: 1/4 - 1/2', 'a: 1/2 - 3/4', 'b: 3/4 - 1']);
|
||||||
|
expect(minS('[<a b c>]!! d')).toEqual(minS('<a b c> <a b c> <a b c> d'));
|
||||||
|
});
|
||||||
it('supports euclidean rhythms', () => {
|
it('supports euclidean rhythms', () => {
|
||||||
expect(minS('a(3, 8)')).toEqual(['a: 0 - 1/8', 'a: 3/8 - 1/2', 'a: 3/4 - 7/8']);
|
expect(minS('a(3, 8)')).toEqual(['a: 0 - 1/8', 'a: 3/8 - 1/2', 'a: 3/4 - 7/8']);
|
||||||
});
|
});
|
||||||
@@ -190,6 +194,16 @@ describe('mini', () => {
|
|||||||
it('supports patterned ranges', () => {
|
it('supports patterned ranges', () => {
|
||||||
expect(minS('[<0 1> .. <2 4>]*2')).toEqual(minS('[0 1 2] [1 2 3 4]'));
|
expect(minS('[<0 1> .. <2 4>]*2')).toEqual(minS('[0 1 2] [1 2 3 4]'));
|
||||||
});
|
});
|
||||||
|
it('supports the . operator', () => {
|
||||||
|
expect(minS('a . b c')).toEqual(minS('a [b c]'));
|
||||||
|
expect(minS('a . b c . [d e f . g h]')).toEqual(minS('a [b c] [[d e f] [g h]]'));
|
||||||
|
});
|
||||||
|
it('supports the _ operator', () => {
|
||||||
|
expect(minS('a _ b _ _')).toEqual(minS('a@2 b@3'));
|
||||||
|
});
|
||||||
|
it('_ and @ are almost interchangeable', () => {
|
||||||
|
expect(minS('a @ b @ @')).toEqual(minS('a _2 b _3'));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getLeafLocation', () => {
|
describe('getLeafLocation', () => {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/osc",
|
"name": "@strudel/osc",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "OSC messaging for strudel",
|
"description": "OSC messaging for strudel",
|
||||||
"main": "osc.mjs",
|
"main": "osc.mjs",
|
||||||
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"server": "node server.js",
|
"server": "node server.js",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'osc.mjs'),
|
entry: resolve(__dirname, 'osc.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
# @strudel/repl
|
# @strudel/repl
|
||||||
|
|
||||||
The Strudel REPL as a web component.
|
The Strudel REPL as a web component.
|
||||||
|
|
||||||
|
[Usage example](https://github.com/tidalcycles/strudel/blob/main/examples/buildless/web-component-no-iframe.html)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/repl",
|
"name": "@strudel/repl",
|
||||||
"version": "0.11.0",
|
"version": "1.0.2",
|
||||||
"description": "Strudel REPL as a Web Component",
|
"description": "Strudel REPL as a Web Component",
|
||||||
"main": "index.mjs",
|
"module": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/index.mjs"
|
"module": "dist/index.mjs"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { controls, noteToMidi, valueToMidi, Pattern, evalScope } from '@strudel/core';
|
import { noteToMidi, valueToMidi, Pattern, evalScope } from '@strudel/core';
|
||||||
import { registerSynthSounds, registerZZFXSounds, samples } from '@strudel/webaudio';
|
import { registerSynthSounds, registerZZFXSounds, samples } from '@strudel/webaudio';
|
||||||
import * as core from '@strudel/core';
|
import * as core from '@strudel/core';
|
||||||
|
|
||||||
@@ -17,7 +17,6 @@ export async function prebake() {
|
|||||||
// import('@strudel/serial'),
|
// import('@strudel/serial'),
|
||||||
// import('@strudel/csound'),
|
// import('@strudel/csound'),
|
||||||
// import('@strudel/osc'),
|
// import('@strudel/osc'),
|
||||||
controls, // sadly, this cannot be exported from core directly (yet)
|
|
||||||
);
|
);
|
||||||
// load samples
|
// load samples
|
||||||
const ds = 'https://raw.githubusercontent.com/felixroos/dough-samples/main/';
|
const ds = 'https://raw.githubusercontent.com/felixroos/dough-samples/main/';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/serial",
|
"name": "@strudel/serial",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Webserial API for strudel",
|
"description": "Webserial API for strudel",
|
||||||
"main": "serial.mjs",
|
"main": "serial.mjs",
|
||||||
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'serial.mjs'),
|
entry: resolve(__dirname, 'serial.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/soundfonts",
|
"name": "@strudel/soundfonts",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Soundsfont support for strudel",
|
"description": "Soundsfont support for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { superdough, samples, initAudioOnFirstClick, registerSynthSounds } from
|
|||||||
|
|
||||||
const init = Promise.all([
|
const init = Promise.all([
|
||||||
initAudioOnFirstClick(),
|
initAudioOnFirstClick(),
|
||||||
samples('github:tidalcycles/Dirt-Samples/master'),
|
samples('github:tidalcycles/dirt-samples'),
|
||||||
registerSynthSounds(),
|
registerSynthSounds(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ The json file is expected to have the same format as described above.
|
|||||||
Because it is common to use github for samples, there is a short way to load a sample map from github:
|
Because it is common to use github for samples, there is a short way to load a sample map from github:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
samples('github:tidalcycles/Dirt-Samples/master')
|
samples('github:tidalcycles/dirt-samples')
|
||||||
```
|
```
|
||||||
|
|
||||||
The format is `github:<user>/<repo>/<branch>`.
|
The format is `github:<user>/<repo>/<branch>`.
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "superdough",
|
"name": "superdough",
|
||||||
"version": "0.10.0",
|
"version": "1.0.1",
|
||||||
"description": "simple web audio synth and sampler intended for live coding. inspired by superdirt and webdirt.",
|
"description": "simple web audio synth and sampler intended for live coding. inspired by superdirt and webdirt.",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.cjs",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"directories": {
|
"directories": {
|
||||||
"example": "examples"
|
"example": "examples"
|
||||||
|
|||||||
@@ -99,6 +99,27 @@ export const getLoadedBuffer = (url) => {
|
|||||||
return bufferCache[url];
|
return bufferCache[url];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function resolveSpecialPaths(base) {
|
||||||
|
if (base.startsWith('bubo:')) {
|
||||||
|
const [_, repo] = base.split(':');
|
||||||
|
base = `github:Bubobubobubobubo/dough-${repo}`;
|
||||||
|
}
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
function githubPath(base, subpath = '') {
|
||||||
|
if (!base.startsWith('github:')) {
|
||||||
|
throw new Error('expected "github:" at the start of pseudoUrl');
|
||||||
|
}
|
||||||
|
let [_, path] = base.split('github:');
|
||||||
|
path = path.endsWith('/') ? path.slice(0, -1) : path;
|
||||||
|
if (path.split('/').length === 2) {
|
||||||
|
// assume main as default branch if none set
|
||||||
|
path += '/main';
|
||||||
|
}
|
||||||
|
return `https://raw.githubusercontent.com/${path}/${subpath}`;
|
||||||
|
}
|
||||||
|
|
||||||
export const processSampleMap = (sampleMap, fn, baseUrl = sampleMap._base || '') => {
|
export const processSampleMap = (sampleMap, fn, baseUrl = sampleMap._base || '') => {
|
||||||
return Object.entries(sampleMap).forEach(([key, value]) => {
|
return Object.entries(sampleMap).forEach(([key, value]) => {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
@@ -108,15 +129,19 @@ export const processSampleMap = (sampleMap, fn, baseUrl = sampleMap._base || '')
|
|||||||
throw new Error('wrong sample map format for ' + key);
|
throw new Error('wrong sample map format for ' + key);
|
||||||
}
|
}
|
||||||
baseUrl = value._base || baseUrl;
|
baseUrl = value._base || baseUrl;
|
||||||
const replaceUrl = (v) => (baseUrl + v).replace('github:', 'https://raw.githubusercontent.com/');
|
baseUrl = resolveSpecialPaths(baseUrl);
|
||||||
|
if (baseUrl.startsWith('github:')) {
|
||||||
|
baseUrl = githubPath(baseUrl, '');
|
||||||
|
}
|
||||||
|
const fullUrl = (v) => baseUrl + v;
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
//return [key, value.map(replaceUrl)];
|
//return [key, value.map(replaceUrl)];
|
||||||
value = value.map(replaceUrl);
|
value = value.map(fullUrl);
|
||||||
} else {
|
} else {
|
||||||
// must be object
|
// must be object
|
||||||
value = Object.fromEntries(
|
value = Object.fromEntries(
|
||||||
Object.entries(value).map(([note, samples]) => {
|
Object.entries(value).map(([note, samples]) => {
|
||||||
return [note, (typeof samples === 'string' ? [samples] : samples).map(replaceUrl)];
|
return [note, (typeof samples === 'string' ? [samples] : samples).map(fullUrl)];
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -142,7 +167,7 @@ function getSamplesPrefixHandler(url) {
|
|||||||
/**
|
/**
|
||||||
* Loads a collection of samples to use with `s`
|
* Loads a collection of samples to use with `s`
|
||||||
* @example
|
* @example
|
||||||
* samples('github:tidalcycles/Dirt-Samples/master');
|
* samples('github:tidalcycles/dirt-samples');
|
||||||
* s("[bd ~]*2, [~ hh]*2, ~ sd")
|
* s("[bd ~]*2, [~ hh]*2, ~ sd")
|
||||||
* @example
|
* @example
|
||||||
* samples({
|
* samples({
|
||||||
@@ -165,18 +190,9 @@ export const samples = async (sampleMap, baseUrl = sampleMap._base || '', option
|
|||||||
if (handler) {
|
if (handler) {
|
||||||
return handler(sampleMap);
|
return handler(sampleMap);
|
||||||
}
|
}
|
||||||
if (sampleMap.startsWith('bubo:')) {
|
sampleMap = resolveSpecialPaths(sampleMap);
|
||||||
const [_, repo] = sampleMap.split(':');
|
|
||||||
sampleMap = `github:Bubobubobubobubo/dough-${repo}`;
|
|
||||||
}
|
|
||||||
if (sampleMap.startsWith('github:')) {
|
if (sampleMap.startsWith('github:')) {
|
||||||
let [_, path] = sampleMap.split('github:');
|
sampleMap = githubPath(sampleMap, 'strudel.json');
|
||||||
path = path.endsWith('/') ? path.slice(0, -1) : path;
|
|
||||||
if (path.split('/').length === 2) {
|
|
||||||
// assume main as default branch if none set
|
|
||||||
path += '/main';
|
|
||||||
}
|
|
||||||
sampleMap = `https://raw.githubusercontent.com/${path}/strudel.json`;
|
|
||||||
}
|
}
|
||||||
if (sampleMap.startsWith('shabda:')) {
|
if (sampleMap.startsWith('shabda:')) {
|
||||||
let [_, path] = sampleMap.split('shabda:');
|
let [_, path] = sampleMap.split('shabda:');
|
||||||
@@ -235,7 +251,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
|||||||
nudge = 0, // TODO: is this in seconds?
|
nudge = 0, // TODO: is this in seconds?
|
||||||
cut,
|
cut,
|
||||||
loop,
|
loop,
|
||||||
clip = undefined, // if 1, samples will be cut off when the hap ends
|
clip = undefined, // if set, 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
|
||||||
|
|||||||
@@ -253,6 +253,11 @@ function effectSend(input, effect, wet) {
|
|||||||
return send;
|
return send;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resetGlobalEffects() {
|
||||||
|
delays = {};
|
||||||
|
reverbs = {};
|
||||||
|
}
|
||||||
|
|
||||||
export const superdough = async (value, deadline, hapDuration) => {
|
export const superdough = async (value, deadline, hapDuration) => {
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
if (typeof value !== 'object') {
|
if (typeof value !== 'object') {
|
||||||
@@ -513,6 +518,7 @@ export const superdough = async (value, deadline, hapDuration) => {
|
|||||||
// toDisconnect = all the node that should be disconnected in onended callback
|
// toDisconnect = all the node that should be disconnected in onended callback
|
||||||
// this is crucial for performance
|
// this is crucial for performance
|
||||||
toDisconnect = chain.concat([delaySend, reverbSend, analyserSend]);
|
toDisconnect = chain.concat([delaySend, reverbSend, analyserSend]);
|
||||||
|
return { mute: (dt) => post.gain.linearRampToValueAtTime(0, ac.currentTime + dt) };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const superdoughTrigger = (t, hap, ct, cps) => superdough(hap, t - ct, hap.duration / cps, cps);
|
export const superdoughTrigger = (t, hap, ct, cps) => superdough(hap, t - ct, hap.duration / cps, cps);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.cjs' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.cjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/tonal",
|
"name": "@strudel/tonal",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Tonal functions for strudel",
|
"description": "Tonal functions for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
// import { strict as assert } from 'assert';
|
// import { strict as assert } from 'assert';
|
||||||
|
|
||||||
import '../tonal.mjs'; // need to import this to add prototypes
|
import '../tonal.mjs'; // need to import this to add prototypes
|
||||||
import { pure, controls, seq } from '@strudel/core';
|
import { pure, n, seq } from '@strudel/core';
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { mini } from '../../mini/mini.mjs';
|
import { mini } from '../../mini/mini.mjs';
|
||||||
const { n } = controls;
|
|
||||||
|
|
||||||
describe('tonal', () => {
|
describe('tonal', () => {
|
||||||
it('Should run tonal functions ', () => {
|
it('Should run tonal functions ', () => {
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ export const transpose = register('transpose', function (intervalOrSemitones, pa
|
|||||||
const semitones = typeof interval === 'string' ? Interval.semitones(interval) || 0 : interval;
|
const semitones = typeof interval === 'string' ? Interval.semitones(interval) || 0 : interval;
|
||||||
return hap.withValue(() => hap.value + semitones);
|
return hap.withValue(() => hap.value + semitones);
|
||||||
}
|
}
|
||||||
|
if (typeof hap.value === 'object')
|
||||||
|
return hap.withValue(() => ({ ...hap.value, note: Note.simplify(Note.transpose(hap.value.note, interval)) }));
|
||||||
// TODO: move simplify to player to preserve enharmonics
|
// TODO: move simplify to player to preserve enharmonics
|
||||||
// tone.js doesn't understand multiple sharps flats e.g. F##3 has to be turned into G3
|
// tone.js doesn't understand multiple sharps flats e.g. F##3 has to be turned into G3
|
||||||
return hap.withValue(() => Note.simplify(Note.transpose(hap.value, interval)));
|
return hap.withValue(() => Note.simplify(Note.transpose(hap.value, interval)));
|
||||||
@@ -133,6 +135,11 @@ export const scaleTranspose = register('scaleTranspose', function (offset /* : n
|
|||||||
if (!hap.context.scale) {
|
if (!hap.context.scale) {
|
||||||
throw new Error('can only use scaleTranspose after .scale');
|
throw new Error('can only use scaleTranspose after .scale');
|
||||||
}
|
}
|
||||||
|
if (typeof hap.value === 'object')
|
||||||
|
return hap.withValue(() => ({
|
||||||
|
...hap.value,
|
||||||
|
note: scaleOffset(hap.context.scale, Number(offset), hap.value.note),
|
||||||
|
}));
|
||||||
if (typeof hap.value !== 'string') {
|
if (typeof hap.value !== 'string') {
|
||||||
throw new Error('can only use scaleTranspose with notes');
|
throw new Error('can only use scaleTranspose with notes');
|
||||||
}
|
}
|
||||||
@@ -157,9 +164,9 @@ export const scaleTranspose = register('scaleTranspose', function (offset /* : n
|
|||||||
* .scale("C:<major minor>/2")
|
* .scale("C:<major minor>/2")
|
||||||
* .s("piano")
|
* .s("piano")
|
||||||
* @example
|
* @example
|
||||||
* n(rand.range(0,12).segment(8).round())
|
* n(rand.range(0,12).segment(8))
|
||||||
* .scale("C:ritusen")
|
* .scale("C:ritusen")
|
||||||
* .s("folkharp")
|
* .s("piano")
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const scale = register('scale', function (scale, pat) {
|
export const scale = register('scale', function (scale, pat) {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/transpiler",
|
"name": "@strudel/transpiler",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"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",
|
||||||
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ describe('transpiler', () => {
|
|||||||
it('supports top level await', () => {
|
it('supports top level await', () => {
|
||||||
expect(transpiler("await samples('xxx');", simple).output).toEqual("await samples('xxx');");
|
expect(transpiler("await samples('xxx');", simple).output).toEqual("await samples('xxx');");
|
||||||
});
|
});
|
||||||
|
it('adds await to bare samples call', () => {
|
||||||
|
expect(transpiler("samples('xxx');", simple).output).toEqual("await samples('xxx');");
|
||||||
|
});
|
||||||
/* it('parses dynamic imports', () => {
|
/* it('parses dynamic imports', () => {
|
||||||
expect(
|
expect(
|
||||||
transpiler("const { default: foo } = await import('https://bar.com/foo.js');", {
|
transpiler("const { default: foo } = await import('https://bar.com/foo.js');", {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import escodegen from 'escodegen';
|
|
||||||
import { parse } from 'acorn';
|
|
||||||
import { walk } from 'estree-walker';
|
|
||||||
import { isNoteWithOctave } from '@strudel/core';
|
|
||||||
import { getLeafLocations } from '@strudel/mini';
|
import { getLeafLocations } from '@strudel/mini';
|
||||||
|
import { parse } from 'acorn';
|
||||||
|
import escodegen from 'escodegen';
|
||||||
|
import { walk } from 'estree-walker';
|
||||||
|
|
||||||
export function transpiler(input, options = {}) {
|
export function transpiler(input, options = {}) {
|
||||||
const { wrapAsync = false, addReturn = true, emitMiniLocations = true, emitWidgets = true } = options;
|
const { wrapAsync = false, addReturn = true, emitMiniLocations = true, emitWidgets = true } = options;
|
||||||
@@ -47,6 +46,9 @@ export function transpiler(input, options = {}) {
|
|||||||
});
|
});
|
||||||
return this.replace(widgetWithLocation(node));
|
return this.replace(widgetWithLocation(node));
|
||||||
}
|
}
|
||||||
|
if (isBareSamplesCall(node, parent)) {
|
||||||
|
return this.replace(withAwait(node));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
leave(node, parent, prop, index) {},
|
leave(node, parent, prop, index) {},
|
||||||
});
|
});
|
||||||
@@ -119,3 +121,14 @@ function widgetWithLocation(node) {
|
|||||||
node.callee.name = 'sliderWithID';
|
node.callee.name = 'sliderWithID';
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isBareSamplesCall(node, parent) {
|
||||||
|
return node.type === 'CallExpression' && node.callee.name === 'samples' && parent.type !== 'AwaitExpression';
|
||||||
|
}
|
||||||
|
|
||||||
|
function withAwait(node) {
|
||||||
|
return {
|
||||||
|
type: 'AwaitExpression',
|
||||||
|
argument: node,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ By default, no external samples are loaded, but you can add them like this:
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
initStrudel({
|
initStrudel({
|
||||||
prebake: () => samples('github:tidalcycles/Dirt-Samples/master'),
|
prebake: () => samples('github:tidalcycles/dirt-samples'),
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('play').addEventListener('click',
|
document.getElementById('play').addEventListener('click',
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/web",
|
"name": "@strudel/web",
|
||||||
"version": "0.11.0",
|
"version": "1.0.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",
|
"module": "web.mjs",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/index.mjs"
|
"module": "dist/index.mjs"
|
||||||
@@ -37,7 +37,8 @@
|
|||||||
"@strudel/mini": "workspace:*",
|
"@strudel/mini": "workspace:*",
|
||||||
"@strudel/tonal": "workspace:*",
|
"@strudel/tonal": "workspace:*",
|
||||||
"@strudel/transpiler": "workspace:*",
|
"@strudel/transpiler": "workspace:*",
|
||||||
"@strudel/webaudio": "workspace:*"
|
"@strudel/webaudio": "workspace:*",
|
||||||
|
"@rollup/plugin-replace": "^5.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^5.0.10"
|
"vite": "^5.0.10"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import { dependencies } from './package.json';
|
import { dependencies } from './package.json';
|
||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
|
import replace from '@rollup/plugin-replace';
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@@ -8,11 +9,18 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'web.mjs'),
|
entry: resolve(__dirname, 'web.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
name: 'strudel',
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
formats: ['es', 'iife'],
|
||||||
|
fileName: (ext) => ({ es: 'index.mjs', iife: 'index.js' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
// external: [...Object.keys(dependencies)],
|
||||||
|
plugins: [
|
||||||
|
replace({
|
||||||
|
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||||
|
preventAssignment: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
target: 'esnext',
|
target: 'esnext',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export * from '@strudel/transpiler';
|
|||||||
export * from '@strudel/mini';
|
export * from '@strudel/mini';
|
||||||
export * from '@strudel/tonal';
|
export * from '@strudel/tonal';
|
||||||
export * from '@strudel/webaudio';
|
export * from '@strudel/webaudio';
|
||||||
import { Pattern, evalScope, controls } from '@strudel/core';
|
import { Pattern, evalScope } from '@strudel/core';
|
||||||
import { initAudioOnFirstClick, registerSynthSounds, webaudioScheduler } from '@strudel/webaudio';
|
import { initAudioOnFirstClick, registerSynthSounds, webaudioScheduler } from '@strudel/webaudio';
|
||||||
// import { registerSoundfonts } from '@strudel/soundfonts';
|
// import { registerSoundfonts } from '@strudel/soundfonts';
|
||||||
import { evaluate as _evaluate } from '@strudel/transpiler';
|
import { evaluate as _evaluate } from '@strudel/transpiler';
|
||||||
@@ -15,7 +15,6 @@ import { miniAllStrings } from '@strudel/mini';
|
|||||||
export async function defaultPrebake() {
|
export async function defaultPrebake() {
|
||||||
const loadModules = evalScope(
|
const loadModules = evalScope(
|
||||||
evalScope,
|
evalScope,
|
||||||
controls,
|
|
||||||
import('@strudel/core'),
|
import('@strudel/core'),
|
||||||
import('@strudel/mini'),
|
import('@strudel/mini'),
|
||||||
import('@strudel/tonal'),
|
import('@strudel/tonal'),
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ npm i @strudel/webaudio --save
|
|||||||
## Example
|
## Example
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { repl, controls } from "@strudel/core";
|
import { repl, note } from "@strudel/core";
|
||||||
import { initAudioOnFirstClick, getAudioContext, webaudioOutput } from "@strudel/webaudio";
|
import { initAudioOnFirstClick, getAudioContext, webaudioOutput } from "@strudel/webaudio";
|
||||||
const { note } = controls;
|
|
||||||
|
|
||||||
initAudioOnFirstClick();
|
initAudioOnFirstClick();
|
||||||
const ctx = getAudioContext();
|
const ctx = getAudioContext();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/webaudio",
|
"name": "@strudel/webaudio",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Web Audio helpers for Strudel",
|
"description": "Web Audio helpers for Strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -8,8 +8,7 @@
|
|||||||
"example": "examples"
|
"example": "examples"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"example": "npx parcel examples/repl.html",
|
"example": "npx parcel examples/repl.html",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ const hap2value = (hap) => {
|
|||||||
return { ...hap.value, velocity: hap.context.velocity };
|
return { ...hap.value, velocity: hap.context.velocity };
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: bind logger
|
|
||||||
export const webaudioOutputTrigger = (t, hap, ct, cps) => superdough(hap2value(hap), t - ct, hap.duration / cps, cps);
|
export const webaudioOutputTrigger = (t, hap, ct, cps) => superdough(hap2value(hap), t - ct, hap.duration / cps, cps);
|
||||||
export const webaudioOutput = (hap, deadline, hapDuration) => superdough(hap2value(hap), deadline, hapDuration);
|
export const webaudioOutput = (hap, deadline, hapDuration) => superdough(hap2value(hap), deadline, hapDuration);
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@strudel/xen",
|
"name": "@strudel/xen",
|
||||||
"version": "0.11.0",
|
"version": "1.0.1",
|
||||||
"description": "Xenharmonic API for strudel",
|
"description": "Xenharmonic API for strudel",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
|
"type": "module",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.mjs"
|
||||||
"module": "dist/index.mjs"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'index.mjs'),
|
entry: resolve(__dirname, 'index.mjs'),
|
||||||
formats: ['es', 'cjs'],
|
formats: ['es'],
|
||||||
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
|
fileName: (ext) => ({ es: 'index.mjs' })[ext],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: [...Object.keys(dependencies)],
|
external: [...Object.keys(dependencies)],
|
||||||
|
|||||||
Generated
+60
-7
@@ -430,6 +430,9 @@ importers:
|
|||||||
|
|
||||||
packages/web:
|
packages/web:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@rollup/plugin-replace':
|
||||||
|
specifier: ^5.0.5
|
||||||
|
version: 5.0.5
|
||||||
'@strudel/core':
|
'@strudel/core':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../core
|
version: link:../core
|
||||||
@@ -476,20 +479,29 @@ importers:
|
|||||||
specifier: ^1.1.0
|
specifier: ^1.1.0
|
||||||
version: 1.1.0(@vitest/ui@1.1.0)
|
version: 1.1.0(@vitest/ui@1.1.0)
|
||||||
|
|
||||||
|
tools/dbpatch:
|
||||||
|
dependencies:
|
||||||
|
csv:
|
||||||
|
specifier: ^6.3.6
|
||||||
|
version: 6.3.6
|
||||||
|
|
||||||
website:
|
website:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@algolia/client-search':
|
'@algolia/client-search':
|
||||||
specifier: ^4.22.0
|
specifier: ^4.22.0
|
||||||
version: 4.22.0
|
version: 4.22.0
|
||||||
'@astro-community/astro-embed-youtube':
|
'@astro-community/astro-embed-youtube':
|
||||||
specifier: ^0.4.3
|
specifier: ^0.4.4
|
||||||
version: 0.4.3(astro@4.0.8)
|
version: 0.4.4(astro@4.0.8)
|
||||||
'@astrojs/mdx':
|
'@astrojs/mdx':
|
||||||
specifier: ^2.0.3
|
specifier: ^2.0.3
|
||||||
version: 2.0.3(astro@4.0.8)
|
version: 2.0.3(astro@4.0.8)
|
||||||
'@astrojs/react':
|
'@astrojs/react':
|
||||||
specifier: ^3.0.9
|
specifier: ^3.0.9
|
||||||
version: 3.0.9(@types/react-dom@18.2.18)(@types/react@18.2.46)(react-dom@18.2.0)(react@18.2.0)(vite@5.0.11)
|
version: 3.0.9(@types/react-dom@18.2.18)(@types/react@18.2.46)(react-dom@18.2.0)(react@18.2.0)(vite@5.0.11)
|
||||||
|
'@astrojs/rss':
|
||||||
|
specifier: ^4.0.2
|
||||||
|
version: 4.0.2
|
||||||
'@astrojs/tailwind':
|
'@astrojs/tailwind':
|
||||||
specifier: ^5.1.0
|
specifier: ^5.1.0
|
||||||
version: 5.1.0(astro@4.0.8)(tailwindcss@3.4.0)
|
version: 5.1.0(astro@4.0.8)(tailwindcss@3.4.0)
|
||||||
@@ -803,8 +815,8 @@ packages:
|
|||||||
leven: 3.1.0
|
leven: 3.1.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@astro-community/astro-embed-youtube@0.4.3(astro@4.0.8):
|
/@astro-community/astro-embed-youtube@0.4.4(astro@4.0.8):
|
||||||
resolution: {integrity: sha512-zXtPmR9yxrTo6cuLhH8v+r62bsXbsLJgsU2FiZalPr4bXJxAUQEIlG46S/qK0AEXi9uNShKqy4+zBaJ98xTVEg==}
|
resolution: {integrity: sha512-fYlycLrJFNnibZ9VHPSJO766kO2IgqYQU4mBd4iaDMaicL0gGX9cVZ80QdnpzGrI6w0XOJOY7prx86eWEVBy8w==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
astro: ^2.0.0 || ^3.0.0-beta || ^4.0.0-beta
|
astro: ^2.0.0 || ^3.0.0-beta || ^4.0.0-beta
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -890,6 +902,13 @@ packages:
|
|||||||
- vite
|
- vite
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@astrojs/rss@4.0.2:
|
||||||
|
resolution: {integrity: sha512-Hb9GKAyvsn5EUjZtB6SniesBScMQe7SQinEHLY5EFa74QEvgcWaXTmA0Mb0P3vqDSN3d/NTYbGivprrSAawfnA==}
|
||||||
|
dependencies:
|
||||||
|
fast-xml-parser: 4.3.3
|
||||||
|
kleur: 4.1.5
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@astrojs/tailwind@5.1.0(astro@4.0.8)(tailwindcss@3.4.0):
|
/@astrojs/tailwind@5.1.0(astro@4.0.8)(tailwindcss@3.4.0):
|
||||||
resolution: {integrity: sha512-BJoCDKuWhU9FT2qYg+fr6Nfb3qP4ShtyjXGHKA/4mHN94z7BGcmauQK23iy+YH5qWvTnhqkd6mQPQ1yTZTe9Ig==}
|
resolution: {integrity: sha512-BJoCDKuWhU9FT2qYg+fr6Nfb3qP4ShtyjXGHKA/4mHN94z7BGcmauQK23iy+YH5qWvTnhqkd6mQPQ1yTZTe9Ig==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3675,7 +3694,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 5.1.0
|
'@rollup/pluginutils': 5.1.0
|
||||||
magic-string: 0.30.5
|
magic-string: 0.30.5
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@rollup/pluginutils@3.1.0(rollup@2.79.1):
|
/@rollup/pluginutils@3.1.0(rollup@2.79.1):
|
||||||
resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
|
resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
|
||||||
@@ -3701,7 +3719,6 @@ packages:
|
|||||||
'@types/estree': 1.0.0
|
'@types/estree': 1.0.0
|
||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@rollup/rollup-android-arm-eabi@4.9.2:
|
/@rollup/rollup-android-arm-eabi@4.9.2:
|
||||||
resolution: {integrity: sha512-RKzxFxBHq9ysZ83fn8Iduv3A283K7zPPYuhL/z9CQuyFrjwpErJx0h4aeb/bnJ+q29GRLgJpY66ceQ/Wcsn3wA==}
|
resolution: {integrity: sha512-RKzxFxBHq9ysZ83fn8Iduv3A283K7zPPYuhL/z9CQuyFrjwpErJx0h4aeb/bnJ+q29GRLgJpY66ceQ/Wcsn3wA==}
|
||||||
@@ -6213,6 +6230,28 @@ packages:
|
|||||||
resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==}
|
resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/csv-generate@4.3.1:
|
||||||
|
resolution: {integrity: sha512-7YeeJq+44/I/O5N2sr2qBMcHZXhpfe38eh7DOFxyMtYO+Pir7kIfgFkW5MPksqKqqR6+/wX7UGoZm1Ot11151w==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/csv-parse@5.5.3:
|
||||||
|
resolution: {integrity: sha512-v0KW6C0qlZzoGjk6u5tLmVfyZxNgPGXZsWTXshpAgKVGmGXzaVWGdlCFxNx5iuzcXT/oJN1HHM9DZKwtAtYa+A==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/csv-stringify@6.4.5:
|
||||||
|
resolution: {integrity: sha512-SPu1Vnh8U5EnzpNOi1NDBL5jU5Rx7DVHr15DNg9LXDTAbQlAVAmEbVt16wZvEW9Fu9Qt4Ji8kmeCJ2B1+4rFTQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/csv@6.3.6:
|
||||||
|
resolution: {integrity: sha512-jsEsX2HhGp7xiwrJu5srQavKsh+HUJcCi78Ar3m4jlmFKRoTkkMy7ZZPP+LnQChmaztW+uj44oyfMb59daAs/Q==}
|
||||||
|
engines: {node: '>= 0.1.90'}
|
||||||
|
dependencies:
|
||||||
|
csv-generate: 4.3.1
|
||||||
|
csv-parse: 5.5.3
|
||||||
|
csv-stringify: 6.4.5
|
||||||
|
stream-transform: 3.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/dargs@7.0.0:
|
/dargs@7.0.0:
|
||||||
resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==}
|
resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -7080,7 +7119,6 @@ packages:
|
|||||||
|
|
||||||
/estree-walker@2.0.2:
|
/estree-walker@2.0.2:
|
||||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/estree-walker@3.0.3:
|
/estree-walker@3.0.3:
|
||||||
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
||||||
@@ -7182,6 +7220,13 @@ packages:
|
|||||||
/fast-levenshtein@2.0.6:
|
/fast-levenshtein@2.0.6:
|
||||||
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
|
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
|
||||||
|
|
||||||
|
/fast-xml-parser@4.3.3:
|
||||||
|
resolution: {integrity: sha512-coV/D1MhrShMvU6D0I+VAK3umz6hUaxxhL0yp/9RjfiYUfAv14rDhGQL+PLForhMdr0wq3PiV07WtkkNjJjNHg==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
strnum: 1.0.5
|
||||||
|
dev: false
|
||||||
|
|
||||||
/fastq@1.15.0:
|
/fastq@1.15.0:
|
||||||
resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
|
resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -12457,6 +12502,10 @@ packages:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
/stream-transform@3.3.0:
|
||||||
|
resolution: {integrity: sha512-pG1NeDdmErNYKtvTpFayrEueAmL0xVU5wd22V7InGnatl4Ocq3HY7dcXIKj629kXvYQvglCC7CeDIGAlx1RNGA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/stream-via@1.0.4:
|
/stream-via@1.0.4:
|
||||||
resolution: {integrity: sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==}
|
resolution: {integrity: sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -12637,6 +12686,10 @@ packages:
|
|||||||
acorn: 8.11.3
|
acorn: 8.11.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/strnum@1.0.5:
|
||||||
|
resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/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==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|||||||
@@ -2,4 +2,5 @@ packages:
|
|||||||
# all packages in direct subdirs of packages/
|
# all packages in direct subdirs of packages/
|
||||||
- "packages/*"
|
- "packages/*"
|
||||||
- "examples/*"
|
- "examples/*"
|
||||||
|
- "tools/dbpatch"
|
||||||
- "website/"
|
- "website/"
|
||||||
|
|||||||
+3426
-1583
File diff suppressed because it is too large
Load Diff
@@ -339,402 +339,6 @@ exports[`renders tunes > tune: blippyRhodes 1`] = `
|
|||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders tunes > tune: bridgeIsOver 1`] = `
|
|
||||||
[
|
|
||||||
"[ -155/52 ⇜ (0/1 → 5/52) | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ -75/26 ⇜ (0/1 → 5/26) | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ -145/52 ⇜ (0/1 → 15/52) | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ -35/13 ⇜ (0/1 → 5/13) | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ -35/13 ⇜ (0/1 → 5/13) | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ -135/52 ⇜ (0/1 → 5/13) ⇝ 25/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ -5/2 ⇜ (0/1 → 5/13) ⇝ 15/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ -125/52 ⇜ (0/1 → 5/13) ⇝ 35/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ -30/13 ⇜ (0/1 → 5/13) ⇝ 10/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ -115/52 ⇜ (0/1 → 5/13) ⇝ 45/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ -55/26 ⇜ (0/1 → 5/13) ⇝ 25/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ -105/52 ⇜ (0/1 → 5/13) ⇝ 55/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 0/1 → 5/13 | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ -135/52 ⇜ (0/1 → 25/52) | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ -5/2 ⇜ (0/1 → 15/26) | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ -125/52 ⇜ (0/1 → 35/52) | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ -30/13 ⇜ (0/1 → 10/13) | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ -115/52 ⇜ (0/1 → 10/13) ⇝ 45/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ -55/26 ⇜ (0/1 → 10/13) ⇝ 25/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ -105/52 ⇜ (0/1 → 10/13) ⇝ 55/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ -25/13 ⇜ (0/1 → 10/13) ⇝ 15/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ -95/52 ⇜ (0/1 → 10/13) ⇝ 5/4 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ -45/26 ⇜ (0/1 → 10/13) ⇝ 35/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ -85/52 ⇜ (0/1 → 10/13) ⇝ 75/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (0/1 → 1/1) ⇝ 40/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ (0/1 → 1/1) ⇝ 80/13 | s:mad ]",
|
|
||||||
"[ (5/52 → 1/1) ⇝ 165/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ (5/26 → 1/1) ⇝ 85/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (15/52 → 1/1) ⇝ 175/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ -135/52 ⇜ (5/13 → 25/52) | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ -5/2 ⇜ (5/13 → 15/26) | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ -125/52 ⇜ (5/13 → 35/52) | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ -30/13 ⇜ (5/13 → 10/13) | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 5/13 → 10/13 | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ -115/52 ⇜ (5/13 → 45/52) | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ -55/26 ⇜ (5/13 → 25/26) | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ -105/52 ⇜ (5/13 → 1/1) ⇝ 55/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (5/13 → 1/1) ⇝ 45/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ (5/13 → 1/1) ⇝ 45/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ (25/52 → 1/1) ⇝ 185/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ (25/52 → 1/1) ⇝ 185/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ (15/26 → 1/1) ⇝ 95/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ (15/26 → 1/1) ⇝ 95/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (35/52 → 1/1) ⇝ 15/4 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (35/52 → 1/1) ⇝ 15/4 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ -115/52 ⇜ (10/13 → 45/52) | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ -55/26 ⇜ (10/13 → 25/26) | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 10/13 → 155/156 | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ -105/52 ⇜ (10/13 → 1/1) ⇝ 55/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ -25/13 ⇜ (10/13 → 1/1) ⇝ 15/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ -95/52 ⇜ (10/13 → 1/1) ⇝ 5/4 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ -45/26 ⇜ (10/13 → 1/1) ⇝ 35/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ -85/52 ⇜ (10/13 → 1/1) ⇝ 75/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (10/13 → 1/1) ⇝ 50/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ (10/13 → 1/1) ⇝ 50/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ (45/52 → 1/1) ⇝ 205/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ (45/52 → 1/1) ⇝ 205/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ (25/26 → 1/1) ⇝ 105/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ (25/26 → 1/1) ⇝ 105/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (155/156 → 1/1) ⇝ 15/13 | note:bb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.46296296296296297 ]",
|
|
||||||
"[ -105/52 ⇜ (1/1 → 55/52) | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ -105/52 ⇜ (1/1 → 55/52) | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ -25/13 ⇜ (1/1 → 15/13) | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 155/156 ⇜ (1/1 → 15/13) | note:bb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.46296296296296297 ]",
|
|
||||||
"[ -95/52 ⇜ (1/1 → 5/4) | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ -45/26 ⇜ (1/1 → 35/26) | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ -85/52 ⇜ (1/1 → 75/52) | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 0/1 ⇜ (1/1 → 2/1) ⇝ 40/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 0/1 ⇜ (1/1 → 2/1) ⇝ 80/13 | s:mad ]",
|
|
||||||
"[ 5/52 ⇜ (1/1 → 2/1) ⇝ 165/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 5/26 ⇜ (1/1 → 2/1) ⇝ 85/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 15/52 ⇜ (1/1 → 2/1) ⇝ 175/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 5/13 ⇜ (1/1 → 2/1) ⇝ 45/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 5/13 ⇜ (1/1 → 2/1) ⇝ 45/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 25/52 ⇜ (1/1 → 2/1) ⇝ 185/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 25/52 ⇜ (1/1 → 2/1) ⇝ 185/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 15/26 ⇜ (1/1 → 2/1) ⇝ 95/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 15/26 ⇜ (1/1 → 2/1) ⇝ 95/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 35/52 ⇜ (1/1 → 2/1) ⇝ 15/4 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 35/52 ⇜ (1/1 → 2/1) ⇝ 15/4 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 10/13 ⇜ (1/1 → 2/1) ⇝ 50/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 10/13 ⇜ (1/1 → 2/1) ⇝ 50/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 45/52 ⇜ (1/1 → 2/1) ⇝ 205/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 45/52 ⇜ (1/1 → 2/1) ⇝ 205/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 25/26 ⇜ (1/1 → 2/1) ⇝ 105/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 25/26 ⇜ (1/1 → 2/1) ⇝ 105/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (55/52 → 2/1) ⇝ 215/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (55/52 → 2/1) ⇝ 215/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/13 → 20/13 | note:ab2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4537037037037037 ]",
|
|
||||||
"[ (15/13 → 2/1) ⇝ 55/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ (5/4 → 2/1) ⇝ 225/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ (35/26 → 2/1) ⇝ 115/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ (75/52 → 2/1) ⇝ 235/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 20/13 → 25/13 | note:gb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4444444444444444 ]",
|
|
||||||
"[ (25/13 → 2/1) ⇝ 30/13 | note:gb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4444444444444444 ]",
|
|
||||||
"[ 25/13 ⇜ (2/1 → 30/13) | note:gb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4444444444444444 ]",
|
|
||||||
"[ 0/1 ⇜ (2/1 → 3/1) ⇝ 40/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 0/1 ⇜ (2/1 → 3/1) ⇝ 80/13 | s:mad ]",
|
|
||||||
"[ 5/52 ⇜ (2/1 → 3/1) ⇝ 165/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 5/26 ⇜ (2/1 → 3/1) ⇝ 85/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 15/52 ⇜ (2/1 → 3/1) ⇝ 175/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 5/13 ⇜ (2/1 → 3/1) ⇝ 45/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 5/13 ⇜ (2/1 → 3/1) ⇝ 45/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 25/52 ⇜ (2/1 → 3/1) ⇝ 185/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 25/52 ⇜ (2/1 → 3/1) ⇝ 185/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 15/26 ⇜ (2/1 → 3/1) ⇝ 95/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 15/26 ⇜ (2/1 → 3/1) ⇝ 95/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 35/52 ⇜ (2/1 → 3/1) ⇝ 15/4 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 35/52 ⇜ (2/1 → 3/1) ⇝ 15/4 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 10/13 ⇜ (2/1 → 3/1) ⇝ 50/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 10/13 ⇜ (2/1 → 3/1) ⇝ 50/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 45/52 ⇜ (2/1 → 3/1) ⇝ 205/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 45/52 ⇜ (2/1 → 3/1) ⇝ 205/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 25/26 ⇜ (2/1 → 3/1) ⇝ 105/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 25/26 ⇜ (2/1 → 3/1) ⇝ 105/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 55/52 ⇜ (2/1 → 3/1) ⇝ 215/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 55/52 ⇜ (2/1 → 3/1) ⇝ 215/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/13 ⇜ (2/1 → 3/1) ⇝ 55/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 5/4 ⇜ (2/1 → 3/1) ⇝ 225/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 35/26 ⇜ (2/1 → 3/1) ⇝ 115/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 75/52 ⇜ (2/1 → 3/1) ⇝ 235/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 30/13 → 395/156 | note:gb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4444444444444444 ]",
|
|
||||||
"[ 395/156 → 35/13 | note:ab2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4537037037037037 ]",
|
|
||||||
"[ (35/13 → 3/1) ⇝ 40/13 | note:bb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.46296296296296297 ]",
|
|
||||||
"[ 0/1 ⇜ (3/1 → 40/13) | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 0/1 ⇜ (3/1 → 40/13) ⇝ 80/13 | s:mad ]",
|
|
||||||
"[ 5/52 ⇜ (3/1 → 40/13) ⇝ 165/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 5/26 ⇜ (3/1 → 40/13) ⇝ 85/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 15/52 ⇜ (3/1 → 40/13) ⇝ 175/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 5/13 ⇜ (3/1 → 40/13) ⇝ 45/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 5/13 ⇜ (3/1 → 40/13) ⇝ 45/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 25/52 ⇜ (3/1 → 40/13) ⇝ 185/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 25/52 ⇜ (3/1 → 40/13) ⇝ 185/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 15/26 ⇜ (3/1 → 40/13) ⇝ 95/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 15/26 ⇜ (3/1 → 40/13) ⇝ 95/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 35/52 ⇜ (3/1 → 40/13) ⇝ 15/4 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 35/52 ⇜ (3/1 → 40/13) ⇝ 15/4 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 10/13 ⇜ (3/1 → 40/13) ⇝ 50/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 10/13 ⇜ (3/1 → 40/13) ⇝ 50/13 | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 45/52 ⇜ (3/1 → 40/13) ⇝ 205/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 45/52 ⇜ (3/1 → 40/13) ⇝ 205/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 25/26 ⇜ (3/1 → 40/13) ⇝ 105/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 25/26 ⇜ (3/1 → 40/13) ⇝ 105/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 55/52 ⇜ (3/1 → 40/13) ⇝ 215/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 55/52 ⇜ (3/1 → 40/13) ⇝ 215/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/13 ⇜ (3/1 → 40/13) ⇝ 55/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 5/4 ⇜ (3/1 → 40/13) ⇝ 225/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 35/26 ⇜ (3/1 → 40/13) ⇝ 115/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 75/52 ⇜ (3/1 → 40/13) ⇝ 235/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 35/13 ⇜ (3/1 → 40/13) | note:bb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.46296296296296297 ]",
|
|
||||||
"[ 5/52 ⇜ (40/13 → 165/52) | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 5/26 ⇜ (40/13 → 85/26) | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 15/52 ⇜ (40/13 → 175/52) | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 5/13 ⇜ (40/13 → 45/13) | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 5/13 ⇜ (40/13 → 45/13) | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 25/52 ⇜ (40/13 → 45/13) ⇝ 185/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 15/26 ⇜ (40/13 → 45/13) ⇝ 95/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 35/52 ⇜ (40/13 → 45/13) ⇝ 15/4 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 10/13 ⇜ (40/13 → 45/13) ⇝ 50/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 45/52 ⇜ (40/13 → 45/13) ⇝ 205/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 25/26 ⇜ (40/13 → 45/13) ⇝ 105/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 55/52 ⇜ (40/13 → 45/13) ⇝ 215/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 40/13 → 45/13 | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ 25/52 ⇜ (40/13 → 185/52) | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 15/26 ⇜ (40/13 → 95/26) | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 35/52 ⇜ (40/13 → 15/4) | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 10/13 ⇜ (40/13 → 50/13) | clip:1 note:C4 s:piano release:0.1 pan:0.5277777777777778 ]",
|
|
||||||
"[ 45/52 ⇜ (40/13 → 50/13) ⇝ 205/52 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 25/26 ⇜ (40/13 → 50/13) ⇝ 105/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 55/52 ⇜ (40/13 → 50/13) ⇝ 215/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/13 ⇜ (40/13 → 50/13) ⇝ 55/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 5/4 ⇜ (40/13 → 50/13) ⇝ 225/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 35/26 ⇜ (40/13 → 50/13) ⇝ 115/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 75/52 ⇜ (40/13 → 50/13) ⇝ 235/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 0/1 ⇜ (40/13 → 4/1) ⇝ 80/13 | s:mad ]",
|
|
||||||
"[ (40/13 → 4/1) ⇝ 80/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ (165/52 → 4/1) ⇝ 25/4 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (85/26 → 4/1) ⇝ 165/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ (175/52 → 4/1) ⇝ 335/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 25/52 ⇜ (45/13 → 185/52) | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 15/26 ⇜ (45/13 → 95/26) | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 35/52 ⇜ (45/13 → 15/4) | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 10/13 ⇜ (45/13 → 50/13) | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 45/13 → 50/13 | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ 45/52 ⇜ (45/13 → 205/52) | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 25/26 ⇜ (45/13 → 4/1) ⇝ 105/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 55/52 ⇜ (45/13 → 4/1) ⇝ 215/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (45/13 → 4/1) ⇝ 85/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ (45/13 → 4/1) ⇝ 85/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ (185/52 → 4/1) ⇝ 345/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ (185/52 → 4/1) ⇝ 345/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (95/26 → 4/1) ⇝ 175/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (95/26 → 4/1) ⇝ 175/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ (15/4 → 4/1) ⇝ 355/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (15/4 → 4/1) ⇝ 355/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 45/52 ⇜ (50/13 → 205/52) | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 25/26 ⇜ (50/13 → 4/1) ⇝ 105/26 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 55/52 ⇜ (50/13 → 4/1) ⇝ 215/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/13 ⇜ (50/13 → 4/1) ⇝ 55/13 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 5/4 ⇜ (50/13 → 4/1) ⇝ 225/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 35/26 ⇜ (50/13 → 4/1) ⇝ 115/26 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 75/52 ⇜ (50/13 → 4/1) ⇝ 235/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (50/13 → 4/1) ⇝ 635/156 | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ (50/13 → 4/1) ⇝ 90/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ (50/13 → 4/1) ⇝ 90/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ (205/52 → 4/1) ⇝ 365/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ (205/52 → 4/1) ⇝ 365/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 25/26 ⇜ (4/1 → 105/26) | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 25/26 ⇜ (4/1 → 105/26) | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 50/13 ⇜ (4/1 → 635/156) | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ 55/52 ⇜ (4/1 → 215/52) | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 55/52 ⇜ (4/1 → 215/52) | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/13 ⇜ (4/1 → 55/13) | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 5/4 ⇜ (4/1 → 225/52) | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 35/26 ⇜ (4/1 → 115/26) | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 75/52 ⇜ (4/1 → 235/52) | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 0/1 ⇜ (4/1 → 5/1) ⇝ 80/13 | s:mad ]",
|
|
||||||
"[ 40/13 ⇜ (4/1 → 5/1) ⇝ 80/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 165/52 ⇜ (4/1 → 5/1) ⇝ 25/4 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 85/26 ⇜ (4/1 → 5/1) ⇝ 165/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 175/52 ⇜ (4/1 → 5/1) ⇝ 335/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 45/13 ⇜ (4/1 → 5/1) ⇝ 85/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 45/13 ⇜ (4/1 → 5/1) ⇝ 85/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 185/52 ⇜ (4/1 → 5/1) ⇝ 345/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 185/52 ⇜ (4/1 → 5/1) ⇝ 345/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 95/26 ⇜ (4/1 → 5/1) ⇝ 175/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 95/26 ⇜ (4/1 → 5/1) ⇝ 175/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/4 ⇜ (4/1 → 5/1) ⇝ 355/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 15/4 ⇜ (4/1 → 5/1) ⇝ 355/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 50/13 ⇜ (4/1 → 5/1) ⇝ 90/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 50/13 ⇜ (4/1 → 5/1) ⇝ 90/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 205/52 ⇜ (4/1 → 5/1) ⇝ 365/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 205/52 ⇜ (4/1 → 5/1) ⇝ 365/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (105/26 → 5/1) ⇝ 185/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (105/26 → 5/1) ⇝ 185/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 635/156 → 55/13 | note:bb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.46296296296296297 ]",
|
|
||||||
"[ (215/52 → 5/1) ⇝ 375/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (215/52 → 5/1) ⇝ 375/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 55/13 → 60/13 | note:ab2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4537037037037037 ]",
|
|
||||||
"[ (55/13 → 5/1) ⇝ 95/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ (225/52 → 5/1) ⇝ 385/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ (115/26 → 5/1) ⇝ 15/2 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (235/52 → 5/1) ⇝ 395/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 60/13 → 5/1 | note:gb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4444444444444444 ]",
|
|
||||||
"[ 5/1 → 70/13 | note:gb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4444444444444444 ]",
|
|
||||||
"[ 0/1 ⇜ (5/1 → 6/1) ⇝ 80/13 | s:mad ]",
|
|
||||||
"[ 40/13 ⇜ (5/1 → 6/1) ⇝ 80/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 165/52 ⇜ (5/1 → 6/1) ⇝ 25/4 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 85/26 ⇜ (5/1 → 6/1) ⇝ 165/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 175/52 ⇜ (5/1 → 6/1) ⇝ 335/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 45/13 ⇜ (5/1 → 6/1) ⇝ 85/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 45/13 ⇜ (5/1 → 6/1) ⇝ 85/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 185/52 ⇜ (5/1 → 6/1) ⇝ 345/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 185/52 ⇜ (5/1 → 6/1) ⇝ 345/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 95/26 ⇜ (5/1 → 6/1) ⇝ 175/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 95/26 ⇜ (5/1 → 6/1) ⇝ 175/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/4 ⇜ (5/1 → 6/1) ⇝ 355/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 15/4 ⇜ (5/1 → 6/1) ⇝ 355/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 50/13 ⇜ (5/1 → 6/1) ⇝ 90/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 50/13 ⇜ (5/1 → 6/1) ⇝ 90/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 205/52 ⇜ (5/1 → 6/1) ⇝ 365/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 205/52 ⇜ (5/1 → 6/1) ⇝ 365/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 105/26 ⇜ (5/1 → 6/1) ⇝ 185/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 105/26 ⇜ (5/1 → 6/1) ⇝ 185/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 215/52 ⇜ (5/1 → 6/1) ⇝ 375/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 215/52 ⇜ (5/1 → 6/1) ⇝ 375/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 55/13 ⇜ (5/1 → 6/1) ⇝ 95/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 225/52 ⇜ (5/1 → 6/1) ⇝ 385/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 115/26 ⇜ (5/1 → 6/1) ⇝ 15/2 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 235/52 ⇜ (5/1 → 6/1) ⇝ 395/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (70/13 → 6/1) ⇝ 80/13 | note:gb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4444444444444444 ]",
|
|
||||||
"[ 0/1 ⇜ (6/1 → 80/13) | s:mad ]",
|
|
||||||
"[ 40/13 ⇜ (6/1 → 80/13) | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 165/52 ⇜ (6/1 → 80/13) ⇝ 25/4 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 85/26 ⇜ (6/1 → 80/13) ⇝ 165/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 175/52 ⇜ (6/1 → 80/13) ⇝ 335/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 45/13 ⇜ (6/1 → 80/13) ⇝ 85/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 45/13 ⇜ (6/1 → 80/13) ⇝ 85/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 185/52 ⇜ (6/1 → 80/13) ⇝ 345/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 185/52 ⇜ (6/1 → 80/13) ⇝ 345/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 95/26 ⇜ (6/1 → 80/13) ⇝ 175/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 95/26 ⇜ (6/1 → 80/13) ⇝ 175/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/4 ⇜ (6/1 → 80/13) ⇝ 355/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 15/4 ⇜ (6/1 → 80/13) ⇝ 355/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 50/13 ⇜ (6/1 → 80/13) ⇝ 90/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 50/13 ⇜ (6/1 → 80/13) ⇝ 90/13 | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 205/52 ⇜ (6/1 → 80/13) ⇝ 365/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 205/52 ⇜ (6/1 → 80/13) ⇝ 365/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 105/26 ⇜ (6/1 → 80/13) ⇝ 185/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 105/26 ⇜ (6/1 → 80/13) ⇝ 185/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 215/52 ⇜ (6/1 → 80/13) ⇝ 375/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 215/52 ⇜ (6/1 → 80/13) ⇝ 375/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 55/13 ⇜ (6/1 → 80/13) ⇝ 95/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 225/52 ⇜ (6/1 → 80/13) ⇝ 385/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 115/26 ⇜ (6/1 → 80/13) ⇝ 15/2 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 235/52 ⇜ (6/1 → 80/13) ⇝ 395/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 70/13 ⇜ (6/1 → 80/13) | note:gb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4444444444444444 ]",
|
|
||||||
"[ 165/52 ⇜ (80/13 → 25/4) | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 85/26 ⇜ (80/13 → 165/26) | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 175/52 ⇜ (80/13 → 335/52) | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 45/13 ⇜ (80/13 → 85/13) | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 45/13 ⇜ (80/13 → 85/13) | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 185/52 ⇜ (80/13 → 85/13) ⇝ 345/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 95/26 ⇜ (80/13 → 85/13) ⇝ 175/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/4 ⇜ (80/13 → 85/13) ⇝ 355/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 50/13 ⇜ (80/13 → 85/13) ⇝ 90/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 205/52 ⇜ (80/13 → 85/13) ⇝ 365/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 105/26 ⇜ (80/13 → 85/13) ⇝ 185/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 215/52 ⇜ (80/13 → 85/13) ⇝ 375/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 80/13 → 85/13 | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ 185/52 ⇜ (80/13 → 345/52) | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 95/26 ⇜ (80/13 → 175/26) | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 15/4 ⇜ (80/13 → 355/52) | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 50/13 ⇜ (80/13 → 90/13) | clip:1 note:D4 s:piano release:0.1 pan:0.537037037037037 ]",
|
|
||||||
"[ 205/52 ⇜ (80/13 → 90/13) ⇝ 365/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 105/26 ⇜ (80/13 → 90/13) ⇝ 185/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 215/52 ⇜ (80/13 → 90/13) ⇝ 375/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 55/13 ⇜ (80/13 → 90/13) ⇝ 95/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 225/52 ⇜ (80/13 → 90/13) ⇝ 385/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 115/26 ⇜ (80/13 → 90/13) ⇝ 15/2 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 235/52 ⇜ (80/13 → 90/13) ⇝ 395/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (80/13 → 7/1) ⇝ 120/13 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (80/13 → 7/1) ⇝ 160/13 | s:mad ]",
|
|
||||||
"[ (25/4 → 7/1) ⇝ 485/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ (165/26 → 7/1) ⇝ 245/26 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ (335/52 → 7/1) ⇝ 495/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 185/52 ⇜ (85/13 → 345/52) | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 95/26 ⇜ (85/13 → 175/26) | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 15/4 ⇜ (85/13 → 355/52) | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 50/13 ⇜ (85/13 → 90/13) | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 85/13 → 90/13 | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ 205/52 ⇜ (85/13 → 7/1) ⇝ 365/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 105/26 ⇜ (85/13 → 7/1) ⇝ 185/26 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 215/52 ⇜ (85/13 → 7/1) ⇝ 375/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (85/13 → 7/1) ⇝ 125/13 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ (85/13 → 7/1) ⇝ 125/13 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (345/52 → 7/1) ⇝ 505/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (345/52 → 7/1) ⇝ 505/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ (175/26 → 7/1) ⇝ 255/26 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (175/26 → 7/1) ⇝ 255/26 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ (355/52 → 7/1) ⇝ 515/52 | clip:1 note:F#5 s:piano release:0.1 pan:0.6111111111111112 ]",
|
|
||||||
"[ (355/52 → 7/1) ⇝ 515/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 205/52 ⇜ (90/13 → 7/1) ⇝ 365/52 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 105/26 ⇜ (90/13 → 7/1) ⇝ 185/26 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 215/52 ⇜ (90/13 → 7/1) ⇝ 375/52 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 55/13 ⇜ (90/13 → 7/1) ⇝ 95/13 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 225/52 ⇜ (90/13 → 7/1) ⇝ 385/52 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 115/26 ⇜ (90/13 → 7/1) ⇝ 15/2 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 235/52 ⇜ (90/13 → 7/1) ⇝ 395/52 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (90/13 → 7/1) ⇝ 1115/156 | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ (90/13 → 7/1) ⇝ 10/1 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ (90/13 → 7/1) ⇝ 10/1 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 205/52 ⇜ (7/1 → 365/52) | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 205/52 ⇜ (7/1 → 365/52) | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 105/26 ⇜ (7/1 → 185/26) | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 105/26 ⇜ (7/1 → 185/26) | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 90/13 ⇜ (7/1 → 1115/156) | note:c3 gain:0.8 clip:1 s:piano release:0.1 pan:0.4722222222222222 ]",
|
|
||||||
"[ 215/52 ⇜ (7/1 → 375/52) | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 215/52 ⇜ (7/1 → 375/52) | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 55/13 ⇜ (7/1 → 95/13) | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 225/52 ⇜ (7/1 → 385/52) | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 115/26 ⇜ (7/1 → 15/2) | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 235/52 ⇜ (7/1 → 395/52) | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 80/13 ⇜ (7/1 → 8/1) ⇝ 120/13 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 80/13 ⇜ (7/1 → 8/1) ⇝ 160/13 | s:mad ]",
|
|
||||||
"[ 25/4 ⇜ (7/1 → 8/1) ⇝ 485/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 165/26 ⇜ (7/1 → 8/1) ⇝ 245/26 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 335/52 ⇜ (7/1 → 8/1) ⇝ 495/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 85/13 ⇜ (7/1 → 8/1) ⇝ 125/13 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 85/13 ⇜ (7/1 → 8/1) ⇝ 125/13 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ 345/52 ⇜ (7/1 → 8/1) ⇝ 505/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ 345/52 ⇜ (7/1 → 8/1) ⇝ 505/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ 175/26 ⇜ (7/1 → 8/1) ⇝ 255/26 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ 175/26 ⇜ (7/1 → 8/1) ⇝ 255/26 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 355/52 ⇜ (7/1 → 8/1) ⇝ 515/52 | clip:1 note:F#5 s:piano release:0.1 pan:0.6111111111111112 ]",
|
|
||||||
"[ 355/52 ⇜ (7/1 → 8/1) ⇝ 515/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 90/13 ⇜ (7/1 → 8/1) ⇝ 10/1 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ 90/13 ⇜ (7/1 → 8/1) ⇝ 10/1 | clip:1 note:E4 s:piano release:0.1 pan:0.5462962962962963 ]",
|
|
||||||
"[ (365/52 → 8/1) ⇝ 525/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (365/52 → 8/1) ⇝ 525/52 | clip:1 note:F#4 s:piano release:0.1 pan:0.5555555555555556 ]",
|
|
||||||
"[ (185/26 → 8/1) ⇝ 265/26 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (185/26 → 8/1) ⇝ 265/26 | clip:1 note:G#4 s:piano release:0.1 pan:0.5648148148148149 ]",
|
|
||||||
"[ 1115/156 → 95/13 | note:bb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.46296296296296297 ]",
|
|
||||||
"[ (375/52 → 8/1) ⇝ 535/52 | clip:1 note:F#5 s:piano release:0.1 pan:0.6111111111111112 ]",
|
|
||||||
"[ (375/52 → 8/1) ⇝ 535/52 | clip:1 note:A#4 s:piano release:0.1 pan:0.5740740740740741 ]",
|
|
||||||
"[ 95/13 → 100/13 | note:ab2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4537037037037037 ]",
|
|
||||||
"[ (95/13 → 8/1) ⇝ 135/13 | clip:1 note:C5 s:piano release:0.1 pan:0.5833333333333333 ]",
|
|
||||||
"[ (385/52 → 8/1) ⇝ 545/52 | clip:1 note:D5 s:piano release:0.1 pan:0.5925925925925926 ]",
|
|
||||||
"[ (15/2 → 8/1) ⇝ 275/26 | clip:1 note:E5 s:piano release:0.1 pan:0.6018518518518519 ]",
|
|
||||||
"[ (395/52 → 8/1) ⇝ 555/52 | clip:1 note:F#5 s:piano release:0.1 pan:0.6111111111111112 ]",
|
|
||||||
"[ (100/13 → 8/1) ⇝ 105/13 | note:gb2 gain:0.8 clip:1 s:piano release:0.1 pan:0.4444444444444444 ]",
|
|
||||||
]
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`renders tunes > tune: caverave 1`] = `
|
exports[`renders tunes > tune: caverave 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd gain:0.8 ]",
|
"[ 0/1 → 1/2 | s:bd gain:0.8 ]",
|
||||||
@@ -1507,14 +1111,14 @@ exports[`renders tunes > tune: caverave 1`] = `
|
|||||||
|
|
||||||
exports[`renders tunes > tune: chop 1`] = `
|
exports[`renders tunes > tune: chop 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/4 | s:p speed:0.03125 unit:c begin:0 end:0.0078125 pan:0 shape:0.4 decay:0.1 sustain:0.6 ]",
|
"[ 0/1 → 1/4 | s:p speed:0.015625 unit:c begin:0 end:0.0078125 pan:0 shape:0.4 decay:0.1 sustain:0.6 ]",
|
||||||
"[ 0/1 → 1/4 | s:p speed:0.03125 unit:c begin:0.0234375 end:0.03125 pan:1 shape:0.4 decay:0.1 sustain:0.6 ]",
|
"[ 0/1 → 1/4 | s:p speed:0.015625 unit:c begin:0.0234375 end:0.03125 pan:1 shape:0.4 decay:0.1 sustain:0.6 ]",
|
||||||
"[ 1/4 → 1/2 | s:p speed:0.03125 unit:c begin:0.0078125 end:0.015625 pan:0 shape:0.4 decay:0.1 sustain:0.6 ]",
|
"[ 1/4 → 1/2 | s:p speed:0.015625 unit:c begin:0.0078125 end:0.015625 pan:0 shape:0.4 decay:0.1 sustain:0.6 ]",
|
||||||
"[ 1/4 → 1/2 | s:p speed:0.03125 unit:c begin:0.015625 end:0.0234375 pan:1 shape:0.4 decay:0.1 sustain:0.6 ]",
|
"[ 1/4 → 1/2 | s:p speed:0.015625 unit:c begin:0.015625 end:0.0234375 pan:1 shape:0.4 decay:0.1 sustain:0.6 ]",
|
||||||
"[ 1/2 → 3/4 | s:p speed:0.03125 unit:c begin:0.015625 end:0.0234375 pan:0 shape:0.4 decay:0.1 sustain:0.6 ]",
|
"[ 1/2 → 3/4 | s:p speed:0.015625 unit:c begin:0.015625 end:0.0234375 pan:0 shape:0.4 decay:0.1 sustain:0.6 ]",
|
||||||
"[ 1/2 → 3/4 | s:p speed:0.03125 unit:c begin:0.0078125 end:0.015625 pan:1 shape:0.4 decay:0.1 sustain:0.6 ]",
|
"[ 1/2 → 3/4 | s:p speed:0.015625 unit:c begin:0.0078125 end:0.015625 pan:1 shape:0.4 decay:0.1 sustain:0.6 ]",
|
||||||
"[ 3/4 → 1/1 | s:p speed:0.03125 unit:c begin:0.0234375 end:0.03125 pan:0 shape:0.4 decay:0.1 sustain:0.6 ]",
|
"[ 3/4 → 1/1 | s:p speed:0.015625 unit:c begin:0.0234375 end:0.03125 pan:0 shape:0.4 decay:0.1 sustain:0.6 ]",
|
||||||
"[ 3/4 → 1/1 | s:p speed:0.03125 unit:c begin:0 end:0.0078125 pan:1 shape:0.4 decay:0.1 sustain:0.6 ]",
|
"[ 3/4 → 1/1 | s:p speed:0.015625 unit:c begin:0 end:0.0078125 pan:1 shape:0.4 decay:0.1 sustain:0.6 ]",
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -1545,7 +1149,7 @@ exports[`renders tunes > tune: dinofunk 1`] = `
|
|||||||
"[ 0/1 → 1/4 | note:Ab4 s:sawtooth cutoff:1239.2541394619345 gain:0.8 decay:0.05125097280354112 sustain:0 delay:0.2561353071307281 room:1 ]",
|
"[ 0/1 → 1/4 | note:Ab4 s:sawtooth cutoff:1239.2541394619345 gain:0.8 decay:0.05125097280354112 sustain:0 delay:0.2561353071307281 room:1 ]",
|
||||||
"[ 0/1 → 1/4 | note:68.1 s:sawtooth cutoff:1239.2541394619345 gain:0.8 decay:0.05125097280354112 sustain:0 delay:0.2561353071307281 room:1 ]",
|
"[ 0/1 → 1/4 | note:68.1 s:sawtooth cutoff:1239.2541394619345 gain:0.8 decay:0.05125097280354112 sustain:0 delay:0.2561353071307281 room:1 ]",
|
||||||
"[ 0/1 → 1/2 | s:bd ]",
|
"[ 0/1 → 1/2 | s:bd ]",
|
||||||
"[ (0/1 → 1/1) ⇝ 8/1 | s:bass speed:0.125 unit:c clip:1 ]",
|
"[ (0/1 → 1/1) ⇝ 8/1 | s:bass speed:0.0625 unit:c clip:1 ]",
|
||||||
"[ (0/1 → 1/1) ⇝ 8/1 | note:b4 s:dino delay:0.8 room:0.5 ]",
|
"[ (0/1 → 1/1) ⇝ 8/1 | note:b4 s:dino delay:0.8 room:0.5 ]",
|
||||||
"[ 1/4 → 1/2 | s:hh ]",
|
"[ 1/4 → 1/2 | s:hh ]",
|
||||||
"[ 1/4 → 1/2 | note:Gb3 ]",
|
"[ 1/4 → 1/2 | note:Gb3 ]",
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
import { createClient } from '@supabase/supabase-js';
|
|
||||||
|
|
||||||
const supabase = createClient(
|
|
||||||
'https://pidxdsxphlhzjnzmifth.supabase.co',
|
|
||||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBpZHhkc3hwaGxoempuem1pZnRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTYyMzA1NTYsImV4cCI6MTk3MTgwNjU1Nn0.bqlw7802fsWRnqU5BLYtmXk_k-D1VFmbkHMywWc15NM',
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data } = await supabase.from('code');
|
|
||||||
|
|
||||||
console.log(JSON.stringify(data));
|
|
||||||
File diff suppressed because one or more lines are too long
+2
-4
@@ -7,7 +7,6 @@ import { evaluate } from '@strudel/transpiler';
|
|||||||
import { evalScope } from '@strudel/core';
|
import { evalScope } from '@strudel/core';
|
||||||
import * as strudel from '@strudel/core';
|
import * as strudel from '@strudel/core';
|
||||||
import * as webaudio from '@strudel/webaudio';
|
import * as webaudio from '@strudel/webaudio';
|
||||||
import controls from '@strudel/core/controls.mjs';
|
|
||||||
// import gist from '@strudel/core/gist.js';
|
// import gist from '@strudel/core/gist.js';
|
||||||
import { mini, m } from '@strudel/mini/mini.mjs';
|
import { mini, m } from '@strudel/mini/mini.mjs';
|
||||||
// import * as voicingHelpers from '@strudel/tonal/voicings.mjs';
|
// import * as voicingHelpers from '@strudel/tonal/voicings.mjs';
|
||||||
@@ -21,7 +20,6 @@ import '@strudel/xen/xen.mjs';
|
|||||||
// import '@strudel/osc/osc.mjs';
|
// import '@strudel/osc/osc.mjs';
|
||||||
// import '@strudel/webaudio/webaudio.mjs';
|
// import '@strudel/webaudio/webaudio.mjs';
|
||||||
// import '@strudel/serial/serial.mjs';
|
// import '@strudel/serial/serial.mjs';
|
||||||
// import controls from '@strudel/core/controls.mjs';
|
|
||||||
import '../website/src/repl/piano';
|
import '../website/src/repl/piano';
|
||||||
|
|
||||||
class MockedNode {
|
class MockedNode {
|
||||||
@@ -153,10 +151,9 @@ evalScope(
|
|||||||
strudel,
|
strudel,
|
||||||
toneHelpersMocked,
|
toneHelpersMocked,
|
||||||
uiHelpersMocked,
|
uiHelpersMocked,
|
||||||
controls,
|
|
||||||
webaudio,
|
webaudio,
|
||||||
tonalHelpers,
|
tonalHelpers,
|
||||||
/* controls,
|
/*
|
||||||
toneHelpers,
|
toneHelpers,
|
||||||
voicingHelpers,
|
voicingHelpers,
|
||||||
drawHelpers,
|
drawHelpers,
|
||||||
@@ -175,6 +172,7 @@ evalScope(
|
|||||||
loadCSound,
|
loadCSound,
|
||||||
loadCsound,
|
loadCsound,
|
||||||
loadcsound,
|
loadcsound,
|
||||||
|
setcps: id,
|
||||||
Clock: {}, // whatever
|
Clock: {}, // whatever
|
||||||
// Tone,
|
// Tone,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import { queryCode } from '../runtime.mjs';
|
|
||||||
import { describe, it } from 'vitest';
|
|
||||||
import data from './dbdump.json';
|
|
||||||
|
|
||||||
describe('renders shared tunes', async () => {
|
|
||||||
data.forEach(({ id, code, hash }) => {
|
|
||||||
const url = `https://strudel.cc/?${hash}`;
|
|
||||||
it(`shared tune ${id} ${url}`, async ({ expect }) => {
|
|
||||||
if (code.includes('import(')) {
|
|
||||||
console.log('skip', url);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const haps = await queryCode(code, 1);
|
|
||||||
expect(haps).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# dbpatch
|
||||||
|
|
||||||
|
this is a little script to update all patterns in the db. Go to supabase and export as csv as `code_rows.csv` to this folder.
|
||||||
|
Then run
|
||||||
|
|
||||||
|
```sh
|
||||||
|
node dbpatch.mjs > code_rows_patched.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
It will output a csv file with the changes implemented in dbpatch.mjs
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { parse } from 'csv-parse/sync';
|
||||||
|
import { readFileSync } from 'fs';
|
||||||
|
import { stringify } from 'csv-stringify/sync';
|
||||||
|
|
||||||
|
const hasCpsCall = (code) =>
|
||||||
|
['setcps', 'setCps', 'setCpm', 'setcpm'].reduce((acc, m) => acc || code.includes(`${m}`), false);
|
||||||
|
|
||||||
|
function withCps(code, cps) {
|
||||||
|
if (hasCpsCall(code)) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
const lines = code.split('\n');
|
||||||
|
const firstNonLineComment = lines.findIndex((l) => !l.startsWith('//'));
|
||||||
|
const cpsCall = `setcps(${cps})`;
|
||||||
|
lines.splice(firstNonLineComment, 0, cpsCall);
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
const dumpNew = readFileSync('./code_rows.csv', { encoding: 'utf-8' });
|
||||||
|
|
||||||
|
const records = parse(dumpNew, {
|
||||||
|
columns: true,
|
||||||
|
skip_empty_lines: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const edited = records.map((entry) => ({
|
||||||
|
...entry,
|
||||||
|
code: withCps(entry.code, 1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.log(stringify(edited));
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"csv": "^6.3.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+14
@@ -262,6 +262,20 @@ declare module 'astro:content' {
|
|||||||
collection: "blog";
|
collection: "blog";
|
||||||
data: InferEntrySchema<"blog">
|
data: InferEntrySchema<"blog">
|
||||||
} & { render(): Render[".mdx"] };
|
} & { render(): Render[".mdx"] };
|
||||||
|
"release-1.0.0-geburtstagskuchen.mdx": {
|
||||||
|
id: "release-1.0.0-geburtstagskuchen.mdx";
|
||||||
|
slug: "release-100-geburtstagskuchen";
|
||||||
|
body: string;
|
||||||
|
collection: "blog";
|
||||||
|
data: InferEntrySchema<"blog">
|
||||||
|
} & { render(): Render[".mdx"] };
|
||||||
|
"year-2.mdx": {
|
||||||
|
id: "year-2.mdx";
|
||||||
|
slug: "year-2";
|
||||||
|
body: string;
|
||||||
|
collection: "blog";
|
||||||
|
data: InferEntrySchema<"blog">
|
||||||
|
} & { render(): Render[".mdx"] };
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,9 +13,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/client-search": "^4.22.0",
|
"@algolia/client-search": "^4.22.0",
|
||||||
"@astro-community/astro-embed-youtube": "^0.4.3",
|
"@astro-community/astro-embed-youtube": "^0.4.4",
|
||||||
"@astrojs/mdx": "^2.0.3",
|
"@astrojs/mdx": "^2.0.3",
|
||||||
"@astrojs/react": "^3.0.9",
|
"@astrojs/react": "^3.0.9",
|
||||||
|
"@astrojs/rss": "^4.0.2",
|
||||||
"@astrojs/tailwind": "^5.1.0",
|
"@astrojs/tailwind": "^5.1.0",
|
||||||
"@docsearch/css": "^3.5.2",
|
"@docsearch/css": "^3.5.2",
|
||||||
"@docsearch/react": "^3.5.2",
|
"@docsearch/react": "^3.5.2",
|
||||||
@@ -23,21 +24,21 @@
|
|||||||
"@heroicons/react": "^2.1.1",
|
"@heroicons/react": "^2.1.1",
|
||||||
"@nanostores/persistent": "^0.9.1",
|
"@nanostores/persistent": "^0.9.1",
|
||||||
"@nanostores/react": "^0.7.1",
|
"@nanostores/react": "^0.7.1",
|
||||||
|
"@strudel/codemirror": "workspace:*",
|
||||||
"@strudel/core": "workspace:*",
|
"@strudel/core": "workspace:*",
|
||||||
"@strudel/csound": "workspace:*",
|
"@strudel/csound": "workspace:*",
|
||||||
|
"@strudel/desktopbridge": "workspace:*",
|
||||||
|
"@strudel/hydra": "workspace:*",
|
||||||
"@strudel/midi": "workspace:*",
|
"@strudel/midi": "workspace:*",
|
||||||
"@strudel/mini": "workspace:*",
|
"@strudel/mini": "workspace:*",
|
||||||
"@strudel/osc": "workspace:*",
|
"@strudel/osc": "workspace:*",
|
||||||
|
"@strudel/repl": "workspace:*",
|
||||||
"@strudel/serial": "workspace:*",
|
"@strudel/serial": "workspace:*",
|
||||||
"@strudel/soundfonts": "workspace:*",
|
"@strudel/soundfonts": "workspace:*",
|
||||||
"@strudel/tonal": "workspace:*",
|
"@strudel/tonal": "workspace:*",
|
||||||
"@strudel/transpiler": "workspace:*",
|
"@strudel/transpiler": "workspace:*",
|
||||||
"@strudel/webaudio": "workspace:*",
|
"@strudel/webaudio": "workspace:*",
|
||||||
"@strudel/xen": "workspace:*",
|
"@strudel/xen": "workspace:*",
|
||||||
"@strudel/codemirror": "workspace:*",
|
|
||||||
"@strudel/desktopbridge": "workspace:*",
|
|
||||||
"@strudel/hydra": "workspace:*",
|
|
||||||
"@strudel/repl": "workspace:*",
|
|
||||||
"@supabase/supabase-js": "^2.39.1",
|
"@supabase/supabase-js": "^2.39.1",
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
"@tailwindcss/typography": "^0.5.10",
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 165 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 387 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 242 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 224 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 497 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user