mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-15 07:38:28 +00:00
30 lines
993 B
JavaScript
30 lines
993 B
JavaScript
// currently duplicate with core util.mjs to skip dependency
|
|
// TODO: add separate util module?
|
|
|
|
export const tokenizeNote = (note) => {
|
|
if (typeof note !== 'string') {
|
|
return [];
|
|
}
|
|
const [pc, acc = '', oct] = note.match(/^([a-gA-G])([#bsf]*)([0-9]*)$/)?.slice(1) || [];
|
|
if (!pc) {
|
|
return [];
|
|
}
|
|
return [pc, acc, oct ? Number(oct) : undefined];
|
|
};
|
|
const chromas = { c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11 };
|
|
const accs = { '#': 1, b: -1, s: 1, f: -1 };
|
|
|
|
export const noteToMidi = (note, defaultOctave = 3) => {
|
|
const [pc, acc, oct = defaultOctave] = tokenizeNote(note);
|
|
if (!pc) {
|
|
throw new Error('not a note: "' + note + '"');
|
|
}
|
|
const chroma = chromas[pc.toLowerCase()];
|
|
const offset = acc?.split('').reduce((o, char) => o + accs[char], 0) || 0;
|
|
return (Number(oct) + 1) * 12 + chroma + offset;
|
|
};
|
|
export const midiToFreq = (n) => {
|
|
return Math.pow(2, (n - 69) / 12) * 440;
|
|
};
|
|
export const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|