From 9017085fa301a549889b89412dba161315a6821b Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 1 Aug 2025 09:36:36 +0100 Subject: [PATCH 1/7] add trans alias for transpose --- packages/tonal/tonal.mjs | 73 +++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs index a425782d2..5ac894f56 100644 --- a/packages/tonal/tonal.mjs +++ b/packages/tonal/tonal.mjs @@ -61,40 +61,7 @@ function scaleOffset(scale, offset, note) { return n + o; } -// Pattern.prototype._transpose = function (intervalOrSemitones: string | number) { -/** - * Change the pitch of each value by the given amount. Expects numbers or note strings as values. - * The amount can be given as a number of semitones or as a string in interval short notation. - * If you don't care about enharmonic correctness, just use numbers. Otherwise, pass the interval of - * the form: ST where S is the degree number and T the type of interval with - * - * - M = major - * - m = minor - * - P = perfect - * - A = augmented - * - d = diminished - * - * Examples intervals: - * - * - 1P = unison - * - 3M = major third - * - 3m = minor third - * - 4P = perfect fourth - * - 4A = augmented fourth - * - 5P = perfect fifth - * - 5d = diminished fifth - * - * @param {string | number} amount Either number of semitones or interval string. - * @returns Pattern - * @memberof Pattern - * @name transpose - * @example - * "c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).note() - * @example - * "c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note() - */ - -export const transpose = register('transpose', function (intervalOrSemitones, pat) { +function transposeFn(intervalOrSemitones, pat) { return pat.withHap((hap) => { const note = hap.value.note ?? hap.value; if (typeof note === 'number') { @@ -128,7 +95,43 @@ export const transpose = register('transpose', function (intervalOrSemitones, pa } return hap.withValue(() => targetNote); }); -}); +} + +// Pattern.prototype._transpose = function (intervalOrSemitones: string | number) { +/** + * Change the pitch of each value by the given amount. Expects numbers or note strings as values. + * The amount can be given as a number of semitones or as a string in interval short notation. + * If you don't care about enharmonic correctness, just use numbers. Otherwise, pass the interval of + * the form: ST where S is the degree number and T the type of interval with + * + * - M = major + * - m = minor + * - P = perfect + * - A = augmented + * - d = diminished + * + * Examples intervals: + * + * - 1P = unison + * - 3M = major third + * - 3m = minor third + * - 4P = perfect fourth + * - 4A = augmented fourth + * - 5P = perfect fifth + * - 5d = diminished fifth + * + * @param {string | number} amount Either number of semitones or interval string. + * @returns Pattern + * @memberof Pattern + * @name transpose + * @example + * "c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).note() + * @example + * "c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note() + */ + +export const transpose = register('transpose', transposeFn); +export const trans = register('trans', transposeFn); // example: transpose(3).late(0.2) will be equivalent to compose(transpose(3), late(0.2)) // e.g. `stack(c3).superimpose(transpose(slowcat(7, 5)))` or From ef3cd56b0dca8f6f677f8b1e72386c2763464fa6 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 1 Aug 2025 09:39:21 +0100 Subject: [PATCH 2/7] add synonym to docs --- packages/tonal/tonal.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs index 5ac894f56..da3a4d507 100644 --- a/packages/tonal/tonal.mjs +++ b/packages/tonal/tonal.mjs @@ -124,6 +124,7 @@ function transposeFn(intervalOrSemitones, pat) { * @returns Pattern * @memberof Pattern * @name transpose + * @synonyms trans * @example * "c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).note() * @example From 051efdc13bdd184daf328fcd146eaf109ea97243 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Fri, 1 Aug 2025 09:39:33 +0100 Subject: [PATCH 3/7] flyby improvement: add dec synonym to docs --- packages/core/controls.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 326343e10..6b3433c31 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -306,6 +306,7 @@ export const { fft } = registerControl('fft'); * * @name decay * @param {number | Pattern} time decay time in seconds + * @synonyms dec * @example * note("c3 e3 f3 g3").decay("<.1 .2 .3 .4>").sustain(0) * From 39c45bc2b2077a2b7cdcd6365af85c2cc15e8395 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Sat, 2 Aug 2025 10:17:33 +0100 Subject: [PATCH 4/7] pass an array of names instead --- packages/tonal/tonal.mjs | 73 +++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs index da3a4d507..7cb987394 100644 --- a/packages/tonal/tonal.mjs +++ b/packages/tonal/tonal.mjs @@ -61,42 +61,6 @@ function scaleOffset(scale, offset, note) { return n + o; } -function transposeFn(intervalOrSemitones, pat) { - return pat.withHap((hap) => { - const note = hap.value.note ?? hap.value; - if (typeof note === 'number') { - // note is a number, so just add the number semitones of the interval - let semitones; - if (typeof intervalOrSemitones === 'number') { - semitones = intervalOrSemitones; - } else if (typeof intervalOrSemitones === 'string') { - semitones = Interval.semitones(intervalOrSemitones) || 0; - } - const targetNote = note + semitones; - if (typeof hap.value === 'object') { - return hap.withValue(() => ({ ...hap.value, note: targetNote })); - } - return hap.withValue(() => targetNote); - } - if (typeof note !== 'string' || !isNote(note)) { - logger(`[tonal] transpose: not a note "${note}"`, 'warning'); - return hap; - } - // note is a string, so we might be able to preserve harmonics if interval is a string as well - const interval = !isNaN(Number(intervalOrSemitones)) - ? Interval.fromSemitones(intervalOrSemitones) - : String(intervalOrSemitones); - // TODO: move simplify to player to preserve enharmonics - // tone.js doesn't understand multiple sharps flats e.g. F##3 has to be turned into G3 - // TODO: check if this is still relevant.. - const targetNote = Note.simplify(Note.transpose(note, interval)); - if (typeof hap.value === 'object') { - return hap.withValue(() => ({ ...hap.value, note: targetNote })); - } - return hap.withValue(() => targetNote); - }); -} - // Pattern.prototype._transpose = function (intervalOrSemitones: string | number) { /** * Change the pitch of each value by the given amount. Expects numbers or note strings as values. @@ -131,8 +95,41 @@ function transposeFn(intervalOrSemitones, pat) { * "c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note() */ -export const transpose = register('transpose', transposeFn); -export const trans = register('trans', transposeFn); +export const transpose = register(['transpose', 'trans'], function transposeFn(intervalOrSemitones, pat) { + return pat.withHap((hap) => { + const note = hap.value.note ?? hap.value; + if (typeof note === 'number') { + // note is a number, so just add the number semitones of the interval + let semitones; + if (typeof intervalOrSemitones === 'number') { + semitones = intervalOrSemitones; + } else if (typeof intervalOrSemitones === 'string') { + semitones = Interval.semitones(intervalOrSemitones) || 0; + } + const targetNote = note + semitones; + if (typeof hap.value === 'object') { + return hap.withValue(() => ({ ...hap.value, note: targetNote })); + } + return hap.withValue(() => targetNote); + } + if (typeof note !== 'string' || !isNote(note)) { + logger(`[tonal] transpose: not a note "${note}"`, 'warning'); + return hap; + } + // note is a string, so we might be able to preserve harmonics if interval is a string as well + const interval = !isNaN(Number(intervalOrSemitones)) + ? Interval.fromSemitones(intervalOrSemitones) + : String(intervalOrSemitones); + // TODO: move simplify to player to preserve enharmonics + // tone.js doesn't understand multiple sharps flats e.g. F##3 has to be turned into G3 + // TODO: check if this is still relevant.. + const targetNote = Note.simplify(Note.transpose(note, interval)); + if (typeof hap.value === 'object') { + return hap.withValue(() => ({ ...hap.value, note: targetNote })); + } + return hap.withValue(() => targetNote); + }); +}); // example: transpose(3).late(0.2) will be equivalent to compose(transpose(3), late(0.2)) // e.g. `stack(c3).superimpose(transpose(slowcat(7, 5)))` or From ad113b3888888fbc34b1742219fab93dadcd4b8d Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Sat, 2 Aug 2025 10:17:48 +0100 Subject: [PATCH 5/7] document ability to specify an array of names --- packages/core/pattern.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index d59a1285d..4d0274c7a 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -1569,7 +1569,7 @@ export const func = curry((a, b) => reify(b).func(a)); /** * Registers a new pattern method. The method is added to the Pattern class + the standalone function is returned from register. * - * @param {string} name name of the function + * @param {string | string[]} name name of the function, or an array of names to be used as synonyms * @param {function} func function with 1 or more params, where last is the current pattern * @noAutocomplete * From efc2333360dd1528f471f1a131cc5f1ebfbe85b0 Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Sat, 2 Aug 2025 10:25:28 +0100 Subject: [PATCH 6/7] add synonyms for scaleTranspose --- packages/tonal/tonal.mjs | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs index a425782d2..dbd9eb8b0 100644 --- a/packages/tonal/tonal.mjs +++ b/packages/tonal/tonal.mjs @@ -142,6 +142,7 @@ export const transpose = register('transpose', function (intervalOrSemitones, pa * @name scaleTranspose * @param {offset} offset number of steps inside the scale * @returns Pattern + * @synonyms scaleTrans * @example * "-8 [2,4,6]" * .scale('C4 bebop major') @@ -149,22 +150,25 @@ export const transpose = register('transpose', function (intervalOrSemitones, pa * .note() */ -export const scaleTranspose = register('scaleTranspose', function (offset /* : number | string */, pat) { - return pat.withHap((hap) => { - if (!hap.context.scale) { - throw new Error('can only use scaleTranspose after .scale'); - } - if (typeof hap.value === 'object') - return hap.withValue(() => ({ - ...hap.value, - note: scaleOffset(hap.context.scale, Number(offset), hap.value.note), - })); - if (typeof hap.value !== 'string') { - throw new Error('can only use scaleTranspose with notes'); - } - return hap.withValue(() => scaleOffset(hap.context.scale, Number(offset), hap.value)); - }); -}); +export const scaleTranspose = register( + ['scaleTranspose', 'scaleTrans', 'strans'], + function (offset /* : number | string */, pat) { + return pat.withHap((hap) => { + if (!hap.context.scale) { + throw new Error('can only use scaleTranspose after .scale'); + } + if (typeof hap.value === 'object') + return hap.withValue(() => ({ + ...hap.value, + note: scaleOffset(hap.context.scale, Number(offset), hap.value.note), + })); + if (typeof hap.value !== 'string') { + throw new Error('can only use scaleTranspose with notes'); + } + return hap.withValue(() => scaleOffset(hap.context.scale, Number(offset), hap.value)); + }); + }, +); /** * Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like {@link Pattern#scaleTranspose}. From d55ef8e84383f201585d0972de17d68c0b00b6cb Mon Sep 17 00:00:00 2001 From: "Lu[ke] Wilson" Date: Sat, 2 Aug 2025 10:26:36 +0100 Subject: [PATCH 7/7] add strans too --- packages/tonal/tonal.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs index dbd9eb8b0..6d18f27b8 100644 --- a/packages/tonal/tonal.mjs +++ b/packages/tonal/tonal.mjs @@ -142,7 +142,7 @@ export const transpose = register('transpose', function (intervalOrSemitones, pa * @name scaleTranspose * @param {offset} offset number of steps inside the scale * @returns Pattern - * @synonyms scaleTrans + * @synonyms scaleTrans, strans * @example * "-8 [2,4,6]" * .scale('C4 bebop major')