mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 21:58:31 +00:00
added _asNumber + interprete numbers as midi
This commit is contained in:
parent
190729df73
commit
8a7e49780a
@ -1,5 +1,6 @@
|
||||
import { useCallback, useState, useMemo } from 'react';
|
||||
import { isNote } from 'tone';
|
||||
import { fromMidi } from '../../util.mjs';
|
||||
import { evaluate } from './evaluate';
|
||||
import type { Pattern } from './types';
|
||||
import useCycle from './useCycle';
|
||||
@ -63,8 +64,12 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw }: any)
|
||||
onEvent?.(event);
|
||||
const { onTrigger } = event.context;
|
||||
if (!onTrigger) {
|
||||
const note = event.value;
|
||||
if (!isNote(note)) {
|
||||
let note = event.value;
|
||||
// if value is number => interpret as midi number...
|
||||
// TODO: what if value is meant as frequency? => check context
|
||||
if (typeof event.value === 'number') {
|
||||
note = fromMidi(event.value);
|
||||
} else if (!isNote(note)) {
|
||||
throw new Error('not a note: ' + note);
|
||||
}
|
||||
if (defaultSynth) {
|
||||
|
||||
30
strudel.mjs
30
strudel.mjs
@ -1,5 +1,6 @@
|
||||
import Fraction from 'fraction.js'
|
||||
import { compose } from 'ramda'; // will remove this as soon as compose is implemented here
|
||||
import { isNote, toMidi } from './util.mjs';
|
||||
|
||||
// Removes 'None' values from given list
|
||||
const removeUndefineds = xs => xs.filter(x => x != undefined)
|
||||
@ -466,20 +467,41 @@ class Pattern {
|
||||
return this.fmap(func).appLeft(reify(other))
|
||||
}
|
||||
|
||||
_asNumber() {
|
||||
return this._withEvent(event => {
|
||||
const asNumber = Number(event.value)
|
||||
if(!isNaN(asNumber)) {
|
||||
return asNumber;
|
||||
}
|
||||
const specialValue = {
|
||||
e: Math.E,
|
||||
pi: Math.PI
|
||||
}[event.value];
|
||||
if(typeof specialValue !== 'undefined') {
|
||||
return specialValue;
|
||||
}
|
||||
if(isNote(event.value)) {
|
||||
// set context type to midi to let the player know its meant as midi number and not as frequency
|
||||
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)
|
||||
}
|
||||
|
||||
union(other) {
|
||||
|
||||
11
util.mjs
Normal file
11
util.mjs
Normal file
@ -0,0 +1,11 @@
|
||||
export const isNote = (name) => /^[a-gA-G][#b]?[0-9]$/.test(name);
|
||||
export const tokenizeNote = (note) => note.match(/^([a-gA-G])([#b])?([0-9])?$/).slice(1);
|
||||
export const toMidi = (note) => {
|
||||
const [pc, acc, oct] = tokenizeNote(note);
|
||||
const chroma = { c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11 }[pc];
|
||||
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;
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user