build
This commit is contained in:
parent
ad42e5eb61
commit
a2ab2b9da5
19 changed files with 72400 additions and 62 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import Fraction from "../pkg/fractionjs.js";
|
||||
import {compose} from "../pkg/ramda.js";
|
||||
import {isNote, toMidi} from "./util.js";
|
||||
const removeUndefineds = (xs) => xs.filter((x) => x != void 0);
|
||||
const flatten = (arr) => [].concat(...arr);
|
||||
const id = (a) => a;
|
||||
|
|
@ -327,17 +328,39 @@ class Pattern {
|
|||
_opleft(other, func) {
|
||||
return this.fmap(func).appLeft(reify(other));
|
||||
}
|
||||
_asNumber() {
|
||||
return this._withEvent((event) => {
|
||||
const asNumber = Number(event.value);
|
||||
if (!isNaN(asNumber)) {
|
||||
return event.withValue(() => asNumber);
|
||||
}
|
||||
const specialValue = {
|
||||
e: Math.E,
|
||||
pi: Math.PI
|
||||
}[event.value];
|
||||
if (typeof specialValue !== "undefined") {
|
||||
return event.withValue(() => specialValue);
|
||||
}
|
||||
if (isNote(event.value)) {
|
||||
return new Hap(event.whole, event.part, toMidi(event.value), {...event.context, type: "midi"});
|
||||
}
|
||||
throw new Error('cannot parse as number: "' + event.value + '"');
|
||||
});
|
||||
}
|
||||
add(other) {
|
||||
return this._opleft(other, (a) => (b) => a + b);
|
||||
return this._asNumber()._opleft(other, (a) => (b) => a + b);
|
||||
}
|
||||
sub(other) {
|
||||
return this._opleft(other, (a) => (b) => a - b);
|
||||
return this._asNumber()._opleft(other, (a) => (b) => a - b);
|
||||
}
|
||||
mul(other) {
|
||||
return this._opleft(other, (a) => (b) => a * b);
|
||||
return this._asNumber()._opleft(other, (a) => (b) => a * b);
|
||||
}
|
||||
div(other) {
|
||||
return this._opleft(other, (a) => (b) => a / b);
|
||||
return this._asNumber()._opleft(other, (a) => (b) => a / b);
|
||||
}
|
||||
round() {
|
||||
return this._asNumber().fmap((v) => Math.round(v));
|
||||
}
|
||||
union(other) {
|
||||
return this._opleft(other, (a) => (b) => Object.assign({}, a, b));
|
||||
|
|
|
|||
33
docs/_snowpack/link/util.js
Normal file
33
docs/_snowpack/link/util.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
export const isNote = (name) => /^[a-gA-G][#b]*[0-9]$/.test(name);
|
||||
export const tokenizeNote = (note) => {
|
||||
if (typeof note !== "string") {
|
||||
return [];
|
||||
}
|
||||
const [pc, acc = "", oct] = note.match(/^([a-gA-G])([#b]*)([0-9])?$/)?.slice(1) || [];
|
||||
if (!pc) {
|
||||
return [];
|
||||
}
|
||||
return [pc, acc, oct ? Number(oct) : void 0];
|
||||
};
|
||||
export const toMidi = (note) => {
|
||||
const [pc, acc, oct] = tokenizeNote(note);
|
||||
if (!pc) {
|
||||
throw new Error('not a note: "' + note + '"');
|
||||
}
|
||||
const chroma = {c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11}[pc.toLowerCase()];
|
||||
const offset = acc?.split("").reduce((o, char) => o + {"#": 1, b: -1}[char], 0) || 0;
|
||||
return (Number(oct) + 1) * 12 + chroma + offset;
|
||||
};
|
||||
export const fromMidi = (n) => {
|
||||
return Math.pow(2, (n - 69) / 12) * 440;
|
||||
};
|
||||
export const mod = (n, m) => n < 0 ? mod(n + m, m) : n % m;
|
||||
export const getPlayableNoteValue = (event) => {
|
||||
let {value: note, context} = event;
|
||||
if (typeof note === "number" && context.type !== "frequency") {
|
||||
note = fromMidi(event.value);
|
||||
} else if (typeof note === "string" && !isNote(note)) {
|
||||
throw new Error("not a note: " + note);
|
||||
}
|
||||
return note;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue