fix: scale errors safety net
This commit is contained in:
parent
9059b16c7c
commit
c44f202c44
1 changed files with 38 additions and 14 deletions
|
|
@ -5,14 +5,20 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Note, Interval, Scale } from '@tonaljs/tonal';
|
import { Note, Interval, Scale } from '@tonaljs/tonal';
|
||||||
import { register, _mod } from '@strudel.cycles/core';
|
import { register, _mod, silence, logger, pure, isNote } from '@strudel.cycles/core';
|
||||||
|
|
||||||
const octavesInterval = (octaves) => (octaves <= 0 ? -1 : 1) + octaves * 7 + 'P';
|
const octavesInterval = (octaves) => (octaves <= 0 ? -1 : 1) + octaves * 7 + 'P';
|
||||||
|
|
||||||
function scaleStep(step, scale) {
|
function scaleStep(step, scale) {
|
||||||
scale = scale.replaceAll(':', ' ');
|
scale = scale.replaceAll(':', ' ');
|
||||||
step = Math.ceil(step);
|
step = Math.ceil(step);
|
||||||
const { intervals, tonic } = Scale.get(scale);
|
let { intervals, tonic, empty } = Scale.get(scale);
|
||||||
|
if ((empty && isNote(scale)) || (!empty && !tonic)) {
|
||||||
|
throw new Error(`incomplete scale. Make sure to use ":" instead of spaces, example: .scale("C:major")`);
|
||||||
|
} else if (empty) {
|
||||||
|
throw new Error(`invalid scale "${scale}"`);
|
||||||
|
}
|
||||||
|
tonic = tonic || 'C';
|
||||||
const { pc, oct = 3 } = Note.get(tonic);
|
const { pc, oct = 3 } = Note.get(tonic);
|
||||||
const octaveOffset = Math.floor(step / intervals.length);
|
const octaveOffset = Math.floor(step / intervals.length);
|
||||||
const scaleStep = _mod(step, intervals.length);
|
const scaleStep = _mod(step, intervals.length);
|
||||||
|
|
@ -160,16 +166,34 @@ export const scale = register('scale', function (scale, pat) {
|
||||||
if (Array.isArray(scale)) {
|
if (Array.isArray(scale)) {
|
||||||
scale = scale.flat().join(' ');
|
scale = scale.flat().join(' ');
|
||||||
}
|
}
|
||||||
return pat.withHap((hap) => {
|
return (
|
||||||
const isObject = typeof hap.value === 'object';
|
pat
|
||||||
let note = isObject ? hap.value.n : hap.value;
|
.fmap((value) => {
|
||||||
if (isObject) {
|
const isObject = typeof value === 'object';
|
||||||
delete hap.value.n; // remove n so it won't cause trouble
|
let step = isObject ? value.n : value;
|
||||||
}
|
if (isObject) {
|
||||||
const asNumber = Number(note);
|
delete value.n; // remove n so it won't cause trouble
|
||||||
if (!isNaN(asNumber)) {
|
}
|
||||||
note = scaleStep(asNumber, scale);
|
if (isNote(step)) {
|
||||||
}
|
// legacy..
|
||||||
return hap.withValue(() => (isObject ? { ...hap.value, note } : note)).setContext({ ...hap.context, scale });
|
return pure(step);
|
||||||
});
|
}
|
||||||
|
const asNumber = Number(step);
|
||||||
|
if (isNaN(asNumber)) {
|
||||||
|
logger(`[tonal] invalid scale step "${step}", expected number`, 'error');
|
||||||
|
return silence;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const note = scaleStep(asNumber, scale);
|
||||||
|
value = pure(isObject ? { ...value, note } : note);
|
||||||
|
} catch (err) {
|
||||||
|
logger(`[tonal] ${err.message}`, 'error');
|
||||||
|
value = silence;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
})
|
||||||
|
.outerJoin()
|
||||||
|
// legacy:
|
||||||
|
.withHap((hap) => hap.setContext({ ...hap.context, scale }))
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue