From 814510f637175e80f65c540ac64ebef40b3e085f Mon Sep 17 00:00:00 2001 From: tyow Date: Mon, 9 Mar 2026 19:32:28 -0400 Subject: [PATCH 01/21] init --- packages/xen/xen.mjs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 828cab6ea..6e67a1e4e 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see . */ -import { register, _mod, parseNumeral, removeUndefineds } from '@strudel/core'; +import { register, _mod, parseNumeral, removeUndefineds, Pattern } from '@strudel/core'; import Tune from './tunejs.js'; // returns a list of frequency ratios for given edo scale @@ -97,15 +97,15 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); */ export const xen = register('xen', function (scaleNameOrRatios, pat) { - return pat.withHaps((haps) => { - haps = haps.map((hap) => { + const query = state => { + let haps = pat.withHap((hap)=> { let hVal = hap.value; const isObject = typeof hVal === 'object'; if (!isObject) { throw new Error(`Expected hap to have control 'i' set, but received ${hap.value.i}, try wrapping input in i()`); } const { i, ...otherValues } = hVal; - const scale = getXenScale(scaleNameOrRatios); + const scale = getXenScale(scaleNameOrRatios.query(state)[0].value); let freq = xenOffset(scale, parseNumeral(hVal.i)); // 10 is somewhat arbitrary freq = trimFreq(freq); @@ -113,10 +113,11 @@ export const xen = register('xen', function (scaleNameOrRatios, pat) { return isEdo(scaleNameOrRatios) ? hap.setContext({ ...hap.context, edoSize: scaleNameOrRatios.match(/^([1-9]+[0-9]*)edo$/)[1] }) : hap; - }); + }).query(state); return removeUndefineds(haps); - }); -}); + }; + return new Pattern(query) +}, false); /** * Assumes pattern of frequencies tuned to some `base` frequency, such as the output of `xen` From 02e0c43f77e03d440b1f3641aff7be7c801bf791 Mon Sep 17 00:00:00 2001 From: tyow Date: Mon, 9 Mar 2026 19:39:27 -0400 Subject: [PATCH 02/21] thoughts --- packages/xen/xen.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 6e67a1e4e..cb45d8069 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -106,6 +106,9 @@ export const xen = register('xen', function (scaleNameOrRatios, pat) { } const { i, ...otherValues } = hVal; const scale = getXenScale(scaleNameOrRatios.query(state)[0].value); + // scale probably needs to not be turned into pure vals + // maintain hap functionality so highlighting works + let freq = xenOffset(scale, parseNumeral(hVal.i)); // 10 is somewhat arbitrary freq = trimFreq(freq); From a161d5a5d3ccbd7fc526e99d0396eb98cd12acb9 Mon Sep 17 00:00:00 2001 From: tyow Date: Mon, 9 Mar 2026 19:44:36 -0400 Subject: [PATCH 03/21] comment in jisc3 --- packages/xen/xen.mjs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index cb45d8069..2282ea7f0 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -61,6 +61,21 @@ function xenOffset(xenScale, offset, index = 0) { const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); +// const JIsc3 = register('JIsc3', (input) => { +// let k = input + +// return new Pattern((state) => { +// let res = k.query(state) +// res = parray(k.query(state).map(x=>{ +// let c = x.context +// x = eval(x.value.join('/')) +// let r = reify(x).setContext(c) +// return r +// })).query(state) +// return res +// }) +// }) + // accepts a scale name such as 31edo, and a pattern // pattern expected to follow format such that a value can be mapped // to an edostep within the scale. Returns the pattern with From 3554a544d638f4cc7752741b1eeb658cb1e29bcf Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 00:18:34 -0400 Subject: [PATCH 04/21] erroring out --- packages/xen/xen.mjs | 62 +++++++++++------- test/__snapshots__/examples.test.mjs.snap | 80 +++++++++++------------ 2 files changed, 80 insertions(+), 62 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 2282ea7f0..759e488f7 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see . */ -import { register, _mod, parseNumeral, removeUndefineds, Pattern } from '@strudel/core'; +import { register, _mod, parseNumeral, removeUndefineds, Pattern, parray, reify } from '@strudel/core'; import Tune from './tunejs.js'; // returns a list of frequency ratios for given edo scale @@ -61,20 +61,7 @@ function xenOffset(xenScale, offset, index = 0) { const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); -// const JIsc3 = register('JIsc3', (input) => { -// let k = input - -// return new Pattern((state) => { -// let res = k.query(state) -// res = parray(k.query(state).map(x=>{ -// let c = x.context -// x = eval(x.value.join('/')) -// let r = reify(x).setContext(c) -// return r -// })).query(state) -// return res -// }) -// }) + // accepts a scale name such as 31edo, and a pattern // pattern expected to follow format such that a value can be mapped @@ -112,24 +99,55 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); */ export const xen = register('xen', function (scaleNameOrRatios, pat) { + const JIsc3 = (input) => { + let k = input + + return new Pattern((state) => { + let res = k.query(state) + res = parray(k.query(state).map(x => { + let c = x.context + x = eval(x.value.join('/')) + let r = reify(x).setContext(c) + return r + })).query(state) + return res + }) + } + const query = state => { - let haps = pat.withHap((hap)=> { + let haps = pat.withHap((hap) => { let hVal = hap.value; const isObject = typeof hVal === 'object'; if (!isObject) { throw new Error(`Expected hap to have control 'i' set, but received ${hap.value.i}, try wrapping input in i()`); } const { i, ...otherValues } = hVal; - const scale = getXenScale(scaleNameOrRatios.query(state)[0].value); - // scale probably needs to not be turned into pure vals - // maintain hap functionality so highlighting works - + // const scale = getXenScale(JIsc3(scaleNameOrRatios).query(state)[0].value); + let scale + let edo = false + if (scaleNameOrRatios.__pure != undefined) { + scale = getXenScale(scaleNameOrRatios.__pure) + } else { + let sc = scaleNameOrRatios.splitQueries().query(state); + let nameMaybe = sc[0].value + if (typeof sc[0].value == 'string') { + scale = getXenScale(sc[0].value) + if (isEdo(nameMaybe)) { + edo = nameMaybe.match(/^([1-9]+[0-9]*)edo$/)[1] + } + hap = hap.setContext(hap.combineContext(sc[0])) + } else { + // we can do [0] here because JIsc3 uses parray + scale = getXenScale(JIsc3(scaleNameOrRatios).query(state)[0].value); + hap = hap.setContext(hap.combineContext(scaleNameOrRatios.query(state)[i])) + } + } let freq = xenOffset(scale, parseNumeral(hVal.i)); // 10 is somewhat arbitrary freq = trimFreq(freq); hap.value = { ...otherValues, freq }; - return isEdo(scaleNameOrRatios) - ? hap.setContext({ ...hap.context, edoSize: scaleNameOrRatios.match(/^([1-9]+[0-9]*)edo$/)[1] }) + return edo + ? hap.setContext({ ...hap.context, edoSize: edo }) : hap; }).query(state); return removeUndefineds(haps); diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 458904baf..54ab8a879 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -5841,29 +5841,29 @@ exports[`runs examples > example "i" example index 0 1`] = ` "[ 3/4 → 7/8 | freq:505.4272762 ]", "[ 7/8 → 1/1 | freq:580.5834807 ]", "[ 1/1 → 9/8 | freq:220 ]", - "[ 9/8 → 5/4 | freq:235.7901618 ]", - "[ 5/4 → 11/8 | freq:252.7136381 ]", - "[ 11/8 → 3/2 | freq:270.8517709 ]", - "[ 3/2 → 13/8 | freq:290.2917404 ]", - "[ 13/8 → 7/4 | freq:311.1269837 ]", - "[ 7/4 → 15/8 | freq:333.4576446 ]", - "[ 15/8 → 2/1 | freq:357.3910544 ]", + "[ 9/8 → 5/4 | freq:252.7136381 ]", + "[ 5/4 → 11/8 | freq:290.2917404 ]", + "[ 11/8 → 3/2 | freq:333.4576446 ]", + "[ 3/2 → 13/8 | freq:383.0422479 ]", + "[ 13/8 → 7/4 | freq:440 ]", + "[ 7/4 → 15/8 | freq:505.4272762 ]", + "[ 15/8 → 2/1 | freq:580.5834807 ]", "[ 2/1 → 17/8 | freq:220 ]", - "[ 17/8 → 9/4 | freq:230.404707 ]", - "[ 9/4 → 19/8 | freq:241.3014955 ]", - "[ 19/8 → 5/2 | freq:252.7136381 ]", - "[ 5/2 → 21/8 | freq:264.6655079 ]", - "[ 21/8 → 11/4 | freq:277.182631 ]", - "[ 11/4 → 23/8 | freq:290.2917404 ]", - "[ 23/8 → 3/1 | freq:304.0208336 ]", + "[ 17/8 → 9/4 | freq:252.7136381 ]", + "[ 9/4 → 19/8 | freq:290.2917404 ]", + "[ 19/8 → 5/2 | freq:333.4576446 ]", + "[ 5/2 → 21/8 | freq:383.0422479 ]", + "[ 21/8 → 11/4 | freq:440 ]", + "[ 11/4 → 23/8 | freq:505.4272762 ]", + "[ 23/8 → 3/1 | freq:580.5834807 ]", "[ 3/1 → 25/8 | freq:220 ]", - "[ 25/8 → 13/4 | freq:275 ]", - "[ 13/4 → 27/8 | freq:293.3333333 ]", - "[ 27/8 → 7/2 | freq:330 ]", - "[ 7/2 → 29/8 | freq:352 ]", + "[ 25/8 → 13/4 | freq:252.7136381 ]", + "[ 13/4 → 27/8 | freq:290.2917404 ]", + "[ 27/8 → 7/2 | freq:333.4576446 ]", + "[ 7/2 → 29/8 | freq:383.0422479 ]", "[ 29/8 → 15/4 | freq:440 ]", - "[ 15/4 → 31/8 | freq:550 ]", - "[ 31/8 → 4/1 | freq:586.6666667 ]", + "[ 15/4 → 31/8 | freq:505.4272762 ]", + "[ 31/8 → 4/1 | freq:580.5834807 ]", ] `; @@ -14637,29 +14637,29 @@ exports[`runs examples > example "xen" example index 3 1`] = ` "[ 3/4 → 7/8 | freq:505.4272762 ]", "[ 7/8 → 1/1 | freq:580.5834807 ]", "[ 1/1 → 9/8 | freq:220 ]", - "[ 9/8 → 5/4 | freq:235.7901618 ]", - "[ 5/4 → 11/8 | freq:252.7136381 ]", - "[ 11/8 → 3/2 | freq:270.8517709 ]", - "[ 3/2 → 13/8 | freq:290.2917404 ]", - "[ 13/8 → 7/4 | freq:311.1269837 ]", - "[ 7/4 → 15/8 | freq:333.4576446 ]", - "[ 15/8 → 2/1 | freq:357.3910544 ]", + "[ 9/8 → 5/4 | freq:252.7136381 ]", + "[ 5/4 → 11/8 | freq:290.2917404 ]", + "[ 11/8 → 3/2 | freq:333.4576446 ]", + "[ 3/2 → 13/8 | freq:383.0422479 ]", + "[ 13/8 → 7/4 | freq:440 ]", + "[ 7/4 → 15/8 | freq:505.4272762 ]", + "[ 15/8 → 2/1 | freq:580.5834807 ]", "[ 2/1 → 17/8 | freq:220 ]", - "[ 17/8 → 9/4 | freq:230.404707 ]", - "[ 9/4 → 19/8 | freq:241.3014955 ]", - "[ 19/8 → 5/2 | freq:252.7136381 ]", - "[ 5/2 → 21/8 | freq:264.6655079 ]", - "[ 21/8 → 11/4 | freq:277.182631 ]", - "[ 11/4 → 23/8 | freq:290.2917404 ]", - "[ 23/8 → 3/1 | freq:304.0208336 ]", + "[ 17/8 → 9/4 | freq:252.7136381 ]", + "[ 9/4 → 19/8 | freq:290.2917404 ]", + "[ 19/8 → 5/2 | freq:333.4576446 ]", + "[ 5/2 → 21/8 | freq:383.0422479 ]", + "[ 21/8 → 11/4 | freq:440 ]", + "[ 11/4 → 23/8 | freq:505.4272762 ]", + "[ 23/8 → 3/1 | freq:580.5834807 ]", "[ 3/1 → 25/8 | freq:220 ]", - "[ 25/8 → 13/4 | freq:275 ]", - "[ 13/4 → 27/8 | freq:293.3333333 ]", - "[ 27/8 → 7/2 | freq:330 ]", - "[ 7/2 → 29/8 | freq:352 ]", + "[ 25/8 → 13/4 | freq:252.7136381 ]", + "[ 13/4 → 27/8 | freq:290.2917404 ]", + "[ 27/8 → 7/2 | freq:333.4576446 ]", + "[ 7/2 → 29/8 | freq:383.0422479 ]", "[ 29/8 → 15/4 | freq:440 ]", - "[ 15/4 → 31/8 | freq:550 ]", - "[ 31/8 → 4/1 | freq:586.6666667 ]", + "[ 15/4 → 31/8 | freq:505.4272762 ]", + "[ 31/8 → 4/1 | freq:580.5834807 ]", ] `; From 7510cb715f0a15732c7834a069e6862567fad468 Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 00:41:23 -0400 Subject: [PATCH 05/21] fixed prev bug. next: support stack --- packages/xen/xen.mjs | 8 +-- test/__snapshots__/examples.test.mjs.snap | 80 +++++++++++------------ 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 759e488f7..237eed039 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see . */ -import { register, _mod, parseNumeral, removeUndefineds, Pattern, parray, reify } from '@strudel/core'; +import { register, _mod, parseNumeral, removeUndefineds, Pattern, parray, reify, State } from '@strudel/core'; import Tune from './tunejs.js'; // returns a list of frequency ratios for given edo scale @@ -122,13 +122,13 @@ export const xen = register('xen', function (scaleNameOrRatios, pat) { throw new Error(`Expected hap to have control 'i' set, but received ${hap.value.i}, try wrapping input in i()`); } const { i, ...otherValues } = hVal; - // const scale = getXenScale(JIsc3(scaleNameOrRatios).query(state)[0].value); let scale let edo = false if (scaleNameOrRatios.__pure != undefined) { scale = getXenScale(scaleNameOrRatios.__pure) } else { - let sc = scaleNameOrRatios.splitQueries().query(state); + let st = new State(state.span.intersection(hap.part)) + let sc = scaleNameOrRatios.splitQueries().query(st); let nameMaybe = sc[0].value if (typeof sc[0].value == 'string') { scale = getXenScale(sc[0].value) @@ -139,7 +139,7 @@ export const xen = register('xen', function (scaleNameOrRatios, pat) { } else { // we can do [0] here because JIsc3 uses parray scale = getXenScale(JIsc3(scaleNameOrRatios).query(state)[0].value); - hap = hap.setContext(hap.combineContext(scaleNameOrRatios.query(state)[i])) + hap = hap.setContext(hap.combineContext(scaleNameOrRatios.query(st)[i])) } } let freq = xenOffset(scale, parseNumeral(hVal.i)); diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 54ab8a879..458904baf 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -5841,29 +5841,29 @@ exports[`runs examples > example "i" example index 0 1`] = ` "[ 3/4 → 7/8 | freq:505.4272762 ]", "[ 7/8 → 1/1 | freq:580.5834807 ]", "[ 1/1 → 9/8 | freq:220 ]", - "[ 9/8 → 5/4 | freq:252.7136381 ]", - "[ 5/4 → 11/8 | freq:290.2917404 ]", - "[ 11/8 → 3/2 | freq:333.4576446 ]", - "[ 3/2 → 13/8 | freq:383.0422479 ]", - "[ 13/8 → 7/4 | freq:440 ]", - "[ 7/4 → 15/8 | freq:505.4272762 ]", - "[ 15/8 → 2/1 | freq:580.5834807 ]", + "[ 9/8 → 5/4 | freq:235.7901618 ]", + "[ 5/4 → 11/8 | freq:252.7136381 ]", + "[ 11/8 → 3/2 | freq:270.8517709 ]", + "[ 3/2 → 13/8 | freq:290.2917404 ]", + "[ 13/8 → 7/4 | freq:311.1269837 ]", + "[ 7/4 → 15/8 | freq:333.4576446 ]", + "[ 15/8 → 2/1 | freq:357.3910544 ]", "[ 2/1 → 17/8 | freq:220 ]", - "[ 17/8 → 9/4 | freq:252.7136381 ]", - "[ 9/4 → 19/8 | freq:290.2917404 ]", - "[ 19/8 → 5/2 | freq:333.4576446 ]", - "[ 5/2 → 21/8 | freq:383.0422479 ]", - "[ 21/8 → 11/4 | freq:440 ]", - "[ 11/4 → 23/8 | freq:505.4272762 ]", - "[ 23/8 → 3/1 | freq:580.5834807 ]", + "[ 17/8 → 9/4 | freq:230.404707 ]", + "[ 9/4 → 19/8 | freq:241.3014955 ]", + "[ 19/8 → 5/2 | freq:252.7136381 ]", + "[ 5/2 → 21/8 | freq:264.6655079 ]", + "[ 21/8 → 11/4 | freq:277.182631 ]", + "[ 11/4 → 23/8 | freq:290.2917404 ]", + "[ 23/8 → 3/1 | freq:304.0208336 ]", "[ 3/1 → 25/8 | freq:220 ]", - "[ 25/8 → 13/4 | freq:252.7136381 ]", - "[ 13/4 → 27/8 | freq:290.2917404 ]", - "[ 27/8 → 7/2 | freq:333.4576446 ]", - "[ 7/2 → 29/8 | freq:383.0422479 ]", + "[ 25/8 → 13/4 | freq:275 ]", + "[ 13/4 → 27/8 | freq:293.3333333 ]", + "[ 27/8 → 7/2 | freq:330 ]", + "[ 7/2 → 29/8 | freq:352 ]", "[ 29/8 → 15/4 | freq:440 ]", - "[ 15/4 → 31/8 | freq:505.4272762 ]", - "[ 31/8 → 4/1 | freq:580.5834807 ]", + "[ 15/4 → 31/8 | freq:550 ]", + "[ 31/8 → 4/1 | freq:586.6666667 ]", ] `; @@ -14637,29 +14637,29 @@ exports[`runs examples > example "xen" example index 3 1`] = ` "[ 3/4 → 7/8 | freq:505.4272762 ]", "[ 7/8 → 1/1 | freq:580.5834807 ]", "[ 1/1 → 9/8 | freq:220 ]", - "[ 9/8 → 5/4 | freq:252.7136381 ]", - "[ 5/4 → 11/8 | freq:290.2917404 ]", - "[ 11/8 → 3/2 | freq:333.4576446 ]", - "[ 3/2 → 13/8 | freq:383.0422479 ]", - "[ 13/8 → 7/4 | freq:440 ]", - "[ 7/4 → 15/8 | freq:505.4272762 ]", - "[ 15/8 → 2/1 | freq:580.5834807 ]", + "[ 9/8 → 5/4 | freq:235.7901618 ]", + "[ 5/4 → 11/8 | freq:252.7136381 ]", + "[ 11/8 → 3/2 | freq:270.8517709 ]", + "[ 3/2 → 13/8 | freq:290.2917404 ]", + "[ 13/8 → 7/4 | freq:311.1269837 ]", + "[ 7/4 → 15/8 | freq:333.4576446 ]", + "[ 15/8 → 2/1 | freq:357.3910544 ]", "[ 2/1 → 17/8 | freq:220 ]", - "[ 17/8 → 9/4 | freq:252.7136381 ]", - "[ 9/4 → 19/8 | freq:290.2917404 ]", - "[ 19/8 → 5/2 | freq:333.4576446 ]", - "[ 5/2 → 21/8 | freq:383.0422479 ]", - "[ 21/8 → 11/4 | freq:440 ]", - "[ 11/4 → 23/8 | freq:505.4272762 ]", - "[ 23/8 → 3/1 | freq:580.5834807 ]", + "[ 17/8 → 9/4 | freq:230.404707 ]", + "[ 9/4 → 19/8 | freq:241.3014955 ]", + "[ 19/8 → 5/2 | freq:252.7136381 ]", + "[ 5/2 → 21/8 | freq:264.6655079 ]", + "[ 21/8 → 11/4 | freq:277.182631 ]", + "[ 11/4 → 23/8 | freq:290.2917404 ]", + "[ 23/8 → 3/1 | freq:304.0208336 ]", "[ 3/1 → 25/8 | freq:220 ]", - "[ 25/8 → 13/4 | freq:252.7136381 ]", - "[ 13/4 → 27/8 | freq:290.2917404 ]", - "[ 27/8 → 7/2 | freq:333.4576446 ]", - "[ 7/2 → 29/8 | freq:383.0422479 ]", + "[ 25/8 → 13/4 | freq:275 ]", + "[ 13/4 → 27/8 | freq:293.3333333 ]", + "[ 27/8 → 7/2 | freq:330 ]", + "[ 7/2 → 29/8 | freq:352 ]", "[ 29/8 → 15/4 | freq:440 ]", - "[ 15/4 → 31/8 | freq:505.4272762 ]", - "[ 31/8 → 4/1 | freq:580.5834807 ]", + "[ 15/4 → 31/8 | freq:550 ]", + "[ 31/8 → 4/1 | freq:586.6666667 ]", ] `; From a1ccb9c0bb311c4815ea0fd2361e0891c0a45099 Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 14:39:25 -0400 Subject: [PATCH 06/21] working stack for named scales --- packages/xen/xen.mjs | 149 ++++++++++++++++++++++++++----------------- 1 file changed, 92 insertions(+), 57 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 237eed039..3d304b706 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see . */ -import { register, _mod, parseNumeral, removeUndefineds, Pattern, parray, reify, State } from '@strudel/core'; +import { register, _mod, parseNumeral, removeUndefineds, Pattern, parray, reify, State, flatten } from '@strudel/core'; import Tune from './tunejs.js'; // returns a list of frequency ratios for given edo scale @@ -61,8 +61,6 @@ function xenOffset(xenScale, offset, index = 0) { const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); - - // accepts a scale name such as 31edo, and a pattern // pattern expected to follow format such that a value can be mapped // to an edostep within the scale. Returns the pattern with @@ -98,62 +96,99 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); * i("0 1 2 3 4 5 6 7").xen("<5edo 10edo 15edo hexany15>") */ -export const xen = register('xen', function (scaleNameOrRatios, pat) { - const JIsc3 = (input) => { - let k = input +export const xen = register( + 'xen', + function (scaleNameOrRatios, pat) { + const JIsc3 = (input) => { + let k = input; - return new Pattern((state) => { - let res = k.query(state) - res = parray(k.query(state).map(x => { - let c = x.context - x = eval(x.value.join('/')) - let r = reify(x).setContext(c) - return r - })).query(state) - return res - }) - } + return new Pattern((state) => { + let res = k.query(state); + res = parray( + k.query(state).map((x) => { + let c = x.context; + x = eval(x.value.join('/')); + let r = reify(x).setContext(c); + return r; + }), + ).query(state); + return res; + }); + }; - const query = state => { - let haps = pat.withHap((hap) => { - let hVal = hap.value; - const isObject = typeof hVal === 'object'; - if (!isObject) { - throw new Error(`Expected hap to have control 'i' set, but received ${hap.value.i}, try wrapping input in i()`); - } - const { i, ...otherValues } = hVal; - let scale - let edo = false - if (scaleNameOrRatios.__pure != undefined) { - scale = getXenScale(scaleNameOrRatios.__pure) - } else { - let st = new State(state.span.intersection(hap.part)) - let sc = scaleNameOrRatios.splitQueries().query(st); - let nameMaybe = sc[0].value - if (typeof sc[0].value == 'string') { - scale = getXenScale(sc[0].value) - if (isEdo(nameMaybe)) { - edo = nameMaybe.match(/^([1-9]+[0-9]*)edo$/)[1] - } - hap = hap.setContext(hap.combineContext(sc[0])) - } else { - // we can do [0] here because JIsc3 uses parray - scale = getXenScale(JIsc3(scaleNameOrRatios).query(state)[0].value); - hap = hap.setContext(hap.combineContext(scaleNameOrRatios.query(st)[i])) - } - } - let freq = xenOffset(scale, parseNumeral(hVal.i)); - // 10 is somewhat arbitrary - freq = trimFreq(freq); - hap.value = { ...otherValues, freq }; - return edo - ? hap.setContext({ ...hap.context, edoSize: edo }) - : hap; - }).query(state); - return removeUndefineds(haps); - }; - return new Pattern(query) -}, false); + // How do we use curry to solve the stack problem + /* + Register does this by effectively saying + are there multiple args? + If so, split them into two arrays + left has 1, right has rest + join left and right: + + result = join(right.reduce((acc, p) => acc.appLeft(p), left.fmap(mapFn))); + + where mapFn applies the registered function 'func'. + ---- + When we're in xen but not in query, then we already have access to `scaleNameOrRatios` + Could we run query for each? (could that be 'func' in this case?) + ---- + I don't think so, I think it makes more sense to do it within the query, but call an innerfunc on each arg + */ + const query = (state) => { + let args = scaleNameOrRatios.query(state); + + let k = args.map((arg) => { + let haps = pat + .withHap((hap) => { + let hVal = hap.value; + const isObject = typeof hVal === 'object'; + if (!isObject) { + throw new Error( + `Expected hap to have control 'i' set, but received ${hap.value.i}, try wrapping input in i()`, + ); + } + const { i, ...otherValues } = hVal; + let scale; + let edo = false; + if (scaleNameOrRatios.__pure != undefined) { + scale = getXenScale(scaleNameOrRatios.__pure); + } else { + let st = new State(state.span.intersection(hap.part)); + let sc = arg; + let nameMaybe = sc.value; + if (typeof sc.value == 'string') { + scale = getXenScale(nameMaybe); + if (isEdo(nameMaybe)) { + edo = nameMaybe.match(/^([1-9]+[0-9]*)edo$/)[1]; + } + hap = hap.setContext(hap.combineContext(sc)); + } else { + // we can do [0] here because JIsc3 uses parray + scale = getXenScale(JIsc3(scaleNameOrRatios).query(state)[0].value); + hap = hap.setContext(hap.combineContext(scaleNameOrRatios.query(st)[i])); + } + } + let freq = xenOffset(scale, parseNumeral(hVal.i)); + // 10 is somewhat arbitrary + freq = trimFreq(freq); + hap.value = { ...otherValues, freq }; + return edo ? hap.setContext({ ...hap.context, edoSize: edo }) : hap; + }) + .query(state); + return removeUndefineds(haps); + }); + console.log(k) + return flatten(k) + }; + + /* + perhaps instead of + return new Pattern(query) + we could do a join on scaleNameOrRatios which creates multiple patterns and then joins them + */ + return new Pattern(query); + }, + false, +); /** * Assumes pattern of frequencies tuned to some `base` frequency, such as the output of `xen` From 3e5c945e1259bae02102a8b5246fbb8f3666a3d3 Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 15:00:39 -0400 Subject: [PATCH 07/21] added thoughts. --- packages/xen/xen.mjs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 3d304b706..248d2739d 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -132,6 +132,23 @@ export const xen = register( Could we run query for each? (could that be 'func' in this case?) ---- I don't think so, I think it makes more sense to do it within the query, but call an innerfunc on each arg + ---- + Okay, working for strings. + + How do you tell the different between these two inputs? + + i("0 1").xen(` + 1:1, + [13:12, 5:4], + 2:1 + `).piano().log() + + i("0 1").xen(` + 1:1, + 13:12, + 5:4, + 2:1 + `).piano().log() */ const query = (state) => { let args = scaleNameOrRatios.query(state); From 7c7da3e783ea486af797511a6b1daec017a7512e Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 18:01:56 -0400 Subject: [PATCH 08/21] progress --- packages/xen/xen.mjs | 72 ++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 248d2739d..ec18819ca 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -149,11 +149,44 @@ export const xen = register( 5:4, 2:1 `).piano().log() - */ - const query = (state) => { - let args = scaleNameOrRatios.query(state); - let k = args.map((arg) => { + + If it's not, we can just do: + xen([ + "1:1", + "[13:12, 5:4]", + ... + ]) + + ---- + + okay I got the above working and now I need to rejigger this one to work with the other stuff + + i("0 1 2 3").xen("hexany15, [sev-elev hexany23]").s("sin") + + */ + + const JIsc2 = (input) => { + let k = parray(input) + + return new Pattern((state) => { + let res = k.withValue(x => x.map(y => eval(y.join('/')))).query(state) + return res + }) + } + + const query = (state) => { + let input = scaleNameOrRatios.query(state); + + let scPat = input[0].value + let scs + if (typeof scPat == 'string') { + scs = [scPat] + } else { + scs = JIsc2(scPat).query(state) + } + + let k = scs.map(sc => { let haps = pat .withHap((hap) => { let hVal = hap.value; @@ -166,22 +199,17 @@ export const xen = register( const { i, ...otherValues } = hVal; let scale; let edo = false; - if (scaleNameOrRatios.__pure != undefined) { - scale = getXenScale(scaleNameOrRatios.__pure); + let st = new State(state.span.intersection(hap.part)); + if (typeof sc == 'string') { + scale = getXenScale(sc); + if (isEdo(sc)) { + edo = sc.match(/^([1-9]+[0-9]*)edo$/)[1]; + } + hap = hap.setContext(hap.combineContext(sc)); } else { - let st = new State(state.span.intersection(hap.part)); - let sc = arg; - let nameMaybe = sc.value; - if (typeof sc.value == 'string') { - scale = getXenScale(nameMaybe); - if (isEdo(nameMaybe)) { - edo = nameMaybe.match(/^([1-9]+[0-9]*)edo$/)[1]; - } - hap = hap.setContext(hap.combineContext(sc)); - } else { - // we can do [0] here because JIsc3 uses parray - scale = getXenScale(JIsc3(scaleNameOrRatios).query(state)[0].value); - hap = hap.setContext(hap.combineContext(scaleNameOrRatios.query(st)[i])); + scale = getXenScale(sc.value); + for (let h of scPat[i].query(state)) { + hap = hap.setContext(hap.combineContext(h)); } } let freq = xenOffset(scale, parseNumeral(hVal.i)); @@ -191,9 +219,9 @@ export const xen = register( return edo ? hap.setContext({ ...hap.context, edoSize: edo }) : hap; }) .query(state); - return removeUndefineds(haps); - }); - console.log(k) + // return removeUndefineds(haps); + return haps + }) return flatten(k) }; From f769b9c7a50d67e7adf985e7f6526273ba137194 Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 18:11:34 -0400 Subject: [PATCH 09/21] It looks good in repl and bad on test --- packages/xen/xen.mjs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index ec18819ca..8ac524c8d 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -178,15 +178,17 @@ export const xen = register( const query = (state) => { let input = scaleNameOrRatios.query(state); + if (input.length == 0) return [] + let scPat = input[0].value let scs if (typeof scPat == 'string') { - scs = [scPat] + scs = input.map(x=>x.value) } else { scs = JIsc2(scPat).query(state) } - let k = scs.map(sc => { + let k = scs.map((sc, ith) => { let haps = pat .withHap((hap) => { let hVal = hap.value; @@ -205,7 +207,7 @@ export const xen = register( if (isEdo(sc)) { edo = sc.match(/^([1-9]+[0-9]*)edo$/)[1]; } - hap = hap.setContext(hap.combineContext(sc)); + hap = hap.setContext(hap.combineContext(input[ith])); } else { scale = getXenScale(sc.value); for (let h of scPat[i].query(state)) { @@ -219,8 +221,8 @@ export const xen = register( return edo ? hap.setContext({ ...hap.context, edoSize: edo }) : hap; }) .query(state); - // return removeUndefineds(haps); - return haps + return removeUndefineds(haps); + // return haps }) return flatten(k) }; @@ -230,7 +232,9 @@ export const xen = register( return new Pattern(query) we could do a join on scaleNameOrRatios which creates multiple patterns and then joins them */ - return new Pattern(query); + let res = new Pattern(query) + + return res; }, false, ); From 25bf6856aedcba1ec1a9b9ebb8a6dae437a018ff Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 18:25:01 -0400 Subject: [PATCH 10/21] format, snapshot --- packages/xen/xen.mjs | 98 ++---- test/__snapshots__/examples.test.mjs.snap | 365 +++++++++++++++++++--- 2 files changed, 349 insertions(+), 114 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 8ac524c8d..a5cd72488 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -67,6 +67,16 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); // values mapped to the frequencies associated with the given edosteps // scaleNameOrRatios: string || number[], steps?: number +// old, currently unsupported +// * @example +// * // You can also use xen with frequency ratios. +// * // This is equivalent to the above: +// * i("0 1 2").xen([ +// * Math.pow(2, 0/31), +// * Math.pow(2, 8/31), +// * Math.pow(2, 18/31), +// * ]).piano() + /** * Assumes a numerical pattern of scale steps, and a scale. Scales accepted are all preset scale names of `tune`, arbitrary edos such as 31edo, or an array of frequency ratios. Assumes scales repeat at octave (2/1). Returns a new pattern with all values mapped to their associated frequency, assuming a base frequency of 220hz. * @@ -79,14 +89,6 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); * // A minor triad in 31edo: * i("0 8 18").xen("31edo").piano() * @example - * // You can also use xen with frequency ratios. - * // This is equivalent to the above: - * i("0 1 2").xen([ - * Math.pow(2, 0/31), - * Math.pow(2, 8/31), - * Math.pow(2, 18/31), - * ]).piano() - * @example * // xen also supports all scale names that * // tune does: * i("0 1 2 3 4 5").xen("hexany15") @@ -116,76 +118,26 @@ export const xen = register( }); }; - // How do we use curry to solve the stack problem - /* - Register does this by effectively saying - are there multiple args? - If so, split them into two arrays - left has 1, right has rest - join left and right: - - result = join(right.reduce((acc, p) => acc.appLeft(p), left.fmap(mapFn))); - - where mapFn applies the registered function 'func'. - ---- - When we're in xen but not in query, then we already have access to `scaleNameOrRatios` - Could we run query for each? (could that be 'func' in this case?) - ---- - I don't think so, I think it makes more sense to do it within the query, but call an innerfunc on each arg - ---- - Okay, working for strings. - - How do you tell the different between these two inputs? - - i("0 1").xen(` - 1:1, - [13:12, 5:4], - 2:1 - `).piano().log() - - i("0 1").xen(` - 1:1, - 13:12, - 5:4, - 2:1 - `).piano().log() - - - If it's not, we can just do: - xen([ - "1:1", - "[13:12, 5:4]", - ... - ]) - - ---- - - okay I got the above working and now I need to rejigger this one to work with the other stuff - - i("0 1 2 3").xen("hexany15, [sev-elev hexany23]").s("sin") - - */ - const JIsc2 = (input) => { - let k = parray(input) + let k = parray(input); return new Pattern((state) => { - let res = k.withValue(x => x.map(y => eval(y.join('/')))).query(state) - return res - }) - } + let res = k.withValue((x) => x.map((y) => eval(y.join('/')))).query(state); + return res; + }); + }; const query = (state) => { let input = scaleNameOrRatios.query(state); - - if (input.length == 0) return [] - let scPat = input[0].value - let scs + if (input.length == 0) return []; + + let scPat = input[0].value; + let scs; if (typeof scPat == 'string') { - scs = input.map(x=>x.value) + scs = input.map((x) => x.value); } else { - scs = JIsc2(scPat).query(state) + scs = JIsc2(scPat).query(state); } let k = scs.map((sc, ith) => { @@ -223,8 +175,8 @@ export const xen = register( .query(state); return removeUndefineds(haps); // return haps - }) - return flatten(k) + }); + return flatten(k); }; /* @@ -232,8 +184,8 @@ export const xen = register( return new Pattern(query) we could do a join on scaleNameOrRatios which creates multiple patterns and then joins them */ - let res = new Pattern(query) - + let res = new Pattern(query); + return res; }, false, diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 458904baf..cc8a73c89 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -5832,37 +5832,133 @@ exports[`runs examples > example "hush" example index 0 1`] = ` exports[`runs examples > example "i" example index 0 1`] = ` [ + "[ 0/1 → 1/8 | freq:220 ]", + "[ 0/1 → 1/8 | freq:220 ]", + "[ 0/1 → 1/8 | freq:220 ]", "[ 0/1 → 1/8 | freq:220 ]", "[ 1/8 → 1/4 | freq:252.7136381 ]", + "[ 1/8 → 1/4 | freq:235.7901618 ]", + "[ 1/8 → 1/4 | freq:230.404707 ]", + "[ 1/8 → 1/4 | freq:275 ]", "[ 1/4 → 3/8 | freq:290.2917404 ]", + "[ 1/4 → 3/8 | freq:252.7136381 ]", + "[ 1/4 → 3/8 | freq:241.3014955 ]", + "[ 1/4 → 3/8 | freq:293.3333333 ]", "[ 3/8 → 1/2 | freq:333.4576446 ]", + "[ 3/8 → 1/2 | freq:270.8517709 ]", + "[ 3/8 → 1/2 | freq:252.7136381 ]", + "[ 3/8 → 1/2 | freq:330 ]", "[ 1/2 → 5/8 | freq:383.0422479 ]", + "[ 1/2 → 5/8 | freq:290.2917404 ]", + "[ 1/2 → 5/8 | freq:264.6655079 ]", + "[ 1/2 → 5/8 | freq:352 ]", + "[ 5/8 → 3/4 | freq:440 ]", + "[ 5/8 → 3/4 | freq:311.1269837 ]", + "[ 5/8 → 3/4 | freq:277.182631 ]", "[ 5/8 → 3/4 | freq:440 ]", "[ 3/4 → 7/8 | freq:505.4272762 ]", + "[ 3/4 → 7/8 | freq:333.4576446 ]", + "[ 3/4 → 7/8 | freq:290.2917404 ]", + "[ 3/4 → 7/8 | freq:550 ]", "[ 7/8 → 1/1 | freq:580.5834807 ]", + "[ 7/8 → 1/1 | freq:357.3910544 ]", + "[ 7/8 → 1/1 | freq:304.0208336 ]", + "[ 7/8 → 1/1 | freq:586.6666667 ]", "[ 1/1 → 9/8 | freq:220 ]", + "[ 1/1 → 9/8 | freq:220 ]", + "[ 1/1 → 9/8 | freq:220 ]", + "[ 1/1 → 9/8 | freq:220 ]", + "[ 9/8 → 5/4 | freq:252.7136381 ]", "[ 9/8 → 5/4 | freq:235.7901618 ]", + "[ 9/8 → 5/4 | freq:230.404707 ]", + "[ 9/8 → 5/4 | freq:275 ]", + "[ 5/4 → 11/8 | freq:290.2917404 ]", "[ 5/4 → 11/8 | freq:252.7136381 ]", + "[ 5/4 → 11/8 | freq:241.3014955 ]", + "[ 5/4 → 11/8 | freq:293.3333333 ]", + "[ 11/8 → 3/2 | freq:333.4576446 ]", "[ 11/8 → 3/2 | freq:270.8517709 ]", + "[ 11/8 → 3/2 | freq:252.7136381 ]", + "[ 11/8 → 3/2 | freq:330 ]", + "[ 3/2 → 13/8 | freq:383.0422479 ]", "[ 3/2 → 13/8 | freq:290.2917404 ]", + "[ 3/2 → 13/8 | freq:264.6655079 ]", + "[ 3/2 → 13/8 | freq:352 ]", + "[ 13/8 → 7/4 | freq:440 ]", "[ 13/8 → 7/4 | freq:311.1269837 ]", + "[ 13/8 → 7/4 | freq:277.182631 ]", + "[ 13/8 → 7/4 | freq:440 ]", + "[ 7/4 → 15/8 | freq:505.4272762 ]", "[ 7/4 → 15/8 | freq:333.4576446 ]", + "[ 7/4 → 15/8 | freq:290.2917404 ]", + "[ 7/4 → 15/8 | freq:550 ]", + "[ 15/8 → 2/1 | freq:580.5834807 ]", "[ 15/8 → 2/1 | freq:357.3910544 ]", + "[ 15/8 → 2/1 | freq:304.0208336 ]", + "[ 15/8 → 2/1 | freq:586.6666667 ]", "[ 2/1 → 17/8 | freq:220 ]", + "[ 2/1 → 17/8 | freq:220 ]", + "[ 2/1 → 17/8 | freq:220 ]", + "[ 2/1 → 17/8 | freq:220 ]", + "[ 17/8 → 9/4 | freq:252.7136381 ]", + "[ 17/8 → 9/4 | freq:235.7901618 ]", "[ 17/8 → 9/4 | freq:230.404707 ]", + "[ 17/8 → 9/4 | freq:275 ]", + "[ 9/4 → 19/8 | freq:290.2917404 ]", + "[ 9/4 → 19/8 | freq:252.7136381 ]", "[ 9/4 → 19/8 | freq:241.3014955 ]", + "[ 9/4 → 19/8 | freq:293.3333333 ]", + "[ 19/8 → 5/2 | freq:333.4576446 ]", + "[ 19/8 → 5/2 | freq:270.8517709 ]", "[ 19/8 → 5/2 | freq:252.7136381 ]", + "[ 19/8 → 5/2 | freq:330 ]", + "[ 5/2 → 21/8 | freq:383.0422479 ]", + "[ 5/2 → 21/8 | freq:290.2917404 ]", "[ 5/2 → 21/8 | freq:264.6655079 ]", + "[ 5/2 → 21/8 | freq:352 ]", + "[ 21/8 → 11/4 | freq:440 ]", + "[ 21/8 → 11/4 | freq:311.1269837 ]", "[ 21/8 → 11/4 | freq:277.182631 ]", + "[ 21/8 → 11/4 | freq:440 ]", + "[ 11/4 → 23/8 | freq:505.4272762 ]", + "[ 11/4 → 23/8 | freq:333.4576446 ]", "[ 11/4 → 23/8 | freq:290.2917404 ]", + "[ 11/4 → 23/8 | freq:550 ]", + "[ 23/8 → 3/1 | freq:580.5834807 ]", + "[ 23/8 → 3/1 | freq:357.3910544 ]", "[ 23/8 → 3/1 | freq:304.0208336 ]", + "[ 23/8 → 3/1 | freq:586.6666667 ]", "[ 3/1 → 25/8 | freq:220 ]", + "[ 3/1 → 25/8 | freq:220 ]", + "[ 3/1 → 25/8 | freq:220 ]", + "[ 3/1 → 25/8 | freq:220 ]", + "[ 25/8 → 13/4 | freq:252.7136381 ]", + "[ 25/8 → 13/4 | freq:235.7901618 ]", + "[ 25/8 → 13/4 | freq:230.404707 ]", "[ 25/8 → 13/4 | freq:275 ]", + "[ 13/4 → 27/8 | freq:290.2917404 ]", + "[ 13/4 → 27/8 | freq:252.7136381 ]", + "[ 13/4 → 27/8 | freq:241.3014955 ]", "[ 13/4 → 27/8 | freq:293.3333333 ]", + "[ 27/8 → 7/2 | freq:333.4576446 ]", + "[ 27/8 → 7/2 | freq:270.8517709 ]", + "[ 27/8 → 7/2 | freq:252.7136381 ]", "[ 27/8 → 7/2 | freq:330 ]", + "[ 7/2 → 29/8 | freq:383.0422479 ]", + "[ 7/2 → 29/8 | freq:290.2917404 ]", + "[ 7/2 → 29/8 | freq:264.6655079 ]", "[ 7/2 → 29/8 | freq:352 ]", "[ 29/8 → 15/4 | freq:440 ]", + "[ 29/8 → 15/4 | freq:311.1269837 ]", + "[ 29/8 → 15/4 | freq:277.182631 ]", + "[ 29/8 → 15/4 | freq:440 ]", + "[ 15/4 → 31/8 | freq:505.4272762 ]", + "[ 15/4 → 31/8 | freq:333.4576446 ]", + "[ 15/4 → 31/8 | freq:290.2917404 ]", "[ 15/4 → 31/8 | freq:550 ]", + "[ 31/8 → 4/1 | freq:580.5834807 ]", + "[ 31/8 → 4/1 | freq:357.3910544 ]", + "[ 31/8 → 4/1 | freq:304.0208336 ]", "[ 31/8 → 4/1 | freq:586.6666667 ]", ] `; @@ -14566,99 +14662,286 @@ exports[`runs examples > example "wtphaserand" example index 0 1`] = ` exports[`runs examples > example "xen" example index 0 1`] = ` [ "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", ] `; exports[`runs examples > example "xen" example index 1 1`] = ` [ - "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 0/1 → 1/6 | freq:220 ]", + "[ 0/1 → 1/6 | freq:220 ]", + "[ 0/1 → 1/6 | freq:220 ]", + "[ 0/1 → 1/6 | freq:220 ]", + "[ 1/6 → 1/3 | freq:275 ]", + "[ 1/6 → 1/3 | freq:275 ]", + "[ 1/6 → 1/3 | freq:275 ]", + "[ 1/6 → 1/3 | freq:275 ]", + "[ 1/3 → 1/2 | freq:293.3333333 ]", + "[ 1/3 → 1/2 | freq:293.3333333 ]", + "[ 1/3 → 1/2 | freq:293.3333333 ]", + "[ 1/3 → 1/2 | freq:293.3333333 ]", + "[ 1/2 → 2/3 | freq:330 ]", + "[ 1/2 → 2/3 | freq:330 ]", + "[ 1/2 → 2/3 | freq:330 ]", + "[ 1/2 → 2/3 | freq:330 ]", + "[ 2/3 → 5/6 | freq:352 ]", + "[ 2/3 → 5/6 | freq:352 ]", + "[ 2/3 → 5/6 | freq:352 ]", + "[ 2/3 → 5/6 | freq:352 ]", + "[ 5/6 → 1/1 | freq:440 ]", + "[ 5/6 → 1/1 | freq:440 ]", + "[ 5/6 → 1/1 | freq:440 ]", + "[ 5/6 → 1/1 | freq:440 ]", + "[ 1/1 → 7/6 | freq:220 ]", + "[ 1/1 → 7/6 | freq:220 ]", + "[ 1/1 → 7/6 | freq:220 ]", + "[ 1/1 → 7/6 | freq:220 ]", + "[ 7/6 → 4/3 | freq:275 ]", + "[ 7/6 → 4/3 | freq:275 ]", + "[ 7/6 → 4/3 | freq:275 ]", + "[ 7/6 → 4/3 | freq:275 ]", + "[ 4/3 → 3/2 | freq:293.3333333 ]", + "[ 4/3 → 3/2 | freq:293.3333333 ]", + "[ 4/3 → 3/2 | freq:293.3333333 ]", + "[ 4/3 → 3/2 | freq:293.3333333 ]", + "[ 3/2 → 5/3 | freq:330 ]", + "[ 3/2 → 5/3 | freq:330 ]", + "[ 3/2 → 5/3 | freq:330 ]", + "[ 3/2 → 5/3 | freq:330 ]", + "[ 5/3 → 11/6 | freq:352 ]", + "[ 5/3 → 11/6 | freq:352 ]", + "[ 5/3 → 11/6 | freq:352 ]", + "[ 5/3 → 11/6 | freq:352 ]", + "[ 11/6 → 2/1 | freq:440 ]", + "[ 11/6 → 2/1 | freq:440 ]", + "[ 11/6 → 2/1 | freq:440 ]", + "[ 11/6 → 2/1 | freq:440 ]", + "[ 2/1 → 13/6 | freq:220 ]", + "[ 2/1 → 13/6 | freq:220 ]", + "[ 2/1 → 13/6 | freq:220 ]", + "[ 2/1 → 13/6 | freq:220 ]", + "[ 13/6 → 7/3 | freq:275 ]", + "[ 13/6 → 7/3 | freq:275 ]", + "[ 13/6 → 7/3 | freq:275 ]", + "[ 13/6 → 7/3 | freq:275 ]", + "[ 7/3 → 5/2 | freq:293.3333333 ]", + "[ 7/3 → 5/2 | freq:293.3333333 ]", + "[ 7/3 → 5/2 | freq:293.3333333 ]", + "[ 7/3 → 5/2 | freq:293.3333333 ]", + "[ 5/2 → 8/3 | freq:330 ]", + "[ 5/2 → 8/3 | freq:330 ]", + "[ 5/2 → 8/3 | freq:330 ]", + "[ 5/2 → 8/3 | freq:330 ]", + "[ 8/3 → 17/6 | freq:352 ]", + "[ 8/3 → 17/6 | freq:352 ]", + "[ 8/3 → 17/6 | freq:352 ]", + "[ 8/3 → 17/6 | freq:352 ]", + "[ 17/6 → 3/1 | freq:440 ]", + "[ 17/6 → 3/1 | freq:440 ]", + "[ 17/6 → 3/1 | freq:440 ]", + "[ 17/6 → 3/1 | freq:440 ]", + "[ 3/1 → 19/6 | freq:220 ]", + "[ 3/1 → 19/6 | freq:220 ]", + "[ 3/1 → 19/6 | freq:220 ]", + "[ 3/1 → 19/6 | freq:220 ]", + "[ 19/6 → 10/3 | freq:275 ]", + "[ 19/6 → 10/3 | freq:275 ]", + "[ 19/6 → 10/3 | freq:275 ]", + "[ 19/6 → 10/3 | freq:275 ]", + "[ 10/3 → 7/2 | freq:293.3333333 ]", + "[ 10/3 → 7/2 | freq:293.3333333 ]", + "[ 10/3 → 7/2 | freq:293.3333333 ]", + "[ 10/3 → 7/2 | freq:293.3333333 ]", + "[ 7/2 → 11/3 | freq:330 ]", + "[ 7/2 → 11/3 | freq:330 ]", + "[ 7/2 → 11/3 | freq:330 ]", + "[ 7/2 → 11/3 | freq:330 ]", + "[ 11/3 → 23/6 | freq:352 ]", + "[ 11/3 → 23/6 | freq:352 ]", + "[ 11/3 → 23/6 | freq:352 ]", + "[ 11/3 → 23/6 | freq:352 ]", + "[ 23/6 → 4/1 | freq:440 ]", + "[ 23/6 → 4/1 | freq:440 ]", + "[ 23/6 → 4/1 | freq:440 ]", + "[ 23/6 → 4/1 | freq:440 ]", ] `; exports[`runs examples > example "xen" example index 2 1`] = ` [ - "[ 0/1 → 1/6 | freq:220 ]", - "[ 1/6 → 1/3 | freq:275 ]", - "[ 1/3 → 1/2 | freq:293.3333333 ]", - "[ 1/2 → 2/3 | freq:330 ]", - "[ 2/3 → 5/6 | freq:352 ]", - "[ 5/6 → 1/1 | freq:440 ]", - "[ 1/1 → 7/6 | freq:220 ]", - "[ 7/6 → 4/3 | freq:275 ]", - "[ 4/3 → 3/2 | freq:293.3333333 ]", - "[ 3/2 → 5/3 | freq:330 ]", - "[ 5/3 → 11/6 | freq:352 ]", - "[ 11/6 → 2/1 | freq:440 ]", - "[ 2/1 → 13/6 | freq:220 ]", - "[ 13/6 → 7/3 | freq:275 ]", - "[ 7/3 → 5/2 | freq:293.3333333 ]", - "[ 5/2 → 8/3 | freq:330 ]", - "[ 8/3 → 17/6 | freq:352 ]", - "[ 17/6 → 3/1 | freq:440 ]", - "[ 3/1 → 19/6 | freq:220 ]", - "[ 19/6 → 10/3 | freq:275 ]", - "[ 10/3 → 7/2 | freq:293.3333333 ]", - "[ 7/2 → 11/3 | freq:330 ]", - "[ 11/3 → 23/6 | freq:352 ]", - "[ 23/6 → 4/1 | freq:440 ]", -] -`; - -exports[`runs examples > example "xen" example index 3 1`] = ` -[ + "[ 0/1 → 1/8 | freq:220 ]", + "[ 0/1 → 1/8 | freq:220 ]", + "[ 0/1 → 1/8 | freq:220 ]", "[ 0/1 → 1/8 | freq:220 ]", "[ 1/8 → 1/4 | freq:252.7136381 ]", + "[ 1/8 → 1/4 | freq:235.7901618 ]", + "[ 1/8 → 1/4 | freq:230.404707 ]", + "[ 1/8 → 1/4 | freq:275 ]", "[ 1/4 → 3/8 | freq:290.2917404 ]", + "[ 1/4 → 3/8 | freq:252.7136381 ]", + "[ 1/4 → 3/8 | freq:241.3014955 ]", + "[ 1/4 → 3/8 | freq:293.3333333 ]", "[ 3/8 → 1/2 | freq:333.4576446 ]", + "[ 3/8 → 1/2 | freq:270.8517709 ]", + "[ 3/8 → 1/2 | freq:252.7136381 ]", + "[ 3/8 → 1/2 | freq:330 ]", "[ 1/2 → 5/8 | freq:383.0422479 ]", + "[ 1/2 → 5/8 | freq:290.2917404 ]", + "[ 1/2 → 5/8 | freq:264.6655079 ]", + "[ 1/2 → 5/8 | freq:352 ]", + "[ 5/8 → 3/4 | freq:440 ]", + "[ 5/8 → 3/4 | freq:311.1269837 ]", + "[ 5/8 → 3/4 | freq:277.182631 ]", "[ 5/8 → 3/4 | freq:440 ]", "[ 3/4 → 7/8 | freq:505.4272762 ]", + "[ 3/4 → 7/8 | freq:333.4576446 ]", + "[ 3/4 → 7/8 | freq:290.2917404 ]", + "[ 3/4 → 7/8 | freq:550 ]", "[ 7/8 → 1/1 | freq:580.5834807 ]", + "[ 7/8 → 1/1 | freq:357.3910544 ]", + "[ 7/8 → 1/1 | freq:304.0208336 ]", + "[ 7/8 → 1/1 | freq:586.6666667 ]", "[ 1/1 → 9/8 | freq:220 ]", + "[ 1/1 → 9/8 | freq:220 ]", + "[ 1/1 → 9/8 | freq:220 ]", + "[ 1/1 → 9/8 | freq:220 ]", + "[ 9/8 → 5/4 | freq:252.7136381 ]", "[ 9/8 → 5/4 | freq:235.7901618 ]", + "[ 9/8 → 5/4 | freq:230.404707 ]", + "[ 9/8 → 5/4 | freq:275 ]", + "[ 5/4 → 11/8 | freq:290.2917404 ]", "[ 5/4 → 11/8 | freq:252.7136381 ]", + "[ 5/4 → 11/8 | freq:241.3014955 ]", + "[ 5/4 → 11/8 | freq:293.3333333 ]", + "[ 11/8 → 3/2 | freq:333.4576446 ]", "[ 11/8 → 3/2 | freq:270.8517709 ]", + "[ 11/8 → 3/2 | freq:252.7136381 ]", + "[ 11/8 → 3/2 | freq:330 ]", + "[ 3/2 → 13/8 | freq:383.0422479 ]", "[ 3/2 → 13/8 | freq:290.2917404 ]", + "[ 3/2 → 13/8 | freq:264.6655079 ]", + "[ 3/2 → 13/8 | freq:352 ]", + "[ 13/8 → 7/4 | freq:440 ]", "[ 13/8 → 7/4 | freq:311.1269837 ]", + "[ 13/8 → 7/4 | freq:277.182631 ]", + "[ 13/8 → 7/4 | freq:440 ]", + "[ 7/4 → 15/8 | freq:505.4272762 ]", "[ 7/4 → 15/8 | freq:333.4576446 ]", + "[ 7/4 → 15/8 | freq:290.2917404 ]", + "[ 7/4 → 15/8 | freq:550 ]", + "[ 15/8 → 2/1 | freq:580.5834807 ]", "[ 15/8 → 2/1 | freq:357.3910544 ]", + "[ 15/8 → 2/1 | freq:304.0208336 ]", + "[ 15/8 → 2/1 | freq:586.6666667 ]", "[ 2/1 → 17/8 | freq:220 ]", + "[ 2/1 → 17/8 | freq:220 ]", + "[ 2/1 → 17/8 | freq:220 ]", + "[ 2/1 → 17/8 | freq:220 ]", + "[ 17/8 → 9/4 | freq:252.7136381 ]", + "[ 17/8 → 9/4 | freq:235.7901618 ]", "[ 17/8 → 9/4 | freq:230.404707 ]", + "[ 17/8 → 9/4 | freq:275 ]", + "[ 9/4 → 19/8 | freq:290.2917404 ]", + "[ 9/4 → 19/8 | freq:252.7136381 ]", "[ 9/4 → 19/8 | freq:241.3014955 ]", + "[ 9/4 → 19/8 | freq:293.3333333 ]", + "[ 19/8 → 5/2 | freq:333.4576446 ]", + "[ 19/8 → 5/2 | freq:270.8517709 ]", "[ 19/8 → 5/2 | freq:252.7136381 ]", + "[ 19/8 → 5/2 | freq:330 ]", + "[ 5/2 → 21/8 | freq:383.0422479 ]", + "[ 5/2 → 21/8 | freq:290.2917404 ]", "[ 5/2 → 21/8 | freq:264.6655079 ]", + "[ 5/2 → 21/8 | freq:352 ]", + "[ 21/8 → 11/4 | freq:440 ]", + "[ 21/8 → 11/4 | freq:311.1269837 ]", "[ 21/8 → 11/4 | freq:277.182631 ]", + "[ 21/8 → 11/4 | freq:440 ]", + "[ 11/4 → 23/8 | freq:505.4272762 ]", + "[ 11/4 → 23/8 | freq:333.4576446 ]", "[ 11/4 → 23/8 | freq:290.2917404 ]", + "[ 11/4 → 23/8 | freq:550 ]", + "[ 23/8 → 3/1 | freq:580.5834807 ]", + "[ 23/8 → 3/1 | freq:357.3910544 ]", "[ 23/8 → 3/1 | freq:304.0208336 ]", + "[ 23/8 → 3/1 | freq:586.6666667 ]", "[ 3/1 → 25/8 | freq:220 ]", + "[ 3/1 → 25/8 | freq:220 ]", + "[ 3/1 → 25/8 | freq:220 ]", + "[ 3/1 → 25/8 | freq:220 ]", + "[ 25/8 → 13/4 | freq:252.7136381 ]", + "[ 25/8 → 13/4 | freq:235.7901618 ]", + "[ 25/8 → 13/4 | freq:230.404707 ]", "[ 25/8 → 13/4 | freq:275 ]", + "[ 13/4 → 27/8 | freq:290.2917404 ]", + "[ 13/4 → 27/8 | freq:252.7136381 ]", + "[ 13/4 → 27/8 | freq:241.3014955 ]", "[ 13/4 → 27/8 | freq:293.3333333 ]", + "[ 27/8 → 7/2 | freq:333.4576446 ]", + "[ 27/8 → 7/2 | freq:270.8517709 ]", + "[ 27/8 → 7/2 | freq:252.7136381 ]", "[ 27/8 → 7/2 | freq:330 ]", + "[ 7/2 → 29/8 | freq:383.0422479 ]", + "[ 7/2 → 29/8 | freq:290.2917404 ]", + "[ 7/2 → 29/8 | freq:264.6655079 ]", "[ 7/2 → 29/8 | freq:352 ]", "[ 29/8 → 15/4 | freq:440 ]", + "[ 29/8 → 15/4 | freq:311.1269837 ]", + "[ 29/8 → 15/4 | freq:277.182631 ]", + "[ 29/8 → 15/4 | freq:440 ]", + "[ 15/4 → 31/8 | freq:505.4272762 ]", + "[ 15/4 → 31/8 | freq:333.4576446 ]", + "[ 15/4 → 31/8 | freq:290.2917404 ]", "[ 15/4 → 31/8 | freq:550 ]", + "[ 31/8 → 4/1 | freq:580.5834807 ]", + "[ 31/8 → 4/1 | freq:357.3910544 ]", + "[ 31/8 → 4/1 | freq:304.0208336 ]", "[ 31/8 → 4/1 | freq:586.6666667 ]", ] `; From fa4d060ed2dd2c92d5ded595992c85b7477c3255 Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 18:25:44 -0400 Subject: [PATCH 11/21] add todo --- packages/xen/xen.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index a5cd72488..400d61362 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -68,6 +68,7 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); // scaleNameOrRatios: string || number[], steps?: number // old, currently unsupported +// TODO support // * @example // * // You can also use xen with frequency ratios. // * // This is equivalent to the above: From c0a43a20dc9fcaee18dd39fa77b3805f3140d938 Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 19:02:25 -0400 Subject: [PATCH 12/21] complete parity with current implementation --- packages/xen/xen.mjs | 39 +++++++---------------- test/__snapshots__/examples.test.mjs.snap | 19 ++++++++++- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 400d61362..20817c3a6 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -69,14 +69,6 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); // old, currently unsupported // TODO support -// * @example -// * // You can also use xen with frequency ratios. -// * // This is equivalent to the above: -// * i("0 1 2").xen([ -// * Math.pow(2, 0/31), -// * Math.pow(2, 8/31), -// * Math.pow(2, 18/31), -// * ]).piano() /** * Assumes a numerical pattern of scale steps, and a scale. Scales accepted are all preset scale names of `tune`, arbitrary edos such as 31edo, or an array of frequency ratios. Assumes scales repeat at octave (2/1). Returns a new pattern with all values mapped to their associated frequency, assuming a base frequency of 220hz. @@ -90,6 +82,14 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); * // A minor triad in 31edo: * i("0 8 18").xen("31edo").piano() * @example + * // You can also use xen with frequency ratios. + * // This is equivalent to the above: + * i("0 1 2").xen([ + * Math.pow(2, 0/31), + * Math.pow(2, 8/31), + * Math.pow(2, 18/31), + * ]).piano() + * @example * // xen also supports all scale names that * // tune does: * i("0 1 2 3 4 5").xen("hexany15") @@ -102,23 +102,6 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); export const xen = register( 'xen', function (scaleNameOrRatios, pat) { - const JIsc3 = (input) => { - let k = input; - - return new Pattern((state) => { - let res = k.query(state); - res = parray( - k.query(state).map((x) => { - let c = x.context; - x = eval(x.value.join('/')); - let r = reify(x).setContext(c); - return r; - }), - ).query(state); - return res; - }); - }; - const JIsc2 = (input) => { let k = parray(input); @@ -137,6 +120,8 @@ export const xen = register( let scs; if (typeof scPat == 'string') { scs = input.map((x) => x.value); + } else if (scPat.every((x) => typeof x == 'number')) { + scs = [scPat]; } else { scs = JIsc2(scPat).query(state); } @@ -154,13 +139,14 @@ export const xen = register( const { i, ...otherValues } = hVal; let scale; let edo = false; - let st = new State(state.span.intersection(hap.part)); if (typeof sc == 'string') { scale = getXenScale(sc); if (isEdo(sc)) { edo = sc.match(/^([1-9]+[0-9]*)edo$/)[1]; } hap = hap.setContext(hap.combineContext(input[ith])); + } else if (sc.every((x) => typeof x == 'number')) { + scale = getXenScale(sc); } else { scale = getXenScale(sc.value); for (let h of scPat[i].query(state)) { @@ -175,7 +161,6 @@ export const xen = register( }) .query(state); return removeUndefineds(haps); - // return haps }); return flatten(k); }; diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index cc8a73c89..379ef4ada 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -14713,6 +14713,23 @@ exports[`runs examples > example "xen" example index 0 1`] = ` `; exports[`runs examples > example "xen" example index 1 1`] = ` +[ + "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", +] +`; + +exports[`runs examples > example "xen" example index 2 1`] = ` [ "[ 0/1 → 1/6 | freq:220 ]", "[ 0/1 → 1/6 | freq:220 ]", @@ -14813,7 +14830,7 @@ exports[`runs examples > example "xen" example index 1 1`] = ` ] `; -exports[`runs examples > example "xen" example index 2 1`] = ` +exports[`runs examples > example "xen" example index 3 1`] = ` [ "[ 0/1 → 1/8 | freq:220 ]", "[ 0/1 → 1/8 | freq:220 ]", From c901ffb37f86fee6e891e7e5f70b611e9f5856e6 Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 19:24:59 -0400 Subject: [PATCH 13/21] example, deprecate tune, swap xen.mdx sections --- packages/xen/tune.mjs | 3 + packages/xen/xen.mjs | 11 +- test/__snapshots__/examples.test.mjs.snap | 263 +++++++++++++++++++++- website/src/pages/learn/xen.mdx | 12 +- 4 files changed, 281 insertions(+), 8 deletions(-) diff --git a/packages/xen/tune.mjs b/packages/xen/tune.mjs index a070515b3..b17ad3292 100644 --- a/packages/xen/tune.mjs +++ b/packages/xen/tune.mjs @@ -8,11 +8,14 @@ import Tune from './tunejs.js'; import { register } from '@strudel/core'; /** + * Deprecated. + * * Assumes pattern contains numerical scale degrees on the `i` control (see examples below). Accepts a scale name or list of frequencies (see all available names at the link on the reference). Returns a new pattern with all values mapped to a frequency ratio. Similar to `xen`. * @name tune * @returns Pattern * @memberof Pattern * @param {(string | number[] )} scale + * @deprecated * @example * i("0 1 2 3 4 5").tune("hexany15").mul("220").freq() * @example diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 20817c3a6..c717c7984 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -90,6 +90,15 @@ const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); * Math.pow(2, 18/31), * ]).piano() * @example + * // However, with the above you won't get highlighting of the scale indices, + * // instead you could do something like: + * i("[<2 ->, 0 1 <- 2> 3]*2").xen([ + * "1:1", // tonic + * "5:4", // Major 3rd + * "[3:2 4:3]", // Perfect 5th, 4th + * "5:3" // Major 6th + * ]).s("tri") + * @example * // xen also supports all scale names that * // tune does: * i("0 1 2 3 4 5").xen("hexany15") @@ -145,7 +154,7 @@ export const xen = register( edo = sc.match(/^([1-9]+[0-9]*)edo$/)[1]; } hap = hap.setContext(hap.combineContext(input[ith])); - } else if (sc.every((x) => typeof x == 'number')) { + } else if (Array.isArray(sc) && sc.every((x) => typeof x == 'number')) { scale = getXenScale(sc); } else { scale = getXenScale(sc.value); diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 379ef4ada..cf14e6a29 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -14730,6 +14730,267 @@ exports[`runs examples > example "xen" example index 1 1`] = ` `; exports[`runs examples > example "xen" example index 2 1`] = ` +[ + "[ 0/1 → 1/8 | freq:220 s:tri ]", + "[ 0/1 → 1/8 | freq:220 s:tri ]", + "[ 0/1 → 1/8 | freq:220 s:tri ]", + "[ 0/1 → 1/8 | freq:220 s:tri ]", + "[ 0/1 → 1/8 | freq:220 s:tri ]", + "[ 0/1 → 1/8 | freq:220 s:tri ]", + "[ 0/1 → 1/8 | freq:220 s:tri ]", + "[ 0/1 → 1/8 | freq:220 s:tri ]", + "[ 0/1 → 1/2 | freq:330 s:tri ]", + "[ 0/1 → 1/2 | freq:293.3333333 s:tri ]", + "[ 0/1 → 1/2 | freq:330 s:tri ]", + "[ 0/1 → 1/2 | freq:293.3333333 s:tri ]", + "[ 0/1 → 1/2 | freq:330 s:tri ]", + "[ 0/1 → 1/2 | freq:293.3333333 s:tri ]", + "[ 0/1 → 1/2 | freq:330 s:tri ]", + "[ 0/1 → 1/2 | freq:293.3333333 s:tri ]", + "[ 1/8 → 1/4 | freq:275 s:tri ]", + "[ 1/8 → 1/4 | freq:275 s:tri ]", + "[ 1/8 → 1/4 | freq:275 s:tri ]", + "[ 1/8 → 1/4 | freq:275 s:tri ]", + "[ 1/8 → 1/4 | freq:275 s:tri ]", + "[ 1/8 → 1/4 | freq:275 s:tri ]", + "[ 1/8 → 1/4 | freq:275 s:tri ]", + "[ 1/8 → 1/4 | freq:275 s:tri ]", + "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", + "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", + "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", + "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", + "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", + "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", + "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", + "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", + "[ 1/2 → 5/8 | freq:220 s:tri ]", + "[ 1/2 → 5/8 | freq:220 s:tri ]", + "[ 1/2 → 5/8 | freq:220 s:tri ]", + "[ 1/2 → 5/8 | freq:220 s:tri ]", + "[ 1/2 → 5/8 | freq:220 s:tri ]", + "[ 1/2 → 5/8 | freq:220 s:tri ]", + "[ 1/2 → 5/8 | freq:220 s:tri ]", + "[ 1/2 → 5/8 | freq:220 s:tri ]", + "[ 5/8 → 3/4 | freq:275 s:tri ]", + "[ 5/8 → 3/4 | freq:275 s:tri ]", + "[ 5/8 → 3/4 | freq:275 s:tri ]", + "[ 5/8 → 3/4 | freq:275 s:tri ]", + "[ 5/8 → 3/4 | freq:275 s:tri ]", + "[ 5/8 → 3/4 | freq:275 s:tri ]", + "[ 5/8 → 3/4 | freq:275 s:tri ]", + "[ 5/8 → 3/4 | freq:275 s:tri ]", + "[ 3/4 → 7/8 | freq:330 s:tri ]", + "[ 3/4 → 7/8 | freq:293.3333333 s:tri ]", + "[ 3/4 → 7/8 | freq:330 s:tri ]", + "[ 3/4 → 7/8 | freq:293.3333333 s:tri ]", + "[ 3/4 → 7/8 | freq:330 s:tri ]", + "[ 3/4 → 7/8 | freq:293.3333333 s:tri ]", + "[ 3/4 → 7/8 | freq:330 s:tri ]", + "[ 3/4 → 7/8 | freq:293.3333333 s:tri ]", + "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", + "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", + "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", + "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", + "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", + "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", + "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", + "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", + "[ 1/1 → 9/8 | freq:220 s:tri ]", + "[ 1/1 → 9/8 | freq:220 s:tri ]", + "[ 1/1 → 9/8 | freq:220 s:tri ]", + "[ 1/1 → 9/8 | freq:220 s:tri ]", + "[ 1/1 → 9/8 | freq:220 s:tri ]", + "[ 1/1 → 9/8 | freq:220 s:tri ]", + "[ 1/1 → 9/8 | freq:220 s:tri ]", + "[ 1/1 → 9/8 | freq:220 s:tri ]", + "[ 1/1 → 3/2 | freq:330 s:tri ]", + "[ 1/1 → 3/2 | freq:293.3333333 s:tri ]", + "[ 1/1 → 3/2 | freq:330 s:tri ]", + "[ 1/1 → 3/2 | freq:293.3333333 s:tri ]", + "[ 1/1 → 3/2 | freq:330 s:tri ]", + "[ 1/1 → 3/2 | freq:293.3333333 s:tri ]", + "[ 1/1 → 3/2 | freq:330 s:tri ]", + "[ 1/1 → 3/2 | freq:293.3333333 s:tri ]", + "[ 9/8 → 5/4 | freq:275 s:tri ]", + "[ 9/8 → 5/4 | freq:275 s:tri ]", + "[ 9/8 → 5/4 | freq:275 s:tri ]", + "[ 9/8 → 5/4 | freq:275 s:tri ]", + "[ 9/8 → 5/4 | freq:275 s:tri ]", + "[ 9/8 → 5/4 | freq:275 s:tri ]", + "[ 9/8 → 5/4 | freq:275 s:tri ]", + "[ 9/8 → 5/4 | freq:275 s:tri ]", + "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", + "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", + "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", + "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", + "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", + "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", + "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", + "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", + "[ 3/2 → 13/8 | freq:220 s:tri ]", + "[ 3/2 → 13/8 | freq:220 s:tri ]", + "[ 3/2 → 13/8 | freq:220 s:tri ]", + "[ 3/2 → 13/8 | freq:220 s:tri ]", + "[ 3/2 → 13/8 | freq:220 s:tri ]", + "[ 3/2 → 13/8 | freq:220 s:tri ]", + "[ 3/2 → 13/8 | freq:220 s:tri ]", + "[ 3/2 → 13/8 | freq:220 s:tri ]", + "[ 13/8 → 7/4 | freq:275 s:tri ]", + "[ 13/8 → 7/4 | freq:275 s:tri ]", + "[ 13/8 → 7/4 | freq:275 s:tri ]", + "[ 13/8 → 7/4 | freq:275 s:tri ]", + "[ 13/8 → 7/4 | freq:275 s:tri ]", + "[ 13/8 → 7/4 | freq:275 s:tri ]", + "[ 13/8 → 7/4 | freq:275 s:tri ]", + "[ 13/8 → 7/4 | freq:275 s:tri ]", + "[ 7/4 → 15/8 | freq:330 s:tri ]", + "[ 7/4 → 15/8 | freq:293.3333333 s:tri ]", + "[ 7/4 → 15/8 | freq:330 s:tri ]", + "[ 7/4 → 15/8 | freq:293.3333333 s:tri ]", + "[ 7/4 → 15/8 | freq:330 s:tri ]", + "[ 7/4 → 15/8 | freq:293.3333333 s:tri ]", + "[ 7/4 → 15/8 | freq:330 s:tri ]", + "[ 7/4 → 15/8 | freq:293.3333333 s:tri ]", + "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", + "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", + "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", + "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", + "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", + "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", + "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", + "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", + "[ 2/1 → 17/8 | freq:220 s:tri ]", + "[ 2/1 → 17/8 | freq:220 s:tri ]", + "[ 2/1 → 17/8 | freq:220 s:tri ]", + "[ 2/1 → 17/8 | freq:220 s:tri ]", + "[ 2/1 → 17/8 | freq:220 s:tri ]", + "[ 2/1 → 17/8 | freq:220 s:tri ]", + "[ 2/1 → 17/8 | freq:220 s:tri ]", + "[ 2/1 → 17/8 | freq:220 s:tri ]", + "[ 2/1 → 5/2 | freq:330 s:tri ]", + "[ 2/1 → 5/2 | freq:293.3333333 s:tri ]", + "[ 2/1 → 5/2 | freq:330 s:tri ]", + "[ 2/1 → 5/2 | freq:293.3333333 s:tri ]", + "[ 2/1 → 5/2 | freq:330 s:tri ]", + "[ 2/1 → 5/2 | freq:293.3333333 s:tri ]", + "[ 2/1 → 5/2 | freq:330 s:tri ]", + "[ 2/1 → 5/2 | freq:293.3333333 s:tri ]", + "[ 17/8 → 9/4 | freq:275 s:tri ]", + "[ 17/8 → 9/4 | freq:275 s:tri ]", + "[ 17/8 → 9/4 | freq:275 s:tri ]", + "[ 17/8 → 9/4 | freq:275 s:tri ]", + "[ 17/8 → 9/4 | freq:275 s:tri ]", + "[ 17/8 → 9/4 | freq:275 s:tri ]", + "[ 17/8 → 9/4 | freq:275 s:tri ]", + "[ 17/8 → 9/4 | freq:275 s:tri ]", + "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", + "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", + "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", + "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", + "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", + "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", + "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", + "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", + "[ 5/2 → 21/8 | freq:220 s:tri ]", + "[ 5/2 → 21/8 | freq:220 s:tri ]", + "[ 5/2 → 21/8 | freq:220 s:tri ]", + "[ 5/2 → 21/8 | freq:220 s:tri ]", + "[ 5/2 → 21/8 | freq:220 s:tri ]", + "[ 5/2 → 21/8 | freq:220 s:tri ]", + "[ 5/2 → 21/8 | freq:220 s:tri ]", + "[ 5/2 → 21/8 | freq:220 s:tri ]", + "[ 21/8 → 11/4 | freq:275 s:tri ]", + "[ 21/8 → 11/4 | freq:275 s:tri ]", + "[ 21/8 → 11/4 | freq:275 s:tri ]", + "[ 21/8 → 11/4 | freq:275 s:tri ]", + "[ 21/8 → 11/4 | freq:275 s:tri ]", + "[ 21/8 → 11/4 | freq:275 s:tri ]", + "[ 21/8 → 11/4 | freq:275 s:tri ]", + "[ 21/8 → 11/4 | freq:275 s:tri ]", + "[ 11/4 → 23/8 | freq:330 s:tri ]", + "[ 11/4 → 23/8 | freq:293.3333333 s:tri ]", + "[ 11/4 → 23/8 | freq:330 s:tri ]", + "[ 11/4 → 23/8 | freq:293.3333333 s:tri ]", + "[ 11/4 → 23/8 | freq:330 s:tri ]", + "[ 11/4 → 23/8 | freq:293.3333333 s:tri ]", + "[ 11/4 → 23/8 | freq:330 s:tri ]", + "[ 11/4 → 23/8 | freq:293.3333333 s:tri ]", + "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", + "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", + "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", + "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", + "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", + "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", + "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", + "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", + "[ 3/1 → 25/8 | freq:220 s:tri ]", + "[ 3/1 → 25/8 | freq:220 s:tri ]", + "[ 3/1 → 25/8 | freq:220 s:tri ]", + "[ 3/1 → 25/8 | freq:220 s:tri ]", + "[ 3/1 → 25/8 | freq:220 s:tri ]", + "[ 3/1 → 25/8 | freq:220 s:tri ]", + "[ 3/1 → 25/8 | freq:220 s:tri ]", + "[ 3/1 → 25/8 | freq:220 s:tri ]", + "[ 3/1 → 7/2 | freq:330 s:tri ]", + "[ 3/1 → 7/2 | freq:293.3333333 s:tri ]", + "[ 3/1 → 7/2 | freq:330 s:tri ]", + "[ 3/1 → 7/2 | freq:293.3333333 s:tri ]", + "[ 3/1 → 7/2 | freq:330 s:tri ]", + "[ 3/1 → 7/2 | freq:293.3333333 s:tri ]", + "[ 3/1 → 7/2 | freq:330 s:tri ]", + "[ 3/1 → 7/2 | freq:293.3333333 s:tri ]", + "[ 25/8 → 13/4 | freq:275 s:tri ]", + "[ 25/8 → 13/4 | freq:275 s:tri ]", + "[ 25/8 → 13/4 | freq:275 s:tri ]", + "[ 25/8 → 13/4 | freq:275 s:tri ]", + "[ 25/8 → 13/4 | freq:275 s:tri ]", + "[ 25/8 → 13/4 | freq:275 s:tri ]", + "[ 25/8 → 13/4 | freq:275 s:tri ]", + "[ 25/8 → 13/4 | freq:275 s:tri ]", + "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", + "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", + "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", + "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", + "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", + "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", + "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", + "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", + "[ 7/2 → 29/8 | freq:220 s:tri ]", + "[ 7/2 → 29/8 | freq:220 s:tri ]", + "[ 7/2 → 29/8 | freq:220 s:tri ]", + "[ 7/2 → 29/8 | freq:220 s:tri ]", + "[ 7/2 → 29/8 | freq:220 s:tri ]", + "[ 7/2 → 29/8 | freq:220 s:tri ]", + "[ 7/2 → 29/8 | freq:220 s:tri ]", + "[ 7/2 → 29/8 | freq:220 s:tri ]", + "[ 29/8 → 15/4 | freq:275 s:tri ]", + "[ 29/8 → 15/4 | freq:275 s:tri ]", + "[ 29/8 → 15/4 | freq:275 s:tri ]", + "[ 29/8 → 15/4 | freq:275 s:tri ]", + "[ 29/8 → 15/4 | freq:275 s:tri ]", + "[ 29/8 → 15/4 | freq:275 s:tri ]", + "[ 29/8 → 15/4 | freq:275 s:tri ]", + "[ 29/8 → 15/4 | freq:275 s:tri ]", + "[ 15/4 → 31/8 | freq:330 s:tri ]", + "[ 15/4 → 31/8 | freq:293.3333333 s:tri ]", + "[ 15/4 → 31/8 | freq:330 s:tri ]", + "[ 15/4 → 31/8 | freq:293.3333333 s:tri ]", + "[ 15/4 → 31/8 | freq:330 s:tri ]", + "[ 15/4 → 31/8 | freq:293.3333333 s:tri ]", + "[ 15/4 → 31/8 | freq:330 s:tri ]", + "[ 15/4 → 31/8 | freq:293.3333333 s:tri ]", + "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", + "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", + "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", + "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", + "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", + "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", + "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", + "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", +] +`; + +exports[`runs examples > example "xen" example index 3 1`] = ` [ "[ 0/1 → 1/6 | freq:220 ]", "[ 0/1 → 1/6 | freq:220 ]", @@ -14830,7 +15091,7 @@ exports[`runs examples > example "xen" example index 2 1`] = ` ] `; -exports[`runs examples > example "xen" example index 3 1`] = ` +exports[`runs examples > example "xen" example index 4 1`] = ` [ "[ 0/1 → 1/8 | freq:220 ]", "[ 0/1 → 1/8 | freq:220 ]", diff --git a/website/src/pages/learn/xen.mdx b/website/src/pages/learn/xen.mdx index 144a40f1a..3e6a5b12f 100644 --- a/website/src/pages/learn/xen.mdx +++ b/website/src/pages/learn/xen.mdx @@ -12,6 +12,12 @@ import { JsDoc } from '../../docs/JsDoc'; These functions allow the use of scales other than your typical chromatic 12 based ones. +### xen(scaleOrRatios) + +{/* TODO add explanation of EDO to documentation */} + + + ### tune(scale) {/* TODO (maybe): combine jsdoc things in tune.mjs with here */} @@ -110,9 +116,3 @@ You can also give tune a list of frequencies to use as the scale: 523.2511306012 ]).mul(220).freq();`} /> - -### xen(scaleOrRatios) - -{/* TODO add explanation of EDO to documentation */} - - From b586d8c4c4bd53287f894310c483c528bcbf8472 Mon Sep 17 00:00:00 2001 From: tyow Date: Tue, 10 Mar 2026 19:39:08 -0400 Subject: [PATCH 14/21] add notes on missing functionality --- packages/xen/xen.mjs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index c717c7984..8a5e242dc 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -120,6 +120,20 @@ export const xen = register( }); }; + // TODO fix the following: + /* + let p1 = i("0 1").xen("hexany15 hexany23") + let p2 = i("[0 1]").xen([ + "[1:1 2:1]", // tonic + "5:4", // Major 3rd + ]).s("tri") + + let p3 = i("[0 1]").xen([ + "[<1:1 2:1>]", // tonic + "5:4", // Major 3rd + ]).s("tri") + */ + const query = (state) => { let input = scaleNameOrRatios.query(state); From beee2bc921ec25a440d9e056e8c7c67cf6e52746 Mon Sep 17 00:00:00 2001 From: tyow Date: Wed, 11 Mar 2026 13:53:24 -0400 Subject: [PATCH 15/21] refactor --- packages/xen/xen.mjs | 189 +++++--- test/__snapshots__/examples.test.mjs.snap | 565 +--------------------- 2 files changed, 146 insertions(+), 608 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 8a5e242dc..7dc4501c8 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -4,7 +4,18 @@ Copyright (C) 2022 Strudel contributors - see . */ -import { register, _mod, parseNumeral, removeUndefineds, Pattern, parray, reify, State, flatten } from '@strudel/core'; +import { + register, + _mod, + parseNumeral, + removeUndefineds, + Pattern, + parray, + reify, + State, + flatten, + Hap, +} from '@strudel/core'; import Tune from './tunejs.js'; // returns a list of frequency ratios for given edo scale @@ -135,67 +146,133 @@ export const xen = register( */ const query = (state) => { - let input = scaleNameOrRatios.query(state); + // let input = scaleNameOrRatios.query(state); - if (input.length == 0) return []; + // if (input.length == 0) return []; - let scPat = input[0].value; - let scs; - if (typeof scPat == 'string') { - scs = input.map((x) => x.value); - } else if (scPat.every((x) => typeof x == 'number')) { - scs = [scPat]; - } else { - scs = JIsc2(scPat).query(state); - } + // let scPat = input[0].value; + // let scs; + // if (typeof scPat == 'string') { + // scs = input.map((x) => x.value); + // } else if (scPat.every((x) => typeof x == 'number')) { + // scs = [scPat]; + // } else { + // scs = JIsc2(scPat).query(state); + // } - let k = scs.map((sc, ith) => { - let haps = pat - .withHap((hap) => { - let hVal = hap.value; - const isObject = typeof hVal === 'object'; - if (!isObject) { - throw new Error( - `Expected hap to have control 'i' set, but received ${hap.value.i}, try wrapping input in i()`, - ); - } - const { i, ...otherValues } = hVal; - let scale; - let edo = false; - if (typeof sc == 'string') { - scale = getXenScale(sc); - if (isEdo(sc)) { - edo = sc.match(/^([1-9]+[0-9]*)edo$/)[1]; - } - hap = hap.setContext(hap.combineContext(input[ith])); - } else if (Array.isArray(sc) && sc.every((x) => typeof x == 'number')) { - scale = getXenScale(sc); - } else { - scale = getXenScale(sc.value); - for (let h of scPat[i].query(state)) { - hap = hap.setContext(hap.combineContext(h)); - } - } - let freq = xenOffset(scale, parseNumeral(hVal.i)); - // 10 is somewhat arbitrary + // outside should be haps + // which then queries the scales using their hap timespans + + // input[0].value.forEach((inp, ith) => { + // let smth = inp.query(state) + // let scs = JIsc2(inp).query(state) + + // let k = scs.map((sc, jth) => { + let haps = pat.query(state); + let resHaps = []; + + haps.forEach((hap) => { + let hVal = hap.value; + const isObject = typeof hVal === 'object'; + if (!isObject) { + throw new Error( + `Expected hap to have control 'i' set, but received ${hap.value.i}, try wrapping input in i()`, + ); + } + const { i, ...otherValues } = hVal; + let edo = false; + let st = new State(hap.wholeOrPart().intersection(state.span), state.controls); + + // Format: An array of values + // Each value is a pattern, representing an index on the scale + let sc = scaleNameOrRatios.query(st); + // Check to see if input is attempting to be a named scale + let isStr = typeof sc[0].value == 'string'; + if (!isStr) { + sc = sc[0].value; + } + + if (!isStr) { + let scaleByIndices = []; + for (let j = 0; j < sc.length; j++) { + scaleByIndices[j] = sc[j].query(st); + } + /* + Format: An array of 1 or more Haps, each Hap has an array of values of + one or more scale index definitions (contains whole scale) + Assumption: inner value array should be same length between each + */ + let sc2 = JIsc2(sc).query(st); + + for (let j = 0; j < scaleByIndices[i].length; j++) { + let scale = getXenScale(sc2[j].value); + let freq = xenOffset(scale, parseNumeral(i)); + let newHap = hap; freq = trimFreq(freq); - hap.value = { ...otherValues, freq }; - return edo ? hap.setContext({ ...hap.context, edoSize: edo }) : hap; - }) - .query(state); - return removeUndefineds(haps); + newHap.value = { ...otherValues, freq }; + newHap = newHap.setContext(newHap.combineContext(scaleByIndices[i][j])); + resHaps.push(newHap); + } + } else { + // scale is named scale(s) + for (let j = 0; j < sc.length; j++) { + let scale = getXenScale(sc[j].value); + let freq = xenOffset(scale, parseNumeral(i)); + let newHap = hap; + freq = trimFreq(freq); + newHap.value = { ...otherValues, freq }; + newHap = newHap.setContext(newHap.combineContext(sc[j])); + resHaps.push(newHap); + } + } + + /* + We need to know: + - How many Haps to make, given a scale index (i value) from a Hap from pat (sc can tell us) + - The whole scale, so the frequency can be set (sc2 can tell us) + - if sc2.length > 1, how do we deal? + - The frequency of the ith element of the scale, given a Hap (from pat) with i value of ith + + The whole scale definitions in sc2 can be indexed by the index of Hap within sc: + + */ + + // if (typeof sc == 'string') { + // scale = getXenScale(sc); + // if (isEdo(sc)) { + // edo = sc.match(/^([1-9]+[0-9]*)edo$/)[1]; + // } + // hap = hap.setContext(hap.combineContext(input[ith])); + // } else if (Array.isArray(sc) && sc.every((x) => typeof x == 'number')) { + // scale = getXenScale(sc); + // } else { + // scale = getXenScale(sc.value); + // for (let h of scPat[_mod(i, scale.length)].query(state)) { + // let ts = hap.wholeOrPart().intersection(h.wholeOrPart()); + // if (ts == undefined) return undefined; + // hap = hap.withSpan((x) => ts); + // hap = hap.setContext(hap.combineContext(h)); + // } + // } + // let freq = xenOffset(scale, parseNumeral(i)); + // // 10 is somewhat arbitrary + // freq = trimFreq(freq); + // hap.value = { ...otherValues, freq }; + return edo ? hap.setContext({ ...hap.context, edoSize: edo }) : hap; }); - return flatten(k); + + // }); + // return flatten(k); + // }) + + /* + perhaps instead of + return new Pattern(query) + we could do a join on scaleNameOrRatios which creates multiple patterns and then joins them + */ + return resHaps; }; - - /* - perhaps instead of - return new Pattern(query) - we could do a join on scaleNameOrRatios which creates multiple patterns and then joins them - */ - let res = new Pattern(query); - - return res; + return new Pattern(query); }, false, ); diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index cf14e6a29..26bbdfe7a 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -5084,18 +5084,18 @@ exports[`runs examples > example "ftranspose" example index 0 1`] = ` exports[`runs examples > example "ftranspose" example index 1 1`] = ` [ - "[ 0/1 → 1/3 | freq:263.0921203 ]", - "[ 1/3 → 2/3 | freq:314.6248353 ]", - "[ 2/3 → 1/1 | freq:393.4589706 ]", - "[ 1/1 → 4/3 | freq:183.965981 ]", - "[ 4/3 → 5/3 | freq:220 ]", - "[ 5/3 → 2/1 | freq:275.1244143 ]", - "[ 2/1 → 7/3 | freq:263.0921203 ]", - "[ 7/3 → 8/3 | freq:314.6248353 ]", - "[ 8/3 → 3/1 | freq:393.4589706 ]", - "[ 3/1 → 10/3 | freq:183.965981 ]", - "[ 10/3 → 11/3 | freq:220 ]", - "[ 11/3 → 4/1 | freq:275.1244143 ]", + "[ 0/1 → 1/3 | freq:349.2282314 ]", + "[ 1/3 → 2/3 | freq:417.6327085 ]", + "[ 2/3 → 1/1 | freq:522.2770651 ]", + "[ 1/1 → 4/3 | freq:138.5913155 ]", + "[ 4/3 → 5/3 | freq:165.7376502 ]", + "[ 5/3 → 2/1 | freq:207.2657906 ]", + "[ 2/1 → 7/3 | freq:349.2282314 ]", + "[ 7/3 → 8/3 | freq:417.6327085 ]", + "[ 8/3 → 3/1 | freq:522.2770651 ]", + "[ 3/1 → 10/3 | freq:138.5913155 ]", + "[ 10/3 → 11/3 | freq:165.7376502 ]", + "[ 11/3 → 4/1 | freq:207.2657906 ]", ] `; @@ -5832,133 +5832,37 @@ exports[`runs examples > example "hush" example index 0 1`] = ` exports[`runs examples > example "i" example index 0 1`] = ` [ - "[ 0/1 → 1/8 | freq:220 ]", - "[ 0/1 → 1/8 | freq:220 ]", - "[ 0/1 → 1/8 | freq:220 ]", "[ 0/1 → 1/8 | freq:220 ]", "[ 1/8 → 1/4 | freq:252.7136381 ]", - "[ 1/8 → 1/4 | freq:235.7901618 ]", - "[ 1/8 → 1/4 | freq:230.404707 ]", - "[ 1/8 → 1/4 | freq:275 ]", "[ 1/4 → 3/8 | freq:290.2917404 ]", - "[ 1/4 → 3/8 | freq:252.7136381 ]", - "[ 1/4 → 3/8 | freq:241.3014955 ]", - "[ 1/4 → 3/8 | freq:293.3333333 ]", "[ 3/8 → 1/2 | freq:333.4576446 ]", - "[ 3/8 → 1/2 | freq:270.8517709 ]", - "[ 3/8 → 1/2 | freq:252.7136381 ]", - "[ 3/8 → 1/2 | freq:330 ]", "[ 1/2 → 5/8 | freq:383.0422479 ]", - "[ 1/2 → 5/8 | freq:290.2917404 ]", - "[ 1/2 → 5/8 | freq:264.6655079 ]", - "[ 1/2 → 5/8 | freq:352 ]", - "[ 5/8 → 3/4 | freq:440 ]", - "[ 5/8 → 3/4 | freq:311.1269837 ]", - "[ 5/8 → 3/4 | freq:277.182631 ]", "[ 5/8 → 3/4 | freq:440 ]", "[ 3/4 → 7/8 | freq:505.4272762 ]", - "[ 3/4 → 7/8 | freq:333.4576446 ]", - "[ 3/4 → 7/8 | freq:290.2917404 ]", - "[ 3/4 → 7/8 | freq:550 ]", "[ 7/8 → 1/1 | freq:580.5834807 ]", - "[ 7/8 → 1/1 | freq:357.3910544 ]", - "[ 7/8 → 1/1 | freq:304.0208336 ]", - "[ 7/8 → 1/1 | freq:586.6666667 ]", "[ 1/1 → 9/8 | freq:220 ]", - "[ 1/1 → 9/8 | freq:220 ]", - "[ 1/1 → 9/8 | freq:220 ]", - "[ 1/1 → 9/8 | freq:220 ]", - "[ 9/8 → 5/4 | freq:252.7136381 ]", "[ 9/8 → 5/4 | freq:235.7901618 ]", - "[ 9/8 → 5/4 | freq:230.404707 ]", - "[ 9/8 → 5/4 | freq:275 ]", - "[ 5/4 → 11/8 | freq:290.2917404 ]", "[ 5/4 → 11/8 | freq:252.7136381 ]", - "[ 5/4 → 11/8 | freq:241.3014955 ]", - "[ 5/4 → 11/8 | freq:293.3333333 ]", - "[ 11/8 → 3/2 | freq:333.4576446 ]", "[ 11/8 → 3/2 | freq:270.8517709 ]", - "[ 11/8 → 3/2 | freq:252.7136381 ]", - "[ 11/8 → 3/2 | freq:330 ]", - "[ 3/2 → 13/8 | freq:383.0422479 ]", "[ 3/2 → 13/8 | freq:290.2917404 ]", - "[ 3/2 → 13/8 | freq:264.6655079 ]", - "[ 3/2 → 13/8 | freq:352 ]", - "[ 13/8 → 7/4 | freq:440 ]", "[ 13/8 → 7/4 | freq:311.1269837 ]", - "[ 13/8 → 7/4 | freq:277.182631 ]", - "[ 13/8 → 7/4 | freq:440 ]", - "[ 7/4 → 15/8 | freq:505.4272762 ]", "[ 7/4 → 15/8 | freq:333.4576446 ]", - "[ 7/4 → 15/8 | freq:290.2917404 ]", - "[ 7/4 → 15/8 | freq:550 ]", - "[ 15/8 → 2/1 | freq:580.5834807 ]", "[ 15/8 → 2/1 | freq:357.3910544 ]", - "[ 15/8 → 2/1 | freq:304.0208336 ]", - "[ 15/8 → 2/1 | freq:586.6666667 ]", "[ 2/1 → 17/8 | freq:220 ]", - "[ 2/1 → 17/8 | freq:220 ]", - "[ 2/1 → 17/8 | freq:220 ]", - "[ 2/1 → 17/8 | freq:220 ]", - "[ 17/8 → 9/4 | freq:252.7136381 ]", - "[ 17/8 → 9/4 | freq:235.7901618 ]", "[ 17/8 → 9/4 | freq:230.404707 ]", - "[ 17/8 → 9/4 | freq:275 ]", - "[ 9/4 → 19/8 | freq:290.2917404 ]", - "[ 9/4 → 19/8 | freq:252.7136381 ]", "[ 9/4 → 19/8 | freq:241.3014955 ]", - "[ 9/4 → 19/8 | freq:293.3333333 ]", - "[ 19/8 → 5/2 | freq:333.4576446 ]", - "[ 19/8 → 5/2 | freq:270.8517709 ]", "[ 19/8 → 5/2 | freq:252.7136381 ]", - "[ 19/8 → 5/2 | freq:330 ]", - "[ 5/2 → 21/8 | freq:383.0422479 ]", - "[ 5/2 → 21/8 | freq:290.2917404 ]", "[ 5/2 → 21/8 | freq:264.6655079 ]", - "[ 5/2 → 21/8 | freq:352 ]", - "[ 21/8 → 11/4 | freq:440 ]", - "[ 21/8 → 11/4 | freq:311.1269837 ]", "[ 21/8 → 11/4 | freq:277.182631 ]", - "[ 21/8 → 11/4 | freq:440 ]", - "[ 11/4 → 23/8 | freq:505.4272762 ]", - "[ 11/4 → 23/8 | freq:333.4576446 ]", "[ 11/4 → 23/8 | freq:290.2917404 ]", - "[ 11/4 → 23/8 | freq:550 ]", - "[ 23/8 → 3/1 | freq:580.5834807 ]", - "[ 23/8 → 3/1 | freq:357.3910544 ]", "[ 23/8 → 3/1 | freq:304.0208336 ]", - "[ 23/8 → 3/1 | freq:586.6666667 ]", "[ 3/1 → 25/8 | freq:220 ]", - "[ 3/1 → 25/8 | freq:220 ]", - "[ 3/1 → 25/8 | freq:220 ]", - "[ 3/1 → 25/8 | freq:220 ]", - "[ 25/8 → 13/4 | freq:252.7136381 ]", - "[ 25/8 → 13/4 | freq:235.7901618 ]", - "[ 25/8 → 13/4 | freq:230.404707 ]", "[ 25/8 → 13/4 | freq:275 ]", - "[ 13/4 → 27/8 | freq:290.2917404 ]", - "[ 13/4 → 27/8 | freq:252.7136381 ]", - "[ 13/4 → 27/8 | freq:241.3014955 ]", "[ 13/4 → 27/8 | freq:293.3333333 ]", - "[ 27/8 → 7/2 | freq:333.4576446 ]", - "[ 27/8 → 7/2 | freq:270.8517709 ]", - "[ 27/8 → 7/2 | freq:252.7136381 ]", "[ 27/8 → 7/2 | freq:330 ]", - "[ 7/2 → 29/8 | freq:383.0422479 ]", - "[ 7/2 → 29/8 | freq:290.2917404 ]", - "[ 7/2 → 29/8 | freq:264.6655079 ]", "[ 7/2 → 29/8 | freq:352 ]", "[ 29/8 → 15/4 | freq:440 ]", - "[ 29/8 → 15/4 | freq:311.1269837 ]", - "[ 29/8 → 15/4 | freq:277.182631 ]", - "[ 29/8 → 15/4 | freq:440 ]", - "[ 15/4 → 31/8 | freq:505.4272762 ]", - "[ 15/4 → 31/8 | freq:333.4576446 ]", - "[ 15/4 → 31/8 | freq:290.2917404 ]", "[ 15/4 → 31/8 | freq:550 ]", - "[ 31/8 → 4/1 | freq:580.5834807 ]", - "[ 31/8 → 4/1 | freq:357.3910544 ]", - "[ 31/8 → 4/1 | freq:304.0208336 ]", "[ 31/8 → 4/1 | freq:586.6666667 ]", ] `; @@ -14662,330 +14566,55 @@ exports[`runs examples > example "wtphaserand" example index 0 1`] = ` exports[`runs examples > example "xen" example index 0 1`] = ` [ "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", ] `; -exports[`runs examples > example "xen" example index 1 1`] = ` -[ - "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", - "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", - "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", - "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", -] -`; +exports[`runs examples > example "xen" example index 1 1`] = `[]`; exports[`runs examples > example "xen" example index 2 1`] = ` [ - "[ 0/1 → 1/8 | freq:220 s:tri ]", - "[ 0/1 → 1/8 | freq:220 s:tri ]", - "[ 0/1 → 1/8 | freq:220 s:tri ]", - "[ 0/1 → 1/8 | freq:220 s:tri ]", - "[ 0/1 → 1/8 | freq:220 s:tri ]", - "[ 0/1 → 1/8 | freq:220 s:tri ]", - "[ 0/1 → 1/8 | freq:220 s:tri ]", "[ 0/1 → 1/8 | freq:220 s:tri ]", "[ 0/1 → 1/2 | freq:330 s:tri ]", - "[ 0/1 → 1/2 | freq:293.3333333 s:tri ]", - "[ 0/1 → 1/2 | freq:330 s:tri ]", - "[ 0/1 → 1/2 | freq:293.3333333 s:tri ]", - "[ 0/1 → 1/2 | freq:330 s:tri ]", - "[ 0/1 → 1/2 | freq:293.3333333 s:tri ]", - "[ 0/1 → 1/2 | freq:330 s:tri ]", - "[ 0/1 → 1/2 | freq:293.3333333 s:tri ]", - "[ 1/8 → 1/4 | freq:275 s:tri ]", - "[ 1/8 → 1/4 | freq:275 s:tri ]", - "[ 1/8 → 1/4 | freq:275 s:tri ]", - "[ 1/8 → 1/4 | freq:275 s:tri ]", - "[ 1/8 → 1/4 | freq:275 s:tri ]", - "[ 1/8 → 1/4 | freq:275 s:tri ]", - "[ 1/8 → 1/4 | freq:275 s:tri ]", "[ 1/8 → 1/4 | freq:275 s:tri ]", "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", - "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", - "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", - "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", - "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", - "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", - "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", - "[ 3/8 → 1/2 | freq:366.6666667 s:tri ]", - "[ 1/2 → 5/8 | freq:220 s:tri ]", - "[ 1/2 → 5/8 | freq:220 s:tri ]", - "[ 1/2 → 5/8 | freq:220 s:tri ]", - "[ 1/2 → 5/8 | freq:220 s:tri ]", - "[ 1/2 → 5/8 | freq:220 s:tri ]", - "[ 1/2 → 5/8 | freq:220 s:tri ]", - "[ 1/2 → 5/8 | freq:220 s:tri ]", "[ 1/2 → 5/8 | freq:220 s:tri ]", "[ 5/8 → 3/4 | freq:275 s:tri ]", - "[ 5/8 → 3/4 | freq:275 s:tri ]", - "[ 5/8 → 3/4 | freq:275 s:tri ]", - "[ 5/8 → 3/4 | freq:275 s:tri ]", - "[ 5/8 → 3/4 | freq:275 s:tri ]", - "[ 5/8 → 3/4 | freq:275 s:tri ]", - "[ 5/8 → 3/4 | freq:275 s:tri ]", - "[ 5/8 → 3/4 | freq:275 s:tri ]", - "[ 3/4 → 7/8 | freq:330 s:tri ]", - "[ 3/4 → 7/8 | freq:293.3333333 s:tri ]", - "[ 3/4 → 7/8 | freq:330 s:tri ]", - "[ 3/4 → 7/8 | freq:293.3333333 s:tri ]", - "[ 3/4 → 7/8 | freq:330 s:tri ]", - "[ 3/4 → 7/8 | freq:293.3333333 s:tri ]", - "[ 3/4 → 7/8 | freq:330 s:tri ]", "[ 3/4 → 7/8 | freq:293.3333333 s:tri ]", "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", - "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", - "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", - "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", - "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", - "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", - "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", - "[ 7/8 → 1/1 | freq:366.6666667 s:tri ]", - "[ 1/1 → 9/8 | freq:220 s:tri ]", - "[ 1/1 → 9/8 | freq:220 s:tri ]", - "[ 1/1 → 9/8 | freq:220 s:tri ]", - "[ 1/1 → 9/8 | freq:220 s:tri ]", - "[ 1/1 → 9/8 | freq:220 s:tri ]", - "[ 1/1 → 9/8 | freq:220 s:tri ]", - "[ 1/1 → 9/8 | freq:220 s:tri ]", "[ 1/1 → 9/8 | freq:220 s:tri ]", "[ 1/1 → 3/2 | freq:330 s:tri ]", - "[ 1/1 → 3/2 | freq:293.3333333 s:tri ]", - "[ 1/1 → 3/2 | freq:330 s:tri ]", - "[ 1/1 → 3/2 | freq:293.3333333 s:tri ]", - "[ 1/1 → 3/2 | freq:330 s:tri ]", - "[ 1/1 → 3/2 | freq:293.3333333 s:tri ]", - "[ 1/1 → 3/2 | freq:330 s:tri ]", - "[ 1/1 → 3/2 | freq:293.3333333 s:tri ]", - "[ 9/8 → 5/4 | freq:275 s:tri ]", - "[ 9/8 → 5/4 | freq:275 s:tri ]", - "[ 9/8 → 5/4 | freq:275 s:tri ]", - "[ 9/8 → 5/4 | freq:275 s:tri ]", - "[ 9/8 → 5/4 | freq:275 s:tri ]", - "[ 9/8 → 5/4 | freq:275 s:tri ]", - "[ 9/8 → 5/4 | freq:275 s:tri ]", "[ 9/8 → 5/4 | freq:275 s:tri ]", "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", - "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", - "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", - "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", - "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", - "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", - "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", - "[ 11/8 → 3/2 | freq:366.6666667 s:tri ]", - "[ 3/2 → 13/8 | freq:220 s:tri ]", - "[ 3/2 → 13/8 | freq:220 s:tri ]", - "[ 3/2 → 13/8 | freq:220 s:tri ]", - "[ 3/2 → 13/8 | freq:220 s:tri ]", - "[ 3/2 → 13/8 | freq:220 s:tri ]", - "[ 3/2 → 13/8 | freq:220 s:tri ]", - "[ 3/2 → 13/8 | freq:220 s:tri ]", "[ 3/2 → 13/8 | freq:220 s:tri ]", "[ 13/8 → 7/4 | freq:275 s:tri ]", - "[ 13/8 → 7/4 | freq:275 s:tri ]", - "[ 13/8 → 7/4 | freq:275 s:tri ]", - "[ 13/8 → 7/4 | freq:275 s:tri ]", - "[ 13/8 → 7/4 | freq:275 s:tri ]", - "[ 13/8 → 7/4 | freq:275 s:tri ]", - "[ 13/8 → 7/4 | freq:275 s:tri ]", - "[ 13/8 → 7/4 | freq:275 s:tri ]", - "[ 7/4 → 15/8 | freq:330 s:tri ]", - "[ 7/4 → 15/8 | freq:293.3333333 s:tri ]", - "[ 7/4 → 15/8 | freq:330 s:tri ]", - "[ 7/4 → 15/8 | freq:293.3333333 s:tri ]", - "[ 7/4 → 15/8 | freq:330 s:tri ]", - "[ 7/4 → 15/8 | freq:293.3333333 s:tri ]", - "[ 7/4 → 15/8 | freq:330 s:tri ]", "[ 7/4 → 15/8 | freq:293.3333333 s:tri ]", "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", - "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", - "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", - "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", - "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", - "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", - "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", - "[ 15/8 → 2/1 | freq:366.6666667 s:tri ]", - "[ 2/1 → 17/8 | freq:220 s:tri ]", - "[ 2/1 → 17/8 | freq:220 s:tri ]", - "[ 2/1 → 17/8 | freq:220 s:tri ]", - "[ 2/1 → 17/8 | freq:220 s:tri ]", - "[ 2/1 → 17/8 | freq:220 s:tri ]", - "[ 2/1 → 17/8 | freq:220 s:tri ]", - "[ 2/1 → 17/8 | freq:220 s:tri ]", "[ 2/1 → 17/8 | freq:220 s:tri ]", "[ 2/1 → 5/2 | freq:330 s:tri ]", - "[ 2/1 → 5/2 | freq:293.3333333 s:tri ]", - "[ 2/1 → 5/2 | freq:330 s:tri ]", - "[ 2/1 → 5/2 | freq:293.3333333 s:tri ]", - "[ 2/1 → 5/2 | freq:330 s:tri ]", - "[ 2/1 → 5/2 | freq:293.3333333 s:tri ]", - "[ 2/1 → 5/2 | freq:330 s:tri ]", - "[ 2/1 → 5/2 | freq:293.3333333 s:tri ]", - "[ 17/8 → 9/4 | freq:275 s:tri ]", - "[ 17/8 → 9/4 | freq:275 s:tri ]", - "[ 17/8 → 9/4 | freq:275 s:tri ]", - "[ 17/8 → 9/4 | freq:275 s:tri ]", - "[ 17/8 → 9/4 | freq:275 s:tri ]", - "[ 17/8 → 9/4 | freq:275 s:tri ]", - "[ 17/8 → 9/4 | freq:275 s:tri ]", "[ 17/8 → 9/4 | freq:275 s:tri ]", "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", - "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", - "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", - "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", - "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", - "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", - "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", - "[ 19/8 → 5/2 | freq:366.6666667 s:tri ]", - "[ 5/2 → 21/8 | freq:220 s:tri ]", - "[ 5/2 → 21/8 | freq:220 s:tri ]", - "[ 5/2 → 21/8 | freq:220 s:tri ]", - "[ 5/2 → 21/8 | freq:220 s:tri ]", - "[ 5/2 → 21/8 | freq:220 s:tri ]", - "[ 5/2 → 21/8 | freq:220 s:tri ]", - "[ 5/2 → 21/8 | freq:220 s:tri ]", "[ 5/2 → 21/8 | freq:220 s:tri ]", "[ 21/8 → 11/4 | freq:275 s:tri ]", - "[ 21/8 → 11/4 | freq:275 s:tri ]", - "[ 21/8 → 11/4 | freq:275 s:tri ]", - "[ 21/8 → 11/4 | freq:275 s:tri ]", - "[ 21/8 → 11/4 | freq:275 s:tri ]", - "[ 21/8 → 11/4 | freq:275 s:tri ]", - "[ 21/8 → 11/4 | freq:275 s:tri ]", - "[ 21/8 → 11/4 | freq:275 s:tri ]", - "[ 11/4 → 23/8 | freq:330 s:tri ]", - "[ 11/4 → 23/8 | freq:293.3333333 s:tri ]", - "[ 11/4 → 23/8 | freq:330 s:tri ]", - "[ 11/4 → 23/8 | freq:293.3333333 s:tri ]", - "[ 11/4 → 23/8 | freq:330 s:tri ]", - "[ 11/4 → 23/8 | freq:293.3333333 s:tri ]", - "[ 11/4 → 23/8 | freq:330 s:tri ]", "[ 11/4 → 23/8 | freq:293.3333333 s:tri ]", "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", - "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", - "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", - "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", - "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", - "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", - "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", - "[ 23/8 → 3/1 | freq:366.6666667 s:tri ]", - "[ 3/1 → 25/8 | freq:220 s:tri ]", - "[ 3/1 → 25/8 | freq:220 s:tri ]", - "[ 3/1 → 25/8 | freq:220 s:tri ]", - "[ 3/1 → 25/8 | freq:220 s:tri ]", - "[ 3/1 → 25/8 | freq:220 s:tri ]", - "[ 3/1 → 25/8 | freq:220 s:tri ]", - "[ 3/1 → 25/8 | freq:220 s:tri ]", "[ 3/1 → 25/8 | freq:220 s:tri ]", "[ 3/1 → 7/2 | freq:330 s:tri ]", - "[ 3/1 → 7/2 | freq:293.3333333 s:tri ]", - "[ 3/1 → 7/2 | freq:330 s:tri ]", - "[ 3/1 → 7/2 | freq:293.3333333 s:tri ]", - "[ 3/1 → 7/2 | freq:330 s:tri ]", - "[ 3/1 → 7/2 | freq:293.3333333 s:tri ]", - "[ 3/1 → 7/2 | freq:330 s:tri ]", - "[ 3/1 → 7/2 | freq:293.3333333 s:tri ]", - "[ 25/8 → 13/4 | freq:275 s:tri ]", - "[ 25/8 → 13/4 | freq:275 s:tri ]", - "[ 25/8 → 13/4 | freq:275 s:tri ]", - "[ 25/8 → 13/4 | freq:275 s:tri ]", - "[ 25/8 → 13/4 | freq:275 s:tri ]", - "[ 25/8 → 13/4 | freq:275 s:tri ]", - "[ 25/8 → 13/4 | freq:275 s:tri ]", "[ 25/8 → 13/4 | freq:275 s:tri ]", "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", - "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", - "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", - "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", - "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", - "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", - "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", - "[ 27/8 → 7/2 | freq:366.6666667 s:tri ]", - "[ 7/2 → 29/8 | freq:220 s:tri ]", - "[ 7/2 → 29/8 | freq:220 s:tri ]", - "[ 7/2 → 29/8 | freq:220 s:tri ]", - "[ 7/2 → 29/8 | freq:220 s:tri ]", - "[ 7/2 → 29/8 | freq:220 s:tri ]", - "[ 7/2 → 29/8 | freq:220 s:tri ]", - "[ 7/2 → 29/8 | freq:220 s:tri ]", "[ 7/2 → 29/8 | freq:220 s:tri ]", "[ 29/8 → 15/4 | freq:275 s:tri ]", - "[ 29/8 → 15/4 | freq:275 s:tri ]", - "[ 29/8 → 15/4 | freq:275 s:tri ]", - "[ 29/8 → 15/4 | freq:275 s:tri ]", - "[ 29/8 → 15/4 | freq:275 s:tri ]", - "[ 29/8 → 15/4 | freq:275 s:tri ]", - "[ 29/8 → 15/4 | freq:275 s:tri ]", - "[ 29/8 → 15/4 | freq:275 s:tri ]", - "[ 15/4 → 31/8 | freq:330 s:tri ]", "[ 15/4 → 31/8 | freq:293.3333333 s:tri ]", - "[ 15/4 → 31/8 | freq:330 s:tri ]", - "[ 15/4 → 31/8 | freq:293.3333333 s:tri ]", - "[ 15/4 → 31/8 | freq:330 s:tri ]", - "[ 15/4 → 31/8 | freq:293.3333333 s:tri ]", - "[ 15/4 → 31/8 | freq:330 s:tri ]", - "[ 15/4 → 31/8 | freq:293.3333333 s:tri ]", - "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", - "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", - "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", - "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", - "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", - "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", - "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", "[ 31/8 → 4/1 | freq:366.6666667 s:tri ]", ] `; @@ -14993,233 +14622,65 @@ exports[`runs examples > example "xen" example index 2 1`] = ` exports[`runs examples > example "xen" example index 3 1`] = ` [ "[ 0/1 → 1/6 | freq:220 ]", - "[ 0/1 → 1/6 | freq:220 ]", - "[ 0/1 → 1/6 | freq:220 ]", - "[ 0/1 → 1/6 | freq:220 ]", - "[ 1/6 → 1/3 | freq:275 ]", - "[ 1/6 → 1/3 | freq:275 ]", - "[ 1/6 → 1/3 | freq:275 ]", "[ 1/6 → 1/3 | freq:275 ]", "[ 1/3 → 1/2 | freq:293.3333333 ]", - "[ 1/3 → 1/2 | freq:293.3333333 ]", - "[ 1/3 → 1/2 | freq:293.3333333 ]", - "[ 1/3 → 1/2 | freq:293.3333333 ]", - "[ 1/2 → 2/3 | freq:330 ]", - "[ 1/2 → 2/3 | freq:330 ]", - "[ 1/2 → 2/3 | freq:330 ]", "[ 1/2 → 2/3 | freq:330 ]", "[ 2/3 → 5/6 | freq:352 ]", - "[ 2/3 → 5/6 | freq:352 ]", - "[ 2/3 → 5/6 | freq:352 ]", - "[ 2/3 → 5/6 | freq:352 ]", - "[ 5/6 → 1/1 | freq:440 ]", - "[ 5/6 → 1/1 | freq:440 ]", - "[ 5/6 → 1/1 | freq:440 ]", "[ 5/6 → 1/1 | freq:440 ]", "[ 1/1 → 7/6 | freq:220 ]", - "[ 1/1 → 7/6 | freq:220 ]", - "[ 1/1 → 7/6 | freq:220 ]", - "[ 1/1 → 7/6 | freq:220 ]", - "[ 7/6 → 4/3 | freq:275 ]", - "[ 7/6 → 4/3 | freq:275 ]", - "[ 7/6 → 4/3 | freq:275 ]", "[ 7/6 → 4/3 | freq:275 ]", "[ 4/3 → 3/2 | freq:293.3333333 ]", - "[ 4/3 → 3/2 | freq:293.3333333 ]", - "[ 4/3 → 3/2 | freq:293.3333333 ]", - "[ 4/3 → 3/2 | freq:293.3333333 ]", - "[ 3/2 → 5/3 | freq:330 ]", - "[ 3/2 → 5/3 | freq:330 ]", - "[ 3/2 → 5/3 | freq:330 ]", "[ 3/2 → 5/3 | freq:330 ]", "[ 5/3 → 11/6 | freq:352 ]", - "[ 5/3 → 11/6 | freq:352 ]", - "[ 5/3 → 11/6 | freq:352 ]", - "[ 5/3 → 11/6 | freq:352 ]", - "[ 11/6 → 2/1 | freq:440 ]", - "[ 11/6 → 2/1 | freq:440 ]", - "[ 11/6 → 2/1 | freq:440 ]", "[ 11/6 → 2/1 | freq:440 ]", "[ 2/1 → 13/6 | freq:220 ]", - "[ 2/1 → 13/6 | freq:220 ]", - "[ 2/1 → 13/6 | freq:220 ]", - "[ 2/1 → 13/6 | freq:220 ]", - "[ 13/6 → 7/3 | freq:275 ]", - "[ 13/6 → 7/3 | freq:275 ]", - "[ 13/6 → 7/3 | freq:275 ]", "[ 13/6 → 7/3 | freq:275 ]", "[ 7/3 → 5/2 | freq:293.3333333 ]", - "[ 7/3 → 5/2 | freq:293.3333333 ]", - "[ 7/3 → 5/2 | freq:293.3333333 ]", - "[ 7/3 → 5/2 | freq:293.3333333 ]", - "[ 5/2 → 8/3 | freq:330 ]", - "[ 5/2 → 8/3 | freq:330 ]", - "[ 5/2 → 8/3 | freq:330 ]", "[ 5/2 → 8/3 | freq:330 ]", "[ 8/3 → 17/6 | freq:352 ]", - "[ 8/3 → 17/6 | freq:352 ]", - "[ 8/3 → 17/6 | freq:352 ]", - "[ 8/3 → 17/6 | freq:352 ]", - "[ 17/6 → 3/1 | freq:440 ]", - "[ 17/6 → 3/1 | freq:440 ]", - "[ 17/6 → 3/1 | freq:440 ]", "[ 17/6 → 3/1 | freq:440 ]", "[ 3/1 → 19/6 | freq:220 ]", - "[ 3/1 → 19/6 | freq:220 ]", - "[ 3/1 → 19/6 | freq:220 ]", - "[ 3/1 → 19/6 | freq:220 ]", - "[ 19/6 → 10/3 | freq:275 ]", - "[ 19/6 → 10/3 | freq:275 ]", - "[ 19/6 → 10/3 | freq:275 ]", "[ 19/6 → 10/3 | freq:275 ]", "[ 10/3 → 7/2 | freq:293.3333333 ]", - "[ 10/3 → 7/2 | freq:293.3333333 ]", - "[ 10/3 → 7/2 | freq:293.3333333 ]", - "[ 10/3 → 7/2 | freq:293.3333333 ]", - "[ 7/2 → 11/3 | freq:330 ]", - "[ 7/2 → 11/3 | freq:330 ]", - "[ 7/2 → 11/3 | freq:330 ]", "[ 7/2 → 11/3 | freq:330 ]", "[ 11/3 → 23/6 | freq:352 ]", - "[ 11/3 → 23/6 | freq:352 ]", - "[ 11/3 → 23/6 | freq:352 ]", - "[ 11/3 → 23/6 | freq:352 ]", - "[ 23/6 → 4/1 | freq:440 ]", - "[ 23/6 → 4/1 | freq:440 ]", - "[ 23/6 → 4/1 | freq:440 ]", "[ 23/6 → 4/1 | freq:440 ]", ] `; exports[`runs examples > example "xen" example index 4 1`] = ` [ - "[ 0/1 → 1/8 | freq:220 ]", - "[ 0/1 → 1/8 | freq:220 ]", - "[ 0/1 → 1/8 | freq:220 ]", "[ 0/1 → 1/8 | freq:220 ]", "[ 1/8 → 1/4 | freq:252.7136381 ]", - "[ 1/8 → 1/4 | freq:235.7901618 ]", - "[ 1/8 → 1/4 | freq:230.404707 ]", - "[ 1/8 → 1/4 | freq:275 ]", "[ 1/4 → 3/8 | freq:290.2917404 ]", - "[ 1/4 → 3/8 | freq:252.7136381 ]", - "[ 1/4 → 3/8 | freq:241.3014955 ]", - "[ 1/4 → 3/8 | freq:293.3333333 ]", "[ 3/8 → 1/2 | freq:333.4576446 ]", - "[ 3/8 → 1/2 | freq:270.8517709 ]", - "[ 3/8 → 1/2 | freq:252.7136381 ]", - "[ 3/8 → 1/2 | freq:330 ]", "[ 1/2 → 5/8 | freq:383.0422479 ]", - "[ 1/2 → 5/8 | freq:290.2917404 ]", - "[ 1/2 → 5/8 | freq:264.6655079 ]", - "[ 1/2 → 5/8 | freq:352 ]", - "[ 5/8 → 3/4 | freq:440 ]", - "[ 5/8 → 3/4 | freq:311.1269837 ]", - "[ 5/8 → 3/4 | freq:277.182631 ]", "[ 5/8 → 3/4 | freq:440 ]", "[ 3/4 → 7/8 | freq:505.4272762 ]", - "[ 3/4 → 7/8 | freq:333.4576446 ]", - "[ 3/4 → 7/8 | freq:290.2917404 ]", - "[ 3/4 → 7/8 | freq:550 ]", "[ 7/8 → 1/1 | freq:580.5834807 ]", - "[ 7/8 → 1/1 | freq:357.3910544 ]", - "[ 7/8 → 1/1 | freq:304.0208336 ]", - "[ 7/8 → 1/1 | freq:586.6666667 ]", "[ 1/1 → 9/8 | freq:220 ]", - "[ 1/1 → 9/8 | freq:220 ]", - "[ 1/1 → 9/8 | freq:220 ]", - "[ 1/1 → 9/8 | freq:220 ]", - "[ 9/8 → 5/4 | freq:252.7136381 ]", "[ 9/8 → 5/4 | freq:235.7901618 ]", - "[ 9/8 → 5/4 | freq:230.404707 ]", - "[ 9/8 → 5/4 | freq:275 ]", - "[ 5/4 → 11/8 | freq:290.2917404 ]", "[ 5/4 → 11/8 | freq:252.7136381 ]", - "[ 5/4 → 11/8 | freq:241.3014955 ]", - "[ 5/4 → 11/8 | freq:293.3333333 ]", - "[ 11/8 → 3/2 | freq:333.4576446 ]", "[ 11/8 → 3/2 | freq:270.8517709 ]", - "[ 11/8 → 3/2 | freq:252.7136381 ]", - "[ 11/8 → 3/2 | freq:330 ]", - "[ 3/2 → 13/8 | freq:383.0422479 ]", "[ 3/2 → 13/8 | freq:290.2917404 ]", - "[ 3/2 → 13/8 | freq:264.6655079 ]", - "[ 3/2 → 13/8 | freq:352 ]", - "[ 13/8 → 7/4 | freq:440 ]", "[ 13/8 → 7/4 | freq:311.1269837 ]", - "[ 13/8 → 7/4 | freq:277.182631 ]", - "[ 13/8 → 7/4 | freq:440 ]", - "[ 7/4 → 15/8 | freq:505.4272762 ]", "[ 7/4 → 15/8 | freq:333.4576446 ]", - "[ 7/4 → 15/8 | freq:290.2917404 ]", - "[ 7/4 → 15/8 | freq:550 ]", - "[ 15/8 → 2/1 | freq:580.5834807 ]", "[ 15/8 → 2/1 | freq:357.3910544 ]", - "[ 15/8 → 2/1 | freq:304.0208336 ]", - "[ 15/8 → 2/1 | freq:586.6666667 ]", "[ 2/1 → 17/8 | freq:220 ]", - "[ 2/1 → 17/8 | freq:220 ]", - "[ 2/1 → 17/8 | freq:220 ]", - "[ 2/1 → 17/8 | freq:220 ]", - "[ 17/8 → 9/4 | freq:252.7136381 ]", - "[ 17/8 → 9/4 | freq:235.7901618 ]", "[ 17/8 → 9/4 | freq:230.404707 ]", - "[ 17/8 → 9/4 | freq:275 ]", - "[ 9/4 → 19/8 | freq:290.2917404 ]", - "[ 9/4 → 19/8 | freq:252.7136381 ]", "[ 9/4 → 19/8 | freq:241.3014955 ]", - "[ 9/4 → 19/8 | freq:293.3333333 ]", - "[ 19/8 → 5/2 | freq:333.4576446 ]", - "[ 19/8 → 5/2 | freq:270.8517709 ]", "[ 19/8 → 5/2 | freq:252.7136381 ]", - "[ 19/8 → 5/2 | freq:330 ]", - "[ 5/2 → 21/8 | freq:383.0422479 ]", - "[ 5/2 → 21/8 | freq:290.2917404 ]", "[ 5/2 → 21/8 | freq:264.6655079 ]", - "[ 5/2 → 21/8 | freq:352 ]", - "[ 21/8 → 11/4 | freq:440 ]", - "[ 21/8 → 11/4 | freq:311.1269837 ]", "[ 21/8 → 11/4 | freq:277.182631 ]", - "[ 21/8 → 11/4 | freq:440 ]", - "[ 11/4 → 23/8 | freq:505.4272762 ]", - "[ 11/4 → 23/8 | freq:333.4576446 ]", "[ 11/4 → 23/8 | freq:290.2917404 ]", - "[ 11/4 → 23/8 | freq:550 ]", - "[ 23/8 → 3/1 | freq:580.5834807 ]", - "[ 23/8 → 3/1 | freq:357.3910544 ]", "[ 23/8 → 3/1 | freq:304.0208336 ]", - "[ 23/8 → 3/1 | freq:586.6666667 ]", "[ 3/1 → 25/8 | freq:220 ]", - "[ 3/1 → 25/8 | freq:220 ]", - "[ 3/1 → 25/8 | freq:220 ]", - "[ 3/1 → 25/8 | freq:220 ]", - "[ 25/8 → 13/4 | freq:252.7136381 ]", - "[ 25/8 → 13/4 | freq:235.7901618 ]", - "[ 25/8 → 13/4 | freq:230.404707 ]", "[ 25/8 → 13/4 | freq:275 ]", - "[ 13/4 → 27/8 | freq:290.2917404 ]", - "[ 13/4 → 27/8 | freq:252.7136381 ]", - "[ 13/4 → 27/8 | freq:241.3014955 ]", "[ 13/4 → 27/8 | freq:293.3333333 ]", - "[ 27/8 → 7/2 | freq:333.4576446 ]", - "[ 27/8 → 7/2 | freq:270.8517709 ]", - "[ 27/8 → 7/2 | freq:252.7136381 ]", "[ 27/8 → 7/2 | freq:330 ]", - "[ 7/2 → 29/8 | freq:383.0422479 ]", - "[ 7/2 → 29/8 | freq:290.2917404 ]", - "[ 7/2 → 29/8 | freq:264.6655079 ]", "[ 7/2 → 29/8 | freq:352 ]", "[ 29/8 → 15/4 | freq:440 ]", - "[ 29/8 → 15/4 | freq:311.1269837 ]", - "[ 29/8 → 15/4 | freq:277.182631 ]", - "[ 29/8 → 15/4 | freq:440 ]", - "[ 15/4 → 31/8 | freq:505.4272762 ]", - "[ 15/4 → 31/8 | freq:333.4576446 ]", - "[ 15/4 → 31/8 | freq:290.2917404 ]", "[ 15/4 → 31/8 | freq:550 ]", - "[ 31/8 → 4/1 | freq:580.5834807 ]", - "[ 31/8 → 4/1 | freq:357.3910544 ]", - "[ 31/8 → 4/1 | freq:304.0208336 ]", "[ 31/8 → 4/1 | freq:586.6666667 ]", ] `; From f2acdc580f3bef060e06bcf1cf19cb98315b77dc Mon Sep 17 00:00:00 2001 From: tyow Date: Wed, 11 Mar 2026 14:01:57 -0400 Subject: [PATCH 16/21] fix edo bug --- packages/xen/xen.mjs | 8 ++++++-- test/__snapshots__/examples.test.mjs.snap | 24 +++++++++++------------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 7dc4501c8..46e93d1e9 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -216,12 +216,17 @@ export const xen = register( } else { // scale is named scale(s) for (let j = 0; j < sc.length; j++) { - let scale = getXenScale(sc[j].value); + let scaleName = sc[j].value; + let scale = getXenScale(scaleName); let freq = xenOffset(scale, parseNumeral(i)); let newHap = hap; freq = trimFreq(freq); newHap.value = { ...otherValues, freq }; newHap = newHap.setContext(newHap.combineContext(sc[j])); + if (isEdo(scaleName)) { + edo = scaleName.match(/^([1-9]+[0-9]*)edo$/)[1]; + newHap = newHap.setContext({ ...newHap.context, edoSize: edo }); + } resHaps.push(newHap); } } @@ -258,7 +263,6 @@ export const xen = register( // // 10 is somewhat arbitrary // freq = trimFreq(freq); // hap.value = { ...otherValues, freq }; - return edo ? hap.setContext({ ...hap.context, edoSize: edo }) : hap; }); // }); diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 26bbdfe7a..715ba5b42 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -5084,18 +5084,18 @@ exports[`runs examples > example "ftranspose" example index 0 1`] = ` exports[`runs examples > example "ftranspose" example index 1 1`] = ` [ - "[ 0/1 → 1/3 | freq:349.2282314 ]", - "[ 1/3 → 2/3 | freq:417.6327085 ]", - "[ 2/3 → 1/1 | freq:522.2770651 ]", - "[ 1/1 → 4/3 | freq:138.5913155 ]", - "[ 4/3 → 5/3 | freq:165.7376502 ]", - "[ 5/3 → 2/1 | freq:207.2657906 ]", - "[ 2/1 → 7/3 | freq:349.2282314 ]", - "[ 7/3 → 8/3 | freq:417.6327085 ]", - "[ 8/3 → 3/1 | freq:522.2770651 ]", - "[ 3/1 → 10/3 | freq:138.5913155 ]", - "[ 10/3 → 11/3 | freq:165.7376502 ]", - "[ 11/3 → 4/1 | freq:207.2657906 ]", + "[ 0/1 → 1/3 | freq:263.0921203 ]", + "[ 1/3 → 2/3 | freq:314.6248353 ]", + "[ 2/3 → 1/1 | freq:393.4589706 ]", + "[ 1/1 → 4/3 | freq:183.965981 ]", + "[ 4/3 → 5/3 | freq:220 ]", + "[ 5/3 → 2/1 | freq:275.1244143 ]", + "[ 2/1 → 7/3 | freq:263.0921203 ]", + "[ 7/3 → 8/3 | freq:314.6248353 ]", + "[ 8/3 → 3/1 | freq:393.4589706 ]", + "[ 3/1 → 10/3 | freq:183.965981 ]", + "[ 10/3 → 11/3 | freq:220 ]", + "[ 11/3 → 4/1 | freq:275.1244143 ]", ] `; From 4596926ac25829e430ee92211ac084b16db7d15b Mon Sep 17 00:00:00 2001 From: tyow Date: Wed, 11 Mar 2026 14:16:26 -0400 Subject: [PATCH 17/21] support old functionality --- packages/xen/xen.mjs | 19 +++++++++++++++---- test/__snapshots__/examples.test.mjs.snap | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 46e93d1e9..7f67d353a 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -186,13 +186,16 @@ export const xen = register( // Format: An array of values // Each value is a pattern, representing an index on the scale let sc = scaleNameOrRatios.query(st); - // Check to see if input is attempting to be a named scale + // Check to see if input is attempting to be a named scale or a raw scale let isStr = typeof sc[0].value == 'string'; - if (!isStr) { + let isRawScale = Array.isArray(sc[0].value) && sc[0].value.every((x) => typeof x == 'number'); + if (!isStr && !isRawScale) { sc = sc[0].value; + } else if (isRawScale) { + sc = getXenScale(sc[0].value); } - if (!isStr) { + if (!isStr && !isRawScale) { let scaleByIndices = []; for (let j = 0; j < sc.length; j++) { scaleByIndices[j] = sc[j].query(st); @@ -213,7 +216,13 @@ export const xen = register( newHap = newHap.setContext(newHap.combineContext(scaleByIndices[i][j])); resHaps.push(newHap); } - } else { + } else if (isRawScale) { + let freq = xenOffset(sc, parseNumeral(i)); + let newHap = hap; + freq = trimFreq(freq); + newHap.value = { ...otherValues, freq }; + resHaps.push(newHap); + } else if (isStr) { // scale is named scale(s) for (let j = 0; j < sc.length; j++) { let scaleName = sc[j].value; @@ -229,6 +238,8 @@ export const xen = register( } resHaps.push(newHap); } + } else { + throw new Error('failed to parse scale'); } /* diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 715ba5b42..d4e7c64b6 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -14580,7 +14580,22 @@ exports[`runs examples > example "xen" example index 0 1`] = ` ] `; -exports[`runs examples > example "xen" example index 1 1`] = `[]`; +exports[`runs examples > example "xen" example index 1 1`] = ` +[ + "[ 0/1 → 1/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 1/3 → 2/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 2/3 → 1/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 1/1 → 4/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 4/3 → 5/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 5/3 → 2/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 2/1 → 7/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 7/3 → 8/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 8/3 → 3/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", + "[ 3/1 → 10/3 | freq:220 clip:1 s:piano release:0.1 pan:0.5138888888888888 ]", + "[ 10/3 → 11/3 | freq:263.0921203 clip:1 s:piano release:0.1 pan:0.5277777777777778 ]", + "[ 11/3 → 4/1 | freq:329.0139341 clip:1 s:piano release:0.1 pan:0.5462962962962963 ]", +] +`; exports[`runs examples > example "xen" example index 2 1`] = ` [ From a58711a311e9384532282a665f84b4c348fea8f7 Mon Sep 17 00:00:00 2001 From: tyow Date: Wed, 11 Mar 2026 14:40:52 -0400 Subject: [PATCH 18/21] bugfix --- packages/xen/xen.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 7f67d353a..66c318296 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -207,13 +207,14 @@ export const xen = register( */ let sc2 = JIsc2(sc).query(st); - for (let j = 0; j < scaleByIndices[i].length; j++) { + let index = _mod(i, sc.length) + for (let j = 0; j < scaleByIndices[index].length; j++) { let scale = getXenScale(sc2[j].value); let freq = xenOffset(scale, parseNumeral(i)); let newHap = hap; freq = trimFreq(freq); newHap.value = { ...otherValues, freq }; - newHap = newHap.setContext(newHap.combineContext(scaleByIndices[i][j])); + newHap = newHap.setContext(newHap.combineContext(scaleByIndices[index][j])); resHaps.push(newHap); } } else if (isRawScale) { From aeeaa500719696027d986c2b36eb75a30f17914e Mon Sep 17 00:00:00 2001 From: tyow Date: Wed, 11 Mar 2026 18:03:50 -0400 Subject: [PATCH 19/21] cleanup --- packages/xen/xen.mjs | 90 +------------------------------------------- 1 file changed, 1 insertion(+), 89 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 66c318296..cf4eb5f7e 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -72,15 +72,6 @@ function xenOffset(xenScale, offset, index = 0) { const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); -// accepts a scale name such as 31edo, and a pattern -// pattern expected to follow format such that a value can be mapped -// to an edostep within the scale. Returns the pattern with -// values mapped to the frequencies associated with the given edosteps -// scaleNameOrRatios: string || number[], steps?: number - -// old, currently unsupported -// TODO support - /** * Assumes a numerical pattern of scale steps, and a scale. Scales accepted are all preset scale names of `tune`, arbitrary edos such as 31edo, or an array of frequency ratios. Assumes scales repeat at octave (2/1). Returns a new pattern with all values mapped to their associated frequency, assuming a base frequency of 220hz. * @@ -131,43 +122,7 @@ export const xen = register( }); }; - // TODO fix the following: - /* - let p1 = i("0 1").xen("hexany15 hexany23") - let p2 = i("[0 1]").xen([ - "[1:1 2:1]", // tonic - "5:4", // Major 3rd - ]).s("tri") - - let p3 = i("[0 1]").xen([ - "[<1:1 2:1>]", // tonic - "5:4", // Major 3rd - ]).s("tri") - */ - const query = (state) => { - // let input = scaleNameOrRatios.query(state); - - // if (input.length == 0) return []; - - // let scPat = input[0].value; - // let scs; - // if (typeof scPat == 'string') { - // scs = input.map((x) => x.value); - // } else if (scPat.every((x) => typeof x == 'number')) { - // scs = [scPat]; - // } else { - // scs = JIsc2(scPat).query(state); - // } - - // outside should be haps - // which then queries the scales using their hap timespans - - // input[0].value.forEach((inp, ith) => { - // let smth = inp.query(state) - // let scs = JIsc2(inp).query(state) - - // let k = scs.map((sc, jth) => { let haps = pat.query(state); let resHaps = []; @@ -207,7 +162,7 @@ export const xen = register( */ let sc2 = JIsc2(sc).query(st); - let index = _mod(i, sc.length) + let index = _mod(i, sc.length); for (let j = 0; j < scaleByIndices[index].length; j++) { let scale = getXenScale(sc2[j].value); let freq = xenOffset(scale, parseNumeral(i)); @@ -242,50 +197,7 @@ export const xen = register( } else { throw new Error('failed to parse scale'); } - - /* - We need to know: - - How many Haps to make, given a scale index (i value) from a Hap from pat (sc can tell us) - - The whole scale, so the frequency can be set (sc2 can tell us) - - if sc2.length > 1, how do we deal? - - The frequency of the ith element of the scale, given a Hap (from pat) with i value of ith - - The whole scale definitions in sc2 can be indexed by the index of Hap within sc: - - */ - - // if (typeof sc == 'string') { - // scale = getXenScale(sc); - // if (isEdo(sc)) { - // edo = sc.match(/^([1-9]+[0-9]*)edo$/)[1]; - // } - // hap = hap.setContext(hap.combineContext(input[ith])); - // } else if (Array.isArray(sc) && sc.every((x) => typeof x == 'number')) { - // scale = getXenScale(sc); - // } else { - // scale = getXenScale(sc.value); - // for (let h of scPat[_mod(i, scale.length)].query(state)) { - // let ts = hap.wholeOrPart().intersection(h.wholeOrPart()); - // if (ts == undefined) return undefined; - // hap = hap.withSpan((x) => ts); - // hap = hap.setContext(hap.combineContext(h)); - // } - // } - // let freq = xenOffset(scale, parseNumeral(i)); - // // 10 is somewhat arbitrary - // freq = trimFreq(freq); - // hap.value = { ...otherValues, freq }; }); - - // }); - // return flatten(k); - // }) - - /* - perhaps instead of - return new Pattern(query) - we could do a join on scaleNameOrRatios which creates multiple patterns and then joins them - */ return resHaps; }; return new Pattern(query); From 08eaa8a57851da1f9243a5adac43957e9a60836a Mon Sep 17 00:00:00 2001 From: tyow Date: Wed, 11 Mar 2026 18:04:29 -0400 Subject: [PATCH 20/21] more cleanup --- packages/xen/xen.mjs | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index cf4eb5f7e..32ed0111d 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -11,10 +11,7 @@ import { removeUndefineds, Pattern, parray, - reify, State, - flatten, - Hap, } from '@strudel/core'; import Tune from './tunejs.js'; From 948f78da1144d805c04e13be3e95e87504f94096 Mon Sep 17 00:00:00 2001 From: tyow Date: Thu, 12 Mar 2026 12:23:30 -0400 Subject: [PATCH 21/21] wording --- packages/xen/xen.mjs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index 32ed0111d..de347d38b 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -4,15 +4,7 @@ Copyright (C) 2022 Strudel contributors - see . */ -import { - register, - _mod, - parseNumeral, - removeUndefineds, - Pattern, - parray, - State, -} from '@strudel/core'; +import { register, _mod, parseNumeral, removeUndefineds, Pattern, parray, State } from '@strudel/core'; import Tune from './tunejs.js'; // returns a list of frequency ratios for given edo scale @@ -70,7 +62,7 @@ function xenOffset(xenScale, offset, index = 0) { const trimFreq = (freq) => parseFloat(freq.toPrecision(10)); /** - * Assumes a numerical pattern of scale steps, and a scale. Scales accepted are all preset scale names of `tune`, arbitrary edos such as 31edo, or an array of frequency ratios. Assumes scales repeat at octave (2/1). Returns a new pattern with all values mapped to their associated frequency, assuming a base frequency of 220hz. + * Assumes a numerical pattern of scale steps, and a scale. Scales accepted are all preset scale names of `tune`, arbitrary edos such as 31edo, or an array of frequency ratios. Assumes scales repeat at octave (2/1). Returns a new pattern with all values mapped to their associated frequency, assuming a base frequency of 220hz. See first 4 examples for the different ways you can input a scale into `xen` * * @name xen * @returns Pattern